From 7f6f6db4101e6192d154cdf218846aa2c52e85a9 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Mon, 16 Nov 2020 18:47:09 +0100 Subject: [PATCH] Add title manager (replaces title search) --- arm9/source/filesys/fsdrive.c | 16 +++++++++--- arm9/source/filesys/fsdrive.h | 14 ++++++++--- arm9/source/filesys/fsgame.c | 11 +++++++-- arm9/source/filesys/fsgame.h | 2 +- arm9/source/godmode.c | 46 ++++++++++++++++++++++++----------- arm9/source/utils/gameutil.c | 6 +++-- arm9/source/virtual/virtual.h | 3 ++- 7 files changed, 70 insertions(+), 28 deletions(-) diff --git a/arm9/source/filesys/fsdrive.c b/arm9/source/filesys/fsdrive.c index 1122387..756c318 100644 --- a/arm9/source/filesys/fsdrive.c +++ b/arm9/source/filesys/fsdrive.c @@ -11,7 +11,7 @@ // last search pattern, path & mode static char search_pattern[256] = { 0 }; static char search_path[256] = { 0 }; -static bool search_title_mode = false; +static bool title_manager_mode = false; int DriveType(const char* path) { int type = DRV_UNKNOWN; @@ -21,6 +21,8 @@ int DriveType(const char* path) { type = DRV_FAT | DRV_ALIAS | ((*path == 'A') ? DRV_SYSNAND : DRV_EMUNAND); } else if (*search_pattern && *search_path && (strncmp(path, "Z:", 3) == 0)) { type = DRV_SEARCH; + } else if (title_manager_mode && (strncmp(path, "Y:", 3) == 0)) { + type = DRV_TITLEMAN; } else if ((pdrv >= 0) && (pdrv < NORM_FS)) { if (pdrv == 0) { type = DRV_FAT | DRV_SDCARD | DRV_STDFAT; @@ -64,16 +66,19 @@ int DriveType(const char* path) { return type; } -void SetFSSearch(const char* pattern, const char* path, bool mode) { +void SetFSSearch(const char* pattern, const char* path) { if (pattern && path) { strncpy(search_pattern, pattern, 256); search_pattern[255] = '\0'; strncpy(search_path, path, 256); search_path[255] = '\0'; - search_title_mode = mode; } else *search_pattern = *search_path = '\0'; } +void SetTitleManagerMode(bool mode) { + title_manager_mode = mode; +} + bool GetFATVolumeLabel(const char* drv, char* label) { return (f_getlabel(drv, label, NULL) == FR_OK); } @@ -208,7 +213,10 @@ void GetDirContents(DirStruct* contents, const char* path) { if (*search_path && (DriveType(path) & DRV_SEARCH)) { ShowString("Searching, please wait..."); SearchDirContents(contents, search_path, search_pattern, true); - if (search_title_mode) SetDirGoodNames(contents); + ClearScreenF(true, false, COLOR_STD_BG); + } else if (title_manager_mode && (DriveType(path) & DRV_TITLEMAN)) { + SearchDirContents(contents, "T:", "*", false); + SetupTitleManager(contents); ClearScreenF(true, false, COLOR_STD_BG); } else SearchDirContents(contents, path, NULL, false); if (*path) SortDirStruct(contents); diff --git a/arm9/source/filesys/fsdrive.h b/arm9/source/filesys/fsdrive.h index 3b94259..e9f4b40 100644 --- a/arm9/source/filesys/fsdrive.h +++ b/arm9/source/filesys/fsdrive.h @@ -25,8 +25,9 @@ #define DRV_VRAM (1UL<<13) #define DRV_ALIAS (1UL<<14) #define DRV_BONUS (1UL<<15) -#define DRV_SEARCH (1UL<<16) -#define DRV_STDFAT (1UL<<17) // standard FAT drive without limitations +#define DRV_TITLEMAN (1UL<<16) +#define DRV_SEARCH (1UL<<17) +#define DRV_STDFAT (1UL<<18) // standard FAT drive without limitations #define DRV_LABEL_LEN (36) @@ -39,16 +40,21 @@ "GAME IMAGE", "AESKEYDB IMAGE", "BDRI IMAGE", "DISA/DIFF IMAGE", \ "MEMORY VIRTUAL", \ "VRAM VIRTUAL", \ + "TITLE MANAGER", \ "LAST SEARCH" \ #define FS_DRVNUM \ - "0:", "1:", "2:", "3:", "A:", "S:", "4:", "5:", "6:", "B:", "E:", "7:", "8:", "9:", "I:", "C:", "G:", "K:", "T:", "D:", "M:", "V:", "Z:" + "0:", "1:", "2:", "3:", "A:", "S:", "4:", "5:", "6:", "B:", "E:", "7:", "8:", "9:", \ + "I:", "C:", "G:", "K:", "T:", "D:", "M:", "V:", "Y:", "Z:" /** Function to identify the type of a drive **/ int DriveType(const char* path); /** Set search pattern / path / mode for special Z: drive **/ -void SetFSSearch(const char* pattern, const char* path, bool mode); +void SetFSSearch(const char* pattern, const char* path); + +/** Enable title manager for special processing of mounted title.db **/ +void SetTitleManagerMode(bool mode); /** Read the FAT volume label of a partition **/ bool GetFATVolumeLabel(const char* drv, char* label); diff --git a/arm9/source/filesys/fsgame.c b/arm9/source/filesys/fsgame.c index 0457bab..e70cdef 100644 --- a/arm9/source/filesys/fsgame.c +++ b/arm9/source/filesys/fsgame.c @@ -1,14 +1,16 @@ #include "fsgame.h" #include "fsperm.h" #include "gameutil.h" +#include "tie.h" #include "ui.h" -#include "ff.h" +#include "vff.h" -void SetDirGoodNames(DirStruct* contents) { +void SetupTitleManager(DirStruct* contents) { char goodname[256]; ShowProgress(0, 0, ""); for (u32 s = 0; s < contents->n_entries; s++) { DirEntry* entry = &(contents->entry[s]); + // set good name for entry u32 plen = strnlen(entry->path, 256); if (!ShowProgress(s+1, contents->n_entries, entry->path)) break; if ((GetGoodName(goodname, entry->path, false) != 0) || @@ -17,6 +19,11 @@ void SetDirGoodNames(DirStruct* contents) { entry->p_name = plen + 1; entry->name = entry->path + entry->p_name; snprintf(entry->name, 256 - entry->p_name, "%s", goodname); + // grab title size from tie + TitleInfoEntry tie; + if (fvx_qread(entry->path, &tie, 0, sizeof(TitleInfoEntry), NULL) != FR_OK) + continue; + entry->size = tie.title_size; } } diff --git a/arm9/source/filesys/fsgame.h b/arm9/source/filesys/fsgame.h index d9de99e..e1cac89 100644 --- a/arm9/source/filesys/fsgame.h +++ b/arm9/source/filesys/fsgame.h @@ -3,5 +3,5 @@ #include "common.h" #include "fsdir.h" -void SetDirGoodNames(DirStruct* contents); +void SetupTitleManager(DirStruct* contents); bool GoodRenamer(DirEntry* entry, bool ask); diff --git a/arm9/source/godmode.c b/arm9/source/godmode.c index aff62a6..32650c5 100644 --- a/arm9/source/godmode.c +++ b/arm9/source/godmode.c @@ -319,7 +319,8 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, u32 curr_pan ((drvtype & DRV_SDCARD) ? "SD" : (drvtype & DRV_RAMDRIVE) ? "RAMdrive" : (drvtype & DRV_GAME) ? "Game" : (drvtype & DRV_SYSNAND) ? "SysNAND" : (drvtype & DRV_EMUNAND) ? "EmuNAND" : (drvtype & DRV_IMAGE) ? "Image" : (drvtype & DRV_XORPAD) ? "XORpad" : (drvtype & DRV_MEMORY) ? "Memory" : (drvtype & DRV_ALIAS) ? "Alias" : - (drvtype & DRV_CART) ? "Gamecart" : (drvtype & DRV_VRAM) ? "VRAM" : (drvtype & DRV_SEARCH) ? "Search" : ""), + (drvtype & DRV_CART) ? "Gamecart" : (drvtype & DRV_VRAM) ? "VRAM" : (drvtype & DRV_SEARCH) ? "Search" : + (drvtype & DRV_TITLEMAN) ? "TitleManager" : ""), ((drvtype & DRV_FAT) ? " FAT" : (drvtype & DRV_VIRTUAL) ? " Virtual" : "")); ResizeString(tempstr, drvstr, str_len_info, 8, false); } else { @@ -1157,7 +1158,14 @@ 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; + int titleman = -1; + if (DriveType(current_path) & DRV_TITLEMAN) { + // special case: title manager (disable almost everything) + hexviewer = textviewer = calcsha = calccmac = fileinfo = copystd = inject = searchdrv = -1; + special = 1; + titleman = 2; + n_opt = 2; + } if (special > 0) optionstr[special-1] = (filetype & IMG_NAND ) ? "NAND image options..." : (filetype & IMG_FAT ) ? (transferable) ? "CTRNAND options..." : "Mount as FAT image" : @@ -1386,6 +1394,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan const char* mnt_drv_paths[] = { "7:", "G:", "K:", "T:", "I:", "D:" }; // maybe move that to fsdrive.h if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_IMAGE)) clipboard->n_entries = 0; // remove last mounted image clipboard entries + SetTitleManagerMode(false); // disable title manager mode InitImgFS((filetype & GAME_TMD) ? cxi_path : file_path); const char* drv_path = NULL; // find path of mounted drive @@ -1628,18 +1637,17 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan if (n_marked > 1) { u32 n_success = 0; u32 num = 0; - ShowProgress(0, 0, "batch uninstall"); for (u32 i = 0; i < current_dir->n_entries; i++) { const char* path = current_dir->entry[i].path; if (!current_dir->entry[i].marked) continue; if (!(IdentifyFileType(path) & filetype & TYPE_BASE)) continue; - if (!ShowProgress(++num, n_marked, path)) break; + if (!num && !CheckWritePermissions(path)) break; + if (!ShowProgress(num++, n_marked, path)) break; if (UninstallGameDataTie(path, true, full_uninstall, full_uninstall) == 0) n_success++; } ShowPrompt(false, "%lu/%lu titles uninstalled", n_success, n_marked); } else { - ShowString("%s\nUninstalling, please wait...", pathstr); if (UninstallGameDataTie(file_path, true, full_uninstall, full_uninstall) != 0) ShowPrompt(false, "%s\nUninstall failed!", pathstr); ClearScreenF(true, false, COLOR_STD_BG); @@ -2353,6 +2361,7 @@ u32 GodMode(int entrypoint) { if (!current_dir->n_entries) { // current dir is empty -> revert to root ShowPrompt(false, "Invalid directory object"); *current_path = '\0'; + SetTitleManagerMode(false); DeinitExtFS(); // deinit and... InitExtFS(); // reinitialize extended file system GetDirContents(current_dir, current_path); @@ -2388,19 +2397,19 @@ u32 GodMode(int entrypoint) { // basic navigation commands if ((pad_state & BUTTON_A) && (curr_entry->type != T_FILE) && (curr_entry->type != T_DOTDOT)) { // for dirs - if (switched && !(DriveType(curr_entry->path) & DRV_SEARCH)) { // search directory + if (switched && !(DriveType(curr_entry->path) & (DRV_SEARCH|DRV_TITLEMAN))) { // exclude Y/Z const char* optionstr[8] = { NULL }; char tpath[16] = { 0 }; - if (!*current_path) snprintf(tpath, 15, "%s/title", curr_entry->path); + snprintf(tpath, 16, "%2.2s/dbs/title.db", curr_entry->path); int n_opt = 0; - int srch_t = ((strncmp(curr_entry->path + 1, ":/title", 7) == 0) || - (*tpath && PathExist(tpath))) ? ++n_opt : -1; + int tman = ((strncmp(curr_entry->path, tpath, 16) == 0) || + (!*current_path && PathExist(tpath))) ? ++n_opt : -1; int srch_f = ++n_opt; int fixcmac = (!*current_path && ((strspn(curr_entry->path, "14AB") == 1) || ((GetMountState() == IMG_NAND) && (*(curr_entry->path) == '7')))) ? ++n_opt : -1; int dirnfo = ++n_opt; int stdcpy = (*current_path && strncmp(current_path, OUTPUT_PATH, 256) != 0) ? ++n_opt : -1; - if (srch_t > 0) optionstr[srch_t-1] = "Search for titles"; + if (tman > 0) optionstr[tman-1] = "Open title manager"; if (srch_f > 0) optionstr[srch_f-1] = "Search for files..."; if (fixcmac > 0) optionstr[fixcmac-1] = "Fix CMACs for drive"; if (dirnfo > 0) optionstr[dirnfo-1] = (*current_path) ? "Show directory info" : "Show drive info"; @@ -2408,12 +2417,20 @@ u32 GodMode(int entrypoint) { char namestr[32+1]; TruncateString(namestr, (*current_path) ? curr_entry->path : curr_entry->name, 32, 8); int user_select = ShowSelectPrompt(n_opt, optionstr, "%s", namestr); - if ((user_select == srch_f) || (user_select == srch_t)) { + if (user_select == tman) { + if (InitImgFS(tpath)) { + SetTitleManagerMode(true); + snprintf(current_path, 256, "Y:"); + GetDirContents(current_dir, current_path); + cursor = 1; + scroll = 0; + } else ShowPrompt(false, "Failed setting up title manager!"); + } else if (user_select == srch_f) { char searchstr[256]; - snprintf(searchstr, 256, (user_select == srch_t) ? "*.tmd" : "*"); + snprintf(searchstr, 256, "*"); TruncateString(namestr, curr_entry->name, 20, 8); - if ((user_select == srch_t) || ShowKeyboardOrPrompt(searchstr, 256, "Search %s?\nEnter search below.", namestr)) { - SetFSSearch(searchstr, curr_entry->path, (user_select == srch_t)); + if (ShowKeyboardOrPrompt(searchstr, 256, "Search %s?\nEnter search below.", namestr)) { + SetFSSearch(searchstr, curr_entry->path); snprintf(current_path, 256, "Z:"); GetDirContents(current_dir, current_path); if (current_dir->n_entries) ShowPrompt(false, "Found %lu results.", current_dir->n_entries - 1); @@ -2535,6 +2552,7 @@ u32 GodMode(int entrypoint) { if (switched && (pad_state & BUTTON_X)) { // unmount image if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_IMAGE)) clipboard->n_entries = 0; // remove last mounted image clipboard entries + SetTitleManagerMode(false); InitImgFS(NULL); ClearScreenF(false, true, COLOR_STD_BG); GetDirContents(current_dir, current_path); diff --git a/arm9/source/utils/gameutil.c b/arm9/source/utils/gameutil.c index 2e0a304..30b9539 100644 --- a/arm9/source/utils/gameutil.c +++ b/arm9/source/utils/gameutil.c @@ -3235,8 +3235,8 @@ u32 GetGoodName(char* name, const char* path, bool quick) { (type_donor & GAME_NDS) ? "nds" : (type_donor & GAME_GBA) ? "gba" : (type_donor & GAME_TMD) ? "tmd" : - (type_donor & GAME_TIE) ? "tie" : ""; - if (!*ext) return 1; + (type_donor & GAME_TIE) ? "" : NULL; + if (!ext) return 1; char appid_str[1 + 8 + 1] = { 0 }; // handling for NCCH / NDS in "?:/title" paths if ((type_donor & (GAME_NCCH|GAME_NDS)) && (strncmp(path + 1, ":/title/", 8) == 0)) { @@ -3328,6 +3328,8 @@ u32 GetGoodName(char* name, const char* path, bool quick) { if ((*c == ':') || (*c == '/') || (*c == '\\') || (*c == '"') || (*c == '*') || (*c == '?') || (*c == '\n') || (*c == '\r')) *c = ' '; + if ((*c == '.') && !*(c+1)) + *c = '\0'; } // remove double spaces from filename diff --git a/arm9/source/virtual/virtual.h b/arm9/source/virtual/virtual.h index 7644b4c..6543803 100644 --- a/arm9/source/virtual/virtual.h +++ b/arm9/source/virtual/virtual.h @@ -25,7 +25,8 @@ #define VRT_DRIVES {'S', VRT_SYSNAND}, {'E', VRT_EMUNAND}, {'I', VRT_IMGNAND}, {'X', VRT_XORPAD }, \ - {'M', VRT_MEMORY}, {'G', VRT_GAME}, {'K', VRT_KEYDB}, {'T', VRT_BDRI}, {'C', VRT_CART}, {'V', VRT_VRAM}, {'D', VRT_DISADIFF} + {'M', VRT_MEMORY}, {'G', VRT_GAME}, {'K', VRT_KEYDB}, {'T', VRT_BDRI}, \ + {'C', VRT_CART}, {'V', VRT_VRAM}, {'D', VRT_DISADIFF} // virtual file flag (subject to change): // bits 0...3 : reserved for NAND virtual sources and info