diff --git a/source/applicationendshook/applicationends_function_replacements.cpp b/source/applicationendshook/applicationends_function_replacements.cpp index 75e1dbc..9060701 100644 --- a/source/applicationendshook/applicationends_function_replacements.cpp +++ b/source/applicationendshook/applicationends_function_replacements.cpp @@ -1,8 +1,10 @@ #include "applicationends_function_replacements.h" #include "globals.h" - #include +#include #include +#include +#include #include static uint32_t lastData0 = 0; @@ -23,6 +25,34 @@ void CallHook(wums_hook_type_t type) { } } } +void ZombiUFix() { + /* + * ZombiU doesn't exit properly. It just calls exit(0) after receiving the + * request to exit. If exiting takes too long, other threads will run again + * and crash for some reason. The (hacky) solution is to set the priority + * of (some) ZombiU threads to something very high. + */ + if (OSGetTitleID() == 0x000500001010EF00 || // ZombiU EUR + OSGetTitleID() == 0x000500001011A700 || // ZombiU EUR + OSGetTitleID() == 0x000500001010DD00 || // ZombiU USA + OSGetTitleID() == 0x0005000010112300 // ZombiU JPN + ) { + auto *curThread = OSGetCurrentThread(); + __OSLockScheduler(curThread); + int state = OSDisableInterrupts(); + OSThread *t = *((OSThread **) 0x100567F8); + while (t) { + if ((uint32_t) t > (uint32_t) curThread && (uint32_t) t < 0x20000000) { + t->priority = 0x80; + OSReport("Set priority to %d for thread %08X (%s) to prevent it from running/crashing\n", t->priority, t, t->name); + } + t = t->activeLink.next; + } + + OSRestoreInterrupts(state); + __OSUnlockScheduler(curThread); + } +} DECL_FUNCTION(uint32_t, OSReceiveMessage, OSMessageQueue *queue, OSMessage *message, uint32_t flags) { uint32_t res = real_OSReceiveMessage(queue, message, flags); @@ -30,6 +60,7 @@ DECL_FUNCTION(uint32_t, OSReceiveMessage, OSMessageQueue *queue, OSMessage *mess if (message != nullptr && res) { if (lastData0 != message->args[0]) { if (message->args[0] == 0xD1E0D1E0) { + ZombiUFix(); CallHook(WUMS_HOOK_APPLICATION_REQUESTS_EXIT); } }