Preserve cheats when OS_ResetSystem is used, move temporary save buffer to main memory

This commit is contained in:
Gericom
2026-03-07 13:49:51 +01:00
parent 1038a3d9cf
commit 8c8f36f5c6
14 changed files with 153 additions and 96 deletions

View File

@@ -205,6 +205,14 @@ extern "C" void loaderMain()
} }
} }
if (gLoaderHeader.v3.cheats != nullptr && gLoaderHeader.v3.cheats->numberOfCheats != 0)
{
// Copy cheats to vram
auto cheats = (pload_cheats_t*)malloc(gLoaderHeader.v3.cheats->length);
memcpy(cheats, gLoaderHeader.v3.cheats, gLoaderHeader.v3.cheats->length);
sLoader.SetCheats(cheats);
}
if (multiboot) if (multiboot)
{ {
LOG_DEBUG("Multiboot\n"); LOG_DEBUG("Multiboot\n");
@@ -219,19 +227,10 @@ extern "C" void loaderMain()
} }
else else
{ {
pload_cheats_t* cheats = nullptr;
if (gLoaderHeader.v3.cheats != nullptr && gLoaderHeader.v3.cheats->numberOfCheats != 0)
{
// Copy cheats to vram
cheats = (pload_cheats_t*)malloc(gLoaderHeader.v3.cheats->length);
memcpy(cheats, gLoaderHeader.v3.cheats, gLoaderHeader.v3.cheats->length);
}
sLoader.SetRomPath(gLoaderHeader.loadParams.romPath); sLoader.SetRomPath(gLoaderHeader.loadParams.romPath);
handleSavePath(); handleSavePath();
sLoader.SetArguments(gLoaderHeader.loadParams.arguments, gLoaderHeader.loadParams.argumentsLength); sLoader.SetArguments(gLoaderHeader.loadParams.arguments, gLoaderHeader.loadParams.argumentsLength);
sLoader.SetLauncherPath(gLoaderHeader.v2.launcherPath); sLoader.SetLauncherPath(gLoaderHeader.v2.launcherPath);
sLoader.SetCheats(cheats);
sLoader.Load(BootMode::Normal); sLoader.Load(BootMode::Normal);
} }

View File

