From 2dd873fcfe9b13426161c37c7c0e763ab509976f Mon Sep 17 00:00:00 2001 From: Naim2000 Date: Fri, 19 Jul 2024 08:42:06 -0500 Subject: [PATCH] FRESH EDITION --- Makefile | 2 +- source/fatfs/ffconf.h | 4 +- source/main.c | 147 ++++++++++++--- source/mset9.c | 415 ++++++++++++++++++++---------------------- source/mset9.h | 41 ++++- source/pad.c | 114 +++++++++++- source/pad.h | 8 +- source/sd.c | 9 - 8 files changed, 464 insertions(+), 276 deletions(-) diff --git a/Makefile b/Makefile index 320f762..fef156a 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -lwiiuse -lbte -logc -lm +LIBS := -lwiiuse -lbte -logc -lm -lwiikeyboard #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/source/fatfs/ffconf.h b/source/fatfs/ffconf.h index bd82ae8..0a8b8c8 100644 --- a/source/fatfs/ffconf.h +++ b/source/fatfs/ffconf.h @@ -25,7 +25,7 @@ / 3: f_lseek() function is removed in addition to 2. */ -#define FF_USE_FIND 1 +#define FF_USE_FIND 0 /* This option switches filtered directory read functions, f_findfirst() and / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ @@ -52,7 +52,7 @@ / (0:Disable or 1:Enable) */ -#define FF_USE_FORWARD 1 +#define FF_USE_FORWARD 0 /* This option switches f_forward() function. (0:Disable or 1:Enable) */ diff --git a/source/main.c b/source/main.c index 8df5737..84ceb4b 100644 --- a/source/main.c +++ b/source/main.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -22,13 +23,50 @@ static void PrintHeader(void) { clearln('\315'); } +static int SelectionMenu(const char* const options[], int count) { + int posX, posY, selected = 0; + CON_GetPosition(&posX, &posY); + + while (true) { + printf("\x1b[%i;0H", posY); + for (int i = 0; i < count; i++) + printf(" %s %s%s\n", i == selected ? "\x1b[47;1m\x1b[30m>>" : " ", options[i], i == selected ? "\x1b[40m\x1b[39m" : ""); + + wait_button(0); + + if (buttons_down(WPAD_BUTTON_UP)) { + if (!selected--) + selected = count - 1; + continue; + } + + else if (buttons_down(WPAD_BUTTON_DOWN)) { + if (++selected == count) + selected = 0; + continue; + } + + else if (buttons_down(WPAD_BUTTON_A)) { + selected++; + break; + } + + else if (buttons_down(WPAD_BUTTON_B | WPAD_BUTTON_HOME)) { + selected = -1; + break; + } + } + + putchar('\n'); + putchar('\n'); + return selected; +} + int main(void) { initpads(); if (!SDMount()) goto exit; - if (!MSET9Start()) goto exit; - - int consoleVer = 0; + if (!MSET9Start() || !MSET9SanityCheckA()) goto exit; PrintHeader(); puts("\n" @@ -52,53 +90,106 @@ int main(void) { "New 3DS, 11.4 up to 11.7" }; - int posX, posY; - CON_GetPosition(&posX, &posY); + int consoleVer = SelectionMenu(options, 4); - while (true) { + if (consoleVer < 0) + goto exit; - printf("\x1b[%i;0H", posY); - for (int ii = 0; ii < 4; ii++) - printf(" %s %s\x1b[40m\x1b[39m\n", ii == consoleVer ? "\x1b[47;1m\x1b[30m>>" : " ", options[ii]); + PrintHeader(); + if (!mset9.hasHaxID1) { // Create hax ID1 + puts( + "\x1b[41;39m=== !! DISCLAIMER !! ===\x1b[40m\x1b[39m\n\n" - wait_button(0); + "This process will temporarily reset all your 3DS data.\n" + "All your applications and themes will disappear.\n" + "This is perfectly normal, and if everything goes right. it will re-appear\n" + "at the end of the process.\n\n" + + "In any case, it is highly recommended to make a backup of your SD card's\n" + "contents to a folder on your PC.\n" + "(Especially the 'Nintendo 3DS' folder.)\n" + ); - if (buttons_down(WPAD_BUTTON_UP)) { if (!consoleVer--) consoleVer = 3; continue; } + sleep(7); - else if (buttons_down(WPAD_BUTTON_DOWN)) { if (++consoleVer == 4) consoleVer = 0; continue; } + puts("Press (+) to confirm.\n" + "Press any other button to cancel.\n"); - else if (buttons_down(WPAD_BUTTON_A)) { consoleVer++; break; } + wait_button(0); + if (buttons_down(WPAD_BUTTON_PLUS)) + MSET9CreateHaxID1((MSET9Version)consoleVer); - else if (buttons_down(WPAD_BUTTON_B | WPAD_BUTTON_HOME)) { consoleVer = 0; break; } + goto exit; } + else if (mset9.consoleVer != consoleVer) { + puts(pBad "Error #03: Don't change console model/version during MSET9!\n"); + + printf("Earlier, you selected: '%s'!\n", shortNames[mset9.consoleVer]); + printf("Are you sure you want to switch to: '%s'?\n\n", shortNames[consoleVer]); + + sleep(3); - if (!consoleVer) goto exit; + puts("Press (+) to confirm.\n" + "Press any other button to cancel.\n"); + + wait_button(0); + if (!buttons_down(WPAD_BUTTON_PLUS)) + goto exit; - MSET9SetConsoleVer((MSET9Version)consoleVer); + MSET9CreateHaxID1((MSET9Version)consoleVer); + } while (true) { - PrintHeader(); - if (MSET9SanityCheck()) { - printf(pNote "Selected console version: %s\n", shortNames[consoleVer - 1]); + if (mset9.hasTriggerFile) { + MSET9Injection(false); + puts(pWarn "Try again?\n\n" + + pInfo "Press (+) to try again.\n" + pInfo "Press (-) to remove MSET9.\n"); + + wait_button(WPAD_BUTTON_PLUS | WPAD_BUTTON_MINUS); + if (buttons_down(WPAD_BUTTON_MINUS)) { + MSET9Remove(); + goto exit; + } + } + else if (mset9.homeExtdataOK && mset9.miiExtdataOK && mset9.titleDbsOK) { + printf(pNote "Selected console version: %s\n", shortNames[consoleVer]); printf(pNote "Inject MSET9 now?\n\n" pInfo "Press (A) to confirm.\n" pInfo "Press [B] to cancel.\n"); wait_button(WPAD_BUTTON_A | WPAD_BUTTON_B | WPAD_BUTTON_HOME); - if (buttons_down(WPAD_BUTTON_A)) MSET9Injection(); + if (buttons_down(WPAD_BUTTON_A)) MSET9Injection(true); } + else { + if (!mset9.homeExtdataOK) { + puts(pBad "HOME menu extdata: Missing!\n" + pInfo "Please power on your console with your SD inserted, then try again.\n" + pInfo "If this does not work, power it on while holding L+R+Down+B.\n"); + } + // else puts(pGood "HOME menu extdata: OK!\n"); + + if (!mset9.miiExtdataOK) { + puts(pBad "Mii Maker extdata: Missing!\n" + pInfo "Please power on your console with your SD inserted,\n" + pInfo "then launch Mii Maker.\n"); + } + // else puts(pGood "Mii Maker extdata: OK!\n"); + + if (!mset9.titleDbsOK) { + puts(pBad "Title database: Not initialized!\n" + pInfo "Please power on your console with your SD inserted,\n" + pInfo "open System Setttings, navigate to Data Management\n" + pInfo "-> Nintendo 3DS -> Software, then select Reset.\n"); + // else puts(pGood "Title database: OK!"); + } + } + if (!SDRemount()) break; PrintHeader(); int ret = MSET9Start(); if (!ret) break; - else if (ret == 2) { - printf(pWarn "Try again?\n\n" - - pInfo "Press (A) to confirm.\n" - pInfo "Press [B] to cancel.\n"); - wait_button(WPAD_BUTTON_A | WPAD_BUTTON_B | WPAD_BUTTON_HOME); - if (!buttons_down(WPAD_BUTTON_A)) break; - } } exit: diff --git a/source/mset9.c b/source/mset9.c index c49611c..9cc57ad 100644 --- a/source/mset9.c +++ b/source/mset9.c @@ -8,6 +8,7 @@ #include "fsop.h" #define ID1backupTag "_user-id1" +#define MSET9TriggerFile "002F003A.txt" enum { dbsSize = 0x31E400, @@ -32,6 +33,14 @@ typedef const struct N3DSRegion uint32_t MiiPlazaExtData; } N3DSRegion; +/* +typedef const struct haxOffsets +{ + uint32_t fopen_offset; + uint32_t fread_offset; +} haxOffsets; +*/ + static N3DSRegion N3DSRegions[NBR_REGIONS] = { { "USA", 0x8F, 0x217, 0x218 }, { "EUR", 0x98, 0x227, 0x228 }, @@ -42,6 +51,7 @@ static N3DSRegion N3DSRegions[NBR_REGIONS] = { }; const char* const haxid1[4] = { + // Old 3DS 11.8<->11.17 "\xef\xbf\xbf\xef\xab\xbf\xe9\xa4\x91\xe4\xa0\x87\xe4\x9a\x85\xe6\x95\xa9\xea\x84\x88\xe2\x88\x81\xe4\xac\x85\xe4\x9e\x98\xe4\x99\xa8\xe4\x99\x99\xea\xab\x80\xe1\xb0\x97\xe4\x99\x83\xe4\xb0\x83\xe4\x9e\xa0\xe4\x9e\xb8\xe9\x80\x80\xe0\xa0\x8a\xea\x81\xb1\xe0\xa0\x85\xec\xba\x99\xe0\xa0\x84sdmc\xe9\x80\x80\xe0\xa0\x8a""b9", @@ -53,40 +63,33 @@ const char* const haxid1[4] = { // New 3DS 11.4<->11.7 "\xef\xbf\xbf\xef\xab\xbf\xe9\xa4\x91\xe4\xa0\x87\xe4\x9a\x85\xe6\x95\xa9\xea\x84\x88\xe2\x88\x81\xe4\xac\x85\xe4\x9e\x98\xe4\x99\xa8\xe4\x99\x99\xea\xab\x80\xe1\xb0\x97\xe4\x99\x83\xe4\xb0\x83\xe4\x9e\xa0\xe4\x9e\xb8\xe9\x80\x80\xe0\xa0\x8a\xe9\xb9\x85\xe0\xa0\x85\xec\xb2\x81\xe0\xa0\x84sdmc\xe9\x80\x80\xe0\xa0\x8a""b9" - }; -struct MSET9 { - bool ready; - MSET9Version consoleVer; - N3DSRegion* region; - char ID[2][32 +1]; - bool hasBackupID1; - bool hasHaxID1; -}; -static struct MSET9 mset9 = {}; +struct MSET9 mset9 = {}; static bool is3DSID(const char* name) { if (strlen(name) != 32) return false; uint32_t idparts[4]; - return sscanf(name, "%08x%08x%08x%08x", &idparts[0], &idparts[1], &idparts[2], &idparts[3]) == 4; + return (sscanf(name, "%08x%08x%08x%08x", &idparts[0], &idparts[1], &idparts[2], &idparts[3]) == 4); } static bool isBackupID1(const char* name) { - return strstr(name, ID1backupTag) == name + 32; + return (strstr(name, ID1backupTag)) == (name + 32); } static bool isHaxID1(const char* name) { - return (bool)strstr(name, "sdmc"); + return (strstr(name, "sdmc") != NULL); } -int MSET9Start() { - char path[256] = "0:/Nintendo 3DS"; - FRESULT fres = 0; +int MSET9Start(void) { + char path[256] = "Nintendo 3DS/"; + FRESULT fres; DIR dp = {}; - FILINFO fl = {}; + FILINFO st[1] = {}; + + memset(&mset9, 0, sizeof(mset9)); fres = f_opendir(&dp, path); if (fres == FR_NO_PATH) { @@ -100,10 +103,15 @@ int MSET9Start() { } int foundID0 = 0; - while ((fres = f_readdir(&dp, &fl)) == FR_OK && fl.fname[0]) { - if (is3DSID(fl.fname)) { - printf(pInfo "Found ID0: %s\n", fl.fname); - memcpy(mset9.ID[0], fl.fname, 32); + while ((fres = f_readdir(&dp, st)) == FR_OK && st->fname[0]) { + if (!(st->fattrib & AM_DIR)) { + printf(pWarn "Found a file in the Nintendo 3DS folder? %s\n", st->fname); + continue; + } + + if (is3DSID(st->fname)) { + printf(pInfo "Found ID0: %s\n", st->fname); + strncpy(mset9.ID[0], st->fname, 32); foundID0++; } } @@ -122,8 +130,7 @@ int MSET9Start() { return false; } - strcat(path, "/"); - strcat(path, mset9.ID[0]); + sprintf(strrchr(path, '/'), "/%.32s/", mset9.ID[0]); fres = f_opendir(&dp, path); if (fres != FR_OK) { printf(pBad "Failed to open ID0 folder (!?) (%i)\n", fres); @@ -132,28 +139,52 @@ int MSET9Start() { int foundID1 = 0; int injectedConsoleVer = -1; - char curhaxID1[100] = {}; - while ((fres = f_readdir(&dp, &fl)) == FR_OK && fl.fname[0]) { - if (is3DSID(fl.fname) || isBackupID1(fl.fname)) { - printf(pInfo "Found ID1: %s\n", fl.fname); - memcpy(mset9.ID[1], fl.fname, 32); - mset9.hasBackupID1 = isBackupID1(fl.fname); + while ((fres = f_readdir(&dp, st)) == FR_OK && st->fname[0]) { + if (!(st->fattrib & AM_DIR)) { + printf(pWarn "Found a file in the ID0 folder? %s\n", st->fname); + continue; + } + + if (is3DSID(st->fname) || isBackupID1(st->fname)) { + printf(pInfo "Found ID1: %s\n", st->fname); + strncpy(mset9.ID[1], st->fname, 32); + mset9.hasBackupID1 = isBackupID1(st->fname); foundID1++; } - else if (isHaxID1(fl.fname)) { - injectedConsoleVer = 0; - strcpy(curhaxID1, fl.fname); - for (int i = 0; i < 4; i++) { - if (!strcmp(haxid1[i], fl.fname)) { - injectedConsoleVer = i + 1; - break; + else if (isHaxID1(st->fname)) { + char* ptr = strrchr(path, '/'); + sprintf(ptr, "/%s/", st->fname); + + if (mset9.hasHaxID1) { + puts(pWarn "Duplicate hax ID1!? Man what the h*ll"); + if ((fres = f_rmdir_r(path)) != FR_OK) + printf(pWarn "Failed to remove duplicate hax ID1 (%i)\n", fres); + } + else { + for (int i = 0; i < 4; i++) { + if (!strcmp(haxid1[i], st->fname)) { + injectedConsoleVer = i; + break; + } + } + + if (injectedConsoleVer >= 0) { + printf(pInfo "Found hacked ID1 (type %i)\n", injectedConsoleVer); + strcat(path, "/extdata/" MSET9TriggerFile); + mset9.consoleVer = (MSET9Version)injectedConsoleVer; + mset9.hasHaxID1 = true; + mset9.hasTriggerFile = (f_stat(path, 0) == FR_OK); + } else { + puts(pWarn "Unrecognized hax ID1. Goodbye"); + if ((fres = f_rmdir_r(path)) != FR_OK) + printf(pWarn "Failed to unknown duplicate hax ID1 (%i)\n", fres); } } - printf(pInfo "Found injected MSET9, #%i\n", injectedConsoleVer); + *ptr = 0; } else { - printf(pWarn "Unrecognized ID1 %s\n", fl.fname); + printf(pWarn "Unrecognized folder in ID0 %s\n", st->fname); } } f_closedir(&dp); @@ -171,54 +202,17 @@ int MSET9Start() { return false; } - if (mset9.hasBackupID1) { - puts(pNote "Found backed up ID1, let's rename it back for you"); - char backupID1name[50]; - strcpy(backupID1name, mset9.ID[1]); - strcat(backupID1name, ID1backupTag); - f_chdir(path); - if ((fres = f_rename(backupID1name, mset9.ID[1])) != FR_OK) { - printf(pWarn "Failed to restore backed up ID1 ..? (%i)\n", fres); - } - f_chdir("0:/"); - } - - if (injectedConsoleVer >= 0) { - puts(pNote "Found hax ID1, let's remove it for you"); - f_chdir(path); - if ((fres = f_rmdir_r(curhaxID1)) != FR_OK) { - printf(pWarn "Failed to remove hax ID1 ..? (%i)\n", fres); - } - f_chdir("0:/"); - - puts(pGood "MSET9 has been removed!"); - return 2; - } - - mset9.ready = true; + mset9.setup = true; return true; } -bool MSET9SetConsoleVer(MSET9Version consoleVer) { - if (!mset9.ready) return false; - - mset9.consoleVer = consoleVer; - return true; -} - -bool MSET9SanityCheck(void) { - char path[256]; - - if (!mset9.ready) return false; - - puts(pNote "Performing sanity checks..."); - - puts(pInfo "Checking extracted files..."); +bool MSET9SanityCheckA(void) { +// puts(pInfo "Checking extracted files..."); if (!CheckFile("/boot9strap/boot9strap.firm", 0, true) - || !CheckFile("/boot.firm", 0, false) - || !CheckFile("/boot.3dsx", 0, false) - || !CheckFile("/b9", 0, false) - || !CheckFile("/SafeB9S.bin", 0, false)) + + !CheckFile("/boot.firm", 0, false) + + !CheckFile("/boot.3dsx", 0, false) + + !CheckFile("/b9", 0, false) + + !CheckFile("/SafeB9S.bin", 0, false)) { puts(pBad "Error #08: One or more files are missing or malformed!"); puts(pInfo "Please re-extract the MSET9 zip file, \n" @@ -226,186 +220,169 @@ bool MSET9SanityCheck(void) { return false; } - puts(pGood "Extracted files look good!"); - - sprintf(path, "0:/Nintendo 3DS/%.32s/%.32s/", mset9.ID[0], mset9.ID[1]); - FRESULT fres = f_chdir(path); - if (fres != FR_OK) { - printf("f_chdir failed? (%i)\n", fres); - return false; - } - - puts(pInfo "Checking databases..."); - if (!CheckFile("dbs/import.db", dbsSize, false) - || !CheckFile("dbs/title.db", dbsSize, false)) - { - puts(pNote "Information #10: No title database!\n"); - - FRESULT fres = f_mkdir("dbs"); - if (fres != FR_OK && fres != FR_EXIST) { - printf("f_mkdir failed! (%i)\n", fres); - return false; - } - f_dummy("dbs/title.db", true); - f_dummy("dbs/import.db", true); + puts(pGood "Extracted files look good!"); + return true; +} - puts(pNote "Created empty databases.\n\n" +bool MSET9CreateHaxID1(MSET9Version ver) { + char path[256] = "/Nintendo 3DS/"; + FRESULT fres; - pInfo "Please initialize the title database by navigating to\n" - pInfo " System Settings -> Data Management -> Nintendo 3DS\n" - pInfo " -> Software -> Reset, then re-run the installer.\n\n" + if (!mset9.setup) return false; - pInfo "Visual aid: \n" - pInfo "https://3ds.hacks.guide/images/screenshots/database-reset.jpg" - ); + sprintf(strrchr(path, '/'), "/%.32s/", mset9.ID[0]); + fres = f_chdir(path); + if (fres != FR_OK) { + printf(pBad "f_chdir failed? (%i)\n", fres); return false; } - puts(pGood "Databases look good!"); - puts(pInfo "Looking for HOME menu extdata..."); - char extDataPath[30]; + if (mset9.hasHaxID1) { + if (ver == mset9.consoleVer) return true; - for (int i = 0; i < NBR_REGIONS; i++) { - N3DSRegion* rgn = N3DSRegions + i; - - sprintf(extDataPath, "extdata/00000000/%08x", rgn->homeMenuExtData); - if (f_stat(extDataPath, 0) == FR_OK) { - printf(pGood "Found %s HOME menu extdata!\n", rgn->name); - mset9.region = rgn; - break; - } + puts(pInfo "Renaming hacked ID1..."); + fres = f_rename(haxid1[mset9.consoleVer], haxid1[ver]); + } else { + puts(pInfo "Creating hacked ID1..."); + fres = f_mkdir(haxid1[ver]); } - if (!mset9.region) { - puts(pBad "Error #04: No HOME menu extdata found!\n\n" - - pNote "TIP: Power on your console while holding L+R+Down+B.\n" - pNote "You should be prompted to reset the HOME menu management info." - ); - - return false; + if (fres == FR_OK) { + f_chdir(haxid1[ver]); + f_mkdir("dbs"); + f_dummy("dbs/title.db", false); + f_dummy("dbs/import.db", false); + f_chdir(path); + } else { + printf(pBad "Failed to create hax ID1 (%i)\n", fres); } - puts(pInfo "Looking for Mii Maker extdata..."); - sprintf(extDataPath, "extdata/00000000/%08x", mset9.region->MiiMakerExtData); - if (f_stat(extDataPath, 0) != FR_OK) { - puts(pBad "Error #05: No Mii Maker extdata found!"); + if (!mset9.hasBackupID1) { + char ID1backupName[42]; + strcpy(ID1backupName, mset9.ID[1]); + strcat(ID1backupName, ID1backupTag); - sprintf(strrchr(extDataPath, '/'), "/%08x", mset9.region->MiiPlazaExtData); - if (f_stat(extDataPath, 0) == FR_OK) { - puts(pWarn "Please make sure you are opening Mii Maker and not Mii Plaza!"); - } - - return false; + puts(pInfo "Backing up original ID1..."); + fres = f_rename(mset9.ID[1], ID1backupName); + if (fres != FR_OK) + printf("f_rename failed? (%i)\n", fres); } - puts(pGood "Found Mii Maker extdata!"); - f_chdir("0:/"); - return true; + f_chdir(""); + return (fres == FR_OK); } -bool MSET9Injection(void) { - char path[256], path2[256]; - FRESULT fres; -// FIL fp; - - if (!mset9.ready || !mset9.consoleVer) return false; - - puts(pNote "Performing injection..."); - - sprintf(path, "0:/Nintendo 3DS/%.32s/", mset9.ID[0]); - f_chdir(path); +bool MSET9SanityCheckB(void) { + char path[256]; - // 1. Create hax ID1 - const char* thishaxID1 = haxid1[mset9.consoleVer - 1]; - sprintf(path, "%s/", thishaxID1); - sprintf(path2, "%s/", mset9.ID[1]); + if (!mset9.hasHaxID1) return -1; - puts(pInfo "Creating hax id1..."); - fres = f_mkdir(path); + sprintf(path, "/Nintendo 3DS/%.32s/%s/", mset9.ID[0], haxid1[mset9.consoleVer]); + FRESULT fres = f_chdir(path); if (fres != FR_OK) { - printf(pBad "f_mkdir #1 failed! (%i)\n", fres); + printf("f_chdir failed? (%i)\n", fres); return false; } - // 2. Copy Mii maker & HOME menu extdata over - puts(pInfo "Copying extdata over..."); +// puts(pNote "Performing sanity checks..."); - sprintf(strchr(path, '/'), "/extdata/"); - sprintf(strchr(path2, '/'), "/extdata/"); - - fres = f_mkdir(path); - if (fres != FR_OK) { - printf(pBad "f_mkdir #2 failed! (%i)\n", fres); - return false; + puts(pInfo "Checking databases..."); + if (!CheckFile("dbs/import.db", dbsSize, false) + + !CheckFile("dbs/title.db", dbsSize, false)) + { + f_mkdir("dbs"); + f_dummy("dbs/title.db", false); + f_dummy("dbs/import.db", false); } + else mset9.titleDbsOK = true; - strcat(path, "00000000/"); - strcat(path2, "00000000/"); - - fres = f_mkdir(path); - if (fres != FR_OK) { - printf(pBad "f_mkdir #3 failed! (%i)\n", fres); - return false; - } + puts(pInfo "Looking for extdata..."); + char extDataPath[30]; - sprintf(strrchr(path, '/'), "/%08x", mset9.region->homeMenuExtData); - sprintf(strrchr(path2, '/'), "/%08x", mset9.region->homeMenuExtData); + for (N3DSRegion* rgn = N3DSRegions; rgn < N3DSRegions + NBR_REGIONS; rgn++) { + if (!mset9.homeExtdataOK) { + sprintf(extDataPath, "extdata/00000000/%08x", rgn->homeMenuExtData); + mset9.homeExtdataOK = (f_stat(extDataPath, 0) == FR_OK); + } - fres = fcopy_r(path2, path); - if (fres != FR_OK) { - printf(pBad "fcopy_r failed! (%i)\n", fres); - return false; + if (!mset9.miiExtdataOK) { + sprintf(extDataPath, "extdata/00000000/%08x", rgn->MiiMakerExtData); + mset9.miiExtdataOK = (f_stat(extDataPath, 0) == FR_OK); + } } - sprintf(strrchr(path, '/'), "/%08x", mset9.region->MiiMakerExtData); - sprintf(strrchr(path2, '/'), "/%08x", mset9.region->MiiMakerExtData); + f_chdir(""); + return mset9.titleDbsOK && mset9.miiExtdataOK && mset9.homeExtdataOK; +} - fres = fcopy_r(path2, path); - if (fres != FR_OK) { - printf(pBad "fcopy_r failed! (%i)\n", fres); - return false; - } +bool MSET9Injection(bool create) { + char path[256]; + FRESULT fres; +// FIL fp; - // 3. Copy databases - puts(pInfo "Copying databases over..."); - strcpy(strchr(path, '/'), "/dbs"); - strcpy(strchr(path2, '/'), "/dbs"); + if (!mset9.hasHaxID1) return false; - fres = fcopy_r(path2, path); - if (fres != FR_OK) { - printf(pBad "fcopy_r failed! (%i)\n", fres); - return false; - } + sprintf(path, "/Nintendo 3DS/%.32s/%s/extdata/" MSET9TriggerFile, mset9.ID[0], haxid1[mset9.consoleVer -1]); - // 4. Create trigger file (002F003A.txt) - puts(pInfo "Injecting trigger file..."); - strcpy(strchr(path, '/'), "/extdata/002F003A.txt"); - fres = f_dummy(path, false); - if (fres != FR_OK) { - printf(pBad "f_dummy failed! (%i)\n", fres); - return false; + if (!create) { + puts(pInfo "Removing trigger file..."); + fres = f_unlink(path); + if (fres != FR_OK) { + printf(pBad "f_unlink failed! (%i)\n", fres); + return false; + } + } else { + puts(pInfo "Injecting trigger file..."); + fres = f_dummy(path, true); + if (fres != FR_OK) { + printf(pBad "f_dummy failed! (%i)\n", fres); + return false; + } } + /* UINT written; fres = f_write(&fp, "arm9 \"security\" processor vs. text file in extdata:", 52, &written); f_close(&fp); */ - // 5. Back up original ID1 - puts(pInfo "Backing up original ID1..."); - strcpy(path, mset9.ID[1]); - strcpy(path2, mset9.ID[1]); - strcat(path2, ID1backupTag); - fres = f_rename(path, path2); + return true; +} + +void MSET9Remove(void) { + char path[256]; + + if (!mset9.setup) return; + + puts(pInfo "Removing MSET9..."); + sprintf(path, "0:/Nintendo 3DS/%.32s/", mset9.ID[0]); + + FRESULT fres = f_chdir(path); if (fres != FR_OK) { - printf(pBad "f_rename failed! (%i)\n", fres); - return false; + printf("f_chdir failed? (%i)\n", fres); + return; } - f_chdir("0:/"); - puts(pGood "MSET9 injected, have fun!"); - return true; + if (mset9.hasHaxID1) { + puts(pInfo "Removing hacked ID1..."); + fres = f_rmdir_r(haxid1[mset9.consoleVer -1]); + if (fres != FR_OK) + printf("f_rmdir failed? (%i)\n", fres); + else + mset9.hasHaxID1 = false; + } + + if (mset9.hasBackupID1) { + char ID1backupName[42]; + strcpy(ID1backupName, mset9.ID[1]); + strcat(ID1backupName, ID1backupTag); + + fres = f_rename(ID1backupName, mset9.ID[1]); + if (fres != FR_OK) + printf("f_rename failed? (%i)\n", fres); + else + mset9.hasBackupID1 = false; + } } diff --git a/source/mset9.h b/source/mset9.h index cef031b..28963be 100644 --- a/source/mset9.h +++ b/source/mset9.h @@ -1,19 +1,40 @@ #include typedef enum MSET9Version { - O3DS_11_8_11_17 = 1, - N3DS_11_8_11_17 = 2, - O3DS_11_4_11_7 = 3, - N3DS_11_4_11_7 = 4, + OLD_11_8__11_17, + NEW_11_8__11_17, + OLD_11_4__11_7, + NEW_11_4__11_7 } MSET9Version; -// Identify the user's ID0 and ID1. Removes mset9 automatically if present. +struct MSET9 { + MSET9Version consoleVer; + char ID[2][32 +1]; + bool setup: 1; + bool hasBackupID1: 1; + bool hasHaxID1: 1; + bool titleDbsOK: 1; + bool homeExtdataOK: 1; + bool miiExtdataOK: 1; + bool hasTriggerFile: 1; +}; + +extern struct MSET9 mset9; + +// Identify the user's ID0 and ID1, hacked ID1 if present int MSET9Start(void); -bool MSET9SetConsoleVer(MSET9Version); +// Create the hacked ID1 +bool MSET9CreateHaxID1(MSET9Version); + +// Check global exploit files +bool MSET9SanityCheckA(void); + +// Check console specific exploit files +bool MSET9SanityCheckB(void); -// Check extracted files, HOME menu/Mii maker extdata, etc. -bool MSET9SanityCheck(void); +// (Un)inject MSET9. +bool MSET9Injection(bool create); -// Inject MSET9. -bool MSET9Injection(void); +// Fully remove MSET9. +void MSET9Remove(void); diff --git a/source/pad.c b/source/pad.c index b7440b7..c512380 100644 --- a/source/pad.c +++ b/source/pad.c @@ -1,26 +1,134 @@ +#include #include -#include -#include +#include +#include #include "pad.h" static uint32_t pad_buttons; +/* USB Keyboard stuffs */ +static lwp_t kbd_thread_hndl = LWP_THREAD_NULL; +static volatile bool kbd_thread_should_run = false; +static uint32_t kbd_buttons; + +// from Priiloader (/tools/Dacoslove/source/Input.cpp (!?)) +void KBEventHandler(USBKeyboard_event event) +{ + if(event.type != USBKEYBOARD_PRESSED && event.type != USBKEYBOARD_RELEASED) + return; + + OSReport("event= %i, 0x%x", event.type, event.keyCode); + uint32_t button = 0; + + switch (event.keyCode) { + case 0x52: // Up + button = WPAD_BUTTON_UP; + break; + case 0x51: // Down + button = WPAD_BUTTON_DOWN; + break; + case 0x50: // Left + button = WPAD_BUTTON_LEFT; + break; + case 0x4F: // Right + button = WPAD_BUTTON_RIGHT; + break; + case 0x28: // Enter + case 0x58: // Enter (Numpad) + button = WPAD_BUTTON_A; + break; + case 0x2A: // Backspace + button = WPAD_BUTTON_B; + break; + case 0x1B: // X + button = WPAD_BUTTON_1; + break; + case 0x1C: // Y + button = WPAD_BUTTON_2; + break; + case 0x4C: // Delete + button = WPAD_BUTTON_MINUS; + break; + case 0x29: // ESC + case 0x4A: // Home + button = WPAD_BUTTON_HOME; + break; + + default: + break; + } + + if(event.type == USBKEYBOARD_PRESSED) + kbd_buttons |= button; + else + kbd_buttons &= ~button; +} + +void* kbd_thread(void* userp) { + while (kbd_thread_should_run) { + if (!USBKeyboard_IsConnected() && USBKeyboard_Open(KBEventHandler)) { + for (int i = 0; i < 3; i++) { USBKeyboard_SetLed(i, 1); usleep(250000); } + } + + USBKeyboard_Scan(); + usleep(400); + } + + return NULL; +} + void initpads() { WPAD_Init(); + PAD_Init(); + USB_Initialize(); + USBKeyboard_Initialize(); + + kbd_thread_should_run = true; + LWP_CreateThread(&kbd_thread_hndl, kbd_thread, 0, 0, 0x4000, 0x7F); } void scanpads() { WPAD_ScanPads(); + PAD_ScanPads(); pad_buttons = WPAD_ButtonsDown(0); + u16 gcn_down = PAD_ButtonsDown(0); + pad_buttons |= kbd_buttons; + kbd_buttons = 0; if (SYS_ResetButtonDown()) pad_buttons |= WPAD_BUTTON_HOME; + + if (gcn_down & PAD_BUTTON_A) pad_buttons |= WPAD_BUTTON_A; + if (gcn_down & PAD_BUTTON_B) pad_buttons |= WPAD_BUTTON_B; + if (gcn_down & PAD_BUTTON_X) pad_buttons |= WPAD_BUTTON_1; + if (gcn_down & PAD_BUTTON_Y) pad_buttons |= WPAD_BUTTON_2; + if (gcn_down & PAD_BUTTON_START) pad_buttons |= WPAD_BUTTON_HOME | WPAD_BUTTON_PLUS; + if (gcn_down & PAD_BUTTON_UP) pad_buttons |= WPAD_BUTTON_UP; + if (gcn_down & PAD_BUTTON_DOWN) pad_buttons |= WPAD_BUTTON_DOWN; + if (gcn_down & PAD_BUTTON_LEFT) pad_buttons |= WPAD_BUTTON_LEFT; + if (gcn_down & PAD_BUTTON_RIGHT) pad_buttons |= WPAD_BUTTON_RIGHT; +} + +void stoppads() { + WPAD_Shutdown(); + + kbd_thread_should_run = false; + usleep(400); + USBKeyboard_Close(); + USBKeyboard_Deinitialize(); + if (kbd_thread_hndl != LWP_THREAD_NULL) + LWP_JoinThread(kbd_thread_hndl, 0); + + kbd_thread_hndl = LWP_THREAD_NULL; + } -void wait_button(uint32_t button) { +uint32_t wait_button(uint32_t button) { scanpads(); while (!(pad_buttons & (button? button : ~0)) ) scanpads(); + + return pad_buttons & (button? button : ~0); } uint32_t buttons_down(uint32_t button) { diff --git a/source/pad.h b/source/pad.h index 3afa255..8964a9b 100644 --- a/source/pad.h +++ b/source/pad.h @@ -1,8 +1,8 @@ +#include #include -#include -#include void initpads(); void scanpads(); -void wait_button(u32); -u32 buttons_down(u32); +void stoppads(); +uint32_t wait_button(uint32_t); +uint32_t buttons_down(uint32_t); diff --git a/source/sd.c b/source/sd.c index a986839..0f052c7 100644 --- a/source/sd.c +++ b/source/sd.c @@ -60,15 +60,6 @@ bool SDMount(void) { usleep(2000000); } - - if (freeSpace < 0x8000) // 16MB (32K sectors) - { - printf(pBad "Error #06: Insufficient SD card space!\n" - pBad "At least 512 blocks (32MB) are required, you have %lu!", freeSpace / 0x100); - - SDUnmount(); - } - } else { printf(pBad "Mounting SD card failed! (%i)\n", fres);