mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
New HOME more... menu
Also: improved H&S inject and easy way to restore old H&S
This commit is contained in:
parent
63527b3467
commit
f83b34d436
@ -41,7 +41,7 @@
|
||||
#define ENTRY_GATEWAY (2)
|
||||
|
||||
// GodMode9 version
|
||||
#define VERSION "1.0.1"
|
||||
#define VERSION "1.0.2"
|
||||
|
||||
// input / output paths
|
||||
#define INPUT_PATHS "0:", "0:/files9", "1:/rw/files9"
|
||||
|
@ -1400,16 +1400,17 @@ u32 BuildNcchInfoXorpads(const char* destdir, const char* path) {
|
||||
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) {
|
||||
const u32 tidlow_hs_o3ds[] = { 0x00020300, 0x00021300, 0x00022300, 0, 0x00026300, 0x00027300, 0x00028300 };
|
||||
const u32 tidlow_hs_n3ds[] = { 0x20020300, 0x20021300, 0x20022300, 0, 0, 0x00027300, 0 };
|
||||
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
|
||||
if (!CheckWritePermissions(destdrv))
|
||||
return 1;
|
||||
@ -1434,17 +1435,35 @@ u32 InjectHealthAndSafety(const char* path, const char* destdrv) {
|
||||
if (!tidlow_hs) return 1;
|
||||
|
||||
// build paths
|
||||
char path_tmd[64];
|
||||
char path_cxi[64];
|
||||
char path_bak[64];
|
||||
snprintf(path_tmd, 64, "%s/title/00040010/%08lx/content/00000000.tmd", destdrv, tidlow_hs);
|
||||
char path_cxi[64] = { 0 };
|
||||
char path_bak[64] = { 0 };
|
||||
char path_mrk[32] = { 0 };
|
||||
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;
|
||||
TmdContentChunk* chunk = (TmdContentChunk*) (tmd + 1);
|
||||
if (LoadTmdFile(tmd, path_tmd) != 0) return 1;
|
||||
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));
|
||||
if (!path) { // if path == NULL -> restore H&S from backup
|
||||
if (f_stat(path_bak, NULL) != FR_OK) return 1;
|
||||
f_unlink(path_mrk);
|
||||
f_unlink(path_cxi);
|
||||
f_rename(path_bak, path_cxi);
|
||||
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
|
||||
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
|
||||
f_unlink(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;
|
||||
|
@ -2,9 +2,12 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define HSINJECT_MARKFILE "__gm9_hsbak.pth"
|
||||
|
||||
u32 VerifyGameFile(const char* path);
|
||||
u32 CheckEncryptedGameFile(const char* path);
|
||||
u32 CryptGameFile(const char* path, bool inplace, bool encrypt);
|
||||
u32 BuildCiaFromGameFile(const char* path, bool force_legit);
|
||||
u32 BuildNcchInfoXorpads(const char* destdir, const char* path);
|
||||
u32 CheckHealthAndSafetyInject(const char* hsdrv);
|
||||
u32 InjectHealthAndSafety(const char* path, const char* destdrv);
|
||||
|
127
source/godmode.c
127
source/godmode.c
@ -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);
|
||||
|
||||
// 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 decryptable = (FYTPE_DECRYPTABLE(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 ||
|
||||
buildable || buildable_legit || hsinjectable || restorable || xorpadable || launchable || ebackupable;
|
||||
|
||||
char pathstr[48];
|
||||
char pathstr[32];
|
||||
TruncateString(pathstr, curr_entry->path, 32, 8);
|
||||
|
||||
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;
|
||||
if (PathCopy(OUTPUT_PATH, path, &flags)) n_success++;
|
||||
else { // on failure: set cursor on failed title, break;
|
||||
char currstr[20+1];
|
||||
TruncateString(currstr, clipboard->entry[0].name, 20, 12);
|
||||
char currstr[32+1];
|
||||
TruncateString(currstr, path, 32, 12);
|
||||
ShowPrompt(false, "%s\nFailed copying file", currstr);
|
||||
*cursor = i;
|
||||
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);
|
||||
}
|
||||
|
||||
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() {
|
||||
static const u32 quick_stp = 20;
|
||||
u32 exit_mode = GODMODE_EXIT_REBOOT;
|
||||
@ -1371,46 +1452,18 @@ u32 GodMode() {
|
||||
exit_mode = GODMODE_EXIT_POWEROFF;
|
||||
break;
|
||||
} 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;
|
||||
int bonus = (GetNandUnusedSectors(NAND_SYSNAND) > 0x2000) ? (int) ++n_opt : -1; // 4MB minsize
|
||||
int multi = (CheckMultiEmuNand()) ? (int) ++n_opt : -1;
|
||||
if (bonus < 0) optionstr[3] = "Switch EmuNAND";
|
||||
u32 user_select = ShowSelectPrompt(n_opt, optionstr, "HOME button pressed.\nSelect action:" );
|
||||
u32 user_select = 0;
|
||||
while (((user_select = ShowSelectPrompt(n_opt, optionstr, promptstr)) == 3) &&
|
||||
(HomeMoreMenu(current_path, current_dir, clipboard) == 1)); // more... menu
|
||||
if (user_select == 1) {
|
||||
exit_mode = GODMODE_EXIT_POWEROFF;
|
||||
break;
|
||||
} else if (user_select == 2) {
|
||||
exit_mode = GODMODE_EXIT_REBOOT;
|
||||
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)) {
|
||||
if (!InitVCartDrive() && (pad_state & CART_INSERT)) // reinit virtual cart drive
|
||||
|
Loading…
x
Reference in New Issue
Block a user