From 210be3b3110203fd6d29316fcec088a1df020d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Oct 2026 20:13:59 +0100 Subject: [PATCH] Savestate: Keep MipsCall actions of type 0 Action type IDs start at 0, and the first one registered is ActionAfterMipsCall, but MipsCall::DoState used 0 to mean no action. So every call made with __KernelCallAddress lost its action chain on load: the thread's wait state was never restored when the call returned, and chained actions never ran. Version 2 of the section marks a missing action with -1. Co-Authored-By: Claude Opus 5.5 (1M context) --- Core/HLE/sceKernelThread.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 1e4d3308f4..3b6ef4a74f 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -599,7 +599,7 @@ PSPAction *__KernelCreateAction(int actionType) { void MipsCall::DoState(PointerWrap &p) { - auto s = p.Section("MipsCall", 1); + auto s = p.Section("MipsCall", 1, 2); if (!s) return; @@ -624,11 +624,14 @@ void MipsCall::DoState(PointerWrap &p) Do(p, savedId); Do(p, reschedAfter); - int actionTypeID = 0; + // Action type 0 is a real type (ActionAfterMipsCall, the first one registered), so version 1 lost + // those actions. Version 2 marks "no action" with -1. + const int noAction = s >= 2 ? -1 : 0; + int actionTypeID = noAction; if (doAfter != NULL) actionTypeID = doAfter->actionTypeID; Do(p, actionTypeID); - if (actionTypeID != 0) + if (actionTypeID != noAction) { if (p.mode == p.MODE_READ) doAfter = __KernelCreateAction(actionTypeID);