You've already forked pico-loader
mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-01-09 16:28:35 -08:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
151b68018d | ||
|
|
4fd7fde362 | ||
|
|
61463ca39a | ||
|
|
c139eacaee | ||
|
|
e8b2f51497 | ||
|
|
48d49f5df8 | ||
|
|
00f6407cf4 | ||
|
|
e36e669daf | ||
|
|
b0d0336e1e | ||
|
|
4416c61158 | ||
|
|
dd062bb4fa | ||
|
|
656f696411 | ||
|
|
0d0fa445c9 | ||
|
|
e5f7283977 | ||
|
|
8550b36dc6 | ||
|
|
79018dee0d | ||
|
|
005b8cab03 | ||
|
|
b0c8dfa5bc | ||
|
|
d12036e6a7 |
@@ -165,9 +165,9 @@ void NdsLoader::Load(BootMode bootMode)
|
||||
}
|
||||
}
|
||||
|
||||
bool isHomebrew = (_romHeader.ntrHeader.makerCode[0] == 0 && _romHeader.ntrHeader.makerCode[1] == 0)
|
||||
|| _romHeader.ntrHeader.arm9AutoLoadDoneHookAddress == 0
|
||||
|| _romHeader.ntrHeader.arm7LoadAddress >= 0x03000000;
|
||||
bool isHomebrew = (_romHeader.makerCode[0] == 0 && _romHeader.makerCode[1] == 0)
|
||||
|| (_romHeader.arm9AutoLoadDoneHookAddress == 0 && _romHeader.arm7AutoLoadDoneHookAddress == 0)
|
||||
|| _romHeader.arm7LoadAddress >= 0x03000000;
|
||||
|
||||
if (isHomebrew)
|
||||
{
|
||||
@@ -186,16 +186,7 @@ void NdsLoader::Load(BootMode bootMode)
|
||||
memset(&_dsiwareSaveResult, 0, sizeof(_dsiwareSaveResult));
|
||||
if (bootMode != BootMode::Multiboot)
|
||||
{
|
||||
if (!_romHeader.IsDsiWare())
|
||||
{
|
||||
if (bootMode != BootMode::SdkResetSystem)
|
||||
{
|
||||
HandleCardSave();
|
||||
}
|
||||
|
||||
HandleAntiPiracy();
|
||||
}
|
||||
else
|
||||
if (_romHeader.IsDsiWare())
|
||||
{
|
||||
if (bootMode == BootMode::SdkResetSystem)
|
||||
{
|
||||
@@ -210,6 +201,15 @@ void NdsLoader::Load(BootMode bootMode)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bootMode != BootMode::SdkResetSystem)
|
||||
{
|
||||
HandleCardSave();
|
||||
}
|
||||
|
||||
HandleAntiPiracy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,14 +224,14 @@ void NdsLoader::Load(BootMode bootMode)
|
||||
|
||||
SetupSharedMemory(cardId, agbMem, resetParam, romOffset, bootType);
|
||||
|
||||
if (Environment::IsDsiMode() && _romHeader.IsTwlRom())
|
||||
{
|
||||
SetupTwlConfig();
|
||||
TwlAes().SetupAes(&_romHeader);
|
||||
}
|
||||
|
||||
if (Environment::IsDsiMode())
|
||||
{
|
||||
if (_romHeader.IsTwlRom())
|
||||
{
|
||||
SetupTwlConfig();
|
||||
TwlAes().SetupAes(&_romHeader);
|
||||
}
|
||||
|
||||
RemapWram();
|
||||
}
|
||||
|
||||
@@ -321,20 +321,20 @@ void NdsLoader::Load(BootMode bootMode)
|
||||
|
||||
if (Environment::IsDsiMode())
|
||||
{
|
||||
if (!_romHeader.IsTwlRom())
|
||||
{
|
||||
DSMode().SwitchToDSMode(_romHeader.ntrHeader.gameCode);
|
||||
}
|
||||
else
|
||||
if (_romHeader.IsTwlRom())
|
||||
{
|
||||
if (!(_romHeader.twlFlags2 & 1))
|
||||
{
|
||||
DSMode().SwitchToDSTouchAndSoundMode(_romHeader.ntrHeader.gameCode);
|
||||
DSMode().SwitchToDSTouchAndSoundMode(_romHeader.gameCode);
|
||||
}
|
||||
|
||||
// Set back power button handling to irq mode
|
||||
mcu_writeReg(MCU_REG_MODE, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
DSMode().SwitchToDSMode(_romHeader.gameCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (isHomebrew)
|
||||
@@ -349,11 +349,11 @@ void NdsLoader::Load(BootMode bootMode)
|
||||
bool NdsLoader::IsCloneBootRom(u32 romOffset)
|
||||
{
|
||||
bool isCloneBootRom = false;
|
||||
if (_romHeader.ntrHeader.ntrRomSize != 0)
|
||||
if (_romHeader.ntrRomSize != 0)
|
||||
{
|
||||
UINT bytesRead = 0;
|
||||
u16 signatureHeader;
|
||||
if (f_lseek(&_romFile, romOffset + _romHeader.ntrHeader.ntrRomSize) == FR_OK &&
|
||||
if (f_lseek(&_romFile, romOffset + _romHeader.ntrRomSize) == FR_OK &&
|
||||
f_read(&_romFile, &signatureHeader, sizeof(signatureHeader), &bytesRead) == FR_OK &&
|
||||
bytesRead == 2 &&
|
||||
signatureHeader == 0x6361)
|
||||
@@ -371,7 +371,7 @@ void NdsLoader::InsertArgv()
|
||||
u32 argSize = 0;
|
||||
|
||||
// Find the address to write argv
|
||||
u32 argDst = ((_romHeader.ntrHeader.arm9LoadAddress + _romHeader.ntrHeader.arm9Size + 3) & ~3) + 4;
|
||||
u32 argDst = ((_romHeader.arm9LoadAddress + _romHeader.arm9Size + 3) & ~3) + 4;
|
||||
if (_romHeader.IsTwlRom())
|
||||
{
|
||||
u32 argDstTwl = ((_romHeader.arm9iLoadAddress + _romHeader.arm9iSize + 3) & ~3) + 4;
|
||||
@@ -475,8 +475,8 @@ void NdsLoader::SetupSharedMemory(u32 cardId, u32 agbMem, u32 resetParam, u32 ro
|
||||
memcpy(TWL_SHARED_MEMORY->ntrSharedMem.romHeader, &_romHeader, sizeof(nds_header_ntr_t));
|
||||
*(vu32*)&TWL_SHARED_MEMORY->ntrSharedMem.bootCheckInfo[0] = cardId;
|
||||
*(vu32*)&TWL_SHARED_MEMORY->ntrSharedMem.bootCheckInfo[4] = cardId;
|
||||
*(vu16*)&TWL_SHARED_MEMORY->ntrSharedMem.bootCheckInfo[8] = _romHeader.ntrHeader.headerCrc;
|
||||
*(vu16*)&TWL_SHARED_MEMORY->ntrSharedMem.bootCheckInfo[0xA] = _romHeader.ntrHeader.secureAreaCrc;
|
||||
*(vu16*)&TWL_SHARED_MEMORY->ntrSharedMem.bootCheckInfo[8] = _romHeader.headerCrc;
|
||||
*(vu16*)&TWL_SHARED_MEMORY->ntrSharedMem.bootCheckInfo[0xA] = _romHeader.secureAreaCrc;
|
||||
*(vu32*)&TWL_SHARED_MEMORY->ntrSharedMem.bootCheckInfo[0x10] = 0x5835; // use correct card id address
|
||||
*(vu32*)&TWL_SHARED_MEMORY->ntrSharedMem.isDebuggerData[0x1C] = agbMem;
|
||||
TWL_SHARED_MEMORY->ntrSharedMem.resetParam = resetParam;
|
||||
@@ -536,7 +536,7 @@ bool NdsLoader::ShouldAttemptDldiPatch()
|
||||
{
|
||||
// Some games contain a fake dldi header to trick flashcards
|
||||
// See also: https://shutterbug2000.github.io/very-clever/
|
||||
switch (_romHeader.ntrHeader.gameCode)
|
||||
switch (_romHeader.gameCode)
|
||||
{
|
||||
// Final Fantasy IV
|
||||
case GAMECODE("YF4P"):
|
||||
@@ -610,7 +610,7 @@ bool NdsLoader::TryLoadRomHeader(u32 romOffset)
|
||||
|
||||
void NdsLoader::HandleCardSave()
|
||||
{
|
||||
if (!CardSaveArranger().SetupCardSave(_romHeader.ntrHeader.gameCode, _savePath))
|
||||
if (!CardSaveArranger().SetupCardSave(_romHeader.gameCode, _savePath))
|
||||
{
|
||||
ErrorDisplay().PrintError("Failed to setup save file.");
|
||||
}
|
||||
@@ -621,7 +621,7 @@ void NdsLoader::HandleAntiPiracy()
|
||||
auto apList = ApListFactory().CreateFromFile(AP_LIST_PATH);
|
||||
if (apList)
|
||||
{
|
||||
auto entry = apList->FindEntry(_romHeader.ntrHeader.gameCode, _romHeader.ntrHeader.softwareVersion);
|
||||
auto entry = apList->FindEntry(_romHeader.gameCode, _romHeader.softwareVersion);
|
||||
if (entry)
|
||||
{
|
||||
entry->Dump();
|
||||
@@ -683,15 +683,15 @@ void NdsLoader::RemapWram()
|
||||
|
||||
bool NdsLoader::TryLoadArm9()
|
||||
{
|
||||
if (f_lseek(&_romFile, _romHeader.ntrHeader.arm9RomOffset + TWL_SHARED_MEMORY->ntrSharedMem.romOffset) != FR_OK)
|
||||
if (f_lseek(&_romFile, _romHeader.arm9RomOffset + TWL_SHARED_MEMORY->ntrSharedMem.romOffset) != FR_OK)
|
||||
{
|
||||
LOG_FATAL("Failed to seek to arm9\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT bytesRead = 0;
|
||||
FRESULT result = f_read(&_romFile, (void*)_romHeader.ntrHeader.arm9LoadAddress, _romHeader.ntrHeader.arm9Size, &bytesRead);
|
||||
if (result != FR_OK || bytesRead != _romHeader.ntrHeader.arm9Size)
|
||||
FRESULT result = f_read(&_romFile, (void*)_romHeader.arm9LoadAddress, _romHeader.arm9Size, &bytesRead);
|
||||
if (result != FR_OK || bytesRead != _romHeader.arm9Size)
|
||||
{
|
||||
LOG_FATAL("Failed to read arm9. Result: %d, bytesRead: %d\n", result, bytesRead);
|
||||
return false;
|
||||
@@ -736,7 +736,7 @@ bool NdsLoader::TryLoadArm9i()
|
||||
|
||||
bool NdsLoader::TryDecryptArm9i()
|
||||
{
|
||||
if (!(_romHeader.ntrHeader.twlFlags & (1 << 1)))
|
||||
if (!(_romHeader.twlFlags & (1 << 1)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -756,7 +756,7 @@ bool NdsLoader::TryDecryptArm9i()
|
||||
|
||||
bool NdsLoader::TryDecryptArm7i()
|
||||
{
|
||||
if (!(_romHeader.ntrHeader.twlFlags & (1 << 1)) || _romHeader.modcryptArea2Size == 0)
|
||||
if (!(_romHeader.twlFlags & (1 << 1)) || _romHeader.modcryptArea2Size == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -776,15 +776,15 @@ bool NdsLoader::TryDecryptArm7i()
|
||||
|
||||
bool NdsLoader::TryLoadArm7()
|
||||
{
|
||||
if (f_lseek(&_romFile, _romHeader.ntrHeader.arm7RomOffset + TWL_SHARED_MEMORY->ntrSharedMem.romOffset) != FR_OK)
|
||||
if (f_lseek(&_romFile, _romHeader.arm7RomOffset + TWL_SHARED_MEMORY->ntrSharedMem.romOffset) != FR_OK)
|
||||
{
|
||||
LOG_FATAL("Failed to seek to arm7\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT bytesRead = 0;
|
||||
FRESULT result = f_read(&_romFile, (void*)_romHeader.ntrHeader.arm7LoadAddress, _romHeader.ntrHeader.arm7Size, &bytesRead);
|
||||
if (result != FR_OK || bytesRead != _romHeader.ntrHeader.arm7Size)
|
||||
FRESULT result = f_read(&_romFile, (void*)_romHeader.arm7LoadAddress, _romHeader.arm7Size, &bytesRead);
|
||||
if (result != FR_OK || bytesRead != _romHeader.arm7Size)
|
||||
{
|
||||
LOG_FATAL("Failed to read arm7. Result: %d, bytesRead: %d\n", result, bytesRead);
|
||||
return false;
|
||||
@@ -828,19 +828,19 @@ void NdsLoader::HandleDldiPatching()
|
||||
}
|
||||
|
||||
int arm9DldiAddr = sDldiStubMatcher.FindFirstOccurance(
|
||||
(const u32*)_romHeader.ntrHeader.arm9LoadAddress, _romHeader.ntrHeader.arm9Size >> 2) << 2;
|
||||
(const u32*)_romHeader.arm9LoadAddress, _romHeader.arm9Size >> 2) << 2;
|
||||
if (arm9DldiAddr >= 0)
|
||||
{
|
||||
dldi_header_t* arm9Dldi = (dldi_header_t*)(_romHeader.ntrHeader.arm9LoadAddress + arm9DldiAddr);
|
||||
dldi_header_t* arm9Dldi = (dldi_header_t*)(_romHeader.arm9LoadAddress + arm9DldiAddr);
|
||||
LOG_DEBUG("Dldi found in arm9 at address %p\n", arm9Dldi);
|
||||
dldi_patchTo(arm9Dldi);
|
||||
}
|
||||
|
||||
int arm7DldiAddr = sDldiStubMatcher.FindFirstOccurance(
|
||||
(const u32*)_romHeader.ntrHeader.arm7LoadAddress, _romHeader.ntrHeader.arm7Size >> 2) << 2;
|
||||
(const u32*)_romHeader.arm7LoadAddress, _romHeader.arm7Size >> 2) << 2;
|
||||
if (arm7DldiAddr >= 0)
|
||||
{
|
||||
dldi_header_t* arm7Dldi = (dldi_header_t*)(_romHeader.ntrHeader.arm7LoadAddress + arm7DldiAddr);
|
||||
dldi_header_t* arm7Dldi = (dldi_header_t*)(_romHeader.arm7LoadAddress + arm7DldiAddr);
|
||||
LOG_DEBUG("Dldi found in arm7 at address %p\n", arm7Dldi);
|
||||
dldi_patchTo(arm7Dldi);
|
||||
}
|
||||
@@ -860,7 +860,7 @@ void NdsLoader::StartRom(BootMode bootMode)
|
||||
REG_IF2 = ~0u;
|
||||
}
|
||||
|
||||
((entrypoint_t)_romHeader.ntrHeader.arm7EntryAddress)();
|
||||
((entrypoint_t)_romHeader.arm7EntryAddress)();
|
||||
}
|
||||
|
||||
void NdsLoader::SetupTwlConfig()
|
||||
@@ -970,20 +970,20 @@ bool NdsLoader::TrySetupDsiWareSave()
|
||||
|
||||
bool NdsLoader::TryDecryptSecureArea()
|
||||
{
|
||||
if (_romHeader.ntrHeader.arm9RomOffset < 0x4000 || _romHeader.ntrHeader.arm9RomOffset >= 0x8000)
|
||||
if (_romHeader.arm9RomOffset < 0x4000 || _romHeader.arm9RomOffset >= 0x8000)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (((u32*)_romHeader.ntrHeader.arm9LoadAddress)[0] == 0xE7FFDEFF &&
|
||||
((u32*)_romHeader.ntrHeader.arm9LoadAddress)[1] == 0xE7FFDEFF)
|
||||
if (((u32*)_romHeader.arm9LoadAddress)[0] == 0xE7FFDEFF &&
|
||||
((u32*)_romHeader.arm9LoadAddress)[1] == 0xE7FFDEFF)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
u16 secureAreaCrc = swi_getCrc16(0xFFFF,
|
||||
(const void*)_romHeader.ntrHeader.arm9LoadAddress, 0x8000 - _romHeader.ntrHeader.arm9RomOffset);
|
||||
if (secureAreaCrc != _romHeader.ntrHeader.secureAreaCrc)
|
||||
(const void*)_romHeader.arm9LoadAddress, 0x8000 - _romHeader.arm9RomOffset);
|
||||
if (secureAreaCrc != _romHeader.secureAreaCrc)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1000,13 +1000,13 @@ bool NdsLoader::TryDecryptSecureArea()
|
||||
}
|
||||
|
||||
auto blowfish = std::make_unique<Blowfish>(keyTable.get());
|
||||
blowfish->TransformTable(_romHeader.ntrHeader.gameCode, 3, 8);
|
||||
blowfish->TransformTable(_romHeader.gameCode, 3, 8);
|
||||
blowfish->Decrypt(
|
||||
(const void*)_romHeader.ntrHeader.arm9LoadAddress,
|
||||
(void*)_romHeader.ntrHeader.arm9LoadAddress,
|
||||
0x4800 - _romHeader.ntrHeader.arm9RomOffset);
|
||||
((u32*)_romHeader.ntrHeader.arm9LoadAddress)[0] = 0xE7FFDEFF;
|
||||
((u32*)_romHeader.ntrHeader.arm9LoadAddress)[1] = 0xE7FFDEFF;
|
||||
(const void*)_romHeader.arm9LoadAddress,
|
||||
(void*)_romHeader.arm9LoadAddress,
|
||||
0x4800 - _romHeader.arm9RomOffset);
|
||||
((u32*)_romHeader.arm9LoadAddress)[0] = 0xE7FFDEFF;
|
||||
((u32*)_romHeader.arm9LoadAddress)[1] = 0xE7FFDEFF;
|
||||
|
||||
LOG_DEBUG("Decrypted secure area\n");
|
||||
return true;
|
||||
|
||||
@@ -104,7 +104,7 @@ void TwlAes::DecryptModuleAes(void* data, u32 length, const aes_u128_t* iv) cons
|
||||
|
||||
void TwlAes::SetupModuleKeyXY(const nds_header_twl_t* romHeader) const
|
||||
{
|
||||
if ((romHeader->ntrHeader.twlFlags & (1 << 2)) || (romHeader->twlFlags2 & (1 << 7)))
|
||||
if ((romHeader->twlFlags & (1 << 2)) || (romHeader->twlFlags2 & (1 << 7)))
|
||||
{
|
||||
// debug
|
||||
aes_setKey(KEY_SLOT_MODULE, (const aes_u128_t*)romHeader);
|
||||
@@ -116,8 +116,8 @@ void TwlAes::SetupModuleKeyXY(const nds_header_twl_t* romHeader) const
|
||||
{
|
||||
MODULE_KEYX_NINT,
|
||||
MODULE_KEYX_ENDO,
|
||||
romHeader->ntrHeader.gameCode,
|
||||
__builtin_bswap32(romHeader->ntrHeader.gameCode)
|
||||
romHeader->gameCode,
|
||||
__builtin_bswap32(romHeader->gameCode)
|
||||
}};
|
||||
aes_setKeyXY(KEY_SLOT_MODULE, &keyX, (const aes_u128_t*)romHeader->arm9iSha1Hmac);
|
||||
}
|
||||
|
||||
@@ -49,15 +49,18 @@ void* Arm7Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform) const
|
||||
patchCollection.AddPatch(arm7ArenaPatch);
|
||||
|
||||
if (romHeader->unitCode == 0) // seems only present on NITRO, not on HYBRID or LIMITED
|
||||
{
|
||||
patchCollection.AddPatch(new DisableArm7WramClearPatch());
|
||||
}
|
||||
|
||||
if (sdkVersion.IsTwlSdk())
|
||||
{
|
||||
if (gIsDsiMode && romHeader->IsTwlRom() && twlRomHeader->IsDsiWare())
|
||||
if (gIsDsiMode && (twlRomHeader->HasNandAccess() || twlRomHeader->HasSdAccess()))
|
||||
{
|
||||
patchCollection.AddPatch(new Sdk5DsiSdCardRedirectPatch());
|
||||
}
|
||||
else
|
||||
|
||||
if (!twlRomHeader->IsDsiWare())
|
||||
{
|
||||
patchCollection.AddPatch(new CardiDoTaskFromArm9Patch());
|
||||
}
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
#include "patches/arm9/CardiReadRomIdCorePatch.h"
|
||||
#include "patches/arm9/OSResetSystemPatch.h"
|
||||
#include "patches/arm9/PokemonDownloaderArm9Patch.h"
|
||||
#include "patches/arm9/DSProtectArm9Patch.h"
|
||||
#include "patches/arm9/OverlayPatches/FsStartOverlayHookPatch.h"
|
||||
#include "patches/arm9/OverlayPatches/DSProtectPatches/DSProtectOverlayPatch.h"
|
||||
#include "patches/arm9/OverlayPatches/PokemonBw1/PokemonBw1IrApPatch.h"
|
||||
#include "patches/arm9/OverlayPatches/PokemonBw2/PokemonBw2IrApPatch.h"
|
||||
#include "patches/arm9/OverlayPatches/DSProtectPatches/DSProtectPuyoPuyo7Patch.h"
|
||||
#include "patches/arm9/OverlayPatches/PokemonIr/PokemonIrApPatch.h"
|
||||
#include "patches/arm9/OverlayPatches/GoldenSunDarkDawn/GoldenSunDarkDawnOverlayHookPatch.h"
|
||||
#include "SecureSysCallsUnusedSpaceLocator.h"
|
||||
#include "fastSearch.h"
|
||||
@@ -33,9 +34,9 @@
|
||||
|
||||
typedef void (*uncompress_func_t)(void* compressedEnd);
|
||||
|
||||
static const u32 sMiiUncompressBackwardPatternOld[] = { 0xE3500000, 0x0A000025, 0xE92D00F0, 0xE9100006 }; // mkds beta; version 0x2012774
|
||||
static const u32 sMiiUncompressBackwardPatternOld2[] = { 0xE3500000, 0x0A00002B, 0xE92D00F0, 0xE9100006 }; // asterix & obelix xxl 2; version 0x3017531
|
||||
static const u32 sMiiUncompressBackwardPattern[] = { 0xE3500000, 0x0A000027, 0xE92D00F0, 0xE9100006 }; // mkds
|
||||
static const u32 sMiiUncompressBackwardPatternOld[] = { 0xE3500000, 0x0A000025, 0xE92D00F0, 0xE9100006 };
|
||||
static const u32 sMiiUncompressBackwardPatternOld2[] = { 0xE3500000, 0x0A00002B, 0xE92D00F0, 0xE9100006 };
|
||||
static const u32 sMiiUncompressBackwardPattern[] = { 0xE3500000, 0x0A000027, 0xE92D00F0, 0xE9100006 };
|
||||
static const u32 sMiiUncompressBackwardPatternHybrid[] = { 0xE3500000, 0x0A000029, 0xE92D01F0, 0xE9100006 };
|
||||
|
||||
void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApListEntry* apListEntry,
|
||||
@@ -43,13 +44,11 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
|
||||
{
|
||||
auto romHeader = (const nds_header_ntr_t*)TWL_SHARED_MEMORY->ntrSharedMem.romHeader;
|
||||
auto twlRomHeader = (const nds_header_twl_t*)TWL_SHARED_MEMORY->twlRomHeader;
|
||||
ModuleParamsLocator moduleParamsLocator;
|
||||
auto moduleParams = moduleParamsLocator.FindModuleParams(romHeader);
|
||||
u32 arm9Size = romHeader->arm9Size;
|
||||
u32 arm9iSize = romHeader->IsTwlRom() ? twlRomHeader->arm9iSize : 0;
|
||||
SdkVersion sdkVersion = moduleParams ? moduleParams->sdkVersion : 0u;
|
||||
u32 compressedEnd = 0;
|
||||
PatchCollection patchCollection;
|
||||
auto moduleParams = ModuleParamsLocator().FindModuleParams(romHeader);
|
||||
SdkVersion sdkVersion = moduleParams ? moduleParams->sdkVersion : 0u;
|
||||
if (moduleParams)
|
||||
{
|
||||
LOG_DEBUG("Module params found at 0x%p\n", moduleParams);
|
||||
@@ -57,18 +56,7 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
|
||||
const u32* miiUncompressBackward = nullptr;
|
||||
if (moduleParams->compressedEnd)
|
||||
{
|
||||
const u32* miiUncompressBackwardPattern;
|
||||
if (sdkVersion <= 0x2017532)
|
||||
miiUncompressBackwardPattern = sMiiUncompressBackwardPatternOld;
|
||||
else
|
||||
miiUncompressBackwardPattern = sMiiUncompressBackwardPattern;
|
||||
|
||||
miiUncompressBackward = fastSearch16((const u32*)romHeader->arm9LoadAddress, 0x1000, miiUncompressBackwardPattern);
|
||||
if (!sdkVersion.IsTwlSdk() && !miiUncompressBackward)
|
||||
miiUncompressBackward = fastSearch16((const u32*)romHeader->arm9LoadAddress, 0x1000, sMiiUncompressBackwardPatternOld2);
|
||||
if (sdkVersion.IsTwlSdk() && !miiUncompressBackward)
|
||||
miiUncompressBackward = fastSearch16((const u32*)romHeader->arm9LoadAddress, 0x1000, sMiiUncompressBackwardPatternHybrid);
|
||||
|
||||
miiUncompressBackward = FindMIiUncompressBackward(romHeader->arm9LoadAddress, sdkVersion);
|
||||
if (miiUncompressBackward)
|
||||
{
|
||||
arm9Size = moduleParams->compressedEnd + *(u32*)(moduleParams->compressedEnd - 4) - romHeader->arm9LoadAddress;
|
||||
@@ -86,22 +74,20 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
|
||||
{
|
||||
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)
|
||||
arm9iModuleParams->magicLittleEndian == MODULE_PARAMS_TWL_MAGIC_LE &&
|
||||
arm9iModuleParams->compressedEnd != 0)
|
||||
{
|
||||
if (arm9iModuleParams->compressedEnd)
|
||||
LOG_DEBUG("Compressed arm9i found\n");
|
||||
if (miiUncompressBackward)
|
||||
{
|
||||
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");
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,6 +112,7 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
|
||||
romHeader->gameCode,
|
||||
loaderPlatform
|
||||
};
|
||||
PatchCollection patchCollection;
|
||||
if (sdkVersion != 0)
|
||||
{
|
||||
if (*(vu32*)0x02FFF00C == GAMECODE("ADAJ") &&
|
||||
@@ -154,14 +141,13 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
|
||||
}
|
||||
else
|
||||
{
|
||||
SecureSysCallsUnusedSpaceLocator secureSysCallsUnusedSpaceLocator;
|
||||
secureSysCallsUnusedSpaceLocator.FindUnusedSpace(romHeader, patchContext.GetPatchHeap());
|
||||
SecureSysCallsUnusedSpaceLocator().FindUnusedSpace(romHeader, patchContext.GetPatchHeap());
|
||||
}
|
||||
}
|
||||
|
||||
if (sdkVersion.IsTwlSdk())
|
||||
{
|
||||
if (!(romHeader->IsTwlRom() && twlRomHeader->IsDsiWare()))
|
||||
if (!twlRomHeader->IsDsiWare())
|
||||
{
|
||||
// if ((romHeader->unitCode & 3) != 3)
|
||||
{
|
||||
@@ -169,7 +155,7 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
|
||||
}
|
||||
patchCollection.AddPatch(new CardiReadRomWithCpuPatch());
|
||||
|
||||
if (gIsDsiMode && (romHeader->unitCode & 2))
|
||||
if (gIsDsiMode && romHeader->IsTwlRom())
|
||||
{
|
||||
patchCollection.AddPatch(new CardiReadCardWithHashInternalAsyncPatch());
|
||||
}
|
||||
@@ -182,98 +168,8 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
|
||||
}
|
||||
|
||||
patchCollection.AddPatch(new CardiReadRomIdCorePatch());
|
||||
|
||||
patchCollection.AddPatch(new OSResetSystemPatch(loaderInfo));
|
||||
|
||||
OverlayHookPatch* overlayHookPatch;
|
||||
if (romHeader->gameCode == GAMECODE("BO5P") ||
|
||||
romHeader->gameCode == GAMECODE("BO5E") ||
|
||||
romHeader->gameCode == GAMECODE("BO5J"))
|
||||
{
|
||||
overlayHookPatch = new GoldenSunDarkDawnOverlayHookPatch();
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(334, 0, DSProtectVersion::v2_01, ~0u));
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(335, 0, DSProtectVersion::v2_01s, ~0u));
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayHookPatch = new FsStartOverlayHookPatch();
|
||||
if (apListEntry)
|
||||
{
|
||||
u32 regularOverlayId = apListEntry->GetRegularOverlayId();
|
||||
if (regularOverlayId != AP_LIST_OVERLAY_ID_INVALID)
|
||||
{
|
||||
if (regularOverlayId == AP_LIST_OVERLAY_ID_STATIC_ARM9)
|
||||
{
|
||||
LOG_WARNING("Patching DSProtect in main memory currently not supported\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(
|
||||
regularOverlayId, apListEntry->GetRegularOffset(),
|
||||
apListEntry->GetDSProtectVersion(), apListEntry->GetDSProtectFunctionMask()));
|
||||
}
|
||||
}
|
||||
u32 sOverlayId = apListEntry->GetSOverlayId();
|
||||
if (sOverlayId != AP_LIST_OVERLAY_ID_INVALID)
|
||||
{
|
||||
if (sOverlayId == AP_LIST_OVERLAY_ID_STATIC_ARM9)
|
||||
{
|
||||
LOG_WARNING("Patching DSProtect in main memory currently not supported\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto version = apListEntry->GetDSProtectVersion();
|
||||
if (version < DSProtectVersion::v2_00s)
|
||||
{
|
||||
version = (DSProtectVersion)((u32)version - (u32)DSProtectVersion::v2_00 + (u32)DSProtectVersion::v2_00s);
|
||||
}
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(
|
||||
sOverlayId, apListEntry->GetSOffset(), version, ~0u));
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (romHeader->gameCode)
|
||||
{
|
||||
// Pokemon Black & White
|
||||
case GAMECODE("IRAD"):
|
||||
case GAMECODE("IRAF"):
|
||||
case GAMECODE("IRAI"):
|
||||
case GAMECODE("IRAJ"):
|
||||
case GAMECODE("IRAK"):
|
||||
case GAMECODE("IRAO"):
|
||||
case GAMECODE("IRAS"):
|
||||
case GAMECODE("IRBD"):
|
||||
case GAMECODE("IRBF"):
|
||||
case GAMECODE("IRBI"):
|
||||
case GAMECODE("IRBJ"):
|
||||
case GAMECODE("IRBK"):
|
||||
case GAMECODE("IRBO"):
|
||||
case GAMECODE("IRBS"):
|
||||
{
|
||||
overlayHookPatch->AddOverlayPatch(new PokemonBw1IrApPatch());
|
||||
break;
|
||||
}
|
||||
// Pokemon Black & White 2
|
||||
// todo: IRDJ and IREJ have two revisions and the first one seems to be different
|
||||
case GAMECODE("IRDD"):
|
||||
case GAMECODE("IRDF"):
|
||||
case GAMECODE("IRDI"):
|
||||
case GAMECODE("IRDK"):
|
||||
case GAMECODE("IRDO"):
|
||||
case GAMECODE("IRDS"):
|
||||
case GAMECODE("IRED"):
|
||||
case GAMECODE("IREF"):
|
||||
case GAMECODE("IREI"):
|
||||
case GAMECODE("IREK"):
|
||||
case GAMECODE("IREO"):
|
||||
case GAMECODE("IRES"):
|
||||
{
|
||||
overlayHookPatch->AddOverlayPatch(new PokemonBw2IrApPatch());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
patchCollection.AddPatch(overlayHookPatch);
|
||||
AddGamePatches(patchCollection, romHeader->gameCode, apListEntry);
|
||||
|
||||
if (moduleParams && compressedEnd != 0)
|
||||
{
|
||||
@@ -293,6 +189,194 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
|
||||
ic_invalidateAll();
|
||||
}
|
||||
|
||||
const u32* Arm9Patcher::FindMIiUncompressBackward(u32 arm9LoadAddress, SdkVersion sdkVersion) const
|
||||
{
|
||||
const u32* miiUncompressBackwardPattern;
|
||||
if (sdkVersion <= 0x2017532)
|
||||
{
|
||||
miiUncompressBackwardPattern = sMiiUncompressBackwardPatternOld;
|
||||
}
|
||||
else
|
||||
{
|
||||
miiUncompressBackwardPattern = sMiiUncompressBackwardPattern;
|
||||
}
|
||||
|
||||
const u32* miiUncompressBackward = fastSearch16((const u32*)arm9LoadAddress, 0x1000, miiUncompressBackwardPattern);
|
||||
if (!sdkVersion.IsTwlSdk() && !miiUncompressBackward)
|
||||
{
|
||||
miiUncompressBackward = fastSearch16((const u32*)arm9LoadAddress, 0x1000, sMiiUncompressBackwardPatternOld2);
|
||||
}
|
||||
if (sdkVersion.IsTwlSdk() && !miiUncompressBackward)
|
||||
{
|
||||
miiUncompressBackward = fastSearch16((const u32*)arm9LoadAddress, 0x1000, sMiiUncompressBackwardPatternHybrid);
|
||||
}
|
||||
|
||||
return miiUncompressBackward;
|
||||
}
|
||||
|
||||
void Arm9Patcher::AddGamePatches(PatchCollection& patchCollection, u32 gameCode, const ApListEntry* apListEntry) const
|
||||
{
|
||||
OverlayHookPatch* overlayHookPatch;
|
||||
if (gameCode == GAMECODE("BO5P") || gameCode == GAMECODE("BO5E") || gameCode == GAMECODE("BO5J"))
|
||||
{
|
||||
overlayHookPatch = new GoldenSunDarkDawnOverlayHookPatch();
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(334, 0, DSProtectVersion::v2_01, ~0u));
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(335, 0, DSProtectVersion::v2_01s, ~0u));
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayHookPatch = new FsStartOverlayHookPatch();
|
||||
if (apListEntry)
|
||||
{
|
||||
AddDSProtectPatches(patchCollection, overlayHookPatch, apListEntry);
|
||||
}
|
||||
AddGameSpecificPatches(patchCollection, overlayHookPatch, gameCode);
|
||||
}
|
||||
|
||||
patchCollection.AddPatch(overlayHookPatch);
|
||||
}
|
||||
|
||||
void Arm9Patcher::AddDSProtectPatches(
|
||||
PatchCollection& patchCollection, OverlayHookPatch* overlayHookPatch, const ApListEntry* apListEntry) const
|
||||
{
|
||||
u32 regularOverlayId = apListEntry->GetRegularOverlayId();
|
||||
if (regularOverlayId != AP_LIST_OVERLAY_ID_INVALID)
|
||||
{
|
||||
if (regularOverlayId == AP_LIST_OVERLAY_ID_STATIC_ARM9)
|
||||
{
|
||||
patchCollection.AddPatch(new DSProtectArm9Patch(
|
||||
apListEntry->GetRegularOffset(), apListEntry->GetDSProtectVersion(),
|
||||
apListEntry->GetDSProtectFunctionMask()));
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(
|
||||
regularOverlayId, apListEntry->GetRegularOffset(),
|
||||
apListEntry->GetDSProtectVersion(), apListEntry->GetDSProtectFunctionMask()));
|
||||
}
|
||||
}
|
||||
u32 sOverlayId = apListEntry->GetSOverlayId();
|
||||
if (sOverlayId != AP_LIST_OVERLAY_ID_INVALID)
|
||||
{
|
||||
auto version = apListEntry->GetDSProtectVersion();
|
||||
if (version < DSProtectVersion::v2_00s)
|
||||
{
|
||||
version = (DSProtectVersion)((u32)version - (u32)DSProtectVersion::v2_00 + (u32)DSProtectVersion::v2_00s);
|
||||
}
|
||||
if (sOverlayId == AP_LIST_OVERLAY_ID_STATIC_ARM9)
|
||||
{
|
||||
patchCollection.AddPatch(new DSProtectArm9Patch(
|
||||
apListEntry->GetSOffset(), version, ~0u));
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(
|
||||
sOverlayId, apListEntry->GetSOffset(), version, ~0u));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arm9Patcher::AddGameSpecificPatches(
|
||||
PatchCollection& patchCollection, OverlayHookPatch* overlayHookPatch, u32 gameCode) const
|
||||
{
|
||||
switch (gameCode)
|
||||
{
|
||||
// Dragon Ball: Origins 2
|
||||
case GAMECODE("BDBE"):
|
||||
{
|
||||
// BDBE;2;1.23;111111;0x1FC;-1;0x0
|
||||
// BDBE;3;1.23;111111;0x47DC;-1;0x0
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(2, 0x1FC, DSProtectVersion::v1_23, ~0u));
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(3, 0x47DC, DSProtectVersion::v1_23, ~0u));
|
||||
break;
|
||||
}
|
||||
case GAMECODE("BDBJ"):
|
||||
{
|
||||
// BDBJ;2;1.23;111111;0x1FC;-1;0x0
|
||||
// BDBJ;3;1.23;111111;0x4C34;-1;0x0
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(2, 0x1FC, DSProtectVersion::v1_23, ~0u));
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(3, 0x4C34, DSProtectVersion::v1_23, ~0u));
|
||||
break;
|
||||
}
|
||||
case GAMECODE("BDBP"):
|
||||
{
|
||||
// BDBP;2;1.23;111111;0x1FC;-1;0x0
|
||||
// BDBP;3;1.23;111111;0x484C;-1;0x0
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(2, 0x1FC, DSProtectVersion::v1_23, ~0u));
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectOverlayPatch(3, 0x484C, DSProtectVersion::v1_23, ~0u));
|
||||
break;
|
||||
}
|
||||
// Puyo Puyo 7
|
||||
case GAMECODE("BYOJ"):
|
||||
{
|
||||
// BYOJ;9;1.08;100110;1.08;0x21AC;-1;0x0
|
||||
// BYOJ;12;1.08;100101;1.08;0xC568;-1;0x0
|
||||
// BYOJ;14;1.08;010101;1.08;0x13AB8;-1;0x0
|
||||
// BYOJ;15;1.08;010110;1.08;0x16DF0;-1;0x0
|
||||
// BYOJ;19;1.08;011010;1.08;0x17F8;-1;0x0
|
||||
overlayHookPatch->AddOverlayPatch(new DSProtectPuyoPuyo7Patch());
|
||||
break;
|
||||
}
|
||||
// Pokemon HeartGold & SoulSilver
|
||||
case GAMECODE("IPGD"):
|
||||
case GAMECODE("IPGE"):
|
||||
case GAMECODE("IPGF"):
|
||||
case GAMECODE("IPGI"):
|
||||
case GAMECODE("IPGJ"):
|
||||
case GAMECODE("IPGK"):
|
||||
case GAMECODE("IPGS"):
|
||||
case GAMECODE("IPKD"):
|
||||
case GAMECODE("IPKE"):
|
||||
case GAMECODE("IPKF"):
|
||||
case GAMECODE("IPKI"):
|
||||
case GAMECODE("IPKJ"):
|
||||
case GAMECODE("IPKK"):
|
||||
case GAMECODE("IPKS"):
|
||||
{
|
||||
overlayHookPatch->AddOverlayPatch(new PokemonIrApPatch(PokemonIrVersion::Hgss));
|
||||
break;
|
||||
}
|
||||
// Pokemon Black & White
|
||||
case GAMECODE("IRAD"):
|
||||
case GAMECODE("IRAF"):
|
||||
case GAMECODE("IRAI"):
|
||||
case GAMECODE("IRAJ"):
|
||||
case GAMECODE("IRAK"):
|
||||
case GAMECODE("IRAO"):
|
||||
case GAMECODE("IRAS"):
|
||||
case GAMECODE("IRBD"):
|
||||
case GAMECODE("IRBF"):
|
||||
case GAMECODE("IRBI"):
|
||||
case GAMECODE("IRBJ"):
|
||||
case GAMECODE("IRBK"):
|
||||
case GAMECODE("IRBO"):
|
||||
case GAMECODE("IRBS"):
|
||||
{
|
||||
overlayHookPatch->AddOverlayPatch(new PokemonIrApPatch(PokemonIrVersion::Bw1));
|
||||
break;
|
||||
}
|
||||
// Pokemon Black & White 2
|
||||
case GAMECODE("IRDD"):
|
||||
case GAMECODE("IRDF"):
|
||||
case GAMECODE("IRDI"):
|
||||
case GAMECODE("IRDJ"):
|
||||
case GAMECODE("IRDK"):
|
||||
case GAMECODE("IRDO"):
|
||||
case GAMECODE("IRDS"):
|
||||
case GAMECODE("IRED"):
|
||||
case GAMECODE("IREF"):
|
||||
case GAMECODE("IREI"):
|
||||
case GAMECODE("IREJ"):
|
||||
case GAMECODE("IREK"):
|
||||
case GAMECODE("IREO"):
|
||||
case GAMECODE("IRES"):
|
||||
{
|
||||
overlayHookPatch->AddOverlayPatch(new PokemonIrApPatch(PokemonIrVersion::Bw2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arm9Patcher::AddRestoreCompressedEndPatch(PatchContext& patchContext,
|
||||
u32 arm9AutoLoadDoneHookAddress, u32* moduleParamsCompressedEnd, u32 originalCompressedEndValue) const
|
||||
{
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#pragma once
|
||||
#include "LoaderInfo.h"
|
||||
#include "SdkVersion.h"
|
||||
|
||||
class ApListEntry;
|
||||
class LoaderPlatform;
|
||||
class PatchContext;
|
||||
class PatchCollection;
|
||||
class OverlayHookPatch;
|
||||
|
||||
/// @brief Class for patching the arm9 of retail roms.
|
||||
class Arm9Patcher
|
||||
@@ -18,6 +21,12 @@ public:
|
||||
bool isCloneBootRom, const loader_info_t* loaderInfo) const;
|
||||
|
||||
private:
|
||||
const u32* FindMIiUncompressBackward(u32 arm9LoadAddress, SdkVersion sdkVersion) const;
|
||||
void AddGamePatches(PatchCollection& patchCollection, u32 gameCode, const ApListEntry* apListEntry) const;
|
||||
void AddDSProtectPatches(PatchCollection& patchCollection,
|
||||
OverlayHookPatch* overlayHookPatch, const ApListEntry* apListEntry) const;
|
||||
void AddGameSpecificPatches(PatchCollection& patchCollection,
|
||||
OverlayHookPatch* overlayHookPatch, u32 gameCode) const;
|
||||
void AddRestoreCompressedEndPatch(PatchContext& patchContext,
|
||||
u32 arm9AutoLoadDoneHookAddress, u32* moduleParamsCompressedEnd, u32 originalCompressedEndValue) const;
|
||||
u32 GetAvailableParentSectionSpace() const;
|
||||
|
||||
@@ -218,22 +218,15 @@ static void handleBootCommand()
|
||||
REG_EXMEMCNT &= ~0x0880; // map ds and gba slot to arm9
|
||||
sLoaderPlatform->PrepareRomBoot(sRomDirSector, sRomDirSectorOffset);
|
||||
Arm9IoRegisterClearer().ClearNtrIoRegisters(isSdkResetSystem);
|
||||
REG_EXMEMCNT |= 0x0880; // map ds and gba slot to arm7
|
||||
auto ntrRomHeader = (const nds_header_ntr_t*)TWL_SHARED_MEMORY->ntrSharedMem.romHeader;
|
||||
if (ntrRomHeader->IsTwlRom())
|
||||
if (gIsDsiMode && ntrRomHeader->IsTwlRom())
|
||||
{
|
||||
if (gIsDsiMode)
|
||||
{
|
||||
Arm9IoRegisterClearer().ClearTwlIoRegisters();
|
||||
REG_SCFG_EXT = 0x8307F100;
|
||||
scfg_setArm9Clock(ScfgArm9Clock::Twl134MHz);
|
||||
REG_SCFG_CLK = 0x87;
|
||||
REG_SCFG_RST = 1;
|
||||
}
|
||||
auto twlRomHeader = (const nds_header_twl_t*)TWL_SHARED_MEMORY->twlRomHeader;
|
||||
if (twlRomHeader->IsDsiWare())
|
||||
{
|
||||
REG_EXMEMCNT |= 0x0880; // map ds and gba slot to arm7
|
||||
}
|
||||
Arm9IoRegisterClearer().ClearTwlIoRegisters();
|
||||
REG_SCFG_EXT = 0x8307F100;
|
||||
scfg_setArm9Clock(ScfgArm9Clock::Twl134MHz);
|
||||
REG_SCFG_CLK = 0x87;
|
||||
REG_SCFG_RST = 1;
|
||||
}
|
||||
bootArm9();
|
||||
}
|
||||
|
||||
@@ -13,3 +13,4 @@ extern u32 __patch_carditaskthread_failoffset;
|
||||
extern u32 __patch_carditaskthread_successoffset;
|
||||
extern u32 __patch_carditaskthread_readsave_asm_address;
|
||||
extern u32 __patch_carditaskthread_writesave_asm_address;
|
||||
extern u32 __patch_carditaskthread_verifysave_asm_address;
|
||||
|
||||
@@ -93,8 +93,17 @@ write_backup:
|
||||
|
||||
verify_backup:
|
||||
ldr r0, [r4]
|
||||
movs r1, #0
|
||||
str r1, [r0] // result
|
||||
ldr r2, [r0, #0xC] // src
|
||||
ldr r1, [r0, #0x10] // dst
|
||||
ldr r3, [r0, #0x14] // len
|
||||
cmp r3, #0
|
||||
beq end_success
|
||||
|
||||
push {r0}
|
||||
ldr r0, __patch_carditaskthread_verifysave_asm_address
|
||||
bl blx_r0
|
||||
pop {r1}
|
||||
str r0, [r1] // result
|
||||
b end_success
|
||||
|
||||
blx_r0:
|
||||
@@ -118,6 +127,10 @@ __patch_carditaskthread_readsave_asm_address:
|
||||
__patch_carditaskthread_writesave_asm_address:
|
||||
.word 0
|
||||
|
||||
.global __patch_carditaskthread_verifysave_asm_address
|
||||
__patch_carditaskthread_verifysave_asm_address:
|
||||
.word 0
|
||||
|
||||
.pool
|
||||
|
||||
.end
|
||||
31
arm9/source/patches/arm7/VerifySaveAsm.h
Normal file
31
arm9/source/patches/arm7/VerifySaveAsm.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "sections.h"
|
||||
#include "../PatchCode.h"
|
||||
#include "../SectorRemapPatchCode.h"
|
||||
#include "../platform/SdReadPatchCode.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(verifysave);
|
||||
|
||||
extern "C" void verifysave_asm(u32, u32 saveSrc, void* memoryDst, u32 byteLength);
|
||||
|
||||
extern u32 verifysave_tmpBufferPtr;
|
||||
extern u32 verifysave_save_offset_to_sd_sector_asm_address;
|
||||
extern u32 verifysave_sdread_asm_address;
|
||||
|
||||
class VerifySavePatchCode : public PatchCode
|
||||
{
|
||||
public:
|
||||
VerifySavePatchCode(PatchHeap& patchHeap, const SectorRemapPatchCode* sectorRemapPatchCode,
|
||||
const SdReadPatchCode* sdReadPatchCode, void* tmpBuffer)
|
||||
: PatchCode(SECTION_START(verifysave), SECTION_SIZE(verifysave), patchHeap)
|
||||
{
|
||||
verifysave_save_offset_to_sd_sector_asm_address = (u32)sectorRemapPatchCode->GetRemapFunction();
|
||||
verifysave_sdread_asm_address = (u32)sdReadPatchCode->GetSdReadFunction();
|
||||
verifysave_tmpBufferPtr = (u32)tmpBuffer;
|
||||
}
|
||||
|
||||
const void* GetVerifySaveFunction() const
|
||||
{
|
||||
return GetAddressAtTarget((void*)verifysave_asm);
|
||||
}
|
||||
};
|
||||
83
arm9/source/patches/arm7/VerifySaveAsm.s
Normal file
83
arm9/source/patches/arm7/VerifySaveAsm.s
Normal file
@@ -0,0 +1,83 @@
|
||||
.cpu arm7tdmi
|
||||
.section "verifysave", "ax"
|
||||
.syntax unified
|
||||
.thumb
|
||||
|
||||
// r1 = save src
|
||||
// r2 = memory src
|
||||
// r3 = byte length
|
||||
.global verifysave_asm
|
||||
.type verifysave_asm, %function
|
||||
verifysave_asm:
|
||||
push {r4,r5,r6,r7,lr}
|
||||
movs r4, r3 // remaining bytes
|
||||
movs r5, r1
|
||||
movs r6, r2
|
||||
1:
|
||||
movs r0, r5 // will be rounded down by function
|
||||
ldr r3, verifysave_save_offset_to_sd_sector_asm_address
|
||||
bl blx_r3
|
||||
cmp r0, #0
|
||||
beq end // out of bounds
|
||||
|
||||
ldr r1, verifysave_tmpBufferPtr
|
||||
movs r2, #1 // single sector
|
||||
lsls r7, r2, #9 // 512
|
||||
ldr r3, verifysave_sdread_asm_address
|
||||
bl blx_r3
|
||||
|
||||
// verify bytes
|
||||
lsls r2, r5, #23
|
||||
lsrs r2, r2, #23 // r2 = byte offset in sector
|
||||
subs r0, r6, r2
|
||||
subs r7, r7, r2 // remaining in sector
|
||||
cmp r7, r4 // if remaining in sector > requested read length
|
||||
bls 2f
|
||||
movs r7, r4 // clamp to requested read length
|
||||
2:
|
||||
subs r4, r7
|
||||
adds r5, r7
|
||||
adds r6, r7
|
||||
ldr r1, verifysave_tmpBufferPtr
|
||||
|
||||
3:
|
||||
ldrb r3, [r1, r2]
|
||||
mov lr, r3
|
||||
ldrb r3, [r0, r2]
|
||||
cmp lr, r3
|
||||
bne bad_end
|
||||
adds r2, #1
|
||||
subs r7, #1
|
||||
bne 3b
|
||||
|
||||
cmp r4, #0
|
||||
bne 1b
|
||||
|
||||
end:
|
||||
movs r0, #0
|
||||
pop {r4,r5,r6,r7,pc}
|
||||
|
||||
bad_end:
|
||||
movs r0, #1
|
||||
pop {r4,r5,r6,r7,pc}
|
||||
|
||||
blx_r3:
|
||||
bx r3
|
||||
|
||||
.balign 4
|
||||
|
||||
.global verifysave_tmpBufferPtr
|
||||
verifysave_tmpBufferPtr:
|
||||
.word 0
|
||||
|
||||
.global verifysave_save_offset_to_sd_sector_asm_address
|
||||
verifysave_save_offset_to_sd_sector_asm_address:
|
||||
.word 0
|
||||
|
||||
.global verifysave_sdread_asm_address
|
||||
verifysave_sdread_asm_address:
|
||||
.word 0
|
||||
|
||||
.pool
|
||||
|
||||
.end
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "patches/PatchContext.h"
|
||||
#include "patches/arm7/ReadSaveAsm.h"
|
||||
#include "patches/arm7/WriteSaveAsm.h"
|
||||
#include "patches/arm7/VerifySaveAsm.h"
|
||||
#include "patches/FunctionSignature.h"
|
||||
#include "patches/platform/LoaderPlatform.h"
|
||||
#include "patches/arm7/SaveOffsetToSdSectorAsm.h"
|
||||
@@ -131,9 +132,16 @@ void CardiTaskThreadPatch::ApplyPatch(PatchContext& patchContext)
|
||||
writePatchCode,
|
||||
tmpBuffer
|
||||
);
|
||||
auto verifySavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<VerifySavePatchCode>(
|
||||
patchContext.GetPatchHeap(),
|
||||
sectorRemapPatchCode,
|
||||
readPatchCode,
|
||||
tmpBuffer
|
||||
);
|
||||
|
||||
__patch_carditaskthread_readsave_asm_address = (u32)readSavePatchCode->GetReadSaveFunction();
|
||||
__patch_carditaskthread_writesave_asm_address = (u32)writeSavePatchCode->GetWriteSaveFunction();
|
||||
__patch_carditaskthread_verifysave_asm_address = (u32)verifySavePatchCode->GetVerifySaveFunction();
|
||||
|
||||
u32 entryAddress;
|
||||
u32 patchOffset;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "fileInfo.h"
|
||||
#include "patches/arm7/ReadSaveAsm.h"
|
||||
#include "patches/arm7/WriteSaveAsm.h"
|
||||
#include "patches/arm7/VerifySaveAsm.h"
|
||||
#include "patches/arm7/SaveOffsetToSdSectorAsm.h"
|
||||
#include "patches/platform/LoaderPlatform.h"
|
||||
#include "patches/OffsetToSectorRemapAsm.h"
|
||||
@@ -82,9 +83,16 @@ void CardiDoTaskFromArm9Patch::ApplyPatch(PatchContext& patchContext)
|
||||
writePatchCode,
|
||||
tmpBuffer
|
||||
);
|
||||
auto verifySavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<VerifySavePatchCode>(
|
||||
patchContext.GetPatchHeap(),
|
||||
sectorRemapPatchCode,
|
||||
readPatchCode,
|
||||
tmpBuffer
|
||||
);
|
||||
|
||||
__patch_carditaskthread_readsave_asm_address = (u32)readSavePatchCode->GetReadSaveFunction();
|
||||
__patch_carditaskthread_writesave_asm_address = (u32)writeSavePatchCode->GetWriteSaveFunction();
|
||||
__patch_carditaskthread_verifysave_asm_address = (u32)verifySavePatchCode->GetVerifySaveFunction();
|
||||
|
||||
u32 patchOffset;
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#include "common.h"
|
||||
#include "sharedMemory.h"
|
||||
#include "ndsHeader.h"
|
||||
#include "moduleParams.h"
|
||||
#include "patches/platform/LoaderPlatform.h"
|
||||
#include "Sdk5DsiSdCardRedirectPatchAsm.h"
|
||||
#include "Sdk5DsiSdCardRedirectPatch.h"
|
||||
@@ -6,6 +9,14 @@
|
||||
static const u32 sAttachFunctionPattern[] = { 0xE92D4018u, 0xE24DDF5Du, 0xE24DDB01u, 0xE59FE050u };
|
||||
static const u32 sAttachFunctionPatternThumb[] = { 0xB0FFB518u, 0xB0DFB0FFu, 0x4A0E490Du, 0x64CA4469u };
|
||||
|
||||
#define BL_TO_GET_DRIVE_STRUCT_OFFSET (-0x20)
|
||||
#define BL_TO_GET_DRIVE_STRUCT_OFFSET_ALT 0x88
|
||||
|
||||
static bool isArmUnconditionalBl(u32 armInstruction)
|
||||
{
|
||||
return (armInstruction >> 24) == 0xEB;
|
||||
}
|
||||
|
||||
bool Sdk5DsiSdCardRedirectPatch::FindPatchTarget(PatchContext& patchContext)
|
||||
{
|
||||
_attachFunction = patchContext.FindPattern32Twl(sAttachFunctionPattern, sizeof(sAttachFunctionPattern));
|
||||
@@ -20,6 +31,16 @@ bool Sdk5DsiSdCardRedirectPatch::FindPatchTarget(PatchContext& patchContext)
|
||||
if (_attachFunction)
|
||||
{
|
||||
LOG_DEBUG("Found FATFSi_sdmcRtfsAttach at %p\n", _attachFunction);
|
||||
_blToGetDriveStructOffset = BL_TO_GET_DRIVE_STRUCT_OFFSET;
|
||||
if (!_thumb && !isArmUnconditionalBl(*(u32*)((u8*)_attachFunction + _blToGetDriveStructOffset)))
|
||||
{
|
||||
_blToGetDriveStructOffset = BL_TO_GET_DRIVE_STRUCT_OFFSET_ALT;
|
||||
if (!isArmUnconditionalBl(*(u32*)((u8*)_attachFunction + _blToGetDriveStructOffset)))
|
||||
{
|
||||
LOG_WARNING("Unsupported arm7 version for SD redirection patches\n");
|
||||
_attachFunction = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -42,6 +63,29 @@ static u32 getThumbBlAddress(const u32* instructionPointer)
|
||||
return (u32)instructionPointer + 5 + ((int)((((blInstruction1 & 0x7FF) << 11) | (blInstruction2 & 0x7FF)) << 10) >> 9);
|
||||
}
|
||||
|
||||
static u32 correctAddressForArm7iAutoLoad(u32 address)
|
||||
{
|
||||
auto romHeader = (const nds_header_twl_t*)TWL_SHARED_MEMORY->twlRomHeader;
|
||||
auto arm7iModuleParams = (const module_params_twl_t*)(
|
||||
romHeader->arm7LoadAddress + romHeader->arm7iModuleParamsAddress);
|
||||
|
||||
auto autoLoadListEntry = (autoload_list_entry_sdk5_t*)arm7iModuleParams->autoloadListStart;
|
||||
u32 currentAddress = arm7iModuleParams->autoloadStart;
|
||||
while (autoLoadListEntry != (autoload_list_entry_sdk5_t*)arm7iModuleParams->autoloadListEnd)
|
||||
{
|
||||
if (address >= currentAddress && address < currentAddress + autoLoadListEntry->size)
|
||||
{
|
||||
address -= currentAddress;
|
||||
address += autoLoadListEntry->targetAddress;
|
||||
break;
|
||||
}
|
||||
currentAddress += autoLoadListEntry->size;
|
||||
autoLoadListEntry++;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
void Sdk5DsiSdCardRedirectPatch::ApplyPatch(PatchContext& patchContext)
|
||||
{
|
||||
if (!_attachFunction)
|
||||
@@ -50,13 +94,15 @@ void Sdk5DsiSdCardRedirectPatch::ApplyPatch(PatchContext& patchContext)
|
||||
u32 getDriveStructAddress;
|
||||
if (_thumb)
|
||||
{
|
||||
getDriveStructAddress = getThumbBlAddress((u32*)((u8*)_attachFunction - 0x20));
|
||||
getDriveStructAddress = getThumbBlAddress((u32*)((u8*)_attachFunction + _blToGetDriveStructOffset));
|
||||
}
|
||||
else
|
||||
{
|
||||
getDriveStructAddress = getArmBlAddress((u32*)((u8*)_attachFunction - 0x20));
|
||||
getDriveStructAddress = getArmBlAddress((u32*)((u8*)_attachFunction + _blToGetDriveStructOffset));
|
||||
}
|
||||
|
||||
getDriveStructAddress = correctAddressForArm7iAutoLoad(getDriveStructAddress);
|
||||
|
||||
auto sdRead = patchContext.GetLoaderPlatform()->CreateSdReadPatchCode(
|
||||
patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap());
|
||||
auto sdWrite = patchContext.GetLoaderPlatform()->CreateSdWritePatchCode(
|
||||
|
||||
@@ -10,5 +10,6 @@ public:
|
||||
|
||||
private:
|
||||
u32* _attachFunction = nullptr;
|
||||
s16 _blToGetDriveStructOffset = 0;
|
||||
u16 _thumb = false;
|
||||
};
|
||||
|
||||
19
arm9/source/patches/arm9/DSProtectArm9Patch.cpp
Normal file
19
arm9/source/patches/arm9/DSProtectArm9Patch.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "common.h"
|
||||
#include "DSProtectArm9Patch.h"
|
||||
#include "OverlayPatches/DSProtectPatches/DSProtectOverlayPatch.h"
|
||||
#include "ApList.h"
|
||||
#include "sharedMemory.h"
|
||||
#include "ndsHeader.h"
|
||||
|
||||
bool DSProtectArm9Patch::FindPatchTarget(PatchContext& patchContext)
|
||||
{
|
||||
return true; // target already specified by _arm9Offset
|
||||
}
|
||||
|
||||
void DSProtectArm9Patch::ApplyPatch(PatchContext& patchContext)
|
||||
{
|
||||
auto patch = new DSProtectOverlayPatch(
|
||||
AP_LIST_OVERLAY_ID_STATIC_ARM9, _arm9Offset, _version, _functionMask);
|
||||
auto romHeader = (const nds_header_ntr_t*)TWL_SHARED_MEMORY->ntrSharedMem.romHeader;
|
||||
patch->ApplyPatchForStaticArm9(romHeader->arm9LoadAddress);
|
||||
}
|
||||
19
arm9/source/patches/arm9/DSProtectArm9Patch.h
Normal file
19
arm9/source/patches/arm9/DSProtectArm9Patch.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "../Patch.h"
|
||||
#include "DSProtectVersion.h"
|
||||
|
||||
/// @brief Arm9 static patch for DS Protect.
|
||||
class DSProtectArm9Patch : public Patch
|
||||
{
|
||||
public:
|
||||
DSProtectArm9Patch(u32 arm9Offset, DSProtectVersion version, u32 functionMask)
|
||||
: _arm9Offset(arm9Offset), _version(version), _functionMask(functionMask) { }
|
||||
|
||||
bool FindPatchTarget(PatchContext& patchContext) override;
|
||||
void ApplyPatch(PatchContext& patchContext) override;
|
||||
|
||||
private:
|
||||
u32 _arm9Offset;
|
||||
DSProtectVersion _version;
|
||||
u32 _functionMask;
|
||||
};
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "common.h"
|
||||
#include "../../../PatchContext.h"
|
||||
#include "thumbInstructions.h"
|
||||
#include "gameCode.h"
|
||||
#include "DSProtectOverlayPatchAsm.h"
|
||||
#include "DSProtectOverlayPatch.h"
|
||||
|
||||
@@ -23,7 +21,10 @@
|
||||
|
||||
const void* DSProtectOverlayPatch::InsertPatch(PatchContext& patchContext)
|
||||
{
|
||||
ConfigurePatch(patchContext);
|
||||
// Next patch and target overlay ID
|
||||
dsprotectpatch_nextAddress = next ? (const void*)next->InsertPatch(patchContext) : nullptr;
|
||||
dsprotectpatch_overlayId = _overlayId;
|
||||
CalculateOffsets();
|
||||
|
||||
u32 patchSize = SECTION_SIZE(dsprotectpatch);
|
||||
void* patchAddress = patchContext.GetPatchHeap().Alloc(patchSize);
|
||||
@@ -33,12 +34,21 @@ const void* DSProtectOverlayPatch::InsertPatch(PatchContext& patchContext)
|
||||
return (const void*)entryAddress;
|
||||
}
|
||||
|
||||
void DSProtectOverlayPatch::ConfigurePatch(PatchContext& patchContext) const
|
||||
void DSProtectOverlayPatch::ApplyPatchForStaticArm9(u32 arm9LoadAddress) const
|
||||
{
|
||||
// Next patch and target overlay ID
|
||||
dsprotectpatch_nextAddress = next ? (const void*)next->InsertPatch(patchContext) : nullptr;
|
||||
dsprotectpatch_overlayId = _overlayId;
|
||||
u32 fakeOverlayInfo[2];
|
||||
fakeOverlayInfo[0] = _overlayId; // ovy_id
|
||||
fakeOverlayInfo[1] = arm9LoadAddress; // ram_start
|
||||
|
||||
dsprotectpatch_nextAddress = nullptr;
|
||||
dsprotectpatch_overlayId = _overlayId;
|
||||
CalculateOffsets();
|
||||
|
||||
dsprotectpatch_executeWithParam(fakeOverlayInfo);
|
||||
}
|
||||
|
||||
void DSProtectOverlayPatch::CalculateOffsets() const
|
||||
{
|
||||
u32 regionOffset = _overlayOffset;
|
||||
|
||||
// Default invalid, enable below
|
||||
|
||||
@@ -10,6 +10,7 @@ public:
|
||||
: _overlayId(overlayId), _overlayOffset(overlayOffset), _version(version), _functionMask(functionMask) { }
|
||||
|
||||
const void* InsertPatch(PatchContext& patchContext) override;
|
||||
void ApplyPatchForStaticArm9(u32 arm9LoadAddress) const;
|
||||
|
||||
private:
|
||||
u32 _overlayId;
|
||||
@@ -17,5 +18,5 @@ private:
|
||||
DSProtectVersion _version;
|
||||
u32 _functionMask;
|
||||
|
||||
void ConfigurePatch(PatchContext& patchContext) const;
|
||||
void CalculateOffsets() const;
|
||||
};
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
DEFINE_SECTION_SYMBOLS(dsprotectpatch);
|
||||
|
||||
extern "C" void dsprotectpatch_entry();
|
||||
extern "C" void dsprotectpatch_executeWithParam(u32* overlayInfo);
|
||||
|
||||
extern u32 dsprotectpatch_patchType; // 0=write dsprotectpatch_writeWord, 1=copy subsequent word
|
||||
extern u32 dsprotectpatch_writeWord; // Word to write if dsprotectpatch_patchType=0
|
||||
extern u32 dsprotectpatch_offsetA1; // Target offset for A1 (0xFFFFFFFF=invalid)
|
||||
extern u32 dsprotectpatch_offsetNotA1; // Target offset for NotA1 (0xFFFFFFFF=invalid)
|
||||
extern u32 dsprotectpatch_offsetA1; // Target offset for A1 (0x8xxxxxxx=invalid)
|
||||
extern u32 dsprotectpatch_offsetNotA1; // Target offset for NotA1 (0x8xxxxxxx=invalid)
|
||||
|
||||
extern u32 dsprotectpatch_overlayId; // Target overlay ID
|
||||
extern const void* dsprotectpatch_nextAddress; // Next patch address
|
||||
|
||||
@@ -86,4 +86,16 @@ dsprotectpatch_nextAddress:
|
||||
|
||||
.pool
|
||||
|
||||
.text
|
||||
|
||||
.global dsprotectpatch_executeWithParam
|
||||
.type dsprotectpatch_executeWithParam, %function
|
||||
dsprotectpatch_executeWithParam:
|
||||
push {r5, lr}
|
||||
movs r5, r0
|
||||
bl dsprotectpatch_entry
|
||||
pop {r5, pc}
|
||||
|
||||
.pool
|
||||
|
||||
.end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user