diff --git a/Makefile b/Makefile index 031c827..bd73d33 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ include $(DEVKITPRO)/wut/share/wut_rules TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := source \ + source/common \ source/utils \ source/fs DATA := data diff --git a/payload b/payload index f017123..c4c1449 160000 --- a/payload +++ b/payload @@ -1 +1 @@ -Subproject commit f0171236eaa5093ccd17894924841bbb2fc6c1e1 +Subproject commit c4c14496afc12b3f4f5ae6e9c335e379a212d1c2 diff --git a/source/ApplicationState.cpp b/source/ApplicationState.cpp index b9f195b..6c09623 100644 --- a/source/ApplicationState.cpp +++ b/source/ApplicationState.cpp @@ -1,12 +1,11 @@ #include "ApplicationState.h" #include "WiiUScreen.h" #include "ScreenUtils.h" -#include "../build/safe_rpx.h" #include "../build/safe_payload.h" #include #include -extern "C" void OSForceFullRelaunch(); +extern "C" void OSShutdown(); void ApplicationState::render() { WiiUScreen::clearScreen(); @@ -36,22 +35,36 @@ void ApplicationState::render() { } else if (this->state == STATE_CHECK_PATCH_POSSIBLE) { WiiUScreen::drawLine("Check if console can be patched."); } else if (this->state == STATE_CHECK_PATCH_POSSIBLE_DONE) { - WiiUScreen::drawLinef("Compatible title: %s", appInfo->appName); + WiiUScreen::drawLinef("Compatible title:"); + WiiUScreen::drawLinef("%s", appInfo->appName); WiiUScreen::drawLine(); - if (this->fstPatchPossible) { + + if (this->fstAlreadyPatched) { + WiiUScreen::drawLine("[ X ] title.fst is already patched!"); + } else if (this->fstPatchPossible) { WiiUScreen::drawLine("[ X ] title.fst can be patched!"); } else { WiiUScreen::drawLine("[ ] title.fst can NOT be patched!"); } - if (this->cosPatchPossible) { + if (this->cosAlreadyPatched) { + WiiUScreen::drawLine("[ X ] cos.xml is already patched!"); + } else if (this->cosPatchPossible) { WiiUScreen::drawLine("[ X ] cos.xml can be patched!"); } else { WiiUScreen::drawLine("[ ] cos.xml can NOT be patched!"); } - if (this->systemXMLPatchPossible) { - WiiUScreen::drawLine("[ X ] system.xml can be patched!"); + if (this->rpxAlreadyPatched) { + WiiUScreen::drawLine("[ X ] safe.rpx is already patched!"); } else { - WiiUScreen::drawLine("[ ] system.xml can NOT be patched!"); + WiiUScreen::drawLine("[ X ] safe.rpx can to be patched!"); + } + + WiiUScreen::drawLine(); + WiiUScreen::drawLinef("System is booting into: "); + if (this->coldbootTitle == nullptr) { + WiiUScreen::drawLinef("%ll016X (Unknown title)", this->coldbootTitleId); + } else { + WiiUScreen::drawLinef("%ll016X (%s)", this->coldbootTitle->tid, this->coldbootTitle->name); } WiiUScreen::drawLine(); @@ -82,6 +95,17 @@ void ApplicationState::render() { } else if (this->selectedOption == 2) { WiiUScreen::drawLine(" Back Coldboot > No Coldboot"); } + } else if (this->state == STATE_INSTALL_NO_COLDBOOT_ALLOWED) { + WiiUScreen::drawLine("Note: To install Aroma as coldboot you need to run this installer"); + WiiUScreen::drawLine("from an already running Aroma instance (and not the browser)"); + WiiUScreen::drawLine("After the installation has finished, reboot the console, open the"); + WiiUScreen::drawLine("Health & Safety app and run the Aroma installer."); + WiiUScreen::drawLine(); + if (this->selectedOption == 0) { + WiiUScreen::drawLine("> Back Install without Coldboot"); + } else if (this->selectedOption == 1) { + WiiUScreen::drawLine("> Back > Install without Coldboot"); + } } else if (this->state == STATE_INSTALL_CONFIRM_DIALOG) { WiiUScreen::drawLine("Are you REALLY sure you want to install Aroma?"); WiiUScreen::drawLine("Installing could permanently damage your console"); @@ -116,7 +140,7 @@ void ApplicationState::render() { } else if (this->state == STATE_INSTALL_SUCCESS) { WiiUScreen::drawLine("Aroma was successfully installed"); WiiUScreen::drawLine(); - WiiUScreen::drawLine("Press A to reboot the console"); + WiiUScreen::drawLine("Press A to shutdown the console"); } printFooter(); WiiUScreen::flipBuffers(); @@ -166,6 +190,13 @@ void ApplicationState::update(Input *input) { } } } else if (this->state == STATE_INSTALL_CHOOSE_COLDBOOT) { + + if (!InstallerService::isColdBootAllowed()) { + this->installColdboot = false; + this->state = STATE_INSTALL_NO_COLDBOOT_ALLOWED; + return; + } + proccessMenuNavigation(input, 3); if (entrySelected(input)) { if (this->selectedOption == 0) { // Back @@ -179,6 +210,16 @@ void ApplicationState::update(Input *input) { this->selectedOption = 0; return; } + } else if (this->state == STATE_INSTALL_NO_COLDBOOT_ALLOWED) { + proccessMenuNavigation(input, 2); + if (entrySelected(input)) { + if (this->selectedOption == 0) { + this->state = STATE_CHECK_PATCH_POSSIBLE_DONE; + } else { + this->state = STATE_INSTALL_CONFIRM_DIALOG; + } + this->selectedOption = 0; + } } else if (this->state == STATE_INSTALL_CONFIRM_DIALOG) { proccessMenuNavigation(input, 2); if (entrySelected(input)) { @@ -232,6 +273,9 @@ void ApplicationState::update(Input *input) { if (IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_mlc01") == 0) { DEBUG_FUNCTION_LINE("Flushed mlc"); } + if (IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/system") == 0) { + DEBUG_FUNCTION_LINE("Flushed slc"); + } IOSUHAX_FSA_Close(fsaFd); } else { DEBUG_FUNCTION_LINE("Failed to open fsa"); @@ -240,8 +284,7 @@ void ApplicationState::update(Input *input) { } } else if (this->state == STATE_INSTALL_SUCCESS) { if (entrySelected(input)) { - OSForceFullRelaunch(); - SYSLaunchMenu(); + OSShutdown(); } } } @@ -260,8 +303,26 @@ void ApplicationState::checkPatchPossible() { DEBUG_FUNCTION_LINE("ERROR"); return; } + + this->coldbootTitleId = InstallerService::getColdbootTitleId("storage_slc_installer:/config"); + + this->coldbootTitle = nullptr; + for (int i = 0; GameList[i].tid != 0; i++) { + if (GameList[i].tid == this->coldbootTitleId) { + this->coldbootTitle = &GameList[i]; + break; + } + } + DEBUG_FUNCTION_LINE("CHECK FST"); + InstallerService::eResults result; + + this->fstAlreadyPatched = ((result = InstallerService::checkFSTAlreadyValid(this->appInfo->path, this->appInfo->fstHash)) == InstallerService::SUCCESS); + this->rpxAlreadyPatched = ((result = InstallerService::checkRPXAlreadyValid(this->appInfo->path, RPX_HASH)) == InstallerService::SUCCESS); + this->cosAlreadyPatched = ((result = InstallerService::checkCOSAlreadyValid(this->appInfo->path, this->appInfo->cosHash)) == InstallerService::SUCCESS); + this->tmdValid = ((result = InstallerService::checkTMDValid(this->appInfo->path, this->appInfo->tmdHash)) == InstallerService::SUCCESS); + this->fstPatchPossible = ((result = InstallerService::checkFST(this->appInfo->path, this->appInfo->fstHash)) == InstallerService::SUCCESS); if (result != InstallerService::SUCCESS) { DEBUG_FUNCTION_LINE("ERROR: %s", InstallerService::ErrorMessage(result).c_str()); @@ -281,7 +342,6 @@ void ApplicationState::checkPatchPossible() { void ApplicationState::getAppInformation() { DEBUG_FUNCTION_LINE("About to call getInstalledAppInformation"); this->appInfo = InstallerService::getInstalledAppInformation(); - DEBUG_FUNCTION_LINE("back"); if (!this->appInfo) { DEBUG_FUNCTION_LINE("ERROR =("); this->state = STATE_ERROR; diff --git a/source/ApplicationState.h b/source/ApplicationState.h index 9014a0d..2e6aa08 100644 --- a/source/ApplicationState.h +++ b/source/ApplicationState.h @@ -23,6 +23,7 @@ public: STATE_CHECK_PATCH_POSSIBLE, STATE_CHECK_PATCH_POSSIBLE_DONE, STATE_INSTALL_CHOOSE_COLDBOOT, + STATE_INSTALL_NO_COLDBOOT_ALLOWED, STATE_INSTALL_CONFIRM_DIALOG, STATE_INSTALL_STARTED, STATE_INSTALL_FST, @@ -70,4 +71,10 @@ private: eGameState state; eErrorState error = ERROR_NONE; + uint64_t coldbootTitleId; + _gList_t *coldbootTitle; + bool fstAlreadyPatched; + bool rpxAlreadyPatched; + bool cosAlreadyPatched; + bool tmdValid; }; diff --git a/source/InstallerService.cpp b/source/InstallerService.cpp index 29ee61c..c373c0e 100644 --- a/source/InstallerService.cpp +++ b/source/InstallerService.cpp @@ -14,21 +14,6 @@ #include #include -systemXMLInformation systemXMLHashInformation[] = { - {WII_U_MENU_JAP, 0x0005001010040000L, "2645065A42D18D390C78543E3C4FE7E1D1957A63", "5E5C707E6DAF82393E93971BE98BE3B12204932A"}, - {WII_U_MENU_USA, 0x0005001010040100L, "124562D41A02C7112DDD5F9A8F0EE5DF97E23471", "DC0F9941E99C629625419F444B5A5B177A67309F"}, - {WII_U_MENU_EUR, 0x0005001010040200L, "F06041A4E5B3F899E748F1BAEB524DE058809F1D", "A0273C466DE15F33EC161BCD908B5BFE359FE6E0"}, - {HEALTH_SAFETY_JAP, 0x000500101004E000L, "066D672824128713F0A7D156142A68B998080148", "2849DE91560F6667FE7415F89FC916BE3A27DE75"}, - {HEALTH_SAFETY_USA, 0x000500101004E100L, "0EBCA1DFC0AB7A6A7FE8FB5EAF23179621B726A1", "83CF5B1CE0B64C51D15B1EFCAD659063790EB590"}, - {HEALTH_SAFETY_EUR, 0x000500101004E200L, "DE46EC3E9B823ABA6CB0638D0C4CDEEF9C793BDD", "ED59630448EC6946F3E51618DA3681EC3A84D391"} -}; - -appInformation supportedApps[] = { - {0x000500101004E000L, "Health and Safety Information [JPN]", false, {'\0'}, "9D34DDD91604D781FDB0727AC75021833304964C", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03"}, - {0x000500101004E100L, "Health and Safety Information [USA]", false, {'\0'}, "045734666A36C7EF0258A740855886EBDB20D59B", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03"}, - {0x000500101004E200L, "Health and Safety Information [EUR]", false, {'\0'}, "130A76F8B36B36D43B88BBC74393D9AFD9CFD2A4", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03"}, -}; - InstallerService::eResults InstallerService::checkCOS(const std::string &path, char *hash) { std::string cosFilePath = path + "/code/cos.xml"; DEBUG_FUNCTION_LINE("Loading %s", cosFilePath.c_str()); @@ -61,8 +46,7 @@ InstallerService::eResults InstallerService::checkSystemXML(const std::string &p std::string inputFile = std::string(path + "/system.xml"); systemXMLInformation *data = nullptr; - int arrayLength = (sizeof(systemXMLHashInformation) / sizeof(*systemXMLHashInformation)); - for (int i = 0; i < arrayLength; i++) { + for (int i = 0; systemXMLHashInformation[i].titleId != 0; i++) { if (systemXMLHashInformation[i].titleId == titleId) { data = &systemXMLHashInformation[i]; break; @@ -76,7 +60,6 @@ InstallerService::eResults InstallerService::checkSystemXML(const std::string &p DEBUG_FUNCTION_LINE("Setting coldboot to %016llX", data->titleId); - pugi::xml_document doc; pugi::xml_parse_result resultSystem = doc.load_file(inputFile.c_str()); @@ -89,13 +72,22 @@ InstallerService::eResults InstallerService::checkSystemXML(const std::string &p snprintf(tmp, 17, "%016llX", data->titleId); doc.child("system").child("default_title_id").first_child().set_value(tmp); + if (!doc.child("system").child("log").attribute("length")) { + doc.child("system").child("log").append_attribute("length") = "0"; + } + if (!doc.child("system").child("standby").attribute("length")) { + doc.child("system").child("standby").append_attribute("length") = "0"; + } + if (!doc.child("system").child("ramdisk").attribute("length")) { + doc.child("system").child("ramdisk").append_attribute("length") = "0"; + } std::stringstream ss; doc.save(ss, " ", pugi::format_default, pugi::encoding_utf8); std::string newHash = Utils::calculateSHA1(ss.str().c_str(), ss.str().size()); - if (std::string(data->hash) == newHash) { + if (std::string(data->hash) == newHash || std::string(data->hash2) == newHash) { DEBUG_FUNCTION_LINE("Success! system.xml is compatible"); return SUCCESS; } else { @@ -163,9 +155,8 @@ std::optional InstallerService::getInstalledAppInformation() { DEBUG_FUNCTION_LINE("%d titles found on the WiiU", titleCount); bool success = false; - int arrayLength = (sizeof(supportedApps) / sizeof(*supportedApps)); for (uint32_t i = 0; i < titleCount; ++i) { - for (int j = 0; j < arrayLength; ++j) { + for (int j = 0; supportedApps[j].titleId != 0; j++) { if (titleList[i].titleId == supportedApps[j].titleId) { DEBUG_FUNCTION_LINE("%s is on the Wii U (%s) %d", supportedApps[j].appName, titleList[i].path, sizeof(supportedApps[j].path)); supportedApps[j].onTheWiiU = true; @@ -175,11 +166,12 @@ std::optional InstallerService::getInstalledAppInformation() { } } } + free(titleList); if (success) { success = false; - for (int j = 0; j < arrayLength; ++j) { + for (int j = 0; supportedApps[j].titleId != 0; j++) { if (supportedApps[j].onTheWiiU) { std::string path(supportedApps[j].path); if (!StringTools::replace(path, "/vol/storage_mlc01", "storage_mlc_installer:")) { @@ -440,7 +432,6 @@ InstallerService::eResults InstallerService::patchCOS(const std::string &path, c return COS_XML_HASH_MISMATCH; } - InstallerService::eResults InstallerService::copyRPX(const std::string &path, const uint8_t *rpx_data, size_t size, const std::string &rpx_hash) { std::string rpxSourceFilePath = path + "/code/safe.rpx"; std::string rpxBackupFilePath = path + "/code/sbac.rpx"; @@ -508,8 +499,7 @@ InstallerService::eResults InstallerService::patchSystemXML(const std::string &p } systemXMLInformation *data = nullptr; - int arrayLength = (sizeof(systemXMLHashInformation) / sizeof(*systemXMLHashInformation)); - for (int i = 0; i < arrayLength; i++) { + for (int i = 0; systemXMLHashInformation[i].titleId != 0; i++) { if (systemXMLHashInformation[i].titleId == titleId) { data = &systemXMLHashInformation[i]; break; @@ -534,6 +524,15 @@ InstallerService::eResults InstallerService::patchSystemXML(const std::string &p snprintf(tmp, 17, "%016llX", data->titleId); doc.child("system").child("default_title_id").first_child().set_value(tmp); + if (!doc.child("system").child("log").attribute("length")) { + doc.child("system").child("log").append_attribute("length") = "0"; + } + if (!doc.child("system").child("standby").attribute("length")) { + doc.child("system").child("standby").append_attribute("length") = "0"; + } + if (!doc.child("system").child("ramdisk").attribute("length")) { + doc.child("system").child("ramdisk").append_attribute("length") = "0"; + } doc.save_file(finalFile.c_str(), " ", pugi::format_default, pugi::encoding_utf8); std::string newHash = Utils::hashFile(finalFile); @@ -559,3 +558,63 @@ InstallerService::eResults InstallerService::patchSystemXML(const std::string &p return SYSTEM_XML_HASH_MISMATCH; } + +uint64_t InstallerService::getColdbootTitleId(const std::string &path) { + std::string inputFile = std::string(path + "/system.xml"); + + pugi::xml_document doc; + pugi::xml_parse_result resultSystem = doc.load_file(inputFile.c_str()); + + if (!resultSystem) { + DEBUG_FUNCTION_LINE("Error while parsing %s: %s", inputFile.c_str(), resultSystem.description()); + return SYSTEM_XML_PARSING_FAILED; + } + + DEBUG_FUNCTION_LINE("%s", doc.child("system").child("default_title_id").first_child().value()); + + uint64_t result = strtoull(doc.child("system").child("default_title_id").first_child().value(), nullptr, 16); + + return result; +} + +InstallerService::eResults InstallerService::checkFSTAlreadyValid(const std::string &path, const std::string &hash) { + std::string filePath = path + "/code/title.fst"; + return checkFileHash(filePath, hash); +} + +InstallerService::eResults InstallerService::checkTMDValid(const std::string &path, const std::string &hash) { + std::string filePath = path + "/code/title.fst"; + return checkFileHash(filePath, hash); +} + +InstallerService::eResults InstallerService::checkCOSAlreadyValid(const std::string &path, const std::string &hash) { + std::string filePath = path + "/code/cos.xml"; + return checkFileHash(filePath, hash); +} + +InstallerService::eResults InstallerService::checkRPXAlreadyValid(const std::string &path, const std::string &hash) { + std::string filePath = path + "/code/safe.rpx"; + return checkFileHash(filePath, hash); +} + +InstallerService::eResults InstallerService::checkFileHash(const std::string &filePath, const std::string &hash) { + uint8_t *fileData = nullptr; + uint32_t fileDataSize = 0; + + if (FSUtils::LoadFileToMem(filePath.c_str(), &fileData, &fileDataSize) < 0) { + return FAILED_TO_LOAD_FILE; + } + + std::string newHash = Utils::calculateSHA1((const char *) fileData, fileDataSize); + + free(fileData); + fileData = nullptr; + + if (StringTools::strCompareIC(hash, newHash)) { + return SUCCESS; + } else { + DEBUG_FUNCTION_LINE("expected %s actual %s", hash.c_str(), newHash.c_str()); + return FST_HASH_MISMATCH; + } +} + diff --git a/source/InstallerService.h b/source/InstallerService.h index 1218d05..8548fc7 100644 --- a/source/InstallerService.h +++ b/source/InstallerService.h @@ -3,6 +3,7 @@ #include "utils/pugixml.hpp" #include "common/common.h" #include +#include class InstallerService { public: @@ -28,6 +29,20 @@ public: FAILED_TO_LOAD_FILE = -18, }; + static bool isColdBootAllowed(){ + if (OSIsAddressValid(0x00FFFFF8)) { + uint64_t bootedFrom = *((uint64_t *) 0x00FFFFF8); + if ( + bootedFrom == 0x000500101004E000L || // H&S JAP + bootedFrom == 0x000500101004E100L || // H&S USA + bootedFrom == 0x000500101004E200L // H&S EUR + ) { + return true; + } + } + return false; + } + static eResults patchCOS(const std::string &path, char *hash); static eResults checkCOS(const std::string &path, char *hash); @@ -39,17 +54,29 @@ public: static std::optional getInstalledAppInformation(); static std::string ErrorMessage(eResults error); + static std::string ErrorDescription(eResults error); static eResults patchFST(const std::string &path, const char *hash); static eResults copyRPX(const std::string &path, const uint8_t *rpx_data, size_t size, const std::string &rpx_hash); - static eResults patchSystemXML(const std::string &path, uint64_t id); + static uint64_t getColdbootTitleId(const std::string &path); + + static eResults checkFSTAlreadyValid(const std::string &path, const std::string &hash); + + static eResults checkTMDValid(const std::string &path, const std::string &hash); + + static eResults checkCOSAlreadyValid(const std::string &path, const std::string &hash); + + static eResults checkRPXAlreadyValid(const std::string &path, const std::string &hash); + private: static eResults patchFSTData(uint8_t *fstData, uint32_t size); static bool patchCOSXMLData(pugi::xml_document *doc); + + static eResults checkFileHash(const std::string &filePath, const std::string &hash); }; \ No newline at end of file diff --git a/source/common/common.cpp b/source/common/common.cpp new file mode 100644 index 0000000..3baa01c --- /dev/null +++ b/source/common/common.cpp @@ -0,0 +1,117 @@ +#include "common.h" + +systemXMLInformation systemXMLHashInformation[] = { + {WII_U_MENU_JAP, 0x0005001010040000L, "2645065A42D18D390C78543E3C4FE7E1D1957A63", "5E5C707E6DAF82393E93971BE98BE3B12204932A"}, + {WII_U_MENU_USA, 0x0005001010040100L, "124562D41A02C7112DDD5F9A8F0EE5DF97E23471", "DC0F9941E99C629625419F444B5A5B177A67309F"}, + {WII_U_MENU_EUR, 0x0005001010040200L, "F06041A4E5B3F899E748F1BAEB524DE058809F1D", "A0273C466DE15F33EC161BCD908B5BFE359FE6E0"}, + {HEALTH_SAFETY_JPN, 0x000500101004E000L, "066D672824128713F0A7D156142A68B998080148", "2849DE91560F6667FE7415F89FC916BE3A27DE75"}, + {HEALTH_SAFETY_USA, 0x000500101004E100L, "0EBCA1DFC0AB7A6A7FE8FB5EAF23179621B726A1", "83CF5B1CE0B64C51D15B1EFCAD659063790EB590"}, + {HEALTH_SAFETY_EUR, 0x000500101004E200L, "DE46EC3E9B823ABA6CB0638D0C4CDEEF9C793BDD", "ED59630448EC6946F3E51618DA3681EC3A84D391"}, + {MAX_SYSTEM_XML_DEFAULT_TITLE_ID, 0, {'\0'}, {'\0'}}, +}; + +appInformation supportedApps[] = { + {0x000500101004E000L, "Health and Safety Information [JPN]", false, {'\0'}, "9D34DDD91604D781FDB0727AC75021833304964C", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03", "2CF358E1F51932D305911A6836ED37DB0F94ABE4"}, + {0x000500101004E100L, "Health and Safety Information [USA]", false, {'\0'}, "045734666A36C7EF0258A740855886EBDB20D59B", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03", "C53C219FB8F777F9AB8F430D6BE4BC034D5638BA"}, + {0x000500101004E200L, "Health and Safety Information [PAL]", false, {'\0'}, "130A76F8B36B36D43B88BBC74393D9AFD9CFD2A4", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03", "4A29A60E5FBDAF410B7C22ECAEBDDBF29D1A874E"}, + {0, nullptr, false, {'\0'}, {'\0'}, {'\0'}}, +}; + +gList_t GameList[] = { + {0x0005001010040000L, "Wii U Menu [JPN]", MCP_REGION_JAPAN}, + {0x0005001010040100L, "Wii U Menu [USA]", MCP_REGION_USA}, + {0x0005001010040200L, "Wii U Menu [PAL]", MCP_REGION_EUROPE}, + + {0x000500101004E000L, "Health and Safety Information [JPN]", MCP_REGION_JAPAN}, + {0x000500101004E100L, "Health and Safety Information [USA]", MCP_REGION_USA}, + {0x000500101004E200L, "Health and Safety Information [PAL]", MCP_REGION_EUROPE}, + + {0x0005000010179A00L, "Kawashima: Motto Nou wo Kitaeru Otona no DS Training [JPN]", MCP_REGION_JAPAN}, + {0x0005000010179B00L, "Brain Age: Train Your Brain in Minutes a Day! [USA]", MCP_REGION_USA}, + {0x0005000010179C00L, "Dr. Kawashima's Brain Training [PAL]", MCP_REGION_EUROPE}, + + {0x0005000010179D00L, "Catch! Touch! Yoshi! [JPN]", MCP_REGION_JAPAN}, + {0x0005000010179E00L, "Yoshi Touch & Go [USA]", MCP_REGION_USA}, + {0x0005000010179F00L, "Yoshi Touch & Go [PAL]", MCP_REGION_EUROPE}, + + {0x0005000010195600L, "Mario Kart DS [JPN]", MCP_REGION_JAPAN}, + {0x0005000010195700L, "Mario Kart DS [USA]", MCP_REGION_USA}, + {0x0005000010195800L, "Mario Kart DS [PAL]", MCP_REGION_EUROPE}, + + {0x0005000010195900L, "New Super Mario Bros. [JPN]", MCP_REGION_JAPAN}, + {0x0005000010195A00L, "New Super Mario Bros. [USA]", MCP_REGION_USA}, + {0x0005000010195B00L, "New Super Mario Bros. [PAL]", MCP_REGION_EUROPE}, + + {0x0005000010198800L, "Yoshi's Island DS [JPN]", MCP_REGION_JAPAN}, + {0x0005000010198900L, "Yoshi's Island DS [USA]", MCP_REGION_USA}, + {0x0005000010198A00L, "Yoshi's Island DS [PAL]", MCP_REGION_EUROPE}, + + {0x0005000010198B00L, "Yawaraka Atama Juku [JPN]", MCP_REGION_JAPAN}, + {0x0005000010198C00L, "Big Brain Academy [USA]", MCP_REGION_USA}, + {0x0005000010198D00L, "Big Brain Academy [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101A1E00L, "Sawaru: Made in Wario [JPN]", MCP_REGION_JAPAN}, + {0x00050000101A1F00L, "WarioWare: Touched! [USA]", MCP_REGION_USA}, + {0x00050000101A2000L, "WarioWare: Touched! [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101A2100L, "Mario & Luigi RPG 2x2 [JPN]", MCP_REGION_JAPAN}, + {0x00050000101A2200L, "Mario & Luigi: Partners in Time [USA]", MCP_REGION_USA}, + {0x00050000101A2300L, "Mario & Luigi: Partners in Time [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101A5200L, "Donkey Kong: Jungle Climber [JPN]", MCP_REGION_JAPAN}, + {0x00050000101A5300L, "DK: Jungle Climber [USA]", MCP_REGION_USA}, + {0x00050000101A5400L, "Donkey Kong: Jungle Climber [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101A5500L, "Hoshi no Kirby: Sanjou! Dorocche Dan [JPN]", MCP_REGION_JAPAN}, + {0x00050000101A5600L, "Kirby: Squeak Squad [USA]", MCP_REGION_USA}, + {0x00050000101A5700L, "Kirby: Mouse Attack [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101ABD00L, "Kaitou Wario the Seven [JPN]", MCP_REGION_JAPAN}, + {0x00050000101ABE00L, "Wario: Master of Disguise [USA]", MCP_REGION_USA}, + {0x00050000101ABF00L, "Wario: Master of Disguise [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101AC000L, "Star Fox Command [JPN]", MCP_REGION_JAPAN}, + {0x00050000101AC100L, "Star Fox Command [USA]", MCP_REGION_USA}, + {0x00050000101AC200L, "Star Fox Command [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101B8800L, "Touch! Kirby's Magic Paintbrush [JPN]", MCP_REGION_JAPAN}, + {0x00050000101B8900L, "Kirby: Canvas Curse [USA]", MCP_REGION_USA}, + {0x00050000101B8A00L, "Kirby: Power Paintbrush [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101B8B00L, "Zelda no Densetsu: Daichi no Kiteki [JPN]", MCP_REGION_JAPAN}, + {0x00050000101B8C00L, "The Legend of Zelda: Spirit Tracks [USA]", MCP_REGION_USA}, + {0x00050000101B8D00L, "The Legend of Zelda: Spirit Tracks [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101C3300L, "Super Mario 64 DS [JPN]", MCP_REGION_JAPAN}, + {0x00050000101C3400L, "Super Mario 64 DS [USA]", MCP_REGION_USA}, + {0x00050000101C3500L, "Super Mario 64 DS [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101C3600L, "Zelda no Densetsu: Mugen no Sunadokei [JPN]", MCP_REGION_JAPAN}, + {0x00050000101C3700L, "The Legend of Zelda: Phantom Hourglass [USA]", MCP_REGION_USA}, + {0x00050000101C3800L, "The Legend of Zelda: Phantom Hourglass [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101C8600L, "Atsumete! Kirby [JPN]", MCP_REGION_JAPAN}, + {0x00050000101C8700L, "Kirby Mass Attack [USA]", MCP_REGION_USA}, + {0x00050000101C8800L, "Kirby Mass Attack [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101CC200L, "Pokemon Ranger [JPN]", MCP_REGION_JAPAN}, + {0x00050000101CC300L, "Pokemon Ranger [USA]", MCP_REGION_USA}, + {0x00050000101CC400L, "Pokemon Ranger [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101D1F00L, "Oideyo Doubutsu no Mori [JPN]", MCP_REGION_JAPAN}, + {0x00050000101D2000L, "Animal Crossing: Wild World [USA]", MCP_REGION_USA}, + {0x00050000101D2100L, "Animal Crossing: Wild World [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101E0C00L, "Pokemon Fushigi no Dungeon: Sora no Tankentai [JPN]", MCP_REGION_JAPAN}, + {0x00050000101E0D00L, "Pokemon Mystery Dungeon: Explorers of Sky [USA]", MCP_REGION_USA}, + {0x00050000101E0E00L, "Pokemon Mystery Dungeon: Explorers of Sky [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101E0F00L, "Pokemon Ranger: Batonnage [JPN]", MCP_REGION_JAPAN}, + {0x00050000101E1000L, "Pokemon Ranger: Shadows of Almia [USA]", MCP_REGION_USA}, + {0x00050000101E1100L, "Pokemon Ranger: Shadows of Almia [PAL]", MCP_REGION_EUROPE}, + + {0x00050000101E6F00L, "Pokemon Ranger: Hikari no Kiseki [JPN]", MCP_REGION_JAPAN}, + {0x00050000101E7000L, "Pokemon Ranger: Guardian Signs [USA]", MCP_REGION_USA}, + {0x00050000101E7100L, "Pokemon Ranger: Guardian Signs [PAL]", MCP_REGION_EUROPE}, + {0, "", MCP_REGION_JAPAN}, +}; diff --git a/source/common/common.h b/source/common/common.h index 815919f..9a18234 100644 --- a/source/common/common.h +++ b/source/common/common.h @@ -1,6 +1,7 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { @@ -14,7 +15,8 @@ enum SYSTEM_XML_DEFAULT_TITLE_ID { WII_U_MENU_JAP, HEALTH_SAFETY_EUR, HEALTH_SAFETY_USA, - HEALTH_SAFETY_JAP + HEALTH_SAFETY_JPN, + MAX_SYSTEM_XML_DEFAULT_TITLE_ID }; typedef struct systemXMLInformation { @@ -31,8 +33,19 @@ typedef struct compatApps { char path[255]; char fstHash[41]; char cosHash[41]; + char tmdHash[41]; } appInformation; +typedef struct _gList_t { + uint64_t tid; + char name[64]; + MCPRegion region; +} gList_t; + +extern systemXMLInformation systemXMLHashInformation[]; +extern appInformation supportedApps[]; +extern _gList_t GameList[]; + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index 5cbc4c9..a79fd7b 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -12,15 +11,15 @@ #include "WiiUScreen.h" #include "InstallerService.h" -#include "../build/safe_payload.h" #include "ApplicationState.h" #include "VPADInput.h" +#include "../build/safe_payload.h" constexpr bool strings_equal(char const *a, char const *b) { return std::string_view(a) == b; } -static_assert(strings_equal(RPX_HASH, "2df9282cadcbe3fa86848ade9c67cbff12b72426"), "Built with an untested safe.rpx! Remove this check if you really know what you're doing."); +static_assert(strings_equal(RPX_HASH, "116cff322148216f38b1eaaf296d1cffc6a3a98f"), "Built with an untested root.rpx! Remove this check if you really know what you're doing."); void initIOSUHax();