@@ -18,6 +18,18 @@
#include "patches/arm7/cheats/CheatEnginePatch.h" #include "patches/arm7/cheats/CheatEnginePatch.h"
#include "Arm7Patcher.h" #include "Arm7Patcher.h"
static u32 correctAddress(u32 address, const nds_header_ntr_t* romHeader)
{
if (gIsDsiMode && romHeader->unitCode == 0)
{
return address & ~0xC00000; // 0x023...
}
else
{
return address | 0x800000; // make sure it ends up in the right place while in 16MB mode
}
}
void* Arm7Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, u32 cheatsLength, void*& cheatsPtr) const void* Arm7Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, u32 cheatsLength, void*& cheatsPtr) const
{ {
cheatsPtr = nullptr; cheatsPtr = nullptr;
@@ -63,6 +75,37 @@ void* Arm7Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, u32 cheats
auto arm7ArenaPatch = new OsGetInitArenaLoPatch(); auto arm7ArenaPatch = new OsGetInitArenaLoPatch();
patchCollection.AddPatch(arm7ArenaPatch); patchCollection.AddPatch(arm7ArenaPatch);
if (!arm7ArenaPatch->FindPatchTarget(patchContext))
{
ErrorDisplay().PrintError("Failed to apply arm7 patches.");
}
const u32 arm7PatchSpaceSize = 0x800;
void* privateWramHeapStart = arm7ArenaPatch->GetArm7PrivateWramArenaLo();
u32 mainMemoryArenaLo = (u32)arm7ArenaPatch->GetMainMemoryArenaLo();
if (0x0380F780 - (u32)privateWramHeapStart - 0x2100 >= arm7PatchSpaceSize)
{
patchSpaceStart = privateWramHeapStart;
arm7ArenaPatch->SetArm7PrivateWramArenaLo((u8*)patchSpaceStart + arm7PatchSpaceSize);
}
else
{
LOG_DEBUG("Arm 7 patches placed in main memory\n");
patchSpaceStart = (void*)correctAddress(mainMemoryArenaLo, romHeader);
mainMemoryArenaLo += arm7PatchSpaceSize;
}
patchContext.GetPatchHeap().AddFreeSpace(patchSpaceStart, arm7PatchSpaceSize);
if (cheatsLength > 0)
{
void* cheats = (void*)correctAddress(mainMemoryArenaLo, romHeader);
LOG_DEBUG("Cheats placed at 0x%p\n", cheats);
cheatsPtr = cheats;
patchCollection.AddPatch(new CheatEnginePatch(cheats));
mainMemoryArenaLo += cheatsLength;
}
if (romHeader->unitCode == 0) // seems only present on NITRO, not on HYBRID or LIMITED if (romHeader->unitCode == 0) // seems only present on NITRO, not on HYBRID or LIMITED
{ {
patchCollection.AddPatch(new DisableArm7WramClearPatch()); patchCollection.AddPatch(new DisableArm7WramClearPatch());
@@ -77,12 +120,16 @@ void* Arm7Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, u32 cheats
if (!twlRomHeader->IsDsiWare()) if (!twlRomHeader->IsDsiWare())
{ {
patchCollection.AddPatch(new CardiDoTaskFromArm9Patch()); void* saveTmpBuffer = (void*)correctAddress(mainMemoryArenaLo, romHeader);
mainMemoryArenaLo += 512;
patchCollection.AddPatch(new CardiDoTaskFromArm9Patch(saveTmpBuffer));
} }
} }
else else
{ {
patchCollection.AddPatch(new CardiTaskThreadPatch()); void* saveTmpBuffer = (void*)correctAddress(mainMemoryArenaLo, romHeader);
mainMemoryArenaLo += 512;
patchCollection.AddPatch(new CardiTaskThreadPatch(saveTmpBuffer));
} }
if (*(vu32*)0x02FFF00C == GAMECODE("ADAJ") && if (*(vu32*)0x02FFF00C == GAMECODE("ADAJ") &&
@@ -93,54 +140,7 @@ void* Arm7Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, u32 cheats
patchCollection.AddPatch(new PokemonDownloaderArm7Patch()); patchCollection.AddPatch(new PokemonDownloaderArm7Patch());
} }
CheatEnginePatch* cheatEnginePatch = nullptr;
if (cheatsLength > 0)
{
cheatEnginePatch = new CheatEnginePatch();
patchCollection.AddPatch(cheatEnginePatch);
}
if (arm7ArenaPatch->FindPatchTarget(patchContext))
{
const u32 arm7PatchSpaceSize = 0x800;
void* privateWramHeapStart = arm7ArenaPatch->GetArm7PrivateWramArenaLo();
u32 mainMemoryArenaLo = (u32)arm7ArenaPatch->GetMainMemoryArenaLo();
if (0x0380F780 - (u32)privateWramHeapStart - 0x2100 >= arm7PatchSpaceSize)
{
patchSpaceStart = privateWramHeapStart;
arm7ArenaPatch->SetArm7PrivateWramArenaLo((u8*)patchSpaceStart + arm7PatchSpaceSize);
}
else
{
LOG_DEBUG("Arm 7 patches placed in main memory\n");
if (gIsDsiMode && romHeader->unitCode == 0)
{
patchSpaceStart = (void*)(mainMemoryArenaLo & ~0xC00000); // 0x023...
}
else
{
patchSpaceStart = (void*)(mainMemoryArenaLo | 0x800000); // make sure it ends up in the right place while in 16MB mode
}
mainMemoryArenaLo += arm7PatchSpaceSize;
}
if (cheatsLength > 0)
{
void* cheats;
if (gIsDsiMode && romHeader->unitCode == 0)
{
cheats = (void*)(mainMemoryArenaLo & ~0xC00000); // 0x023...
}
else
{
cheats = (void*)(mainMemoryArenaLo | 0x800000); // make sure it ends up in the right place while in 16MB mode
}
cheatsPtr = cheats;
cheatEnginePatch->SetCheats(cheats);
mainMemoryArenaLo += cheatsLength;
}
arm7ArenaPatch->SetMainMemoryArenaLo((void*)mainMemoryArenaLo); arm7ArenaPatch->SetMainMemoryArenaLo((void*)mainMemoryArenaLo);
patchContext.GetPatchHeap().AddFreeSpace(patchSpaceStart, arm7PatchSpaceSize);
}
// The arm7 patcher uses the fact that the ntr wram is mirrored over the entire 03 region. // The arm7 patcher uses the fact that the ntr wram is mirrored over the entire 03 region.
// Since the reserved patch space is smaller than the ntr wram, it will never overlap. // Since the reserved patch space is smaller than the ntr wram, it will never overlap.

View File

@@ -47,7 +47,7 @@ static const u32 sMiiUncompressBackwardPatternOld2[] = { 0xE3500000, 0x0A00002B,
static const u32 sMiiUncompressBackwardPattern[] = { 0xE3500000, 0x0A000027, 0xE92D00F0, 0xE9100006 }; static const u32 sMiiUncompressBackwardPattern[] = { 0xE3500000, 0x0A000027, 0xE92D00F0, 0xE9100006 };
static const u32 sMiiUncompressBackwardPatternHybrid[] = { 0xE3500000, 0x0A000029, 0xE92D01F0, 0xE9100006 }; static const u32 sMiiUncompressBackwardPatternHybrid[] = { 0xE3500000, 0x0A000029, 0xE92D01F0, 0xE9100006 };
void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApListEntry* apListEntry, Arm9Patcher::PatchResult Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApListEntry* apListEntry,
bool isCloneBootRom, const loader_info_t* loaderInfo) const bool isCloneBootRom, const loader_info_t* loaderInfo) const
{ {
auto romHeader = (const nds_header_ntr_t*)TWL_SHARED_MEMORY->ntrSharedMem.romHeader; auto romHeader = (const nds_header_ntr_t*)TWL_SHARED_MEMORY->ntrSharedMem.romHeader;
@@ -165,6 +165,7 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
loaderPlatform loaderPlatform
}; };
PatchCollection patchCollection; PatchCollection patchCollection;
OSResetSystemPatch* osResetSystemPatch = nullptr;
if (sdkVersion != 0) if (sdkVersion != 0)
{ {
if (*(vu32*)0x02FFF00C == GAMECODE("ADAJ") && if (*(vu32*)0x02FFF00C == GAMECODE("ADAJ") &&
@@ -217,7 +218,8 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
} }
patchCollection.AddPatch(new CardiReadRomIdCorePatch()); patchCollection.AddPatch(new CardiReadRomIdCorePatch());
patchCollection.AddPatch(new OSResetSystemPatch(loaderInfo)); osResetSystemPatch = new OSResetSystemPatch(loaderInfo);
patchCollection.AddPatch(osResetSystemPatch);
AddGamePatches(patchCollection, romHeader->gameCode, apListEntry); AddGamePatches(patchCollection, romHeader->gameCode, apListEntry);
if (moduleParams && compressedEnd != 0) if (moduleParams && compressedEnd != 0)
@@ -236,6 +238,17 @@ void Arm9Patcher::ApplyPatches(const LoaderPlatform* loaderPlatform, const ApLis
dc_flushAll(); dc_flushAll();
dc_drainWriteBuffer(); dc_drainWriteBuffer();
ic_invalidateAll(); ic_invalidateAll();
void** softResetCheatsPointer = nullptr;
if (osResetSystemPatch != nullptr)
{
softResetCheatsPointer = osResetSystemPatch->GetCheatsPointerAtTarget();
}
return PatchResult
{
.softResetCheatsPointer = softResetCheatsPointer
};
} }
const u32* Arm9Patcher::FindMIiUncompressBackward(u32 arm9LoadAddress, SdkVersion sdkVersion) const const u32* Arm9Patcher::FindMIiUncompressBackward(u32 arm9LoadAddress, SdkVersion sdkVersion) const

View File

@@ -12,12 +12,20 @@ class OverlayHookPatch;
class Arm9Patcher class Arm9Patcher
{ {
public: public:
struct PatchResult
{
/// @brief Pointer to the cheats pointer used for soft reset.
/// This pointer must be set to keep cheats over soft resets.
void** softResetCheatsPointer;
};
/// @brief Applies arm9 patches using the given \p loaderPlatform. /// @brief Applies arm9 patches using the given \p loaderPlatform.
/// @param loaderPlatform The loader platform to use. /// @param loaderPlatform The loader platform to use.
/// @param apListEntry The AP list entry for the rom being loaded, or \c nullptr if there is none. /// @param apListEntry The AP list entry for the rom being loaded, or \c nullptr if there is none.
/// @param isCloneBootRom \c true if the rom being loaded is a clone boot rom, or \c false otherwise. /// @param isCloneBootRom \c true if the rom being loaded is a clone boot rom, or \c false otherwise.
/// @param loaderInfo The loader info to use. /// @param loaderInfo The loader info to use.
void ApplyPatches(const LoaderPlatform* loaderPlatform, const ApListEntry* apListEntry, /// @return Some information resulting from the patching.
PatchResult ApplyPatches(const LoaderPlatform* loaderPlatform, const ApListEntry* apListEntry,
bool isCloneBootRom, const loader_info_t* loaderInfo) const; bool isCloneBootRom, const loader_info_t* loaderInfo) const;
private: private:

View File

@@ -47,6 +47,7 @@ static u32 sRomDirSector;
static u32 sRomDirSectorOffset; static u32 sRomDirSectorOffset;
static u16 sIsCloneBootRom; static u16 sIsCloneBootRom;
static loader_info_t sLoaderInfo; static loader_info_t sLoaderInfo;
static void** sSoftResetCheatsPointer = nullptr;
u16 gIsDsiMode; u16 gIsDsiMode;
@@ -147,11 +148,12 @@ static void handleClearMainMemCommand()
static void handleApplyArm9PatchesCommand() static void handleApplyArm9PatchesCommand()
{ {
Arm9Patcher().ApplyPatches( auto result = Arm9Patcher().ApplyPatches(
sLoaderPlatform, sLoaderPlatform,
sApListEntry.GetGameCode() == 0 ? nullptr : &sApListEntry, sApListEntry.GetGameCode() == 0 ? nullptr : &sApListEntry,
sIsCloneBootRom, sIsCloneBootRom,
&sLoaderInfo); &sLoaderInfo);
sSoftResetCheatsPointer = result.softResetCheatsPointer;
ipc_sendWordDirect(1); ipc_sendWordDirect(1);
} }
@@ -159,6 +161,10 @@ static void handleApplyArm7PatchesCommand(u32 cheatsLength)
{ {
void* cheats = nullptr; void* cheats = nullptr;
void* patchSpaceStart = Arm7Patcher().ApplyPatches(sLoaderPlatform, cheatsLength, cheats); void* patchSpaceStart = Arm7Patcher().ApplyPatches(sLoaderPlatform, cheatsLength, cheats);
if (sSoftResetCheatsPointer != nullptr)
{
*sSoftResetCheatsPointer = cheats;
}
ipc_sendWordDirect((u32)patchSpaceStart); ipc_sendWordDirect((u32)patchSpaceStart);
ipc_sendWordDirect((u32)cheats); ipc_sendWordDirect((u32)cheats);
} }

View File

@@ -5,16 +5,14 @@
class CheatEnginePatch : public Patch class CheatEnginePatch : public Patch
{ {
public: public:
explicit CheatEnginePatch(const void* cheats)
: _cheats(cheats) { }
bool FindPatchTarget(PatchContext& patchContext) override; bool FindPatchTarget(PatchContext& patchContext) override;
void ApplyPatch(PatchContext& patchContext) override; void ApplyPatch(PatchContext& patchContext) override;
void SetCheats(const void* cheats)
{
_cheats = cheats;
}
private: private:
const void* _cheats = nullptr; const void* _cheats;
u32* _vblankIrqHandler = nullptr; u32* _vblankIrqHandler = nullptr;
const u32* _foundPattern = nullptr; const u32* _foundPattern = nullptr;
}; };

View File

@@ -103,13 +103,12 @@ void CardiTaskThreadPatch::ApplyPatch(PatchContext& patchContext)
patchContext.GetPatchHeap(), patchContext.GetPatchHeap(),
(const save_file_info_t*)((u32)SHARED_SAVE_FILE_INFO - 0x02F00000 + 0x02700000) (const save_file_info_t*)((u32)SHARED_SAVE_FILE_INFO - 0x02F00000 + 0x02700000)
); );
void* tmpBuffer = patchContext.GetPatchHeap().Alloc(512);
auto readSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<ReadSavePatchCode> auto readSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<ReadSavePatchCode>
( (
patchContext.GetPatchHeap(), patchContext.GetPatchHeap(),
sectorRemapPatchCode, sectorRemapPatchCode,
readPatchCode, readPatchCode,
tmpBuffer _saveTmpBuffer
); );
auto writeSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<WriteSavePatchCode> auto writeSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<WriteSavePatchCode>
( (
@@ -117,13 +116,13 @@ void CardiTaskThreadPatch::ApplyPatch(PatchContext& patchContext)
sectorRemapPatchCode, sectorRemapPatchCode,
readPatchCode, readPatchCode,
writePatchCode, writePatchCode,
tmpBuffer _saveTmpBuffer
); );
auto verifySavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<VerifySavePatchCode>( auto verifySavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<VerifySavePatchCode>(
patchContext.GetPatchHeap(), patchContext.GetPatchHeap(),
sectorRemapPatchCode, sectorRemapPatchCode,
readPatchCode, readPatchCode,
tmpBuffer _saveTmpBuffer
); );
__patch_carditaskthread_readsave_asm_address = (u32)readSavePatchCode->GetReadSaveFunction(); __patch_carditaskthread_readsave_asm_address = (u32)readSavePatchCode->GetReadSaveFunction();

View File

@@ -22,11 +22,15 @@ public:
ThumbF ThumbF
}; };
explicit CardiTaskThreadPatch(void* saveTmpBuffer)
: _saveTmpBuffer(saveTmpBuffer) { }
bool FindPatchTarget(PatchContext& patchContext) override; bool FindPatchTarget(PatchContext& patchContext) override;
void ApplyPatch(PatchContext& patchContext) override; void ApplyPatch(PatchContext& patchContext) override;
private: private:
u32* _cardiTaskThread = nullptr; u32* _cardiTaskThread = nullptr;
void* _saveTmpBuffer;
PatchVariant _patchVariant = PatchVariant::None; PatchVariant _patchVariant = PatchVariant::None;
void ApplyArmPatch(void* patch1Address) const; void ApplyArmPatch(void* patch1Address) const;

View File

@@ -68,25 +68,24 @@ void CardiDoTaskFromArm9Patch::ApplyPatch(PatchContext& patchContext)
patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap()); patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap());
auto sectorRemapPatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<SaveOffsetToSdSectorPatchCode>( auto sectorRemapPatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<SaveOffsetToSdSectorPatchCode>(
patchContext.GetPatchHeap(), SHARED_SAVE_FILE_INFO); patchContext.GetPatchHeap(), SHARED_SAVE_FILE_INFO);
void* tmpBuffer = patchContext.GetPatchHeap().Alloc(512);
auto readSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<ReadSavePatchCode>( auto readSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<ReadSavePatchCode>(
patchContext.GetPatchHeap(), patchContext.GetPatchHeap(),
sectorRemapPatchCode, sectorRemapPatchCode,
readPatchCode, readPatchCode,
tmpBuffer _saveTmpBuffer
); );
auto writeSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<WriteSavePatchCode>( auto writeSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<WriteSavePatchCode>(
patchContext.GetPatchHeap(), patchContext.GetPatchHeap(),
sectorRemapPatchCode, sectorRemapPatchCode,
readPatchCode, readPatchCode,
writePatchCode, writePatchCode,
tmpBuffer _saveTmpBuffer
); );
auto verifySavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<VerifySavePatchCode>( auto verifySavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<VerifySavePatchCode>(
patchContext.GetPatchHeap(), patchContext.GetPatchHeap(),
sectorRemapPatchCode, sectorRemapPatchCode,
readPatchCode, readPatchCode,
tmpBuffer _saveTmpBuffer
); );
__patch_carditaskthread_readsave_asm_address = (u32)readSavePatchCode->GetReadSaveFunction(); __patch_carditaskthread_readsave_asm_address = (u32)readSavePatchCode->GetReadSaveFunction();

View File

@@ -5,12 +5,16 @@
class CardiDoTaskFromArm9Patch : public Patch class CardiDoTaskFromArm9Patch : public Patch
{ {
public: public:
explicit CardiDoTaskFromArm9Patch(void* saveTmpBuffer)
: _saveTmpBuffer(saveTmpBuffer) { }
bool FindPatchTarget(PatchContext& patchContext) override; bool FindPatchTarget(PatchContext& patchContext) override;
void ApplyPatch(PatchContext& patchContext) override; void ApplyPatch(PatchContext& patchContext) override;
private: private:
u32* _cardiDoTaskFromArm9 = nullptr; u32* _cardiDoTaskFromArm9 = nullptr;
const u32* _foundPattern = nullptr; const u32* _foundPattern = nullptr;
void* _saveTmpBuffer;
u16 _thumb = false; u16 _thumb = false;
void TryPattern(PatchContext& patchContext, const u32* pattern); void TryPattern(PatchContext& patchContext, const u32* pattern);

View File

@@ -126,5 +126,7 @@ void OSResetSystemPatch::ApplyPatch(PatchContext& patchContext)
*(u32*)((u8*)_osResetSystem + offset) = 0xE51FF004; *(u32*)((u8*)_osResetSystem + offset) = 0xE51FF004;
*(u32*)((u8*)_osResetSystem + offset + 4) = (u32)patchCode->GetOSResetSystemFunction(); *(u32*)((u8*)_osResetSystem + offset + 4) = (u32)patchCode->GetOSResetSystemFunction();
_cheatsPointer = patchCodePart2->GetCheatsPointerAtTarget();
} }

View File

@@ -12,8 +12,14 @@ public:
bool FindPatchTarget(PatchContext& patchContext) override; bool FindPatchTarget(PatchContext& patchContext) override;
void ApplyPatch(PatchContext& patchContext) override; void ApplyPatch(PatchContext& patchContext) override;
void** GetCheatsPointerAtTarget() const
{
return _cheatsPointer;
}
private: private:
u32* _osResetSystem = nullptr; u32* _osResetSystem = nullptr;
u32 _hybrid = false; u32 _hybrid = false;
const loader_info_t* _loaderInfo; const loader_info_t* _loaderInfo;
void** _cheatsPointer = nullptr;
}; };

View File

@@ -15,6 +15,7 @@ extern u32 patch_osresetsystem_readSdSectors_address;
extern u32 patch_osresetsystem_bootPicoLoader_address; extern u32 patch_osresetsystem_bootPicoLoader_address;
extern u16 patch_osresetsystem_entry_jump_to_twl_arm7_sync; extern u16 patch_osresetsystem_entry_jump_to_twl_arm7_sync;
extern u32 patch_osresetsystem_arm7Entry_address; extern u32 patch_osresetsystem_arm7Entry_address;
extern u32 patch_osresetsystem_cheats_address;
class OSResetSystemPart2PatchCode : public PatchCode class OSResetSystemPart2PatchCode : public PatchCode
{ {
@@ -28,6 +29,11 @@ public:
{ {
return GetAddressAtTarget((void*)patch_osresetsystem_bootPicoLoader); return GetAddressAtTarget((void*)patch_osresetsystem_bootPicoLoader);
} }
void** GetCheatsPointerAtTarget() const
{
return (void**)GetAddressAtTarget(&patch_osresetsystem_cheats_address);
}
}; };
class OSResetSystemPatchCode : public PatchCode class OSResetSystemPatchCode : public PatchCode

