diff options
Diffstat (limited to 'arm9/lib')
-rw-r--r-- | arm9/lib/include/FS_archive.h | 23 | ||||
-rw-r--r-- | arm9/lib/include/FS_file.h | 19 | ||||
-rw-r--r-- | arm9/lib/include/FS_rom.h | 6 | ||||
-rw-r--r-- | arm9/lib/include/MI_byteAccess.h | 9 | ||||
-rw-r--r-- | arm9/lib/include/OS_thread.h | 6 | ||||
-rw-r--r-- | arm9/lib/src/FS_file.c | 258 |
6 files changed, 319 insertions, 2 deletions
diff --git a/arm9/lib/include/FS_archive.h b/arm9/lib/include/FS_archive.h index 65bb2ea1..66840b32 100644 --- a/arm9/lib/include/FS_archive.h +++ b/arm9/lib/include/FS_archive.h @@ -8,6 +8,19 @@ struct FSFile; struct FSArchive; +#define FS_ARCHIVE_NAME_LEN_MAX 3 + +#define FS_ARCHIVE_FLAG_REGISTER 0x00000001 +#define FS_ARCHIVE_FLAG_LOADED 0x00000002 +#define FS_ARCHIVE_FLAG_TABLE_LOAD 0x00000004 +#define FS_ARCHIVE_FLAG_SUSPEND 0x00000008 +#define FS_ARCHIVE_FLAG_RUNNING 0x00000010 +#define FS_ARCHIVE_FLAG_CANCELING 0x00000020 +#define FS_ARCHIVE_FLAG_SUSPENDING 0x00000040 +#define FS_ARCHIVE_FLAG_UNLOADING 0x00000080 +#define FS_ARCHIVE_FLAG_IS_ASYNC 0x00000100 +#define FS_ARCHIVE_FLAG_IS_SYNC 0x00000200 + typedef enum { FS_COMMAND_ASYNC_BEGIN = 0, FS_COMMAND_READFILE = FS_COMMAND_ASYNC_BEGIN, @@ -87,4 +100,14 @@ typedef struct FSArchive u32 proc_flag; } FSArchive; +FSArchive * const FS_FindArchive(const char * path, int offset); + +static inline BOOL FS_IsArchiveLoaded(volatile const FSArchive * p_arc) +{ + return (p_arc->flag & FS_ARCHIVE_FLAG_LOADED) ? TRUE : FALSE; +} + +BOOL FSi_SendCommand(struct FSFile * file, FSCommandType command); +BOOL FSi_ExecuteSyncCommand(struct FSFile * file); + #endif //NITRO_FS_ARCHIVE_H_ diff --git a/arm9/lib/include/FS_file.h b/arm9/lib/include/FS_file.h index 08a698d0..4871b660 100644 --- a/arm9/lib/include/FS_file.h +++ b/arm9/lib/include/FS_file.h @@ -5,6 +5,21 @@ #include "FS_archive.h" +#define FS_FILE_STATUS_BUSY 0x00000001 +#define FS_FILE_STATUS_CANCEL 0x00000002 +#define FS_FILE_STATUS_SYNC 0x00000004 +#define FS_FILE_STATUS_ASYNC 0x00000008 +#define FS_FILE_STATUS_IS_FILE 0x00000010 +#define FS_FILE_STATUS_IS_DIR 0x00000020 +#define FS_FILE_STATUS_OPERATING 0x00000040 + +typedef enum FSSeekFileMode +{ + FS_SEEK_SET = 0, + FS_SEEK_CUR, + FS_SEEK_END +} FSSeekFileMode; + struct FSFile; #define FS_DMA_NOT_USE ((u32)~0) @@ -127,7 +142,6 @@ typedef struct FSFile FSCommandType command; FSResult error; OSThreadQueue queue[1]; - u32 filler; // Figure out what this actually is union { struct { @@ -154,11 +168,12 @@ typedef struct FSFile FSOpenFileFastInfo openfilefast; FSOpenFileDirectInfo openfiledirect; FSCloseFileInfo closefile; - }; + } arg; } FSFile; u32 FS_SetDefaultDMA(u32 dma_no); // returns the previous selection void FS_InitFile(FSFile * p_file); +BOOL FS_WaitAsync(FSFile * p_file); #endif //NITRO_FS_FILE_H_ diff --git a/arm9/lib/include/FS_rom.h b/arm9/lib/include/FS_rom.h new file mode 100644 index 00000000..fc62b579 --- /dev/null +++ b/arm9/lib/include/FS_rom.h @@ -0,0 +1,6 @@ +#ifndef NITRO_FS_ROM_H_ +#define NITRO_FS_ROM_H_ + +void FSi_InitRom(u32 default_dma_no); + +#endif //NITRO_FS_ROM_H_ diff --git a/arm9/lib/include/MI_byteAccess.h b/arm9/lib/include/MI_byteAccess.h new file mode 100644 index 00000000..10dae4c9 --- /dev/null +++ b/arm9/lib/include/MI_byteAccess.h @@ -0,0 +1,9 @@ +#ifndef NITRO_MI_BYTEACCESS_H_ +#define NITRO_MI_BYTEACCESS_H_ + +static inline u8 MI_ReadByte(const void *address) +{ + return *(u8 *)address; +} + +#endif //NITRO_MI_BYTEACCESS_H_ diff --git a/arm9/lib/include/OS_thread.h b/arm9/lib/include/OS_thread.h index 207dac1b..8820a7a0 100644 --- a/arm9/lib/include/OS_thread.h +++ b/arm9/lib/include/OS_thread.h @@ -28,4 +28,10 @@ struct _OSThread u8 padding[0x80]; //todo: not the correct size but idfk }; +void OS_SleepThread(OSThreadQueue * queue); +static inline void OS_InitThreadQueue(OSThreadQueue * queue) +{ + queue->head = queue->tail = NULL; +} + #endif //POKEDIAMOND_OS_THREAD_H diff --git a/arm9/lib/src/FS_file.c b/arm9/lib/src/FS_file.c new file mode 100644 index 00000000..8ca89af8 --- /dev/null +++ b/arm9/lib/src/FS_file.c @@ -0,0 +1,258 @@ +#include "nitro.h" +#include "MI_byteAccess.h" +#include "FS_rom.h" +#include "FS_file.h" + +extern FSDirPos current_dir_pos; +BOOL is_init = FALSE; + +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) + { + is_init = TRUE; + FSi_InitRom(default_dma_no); + } +} + +BOOL FS_IsAvailable(void) +{ + return is_init; +} + +void FS_InitFile(FSFile * p_file) +{ + p_file->link.next = p_file->link.prev = NULL; + OS_InitThreadQueue(p_file->queue); + p_file->arc = NULL; + p_file->command = FS_COMMAND_INVALID; + p_file->stat = 0; +} + +static BOOL FSi_FindPath(FSFile * p_dir, const char * path, FSFileID * p_file_id, FSDirPos * p_dir_pos) +{ + FSDirPos pos; + if (FSi_IsSlash(MI_ReadByte(path))) + { + pos.arc = current_dir_pos.arc; + pos.own_id = 0; + pos.pos = 0; + pos.index = 0; + path++; + } + else + { + int i; + pos = current_dir_pos; + for (i = 0; i <= FS_ARCHIVE_NAME_LEN_MAX; ++i) + { + u32 c = MI_ReadByte(path + i); + if (!c || FSi_IsSlash(c)) + break; + else if (c == ':') + { + FSArchive * const p_arc = FS_FindArchive(path, i); + if (!p_arc) + { + return FALSE; + } + else if (!FS_IsArchiveLoaded(p_arc)) + { + return FALSE; + } + pos.arc = p_arc; + pos.pos = 0; + pos.index = 0; + pos.own_id = 0; + path += i + 1; + if (FSi_IsSlash(MI_ReadByte(path))) + ++path; + break; + } + } + } + p_dir->arc = pos.arc; + p_dir->arg.findpath.path = path; + p_dir->arg.findpath.pos = pos; + if (p_dir_pos) + { + p_dir->arg.findpath.find_directory = TRUE; + p_dir->arg.findpath.result.dir = p_dir_pos; + } + else + { + p_dir->arg.findpath.find_directory = FALSE; + p_dir->arg.findpath.result.file = p_file_id; + } + return FSi_SendCommand(p_dir, FS_COMMAND_FINDPATH); +} + +int FSi_ReadFileCore(FSFile * p_file, void * dst, s32 len, BOOL async) +{ + { + const s32 pos = (s32)p_file->prop.file.pos; + const s32 rest = (s32)p_file->prop.file.bottom - pos; + const u32 org = (u32)len; + if (len > rest) + len = rest; + if (len < 0) + len = 0; + p_file->arg.readfile.dst = dst; + p_file->arg.readfile.len_org = org; + p_file->arg.readfile.len = (u32)(len); + if (!async) + p_file->stat |= FS_FILE_STATUS_SYNC; + (void)FSi_SendCommand(p_file, FS_COMMAND_READFILE); + if (!async) + { + if (FS_WaitAsync(p_file)) + len = (s32)p_file->prop.file.pos - pos; + else + len = -1; + } + } + return len; +} + +BOOL FS_ConvertPathToFileID(FSFileID * p_file_id, const char * path) +{ + FSFile dir; + FS_InitFile(&dir); + if (!FSi_FindPath(&dir, path, p_file_id, NULL)) + return FALSE; + return TRUE; +} + +BOOL FS_OpenFileDirect(FSFile * p_file, FSArchive * p_arc, u32 image_top, u32 image_bottom, u32 file_index) +{ + p_file->arc = p_arc; + p_file->arg.openfiledirect.index = file_index; + p_file->arg.openfiledirect.top = image_top; + p_file->arg.openfiledirect.bottom = image_bottom; + if (!FSi_SendCommand(p_file, FS_COMMAND_OPENFILEDIRECT)) + return FALSE; + p_file->stat |= FS_FILE_STATUS_IS_FILE; + p_file->stat &= ~FS_FILE_STATUS_IS_DIR; + return TRUE; +} + +BOOL FS_OpenFileFast(FSFile * p_file, FSFileID file_id) +{ + if (!file_id.arc) + return FALSE; + p_file->arc = file_id.arc; + p_file->arg.openfilefast.id = file_id; + if (!FSi_SendCommand(p_file, FS_COMMAND_OPENFILEFAST)) + return FALSE; + p_file->stat |= FS_FILE_STATUS_IS_FILE; + p_file->stat &= ~FS_FILE_STATUS_IS_DIR; + return TRUE; +} + +BOOL FS_OpenFile(FSFile * p_file, const char * path) +{ + FSFileID file_id; + return FS_ConvertPathToFileID(&file_id, path) && FS_OpenFileFast(p_file, file_id); +} + +BOOL FS_CloseFile(FSFile * p_file) +{ + if (!FSi_SendCommand(p_file, FS_COMMAND_CLOSEFILE)) + return FALSE; + p_file->arc = NULL; + p_file->command = FS_COMMAND_INVALID; + p_file->stat &= ~(FS_FILE_STATUS_IS_FILE | FS_FILE_STATUS_IS_DIR); + return TRUE; +} + +BOOL FS_WaitAsync(FSFile * p_file) +{ + BOOL is_owner = FALSE; + OSIntrMode bak_par = OS_DisableInterrupts(); + if (FS_IsBusy(p_file)) + { + is_owner = !(p_file->stat & (FS_FILE_STATUS_SYNC | FS_FILE_STATUS_OPERATING)); + if (is_owner) + { + p_file->stat |= FS_FILE_STATUS_SYNC; + do + { + OS_SleepThread(p_file->queue); + } while (!(p_file->stat & FS_FILE_STATUS_OPERATING)); + } + else + { + do + { + OS_SleepThread(p_file->queue); + } while (FS_IsBusy(p_file)); + } + } + (void)OS_RestoreInterrupts(bak_par); + if (is_owner) + { + return FSi_ExecuteSyncCommand(p_file); + } + + return FS_IsSucceeded(p_file); +} + +int FS_ReadFileAsync(FSFile * p_file, void * dst, s32 len) +{ + return FSi_ReadFileCore(p_file, dst, len, TRUE); +} + +int FS_ReadFile(FSFile * p_file, void * dst, s32 len) +{ + return FSi_ReadFileCore(p_file, dst, len, FALSE); +} + +BOOL FS_SeekFile(FSFile * p_file, int offset, FSSeekFileMode origin) +{ + switch (origin) + { + case FS_SEEK_SET: + offset += p_file->prop.file.top; + break; + case FS_SEEK_CUR: + offset += p_file->prop.file.pos; + break; + case FS_SEEK_END: + offset += p_file->prop.file.bottom; + break; + default: + return FALSE; + } + if (offset < (s32)p_file->prop.file.top) + offset = (s32)p_file->prop.file.top; + if (offset > (s32)p_file->prop.file.bottom) + offset = (s32)p_file->prop.file.bottom; + p_file->prop.file.pos = offset; + return TRUE; +} + +BOOL FS_ChangeDir(const char * path) +{ + FSDirPos pos; + FSFile dir; + FS_InitFile(&dir); + if (!FSi_FindPath(&dir, path, NULL, &pos)) + return FALSE; + current_dir_pos = pos; + return TRUE; +} |