mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-02 09:16:49 +02:00
Use OSi_IrqVBlank for cheat patching (#156)
This commit is contained in:
@@ -3,89 +3,38 @@
|
|||||||
#include "CheatEnginePatchCode.h"
|
#include "CheatEnginePatchCode.h"
|
||||||
#include "CheatEnginePatch.h"
|
#include "CheatEnginePatch.h"
|
||||||
|
|
||||||
// sdk2-4
|
static const u32 sOSiIrqVBlankPattern0[] = { 0xE92D4008u, 0xE59F2038u, 0xE59F0038u, 0xE5921000u };
|
||||||
static const u32 sVBlankIntrPatternArm0[] = { 0xE92D4000u, 0xE24DD004u, 0xE59F0018u, 0xE5900000u };
|
static const u32 sOSiIrqVBlankPattern1[] = { 0xE92D4000u, 0xE24DD004u, 0xE59F003Cu, 0xE5902060u };
|
||||||
static const u32 sVBlankIntrPatternArm1[] = { 0xE92D4008u, 0xE59F0014u, 0xE5900000u, 0xE3500000u };
|
static const u32 sOSiIrqVBlankPatternThumb0[] = { 0x4809B508u, 0x69024909u, 0x1C406808u, 0x2A006008u };
|
||||||
static const u32 sVBlankIntrPatternThumb0[] = { 0x00000000u, 0xB081B500u, 0x68004804u, 0xD0012800u }; // +4
|
|
||||||
static const u32 sVBlankIntrPatternThumb1[] = { 0x46C04770u, 0x027FFE1Du, 0x4804B508u, 0x28006800u }; // +8
|
|
||||||
static const u32 sVBlankIntrPatternThumb2[] = { 0x46C04718u, 0x0000FFFFu, 0x4804B508u, 0x28006800u }; // +8
|
|
||||||
static const u32 sVBlankIntrPatternThumb3[] = { 0xE51FF004u, 0x037FD67Cu, 0x4804B508u, 0x28006800u }; // +8
|
|
||||||
static const u32 sVBlankIntrPatternThumb4[] = { 0x46C04770u, 0x02FFFE1Du, 0x4804B508u, 0x28006800u }; // +8
|
|
||||||
static const u32 sVBlankIntrPatternThumb5[] = { 0xE51FF004u, 0x037FA868u, 0x4804B508u, 0x28006800u }; // +8
|
|
||||||
|
|
||||||
bool CheatEnginePatch::FindPatchTarget(PatchContext& patchContext)
|
bool CheatEnginePatch::FindPatchTarget(PatchContext& patchContext)
|
||||||
{
|
{
|
||||||
_vblankIrqHandler = patchContext.FindPattern32(sVBlankIntrPatternArm0, sizeof(sVBlankIntrPatternArm0));
|
_vblankIrqHandler = patchContext.FindPattern32(sOSiIrqVBlankPattern0, sizeof(sOSiIrqVBlankPattern0));
|
||||||
if (_vblankIrqHandler)
|
if (_vblankIrqHandler)
|
||||||
{
|
{
|
||||||
_foundPattern = sVBlankIntrPatternArm0;
|
_foundPattern = sOSiIrqVBlankPattern0;
|
||||||
}
|
}
|
||||||
if (!_vblankIrqHandler)
|
if (!_vblankIrqHandler)
|
||||||
{
|
{
|
||||||
_vblankIrqHandler = patchContext.FindPattern32(sVBlankIntrPatternArm1, sizeof(sVBlankIntrPatternArm1));
|
_vblankIrqHandler = patchContext.FindPattern32(sOSiIrqVBlankPattern1, sizeof(sOSiIrqVBlankPattern1));
|
||||||
if (_vblankIrqHandler)
|
if (_vblankIrqHandler)
|
||||||
{
|
{
|
||||||
_foundPattern = sVBlankIntrPatternArm1;
|
_foundPattern = sOSiIrqVBlankPattern1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_vblankIrqHandler)
|
if (!_vblankIrqHandler)
|
||||||
{
|
{
|
||||||
_vblankIrqHandler = patchContext.FindPattern32(sVBlankIntrPatternThumb0, sizeof(sVBlankIntrPatternThumb0));
|
_vblankIrqHandler = patchContext.FindPattern32(sOSiIrqVBlankPatternThumb0, sizeof(sOSiIrqVBlankPatternThumb0));
|
||||||
if (_vblankIrqHandler)
|
if (_vblankIrqHandler)
|
||||||
{
|
{
|
||||||
_foundPattern = sVBlankIntrPatternThumb0;
|
_foundPattern = sOSiIrqVBlankPatternThumb0;
|
||||||
_vblankIrqHandler += 1;
|
_thumb = true;
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!_vblankIrqHandler)
|
|
||||||
{
|
|
||||||
_vblankIrqHandler = patchContext.FindPattern32(sVBlankIntrPatternThumb1, sizeof(sVBlankIntrPatternThumb1));
|
|
||||||
if (_vblankIrqHandler)
|
|
||||||
{
|
|
||||||
_foundPattern = sVBlankIntrPatternThumb1;
|
|
||||||
_vblankIrqHandler += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!_vblankIrqHandler)
|
|
||||||
{
|
|
||||||
_vblankIrqHandler = patchContext.FindPattern32(sVBlankIntrPatternThumb2, sizeof(sVBlankIntrPatternThumb2));
|
|
||||||
if (_vblankIrqHandler)
|
|
||||||
{
|
|
||||||
_foundPattern = sVBlankIntrPatternThumb2;
|
|
||||||
_vblankIrqHandler += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!_vblankIrqHandler)
|
|
||||||
{
|
|
||||||
_vblankIrqHandler = patchContext.FindPattern32(sVBlankIntrPatternThumb3, sizeof(sVBlankIntrPatternThumb3));
|
|
||||||
if (_vblankIrqHandler)
|
|
||||||
{
|
|
||||||
_foundPattern = sVBlankIntrPatternThumb3;
|
|
||||||
_vblankIrqHandler += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!_vblankIrqHandler)
|
|
||||||
{
|
|
||||||
_vblankIrqHandler = patchContext.FindPattern32(sVBlankIntrPatternThumb4, sizeof(sVBlankIntrPatternThumb4));
|
|
||||||
if (_vblankIrqHandler)
|
|
||||||
{
|
|
||||||
_foundPattern = sVBlankIntrPatternThumb4;
|
|
||||||
_vblankIrqHandler += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!_vblankIrqHandler)
|
|
||||||
{
|
|
||||||
_vblankIrqHandler = patchContext.FindPattern32(sVBlankIntrPatternThumb5, sizeof(sVBlankIntrPatternThumb5));
|
|
||||||
if (_vblankIrqHandler)
|
|
||||||
{
|
|
||||||
_foundPattern = sVBlankIntrPatternThumb5;
|
|
||||||
_vblankIrqHandler += 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_vblankIrqHandler)
|
if (_vblankIrqHandler)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("ARM7 VBlankIntr found at 0x%p\n", _vblankIrqHandler);
|
LOG_DEBUG("ARM7 OSi_IrqVBlank found at 0x%p\n", _vblankIrqHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _vblankIrqHandler != nullptr;
|
return _vblankIrqHandler != nullptr;
|
||||||
@@ -102,91 +51,35 @@ void CheatEnginePatch::ApplyPatch(PatchContext& patchContext)
|
|||||||
_cheats
|
_cheats
|
||||||
);
|
);
|
||||||
|
|
||||||
if (_foundPattern == sVBlankIntrPatternArm0)
|
int patchOffset;
|
||||||
|
if (_foundPattern == sOSiIrqVBlankPattern0)
|
||||||
{
|
{
|
||||||
// push {lr}
|
patchOffset = 0x3C;
|
||||||
// sub sp, sp, #4
|
|
||||||
// ldr r0,=
|
|
||||||
// ldr r0, [r0]
|
|
||||||
// cmp r0, #0
|
|
||||||
// beq 1f
|
|
||||||
// bl
|
|
||||||
// 1:
|
|
||||||
// add sp, sp, #4
|
|
||||||
// pop {lr}
|
|
||||||
// bx lr
|
|
||||||
_vblankIrqHandler[7] = 0xE59F0000; // ldr r0,= address
|
|
||||||
_vblankIrqHandler[8] = 0xE12FFF10; // bx r0
|
|
||||||
_vblankIrqHandler[9] = (u32)cheatEnginePatchCode->GetCheatEngineFunction(); // address
|
|
||||||
}
|
}
|
||||||
else if (_foundPattern == sVBlankIntrPatternArm1)
|
else if (_foundPattern == sOSiIrqVBlankPattern1)
|
||||||
{
|
{
|
||||||
// push {r3,lr}
|
patchOffset = 0x40;
|
||||||
// ldr r0,=
|
|
||||||
// ldr r0, [r0]
|
|
||||||
// cmp r0, #0
|
|
||||||
// beq 1f
|
|
||||||
// bl
|
|
||||||
// 1:
|
|
||||||
// pop {r3,lr}
|
|
||||||
// bx lr
|
|
||||||
_vblankIrqHandler[6] = 0xE51FF004; // ldr pc,= address
|
|
||||||
_vblankIrqHandler[7] = (u32)cheatEnginePatchCode->GetCheatEngineFunctionArm(); // address
|
|
||||||
}
|
}
|
||||||
else if (_foundPattern == sVBlankIntrPatternThumb0)
|
else if (_foundPattern == sOSiIrqVBlankPatternThumb0)
|
||||||
{
|
{
|
||||||
// push {lr}
|
patchOffset = 0x20;
|
||||||
// sub sp, sp, #4
|
|
||||||
// ldr r0,=
|
|
||||||
// ldr r0, [r0]
|
|
||||||
// cmp r0, #0
|
|
||||||
// beq 1f
|
|
||||||
// bl
|
|
||||||
// 1:
|
|
||||||
// add sp, sp, #4
|
|
||||||
// pop {r3}
|
|
||||||
// bx r3
|
|
||||||
// nop
|
|
||||||
((u16*)_vblankIrqHandler)[8] = THUMB_LDR_PC_IMM(THUMB_R1, 0); // ldr r1,= address
|
|
||||||
((u16*)_vblankIrqHandler)[9] = THUMB_BX(THUMB_R1); // bx r1
|
|
||||||
_vblankIrqHandler[10 >> 1] = (u32)cheatEnginePatchCode->GetCheatEngineFunction(); // address
|
|
||||||
}
|
|
||||||
else if (_foundPattern == sVBlankIntrPatternThumb1
|
|
||||||
|| _foundPattern == sVBlankIntrPatternThumb2
|
|
||||||
|| _foundPattern == sVBlankIntrPatternThumb3
|
|
||||||
|| _foundPattern == sVBlankIntrPatternThumb4
|
|
||||||
|| _foundPattern == sVBlankIntrPatternThumb5)
|
|
||||||
{
|
|
||||||
// push {r3,lr}
|
|
||||||
// ldr r0,=
|
|
||||||
// ldr r0, [r0]
|
|
||||||
// cmp r0, #0
|
|
||||||
// beq 1f
|
|
||||||
// bl
|
|
||||||
// 1:
|
|
||||||
// pop {r3}
|
|
||||||
// pop {r3}
|
|
||||||
// bx r3
|
|
||||||
|
|
||||||
// rewrite the function to
|
|
||||||
// add r1, pc, #4
|
|
||||||
// ldr r0,=
|
|
||||||
// ldr r2,= cheatengine_entry_thumb_replace
|
|
||||||
// bx r2
|
|
||||||
// beq 1f
|
|
||||||
// bl
|
|
||||||
// 1:
|
|
||||||
// mov pc, r4
|
|
||||||
// .word cheatengine_entry_thumb_replace
|
|
||||||
|
|
||||||
((u16*)_vblankIrqHandler)[0] = THUMB_ADD_PC_IMM(THUMB_R1, 4); // add r1, pc, #4
|
|
||||||
((u16*)_vblankIrqHandler)[2] = THUMB_LDR_PC_IMM(THUMB_R2, 8); // ldr r2,= cheatengine_entry_thumb_replace
|
|
||||||
((u16*)_vblankIrqHandler)[3] = THUMB_BX(THUMB_R2); // bx r2
|
|
||||||
((u16*)_vblankIrqHandler)[7] = THUMB_MOV_HIREG(THUMB_HI_PC, THUMB_R4); // mov pc, r4
|
|
||||||
_vblankIrqHandler[8 >> 1] = (u32)cheatEnginePatchCode->GetCheatEngineFunctionThumbReplace(); // .word cheatengine_entry_thumb_replace
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_ERROR("ARM7 VBlankIntr signature not implemented\n");
|
LOG_ERROR("ARM7 OSi_IrqVBlank signature not implemented\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_thumb)
|
||||||
|
{
|
||||||
|
*(u16*)((u8*)_vblankIrqHandler + patchOffset + 0) = THUMB_LDR_PC_IMM(THUMB_R1, 0); // ldr r1,= address
|
||||||
|
*(u16*)((u8*)_vblankIrqHandler + patchOffset + 2) = THUMB_BX(THUMB_R1); // bx r1
|
||||||
|
*(u32*)((u8*)_vblankIrqHandler + patchOffset + 4) = (u32)cheatEnginePatchCode->GetCheatEngineFunction(); // address
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(u32*)((u8*)_vblankIrqHandler + patchOffset + 0) = 0xE51FF004; // ldr pc,= address
|
||||||
|
*(u32*)((u8*)_vblankIrqHandler + patchOffset + 4) = (u32)cheatEnginePatchCode->GetCheatEngineFunctionArm(); // address
|
||||||
|
}
|
||||||
|
LOG_DEBUG("Cheats enabled\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,5 @@ private:
|
|||||||
const void* _cheats;
|
const void* _cheats;
|
||||||
u32* _vblankIrqHandler = nullptr;
|
u32* _vblankIrqHandler = nullptr;
|
||||||
const u32* _foundPattern = nullptr;
|
const u32* _foundPattern = nullptr;
|
||||||
|
u16 _thumb = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
DEFINE_SECTION_SYMBOLS(patch_cheatengine);
|
DEFINE_SECTION_SYMBOLS(patch_cheatengine);
|
||||||
|
|
||||||
extern "C" void cheatengine_entry_arm(void);
|
extern "C" void cheatengine_entry_arm(void);
|
||||||
extern "C" void cheatengine_entry_thumb_replace(void);
|
|
||||||
extern "C" void cheatengine_entry(void);
|
extern "C" void cheatengine_entry(void);
|
||||||
|
|
||||||
extern const void* cheatengine_cheatsPtr;
|
extern const void* cheatengine_cheatsPtr;
|
||||||
@@ -28,9 +27,4 @@ public:
|
|||||||
{
|
{
|
||||||
return GetAddressAtTarget((void*)cheatengine_entry_arm);
|
return GetAddressAtTarget((void*)cheatengine_entry_arm);
|
||||||
}
|
}
|
||||||
|
|
||||||
const void* GetCheatEngineFunctionThumbReplace() const
|
|
||||||
{
|
|
||||||
return GetAddressAtTarget((void*)cheatengine_entry_thumb_replace);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,21 +14,6 @@ cheatengine_entry_arm:
|
|||||||
bx r12
|
bx r12
|
||||||
|
|
||||||
.thumb
|
.thumb
|
||||||
.global cheatengine_entry_thumb_replace
|
|
||||||
.type cheatengine_entry_thumb_replace, %function
|
|
||||||
cheatengine_entry_thumb_replace:
|
|
||||||
push {r4, r5, lr} // r5 is a dummy
|
|
||||||
ldr r0, [r0]
|
|
||||||
adr r4, cheatengine_entry_thumb_replace_return
|
|
||||||
cmp r0, #0
|
|
||||||
mov pc, r1
|
|
||||||
|
|
||||||
.balign 4
|
|
||||||
|
|
||||||
cheatengine_entry_thumb_replace_return:
|
|
||||||
pop {r4}
|
|
||||||
nop
|
|
||||||
|
|
||||||
.global cheatengine_entry
|
.global cheatengine_entry
|
||||||
.type cheatengine_entry, %function
|
.type cheatengine_entry, %function
|
||||||
cheatengine_entry:
|
cheatengine_entry:
|
||||||
|
|||||||
Reference in New Issue
Block a user