View File

@@ -108,16 +108,24 @@ patch_osresetsystem_bootPicoLoader:
ldmia r5, {r3, r5} ldmia r5, {r3, r5}
ldrh r0, [r3, #2] // loader_info_t::picoLoaderBootDrive ldrh r0, [r3, #2] // loader_info_t::picoLoaderBootDrive
strh r0, [r5, #8] // pload_header7_t::bootDrive strh r0, [r5, #8] // pload_header7_t::bootDrive
ldr r0, [r5] // pload_header7_t::entryPoint
adr r0, regVramCntA
ldmia r0, {r0, r4, r6, r7}
// r0 = regVramCntA
// r4 = patch_osresetsystem_arm7Entry_address
// r6 = vramCDSettings
// r7 = patch_osresetsystem_cheats_address
movs r2, #0x41
lsls r2, r2, #4 // 0x410
str r7, [r5, r2] // pload_header7_t::v3.cheats
ldr r1, [r5] // pload_header7_t::entryPoint
// set NTR_SHARED_MEMORY->romHeader.arm7EntryAddress // set NTR_SHARED_MEMORY->romHeader.arm7EntryAddress
ldr r4, patch_osresetsystem_arm7Entry_address str r1, [r4]
str r0, [r4]
// map vram CD to arm7 // map vram CD to arm7
ldr r0,= 0x04000240 strh r6, [r0, #2]
ldr r7,= 0x8A82
strh r7, [r0, #2]
adds r0, #(0x04000180 - 0x04000240) // REG_IPC_SYNC adds r0, #(0x04000180 - 0x04000240) // REG_IPC_SYNC
movs r1, #1 movs r1, #1
@@ -139,21 +147,17 @@ twl_arm7_sync:
ldr r7,= 0x02FFFC24 ldr r7,= 0x02FFFC24
movs r1, #1 movs r1, #1
strh r1, [r7, #4] strh r1, [r7, #4]
mov r11, pc
ldrh r6, [r7, #2] b do_sync
ldrh r1, [r7]
1:
adds r1, #1
strh r1, [r7]
ldrh r4, [r7, #2]
cmp r6, r4
beq 1b
adds r1, #1
strh r1, [r7]
movs r1, #3 movs r1, #3
strh r1, [r7, #4] strh r1, [r7, #4]
mov r11, pc
b do_sync
mov pc, lr
do_sync:
ldrh r6, [r7, #2] ldrh r6, [r7, #2]
ldrh r1, [r7] ldrh r1, [r7]
1: 1:
@@ -164,14 +168,23 @@ twl_arm7_sync:
beq 1b beq 1b
adds r1, #1 adds r1, #1
strh r1, [r7] strh r1, [r7]
mov pc, r11
mov pc, lr
.balign 4 .balign 4
regVramCntA:
.word 0x04000240
.global patch_osresetsystem_arm7Entry_address .global patch_osresetsystem_arm7Entry_address
patch_osresetsystem_arm7Entry_address: patch_osresetsystem_arm7Entry_address:
.word 0x027FFE34 .word 0x027FFE34
vramCDSettings:
.word 0x8A82
.global patch_osresetsystem_cheats_address
patch_osresetsystem_cheats_address:
.word 0
.pool .pool
.end .end