diff --git a/arm9/source/Arm9Patcher.cpp b/arm9/source/Arm9Patcher.cpp index 1d679af..9e0442b 100644 --- a/arm9/source/Arm9Patcher.cpp +++ b/arm9/source/Arm9Patcher.cpp @@ -57,83 +57,88 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis u32 compressedEnd = 0; std::unique_ptr arm9Autoload; std::unique_ptr arm9iAutoload; - auto moduleParams = ModuleParamsLocator().FindModuleParams(romHeader); - SdkVersion sdkVersion = moduleParams ? moduleParams->sdkVersion : 0u; - if (moduleParams) + module_params_ntr_t* moduleParams = nullptr; + SdkVersion sdkVersion = 0u; + if (romHeader->gameCode == GAMECODE("AS2E")) { - LOG_DEBUG("Module params found at 0x%p\n", moduleParams); - LOG_DEBUG("Sdk version: 0x%x\n", moduleParams->sdkVersion); - const u32* miiUncompressBackward = nullptr; - if (moduleParams->compressedEnd) - { - miiUncompressBackward = FindMIiUncompressBackward(romHeader->arm9LoadAddress, sdkVersion); - if (miiUncompressBackward) - { - arm9Size = moduleParams->compressedEnd + *(u32*)(moduleParams->compressedEnd - 4) - romHeader->arm9LoadAddress; - ((uncompress_func_t)miiUncompressBackward)((void*)moduleParams->compressedEnd); - compressedEnd = moduleParams->compressedEnd; - moduleParams->compressedEnd = 0; - } - else - { - LOG_DEBUG("MIi_UncompressBackward not found\n"); - } - } - - if (sdkVersion.IsTwlSdk()) - { - arm9Autoload = std::make_unique>( - (autoload_list_entry_sdk5_t*)moduleParams->autoloadListStart, - (autoload_list_entry_sdk5_t*)moduleParams->autoloadListEnd, - moduleParams->autoloadStart); - } - else - { - arm9Autoload = std::make_unique>( - (autoload_list_entry_t*)moduleParams->autoloadListStart, - (autoload_list_entry_t*)moduleParams->autoloadListEnd, - moduleParams->autoloadStart); - } - - if (gIsDsiMode && romHeader->SupportsDsiMode()) - { - auto arm9iModuleParams = (module_params_twl_t*)(romHeader->arm9LoadAddress + twlRomHeader->arm9iModuleParamsAddress); - if (arm9iModuleParams->magicBigEndian == MODULE_PARAMS_TWL_MAGIC_BE && - arm9iModuleParams->magicLittleEndian == MODULE_PARAMS_TWL_MAGIC_LE) - { - if (arm9iModuleParams->compressedEnd != 0) - { - LOG_DEBUG("Compressed arm9i found\n"); - if (miiUncompressBackward) - { - arm9iSize = arm9iModuleParams->compressedEnd + *(u32*)(arm9iModuleParams->compressedEnd - 4) - twlRomHeader->arm9iLoadAddress; - ((uncompress_func_t)miiUncompressBackward)((void*)arm9iModuleParams->compressedEnd); - arm9iModuleParams->compressedEnd = 0; - LOG_DEBUG("Decompressed arm9i\n"); - } - else - { - LOG_DEBUG("Could not decompress arm9i\n"); - } - } - arm9iAutoload = std::make_unique>( - (autoload_list_entry_sdk5_t*)arm9iModuleParams->autoloadListStart, - (autoload_list_entry_sdk5_t*)arm9iModuleParams->autoloadListEnd, - arm9iModuleParams->autoloadStart); - } - } + // Spider-Man 2 (USA) is probably the only game without module params + sdkVersion = 0x02004F50; + arm9Autoload = std::make_unique>( + (autoload_list_entry_t*)0x0215DBA0, + (autoload_list_entry_t*)0x0215DBB8, + 0x02157CC0); } else { - LOG_DEBUG("Module params not found!\n"); - if (romHeader->gameCode == GAMECODE("AS2E")) + moduleParams = ModuleParamsLocator().FindModuleParams(romHeader); + if (moduleParams) { - // Spider-Man 2 (USA) is probably the only game without module params - sdkVersion = 0x02004F50; - arm9Autoload = std::make_unique>( - (autoload_list_entry_t*)0x0215DBA0, - (autoload_list_entry_t*)0x0215DBB8, - 0x02157CC0); + LOG_DEBUG("Module params found at 0x%p\n", moduleParams); + sdkVersion = moduleParams->sdkVersion; + LOG_DEBUG("Sdk version: 0x%x\n", sdkVersion); + const u32* miiUncompressBackward = nullptr; + if (moduleParams->compressedEnd) + { + miiUncompressBackward = FindMIiUncompressBackward(romHeader->arm9LoadAddress, sdkVersion); + if (miiUncompressBackward) + { + arm9Size = moduleParams->compressedEnd + *(u32*)(moduleParams->compressedEnd - 4) - romHeader->arm9LoadAddress; + ((uncompress_func_t)miiUncompressBackward)((void*)moduleParams->compressedEnd); + compressedEnd = moduleParams->compressedEnd; + moduleParams->compressedEnd = 0; + } + else + { + LOG_ERROR("MIi_UncompressBackward not found\n"); + } + } + + if (sdkVersion.IsTwlSdk()) + { + arm9Autoload = std::make_unique>( + (autoload_list_entry_sdk5_t*)moduleParams->autoloadListStart, + (autoload_list_entry_sdk5_t*)moduleParams->autoloadListEnd, + moduleParams->autoloadStart); + } + else + { + arm9Autoload = std::make_unique>( + (autoload_list_entry_t*)moduleParams->autoloadListStart, + (autoload_list_entry_t*)moduleParams->autoloadListEnd, + moduleParams->autoloadStart); + } + + if (gIsDsiMode && romHeader->SupportsDsiMode()) + { + auto arm9iModuleParams = (module_params_twl_t*)(romHeader->arm9LoadAddress + twlRomHeader->arm9iModuleParamsAddress); + if (arm9iModuleParams->magicBigEndian == MODULE_PARAMS_TWL_MAGIC_BE && + arm9iModuleParams->magicLittleEndian == MODULE_PARAMS_TWL_MAGIC_LE) + { + if (arm9iModuleParams->compressedEnd != 0) + { + LOG_DEBUG("Compressed arm9i found\n"); + if (miiUncompressBackward) + { + arm9iSize = arm9iModuleParams->compressedEnd + *(u32*)(arm9iModuleParams->compressedEnd - 4) - twlRomHeader->arm9iLoadAddress; + ((uncompress_func_t)miiUncompressBackward)((void*)arm9iModuleParams->compressedEnd); + arm9iModuleParams->compressedEnd = 0; + LOG_DEBUG("Decompressed arm9i\n"); + } + else + { + LOG_ERROR("Could not decompress arm9i\n"); + } + } + arm9iAutoload = std::make_unique>( + (autoload_list_entry_sdk5_t*)arm9iModuleParams->autoloadListStart, + (autoload_list_entry_sdk5_t*)arm9iModuleParams->autoloadListEnd, + arm9iModuleParams->autoloadStart); + } + } + } + else + { + LOG_ERROR("Module params not found!\n"); } } LOG_DEBUG("Arm9 region: 0x%x - 0x%x\n", romHeader->arm9LoadAddress, romHeader->arm9LoadAddress + arm9Size); diff --git a/arm9/source/ModuleParamsLocator.cpp b/arm9/source/ModuleParamsLocator.cpp index 768b39f..e895213 100644 --- a/arm9/source/ModuleParamsLocator.cpp +++ b/arm9/source/ModuleParamsLocator.cpp @@ -1,19 +1,26 @@ #include "common.h" #include "ModuleParamsLocator.h" -module_params_ntr_t* ModuleParamsLocator::FindModuleParams(const nds_header_ntr_t* romHeader) +static bool isValidArm9Address(const nds_header_ntr_t* romHeader, const void* address) +{ + return romHeader->arm9LoadAddress <= (u32)address && (u32)address < romHeader->arm9LoadAddress + romHeader->arm9Size; +} + +module_params_ntr_t* ModuleParamsLocator::FindModuleParams(const nds_header_ntr_t* romHeader) const { //todo: static footer module_params_ntr_t* moduleParams = nullptr; if (romHeader->arm9ModuleParamsAddress != 0) { moduleParams = (module_params_ntr_t*)(romHeader->arm9LoadAddress + romHeader->arm9ModuleParamsAddress); - if (moduleParams->magicBigEndian != MODULE_PARAMS_NTR_MAGIC_BE || + if (!isValidArm9Address(romHeader, &moduleParams->magicLittleEndian) || + moduleParams->magicBigEndian != MODULE_PARAMS_NTR_MAGIC_BE || moduleParams->magicLittleEndian != MODULE_PARAMS_NTR_MAGIC_LE) { // try again by subtracting arm9 rom address moduleParams = (module_params_ntr_t*)((u8*)moduleParams - romHeader->arm9RomOffset); - if (moduleParams->magicBigEndian != MODULE_PARAMS_NTR_MAGIC_BE || + if (!isValidArm9Address(romHeader, &moduleParams->magicLittleEndian) || + moduleParams->magicBigEndian != MODULE_PARAMS_NTR_MAGIC_BE || moduleParams->magicLittleEndian != MODULE_PARAMS_NTR_MAGIC_LE) { LOG_DEBUG("Module params not found at header specified offset 0x%x\n", romHeader->arm9ModuleParamsAddress); @@ -29,21 +36,6 @@ module_params_ntr_t* ModuleParamsLocator::FindModuleParams(const nds_header_ntr_ if (!moduleParams) { // try searching for the module params as not all roms have the address in the header - // it should be within the first 0x1000 bytes of the arm9 - for (u32 i = 0; i < 0x1000; i += 4) - { - u32* ptr = (u32*)(romHeader->arm9LoadAddress + i); - if (ptr[0] == MODULE_PARAMS_NTR_MAGIC_BE && ptr[1] == MODULE_PARAMS_NTR_MAGIC_LE) - { - moduleParams = (module_params_ntr_t*)((u8*)ptr + 8 - sizeof(module_params_ntr_t)); - break; - } - } - } - - if (!moduleParams) - { - // as a last resort, scan the entire arm9 binary for (u32 i = 0; i < romHeader->arm9Size; i += 4) { u32* ptr = (u32*)(romHeader->arm9LoadAddress + i); @@ -53,6 +45,11 @@ module_params_ntr_t* ModuleParamsLocator::FindModuleParams(const nds_header_ntr_ break; } } + + if (moduleParams != nullptr && (u32)moduleParams - romHeader->arm9LoadAddress > 0x1000) + { + LOG_WARNING("Module params not found in first 0x1000 bytes of arm9\n"); + } } return moduleParams; diff --git a/arm9/source/ModuleParamsLocator.h b/arm9/source/ModuleParamsLocator.h index f6db3f9..180eee4 100644 --- a/arm9/source/ModuleParamsLocator.h +++ b/arm9/source/ModuleParamsLocator.h @@ -9,5 +9,5 @@ public: /// @brief Searches for the module params of the arm9 of the rom with the given \p romHeader. /// @param romHeader The header of the rom. /// @return A pointer to the found module params, or \c nullptr if the module params could not be found. - module_params_ntr_t* FindModuleParams(const nds_header_ntr_t* romHeader); + module_params_ntr_t* FindModuleParams(const nds_header_ntr_t* romHeader) const; }; diff --git a/arm9/source/SecureSysCallsUnusedSpaceLocator.cpp b/arm9/source/SecureSysCallsUnusedSpaceLocator.cpp index 266da0a..e389190 100644 --- a/arm9/source/SecureSysCallsUnusedSpaceLocator.cpp +++ b/arm9/source/SecureSysCallsUnusedSpaceLocator.cpp @@ -78,8 +78,7 @@ const u16* SecureSysCallsUnusedSpaceLocator::FindPattern(const u16* data, u32 le void SecureSysCallsUnusedSpaceLocator::FindUnusedSpace(const nds_header_ntr_t* romHeader, PatchHeap& patchHeap) const { - if (romHeader->arm9RomOffset != 0x4000) - return; + // NOTE: We can not check if arm9RomOffset == 0x4000, because some rom hacks repack the rom in unusual ways. u32 secureStart = romHeader->arm9LoadAddress; @@ -91,6 +90,12 @@ void SecureSysCallsUnusedSpaceLocator::FindUnusedSpace(const nds_header_ntr_t* r return; } + if (((u32*)secureStart)[0] != 0xE7FFDEFF || ((u32*)secureStart)[1] != 0xE7FFDEFF) + { + LOG_ERROR("No secure area space found\n"); + return; + } + std::array patternLocations; for (u32 i = 0; i < sSvcPatterns.size(); i++)