Saveload: Fix SlNullPointers with upstream chunks

This commit is contained in:
Jonathan G Rennison
2024-02-21 18:40:23 +00:00
parent b58ecb0cd8
commit ba1fa3ad29
3 changed files with 36 additions and 3 deletions

View File

@@ -184,7 +184,7 @@ void SlNullPointers()
/* We don't want any savegame conversion code to run /* We don't want any savegame conversion code to run
* during NULLing; especially those that try to get * during NULLing; especially those that try to get
* pointers from other pools. */ * pointers from other pools. */
_sl_version = SAVEGAME_VERSION; _sl_version = MAX_LOAD_SAVEGAME_VERSION;
for (const ChunkHandler &ch : ChunkHandlers()) { for (const ChunkHandler &ch : ChunkHandlers()) {
DEBUG(sl, 3, "Nulling pointers for %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); DEBUG(sl, 3, "Nulling pointers for %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id);
@@ -2038,12 +2038,24 @@ void SlFixPointers()
void SlFixPointerChunkByID(uint32_t id) void SlFixPointerChunkByID(uint32_t id)
{ {
_sl.action = SLA_PTRS;
const ChunkHandler *ch = SlFindChunkHandler(id); const ChunkHandler *ch = SlFindChunkHandler(id);
if (ch == nullptr) SlErrorCorrupt("Unknown chunk type"); if (ch == nullptr) SlErrorCorrupt("Unknown chunk type");
DEBUG(sl, 3, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id); DEBUG(sl, 3, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
ch->FixPointers(); ch->FixPointers();
} }
void SlNullPointerChunkByID(uint32_t id)
{
_sl.action = SLA_NULL;
const ChunkHandler *ch = SlFindChunkHandler(id);
if (ch == nullptr) SlErrorCorrupt("Unknown chunk type");
DEBUG(sl, 3, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
ch->FixPointers();
}
/** /**
* Save a chunk of data (eg. vehicles, stations, etc.). Each chunk is * Save a chunk of data (eg. vehicles, stations, etc.). Each chunk is
* prefixed by an ID identifying it, followed by data, and terminator where appropriate * prefixed by an ID identifying it, followed by data, and terminator where appropriate

View File

@@ -91,6 +91,7 @@ extern bool _sl_upstream_mode;
namespace upstream_sl { namespace upstream_sl {
void SlNullPointers(); void SlNullPointers();
void SlNullPointerChunkByID(uint32_t);
void SlLoadChunks(); void SlLoadChunks();
void SlLoadChunkByID(uint32_t id); void SlLoadChunkByID(uint32_t id);
void SlLoadCheckChunks(); void SlLoadCheckChunks();
@@ -380,6 +381,14 @@ static void SlNullPointers()
_sl.action = SLA_NULL; _sl.action = SLA_NULL;
/* Do upstream chunk tests before clearing version data */
ring_buffer<uint32_t> upstream_null_chunks;
for (auto &ch : ChunkHandlers()) {
if (ch.special_proc != nullptr && ch.special_proc(ch.id, CSLSO_PRE_NULL_PTRS) == CSLSOR_UPSTREAM_NULL_PTRS) {
upstream_null_chunks.push_back(ch.id);
}
}
/* We don't want any savegame conversion code to run /* We don't want any savegame conversion code to run
* during NULLing; especially those that try to get * during NULLing; especially those that try to get
* pointers from other pools. */ * pointers from other pools. */
@@ -387,9 +396,14 @@ static void SlNullPointers()
SlXvSetCurrentState(); SlXvSetCurrentState();
for (auto &ch : ChunkHandlers()) { for (auto &ch : ChunkHandlers()) {
if (ch.special_proc != nullptr) { if (!upstream_null_chunks.empty() && upstream_null_chunks.front() == ch.id) {
if (ch.special_proc(ch.id, CSLSO_PRE_PTRS) == CSLSOR_LOAD_CHUNK_CONSUMED) continue; upstream_null_chunks.pop_front();
SlExecWithSlVersion(MAX_LOAD_SAVEGAME_VERSION, [&]() {
upstream_sl::SlNullPointerChunkByID(ch.id);
});
continue;
} }
if (ch.ptrs_proc != nullptr) { 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); DEBUG(sl, 3, "Nulling pointers for %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id);
ch.ptrs_proc(); ch.ptrs_proc();

View File

@@ -90,6 +90,7 @@ enum ChunkSaveLoadSpecialOp {
CSLSO_PRE_LOAD, CSLSO_PRE_LOAD,
CSLSO_PRE_LOADCHECK, CSLSO_PRE_LOADCHECK,
CSLSO_PRE_PTRS, CSLSO_PRE_PTRS,
CSLSO_PRE_NULL_PTRS,
CSLSO_SHOULD_SAVE_CHUNK, CSLSO_SHOULD_SAVE_CHUNK,
}; };
enum ChunkSaveLoadSpecialOpResult { enum ChunkSaveLoadSpecialOpResult {
@@ -97,6 +98,7 @@ enum ChunkSaveLoadSpecialOpResult {
CSLSOR_LOAD_CHUNK_CONSUMED, CSLSOR_LOAD_CHUNK_CONSUMED,
CSLSOR_DONT_SAVE_CHUNK, CSLSOR_DONT_SAVE_CHUNK,
CSLSOR_UPSTREAM_SAVE_CHUNK, CSLSOR_UPSTREAM_SAVE_CHUNK,
CSLSOR_UPSTREAM_NULL_PTRS,
}; };
typedef ChunkSaveLoadSpecialOpResult ChunkSaveLoadSpecialProc(uint32_t, ChunkSaveLoadSpecialOp); typedef ChunkSaveLoadSpecialOpResult ChunkSaveLoadSpecialProc(uint32_t, ChunkSaveLoadSpecialOp);
@@ -189,6 +191,8 @@ namespace upstream_sl {
SlFixPointerChunkByID(id); SlFixPointerChunkByID(id);
}); });
return CSLSOR_LOAD_CHUNK_CONSUMED; return CSLSOR_LOAD_CHUNK_CONSUMED;
case CSLSO_PRE_NULL_PTRS:
return CSLSOR_UPSTREAM_NULL_PTRS;
case CSLSO_SHOULD_SAVE_CHUNK: case CSLSO_SHOULD_SAVE_CHUNK:
return CSLSOR_UPSTREAM_SAVE_CHUNK; return CSLSOR_UPSTREAM_SAVE_CHUNK;
default: default:
@@ -234,6 +238,9 @@ namespace upstream_sl {
SlFixPointerChunkByID(id); SlFixPointerChunkByID(id);
}); });
return CSLSOR_LOAD_CHUNK_CONSUMED; return CSLSOR_LOAD_CHUNK_CONSUMED;
case CSLSO_PRE_NULL_PTRS:
if (!F::LoadUpstream()) return CSLSOR_NONE;
return CSLSOR_UPSTREAM_NULL_PTRS;
case CSLSO_SHOULD_SAVE_CHUNK: case CSLSO_SHOULD_SAVE_CHUNK:
return F::SaveUpstream() ? CSLSOR_UPSTREAM_SAVE_CHUNK : CSLSOR_NONE; return F::SaveUpstream() ? CSLSOR_UPSTREAM_SAVE_CHUNK : CSLSOR_NONE;
default: default: