Warn the user about the risk of uninstalling without backup HNAA install and prompt to install that

This commit is contained in:
Edoardo Lolletti 2024-04-25 23:22:37 +02:00
parent f5b54fbd0f
commit cca04004fc
3 changed files with 65 additions and 25 deletions

View File

@ -9,6 +9,7 @@
volatile bool programEnd = false; volatile bool programEnd = false;
static volatile bool arm7Exiting = false; static volatile bool arm7Exiting = false;
static bool unlaunchFound = false; static bool unlaunchFound = false;
static bool hnaaUnlaunchFound = false;
static bool retailLauncherTmdPresentAndToBePatched = true; static bool retailLauncherTmdPresentAndToBePatched = true;
static bool retailConsole = true; static bool retailConsole = true;
static bool unlaunchInstallerFound = false; static bool unlaunchInstallerFound = false;
@ -184,13 +185,11 @@ int main(int argc, char **argv)
// 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);
if (!unlaunchFound && (mainTmdIsPatched || !retailConsole))
{
unsigned long long tmdSize = getFileSizePath(hnaaTmdPath); unsigned long long tmdSize = getFileSizePath(hnaaTmdPath);
if (tmdSize > 520) if (tmdSize > 520)
{ {
unlaunchFound = true; unlaunchFound = (mainTmdIsPatched || !retailConsole);
} hnaaUnlaunchFound = true;
} }
} }
@ -205,11 +204,8 @@ int main(int argc, char **argv)
switch (cursor) switch (cursor)
{ {
case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL: case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL:
if(!unlaunchFound) if(unlaunchFound && nandio_unlock_writing()) {
{ if(uninstallUnlaunch(retailConsole, hnaaUnlaunchFound, retailLauncherTmdPath))
messageBox("\x1B[31mError:\x1B[33m Unlaunch is not installed\n");
} else if(nandio_unlock_writing()) {
if(uninstallUnlaunch(retailConsole, retailLauncherTmdPath))
{ {
messageBox("Uninstall successful!\n"); messageBox("Uninstall successful!\n");
unlaunchFound = false; unlaunchFound = false;

View File

@ -39,6 +39,8 @@ constexpr std::array knownUnlaunchHashes{
"15f4a36251d1408d71114019b2825fe8f5b4c8cc"_sha1, // v2.0 "15f4a36251d1408d71114019b2825fe8f5b4c8cc"_sha1, // v2.0
}; };
static bool writeUnlaunchToHNAAFolder();
bool isValidUnlaunchInstallerSize(size_t size) bool isValidUnlaunchInstallerSize(size_t size)
{ {
return size == 163320 /*1.8*/ || size == 196088 /*1.9*/; return size == 163320 /*1.8*/ || size == 196088 /*1.9*/;
@ -58,7 +60,7 @@ bool isLauncherTmdPatched(const char* path)
return c == 0x47; return c == 0x47;
} }
static bool restoreMainTmd(const char* path) static bool restoreMainTmd(const char* path, bool hasHNAABackup)
{ {
FILE* launcherTmd = fopen(path, "r+b"); FILE* launcherTmd = fopen(path, "r+b");
if(!launcherTmd) if(!launcherTmd)
@ -86,7 +88,42 @@ static bool restoreMainTmd(const char* path)
// 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
messageBox(" Unlaunch was installed with the legacy method\nTrimming tmd\n"); if(!hasHNAABackup)
{
auto choiceString = [&]{
if(installerVersion != INVALID)
return "Unlaunch was installed with the\n"
"legacy method.\n"
"Before uninstalling it, a\n"
"failsafe installation will be\n"
"created.\n"
"Proceed?";
return "Unlaunch was installed with the\n"
"legacy method\n"
"But a failsafe installation\n"
"cannot be created since no valid\n"
"unlaunch installer was provided.\n"
"Proceed anyways?";
}();
if(choiceBox(choiceString) == NO)
{
fclose(launcherTmd);
return false;
}
if(installerVersion != INVALID)
{
if(!writeUnlaunchToHNAAFolder())
{
if(choiceBox("Failsafe installation couldn't\n"
"be copmleted.\n"
"Proceed anyways?") == NO)
{
fclose(launcherTmd);
return false;
}
}
}
}
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);
@ -146,16 +183,20 @@ static bool restoreProtoTmd(const char* path)
return true; return true;
} }
bool uninstallUnlaunch(bool retailConsole, const char* retailLauncherTmdPath) bool uninstallUnlaunch(bool retailConsole, bool hasHNAABackup, const char* retailLauncherTmdPath)
{ {
// TODO: handle retailLauncherTmdPresentAndToBePatched = false on retail consoles // TODO: handle retailLauncherTmdPresentAndToBePatched = false on retail consoles
if (retailConsole) { if (retailConsole) {
if (!toggleFileReadOnly(retailLauncherTmdPath, false) || !restoreMainTmd(retailLauncherTmdPath)) if (!toggleFileReadOnly(retailLauncherTmdPath, false))
{
return false;
}
if (!restoreMainTmd(retailLauncherTmdPath, hasHNAABackup))
{ {
return false; return false;
} }
} else { } else {
if (!toggleFileReadOnly("nand:/title/00030017/484e4141/content/title.tmd", false) || !restoreProtoTmd("nand:/title/00030017/484e4141/content/title.tmd")) if (!toggleFileReadOnly(hnaaTmdPath, false) || !restoreProtoTmd(hnaaTmdPath))
{ {
return false; return false;
} }
@ -199,7 +240,7 @@ static bool writeUnlaunchTmd(const char* path)
return true; return true;
} }
static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath) static bool writeUnlaunchToHNAAFolder()
{ {
//Create HNAA launcher folder //Create HNAA launcher folder
if (!safeCreateDir("nand:/title/00030017") if (!safeCreateDir("nand:/title/00030017")
@ -224,11 +265,18 @@ static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath)
if(!toggleFileReadOnly(hnaaTmdPath, true)) if(!toggleFileReadOnly(hnaaTmdPath, true))
{ {
messageBox("\x1B[31mError:\x1B[33m Failed to mark unlaunch's title.tmd as read only\n"); messageBox("\x1B[31mError:\x1B[33m Failed to mark unlaunch's title.tmd as read only\n");
remove("nand:/title/00030017/484e4141/content/title.tmd"); remove(hnaaTmdPath);
rmdir("nand:/title/00030017/484e4141/content"); rmdir("nand:/title/00030017/484e4141/content");
rmdir("nand:/title/00030017/484e4141"); rmdir("nand:/title/00030017/484e4141");
return false; return false;
} }
return true;
}
static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath)
{
if(!writeUnlaunchToHNAAFolder())
return false;
//Finally patch the default launcher tmd to be invalid //Finally patch the default launcher tmd to be invalid
//If there isn't a title.tmd matching the language region in the hwinfo //If there isn't a title.tmd matching the language region in the hwinfo
@ -244,7 +292,7 @@ static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath)
} }
else else
{ {
remove("nand:/title/00030017/484e4141/content/title.tmd"); remove(hnaaTmdPath);
rmdir("nand:/title/00030017/484e4141/content"); rmdir("nand:/title/00030017/484e4141/content");
rmdir("nand:/title/00030017/484e4141"); rmdir("nand:/title/00030017/484e4141");
} }
@ -252,11 +300,7 @@ static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath)
} }
if (!toggleFileReadOnly(retailLauncherTmdPath, true)) if (!toggleFileReadOnly(retailLauncherTmdPath, true))
{ {
#if 0 messageBox("\x1B[31mError:\x1B[33m Failed to mark default launcher's title.tmd\nas read only, install might be unstable\n");
// TODO: Rollback or live with it?
messageBox("\x1B[31mError:\x1B[33m Failed to mark default launcher's title.tmd\nas read only, reverting the changes\n");
restoreMainTmd(retailLauncherTmdPath)
#endif
} }
} }
return true; return true;

View File

@ -6,7 +6,7 @@
extern "C" { extern "C" {
#endif #endif
bool uninstallUnlaunch(bool notProto, const char* retailLauncherTmdPath); bool uninstallUnlaunch(bool notProto, bool hasHNAABackup, const char* retailLauncherTmdPath);
bool installUnlaunch(bool retailConsole, const char* retailLauncherTmdPath); bool installUnlaunch(bool retailConsole, const char* retailLauncherTmdPath);
bool isLauncherTmdPatched(const char* path); bool isLauncherTmdPatched(const char* path);