diff --git a/source/dumper.c b/source/dumper.c index 79d9aa3..a7a8459 100644 --- a/source/dumper.c +++ b/source/dumper.c @@ -10,11 +10,25 @@ void workaroundPartitionZeroAccess(FsDeviceOperator* fsOperator) { if (R_FAILED(fsDeviceOperatorGetGameCardHandle(fsOperator, &handle))) return; FsStorage gameCardStorage; - if (R_FAILED(fsOpenGameCard(&gameCardStorage, handle, 0))) + if (R_FAILED(fsOpenGameCardStorage(&gameCardStorage, handle, 0))) return; fsStorageClose(&gameCardStorage); } +bool openPartitionFs(FsFileSystem* ret, FsDeviceOperator* fsOperator, u32 partition) { + u32 handle; + if (R_FAILED(fsDeviceOperatorGetGameCardHandle(fsOperator, &handle))) { + printf("GetGameCardHandle failed\n"); + return false; + } + Result result; + if (R_FAILED(result = fsMountGameCard(ret, handle, partition))) { + printf("MountGameCard failed %x\n", result); + return false; + } + printf("Opened card\n"); +} + bool dumpPartitionRaw(FsDeviceOperator* fsOperator, u32 partition) { u32 handle; if (R_FAILED(fsDeviceOperatorGetGameCardHandle(fsOperator, &handle))) { @@ -32,7 +46,7 @@ bool dumpPartitionRaw(FsDeviceOperator* fsOperator, u32 partition) { FsStorage gameCardStorage; Result result; - if (R_FAILED(result = fsOpenGameCard(&gameCardStorage, handle, partition))) { + if (R_FAILED(result = fsOpenGameCardStorage(&gameCardStorage, handle, partition))) { printf("MountGameCard failed %x\n", result); return false; } diff --git a/source/dumper.h b/source/dumper.h index 8ac39d1..5a430b3 100644 --- a/source/dumper.h +++ b/source/dumper.h @@ -3,4 +3,5 @@ #include void workaroundPartitionZeroAccess(FsDeviceOperator* fsOperator); +bool openPartitionFs(FsFileSystem* ret, FsDeviceOperator* fsOperator, u32 partition); bool dumpPartitionRaw(FsDeviceOperator* fsOperator, u32 partition); \ No newline at end of file diff --git a/source/filebrowser.c b/source/filebrowser.c new file mode 100644 index 0000000..ae88ef4 --- /dev/null +++ b/source/filebrowser.c @@ -0,0 +1,77 @@ +#include "filebrowser.h" +#include +#include +#include + +void openMainMenu(); + +MenuItem* currentFileListBuf; + +void freeCurrentFileListBuf() { + MenuItem* ptr = currentFileListBuf; + while (ptr != NULL) { + free(ptr->text); + if (ptr->userdata != NULL) + free(ptr->userdata); + ptr++; + } + free(currentFileListBuf); +} +void exitFileList() { + freeCurrentFileListBuf(); + openMainMenu(); +} +char* getParentDir(const char* path) { + char* ptr = strrchr(path, '/'); + if (ptr == NULL || ptr == path) // not found or first character + return NULL; + char* retval = (char*) malloc(ptr - path + 1); + memcpy(retval, path, ptr - path); + retval[ptr - path] = '\0'; + return retval; +} +char* pathJoin(const char* p1, const char* p2) { + size_t p1s = strlen(p1); + if (p1s == 0) + return strdup(p2); + size_t p2s = strlen(p2); + char* retval = (char*) malloc(p1s + 1 + p2s + 1); + memcpy(retval, p1, p1s); + retval[p1s] = '/'; + memcpy(&retval[p1s + 1], p2, p2s + 1); // copy with null terminator + return retval; +} +void printFilesInDir(const char* path) { + int maxMenuItemCount = 48; + MenuItem* buf = (MenuItem*) malloc(sizeof(MenuItem) * (maxMenuItemCount + 1)); + currentFileListBuf = buf; + DIR* dir = opendir(path); + struct dirent* ent; + int bufi = 0; + char* parentDir = getParentDir(path); + if (parentDir != NULL) { + buf[bufi].userdata = parentDir; + buf[bufi].text = strdup(".."); + buf[bufi].callback = printFilesInDirMenuItem; + bufi++; + } + while ((ent = readdir(dir)) != NULL) { + if (ent->d_type == DT_DIR) { + buf[bufi].text = pathJoin(ent->d_name, ""); + buf[bufi].userdata = pathJoin(path, ent->d_name); + buf[bufi].callback = printFilesInDirMenuItem; + } else { + buf[bufi].text = strdup(ent->d_name); + buf[bufi].userdata = buf[bufi].callback = NULL; + } + if (++bufi >= maxMenuItemCount) + break; + } + buf[bufi].text = NULL; + closedir(dir); + menuSetCurrent(buf, exitFileList); +} + +void printFilesInDirMenuItem(MenuItem* item) { + printFilesInDir(item->userdata); +} diff --git a/source/filebrowser.h b/source/filebrowser.h new file mode 100644 index 0000000..6292515 --- /dev/null +++ b/source/filebrowser.h @@ -0,0 +1,6 @@ +#pragma once + +#include "menu.h" + +void printFilesInDir(const char* path); +void printFilesInDirMenuItem(MenuItem* item); \ No newline at end of file diff --git a/source/fsext.c b/source/fsext.c index 9349d75..4f880e1 100644 --- a/source/fsext.c +++ b/source/fsext.c @@ -4,7 +4,7 @@ // IFileSystemProxy -Result fsOpenGameCard(FsStorage* out, u32 handle, u32 partition) { +Result fsOpenGameCardStorage(FsStorage* out, u32 handle, u32 partition) { IpcCommand c; ipcInitialize(&c); @@ -42,6 +42,44 @@ Result fsOpenGameCard(FsStorage* out, u32 handle, u32 partition) { return rc; } +Result fsMountGameCard(FsFileSystem* out, u32 handle, u32 partition) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 handle; + u32 partition; + } PACKED *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 31; + raw->handle = handle; + raw->partition = partition; + + Result rc = serviceIpcDispatch(fsGetServiceSession()); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreate(&out->s, r.Handles[0]); + } + } + + return rc; +} // IDeviceOperator diff --git a/source/fsext.h b/source/fsext.h index 55045bb..612910d 100644 --- a/source/fsext.h +++ b/source/fsext.h @@ -4,7 +4,8 @@ #include // IFileSystemProxy -Result fsOpenGameCard(FsStorage* out, u32 handle, u32 partition); +Result fsOpenGameCardStorage(FsStorage* out, u32 handle, u32 partition); +Result fsMountGameCard(FsFileSystem* out, u32 handle, u32 partition); // IDeviceOperator diff --git a/source/main.c b/source/main.c index fe04064..e60c233 100644 --- a/source/main.c +++ b/source/main.c @@ -2,17 +2,19 @@ #include #include -#include #include #include "menu.h" #include "dumper.h" #include "ccolor.h" +#include "filebrowser.h" FsDeviceOperator fsOperatorInstance; bool shouldExit = false; bool shouldWaitForAnyButton = false; + + void menuExit() { shouldExit = true; } @@ -34,85 +36,32 @@ void dumpPartitionZero(MenuItem* item) { menuWaitForAnyButton(); } -void printFilesInDirMenuItem(MenuItem* item); +void viewPartitionZero() { + startOperation("Mount Partition 0 (SysUpdate)"); + workaroundPartitionZeroAccess(&fsOperatorInstance); + FsFileSystem fs; + if (!openPartitionFs(&fs, &fsOperatorInstance, 0)) { + menuWaitForAnyButton(); + return; + } + if (fsdevMountDevice("test", fs) == -1) { + printf("fsdevMountDevice failed\n"); + menuWaitForAnyButton(); + return; + } + printFilesInDir("test:/"); +} + MenuItem mainMenu[] = { { .text = "Raw Dump Partition 0 (SysUpdate)", .callback = dumpPartitionZero }, - { .text = "Print files on SD Card", .callback = printFilesInDirMenuItem, .userdata = "/" }, + { .text = "View files on Game Card (SysUpdate)", .callback = viewPartitionZero }, { .text = NULL } }; - - -MenuItem* currentFileListBuf; - -void freeCurrentFileListBuf() { - MenuItem* ptr = currentFileListBuf; - while (ptr != NULL) { - free(ptr->text); - if (ptr->userdata != NULL) - free(ptr->userdata); - ptr++; - } - free(currentFileListBuf); -} -void exitFileList() { - freeCurrentFileListBuf(); +void openMainMenu() { menuSetCurrent(mainMenu, menuExit); } -char* getParentDir(const char* path) { - char* ptr = strrchr(path, '/'); - if (ptr == NULL || ptr == path) // not found or first character - return NULL; - char* retval = (char*) malloc(ptr - path + 1); - memcpy(retval, path, ptr - path); - retval[ptr - path] = '\0'; - return retval; -} -char* pathJoin(const char* p1, const char* p2) { - size_t p1s = strlen(p1); - if (p1s == 0) - return strdup(p2); - size_t p2s = strlen(p2); - char* retval = (char*) malloc(p1s + 1 + p2s + 1); - memcpy(retval, p1, p1s); - retval[p1s] = '/'; - memcpy(&retval[p1s + 1], p2, p2s + 1); // copy with null terminator - return retval; -} -void printFilesInDir(const char* path) { - int maxMenuItemCount = 48; - MenuItem* buf = (MenuItem*) malloc(sizeof(MenuItem) * (maxMenuItemCount + 1)); - currentFileListBuf = buf; - DIR* dir = opendir(path); - struct dirent* ent; - int bufi = 0; - char* parentDir = getParentDir(path); - if (parentDir != NULL) { - buf[bufi].userdata = parentDir; - buf[bufi].text = strdup(".."); - buf[bufi].callback = printFilesInDirMenuItem; - bufi++; - } - while ((ent = readdir(dir)) != NULL) { - if (ent->d_type == DT_DIR) { - buf[bufi].text = pathJoin(ent->d_name, ""); - buf[bufi].userdata = pathJoin(path, ent->d_name); - buf[bufi].callback = printFilesInDirMenuItem; - } else { - buf[bufi].text = strdup(ent->d_name); - buf[bufi].userdata = buf[bufi].callback = NULL; - } - if (++bufi >= maxMenuItemCount) - break; - } - buf[bufi].text = NULL; - closedir(dir); - menuSetCurrent(buf, exitFileList); -} -void printFilesInDirMenuItem(MenuItem* item) { - printFilesInDir(item->userdata); -} int main(int argc, char **argv) { @@ -123,8 +72,7 @@ int main(int argc, char **argv) { printf("Failed to open device operator\n"); return -1; } - - menuSetCurrent(mainMenu, menuExit); + openMainMenu(); while(appletMainLoop()) {