From c0059c83aca3b20740e265276bc5992c90989da1 Mon Sep 17 00:00:00 2001 From: Ezekiel Bethel Date: Wed, 7 Jun 2017 17:32:39 +0100 Subject: [PATCH] inputredirection hook in ir:user cpp emulation => c-stick works in games now, also hook refactoring --- .../rosalina/source/input_redirection.c | 47 ++++++++++++++----- .../rosalina/source/input_redirection_hooks.s | 28 ++++++----- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/sysmodules/rosalina/source/input_redirection.c b/sysmodules/rosalina/source/input_redirection.c index b8f3798..0c4a5e0 100644 --- a/sysmodules/rosalina/source/input_redirection.c +++ b/sysmodules/rosalina/source/input_redirection.c @@ -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; } } diff --git a/sysmodules/rosalina/source/input_redirection_hooks.s b/sysmodules/rosalina/source/input_redirection_hooks.s index 0d5da78..315499b 100644 --- a/sysmodules/rosalina/source/input_redirection_hooks.s +++ b/sysmodules/rosalina/source/input_redirection_hooks.s @@ -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 \ No newline at end of file