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

View File

@ -39,6 +39,8 @@ constexpr std::array knownUnlaunchHashes{
"15f4a36251d1408d71114019b2825fe8f5b4c8cc"_sha1, // v2.0
};
static bool writeUnlaunchToHNAAFolder();
bool isValidUnlaunchInstallerSize(size_t size)
{
return size == 163320 /*1.8*/ || size == 196088 /*1.9*/;
@ -58,7 +60,7 @@ bool isLauncherTmdPatched(const char* path)
return c == 0x47;
}
static bool restoreMainTmd(const char* path)
static bool restoreMainTmd(const char* path, bool hasHNAABackup)
{
FILE* launcherTmd = fopen(path, "r+b");
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.
// You will have a much higher brick risk if something goes wrong with a tmd over 520b.
// 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) {
messageBox("\x1B[31mError:\x1B[33m Failed to remove unlaunch\n");
fclose(launcherTmd);
@ -146,16 +183,20 @@ static bool restoreProtoTmd(const char* path)
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
if (retailConsole) {
if (!toggleFileReadOnly(retailLauncherTmdPath, false) || !restoreMainTmd(retailLauncherTmdPath))
if (!toggleFileReadOnly(retailLauncherTmdPath, false))
{
return false;
}
if (!restoreMainTmd(retailLauncherTmdPath, hasHNAABackup))
{
return false;
}
} 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;
}
@ -199,7 +240,7 @@ static bool writeUnlaunchTmd(const char* path)
return true;
}
static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath)
static bool writeUnlaunchToHNAAFolder()
{
//Create HNAA launcher folder
if (!safeCreateDir("nand:/title/00030017")
@ -224,11 +265,18 @@ static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath)
if(!toggleFileReadOnly(hnaaTmdPath, true))
{
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");
return false;
}
return true;
}
static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath)
{
if(!writeUnlaunchToHNAAFolder())
return false;
//Finally patch the default launcher tmd to be invalid
//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
{
remove("nand:/title/00030017/484e4141/content/title.tmd");
remove(hnaaTmdPath);
rmdir("nand:/title/00030017/484e4141/content");
rmdir("nand:/title/00030017/484e4141");
}
@ -252,11 +300,7 @@ static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath)
}
if (!toggleFileReadOnly(retailLauncherTmdPath, true))
{
#if 0
// 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
messageBox("\x1B[31mError:\x1B[33m Failed to mark default launcher's title.tmd\nas read only, install might be unstable\n");
}
}
return true;

View File

@ -6,7 +6,7 @@
extern "C" {
#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 isLauncherTmdPatched(const char* path);