diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 19a18a96d4..e66e489806 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -486,16 +486,30 @@ void HLEDoState(PointerWrap &p) { if (s >= 2) { int actions = (int)mipsCallActions.size(); Do(p, actions); - if (actions != (int)mipsCallActions.size()) { - mipsCallActions.resize(actions); + if (p.mode == p.MODE_READ) { + for (PSPAction *action : mipsCallActions) { + delete action; + } + mipsCallActions.clear(); + if (actions < 0) { + p.SetError(p.ERROR_FAILURE); + return; + } + mipsCallActions.resize(actions, nullptr); } for (auto &action : mipsCallActions) { int actionTypeID = action != nullptr ? action->actionTypeID : -1; Do(p, actionTypeID); if (actionTypeID != -1) { - if (p.mode == p.MODE_READ) + if (p.mode == p.MODE_READ) { action = __KernelCreateAction(actionTypeID); + if (!action) { + ERROR_LOG(Log::SaveState, "Unable to load state: unknown action type %d", actionTypeID); + p.SetError(p.ERROR_FAILURE); + return; + } + } action->DoState(p); } } diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index da1ee11e43..8bafc3b1cc 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -223,6 +223,10 @@ public: { if (p.mode == p.MODE_READ) chainedAction = __KernelCreateAction(chainedActionType); + if (!chainedAction) { + p.SetError(p.ERROR_FAILURE); + return; + } chainedAction->DoState(p); } } @@ -286,6 +290,10 @@ public: auto s = p.Section("ActionAfterExitCallback", 1); if (!s) return; + if (p.mode == p.MODE_READ) { + // The dispatch is still in flight in the loaded state (see __KernelThreadingDoState.) + g_exitCallbackPending = true; + } } }; @@ -570,6 +578,10 @@ void MipsCall::DoState(PointerWrap &p) { if (p.mode == p.MODE_READ) doAfter = __KernelCreateAction(actionTypeID); + if (!doAfter) { + p.SetError(p.ERROR_FAILURE); + return; + } doAfter->DoState(p); } } @@ -810,6 +822,11 @@ void __KernelThreadingInit() { void __KernelThreadingDoState(PointerWrap &p) { + if (p.mode == p.MODE_READ) { + // Set again if an ActionAfterExitCallback is loaded (with the mips calls, later.) + g_exitCallbackPending = false; + } + auto s = p.Section("sceKernelThread", 1, 5); if (!s) return;