mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-31 03:26:47 +01:00
SaveState: Fixes from a review of the kernel savestates
- A partition memory block restored its allocator through BlockAllocatorFromID, whose privilege check asked the thread current before the load, already deleted with the kernel objects. Loading a kernel-partition block under a user thread left it without an allocator, crashing when it was freed. The saved id maps straight back now, and the current thread is cleared along with the objects. - The thread LoadExec leaves waiting (with no timeout) for plugins and VSH modules to start wasn't saved, so a state saved while one was starting hung the game thread after loading. The VSH modules still to start weren't saved either, nor cleared. - A state without the exit callback id left the previous session's. - From a broken or crafted state: thread ids that GetFast trusts (current, idle and ready), interrupt handler numbers, FPL and TLSPL indices, and a MIPS call or action slot that isn't there. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
d40137a007
commit
30cab94840
8 files changed
+91
-6
No files matched your search
@@ -239,7 +239,7 @@ u32 PSPModule::GetMissingErrorCode() {
|
||||
}
|
||||
|
||||
void PSPModule::DoState(PointerWrap &p) {
|
||||
auto s = p.Section("Module", 1, 6);
|
||||
auto s = p.Section("Module", 1, 7);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
@@ -285,6 +285,14 @@ void PSPModule::DoState(PointerWrap &p) {
|
||||
if (s >= 5) {
|
||||
Do(p, modulePtr.ptr);
|
||||
}
|
||||
if (s >= 7) {
|
||||
// LoadExec's thread waits for plugins (and VSH modules) to start, with no timeout.
|
||||
Do(p, pluginWaitingThread);
|
||||
Do(p, startingPlugins);
|
||||
} else if (p.mode == p.MODE_READ) {
|
||||
pluginWaitingThread = 0;
|
||||
startingPlugins.clear();
|
||||
}
|
||||
|
||||
ModuleWaitingThread mwt = { 0 };
|
||||
Do(p, waitingThreads, mwt);
|
||||
@@ -555,7 +563,7 @@ std::vector<std::pair<u32, u32>> __KernelModuleCodeRanges() {
|
||||
}
|
||||
|
||||
void __KernelModuleDoState(PointerWrap &p) {
|
||||
auto s = p.Section("sceKernelModule", 1, 5);
|
||||
auto s = p.Section("sceKernelModule", 1, 6);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
@@ -596,6 +604,14 @@ void __KernelModuleDoState(PointerWrap &p) {
|
||||
}
|
||||
CoreTiming::RestoreRegisterEvent(eventModuleLoadDone, "LoadModuleDone", &__KernelLoadModuleDone);
|
||||
|
||||
if (s >= 6) {
|
||||
Do(p, g_vshModulesToStart);
|
||||
Do(p, g_vshModuleStarting);
|
||||
} else if (p.mode == p.MODE_READ) {
|
||||
g_vshModulesToStart.clear();
|
||||
g_vshModuleStarting = 0;
|
||||
}
|
||||
|
||||
if (p.mode == p.MODE_READ) {
|
||||
u32 error;
|
||||
// We process these late, since they depend on loadedModules for interlinking.
|
||||
|
||||
Reference in new issue
Block a user