From a52a1e1824021fe7ea6d4ec5b65899aaf99f42da Mon Sep 17 00:00:00 2001 From: Ziemas Date: Mon, 13 Oct 2025 12:31:00 +0200 Subject: [PATCH 1/2] IOP Kernel: Handle thread sleeping better. Prevents wakeup thread from erroneously waking up threads waiting on semaphores. --- game/system/IOP_Kernel.cpp | 16 +++++++++++++++- game/system/IOP_Kernel.h | 3 ++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/game/system/IOP_Kernel.cpp b/game/system/IOP_Kernel.cpp index 56b8d663ff0..149c1f4d7c5 100644 --- a/game/system/IOP_Kernel.cpp +++ b/game/system/IOP_Kernel.cpp @@ -101,7 +101,14 @@ void IOP_Kernel::DelayThread(u32 usec) { void IOP_Kernel::SleepThread() { ASSERT(_currentThread); - _currentThread->state = IopThread::State::Suspend; + if (_currentThread->wakeupCount > 0) { + _currentThread->wakeupCount--; + return; + } + + _currentThread->state = IopThread::State::Wait; + _currentThread->waitType = IopThread::Wait::Sleep; + leaveThread(); } @@ -116,6 +123,13 @@ void IOP_Kernel::YieldThread() { */ void IOP_Kernel::WakeupThread(s32 id) { ASSERT(id > 0); + + auto& thread = threads.at(id); + if (thread.state != IopThread::State::Wait || thread.waitType != IopThread::Wait::Sleep) { + thread.wakeupCount++; + return; + } + threads.at(id).state = IopThread::State::Ready; } diff --git a/game/system/IOP_Kernel.h b/game/system/IOP_Kernel.h index 3409d639a96..065c7caa53e 100644 --- a/game/system/IOP_Kernel.h +++ b/game/system/IOP_Kernel.h @@ -53,7 +53,7 @@ struct IopThread { Dormant, }; - enum class Wait { None, Semaphore, Delay, Messagebox, EventFlag }; + enum class Wait { None, Sleep, Semaphore, Delay, Messagebox, EventFlag }; IopThread(std::string n, void (*f)(), s32 ID, u32 pri) : name(std::move(n)), function(f), priority(pri), thID(ID) { @@ -71,6 +71,7 @@ struct IopThread { time_stamp resumeTime = {}; u32 priority = 0; s32 thID = -1; + s32 wakeupCount = 0; }; struct Semaphore { From ddb82aae5ce22ed4287275077823aefc5e2bbdfd Mon Sep 17 00:00:00 2001 From: Ziemas Date: Mon, 13 Oct 2025 12:35:15 +0200 Subject: [PATCH 2/2] Disable waiting on uninitialized LfoList sema. --- game/overlord/jak2/streamlist.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/game/overlord/jak2/streamlist.cpp b/game/overlord/jak2/streamlist.cpp index f6dd7614d83..e74cba7fe9a 100644 --- a/game/overlord/jak2/streamlist.cpp +++ b/game/overlord/jak2/streamlist.cpp @@ -407,15 +407,20 @@ u32 StreamListThread() { } uVar9 = uVar9 + 1; } while (uVar9 < 4); + SignalSema(EEStreamsList.sema); RequestedStreamsList.unk2_init0 = 1; SignalSema(RequestedStreamsList.sema); + WaitSema(EEPlayList.sema); CheckPlayList(&EEPlayList); SignalSema(EEPlayList.sema); - WaitSema(LfoList.sema); - CheckLfoList(&LfoList); - SignalSema(LfoList.sema); + + // FIXME LfoList hasn't been initialised because of unimplemented + // streamlfo functions. + // WaitSema(LfoList.sema); + // CheckLfoList(&LfoList); + // SignalSema(LfoList.sema); } while (true); return 0; }