From 2c941cd8b3cb1774f4982b86735e276597a91750 Mon Sep 17 00:00:00 2001 From: glx22 Date: Mon, 7 Jun 2021 23:24:37 +0200 Subject: [PATCH] Codechange: Use ChunkHandlers sub-classes --- src/order_backup.h | 2 +- src/order_base.h | 2 +- src/saveload/ai_sl.cpp | 116 +++--- src/saveload/airport_sl.cpp | 44 ++- src/saveload/animated_tile_sl.cpp | 75 ++-- src/saveload/autoreplace_sl.cpp | 65 ++-- src/saveload/cargomonitor_sl.cpp | 125 +++---- src/saveload/cargopacket_sl.cpp | 42 ++- src/saveload/cheat_sl.cpp | 69 ++-- src/saveload/company_sl.cpp | 105 +++--- src/saveload/depot_sl.cpp | 61 ++-- src/saveload/economy_sl.cpp | 129 ++++--- src/saveload/engine_sl.cpp | 128 ++++--- src/saveload/game_sl.cpp | 166 ++++----- src/saveload/gamelog_sl.cpp | 83 +++-- src/saveload/goal_sl.cpp | 36 +- src/saveload/group_sl.cpp | 58 +-- src/saveload/industry_sl.cpp | 203 ++++++----- src/saveload/labelmaps_sl.cpp | 42 ++- src/saveload/linkgraph_sl.cpp | 133 +++---- src/saveload/map_sl.cpp | 567 ++++++++++++++++-------------- src/saveload/misc_sl.cpp | 99 +++--- src/saveload/newgrf_sl.cpp | 83 +++-- src/saveload/object_sl.cpp | 85 +++-- src/saveload/order_sl.cpp | 277 ++++++++------- src/saveload/settings_sl.cpp | 63 ++-- src/saveload/signs_sl.cpp | 68 ++-- src/saveload/station_sl.cpp | 182 +++++----- src/saveload/storage_sl.cpp | 45 +-- src/saveload/story_sl.cpp | 108 +++--- src/saveload/strings_sl.cpp | 29 +- src/saveload/subsidy_sl.cpp | 36 +- src/saveload/town_sl.cpp | 82 +++-- src/saveload/vehicle_sl.cpp | 131 +++---- src/saveload/waypoint_sl.cpp | 79 +++-- 35 files changed, 1953 insertions(+), 1665 deletions(-) diff --git a/src/order_backup.h b/src/order_backup.h index e1b71a71d7..c92adbb411 100644 --- a/src/order_backup.h +++ b/src/order_backup.h @@ -36,7 +36,7 @@ static const uint32 MAKE_ORDER_BACKUP_FLAG = 1U << 31; struct OrderBackup : OrderBackupPool::PoolItem<&_order_backup_pool>, BaseConsist { private: friend SaveLoadTable GetOrderBackupDescription(); ///< Saving and loading of order backups. - friend void Load_BKOR(); ///< Creating empty orders upon savegame loading. + friend struct BKORChunkHandler; ///< Creating empty orders upon savegame loading. uint32 user; ///< The user that requested the backup. TileIndex tile; ///< Tile of the depot where the order was changed. GroupID group; ///< The group the vehicle was part of. diff --git a/src/order_base.h b/src/order_base.h index 84f5289ec1..a722ef5d45 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -32,7 +32,7 @@ extern OrderListPool _orderlist_pool; */ struct Order : OrderPool::PoolItem<&_order_pool> { private: - friend void Load_VEHS(); ///< Loading of ancient vehicles. + friend struct VEHSChunkHandler; ///< Loading of ancient vehicles. friend SaveLoadTable GetOrderDescription(); ///< Saving and loading of orders. /* So we can use private/protected variables in the saveload code */ friend class SlVehicleCommon; diff --git a/src/saveload/ai_sl.cpp b/src/saveload/ai_sl.cpp index f5cf040a93..51a67b14aa 100644 --- a/src/saveload/ai_sl.cpp +++ b/src/saveload/ai_sl.cpp @@ -57,77 +57,81 @@ static void SaveReal_AIPL(int *index_ptr) if (Company::IsValidAiID(index)) AI::Save(index); } -static void Load_AIPL() -{ - const std::vector slt = SlCompatTableHeader(_ai_company_desc, _ai_company_sl_compat); +struct AIPLChunkHandler : ChunkHandler { + AIPLChunkHandler() : ChunkHandler('AIPL', CH_TABLE) {} - /* Free all current data */ - for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) { - AIConfig::GetConfig(c, AIConfig::SSS_FORCE_GAME)->Change(nullptr); - } + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_ai_company_desc, _ai_company_sl_compat); - CompanyID index; - while ((index = (CompanyID)SlIterateArray()) != (CompanyID)-1) { - if (index >= MAX_COMPANIES) SlErrorCorrupt("Too many AI configs"); - - _ai_saveload_is_random = false; - _ai_saveload_version = -1; - SlObject(nullptr, slt); - - if (_networking && !_network_server) { - if (Company::IsValidAiID(index)) AIInstance::LoadEmpty(); - continue; + /* Free all current data */ + for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) { + AIConfig::GetConfig(c, AIConfig::SSS_FORCE_GAME)->Change(nullptr); } - AIConfig *config = AIConfig::GetConfig(index, AIConfig::SSS_FORCE_GAME); - if (_ai_saveload_name.empty()) { - /* A random AI. */ - config->Change(nullptr, -1, false, true); - } else { - config->Change(_ai_saveload_name.c_str(), _ai_saveload_version, false, _ai_saveload_is_random); - if (!config->HasScript()) { - /* No version of the AI available that can load the data. Try to load the - * latest version of the AI instead. */ - config->Change(_ai_saveload_name.c_str(), -1, false, _ai_saveload_is_random); + CompanyID index; + while ((index = (CompanyID)SlIterateArray()) != (CompanyID)-1) { + if (index >= MAX_COMPANIES) SlErrorCorrupt("Too many AI configs"); + + _ai_saveload_is_random = false; + _ai_saveload_version = -1; + SlObject(nullptr, slt); + + if (_networking && !_network_server) { + if (Company::IsValidAiID(index)) AIInstance::LoadEmpty(); + continue; + } + + AIConfig *config = AIConfig::GetConfig(index, AIConfig::SSS_FORCE_GAME); + if (_ai_saveload_name.empty()) { + /* A random AI. */ + config->Change(nullptr, -1, false, true); + } else { + config->Change(_ai_saveload_name.c_str(), _ai_saveload_version, false, _ai_saveload_is_random); if (!config->HasScript()) { - if (_ai_saveload_name.compare("%_dummy") != 0) { - Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version); - Debug(script, 0, "A random other AI will be loaded in its place."); + /* No version of the AI available that can load the data. Try to load the + * latest version of the AI instead. */ + config->Change(_ai_saveload_name.c_str(), -1, false, _ai_saveload_is_random); + if (!config->HasScript()) { + if (_ai_saveload_name.compare("%_dummy") != 0) { + Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version); + Debug(script, 0, "A random other AI will be loaded in its place."); + } else { + Debug(script, 0, "The savegame had no AIs available at the time of saving."); + Debug(script, 0, "A random available AI will be loaded now."); + } } else { - Debug(script, 0, "The savegame had no AIs available at the time of saving."); - Debug(script, 0, "A random available AI will be loaded now."); + Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version); + Debug(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible."); } - } else { - Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version); - Debug(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible."); + /* Make sure the AI doesn't get the saveload data, as it was not the + * writer of the saveload data in the first place */ + _ai_saveload_version = -1; } - /* Make sure the AI doesn't get the saveload data, as it was not the - * writer of the saveload data in the first place */ - _ai_saveload_version = -1; + } + + config->StringToSettings(_ai_saveload_settings); + + /* Start the AI directly if it was active in the savegame */ + if (Company::IsValidAiID(index)) { + AI::StartNew(index, false); + AI::Load(index, _ai_saveload_version); } } + } - config->StringToSettings(_ai_saveload_settings); + void Save() const override + { + SlTableHeader(_ai_company_desc); - /* Start the AI directly if it was active in the savegame */ - if (Company::IsValidAiID(index)) { - AI::StartNew(index, false); - AI::Load(index, _ai_saveload_version); + for (int i = COMPANY_FIRST; i < MAX_COMPANIES; i++) { + SlSetArrayIndex(i); + SlAutolength((AutolengthProc *)SaveReal_AIPL, &i); } } -} +}; -static void Save_AIPL() -{ - SlTableHeader(_ai_company_desc); - - for (int i = COMPANY_FIRST; i < MAX_COMPANIES; i++) { - SlSetArrayIndex(i); - SlAutolength((AutolengthProc *)SaveReal_AIPL, &i); - } -} - -static const ChunkHandler AIPL{ 'AIPL', Save_AIPL, Load_AIPL, nullptr, nullptr, CH_TABLE }; +static const AIPLChunkHandler AIPL; static const ChunkHandlerRef ai_chunk_handlers[] = { AIPL, }; diff --git a/src/saveload/airport_sl.cpp b/src/saveload/airport_sl.cpp index 3ab852150f..e762c54d01 100644 --- a/src/saveload/airport_sl.cpp +++ b/src/saveload/airport_sl.cpp @@ -14,28 +14,36 @@ #include "../safeguards.h" -static void Save_APID() -{ - Save_NewGRFMapping(_airport_mngr); -} +struct APIDChunkHandler : ChunkHandler { + APIDChunkHandler() : ChunkHandler('APID', CH_TABLE) {} -static void Load_APID() -{ - Load_NewGRFMapping(_airport_mngr); -} + void Save() const override + { + Save_NewGRFMapping(_airport_mngr); + } -static void Save_ATID() -{ - Save_NewGRFMapping(_airporttile_mngr); -} + void Load() const override + { + Load_NewGRFMapping(_airport_mngr); + } +}; -static void Load_ATID() -{ - Load_NewGRFMapping(_airporttile_mngr); -} +struct ATIDChunkHandler : ChunkHandler { + ATIDChunkHandler() : ChunkHandler('ATID', CH_TABLE) {} -static const ChunkHandler ATID{ 'ATID', Save_ATID, Load_ATID, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler APID{ 'APID', Save_APID, Load_APID, nullptr, nullptr, CH_TABLE }; + void Save() const override + { + Save_NewGRFMapping(_airporttile_mngr); + } + + void Load() const override + { + Load_NewGRFMapping(_airporttile_mngr); + } +}; + +static const ATIDChunkHandler ATID; +static const APIDChunkHandler APID; static const ChunkHandlerRef airport_chunk_handlers[] = { ATID, APID, diff --git a/src/saveload/animated_tile_sl.cpp b/src/saveload/animated_tile_sl.cpp index 607c2ed978..282968f9b4 100644 --- a/src/saveload/animated_tile_sl.cpp +++ b/src/saveload/animated_tile_sl.cpp @@ -24,51 +24,50 @@ static const SaveLoad _animated_tile_desc[] = { SLEG_VECTOR("tiles", _animated_tiles, SLE_UINT32), }; -/** - * Save the ANIT chunk. - */ -static void Save_ANIT() -{ - SlTableHeader(_animated_tile_desc); +struct ANITChunkHandler : ChunkHandler { + ANITChunkHandler() : ChunkHandler('ANIT', CH_TABLE) {} - SlSetArrayIndex(0); - SlGlobList(_animated_tile_desc); -} + void Save() const override + { + SlTableHeader(_animated_tile_desc); -/** - * Load the ANIT chunk; the chunk containing the animated tiles. - */ -static void Load_ANIT() -{ - /* Before version 80 we did NOT have a variable length animated tile table */ - if (IsSavegameVersionBefore(SLV_80)) { - /* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */ - TileIndex anim_list[256]; - SlCopy(anim_list, 256, IsSavegameVersionBefore(SLV_6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32); + SlSetArrayIndex(0); + SlGlobList(_animated_tile_desc); + } - for (int i = 0; i < 256; i++) { - if (anim_list[i] == 0) break; - _animated_tiles.push_back(anim_list[i]); + void Load() const override + { + /* Before version 80 we did NOT have a variable length animated tile table */ + if (IsSavegameVersionBefore(SLV_80)) { + /* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */ + TileIndex anim_list[256]; + SlCopy(anim_list, 256, IsSavegameVersionBefore(SLV_6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32); + + for (int i = 0; i < 256; i++) { + if (anim_list[i] == 0) break; + _animated_tiles.push_back(anim_list[i]); + } + return; } - return; + + if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) { + size_t count = SlGetFieldLength() / sizeof(_animated_tiles.front()); + _animated_tiles.clear(); + _animated_tiles.resize(_animated_tiles.size() + count); + SlCopy(_animated_tiles.data(), count, SLE_UINT32); + return; + } + + const std::vector slt = SlCompatTableHeader(_animated_tile_desc, _animated_tile_sl_compat); + + if (SlIterateArray() == -1) return; + SlGlobList(slt); + if (SlIterateArray() != -1) SlErrorCorrupt("Too many ANIT entries"); } +}; - if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) { - size_t count = SlGetFieldLength() / sizeof(_animated_tiles.front()); - _animated_tiles.clear(); - _animated_tiles.resize(_animated_tiles.size() + count); - SlCopy(_animated_tiles.data(), count, SLE_UINT32); - return; - } - const std::vector slt = SlCompatTableHeader(_animated_tile_desc, _animated_tile_sl_compat); - - if (SlIterateArray() == -1) return; - SlGlobList(slt); - if (SlIterateArray() != -1) SlErrorCorrupt("Too many ANIT entries"); -} - -static const ChunkHandler ANIT{ 'ANIT', Save_ANIT, Load_ANIT, nullptr, nullptr, CH_TABLE }; +static const ANITChunkHandler ANIT; static const ChunkHandlerRef animated_tile_chunk_handlers[] = { ANIT, }; diff --git a/src/saveload/autoreplace_sl.cpp b/src/saveload/autoreplace_sl.cpp index 3882468330..6a9dd8f006 100644 --- a/src/saveload/autoreplace_sl.cpp +++ b/src/saveload/autoreplace_sl.cpp @@ -25,43 +25,50 @@ static const SaveLoad _engine_renew_desc[] = { SLE_CONDVAR(EngineRenew, replace_when_old, SLE_BOOL, SLV_175, SL_MAX_VERSION), }; -static void Save_ERNW() -{ - SlTableHeader(_engine_renew_desc); - - for (EngineRenew *er : EngineRenew::Iterate()) { - SlSetArrayIndex(er->index); - SlObject(er, _engine_renew_desc); +struct ERNWChunkHandler : ChunkHandler { + ERNWChunkHandler() : ChunkHandler('ERNW', CH_TABLE) + { + this->fix_pointers = true; } -} -static void Load_ERNW() -{ - const std::vector slt = SlCompatTableHeader(_engine_renew_desc, _engine_renew_sl_compat); + void Save() const override + { + SlTableHeader(_engine_renew_desc); - int index; - - while ((index = SlIterateArray()) != -1) { - EngineRenew *er = new (index) EngineRenew(); - SlObject(er, slt); - - /* Advanced vehicle lists, ungrouped vehicles got added */ - if (IsSavegameVersionBefore(SLV_60)) { - er->group_id = ALL_GROUP; - } else if (IsSavegameVersionBefore(SLV_71)) { - if (er->group_id == DEFAULT_GROUP) er->group_id = ALL_GROUP; + for (EngineRenew *er : EngineRenew::Iterate()) { + SlSetArrayIndex(er->index); + SlObject(er, _engine_renew_desc); } } -} -static void Ptrs_ERNW() -{ - for (EngineRenew *er : EngineRenew::Iterate()) { - SlObject(er, _engine_renew_desc); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_engine_renew_desc, _engine_renew_sl_compat); + + int index; + + while ((index = SlIterateArray()) != -1) { + EngineRenew *er = new (index) EngineRenew(); + SlObject(er, slt); + + /* Advanced vehicle lists, ungrouped vehicles got added */ + if (IsSavegameVersionBefore(SLV_60)) { + er->group_id = ALL_GROUP; + } else if (IsSavegameVersionBefore(SLV_71)) { + if (er->group_id == DEFAULT_GROUP) er->group_id = ALL_GROUP; + } + } } -} -static const ChunkHandler ERNW{ 'ERNW', Save_ERNW, Load_ERNW, Ptrs_ERNW, nullptr, CH_TABLE }; + void FixPointers() const override + { + for (EngineRenew *er : EngineRenew::Iterate()) { + SlObject(er, _engine_renew_desc); + } + } +}; + +static const ERNWChunkHandler ERNW; static const ChunkHandlerRef autoreplace_chunk_handlers[] = { ERNW, }; diff --git a/src/saveload/cargomonitor_sl.cpp b/src/saveload/cargomonitor_sl.cpp index b660609b5f..80b32f16b6 100644 --- a/src/saveload/cargomonitor_sl.cpp +++ b/src/saveload/cargomonitor_sl.cpp @@ -43,92 +43,97 @@ static CargoMonitorID FixupCargoMonitor(CargoMonitorID number) return number; } -/** Save the #_cargo_deliveries monitoring map. */ -static void SaveDelivery() -{ - SlTableHeader(_cargomonitor_pair_desc); +/** #_cargo_deliveries monitoring map. */ +struct CMDLChunkHandler : ChunkHandler { + CMDLChunkHandler() : ChunkHandler('CMDL', CH_TABLE) {} - TempStorage storage; + void Save() const override + { + SlTableHeader(_cargomonitor_pair_desc); - int i = 0; - CargoMonitorMap::const_iterator iter = _cargo_deliveries.begin(); - while (iter != _cargo_deliveries.end()) { - storage.number = iter->first; - storage.amount = iter->second; + TempStorage storage; - SlSetArrayIndex(i); - SlObject(&storage, _cargomonitor_pair_desc); + int i = 0; + CargoMonitorMap::const_iterator iter = _cargo_deliveries.begin(); + while (iter != _cargo_deliveries.end()) { + storage.number = iter->first; + storage.amount = iter->second; - i++; - iter++; + SlSetArrayIndex(i); + SlObject(&storage, _cargomonitor_pair_desc); + + i++; + iter++; + } } -} -/** Load the #_cargo_deliveries monitoring map. */ -static void LoadDelivery() -{ - const std::vector slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat); - TempStorage storage; - bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR); + TempStorage storage; + bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR); - ClearCargoDeliveryMonitoring(); - for (;;) { - if (SlIterateArray() < 0) break; - SlObject(&storage, slt); + ClearCargoDeliveryMonitoring(); + for (;;) { + if (SlIterateArray() < 0) break; + SlObject(&storage, slt); - if (fix) storage.number = FixupCargoMonitor(storage.number); + if (fix) storage.number = FixupCargoMonitor(storage.number); - std::pair p(storage.number, storage.amount); - _cargo_deliveries.insert(p); + std::pair p(storage.number, storage.amount); + _cargo_deliveries.insert(p); + } } -} +}; +/** #_cargo_pickups monitoring map. */ +struct CMPUChunkHandler : ChunkHandler { + CMPUChunkHandler() : ChunkHandler('CMPU', CH_TABLE) {} -/** Save the #_cargo_pickups monitoring map. */ -static void SavePickup() -{ - SlTableHeader(_cargomonitor_pair_desc); + void Save() const override + { + SlTableHeader(_cargomonitor_pair_desc); - TempStorage storage; + TempStorage storage; - int i = 0; - CargoMonitorMap::const_iterator iter = _cargo_pickups.begin(); - while (iter != _cargo_pickups.end()) { - storage.number = iter->first; - storage.amount = iter->second; + int i = 0; + CargoMonitorMap::const_iterator iter = _cargo_pickups.begin(); + while (iter != _cargo_pickups.end()) { + storage.number = iter->first; + storage.amount = iter->second; - SlSetArrayIndex(i); - SlObject(&storage, _cargomonitor_pair_desc); + SlSetArrayIndex(i); + SlObject(&storage, _cargomonitor_pair_desc); - i++; - iter++; + i++; + iter++; + } } -} -/** Load the #_cargo_pickups monitoring map. */ -static void LoadPickup() -{ - const std::vector slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat); - TempStorage storage; - bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR); + TempStorage storage; + bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR); - ClearCargoPickupMonitoring(); - for (;;) { - if (SlIterateArray() < 0) break; - SlObject(&storage, slt); + ClearCargoPickupMonitoring(); + for (;;) { + if (SlIterateArray() < 0) break; + SlObject(&storage, slt); - if (fix) storage.number = FixupCargoMonitor(storage.number); + if (fix) storage.number = FixupCargoMonitor(storage.number); - std::pair p(storage.number, storage.amount); - _cargo_pickups.insert(p); + std::pair p(storage.number, storage.amount); + _cargo_pickups.insert(p); + } } -} +}; /** Chunk definition of the cargomonitoring maps. */ -static const ChunkHandler CMDL{ 'CMDL', SaveDelivery, LoadDelivery, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler CMPU{ 'CMPU', SavePickup, LoadPickup, nullptr, nullptr, CH_TABLE }; +static const CMDLChunkHandler CMDL; +static const CMPUChunkHandler CMPU; static const ChunkHandlerRef cargomonitor_chunk_handlers[] = { CMDL, CMPU, diff --git a/src/saveload/cargopacket_sl.cpp b/src/saveload/cargopacket_sl.cpp index c37d6434be..95b9bec6bf 100644 --- a/src/saveload/cargopacket_sl.cpp +++ b/src/saveload/cargopacket_sl.cpp @@ -100,35 +100,33 @@ SaveLoadTable GetCargoPacketDesc() return _cargopacket_desc; } -/** - * Save the cargo packets. - */ -static void Save_CAPA() -{ - SlTableHeader(GetCargoPacketDesc()); +struct CAPAChunkHandler : ChunkHandler { + CAPAChunkHandler() : ChunkHandler('CAPA', CH_TABLE) {} - for (CargoPacket *cp : CargoPacket::Iterate()) { - SlSetArrayIndex(cp->index); - SlObject(cp, GetCargoPacketDesc()); + void Save() const override + { + SlTableHeader(GetCargoPacketDesc()); + + for (CargoPacket *cp : CargoPacket::Iterate()) { + SlSetArrayIndex(cp->index); + SlObject(cp, GetCargoPacketDesc()); + } } -} -/** - * Load the cargo packets. - */ -static void Load_CAPA() -{ - const std::vector slt = SlCompatTableHeader(GetCargoPacketDesc(), _cargopacket_sl_compat); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(GetCargoPacketDesc(), _cargopacket_sl_compat); - int index; + int index; - while ((index = SlIterateArray()) != -1) { - CargoPacket *cp = new (index) CargoPacket(); - SlObject(cp, slt); + while ((index = SlIterateArray()) != -1) { + CargoPacket *cp = new (index) CargoPacket(); + SlObject(cp, slt); + } } -} +}; -static const ChunkHandler CAPA{ 'CAPA', Save_CAPA, Load_CAPA, nullptr, nullptr, CH_TABLE }; +static const CAPAChunkHandler CAPA; static const ChunkHandlerRef cargopacket_chunk_handlers[] = { CAPA, }; diff --git a/src/saveload/cheat_sl.cpp b/src/saveload/cheat_sl.cpp index f68b5a5a57..939a734aaf 100644 --- a/src/saveload/cheat_sl.cpp +++ b/src/saveload/cheat_sl.cpp @@ -35,47 +35,46 @@ static const SaveLoad _cheats_desc[] = { SLE_VAR(Cheats, edit_max_hl.value, SLE_BOOL), }; -/** - * Save the cheat values. - */ -static void Save_CHTS() -{ - SlTableHeader(_cheats_desc); - SlSetArrayIndex(0); - SlObject(&_cheats, _cheats_desc); -} +struct CHTSChunkHandler : ChunkHandler { + CHTSChunkHandler() : ChunkHandler('CHTS', CH_TABLE) {} -/** - * Load the cheat values. - */ -static void Load_CHTS() -{ - std::vector slt = SlCompatTableHeader(_cheats_desc, _cheats_sl_compat); + void Save() const override + { + SlTableHeader(_cheats_desc); - if (IsSavegameVersionBefore(SLV_TABLE_CHUNKS)) { - size_t count = SlGetFieldLength(); - std::vector oslt; - - /* Cheats were added over the years without a savegame bump. They are - * stored as 2 SLE_BOOLs per entry. "count" indicates how many SLE_BOOLs - * are stored for this savegame. So read only "count" SLE_BOOLs (and in - * result "count / 2" cheats). */ - for (auto &sld : slt) { - count--; - oslt.push_back(sld); - - if (count == 0) break; - } - slt = oslt; + SlSetArrayIndex(0); + SlObject(&_cheats, _cheats_desc); } - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; - SlObject(&_cheats, slt); - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many CHTS entries"); -} + void Load() const override + { + std::vector slt = SlCompatTableHeader(_cheats_desc, _cheats_sl_compat); -static const ChunkHandler CHTS{ 'CHTS', Save_CHTS, Load_CHTS, nullptr, nullptr, CH_TABLE }; + if (IsSavegameVersionBefore(SLV_TABLE_CHUNKS)) { + size_t count = SlGetFieldLength(); + std::vector oslt; + + /* Cheats were added over the years without a savegame bump. They are + * stored as 2 SLE_BOOLs per entry. "count" indicates how many SLE_BOOLs + * are stored for this savegame. So read only "count" SLE_BOOLs (and in + * result "count / 2" cheats). */ + for (auto &sld : slt) { + count--; + oslt.push_back(sld); + + if (count == 0) break; + } + slt = oslt; + } + + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlObject(&_cheats, slt); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many CHTS entries"); + } +}; + +static const CHTSChunkHandler CHTS; static const ChunkHandlerRef cheat_chunk_handlers[] = { CHTS, }; diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index b4dfd13507..fab674f8bf 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -497,67 +497,76 @@ static const SaveLoad _company_desc[] = { SLEG_CONDSTRUCTLIST("liveries", SlCompanyLiveries, SLV_34, SL_MAX_VERSION), }; -static void Save_PLYR() -{ - SlTableHeader(_company_desc); - - for (Company *c : Company::Iterate()) { - SlSetArrayIndex(c->index); - SlObject(c, _company_desc); +struct PLYRChunkHandler : ChunkHandler { + PLYRChunkHandler() : ChunkHandler('PLYR', CH_TABLE) + { + this->load_check = true; + this->fix_pointers = true; } -} -static void Load_PLYR() -{ - const std::vector slt = SlCompatTableHeader(_company_desc, _company_sl_compat); + void Save() const override + { + SlTableHeader(_company_desc); - int index; - while ((index = SlIterateArray()) != -1) { - Company *c = new (index) Company(); - SlObject(c, slt); - _company_colours[index] = (Colours)c->colour; - } -} - -static void Check_PLYR() -{ - const std::vector slt = SlCompatTableHeader(_company_desc, _company_sl_compat); - - int index; - while ((index = SlIterateArray()) != -1) { - CompanyProperties *cprops = new CompanyProperties(); - SlObject(cprops, slt); - - /* We do not load old custom names */ - if (IsSavegameVersionBefore(SLV_84)) { - if (GetStringTab(cprops->name_1) == TEXT_TAB_OLD_CUSTOM) { - cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE; - } - - if (GetStringTab(cprops->president_name_1) == TEXT_TAB_OLD_CUSTOM) { - cprops->president_name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE; - } + for (Company *c : Company::Iterate()) { + SlSetArrayIndex(c->index); + SlObject(c, _company_desc); } + } - if (cprops->name.empty() && !IsInsideMM(cprops->name_1, SPECSTR_COMPANY_NAME_START, SPECSTR_COMPANY_NAME_LAST + 1) && + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_company_desc, _company_sl_compat); + + int index; + while ((index = SlIterateArray()) != -1) { + Company *c = new (index) Company(); + SlObject(c, slt); + _company_colours[index] = (Colours)c->colour; + } + } + + + void LoadCheck(size_t) const override + { + const std::vector slt = SlCompatTableHeader(_company_desc, _company_sl_compat); + + int index; + while ((index = SlIterateArray()) != -1) { + CompanyProperties *cprops = new CompanyProperties(); + SlObject(cprops, slt); + + /* We do not load old custom names */ + if (IsSavegameVersionBefore(SLV_84)) { + if (GetStringTab(cprops->name_1) == TEXT_TAB_OLD_CUSTOM) { + cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE; + } + + if (GetStringTab(cprops->president_name_1) == TEXT_TAB_OLD_CUSTOM) { + cprops->president_name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE; + } + } + + if (cprops->name.empty() && !IsInsideMM(cprops->name_1, SPECSTR_COMPANY_NAME_START, SPECSTR_COMPANY_NAME_LAST + 1) && cprops->name_1 != STR_GAME_SAVELOAD_NOT_AVAILABLE && cprops->name_1 != STR_SV_UNNAMED && cprops->name_1 != SPECSTR_ANDCO_NAME && cprops->name_1 != SPECSTR_PRESIDENT_NAME && cprops->name_1 != SPECSTR_SILLY_NAME) { - cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE; + cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE; + } + + if (!_load_check_data.companies.Insert(index, cprops)) delete cprops; } - - if (!_load_check_data.companies.Insert(index, cprops)) delete cprops; } -} -static void Ptrs_PLYR() -{ - for (Company *c : Company::Iterate()) { - SlObject(c, _company_desc); + void FixPointers() const override + { + for (Company *c : Company::Iterate()) { + SlObject(c, _company_desc); + } } -} +}; -static const ChunkHandler PLYR{ 'PLYR', Save_PLYR, Load_PLYR, Ptrs_PLYR, Check_PLYR, CH_TABLE }; +static const PLYRChunkHandler PLYR; static const ChunkHandlerRef company_chunk_handlers[] = { PLYR, }; diff --git a/src/saveload/depot_sl.cpp b/src/saveload/depot_sl.cpp index b34108c214..ef0c406e22 100644 --- a/src/saveload/depot_sl.cpp +++ b/src/saveload/depot_sl.cpp @@ -29,40 +29,47 @@ static const SaveLoad _depot_desc[] = { SLE_CONDVAR(Depot, build_date, SLE_INT32, SLV_142, SL_MAX_VERSION), }; -static void Save_DEPT() -{ - SlTableHeader(_depot_desc); - - for (Depot *depot : Depot::Iterate()) { - SlSetArrayIndex(depot->index); - SlObject(depot, _depot_desc); +struct DEPTChunkHandler : ChunkHandler { + DEPTChunkHandler() : ChunkHandler('DEPT', CH_TABLE) + { + this->fix_pointers = true; } -} -static void Load_DEPT() -{ - const std::vector slt = SlCompatTableHeader(_depot_desc, _depot_sl_compat); + void Save() const override + { + SlTableHeader(_depot_desc); - int index; - - while ((index = SlIterateArray()) != -1) { - Depot *depot = new (index) Depot(); - SlObject(depot, slt); - - /* Set the town 'pointer' so we can restore it later. */ - if (IsSavegameVersionBefore(SLV_141)) depot->town = (Town *)(size_t)_town_index; + for (Depot *depot : Depot::Iterate()) { + SlSetArrayIndex(depot->index); + SlObject(depot, _depot_desc); + } } -} -static void Ptrs_DEPT() -{ - for (Depot *depot : Depot::Iterate()) { - SlObject(depot, _depot_desc); - if (IsSavegameVersionBefore(SLV_141)) depot->town = Town::Get((size_t)depot->town); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_depot_desc, _depot_sl_compat); + + int index; + + while ((index = SlIterateArray()) != -1) { + Depot *depot = new (index) Depot(); + SlObject(depot, slt); + + /* Set the town 'pointer' so we can restore it later. */ + if (IsSavegameVersionBefore(SLV_141)) depot->town = (Town *)(size_t)_town_index; + } } -} -static const ChunkHandler DEPT{ 'DEPT', Save_DEPT, Load_DEPT, Ptrs_DEPT, nullptr, CH_TABLE }; + void FixPointers() const override + { + for (Depot *depot : Depot::Iterate()) { + SlObject(depot, _depot_desc); + if (IsSavegameVersionBefore(SLV_141)) depot->town = Town::Get((size_t)depot->town); + } + } +}; + +static const DEPTChunkHandler DEPT; static const ChunkHandlerRef depot_chunk_handlers[] = { DEPT, }; diff --git a/src/saveload/economy_sl.cpp b/src/saveload/economy_sl.cpp index 277901845c..3ce1441eea 100644 --- a/src/saveload/economy_sl.cpp +++ b/src/saveload/economy_sl.cpp @@ -18,22 +18,30 @@ #include "../safeguards.h" /** Prices in pre 126 savegames */ -static void Load_PRIC() -{ - /* Old games store 49 base prices, very old games store them as int32 */ - int vt = IsSavegameVersionBefore(SLV_65) ? SLE_FILE_I32 : SLE_FILE_I64; - SlCopy(nullptr, 49, vt | SLE_VAR_NULL); - SlCopy(nullptr, 49, SLE_FILE_U16 | SLE_VAR_NULL); -} +struct PRICChunkHandler : ChunkHandler { + PRICChunkHandler() : ChunkHandler('PRIC', CH_READONLY) {} + + void Load() const override + { + /* Old games store 49 base prices, very old games store them as int32 */ + int vt = IsSavegameVersionBefore(SLV_65) ? SLE_FILE_I32 : SLE_FILE_I64; + SlCopy(nullptr, 49, vt | SLE_VAR_NULL); + SlCopy(nullptr, 49, SLE_FILE_U16 | SLE_VAR_NULL); + } +}; /** Cargo payment rates in pre 126 savegames */ -static void Load_CAPR() -{ - uint num_cargo = IsSavegameVersionBefore(SLV_55) ? 12 : IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO; - int vt = IsSavegameVersionBefore(SLV_65) ? SLE_FILE_I32 : SLE_FILE_I64; - SlCopy(nullptr, num_cargo, vt | SLE_VAR_NULL); - SlCopy(nullptr, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL); -} +struct CAPRChunkHandler : ChunkHandler { + CAPRChunkHandler() : ChunkHandler('CAPR', CH_READONLY) {} + + void Load() const override + { + uint num_cargo = IsSavegameVersionBefore(SLV_55) ? 12 : IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO; + int vt = IsSavegameVersionBefore(SLV_65) ? SLE_FILE_I32 : SLE_FILE_I64; + SlCopy(nullptr, num_cargo, vt | SLE_VAR_NULL); + SlCopy(nullptr, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL); + } +}; static const SaveLoad _economy_desc[] = { SLE_CONDVAR(Economy, old_max_loan_unround, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65), @@ -49,25 +57,29 @@ static const SaveLoad _economy_desc[] = { }; /** Economy variables */ -static void Save_ECMY() -{ - SlTableHeader(_economy_desc); +struct ECMYChunkHandler : ChunkHandler { + ECMYChunkHandler() : ChunkHandler('ECMY', CH_TABLE) {} - SlSetArrayIndex(0); - SlObject(&_economy, _economy_desc); -} + void Save() const override + { + SlTableHeader(_economy_desc); -/** Economy variables */ -static void Load_ECMY() -{ - const std::vector slt = SlCompatTableHeader(_economy_desc, _economy_sl_compat); + SlSetArrayIndex(0); + SlObject(&_economy, _economy_desc); + } - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; - SlObject(&_economy, slt); - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many ECMY entries"); - StartupIndustryDailyChanges(IsSavegameVersionBefore(SLV_102)); // old savegames will need to be initialized -} + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_economy_desc, _economy_sl_compat); + + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlObject(&_economy, slt); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many ECMY entries"); + + StartupIndustryDailyChanges(IsSavegameVersionBefore(SLV_102)); // old savegames will need to be initialized + } +}; static const SaveLoad _cargopayment_desc[] = { SLE_REF(CargoPayment, front, REF_VEHICLE), @@ -76,39 +88,46 @@ static const SaveLoad _cargopayment_desc[] = { SLE_CONDVAR(CargoPayment, visual_transfer, SLE_INT64, SLV_181, SL_MAX_VERSION), }; -static void Save_CAPY() -{ - SlTableHeader(_cargopayment_desc); - - for (CargoPayment *cp : CargoPayment::Iterate()) { - SlSetArrayIndex(cp->index); - SlObject(cp, _cargopayment_desc); +struct CAPYChunkHandler : ChunkHandler { + CAPYChunkHandler() : ChunkHandler('CAPY', CH_TABLE) + { + this->fix_pointers = true; } -} -static void Load_CAPY() -{ - const std::vector slt = SlCompatTableHeader(_cargopayment_desc, _cargopayment_sl_compat); + void Save() const override + { + SlTableHeader(_cargopayment_desc); - int index; - - while ((index = SlIterateArray()) != -1) { - CargoPayment *cp = new (index) CargoPayment(); - SlObject(cp, slt); + for (CargoPayment *cp : CargoPayment::Iterate()) { + SlSetArrayIndex(cp->index); + SlObject(cp, _cargopayment_desc); + } } -} -static void Ptrs_CAPY() -{ - for (CargoPayment *cp : CargoPayment::Iterate()) { - SlObject(cp, _cargopayment_desc); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_cargopayment_desc, _cargopayment_sl_compat); + + int index; + + while ((index = SlIterateArray()) != -1) { + CargoPayment *cp = new (index) CargoPayment(); + SlObject(cp, slt); + } } -} -static const ChunkHandler CAPY{ 'CAPY', Save_CAPY, Load_CAPY, Ptrs_CAPY, nullptr, CH_TABLE }; -static const ChunkHandler PRIC{ 'PRIC', nullptr, Load_PRIC, nullptr, nullptr, CH_READONLY }; -static const ChunkHandler CAPR{ 'CAPR', nullptr, Load_CAPR, nullptr, nullptr, CH_READONLY }; -static const ChunkHandler ECMY{ 'ECMY', Save_ECMY, Load_ECMY, nullptr, nullptr, CH_TABLE }; + void FixPointers() const override + { + for (CargoPayment *cp : CargoPayment::Iterate()) { + SlObject(cp, _cargopayment_desc); + } + } +}; + +static const CAPYChunkHandler CAPY; +static const PRICChunkHandler PRIC; +static const CAPRChunkHandler CAPR; +static const ECMYChunkHandler ECMY; static const ChunkHandlerRef economy_chunk_handlers[] = { CAPY, PRIC, diff --git a/src/saveload/engine_sl.cpp b/src/saveload/engine_sl.cpp index aca046ec12..39699e04d5 100644 --- a/src/saveload/engine_sl.cpp +++ b/src/saveload/engine_sl.cpp @@ -80,37 +80,41 @@ Engine *GetTempDataEngine(EngineID index) } } -static void Save_ENGN() -{ - SlTableHeader(_engine_desc); +struct ENGNChunkHandler : ChunkHandler { + ENGNChunkHandler() : ChunkHandler('ENGN', CH_TABLE) {} - for (Engine *e : Engine::Iterate()) { - SlSetArrayIndex(e->index); - SlObject(e, _engine_desc); - } -} + void Save() const override + { + SlTableHeader(_engine_desc); -static void Load_ENGN() -{ - const std::vector slt = SlCompatTableHeader(_engine_desc, _engine_sl_compat); - - /* As engine data is loaded before engines are initialized we need to load - * this information into a temporary array. This is then copied into the - * engine pool after processing NewGRFs by CopyTempEngineData(). */ - int index; - while ((index = SlIterateArray()) != -1) { - Engine *e = GetTempDataEngine(index); - SlObject(e, slt); - - if (IsSavegameVersionBefore(SLV_179)) { - /* preview_company_rank was replaced with preview_company and preview_asked. - * Just cancel any previews. */ - e->flags &= ~4; // ENGINE_OFFER_WINDOW_OPEN - e->preview_company = INVALID_COMPANY; - e->preview_asked = (CompanyMask)-1; + for (Engine *e : Engine::Iterate()) { + SlSetArrayIndex(e->index); + SlObject(e, _engine_desc); } } -} + + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_engine_desc, _engine_sl_compat); + + /* As engine data is loaded before engines are initialized we need to load + * this information into a temporary array. This is then copied into the + * engine pool after processing NewGRFs by CopyTempEngineData(). */ + int index; + while ((index = SlIterateArray()) != -1) { + Engine *e = GetTempDataEngine(index); + SlObject(e, slt); + + if (IsSavegameVersionBefore(SLV_179)) { + /* preview_company_rank was replaced with preview_company and preview_asked. + * Just cancel any previews. */ + e->flags &= ~4; // ENGINE_OFFER_WINDOW_OPEN + e->preview_company = INVALID_COMPANY; + e->preview_asked = (CompanyMask)-1; + } + } + } +}; /** * Copy data from temporary engine array into the real engine pool. @@ -152,20 +156,24 @@ void ResetTempEngineData() _temp_engine.clear(); } -static void Load_ENGS() -{ - /* Load old separate String ID list into a temporary array. This - * was always 256 entries. */ - StringID names[256]; +struct ENGSChunkHandler : ChunkHandler { + ENGSChunkHandler() : ChunkHandler('ENGS', CH_READONLY) {} - SlCopy(names, lengthof(names), SLE_STRINGID); + void Load() const override + { + /* Load old separate String ID list into a temporary array. This + * was always 256 entries. */ + StringID names[256]; - /* Copy each string into the temporary engine array. */ - for (EngineID engine = 0; engine < lengthof(names); engine++) { - Engine *e = GetTempDataEngine(engine); - e->name = CopyFromOldName(names[engine]); + SlCopy(names, lengthof(names), SLE_STRINGID); + + /* Copy each string into the temporary engine array. */ + for (EngineID engine = 0; engine < lengthof(names); engine++) { + Engine *e = GetTempDataEngine(engine); + e->name = CopyFromOldName(names[engine]); + } } -} +}; /** Save and load the mapping between the engine id in the pool, and the grf file it came from. */ static const SaveLoad _engine_id_mapping_desc[] = { @@ -175,33 +183,37 @@ static const SaveLoad _engine_id_mapping_desc[] = { SLE_VAR(EngineIDMapping, substitute_id, SLE_UINT8), }; -static void Save_EIDS() -{ - SlTableHeader(_engine_id_mapping_desc); +struct EIDSChunkHandler : ChunkHandler { + EIDSChunkHandler() : ChunkHandler('EIDS', CH_TABLE) {} - uint index = 0; - for (EngineIDMapping &eid : _engine_mngr) { - SlSetArrayIndex(index); - SlObject(&eid, _engine_id_mapping_desc); - index++; + void Save() const override + { + SlTableHeader(_engine_id_mapping_desc); + + uint index = 0; + for (EngineIDMapping &eid : _engine_mngr) { + SlSetArrayIndex(index); + SlObject(&eid, _engine_id_mapping_desc); + index++; + } } -} -static void Load_EIDS() -{ - const std::vector slt = SlCompatTableHeader(_engine_id_mapping_desc, _engine_id_mapping_sl_compat); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_engine_id_mapping_desc, _engine_id_mapping_sl_compat); - _engine_mngr.clear(); + _engine_mngr.clear(); - while (SlIterateArray() != -1) { - EngineIDMapping *eid = &_engine_mngr.emplace_back(); - SlObject(eid, slt); + while (SlIterateArray() != -1) { + EngineIDMapping *eid = &_engine_mngr.emplace_back(); + SlObject(eid, slt); + } } -} +}; -static const ChunkHandler EIDS{ 'EIDS', Save_EIDS, Load_EIDS, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler ENGN{ 'ENGN', Save_ENGN, Load_ENGN, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler ENGS{ 'ENGS', nullptr, Load_ENGS, nullptr, nullptr, CH_READONLY }; +static const EIDSChunkHandler EIDS; +static const ENGNChunkHandler ENGN; +static const ENGSChunkHandler ENGS; static const ChunkHandlerRef engine_chunk_handlers[] = { EIDS, ENGN, diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index e075326ae0..bfd0b910c2 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -54,64 +54,68 @@ static void SaveReal_GSDT(int *index_ptr) Game::Save(); } -static void Load_GSDT() -{ - const std::vector slt = SlCompatTableHeader(_game_script_desc, _game_script_sl_compat); +struct GSDTChunkHandler : ChunkHandler { + GSDTChunkHandler() : ChunkHandler('GSDT', CH_TABLE) {} - /* Free all current data */ - GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME)->Change(nullptr); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_game_script_desc, _game_script_sl_compat); - if (SlIterateArray() == -1) return; + /* Free all current data */ + GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME)->Change(nullptr); - _game_saveload_version = -1; - SlObject(nullptr, slt); + if (SlIterateArray() == -1) return; - if (_networking && !_network_server) { - GameInstance::LoadEmpty(); - if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs"); - return; - } + _game_saveload_version = -1; + SlObject(nullptr, slt); - GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME); - if (!_game_saveload_name.empty()) { - config->Change(_game_saveload_name.c_str(), _game_saveload_version, false, _game_saveload_is_random); - if (!config->HasScript()) { - /* No version of the GameScript available that can load the data. Try to load the - * latest version of the GameScript instead. */ - config->Change(_game_saveload_name.c_str(), -1, false, _game_saveload_is_random); - if (!config->HasScript()) { - if (_game_saveload_name.compare("%_dummy") != 0) { - Debug(script, 0, "The savegame has an GameScript by the name '{}', version {} which is no longer available.", _game_saveload_name, _game_saveload_version); - Debug(script, 0, "This game will continue to run without GameScript."); - } else { - Debug(script, 0, "The savegame had no GameScript available at the time of saving."); - Debug(script, 0, "This game will continue to run without GameScript."); - } - } else { - Debug(script, 0, "The savegame has an GameScript by the name '{}', version {} which is no longer available.", _game_saveload_name, _game_saveload_version); - Debug(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible."); - } - /* Make sure the GameScript doesn't get the saveload data, as it was not the - * writer of the saveload data in the first place */ - _game_saveload_version = -1; + if (_networking && !_network_server) { + GameInstance::LoadEmpty(); + if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs"); + return; } + + GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME); + if (!_game_saveload_name.empty()) { + config->Change(_game_saveload_name.c_str(), _game_saveload_version, false, _game_saveload_is_random); + if (!config->HasScript()) { + /* No version of the GameScript available that can load the data. Try to load the + * latest version of the GameScript instead. */ + config->Change(_game_saveload_name.c_str(), -1, false, _game_saveload_is_random); + if (!config->HasScript()) { + if (_game_saveload_name.compare("%_dummy") != 0) { + Debug(script, 0, "The savegame has an GameScript by the name '{}', version {} which is no longer available.", _game_saveload_name, _game_saveload_version); + Debug(script, 0, "This game will continue to run without GameScript."); + } else { + Debug(script, 0, "The savegame had no GameScript available at the time of saving."); + Debug(script, 0, "This game will continue to run without GameScript."); + } + } else { + Debug(script, 0, "The savegame has an GameScript by the name '{}', version {} which is no longer available.", _game_saveload_name, _game_saveload_version); + Debug(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible."); + } + /* Make sure the GameScript doesn't get the saveload data, as it was not the + * writer of the saveload data in the first place */ + _game_saveload_version = -1; + } + } + + config->StringToSettings(_game_saveload_settings); + + /* Start the GameScript directly if it was active in the savegame */ + Game::StartNew(); + Game::Load(_game_saveload_version); + + if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs"); } - config->StringToSettings(_game_saveload_settings); - - /* Start the GameScript directly if it was active in the savegame */ - Game::StartNew(); - Game::Load(_game_saveload_version); - - if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs"); -} - -static void Save_GSDT() -{ - SlTableHeader(_game_script_desc); - SlSetArrayIndex(0); - SlAutolength((AutolengthProc *)SaveReal_GSDT, nullptr); -} + void Save() const override + { + SlTableHeader(_game_script_desc); + SlSetArrayIndex(0); + SlAutolength((AutolengthProc *)SaveReal_GSDT, nullptr); + } +}; extern GameStrings *_current_data; @@ -152,44 +156,48 @@ static const SaveLoad _game_language_desc[] = { SLEG_STRUCTLIST("strings", SlGameLanguageString), }; -static void Load_GSTR() -{ - const std::vector slt = SlCompatTableHeader(_game_language_desc, _game_language_sl_compat); +struct GSTRChunkHandler : ChunkHandler { + GSTRChunkHandler() : ChunkHandler('GSTR', CH_TABLE) {} - delete _current_data; - _current_data = new GameStrings(); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_game_language_desc, _game_language_sl_compat); - while (SlIterateArray() != -1) { - LanguageStrings ls; - SlObject(&ls, slt); - _current_data->raw_strings.push_back(std::move(ls)); - } - - /* If there were no strings in the savegame, set GameStrings to nullptr */ - if (_current_data->raw_strings.size() == 0) { delete _current_data; - _current_data = nullptr; - return; + _current_data = new GameStrings(); + + while (SlIterateArray() != -1) { + LanguageStrings ls; + SlObject(&ls, slt); + _current_data->raw_strings.push_back(std::move(ls)); + } + + /* If there were no strings in the savegame, set GameStrings to nullptr */ + if (_current_data->raw_strings.size() == 0) { + delete _current_data; + _current_data = nullptr; + return; + } + + _current_data->Compile(); + ReconsiderGameScriptLanguage(); } - _current_data->Compile(); - ReconsiderGameScriptLanguage(); -} + void Save() const override + { + SlTableHeader(_game_language_desc); -static void Save_GSTR() -{ - SlTableHeader(_game_language_desc); + if (_current_data == nullptr) return; - if (_current_data == nullptr) return; - - for (uint i = 0; i < _current_data->raw_strings.size(); i++) { - SlSetArrayIndex(i); - SlObject(&_current_data->raw_strings[i], _game_language_desc); + for (uint i = 0; i < _current_data->raw_strings.size(); i++) { + SlSetArrayIndex(i); + SlObject(&_current_data->raw_strings[i], _game_language_desc); + } } -} +}; -static const ChunkHandler GSTR{ 'GSTR', Save_GSTR, Load_GSTR, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler GSDT{ 'GSDT', Save_GSDT, Load_GSDT, nullptr, nullptr, CH_TABLE }; +static const GSTRChunkHandler GSTR; +static const GSDTChunkHandler GSDT; static const ChunkHandlerRef game_chunk_handlers[] = { GSTR, GSDT, diff --git a/src/saveload/gamelog_sl.cpp b/src/saveload/gamelog_sl.cpp index d2ca49aed2..3d71f2ff9e 100644 --- a/src/saveload/gamelog_sl.cpp +++ b/src/saveload/gamelog_sl.cpp @@ -347,61 +347,68 @@ static const SaveLoad _gamelog_desc[] = { SLEG_STRUCTLIST("action", SlGamelogAction), }; -static void Load_GLOG_common(LoggedAction *&gamelog_action, uint &gamelog_actions) -{ - assert(gamelog_action == nullptr); - assert(gamelog_actions == 0); +struct GLOGChunkHandler : ChunkHandler { + GLOGChunkHandler() : ChunkHandler('GLOG', CH_TABLE) + { + this->load_check = true; + } - const std::vector slt = SlCompatTableHeader(_gamelog_desc, _gamelog_sl_compat); + void LoadCommon(LoggedAction *&gamelog_action, uint &gamelog_actions) const + { + assert(gamelog_action == nullptr); + assert(gamelog_actions == 0); - if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) { - byte type; - while ((type = SlReadByte()) != GLAT_NONE) { - if (type >= GLAT_END) SlErrorCorrupt("Invalid gamelog action type"); + const std::vector slt = SlCompatTableHeader(_gamelog_desc, _gamelog_sl_compat); + if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) { + byte type; + while ((type = SlReadByte()) != GLAT_NONE) { + if (type >= GLAT_END) SlErrorCorrupt("Invalid gamelog action type"); + + gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1); + LoggedAction *la = &gamelog_action[gamelog_actions++]; + memset(la, 0, sizeof(*la)); + + la->at = (GamelogActionType)type; + SlObject(la, slt); + } + return; + } + + while (SlIterateArray() != -1) { gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1); LoggedAction *la = &gamelog_action[gamelog_actions++]; memset(la, 0, sizeof(*la)); - la->at = (GamelogActionType)type; SlObject(la, slt); } - return; } - while (SlIterateArray() != -1) { - gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1); - LoggedAction *la = &gamelog_action[gamelog_actions++]; - memset(la, 0, sizeof(*la)); + void Save() const override + { + SlTableHeader(_gamelog_desc); - SlObject(la, slt); + const LoggedAction *laend = &_gamelog_action[_gamelog_actions]; + + uint i = 0; + for (LoggedAction *la = _gamelog_action; la != laend; la++, i++) { + SlSetArrayIndex(i); + SlObject(la, _gamelog_desc); + } } -} -static void Save_GLOG() -{ - SlTableHeader(_gamelog_desc); - - const LoggedAction *laend = &_gamelog_action[_gamelog_actions]; - - uint i = 0; - for (LoggedAction *la = _gamelog_action; la != laend; la++, i++) { - SlSetArrayIndex(i); - SlObject(la, _gamelog_desc); + void Load() const override + { + this->LoadCommon(_gamelog_action, _gamelog_actions); } -} -static void Load_GLOG() -{ - Load_GLOG_common(_gamelog_action, _gamelog_actions); -} + void LoadCheck(size_t) const override + { + this->LoadCommon(_load_check_data.gamelog_action, _load_check_data.gamelog_actions); + } +}; -static void Check_GLOG() -{ - Load_GLOG_common(_load_check_data.gamelog_action, _load_check_data.gamelog_actions); -} - -static const ChunkHandler GLOG{ 'GLOG', Save_GLOG, Load_GLOG, nullptr, Check_GLOG, CH_TABLE }; +static const GLOGChunkHandler GLOG; static const ChunkHandlerRef gamelog_chunk_handlers[] = { GLOG, }; diff --git a/src/saveload/goal_sl.cpp b/src/saveload/goal_sl.cpp index 2dac477d0d..ae6b8577b2 100644 --- a/src/saveload/goal_sl.cpp +++ b/src/saveload/goal_sl.cpp @@ -25,28 +25,32 @@ static const SaveLoad _goals_desc[] = { SLE_CONDVAR(Goal, completed, SLE_BOOL, SLV_182, SL_MAX_VERSION), }; -static void Save_GOAL() -{ - SlTableHeader(_goals_desc); +struct GOALChunkHandler : ChunkHandler { + GOALChunkHandler() : ChunkHandler('GOAL', CH_TABLE) {} - for (Goal *s : Goal::Iterate()) { - SlSetArrayIndex(s->index); - SlObject(s, _goals_desc); + void Save() const override + { + SlTableHeader(_goals_desc); + + for (Goal *s : Goal::Iterate()) { + SlSetArrayIndex(s->index); + SlObject(s, _goals_desc); + } } -} -static void Load_GOAL() -{ - const std::vector slt = SlCompatTableHeader(_goals_desc, _goals_sl_compat); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_goals_desc, _goals_sl_compat); - int index; - while ((index = SlIterateArray()) != -1) { - Goal *s = new (index) Goal(); - SlObject(s, slt); + int index; + while ((index = SlIterateArray()) != -1) { + Goal *s = new (index) Goal(); + SlObject(s, slt); + } } -} +}; -static const ChunkHandler GOAL{ 'GOAL', Save_GOAL, Load_GOAL, nullptr, nullptr, CH_TABLE }; +static const GOALChunkHandler GOAL; static const ChunkHandlerRef goal_chunk_handlers[] = { GOAL, }; diff --git a/src/saveload/group_sl.cpp b/src/saveload/group_sl.cpp index 6c510b6e66..d286f1f204 100644 --- a/src/saveload/group_sl.cpp +++ b/src/saveload/group_sl.cpp @@ -28,38 +28,42 @@ static const SaveLoad _group_desc[] = { SLE_CONDVAR(Group, parent, SLE_UINT16, SLV_189, SL_MAX_VERSION), }; -static void Save_GRPS() -{ - SlTableHeader(_group_desc); +struct GRPSChunkHandler : ChunkHandler { + GRPSChunkHandler() : ChunkHandler('GRPS', CH_TABLE) {} - for (Group *g : Group::Iterate()) { - SlSetArrayIndex(g->index); - SlObject(g, _group_desc); - } -} + void Save() const override + { + SlTableHeader(_group_desc); - -static void Load_GRPS() -{ - const std::vector slt = SlCompatTableHeader(_group_desc, _group_sl_compat); - - int index; - - while ((index = SlIterateArray()) != -1) { - Group *g = new (index) Group(); - SlObject(g, slt); - - if (IsSavegameVersionBefore(SLV_189)) g->parent = INVALID_GROUP; - - if (IsSavegameVersionBefore(SLV_GROUP_LIVERIES)) { - const Company *c = Company::Get(g->owner); - g->livery.colour1 = c->livery[LS_DEFAULT].colour1; - g->livery.colour2 = c->livery[LS_DEFAULT].colour2; + for (Group *g : Group::Iterate()) { + SlSetArrayIndex(g->index); + SlObject(g, _group_desc); } } -} -static const ChunkHandler GRPS{ 'GRPS', Save_GRPS, Load_GRPS, nullptr, nullptr, CH_TABLE }; + + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_group_desc, _group_sl_compat); + + int index; + + while ((index = SlIterateArray()) != -1) { + Group *g = new (index) Group(); + SlObject(g, slt); + + if (IsSavegameVersionBefore(SLV_189)) g->parent = INVALID_GROUP; + + if (IsSavegameVersionBefore(SLV_GROUP_LIVERIES)) { + const Company *c = Company::Get(g->owner); + g->livery.colour1 = c->livery[LS_DEFAULT].colour1; + g->livery.colour2 = c->livery[LS_DEFAULT].colour2; + } + } + } +}; + +static const GRPSChunkHandler GRPS; static const ChunkHandlerRef group_chunk_handlers[] = { GRPS, }; diff --git a/src/saveload/industry_sl.cpp b/src/saveload/industry_sl.cpp index e1d2da93a0..d70e1a4ee7 100644 --- a/src/saveload/industry_sl.cpp +++ b/src/saveload/industry_sl.cpp @@ -74,90 +74,108 @@ static const SaveLoad _industry_desc[] = { SLE_CONDSSTR(Industry, text, SLE_STR | SLF_ALLOW_CONTROL, SLV_INDUSTRY_TEXT, SL_MAX_VERSION), }; -static void Save_INDY() -{ - SlTableHeader(_industry_desc); - - /* Write the industries */ - for (Industry *ind : Industry::Iterate()) { - SlSetArrayIndex(ind->index); - SlObject(ind, _industry_desc); +struct INDYChunkHandler : ChunkHandler { + INDYChunkHandler() : ChunkHandler('INDY', CH_TABLE) + { + this->fix_pointers = true; } -} -static void Save_IIDS() -{ - Save_NewGRFMapping(_industry_mngr); -} + void Save() const override + { + SlTableHeader(_industry_desc); -static void Save_TIDS() -{ - Save_NewGRFMapping(_industile_mngr); -} - -static void Load_INDY() -{ - const std::vector slt = SlCompatTableHeader(_industry_desc, _industry_sl_compat); - - int index; - - Industry::ResetIndustryCounts(); - - while ((index = SlIterateArray()) != -1) { - Industry *i = new (index) Industry(); - SlObject(i, slt); - - /* Before savegame version 161, persistent storages were not stored in a pool. */ - if (IsSavegameVersionBefore(SLV_161) && !IsSavegameVersionBefore(SLV_76)) { - /* Store the old persistent storage. The GRFID will be added later. */ - assert(PersistentStorage::CanAllocateItem()); - i->psa = new PersistentStorage(0, 0, 0); - memcpy(i->psa->storage, _old_ind_persistent_storage.storage, sizeof(_old_ind_persistent_storage.storage)); + /* Write the industries */ + for (Industry *ind : Industry::Iterate()) { + SlSetArrayIndex(ind->index); + SlObject(ind, _industry_desc); } - Industry::IncIndustryTypeCount(i->type); } -} -static void Load_IIDS() -{ - Load_NewGRFMapping(_industry_mngr); -} + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_industry_desc, _industry_sl_compat); -static void Load_TIDS() -{ - Load_NewGRFMapping(_industile_mngr); -} + int index; -static void Ptrs_INDY() -{ - for (Industry *i : Industry::Iterate()) { - SlObject(i, _industry_desc); + Industry::ResetIndustryCounts(); + + while ((index = SlIterateArray()) != -1) { + Industry *i = new (index) Industry(); + SlObject(i, slt); + + /* Before savegame version 161, persistent storages were not stored in a pool. */ + if (IsSavegameVersionBefore(SLV_161) && !IsSavegameVersionBefore(SLV_76)) { + /* Store the old persistent storage. The GRFID will be added later. */ + assert(PersistentStorage::CanAllocateItem()); + i->psa = new PersistentStorage(0, 0, 0); + memcpy(i->psa->storage, _old_ind_persistent_storage.storage, sizeof(_old_ind_persistent_storage.storage)); + } + Industry::IncIndustryTypeCount(i->type); + } } -} + + void FixPointers() const override + { + for (Industry *i : Industry::Iterate()) { + SlObject(i, _industry_desc); + } + } +}; + +struct IIDSChunkHandler : ChunkHandler { + IIDSChunkHandler() : ChunkHandler('IIDS', CH_TABLE) {} + + void Save() const override + { + Save_NewGRFMapping(_industry_mngr); + } + + void Load() const override + { + Load_NewGRFMapping(_industry_mngr); + } +}; + +struct TIDSChunkHandler : ChunkHandler { + TIDSChunkHandler() : ChunkHandler('TIDS', CH_TABLE) {} + + void Save() const override + { + Save_NewGRFMapping(_industile_mngr); + } + + void Load() const override + { + Load_NewGRFMapping(_industile_mngr); + } +}; /** Description of the data to save and load in #IndustryBuildData. */ static const SaveLoad _industry_builder_desc[] = { SLEG_VAR("wanted_inds", _industry_builder.wanted_inds, SLE_UINT32), }; -/** Save industry builder. */ -static void Save_IBLD() -{ - SlTableHeader(_industry_builder_desc); +/** Industry builder. */ +struct IBLDChunkHandler : ChunkHandler { + IBLDChunkHandler() : ChunkHandler('IBLD', CH_TABLE) {} - SlSetArrayIndex(0); - SlGlobList(_industry_builder_desc); -} + void Save() const override + { + SlTableHeader(_industry_builder_desc); -/** Load industry builder. */ -static void Load_IBLD() -{ - const std::vector slt = SlCompatTableHeader(_industry_builder_desc, _industry_builder_sl_compat); + SlSetArrayIndex(0); + SlGlobList(_industry_builder_desc); + } - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; - SlGlobList(slt); - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many IBLD entries"); -} + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_industry_builder_desc, _industry_builder_sl_compat); + + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlGlobList(slt); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many IBLD entries"); + } +}; /** Description of the data to save and load in #IndustryTypeBuildData. */ static const SaveLoad _industrytype_builder_desc[] = { @@ -168,37 +186,40 @@ static const SaveLoad _industrytype_builder_desc[] = { SLE_VAR(IndustryTypeBuildData, wait_count, SLE_UINT16), }; -/** Save industry-type build data. */ -static void Save_ITBL() -{ - SlTableHeader(_industrytype_builder_desc); +/** Industry-type build data. */ +struct ITBLChunkHandler : ChunkHandler { + ITBLChunkHandler() : ChunkHandler('ITBL', CH_TABLE) {} - for (int i = 0; i < NUM_INDUSTRYTYPES; i++) { - SlSetArrayIndex(i); - SlObject(_industry_builder.builddata + i, _industrytype_builder_desc); + void Save() const override + { + SlTableHeader(_industrytype_builder_desc); + + for (int i = 0; i < NUM_INDUSTRYTYPES; i++) { + SlSetArrayIndex(i); + SlObject(_industry_builder.builddata + i, _industrytype_builder_desc); + } } -} -/** Load industry-type build data. */ -static void Load_ITBL() -{ - const std::vector slt = SlCompatTableHeader(_industrytype_builder_desc, _industrytype_builder_sl_compat); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_industrytype_builder_desc, _industrytype_builder_sl_compat); - for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) { - _industry_builder.builddata[it].Reset(); + for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) { + _industry_builder.builddata[it].Reset(); + } + int index; + while ((index = SlIterateArray()) != -1) { + if ((uint)index >= NUM_INDUSTRYTYPES) SlErrorCorrupt("Too many industry builder datas"); + SlObject(_industry_builder.builddata + index, slt); + } } - int index; - while ((index = SlIterateArray()) != -1) { - if ((uint)index >= NUM_INDUSTRYTYPES) SlErrorCorrupt("Too many industry builder datas"); - SlObject(_industry_builder.builddata + index, slt); - } -} +}; -static const ChunkHandler INDY{ 'INDY', Save_INDY, Load_INDY, Ptrs_INDY, nullptr, CH_TABLE }; -static const ChunkHandler IIDS{ 'IIDS', Save_IIDS, Load_IIDS, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler TIDS{ 'TIDS', Save_TIDS, Load_TIDS, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler IBLD{ 'IBLD', Save_IBLD, Load_IBLD, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler ITBL{ 'ITBL', Save_ITBL, Load_ITBL, nullptr, nullptr, CH_TABLE }; +static const INDYChunkHandler INDY; +static const IIDSChunkHandler IIDS; +static const TIDSChunkHandler TIDS; +static const IBLDChunkHandler IBLD; +static const ITBLChunkHandler ITBL; static const ChunkHandlerRef industry_chunk_handlers[] = { INDY, IIDS, diff --git a/src/saveload/labelmaps_sl.cpp b/src/saveload/labelmaps_sl.cpp index 970985b929..432aa9ce48 100644 --- a/src/saveload/labelmaps_sl.cpp +++ b/src/saveload/labelmaps_sl.cpp @@ -99,35 +99,39 @@ static const SaveLoad _label_object_desc[] = { SLE_VAR(LabelObject, label, SLE_UINT32), }; -static void Save_RAIL() -{ - SlTableHeader(_label_object_desc); +struct RAILChunkHandler : ChunkHandler { + RAILChunkHandler() : ChunkHandler('RAIL', CH_TABLE) {} - LabelObject lo; + void Save() const override + { + SlTableHeader(_label_object_desc); - for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) { - lo.label = GetRailTypeInfo(r)->label; + LabelObject lo; - SlSetArrayIndex(r); - SlObject(&lo, _label_object_desc); + for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) { + lo.label = GetRailTypeInfo(r)->label; + + SlSetArrayIndex(r); + SlObject(&lo, _label_object_desc); + } } -} -static void Load_RAIL() -{ - const std::vector slt = SlCompatTableHeader(_label_object_desc, _label_object_sl_compat); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_label_object_desc, _label_object_sl_compat); - ResetLabelMaps(); + ResetLabelMaps(); - LabelObject lo; + LabelObject lo; - while (SlIterateArray() != -1) { - SlObject(&lo, slt); - _railtype_list.push_back((RailTypeLabel)lo.label); + while (SlIterateArray() != -1) { + SlObject(&lo, slt); + _railtype_list.push_back((RailTypeLabel)lo.label); + } } -} +}; -static const ChunkHandler RAIL{ 'RAIL', Save_RAIL, Load_RAIL, nullptr, nullptr, CH_TABLE }; +static const RAILChunkHandler RAIL; static const ChunkHandlerRef labelmaps_chunk_handlers[] = { RAIL, }; diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index 04664bed9f..70dfb7b39e 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -242,93 +242,96 @@ void AfterLoadLinkGraphs() } /** - * Save all link graphs. + * All link graphs. */ -static void Save_LGRP() -{ - SlTableHeader(GetLinkGraphDesc()); +struct LGRPChunkHandler : ChunkHandler { + LGRPChunkHandler() : ChunkHandler('LGRP', CH_TABLE) {} - for (LinkGraph *lg : LinkGraph::Iterate()) { - SlSetArrayIndex(lg->index); - SlObject(lg, GetLinkGraphDesc()); + void Save() const override + { + SlTableHeader(GetLinkGraphDesc()); + + for (LinkGraph *lg : LinkGraph::Iterate()) { + SlSetArrayIndex(lg->index); + SlObject(lg, GetLinkGraphDesc()); + } } -} -/** - * Load all link graphs. - */ -static void Load_LGRP() -{ - const std::vector slt = SlCompatTableHeader(GetLinkGraphDesc(), _linkgraph_sl_compat); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(GetLinkGraphDesc(), _linkgraph_sl_compat); - int index; - while ((index = SlIterateArray()) != -1) { - LinkGraph *lg = new (index) LinkGraph(); - SlObject(lg, slt); + int index; + while ((index = SlIterateArray()) != -1) { + LinkGraph *lg = new (index) LinkGraph(); + SlObject(lg, slt); + } } -} +}; /** - * Save all link graph jobs. + * All link graph jobs. */ -static void Save_LGRJ() -{ - SlTableHeader(GetLinkGraphJobDesc()); +struct LGRJChunkHandler : ChunkHandler { + LGRJChunkHandler() : ChunkHandler('LGRJ', CH_TABLE) {} - for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) { - SlSetArrayIndex(lgj->index); - SlObject(lgj, GetLinkGraphJobDesc()); + void Save() const override + { + SlTableHeader(GetLinkGraphJobDesc()); + + for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) { + SlSetArrayIndex(lgj->index); + SlObject(lgj, GetLinkGraphJobDesc()); + } } -} -/** - * Load all link graph jobs. - */ -static void Load_LGRJ() -{ - const std::vector slt = SlCompatTableHeader(GetLinkGraphJobDesc(), _linkgraph_job_sl_compat); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(GetLinkGraphJobDesc(), _linkgraph_job_sl_compat); - int index; - while ((index = SlIterateArray()) != -1) { - LinkGraphJob *lgj = new (index) LinkGraphJob(); - SlObject(lgj, slt); + int index; + while ((index = SlIterateArray()) != -1) { + LinkGraphJob *lgj = new (index) LinkGraphJob(); + SlObject(lgj, slt); + } } -} +}; /** - * Save the link graph schedule. + * Link graph schedule. */ -static void Save_LGRS() -{ - SlTableHeader(GetLinkGraphScheduleDesc()); +struct LGRSChunkHandler : ChunkHandler { + LGRSChunkHandler() : ChunkHandler('LGRS', CH_TABLE) + { + this->fix_pointers = true; + } - SlSetArrayIndex(0); - SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc()); -} + void Save() const override + { + SlTableHeader(GetLinkGraphScheduleDesc()); -/** - * Load the link graph schedule. - */ -static void Load_LGRS() -{ - const std::vector slt = SlCompatTableHeader(GetLinkGraphScheduleDesc(), _linkgraph_schedule_sl_compat); + SlSetArrayIndex(0); + SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc()); + } - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; - SlObject(&LinkGraphSchedule::instance, slt); - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many LGRS entries"); -} + void Load() const override + { + const std::vector slt = SlCompatTableHeader(GetLinkGraphScheduleDesc(), _linkgraph_schedule_sl_compat); -/** - * Substitute pointers in link graph schedule. - */ -static void Ptrs_LGRS() -{ - SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc()); -} + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlObject(&LinkGraphSchedule::instance, slt); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many LGRS entries"); + } -static const ChunkHandler LGRP{ 'LGRP', Save_LGRP, Load_LGRP, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler LGRJ{ 'LGRJ', Save_LGRJ, Load_LGRJ, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler LGRS{ 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, nullptr, CH_TABLE }; + void FixPointers() const override + { + SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc()); + } +}; + +static const LGRPChunkHandler LGRP; +static const LGRJChunkHandler LGRJ; +static const LGRSChunkHandler LGRS; static const ChunkHandlerRef linkgraph_chunk_handlers[] = { LGRP, LGRJ, diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp index a6f9448e52..d654f3f6bc 100644 --- a/src/saveload/map_sl.cpp +++ b/src/saveload/map_sl.cpp @@ -27,299 +27,346 @@ static const SaveLoad _map_desc[] = { SLEG_CONDVAR("dim_y", _map_dim_y, SLE_UINT32, SLV_6, SL_MAX_VERSION), }; -static void Save_MAPS() -{ - SlTableHeader(_map_desc); +struct MAPSChunkHandler : ChunkHandler { + MAPSChunkHandler() : ChunkHandler('MAPS', CH_TABLE) + { + this->load_check = true; + } - _map_dim_x = MapSizeX(); - _map_dim_y = MapSizeY(); + void Save() const override + { + SlTableHeader(_map_desc); - SlSetArrayIndex(0); - SlGlobList(_map_desc); -} + _map_dim_x = MapSizeX(); + _map_dim_y = MapSizeY(); -static void Load_MAPS() -{ - const std::vector slt = SlCompatTableHeader(_map_desc, _map_sl_compat); + SlSetArrayIndex(0); + SlGlobList(_map_desc); + } - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; - SlGlobList(slt); - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries"); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_map_desc, _map_sl_compat); - AllocateMap(_map_dim_x, _map_dim_y); -} + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlGlobList(slt); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries"); -static void Check_MAPS() -{ - const std::vector slt = SlCompatTableHeader(_map_desc, _map_sl_compat); + AllocateMap(_map_dim_x, _map_dim_y); + } - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; - SlGlobList(slt); - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries"); + void LoadCheck(size_t) const override + { + const std::vector slt = SlCompatTableHeader(_map_desc, _map_sl_compat); - _load_check_data.map_size_x = _map_dim_x; - _load_check_data.map_size_y = _map_dim_y; -} + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlGlobList(slt); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries"); + + _load_check_data.map_size_x = _map_dim_x; + _load_check_data.map_size_y = _map_dim_y; + } +}; static const uint MAP_SL_BUF_SIZE = 4096; -static void Load_MAPT() -{ - std::array buf; - TileIndex size = MapSize(); +struct MAPTChunkHandler : ChunkHandler { + MAPTChunkHandler() : ChunkHandler('MAPT', CH_RIFF) {} - for (TileIndex i = 0; i != size;) { - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type = buf[j]; - } -} + void Load() const override + { + std::array buf; + TileIndex size = MapSize(); -static void Save_MAPT() -{ - std::array buf; - TileIndex size = MapSize(); - - SlSetLength(size); - for (TileIndex i = 0; i != size;) { - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type; - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - } -} - -static void Load_MAPH() -{ - std::array buf; - TileIndex size = MapSize(); - - for (TileIndex i = 0; i != size;) { - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j]; - } -} - -static void Save_MAPH() -{ - std::array buf; - TileIndex size = MapSize(); - - SlSetLength(size); - for (TileIndex i = 0; i != size;) { - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].height; - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - } -} - -static void Load_MAP1() -{ - std::array buf; - TileIndex size = MapSize(); - - for (TileIndex i = 0; i != size;) { - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m1 = buf[j]; - } -} - -static void Save_MAP1() -{ - std::array buf; - TileIndex size = MapSize(); - - SlSetLength(size); - for (TileIndex i = 0; i != size;) { - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m1; - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - } -} - -static void Load_MAP2() -{ - std::array buf; - TileIndex size = MapSize(); - - for (TileIndex i = 0; i != size;) { - SlCopy(buf.data(), MAP_SL_BUF_SIZE, - /* In those versions the m2 was 8 bits */ - IsSavegameVersionBefore(SLV_5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16 - ); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m2 = buf[j]; - } -} - -static void Save_MAP2() -{ - std::array buf; - TileIndex size = MapSize(); - - SlSetLength(size * sizeof(uint16)); - for (TileIndex i = 0; i != size;) { - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m2; - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); - } -} - -static void Load_MAP3() -{ - std::array buf; - TileIndex size = MapSize(); - - for (TileIndex i = 0; i != size;) { - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m3 = buf[j]; - } -} - -static void Save_MAP3() -{ - std::array buf; - TileIndex size = MapSize(); - - SlSetLength(size); - for (TileIndex i = 0; i != size;) { - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m3; - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - } -} - -static void Load_MAP4() -{ - std::array buf; - TileIndex size = MapSize(); - - for (TileIndex i = 0; i != size;) { - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m4 = buf[j]; - } -} - -static void Save_MAP4() -{ - std::array buf; - TileIndex size = MapSize(); - - SlSetLength(size); - for (TileIndex i = 0; i != size;) { - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m4; - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - } -} - -static void Load_MAP5() -{ - std::array buf; - TileIndex size = MapSize(); - - for (TileIndex i = 0; i != size;) { - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m5 = buf[j]; - } -} - -static void Save_MAP5() -{ - std::array buf; - TileIndex size = MapSize(); - - SlSetLength(size); - for (TileIndex i = 0; i != size;) { - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m5; - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - } -} - -static void Load_MAP6() -{ - std::array buf; - TileIndex size = MapSize(); - - if (IsSavegameVersionBefore(SLV_42)) { - for (TileIndex i = 0; i != size;) { - /* 1024, otherwise we overflow on 64x64 maps! */ - SlCopy(buf.data(), 1024, SLE_UINT8); - for (uint j = 0; j != 1024; j++) { - _me[i++].m6 = GB(buf[j], 0, 2); - _me[i++].m6 = GB(buf[j], 2, 2); - _me[i++].m6 = GB(buf[j], 4, 2); - _me[i++].m6 = GB(buf[j], 6, 2); - } - } - } else { for (TileIndex i = 0; i != size;) { SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m6 = buf[j]; + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type = buf[j]; } } -} -static void Save_MAP6() -{ - std::array buf; - TileIndex size = MapSize(); + void Save() const override + { + std::array buf; + TileIndex size = MapSize(); - SlSetLength(size); - for (TileIndex i = 0; i != size;) { - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m6; - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + SlSetLength(size); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type; + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + } } -} +}; -static void Load_MAP7() -{ - std::array buf; - TileIndex size = MapSize(); +struct MAPHChunkHandler : ChunkHandler { + MAPHChunkHandler() : ChunkHandler('MAPH', CH_RIFF) {} - for (TileIndex i = 0; i != size;) { - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m7 = buf[j]; + void Load() const override + { + std::array buf; + TileIndex size = MapSize(); + + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j]; + } } -} -static void Save_MAP7() -{ - std::array buf; - TileIndex size = MapSize(); + void Save() const override + { + std::array buf; + TileIndex size = MapSize(); - SlSetLength(size); - for (TileIndex i = 0; i != size;) { - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m7; - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + SlSetLength(size); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].height; + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + } } -} +}; -static void Load_MAP8() -{ - std::array buf; - TileIndex size = MapSize(); +struct MAPOChunkHandler : ChunkHandler { + MAPOChunkHandler() : ChunkHandler('MAPO', CH_RIFF) {} - for (TileIndex i = 0; i != size;) { - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m8 = buf[j]; + void Load() const override + { + std::array buf; + TileIndex size = MapSize(); + + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m1 = buf[j]; + } } -} -static void Save_MAP8() -{ - std::array buf; - TileIndex size = MapSize(); + void Save() const override + { + std::array buf; + TileIndex size = MapSize(); - SlSetLength(size * sizeof(uint16)); - for (TileIndex i = 0; i != size;) { - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m8; - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); + SlSetLength(size); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m1; + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + } } -} +}; -static const ChunkHandler MAPS{ 'MAPS', Save_MAPS, Load_MAPS, nullptr, Check_MAPS, CH_TABLE }; -static const ChunkHandler MAPT{ 'MAPT', Save_MAPT, Load_MAPT, nullptr, nullptr, CH_RIFF }; -static const ChunkHandler MAPH{ 'MAPH', Save_MAPH, Load_MAPH, nullptr, nullptr, CH_RIFF }; -static const ChunkHandler MAPO{ 'MAPO', Save_MAP1, Load_MAP1, nullptr, nullptr, CH_RIFF }; -static const ChunkHandler MAP2{ 'MAP2', Save_MAP2, Load_MAP2, nullptr, nullptr, CH_RIFF }; -static const ChunkHandler M3LO{ 'M3LO', Save_MAP3, Load_MAP3, nullptr, nullptr, CH_RIFF }; -static const ChunkHandler M3HI{ 'M3HI', Save_MAP4, Load_MAP4, nullptr, nullptr, CH_RIFF }; -static const ChunkHandler MAP5{ 'MAP5', Save_MAP5, Load_MAP5, nullptr, nullptr, CH_RIFF }; -static const ChunkHandler MAPE{ 'MAPE', Save_MAP6, Load_MAP6, nullptr, nullptr, CH_RIFF }; -static const ChunkHandler MAP7{ 'MAP7', Save_MAP7, Load_MAP7, nullptr, nullptr, CH_RIFF }; -static const ChunkHandler MAP8{ 'MAP8', Save_MAP8, Load_MAP8, nullptr, nullptr, CH_RIFF }; +struct MAP2ChunkHandler : ChunkHandler { + MAP2ChunkHandler() : ChunkHandler('MAP2', CH_RIFF) {} + + void Load() const override + { + std::array buf; + TileIndex size = MapSize(); + + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, + /* In those versions the m2 was 8 bits */ + IsSavegameVersionBefore(SLV_5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16 + ); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m2 = buf[j]; + } + } + + void Save() const override + { + std::array buf; + TileIndex size = MapSize(); + + SlSetLength(size * sizeof(uint16)); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m2; + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); + } + } +}; + +struct M3LOChunkHandler : ChunkHandler { + M3LOChunkHandler() : ChunkHandler('M3LO', CH_RIFF) {} + + void Load() const override + { + std::array buf; + TileIndex size = MapSize(); + + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m3 = buf[j]; + } + } + + void Save() const override + { + std::array buf; + TileIndex size = MapSize(); + + SlSetLength(size); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m3; + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + } + } +}; + +struct M3HIChunkHandler : ChunkHandler { + M3HIChunkHandler() : ChunkHandler('M3HI', CH_RIFF) {} + + void Load() const override + { + std::array buf; + TileIndex size = MapSize(); + + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m4 = buf[j]; + } + } + + void Save() const override + { + std::array buf; + TileIndex size = MapSize(); + + SlSetLength(size); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m4; + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + } + } +}; + +struct MAP5ChunkHandler : ChunkHandler { + MAP5ChunkHandler() : ChunkHandler('MAP5', CH_RIFF) {} + + void Load() const override + { + std::array buf; + TileIndex size = MapSize(); + + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m5 = buf[j]; + } + } + + void Save() const override + { + std::array buf; + TileIndex size = MapSize(); + + SlSetLength(size); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m5; + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + } + } +}; + +struct MAPEChunkHandler : ChunkHandler { + MAPEChunkHandler() : ChunkHandler('MAPE', CH_RIFF) {} + + void Load() const override + { + std::array buf; + TileIndex size = MapSize(); + + if (IsSavegameVersionBefore(SLV_42)) { + for (TileIndex i = 0; i != size;) { + /* 1024, otherwise we overflow on 64x64 maps! */ + SlCopy(buf.data(), 1024, SLE_UINT8); + for (uint j = 0; j != 1024; j++) { + _me[i++].m6 = GB(buf[j], 0, 2); + _me[i++].m6 = GB(buf[j], 2, 2); + _me[i++].m6 = GB(buf[j], 4, 2); + _me[i++].m6 = GB(buf[j], 6, 2); + } + } + } else { + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m6 = buf[j]; + } + } + } + + void Save() const override + { + std::array buf; + TileIndex size = MapSize(); + + SlSetLength(size); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m6; + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + } + } +}; + +struct MAP7ChunkHandler : ChunkHandler { + MAP7ChunkHandler() : ChunkHandler('MAP7', CH_RIFF) {} + + void Load() const override + { + std::array buf; + TileIndex size = MapSize(); + + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m7 = buf[j]; + } + } + + void Save() const override + { + std::array buf; + TileIndex size = MapSize(); + + SlSetLength(size); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m7; + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + } + } +}; + +struct MAP8ChunkHandler : ChunkHandler { + MAP8ChunkHandler() : ChunkHandler('MAP8', CH_RIFF) {} + + void Load() const override + { + std::array buf; + TileIndex size = MapSize(); + + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m8 = buf[j]; + } + } + + void Save() const override + { + std::array buf; + TileIndex size = MapSize(); + + SlSetLength(size * sizeof(uint16)); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m8; + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); + } + } +}; + +static const MAPSChunkHandler MAPS; +static const MAPTChunkHandler MAPT; +static const MAPHChunkHandler MAPH; +static const MAPOChunkHandler MAPO; +static const MAP2ChunkHandler MAP2; +static const M3LOChunkHandler M3LO; +static const M3HIChunkHandler M3HI; +static const MAP5ChunkHandler MAP5; +static const MAPEChunkHandler MAPE; +static const MAP7ChunkHandler MAP7; +static const MAP8ChunkHandler MAP8; static const ChunkHandlerRef map_chunk_handlers[] = { MAPS, MAPT, diff --git a/src/saveload/misc_sl.cpp b/src/saveload/misc_sl.cpp index a742090e8d..a7e00f88c9 100644 --- a/src/saveload/misc_sl.cpp +++ b/src/saveload/misc_sl.cpp @@ -95,37 +95,44 @@ static const SaveLoad _date_check_desc[] = { /* Save load date related variables as well as persistent tick counters * XXX: currently some unrelated stuff is just put here */ -static void Save_DATE() -{ - SlTableHeader(_date_desc); - - SlSetArrayIndex(0); - SlGlobList(_date_desc); -} - -static void Load_DATE_common(const SaveLoadTable &slt, const SaveLoadCompatTable &slct) -{ - const std::vector oslt = SlCompatTableHeader(slt, slct); - - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; - SlGlobList(oslt); - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries"); -} - -static void Load_DATE() -{ - Load_DATE_common(_date_desc, _date_sl_compat); -} - -static void Check_DATE() -{ - Load_DATE_common(_date_check_desc, _date_check_sl_compat); - - if (IsSavegameVersionBefore(SLV_31)) { - _load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR; +struct DATEChunkHandler : ChunkHandler { + DATEChunkHandler() : ChunkHandler('DATE', CH_TABLE) + { + this->load_check = true; } -} + void Save() const override + { + SlTableHeader(_date_desc); + + SlSetArrayIndex(0); + SlGlobList(_date_desc); + } + + void LoadCommon(const SaveLoadTable &slt, const SaveLoadCompatTable &slct) const + { + const std::vector oslt = SlCompatTableHeader(slt, slct); + + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlGlobList(oslt); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries"); + } + + void Load() const override + { + this->LoadCommon(_date_desc, _date_sl_compat); + } + + + void LoadCheck(size_t) const override + { + this->LoadCommon(_date_check_desc, _date_check_sl_compat); + + if (IsSavegameVersionBefore(SLV_31)) { + _load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR; + } + } +}; static const SaveLoad _view_desc[] = { SLEG_CONDVAR("x", _saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6), @@ -135,25 +142,29 @@ static const SaveLoad _view_desc[] = { SLEG_VAR("zoom", _saved_scrollpos_zoom, SLE_UINT8), }; -static void Save_VIEW() -{ - SlTableHeader(_view_desc); +struct VIEWChunkHandler : ChunkHandler { + VIEWChunkHandler() : ChunkHandler('VIEW', CH_TABLE) {} - SlSetArrayIndex(0); - SlGlobList(_view_desc); -} + void Save() const override + { + SlTableHeader(_view_desc); -static void Load_VIEW() -{ - const std::vector slt = SlCompatTableHeader(_view_desc, _view_sl_compat); + SlSetArrayIndex(0); + SlGlobList(_view_desc); + } - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; - SlGlobList(slt); - if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries"); -} + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_view_desc, _view_sl_compat); -static const ChunkHandler DATE{ 'DATE', Save_DATE, Load_DATE, nullptr, Check_DATE, CH_TABLE }; -static const ChunkHandler VIEW{ 'VIEW', Save_VIEW, Load_VIEW, nullptr, nullptr, CH_TABLE }; + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlGlobList(slt); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries"); + } +}; + +static const DATEChunkHandler DATE; +static const VIEWChunkHandler VIEW; static const ChunkHandlerRef misc_chunk_handlers[] = { DATE, VIEW, diff --git a/src/saveload/newgrf_sl.cpp b/src/saveload/newgrf_sl.cpp index 10a65e9362..43f0bd01a9 100644 --- a/src/saveload/newgrf_sl.cpp +++ b/src/saveload/newgrf_sl.cpp @@ -73,55 +73,62 @@ static const SaveLoad _grfconfig_desc[] = { }; -static void Save_NGRF() -{ - SlTableHeader(_grfconfig_desc); - - int index = 0; - - for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) { - if (HasBit(c->flags, GCF_STATIC)) continue; - SlSetArrayIndex(index++); - SlObject(c, _grfconfig_desc); +struct NGRFChunkHandler : ChunkHandler { + NGRFChunkHandler() : ChunkHandler('NGRF', CH_TABLE) + { + this->load_check = true; } -} + void Save() const override + { + SlTableHeader(_grfconfig_desc); -static void Load_NGRF_common(GRFConfig *&grfconfig) -{ - const std::vector slt = SlCompatTableHeader(_grfconfig_desc, _grfconfig_sl_compat); + int index = 0; - ClearGRFConfigList(&grfconfig); - while (SlIterateArray() != -1) { - GRFConfig *c = new GRFConfig(); - SlObject(c, slt); - if (IsSavegameVersionBefore(SLV_101)) c->SetSuitablePalette(); - AppendToGRFConfigList(&grfconfig, c); + for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) { + if (HasBit(c->flags, GCF_STATIC)) continue; + SlSetArrayIndex(index++); + SlObject(c, _grfconfig_desc); + } } -} -static void Load_NGRF() -{ - Load_NGRF_common(_grfconfig); - if (_game_mode == GM_MENU) { - /* Intro game must not have NewGRF. */ - if (_grfconfig != nullptr) SlErrorCorrupt("The intro game must not use NewGRF"); + void LoadCommon(GRFConfig *&grfconfig) const + { + const std::vector slt = SlCompatTableHeader(_grfconfig_desc, _grfconfig_sl_compat); - /* Activate intro NewGRFs (townnames) */ - ResetGRFConfig(false); - } else { - /* Append static NewGRF configuration */ - AppendStaticGRFConfigs(&_grfconfig); + ClearGRFConfigList(&grfconfig); + while (SlIterateArray() != -1) { + GRFConfig *c = new GRFConfig(); + SlObject(c, slt); + if (IsSavegameVersionBefore(SLV_101)) c->SetSuitablePalette(); + AppendToGRFConfigList(&grfconfig, c); + } } -} -static void Check_NGRF() -{ - Load_NGRF_common(_load_check_data.grfconfig); -} + void Load() const override + { + this->LoadCommon(_grfconfig); -static const ChunkHandler NGRF{ 'NGRF', Save_NGRF, Load_NGRF, nullptr, Check_NGRF, CH_TABLE }; + if (_game_mode == GM_MENU) { + /* Intro game must not have NewGRF. */ + if (_grfconfig != nullptr) SlErrorCorrupt("The intro game must not use NewGRF"); + + /* Activate intro NewGRFs (townnames) */ + ResetGRFConfig(false); + } else { + /* Append static NewGRF configuration */ + AppendStaticGRFConfigs(&_grfconfig); + } + } + + void LoadCheck(size_t) const override + { + this->LoadCommon(_load_check_data.grfconfig); + } +}; + +static const NGRFChunkHandler NGRF; static const ChunkHandlerRef newgrf_chunk_handlers[] = { NGRF, }; diff --git a/src/saveload/object_sl.cpp b/src/saveload/object_sl.cpp index b970c39345..fc49970020 100644 --- a/src/saveload/object_sl.cpp +++ b/src/saveload/object_sl.cpp @@ -29,51 +29,62 @@ static const SaveLoad _object_desc[] = { SLE_CONDVAR(Object, type, SLE_UINT16, SLV_186, SL_MAX_VERSION), }; -static void Save_OBJS() -{ - SlTableHeader(_object_desc); - - /* Write the objects */ - for (Object *o : Object::Iterate()) { - SlSetArrayIndex(o->index); - SlObject(o, _object_desc); +struct OBJSChunkHandler : ChunkHandler { + OBJSChunkHandler() : ChunkHandler('OBJS', CH_TABLE) + { + this->fix_pointers = true; } -} -static void Load_OBJS() -{ - const std::vector slt = SlCompatTableHeader(_object_desc, _object_sl_compat); + void Save() const override + { + SlTableHeader(_object_desc); - int index; - while ((index = SlIterateArray()) != -1) { - Object *o = new (index) Object(); - SlObject(o, slt); - } -} - -static void Ptrs_OBJS() -{ - for (Object *o : Object::Iterate()) { - SlObject(o, _object_desc); - if (IsSavegameVersionBefore(SLV_148) && !IsTileType(o->location.tile, MP_OBJECT)) { - /* Due to a small bug stale objects could remain. */ - delete o; + /* Write the objects */ + for (Object *o : Object::Iterate()) { + SlSetArrayIndex(o->index); + SlObject(o, _object_desc); } } -} -static void Save_OBID() -{ - Save_NewGRFMapping(_object_mngr); -} + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_object_desc, _object_sl_compat); -static void Load_OBID() -{ - Load_NewGRFMapping(_object_mngr); -} + int index; + while ((index = SlIterateArray()) != -1) { + Object *o = new (index) Object(); + SlObject(o, slt); + } + } -static const ChunkHandler OBID{ 'OBID', Save_OBID, Load_OBID, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler OBJS{ 'OBJS', Save_OBJS, Load_OBJS, Ptrs_OBJS, nullptr, CH_TABLE }; + void FixPointers() const override + { + for (Object *o : Object::Iterate()) { + SlObject(o, _object_desc); + if (IsSavegameVersionBefore(SLV_148) && !IsTileType(o->location.tile, MP_OBJECT)) { + /* Due to a small bug stale objects could remain. */ + delete o; + } + } + } +}; + +struct OBIDChunkHandler : ChunkHandler { + OBIDChunkHandler() : ChunkHandler('OBID', CH_TABLE) {} + + void Save() const override + { + Save_NewGRFMapping(_object_mngr); + } + + void Load() const override + { + Load_NewGRFMapping(_object_mngr); + } +}; + +static const OBIDChunkHandler OBID; +static const OBJSChunkHandler OBJS; static const ChunkHandlerRef object_chunk_handlers[] = { OBID, OBJS, diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp index 797c16d1b0..16ee420137 100644 --- a/src/saveload/order_sl.cpp +++ b/src/saveload/order_sl.cpp @@ -118,85 +118,92 @@ SaveLoadTable GetOrderDescription() return _order_desc; } -static void Save_ORDR() -{ - const SaveLoadTable slt = GetOrderDescription(); - SlTableHeader(slt); - - for (Order *order : Order::Iterate()) { - SlSetArrayIndex(order->index); - SlObject(order, slt); +struct ORDRChunkHandler : ChunkHandler { + ORDRChunkHandler() : ChunkHandler('ORDR', CH_TABLE) + { + this->fix_pointers = true; } -} -static void Load_ORDR() -{ - if (IsSavegameVersionBefore(SLV_5, 2)) { - /* Version older than 5.2 did not have a ->next pointer. Convert them - * (in the old days, the orderlist was 5000 items big) */ - size_t len = SlGetFieldLength(); + void Save() const override + { + const SaveLoadTable slt = GetOrderDescription(); + SlTableHeader(slt); - if (IsSavegameVersionBefore(SLV_5)) { - /* Pre-version 5 had another layout for orders - * (uint16 instead of uint32) */ - len /= sizeof(uint16); - uint16 *orders = MallocT(len + 1); - - SlCopy(orders, len, SLE_UINT16); - - for (size_t i = 0; i < len; ++i) { - Order *o = new (i) Order(); - o->AssignOrder(UnpackVersion4Order(orders[i])); - } - - free(orders); - } else if (IsSavegameVersionBefore(SLV_5, 2)) { - len /= sizeof(uint32); - uint32 *orders = MallocT(len + 1); - - SlCopy(orders, len, SLE_UINT32); - - for (size_t i = 0; i < len; ++i) { - new (i) Order(orders[i]); - } - - free(orders); - } - - /* Update all the next pointer */ - for (Order *o : Order::Iterate()) { - size_t order_index = o->index; - /* Delete invalid orders */ - if (o->IsType(OT_NOTHING)) { - delete o; - continue; - } - /* The orders were built like this: - * While the order is valid, set the previous will get its next pointer set */ - Order *prev = Order::GetIfValid(order_index - 1); - if (prev != nullptr) prev->next = o; - } - } else { - const std::vector slt = SlCompatTableHeader(GetOrderDescription(), _order_sl_compat); - - int index; - - while ((index = SlIterateArray()) != -1) { - Order *order = new (index) Order(); + for (Order *order : Order::Iterate()) { + SlSetArrayIndex(order->index); SlObject(order, slt); } } -} -static void Ptrs_ORDR() -{ - /* Orders from old savegames have pointers corrected in Load_ORDR */ - if (IsSavegameVersionBefore(SLV_5, 2)) return; + void Load() const override + { + if (IsSavegameVersionBefore(SLV_5, 2)) { + /* Version older than 5.2 did not have a ->next pointer. Convert them + * (in the old days, the orderlist was 5000 items big) */ + size_t len = SlGetFieldLength(); - for (Order *o : Order::Iterate()) { - SlObject(o, GetOrderDescription()); + if (IsSavegameVersionBefore(SLV_5)) { + /* Pre-version 5 had another layout for orders + * (uint16 instead of uint32) */ + len /= sizeof(uint16); + uint16 *orders = MallocT(len + 1); + + SlCopy(orders, len, SLE_UINT16); + + for (size_t i = 0; i < len; ++i) { + Order *o = new (i) Order(); + o->AssignOrder(UnpackVersion4Order(orders[i])); + } + + free(orders); + } else if (IsSavegameVersionBefore(SLV_5, 2)) { + len /= sizeof(uint32); + uint32 *orders = MallocT(len + 1); + + SlCopy(orders, len, SLE_UINT32); + + for (size_t i = 0; i < len; ++i) { + new (i) Order(orders[i]); + } + + free(orders); + } + + /* Update all the next pointer */ + for (Order *o : Order::Iterate()) { + size_t order_index = o->index; + /* Delete invalid orders */ + if (o->IsType(OT_NOTHING)) { + delete o; + continue; + } + /* The orders were built like this: + * While the order is valid, set the previous will get its next pointer set */ + Order *prev = Order::GetIfValid(order_index - 1); + if (prev != nullptr) prev->next = o; + } + } else { + const std::vector slt = SlCompatTableHeader(GetOrderDescription(), _order_sl_compat); + + int index; + + while ((index = SlIterateArray()) != -1) { + Order *order = new (index) Order(); + SlObject(order, slt); + } + } } -} + + void FixPointers() const override + { + /* Orders from old savegames have pointers corrected in Load_ORDR */ + if (IsSavegameVersionBefore(SLV_5, 2)) return; + + for (Order *o : Order::Iterate()) { + SlObject(o, GetOrderDescription()); + } + } +}; SaveLoadTable GetOrderListDescription() { @@ -207,37 +214,44 @@ SaveLoadTable GetOrderListDescription() return _orderlist_desc; } -static void Save_ORDL() -{ - const SaveLoadTable slt = GetOrderListDescription(); - SlTableHeader(slt); - - for (OrderList *list : OrderList::Iterate()) { - SlSetArrayIndex(list->index); - SlObject(list, slt); - } -} - -static void Load_ORDL() -{ - const std::vector slt = SlCompatTableHeader(GetOrderListDescription(), _orderlist_sl_compat); - - int index; - - while ((index = SlIterateArray()) != -1) { - /* set num_orders to 0 so it's a valid OrderList */ - OrderList *list = new (index) OrderList(0); - SlObject(list, slt); +struct ORDLChunkHandler : ChunkHandler { + ORDLChunkHandler() : ChunkHandler('ORDL', CH_TABLE) + { + this->fix_pointers = true; } -} + void Save() const override + { + const SaveLoadTable slt = GetOrderListDescription(); + SlTableHeader(slt); -static void Ptrs_ORDL() -{ - for (OrderList *list : OrderList::Iterate()) { - SlObject(list, GetOrderListDescription()); + for (OrderList *list : OrderList::Iterate()) { + SlSetArrayIndex(list->index); + SlObject(list, slt); + } } -} + + void Load() const override + { + const std::vector slt = SlCompatTableHeader(GetOrderListDescription(), _orderlist_sl_compat); + + int index; + + while ((index = SlIterateArray()) != -1) { + /* set num_orders to 0 so it's a valid OrderList */ + OrderList *list = new (index) OrderList(0); + SlObject(list, slt); + } + + } + + void FixPointers() const override + { + for (OrderList *list : OrderList::Iterate()) { + SlObject(list, GetOrderListDescription()); + } + } +}; SaveLoadTable GetOrderBackupDescription() { @@ -262,45 +276,52 @@ SaveLoadTable GetOrderBackupDescription() return _order_backup_desc; } -static void Save_BKOR() -{ - const SaveLoadTable slt = GetOrderBackupDescription(); - SlTableHeader(slt); - - /* We only save this when we're a network server - * as we want this information on our clients. For - * normal games this information isn't needed. */ - if (!_networking || !_network_server) return; - - for (OrderBackup *ob : OrderBackup::Iterate()) { - SlSetArrayIndex(ob->index); - SlObject(ob, slt); +struct BKORChunkHandler : ChunkHandler { + BKORChunkHandler() : ChunkHandler('BKOR', CH_TABLE) + { + this->fix_pointers = true; } -} -void Load_BKOR() -{ - const std::vector slt = SlCompatTableHeader(GetOrderBackupDescription(), _order_backup_sl_compat); + void Save() const override + { + const SaveLoadTable slt = GetOrderBackupDescription(); + SlTableHeader(slt); - int index; + /* We only save this when we're a network server + * as we want this information on our clients. For + * normal games this information isn't needed. */ + if (!_networking || !_network_server) return; - while ((index = SlIterateArray()) != -1) { - /* set num_orders to 0 so it's a valid OrderList */ - OrderBackup *ob = new (index) OrderBackup(); - SlObject(ob, slt); + for (OrderBackup *ob : OrderBackup::Iterate()) { + SlSetArrayIndex(ob->index); + SlObject(ob, slt); + } } -} -static void Ptrs_BKOR() -{ - for (OrderBackup *ob : OrderBackup::Iterate()) { - SlObject(ob, GetOrderBackupDescription()); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(GetOrderBackupDescription(), _order_backup_sl_compat); + + int index; + + while ((index = SlIterateArray()) != -1) { + /* set num_orders to 0 so it's a valid OrderList */ + OrderBackup *ob = new (index) OrderBackup(); + SlObject(ob, slt); + } } -} -static const ChunkHandler BKOR{ 'BKOR', Save_BKOR, Load_BKOR, Ptrs_BKOR, nullptr, CH_TABLE }; -static const ChunkHandler ORDR{ 'ORDR', Save_ORDR, Load_ORDR, Ptrs_ORDR, nullptr, CH_TABLE }; -static const ChunkHandler ORDL{ 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, nullptr, CH_TABLE }; + void FixPointers() const override + { + for (OrderBackup *ob : OrderBackup::Iterate()) { + SlObject(ob, GetOrderBackupDescription()); + } + } +}; + +static const BKORChunkHandler BKOR; +static const ORDRChunkHandler ORDR; +static const ORDLChunkHandler ORDL; static const ChunkHandlerRef order_chunk_handlers[] = { BKOR, ORDR, diff --git a/src/saveload/settings_sl.cpp b/src/saveload/settings_sl.cpp index fe320db5d1..53254cde7c 100644 --- a/src/saveload/settings_sl.cpp +++ b/src/saveload/settings_sl.cpp @@ -142,36 +142,47 @@ static void SaveSettings(const SettingTable &settings, void *object) SlObject(object, slt); } -static void Load_OPTS() -{ - /* Copy over default setting since some might not get loaded in - * a networking environment. This ensures for example that the local - * autosave-frequency stays when joining a network-server */ - PrepareOldDiffCustom(); - LoadSettings(_gameopt_settings, &_settings_game, _gameopt_sl_compat); - HandleOldDiffCustom(true); -} +struct OPTSChunkHandler : ChunkHandler { + OPTSChunkHandler() : ChunkHandler('OPTS', CH_READONLY) {} -static void Load_PATS() -{ - /* Copy over default setting since some might not get loaded in - * a networking environment. This ensures for example that the local - * currency setting stays when joining a network-server */ - LoadSettings(_settings, &_settings_game, _settings_sl_compat); -} + void Load() const override + { + /* Copy over default setting since some might not get loaded in + * a networking environment. This ensures for example that the local + * autosave-frequency stays when joining a network-server */ + PrepareOldDiffCustom(); + LoadSettings(_gameopt_settings, &_settings_game, _gameopt_sl_compat); + HandleOldDiffCustom(true); + } +}; -static void Check_PATS() -{ - LoadSettings(_settings, &_load_check_data.settings, _settings_sl_compat); -} +struct PATSChunkHandler : ChunkHandler { + PATSChunkHandler() : ChunkHandler('PATS', CH_TABLE) + { + this->load_check = true; + } -static void Save_PATS() -{ - SaveSettings(_settings, &_settings_game); -} + void Load() const override + { + /* Copy over default setting since some might not get loaded in + * a networking environment. This ensures for example that the local + * currency setting stays when joining a network-server */ + LoadSettings(_settings, &_settings_game, _settings_sl_compat); + } -static const ChunkHandler OPTS{ 'OPTS', nullptr, Load_OPTS, nullptr, nullptr, CH_READONLY }; -static const ChunkHandler PATS{ 'PATS', Save_PATS, Load_PATS, nullptr, Check_PATS, CH_TABLE }; + void LoadCheck(size_t) const override + { + LoadSettings(_settings, &_load_check_data.settings, _settings_sl_compat); + } + + void Save() const override + { + SaveSettings(_settings, &_settings_game); + } +}; + +static const OPTSChunkHandler OPTS; +static const PATSChunkHandler PATS; static const ChunkHandlerRef setting_chunk_handlers[] = { OPTS, PATS, diff --git a/src/saveload/signs_sl.cpp b/src/saveload/signs_sl.cpp index 21cd69f155..336a552f76 100644 --- a/src/saveload/signs_sl.cpp +++ b/src/saveload/signs_sl.cpp @@ -30,44 +30,46 @@ static const SaveLoad _sign_desc[] = { SLE_CONDVAR(Sign, z, SLE_INT32, SLV_164, SL_MAX_VERSION), }; -/** Save all signs */ -static void Save_SIGN() -{ - SlTableHeader(_sign_desc); +struct SIGNChunkHandler : ChunkHandler { + SIGNChunkHandler() : ChunkHandler('SIGN', CH_TABLE) {} - for (Sign *si : Sign::Iterate()) { - SlSetArrayIndex(si->index); - SlObject(si, _sign_desc); - } -} + void Save() const override + { + SlTableHeader(_sign_desc); -/** Load all signs */ -static void Load_SIGN() -{ - const std::vector slt = SlCompatTableHeader(_sign_desc, _sign_sl_compat); - - int index; - while ((index = SlIterateArray()) != -1) { - Sign *si = new (index) Sign(); - SlObject(si, slt); - /* Before version 6.1, signs didn't have owner. - * Before version 83, invalid signs were determined by si->str == 0. - * Before version 103, owner could be a bankrupted company. - * - we can't use IsValidCompany() now, so this is fixed in AfterLoadGame() - * All signs that were saved are valid (including those with just 'Sign' and INVALID_OWNER). - * - so set owner to OWNER_NONE if needed (signs from pre-version 6.1 would be lost) */ - if (IsSavegameVersionBefore(SLV_6, 1) || (IsSavegameVersionBefore(SLV_83) && si->owner == INVALID_OWNER)) { - si->owner = OWNER_NONE; - } - - /* Signs placed in scenario editor shall now be OWNER_DEITY */ - if (IsSavegameVersionBefore(SLV_171) && si->owner == OWNER_NONE && _file_to_saveload.abstract_ftype == FT_SCENARIO) { - si->owner = OWNER_DEITY; + for (Sign *si : Sign::Iterate()) { + SlSetArrayIndex(si->index); + SlObject(si, _sign_desc); } } -} -static const ChunkHandler SIGN{ 'SIGN', Save_SIGN, Load_SIGN, nullptr, nullptr, CH_TABLE }; + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_sign_desc, _sign_sl_compat); + + int index; + while ((index = SlIterateArray()) != -1) { + Sign *si = new (index) Sign(); + SlObject(si, slt); + /* Before version 6.1, signs didn't have owner. + * Before version 83, invalid signs were determined by si->str == 0. + * Before version 103, owner could be a bankrupted company. + * - we can't use IsValidCompany() now, so this is fixed in AfterLoadGame() + * All signs that were saved are valid (including those with just 'Sign' and INVALID_OWNER). + * - so set owner to OWNER_NONE if needed (signs from pre-version 6.1 would be lost) */ + if (IsSavegameVersionBefore(SLV_6, 1) || (IsSavegameVersionBefore(SLV_83) && si->owner == INVALID_OWNER)) { + si->owner = OWNER_NONE; + } + + /* Signs placed in scenario editor shall now be OWNER_DEITY */ + if (IsSavegameVersionBefore(SLV_171) && si->owner == OWNER_NONE && _file_to_saveload.abstract_ftype == FT_SCENARIO) { + si->owner = OWNER_DEITY; + } + } + } +}; + +static const SIGNChunkHandler SIGN; static const ChunkHandlerRef sign_chunk_handlers[] = { SIGN, }; diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 5662e4a465..9c97792cef 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -484,34 +484,41 @@ static const SaveLoad _old_station_desc[] = { SLEG_CONDSTRUCTLIST("speclist", SlStationSpecList, SLV_27, SL_MAX_VERSION), }; -static void Load_STNS() -{ - const std::vector slt = SlCompatTableHeader(_old_station_desc, _old_station_sl_compat); - - _cargo_source_xy = 0; - _cargo_days = 0; - _cargo_feeder_share = 0; - - int index; - while ((index = SlIterateArray()) != -1) { - Station *st = new (index) Station(); - - _waiting_acceptance = 0; - SlObject(st, slt); +struct STNSChunkHandler : ChunkHandler { + STNSChunkHandler() : ChunkHandler('STNS', CH_READONLY) + { + this->fix_pointers = true; } -} -static void Ptrs_STNS() -{ - /* From SLV_123 we store stations in STNN; before that in STNS. So do not - * fix pointers when the version is SLV_123 or up, as that would fix - * pointers twice: once in STNN chunk and once here. */ - if (!IsSavegameVersionBefore(SLV_123)) return; + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_old_station_desc, _old_station_sl_compat); - for (Station *st : Station::Iterate()) { - SlObject(st, _old_station_desc); + _cargo_source_xy = 0; + _cargo_days = 0; + _cargo_feeder_share = 0; + + int index; + while ((index = SlIterateArray()) != -1) { + Station *st = new (index) Station(); + + _waiting_acceptance = 0; + SlObject(st, slt); + } } -} + + void FixPointers() const override + { + /* From SLV_123 we store stations in STNN; before that in STNS. So do not + * fix pointers when the version is SLV_123 or up, as that would fix + * pointers twice: once in STNN chunk and once here. */ + if (!IsSavegameVersionBefore(SLV_123)) return; + + for (Station *st : Station::Iterate()) { + SlObject(st, _old_station_desc); + } + } +}; /** * SaveLoad handler for the BaseStation, which all other stations / waypoints @@ -651,77 +658,92 @@ static const SaveLoad _station_desc[] = { SLEG_CONDSTRUCTLIST("speclist", SlStationSpecList, SLV_27, SL_MAX_VERSION), }; -static void Save_STNN() -{ - SlTableHeader(_station_desc); - - /* Write the stations */ - for (BaseStation *st : BaseStation::Iterate()) { - SlSetArrayIndex(st->index); - SlObject(st, _station_desc); +struct STNNChunkHandler : ChunkHandler { + STNNChunkHandler() : ChunkHandler('STNN', CH_TABLE) + { + this->fix_pointers = true; } -} -static void Load_STNN() -{ - const std::vector slt = SlCompatTableHeader(_station_desc, _station_sl_compat); + void Save() const override + { + SlTableHeader(_station_desc); - _old_num_flows = 0; - - int index; - while ((index = SlIterateArray()) != -1) { - bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0; - - BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station(); - SlObject(bst, slt); + /* Write the stations */ + for (BaseStation *st : BaseStation::Iterate()) { + SlSetArrayIndex(st->index); + SlObject(st, _station_desc); + } } -} -static void Ptrs_STNN() -{ - /* From SLV_123 we store stations in STNN; before that in STNS. So do not - * fix pointers when the version is below SLV_123, as that would fix - * pointers twice: once in STNS chunk and once here. */ - if (IsSavegameVersionBefore(SLV_123)) return; - for (BaseStation *bst : BaseStation::Iterate()) { - SlObject(bst, _station_desc); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_station_desc, _station_sl_compat); + + _old_num_flows = 0; + + int index; + while ((index = SlIterateArray()) != -1) { + bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0; + + BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station(); + SlObject(bst, slt); + } } -} -static void Save_ROADSTOP() -{ - SlTableHeader(_roadstop_desc); + void FixPointers() const override + { + /* From SLV_123 we store stations in STNN; before that in STNS. So do not + * fix pointers when the version is below SLV_123, as that would fix + * pointers twice: once in STNS chunk and once here. */ + if (IsSavegameVersionBefore(SLV_123)) return; - for (RoadStop *rs : RoadStop::Iterate()) { - SlSetArrayIndex(rs->index); - SlObject(rs, _roadstop_desc); + for (BaseStation *bst : BaseStation::Iterate()) { + SlObject(bst, _station_desc); + } } -} +}; -static void Load_ROADSTOP() -{ - const std::vector slt = SlCompatTableHeader(_roadstop_desc, _roadstop_sl_compat); - - int index; - - while ((index = SlIterateArray()) != -1) { - RoadStop *rs = new (index) RoadStop(INVALID_TILE); - - SlObject(rs, slt); +struct ROADChunkHandler : ChunkHandler { + ROADChunkHandler() : ChunkHandler('ROAD', CH_TABLE) + { + this->fix_pointers = true; } -} -static void Ptrs_ROADSTOP() -{ - for (RoadStop *rs : RoadStop::Iterate()) { - SlObject(rs, _roadstop_desc); + void Save() const override + { + SlTableHeader(_roadstop_desc); + + for (RoadStop *rs : RoadStop::Iterate()) { + SlSetArrayIndex(rs->index); + SlObject(rs, _roadstop_desc); + } } -} -static const ChunkHandler STNS{ 'STNS', nullptr, Load_STNS, Ptrs_STNS, nullptr, CH_READONLY }; -static const ChunkHandler STNN{ 'STNN', Save_STNN, Load_STNN, Ptrs_STNN, nullptr, CH_TABLE }; -static const ChunkHandler ROAD{ 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, nullptr, CH_TABLE }; + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_roadstop_desc, _roadstop_sl_compat); + + int index; + + while ((index = SlIterateArray()) != -1) { + RoadStop *rs = new (index) RoadStop(INVALID_TILE); + + SlObject(rs, slt); + } + } + + void FixPointers() const override + { + for (RoadStop *rs : RoadStop::Iterate()) { + SlObject(rs, _roadstop_desc); + } + } +}; + +static const STNSChunkHandler STNS; +static const STNNChunkHandler STNN; +static const ROADChunkHandler ROAD; static const ChunkHandlerRef station_chunk_handlers[] = { STNS, STNN, diff --git a/src/saveload/storage_sl.cpp b/src/saveload/storage_sl.cpp index 4a360d58d8..4db185e9af 100644 --- a/src/saveload/storage_sl.cpp +++ b/src/saveload/storage_sl.cpp @@ -23,34 +23,37 @@ static const SaveLoad _storage_desc[] = { SLE_CONDARR(PersistentStorage, storage, SLE_UINT32, 256, SLV_EXTEND_PERSISTENT_STORAGE, SL_MAX_VERSION), }; -/** Load persistent storage data. */ -static void Load_PSAC() -{ - const std::vector slt = SlCompatTableHeader(_storage_desc, _storage_sl_compat); +/** Persistent storage data. */ +struct PSACChunkHandler : ChunkHandler { + PSACChunkHandler() : ChunkHandler('PSAC', CH_TABLE) {} - int index; + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_storage_desc, _storage_sl_compat); - while ((index = SlIterateArray()) != -1) { - assert(PersistentStorage::CanAllocateItem()); - PersistentStorage *ps = new (index) PersistentStorage(0, 0, 0); - SlObject(ps, slt); + int index; + + while ((index = SlIterateArray()) != -1) { + assert(PersistentStorage::CanAllocateItem()); + PersistentStorage *ps = new (index) PersistentStorage(0, 0, 0); + SlObject(ps, slt); + } } -} -/** Save persistent storage data. */ -static void Save_PSAC() -{ - SlTableHeader(_storage_desc); + void Save() const override + { + SlTableHeader(_storage_desc); - /* Write the industries */ - for (PersistentStorage *ps : PersistentStorage::Iterate()) { - ps->ClearChanges(); - SlSetArrayIndex(ps->index); - SlObject(ps, _storage_desc); + /* Write the industries */ + for (PersistentStorage *ps : PersistentStorage::Iterate()) { + ps->ClearChanges(); + SlSetArrayIndex(ps->index); + SlObject(ps, _storage_desc); + } } -} +}; -static const ChunkHandler PSAC{ 'PSAC', Save_PSAC, Load_PSAC, nullptr, nullptr, CH_TABLE }; +static const PSACChunkHandler PSAC; static const ChunkHandlerRef persistent_storage_chunk_handlers[] = { PSAC, }; diff --git a/src/saveload/story_sl.cpp b/src/saveload/story_sl.cpp index 6371b4162b..d20bc3b4cd 100644 --- a/src/saveload/story_sl.cpp +++ b/src/saveload/story_sl.cpp @@ -38,34 +38,38 @@ static const SaveLoad _story_page_elements_desc[] = { SLE_STR(StoryPageElement, text, SLE_STR | SLF_ALLOW_CONTROL, 0), }; -static void Save_STORY_PAGE_ELEMENT() -{ - SlTableHeader(_story_page_elements_desc); +struct STPEChunkHandler : ChunkHandler { + STPEChunkHandler() : ChunkHandler('STPE', CH_TABLE) {} - for (StoryPageElement *s : StoryPageElement::Iterate()) { - SlSetArrayIndex(s->index); - SlObject(s, _story_page_elements_desc); - } -} + void Save() const override + { + SlTableHeader(_story_page_elements_desc); -static void Load_STORY_PAGE_ELEMENT() -{ - const std::vector slt = SlCompatTableHeader(_story_page_elements_desc, _story_page_elements_sl_compat); - - int index; - uint32 max_sort_value = 0; - while ((index = SlIterateArray()) != -1) { - StoryPageElement *s = new (index) StoryPageElement(); - SlObject(s, slt); - if (s->sort_value > max_sort_value) { - max_sort_value = s->sort_value; + for (StoryPageElement *s : StoryPageElement::Iterate()) { + SlSetArrayIndex(s->index); + SlObject(s, _story_page_elements_desc); } } - /* Update the next sort value, so that the next - * created page is shown after all existing pages. - */ - _story_page_element_next_sort_value = max_sort_value + 1; -} + + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_story_page_elements_desc, _story_page_elements_sl_compat); + + int index; + uint32 max_sort_value = 0; + while ((index = SlIterateArray()) != -1) { + StoryPageElement *s = new (index) StoryPageElement(); + SlObject(s, slt); + if (s->sort_value > max_sort_value) { + max_sort_value = s->sort_value; + } + } + /* Update the next sort value, so that the next + * created page is shown after all existing pages. + */ + _story_page_element_next_sort_value = max_sort_value + 1; + } +}; static const SaveLoad _story_pages_desc[] = { SLE_CONDVAR(StoryPage, sort_value, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_185), @@ -76,37 +80,41 @@ static const SaveLoad _story_pages_desc[] = { SLE_STR(StoryPage, title, SLE_STR | SLF_ALLOW_CONTROL, 0), }; -static void Save_STORY_PAGE() -{ - SlTableHeader(_story_pages_desc); +struct STPAChunkHandler : ChunkHandler { + STPAChunkHandler() : ChunkHandler('STPA', CH_TABLE) {} - for (StoryPage *s : StoryPage::Iterate()) { - SlSetArrayIndex(s->index); - SlObject(s, _story_pages_desc); - } -} + void Save() const override + { + SlTableHeader(_story_pages_desc); -static void Load_STORY_PAGE() -{ - const std::vector slt = SlCompatTableHeader(_story_pages_desc, _story_pages_sl_compat); - - int index; - uint32 max_sort_value = 0; - while ((index = SlIterateArray()) != -1) { - StoryPage *s = new (index) StoryPage(); - SlObject(s, slt); - if (s->sort_value > max_sort_value) { - max_sort_value = s->sort_value; + for (StoryPage *s : StoryPage::Iterate()) { + SlSetArrayIndex(s->index); + SlObject(s, _story_pages_desc); } } - /* Update the next sort value, so that the next - * created page is shown after all existing pages. - */ - _story_page_next_sort_value = max_sort_value + 1; -} -static const ChunkHandler STPE{ 'STPE', Save_STORY_PAGE_ELEMENT, Load_STORY_PAGE_ELEMENT, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler STPA{ 'STPA', Save_STORY_PAGE, Load_STORY_PAGE, nullptr, nullptr, CH_TABLE }; + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_story_pages_desc, _story_pages_sl_compat); + + int index; + uint32 max_sort_value = 0; + while ((index = SlIterateArray()) != -1) { + StoryPage *s = new (index) StoryPage(); + SlObject(s, slt); + if (s->sort_value > max_sort_value) { + max_sort_value = s->sort_value; + } + } + /* Update the next sort value, so that the next + * created page is shown after all existing pages. + */ + _story_page_next_sort_value = max_sort_value + 1; + } +}; + +static const STPEChunkHandler STPE; +static const STPAChunkHandler STPA; static const ChunkHandlerRef story_page_chunk_handlers[] = { STPE, STPA, diff --git a/src/saveload/strings_sl.cpp b/src/saveload/strings_sl.cpp index 7cad1fba6e..512a743d98 100644 --- a/src/saveload/strings_sl.cpp +++ b/src/saveload/strings_sl.cpp @@ -113,24 +113,25 @@ void InitializeOldNames() _old_name_array = CallocT(NUM_OLD_STRINGS * LEN_OLD_STRINGS); // 200 * 24 would be enough for TTO savegames } -/** - * Load the NAME chunk. - */ -static void Load_NAME() -{ - int index; +struct NAMEChunkHandler : ChunkHandler { + NAMEChunkHandler() : ChunkHandler('NAME', CH_READONLY) {} - while ((index = SlIterateArray()) != -1) { - if (index >= NUM_OLD_STRINGS) SlErrorCorrupt("Invalid old name index"); - if (SlGetFieldLength() > (uint)LEN_OLD_STRINGS) SlErrorCorrupt("Invalid old name length"); + void Load() const override + { + int index; - SlCopy(&_old_name_array[LEN_OLD_STRINGS * index], SlGetFieldLength(), SLE_UINT8); - /* Make sure the old name is null terminated */ - _old_name_array[LEN_OLD_STRINGS * index + LEN_OLD_STRINGS - 1] = '\0'; + while ((index = SlIterateArray()) != -1) { + if (index >= NUM_OLD_STRINGS) SlErrorCorrupt("Invalid old name index"); + if (SlGetFieldLength() > (uint)LEN_OLD_STRINGS) SlErrorCorrupt("Invalid old name length"); + + SlCopy(&_old_name_array[LEN_OLD_STRINGS * index], SlGetFieldLength(), SLE_UINT8); + /* Make sure the old name is null terminated */ + _old_name_array[LEN_OLD_STRINGS * index + LEN_OLD_STRINGS - 1] = '\0'; + } } -} +}; -static const ChunkHandler NAME{ 'NAME', nullptr, Load_NAME, nullptr, nullptr, CH_READONLY }; +static const NAMEChunkHandler NAME; static const ChunkHandlerRef name_chunk_handlers[] = { NAME, }; diff --git a/src/saveload/subsidy_sl.cpp b/src/saveload/subsidy_sl.cpp index a02c19319f..d4a882dad7 100644 --- a/src/saveload/subsidy_sl.cpp +++ b/src/saveload/subsidy_sl.cpp @@ -29,28 +29,32 @@ static const SaveLoad _subsidies_desc[] = { SLE_CONDVAR(Subsidy, dst, SLE_UINT16, SLV_5, SL_MAX_VERSION), }; -static void Save_SUBS() -{ - SlTableHeader(_subsidies_desc); +struct SUBSChunkHandler : ChunkHandler { + SUBSChunkHandler() : ChunkHandler('SUBS', CH_TABLE) {} - for (Subsidy *s : Subsidy::Iterate()) { - SlSetArrayIndex(s->index); - SlObject(s, _subsidies_desc); + void Save() const override + { + SlTableHeader(_subsidies_desc); + + for (Subsidy *s : Subsidy::Iterate()) { + SlSetArrayIndex(s->index); + SlObject(s, _subsidies_desc); + } } -} -static void Load_SUBS() -{ - const std::vector slt = SlCompatTableHeader(_subsidies_desc, _subsidies_sl_compat); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_subsidies_desc, _subsidies_sl_compat); - int index; - while ((index = SlIterateArray()) != -1) { - Subsidy *s = new (index) Subsidy(); - SlObject(s, slt); + int index; + while ((index = SlIterateArray()) != -1) { + Subsidy *s = new (index) Subsidy(); + SlObject(s, slt); + } } -} +}; -static const ChunkHandler SUBS{ 'SUBS', Save_SUBS, Load_SUBS, nullptr, nullptr, CH_TABLE }; +static const SUBSChunkHandler SUBS; static const ChunkHandlerRef subsidy_chunk_handlers[] = { SUBS, }; diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 906940033f..09c575e6a0 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -272,54 +272,64 @@ static const SaveLoad _town_desc[] = { SLEG_CONDSTRUCTLIST("acceptance_matrix", SlTownAcceptanceMatrix, SLV_166, SLV_REMOVE_TOWN_CARGO_CACHE), }; -static void Save_HIDS() -{ - Save_NewGRFMapping(_house_mngr); -} +struct HIDSChunkHandler : ChunkHandler { + HIDSChunkHandler() : ChunkHandler('HIDS', CH_TABLE) {} -static void Load_HIDS() -{ - Load_NewGRFMapping(_house_mngr); -} - -static void Save_TOWN() -{ - SlTableHeader(_town_desc); - - for (Town *t : Town::Iterate()) { - SlSetArrayIndex(t->index); - SlObject(t, _town_desc); + void Save() const override + { + Save_NewGRFMapping(_house_mngr); } -} -static void Load_TOWN() -{ - const std::vector slt = SlCompatTableHeader(_town_desc, _town_sl_compat); + void Load() const override + { + Load_NewGRFMapping(_house_mngr); + } +}; - int index; +struct CITYChunkHandler : ChunkHandler { + CITYChunkHandler() : ChunkHandler('CITY', CH_TABLE) + { + this->fix_pointers = true; + } - while ((index = SlIterateArray()) != -1) { - Town *t = new (index) Town(); - SlObject(t, slt); + void Save() const override + { + SlTableHeader(_town_desc); - if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GetStringTab(t->townnametype) != TEXT_TAB_OLD_CUSTOM) { - SlErrorCorrupt("Invalid town name generator"); + for (Town *t : Town::Iterate()) { + SlSetArrayIndex(t->index); + SlObject(t, _town_desc); } } -} -/** Fix pointers when loading town data. */ -static void Ptrs_TOWN() -{ - if (IsSavegameVersionBefore(SLV_161)) return; + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_town_desc, _town_sl_compat); - for (Town *t : Town::Iterate()) { - SlObject(t, _town_desc); + int index; + + while ((index = SlIterateArray()) != -1) { + Town *t = new (index) Town(); + SlObject(t, slt); + + if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GetStringTab(t->townnametype) != TEXT_TAB_OLD_CUSTOM) { + SlErrorCorrupt("Invalid town name generator"); + } + } } -} -static const ChunkHandler HIDS{ 'HIDS', Save_HIDS, Load_HIDS, nullptr, nullptr, CH_TABLE }; -static const ChunkHandler CITY{ 'CITY', Save_TOWN, Load_TOWN, Ptrs_TOWN, nullptr, CH_TABLE }; + void FixPointers() const override + { + if (IsSavegameVersionBefore(SLV_161)) return; + + for (Town *t : Town::Iterate()) { + SlObject(t, _town_desc); + } + } +}; + +static const HIDSChunkHandler HIDS; +static const CITYChunkHandler CITY; static const ChunkHandlerRef town_chunk_handlers[] = { HIDS, CITY, diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 2be5998f59..24b3a13c9f 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -994,77 +994,82 @@ const static SaveLoad _vehicle_desc[] = { SLEG_STRUCT("disaster", SlVehicleDisaster), }; -/** Will be called when the vehicles need to be saved. */ -static void Save_VEHS() -{ - SlTableHeader(_vehicle_desc); - - /* Write the vehicles */ - for (Vehicle *v : Vehicle::Iterate()) { - SlSetArrayIndex(v->index); - SlObject(v, _vehicle_desc); +struct VEHSChunkHandler : ChunkHandler { + VEHSChunkHandler() : ChunkHandler('VEHS', CH_SPARSE_TABLE) + { + this->fix_pointers = true; } -} -/** Will be called when vehicles need to be loaded. */ -void Load_VEHS() -{ - const std::vector slt = SlCompatTableHeader(_vehicle_desc, _vehicle_sl_compat); + void Save() const override + { + SlTableHeader(_vehicle_desc); - int index; - - _cargo_count = 0; - - while ((index = SlIterateArray()) != -1) { - Vehicle *v; - VehicleType vtype = (VehicleType)SlReadByte(); - - switch (vtype) { - case VEH_TRAIN: v = new (index) Train(); break; - case VEH_ROAD: v = new (index) RoadVehicle(); break; - case VEH_SHIP: v = new (index) Ship(); break; - case VEH_AIRCRAFT: v = new (index) Aircraft(); break; - case VEH_EFFECT: v = new (index) EffectVehicle(); break; - case VEH_DISASTER: v = new (index) DisasterVehicle(); break; - case VEH_INVALID: // Savegame shouldn't contain invalid vehicles - default: SlErrorCorrupt("Invalid vehicle type"); + /* Write the vehicles */ + for (Vehicle *v : Vehicle::Iterate()) { + SlSetArrayIndex(v->index); + SlObject(v, _vehicle_desc); } - - SlObject(v, slt); - - if (_cargo_count != 0 && IsCompanyBuildableVehicleType(v) && CargoPacket::CanAllocateItem()) { - /* Don't construct the packet with station here, because that'll fail with old savegames */ - CargoPacket *cp = new CargoPacket(_cargo_count, _cargo_days, _cargo_source, _cargo_source_xy, _cargo_loaded_at_xy, _cargo_feeder_share); - v->cargo.Append(cp); - } - - /* Old savegames used 'last_station_visited = 0xFF' */ - if (IsSavegameVersionBefore(SLV_5) && v->last_station_visited == 0xFF) { - v->last_station_visited = INVALID_STATION; - } - - if (IsSavegameVersionBefore(SLV_182)) v->last_loading_station = INVALID_STATION; - - if (IsSavegameVersionBefore(SLV_5)) { - /* Convert the current_order.type (which is a mix of type and flags, because - * in those versions, they both were 4 bits big) to type and flags */ - v->current_order.flags = GB(v->current_order.type, 4, 4); - v->current_order.type &= 0x0F; - } - - /* Advanced vehicle lists got added */ - if (IsSavegameVersionBefore(SLV_60)) v->group_id = DEFAULT_GROUP; } -} -void Ptrs_VEHS() -{ - for (Vehicle *v : Vehicle::Iterate()) { - SlObject(v, _vehicle_desc); + void Load() const override + { + const std::vector slt = SlCompatTableHeader(_vehicle_desc, _vehicle_sl_compat); + + int index; + + _cargo_count = 0; + + while ((index = SlIterateArray()) != -1) { + Vehicle *v; + VehicleType vtype = (VehicleType)SlReadByte(); + + switch (vtype) { + case VEH_TRAIN: v = new (index) Train(); break; + case VEH_ROAD: v = new (index) RoadVehicle(); break; + case VEH_SHIP: v = new (index) Ship(); break; + case VEH_AIRCRAFT: v = new (index) Aircraft(); break; + case VEH_EFFECT: v = new (index) EffectVehicle(); break; + case VEH_DISASTER: v = new (index) DisasterVehicle(); break; + case VEH_INVALID: // Savegame shouldn't contain invalid vehicles + default: SlErrorCorrupt("Invalid vehicle type"); + } + + SlObject(v, slt); + + if (_cargo_count != 0 && IsCompanyBuildableVehicleType(v) && CargoPacket::CanAllocateItem()) { + /* Don't construct the packet with station here, because that'll fail with old savegames */ + CargoPacket *cp = new CargoPacket(_cargo_count, _cargo_days, _cargo_source, _cargo_source_xy, _cargo_loaded_at_xy, _cargo_feeder_share); + v->cargo.Append(cp); + } + + /* Old savegames used 'last_station_visited = 0xFF' */ + if (IsSavegameVersionBefore(SLV_5) && v->last_station_visited == 0xFF) { + v->last_station_visited = INVALID_STATION; + } + + if (IsSavegameVersionBefore(SLV_182)) v->last_loading_station = INVALID_STATION; + + if (IsSavegameVersionBefore(SLV_5)) { + /* Convert the current_order.type (which is a mix of type and flags, because + * in those versions, they both were 4 bits big) to type and flags */ + v->current_order.flags = GB(v->current_order.type, 4, 4); + v->current_order.type &= 0x0F; + } + + /* Advanced vehicle lists got added */ + if (IsSavegameVersionBefore(SLV_60)) v->group_id = DEFAULT_GROUP; + } } -} -static const ChunkHandler VEHS{ 'VEHS', Save_VEHS, Load_VEHS, Ptrs_VEHS, nullptr, CH_SPARSE_TABLE }; + void FixPointers() const override + { + for (Vehicle *v : Vehicle::Iterate()) { + SlObject(v, _vehicle_desc); + } + } +}; + +static const VEHSChunkHandler VEHS; static const ChunkHandlerRef veh_chunk_handlers[] = { VEHS, }; diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp index bf22720fcb..739fd5655b 100644 --- a/src/saveload/waypoint_sl.cpp +++ b/src/saveload/waypoint_sl.cpp @@ -182,49 +182,56 @@ static const SaveLoad _old_waypoint_desc[] = { SLE_CONDVAR(OldWaypoint, owner, SLE_UINT8, SLV_101, SL_MAX_VERSION), }; -static void Load_WAYP() -{ - /* Precaution for when loading failed and it didn't get cleared */ - ResetOldWaypoints(); - - int index; - - while ((index = SlIterateArray()) != -1) { - OldWaypoint *wp = &_old_waypoints.emplace_back(); - - wp->index = index; - SlObject(wp, _old_waypoint_desc); +struct CHKPChunkHandler : ChunkHandler { + CHKPChunkHandler() : ChunkHandler('CHKP', CH_READONLY) + { + this->fix_pointers = true; } -} -static void Ptrs_WAYP() -{ - for (OldWaypoint &wp : _old_waypoints) { - SlObject(&wp, _old_waypoint_desc); + void Load() const override + { + /* Precaution for when loading failed and it didn't get cleared */ + ResetOldWaypoints(); - if (IsSavegameVersionBefore(SLV_12)) { - wp.town_cn = (wp.string_id & 0xC000) == 0xC000 ? (wp.string_id >> 8) & 0x3F : 0; - wp.town = ClosestTownFromTile(wp.xy, UINT_MAX); - } else if (IsSavegameVersionBefore(SLV_122)) { - /* Only for versions 12 .. 122 */ - if (!Town::IsValidID(wp.town_index)) { - /* Upon a corrupted waypoint we'll likely get here. The next step will be to - * loop over all Ptrs procs to nullptr the pointers. However, we don't know - * whether we're in the nullptr or "normal" Ptrs proc. So just clear the list - * of old waypoints we constructed and then this waypoint (and the other - * possibly corrupt ones) will not be queried in the nullptr Ptrs proc run. */ - _old_waypoints.clear(); - SlErrorCorrupt("Referencing invalid Town"); + int index; + + while ((index = SlIterateArray()) != -1) { + OldWaypoint *wp = &_old_waypoints.emplace_back(); + + wp->index = index; + SlObject(wp, _old_waypoint_desc); + } + } + + void FixPointers() const override + { + for (OldWaypoint &wp : _old_waypoints) { + SlObject(&wp, _old_waypoint_desc); + + if (IsSavegameVersionBefore(SLV_12)) { + wp.town_cn = (wp.string_id & 0xC000) == 0xC000 ? (wp.string_id >> 8) & 0x3F : 0; + wp.town = ClosestTownFromTile(wp.xy, UINT_MAX); + } else if (IsSavegameVersionBefore(SLV_122)) { + /* Only for versions 12 .. 122 */ + if (!Town::IsValidID(wp.town_index)) { + /* Upon a corrupted waypoint we'll likely get here. The next step will be to + * loop over all Ptrs procs to nullptr the pointers. However, we don't know + * whether we're in the nullptr or "normal" Ptrs proc. So just clear the list + * of old waypoints we constructed and then this waypoint (and the other + * possibly corrupt ones) will not be queried in the nullptr Ptrs proc run. */ + _old_waypoints.clear(); + SlErrorCorrupt("Referencing invalid Town"); + } + wp.town = Town::Get(wp.town_index); + } + if (IsSavegameVersionBefore(SLV_84)) { + wp.name = CopyFromOldName(wp.string_id); } - wp.town = Town::Get(wp.town_index); - } - if (IsSavegameVersionBefore(SLV_84)) { - wp.name = CopyFromOldName(wp.string_id); } } -} +}; -static const ChunkHandler CHKP{ 'CHKP', nullptr, Load_WAYP, Ptrs_WAYP, nullptr, CH_READONLY }; +static const CHKPChunkHandler CHKP; static const ChunkHandlerRef waypoint_chunk_handlers[] = { CHKP, };