Show title id & game icon in file handler menu

This commit is contained in:
d0k3 2021-03-18 22:44:33 +01:00
parent 0bbbc7c324
commit fd8c5d1897
5 changed files with 37 additions and 47 deletions

View File

@ -59,7 +59,7 @@
#define FTYPE_UNINSTALL(tp) (tp&(GAME_TIE)) #define FTYPE_UNINSTALL(tp) (tp&(GAME_TIE))
#define FTYPE_TIKBUILD(tp) (tp&(GAME_TICKET|SYS_TICKDB|BIN_TIKDB)) #define FTYPE_TIKBUILD(tp) (tp&(GAME_TICKET|SYS_TICKDB|BIN_TIKDB))
#define FTYPE_KEYBUILD(tp) (tp&(BIN_KEYDB|BIN_LEGKEY)) #define FTYPE_KEYBUILD(tp) (tp&(BIN_KEYDB|BIN_LEGKEY))
#define FTYPE_TITLEINFO(tp) (tp&(GAME_TIE|GAME_TICKET|GAME_SMDH|GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_TMD|GAME_CDNTMD|GAME_TWLTMD|GAME_NDS|GAME_GBA|GAME_TAD|GAME_3DSX)) #define FTYPE_TITLEINFO(tp) (tp&(GAME_TIE|GAME_CIA|GAME_TMD|GAME_CDNTMD|GAME_TWLTMD))
#define FTYPE_RENAMABLE(tp) (tp&(GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_NDS|GAME_GBA)) #define FTYPE_RENAMABLE(tp) (tp&(GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_NDS|GAME_GBA))
#define FTYPE_TRIMABLE(tp) (tp&(IMG_NAND|GAME_NCCH|GAME_NCSD|GAME_NDS|GAME_GBA|SYS_FIRM)) #define FTYPE_TRIMABLE(tp) (tp&(IMG_NAND|GAME_NCCH|GAME_NCSD|GAME_NDS|GAME_GBA|SYS_FIRM))
#define FTYPE_TRANSFERABLE(tp) ((u64) (tp&(IMG_FAT|FLAG_CTR)) == (u64) (IMG_FAT|FLAG_CTR)) #define FTYPE_TRANSFERABLE(tp) ((u64) (tp&(IMG_FAT|FLAG_CTR)) == (u64) (IMG_FAT|FLAG_CTR))

View File

