From a9914c3e03dba73ecc2f658e3d016866fb59affc Mon Sep 17 00:00:00 2001 From: Maschell Date: Wed, 7 Sep 2022 01:08:35 +0200 Subject: [PATCH] Fix booting Shantae Half Genie Hero and Ducktales Remastered --- Makefile | 3 +- source/main.cpp | 6 +++ source/patches/patches.cpp | 34 +++++++++++++++++ source/patches/patches.h | 9 +++++ source/patches/patches_replacements.cpp | 49 +++++++++++++++++++++++++ source/patches/patches_replacements.h | 16 ++++++++ 6 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 source/patches/patches.cpp create mode 100644 source/patches/patches.h create mode 100644 source/patches/patches_replacements.cpp create mode 100644 source/patches/patches_replacements.h diff --git a/Makefile b/Makefile index 4e90fb4..0973f9d 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,8 @@ SOURCES := source \ source/applicationendshook \ source/dynload \ source/sdrefcount \ - source/symbolnamepatcher + source/symbolnamepatcher \ + source/patches DATA := data INCLUDES := source diff --git a/source/main.cpp b/source/main.cpp index 75ad3cc..29456ad 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -2,6 +2,7 @@ #include "dynload/dynload.h" #include "globals.h" #include "logger.h" +#include "patches/patches.h" #include "sdrefcount/refcount.h" #include "symbolnamepatcher/symbolname.h" #include @@ -23,6 +24,11 @@ WUMS_INITIALIZE(args) { initSDRefCount(); initSymbolNamePatcher(); initDynload(); + initCommonPatches(); deinitLogging(); } + +WUMS_APPLICATION_STARTS() { + commonPatchesStart(); +} diff --git a/source/patches/patches.cpp b/source/patches/patches.cpp new file mode 100644 index 0000000..ab63090 --- /dev/null +++ b/source/patches/patches.cpp @@ -0,0 +1,34 @@ +#include "globals.h" +#include "logger.h" +#include "patches_replacements.h" +#include + +// init is not called for this module. We need to make sure to init these values in initCommonPatches() +uint32_t gHeapMask; +uint32_t gNonHomebrewFSClientCount; + +void initCommonPatches() { + // Determine which region the memory mapping is using. We need this to count the + // number of FSClients which are stored in that region. + auto dummy = malloc(0x4); + if (!dummy) { + gHeapMask = 0x80000000; + } else { + DEBUG_FUNCTION_LINE_ERR("%08X", dummy); + gHeapMask = (uint32_t) dummy & 0xF0000000; + free(dummy); + } + gNonHomebrewFSClientCount = 0; + + DEBUG_FUNCTION_LINE("Do common patches"); + for (uint32_t i = 0; i < patches_function_replacements_size; i++) { + if (!FunctionPatcherPatchFunction(&patches_function_replacements[i], nullptr)) { + OSFatal("AromaBaseModule: Failed apply common patches"); + } + } + DEBUG_FUNCTION_LINE("Common patches finished"); +} + +void commonPatchesStart() { + gNonHomebrewFSClientCount = 0; +} \ No newline at end of file diff --git a/source/patches/patches.h b/source/patches/patches.h new file mode 100644 index 0000000..0ed1aae --- /dev/null +++ b/source/patches/patches.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +extern uint32_t gHeapMask; +extern uint32_t gNonHomebrewFSClientCount; + +void initCommonPatches(); +void commonPatchesStart(); \ No newline at end of file diff --git a/source/patches/patches_replacements.cpp b/source/patches/patches_replacements.cpp new file mode 100644 index 0000000..80f556d --- /dev/null +++ b/source/patches/patches_replacements.cpp @@ -0,0 +1,49 @@ +#include "patches_replacements.h" +#include "globals.h" +#include "logger.h" +#include "patches.h" +#include +#include + +DECL_FUNCTION(FSStatus, FSAddClient, FSClient *client, FSErrorFlag errorMask) { + auto res = real_FSAddClient(client, errorMask); + if (res == FS_STATUS_OK) { + if (((uint32_t) client & 0xF0000000) != gHeapMask) { + gNonHomebrewFSClientCount++; + } + } + return res; +} + +DECL_FUNCTION(FSStatus, FSDelClient, FSClient *client, FSErrorFlag errorMask) { + auto res = real_FSDelClient(client, errorMask); + if (res == FS_STATUS_OK) { + if (((uint32_t) client & 0xF0000000) != gHeapMask) { + gNonHomebrewFSClientCount--; + } + } + return res; +} + +DECL_FUNCTION(uint32_t, FSGetClientNum) { + auto titleID = OSGetTitleID(); + // Some games rely on the "correct" FSGetClientNum count and only init their + // FS system if FSGetClientNum returns 0. Whitelisting games for this hack seems + // better than breaking other games by accident... + if (titleID == 0x0005000010129000 || // DuckTales: Remastered USA + titleID == 0x0005000010129200 || // DuckTales: Remastered EUR + titleID == 0x00050000101DB200 || // Shantae: Half-Genie Hero USA + titleID == 0x0005000010203200 // Shantae: Half-Genie Hero EUR + ) { + DEBUG_FUNCTION_LINE("Fake FSGetClientNum num to %d instead of %d", gNonHomebrewFSClientCount, real_FSGetClientNum()); + return gNonHomebrewFSClientCount; + } + return real_FSGetClientNum(); +} +function_replacement_data_t patches_function_replacements[] = { + REPLACE_FUNCTION(FSAddClient, LIBRARY_COREINIT, FSAddClient), + REPLACE_FUNCTION(FSDelClient, LIBRARY_COREINIT, FSDelClient), + REPLACE_FUNCTION(FSGetClientNum, LIBRARY_COREINIT, FSGetClientNum), +}; + +uint32_t patches_function_replacements_size = sizeof(patches_function_replacements) / sizeof(function_replacement_data_t); \ No newline at end of file diff --git a/source/patches/patches_replacements.h b/source/patches/patches_replacements.h new file mode 100644 index 0000000..60bea2a --- /dev/null +++ b/source/patches/patches_replacements.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern function_replacement_data_t patches_function_replacements[]; + +#ifdef __cplusplus +} +#endif + +extern uint32_t patches_function_replacements_size; \ No newline at end of file