Last active
January 11, 2025 14:42
-
-
Save ZeroSkill1/061de41abd9fc425b2355a638fba421b to your computer and use it in GitHub Desktop.
DSP patch to signal custom handle on interrupt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <3ds.h> | |
typedef struct arg { | |
Handle exit; | |
Handle interrupt; | |
int fire_count; | |
} arg; | |
void tmain (void *a) { | |
arg *ins = (arg *)a; | |
Handle handles[2] = { ins->interrupt, ins->exit }; | |
while (true) { | |
s32 idx = -1; | |
Result res = svcWaitSynchronizationN(&idx, handles, 2, false, -1); | |
if (R_SUCCEEDED(res)) { | |
if (idx == 0) // interrupt | |
++ins->fire_count; | |
else if (idx == 1) // break | |
break; | |
} | |
} | |
threadExit(0); | |
} | |
Result dsp_GetCustomHandle(Handle dsp, Handle *out) { | |
u32 *cmdbuf = getThreadCommandBuffer(); | |
cmdbuf[0] = IPC_MakeHeader(0xFFFF, 2, 0); | |
cmdbuf[1] = 123; | |
Result res = svcSendSyncRequest(dsp); | |
if (R_FAILED(res)) return res; | |
res = cmdbuf[1]; | |
if (cmdbuf[1] == 124) { | |
*out = cmdbuf[3]; | |
} | |
return res; | |
} | |
int main(int argc, char* argv[]) | |
{ | |
gfxInitDefault(); | |
consoleInit(GFX_TOP, NULL); | |
Handle dsp = 0, custom = 0; | |
Result res = srvGetServiceHandle(&dsp, "dsp::DSP"); | |
printf("get dsp::DSP %08lX\n", res); | |
res = dsp_GetCustomHandle(dsp, &custom); | |
printf("get custom interrupt event %08lX\n", res); | |
svcCloseHandle(dsp); | |
Handle exit_evt = 0; | |
res = svcCreateEvent(&exit_evt, RESET_ONESHOT); | |
printf("create thread exit event %08lX\n", res); | |
arg a; | |
a.exit = exit_evt; | |
a.interrupt = custom; | |
a.fire_count = 0; | |
Thread t = threadCreate(&tmain, &a, 0x200, 0x30 - 1, -2, true); | |
printf("NOTE: suspend and unsuspend this app\nby using the home button so the event fires\n"); | |
while (aptMainLoop()) | |
{ | |
gspWaitForVBlank(); | |
gfxSwapBuffers(); | |
hidScanInput(); | |
// Your code goes here | |
u32 kDown = hidKeysDown(); | |
if (kDown & KEY_START) { | |
svcSignalEvent(a.exit); | |
threadJoin(t, 5000000000); | |
svcCloseHandle(a.exit); | |
break; // break in order to return to hbmenu | |
} | |
printf("\rfire count: %d", a.fire_count); | |
} | |
gfxExit(); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; vim: filetype=arm | |
.3ds | |
.open "code.bin", "patched_code.bin", 0x00100000 | |
; this version of the patch is way simpler. it just returns the actual handle the DSP service binds to the interrupt | |
.org 0x001079C4 | |
ldr r0, [r4, #4] | |
cmp r0, #123 ; if the caller didn't use our magic, we continue as usual | |
beq custom_return | |
mov r0, #0x40 | |
str r0, [r4] | |
adr r0, bad_result | |
ldr r0, [r0] | |
b 0x1053FC | |
custom_return: ; otherwise, return the handle | |
adr r0, ret_header | |
ldr r0, [r0] | |
str r0, [r4] | |
mov r0, #0 | |
str r0, [r4, #8] | |
adr r0, handle1 | |
ldr r0, [r0] | |
ldr r0, [r0] | |
str r0, [r4, #12] | |
mov r0, #124 | |
b 0x1053FC ; return as usual | |
handle1: | |
dcd 0x00109288 | |
ret_header: | |
dcd 0x007C0042 | |
bad_result: | |
dcd 0xD900182F | |
.org 0x00105458 ; ipc handler default switch branch | |
b 0x1079C4 ; replace the "invalid ipc command" code with our own | |
nop | |
nop | |
nop | |
.close |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment