inputredirection hook in ir:user cpp emulation => c-stick works in games now, also hook refactoring
This commit is contained in:
parent
37eb21d297
commit
c0059c83ac
@ -243,20 +243,29 @@ Result InputRedirection_DoOrUndoPatches(void)
|
|||||||
0xE1A01005, // mov r1, r5
|
0xE1A01005, // mov r1, r5
|
||||||
0xE3A03005, // mov r3, #5
|
0xE3A03005, // mov r3, #5
|
||||||
0xE3A02011, // mov r2, #17
|
0xE3A02011, // mov r2, #17
|
||||||
|
0x00000000 // (bl i2c_read_raw goes here)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u32 irOrigWaitSyncCode[] = {
|
static const u32 irOrigWaitSyncCode[] = {
|
||||||
0xEF000024, // svc 0x24 (WaitSynchronization)
|
0xEF000024, // svc 0x24 (WaitSynchronization)
|
||||||
0xE1B01FA0, // movs r1, r0,lsr#31
|
0xE1B01FA0, // movs r1, r0, lsr#31
|
||||||
0xE1A0A000, // mov r10, r0
|
0xE1A0A000, // mov r10, r0
|
||||||
};
|
};
|
||||||
|
|
||||||
static u32 *irHookLoc, *irWaitSyncLoc;
|
static const u32 irOrigCppFlagCode[] = {
|
||||||
|
0xE3550000, // cmp r5, #0
|
||||||
|
0xE3A0B080, // mov r11, #0x80
|
||||||
|
0xE28D0060, // add r0, sp, #0xb0+var_50
|
||||||
|
0x0A00002C // beq loc_105688
|
||||||
|
};
|
||||||
|
|
||||||
|
static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc;
|
||||||
|
|
||||||
if(inputRedirectionEnabled)
|
if(inputRedirectionEnabled)
|
||||||
{
|
{
|
||||||
memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode));
|
memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode));
|
||||||
memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode));
|
memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode));
|
||||||
|
memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -264,10 +273,10 @@ Result InputRedirection_DoOrUndoPatches(void)
|
|||||||
u32 irCodePhys = (u32)PA_FROM_VA_PTR(&irCodePatchFunc);
|
u32 irCodePhys = (u32)PA_FROM_VA_PTR(&irCodePatchFunc);
|
||||||
|
|
||||||
u32 irHook[] = {
|
u32 irHook[] = {
|
||||||
0xE59F0004, // ldr r0, [pc, #4]
|
0xE5940000, // ldr r0, [r4]
|
||||||
0xE59FC004, // ldr r12, [pc, #4]
|
0xE1A01005, // mov r1, r5
|
||||||
0xE12FFF1C, // bx r12
|
0xE59FC000, // ldr r12, [pc] (actually +8)
|
||||||
irDataPhys,
|
0xE12FFF3C, // blx r12
|
||||||
irCodePhys,
|
irCodePhys,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -285,17 +294,29 @@ Result InputRedirection_DoOrUndoPatches(void)
|
|||||||
return -5;
|
return -5;
|
||||||
}
|
}
|
||||||
|
|
||||||
*(void **)(irCodePhys + 4) = decodeARMBranch(off + 4);
|
u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &irOrigCppFlagCode, totalSize, sizeof(irOrigCppFlagCode));
|
||||||
|
if(off3 == NULL)
|
||||||
|
{
|
||||||
|
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(void **)(irCodePhys + 8) = decodeARMBranch(off + 4);
|
||||||
|
*(void **)(irCodePhys + 12) = (void*)irDataPhys;
|
||||||
|
|
||||||
irHookLoc = off;
|
irHookLoc = off;
|
||||||
irWaitSyncLoc = off2;
|
irWaitSyncLoc = off2;
|
||||||
|
irCppFlagLoc = off3;
|
||||||
|
|
||||||
|
irOrigReadingCode[4] = off[4]; // Copy the branch.
|
||||||
|
|
||||||
irOrigReadingCode[4] = off[4];
|
|
||||||
memcpy(irHookLoc, &irHook, sizeof(irHook));
|
memcpy(irHookLoc, &irHook, sizeof(irHook));
|
||||||
|
|
||||||
// This "NOP"s out a WaitSynchronisation1 (on the event bound to the 'IR' interrupt)
|
// This "NOP"s out a WaitSynchronisation1 (on the event bound to the 'IR' interrupt)
|
||||||
*irWaitSyncLoc = 0xE3A00000; // mov r0, #0
|
*irWaitSyncLoc = 0xE3A00000; // mov r0, #0
|
||||||
memcpy((u32*)irHookLoc, irHook, sizeof(irHook));
|
|
||||||
|
// This NOPs out a flag check in ir:user's CPP emulation
|
||||||
|
*(irCppFlagLoc+3) = 0xea00002c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,20 +102,21 @@ pop {r4-r6, pc}
|
|||||||
.global irCodePatchFunc
|
.global irCodePatchFunc
|
||||||
.type irCodePatchFunc, %function
|
.type irCodePatchFunc, %function
|
||||||
irCodePatchFunc:
|
irCodePatchFunc:
|
||||||
|
add lr, lr, #4 @ Skip the address in the hook when we return to the original function
|
||||||
b skip_vars
|
b skip_vars
|
||||||
|
|
||||||
i2c_readdeviceraw_addr:
|
i2c_readdeviceraw_addr:
|
||||||
.word 0
|
.word 0
|
||||||
|
redirected_input_addr:
|
||||||
|
.word 0
|
||||||
|
|
||||||
skip_vars:
|
skip_vars:
|
||||||
|
stmfd sp!, {r4-r5, lr}
|
||||||
@ Address to read from is passed by the hook, save it.
|
|
||||||
mov r6, r0
|
|
||||||
|
|
||||||
ir_check_i2c:
|
ir_check_i2c:
|
||||||
@ Original code. Does an i2c read at device 17 func 5.
|
@ Original code. Does an i2c read at device 17 func 5.
|
||||||
ldr r0, [r4]
|
@ r0 and r1 were set up by the hook
|
||||||
mov r1, r5
|
|
||||||
|
mov r4, r1 @ save r1
|
||||||
mov r2, #17
|
mov r2, #17
|
||||||
mov r3, #5
|
mov r3, #5
|
||||||
|
|
||||||
@ -123,18 +124,21 @@ adr r12, i2c_readdeviceraw_addr
|
|||||||
ldr r12, [r12]
|
ldr r12, [r12]
|
||||||
blx r12
|
blx r12
|
||||||
|
|
||||||
|
adr r5, redirected_input_addr
|
||||||
|
ldr r5, [r5]
|
||||||
|
|
||||||
ldr r1, =0x80800081 @ no c-stick activity / zlzr not pressed
|
ldr r1, =0x80800081 @ no c-stick activity / zlzr not pressed
|
||||||
cmp r0, #0 @ check if the i2c read succeeded completely
|
cmp r0, #0 @ check if the i2c read succeeded completely
|
||||||
|
|
||||||
ldreq r2, [r5]
|
ldreq r2, [r4]
|
||||||
tsteq r2, #0x100 @ apparently this is set only if the c-stick hasn't been moved yet
|
tsteq r2, #0x100 @ apparently this is set only if the c-stick hasn't been moved yet
|
||||||
movne r2, r1
|
movne r2, r1
|
||||||
|
|
||||||
cmp r1, r2
|
cmp r1, r2
|
||||||
ldreq r0, [r6] @ Pull the remote input in.
|
ldreq r0, [r5] @ Pull the remote input in.
|
||||||
streq r0, [r5] @ store it instead of the value read from i2c
|
streq r0, [r4] @ store it instead of the value read from i2c
|
||||||
|
|
||||||
@ Return!
|
@ Return!
|
||||||
ldmfd sp!, {r4-r6,pc}
|
mov r0, #0 @ For ir:user.
|
||||||
|
ldmfd sp!, {r4-r5, pc}
|
||||||
.pool
|
.pool
|
Reference in New Issue
Block a user