diff --git a/source/common/common.h b/source/common/common.h index 7eca95a..b74b3b1 100644 --- a/source/common/common.h +++ b/source/common/common.h @@ -49,7 +49,7 @@ #endif // GodMode9 version -#define VERSION "1.1.6" +#define VERSION "1.1.7" // Maximum payload size (arbitrary value!) #define SELF_MAX_SIZE (320 * 1024) // 320kB diff --git a/source/fs/filetype.h b/source/fs/filetype.h index 3ef1bf1..30a8560 100644 --- a/source/fs/filetype.h +++ b/source/fs/filetype.h @@ -40,6 +40,7 @@ #define FTYPE_TIKBUILD(tp) (tp&(GAME_TICKET|SYS_TICKDB|BIN_TIKDB)) #define FTYPE_KEYBUILD(tp) (tp&(BIN_KEYDB|BIN_LEGKEY)) #define FTYPE_TITLEINFO(tp) (tp&(GAME_SMDH|GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_TMD|GAME_NDS)) +#define FTYPE_RENAMABLE(tp) (tp&(GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_NDS)) #define FTYPE_TRANSFERABLE(tp) ((u32) (tp&(IMG_FAT|FLAG_CTR)) == (u32) (IMG_FAT|FLAG_CTR)) #define FTYPE_HSINJECTABLE(tp) ((u32) (tp&(GAME_NCCH|FLAG_CXI)) == (u32) (GAME_NCCH|FLAG_CXI)) #define FTYPE_RESTORABLE(tp) (tp&(IMG_NAND)) diff --git a/source/fs/fsgame.c b/source/fs/fsgame.c index d18cfe7..2a226a7 100644 --- a/source/fs/fsgame.c +++ b/source/fs/fsgame.c @@ -1,6 +1,8 @@ #include "fsgame.h" +#include "fsperm.h" #include "gameutil.h" #include "ui.h" +#include "ff.h" void SetDirGoodNames(DirStruct* contents) { char goodname[256]; @@ -16,3 +18,34 @@ void SetDirGoodNames(DirStruct* contents) { entry->name = entry->path + plen + 1; } } + +bool GoodRenamer(DirEntry* entry, bool ask) { + char goodname[256]; // get goodname + if ((GetGoodName(goodname, entry->path, false) != 0) || + (strncmp(goodname + strnlen(goodname, 256) - 4, ".tmd", 4) == 0)) // no TMD, please + return false; + + if (ask) { // ask for confirmatiom + char oldname_tr[32+1]; + char newname_ww[256]; + TruncateString(oldname_tr, entry->name, 32, 8); + strncpy(newname_ww, goodname, 256); + WordWrapString(newname_ww, 32); + if (!ShowPrompt(true, "%s\nRename to good name?\n \n%s", oldname_tr, newname_ww)) + return true; // call it a success because user choice + } + + char npath[256]; // get new path + strncpy(npath, entry->path, 256 - 1); + char* nname = strrchr(npath, '/'); + if (!nname) return false; + nname++; + strncpy(nname, goodname, 256 - 1 - (nname - npath)); + // actual rename + if (!CheckDirWritePermissions(entry->path)) return false; + if (f_rename(entry->path, npath) != FR_OK) return false; + strncpy(entry->path, npath, 256); + entry->name = entry->path + (nname - npath); + + return true; +} diff --git a/source/fs/fsgame.h b/source/fs/fsgame.h index d6fc59b..d9de99e 100644 --- a/source/fs/fsgame.h +++ b/source/fs/fsgame.h @@ -4,3 +4,4 @@ #include "fsdir.h" void SetDirGoodNames(DirStruct* contents); +bool GoodRenamer(DirEntry* entry, bool ask); diff --git a/source/godmode.c b/source/godmode.c index e1db100..181e52f 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -5,6 +5,7 @@ #include "fsdrive.h" #include "fsutil.h" #include "fsperm.h" +#include "fsgame.h" #include "gameutil.h" #include "keydbutil.h" #include "nandutil.h" @@ -672,14 +673,16 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur bool tik_buildable = (FTYPE_TIKBUILD(filetype)) && !in_output_path; bool key_buildable = (FTYPE_KEYBUILD(filetype)) && !in_output_path; bool titleinfo = (FTYPE_TITLEINFO(filetype)); + bool renamable = (FTYPE_RENAMABLE(filetype)); bool transferable = (FTYPE_TRANSFERABLE(filetype) && IS_A9LH && (drvtype & DRV_FAT)); bool hsinjectable = (FTYPE_HSINJECTABLE(filetype)); bool restorable = (FTYPE_RESTORABLE(filetype) && IS_A9LH && !(drvtype & DRV_SYSNAND)); bool ebackupable = (FTYPE_EBACKUP(filetype)); bool xorpadable = (FTYPE_XORPAD(filetype)); bool launchable = ((FTYPE_PAYLOAD(filetype)) && (drvtype & DRV_FAT)); - bool special_opt = mountable || verificable || decryptable || encryptable || cia_buildable || cia_buildable_legit || - tik_buildable || key_buildable || titleinfo || hsinjectable || restorable || xorpadable || launchable || ebackupable; + bool special_opt = mountable || verificable || decryptable || encryptable || cia_buildable || cia_buildable_legit || cxi_dumpable || + tik_buildable || key_buildable || titleinfo || renamable || transferable || hsinjectable || restorable || xorpadable || + launchable || ebackupable; char pathstr[32+1]; TruncateString(pathstr, curr_entry->path, 32, 8); @@ -715,7 +718,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur (filetype & GAME_BOSS ) ? "BOSS file options..." : (filetype & GAME_NUSCDN)? "Decrypt NUS/CDN file" : (filetype & GAME_SMDH) ? "Show SMDH title info" : - (filetype & GAME_NDS) ? "Show NDS title info" : + (filetype & GAME_NDS) ? "NDS image options..." : (filetype & GAME_TICKET)? "Ticket options..." : (filetype & SYS_FIRM ) ? "FIRM image options..." : (filetype & SYS_TICKDB) ? (tik_buildable) ? "Ticket.db options..." : "Mount as ticket.db" : @@ -826,6 +829,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur int verify = (verificable) ? ++n_opt : -1; int ctrtransfer = (transferable) ? ++n_opt : -1; int hsinject = (hsinjectable) ? ++n_opt : -1; + int rename = (renamable) ? ++n_opt : -1; int xorpad = (xorpadable) ? ++n_opt : -1; int xorpad_inplace = (xorpadable) ? ++n_opt : -1; int launch = (launchable) ? ++n_opt : -1; @@ -844,6 +848,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur if (verify > 0) optionstr[verify-1] = "Verify file"; if (ctrtransfer > 0) optionstr[ctrtransfer-1] = "Transfer image to CTRNAND"; if (hsinject > 0) optionstr[hsinject-1] = "Inject to H&S"; + if (rename > 0) optionstr[rename-1] = "Rename file"; if (xorpad > 0) optionstr[xorpad-1] = "Build XORpads (SD output)"; if (xorpad_inplace > 0) optionstr[xorpad_inplace-1] = "Build XORpads (inplace)"; if (launch > 0) optionstr[launch-1] = "Launch as ARM9 payload"; @@ -1097,6 +1102,23 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur } else ShowPrompt(false, "%s\nBuild database %s.", path_out, (BuildKeyDb(curr_entry->path, true) == 0) ? "success" : "failed"); return 0; + } else if (user_select == rename) { // -> Game file renamer + if ((n_marked > 1) && ShowPrompt(true, "Try to rename all %lu selected files?", n_marked)) { + u32 n_success = 0; + ShowProgress(0, 0, ""); + for (u32 i = 0; i < current_dir->n_entries; i++) { + DirEntry* entry = &(current_dir->entry[i]); + if (!current_dir->entry[i].marked) continue; + ShowProgress(i+1, current_dir->n_entries, entry->name); + if (!GoodRenamer(entry, false)) continue; + n_success++; + current_dir->entry[i].marked = false; + } + ShowPrompt(false, "%lu/%lu renamed ok", n_success, n_marked); + } else if (!GoodRenamer(&(current_dir->entry[*cursor]), true)) { + ShowPrompt(false, "%s\nGood name not found\n(Maybe try decrypt?)", pathstr); + } + return 0; } else if (user_select == show_info) { // -> Show title info if (ShowGameFileTitleInfo(curr_entry->path) != 0) ShowPrompt(false, "Title info: not found");