diff --git a/include/fs.h b/include/fs.h index 4ee6278..d1ac6bf 100644 --- a/include/fs.h +++ b/include/fs.h @@ -49,20 +49,25 @@ FS_OPEN_APPEND = FA_OPEN_APPEND } FsOpenMode; +typedef FILINFO FsFileInfo; + s32 fMount(FsDrive drive); s32 fUnmount(FsDrive drive); s32 fOpen(const char *const path, FsOpenMode mode); -s32 fClose(s32 handle); s32 fRead(s32 handle, void *const buf, u32 size); s32 fWrite(s32 handle, const void *const buf, u32 size); s32 fSync(s32 handle); s32 fLseek(s32 handle, u32 offset); u32 fTell(s32 handle); u32 fSize(s32 handle); +s32 fClose(s32 handle); +s32 fStat(const char *const path, FsFileInfo *fi); s32 fExpand(s32 handle, u32 size); +s32 fOpenDir(const char *const path); +s32 fReadDir(s32 handle, FsFileInfo *fi, u32 num); +s32 fCloseDir(s32 handle); s32 fMkdir(const char *const path); s32 fRename(const char *const old, const char *const new); -// fStat s32 fUnlink(const char *const path); diff --git a/include/ipc_handler.h b/include/ipc_handler.h index aa3f4d6..2de4a0b 100644 --- a/include/ipc_handler.h +++ b/include/ipc_handler.h @@ -38,30 +38,31 @@ IPC_CMD9_FMOUNT = CMD_ID(0) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), IPC_CMD9_FUNMOUNT = CMD_ID(1) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), IPC_CMD9_FOPEN = CMD_ID(2) | CMD_IN_BUFS(1) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), - IPC_CMD9_FCLOSE = CMD_ID(3) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), - IPC_CMD9_FREAD = CMD_ID(4) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(1) | CMD_PARAMS(1), - IPC_CMD9_FWRITE = CMD_ID(5) | CMD_IN_BUFS(1) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), - IPC_CMD9_FSYNC = CMD_ID(6) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), - IPC_CMD9_FLSEEK = CMD_ID(7) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(2), - IPC_CMD9_FTELL = CMD_ID(8) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), - IPC_CMD9_FSIZE = CMD_ID(9) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), - IPC_CMD9_FEXPAND = CMD_ID(10) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(2), - IPC_CMD9_FOPEN_DIR = CMD_ID(11) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), // Invalid on purpose. Will be decided later. - IPC_CMD9_FREAD_DIR = CMD_ID(12) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_FCLOSE_DIR = CMD_ID(13) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_FMKDIR = CMD_ID(14) | CMD_IN_BUFS(1) | CMD_OUT_BUFS(0) | CMD_PARAMS(0), - IPC_CMD9_FRENAME = CMD_ID(15) | CMD_IN_BUFS(2) | CMD_OUT_BUFS(0) | CMD_PARAMS(0), - IPC_CMD9_FUNLINK = CMD_ID(16) | CMD_IN_BUFS(1) | CMD_OUT_BUFS(0) | CMD_PARAMS(0), - IPC_CMD9_FGETFREE = CMD_ID(17) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_READ_SECTORS = CMD_ID(18) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_WRITE_SECTORS = CMD_ID(19) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_MALLOC = CMD_ID(20) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_FREE = CMD_ID(21) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_LOAD_VERIFY_FIRM = CMD_ID(22) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_FIRM_LAUNCH = CMD_ID(23) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_PREPA_POWER = CMD_ID(24) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_PANIC = CMD_ID(25) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), - IPC_CMD9_EXCEPTION = CMD_ID(26) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15) + IPC_CMD9_FREAD = CMD_ID(3) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(1) | CMD_PARAMS(1), + IPC_CMD9_FWRITE = CMD_ID(4) | CMD_IN_BUFS(1) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), + IPC_CMD9_FSYNC = CMD_ID(5) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), + IPC_CMD9_FLSEEK = CMD_ID(6) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(2), + IPC_CMD9_FTELL = CMD_ID(7) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), + IPC_CMD9_FSIZE = CMD_ID(8) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), + IPC_CMD9_FCLOSE = CMD_ID(9) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), + IPC_CMD9_FSTAT = CMD_ID(10) | CMD_IN_BUFS(1) | CMD_OUT_BUFS(1) | CMD_PARAMS(0), + IPC_CMD9_FEXPAND = CMD_ID(11) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(2), + IPC_CMD9_FOPEN_DIR = CMD_ID(12) | CMD_IN_BUFS(1) | CMD_OUT_BUFS(0) | CMD_PARAMS(0), // Invalid on purpose. Will be decided later. + IPC_CMD9_FREAD_DIR = CMD_ID(13) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(1) | CMD_PARAMS(2), + IPC_CMD9_FCLOSE_DIR = CMD_ID(14) | CMD_IN_BUFS(0) | CMD_OUT_BUFS(0) | CMD_PARAMS(1), + IPC_CMD9_FMKDIR = CMD_ID(15) | CMD_IN_BUFS(1) | CMD_OUT_BUFS(0) | CMD_PARAMS(0), + IPC_CMD9_FRENAME = CMD_ID(16) | CMD_IN_BUFS(2) | CMD_OUT_BUFS(0) | CMD_PARAMS(0), + IPC_CMD9_FUNLINK = CMD_ID(17) | CMD_IN_BUFS(1) | CMD_OUT_BUFS(0) | CMD_PARAMS(0), + IPC_CMD9_FGETFREE = CMD_ID(18) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), + IPC_CMD9_READ_SECTORS = CMD_ID(19) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), + IPC_CMD9_WRITE_SECTORS = CMD_ID(20) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), + IPC_CMD9_MALLOC = CMD_ID(21) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), + IPC_CMD9_FREE = CMD_ID(22) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), + IPC_CMD9_LOAD_VERIFY_FIRM = CMD_ID(23) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), + IPC_CMD9_FIRM_LAUNCH = CMD_ID(24) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), + IPC_CMD9_PREPA_POWER = CMD_ID(25) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), + IPC_CMD9_PANIC = CMD_ID(26) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15), + IPC_CMD9_EXCEPTION = CMD_ID(27) | CMD_IN_BUFS(15) | CMD_OUT_BUFS(15) | CMD_PARAMS(15) } IpcCmd9; typedef enum diff --git a/source/arm11/fs.c b/source/arm11/fs.c index d194ddb..4602e8d 100644 --- a/source/arm11/fs.c +++ b/source/arm11/fs.c @@ -46,12 +46,6 @@ return PXI_sendCmd(IPC_CMD9_FOPEN, cmdBuf, 3); } -s32 fClose(s32 handle) -{ - const u32 cmdBuf = handle; - return PXI_sendCmd(IPC_CMD9_FCLOSE, &cmdBuf, 1); -} - s32 fRead(s32 handle, void *const buf, u32 size) { u32 cmdBuf[3]; @@ -99,6 +93,23 @@ return PXI_sendCmd(IPC_CMD9_FSIZE, &cmdBuf, 1); } +s32 fClose(s32 handle) +{ + const u32 cmdBuf = handle; + return PXI_sendCmd(IPC_CMD9_FCLOSE, &cmdBuf, 1); +} + +s32 fStat(const char *const path, FsFileInfo *fi) +{ + u32 cmdBuf[4]; + cmdBuf[0] = (u32)path; + cmdBuf[1] = strlen(path) + 1; + cmdBuf[2] = (u32)fi; + cmdBuf[3] = sizeof(FsFileInfo); + + return PXI_sendCmd(IPC_CMD9_FSTAT, cmdBuf, 4); +} + s32 fExpand(s32 handle, u32 size) { u32 cmdBuf[2]; @@ -108,6 +119,32 @@ return PXI_sendCmd(IPC_CMD9_FEXPAND, cmdBuf, 2); } +s32 fOpenDir(const char *const path) +{ + u32 cmdBuf[2]; + cmdBuf[0] = (u32)path; + cmdBuf[1] = strlen(path) + 1; + + return PXI_sendCmd(IPC_CMD9_FOPEN_DIR, cmdBuf, 2); +} + +s32 fReadDir(s32 handle, FsFileInfo *fi, u32 num) +{ + u32 cmdBuf[4]; + cmdBuf[0] = (u32)fi; + cmdBuf[1] = sizeof(FsFileInfo) * num; + cmdBuf[2] = handle; + cmdBuf[3] = num; + + return PXI_sendCmd(IPC_CMD9_FREAD_DIR, cmdBuf, 4); +} + +s32 fCloseDir(s32 handle) +{ + const u32 cmdBuf = handle; + return PXI_sendCmd(IPC_CMD9_FCLOSE_DIR, &cmdBuf, 1); +} + s32 fMkdir(const char *const path) { u32 cmdBuf[2]; diff --git a/source/arm9/fs.c b/source/arm9/fs.c index 0485c3c..68bac39 100644 --- a/source/arm9/fs.c +++ b/source/arm9/fs.c @@ -29,6 +29,10 @@ static bool fStatTable[FS_MAX_FILES] = {0}; static u32 fHandles = 0; +static DIR dTable[FS_MAX_DIRS] = {0}; +static bool dStatTable[FS_MAX_DIRS] = {0}; +static u32 dHandles = 0; + s32 fMount(FsDrive drive) @@ -74,7 +78,7 @@ else return i; } -static bool isHandleValid(s32 handle) +static bool isFileHandleValid(s32 handle) { if((u32)handle > fHandles) return false; else return true; @@ -90,28 +94,14 @@ { fStatTable[i] = true; fHandles++; - return i; - } - else return -res; -} - -s32 fClose(s32 handle) -{ - if(fHandles == 0 || !isHandleValid(handle)) return -30; - - FRESULT res = f_close(&fTable[handle]); - if(res == FR_OK) - { - fStatTable[handle] = false; - fHandles--; - return FR_OK; + return i; // Handle } else return -res; } s32 fRead(s32 handle, void *const buf, u32 size) { - if(!isHandleValid(handle)) return -30; + if(!isFileHandleValid(handle)) return -30; UINT bytesRead; FRESULT res = f_read(&fTable[handle], buf, size, &bytesRead); @@ -123,7 +113,7 @@ s32 fWrite(s32 handle, const void *const buf, u32 size) { - if(!isHandleValid(handle)) return -30; + if(!isFileHandleValid(handle)) return -30; UINT bytesWritten; FRESULT res = f_write(&fTable[handle], buf, size, &bytesWritten); @@ -135,7 +125,7 @@ s32 fSync(s32 handle) { - if(!isHandleValid(handle)) return -30; + if(!isFileHandleValid(handle)) return -30; FRESULT res = f_sync(&fTable[handle]); if(res == FR_OK) return res; @@ -144,7 +134,7 @@ s32 fLseek(s32 handle, u32 offset) { - if(!isHandleValid(handle)) return -30; + if(!isFileHandleValid(handle)) return -30; FRESULT res = f_lseek(&fTable[handle], offset); if(res == FR_OK) return res; @@ -153,25 +143,112 @@ u32 fTell(s32 handle) { - if(!isHandleValid(handle)) return 0; + if(!isFileHandleValid(handle)) return 0; return f_tell(&fTable[handle]); } u32 fSize(s32 handle) { - if(!isHandleValid(handle)) return 0; + if(!isFileHandleValid(handle)) return 0; return f_size(&fTable[handle]); } +s32 fClose(s32 handle) +{ + if(fHandles == 0 || !isFileHandleValid(handle)) return -30; + + FRESULT res = f_close(&fTable[handle]); + if(res == FR_OK) + { + fStatTable[handle] = false; + fHandles--; + return FR_OK; + } + else return -res; +} + +s32 fStat(const char *const path, FsFileInfo *fi) +{ + FRESULT res = f_stat(path, fi); + if(res == FR_OK) return res; + else return -res; +} + s32 fExpand(s32 handle, u32 size) { - if(!isHandleValid(handle)) return -30; + if(!isFileHandleValid(handle)) return -30; FRESULT res = f_expand(&fTable[handle], size, 1); if(res == FR_OK) return res; else return -res; } +static s32 findUnusedDirSlot(void) +{ + if(dHandles >= FS_MAX_DIRS) return -1; + + s32 i = 0; + while(i < FS_MAX_DIRS) + { + if(!dStatTable[i]) break; + i++; + } + + if(i == FS_MAX_DIRS) return -1; + else return i; +} + +static bool isDirHandleValid(s32 handle) +{ + if((u32)handle > dHandles) return false; + else return true; +} + +s32 fOpenDir(const char *const path) +{ + const s32 i = findUnusedDirSlot(); + if(i < 0) return -30; + + FRESULT res = f_opendir(&dTable[i], path); + if(res == FR_OK) + { + dStatTable[i] = true; + dHandles++; + return i; // Handle + } + else return -res; +} + +s32 fReadDir(s32 handle, FsFileInfo *fi, u32 num) +{ + if(!isDirHandleValid(handle)) return -30; + if(num > 1000) return -31; + + u32 i; + for(i = 0; i < num; i++) + { + FRESULT res = f_readdir(&dTable[handle], &fi[i]); + if(res != FR_OK) return -res; + if(!fi[i].fname[0]) break; + } + + return i; +} + +s32 fCloseDir(s32 handle) +{ + if(dHandles == 0 || !isDirHandleValid(handle)) return -30; + + FRESULT res = f_closedir(&dTable[handle]); + if(res == FR_OK) + { + dStatTable[handle] = false; + dHandles--; + return FR_OK; + } + else return -res; +} + s32 fMkdir(const char *const path) { FRESULT res = f_mkdir(path); diff --git a/source/arm9/ipc_handler.c b/source/arm9/ipc_handler.c index 7c6be49..f7dec85 100644 --- a/source/arm9/ipc_handler.c +++ b/source/arm9/ipc_handler.c @@ -45,9 +45,6 @@ case IPC_CMD_ID_MASK(IPC_CMD9_FOPEN): result = fOpen((const char *const)buf[0], buf[2]); break; - case IPC_CMD_ID_MASK(IPC_CMD9_FCLOSE): - result = fClose(buf[0]); - break; case IPC_CMD_ID_MASK(IPC_CMD9_FREAD): result = fRead(buf[2], (void *const)buf[0], buf[1]); break; @@ -66,14 +63,23 @@ case IPC_CMD_ID_MASK(IPC_CMD9_FSIZE): result = fSize(buf[0]); break; + case IPC_CMD_ID_MASK(IPC_CMD9_FCLOSE): + result = fClose(buf[0]); + break; + case IPC_CMD_ID_MASK(IPC_CMD9_FSTAT): + result = fStat((const char *const)buf[0], (FsFileInfo*)buf[2]); + break; case IPC_CMD_ID_MASK(IPC_CMD9_FEXPAND): result = fExpand(buf[0], buf[1]); break; case IPC_CMD_ID_MASK(IPC_CMD9_FOPEN_DIR): + result = fOpenDir((const char *const)buf[0]); break; case IPC_CMD_ID_MASK(IPC_CMD9_FREAD_DIR): + result = fReadDir(buf[2], (FsFileInfo*)buf[0], buf[3]); break; case IPC_CMD_ID_MASK(IPC_CMD9_FCLOSE_DIR): + result = fCloseDir(buf[0]); break; case IPC_CMD_ID_MASK(IPC_CMD9_FMKDIR): result = fMkdir((const char *const)buf[0]);