diff --git a/src/sl/saveload.cpp b/src/sl/saveload.cpp index 426414eae0..1c5d79eeb0 100644 --- a/src/sl/saveload.cpp +++ b/src/sl/saveload.cpp @@ -387,6 +387,9 @@ static void SlNullPointers() SlXvSetCurrentState(); for (auto &ch : ChunkHandlers()) { + if (ch.special_proc != nullptr) { + if (ch.special_proc(ch.id, CSLSO_PRE_PTRS) == CSLSOR_LOAD_CHUNK_CONSUMED) continue; + } if (ch.ptrs_proc != nullptr) { DEBUG(sl, 3, "Nulling pointers for %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); ch.ptrs_proc(); @@ -2312,14 +2315,18 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) */ static void SlSaveChunk(const ChunkHandler &ch) { - if (ch.type == CH_UPSTREAM_SAVE) { - SaveLoadVersion old_ver = _sl_version; - _sl_version = MAX_LOAD_SAVEGAME_VERSION; - auto guard = scope_guard([&]() { - _sl_version = old_ver; - }); - upstream_sl::SlSaveChunkChunkByID(ch.id); - return; + if (ch.special_proc != nullptr) { + ChunkSaveLoadSpecialOpResult result = ch.special_proc(ch.id, CSLSO_SHOULD_SAVE_CHUNK); + if (result == CSLSOR_DONT_SAVE_CHUNK) return; + if (result == CSLSOR_UPSTREAM_SAVE_CHUNK) { + SaveLoadVersion old_ver = _sl_version; + _sl_version = MAX_LOAD_SAVEGAME_VERSION; + auto guard = scope_guard([&]() { + _sl_version = old_ver; + }); + upstream_sl::SlSaveChunkChunkByID(ch.id); + return; + } } ChunkSaveLoadProc *proc = ch.save_proc; @@ -2327,10 +2334,6 @@ static void SlSaveChunk(const ChunkHandler &ch) /* Don't save any chunk information if there is no save handler. */ if (proc == nullptr) return; - if (ch.special_proc != nullptr) { - if (ch.special_proc(ch.id, CSLSO_SHOULD_SAVE_CHUNK) == CSLSOR_DONT_SAVE_CHUNK) return; - } - SlWriteUint32(ch.id); DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); @@ -2449,6 +2452,9 @@ static void SlFixPointers() _sl.action = SLA_PTRS; for (auto &ch : ChunkHandlers()) { + if (ch.special_proc != nullptr) { + if (ch.special_proc(ch.id, CSLSO_PRE_PTRS) == CSLSOR_LOAD_CHUNK_CONSUMED) continue; + } if (ch.ptrs_proc != nullptr) { DEBUG(sl, 3, "Fixing pointers for %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); ch.ptrs_proc(); diff --git a/src/sl/saveload.h b/src/sl/saveload.h index 0ff75523f0..67eaaaeef0 100644 --- a/src/sl/saveload.h +++ b/src/sl/saveload.h @@ -83,12 +83,14 @@ void SlUnreachablePlaceholder(); enum ChunkSaveLoadSpecialOp { CSLSO_PRE_LOAD, CSLSO_PRE_LOADCHECK, + CSLSO_PRE_PTRS, CSLSO_SHOULD_SAVE_CHUNK, }; enum ChunkSaveLoadSpecialOpResult { CSLSOR_NONE, CSLSOR_LOAD_CHUNK_CONSUMED, CSLSOR_DONT_SAVE_CHUNK, + CSLSOR_UPSTREAM_SAVE_CHUNK, }; typedef ChunkSaveLoadSpecialOpResult ChunkSaveLoadSpecialProc(uint32, ChunkSaveLoadSpecialOp); @@ -99,7 +101,7 @@ enum ChunkType { CH_SPARSE_ARRAY = 2, CH_EXT_HDR = 15, ///< Extended chunk header - CH_UPSTREAM_SAVE = 0x80, + CH_UNUSED = 0x80, }; /** Handlers and description of chunk. */ @@ -135,15 +137,11 @@ namespace upstream_sl { ChunkHandler ch = { id, - nullptr, SlUnreachablePlaceholder, - []() { - SlExecWithSlVersion(F::GetLoadVersion(), []() { - SlFixPointerChunkByID(id); - }); - }, SlUnreachablePlaceholder, - CH_UPSTREAM_SAVE + SlUnreachablePlaceholder, + SlUnreachablePlaceholder, + CH_UNUSED }; ch.special_proc = [](uint32 chunk_id, ChunkSaveLoadSpecialOp op) -> ChunkSaveLoadSpecialOpResult { assert(id == chunk_id); @@ -158,6 +156,13 @@ namespace upstream_sl { SlLoadCheckChunkByID(id); }); return CSLSOR_LOAD_CHUNK_CONSUMED; + case CSLSO_PRE_PTRS: + SlExecWithSlVersion(F::GetLoadVersion(), []() { + SlFixPointerChunkByID(id); + }); + return CSLSOR_LOAD_CHUNK_CONSUMED; + case CSLSO_SHOULD_SAVE_CHUNK: + return CSLSOR_UPSTREAM_SAVE_CHUNK; default: return CSLSOR_NONE; }