mirror of
https://github.com/rvtr/unlaunch-installer_dev.git
synced 2026-01-26 13:43:08 -05:00
Warn the user about the risk of uninstalling without backup HNAA install and prompt to install that
This commit is contained in:
parent
f5b54fbd0f
commit
cca04004fc
@ -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);
|
||||||
|
if (tmdSize > 520)
|
||||||
{
|
{
|
||||||
unsigned long long tmdSize = getFileSizePath(hnaaTmdPath);
|
unlaunchFound = (mainTmdIsPatched || !retailConsole);
|
||||||
if (tmdSize > 520)
|
hnaaUnlaunchFound = true;
|
||||||
{
|
|
||||||
unlaunchFound = 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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user