From cae02f660756904eea706fdca81df1e5c000d02f Mon Sep 17 00:00:00 2001 From: Edoardo Lolletti Date: Tue, 12 Aug 2025 17:42:03 +0200 Subject: [PATCH] Rework install/unlinstall flow Restructure the code and use the same approach as the launcher tmd restorer to deal with tmds. Store all the known tmds for all the launcher versions with their corresponding shas, and use them when restoring the console. Now if the main tmd isn't either the stock one or one with the patch done by this program, it's treated a invalid and will be restored from the saved ones when uninstalling. This breaks for now proto/dev consoles as there is no handling for "default tmds" on them and the program logic has to be changed accordingly --- Makefile | 3 +- arm9/Makefile | 2 +- arm9/include/version.h | 2 +- arm9/src/consoleInfo.h | 27 + arm9/src/main.c | 561 ------------------- arm9/src/main.cpp | 705 ++++++++++++++++++++++++ arm9/src/unlaunch.cpp | 231 ++++---- arm9/src/unlaunch.h | 18 +- nitrofiles/484e4143/tmd.1024 | Bin 0 -> 520 bytes nitrofiles/484e4143/tmd.1024.patch.sha1 | 1 + nitrofiles/484e4143/tmd.1024.sha1 | 1 + nitrofiles/484e4143/tmd.1280 | Bin 0 -> 520 bytes nitrofiles/484e4143/tmd.1280.patch.sha1 | 1 + nitrofiles/484e4143/tmd.1280.sha1 | 1 + nitrofiles/484e4143/tmd.1536 | Bin 0 -> 520 bytes nitrofiles/484e4143/tmd.1536.patch.sha1 | 1 + nitrofiles/484e4143/tmd.1536.sha1 | 1 + nitrofiles/484e4143/tmd.1792 | Bin 0 -> 520 bytes nitrofiles/484e4143/tmd.1792.patch.sha1 | 1 + nitrofiles/484e4143/tmd.1792.sha1 | 1 + nitrofiles/484e4143/tmd.512 | Bin 0 -> 520 bytes nitrofiles/484e4143/tmd.512.patch.sha1 | 1 + nitrofiles/484e4143/tmd.512.sha1 | 1 + nitrofiles/484e4143/tmd.768 | Bin 0 -> 520 bytes nitrofiles/484e4143/tmd.768.patch.sha1 | 1 + nitrofiles/484e4143/tmd.768.sha1 | 1 + nitrofiles/484e4145/tmd.1024 | Bin 0 -> 520 bytes nitrofiles/484e4145/tmd.1024.patch.sha1 | 1 + nitrofiles/484e4145/tmd.1024.sha1 | 1 + nitrofiles/484e4145/tmd.1280 | Bin 0 -> 520 bytes nitrofiles/484e4145/tmd.1280.patch.sha1 | 1 + nitrofiles/484e4145/tmd.1280.sha1 | 1 + nitrofiles/484e4145/tmd.1536 | Bin 0 -> 520 bytes nitrofiles/484e4145/tmd.1536.patch.sha1 | 1 + nitrofiles/484e4145/tmd.1536.sha1 | 1 + nitrofiles/484e4145/tmd.1792 | Bin 0 -> 520 bytes nitrofiles/484e4145/tmd.1792.patch.sha1 | 1 + nitrofiles/484e4145/tmd.1792.sha1 | 1 + nitrofiles/484e4145/tmd.256 | Bin 0 -> 520 bytes nitrofiles/484e4145/tmd.256.patch.sha1 | 1 + nitrofiles/484e4145/tmd.256.sha1 | 1 + nitrofiles/484e4145/tmd.512 | Bin 0 -> 520 bytes nitrofiles/484e4145/tmd.512.patch.sha1 | 1 + nitrofiles/484e4145/tmd.512.sha1 | 1 + nitrofiles/484e4145/tmd.768 | Bin 0 -> 520 bytes nitrofiles/484e4145/tmd.768.patch.sha1 | 1 + nitrofiles/484e4145/tmd.768.sha1 | 1 + nitrofiles/484e414a/tmd.0 | Bin 0 -> 520 bytes nitrofiles/484e414a/tmd.0.patch.sha1 | 1 + nitrofiles/484e414a/tmd.0.sha1 | 1 + nitrofiles/484e414a/tmd.1024 | Bin 0 -> 520 bytes nitrofiles/484e414a/tmd.1024.patch.sha1 | 1 + nitrofiles/484e414a/tmd.1024.sha1 | 1 + nitrofiles/484e414a/tmd.1280 | Bin 0 -> 520 bytes nitrofiles/484e414a/tmd.1280.patch.sha1 | 1 + nitrofiles/484e414a/tmd.1280.sha1 | 1 + nitrofiles/484e414a/tmd.1536 | Bin 0 -> 520 bytes nitrofiles/484e414a/tmd.1536.patch.sha1 | 1 + nitrofiles/484e414a/tmd.1536.sha1 | 1 + nitrofiles/484e414a/tmd.1792 | Bin 0 -> 520 bytes nitrofiles/484e414a/tmd.1792.patch.sha1 | 1 + nitrofiles/484e414a/tmd.1792.sha1 | 1 + nitrofiles/484e414a/tmd.256 | Bin 0 -> 520 bytes nitrofiles/484e414a/tmd.256.patch.sha1 | 1 + nitrofiles/484e414a/tmd.256.sha1 | 1 + nitrofiles/484e414a/tmd.512 | Bin 0 -> 520 bytes nitrofiles/484e414a/tmd.512.patch.sha1 | 1 + nitrofiles/484e414a/tmd.512.sha1 | 1 + nitrofiles/484e414a/tmd.768 | Bin 0 -> 520 bytes nitrofiles/484e414a/tmd.768.patch.sha1 | 1 + nitrofiles/484e414a/tmd.768.sha1 | 1 + nitrofiles/484e414b/tmd.1024 | Bin 0 -> 520 bytes nitrofiles/484e414b/tmd.1024.patch.sha1 | 1 + nitrofiles/484e414b/tmd.1024.sha1 | 1 + nitrofiles/484e414b/tmd.1280 | Bin 0 -> 520 bytes nitrofiles/484e414b/tmd.1280.patch.sha1 | 1 + nitrofiles/484e414b/tmd.1280.sha1 | 1 + nitrofiles/484e414b/tmd.1536 | Bin 0 -> 520 bytes nitrofiles/484e414b/tmd.1536.patch.sha1 | 1 + nitrofiles/484e414b/tmd.1536.sha1 | 1 + nitrofiles/484e414b/tmd.1792 | Bin 0 -> 520 bytes nitrofiles/484e414b/tmd.1792.patch.sha1 | 1 + nitrofiles/484e414b/tmd.1792.sha1 | 1 + nitrofiles/484e414b/tmd.512 | Bin 0 -> 520 bytes nitrofiles/484e414b/tmd.512.patch.sha1 | 1 + nitrofiles/484e414b/tmd.512.sha1 | 1 + nitrofiles/484e414b/tmd.768 | Bin 0 -> 520 bytes nitrofiles/484e414b/tmd.768.patch.sha1 | 1 + nitrofiles/484e414b/tmd.768.sha1 | 1 + nitrofiles/484e4150/tmd.1024 | Bin 0 -> 520 bytes nitrofiles/484e4150/tmd.1024.patch.sha1 | 1 + nitrofiles/484e4150/tmd.1024.sha1 | 1 + nitrofiles/484e4150/tmd.1280 | Bin 0 -> 520 bytes nitrofiles/484e4150/tmd.1280.patch.sha1 | 1 + nitrofiles/484e4150/tmd.1280.sha1 | 1 + nitrofiles/484e4150/tmd.1536 | Bin 0 -> 520 bytes nitrofiles/484e4150/tmd.1536.patch.sha1 | 1 + nitrofiles/484e4150/tmd.1536.sha1 | 1 + nitrofiles/484e4150/tmd.1792 | Bin 0 -> 520 bytes nitrofiles/484e4150/tmd.1792.patch.sha1 | 1 + nitrofiles/484e4150/tmd.1792.sha1 | 1 + nitrofiles/484e4150/tmd.256 | Bin 0 -> 520 bytes nitrofiles/484e4150/tmd.256.patch.sha1 | 1 + nitrofiles/484e4150/tmd.256.sha1 | 1 + nitrofiles/484e4150/tmd.512 | Bin 0 -> 520 bytes nitrofiles/484e4150/tmd.512.patch.sha1 | 1 + nitrofiles/484e4150/tmd.512.sha1 | 1 + nitrofiles/484e4150/tmd.768 | Bin 0 -> 520 bytes nitrofiles/484e4150/tmd.768.patch.sha1 | 1 + nitrofiles/484e4150/tmd.768.sha1 | 1 + nitrofiles/484e4155/tmd.1024 | Bin 0 -> 520 bytes nitrofiles/484e4155/tmd.1024.patch.sha1 | 1 + nitrofiles/484e4155/tmd.1024.sha1 | 1 + nitrofiles/484e4155/tmd.1280 | Bin 0 -> 520 bytes nitrofiles/484e4155/tmd.1280.patch.sha1 | 1 + nitrofiles/484e4155/tmd.1280.sha1 | 1 + nitrofiles/484e4155/tmd.1536 | Bin 0 -> 520 bytes nitrofiles/484e4155/tmd.1536.patch.sha1 | 1 + nitrofiles/484e4155/tmd.1536.sha1 | 1 + nitrofiles/484e4155/tmd.1792 | Bin 0 -> 520 bytes nitrofiles/484e4155/tmd.1792.patch.sha1 | 1 + nitrofiles/484e4155/tmd.1792.sha1 | 1 + nitrofiles/484e4155/tmd.256 | Bin 0 -> 520 bytes nitrofiles/484e4155/tmd.256.patch.sha1 | 1 + nitrofiles/484e4155/tmd.256.sha1 | 1 + nitrofiles/484e4155/tmd.512 | Bin 0 -> 520 bytes nitrofiles/484e4155/tmd.512.patch.sha1 | 1 + nitrofiles/484e4155/tmd.512.sha1 | 1 + nitrofiles/484e4155/tmd.768 | Bin 0 -> 520 bytes nitrofiles/484e4155/tmd.768.patch.sha1 | 1 + nitrofiles/484e4155/tmd.768.sha1 | 1 + 131 files changed, 932 insertions(+), 699 deletions(-) create mode 100644 arm9/src/consoleInfo.h delete mode 100644 arm9/src/main.c create mode 100644 arm9/src/main.cpp create mode 100644 nitrofiles/484e4143/tmd.1024 create mode 100644 nitrofiles/484e4143/tmd.1024.patch.sha1 create mode 100644 nitrofiles/484e4143/tmd.1024.sha1 create mode 100644 nitrofiles/484e4143/tmd.1280 create mode 100644 nitrofiles/484e4143/tmd.1280.patch.sha1 create mode 100644 nitrofiles/484e4143/tmd.1280.sha1 create mode 100644 nitrofiles/484e4143/tmd.1536 create mode 100644 nitrofiles/484e4143/tmd.1536.patch.sha1 create mode 100644 nitrofiles/484e4143/tmd.1536.sha1 create mode 100644 nitrofiles/484e4143/tmd.1792 create mode 100644 nitrofiles/484e4143/tmd.1792.patch.sha1 create mode 100644 nitrofiles/484e4143/tmd.1792.sha1 create mode 100644 nitrofiles/484e4143/tmd.512 create mode 100644 nitrofiles/484e4143/tmd.512.patch.sha1 create mode 100644 nitrofiles/484e4143/tmd.512.sha1 create mode 100644 nitrofiles/484e4143/tmd.768 create mode 100644 nitrofiles/484e4143/tmd.768.patch.sha1 create mode 100644 nitrofiles/484e4143/tmd.768.sha1 create mode 100644 nitrofiles/484e4145/tmd.1024 create mode 100644 nitrofiles/484e4145/tmd.1024.patch.sha1 create mode 100644 nitrofiles/484e4145/tmd.1024.sha1 create mode 100644 nitrofiles/484e4145/tmd.1280 create mode 100644 nitrofiles/484e4145/tmd.1280.patch.sha1 create mode 100644 nitrofiles/484e4145/tmd.1280.sha1 create mode 100644 nitrofiles/484e4145/tmd.1536 create mode 100644 nitrofiles/484e4145/tmd.1536.patch.sha1 create mode 100644 nitrofiles/484e4145/tmd.1536.sha1 create mode 100644 nitrofiles/484e4145/tmd.1792 create mode 100644 nitrofiles/484e4145/tmd.1792.patch.sha1 create mode 100644 nitrofiles/484e4145/tmd.1792.sha1 create mode 100644 nitrofiles/484e4145/tmd.256 create mode 100644 nitrofiles/484e4145/tmd.256.patch.sha1 create mode 100644 nitrofiles/484e4145/tmd.256.sha1 create mode 100644 nitrofiles/484e4145/tmd.512 create mode 100644 nitrofiles/484e4145/tmd.512.patch.sha1 create mode 100644 nitrofiles/484e4145/tmd.512.sha1 create mode 100644 nitrofiles/484e4145/tmd.768 create mode 100644 nitrofiles/484e4145/tmd.768.patch.sha1 create mode 100644 nitrofiles/484e4145/tmd.768.sha1 create mode 100644 nitrofiles/484e414a/tmd.0 create mode 100644 nitrofiles/484e414a/tmd.0.patch.sha1 create mode 100644 nitrofiles/484e414a/tmd.0.sha1 create mode 100644 nitrofiles/484e414a/tmd.1024 create mode 100644 nitrofiles/484e414a/tmd.1024.patch.sha1 create mode 100644 nitrofiles/484e414a/tmd.1024.sha1 create mode 100644 nitrofiles/484e414a/tmd.1280 create mode 100644 nitrofiles/484e414a/tmd.1280.patch.sha1 create mode 100644 nitrofiles/484e414a/tmd.1280.sha1 create mode 100644 nitrofiles/484e414a/tmd.1536 create mode 100644 nitrofiles/484e414a/tmd.1536.patch.sha1 create mode 100644 nitrofiles/484e414a/tmd.1536.sha1 create mode 100644 nitrofiles/484e414a/tmd.1792 create mode 100644 nitrofiles/484e414a/tmd.1792.patch.sha1 create mode 100644 nitrofiles/484e414a/tmd.1792.sha1 create mode 100644 nitrofiles/484e414a/tmd.256 create mode 100644 nitrofiles/484e414a/tmd.256.patch.sha1 create mode 100644 nitrofiles/484e414a/tmd.256.sha1 create mode 100644 nitrofiles/484e414a/tmd.512 create mode 100644 nitrofiles/484e414a/tmd.512.patch.sha1 create mode 100644 nitrofiles/484e414a/tmd.512.sha1 create mode 100644 nitrofiles/484e414a/tmd.768 create mode 100644 nitrofiles/484e414a/tmd.768.patch.sha1 create mode 100644 nitrofiles/484e414a/tmd.768.sha1 create mode 100644 nitrofiles/484e414b/tmd.1024 create mode 100644 nitrofiles/484e414b/tmd.1024.patch.sha1 create mode 100644 nitrofiles/484e414b/tmd.1024.sha1 create mode 100644 nitrofiles/484e414b/tmd.1280 create mode 100644 nitrofiles/484e414b/tmd.1280.patch.sha1 create mode 100644 nitrofiles/484e414b/tmd.1280.sha1 create mode 100644 nitrofiles/484e414b/tmd.1536 create mode 100644 nitrofiles/484e414b/tmd.1536.patch.sha1 create mode 100644 nitrofiles/484e414b/tmd.1536.sha1 create mode 100644 nitrofiles/484e414b/tmd.1792 create mode 100644 nitrofiles/484e414b/tmd.1792.patch.sha1 create mode 100644 nitrofiles/484e414b/tmd.1792.sha1 create mode 100644 nitrofiles/484e414b/tmd.512 create mode 100644 nitrofiles/484e414b/tmd.512.patch.sha1 create mode 100644 nitrofiles/484e414b/tmd.512.sha1 create mode 100644 nitrofiles/484e414b/tmd.768 create mode 100644 nitrofiles/484e414b/tmd.768.patch.sha1 create mode 100644 nitrofiles/484e414b/tmd.768.sha1 create mode 100644 nitrofiles/484e4150/tmd.1024 create mode 100644 nitrofiles/484e4150/tmd.1024.patch.sha1 create mode 100644 nitrofiles/484e4150/tmd.1024.sha1 create mode 100644 nitrofiles/484e4150/tmd.1280 create mode 100644 nitrofiles/484e4150/tmd.1280.patch.sha1 create mode 100644 nitrofiles/484e4150/tmd.1280.sha1 create mode 100644 nitrofiles/484e4150/tmd.1536 create mode 100644 nitrofiles/484e4150/tmd.1536.patch.sha1 create mode 100644 nitrofiles/484e4150/tmd.1536.sha1 create mode 100644 nitrofiles/484e4150/tmd.1792 create mode 100644 nitrofiles/484e4150/tmd.1792.patch.sha1 create mode 100644 nitrofiles/484e4150/tmd.1792.sha1 create mode 100644 nitrofiles/484e4150/tmd.256 create mode 100644 nitrofiles/484e4150/tmd.256.patch.sha1 create mode 100644 nitrofiles/484e4150/tmd.256.sha1 create mode 100644 nitrofiles/484e4150/tmd.512 create mode 100644 nitrofiles/484e4150/tmd.512.patch.sha1 create mode 100644 nitrofiles/484e4150/tmd.512.sha1 create mode 100644 nitrofiles/484e4150/tmd.768 create mode 100644 nitrofiles/484e4150/tmd.768.patch.sha1 create mode 100644 nitrofiles/484e4150/tmd.768.sha1 create mode 100644 nitrofiles/484e4155/tmd.1024 create mode 100644 nitrofiles/484e4155/tmd.1024.patch.sha1 create mode 100644 nitrofiles/484e4155/tmd.1024.sha1 create mode 100644 nitrofiles/484e4155/tmd.1280 create mode 100644 nitrofiles/484e4155/tmd.1280.patch.sha1 create mode 100644 nitrofiles/484e4155/tmd.1280.sha1 create mode 100644 nitrofiles/484e4155/tmd.1536 create mode 100644 nitrofiles/484e4155/tmd.1536.patch.sha1 create mode 100644 nitrofiles/484e4155/tmd.1536.sha1 create mode 100644 nitrofiles/484e4155/tmd.1792 create mode 100644 nitrofiles/484e4155/tmd.1792.patch.sha1 create mode 100644 nitrofiles/484e4155/tmd.1792.sha1 create mode 100644 nitrofiles/484e4155/tmd.256 create mode 100644 nitrofiles/484e4155/tmd.256.patch.sha1 create mode 100644 nitrofiles/484e4155/tmd.256.sha1 create mode 100644 nitrofiles/484e4155/tmd.512 create mode 100644 nitrofiles/484e4155/tmd.512.patch.sha1 create mode 100644 nitrofiles/484e4155/tmd.512.sha1 create mode 100644 nitrofiles/484e4155/tmd.768 create mode 100644 nitrofiles/484e4155/tmd.768.patch.sha1 create mode 100644 nitrofiles/484e4155/tmd.768.sha1 diff --git a/Makefile b/Makefile index 9d44a2f..fd7e2d6 100644 --- a/Makefile +++ b/Makefile @@ -53,6 +53,7 @@ $(TARGET).dsi : $(NITRO_FILES) arm7/$(TARGET).elf arm9/$(TARGET).elf -g "$(GAME_CODE)" "00" "$(GAME_LABEL)" \ -b $(GAME_ICON) "$(GAME_TITLE);$(GAME_SUBTITLE1)" \ $(_ADDFILES) + cp $(TARGET).dsi ntrboot.nds #--------------------------------------------------------------------------------- arm7/$(TARGET).elf: @@ -66,4 +67,4 @@ arm9/$(TARGET).elf: clean: $(MAKE) -C arm9 clean $(MAKE) -C arm7 clean - rm -f $(TARGET).dsi $(TARGET).arm7 $(TARGET).arm9 + rm -f $(TARGET).dsi $(TARGET).arm7 $(TARGET).arm9 ntrboot.nds diff --git a/arm9/Makefile b/arm9/Makefile index 7110017..d464ce4 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -31,7 +31,7 @@ CFLAGS := -g -Wall -O2\ $(ARCH) CFLAGS += $(INCLUDE) -DARM9 -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++23 +CXXFLAGS := $(CFLAGS) -fno-rtti -fexceptions -std=gnu++23 -Wno-psabi ASFLAGS := -g $(ARCH) -march=armv5te -mtune=arm946e-s diff --git a/arm9/include/version.h b/arm9/include/version.h index 8222156..3458667 100644 --- a/arm9/include/version.h +++ b/arm9/include/version.h @@ -1,6 +1,6 @@ #ifndef VERSION_H #define VERSION_H -#define VERSION "v0.1" +#define VERSION "v1.0" #endif // VERSION_H diff --git a/arm9/src/consoleInfo.h b/arm9/src/consoleInfo.h new file mode 100644 index 0000000..20eb3d4 --- /dev/null +++ b/arm9/src/consoleInfo.h @@ -0,0 +1,27 @@ +#ifndef CONSOLE_INFO_H +#define CONSOLE_INFO_H + +#include +#include +#include + +#include "sha1digest.h" +#include "nocashFooter.h" + +struct consoleInfo { + bool isRetail{true}; + bool tmdPatched{false}; + bool tmdInvalid{false}; + bool tmdFound{true}; + bool tmdGood{false}; + bool UnlaunchHNAAtmdFound{false}; + bool needsNocashFooterToBeWritten{false}; + uint32_t launcherVersion{0}; + std::string launcherTmdPath; + std::string launcherAppPath; + std::array recoveryTmdData; + Sha1Digest recoveryTmdDataSha; + NocashFooter nocashFooter; +}; + +#endif diff --git a/arm9/src/main.c b/arm9/src/main.c deleted file mode 100644 index 27ee73f..0000000 --- a/arm9/src/main.c +++ /dev/null @@ -1,561 +0,0 @@ -#include "bgMenu.h" -#include "main.h" -#include "menu.h" -#include "message.h" -#include "nand/nandio.h" -#include "storage.h" -#include "version.h" -#include "unlaunch.h" -#include "nitrofs.h" -#include "deviceList.h" -#include "nocashFooter.h" - -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 UNLAUNCH_VERSION foundUnlaunchInstallerVersion = INVALID; -static bool disableAllPatches = false; -static bool enableSoundAndSplash = false; -static const char* splashSoundBinaryPatchPath = NULL; -static const char* customBgPath = NULL; -volatile bool charging = false; -volatile u8 batteryLevel = 0; -static bool advancedOptionsUnlocked = false; -static bool needsNocashFooterToBeWritten = false; -static bool isLauncherVersionSupported = true; -static NocashFooter computedNocashFooter; - -PrintConsole topScreen; -PrintConsole bottomScreen; - -enum { - MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL, - MAIN_MENU_CUSTOM_BG, - MAIN_MENU_SOUND_SPLASH_PATCHES, - MAIN_MENU_SAFE_UNLAUNCH_INSTALL, - MAIN_MENU_EXIT, - MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP, - MAIN_MENU_WRITE_NOCASH_FOOTER_ONLY, - MAIN_MENU_TID_PATCHES, -}; - -static void setupScreens() -{ - REG_DISPCNT = MODE_FB0; - VRAM_A_CR = VRAM_ENABLE; - - videoSetMode(MODE_0_2D); - videoSetModeSub(MODE_0_2D); - - vramSetBankA(VRAM_A_MAIN_BG); - vramSetBankC(VRAM_C_SUB_BG); - - consoleInit(&topScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true); - consoleInit(&bottomScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true); - - clearScreen(&bottomScreen); - - VRAM_A[100] = 0xFFFF; -} - -static int mainMenu(int cursor) -{ - //top screen - clearScreen(&topScreen); - - iprintf("\t\"Safe\" unlaunch installer\n"); - iprintf("\nversion %s\n", VERSION); - iprintf("\n\n\x1B[41mWARNING:\x1B[47m This tool can write to" - "\nyour internal NAND!" - "\n\nThis always has a risk, albeit" - "\nlow, of \x1B[41mbricking\x1B[47m your system" - "\nand should be done with caution!\n"); - iprintf("\n\t \x1B[46mhttps://dsi.cfw.guide\x1B[47m\n"); - iprintf("\x1b[23;0Hedo9300 - 2024"); - - //menu - Menu* m = newMenu(); - setMenuHeader(m, "MAIN MENU"); - - char soundPatchesStr[64], tidPatchesStr[32], installUnlaunchStr[32]; - sprintf(tidPatchesStr, "Disable all patches: %s", - disableAllPatches ? "On" : "Off"); - sprintf(soundPatchesStr, "Enable sound and splash: %s", - enableSoundAndSplash ? "On" : "Off"); - if(foundUnlaunchInstallerVersion != INVALID) - { - sprintf(installUnlaunchStr, "Install unlaunch (%s)", getUnlaunchVersionString(foundUnlaunchInstallerVersion)); - } - else - { - strcpy(installUnlaunchStr, "Install unlaunch"); - } - addMenuItem(m, "Uninstall unlaunch", NULL, unlaunchFound && isLauncherVersionSupported, false); - addMenuItem(m, "Custom background", NULL, foundUnlaunchInstallerVersion != INVALID && isLauncherVersionSupported, true); - addMenuItem(m, soundPatchesStr, NULL, foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL && isLauncherVersionSupported, false); - addMenuItem(m, installUnlaunchStr, NULL, foundUnlaunchInstallerVersion != INVALID && !unlaunchFound && isLauncherVersionSupported, false); - addMenuItem(m, "Exit", NULL, true, false); - if(!isLauncherVersionSupported) - { - addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false); - } - else if(advancedOptionsUnlocked) - { - addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false); - addMenuItem(m, "Write nocash footer", NULL, needsNocashFooterToBeWritten, false); - addMenuItem(m, tidPatchesStr, NULL, (foundUnlaunchInstallerVersion == v1_9 || foundUnlaunchInstallerVersion == v2_0) && isLauncherVersionSupported, false); - } - - m->cursor = cursor; - - //bottom screen - printMenu(m); - - int konamiCode = 0; - bool konamiCodeCooldown = false; - - while (!programEnd) - { - swiWaitForVBlank(); - scanKeys(); - - if (moveCursor(m)) - printMenu(m); - - if (keysDown() & KEY_A) - break; - - if(advancedOptionsUnlocked) - 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) - { - advancedOptionsUnlocked = true; - // Enabled by default when unsupported - if(isLauncherVersionSupported) - { - addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false); - } - addMenuItem(m, "Write nocash footer", NULL, needsNocashFooterToBeWritten, false); - addMenuItem(m, tidPatchesStr, NULL, (foundUnlaunchInstallerVersion == v1_9 || foundUnlaunchInstallerVersion == v2_0) && isLauncherVersionSupported, false); - } - } - - int result = m->cursor; - freeMenu(m); - - return result; -} - -static void fifoHandlerPower(u32 value32, void* userdata) -{ - if (value32 == 0x54495845) // 'EXIT' - { - programEnd = true; - arm7Exiting = true; - } -} - -static void fifoHandlerBattery(u32 value32, void* userdata) -{ - batteryLevel = value32 & 0xF; - charging = (value32 & BIT(7)) != 0; -} - -int main(int argc, char **argv) -{ - keysSetRepeat(25, 5); - setupScreens(); - - fifoSetValue32Handler(FIFO_USER_01, fifoHandlerPower, NULL); - fifoSetValue32Handler(FIFO_USER_03, fifoHandlerBattery, NULL); - - //DSi check - if (!isDSiMode()) - { - messageBox("\x1B[31mError:\x1B[33m This app is exclusively for DSi."); - return 0; - } - - //setup sd card access - if (!fatInitDefault()) - { - messageBox("fatInitDefault()...\x1B[31mFailed\n\x1B[47m"); - } - - u32 clusterSize = getClusterSizeForPartition("sd:/"); - if(clusterSize > 32768) - { - messageBox("Sd card cluster size is too large"); - return 0; - } - - //setup nand access - if (!fatMountSimple("nand", &io_dsi_nand)) - { - messageBox("nand init \x1B[31mfailed\n\x1B[47m"); - return 0; - } - - NocashFooter footer; - - nandio_read_nocash_footer(&footer); - nandio_construct_nocash_footer(&computedNocashFooter); - - if(!(needsNocashFooterToBeWritten = !isFooterValid(&footer))) - { - if(memcmp(&footer, &computedNocashFooter, sizeof(footer)) != 0) - { - messageBox("\x1B[31mError:\x1B[33m This console has a\n" - "nocash footer embedded in its\n" - "nand that doesn't match the one\n" - "generated.\n" - "The footer already present will\n" - "be overwritten."); - needsNocashFooterToBeWritten = true; - } - } - - while (batteryLevel < 7 && !charging) - { - if (choiceBox("\x1B[47mBattery is too low!\nPlease plug in the console.\n\nContinue?") == NO) - return 0; - } - - DeviceList* deviceList = getDeviceList(); - - const char* installerPath = (argc > 0) ? argv[0] : (deviceList ? deviceList->appname : "sd:/ntrboot.nds"); - - if (!nitroFSInit(installerPath)) - { - messageBox("nitroFSInit()...\x1B[31mFailed\n\x1B[47m"); - } - - if (fileExists("sd:/unlaunch.dsi")) - { - foundUnlaunchInstallerVersion = loadUnlaunchInstaller("sd:/unlaunch.dsi"); - if (foundUnlaunchInstallerVersion == INVALID) - { - messageBox("\x1B[41mWARNING:\x1B[47m Failed to load unlaunch.dsi\n" - "from the root of the sd card.\n" - "Attempting to use the bundled one."); - } - } - - if(foundUnlaunchInstallerVersion == INVALID) - { - foundUnlaunchInstallerVersion = loadUnlaunchInstaller("nitro:/unlaunch.dsi"); - if (foundUnlaunchInstallerVersion == INVALID) - { - messageBox("\x1B[41mWARNING:\x1B[47m Failed to load bundled unlaunch\n" - "installer.\n" - "Installing unlaunch won't be possible."); - } - } - if (fileExists("sd:/unlaunch-patch.bin")) { - splashSoundBinaryPatchPath = "sd:/unlaunch-patch.bin"; - } - else if(fileExists("nitro:/unlaunch-patch.bin")) - { - splashSoundBinaryPatchPath = "nitro:/unlaunch-patch.bin"; - } - - //check for unlaunch and region - u8 region = 0xff; - char retailLauncherTmdPath[64]; - char retailLauncherPath[64]; - const char* hnaaTmdPath = "nand:/title/00030017/484e4141/content/title.tmd"; - { - FILE* file = fopen("nand:/sys/HWINFO_S.dat", "rb"); - bool mainTmdIsPatched = false; - if (file) - { - fseek(file, 0xA0, SEEK_SET); - u32 launcherTid; - fread(&launcherTid, sizeof(u32), 1, file); - fclose(file); - - region = launcherTid & 0xFF; - - sprintf(retailLauncherTmdPath, "nand:/title/00030017/%08lx/content/title.tmd", launcherTid); - FILE* tmd = fopen(retailLauncherTmdPath, "rb"); - unsigned long long tmdSize = getFileSize(tmd); - if(!tmd || tmdSize < 520) - { - //if size isn't 520 then the tmd either is not present, or is already invalid, thus no need to patch - retailLauncherTmdPresentAndToBePatched = false; - } - else - { - if (tmdSize > 520) - { - unlaunchFound = true; - } - else - { - mainTmdIsPatched = isLauncherTmdPatched(retailLauncherTmdPath); - } - fseek(tmd, 0x1DC, SEEK_SET); - unsigned short launcherVersion; - fread(&launcherVersion, sizeof(launcherVersion), 1, tmd); - // Launcher v4, build v1024 (shipped with firmware 1.4.2 (1.4.3 for china and korea) - // will fail to launch if another tmd withouth appropriate application, or an invalid - // tmd (in our case the one installed from unlaunch) is found in the HNAA launcher folder - // there's really no workaround to that, so that specific version is blacklisted and only uninstalling - // an "officially" installed unlaunch without leaving any backup behind will be allowed - if(launcherVersion == 4) - { - isLauncherVersionSupported = false; - messageBox("\x1B[41mWARNING:\x1B[47m This system version\n" - "doesn't support this install\n" - "method, only uninstalling\n" - "unaunch without backups will\n" - "be possible"); - } - else if (launcherVersion > 7) - { - char messageBoxError[128]; - sprintf(messageBoxError, "\x1B[41mWARNING:\x1B[47m This system version (%d)\n" - "is unknown\n" - "nothing will be done", (int)launcherVersion); - messageBox("\x1B[41mWARNING:\x1B[47m This system version\n" - "is unknown\n" - "nothing will be done"); - goto abort; - } - sprintf(retailLauncherPath, "nand:/title/00030017/%08lx/content/0000000%d.app", launcherTid, (int)launcherVersion); - } - if(tmd) - { - fclose(tmd); - } - // 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 - // These can normally be identified by having the region set to ALL (0x41) - retailConsole = (region != 0x41 && region != 0xFF); - - unsigned long long tmdSize = getFileSizePath(hnaaTmdPath); - if (tmdSize > 520) - { - unlaunchFound = unlaunchFound || (mainTmdIsPatched || !retailConsole); - hnaaUnlaunchFound = true; - } - } - - messageBox("\x1B[41mWARNING:\x1B[47m This tool can write to\n" - "your internal NAND!\n\n" - "This always has a risk, albeit\n" - "low, of \x1B[41mbricking\x1B[47m your system\n" - "and should be done with caution!\n\n" - "If you have not yet done so,\n" - "you should make a NAND backup."); - //main menu - int cursor = 0; - - while (!programEnd) - { - cursor = mainMenu(cursor); - if(programEnd) - break; - - switch (cursor) - { - case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL: - case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP: - if(!unlaunchFound) - { - break; - } - bool unsafeUninstall = advancedOptionsUnlocked && cursor == MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP; - if(!isLauncherVersionSupported && !unsafeUninstall) - { - break; - } - if(!nandio_unlock_writing()) - { - break; - } - printf("Uninstalling"); - if(needsNocashFooterToBeWritten) - { - printf("Writing nocash footer\n"); - if(!nandio_write_nocash_footer(&computedNocashFooter)) - { - nandio_lock_writing(); - messageBox("Failed to write nocash footer"); - break; - } - needsNocashFooterToBeWritten = false; - } - if(uninstallUnlaunch(retailConsole, hnaaUnlaunchFound, retailLauncherTmdPath, retailLauncherPath, unsafeUninstall)) - { - messageBox("Uninstall successful!\n"); - unlaunchFound = false; - } - else - { - messageBox("\x1B[31mError:\x1B[33m Uninstall failed\n"); - } - nandio_lock_writing(); - printf("Synchronizing FAT tables...\n"); - nandio_synchronize_fats(); - break; - - case MAIN_MENU_CUSTOM_BG: - if(!isLauncherVersionSupported) - { - break; - } - if(foundUnlaunchInstallerVersion == INVALID) - { - break; - } - const char* customBg = backgroundMenu(); - if(!customBg) - { - break; - } - if(strcmp(customBg, "default") == 0) - { - customBgPath = NULL; - } - else - { - customBgPath = customBg; - } - break; - - case MAIN_MENU_TID_PATCHES: - if(!isLauncherVersionSupported) - { - break; - } - if(advancedOptionsUnlocked && (foundUnlaunchInstallerVersion == v1_9 || foundUnlaunchInstallerVersion == v2_0)) { - disableAllPatches = !disableAllPatches; - } - break; - - case MAIN_MENU_SOUND_SPLASH_PATCHES: - if(!isLauncherVersionSupported) - { - break; - } - if(foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL) { - enableSoundAndSplash = !enableSoundAndSplash; - } - break; - - case MAIN_MENU_SAFE_UNLAUNCH_INSTALL: - if(!isLauncherVersionSupported) - { - break; - } - if(unlaunchFound || foundUnlaunchInstallerVersion == INVALID) - { - break; - } - if(choiceBox("Install unlaunch?") == NO) - { - break; - } - if(!retailLauncherTmdPresentAndToBePatched - && (choiceBox("There doesn't seem to be a launcher.tmd\n" - "file matcing the hwinfo file\n" - "Keep installing?") == NO)) - { - break; - } - if(!nandio_unlock_writing()) - { - break; - } - printf("Installing\n"); - if(needsNocashFooterToBeWritten) - { - printf("Writing nocash footer\n"); - if(!nandio_write_nocash_footer(&computedNocashFooter)) - { - nandio_lock_writing(); - messageBox("Failed to write nocash footer"); - break; - } - needsNocashFooterToBeWritten = false; - } - if(installUnlaunch(retailConsole, - retailLauncherTmdPresentAndToBePatched ? retailLauncherTmdPath : NULL, - retailLauncherTmdPresentAndToBePatched ? retailLauncherPath : NULL, - disableAllPatches, - enableSoundAndSplash ? splashSoundBinaryPatchPath : NULL, - customBgPath)) - { - messageBox("Install successful!\n"); - unlaunchFound = true; - } - else - { - messageBox("\x1B[31mError:\x1B[33m Install failed\n"); - } - nandio_lock_writing(); - printf("Synchronizing FAT tables...\n"); - nandio_synchronize_fats(); - break; - - case MAIN_MENU_WRITE_NOCASH_FOOTER_ONLY: - if(!needsNocashFooterToBeWritten) - { - break; - } - if(!nandio_write_nocash_footer(&computedNocashFooter)) - { - messageBox("Failed to write nocash footer"); - break; - } - needsNocashFooterToBeWritten = false; - break; - - case MAIN_MENU_EXIT: - programEnd = true; - break; - } - } - - abort: - - clearScreen(&bottomScreen); - printf("Unmounting NAND...\n"); - fatUnmount("nand:"); - printf("Merging stages...\n"); - nandio_shutdown(); - - fifoSendValue32(FIFO_USER_02, 0x54495845); // 'EXIT' - - while (arm7Exiting) - swiWaitForVBlank(); - - return 0; -} - -void clearScreen(PrintConsole* screen) -{ - consoleSelect(screen); - consoleClear(); -} \ No newline at end of file diff --git a/arm9/src/main.cpp b/arm9/src/main.cpp new file mode 100644 index 0000000..2fefba9 --- /dev/null +++ b/arm9/src/main.cpp @@ -0,0 +1,705 @@ +#include +#include +#include +#include +#include + +#include "bgMenu.h" +#include "consoleInfo.h" +#include "main.h" +#include "menu.h" +#include "message.h" +#include "nand/nandio.h" +#include "storage.h" +#include "version.h" +#include "unlaunch.h" +#include "nitrofs.h" +#include "deviceList.h" +#include "nocashFooter.h" + +using namespace std::string_view_literals; + +volatile bool programEnd = false; +static volatile bool arm7Exiting = false; +static bool retailLauncherTmdPresentAndToBePatched = true; +static UNLAUNCH_VERSION foundUnlaunchInstallerVersion = INVALID; +static bool disableAllPatches = false; +static bool enableSoundAndSplash = false; +static const char* splashSoundBinaryPatchPath = NULL; +static const char* customBgPath = NULL; +volatile bool charging = false; +volatile u8 batteryLevel = 0; +static bool advancedOptionsUnlocked = false; +static bool isLauncherVersionSupported = true; + +PrintConsole topScreen; +PrintConsole bottomScreen; + +enum { + MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL, + MAIN_MENU_CUSTOM_BG, + MAIN_MENU_SOUND_SPLASH_PATCHES, + MAIN_MENU_SAFE_UNLAUNCH_INSTALL, + MAIN_MENU_EXIT, + MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP, + MAIN_MENU_WRITE_NOCASH_FOOTER_ONLY, + MAIN_MENU_TID_PATCHES, +}; + +static void setupScreens() +{ + REG_DISPCNT = MODE_FB0; + VRAM_A_CR = VRAM_ENABLE; + + videoSetMode(MODE_0_2D); + videoSetModeSub(MODE_0_2D); + + vramSetBankA(VRAM_A_MAIN_BG); + vramSetBankC(VRAM_C_SUB_BG); + + consoleInit(&topScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true); + consoleInit(&bottomScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true); + + clearScreen(&bottomScreen); + + VRAM_A[100] = 0xFFFF; +} + +static int mainMenu(const consoleInfo& info, int cursor) +{ + const auto tidPatchesSupported = (foundUnlaunchInstallerVersion == v1_9 || foundUnlaunchInstallerVersion == v2_0) && isLauncherVersionSupported; + //top screen + clearScreen(&topScreen); + + iprintf("\t\"Safe\" unlaunch installer\n"); + iprintf("\nversion %s\n", VERSION); + iprintf("\n\n\x1B[41mWARNING:\x1B[47m This tool can write to" + "\nyour internal NAND!" + "\n\nThis always has a risk, albeit" + "\nlow, of \x1B[41mbricking\x1B[47m your system" + "\nand should be done with caution!\n"); + iprintf("\n\t \x1B[46mhttps://dsi.cfw.guide\x1B[47m\n"); + iprintf("\x1b[23;0Hedo9300 - 2025"); + + //menu + Menu* m = newMenu(); + setMenuHeader(m, "MAIN MENU"); + + auto [restore_string, restore_string_no_backup] = [&]{ + if(info.tmdInvalid) { + return std::make_pair("Restore launcher tmd", "Restore launcher tmd no backup"); + } + return std::make_pair("Uninstall unlaunch", "Uninstall unlaunch no backup"); + }(); + + char soundPatchesStr[64], tidPatchesStr[32], installUnlaunchStr[32]; + sprintf(tidPatchesStr, "Disable all patches: %s", + disableAllPatches ? "On" : "Off"); + sprintf(soundPatchesStr, "Enable sound and splash: %s", + enableSoundAndSplash ? "On" : "Off"); + if(foundUnlaunchInstallerVersion != INVALID) + { + sprintf(installUnlaunchStr, "Install unlaunch (%s)", getUnlaunchVersionString(foundUnlaunchInstallerVersion)); + } + else + { + strcpy(installUnlaunchStr, "Install unlaunch"); + } + addMenuItem(m, restore_string, NULL, (info.tmdInvalid || info.tmdPatched) && isLauncherVersionSupported, false); + addMenuItem(m, "Custom background", NULL, foundUnlaunchInstallerVersion != INVALID && isLauncherVersionSupported, true); + addMenuItem(m, soundPatchesStr, NULL, foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL && isLauncherVersionSupported, false); + addMenuItem(m, installUnlaunchStr, NULL, foundUnlaunchInstallerVersion != INVALID && !(info.tmdInvalid || info.tmdPatched) && isLauncherVersionSupported, false); + addMenuItem(m, "Exit", NULL, true, false); + if(!isLauncherVersionSupported) + { + addMenuItem(m, restore_string_no_backup, NULL, (info.tmdInvalid || info.tmdPatched), false); + } + else if(advancedOptionsUnlocked) + { + addMenuItem(m, restore_string_no_backup, NULL, (info.tmdInvalid || info.tmdPatched), false); + addMenuItem(m, "Write nocash footer", NULL, info.needsNocashFooterToBeWritten, false); + addMenuItem(m, tidPatchesStr, NULL, tidPatchesSupported, false); + } + + m->cursor = cursor; + + //bottom screen + printMenu(m); + + int konamiCode = 0; + bool konamiCodeCooldown = false; + + while (!programEnd) + { + swiWaitForVBlank(); + scanKeys(); + + if (moveCursor(m)) + printMenu(m); + + if (keysDown() & KEY_A) + break; + + if(advancedOptionsUnlocked) + 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) + { + advancedOptionsUnlocked = true; + // Enabled by default when unsupported + if(isLauncherVersionSupported) + { + addMenuItem(m, "Uninstall unlaunch no backup", NULL, (info.tmdInvalid || info.tmdPatched), false); + } + addMenuItem(m, "Write nocash footer", NULL, info.needsNocashFooterToBeWritten, false); + addMenuItem(m, tidPatchesStr, NULL, tidPatchesSupported, false); + } + } + + int result = m->cursor; + freeMenu(m); + + return result; +} + +void setup() { + keysSetRepeat(25, 5); + setupScreens(); + + fifoSetValue32Handler(FIFO_USER_01, [](u32 value32, void*) { + if (value32 != 0x54495845) // 'EXIT' + return; + programEnd = true; + arm7Exiting = true; + }, NULL); + fifoSetValue32Handler(FIFO_USER_03, [](u32 value32, void*) { + batteryLevel = value32 & 0xF; + charging = (value32 & BIT(7)) != 0; + }, NULL); + + //DSi check + if (!isDSiMode()) + { + messageBox("\x1B[31mError:\x1B[33m This app is exclusively for DSi."); + exit(0); + } + + //setup sd card access + if (!fatInitDefault()) + { + messageBox("fatInitDefault()...\x1B[31mFailed\n\x1B[47m"); + } + + u32 clusterSize = getClusterSizeForPartition("sd:/"); + if(clusterSize > 32768) + { + messageBox("Sd card cluster size is too large"); + exit(0); + } + + //setup nand access + if (!fatMountSimple("nand", &io_dsi_nand)) + { + messageBox("nand init \x1B[31mfailed\n\x1B[47m"); + exit(0); + } +} + +void checkNocashFooter(consoleInfo& info) { + NocashFooter footer; + + nandio_read_nocash_footer(&footer); + nandio_construct_nocash_footer(&info.nocashFooter); + + info.needsNocashFooterToBeWritten = !isFooterValid(&footer); + + if(!info.needsNocashFooterToBeWritten) + { + if(memcmp(&footer, &info.nocashFooter, sizeof(footer)) != 0) + { + messageBox("\x1B[31mError:\x1B[33m This console has a\n" + "nocash footer embedded in its\n" + "nand that doesn't match the one\n" + "generated.\n" + "The footer already present will\n" + "be overwritten."); + info.needsNocashFooterToBeWritten = true; + } + } +} + +bool writeNocashFooter(consoleInfo& info) { + if(!info.needsNocashFooterToBeWritten) + return true; + + if(!nandio_unlock_writing()) + return false; + + printf("Writing nocash footer\n"); + auto res = nandio_write_nocash_footer(&info.nocashFooter); + nandio_lock_writing(); + if(!res) + { + messageBox("Failed to write nocash footer"); + return false; + } + info.needsNocashFooterToBeWritten = false; + return true; +} + +void waitForBatteryChargedEnough() { + + while (batteryLevel < 7 && !charging) + { + if (choiceBox("\x1B[47mBattery is too low!\nPlease plug in the console.\n\nContinue?") == NO) + exit(0); + } +} + +const char* getInstallerPath(int argc, char **argv) { + if(argc > 0) + return argv[0]; + DeviceList* deviceList = getDeviceList(); + + if(deviceList) return deviceList->appname; + + return "sd:/ntrboot.nds"; +} + +void loadUnlaunchInstaller() { + if (fileExists("sd:/unlaunch.dsi")) + { + foundUnlaunchInstallerVersion = loadUnlaunchInstaller("sd:/unlaunch.dsi"); + if(foundUnlaunchInstallerVersion != INVALID) + return; + + messageBox("\x1B[41mWARNING:\x1B[47m Failed to load unlaunch.dsi\n" + "from the root of the sd card.\n" + "Attempting to use the bundled one."); + } + + foundUnlaunchInstallerVersion = loadUnlaunchInstaller("nitro:/unlaunch.dsi"); + + if(foundUnlaunchInstallerVersion != INVALID) + return; + + messageBox("\x1B[41mWARNING:\x1B[47m Failed to load bundled unlaunch\n" + "installer.\n" + "Installing unlaunch won't be possible."); +} + +void loadUnlaunchInstallerPatch() { + if (fileExists("sd:/unlaunch-patch.bin")) { + splashSoundBinaryPatchPath = "sd:/unlaunch-patch.bin"; + } + else if(fileExists("nitro:/unlaunch-patch.bin")) + { + splashSoundBinaryPatchPath = "nitro:/unlaunch-patch.bin"; + } +} + +void parseLauncherInfo(std::string_view launcher_tid_str, consoleInfo& info) { + auto launcher_content_path = std::format("nand:/title/00030017/{}/content", launcher_tid_str); + + auto [tmd_found, expected_launcher_build, retailLauncherPath] = [&] { + std::shared_ptr pdir{opendir(launcher_content_path.c_str()), closedir}; + if (!pdir) + throw std::runtime_error(std::format("Could not open launcher title directory ({})", launcher_content_path)); + dirent* pent; + std::optional> foundApp; + bool tmdFound; + while((pent = readdir(pdir.get())) != nullptr) { + if(foundApp && tmdFound) { + break; + } + if(pent->d_type == DT_DIR) + continue; + std::string_view filename{pent->d_name}; + if(filename == "title.tmd") { + tmdFound = true; + continue; + } + + if(filename.size() != 12 || !filename.ends_with(".app") || !filename.starts_with("0000000")) + continue; + + auto launcher_app_version = static_cast(static_cast(filename[7]) - static_cast('0')); + if(launcher_app_version > 7) + throw std::runtime_error(std::format("Found an unsupported launcher version: {}", launcher_app_version)); + + foundApp = std::make_pair(static_cast(256 * launcher_app_version), std::string{filename}); + } + if(!foundApp) + throw std::runtime_error("Launcher app not found"); + const auto& [launcher_build, launcher_app_name] = *foundApp; + return std::make_tuple(tmdFound, launcher_build, std::format("{}/{}", launcher_content_path, launcher_app_name)); + }(); + + if((info.tmdFound = tmd_found)) { + const auto recoveryTmdPath = std::format("nitro:/{}/tmd.{}", launcher_tid_str, static_cast(expected_launcher_build)); + info.launcherTmdPath = std::format("{}/title.tmd", launcher_content_path); + info.recoveryTmdDataSha = [&] -> Sha1Digest { + auto file = fopen(std::format("{}.sha1", recoveryTmdPath).data(), "rb"); + if(!file) + throw std::runtime_error("Good tmd sha1 not found"); + char sha1StrBuff[41]{}; + auto read = fread(sha1StrBuff, sizeof(sha1StrBuff) - 1, 1, file); + fclose(file); + if(read != 1) + throw std::runtime_error("Failed to parse good tmd's sha1 file"); + return {sha1StrBuff}; + }(); + + auto patchedTmdSha1 = [&] -> Sha1Digest { + auto file = fopen(std::format("{}.patch.sha1", recoveryTmdPath).data(), "rb"); + if(!file) + throw std::runtime_error("Patched tmd sha1 not found"); + char sha1StrBuff[41]{}; + auto read = fread(sha1StrBuff, sizeof(sha1StrBuff) - 1, 1, file); + fclose(file); + if(read != 1) + throw std::runtime_error("Failed to parse patched tmd's sha1 file"); + return {sha1StrBuff}; + }(); + + info.recoveryTmdData = [&] { + auto* sourceTmd = fopen(recoveryTmdPath.data(), "rb"); + + std::array ret; + auto read = fread(ret.data(), ret.size(), 1, sourceTmd); + fclose(sourceTmd); + if(read != 1) + { + throw std::runtime_error("Failed to read good tmd's buffer"); + } + + Sha1Digest digest; + swiSHA1Calc(digest.data(), ret.data(), ret.size()); + if(digest != info.recoveryTmdDataSha) + { + throw std::runtime_error("Good tmd's sha mismatching"); + } + return ret; + }(); + + std::shared_ptr tmd{fopen(info.launcherTmdPath.data(), "rb"), fclose}; + if(!tmd) { + info.tmdFound = false; + } else if(auto tmdSize = getFileSize(tmd.get()); tmdSize < 520) { + //if size isn't at least 520 then the tmd is already invalid + info.tmdInvalid = true; + } else { + info.launcherAppPath = retailLauncherPath; + if(tmdSize > 520) { + info.tmdInvalid = true; + } + else + { + Sha1Digest digest; + calculateFileSha1(tmd.get(), &digest); + if(digest == info.recoveryTmdDataSha){ + info.tmdGood = true; + } else if(digest == patchedTmdSha1) { + info.tmdPatched = true; + } else { + info.tmdInvalid = true; + } + } + if(!info.tmdInvalid) { + fseek(tmd.get(), 0x1DC, SEEK_SET); + uint16_t launcherVersion; + fread(&launcherVersion, sizeof(launcherVersion), 1, tmd.get()); + if(static_cast(launcherVersion) * 256 != expected_launcher_build) { + throw std::runtime_error("Launcher version found doesn't match with the one in the tmd"); + } + info.launcherVersion = launcherVersion; + } + } + if(info.tmdInvalid || !info.tmdFound) { + // if the tmd is invalid, don't read the launcher version from it and assume it's the one + // matching the app file + info.launcherVersion = expected_launcher_build / 256; + } + } +} + +void retrieveInstalledLauncherInfo(consoleInfo& info) { + static constexpr auto hnaaTmdPath = "nand:/title/00030017/484e4141/content/title.tmd"sv; + const auto [launcher_tid_str, region] = [] -> std::pair { + uint32_t launcherTid; + { + auto* file = fopen("nand:/sys/HWINFO_S.dat", "rb"); + if(!file) + return std::make_pair("", static_cast(0xFF)); + fseek(file, 0xA0, SEEK_SET); + fread(&launcherTid, sizeof(uint32_t), 1, file); + fclose(file); + } + return std::make_pair(std::format("{:08x}", launcherTid), static_cast(launcherTid & 0xFF)); + }(); + + // 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) + info.isRetail = (region != 0x41 && region != 0xFF); + + //check for unlaunch and region + if (info.isRetail && launcher_tid_str.size() != 0) { + parseLauncherInfo(launcher_tid_str, info); + } else { + // HWINFO_S may not always exist (PRE_IMPORT). Fill in defaults if that happens. + (void)0; + } + + if (auto tmdSize = getFileSizePath(hnaaTmdPath.data()); tmdSize > 520) { + info.UnlaunchHNAAtmdFound = true; + } +} + +void uninstall(consoleInfo& info, bool noBackup) { + if(!(info.tmdInvalid || info.tmdPatched)) + { + return; + } + bool unsafeUninstall = advancedOptionsUnlocked && noBackup; + if(!isLauncherVersionSupported && !unsafeUninstall) + { + return; + } + printf("Uninstalling"); + if(!writeNocashFooter(info)) + { + return; + } + if(!nandio_unlock_writing()) + { + return; + } + if(uninstallUnlaunch(info, unsafeUninstall)) + { + messageBox("Uninstall successful!\n"); + info.tmdInvalid = false; + info.tmdPatched = false; + info.tmdGood = true; + info.UnlaunchHNAAtmdFound = !unsafeUninstall; + } + else + { + messageBox("\x1B[31mError:\x1B[33m Uninstall failed\n"); + } + nandio_lock_writing(); + printf("Synchronizing FAT tables...\n"); + nandio_synchronize_fats(); +} + +void install(consoleInfo& info) { + if(!isLauncherVersionSupported) + { + return; + } + if(info.tmdInvalid || info.tmdPatched || !info.tmdGood || foundUnlaunchInstallerVersion == INVALID) + { + return; + } + if(choiceBox("Install unlaunch?") == NO) + { + return; + } + if(!retailLauncherTmdPresentAndToBePatched + && (choiceBox("There doesn't seem to be a launcher.tmd\n" + "file matcing the hwinfo file\n" + "Keep installing?") == NO)) + { + return; + } + printf("Installing\n"); + if(!writeNocashFooter(info)) + { + return; + } + if(!nandio_unlock_writing()) + { + return; + } + if(installUnlaunch(info, disableAllPatches, + enableSoundAndSplash ? splashSoundBinaryPatchPath : NULL, + customBgPath)) + { + messageBox("Install successful!\n"); + info.tmdGood = false; + info.tmdPatched = true; + info.UnlaunchHNAAtmdFound = true; + } + else + { + messageBox("\x1B[31mError:\x1B[33m Install failed\n"); + } + nandio_lock_writing(); + printf("Synchronizing FAT tables...\n"); + nandio_synchronize_fats(); +} + +void customBg() { + if(!isLauncherVersionSupported) + { + return; + } + if(foundUnlaunchInstallerVersion == INVALID) + { + return; + } + const char* customBg = backgroundMenu(); + if(!customBg) + { + return; + } + if(strcmp(customBg, "default") == 0) + { + customBgPath = NULL; + } + else + { + customBgPath = customBg; + } +} + +void doMainMenu(consoleInfo& info) { + int cursor = 0; + while(!programEnd) + { + cursor = mainMenu(info, cursor); + if(programEnd) + break; + + switch (cursor) + { + case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL: + case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP: + { + uninstall(info, cursor == MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP); + } + break; + + case MAIN_MENU_CUSTOM_BG: + { + customBg(); + } + break; + + case MAIN_MENU_TID_PATCHES: + if(!isLauncherVersionSupported) + { + break; + } + if(advancedOptionsUnlocked && (foundUnlaunchInstallerVersion == v1_9 || foundUnlaunchInstallerVersion == v2_0)) { + disableAllPatches = !disableAllPatches; + } + break; + + case MAIN_MENU_SOUND_SPLASH_PATCHES: + if(!isLauncherVersionSupported) + { + break; + } + if(foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL) { + enableSoundAndSplash = !enableSoundAndSplash; + } + break; + + case MAIN_MENU_SAFE_UNLAUNCH_INSTALL: + { + install(info); + } + break; + + case MAIN_MENU_WRITE_NOCASH_FOOTER_ONLY: + (void)writeNocashFooter(info); + break; + + case MAIN_MENU_EXIT: + programEnd = true; + return; + } + } +} + +int main(int argc, char **argv) +{ + setup(); + + if (!nitroFSInit(getInstallerPath(argc, argv))) + { + messageBox("nitroFSInit()...\x1B[31mFailed\n\x1B[47m"); + } + + loadUnlaunchInstaller(); + loadUnlaunchInstallerPatch(); + + consoleInfo info; + + try { + retrieveInstalledLauncherInfo(info); + + checkNocashFooter(info); + + // Launcher v4, build v1024 (shipped with firmware 1.4.2 (1.4.3 for china and korea) + // will fail to launch if another tmd withouth appropriate application, or an invalid + // tmd (in our case the one installed from unlaunch) is found in the HNAA launcher folder + // there's really no workaround to that, so that specific version is blacklisted and only uninstalling + // an "officially" installed unlaunch without leaving any backup behind will be allowed + if(info.launcherVersion == 4) { + isLauncherVersionSupported = false; + messageBox("\x1B[41mWARNING:\x1B[47m This system version\n" + "doesn't support this install\n" + "method, only uninstalling\n" + "unaunch without backups will\n" + "be possible"); + } + + messageBox("\x1B[41mWARNING:\x1B[47m This tool can write to\n" + "your internal NAND!\n\n" + "This always has a risk, albeit\n" + "low, of \x1B[41mbricking\x1B[47m your system\n" + "and should be done with caution!\n\n" + "If you have not yet done so,\n" + "you should make a NAND backup."); + + waitForBatteryChargedEnough(); + + doMainMenu(info); + } catch (const std::exception& e) { + messageBox(e.what()); + } + + clearScreen(&bottomScreen); + printf("Unmounting NAND...\n"); + fatUnmount("nand:"); + printf("Merging stages...\n"); + nandio_shutdown(); + + fifoSendValue32(FIFO_USER_02, 0x54495845); // 'EXIT' + + while (arm7Exiting) + swiWaitForVBlank(); + + return 0; +} + +void clearScreen(PrintConsole* screen) +{ + consoleSelect(screen); + consoleClear(); +} diff --git a/arm9/src/unlaunch.cpp b/arm9/src/unlaunch.cpp index fb6126b..45e81c4 100644 --- a/arm9/src/unlaunch.cpp +++ b/arm9/src/unlaunch.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include static char unlaunchInstallerBuffer[0x30000]; static char ogUnlaunchInstallerBuffer[0x30000]; @@ -51,23 +53,9 @@ bool isValidUnlaunchInstallerSize(size_t size) return size == 163320 /*1.8*/ || size == 196088 /*1.9, 2.0*/; } -bool isLauncherTmdPatched(const char* path) -{ - FILE* launcherTmd = fopen(path, "rb"); - if(!launcherTmd) - { - return false; - } - fseek(launcherTmd, 0x190, SEEK_SET); - char c; - fread(&c, 1, 1, launcherTmd); - fclose(launcherTmd); - return c == 0x47; -} - static bool removeHnaaLauncher() { - auto* errString = [] -> const char* { + auto* errString = [] -> const char* { if(!toggleFileReadOnly(hnaaTmdPath, false)) { return "\x1B[31mError:\x1B[33m Failed to mark unlaunch's title.tmd as writable\nLeaving as is\n"; @@ -94,92 +82,85 @@ static bool removeHnaaLauncher() return true; } -static bool restoreMainTmd(const char* path, bool hasHNAABackup, bool removeHNAABackup) +static bool restoreMainTmd(const consoleInfo& info, bool removeHNAABackup) { - FILE* launcherTmd = fopen(path, "r+b"); - if(!launcherTmd) + std::shared_ptr launcherTmdSptr{fopen(info.launcherTmdPath.data(), "r+b"), fclose}; + if(!launcherTmdSptr) { messageBox("\x1B[31mError:\x1B[33m Failed to open default launcher's title.tmd\n"); return false; } - // Set back the title.tmd's title id from GNXX to HNXX - fseek(launcherTmd, 0x190, SEEK_SET); - char c; - fread(&c, 1, 1, launcherTmd); - //if byte is not what we expect, the install method was different - if(c == 0x47) - { - fseek(launcherTmd, -1, SEEK_CUR); - c = 0x48; - fwrite(&c, 1, 1, launcherTmd); - fclose(launcherTmd); - if(removeHNAABackup && hasHNAABackup) - { - removeHnaaLauncher(); - } - } - else if(c != 0x47) - { - if (getFileSize(launcherTmd) > 520) { - // Remove unlaunch if it already exists on the main launcher tmd. - // If we don't do this and unlaunch is on the tmd, it will take over and prevent loading HNAA + FILE* launcherTmd = launcherTmdSptr.get(); - // 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 - if(!hasHNAABackup && !removeHNAABackup) - { - 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(removeHNAABackup && hasHNAABackup) - { - removeHnaaLauncher(); - } - if (ftruncate(fileno(launcherTmd), 520) != 0) { - messageBox("\x1B[31mError:\x1B[33m Failed to remove unlaunch\n"); - fclose(launcherTmd); - return false; - } - fclose(launcherTmd); - return true; - } - messageBox("\x1B[31mError:\x1B[33m Unlaunch was installed with an\nunknown method\naborting\n"); - fclose(launcherTmd); - return false; - } - return true; + // If the tmd is patched, assume the HNAA backup is already set in place. + if(info.tmdPatched) { + fseek(launcherTmd, 0x190, SEEK_SET); + // Set back the title.tmd's title id from GNXX to HNXX + char c = 0x48; + fwrite(&c, 1, 1, launcherTmd); + fflush(launcherTmd); + } else if(!info.tmdGood || info.tmdInvalid) { + // The tmd isn't good, it either has the wrong size, or the hash didn't match + // and it wasn't patched with the new method + // Install the hnaa backup if not found and then truncate the tmd to 520b + // before restoring it + if(!info.UnlaunchHNAAtmdFound && !removeHNAABackup) + { + 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) + { + return false; + } + if(installerVersion != INVALID) + { + if(!writeUnlaunchToHNAAFolder()) + { + if(choiceBox("Failsafe installation couldn't\n" + "be copmleted.\n" + "Proceed anyways?") == NO) + { + return false; + } + } + } + } + if (ftruncate(fileno(launcherTmd), 520) != 0) { + messageBox("\x1B[31mError:\x1B[33m Failed to remove unlaunch\n"); + return false; + } + } + + Sha1Digest digest; + calculateFileSha1(launcherTmd, &digest); + + // the tmd still doesn't match, write a known good one + if(digest != info.recoveryTmdDataSha) { + fseek(launcherTmd, 0, SEEK_SET); + auto written = fwrite(info.recoveryTmdData.data(), info.recoveryTmdData.size(), 1, launcherTmd); + if(written != 1) { + messageBox("\x1B[31mError:\x1B[33m Failed to remove unlaunch\n"); + return false; + } + } + if(removeHNAABackup && info.UnlaunchHNAAtmdFound) + { + return removeHnaaLauncher(); + } + return true; } static bool patchMainTmd(const char* path) @@ -225,15 +206,21 @@ static bool restoreProtoTmd(const char* path) return true; } -bool uninstallUnlaunch(bool retailConsole, bool hasHNAABackup, const char* retailLauncherTmdPath, const char* retailLauncherPath, bool removeHNAABackup) +bool uninstallUnlaunch(const consoleInfo& info, bool removeHNAABackup) { // TODO: handle retailLauncherTmdPresentAndToBePatched = false on retail consoles - if (retailConsole) { - if (!toggleFileReadOnly(retailLauncherTmdPath, false) || !toggleFileReadOnly(retailLauncherPath, false)) + if (info.isRetail) { + if(!toggleFileReadOnly(info.launcherTmdPath.data(), false)) + { + messageBox(std::format("\x1B[31mError:\x1B[33m Failed to make {} writable\n", info.launcherTmdPath).data()); + return false; + } + if(!toggleFileReadOnly(info.launcherAppPath.data(), false)) { + messageBox(std::format("\x1B[31mError:\x1B[33m Failed to make {} writable\n", info.launcherAppPath).data()); return false; - } - if (!restoreMainTmd(retailLauncherTmdPath, hasHNAABackup, removeHNAABackup)) + } + if (!restoreMainTmd(info, removeHNAABackup)) { return false; } @@ -312,7 +299,7 @@ static bool writeUnlaunchToHNAAFolder() return true; } -static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath, const char* retailLauncherPath) +static bool installUnlaunchRetailConsole(const consoleInfo& info) { if(!writeUnlaunchToHNAAFolder()) return false; @@ -320,20 +307,20 @@ static bool installUnlaunchRetailConsole(const char* retailLauncherTmdPath, cons //Finally patch the default launcher tmd to be invalid //If there isn't a title.tmd matching the language region in the hwinfo // nothing else has to be done, could be a language patch, or a dev system, the user will know what they have done - if (retailLauncherTmdPath) - { - // Set tmd as writable in case unlaunch was already installed through the old method - if(!toggleFileReadOnly(retailLauncherTmdPath, false) || !patchMainTmd(retailLauncherTmdPath)) - { - removeHnaaLauncher(); - return false; - } - if (!toggleFileReadOnly(retailLauncherTmdPath, true) || !toggleFileReadOnly(retailLauncherPath, true)) - { - messageBox("\x1B[31mError:\x1B[33m Failed to mark default launcher's title.tmd\nas read only, install might be unstable\n"); - } - } - return true; + if (!info.tmdFound) + return true; + + // Set tmd as writable in case unlaunch was already installed through the old method + if(!toggleFileReadOnly(info.launcherTmdPath.data(), false) || !patchMainTmd(info.launcherTmdPath.data())) + { + removeHnaaLauncher(); + return false; + } + if (!toggleFileReadOnly(info.launcherTmdPath.data(), true) || !toggleFileReadOnly(info.launcherAppPath.data(), true)) + { + messageBox("\x1B[31mError:\x1B[33m Failed to mark default launcher's title.tmd\nas read only, install might be unstable\n"); + } + return true; } static bool installUnlaunchProtoConsole(void) @@ -381,9 +368,9 @@ static bool installUnlaunchProtoConsole(void) return true; } -static bool readUnlaunchInstaller(const char* path) +static bool readUnlaunchInstaller(std::string_view path) { - FILE* unlaunchInstaller = fopen(path, "rb"); + FILE* unlaunchInstaller = fopen(path.data(), "rb"); if (!unlaunchInstaller) { messageBox("\x1B[31mError:\x1B[33m Failed to open unlaunch installer\n"); @@ -545,7 +532,7 @@ static bool patchUnlaunchInstaller(bool disableAllPatches, const char* splashSou return true; } -UNLAUNCH_VERSION loadUnlaunchInstaller(const char* path) +UNLAUNCH_VERSION loadUnlaunchInstaller(std::string_view path) { if(readUnlaunchInstaller(path) && verifyUnlaunchInstaller()) { @@ -569,16 +556,16 @@ const char* getUnlaunchVersionString(UNLAUNCH_VERSION version) return unlaunchVersionStrings[version]; } -bool installUnlaunch(bool retailConsole, const char* retailLauncherTmdPath, const char* retailLauncherPath, bool disableAllPatches, const char* splashSoundBinaryPatchPath, const char* customBackgroundPath) +bool installUnlaunch(const consoleInfo& info, bool disableAllPatches, const char* splashSoundBinaryPatchPath, const char* customBackgroundPath) { if (installerVersion == INVALID || !patchUnlaunchInstaller(disableAllPatches, splashSoundBinaryPatchPath, customBackgroundPath)) return false; // Treat protos differently - if (!retailConsole) + if (!info.isRetail) { return installUnlaunchProtoConsole(); } // Do things normally for production units - return installUnlaunchRetailConsole(retailLauncherTmdPath, retailLauncherPath); -} \ No newline at end of file + return installUnlaunchRetailConsole(info); +} diff --git a/arm9/src/unlaunch.h b/arm9/src/unlaunch.h index 72108a9..b179d2b 100644 --- a/arm9/src/unlaunch.h +++ b/arm9/src/unlaunch.h @@ -1,10 +1,8 @@ #ifndef UNLAUNCH_H #define UNLAUNCH_H -#include +#include -#ifdef __cplusplus -extern "C" { -#endif +#include "consoleInfo.h" typedef enum UNLAUNCH_VERSION { v1_8, @@ -15,15 +13,9 @@ typedef enum UNLAUNCH_VERSION { const char* getUnlaunchVersionString(UNLAUNCH_VERSION); -bool uninstallUnlaunch(bool notProto, bool hasHNAABackup, const char* retailLauncherTmdPath, const char* retailLauncherPath, bool removeHNAABackup); -bool installUnlaunch(bool retailConsole, const char* retailLauncherTmdPath, const char* retailLauncherPath, bool disableAllPatches, const char* splashSoundBinaryPatchPath, const char* customBackgroundPath); +bool uninstallUnlaunch(const consoleInfo& info, bool removeHNAABackup); +bool installUnlaunch(const consoleInfo& info, bool disableAllPatches, const char* splashSoundBinaryPatchPath, const char* customBackgroundPath); -bool isLauncherTmdPatched(const char* path); +UNLAUNCH_VERSION loadUnlaunchInstaller(std::string_view path); -UNLAUNCH_VERSION loadUnlaunchInstaller(const char* path); - -#ifdef __cplusplus -} #endif - -#endif \ No newline at end of file diff --git a/nitrofiles/484e4143/tmd.1024 b/nitrofiles/484e4143/tmd.1024 new file mode 100644 index 0000000000000000000000000000000000000000..088abb8886ca4317bc6ffff7f98715e820d2a4ab GIT binary patch literal 520 zcmZQzWMDM$-xXtdpXa1?d7M??sT`H%Zz}Xp+a;{2+-IMCFn9kJ1wGGu50)8T@od<6 zFgJbLw}bjIGiL_)+7?&1)?Q3u{Cg}d&1;)0W7!t{N}}gy&a+Fc zB@5>YUW?wgp{VQ6hh44#^X)qR_}V9nt4*J;eR7iY@&fs(YdSkFH>u~rrU2se?W literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4143/tmd.1024.patch.sha1 b/nitrofiles/484e4143/tmd.1024.patch.sha1 new file mode 100644 index 0000000..3d3304c --- /dev/null +++ b/nitrofiles/484e4143/tmd.1024.patch.sha1 @@ -0,0 +1 @@ +d20ef5520ef3df8bc418f46075cc5e6865ed4b6e \ No newline at end of file diff --git a/nitrofiles/484e4143/tmd.1024.sha1 b/nitrofiles/484e4143/tmd.1024.sha1 new file mode 100644 index 0000000..18515e3 --- /dev/null +++ b/nitrofiles/484e4143/tmd.1024.sha1 @@ -0,0 +1 @@ +88076c8d9e8330e43e32bba7c24fb2970d16241e \ No newline at end of file diff --git a/nitrofiles/484e4143/tmd.1280 b/nitrofiles/484e4143/tmd.1280 new file mode 100644 index 0000000000000000000000000000000000000000..fc6661893b9429db8ba325c2cf19011765b6f22e GIT binary patch literal 520 zcmZQzWMHg{YD$~5W6qS4%QH{Rw|RB7>EW~9-T5odPYn;e`ovaEcJjv6C#G^(O*?k| z+1Bc=^-k~lF70?65o0%5kY9E;|8lS0`#A#^PxAe_AFy*c&4EP>OnKg?sX6i7T7uCiD;@AcQG zx9k`+jROT&>AX;~{Fm~GfdUYepI@Tu>}UW1hPuuHP^LK8-To(j)x|O<(*;*=u&kWScdlm6dafSLnNj~$|E%0$Z#nhN z-lL}-FIz~a<=I4@>A3rJ-roT2hdZ7zbgg=4vvrT#0}jK=SKMqXE*o*HZVfSt|NJ+p zzjNC*A)&ZQ8qP((;`b_S()Gwap?z_8B2(p*mG|{o7xBF=NR?Xu?(r&@My+d`mq#C% z`eE~}YyZA-R+o8d$g!z+l+Ifhwf!@z(?or(t;?@w{5odL({8QE7<}Y_V#d+ivQg5a z;wSC)9rbFBKh!&Qamw5ezZob1LHYS5y3URU5MZe58~|mSlVK<`gSdyEqccdSfgxDG x1DFI84QK!%gNwz+z`zKVV*%0-wtNHw<8@YThW9oz*`05R9h+73RmAi9PXD!4Lsj)^O=3rIjJv?$ zq`;FQQ&wvoUBb_QF8_;2snSs4xf7urBw8V9R##V;(gImw7?P}NmpR(+S zN$saeeX400Q=CKRhH>jo=*o9I-aDhxyA$w zSzIgrJehFaVy3!oz-H5Zp}NyQwHAo(&AVK$Sbc}>cUjGa89NOnmRs+CZWcJ{uC|Y= z`;O8n_lv8hDSYl_@LP0%fdUYepI@Tu>}UW1hPuuHP^LK($Q%bZm zuwC@^D;$51Xq<_Uvq)*rn%%cjeck8ad5c9Wp53i-vUUo7q_*|gI?u0yZ7WaobGgZJ z*ZgtKjuZ_wEbg2W zd9`^xalAYp#RAU`RUIvuz(4^A%Fi#+b#^p>07G5p04UR(3`3b2#6A2Rok2Pc48i&x uz$BPxKm!OFTr4IA21X<~2wUER!N;QhU<1RP>9-8O9l5x>|3|#v;s5}K37w|^ literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4143/tmd.512.patch.sha1 b/nitrofiles/484e4143/tmd.512.patch.sha1 new file mode 100644 index 0000000..93e1e49 --- /dev/null +++ b/nitrofiles/484e4143/tmd.512.patch.sha1 @@ -0,0 +1 @@ +4e350d55f0b134748ddaf1ff1eef99de4c7dfa85 \ No newline at end of file diff --git a/nitrofiles/484e4143/tmd.512.sha1 b/nitrofiles/484e4143/tmd.512.sha1 new file mode 100644 index 0000000..a0bb6cb --- /dev/null +++ b/nitrofiles/484e4143/tmd.512.sha1 @@ -0,0 +1 @@ +76727f47fa55a06d0b684745c5e6cdd5f596c4e5 \ No newline at end of file diff --git a/nitrofiles/484e4143/tmd.768 b/nitrofiles/484e4143/tmd.768 new file mode 100644 index 0000000000000000000000000000000000000000..fdcfb50d495704335485238140b32fffa5c4f428 GIT binary patch literal 520 zcmZQzWMEXQ#UtNmq(~H9v$bSB)Zv12M z;>2uA$6f9BB`-hYXMYfw9QV=E)cN%`^Dl}L;gje2&;0V!uQ|B)*EU1819#K~VqZJQ zlz($KS1x$l`(@!Zsf%XcuXUwgYwXqkT;6E%@{jF;-WR9mIlp#n-@T!ad;780$OV(8 zZM661(wxec)FU8i+04(S#&>O&ddu$hTrH>mFFUs=^i}+I&HAk0|g)`KfgrR+0g(340W9YpiFZz3}t2z_waLc2I({~1nYMI vlVG9&4IpH2v6vYc7@=|?8p4+MU|264wQKY9p5^{i)DLb-zbbrx?wq>-@U)nw literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4143/tmd.768.patch.sha1 b/nitrofiles/484e4143/tmd.768.patch.sha1 new file mode 100644 index 0000000..92ee74c --- /dev/null +++ b/nitrofiles/484e4143/tmd.768.patch.sha1 @@ -0,0 +1 @@ +b1d18a727dae139451a6e2ca4b89dd22253d4639 \ No newline at end of file diff --git a/nitrofiles/484e4143/tmd.768.sha1 b/nitrofiles/484e4143/tmd.768.sha1 new file mode 100644 index 0000000..4873b75 --- /dev/null +++ b/nitrofiles/484e4143/tmd.768.sha1 @@ -0,0 +1 @@ +ebd7cff8b0d3ccca8579872b29dc20cc3a0827d1 \ No newline at end of file diff --git a/nitrofiles/484e4145/tmd.1024 b/nitrofiles/484e4145/tmd.1024 new file mode 100644 index 0000000000000000000000000000000000000000..fd82d3e9bdbb9ac791863b68ae6dfb1de3be51a2 GIT binary patch literal 520 zcmZQzWMC9J?obsT+vUOI@Q$@ML*`p}{LGyDk%~tv+^*lzUeso1eIQzLI-^(vv-uy( zf3mWdJH8gQmVdis9>UYdcu$>sZ8DSETdqGhSf%eQGmLs5b2BK|!n;kuf18Ax$+nt+ zXHUNiU-do9EZetnrkP4Zbj<%d4;@zgdpcX?#K|df!c+D=y%O?G&a%p(-zJ9h0mlnF zdsW8*{bf^%YQJRqrA$#&&XYU(zU-!?@trsotxJlJ91c*5BKgEp&mDHzxzr( z9&a_?7$-brE!?u>j~W97ASge-MAzBT00Inkodcjub21ENW)S!Ab94piG%y6~cL0-M vqM?BSjDQ4@fQ5m95vml(gt8@{Fq{{8r?l8|o04(eCi}N1ZJtdHkm>^f1yhVX literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4145/tmd.1024.patch.sha1 b/nitrofiles/484e4145/tmd.1024.patch.sha1 new file mode 100644 index 0000000..23c5871 --- /dev/null +++ b/nitrofiles/484e4145/tmd.1024.patch.sha1 @@ -0,0 +1 @@ +a91f95d68dccd359987ef7e32ec2221148153da6 \ No newline at end of file diff --git a/nitrofiles/484e4145/tmd.1024.sha1 b/nitrofiles/484e4145/tmd.1024.sha1 new file mode 100644 index 0000000..9afea24 --- /dev/null +++ b/nitrofiles/484e4145/tmd.1024.sha1 @@ -0,0 +1 @@ +7795346d34093c0d73db587f6c5fd8510b947ec7 \ No newline at end of file diff --git a/nitrofiles/484e4145/tmd.1280 b/nitrofiles/484e4145/tmd.1280 new file mode 100644 index 0000000000000000000000000000000000000000..736276edf1cb5577acce27c3fc5435c01873676f GIT binary patch literal 520 zcmZQzWMI@f#Z>krp6l@r!F$&(Shnt45VVm?dyUAo_U2Q)hYja%P@5CEwzT@bsh5LP z^Lxo)7E#BZ-BOk}_D!2CnJ2jJ#DOi=I^Qik%%)$?aVcM&2s5EuTS8)3;;t8mI43( literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4145/tmd.1280.patch.sha1 b/nitrofiles/484e4145/tmd.1280.patch.sha1 new file mode 100644 index 0000000..cc3e19b --- /dev/null +++ b/nitrofiles/484e4145/tmd.1280.patch.sha1 @@ -0,0 +1 @@ +4c482027655615abe80ed32a26f064fd97caf80c \ No newline at end of file diff --git a/nitrofiles/484e4145/tmd.1280.sha1 b/nitrofiles/484e4145/tmd.1280.sha1 new file mode 100644 index 0000000..b669eb7 --- /dev/null +++ b/nitrofiles/484e4145/tmd.1280.sha1 @@ -0,0 +1 @@ +978f1a3b26a4f983a7e305d1a89c73d0890e6683 \ No newline at end of file diff --git a/nitrofiles/484e4145/tmd.1536 b/nitrofiles/484e4145/tmd.1536 new file mode 100644 index 0000000000000000000000000000000000000000..c432d9b3c9c2506a61d9b473d70acb0f545b85c8 GIT binary patch literal 520 zcmZQzWMH(~oBq4We1mP!dc~JtuI|(4bmLpnkuu|mEc1`KkxR}bG8WGf)i^mNti~f+ zL2!d^=m}5t@VC76LES%>X}`;{(bkiC+AD{E9Wk8;=cK@pYPA~ zq?hvMUafx>Ekpyen}WDv8LjVc|6lxRrqqW|n*^>zU$MNMz12k2iD`FMQ)LpUL|CD$Pid|Ty)0Qi5ZI}5hnEK-(r$)CM^TMT*E7zYgH|wx0z43c_ z$n77el72V01Z}@#5jR`ZRnGYjgClS3igod}E9A^3tZcLPYut3@FC|jzAq3O_`^ZKE4`j)kA;%<;Q(aZenz61c68kk4` literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4145/tmd.1792.patch.sha1 b/nitrofiles/484e4145/tmd.1792.patch.sha1 new file mode 100644 index 0000000..1912cac --- /dev/null +++ b/nitrofiles/484e4145/tmd.1792.patch.sha1 @@ -0,0 +1 @@ +4702ac21227a9a1e2d46b6c336e8dc99b1ec25bf \ No newline at end of file diff --git a/nitrofiles/484e4145/tmd.1792.sha1 b/nitrofiles/484e4145/tmd.1792.sha1 new file mode 100644 index 0000000..83984d1 --- /dev/null +++ b/nitrofiles/484e4145/tmd.1792.sha1 @@ -0,0 +1 @@ +a297f64a9d574a9c7abe71998553c3a602f124d9 \ No newline at end of file diff --git a/nitrofiles/484e4145/tmd.256 b/nitrofiles/484e4145/tmd.256 new file mode 100644 index 0000000000000000000000000000000000000000..4b970c1dd3e065c5fbec01931f28f6620c1eb576 GIT binary patch literal 520 zcmZQzWMFKQ4B`(s*0tmOrt~sjotf{;cRRgt`DOF&9Os6^H*Cay9MjKRo1zx~+kfBY zMGHUAIqA&z^hmzk(w(#0EBsz-8qF;UvgF?6uzX2=)vftYW2+8c6Whiu^jQ1L`UiYw zjVpE;G}uL#tbAsFL&`>6%`W%LoL+yK#jNrF%dVbT+5D5 zT|f0(@2_fJBNJA+4>NxYRV-6XpKG-6z3;b;&)f{YFKw!p&WwF~H7=rc_LYt=HWIZz zo*355n0fWqEryuqS}_mvG6ggj=$@NexBQyhhlRhMEY?y}m(Yxy-xgrMs_4UMmWI|a zlT&*I`L{A!D|sz>RPswUgMk7Nl%HRs>+EO%0fxHH0Z^tn8HO@5hZar&pOU<@z5=>d|SA4MA!R8{nbb9aF=wtm`Zu)+$>}Ox5s;+3d zCheBble6%dg*@M9?CoNF`+rsY z_xgK#;#tb7X9*Yhv+e!KzWnx%*yVrf3?kA}cZf{)bbFH9TruSu%fzRj&adFlO+G$B zFE;Me9HYo*PYZM({<4-7@|>KduJrL*+797e`R#@ua)MeDL#|llFILk^$&o((v$*Hq znYFi-%3^7Bh{ogEDzz);sY0LnBc!%$`haSuO7SCCEvL$H1a xFbO6a8W_L`NDv8_7#J9#N`Xu$Tk;8mu;t#8a1Rg5kJshZ@9Foh;OsEj0sy&SmCyhH literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4145/tmd.512.patch.sha1 b/nitrofiles/484e4145/tmd.512.patch.sha1 new file mode 100644 index 0000000..0915014 --- /dev/null +++ b/nitrofiles/484e4145/tmd.512.patch.sha1 @@ -0,0 +1 @@ +7cf1ab87b14a325626f730579277e66ad51f7134 \ No newline at end of file diff --git a/nitrofiles/484e4145/tmd.512.sha1 b/nitrofiles/484e4145/tmd.512.sha1 new file mode 100644 index 0000000..e62f7b9 --- /dev/null +++ b/nitrofiles/484e4145/tmd.512.sha1 @@ -0,0 +1 @@ +6c52561a047c8036f31f9d468570d50d36f7d988 \ No newline at end of file diff --git a/nitrofiles/484e4145/tmd.768 b/nitrofiles/484e4145/tmd.768 new file mode 100644 index 0000000000000000000000000000000000000000..9409f4742fb19ea89c16b0c76df00c858f91fcc5 GIT binary patch literal 520 zcmZQzWMFhpXekie_q0P||3UM&t!%f`<-S)6O%Sc*+q2;Hz32OD{?3hDU;1Q1%kjSR zlKX5~mL~39^Yq}>l7qXitEoRd_PZeE!s2JKSCW5yRQ}tWY;#T}+#znyhaS}zpJQBf zK8GjCPcQz#Z}p;utykulPaS8$wbLd?UH#i;Z@bO5^8PFqp_+_~$v66K&wsO;|JZWA z)#4l6J+~DO97$hkci>@dqHFTD6F>Xsm(07ppigCmPObH`d6TExt37X6EArQI^UH3> z*4l%?dtyELf}_8EOxH+$v~S-1v$I1#vsHaqr{CM-Un;Am-4Sn({&A%C4SPe*W$6md#;{69NEYm7LcA literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4145/tmd.768.patch.sha1 b/nitrofiles/484e4145/tmd.768.patch.sha1 new file mode 100644 index 0000000..0533d6f --- /dev/null +++ b/nitrofiles/484e4145/tmd.768.patch.sha1 @@ -0,0 +1 @@ +393fdcc1a46baf35fc5324928865736fa9bb1816 \ No newline at end of file diff --git a/nitrofiles/484e4145/tmd.768.sha1 b/nitrofiles/484e4145/tmd.768.sha1 new file mode 100644 index 0000000..021f237 --- /dev/null +++ b/nitrofiles/484e4145/tmd.768.sha1 @@ -0,0 +1 @@ +5a27d8d7437380252cf35786231f8adcc4cf3ff6 \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.0 b/nitrofiles/484e414a/tmd.0 new file mode 100644 index 0000000000000000000000000000000000000000..c83b3022d5c0674ab63d3a2bf8965d02ab5b2335 GIT binary patch literal 520 zcmZQzWMC|vzC>h2P?y0~6^|lat&q@DPbB}|+4<3K(xpfdjUJcW+iTXPUir>9+0d_k z{ocdPqVxAmJg58n(42TN;r*YF@|EqMJ?D1oh1U~`Wv9P0y~>55}aS@KKw%$ynPWsjXKD!$1);Xw9Eo=0!m<#nbN>F-iqlx=NyU&7Yz z*4@pQbRD+-d1A=W*5$MDbkgZ}2EScm?%rE*eBIGo)_W%C3Gg3&SpCsEU*yB)ExR}W zJ#76+I((b4M32#h7}(RIkC1)(-r_@Seh09 literal 0 HcmV?d00001 diff --git a/nitrofiles/484e414a/tmd.0.patch.sha1 b/nitrofiles/484e414a/tmd.0.patch.sha1 new file mode 100644 index 0000000..5a54df9 --- /dev/null +++ b/nitrofiles/484e414a/tmd.0.patch.sha1 @@ -0,0 +1 @@ +f98c9648e668b8c30d1e85926626bf971cfbf749 \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.0.sha1 b/nitrofiles/484e414a/tmd.0.sha1 new file mode 100644 index 0000000..cc9be54 --- /dev/null +++ b/nitrofiles/484e414a/tmd.0.sha1 @@ -0,0 +1 @@ +e99b6e6e9e8e46d2a0ad820a2c8e187829b3001a \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.1024 b/nitrofiles/484e414a/tmd.1024 new file mode 100644 index 0000000000000000000000000000000000000000..7df516a6a9937143357765f2ecc192f3c1d6cb92 GIT binary patch literal 520 zcmZQzWME9-$o+YZZOtat6%!`5`LX04ymGn5R_#%~^NG-^rl8%gHmr_6cdY*S#}%$C zzb(^Ro5bk&XKAnhleBePb~&~NNtk&y9vP&6uEL|v@ zU9e|Oy`1%|iVv3-FtYIEEqPJ*(LD6{SBrBi^!ygcKbv&gaG&X}^6w@Op14n`cWJ)5 zVb%lxo{UY^yQ{M%>3hgt6W(ZD`YR<^2nxpLtCE z3tG>lD?WVFb|8meUrMT|@ac4;#9s+QTCQi7Jo&0z!0q8 y0Zf94h6V;O0un?576t}Js8S#k%9eb>uytjT$~MKlN(Hy=66K!gIxZ_(BLo0b-If;s literal 0 HcmV?d00001 diff --git a/nitrofiles/484e414a/tmd.1024.patch.sha1 b/nitrofiles/484e414a/tmd.1024.patch.sha1 new file mode 100644 index 0000000..ce16cbe --- /dev/null +++ b/nitrofiles/484e414a/tmd.1024.patch.sha1 @@ -0,0 +1 @@ +ea8006223ad563928c0174c5792e9d823ab6bd3a \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.1024.sha1 b/nitrofiles/484e414a/tmd.1024.sha1 new file mode 100644 index 0000000..1118e92 --- /dev/null +++ b/nitrofiles/484e414a/tmd.1024.sha1 @@ -0,0 +1 @@ +dbbebf6f8c5697e1eb1727a6a20c7a077670c30c \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.1280 b/nitrofiles/484e414a/tmd.1280 new file mode 100644 index 0000000000000000000000000000000000000000..21a55c30afcc15b4a99e68b5ca64a4d48d6370ec GIT binary patch literal 520 zcmZQzWMH&R%;V-NQti!L^mQxa7SSi|4G!89H*7DGo0le2e=@1dv|VJaqqL%3xZlT9 z6N{4PXdd8L?svgzf~I@!l%j1_yV&=~oPYaIFXya8+EwZL2jK4x=&fRLZR`#;Qo|O_zMo&UkM9s9am(P9V$(bzD6H7 z79HBuSoX@fbkzY_+f8nP>lr8jLHYS5y3URU5MZe58~|mSlVK<`gSdyEqZdf0fgxDG y1DFI84Gj!n1SE(AtPBi{P^Ca7lr8y$;e$@0B!jIMD`Onn@slC!`xLagwg3S436m%Q literal 0 HcmV?d00001 diff --git a/nitrofiles/484e414a/tmd.1280.patch.sha1 b/nitrofiles/484e414a/tmd.1280.patch.sha1 new file mode 100644 index 0000000..d73efd8 --- /dev/null +++ b/nitrofiles/484e414a/tmd.1280.patch.sha1 @@ -0,0 +1 @@ +9a51af752391184023f9bf2bfe33e9a17af7f977 \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.1280.sha1 b/nitrofiles/484e414a/tmd.1280.sha1 new file mode 100644 index 0000000..42e8d1b --- /dev/null +++ b/nitrofiles/484e414a/tmd.1280.sha1 @@ -0,0 +1 @@ +470a6087932b7a435f879ad2ff695c4e097eae22 \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.1536 b/nitrofiles/484e414a/tmd.1536 new file mode 100644 index 0000000000000000000000000000000000000000..b4b01c148a32e91b8b610c253834a98a6a37d591 GIT binary patch literal 520 zcmZQzWMC|n+nTj)f!WIMVtJc|GGm%H6kW`TvEQt+(NL;$uiNeio)68dgMWH&Ioxtz z=4O|TD?`rOiMn0W@BT^KZhLQeolnSCiK8{)dp8+>pVwhCMI+PYW@DhF?bf7TIZ5fM zlJ}JileEsy&Aw^A^v~T@T+3!3Ta&s~&GB>k`mC;5H-2>fdGie0G7&Y|X~!cZ zJH#(;Q2xwN|NN;nn@?AT;U(QBE9*G_lvzKbZf*SWQE%hj=3DJg@_H(kHGiCF!RYxu zqbHM%he$8XRVZW4;!b<-f_ zo9vOFdO39kcjxSkFIbh%KmiEK&o9w+b~JzhLtW7#WsOq*(^DdgNw`JiAh!CJ>{ zX2zkYwH`5L(ry*;ww^KTAMc3R^wxLvTXROCeOE-oezm2X{dJ=Ja6!o$6K-FZc}W4E zW-a>mBkrM=WyR%tHpxy$UkWG-p3=6xd&#pXr$D%`C$==bcizG}SFWhjoUR<6Y$=PT zo!!c8w)$-PRa0-4lc2tz1jKr*368JD$jb>Z@2lpZR_bv+-WoQ4f}<5 zEYbhsWfr!5@)xdYERO=TCbRfIpL17qarU-l-zL{NO#WK9PJ$)s%T=8{kEZmceRSC~ zS#bSwIjN??H(lLRjyraVGf)76^7Bh{ogEDzz);sY0LnBc!%$`haSuO7FOW_HL$H1a xFbO6a8W_L`NDv9w85kI$N`Xu$TdIcPEcdjsd65UcWPZ}zz5DuN9$8b>3jhw_lk@-p literal 0 HcmV?d00001 diff --git a/nitrofiles/484e414a/tmd.1792.patch.sha1 b/nitrofiles/484e414a/tmd.1792.patch.sha1 new file mode 100644 index 0000000..b1c5503 --- /dev/null +++ b/nitrofiles/484e414a/tmd.1792.patch.sha1 @@ -0,0 +1 @@ +ad741b0ef09b4a5f1f35f5737c8abd7b2edb9239 \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.1792.sha1 b/nitrofiles/484e414a/tmd.1792.sha1 new file mode 100644 index 0000000..b37aeaf --- /dev/null +++ b/nitrofiles/484e414a/tmd.1792.sha1 @@ -0,0 +1 @@ +c731a5a43941ff12d6814e0fc8b4f41b0481aa21 \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.256 b/nitrofiles/484e414a/tmd.256 new file mode 100644 index 0000000000000000000000000000000000000000..e3f6fe825d2fdf3f74b15d6ea9514dc359ccc8e0 GIT binary patch literal 520 zcmZQzWMFL2zjq|q-+RAxk@tPRM?d$riLoVZtk}yT+NBftU2Bd>glbIZSY@9kbxRH(FFs%5F#pf8)Fq34EwXV?mW!ypYGe4cI&=A>b;4B@>wXxu zP7qtRY2DYGYebKWP4eEV`Lg%K{q3J^nqF1fS_OsvyXw958K16LtgC0*T7RwX z(fg%Y376(H|HyJuXE#cp_>+rU;L+!zSF3Vb8V&MlC#GDKn!b~X@8tETx1%?4reFVZ zLhrAC?h&=b9*qyC(|rY%lTP+NmQmX+rO={VD!k;2%(r;Q?GtNvq^;R%k^bh<*IgUA z?w8ES{2IPByf|kn$`dS literal 0 HcmV?d00001 diff --git a/nitrofiles/484e414a/tmd.256.patch.sha1 b/nitrofiles/484e414a/tmd.256.patch.sha1 new file mode 100644 index 0000000..9a901b3 --- /dev/null +++ b/nitrofiles/484e414a/tmd.256.patch.sha1 @@ -0,0 +1 @@ +3b321c1e135fcbde14b9e2016c5d4b6abd19bdea \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.256.sha1 b/nitrofiles/484e414a/tmd.256.sha1 new file mode 100644 index 0000000..0c4b829 --- /dev/null +++ b/nitrofiles/484e414a/tmd.256.sha1 @@ -0,0 +1 @@ +84796177e89ec2687929becfb9a83481ae93f077 \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.512 b/nitrofiles/484e414a/tmd.512 new file mode 100644 index 0000000000000000000000000000000000000000..822b24cee8ffe48c2b165fe044ed13d36fc88a86 GIT binary patch literal 520 zcmZQzWMG`Ar1D6n-|vBo^vrFoS)s{Ioac`vPj)P@6Zj)Di8IMRYc2Z%S!0C+gGnu& zfl(6ExDrwr5Um-&Ok-uU^=?X!janMK0+X%a`3?&3jy^5q0eF zC+2ODtWw7~em;-PQhWF$rn4bmVIzNQbJJ~8csqqFWa zJD1Y)b9zkKk{ymMt5jv600iadm*_e>8bE-du5$pCX-3^FhZ3AnNYUm6NbzqN()!ZtC@J&YHRu(7rAYwAN~OV@K1{= literal 0 HcmV?d00001 diff --git a/nitrofiles/484e414a/tmd.512.patch.sha1 b/nitrofiles/484e414a/tmd.512.patch.sha1 new file mode 100644 index 0000000..c8f10e3 --- /dev/null +++ b/nitrofiles/484e414a/tmd.512.patch.sha1 @@ -0,0 +1 @@ +efc5c2e832373f76a0fa3e02aa9ba57c31b7b450 \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.512.sha1 b/nitrofiles/484e414a/tmd.512.sha1 new file mode 100644 index 0000000..c778286 --- /dev/null +++ b/nitrofiles/484e414a/tmd.512.sha1 @@ -0,0 +1 @@ +6a20da037dd7fcb454bdf5b3f3553f4fa37a24ce \ No newline at end of file diff --git a/nitrofiles/484e414a/tmd.768 b/nitrofiles/484e414a/tmd.768 new file mode 100644 index 0000000000000000000000000000000000000000..39f6c5ec0ab50915ac7dd63857d3f67526b43a15 GIT binary patch literal 520 zcmZQzWMGtS+Q3{AvA&{P^X-i;yT*GQ9Ch*k{n_Hx?@oTKErwlXny=$3 zURO8@9}-)3`G?$!2#qZE1Y?ew4`*txI{Wgt=Zx6? zR-1V4rDe5+`0tksAH<|yRJ$|hipcBSww28Z>fXgM?22Fg1d4PFgSLKdvT^D-wZ?cw zeP_pilO1ogTlxckGXHI1pa2Br=a=X@I~qWMp{{cPlxa?eq09{89)6BqAe{z=VEqnY w5==BSFn|$|AQCV$Ffc-u0+~>@>vkfezzOXIEdcCSm(1!|Hv^X4ZUopRQs-e-F5k;9KxS6TkO zBCx;t{bPdd&k|AIHgHIQE&G1(vx=;7HHOgh!VZCSV8~R%%?YPB(JElZ4$g2&0HK5wcY5! zlouzxSESmx2<9!hz)`xfHOI5&olNhJLza`S7@d6Fw?yvo;{Y4y@IH~I=1UjurACL( z-qOg#z!RRj;W3|Y*z8CK3P4bPeu=KLqX7gM>N*ENndW2|%FH0{;pgZL(rI7_*6#o& x!9+s?0~i4bA^{5n10z%^6Oe|mr5G5T44$6+BrdRtqkX!xeIQa$fX^1%R?izmE(M#czN zOyjAWYVgLSQf7XHzhJ>kt2D7+K_Azg*8C{=;`@tEe)cQJjq@*YKbtW{s9B3C)xw?a zw$7u+A@jU$SHC&U)6y<+%i_T9#p~-|9}WE^#@|>XxRL$uRE{2%eQg!&tRWBIA5&da zdv0QStws95NhdRkFW4<#u-U2nL(#1pbK~N6emmwUq2^%3vOa*VN!a#8(d^w<%$fCM zpS+wUG-svw(--eqa#C-|pMSe;vZVg6En70xvSy^_9`NaIKeOJ}_QaLPvmfY7i7nia z^Yn$$rF(|z=HE=FTg-jp$v^=J%Fi#+b#^p>07G5p04UR(3`3b2#6A2Ry+Jw+48i&x yz$BPxXkY*%AVDNxWnf^0DrE-J5VjNpgAb470u#UB52?xKGhW|slAjpD_8S0diINfk literal 0 HcmV?d00001 diff --git a/nitrofiles/484e414b/tmd.1280.patch.sha1 b/nitrofiles/484e414b/tmd.1280.patch.sha1 new file mode 100644 index 0000000..545cb5f --- /dev/null +++ b/nitrofiles/484e414b/tmd.1280.patch.sha1 @@ -0,0 +1 @@ +049a12c7ab4d714409554e51ba4ba420f790ada4 \ No newline at end of file diff --git a/nitrofiles/484e414b/tmd.1280.sha1 b/nitrofiles/484e414b/tmd.1280.sha1 new file mode 100644 index 0000000..82ccd85 --- /dev/null +++ b/nitrofiles/484e414b/tmd.1280.sha1 @@ -0,0 +1 @@ +52dc147e431a7f219096165e1d1521b1a6dba705 \ No newline at end of file diff --git a/nitrofiles/484e414b/tmd.1536 b/nitrofiles/484e414b/tmd.1536 new file mode 100644 index 0000000000000000000000000000000000000000..0eb6bae16a0b3cd9e6ed7f3a3a853e1e3d4b8f9a GIT binary patch literal 520 zcmZQzWME7ap8NKIvhO?25cRjJ`?=VRLi;agc<35*hl}0{zIV=OwQI@jza66P8TyyD z%yZcy`Yn%5W2)=#@;Z^nFHIv)IB&V|dY8+`oX_^}qX;Wrl~J zr!0Rq?UBgh`_H~jsLQ?hCTTb0%&qnFyBN=$KD%(?stXO%e?QuIW$GFAQ{q4Ge9_vK z>Fl4f$Ht-4?UrKD`h_AV7qdLNweIqc^^a3)9UC>Su3rE5)FWqJi<7Jy@ABp`ZuL~| z`DB{7e8Tya;X5{4bw@0oCs!jS-TIZObJAp?tjfuaB^xee1jK0+={<7TY^tcFvF>ZJ zO+rJ@>tzO8kGxrF{dLI>7DEOKKu~^uiLSGw0R$N8ItM_R=42Sk%pmUJ=jaX6X#jDR y1HzPs1_m$!5<~(v1_nl`QWhW$VN3BaOt+}IyXMYxhxy)f4=CC*<^7y59RmPv^O@QJ literal 0 HcmV?d00001 diff --git a/nitrofiles/484e414b/tmd.1536.patch.sha1 b/nitrofiles/484e414b/tmd.1536.patch.sha1 new file mode 100644 index 0000000..d9922dd --- /dev/null +++ b/nitrofiles/484e414b/tmd.1536.patch.sha1 @@ -0,0 +1 @@ +9dc4d3093880a1ed965d0768f69099c160ad5c48 \ No newline at end of file diff --git a/nitrofiles/484e414b/tmd.1536.sha1 b/nitrofiles/484e414b/tmd.1536.sha1 new file mode 100644 index 0000000..c5c72f3 --- /dev/null +++ b/nitrofiles/484e414b/tmd.1536.sha1 @@ -0,0 +1 @@ +d3449c4cbfb0904246ad2091a30c11b40c48ef16 \ No newline at end of file diff --git a/nitrofiles/484e414b/tmd.1792 b/nitrofiles/484e414b/tmd.1792 new file mode 100644 index 0000000000000000000000000000000000000000..7f0d5deb64d351f2034fada4ae02c5e47cc020e2 GIT binary patch literal 520 zcmZQzWMB+_rjnJ?D(lpAd#S0~R9%<%9dj&eR_AeLFiT#}P28F2+W!B8h_|s9(;>!V zSJT?cj55Djmb!e`s9fz{v4LsrEy?z$j3+vh^j$u8<|mx#IahbNg;l})vc9qN4$-&e z(~XRjW=8h2?l>6V=9E0m|Ah7b?^hSE4&^x`VW7~Ea*=PwFTRUekM&rNI;Fn8y*TiQ z=IUFLqITlVO#%(uCM{MsF9;2M_bBe!tlM=D83Q!WY!*&k`zYXoeM0iNSAUIcH80M( zrt$mb-~PoxTOyt@?{LeHS)E^Ugmvnh_r*(pmp*SgI!#IR;B$}Zi{p093R+N>Ud^E4 zzwX5Dtngbx%LTfRPy3_KKmiEK&o9w+b~JzhLtW-FaU%V3u0z^R0T)aRQ-_es1CKx+?l1rSz3NH|NX;#b>;hTw2+4BHAk9 z_v%->UKFdf?eWlG+4qq>H8^td>UqC-53<;6KK;EbWJl^drSE(Xrr!8{@A|&U_FE?H zD~;B?{@-op)kfD&g@~e;8|FA>`5o=Qy)M>$e$Hlg=2MO}ahHxaYv zQ#XI|ZTg+R%>K&^wk>@tFZ|~aO5L^Vphu-pte)^Y$>t)z-v$!N`VTHxO}poG{`?ky zfjx}}Dz|aY&ANIr`#F<%#-c|anydZ)eA-t&|K)R8rQ8oEpNs20iVe1ycJb&Ip7^HN zUx(xJqno9^o_nz1QPTqUrfUoofS~;R5?yCU0|+qGbq;_s&B-v7nL*sc&(RyC)4&j{ x-vLa5iG~ISFai=p0wx9qMkJ*Ww&Wj%TMAVHySY3*9B`h=SNw5@_MyyzW&kLPp6LJp literal 0 HcmV?d00001 diff --git a/nitrofiles/484e414b/tmd.512.patch.sha1 b/nitrofiles/484e414b/tmd.512.patch.sha1 new file mode 100644 index 0000000..09a6c64 --- /dev/null +++ b/nitrofiles/484e414b/tmd.512.patch.sha1 @@ -0,0 +1 @@ +e483dcfd3fa330dc95fe349c0fa95f32ccb6f6ec \ No newline at end of file diff --git a/nitrofiles/484e414b/tmd.512.sha1 b/nitrofiles/484e414b/tmd.512.sha1 new file mode 100644 index 0000000..0b677a8 --- /dev/null +++ b/nitrofiles/484e414b/tmd.512.sha1 @@ -0,0 +1 @@ +8b94dea2b03055a5729e61a247ee70df0d9ebbff \ No newline at end of file diff --git a/nitrofiles/484e414b/tmd.768 b/nitrofiles/484e414b/tmd.768 new file mode 100644 index 0000000000000000000000000000000000000000..e2f22cce8f751b59e184b3531c4557b8b237d79a GIT binary patch literal 520 zcmZQzWMHiN_#o=tdWH9~_B{;yymi%USAH&jm8o9rA$COY?%P*!+xWWbybJk{#m7IB zd%Qx9J>kXkzoyq-XqTFrKW;t-q(VeBEK!SHR-Uoxo%$ktSs6t;%;B`)$F#YKW)=xZrKQkYfR3H z5&EoX>3^^N)ibucoI=0-ewOTuI?8!;qFL*MfEPzUUj0xN9&`Ruzv3nLoz^-!x;^es zwyn)+vi%)2f47U>Tl07G5p04UR(3`3b2#6A2Ry+Jw+48i&x xz$BPxXkY*%AVDNxW?*21Dh1IHwiE+H-;+zxqIX#`-yio`JhRs?C{A-p2>>*-myiGe literal 0 HcmV?d00001 diff --git a/nitrofiles/484e414b/tmd.768.patch.sha1 b/nitrofiles/484e414b/tmd.768.patch.sha1 new file mode 100644 index 0000000..4035995 --- /dev/null +++ b/nitrofiles/484e414b/tmd.768.patch.sha1 @@ -0,0 +1 @@ +86ca8b148a65462b51e59b6d0f47a3fd6da1a597 \ No newline at end of file diff --git a/nitrofiles/484e414b/tmd.768.sha1 b/nitrofiles/484e414b/tmd.768.sha1 new file mode 100644 index 0000000..b628fbe --- /dev/null +++ b/nitrofiles/484e414b/tmd.768.sha1 @@ -0,0 +1 @@ +8bda71fb406de03486825c27c653d8968c039fe3 \ No newline at end of file diff --git a/nitrofiles/484e4150/tmd.1024 b/nitrofiles/484e4150/tmd.1024 new file mode 100644 index 0000000000000000000000000000000000000000..3f6cd9c1248b7b3b48c580b9e725764b60ee4500 GIT binary patch literal 520 zcmZQzWMGVAUau%JvvW~a;12(<-zp}3Jh`X!e(}GGq|bM^o)YFdbzqC?MV7F1WMDmw^Hhl%HRs>+EO%0fxHH0Z^tn8HO@5hmL&iH literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4150/tmd.1024.patch.sha1 b/nitrofiles/484e4150/tmd.1024.patch.sha1 new file mode 100644 index 0000000..2053caf --- /dev/null +++ b/nitrofiles/484e4150/tmd.1024.patch.sha1 @@ -0,0 +1 @@ +f60acf3acadb565d08719a79efaba5231f077a62 \ No newline at end of file diff --git a/nitrofiles/484e4150/tmd.1024.sha1 b/nitrofiles/484e4150/tmd.1024.sha1 new file mode 100644 index 0000000..1f74f29 --- /dev/null +++ b/nitrofiles/484e4150/tmd.1024.sha1 @@ -0,0 +1 @@ +1141459540fd9df26208609a41db5eb19fce2093 \ No newline at end of file diff --git a/nitrofiles/484e4150/tmd.1280 b/nitrofiles/484e4150/tmd.1280 new file mode 100644 index 0000000000000000000000000000000000000000..3ef63d1d7f185c73d3851bab37eb4bf8d6e81c62 GIT binary patch literal 520 zcmZQzWMG^i>s+yktuQZHK1k*1mmMj)95^p%HqJY7=W@%ZN#YR}FH)5&ZC9>KhnDX8Q!{nC`l znl~?T*z7J)V_JB(;q#Ie-{xOy@^D$d+c9J1kFIIOjZAZESZA_d(3xods5JHe;)zY? z?OcMsWjUX8E9WV-QSDriZXO;yzh`IMF~`!5_cwzJe!rS6b2K{VP`C3#jlDPDriM>d zf9O_lC8$qug?v3r)*t1JoPCn@EuZ`%!h_PXVdb^A{oPh!ml%HRs>+EO%0fxHH0Z^tn8HO@5hIy literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4150/tmd.1280.patch.sha1 b/nitrofiles/484e4150/tmd.1280.patch.sha1 new file mode 100644 index 0000000..a14cbfd --- /dev/null +++ b/nitrofiles/484e4150/tmd.1280.patch.sha1 @@ -0,0 +1 @@ +60374b640ce21b3cae134b6ee29d16eabbaaad6d \ No newline at end of file diff --git a/nitrofiles/484e4150/tmd.1280.sha1 b/nitrofiles/484e4150/tmd.1280.sha1 new file mode 100644 index 0000000..09bb34f --- /dev/null +++ b/nitrofiles/484e4150/tmd.1280.sha1 @@ -0,0 +1 @@ +51e5befb51db74fb9fd0da19906dd5b03aaea92d \ No newline at end of file diff --git a/nitrofiles/484e4150/tmd.1536 b/nitrofiles/484e4150/tmd.1536 new file mode 100644 index 0000000000000000000000000000000000000000..c607b5be65a406b9cb1d5886e9690f92532d7e00 GIT binary patch literal 520 zcmZQzWMK4CyJR8Rrs%cS`2BvlQ@6iK%K#2`#v00`8a(~qn>SWIL8L9ACnL0o_eSMi2Y;y&H1mFD|Ec^w3I#cp1sAx zV_VBcpEn$Lr%Io%RD2reQu^XPvyo*)V$D`JwW=xGEnYKeecog6&-|ggT;uaq`3KVM z&d>e))Y*k+ySD^Ewhl&M|U67$x0Z}t+|a+c%|I}!u7SZGZ+rBjiyV9!6P{3p4y z<6C>q7EHLZL-x48q3WLw(Fv>G2jzS0+;qSt>A;OAtzC>N99Cc7GklPo+ZR)I`Avn~ zhxr$|-kN%c_(+EO%0fxHH0Z^tn8HO@5hzp=jhbe8eKNg?JnXM%17x{Fyb`ZxaEHKjXJ;Kf32{f!e6dFLuO|2#E) z>7K)qi9IVAr4$~jKYMFiA$3FJ=6=zq<-r#UQ?@;n)XlS(WxJ6!$BMuEoX_8s`KLsR zRZdh*_{^+wGhqKrb0@A-nwo(07F$KHPXw0Sy9?|fbVdmU$0JFX-gTGxH^_4G-t z3oAc#POM*4S7d6^+9;axo`C`ol%HRs>+EO%0fxHH0Z^tn8HO@5hWr>6X$aAe-o@V7r_%*c3F zwNyv^d9YTbiPc)8f}-}io813}D{9_MecC4SX_MW%bl%x3J#ToflWpvsu3K>Rg?ijh zk*f*|Ztz;Cb27MonSJ@0_S<*Qizj{UtyYmuDbL)TVpFPjs6y*>*S^ZNeCmNa8Kt?~ zocom@p8s@e0!LS&_~zv3?xF*FPuIt7$|^Z`OK<6w`Rvtudye``mJ6GS%Ps4Y*EjiT zuD~a7al7fEtL&!lOAK^3Gf)76^7Bh{ogEDzz);sY0LnBc!%$`haSuPo0FX`tL$H1a xFbO6a8W_L`NDv7a85n>F3_vu5EhWHkzUlXSDc(cx?f2h1a!!shw)#!@1psSumZ1Ou literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4150/tmd.256.patch.sha1 b/nitrofiles/484e4150/tmd.256.patch.sha1 new file mode 100644 index 0000000..f7e163b --- /dev/null +++ b/nitrofiles/484e4150/tmd.256.patch.sha1 @@ -0,0 +1 @@ +7bac9563d8ad82cb1a17f108e4f838de217b9b79 \ No newline at end of file diff --git a/nitrofiles/484e4150/tmd.256.sha1 b/nitrofiles/484e4150/tmd.256.sha1 new file mode 100644 index 0000000..c91d38e --- /dev/null +++ b/nitrofiles/484e4150/tmd.256.sha1 @@ -0,0 +1 @@ +aa9d8a660235102398d7791d4220689ccee5db17 \ No newline at end of file diff --git a/nitrofiles/484e4150/tmd.512 b/nitrofiles/484e4150/tmd.512 new file mode 100644 index 0000000000000000000000000000000000000000..152b271a7009ada6b5ea417ac46ae032271d5792 GIT binary patch literal 520 zcmZQzWMI_X_A)GJN4Ztk*TBu|C(6%O7o4Hyze@64Nl;kVbiH$mCL4PF{!W;%Rnzg* z@rB=~94f8VeAbn;PAXab*e9MT7q40NnLB-5u2MCjuj#H$TH0dnD~>m-lsMcv@?O_2 zdp$k&&w<^+Z(qo;+)5H=TDz}ljZ>s3o7PX=c}bg0_dI#Qb|?MLhQ0A7Q`P0f*f;Kw zHaoj|)9Q^EZtTm>_%ttDz_r}WqgX(yx~B2!$sVq7ro$?mV{fj!p!v03Ds+lO^1&k6 zCne5ZmoD7Czp$m{-pjsH*F@nz&u6c0yEDJ9u_{^Nl8r?DI_2;hqau#0D__mqxwxTp z_M+J>leFHo2WTWe(fcG6#XtcF%Fi#+b#^p>07G5p04UR(3`3b2#6A2R13)?r48i&x xz$BPxXkY*%AVDNxVqjo|Dg`p3Y{@4KM;8YaHhRntoG?9WLbPUZYApO^-SvOHp5yaPAzD6~8|L1*f9dn0Ew($nZ!%T}tt>9*Px;=Y zXO`Y&Bzno%R^Cao)_#GC&g)ZC7H($`z52eZ$k17YjX_Mf>VPF*-t+7CuX?=*h^h!% zwafpYrh6=7cyqx0Gc(_~S$O>N&2WzUxJ{(bL-g`Jx5-Uyhn9$av(mIK$jy%OR#@<- zA>_@~!{z0h-KSI>TdF>dfdUYepI@Tu>}UW1hPuuHP^LKgrl1~^KgC?}5Ull)B{fGOwHxr+?Qi?{Ir7t4%z3sz4zq!=xEA%$VsO>uSJIZ?g@`kV`N8^7tQ;z8u{BYT#!TiAdK=l7E z(@GX0#de9u{NV-a3GKgr;_Z+9l6}{B+XV9&SK%G>O#7{K80r&c}4SPecW08-Y06NdGguGD^D19Jgt5du9{!W zSaWaJX7|46!=qIcu3x(4Ca;4?O-n-!E@< zS@6Hq)VS>`JQKA&E*pJqt3J1hdtea&SU-*W literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4155/tmd.1024.patch.sha1 b/nitrofiles/484e4155/tmd.1024.patch.sha1 new file mode 100644 index 0000000..4683d22 --- /dev/null +++ b/nitrofiles/484e4155/tmd.1024.patch.sha1 @@ -0,0 +1 @@ +58e72dd4db37392add6c90e57d45738596e1e4e1 \ No newline at end of file diff --git a/nitrofiles/484e4155/tmd.1024.sha1 b/nitrofiles/484e4155/tmd.1024.sha1 new file mode 100644 index 0000000..5f6f5d6 --- /dev/null +++ b/nitrofiles/484e4155/tmd.1024.sha1 @@ -0,0 +1 @@ +317c8fb18be531edc349657b082bb2f019eb00f0 \ No newline at end of file diff --git a/nitrofiles/484e4155/tmd.1280 b/nitrofiles/484e4155/tmd.1280 new file mode 100644 index 0000000000000000000000000000000000000000..411aea9cff6016ea066a33eee519a0ba232f8958 GIT binary patch literal 520 zcmZQzWMC|4l*kV`YjWJCTF7M29nU>?p6k?Pzy4Ug%cJI3d49wxAqF#MbTUOR8~S^WW< zm;^g2eV$!>P`E*@G-|8s*-Z)Ue`LB4^{s@>Vck%arwWosL-u3&&D>9UByZCDU$IWr>kAL4c5MNw) zxGW?5&YaEW@;Q&U#Wz0u{d<0MK>b&?NB*%+@f>^SrOmQk^7HVTFBU5+f3_}?vRj_M zpvC5Lc+XMm8_Qq6&sz|a%Rm7L%Fi#+b#^p>07G5p04UR(3`3b2#6A2RLqR$X48i&x yz$BPxXkY*%AVDNxWnf^0Dg`p3Y{@4KQ!F=^FYA>SW4QXBck?N)_f?Wx*8>3YU7ckB literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4155/tmd.1280.patch.sha1 b/nitrofiles/484e4155/tmd.1280.patch.sha1 new file mode 100644 index 0000000..5f2888d --- /dev/null +++ b/nitrofiles/484e4155/tmd.1280.patch.sha1 @@ -0,0 +1 @@ +849d5e690d99989ec9e17dfced89e68a2ceb0950 \ No newline at end of file diff --git a/nitrofiles/484e4155/tmd.1280.sha1 b/nitrofiles/484e4155/tmd.1280.sha1 new file mode 100644 index 0000000..e901936 --- /dev/null +++ b/nitrofiles/484e4155/tmd.1280.sha1 @@ -0,0 +1 @@ +9463fdc0fb1bb75fa54e70844fcfb07b2552f928 \ No newline at end of file diff --git a/nitrofiles/484e4155/tmd.1536 b/nitrofiles/484e4155/tmd.1536 new file mode 100644 index 0000000000000000000000000000000000000000..4a3dc3c9b4eb37410bdec1fd7fa9e854c1c90726 GIT binary patch literal 520 zcmZQzWME``ZK(U?+yuJ|XOFsztUtK#$Le)I%WnQSWdC%1;?mB&apfP+UVq3dp>Q?y zWKO8vqTYlXZ@R6f-LcyB`olp-$z0CTnTI6ag%@fxJIisr-OqW_Q*64k*zS$9WU^!R z|6a}!Y0J30!9YduYs!9ApP6>H=bRFI-yhT!?9n{E@?q(`>EAV8SnfU7cREz;_}YzI zmzW;-aiX~MrB1+EO%0fxHH0Z^tn8HO@5hjmFTl1 zIrTh0e1Yj?_KkVI(`t4y7p_lf(v;M?a$?V$r023ltfuRx{CA8vt@rnt)wTDXdiGD* zUh#EpT~L~sVcsu0FYZA=V#cgBx_eJfJ3F=b^|`p1=?lvo(&qgSziYW-w!nlNQG#~S zqAQ(pp5HFq!dLfCyWLlCTYaB+(2=;s!83AQ=N&aV6U@E1tWZ?+NS9E@Pm3MdMq*pu zocLN3nSLjFkpy37nS7DDnCP{0RtFX<9Jf5beEShLhXYG~CgcllxYygVJ$jG(k$;?g zq3g6R7xH)OF8}aSeEFXR3>1K%{QMGKXGa4FFw}JpfHKX=FqD}=+{4c?6r|I@5Uk$; xOoEAq1_m$!5<~)a1_nl`QXmt`ma1W>W(xawy0c=^+w7U0?__@nHM1(c005Hol6C+9 literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4155/tmd.1792.patch.sha1 b/nitrofiles/484e4155/tmd.1792.patch.sha1 new file mode 100644 index 0000000..f9f564e --- /dev/null +++ b/nitrofiles/484e4155/tmd.1792.patch.sha1 @@ -0,0 +1 @@ +7ca86964bb72c8f1cbeb80abff372b2bd9aed62e \ No newline at end of file diff --git a/nitrofiles/484e4155/tmd.1792.sha1 b/nitrofiles/484e4155/tmd.1792.sha1 new file mode 100644 index 0000000..0b65390 --- /dev/null +++ b/nitrofiles/484e4155/tmd.1792.sha1 @@ -0,0 +1 @@ +2847ac650cca6f884124fe8803c830945f114da1 \ No newline at end of file diff --git a/nitrofiles/484e4155/tmd.256 b/nitrofiles/484e4155/tmd.256 new file mode 100644 index 0000000000000000000000000000000000000000..fec6a000a1e0e1d0aad88f06ce0d5781bb54ed9d GIT binary patch literal 520 zcmZQzWMFhS#Vebj$1hbB&eWZJeYS4O4-F1s?X532PZV347`D>KXqobjm1bwpT;|;* z(0qU11d-NNp%Yw9b*ry!2sxkF%U+?)eHCrxAj@@4VX1M`$QMP@n4aYR1; z5of(3<=Sd5gWTga+157;G&HK$wVV-{yY7q6lZvqR*?XjZ3oNs(i4~exwRCYehXMO# zE>Zo8T8X}SYu`U+x;$ler294BO8+!hxtUiRntz4}9lPgZd-!kNnxz@rRQ!!t7VU^+ zFj4bRXW?J}-sau`zpjg2@5Iuif+aYGzw(<$_Ob-czLi+lHiL`W?U| vm}qEV03#qlBw%D<03t8|(Ga$j07J$FWj%wNLWaS!0^D9-{i-#8?(qizNbiXQ literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4155/tmd.256.patch.sha1 b/nitrofiles/484e4155/tmd.256.patch.sha1 new file mode 100644 index 0000000..57dd3c5 --- /dev/null +++ b/nitrofiles/484e4155/tmd.256.patch.sha1 @@ -0,0 +1 @@ +df8002ff01bb3d07a6972141024d43228b8703d1 \ No newline at end of file diff --git a/nitrofiles/484e4155/tmd.256.sha1 b/nitrofiles/484e4155/tmd.256.sha1 new file mode 100644 index 0000000..aa3965f --- /dev/null +++ b/nitrofiles/484e4155/tmd.256.sha1 @@ -0,0 +1 @@ +de7020064cfe5e6aec10455b86bd8e1d432ec9a9 \ No newline at end of file diff --git a/nitrofiles/484e4155/tmd.512 b/nitrofiles/484e4155/tmd.512 new file mode 100644 index 0000000000000000000000000000000000000000..7aa494d77563fbd5eac7b92c3092e08be715f3d7 GIT binary patch literal 520 zcmZQzWMGWSe#D-0`QgH7hyRxxCaqZh=i86-H*bZ%$U51RA5(UKbB@-cC9AYK7n<|# zuszv&F*sjWIwtq=i*47A@y3MRpODDPZYCAqq}&xR!Ek$Dm!LIoT;NviyZ`$np3i8E zo$Yr1ZLZp9LGJ1n%O11VZ|^0)o|&6JFFmYN;Ps&fnZFJK-OibNg4q1$we2_Ix@YTf zENb$>qgPKQ|2fwEKDttPL67(RJLdW3Dl<+prd0h&J^1p1tV*#c|0nMQGw&UZeE)OF zSwqtuyJpQRj}gw8*8XbUnG5UIs(<)gxWVOTRI`xOO$8%AUF+IAPZHl9FN(F*j}oz0 zUQ_Tkbk_S>i8hr|n+pTe87Kfj`S~Tf&W;8UV5sXH0A-q!VJI_$xQCx(C`hM)Ay~fy xm;@6I4GdreB!~n|3=E7=r9dW>E%}6@zw+2Y7hOB!OM++_wWKX>u% zIdf)fbKRC7Ju8|2U+Y>e+Iit@T-(A0+mxc*9zEsSU&u3C`SHG|sv7gVncA0qx$t!V zr6sCUn)xzy%S`xrKkoF-@$;1PD_pj>{9o>o8Q0mf?=Hyst0T|wN?^^myq|72=YDwl zRJFy;mGAR2rK1+B*s6-3cQxhu&$#B=RP)2Rb>_49<-UzipN75OD&jFcCC^LAxNXAL z?EHr^c1tv`Eajg!p}qQ=76Sz!C_leM*V)kk0t|JX1E5TEG7M#A5clwN3lFa+y& y0Fz*%p@9L6fCQ0%nSp^3suakCvL&A|n6fFV9yc+ab|+w&bmeoAjYk$)&jkSR(wGJS literal 0 HcmV?d00001 diff --git a/nitrofiles/484e4155/tmd.768.patch.sha1 b/nitrofiles/484e4155/tmd.768.patch.sha1 new file mode 100644 index 0000000..fc97737 --- /dev/null +++ b/nitrofiles/484e4155/tmd.768.patch.sha1 @@ -0,0 +1 @@ +8cb3e55d23f77024ba231fb293b3df3328d8b6d4 \ No newline at end of file diff --git a/nitrofiles/484e4155/tmd.768.sha1 b/nitrofiles/484e4155/tmd.768.sha1 new file mode 100644 index 0000000..e697d32 --- /dev/null +++ b/nitrofiles/484e4155/tmd.768.sha1 @@ -0,0 +1 @@ +59fd7fad402f379d9b966e06fe8691a28e94091f \ No newline at end of file