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

@ -239,24 +239,33 @@ Result InputRedirection_DoOrUndoPatches(void)
if(R_SUCCEEDED(res))
{
static u32 irOrigReadingCode[5] = {
0xE5940000, // ldr r0, [r4]
0xE1A01005, // mov r1, r5
0xE3A03005, // mov r3, #5
0xE3A02011, // mov r2, #17
0xE5940000, // ldr r0, [r4]
0xE1A01005, // mov r1, r5
0xE3A03005, // mov r3, #5
0xE3A02011, // mov r2, #17
0x00000000 // (bl i2c_read_raw goes here)
};
static const u32 irOrigWaitSyncCode[] = {
0xEF000024, // svc 0x24 (WaitSynchronization)
0xE1B01FA0, // movs r1, r0,lsr#31
0xE1B01FA0, // movs r1, r0, lsr#31
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)
{
memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode));
memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode));
memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode));
}
else
{
@ -264,10 +273,10 @@ Result InputRedirection_DoOrUndoPatches(void)
u32 irCodePhys = (u32)PA_FROM_VA_PTR(&irCodePatchFunc);
u32 irHook[] = {
0xE59F0004, // ldr r0, [pc, #4]
0xE59FC004, // ldr r12, [pc, #4]
0xE12FFF1C, // bx r12
irDataPhys,
0xE5940000, // ldr r0, [r4]
0xE1A01005, // mov r1, r5
0xE59FC000, // ldr r12, [pc] (actually +8)
0xE12FFF3C, // blx r12
irCodePhys,
};
@ -285,17 +294,29 @@ Result InputRedirection_DoOrUndoPatches(void)
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;
irWaitSyncLoc = off2;
irCppFlagLoc = off3;
irOrigReadingCode[4] = off[4]; // Copy the branch.
irOrigReadingCode[4] = off[4];
memcpy(irHookLoc, &irHook, sizeof(irHook));
// This "NOP"s out a WaitSynchronisation1 (on the event bound to the 'IR' interrupt)
*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
.type irCodePatchFunc, %function
irCodePatchFunc:
add lr, lr, #4 @ Skip the address in the hook when we return to the original function
b skip_vars
i2c_readdeviceraw_addr:
.word 0
redirected_input_addr:
.word 0
skip_vars:
@ Address to read from is passed by the hook, save it.
mov r6, r0
stmfd sp!, {r4-r5, lr}
ir_check_i2c:
@ Original code. Does an i2c read at device 17 func 5.
ldr r0, [r4]
mov r1, r5
@ r0 and r1 were set up by the hook
mov r4, r1 @ save r1
mov r2, #17
mov r3, #5
@ -123,18 +124,21 @@ adr r12, i2c_readdeviceraw_addr
ldr r12, [r12]
blx r12
adr r5, redirected_input_addr
ldr r5, [r5]
ldr r1, =0x80800081 @ no c-stick activity / zlzr not pressed
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
movne r2, r1
cmp r1, r2
ldreq r0, [r6] @ Pull the remote input in.
streq r0, [r5] @ store it instead of the value read from i2c
ldreq r0, [r5] @ Pull the remote input in.
streq r0, [r4] @ store it instead of the value read from i2c
@ Return!
ldmfd sp!, {r4-r6,pc}
.pool
mov r0, #0 @ For ir:user.
ldmfd sp!, {r4-r5, pc}
.pool