New HOME more... menu

Also: improved H&S inject and easy way to restore old H&S
This commit is contained in:
d0k3 2017-02-28 04:10:23 +01:00
parent 63527b3467
commit f83b34d436
4 changed files with 131 additions and 53 deletions

View File

@ -41,7 +41,7 @@
#define ENTRY_GATEWAY (2) #define ENTRY_GATEWAY (2)
// GodMode9 version // GodMode9 version
#define VERSION "1.0.1" #define VERSION "1.0.2"
// input / output paths // input / output paths
#define INPUT_PATHS "0:", "0:/files9", "1:/rw/files9" #define INPUT_PATHS "0:", "0:/files9", "1:/rw/files9"

View File

@ -1400,16 +1400,17 @@ u32 BuildNcchInfoXorpads(const char* destdir, const char* path) {
return ret; return ret;
} }
u32 CheckHealthAndSafetyInject(const char* hsdrv) {
char path_mrk[32] = { 0 };
snprintf(path_mrk, 32, "%s/%s", hsdrv, HSINJECT_MARKFILE);
return (f_stat(path_mrk, NULL) == FR_OK) ? 0 : 1;
}
u32 InjectHealthAndSafety(const char* path, const char* destdrv) { u32 InjectHealthAndSafety(const char* path, const char* destdrv) {
const u32 tidlow_hs_o3ds[] = { 0x00020300, 0x00021300, 0x00022300, 0, 0x00026300, 0x00027300, 0x00028300 }; const u32 tidlow_hs_o3ds[] = { 0x00020300, 0x00021300, 0x00022300, 0, 0x00026300, 0x00027300, 0x00028300 };
const u32 tidlow_hs_n3ds[] = { 0x20020300, 0x20021300, 0x20022300, 0, 0, 0x00027300, 0 }; const u32 tidlow_hs_n3ds[] = { 0x20020300, 0x20021300, 0x20022300, 0, 0, 0x00027300, 0 };
NcchHeader ncch; NcchHeader ncch;
// check input file / crypto
if ((LoadNcchHeaders(&ncch, NULL, NULL, path, 0) != 0) ||
!(NCCH_IS_CXI(&ncch)) || (SetupNcchCrypto(&ncch, NCCH_NOCRYPTO) != 0))
return 1;
// write permissions // write permissions
if (!CheckWritePermissions(destdrv)) if (!CheckWritePermissions(destdrv))
return 1; return 1;
@ -1434,17 +1435,35 @@ u32 InjectHealthAndSafety(const char* path, const char* destdrv) {
if (!tidlow_hs) return 1; if (!tidlow_hs) return 1;
// build paths // build paths
char path_tmd[64]; char path_cxi[64] = { 0 };
char path_cxi[64]; char path_bak[64] = { 0 };
char path_bak[64]; char path_mrk[32] = { 0 };
snprintf(path_tmd, 64, "%s/title/00040010/%08lx/content/00000000.tmd", destdrv, tidlow_hs); snprintf(path_mrk, 32, "%s/%s", destdrv, HSINJECT_MARKFILE);
for (u32 i = 0; i < 8; i++) { // 8 is an arbitrary number
TitleMetaData* tmd = (TitleMetaData*) TEMP_BUFFER;
TmdContentChunk* chunk = (TmdContentChunk*) (tmd + 1);
char path_tmd[64];
snprintf(path_tmd, 64, "%s/title/00040010/%08lx/content/%08lx.tmd", destdrv, tidlow_hs, i);
if (LoadTmdFile(tmd, path_tmd) != 0) continue;
if (!getbe16(tmd->content_count)) return 1;
snprintf(path_cxi, 64, "%s/title/00040010/%08lx/content/%08lx.app", destdrv, tidlow_hs, getbe32(chunk->id));
snprintf(path_bak, 64, "%s/title/00040010/%08lx/content/%08lx.bak", destdrv, tidlow_hs, getbe32(chunk->id));
break;
}
if (!(*path_cxi)) return 1;
TitleMetaData* tmd = (TitleMetaData*) TEMP_BUFFER; if (!path) { // if path == NULL -> restore H&S from backup
TmdContentChunk* chunk = (TmdContentChunk*) (tmd + 1); if (f_stat(path_bak, NULL) != FR_OK) return 1;
if (LoadTmdFile(tmd, path_tmd) != 0) return 1; f_unlink(path_mrk);
if (!getbe16(tmd->content_count)) return 1; f_unlink(path_cxi);
snprintf(path_cxi, 64, "%s/title/00040010/%08lx/content/%08lX.app", destdrv, tidlow_hs, getbe32(chunk->id)); f_rename(path_bak, path_cxi);
snprintf(path_bak, 64, "%s/title/00040010/%08lx/content/%08lX.bak", destdrv, tidlow_hs, getbe32(chunk->id)); return 0;
}
// check input file / crypto
if ((LoadNcchHeaders(&ncch, NULL, NULL, path, 0) != 0) ||
!(NCCH_IS_CXI(&ncch)) || (SetupNcchCrypto(&ncch, NCCH_NOCRYPTO) != 0))
return 1;
// check crypto, get sig // check crypto, get sig
u64 tid_hs = ((u64) 0x00040010 << 32) | tidlow_hs; u64 tid_hs = ((u64) 0x00040010 << 32) | tidlow_hs;
@ -1485,6 +1504,9 @@ u32 InjectHealthAndSafety(const char* path, const char* destdrv) {
if (ret != 0) { // in case of failure: try recover if (ret != 0) { // in case of failure: try recover
f_unlink(path_cxi); f_unlink(path_cxi);
f_rename(path_bak, path_cxi); f_rename(path_bak, path_cxi);
} else { // in case of success: mark this ctrnand as H&S injected
UINT bw;
fvx_qwrite(path_mrk, path_bak, 0, strnlen(path_bak, 63) + 1, &bw);
} }
return ret; return ret;

View File

@ -2,9 +2,12 @@
#include "common.h" #include "common.h"
#define HSINJECT_MARKFILE "__gm9_hsbak.pth"
u32 VerifyGameFile(const char* path); u32 VerifyGameFile(const char* path);
u32 CheckEncryptedGameFile(const char* path); u32 CheckEncryptedGameFile(const char* path);
u32 CryptGameFile(const char* path, bool inplace, bool encrypt); u32 CryptGameFile(const char* path, bool inplace, bool encrypt);
u32 BuildCiaFromGameFile(const char* path, bool force_legit); u32 BuildCiaFromGameFile(const char* path, bool force_legit);
u32 BuildNcchInfoXorpads(const char* destdir, const char* path); u32 BuildNcchInfoXorpads(const char* destdir, const char* path);
u32 CheckHealthAndSafetyInject(const char* hsdrv);
u32 InjectHealthAndSafety(const char* path, const char* destdrv); u32 InjectHealthAndSafety(const char* path, const char* destdrv);

View File

@ -608,7 +608,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
bool in_output_path = (strncmp(current_path, OUTPUT_PATH, 256) == 0); bool in_output_path = (strncmp(current_path, OUTPUT_PATH, 256) == 0);
// special stuff, only available for known filetypes (see int special below) // special stuff, only available for known filetypes (see int special below)
bool mountable = (FTYPE_MOUNTABLE(filetype) && !(drvtype & (DRV_IMAGE|DRV_RAMDRIVE))); bool mountable = (FTYPE_MOUNTABLE(filetype) && !(drvtype & (DRV_IMAGE|DRV_BONUS|DRV_RAMDRIVE)));
bool verificable = (FYTPE_VERIFICABLE(filetype)); bool verificable = (FYTPE_VERIFICABLE(filetype));
bool decryptable = (FYTPE_DECRYPTABLE(filetype)); bool decryptable = (FYTPE_DECRYPTABLE(filetype));
bool encryptable = (FYTPE_ENCRYPTABLE(filetype)); bool encryptable = (FYTPE_ENCRYPTABLE(filetype));
@ -623,7 +623,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
bool special_opt = mountable || verificable || decryptable || encryptable || bool special_opt = mountable || verificable || decryptable || encryptable ||
buildable || buildable_legit || hsinjectable || restorable || xorpadable || launchable || ebackupable; buildable || buildable_legit || hsinjectable || restorable || xorpadable || launchable || ebackupable;
char pathstr[48]; char pathstr[32];
TruncateString(pathstr, curr_entry->path, 32, 8); TruncateString(pathstr, curr_entry->path, 32, 8);
u32 n_marked = 0; u32 n_marked = 0;
@ -731,8 +731,8 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
current_dir->entry[i].marked = false; current_dir->entry[i].marked = false;
if (PathCopy(OUTPUT_PATH, path, &flags)) n_success++; if (PathCopy(OUTPUT_PATH, path, &flags)) n_success++;
else { // on failure: set cursor on failed title, break; else { // on failure: set cursor on failed title, break;
char currstr[20+1]; char currstr[32+1];
TruncateString(currstr, clipboard->entry[0].name, 20, 12); TruncateString(currstr, path, 32, 12);
ShowPrompt(false, "%s\nFailed copying file", currstr); ShowPrompt(false, "%s\nFailed copying file", currstr);
*cursor = i; *cursor = i;
break; break;
@ -1034,6 +1034,87 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
return FileHandlerMenu(current_path, cursor, scroll, current_dir, clipboard); return FileHandlerMenu(current_path, cursor, scroll, current_dir, clipboard);
} }
u32 HomeMoreMenu(char* current_path, DirStruct* current_dir, DirStruct* clipboard) {
const char* optionstr[8];
const char* promptstr = "HOME more.. menu.\nSelect action:";
u32 n_opt = 0;
int sdformat = ++n_opt;
int bonus = (GetNandUnusedSectors(NAND_SYSNAND) > 0x2000) ? (int) ++n_opt : -1; // 4MB minsize
int multi = (CheckMultiEmuNand()) ? (int) ++n_opt : -1;
int hsrestore = ((CheckHealthAndSafetyInject("1:") == 0) || (CheckHealthAndSafetyInject("4:") == 0)) ? (int) ++n_opt : -1;
int nandbak = ++n_opt;
if (sdformat > 0) optionstr[sdformat - 1] = "SD format menu";
if (bonus > 0) optionstr[bonus - 1] = "Bonus drive setup";
if (multi > 0) optionstr[multi - 1] = "Switch EmuNAND";
if (hsrestore > 0) optionstr[hsrestore - 1] = "Restore H&S";
if (nandbak > 0) optionstr[nandbak - 1] = "Backup NAND";
int user_select = ShowSelectPrompt(n_opt, optionstr, promptstr);
if (user_select == sdformat) { // format SD card
bool sd_state = CheckSDMountState();
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & (DRV_SDCARD|DRV_ALIAS|DRV_EMUNAND|DRV_IMAGE)))
clipboard->n_entries = 0; // remove SD clipboard entries
DeinitExtFS();
DeinitSDCardFS();
if ((SdFormatMenu() == 0) || sd_state) {;
while (!InitSDCardFS() &&
ShowPrompt(true, "Reinitialising SD card failed! Retry?"));
}
ClearScreenF(true, true, COLOR_STD_BG);
InitEmuNandBase(true);
InitExtFS();
GetDirContents(current_dir, current_path);
return 0;
} else if (user_select == bonus) { // setup bonus drive
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & (DRV_BONUS|DRV_IMAGE)))
clipboard->n_entries = 0; // remove bonus drive clipboard entries
if (!SetupBonusDrive()) ShowPrompt(false, "Setup failed!");
ClearScreenF(true, true, COLOR_STD_BG);
GetDirContents(current_dir, current_path);
return 0;
} else if (user_select == multi) { // switch EmuNAND offset
while (ShowPrompt(true, "Current EmuNAND offset is %06X.\nSwitch to next offset?", GetEmuNandBase())) {
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_EMUNAND))
clipboard->n_entries = 0; // remove EmuNAND clipboard entries
DismountDriveType(DRV_EMUNAND);
InitEmuNandBase(false);
InitExtFS();
}
GetDirContents(current_dir, current_path);
return 0;
} else if (user_select == hsrestore) { // restore Health & Safety
n_opt = 0;
int sys = (CheckHealthAndSafetyInject("1:") == 0) ? (int) ++n_opt : -1;
int emu = (CheckHealthAndSafetyInject("4:") == 0) ? (int) ++n_opt : -1;
if (sys > 0) optionstr[sys - 1] = "Restore H&S (SysNAND)";
if (emu > 0) optionstr[emu - 1] = "Restore H&S (EmuNAND)";
user_select = (n_opt > 1) ? ShowSelectPrompt(n_opt, optionstr, promptstr) : n_opt;
if (user_select > 0) {
InjectHealthAndSafety(NULL, (user_select == sys) ? "1:" : "4:");
GetDirContents(current_dir, current_path);
return 0;
}
} else if (user_select == nandbak) { // dump NAND backup
n_opt = 0;
int sys = (DriveType("1:")) ? (int) ++n_opt : -1;
int emu = (DriveType("4:")) ? (int) ++n_opt : -1;
if (sys > 0) optionstr[sys - 1] = "Backup SysNAND";
if (emu > 0) optionstr[emu - 1] = "BAckup EmuNAND";
user_select = (n_opt > 1) ? ShowSelectPrompt(n_opt, optionstr, promptstr) : n_opt;
if (user_select > 0) {
u32 flags = CALC_SHA;
ShowPrompt(false, "NAND backup: %s",
(PathCopy(OUTPUT_PATH, (user_select == sys) ? "1:/nand_min.bin" : "4:/nand_min.bin", &flags)) ?
"success" : "failed");
GetDirContents(current_dir, current_path);
return 0;
}
} else return 1;
return HomeMoreMenu(current_path, current_dir, clipboard);
}
u32 GodMode() { u32 GodMode() {
static const u32 quick_stp = 20; static const u32 quick_stp = 20;
u32 exit_mode = GODMODE_EXIT_REBOOT; u32 exit_mode = GODMODE_EXIT_REBOOT;
@ -1371,46 +1452,18 @@ u32 GodMode() {
exit_mode = GODMODE_EXIT_POWEROFF; exit_mode = GODMODE_EXIT_POWEROFF;
break; break;
} else if (pad_state & BUTTON_HOME) { // Home menu } else if (pad_state & BUTTON_HOME) { // Home menu
const char* optionstr[] = { "Poweroff system", "Reboot system", "SD format menu", "Bonus drive setup", "Switch EmuNAND" }; const char* optionstr[] = { "Poweroff system", "Reboot system", "More..." };
const char* promptstr = "HOME button pressed.\nSelect action:";
u32 n_opt = 3; u32 n_opt = 3;
int bonus = (GetNandUnusedSectors(NAND_SYSNAND) > 0x2000) ? (int) ++n_opt : -1; // 4MB minsize u32 user_select = 0;
int multi = (CheckMultiEmuNand()) ? (int) ++n_opt : -1; while (((user_select = ShowSelectPrompt(n_opt, optionstr, promptstr)) == 3) &&
if (bonus < 0) optionstr[3] = "Switch EmuNAND"; (HomeMoreMenu(current_path, current_dir, clipboard) == 1)); // more... menu
u32 user_select = ShowSelectPrompt(n_opt, optionstr, "HOME button pressed.\nSelect action:" );
if (user_select == 1) { if (user_select == 1) {
exit_mode = GODMODE_EXIT_POWEROFF; exit_mode = GODMODE_EXIT_POWEROFF;
break; break;
} else if (user_select == 2) { } else if (user_select == 2) {
exit_mode = GODMODE_EXIT_REBOOT; exit_mode = GODMODE_EXIT_REBOOT;
break; break;
} else if (user_select == 3) { // format SD card
bool sd_state = CheckSDMountState();
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & (DRV_SDCARD|DRV_ALIAS|DRV_EMUNAND|DRV_IMAGE)))
clipboard->n_entries = 0; // remove SD clipboard entries
DeinitExtFS();
DeinitSDCardFS();
if ((SdFormatMenu() == 0) || sd_state) {;
while (!InitSDCardFS() &&
ShowPrompt(true, "Reinitialising SD card failed! Retry?"));
}
ClearScreenF(true, true, COLOR_STD_BG);
InitEmuNandBase(true);
InitExtFS();
GetDirContents(current_dir, current_path);
} else if (user_select == (u32) bonus) { // setup bonus drive
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & (DRV_BONUS|DRV_IMAGE)))
clipboard->n_entries = 0; // remove bonus drive clipboard entries
if (!SetupBonusDrive()) ShowPrompt(false, "Setup failed!");
ClearScreenF(true, true, COLOR_STD_BG);
GetDirContents(current_dir, current_path);
} else if (user_select == (u32) multi) { // switch EmuNAND offset
while (ShowPrompt(true, "Current EmuNAND offset is %06X.\nSwitch to next offset?", GetEmuNandBase())) {
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_EMUNAND))
clipboard->n_entries = 0; // remove SD clipboard entries
DismountDriveType(DRV_EMUNAND);
InitEmuNandBase(false);
InitExtFS();
}
} }
} else if (pad_state & (CART_INSERT|CART_EJECT)) { } else if (pad_state & (CART_INSERT|CART_EJECT)) {
if (!InitVCartDrive() && (pad_state & CART_INSERT)) // reinit virtual cart drive if (!InitVCartDrive() && (pad_state & CART_INSERT)) // reinit virtual cart drive