From e7c23bb381b51f6faf9643ece081fa5f69db4eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 28 Sep 2026 14:47:49 -0600 Subject: [PATCH] Don't run wait callback hooks for a thread that isn't waiting A thread whose wait ends without a context switch (for example when a callback run from the wait satisfies it) keeps its old waitType. If it later ran a callback, from sceUmdWaitDriveStatCB with the drive already ready for instance, the stale wait's begin/end hooks ran, couldn't find the paused wait, and resumed the thread with SCE_KERNEL_ERROR_WAIT_DELETE, overwriting the HLE call's return value. Should fix "sceUmdWaitDriveStatCB: error 0x800201b5" dialog in Maru Goukaku TOEIC Test Portable (#7576). Co-Authored-By: Claude Opus 5.5 (1M context) --- Core/HLE/sceKernelThread.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 8bafc3b1cc..e84201af14 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -3090,8 +3090,9 @@ void __KernelCallAddress(PSPThread *thread, u32 entryPoint, PSPAction *afterActi afterAction = after; if (thread->nt.waitType != WAITTYPE_NONE) { - // If it's a callback, tell the wait to stop. - if (cbId > 0) { + // If it's a callback, tell the wait to stop. A thread that already returned from its + // wait keeps a stale waitType until it's switched out, so check that it's waiting. + if (cbId > 0 && (thread->nt.status & THREADSTATUS_WAIT) != 0) { if (waitTypeFuncs[thread->nt.waitType].beginFunc != NULL) { waitTypeFuncs[thread->nt.waitType].beginFunc(after->threadID, thread->currentCallbackId); } else { @@ -3250,7 +3251,7 @@ void __KernelReturnFromMipsCall() { } currentCallbackThreadID = 0; - if (cur->nt.waitType != WAITTYPE_NONE && call->cbId > 0) { + if (cur->nt.waitType != WAITTYPE_NONE && (cur->nt.status & THREADSTATUS_WAIT) != 0 && call->cbId > 0) { if (waitTypeFuncs[cur->nt.waitType].endFunc != NULL) waitTypeFuncs[cur->nt.waitType].endFunc(cur->GetUID(), cur->currentCallbackId); else