This commit is contained in:
Maschell 2020-11-30 17:49:32 +01:00
parent 8dabb403ca
commit 29e8b0b8c3
9 changed files with 326 additions and 43 deletions

View File

@ -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

@ -1 +1 @@
Subproject commit f0171236eaa5093ccd17894924841bbb2fc6c1e1
Subproject commit c4c14496afc12b3f4f5ae6e9c335e379a212d1c2

View File

@ -1,12 +1,11 @@
#include "ApplicationState.h"
#include "WiiUScreen.h"
#include "ScreenUtils.h"
#include "../build/safe_rpx.h"
#include "../build/safe_payload.h"
#include <sysapp/launch.h>
#include <iosuhax.h>
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;

View File

@ -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;
};

View File

@ -14,21 +14,6 @@
#include <malloc.h>
#include <sstream>
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<appInformation> 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<appInformation> 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;
}
}

View File

@ -3,6 +3,7 @@
#include "utils/pugixml.hpp"
#include "common/common.h"
#include <optional>
#include <coreinit/memorymap.h>
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<appInformation> 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);
};

117
source/common/common.cpp Normal file
View File

@ -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},
};

View File

@ -1,6 +1,7 @@
#pragma once
#include <cstdint>
#include <coreinit/mcp.h>
#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

View File

@ -1,4 +1,3 @@
#include <coreinit/time.h>
#include <coreinit/debug.h>
#include <whb/proc.h>
@ -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();