diff --git a/arm9/source/filesys/filetype.h b/arm9/source/filesys/filetype.h index 8b6f07b..47ba861 100644 --- a/arm9/source/filesys/filetype.h +++ b/arm9/source/filesys/filetype.h @@ -46,11 +46,11 @@ #define FLAG_CXI (1ULL<<63) #define FTYPE_MOUNTABLE(tp) (tp&(IMG_FAT|IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_EXEFS|GAME_ROMFS|GAME_NDS|GAME_TAD|SYS_FIRM|SYS_DIFF|SYS_DISA|SYS_TICKDB|BIN_KEYDB)) -#define FTYPE_VERIFICABLE(tp) (tp&(IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_TMD|GAME_BOSS|SYS_FIRM)) +#define FTYPE_VERIFICABLE(tp) (tp&(IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_TMD|GAME_TIE|GAME_BOSS|SYS_FIRM)) #define FTYPE_DECRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS|GAME_NUSCDN|SYS_FIRM|BIN_KEYDB)) #define FTYPE_ENCRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS|BIN_KEYDB)) -#define FTYPE_CIABUILD(tp) ((tp&(GAME_NCSD|GAME_NCCH|GAME_TMD)) || ((tp&GAME_NDS)&&(tp&(FLAG_DSIW)))) -#define FTYPE_CIABUILD_L(tp) (FTYPE_CIABUILD(tp) && (tp&(GAME_TMD))) +#define FTYPE_CIABUILD(tp) ((tp&(GAME_NCSD|GAME_NCCH|GAME_TMD|GAME_TIE)) || ((tp&GAME_NDS)&&(tp&(FLAG_DSIW)))) +#define FTYPE_CIABUILD_L(tp) (FTYPE_CIABUILD(tp) && (tp&(GAME_TMD|GAME_TIE))) #define FTYPE_CIAINSTALL(tp) ((tp&(GAME_NCSD|GAME_NCCH|GAME_CIA)) || ((tp&GAME_NDS)&&(tp&(FLAG_DSIW))) || (tp&(GAME_TMD)&&(tp&(FLAG_NUSCDN)))) #define FTYPE_CXIDUMP(tp) (tp&(GAME_TMD)) #define FTYPE_UNINSTALL(tp) (tp&(GAME_TIE)) diff --git a/arm9/source/godmode.c b/arm9/source/godmode.c index ab61a8e..69f0985 100644 --- a/arm9/source/godmode.c +++ b/arm9/source/godmode.c @@ -1157,6 +1157,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan (strncmp(clipboard->entry[0].path, file_path, 256) != 0)) ? (int) ++n_opt : -1; int searchdrv = (DriveType(current_path) & DRV_SEARCH) ? ++n_opt : -1; + int titleman = (filetype & GAME_TIE) ? ++n_opt : -1; if (special > 0) optionstr[special-1] = (filetype & IMG_NAND ) ? "NAND image options..." : (filetype & IMG_FAT ) ? (transferable) ? "CTRNAND options..." : "Mount as FAT image" : @@ -1197,6 +1198,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan if (copystd > 0) optionstr[copystd-1] = "Copy to " OUTPUT_PATH; if (inject > 0) optionstr[inject-1] = "Inject data @offset"; if (searchdrv > 0) optionstr[searchdrv-1] = "Open containing folder"; + if (titleman > 0) optionstr[titleman-1] = "Open title folder"; int user_select = ShowSelectPrompt(n_opt, optionstr, (n_marked > 1) ? "%s\n%(%lu files selected)" : "%s", pathstr, n_marked); @@ -1277,8 +1279,12 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan } return 0; } - else if (user_select == searchdrv) { // -> search drive, open containing path - char* last_slash = strrchr(file_path, '/'); + else if ((user_select == searchdrv) || (user_select == titleman)) { // -> open containing path + char temp_path[256]; + if (user_select == searchdrv) strncpy(temp_path, file_path, 256); + else if (GetTieContentPath(temp_path, file_path) != 0) return 0; + + char* last_slash = strrchr(temp_path, '/'); if (last_slash) { if (N_PANES) { // switch to next pane memcpy((*pane)->path, current_path, 256); // store current pane state @@ -1286,12 +1292,12 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan (*pane)->scroll = *scroll; if (++*pane >= panedata + N_PANES) *pane -= N_PANES; } - snprintf(current_path, last_slash - file_path + 1, "%s", file_path); + snprintf(current_path, last_slash - temp_path + 1, "%s", temp_path); GetDirContents(current_dir, current_path); *scroll = 0; for (*cursor = 1; *cursor < current_dir->n_entries; (*cursor)++) { DirEntry* entry = &(current_dir->entry[*cursor]); - if (strncasecmp(entry->path, file_path, 256) == 0) break; + if (strncasecmp(entry->path, temp_path, 256) == 0) break; } if (*cursor >= current_dir->n_entries) *cursor = 1; diff --git a/arm9/source/utils/gameutil.c b/arm9/source/utils/gameutil.c index 33f3b82..ae639a9 100644 --- a/arm9/source/utils/gameutil.c +++ b/arm9/source/utils/gameutil.c @@ -261,8 +261,7 @@ u32 GetTmdContentPath(char* path_content, const char* path_tmd) { return 0; } -u32 GetTieContentPath(char* path_content, const char* path_tie) { - char path_tmd[64]; +u32 GetTieTmdPath(char* path_tmd, const char* path_tie) { char drv[3] = { 0x00 }; u64 tid64 = 0; @@ -297,6 +296,17 @@ u32 GetTieContentPath(char* path_content, const char* path_tie) { snprintf(path_tmd, 64, "%2.2s/title/%08lX/%08lX/content/%08lx.tmd", drv, tid_high, tid_low, tie.tmd_content_id); + // done + return 0; +} + +u32 GetTieContentPath(char* path_content, const char* path_tie) { + char path_tmd[64]; + + // get the TMD path first + if (GetTieTmdPath(path_tmd, path_tie) != 0) + return 1; + // let the TMD content path function take over return GetTmdContentPath(path_content, path_tmd); } @@ -704,6 +714,17 @@ u32 VerifyTmdFile(const char* path, bool cdn) { return 0; } +u32 VerifyTieFile(const char* path) { + char path_tmd[64]; + + // get the TMD path + if (GetTieTmdPath(path_tmd, path) != 0) + return 1; + + // let the TMD verificator take over + return VerifyTmdFile(path_tmd, false); +} + u32 VerifyFirmFile(const char* path) { char pathstr[32 + 1]; TruncateString(pathstr, path, 32, 8); @@ -830,6 +851,8 @@ u32 VerifyGameFile(const char* path) { return VerifyNcchFile(path, 0, 0); else if (filetype & GAME_TMD) return VerifyTmdFile(path, filetype & FLAG_NUSCDN); + else if (filetype & GAME_TIE) + return VerifyTieFile(path); else if (filetype & GAME_BOSS) return VerifyBossFile(path); else if (filetype & SYS_FIRM) @@ -2016,6 +2039,17 @@ u32 BuildCiaFromTmdFile(const char* path_tmd, const char* path_dest, bool force_ return ret; } +u32 BuildCiaFromTieFile(const char* path_tie, const char* path_dest, bool force_legit) { + char path_tmd[64]; + + // get the TMD path + if (GetTieTmdPath(path_tmd, path_tie) != 0) + return 1; + + // let the TMD builder function take over + return BuildCiaFromTmdFile(path_tmd, path_dest, force_legit, false); +} + u32 BuildInstallFromNcchFile(const char* path_ncch, const char* path_dest, bool install) { NcchExtHeader exthdr; NcchHeader ncch; @@ -2248,7 +2282,7 @@ u32 BuildCiaFromGameFile(const char* path, bool force_legit) { // build output name snprintf(dest, 256, OUTPUT_PATH "/"); char* dname = dest + strnlen(dest, 256); - if (!((filetype & GAME_TMD) || (strncmp(path + 1, ":/title/", 8) == 0)) || + if (!((filetype & (GAME_TMD|GAME_TIE)) || (strncmp(path + 1, ":/title/", 8) == 0)) || (GetGoodName(dname, path, false) != 0)) { char* name = strrchr(path, '/'); if (!name) return 1; @@ -2268,7 +2302,9 @@ u32 BuildCiaFromGameFile(const char* path, bool force_legit) { return 1; // build CIA from game file - if (filetype & GAME_TMD) + if (filetype & GAME_TIE) + ret = BuildCiaFromTieFile(path, dest, force_legit); + else if (filetype & GAME_TMD) ret = BuildCiaFromTmdFile(path, dest, force_legit, filetype & FLAG_NUSCDN); else if (filetype & GAME_NCCH) ret = BuildInstallFromNcchFile(path, dest, false); @@ -3209,7 +3245,8 @@ u32 GetGoodName(char* name, const char* path, bool quick) { (type_donor & GAME_NCCH) ? ((type_donor & FLAG_CXI) ? "cxi" : "cfa") : (type_donor & GAME_NDS) ? "nds" : (type_donor & GAME_GBA) ? "gba" : - (type_donor & GAME_TMD) ? "tmd" : ""; + (type_donor & GAME_TMD) ? "tmd" : + (type_donor & GAME_TIE) ? "tie" : ""; if (!*ext) return 1; char appid_str[1 + 8 + 1] = { 0 }; // handling for NCCH / NDS in "?:/title" paths @@ -3225,6 +3262,10 @@ u32 GetGoodName(char* name, const char* path, bool quick) { if (GetTmdContentPath(path_content, path) != 0) return 1; path_donor = path_content; type_donor = IdentifyFileType(path_donor); + } else if (type_donor & GAME_TIE) { + if (GetTieContentPath(path_content, path) != 0) return 1; + path_donor = path_content; + type_donor = IdentifyFileType(path_donor); } if (type_donor & GAME_GBA) { // AGB diff --git a/arm9/source/utils/gameutil.h b/arm9/source/utils/gameutil.h index ad2064c..bed434e 100644 --- a/arm9/source/utils/gameutil.h +++ b/arm9/source/utils/gameutil.h @@ -17,6 +17,7 @@ u32 ShowGameFileTitleInfo(const char* path); u32 ShowCiaCheckerInfo(const char* path); u32 UninstallGameDataTie(const char* path, bool remove_tie, bool remove_ticket, bool remove_save); u32 GetTmdContentPath(char* path_content, const char* path_tmd); +u32 GetTieContentPath(char* path_content, const char* path_tie); u32 BuildNcchInfoXorpads(const char* destdir, const char* path); u32 CheckHealthAndSafetyInject(const char* hsdrv); u32 InjectHealthAndSafety(const char* path, const char* destdrv);