diff --git a/src/sl/saveload.cpp b/src/sl/saveload.cpp index db4c7c0a9d..052f478596 100644 --- a/src/sl/saveload.cpp +++ b/src/sl/saveload.cpp @@ -405,7 +405,7 @@ static void SlNullPointers() } 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 %s", ChunkIDDumper()(ch.id)); ch.ptrs_proc(); } } @@ -2270,7 +2270,7 @@ void SlLoadTableOrRiffFiltered(const SaveLoadTable &slt) SlObjectLoadFiltered(nullptr, slt); if (SlIsTableChunk() && SlIterateArray() != -1) { uint32_t id = _sl.current_chunk_id; - SlErrorCorruptFmt("Too many %c%c%c%c entries", id >> 24, id >> 16, id >> 8, id); + SlErrorCorruptFmt("Too many %s entries", ChunkIDDumper()(id)); } } @@ -2409,6 +2409,8 @@ static void SlLoadChunk(const ChunkHandler &ch) if (ch.special_proc(ch.id, CSLSO_PRE_LOAD) == CSLSOR_LOAD_CHUNK_CONSUMED) return; } + DEBUG(sl, 2, "Loading chunk %s", ChunkIDDumper()(ch.id)); + byte m = SlReadByte(); size_t len; size_t endoffs; @@ -2438,12 +2440,12 @@ static void SlLoadChunk(const ChunkHandler &ch) case CH_TABLE: _sl.array_index = 0; ch.load_proc(); - if (_next_offs != 0) SlErrorCorrupt("Invalid array length"); + if (_next_offs != 0) SlErrorCorruptFmt("Invalid array length in %s", ChunkIDDumper()(ch.id)); break; case CH_SPARSE_ARRAY: case CH_SPARSE_TABLE: ch.load_proc(); - if (_next_offs != 0) SlErrorCorrupt("Invalid array length"); + if (_next_offs != 0) SlErrorCorruptFmt("Invalid array length in %s", ChunkIDDumper()(ch.id)); break; default: if ((m & 0xF) == CH_RIFF) { @@ -2453,7 +2455,7 @@ static void SlLoadChunk(const ChunkHandler &ch) SlRIFFSpringPPCheck(len); if (SlXvIsFeaturePresent(XSLFI_RIFF_HEADER_60_BIT)) { if (len != 0) { - SlErrorCorrupt("RIFF chunk too large"); + SlErrorCorruptFmt("RIFF chunk too large: %s", ChunkIDDumper()(ch.id)); } len = SlReadUint32(); } @@ -2465,17 +2467,17 @@ static void SlLoadChunk(const ChunkHandler &ch) endoffs = _sl.reader->GetSize() + len; ch.load_proc(); if (_sl.reader->GetSize() != endoffs) { - DEBUG(sl, 1, "Invalid chunk size: " PRINTF_SIZE " != " PRINTF_SIZE ", (" PRINTF_SIZE ")", _sl.reader->GetSize(), endoffs, len); - SlErrorCorruptFmt("Invalid chunk size - expected to be at position " PRINTF_SIZE ", actually at " PRINTF_SIZE ", length: " PRINTF_SIZE, - endoffs, _sl.reader->GetSize(), len); + DEBUG(sl, 1, "Invalid chunk size: " PRINTF_SIZE " != " PRINTF_SIZE ", (" PRINTF_SIZE ") for %s", _sl.reader->GetSize(), endoffs, len, ChunkIDDumper()(ch.id)); + SlErrorCorruptFmt("Invalid chunk size - expected to be at position " PRINTF_SIZE ", actually at " PRINTF_SIZE ", length: " PRINTF_SIZE " for %s", + endoffs, _sl.reader->GetSize(), len, ChunkIDDumper()(ch.id)); } } else { - SlErrorCorrupt("Invalid chunk type"); + SlErrorCorruptFmt("Invalid chunk type for %s", ChunkIDDumper()(ch.id)); } break; } - if (_sl.expect_table_header) SlErrorCorruptFmt("Table chunk without header: %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); + if (_sl.expect_table_header) SlErrorCorruptFmt("Table chunk without header: %s", ChunkIDDumper()(ch.id)); } /** @@ -2483,12 +2485,18 @@ static void SlLoadChunk(const ChunkHandler &ch) * If the chunkhandler is nullptr, the chunk is skipped. * @param ch The chunkhandler that will be used for the operation, this may be nullptr */ -static void SlLoadCheckChunk(const ChunkHandler *ch) +static void SlLoadCheckChunk(const ChunkHandler *ch, uint32_t chunk_id) { - if (ch && ch->special_proc != nullptr) { + if (ch != nullptr && ch->special_proc != nullptr) { if (ch->special_proc(ch->id, CSLSO_PRE_LOADCHECK) == CSLSOR_LOAD_CHUNK_CONSUMED) return; } + if (ch == nullptr) { + DEBUG(sl, 1, "Discarding chunk %s", ChunkIDDumper()(chunk_id)); + } else { + DEBUG(sl, 2, "Loading chunk %s", ChunkIDDumper()(chunk_id)); + } + byte m = SlReadByte(); size_t len; size_t endoffs; @@ -2518,7 +2526,7 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) case CH_TABLE: _sl.array_index = 0; if (ext_flags) { - SlErrorCorruptFmt("CH_ARRAY does not take chunk header extension flags: 0x%X", ext_flags); + SlErrorCorruptFmt("CH_ARRAY does not take chunk header extension flags: 0x%X in %s", ext_flags, ChunkIDDumper()(chunk_id)); } if (ch && ch->load_check_proc) { ch->load_check_proc(); @@ -2530,7 +2538,7 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) case CH_SPARSE_ARRAY: case CH_SPARSE_TABLE: if (ext_flags) { - SlErrorCorruptFmt("CH_SPARSE_ARRAY does not take chunk header extension flags: 0x%X", ext_flags); + SlErrorCorruptFmt("CH_SPARSE_ARRAY does not take chunk header extension flags: 0x%X in %s", ext_flags, ChunkIDDumper()(chunk_id)); } if (ch && ch->load_check_proc) { ch->load_check_proc(); @@ -2542,7 +2550,7 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) default: if ((m & 0xF) == CH_RIFF) { if (ext_flags != (ext_flags & SLCEHF_BIG_RIFF)) { - SlErrorCorruptFmt("Unknown chunk header extension flags for CH_RIFF: 0x%X", ext_flags); + SlErrorCorruptFmt("Unknown chunk header extension flags for CH_RIFF: 0x%X in %s", ext_flags, ChunkIDDumper()(chunk_id)); } /* Read length */ len = (SlReadByte() << 16) | ((m >> 4) << 24); @@ -2553,12 +2561,12 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) SlErrorCorrupt("RIFF chunk too large"); } len = SlReadUint32(); - if (ext_flags & SLCEHF_BIG_RIFF) SlErrorCorrupt("XSLFI_RIFF_HEADER_60_BIT and SLCEHF_BIG_RIFF both present"); + if (ext_flags & SLCEHF_BIG_RIFF) SlErrorCorruptFmt("XSLFI_RIFF_HEADER_60_BIT and SLCEHF_BIG_RIFF both present in %s", ChunkIDDumper()(chunk_id)); } if (ext_flags & SLCEHF_BIG_RIFF) { uint64_t full_len = len | (static_cast(SlReadUint32()) << 28); if (full_len >= (1LL << 32)) { - SlErrorCorruptFmt("Chunk size too large: " OTTD_PRINTFHEX64, full_len); + SlErrorCorruptFmt("Chunk size too large: " OTTD_PRINTFHEX64 " in %s", full_len, ChunkIDDumper()(chunk_id)); } len = static_cast(full_len); } @@ -2570,17 +2578,17 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) SlSkipBytes(len); } if (_sl.reader->GetSize() != endoffs) { - DEBUG(sl, 1, "Invalid chunk size: " PRINTF_SIZE " != " PRINTF_SIZE ", (" PRINTF_SIZE ")", _sl.reader->GetSize(), endoffs, len); - SlErrorCorruptFmt("Invalid chunk size - expected to be at position " PRINTF_SIZE ", actually at " PRINTF_SIZE ", length: " PRINTF_SIZE, - endoffs, _sl.reader->GetSize(), len); + DEBUG(sl, 1, "Invalid chunk size: " PRINTF_SIZE " != " PRINTF_SIZE ", (" PRINTF_SIZE ") for %s", _sl.reader->GetSize(), endoffs, len, ChunkIDDumper()(chunk_id)); + SlErrorCorruptFmt("Invalid chunk size - expected to be at position " PRINTF_SIZE ", actually at " PRINTF_SIZE ", length: " PRINTF_SIZE " for %s", + endoffs, _sl.reader->GetSize(), len, ChunkIDDumper()(chunk_id)); } } else { - SlErrorCorrupt("Invalid chunk type"); + SlErrorCorruptFmt("Invalid chunk type for: %s", ChunkIDDumper()(chunk_id)); } break; } - if (_sl.expect_table_header) SlErrorCorrupt("Table chunk without header"); + if (_sl.expect_table_header) SlErrorCorruptFmt("Table chunk without header: %s", ChunkIDDumper()(chunk_id)); } /** @@ -2611,7 +2619,7 @@ static void SlSaveChunk(const ChunkHandler &ch) _sl.current_chunk_id = ch.id; SlWriteUint32(ch.id); - DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); + DEBUG(sl, 2, "Saving chunk %s", ChunkIDDumper()(ch.id)); size_t written = 0; if (_debug_sl_level >= 3) written = SlGetBytesWritten(); @@ -2640,9 +2648,9 @@ static void SlSaveChunk(const ChunkHandler &ch) default: NOT_REACHED(); } - if (_sl.expect_table_header) SlErrorCorruptFmt("Table chunk without header: %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); + if (_sl.expect_table_header) SlErrorCorruptFmt("Table chunk without header: %s", ChunkIDDumper()(ch.id)); - DEBUG(sl, 3, "Saved chunk %c%c%c%c (" PRINTF_SIZE " bytes)", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id, SlGetBytesWritten() - written); + DEBUG(sl, 3, "Saved chunk %s (" PRINTF_SIZE " bytes)", ChunkIDDumper()(ch.id), SlGetBytesWritten() - written); } /** Save all chunks */ @@ -2678,22 +2686,20 @@ static void SlLoadChunks() for (uint32_t id = SlReadUint32(); id != 0; id = SlReadUint32()) { _sl.current_chunk_id = id; - DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id); size_t read = 0; if (_debug_sl_level >= 3) read = SlGetBytesRead(); if (SlXvIsChunkDiscardable(id)) { - DEBUG(sl, 1, "Discarding chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id); - SlLoadCheckChunk(nullptr); + SlLoadCheckChunk(nullptr, id); } else { const ChunkHandler *ch = SlFindChunkHandler(id); if (ch == nullptr) { - SlErrorCorrupt("Unknown chunk type"); + SlErrorCorruptFmt("Unknown chunk type: %s", ChunkIDDumper()(id)); } else { SlLoadChunk(*ch); } } - DEBUG(sl, 3, "Loaded chunk %c%c%c%c (" PRINTF_SIZE " bytes)", id >> 24, id >> 16, id >> 8, id, SlGetBytesRead() - read); + DEBUG(sl, 3, "Loaded chunk %s (" PRINTF_SIZE " bytes)", ChunkIDDumper()(id), SlGetBytesRead() - read); } } @@ -2710,7 +2716,6 @@ static void SlLoadCheckChunks() for (id = SlReadUint32(); id != 0; id = SlReadUint32()) { _sl.current_chunk_id = id; - DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id); size_t read = 0; if (_debug_sl_level >= 3) read = SlGetBytesRead(); @@ -2718,10 +2723,10 @@ static void SlLoadCheckChunks() ch = nullptr; } else { ch = SlFindChunkHandler(id); - if (ch == nullptr) SlErrorCorrupt("Unknown chunk type"); + if (ch == nullptr) SlErrorCorruptFmt("Unknown chunk type: %s", ChunkIDDumper()(id)); } - SlLoadCheckChunk(ch); - DEBUG(sl, 3, "Loaded chunk %c%c%c%c (" PRINTF_SIZE " bytes)", id >> 24, id >> 16, id >> 8, id, SlGetBytesRead() - read); + SlLoadCheckChunk(ch, id); + DEBUG(sl, 3, "Loaded chunk %s (" PRINTF_SIZE " bytes)", ChunkIDDumper()(id), SlGetBytesRead() - read); } } @@ -2740,7 +2745,7 @@ static void SlFixPointers() 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); + DEBUG(sl, 3, "Fixing pointers for %s", ChunkIDDumper()(ch.id)); ch.ptrs_proc(); } } @@ -4198,3 +4203,9 @@ void SlUnreachablePlaceholder() { NOT_REACHED(); } + +const char *ChunkIDDumper::operator()(uint32_t id) +{ + seprintf(this->buffer, lastof(this->buffer), "%c%c%c%c", id >> 24, id >> 16, id >> 8, id); + return this->buffer; +} diff --git a/src/sl/saveload.h b/src/sl/saveload.h index 00d7f93589..a55acd3a08 100644 --- a/src/sl/saveload.h +++ b/src/sl/saveload.h @@ -125,6 +125,13 @@ struct ChunkHandler { ChunkSaveLoadSpecialProc *special_proc = nullptr; }; +struct ChunkIDDumper { + const char *operator()(uint32_t id); + +private: + char buffer[5]; +}; + template void SlExecWithSlVersion(SaveLoadVersion use_version, F proc) {