diff options
author | smatz <smatz@openttd.org> | 2009-05-17 16:28:29 +0000 |
---|---|---|
committer | smatz <smatz@openttd.org> | 2009-05-17 16:28:29 +0000 |
commit | 570af0ce449b6c94427233d7eae07c40bb789197 (patch) | |
tree | 81450baf6a65200503c2871c31e586ac5214d054 | |
parent | 83dc6ef6e6064441c9a5ebc22061de313147821a (diff) | |
download | openttd-570af0ce449b6c94427233d7eae07c40bb789197.tar.xz |
(svn r16338) -Codechange: split loading of references to two phases
In the first phase, indexes are stored. In the second phase, indexes are checked for validity and converted to pointers
29 files changed, 222 insertions, 90 deletions
diff --git a/src/cargopacket.h b/src/cargopacket.h index 941e6da8a..74b9287b7 100644 --- a/src/cargopacket.h +++ b/src/cargopacket.h @@ -71,7 +71,7 @@ struct CargoPacket : PoolItem<CargoPacket, CargoPacketID, &_CargoPacket_pool> { */ #define FOR_ALL_CARGOPACKETS(cp) FOR_ALL_CARGOPACKETS_FROM(cp, 0) -extern void SaveLoad_STNS(Station *st); +extern const struct SaveLoad *GetGoodsDesc(); /** * Simple collection class for a list of cargo packets @@ -99,7 +99,7 @@ private: uint days_in_transit; ///< Cache for the number of days in transit public: - friend void SaveLoad_STNS(Station *st); + friend const struct SaveLoad *GetGoodsDesc(); /** Create the cargo list */ CargoList() { this->InvalidateCache(); } diff --git a/src/order_base.h b/src/order_base.h index 0490db068..f239fdff0 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -260,8 +260,8 @@ private: public: /** Default constructor producing an invalid order list. */ - OrderList() - : first(NULL), num_orders(INVALID_VEH_ORDER_ID), num_vehicles(0), first_shared(NULL), + OrderList(VehicleOrderID num_orders = INVALID_VEH_ORDER_ID) + : first(NULL), num_orders(num_orders), num_vehicles(0), first_shared(NULL), timetable_duration(0) { } /** Create an order list with the given order chain for the given vehicle. diff --git a/src/saveload/ai_sl.cpp b/src/saveload/ai_sl.cpp index ae6253902..4001fb81f 100644 --- a/src/saveload/ai_sl.cpp +++ b/src/saveload/ai_sl.cpp @@ -102,5 +102,5 @@ static void Save_AIPL() } extern const ChunkHandler _ai_chunk_handlers[] = { - { 'AIPL', Save_AIPL, Load_AIPL, CH_ARRAY | CH_LAST}, + { 'AIPL', Save_AIPL, Load_AIPL, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/animated_tile_sl.cpp b/src/saveload/animated_tile_sl.cpp index ba3f519db..a6305c813 100644 --- a/src/saveload/animated_tile_sl.cpp +++ b/src/saveload/animated_tile_sl.cpp @@ -52,5 +52,5 @@ static void Load_ANIT() * the animated tile table. */ extern const ChunkHandler _animated_tile_chunk_handlers[] = { - { 'ANIT', Save_ANIT, Load_ANIT, CH_RIFF | CH_LAST}, + { 'ANIT', Save_ANIT, Load_ANIT, NULL, CH_RIFF | CH_LAST}, }; diff --git a/src/saveload/autoreplace_sl.cpp b/src/saveload/autoreplace_sl.cpp index 7ed3a2051..377fec902 100644 --- a/src/saveload/autoreplace_sl.cpp +++ b/src/saveload/autoreplace_sl.cpp @@ -45,6 +45,15 @@ static void Load_ERNW() } } +static void Ptrs_ERNW() +{ + EngineRenew *er; + + FOR_ALL_ENGINE_RENEWS(er) { + SlObject(er, _engine_renew_desc); + } +} + extern const ChunkHandler _autoreplace_chunk_handlers[] = { - { 'ERNW', Save_ERNW, Load_ERNW, CH_ARRAY | CH_LAST}, + { 'ERNW', Save_ERNW, Load_ERNW, Ptrs_ERNW, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/cargopacket_sl.cpp b/src/saveload/cargopacket_sl.cpp index c871d66c8..08710dc34 100644 --- a/src/saveload/cargopacket_sl.cpp +++ b/src/saveload/cargopacket_sl.cpp @@ -40,5 +40,5 @@ static void Load_CAPA() } extern const ChunkHandler _cargopacket_chunk_handlers[] = { - { 'CAPA', Save_CAPA, Load_CAPA, CH_ARRAY | CH_LAST}, + { 'CAPA', Save_CAPA, Load_CAPA, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/cheat_sl.cpp b/src/saveload/cheat_sl.cpp index a8c939fed..e068a5538 100644 --- a/src/saveload/cheat_sl.cpp +++ b/src/saveload/cheat_sl.cpp @@ -33,5 +33,5 @@ static void Load_CHTS() } extern const ChunkHandler _cheat_chunk_handlers[] = { - { 'CHTS', Save_CHTS, Load_CHTS, CH_RIFF | CH_LAST} + { 'CHTS', Save_CHTS, Load_CHTS, NULL, CH_RIFF | CH_LAST}, }; diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 0e242422f..8c44fee0c 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -277,6 +277,15 @@ static void Load_PLYR() } } +static void Ptrs_PLYR() +{ + Company *c; + FOR_ALL_COMPANIES(c) { + SlObject(c, _company_desc); + } +} + + extern const ChunkHandler _company_chunk_handlers[] = { - { 'PLYR', Save_PLYR, Load_PLYR, CH_ARRAY | CH_LAST}, + { 'PLYR', Save_PLYR, Load_PLYR, Ptrs_PLYR, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/depot_sl.cpp b/src/saveload/depot_sl.cpp index fb546ef73..54feb350b 100644 --- a/src/saveload/depot_sl.cpp +++ b/src/saveload/depot_sl.cpp @@ -35,5 +35,5 @@ static void Load_DEPT() } extern const ChunkHandler _depot_chunk_handlers[] = { - { 'DEPT', Save_DEPT, Load_DEPT, CH_ARRAY | CH_LAST}, + { 'DEPT', Save_DEPT, Load_DEPT, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/economy_sl.cpp b/src/saveload/economy_sl.cpp index 99f306f52..46c5b67ad 100644 --- a/src/saveload/economy_sl.cpp +++ b/src/saveload/economy_sl.cpp @@ -52,7 +52,7 @@ static void Load_ECMY() } extern const ChunkHandler _economy_chunk_handlers[] = { - { 'PRIC', SaveLoad_PRIC, SaveLoad_PRIC, CH_RIFF | CH_AUTO_LENGTH}, - { 'CAPR', SaveLoad_CAPR, SaveLoad_CAPR, CH_RIFF | CH_AUTO_LENGTH}, - { 'ECMY', Save_ECMY, Load_ECMY, CH_RIFF | CH_LAST}, + { 'PRIC', SaveLoad_PRIC, SaveLoad_PRIC, NULL, CH_RIFF | CH_AUTO_LENGTH}, + { 'CAPR', SaveLoad_CAPR, SaveLoad_CAPR, NULL, CH_RIFF | CH_AUTO_LENGTH}, + { 'ECMY', Save_ECMY, Load_ECMY, NULL, CH_RIFF | CH_LAST}, }; diff --git a/src/saveload/engine_sl.cpp b/src/saveload/engine_sl.cpp index 8da2aa879..a3557dfd0 100644 --- a/src/saveload/engine_sl.cpp +++ b/src/saveload/engine_sl.cpp @@ -143,7 +143,7 @@ static void Load_EIDS() } extern const ChunkHandler _engine_chunk_handlers[] = { - { 'EIDS', Save_EIDS, Load_EIDS, CH_ARRAY }, - { 'ENGN', Save_ENGN, Load_ENGN, CH_ARRAY }, - { 'ENGS', NULL, Load_ENGS, CH_RIFF | CH_LAST }, + { 'EIDS', Save_EIDS, Load_EIDS, NULL, CH_ARRAY }, + { 'ENGN', Save_ENGN, Load_ENGN, NULL, CH_ARRAY }, + { 'ENGS', NULL, Load_ENGS, NULL, CH_RIFF | CH_LAST }, }; diff --git a/src/saveload/gamelog_sl.cpp b/src/saveload/gamelog_sl.cpp index e913e2dd1..f1f784280 100644 --- a/src/saveload/gamelog_sl.cpp +++ b/src/saveload/gamelog_sl.cpp @@ -162,5 +162,5 @@ static void Save_GLOG() extern const ChunkHandler _gamelog_chunk_handlers[] = { - { 'GLOG', Save_GLOG, Load_GLOG, CH_RIFF | CH_LAST } + { 'GLOG', Save_GLOG, Load_GLOG, NULL, CH_RIFF | CH_LAST } }; diff --git a/src/saveload/group_sl.cpp b/src/saveload/group_sl.cpp index 66e3585b4..33edf51eb 100644 --- a/src/saveload/group_sl.cpp +++ b/src/saveload/group_sl.cpp @@ -39,5 +39,5 @@ static void Load_GRPS(void) } extern const ChunkHandler _group_chunk_handlers[] = { - { 'GRPS', Save_GRPS, Load_GRPS, CH_ARRAY | CH_LAST}, + { 'GRPS', Save_GRPS, Load_GRPS, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/industry_sl.cpp b/src/saveload/industry_sl.cpp index 1e4a77ee4..25a3ca4ab 100644 --- a/src/saveload/industry_sl.cpp +++ b/src/saveload/industry_sl.cpp @@ -148,8 +148,17 @@ static void Load_TIDS() } } +static void Ptrs_INDY() +{ + Industry *i; + + FOR_ALL_INDUSTRIES(i) { + SlObject(i, _industry_desc); + } +} + extern const ChunkHandler _industry_chunk_handlers[] = { - { 'INDY', Save_INDY, Load_INDY, CH_ARRAY}, - { 'IIDS', Save_IIDS, Load_IIDS, CH_ARRAY}, - { 'TIDS', Save_TIDS, Load_TIDS, CH_ARRAY | CH_LAST}, + { 'INDY', Save_INDY, Load_INDY, Ptrs_INDY, CH_ARRAY}, + { 'IIDS', Save_IIDS, Load_IIDS, NULL, CH_ARRAY}, + { 'TIDS', Save_TIDS, Load_TIDS, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/labelmaps_sl.cpp b/src/saveload/labelmaps_sl.cpp index e39e4d9b6..f216b8333 100644 --- a/src/saveload/labelmaps_sl.cpp +++ b/src/saveload/labelmaps_sl.cpp @@ -120,6 +120,6 @@ static void Load_RAIL() } extern const ChunkHandler _labelmaps_chunk_handlers[] = { - { 'RAIL', Save_RAIL, Load_RAIL, CH_ARRAY | CH_LAST}, + { 'RAIL', Save_RAIL, Load_RAIL, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp index 005960582..9fd90f28a 100644 --- a/src/saveload/map_sl.cpp +++ b/src/saveload/map_sl.cpp @@ -236,13 +236,13 @@ static void Save_MAP7() } extern const ChunkHandler _map_chunk_handlers[] = { - { 'MAPS', Save_MAPS, Load_MAPS, CH_RIFF }, - { 'MAPT', Save_MAPT, Load_MAPT, CH_RIFF }, - { 'MAPO', Save_MAP1, Load_MAP1, CH_RIFF }, - { 'MAP2', Save_MAP2, Load_MAP2, CH_RIFF }, - { 'M3LO', Save_MAP3, Load_MAP3, CH_RIFF }, - { 'M3HI', Save_MAP4, Load_MAP4, CH_RIFF }, - { 'MAP5', Save_MAP5, Load_MAP5, CH_RIFF }, - { 'MAPE', Save_MAP6, Load_MAP6, CH_RIFF }, - { 'MAP7', Save_MAP7, Load_MAP7, CH_RIFF | CH_LAST }, + { 'MAPS', Save_MAPS, Load_MAPS, NULL, CH_RIFF }, + { 'MAPT', Save_MAPT, Load_MAPT, NULL, CH_RIFF }, + { 'MAPO', Save_MAP1, Load_MAP1, NULL, CH_RIFF }, + { 'MAP2', Save_MAP2, Load_MAP2, NULL, CH_RIFF }, + { 'M3LO', Save_MAP3, Load_MAP3, NULL, CH_RIFF }, + { 'M3HI', Save_MAP4, Load_MAP4, NULL, CH_RIFF }, + { 'MAP5', Save_MAP5, Load_MAP5, NULL, CH_RIFF }, + { 'MAPE', Save_MAP6, Load_MAP6, NULL, CH_RIFF }, + { 'MAP7', Save_MAP7, Load_MAP7, NULL, CH_RIFF | CH_LAST }, }; diff --git a/src/saveload/misc_sl.cpp b/src/saveload/misc_sl.cpp index 12e74aebb..1ded1b730 100644 --- a/src/saveload/misc_sl.cpp +++ b/src/saveload/misc_sl.cpp @@ -102,6 +102,6 @@ static void SaveLoad_VIEW() } extern const ChunkHandler _misc_chunk_handlers[] = { - { 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF}, - { 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF | CH_LAST}, + { 'DATE', SaveLoad_DATE, SaveLoad_DATE, NULL, CH_RIFF}, + { 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, NULL, CH_RIFF | CH_LAST}, }; diff --git a/src/saveload/newgrf_sl.cpp b/src/saveload/newgrf_sl.cpp index 5269f235d..5f977f515 100644 --- a/src/saveload/newgrf_sl.cpp +++ b/src/saveload/newgrf_sl.cpp @@ -48,5 +48,5 @@ static void Load_NGRF() } extern const ChunkHandler _newgrf_chunk_handlers[] = { - { 'NGRF', Save_NGRF, Load_NGRF, CH_ARRAY | CH_LAST } + { 'NGRF', Save_NGRF, Load_NGRF, NULL, CH_ARRAY | CH_LAST } }; diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp index c7c66e130..6325b3cca 100644 --- a/src/saveload/order_sl.cpp +++ b/src/saveload/order_sl.cpp @@ -121,7 +121,7 @@ static void Load_ORDR() { if (CheckSavegameVersionOldStyle(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) */ + * (in the old days, the orderlist was 5000 items big) */ size_t len = SlGetFieldLength(); uint i; @@ -170,6 +170,17 @@ static void Load_ORDR() } } +static void Ptrs_ORDR() +{ + if (CheckSavegameVersionOldStyle(5, 2)) return; + + Order *o; + + FOR_ALL_ORDERS(o) { + SlObject(o, GetOrderDescription()); + } +} + const SaveLoad *GetOrderListDescription() { static const SaveLoad _orderlist_desc[] = { @@ -195,12 +206,23 @@ static void Load_ORDL() int index; while ((index = SlIterateArray()) != -1) { - OrderList *list = new (index) OrderList(); + /* set num_orders to 0 so it's a valid OrderList */ + OrderList *list = new (index) OrderList(0); + SlObject(list, GetOrderListDescription()); + } + +} + +static void Ptrs_ORDL() +{ + OrderList *list; + + FOR_ALL_ORDER_LISTS(list) { SlObject(list, GetOrderListDescription()); } } extern const ChunkHandler _order_chunk_handlers[] = { - { 'ORDR', Save_ORDR, Load_ORDR, CH_ARRAY}, - { 'ORDL', Save_ORDL, Load_ORDL, CH_ARRAY | CH_LAST}, + { 'ORDR', Save_ORDR, Load_ORDR, Ptrs_ORDR, CH_ARRAY}, + { 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index e7091b6bf..c0b6561c2 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -56,6 +56,7 @@ typedef size_t ReaderProc(); enum SaveLoadAction { SLA_LOAD, ///< loading SLA_SAVE, ///< saving + SLA_PTRS, ///< fixing pointers }; enum NeedLength { @@ -564,6 +565,7 @@ static void SlSaveLoadConv(void *ptr, VarType conv) WriteValue(ptr, conv, x); break; } + case SLA_PTRS: break; default: NOT_REACHED(); } } @@ -671,6 +673,7 @@ static void SlString(void *ptr, size_t length, VarType conv) str_validate((char *)ptr, (char *)ptr + len); break; } + case SLA_PTRS: break; default: NOT_REACHED(); } } @@ -693,6 +696,8 @@ static inline size_t SlCalcArrayLen(size_t length, VarType conv) */ void SlArray(void *array, size_t length, VarType conv) { + if (_sl.action == SLA_PTRS) return; + /* Automatically calculate the length? */ if (_sl.need_length != NL_NONE) { SlSetLength(SlCalcArrayLen(length, conv)); @@ -767,13 +772,14 @@ void SlList(void *list, SLRefType conv) if (_sl.need_length == NL_CALCLENGTH) return; } - std::list<void *> *l = (std::list<void *> *) list; + typedef std::list<void *> PtrList; + PtrList *l = (PtrList *)list; switch (_sl.action) { case SLA_SAVE: { SlWriteUint32((uint32)l->size()); - std::list<void *>::iterator iter; + PtrList::iterator iter; for (iter = l->begin(); iter != l->end(); ++iter) { void *ptr = *iter; SlWriteUint32(ReferenceToInt(ptr, conv)); @@ -785,7 +791,18 @@ void SlList(void *list, SLRefType conv) /* Load each reference and push to the end of the list */ for (uint i = 0; i < length; i++) { - void *ptr = IntToReference(CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32(), conv); + size_t data = CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32(); + l->push_back((void *)data); + } + break; + } + case SLA_PTRS: { + PtrList temp = *l; + + l->clear(); + PtrList::iterator iter; + for (iter = temp.begin(); iter != temp.end(); ++iter) { + void *ptr = IntToReference((size_t)*iter, conv); l->push_back(ptr); } break; @@ -885,7 +902,10 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) SlWriteUint32(ReferenceToInt(*(void **)ptr, (SLRefType)conv)); break; case SLA_LOAD: - *(void **)ptr = IntToReference(CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32(), (SLRefType)conv); + *(size_t *)ptr = (size_t)(CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32()); + break; + case SLA_PTRS: + *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv); break; default: NOT_REACHED(); } @@ -906,6 +926,7 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) switch (_sl.action) { case SLA_SAVE: SlWriteByte(sld->version_to); break; case SLA_LOAD: *(byte *)ptr = sld->version_from; break; + case SLA_PTRS: break; default: NOT_REACHED(); } break; @@ -1116,6 +1137,33 @@ static void SlLoadChunks() } } +/** Fix all pointers (convert index -> pointer) */ +static void SlFixPointers() +{ + const ChunkHandler *ch; + const ChunkHandler * const *chsc; + + _sl.action = SLA_PTRS; + + DEBUG(sl, 1, "Fixing pointers"); + + for (chsc = _sl.chs; (ch = *chsc++) != NULL;) { + while (true) { + if (ch->ptrs_proc != NULL) { + DEBUG(sl, 2, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id); + ch->ptrs_proc(); + } + if (ch->flags & CH_LAST) + break; + ch++; + } + } + + DEBUG(sl, 1, "All pointers fixed"); + + assert(_sl.action == SLA_PTRS); +} + /******************************************* ********** START OF LZO CODE ************** *******************************************/ @@ -1424,6 +1472,8 @@ static const ChunkHandler * const _chunk_handlers[] = { */ static uint ReferenceToInt(const void *obj, SLRefType rt) { + assert(_sl.action == SLA_SAVE); + if (obj == NULL) return 0; switch (rt) { @@ -1452,8 +1502,13 @@ static uint ReferenceToInt(const void *obj, SLRefType rt) * @param rt SLRefType type of the object the pointer is sought of * @return Return the index converted to a pointer of any type */ + +assert_compile(sizeof(size_t) <= sizeof(void *)); + static void *IntToReference(uint index, SLRefType rt) { + assert(_sl.action == SLA_PTRS); + /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE, * and should be loaded like that */ if (rt == REF_VEHICLE_OLD && !CheckSavegameVersionOldStyle(4, 4)) { @@ -1461,59 +1516,50 @@ static void *IntToReference(uint index, SLRefType rt) } /* No need to look up NULL pointers, just return immediately */ - if (rt != REF_VEHICLE_OLD && index == 0) { - return NULL; - } + if (index == (rt == REF_VEHICLE_OLD ? 0xFFFF : 0)) return NULL; - index--; // correct for the NULL index + /* Correct index. Old vehicles were saved differently: + * invalid vehicle was 0xFFFF, now we use 0x0000 for everything invalid. */ + if (rt != REF_VEHICLE_OLD) index--; switch (rt) { case REF_ORDERLIST: - if (_OrderList_pool.AddBlockIfNeeded(index)) return OrderList::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "OrderList index out of range"); + if (OrderList::IsValidID(index)) return OrderList::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid OrderList"); case REF_ORDER: - if (_Order_pool.AddBlockIfNeeded(index)) return Order::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Order index out of range"); + if (Order::IsValidID(index)) return Order::Get(index); + /* in old versions, invalid order was used to mark end of order list */ + if (CheckSavegameVersionOldStyle(5, 2)) return NULL; + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Order"); + case REF_VEHICLE_OLD: case REF_VEHICLE: - if (_Vehicle_pool.AddBlockIfNeeded(index)) return Vehicle::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Vehicle index out of range"); + if (Vehicle::IsValidID(index)) return Vehicle::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Vehicle"); case REF_STATION: - if (_Station_pool.AddBlockIfNeeded(index)) return Station::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Station index out of range"); + if (Station::IsValidID(index)) return Station::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Station"); case REF_TOWN: - if (_Town_pool.AddBlockIfNeeded(index)) return Town::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Town index out of range"); + if (Town::IsValidID(index)) return Town::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Town"); case REF_ROADSTOPS: - if (_RoadStop_pool.AddBlockIfNeeded(index)) return RoadStop::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "RoadStop index out of range"); + if (RoadStop::IsValidID(index)) return RoadStop::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid RoadStop"); case REF_ENGINE_RENEWS: - if (_EngineRenew_pool.AddBlockIfNeeded(index)) return EngineRenew::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "EngineRenew index out of range"); + if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid EngineRenew"); case REF_CARGO_PACKET: - if (_CargoPacket_pool.AddBlockIfNeeded(index)) return CargoPacket::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "CargoPacket index out of range"); - - case REF_VEHICLE_OLD: - /* Old vehicles were saved differently: - * invalid vehicle was 0xFFFF, - * and the index was not - 1.. correct for this */ - index++; - if (index == INVALID_VEHICLE) return NULL; - - if (_Vehicle_pool.AddBlockIfNeeded(index)) return Vehicle::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Vehicle index out of range"); + if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid CargoPacket"); default: NOT_REACHED(); } - - return NULL; } /** The format for a reader/writer type of a savegame */ @@ -1852,6 +1898,7 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb) GamelogReset(); SlLoadChunks(); + SlFixPointers(); fmt->uninit_read(); fclose(_sl.fh); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 38d95db29..cd1b9464c 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -52,6 +52,7 @@ struct ChunkHandler { uint32 id; ChunkSaveLoadProc *save_proc; ChunkSaveLoadProc *load_proc; + ChunkSaveLoadProc *ptrs_proc; uint32 flags; }; diff --git a/src/saveload/signs_sl.cpp b/src/saveload/signs_sl.cpp index 3006a50de..76df7ce15 100644 --- a/src/saveload/signs_sl.cpp +++ b/src/saveload/signs_sl.cpp @@ -51,5 +51,5 @@ static void Load_SIGN() } extern const ChunkHandler _sign_chunk_handlers[] = { - { 'SIGN', Save_SIGN, Load_SIGN, CH_ARRAY | CH_LAST}, + { 'SIGN', Save_SIGN, Load_SIGN, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 715ded17a..d85a5728b 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -118,10 +118,9 @@ static const SaveLoad _station_speclist_desc[] = { SLE_END() }; - -void SaveLoad_STNS(Station *st) +const SaveLoad *GetGoodsDesc() { - static const SaveLoad _goods_desc[] = { + static const SaveLoad goods_desc[] = { SLEG_CONDVAR( _waiting_acceptance, SLE_UINT16, 0, 67), SLE_CONDVAR(GoodsEntry, acceptance_pickup, SLE_UINT8, 68, SL_MAX_VERSION), SLE_CONDNULL(2, 51, 67), @@ -140,7 +139,12 @@ void SaveLoad_STNS(Station *st) SLE_END() }; + return goods_desc; +} + +static void SaveLoad_STNS(Station *st) +{ SlObject(st, _station_desc); _waiting_acceptance = 0; @@ -148,7 +152,7 @@ void SaveLoad_STNS(Station *st) uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO; for (CargoID i = 0; i < num_cargo; i++) { GoodsEntry *ge = &st->goods[i]; - SlObject(ge, _goods_desc); + SlObject(ge, GetGoodsDesc()); if (CheckSavegameVersion(68)) { SB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15)); if (GB(_waiting_acceptance, 0, 12) != 0) { @@ -197,6 +201,21 @@ static void Load_STNS() } } +void Ptrs_STNS() +{ + Station *st; + FOR_ALL_STATIONS(st) { + if (!CheckSavegameVersion(68)) { + for (CargoID i = 0; i < NUM_CARGO; i++) { + GoodsEntry *ge = &st->goods[i]; + SlObject(ge, GetGoodsDesc()); + } + } + SlObject(st, _station_desc); + } +} + + static void Save_ROADSTOP() { RoadStop *rs; @@ -218,7 +237,15 @@ static void Load_ROADSTOP() } } +static void Ptrs_ROADSTOP() +{ + RoadStop *rs; + FOR_ALL_ROADSTOPS(rs) { + SlObject(rs, _roadstop_desc); + } +} + extern const ChunkHandler _station_chunk_handlers[] = { - { 'STNS', Save_STNS, Load_STNS, CH_ARRAY }, - { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, CH_ARRAY | CH_LAST}, + { 'STNS', Save_STNS, Load_STNS, Ptrs_STNS, CH_ARRAY }, + { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/strings_sl.cpp b/src/saveload/strings_sl.cpp index cd5cd187d..6813c2c06 100644 --- a/src/saveload/strings_sl.cpp +++ b/src/saveload/strings_sl.cpp @@ -119,5 +119,5 @@ static void Load_NAME() } extern const ChunkHandler _name_chunk_handlers[] = { - { 'NAME', NULL, Load_NAME, CH_ARRAY | CH_LAST}, + { 'NAME', NULL, Load_NAME, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/subsidy_sl.cpp b/src/saveload/subsidy_sl.cpp index 1252f9793..dca315f96 100644 --- a/src/saveload/subsidy_sl.cpp +++ b/src/saveload/subsidy_sl.cpp @@ -39,5 +39,5 @@ void Load_SUBS() } extern const ChunkHandler _subsidy_chunk_handlers[] = { - { 'SUBS', Save_SUBS, Load_SUBS, CH_ARRAY | CH_LAST}, + { 'SUBS', Save_SUBS, Load_SUBS, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index c28f6acac..584727918 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -192,6 +192,6 @@ static void Load_TOWN() } extern const ChunkHandler _town_chunk_handlers[] = { - { 'HIDS', Save_HOUSEIDS, Load_HOUSEIDS, CH_ARRAY }, - { 'CITY', Save_TOWN, Load_TOWN, CH_ARRAY | CH_LAST}, + { 'HIDS', Save_HOUSEIDS, Load_HOUSEIDS, NULL, CH_ARRAY }, + { 'CITY', Save_TOWN, Load_TOWN, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 2058bd819..3d498851c 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -732,6 +732,14 @@ void Load_VEHS() } } +void Ptrs_VEHS() +{ + Vehicle *v; + FOR_ALL_VEHICLES(v) { + SlObject(v, GetVehicleDescription(v->type)); + } +} + extern const ChunkHandler _veh_chunk_handlers[] = { - { 'VEHS', Save_VEHS, Load_VEHS, CH_SPARSE_ARRAY | CH_LAST}, + { 'VEHS', Save_VEHS, Load_VEHS, Ptrs_VEHS, CH_SPARSE_ARRAY | CH_LAST}, }; diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp index e8a8bf949..48c1c92f1 100644 --- a/src/saveload/waypoint_sl.cpp +++ b/src/saveload/waypoint_sl.cpp @@ -92,5 +92,5 @@ static void Load_WAYP() } extern const ChunkHandler _waypoint_chunk_handlers[] = { - { 'CHKP', Save_WAYP, Load_WAYP, CH_ARRAY | CH_LAST}, + { 'CHKP', Save_WAYP, Load_WAYP, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/settings.cpp b/src/settings.cpp index 83db910ce..f3e5fb9ad 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1704,8 +1704,8 @@ void CheckConfig() } extern const ChunkHandler _setting_chunk_handlers[] = { - { 'OPTS', NULL, Load_OPTS, CH_RIFF}, - { 'PATS', Save_PATS, Load_PATS, CH_RIFF | CH_LAST}, + { 'OPTS', NULL, Load_OPTS, NULL, CH_RIFF}, + { 'PATS', Save_PATS, Load_PATS, NULL, CH_RIFF | CH_LAST}, }; static bool IsSignedVarMemType(VarType vt) |