diff options
Diffstat (limited to 'arm9/lib')
-rw-r--r-- | arm9/lib/include/FS_archive.h | 56 | ||||
-rw-r--r-- | arm9/lib/include/FS_command.h | 9 | ||||
-rw-r--r-- | arm9/lib/include/FS_file.h | 20 | ||||
-rw-r--r-- | arm9/lib/include/OS_thread.h | 1 | ||||
-rw-r--r-- | arm9/lib/src/FS_archive.c | 147 | ||||
-rw-r--r-- | arm9/lib/src/FS_file.c | 10 |
6 files changed, 233 insertions, 10 deletions
diff --git a/arm9/lib/include/FS_archive.h b/arm9/lib/include/FS_archive.h index 66840b32..b39e7738 100644 --- a/arm9/lib/include/FS_archive.h +++ b/arm9/lib/include/FS_archive.h @@ -47,6 +47,37 @@ typedef enum { FS_COMMAND_INVALID } FSCommandType; +/* Asynchronous commands*/ +#define FS_ARCHIVE_PROC_READFILE (1 << FS_COMMAND_READFILE) +#define FS_ARCHIVE_PROC_WRITEFILE (1 << FS_COMMAND_WRITEFILE) +/* All asynchronous commands*/ +#define FS_ARCHIVE_PROC_ASYNC \ + (FS_ARCHIVE_PROC_READFILE | FS_ARCHIVE_PROC_WRITEFILE) + +/* Synchronous commands*/ +#define FS_ARCHIVE_PROC_SEEKDIR (1 << FS_COMMAND_SEEKDIR) +#define FS_ARCHIVE_PROC_READDIR (1 << FS_COMMAND_READDIR) +#define FS_ARCHIVE_PROC_FINDPATH (1 << FS_COMMAND_FINDPATH) +#define FS_ARCHIVE_PROC_GETPATH (1 << FS_COMMAND_GETPATH) +#define FS_ARCHIVE_PROC_OPENFILEFAST (1 << FS_COMMAND_OPENFILEFAST) +#define FS_ARCHIVE_PROC_OPENFILEDIRECT (1 << FS_COMMAND_OPENFILEDIRECT) +#define FS_ARCHIVE_PROC_CLOSEFILE (1 << FS_COMMAND_CLOSEFILE) +/* All synchronous commands*/ +#define FS_ARCHIVE_PROC_SYNC \ + (FS_ARCHIVE_PROC_SEEKDIR | FS_ARCHIVE_PROC_READDIR | \ + FS_ARCHIVE_PROC_FINDPATH | FS_ARCHIVE_PROC_GETPATH | \ + FS_ARCHIVE_PROC_OPENFILEFAST | FS_ARCHIVE_PROC_OPENFILEDIRECT | FS_ARCHIVE_PROC_CLOSEFILE) + +/* Messages when status changes*/ +#define FS_ARCHIVE_PROC_ACTIVATE (1 << FS_COMMAND_ACTIVATE) +#define FS_ARCHIVE_PROC_IDLE (1 << FS_COMMAND_IDLE) +#define FS_ARCHIVE_PROC_SUSPENDING (1 << FS_COMMAND_SUSPEND) +#define FS_ARCHIVE_PROC_RESUME (1 << FS_COMMAND_RESUME) +/* All messages when status changes*/ +#define FS_ARCHIVE_PROC_STATUS \ + (FS_ARCHIVE_PROC_ACTIVATE | FS_ARCHIVE_PROC_IDLE | \ + FS_ARCHIVE_PROC_SUSPENDING | FS_ARCHIVE_PROC_RESUME) + typedef enum { FS_RESULT_SUCCESS = 0, FS_RESULT_FAILURE, @@ -107,6 +138,31 @@ static inline BOOL FS_IsArchiveLoaded(volatile const FSArchive * p_arc) return (p_arc->flag & FS_ARCHIVE_FLAG_LOADED) ? TRUE : FALSE; } +static inline u32 FS_GetArchiveOffset(const FSArchive * p_arc, u32 pos) +{ + return p_arc->base + pos; +} + +static inline BOOL FSi_IsArchiveCanceling(volatile const FSArchive * p_arc) +{ + return (p_arc->flag & FS_ARCHIVE_FLAG_CANCELING) != 0; +} + +static inline BOOL FS_IsArchiveSuspended(volatile const FSArchive * p_arc) +{ + return (p_arc->flag & FS_ARCHIVE_FLAG_SUSPEND) ? TRUE : FALSE; +} + +static inline BOOL FSi_IsArchiveSuspending(volatile const FSArchive * p_arc) +{ + return (p_arc->flag & FS_ARCHIVE_FLAG_SUSPENDING) != 0; +} + +static inline BOOL FSi_IsArchiveRunning(volatile const FSArchive * p_arc) +{ + return (p_arc->flag & FS_ARCHIVE_FLAG_RUNNING) != 0; +} + BOOL FSi_SendCommand(struct FSFile * file, FSCommandType command); BOOL FSi_ExecuteSyncCommand(struct FSFile * file); diff --git a/arm9/lib/include/FS_command.h b/arm9/lib/include/FS_command.h new file mode 100644 index 00000000..db878f3f --- /dev/null +++ b/arm9/lib/include/FS_command.h @@ -0,0 +1,9 @@ +#ifndef NITRO_FS_COMMAND_H_ +#define NITRO_FS_COMMAND_H_ + +#include "FS_file.h" + +void FSi_ReleaseCommand(FSFile * file, FSResult signal); +FSResult FSi_TranslateCommand(FSFile * file, FSCommandType command); + +#endif //NITRO_FS_COMMAND_H_ diff --git a/arm9/lib/include/FS_file.h b/arm9/lib/include/FS_file.h index 89f69d86..92e2149e 100644 --- a/arm9/lib/include/FS_file.h +++ b/arm9/lib/include/FS_file.h @@ -189,4 +189,24 @@ static inline u32 const FS_GetLength(volatile const FSFile * p_file) return p_file->prop.file.bottom - p_file->prop.file.top; } +static inline BOOL FS_IsCanceling(volatile const FSFile * p_file) +{ + return (p_file->stat & FS_FILE_STATUS_CANCEL) ? TRUE : FALSE; +} + +static inline BOOL FS_IsFileSyncMode(volatile const FSFile * p_file) +{ + return (p_file->stat & FS_FILE_STATUS_SYNC) ? TRUE : FALSE; +} + +static inline BOOL FS_IsBusy(volatile const FSFile * p_file) +{ + return p_file->stat & FS_FILE_STATUS_BUSY ? TRUE : FALSE; +} + +static inline BOOL FS_IsSucceeded(volatile const FSFile * p_file) +{ + return (p_file->error == FS_RESULT_SUCCESS) ? TRUE : FALSE; +} + #endif //NITRO_FS_FILE_H_ diff --git a/arm9/lib/include/OS_thread.h b/arm9/lib/include/OS_thread.h index 8820a7a0..c5602559 100644 --- a/arm9/lib/include/OS_thread.h +++ b/arm9/lib/include/OS_thread.h @@ -29,6 +29,7 @@ struct _OSThread }; void OS_SleepThread(OSThreadQueue * queue); +void OS_WakeupThread(OSThreadQueue * queue); static inline void OS_InitThreadQueue(OSThreadQueue * queue) { queue->head = queue->tail = NULL; diff --git a/arm9/lib/src/FS_archive.c b/arm9/lib/src/FS_archive.c new file mode 100644 index 00000000..39daa324 --- /dev/null +++ b/arm9/lib/src/FS_archive.c @@ -0,0 +1,147 @@ +#include "FS_archive.h" +#include "FS_file.h" +#include "FS_command.h" +#include "MI_memory.h" +#include "MI_byteAccess.h" + +FSArchive * arc_list = NULL; +FSDirPos current_dir_pos; + +u32 FSi_GetPackedName(const char * name, int name_len) +{ + u32 ret = 0; + if (name_len <= FS_ARCHIVE_NAME_LEN_MAX) + { + int i = 0; + for (; i < name_len; i++) + { + u32 c = MI_ReadByte(name + i); + if (!c) + break; + c = (u32)(c - 'A'); + if (c <= (u32)('Z' - 'A')) + c = (u32)(c + 'a'); + else + c = (u32)(c + 'A'); + ret |= (u32)(c << (i * 8)); + } + } + return ret; +} + +FSResult FSi_ReadMemCallback(FSArchive * p_arc, u8 * dest, u32 offset, u32 size) +{ + MI_CpuCopy8((const void *)FS_GetArchiveOffset(p_arc, offset), dest, size); + return FS_RESULT_SUCCESS; +} + +FSResult FSi_WriteMemCallback(FSArchive * p_arc, const u8 * src, u32 offset, u32 size) +{ + MI_CpuCopy8(src, (void *)FS_GetArchiveOffset(p_arc, offset), size); + return FS_RESULT_SUCCESS; +} + +FSResult FSi_ReadMemoryCore(FSArchive * p_arc, u8 * dest, u32 offset, u32 size) +{ + MI_CpuCopy8((const void *)offset, dest, size); + return FS_RESULT_SUCCESS; +} + +FSFile * FSi_NextCommand(FSArchive * p_arc) +{ + OSIntrMode bak_psr = OS_DisableInterrupts(); + if (FSi_IsArchiveCanceling(p_arc)) + { + FSFile *p, *q; + p_arc->flag &= ~FS_ARCHIVE_FLAG_CANCELING; + for (p = p_arc->list.next; p; p = q) + { + q = p->link.next; + if (FS_IsCanceling(p)) + { + if (p_arc->list.next == p) + p_arc->list.next = q; + FSi_ReleaseCommand(p, FS_RESULT_CANCELED); + if (!q) + q = p_arc->list.next; + } + } + } + if (!FSi_IsArchiveSuspending(p_arc) && !FS_IsArchiveSuspended(p_arc)) + { + FSFile * p_file = p_arc->list.next; + if (p_file != NULL) + { + const BOOL is_start = !FSi_IsArchiveRunning(p_arc); + if (is_start) + p_arc->flag |= FS_ARCHIVE_FLAG_RUNNING; + OS_RestoreInterrupts(bak_psr); + if (is_start) + { + if ((p_arc->proc_flag & FS_ARCHIVE_PROC_ACTIVATE) != 0) + (*p_arc->proc) (p_file, FS_COMMAND_ACTIVATE); + } + bak_psr = OS_DisableInterrupts(); + p_file->stat |= FS_FILE_STATUS_OPERATING; + if (FS_IsFileSyncMode(p_file)) + { + OS_WakeupThread(p_file->queue); + OS_RestoreInterrupts(bak_psr); + return NULL; + } + OS_RestoreInterrupts(bak_psr); + return p_file; + } + } + if (FSi_IsArchiveRunning(p_arc)) + { + p_arc->flag &= ~FS_ARCHIVE_FLAG_RUNNING; + if (p_arc->proc_flag & FS_ARCHIVE_PROC_IDLE) + { + FSFile tmp; + FS_InitFile(&tmp); + tmp.arc = p_arc; + (*p_arc->proc)(&tmp, FS_COMMAND_IDLE); + } + } + if (FSi_IsArchiveSuspending(p_arc)) + { + p_arc->flag &= ~FS_ARCHIVE_FLAG_SUSPENDING; + p_arc->flag |= FS_ARCHIVE_FLAG_SUSPEND; + OS_WakeupThread(&p_arc->stat_q); + } + OS_RestoreInterrupts(bak_psr); + return NULL; +} + +void FSi_ExecuteAsyncCommand(FSFile * p_file) +{ + FSArchive *const p_arc = p_file->arc; + while (p_file) + { + OSIntrMode bak_psr = OS_DisableInterrupts(); + p_file->stat |= FS_FILE_STATUS_OPERATING; + if (FS_IsFileSyncMode(p_file)) + { + OS_WakeupThread(p_file->queue); + OS_RestoreInterrupts(bak_psr); + break; + } + p_file->stat |= FS_FILE_STATUS_ASYNC; + OS_RestoreInterrupts(bak_psr); + if (FSi_TranslateCommand(p_file, p_file->command) == FS_RESULT_PROC_ASYNC) + break; + p_file = FSi_NextCommand(p_arc); + } +} + +BOOL FSi_ExecuteSyncCommand(FSFile * p_file) +{ + FSFile * p_target; + FSResult ret = FSi_TranslateCommand(p_file, p_file->command); + FSi_ReleaseCommand(p_file, ret); + p_target = FSi_NextCommand(p_file->arc); + if (p_target) + FSi_ExecuteAsyncCommand(p_target); + return FS_IsSucceeded(p_file); +} diff --git a/arm9/lib/src/FS_file.c b/arm9/lib/src/FS_file.c index 8ca89af8..479a5085 100644 --- a/arm9/lib/src/FS_file.c +++ b/arm9/lib/src/FS_file.c @@ -11,16 +11,6 @@ static inline BOOL FSi_IsSlash(u32 c) return (c == '/') || (c == '\\'); } -static inline BOOL FS_IsBusy(volatile const FSFile * p_file) -{ - return p_file->stat & FS_FILE_STATUS_BUSY ? TRUE : FALSE; -} - -static inline BOOL FS_IsSucceeded(volatile const FSFile * p_file) -{ - return p_file->error == FS_RESULT_SUCCESS ? TRUE : FALSE; -} - void FS_Init(u32 default_dma_no) { if (!is_init) |