Fix loading savestates made before flash1: was mounted

78ef1eae82 added a flash1: mount, but MetaFileSystem::DoState serializes the
mounts positionally - one section each, with no length to skip by - so a state
written before that commit has one section fewer than we now have mounts.

The existing count check assumed a single missing entry could only be pfat0:,
which was the previous mount added this way. So it took the skipPfat0 path,
skipped pfat0's section while still only looping n times, and ended up making
n-1 DoState calls against n sections. Everything after that read shifted, and
the load died with "Failure at DirectoryFileSystem".

Make the "these were added later" set explicit and ordered instead, and iterate
over the mounts rather than over the saved count, so the number of DoState calls
matches the state regardless of which of them are missing.

Verified against Wipeout Pure (UCUS98612): both save slots report n=9 against 10
mounts and fail to load before this, and load after, in both the app and headless.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCPmm7FoQUoqrbMdhfqhQ2
This commit is contained in:
Henrik Rydgård
2026-08-30 23:52:09 +02:00
co-authored by Claude Opus 5
parent e4a0f649fa
commit 729653bf42
+21 -12
View File
@@ -644,20 +644,29 @@ void MetaFileSystem::DoState(PointerWrap &p) {
u32 n = (u32) fileSystems.size();
Do(p, n);
bool skipPfat0 = false;
if (n != (u32) fileSystems.size()) {
if (n == (u32) fileSystems.size() - 1) {
skipPfat0 = true;
} else {
p.SetError(p.ERROR_FAILURE);
ERROR_LOG(Log::FileSystem, "Savestate failure: number of filesystems doesn't match.");
return;
}
// The mounts are serialized positionally, one section each and no length to skip by, so a
// savestate from an older build is simply missing the sections for mounts that didn't exist
// yet - and we have to leave out exactly those to stay lined up. Most recently added first.
static const char * const mountsAddedOverTime[] = { "flash1:", "pfat0:" };
const size_t missing = n < (u32)fileSystems.size() ? fileSystems.size() - n : 0;
if (n > (u32)fileSystems.size() || missing > ARRAY_SIZE(mountsAddedOverTime)) {
p.SetError(p.ERROR_FAILURE);
ERROR_LOG(Log::FileSystem, "Savestate failure: number of filesystems doesn't match (%d in state, %d mounted).", (int)n, (int)fileSystems.size());
return;
}
for (u32 i = 0; i < n; ++i) {
if (!skipPfat0 || fileSystems[i].prefix != "pfat0:") {
fileSystems[i].system->DoState(p);
for (const MountPoint &mount : fileSystems) {
bool skip = false;
for (size_t i = 0; i < missing; i++) {
if (mount.prefix == mountsAddedOverTime[i]) {
skip = true;
break;
}
}
if (!skip) {
mount.system->DoState(p);
}
}
}