rosalina inputredir: Use ir patch from @Nanquitas ; also refactor the code
Fixes #1428, #1438 (I think)
This commit is contained in:
parent
9ca52054cf
commit
b17eb66d55
@ -168,6 +168,246 @@ void inputRedirectionThreadMain(void)
|
|||||||
void hidCodePatchFunc(void);
|
void hidCodePatchFunc(void);
|
||||||
void irCodePatchFunc(void);
|
void irCodePatchFunc(void);
|
||||||
|
|
||||||
|
static Result InputRedirection_DoUndoIrPatches(Handle processHandle, bool doPatch)
|
||||||
|
{
|
||||||
|
static u32* hookLoc = NULL;
|
||||||
|
static u32* syncLoc = NULL;
|
||||||
|
static u32* cppFlagLoc = NULL;
|
||||||
|
static u32 origIrSync = 0;
|
||||||
|
static u32 origCppFlag = 0;
|
||||||
|
|
||||||
|
static bool patchPrepared = false;
|
||||||
|
|
||||||
|
static u32 irOrigReadingCode[5] = {
|
||||||
|
0xE5940000, // ldr r0, [r4]
|
||||||
|
0xE1A01005, // mov r1, r5
|
||||||
|
0xE3A03005, // mov r3, #5
|
||||||
|
0xE3A02011, // mov r2, #17
|
||||||
|
0x00000000 // (bl i2c_read_raw goes here)
|
||||||
|
};
|
||||||
|
|
||||||
|
static u32 irHook[] = {
|
||||||
|
0xE5940000, // ldr r0, [r4]
|
||||||
|
0xE1A01005, // mov r1, r5
|
||||||
|
0xE59FC000, // ldr r12, [pc] (actually +8)
|
||||||
|
0xE12FFF3C, // blx r12
|
||||||
|
0x00000000 // irCodePhys goes here
|
||||||
|
};
|
||||||
|
|
||||||
|
static u32 syncHookCode[] = {
|
||||||
|
0xE5900000, // ldr r0, [r0]
|
||||||
|
0xEF000024, // svc 0x24
|
||||||
|
0xE3A00000, // mov r0, #0
|
||||||
|
0xE51FF004, // ldr pc, [pc, #-4]
|
||||||
|
0x00000000, // (return address goes here)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find offsets for required patches
|
||||||
|
s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
|
||||||
|
u32 totalSize;
|
||||||
|
Result res;
|
||||||
|
|
||||||
|
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
|
||||||
|
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
|
||||||
|
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
|
||||||
|
|
||||||
|
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
||||||
|
|
||||||
|
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
|
||||||
|
res = svcMapProcessMemoryEx(processHandle, 0x00100000, (u32) startAddress, totalSize);
|
||||||
|
|
||||||
|
if(R_SUCCEEDED(res) && !patchPrepared)
|
||||||
|
{
|
||||||
|
static const u32 irOrigWaitSyncCode[] = {
|
||||||
|
0xEF000024, // svc 0x24 (WaitSynchronization)
|
||||||
|
0xE1B01FA0, // movs r1, r0, lsr#31
|
||||||
|
0xE1A0A000, // mov r10, r0
|
||||||
|
}, irOrigWaitSyncCodeOld[] = {
|
||||||
|
0xE0AC6000, // adc r6, r12, r0
|
||||||
|
0xE5D70000, // ldrb r0, [r7]
|
||||||
|
}; // pattern for 8.1
|
||||||
|
|
||||||
|
static const u32 irOrigCppFlagCode[] = {
|
||||||
|
0xE3550000, // cmp r5, #0
|
||||||
|
0xE3A0B080, // mov r11, #0x80
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 irDataPhys = (u32)PA_FROM_VA_PTR(irData);
|
||||||
|
u32 irCodePhys = (u32)PA_FROM_VA_PTR(&irCodePatchFunc);
|
||||||
|
|
||||||
|
u32 *off = (u32 *)memsearch((u8 *)0x00100000, &irOrigReadingCode, totalSize, sizeof(irOrigReadingCode) - 4);
|
||||||
|
if(off == NULL)
|
||||||
|
{
|
||||||
|
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 *off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCode, totalSize, sizeof(irOrigWaitSyncCode));
|
||||||
|
if(off2 == NULL)
|
||||||
|
{
|
||||||
|
off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCodeOld, totalSize, sizeof(irOrigWaitSyncCodeOld));
|
||||||
|
if(off2 == NULL)
|
||||||
|
{
|
||||||
|
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &irOrigCppFlagCode, totalSize, sizeof(irOrigCppFlagCode));
|
||||||
|
if(off3 == NULL)
|
||||||
|
{
|
||||||
|
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
origIrSync = *off2;
|
||||||
|
origCppFlag = *off3;
|
||||||
|
|
||||||
|
*(void **)(irCodePhys + 8) = decodeArmBranch(off + 4);
|
||||||
|
*(void **)(irCodePhys + 12) = (void*)irDataPhys;
|
||||||
|
|
||||||
|
irHook[4] = irCodePhys;
|
||||||
|
irOrigReadingCode[4] = off[4]; // Copy the branch.
|
||||||
|
syncHookCode[4] = (u32)off2 + 4; // Hook return address
|
||||||
|
|
||||||
|
hookLoc = PA_FROM_VA_PTR(off);
|
||||||
|
syncLoc = PA_FROM_VA_PTR(off2);
|
||||||
|
cppFlagLoc = PA_FROM_VA_PTR(off3);
|
||||||
|
|
||||||
|
patchPrepared = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(res))
|
||||||
|
{
|
||||||
|
if (doPatch)
|
||||||
|
{
|
||||||
|
memcpy(hookLoc, &irHook, sizeof(irHook));
|
||||||
|
|
||||||
|
// We keep the WaitSynchronization1 to avoid general slowdown because of the high cpu load
|
||||||
|
if (*syncLoc == 0xEF000024) // svc 0x24 (WaitSynchronization)
|
||||||
|
{
|
||||||
|
syncLoc[-1] = 0xE51FF004;
|
||||||
|
syncLoc[0] = (u32)PA_FROM_VA_PTR(&syncHookCode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This "NOP"s out a WaitSynchronisation1 (on the event bound to the 'IR' interrupt) or the check of a previous one
|
||||||
|
*syncLoc = 0xE3A00000; // mov r0, #0
|
||||||
|
}
|
||||||
|
|
||||||
|
// This NOPs out a flag check in ir:user's CPP emulation
|
||||||
|
*cppFlagLoc = 0xE3150000; // tst r5, #0
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(hookLoc, irOrigReadingCode, sizeof(irOrigReadingCode));
|
||||||
|
|
||||||
|
if (*syncLoc == 0xE3A00000)
|
||||||
|
*syncLoc = origIrSync;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syncLoc[-1] = 0xE5900000; // ldr r0, [r0]
|
||||||
|
syncLoc[0] = 0xEF000024; // svc 0x24
|
||||||
|
}
|
||||||
|
|
||||||
|
*cppFlagLoc = origCppFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svcInvalidateEntireInstructionCache();
|
||||||
|
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result InputRedirection_DoUndoHidPatches(Handle processHandle, bool doPatches)
|
||||||
|
{
|
||||||
|
static const u32 hidOrigRegisterAndValue[] = { 0x1EC46000, 0x4001 };
|
||||||
|
static const u32 hidOrigCode[] = {
|
||||||
|
0xE92D4070, // push {r4-r6, lr}
|
||||||
|
0xE1A05001, // mov r5, r1
|
||||||
|
0xEE1D4F70, // mrc p15, 0, r4, c13, c0, 3
|
||||||
|
0xE3A01801, // mov r1, #0x10000
|
||||||
|
0xE5A41080, // str r1, [r4,#0x80]!
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool patchPrepared = false;
|
||||||
|
static u32 *hidRegPatchOffsets[2];
|
||||||
|
static u32 *hidPatchJumpLoc;
|
||||||
|
|
||||||
|
// Find offsets for required patches
|
||||||
|
s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
|
||||||
|
u32 totalSize;
|
||||||
|
Result res;
|
||||||
|
|
||||||
|
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
|
||||||
|
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
|
||||||
|
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
|
||||||
|
|
||||||
|
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
||||||
|
|
||||||
|
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
|
||||||
|
res = svcMapProcessMemoryEx(processHandle, 0x00100000, (u32) startAddress, totalSize);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(res) && !patchPrepared)
|
||||||
|
{
|
||||||
|
u32 *off = (u32 *)memsearch((u8 *)0x00100000, &hidOrigRegisterAndValue, totalSize, sizeof(hidOrigRegisterAndValue));
|
||||||
|
if(off == NULL)
|
||||||
|
{
|
||||||
|
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 *off2 = (u32 *)memsearch((u8 *)off + sizeof(hidOrigRegisterAndValue), &hidOrigRegisterAndValue, totalSize - ((u32)off - 0x00100000), sizeof(hidOrigRegisterAndValue));
|
||||||
|
if(off2 == NULL)
|
||||||
|
{
|
||||||
|
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &hidOrigCode, totalSize, sizeof(hidOrigCode));
|
||||||
|
if(off3 == NULL)
|
||||||
|
{
|
||||||
|
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
hidRegPatchOffsets[0] = off;
|
||||||
|
hidRegPatchOffsets[1] = off2;
|
||||||
|
hidPatchJumpLoc = off3;
|
||||||
|
|
||||||
|
patchPrepared = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(R_SUCCEEDED(res))
|
||||||
|
{
|
||||||
|
if (doPatches)
|
||||||
|
{
|
||||||
|
u32 hidDataPhys = (u32)PA_FROM_VA_PTR(hidData);
|
||||||
|
u32 hidCodePhys = (u32)PA_FROM_VA_PTR(&hidCodePatchFunc);
|
||||||
|
u32 hidHook[] = {
|
||||||
|
0xE59F3004, // ldr r3, [pc, #4]
|
||||||
|
0xE59FC004, // ldr r12, [pc, #4]
|
||||||
|
0xE12FFF1C, // bx r12
|
||||||
|
hidDataPhys,
|
||||||
|
hidCodePhys,
|
||||||
|
};
|
||||||
|
|
||||||
|
*hidRegPatchOffsets[0] = *hidRegPatchOffsets[1] = hidDataPhys;
|
||||||
|
memcpy(hidPatchJumpLoc, &hidHook, sizeof(hidHook));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
|
||||||
|
memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
|
||||||
|
memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
Result InputRedirection_Disable(s64 timeout)
|
Result InputRedirection_Disable(s64 timeout)
|
||||||
{
|
{
|
||||||
if(!inputRedirectionEnabled)
|
if(!inputRedirectionEnabled)
|
||||||
@ -186,209 +426,46 @@ Result InputRedirection_Disable(s64 timeout)
|
|||||||
|
|
||||||
Result InputRedirection_DoOrUndoPatches(void)
|
Result InputRedirection_DoOrUndoPatches(void)
|
||||||
{
|
{
|
||||||
s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
|
|
||||||
u32 totalSize;
|
|
||||||
Handle processHandle;
|
|
||||||
|
|
||||||
Result res = OpenProcessByName("hid", &processHandle);
|
|
||||||
static bool hidPatched = false;
|
static bool hidPatched = false;
|
||||||
static bool irPatched = false;
|
static bool irPatched = false;
|
||||||
|
|
||||||
|
Handle hidProcHandle = 0, irProcHandle = 0;
|
||||||
|
|
||||||
|
// Prevent hid and ir from running, in any case
|
||||||
|
|
||||||
|
svcKernelSetState(0x10000, 4);
|
||||||
|
|
||||||
|
Result res = OpenProcessByName("hid", &hidProcHandle);
|
||||||
|
if (R_FAILED(res))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
res = OpenProcessByName("ir", &irProcHandle);
|
||||||
|
if (R_FAILED(res))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if(R_SUCCEEDED(res))
|
if(R_SUCCEEDED(res))
|
||||||
{
|
{
|
||||||
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
|
res = InputRedirection_DoUndoHidPatches(hidProcHandle, !hidPatched);
|
||||||
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
|
if (R_SUCCEEDED(res))
|
||||||
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
|
hidPatched = !hidPatched;
|
||||||
|
|
||||||
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
|
||||||
|
|
||||||
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
|
|
||||||
res = svcMapProcessMemoryEx(processHandle, 0x00100000, (u32) startAddress, totalSize);
|
|
||||||
|
|
||||||
if(R_SUCCEEDED(res))
|
|
||||||
{
|
|
||||||
static const u32 hidOrigRegisterAndValue[] = { 0x1EC46000, 0x4001 };
|
|
||||||
static const u32 hidOrigCode[] = {
|
|
||||||
0xE92D4070, // push {r4-r6, lr}
|
|
||||||
0xE1A05001, // mov r5, r1
|
|
||||||
0xEE1D4F70, // mrc p15, 0, r4, c13, c0, 3
|
|
||||||
0xE3A01801, // mov r1, #0x10000
|
|
||||||
0xE5A41080, // str r1, [r4,#0x80]!
|
|
||||||
};
|
|
||||||
|
|
||||||
static u32 *hidRegPatchOffsets[2];
|
|
||||||
static u32 *hidPatchJumpLoc;
|
|
||||||
|
|
||||||
if(hidPatched)
|
|
||||||
{
|
|
||||||
memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
|
|
||||||
memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
|
|
||||||
memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode));
|
|
||||||
hidPatched = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u32 hidDataPhys = (u32)PA_FROM_VA_PTR(hidData);
|
|
||||||
u32 hidCodePhys = (u32)PA_FROM_VA_PTR(&hidCodePatchFunc);
|
|
||||||
u32 hidHook[] = {
|
|
||||||
0xE59F3004, // ldr r3, [pc, #4]
|
|
||||||
0xE59FC004, // ldr r12, [pc, #4]
|
|
||||||
0xE12FFF1C, // bx r12
|
|
||||||
hidDataPhys,
|
|
||||||
hidCodePhys,
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 *off = (u32 *)memsearch((u8 *)0x00100000, &hidOrigRegisterAndValue, totalSize, sizeof(hidOrigRegisterAndValue));
|
|
||||||
if(off == NULL)
|
|
||||||
{
|
|
||||||
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 *off2 = (u32 *)memsearch((u8 *)off + sizeof(hidOrigRegisterAndValue), &hidOrigRegisterAndValue, totalSize - ((u32)off - 0x00100000), sizeof(hidOrigRegisterAndValue));
|
|
||||||
if(off2 == NULL)
|
|
||||||
{
|
|
||||||
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &hidOrigCode, totalSize, sizeof(hidOrigCode));
|
|
||||||
if(off3 == NULL)
|
|
||||||
{
|
|
||||||
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
hidRegPatchOffsets[0] = off;
|
|
||||||
hidRegPatchOffsets[1] = off2;
|
|
||||||
hidPatchJumpLoc = off3;
|
|
||||||
|
|
||||||
*off = *off2 = hidDataPhys;
|
|
||||||
memcpy(off3, &hidHook, sizeof(hidHook));
|
|
||||||
hidPatched = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res = svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
|
||||||
}
|
}
|
||||||
svcCloseHandle(processHandle);
|
|
||||||
|
|
||||||
res = OpenProcessByName("ir", &processHandle);
|
|
||||||
if(R_SUCCEEDED(res) && GET_VERSION_MINOR(osGetKernelVersion()) >= 44)
|
if(R_SUCCEEDED(res) && GET_VERSION_MINOR(osGetKernelVersion()) >= 44)
|
||||||
{
|
{
|
||||||
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
|
res = InputRedirection_DoUndoIrPatches(irProcHandle, !irPatched);
|
||||||
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
|
if (R_SUCCEEDED(res))
|
||||||
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
|
irPatched = !irPatched;
|
||||||
|
else if (!irPatched)
|
||||||
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
|
||||||
|
|
||||||
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
|
|
||||||
res = svcMapProcessMemoryEx(processHandle, 0x00100000, (u32) startAddress, totalSize);
|
|
||||||
|
|
||||||
if(R_SUCCEEDED(res))
|
|
||||||
{
|
{
|
||||||
static bool useOldSyncCode;
|
InputRedirection_DoUndoHidPatches(hidProcHandle, false);
|
||||||
static u32 irOrigReadingCode[5] = {
|
hidPatched = false;
|
||||||
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
|
|
||||||
0xE1A0A000, // mov r10, r0
|
|
||||||
}, irOrigWaitSyncCodeOld[] = {
|
|
||||||
0xE0AC6000, // adc r6, r12, r0
|
|
||||||
0xE5D70000, // ldrb r0, [r7]
|
|
||||||
}; // pattern for 8.1
|
|
||||||
|
|
||||||
static const u32 irOrigCppFlagCode[] = {
|
|
||||||
0xE3550000, // cmp r5, #0
|
|
||||||
0xE3A0B080, // mov r11, #0x80
|
|
||||||
};
|
|
||||||
|
|
||||||
static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc;
|
|
||||||
|
|
||||||
if(irPatched)
|
|
||||||
{
|
|
||||||
memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode));
|
|
||||||
if(useOldSyncCode)
|
|
||||||
memcpy(irWaitSyncLoc, &irOrigWaitSyncCodeOld, sizeof(irOrigWaitSyncCodeOld));
|
|
||||||
else
|
|
||||||
memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode));
|
|
||||||
memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode));
|
|
||||||
|
|
||||||
irPatched = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u32 irDataPhys = (u32)PA_FROM_VA_PTR(irData);
|
|
||||||
u32 irCodePhys = (u32)PA_FROM_VA_PTR(&irCodePatchFunc);
|
|
||||||
|
|
||||||
u32 irHook[] = {
|
|
||||||
0xE5940000, // ldr r0, [r4]
|
|
||||||
0xE1A01005, // mov r1, r5
|
|
||||||
0xE59FC000, // ldr r12, [pc] (actually +8)
|
|
||||||
0xE12FFF3C, // blx r12
|
|
||||||
irCodePhys,
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 *off = (u32 *)memsearch((u8 *)0x00100000, &irOrigReadingCode, totalSize, sizeof(irOrigReadingCode) - 4);
|
|
||||||
if(off == NULL)
|
|
||||||
{
|
|
||||||
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
|
||||||
return -4;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 *off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCode, totalSize, sizeof(irOrigWaitSyncCode));
|
|
||||||
if(off2 == NULL)
|
|
||||||
{
|
|
||||||
off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCodeOld, totalSize, sizeof(irOrigWaitSyncCodeOld));
|
|
||||||
if(off2 == NULL)
|
|
||||||
{
|
|
||||||
svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
useOldSyncCode = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
useOldSyncCode = false;
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
memcpy(irHookLoc, &irHook, sizeof(irHook));
|
|
||||||
|
|
||||||
// This "NOP"s out a WaitSynchronisation1 (on the event bound to the 'IR' interrupt) or the check of a previous one
|
|
||||||
*irWaitSyncLoc = 0xE3A00000; // mov r0, #0
|
|
||||||
|
|
||||||
// This NOPs out a flag check in ir:user's CPP emulation
|
|
||||||
*irCppFlagLoc = 0xE3150000; // tst r5, #0
|
|
||||||
|
|
||||||
irPatched = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
|
|
||||||
}
|
}
|
||||||
svcCloseHandle(processHandle);
|
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
svcKernelSetState(0x10000, 4);
|
||||||
|
|
||||||
|
svcCloseHandle(hidProcHandle);
|
||||||
|
svcCloseHandle(irProcHandle);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user