Add key combo to uninstall unlaunch alongside the hnaa failsafe

This commit is contained in:
Edoardo Lolletti 2024-04-27 19:09:23 +02:00
parent 027308e1f5
commit 593141e702
3 changed files with 78 additions and 20 deletions

View File

@ -22,6 +22,7 @@ static const char* splashSoundBinaryPatchPath = NULL;
static const char* customBgPath = NULL; static const char* customBgPath = NULL;
volatile bool charging = false; volatile bool charging = false;
volatile u8 batteryLevel = 0; volatile u8 batteryLevel = 0;
static bool wantsUnsafeUnlaunchUninstall = false;
PrintConsole topScreen; PrintConsole topScreen;
PrintConsole bottomScreen; PrintConsole bottomScreen;
@ -32,7 +33,8 @@ enum {
MAIN_MENU_TID_PATCHES, MAIN_MENU_TID_PATCHES,
MAIN_MENU_SOUND_SPLASH_PATCHES, MAIN_MENU_SOUND_SPLASH_PATCHES,
MAIN_MENU_SAFE_UNLAUNCH_INSTALL, MAIN_MENU_SAFE_UNLAUNCH_INSTALL,
MAIN_MENU_EXIT MAIN_MENU_EXIT,
MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP,
}; };
static void setupScreens() static void setupScreens()
@ -92,12 +94,17 @@ static int mainMenu(int cursor)
addMenuItem(m, soundPatchesStr, NULL, foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL, false); addMenuItem(m, soundPatchesStr, NULL, foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL, false);
addMenuItem(m, installUnlaunchStr, NULL, foundUnlaunchInstallerVersion != INVALID && !unlaunchFound, false); addMenuItem(m, installUnlaunchStr, NULL, foundUnlaunchInstallerVersion != INVALID && !unlaunchFound, false);
addMenuItem(m, "Exit", NULL, true, false); addMenuItem(m, "Exit", NULL, true, false);
if(wantsUnsafeUnlaunchUninstall)
addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false);
m->cursor = cursor; m->cursor = cursor;
//bottom screen //bottom screen
printMenu(m); printMenu(m);
int konamiCode = 0;
bool konamiCodeCooldown = false;
while (!programEnd) while (!programEnd)
{ {
swiWaitForVBlank(); swiWaitForVBlank();
@ -108,6 +115,29 @@ static int mainMenu(int cursor)
if (keysDown() & KEY_A) if (keysDown() & KEY_A)
break; break;
if(wantsUnsafeUnlaunchUninstall)
continue;
int held = keysHeld();
if ((held & (KEY_L | KEY_R | KEY_Y)) == (KEY_L | KEY_R | KEY_Y))
{
if(held == (KEY_L | KEY_R | KEY_Y) && !konamiCodeCooldown)
{
konamiCodeCooldown = true;
++konamiCode;
}
}
else
{
konamiCodeCooldown = false;
}
if (konamiCode == 5)
{
wantsUnsafeUnlaunchUninstall = true;
addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false);
}
} }
int result = m->cursor; int result = m->cursor;
@ -158,22 +188,22 @@ int main(int argc, char **argv)
messageBox("nand init \x1B[31mfailed\n\x1B[47m"); messageBox("nand init \x1B[31mfailed\n\x1B[47m");
return 0; return 0;
} }
while (batteryLevel < 7 && !charging) while (batteryLevel < 7 && !charging)
{ {
if (choiceBox("\x1B[47mBattery is too low!\nPlease plug in the console.\n\nContinue?") == NO) if (choiceBox("\x1B[47mBattery is too low!\nPlease plug in the console.\n\nContinue?") == NO)
return 0; return 0;
} }
DeviceList* deviceList = getDeviceList(); DeviceList* deviceList = getDeviceList();
const char* installerPath = (argc > 0) ? argv[0] : (deviceList ? deviceList->appname : "sd:/ntrboot.nds"); const char* installerPath = (argc > 0) ? argv[0] : (deviceList ? deviceList->appname : "sd:/ntrboot.nds");
if (!nitroFSInit(installerPath)) if (!nitroFSInit(installerPath))
{ {
messageBox("nitroFSInit()...\x1B[31mFailed\n\x1B[47m"); messageBox("nitroFSInit()...\x1B[31mFailed\n\x1B[47m");
} }
if (fileExists("sd:/unlaunch.dsi")) if (fileExists("sd:/unlaunch.dsi"))
{ {
foundUnlaunchInstallerVersion = loadUnlaunchInstaller("sd:/unlaunch.dsi"); foundUnlaunchInstallerVersion = loadUnlaunchInstaller("sd:/unlaunch.dsi");
@ -184,7 +214,7 @@ int main(int argc, char **argv)
"Attempting to use the bundled one."); "Attempting to use the bundled one.");
} }
} }
if(foundUnlaunchInstallerVersion == INVALID) if(foundUnlaunchInstallerVersion == INVALID)
{ {
foundUnlaunchInstallerVersion = loadUnlaunchInstaller("nitro:/unlaunch.dsi"); foundUnlaunchInstallerVersion = loadUnlaunchInstaller("nitro:/unlaunch.dsi");
@ -195,7 +225,7 @@ int main(int argc, char **argv)
"Installing unlaunch won't be possible."); "Installing unlaunch won't be possible.");
} }
} }
if(fileExists("nitro:/unlaunch-patch.bin")) if(fileExists("nitro:/unlaunch-patch.bin"))
{ {
splashSoundBinaryPatchPath = "nitro:/unlaunch-patch.bin"; splashSoundBinaryPatchPath = "nitro:/unlaunch-patch.bin";
@ -236,11 +266,11 @@ int main(int argc, char **argv)
} }
// HWINFO_S may not always exist (PRE_IMPORT). Fill in defaults if that happens. // HWINFO_S may not always exist (PRE_IMPORT). Fill in defaults if that happens.
} }
// I own and know of many people with retail and dev prototypes // I own and know of many people with retail and dev prototypes
// These can normally be identified by having the region set to ALL (0x41) // These can normally be identified by having the region set to ALL (0x41)
retailConsole = (region != 0x41 && region != 0xFF); retailConsole = (region != 0x41 && region != 0xFF);
unsigned long long tmdSize = getFileSizePath(hnaaTmdPath); unsigned long long tmdSize = getFileSizePath(hnaaTmdPath);
if (tmdSize > 520) if (tmdSize > 520)
{ {
@ -260,8 +290,10 @@ int main(int argc, char **argv)
switch (cursor) switch (cursor)
{ {
case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL: case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL:
case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP:
if(unlaunchFound && nandio_unlock_writing()) { if(unlaunchFound && nandio_unlock_writing()) {
if(uninstallUnlaunch(retailConsole, hnaaUnlaunchFound, retailLauncherTmdPath)) bool unsafeUninstall = wantsUnsafeUnlaunchUninstall && cursor == MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP;
if(uninstallUnlaunch(retailConsole, hnaaUnlaunchFound, retailLauncherTmdPath, unsafeUninstall))
{ {
messageBox("Uninstall successful!\n"); messageBox("Uninstall successful!\n");
unlaunchFound = false; unlaunchFound = false;
@ -273,7 +305,7 @@ int main(int argc, char **argv)
nandio_synchronize_fats(); nandio_synchronize_fats();
} }
break; break;
case MAIN_MENU_CUSTOM_BG: case MAIN_MENU_CUSTOM_BG:
if(foundUnlaunchInstallerVersion != INVALID) { if(foundUnlaunchInstallerVersion != INVALID) {
const char* customBg = backgroundMenu(); const char* customBg = backgroundMenu();
@ -289,13 +321,13 @@ int main(int argc, char **argv)
} }
} }
break; break;
case MAIN_MENU_TID_PATCHES: case MAIN_MENU_TID_PATCHES:
if(foundUnlaunchInstallerVersion == v1_9 || foundUnlaunchInstallerVersion == v2_0) { if(foundUnlaunchInstallerVersion == v1_9 || foundUnlaunchInstallerVersion == v2_0) {
disableAllPatches = !disableAllPatches; disableAllPatches = !disableAllPatches;
} }
break; break;
case MAIN_MENU_SOUND_SPLASH_PATCHES: case MAIN_MENU_SOUND_SPLASH_PATCHES:
if(foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL) { if(foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL) {
enableSoundAndSplash = !enableSoundAndSplash; enableSoundAndSplash = !enableSoundAndSplash;

View File

@ -65,7 +65,7 @@ bool isLauncherTmdPatched(const char* path)
return c == 0x47; return c == 0x47;
} }
static bool restoreMainTmd(const char* path, bool hasHNAABackup) static bool restoreMainTmd(const char* path, bool hasHNAABackup, bool removeHNAABackup)
{ {
FILE* launcherTmd = fopen(path, "r+b"); FILE* launcherTmd = fopen(path, "r+b");
if(!launcherTmd) if(!launcherTmd)
@ -83,6 +83,20 @@ static bool restoreMainTmd(const char* path, bool hasHNAABackup)
fseek(launcherTmd, -1, SEEK_CUR); fseek(launcherTmd, -1, SEEK_CUR);
c = 0x48; c = 0x48;
fwrite(&c, 1, 1, launcherTmd); fwrite(&c, 1, 1, launcherTmd);
fclose(launcherTmd);
if(removeHNAABackup && hasHNAABackup)
{
if(!toggleFileReadOnly(hnaaTmdPath, false))
{
messageBox("\x1B[31mError:\x1B[33m Failed to mark unlaunch's title.tmd as writable\nLeaving as is\n");
}
else
{
remove(hnaaTmdPath);
rmdir("nand:/title/00030017/484e4141/content");
rmdir("nand:/title/00030017/484e4141");
}
}
} }
else if(c != 0x47) else if(c != 0x47)
{ {
@ -93,7 +107,7 @@ static bool restoreMainTmd(const char* path, bool hasHNAABackup)
// This is also a good idea to make sure the tmd is 520b. // This is also a good idea to make sure the tmd is 520b.
// You will have a much higher brick risk if something goes wrong with a tmd over 520b. // You will have a much higher brick risk if something goes wrong with a tmd over 520b.
// See: http://docs.randommeaninglesscharacters.com/unlaunch.html // See: http://docs.randommeaninglesscharacters.com/unlaunch.html
if(!hasHNAABackup) if(!hasHNAABackup && !removeHNAABackup)
{ {
auto choiceString = [&]{ auto choiceString = [&]{
if(installerVersion != INVALID) if(installerVersion != INVALID)
@ -129,6 +143,19 @@ static bool restoreMainTmd(const char* path, bool hasHNAABackup)
} }
} }
} }
if(removeHNAABackup && hasHNAABackup)
{
if(!toggleFileReadOnly(hnaaTmdPath, false))
{
messageBox("\x1B[31mError:\x1B[33m Failed to mark unlaunch's title.tmd as writable\nLeaving as is\n");
}
else
{
remove(hnaaTmdPath);
rmdir("nand:/title/00030017/484e4141/content");
rmdir("nand:/title/00030017/484e4141");
}
}
if (ftruncate(fileno(launcherTmd), 520) != 0) { if (ftruncate(fileno(launcherTmd), 520) != 0) {
messageBox("\x1B[31mError:\x1B[33m Failed to remove unlaunch\n"); messageBox("\x1B[31mError:\x1B[33m Failed to remove unlaunch\n");
fclose(launcherTmd); fclose(launcherTmd);
@ -141,7 +168,6 @@ static bool restoreMainTmd(const char* path, bool hasHNAABackup)
fclose(launcherTmd); fclose(launcherTmd);
return false; return false;
} }
fclose(launcherTmd);
return true; return true;
} }
@ -188,7 +214,7 @@ static bool restoreProtoTmd(const char* path)
return true; return true;
} }
bool uninstallUnlaunch(bool retailConsole, bool hasHNAABackup, const char* retailLauncherTmdPath) bool uninstallUnlaunch(bool retailConsole, bool hasHNAABackup, const char* retailLauncherTmdPath, bool removeHNAABackup)
{ {
// TODO: handle retailLauncherTmdPresentAndToBePatched = false on retail consoles // TODO: handle retailLauncherTmdPresentAndToBePatched = false on retail consoles
if (retailConsole) { if (retailConsole) {
@ -196,7 +222,7 @@ bool uninstallUnlaunch(bool retailConsole, bool hasHNAABackup, const char* retai
{ {
return false; return false;
} }
if (!restoreMainTmd(retailLauncherTmdPath, hasHNAABackup)) if (!restoreMainTmd(retailLauncherTmdPath, hasHNAABackup, removeHNAABackup))
{ {
return false; return false;
} }

View File

@ -15,7 +15,7 @@ typedef enum UNLAUNCH_VERSION {
const char* getUnlaunchVersionString(UNLAUNCH_VERSION); const char* getUnlaunchVersionString(UNLAUNCH_VERSION);
bool uninstallUnlaunch(bool notProto, bool hasHNAABackup, const char* retailLauncherTmdPath); bool uninstallUnlaunch(bool notProto, bool hasHNAABackup, const char* retailLauncherTmdPath, bool removeHNAABackup);
bool installUnlaunch(bool retailConsole, const char* retailLauncherTmdPath, bool disableAllPatches, const char* splashSoundBinaryPatchPath, const char* customBackgroundPath); bool installUnlaunch(bool retailConsole, const char* retailLauncherTmdPath, bool disableAllPatches, const char* splashSoundBinaryPatchPath, const char* customBackgroundPath);
bool isLauncherTmdPatched(const char* path); bool isLauncherTmdPatched(const char* path);