inputredirection hook in ir:user cpp emulation => c-stick works in games now, also hook refactoring

This commit is contained in:
Ezekiel Bethel 2017-06-07 17:32:39 +01:00
parent 37eb21d297
commit c0059c83ac
No known key found for this signature in database
GPG Key ID: 6915A190A8C54CCB
2 changed files with 50 additions and 25 deletions

View File

@ -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;
} }
} }

View File

@ -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