From 67fd193430b5bb66b6b1015c927212b72c537332 Mon Sep 17 00:00:00 2001 From: BernardoGiordano Date: Sun, 7 Jun 2026 22:30:03 +0200 Subject: [PATCH] FIx #31 --- src/universal/injector.c | 165 +++++++++++++++++++++++++++++++++++---- 1 file changed, 150 insertions(+), 15 deletions(-) diff --git a/src/universal/injector.c b/src/universal/injector.c index b2ba983..010c984 100644 --- a/src/universal/injector.c +++ b/src/universal/injector.c @@ -4,30 +4,142 @@ #include #include +// On the 3DS, fopen on a folder returns NULL, so a path we cannot open as a +// file is treated as a directory to navigate into. +int is_directory(char* path) +{ + FILE* file = fopen(path, "rb"); + if (file) + { + fclose(file); + return 0; + } + return 1; +} + +// Returns a pointer to the last path component (the part after the final '/'). +char* base_name(char* path) +{ + int last = -1; + for (int i = 0; path[i] != '\0'; i++) + { + if (path[i] == '/') + { + last = i; + } + } + return path + last + 1; +} + +// Trims the last path component in place, moving one level up. +void path_up(char* path) +{ + int last = -1; + for (int i = 0; path[i] != '\0'; i++) + { + if (path[i] == '/') + { + last = i; + } + } + if (last > 0) + { + path[last] = '\0'; + } +} + int main(int argc, char** argv) { - unsigned char version = *argv[0]; - struct directory* injectables = read_directory("/3ds/PKSM/inject"); + unsigned char version = *argv[0]; - if (injectables->count == 0) + char path[768]; + strcpy(path, "/3ds/PKSM/inject"); + + struct directory* root = read_directory(path); + int rootCount = root->count; + delete_directory(root); + + if (rootCount == 0) { - delete_directory(injectables); gui_warn("There are no files in \'/3ds/PKSM/inject\'!\nPlace Wonder Card or Pokemon files there"); return 0; } - int chosen = gui_menu_20x2("Choose a file to inject", injectables->count, injectables->files); + // Browse starting from the inject folder, descending into folders until a + // file is chosen. chosenFile ends up holding the path of the picked file. + char chosenFile[768]; + chosenFile[0] = '\0'; + + while (chosenFile[0] == '\0') + { + struct directory* dir = read_directory(path); + int atRoot = !strcmp(path, "/3ds/PKSM/inject"); + + // First entry navigates up (or cancels at the root), the rest are the + // folder contents shown by name. + int total = dir->count + 1; + char** labels = malloc(total * sizeof(char*)); + if (!labels) + { + delete_directory(dir); + gui_warn("Out of memory."); + return 0; + } + if (atRoot) + { + labels[0] = "[ Cancel ]"; + } + else + { + labels[0] = "[ .. ]"; + } + for (int i = 0; i < dir->count; i++) + { + labels[i + 1] = base_name(dir->files[i]); + } + + int chosen = gui_menu_20x2("Choose a file to inject.\nSelect a folder to open it.", total, labels); + free(labels); + + if (chosen <= 0) + { + delete_directory(dir); + if (atRoot) + { + return 0; + } + path_up(path); + continue; + } + + if (strlen(dir->files[chosen - 1]) >= 768) + { + gui_warn("Path is too long to open."); + delete_directory(dir); + continue; + } + + if (is_directory(dir->files[chosen - 1])) + { + strcpy(path, dir->files[chosen - 1]); + delete_directory(dir); + continue; + } + + strcpy(chosenFile, dir->files[chosen - 1]); + delete_directory(dir); + } + char* extension = NULL; - if (strlen(injectables->files[chosen]) > 3) + if (strlen(chosenFile) > 3) { - if (injectables->files[chosen][strlen(injectables->files[chosen]) - 4] == '.') + if (chosenFile[strlen(chosenFile) - 4] == '.') { - extension = injectables->files[chosen] + strlen(injectables->files[chosen]) - 3; + extension = chosenFile + strlen(chosenFile) - 3; } - else if (strlen(injectables->files[chosen]) > 7 && - injectables->files[chosen][strlen(injectables->files[chosen]) - 8] == '.') + else if (strlen(chosenFile) > 7 && chosenFile[strlen(chosenFile) - 8] == '.') { - extension = injectables->files[chosen] + strlen(injectables->files[chosen]) - 7; + extension = chosenFile + strlen(chosenFile) - 7; } } @@ -37,11 +149,22 @@ int main(int argc, char** argv) !strcasecmp(extension, "wc7") || !strcasecmp(extension, "wc7full") || !strcasecmp(extension, "wb7") || !strcasecmp(extension, "wb7full"))) { - FILE* file = fopen(injectables->files[chosen], "rb"); + FILE* file = fopen(chosenFile, "rb"); + if (!file) + { + gui_warn("Could not open the selected file."); + return 0; + } fseek(file, 0, SEEK_END); int size = ftell(file); fseek(file, 0, SEEK_SET); char* data = malloc(size); + if (!data) + { + fclose(file); + gui_warn("Out of memory."); + return 0; + } fread(data, 1, size, file); fclose(file); @@ -92,12 +215,25 @@ int main(int argc, char** argv) if (!gui_boxes(&fromStorage, &box, &slot, 0)) { bool ekx = true; - FILE* file = fopen(injectables->files[chosen], "rb"); + FILE* file = fopen(chosenFile, "rb"); + if (!file) + { + gui_warn("Could not open the selected file."); + sav_box_encrypt(); + return 0; + } fseek(file, 0, SEEK_END); int size = ftell(file); fseek(file, 0, SEEK_SET); char* data = malloc(size); - fread(data, size, size, file); + if (!data) + { + fclose(file); + gui_warn("Out of memory."); + sav_box_encrypt(); + return 0; + } + fread(data, 1, size, file); fclose(file); enum Generation gen; @@ -172,6 +308,5 @@ int main(int argc, char** argv) gui_warn("Extension not recognized!"); } - delete_directory(injectables); return 0; }