@ -1077,6 +1077,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
u64 filetype = IdentifyFileType(file_path); u64 filetype = IdentifyFileType(file_path);
u32 drvtype = DriveType(file_path); u32 drvtype = DriveType(file_path);
u64 tid = GetGameFileTitleId(file_path);
bool in_output_path = (strncasecmp(current_path, OUTPUT_PATH, 256) == 0); bool in_output_path = (strncasecmp(current_path, OUTPUT_PATH, 256) == 0);
@ -1143,6 +1144,9 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
char pathstr[32+1]; char pathstr[32+1];
TruncateString(pathstr, file_path, 32, 8); TruncateString(pathstr, file_path, 32, 8);
char tidstr[32] = { 0 };
if (tid) snprintf(tidstr, 32, "\ntid: <%016llX>", tid);
u32 n_marked = 0; u32 n_marked = 0;
if ((&(current_dir->entry[*cursor]))->marked) { if ((&(current_dir->entry[*cursor]))->marked) {
for (u32 i = 0; i < current_dir->n_entries; i++) for (u32 i = 0; i < current_dir->n_entries; i++)
@ -1216,7 +1220,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
if (titleman > 0) optionstr[titleman-1] = "Open title folder"; if (titleman > 0) optionstr[titleman-1] = "Open title folder";
int user_select = ShowSelectPrompt(n_opt, optionstr, (n_marked > 1) ? int user_select = ShowSelectPrompt(n_opt, optionstr, (n_marked > 1) ?
"%s\n%(%lu files selected)" : "%s", pathstr, n_marked); "%s%0.0s\n(%lu files selected)" : "%s%s", pathstr, tidstr, n_marked);
if (user_select == hexviewer) { // -> show in hex viewer if (user_select == hexviewer) { // -> show in hex viewer
FileHexViewer(file_path); FileHexViewer(file_path);
GetDirContents(current_dir, current_path); GetDirContents(current_dir, current_path);
@ -1235,7 +1239,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
optionstr[0] = "Check current CMAC only"; optionstr[0] = "Check current CMAC only";
optionstr[1] = "Verify CMAC for all"; optionstr[1] = "Verify CMAC for all";
optionstr[2] = "Fix CMAC for all"; optionstr[2] = "Fix CMAC for all";
user_select = (n_marked > 1) ? ShowSelectPrompt(3, optionstr, "%s\n%(%lu files selected)", pathstr, n_marked) : 1; user_select = (n_marked > 1) ? ShowSelectPrompt(3, optionstr, "%s\n(%lu files selected)", pathstr, n_marked) : 1;
if (user_select == 1) { if (user_select == 1) {
CmacCalculator(file_path); CmacCalculator(file_path);
return 0; return 0;
@ -1398,7 +1402,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
// auto select when there is only one option // auto select when there is only one option
user_select = (n_opt <= 1) ? n_opt : (int) ShowSelectPrompt(n_opt, optionstr, (n_marked > 1) ? user_select = (n_opt <= 1) ? n_opt : (int) ShowSelectPrompt(n_opt, optionstr, (n_marked > 1) ?
"%s\n%(%lu files selected)" : "%s", pathstr, n_marked); "%s%0.0s\n(%lu files selected)" : "%s%s", pathstr, tidstr, n_marked);
if (user_select == mount) { // -> mount file as image if (user_select == mount) { // -> mount file as image
const char* mnt_drv_paths[] = { "7:", "G:", "K:", "T:", "I:", "D:" }; // maybe move that to fsdrive.h 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)) if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_IMAGE))
@ -1437,7 +1441,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
optionstr[0] = "Decrypt to " OUTPUT_PATH; optionstr[0] = "Decrypt to " OUTPUT_PATH;
optionstr[1] = "Decrypt inplace"; optionstr[1] = "Decrypt inplace";
user_select = (int) ShowSelectPrompt(2, optionstr, (n_marked > 1) ? user_select = (int) ShowSelectPrompt(2, optionstr, (n_marked > 1) ?
"%s\n%(%lu files selected)" : "%s", pathstr, n_marked); "%s%0.0s\n(%lu files selected)" : "%s%s", pathstr, tidstr, n_marked);
} else user_select = 1; } else user_select = 1;
bool inplace = (user_select == 2); bool inplace = (user_select == 2);
if (!user_select) { // do nothing when no choice is made if (!user_select) { // do nothing when no choice is made
@ -1491,7 +1495,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
optionstr[0] = "Encrypt to " OUTPUT_PATH; optionstr[0] = "Encrypt to " OUTPUT_PATH;
optionstr[1] = "Encrypt inplace"; optionstr[1] = "Encrypt inplace";
user_select = (int) ShowSelectPrompt(2, optionstr, (n_marked > 1) ? user_select = (int) ShowSelectPrompt(2, optionstr, (n_marked > 1) ?
"%s\n%(%lu files selected)" : "%s", pathstr, n_marked); "%s%0.0s\n(%lu files selected)" : "%s%s", pathstr, tidstr, n_marked);
} else user_select = 1; } else user_select = 1;
bool inplace = (user_select == 2); bool inplace = (user_select == 2);
if (!user_select) { // do nothing when no choice is made if (!user_select) { // do nothing when no choice is made
@ -1588,7 +1592,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
optionstr[0] = "Install to SysNAND"; optionstr[0] = "Install to SysNAND";
optionstr[1] = "Install to EmuNAND"; optionstr[1] = "Install to EmuNAND";
user_select = (int) ShowSelectPrompt(2, optionstr, (n_marked > 1) ? user_select = (int) ShowSelectPrompt(2, optionstr, (n_marked > 1) ?
"%s\n%(%lu files selected)" : "%s", pathstr, n_marked); "%s%0.0s\n(%lu files selected)" : "%s%s", pathstr, tidstr, n_marked);
if (!user_select) return 0; if (!user_select) return 0;
else to_emunand = (user_select == 2); else to_emunand = (user_select == 2);
} }
@ -1882,8 +1886,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
return 0; return 0;
} }
else if (user_select == show_info) { // -> Show title info else if (user_select == show_info) { // -> Show title info
if (ShowGameFileTitleInfo(file_path) != 0) ShowGameCheckerInfo(file_path);
ShowPrompt(false, "Title info: not found");
return 0; return 0;
} }
else if (user_select == hsinject) { // -> Inject to Health & Safety else if (user_select == hsinject) { // -> Inject to Health & Safety
@ -2513,7 +2516,10 @@ u32 GodMode(int entrypoint) {
} }
} }
} else if ((pad_state & BUTTON_A) && (curr_entry->type == T_FILE)) { // process a file } else if ((pad_state & BUTTON_A) && (curr_entry->type == T_FILE)) { // process a file
if (!curr_entry->marked) ShowGameFileIcon(curr_entry->path, ALT_SCREEN);
DrawTopBar(current_path);
FileHandlerMenu(current_path, &cursor, &scroll, &pane); // processed externally FileHandlerMenu(current_path, &cursor, &scroll, &pane); // processed externally
ClearScreenF(true, true, COLOR_STD_BG);
} else if (*current_path && ((pad_state & BUTTON_B) || // one level down } else if (*current_path && ((pad_state & BUTTON_B) || // one level down
((pad_state & BUTTON_A) && (curr_entry->type == T_DOTDOT)))) { ((pad_state & BUTTON_A) && (curr_entry->type == T_DOTDOT)))) {
if (switched) { // use R+B to return to root fast if (switched) { // use R+B to return to root fast

View File

@ -2719,6 +2719,14 @@ u64 GetGameFileTitleId(const char* path) {
u8 tid[8]; u8 tid[8];
if (fvx_qread(path, tid, 0x18C, 8, NULL) == FR_OK) if (fvx_qread(path, tid, 0x18C, 8, NULL) == FR_OK)
tid64 = getbe64(tid); tid64 = getbe64(tid);
} else if (filetype & GAME_TICKET) {
u8 tid[8];
if (fvx_qread(path, tid, 0x1DC, 8, NULL) == FR_OK)
tid64 = getbe64(tid);
} else if (filetype & GAME_TAD) {
TadHeader tad;
if (fvx_qread(path, &tad, TAD_HEADER_OFFSET, sizeof(TadHeader), NULL) == FR_OK)
tid64 = tad.title_id;
} else if (filetype & GAME_NCCH) { } else if (filetype & GAME_NCCH) {
NcchHeader ncch; NcchHeader ncch;
if (LoadNcchHeaders(&ncch, NULL, NULL, path, 0) == 0) if (LoadNcchHeaders(&ncch, NULL, NULL, path, 0) == 0)
@ -3273,7 +3281,7 @@ u32 LoadSmdhFromGameFile(const char* path, Smdh* smdh) {
return 1; return 1;
} }
u32 ShowSmdhTitleInfo(Smdh* smdh, char* str, u16* screen) { u32 ShowSmdhTitleInfo(Smdh* smdh, u16* screen) {
static const u8 smdh_magic[] = { SMDH_MAGIC }; static const u8 smdh_magic[] = { SMDH_MAGIC };
const u32 lwrap = 24; const u32 lwrap = 24;
u16 icon[SMDH_SIZE_ICON_BIG / sizeof(u16)]; u16 icon[SMDH_SIZE_ICON_BIG / sizeof(u16)];
@ -3289,11 +3297,11 @@ u32 ShowSmdhTitleInfo(Smdh* smdh, char* str, u16* screen) {
WordWrapString(desc_l, lwrap); WordWrapString(desc_l, lwrap);
WordWrapString(desc_s, lwrap); WordWrapString(desc_s, lwrap);
WordWrapString(pub, lwrap); WordWrapString(pub, lwrap);
ShowIconStringF(screen, icon, SMDH_DIM_ICON_BIG, SMDH_DIM_ICON_BIG, "%s%s\n%s\n%s", str, desc_l, desc_s, pub); ShowIconStringF(screen, icon, SMDH_DIM_ICON_BIG, SMDH_DIM_ICON_BIG, "%s\n%s\n%s", desc_l, desc_s, pub);
return 0; return 0;
} }
u32 ShowTwlIconTitleInfo(TwlIconData* twl_icon, char* str, u16* screen) { u32 ShowTwlIconTitleInfo(TwlIconData* twl_icon, u16* screen) {
const u32 lwrap = 24; const u32 lwrap = 24;
u16 icon[TWLICON_SIZE_ICON / sizeof(u16)]; u16 icon[TWLICON_SIZE_ICON / sizeof(u16)];
char desc[TWLICON_SIZE_DESC+1]; char desc[TWLICON_SIZE_DESC+1];
@ -3301,7 +3309,7 @@ u32 ShowTwlIconTitleInfo(TwlIconData* twl_icon, char* str, u16* screen) {
(GetTwlTitle(desc, twl_icon) != 0)) (GetTwlTitle(desc, twl_icon) != 0))
return 1; return 1;
WordWrapString(desc, lwrap); WordWrapString(desc, lwrap);
ShowIconStringF(screen, icon, TWLICON_DIM_ICON, TWLICON_DIM_ICON, "%s%s", str, desc); ShowIconStringF(screen, icon, TWLICON_DIM_ICON, TWLICON_DIM_ICON, "%s", desc);
return 0; return 0;
} }
@ -3309,11 +3317,12 @@ u32 ShowGbaFileTitleInfo(const char* path, u16* screen) {
AgbHeader agb; AgbHeader agb;
if ((fvx_qread(path, &agb, 0, sizeof(AgbHeader), NULL) != FR_OK) || if ((fvx_qread(path, &agb, 0, sizeof(AgbHeader), NULL) != FR_OK) ||
(ValidateAgbHeader(&agb) != 0)) return 1; (ValidateAgbHeader(&agb) != 0)) return 1;
ClearScreen(screen, COLOR_STD_BG);
ShowStringF(screen, "%.12s (AGB-%.4s)\n%s", agb.game_title, agb.game_code, AGB_DESTSTR(agb.game_code)); ShowStringF(screen, "%.12s (AGB-%.4s)\n%s", agb.game_title, agb.game_code, AGB_DESTSTR(agb.game_code));
return 0; return 0;
} }
u32 ShowGameFileTitleInfoF(const char* path, u16* screen, const char* str, bool clear) { u32 ShowGameFileIcon(const char* path, u16* screen) {
char path_content[256]; char path_content[256];
u64 itype = IdentifyFileType(path); // initial type u64 itype = IdentifyFileType(path); // initial type
if (itype & GAME_TMD) { if (itype & GAME_TMD) {
@ -3331,27 +3340,19 @@ u32 ShowGameFileTitleInfoF(const char* path, u16* screen, const char* str, bool
Smdh* smdh = (Smdh*) buffer; Smdh* smdh = (Smdh*) buffer;
TwlIconData* twl_icon = (TwlIconData*) buffer; TwlIconData* twl_icon = (TwlIconData*) buffer;
char disp_str[64];
snprintf(disp_str, 64, str ? "%s\n" : "", str);
// try loading SMDH, then try NDS / encrypted / GBA // try loading SMDH, then try NDS / encrypted / GBA
u32 ret = 1; u32 ret = 1;
u32 tp = 0; u32 tp = 0;
if (LoadSmdhFromGameFile(path, smdh) == 0) if (LoadSmdhFromGameFile(path, smdh) == 0)
ret = ShowSmdhTitleInfo(smdh, disp_str, screen); ret = ShowSmdhTitleInfo(smdh, screen);
else if ((LoadTwlMetaData(path, NULL, twl_icon) == 0) || else if ((LoadTwlMetaData(path, NULL, twl_icon) == 0) ||
((itype & GAME_TAD) && (fvx_qread(path, twl_icon, TAD_BANNER_OFFSET, sizeof(TwlIconData), NULL) == FR_OK))) ((itype & GAME_TAD) && (fvx_qread(path, twl_icon, TAD_BANNER_OFFSET, sizeof(TwlIconData), NULL) == FR_OK)))
ret = ShowTwlIconTitleInfo(twl_icon, disp_str, screen); ret = ShowTwlIconTitleInfo(twl_icon, screen);
else if ((tp = LoadEncryptedIconFromCiaTmd(path, buffer, NULL, false)) != 0) else if ((tp = LoadEncryptedIconFromCiaTmd(path, buffer, NULL, false)) != 0)
ret = (tp == GAME_NCCH) ? ShowSmdhTitleInfo(smdh, disp_str, screen) : ret = (tp == GAME_NCCH) ? ShowSmdhTitleInfo(smdh, screen) :
(tp == GAME_NDS ) ? ShowTwlIconTitleInfo(twl_icon, disp_str, screen) : 1; (tp == GAME_NDS ) ? ShowTwlIconTitleInfo(twl_icon, screen) : 1;
else ret = ShowGbaFileTitleInfo(path, screen); else ret = ShowGbaFileTitleInfo(path, screen);
if (!ret && clear) {
while(!(InputWait(0) & (BUTTON_A | BUTTON_B)));
ClearScreen(screen, COLOR_STD_BG);
}
free(buffer); free(buffer);
return ret; return ret;
} }
@ -3487,8 +3488,6 @@ u32 ShowGameCheckerInfo(const char* path) {
char conid_str[32] = { '\0' }; char conid_str[32] = { '\0' };
if (type & (GAME_CIA|GAME_TIE)) snprintf(conid_str, 64, "Console ID: %08lX\n", console_id); if (type & (GAME_CIA|GAME_TIE)) snprintf(conid_str, 64, "Console ID: %08lX\n", console_id);
// show icon on top
u32 icon_res = ShowGameFileTitleInfoF(path, ALT_SCREEN, NULL, false);
// output results // output results
s32 state_verify = -1; s32 state_verify = -1;
@ -3500,14 +3499,12 @@ u32 ShowGameCheckerInfo(const char* path) {
"Contents size: %s\n" "Contents size: %s\n"
"%s\n%s \n" "%s\n%s \n"
"Ticket/TMD: %s/%s\n" "Ticket/TMD: %s/%s\n"
"Icon data: %s\n"
"Verification: %s", "Verification: %s",
pathstr, typestr, srcstr, title_id, pathstr, typestr, srcstr, title_id,
(title_version>>10)&0x3F, (title_version>>4)&0x3F, (title_version)&0xF, (title_version>>10)&0x3F, (title_version>>4)&0x3F, (title_version)&0xF,
bytestr, contents_str, conid_str, bytestr, contents_str, conid_str,
(state_ticket == 0) ? "unknown" : (state_ticket == 2) ? "legit" : "illegit", (state_ticket == 0) ? "unknown" : (state_ticket == 2) ? "legit" : "illegit",
(state_tmd == 0) ? "invalid" : (state_tmd == 2) ? "legit" : "illegit", (state_tmd == 0) ? "invalid" : (state_tmd == 2) ? "legit" : "illegit",
(icon_res) ? "unavailable" : "(see other screen)",
(state_verify < 0) ? "pending\n \nProceed with verification?" : (state_verify == 0) ? "passed" : "failed") || (state_verify < 0) ? "pending\n \nProceed with verification?" : (state_verify == 0) ? "passed" : "failed") ||
(state_verify >= 0)) break; (state_verify >= 0)) break;
state_verify = VerifyGameFile(path); state_verify = VerifyGameFile(path);
@ -3515,23 +3512,9 @@ u32 ShowGameCheckerInfo(const char* path) {
if (tmd) free(tmd); if (tmd) free(tmd);
if (ticket) free(ticket); if (ticket) free(ticket);
if (!icon_res) ClearScreenF(true, true, COLOR_STD_BG);
return 0; return 0;
} }
u32 ShowGameFileTitleInfo(const char* path) {
// try the checker tool first
if (ShowGameCheckerInfo(path) == 0)
return 0;
// title id available?
char tidstr[32] = { '\0' };
u64 tid = GetGameFileTitleId(path);
if (tid) snprintf(tidstr, 32, "<%016llX>", tid);
return ShowGameFileTitleInfoF(path, MAIN_SCREEN, tidstr, true);
}
u32 BuildNcchInfoXorpads(const char* destdir, const char* path) { u32 BuildNcchInfoXorpads(const char* destdir, const char* path) {
FIL fp_info; FIL fp_info;
FIL fp_xorpad; FIL fp_xorpad;

View File

@ -14,8 +14,9 @@ u32 ExtractCodeFromCxiFile(const char* path, const char* path_out, char* extstr)
u32 CompressCode(const char* path, const char* path_out); u32 CompressCode(const char* path, const char* path_out);
u64 GetGameFileTrimmedSize(const char* path); u64 GetGameFileTrimmedSize(const char* path);
u32 TrimGameFile(const char* path); u32 TrimGameFile(const char* path);
u32 ShowGameFileTitleInfoF(const char* path, u16* screen, const char* str, bool clear); u32 ShowGameFileIcon(const char* path, u16* screen);
u32 ShowGameFileTitleInfo(const char* path); u32 ShowGameCheckerInfo(const char* path);
u64 GetGameFileTitleId(const char* path);
u32 UninstallGameDataTie(const char* path, bool remove_tie, bool remove_ticket, bool remove_save); u32 UninstallGameDataTie(const char* path, bool remove_tie, bool remove_ticket, bool remove_save);
u32 GetTmdContentPath(char* path_content, const char* path_tmd); u32 GetTmdContentPath(char* path_content, const char* path_tmd);
u32 GetTieContentPath(char* path_content, const char* path_tie); u32 GetTieContentPath(char* path_content, const char* path_tie);

View File

@ -1880,7 +1880,7 @@ bool ExecuteGM9Script(const char* path_script) {
if (bitmap) { if (bitmap) {
DrawBitmap(TOP_SCREEN, -1, -1, bitmap_width, bitmap_height, bitmap); DrawBitmap(TOP_SCREEN, -1, -1, bitmap_width, bitmap_height, bitmap);
free(bitmap); free(bitmap);
} else if (ShowGameFileTitleInfoF(preview_str, TOP_SCREEN, NULL, false) != 0) { } else if (ShowGameFileIcon(preview_str, TOP_SCREEN) != 0) {
if (strncmp(preview_str, "off", _VAR_CNT_LEN) == 0) preview_str = "(preview disabled)"; if (strncmp(preview_str, "off", _VAR_CNT_LEN) == 0) preview_str = "(preview disabled)";
DrawStringCenter(TOP_SCREEN, COLOR_STD_FONT, COLOR_STD_BG, "%s", preview_str); DrawStringCenter(TOP_SCREEN, COLOR_STD_FONT, COLOR_STD_BG, "%s", preview_str);
} }