diff --git a/src/cargopacket.h b/src/cargopacket.h index 941e6da8ac..74b9287b74 100644 --- a/src/cargopacket.h +++ b/src/cargopacket.h @@ -71,7 +71,7 @@ struct CargoPacket : PoolItem { */ #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 0490db068c..f239fdff0b 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 ae62539020..4001fb81fd 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 ba3f519db4..a6305c8130 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 7ed3a2051a..377fec902a 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 c871d66c81..08710dc341 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 a8c939fedf..e068a55389 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 0e242422f9..8c44fee0c2 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 fb546ef735..54feb350b2 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 99f306f527..46c5b67ad5 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 8da2aa879e..a3557dfd08 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 e913e2dd1f..f1f7842808 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 66e3585b48..33edf51eb0 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 1e4a77ee45..25a3ca4ab6 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 e39e4d9b6c..f216b83339 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 005960582e..9fd90f28aa 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 12e74aebb5..1ded1b7301 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 5269f235d5..5f977f515b 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 c7c66e1307..6325b3cca6 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 e7091b6bf8..c0b6561c2c 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 *l = (std::list *) list; + typedef std::list PtrList; + PtrList *l = (PtrList *)list; switch (_sl.action) { case SLA_SAVE: { SlWriteUint32((uint32)l->size()); - std::list::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"); - - case REF_VEHICLE: - if (_Vehicle_pool.AddBlockIfNeeded(index)) return Vehicle::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Vehicle index out of range"); - - case REF_STATION: - if (_Station_pool.AddBlockIfNeeded(index)) return Station::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Station index out of range"); - - case REF_TOWN: - if (_Town_pool.AddBlockIfNeeded(index)) return Town::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Town index out of range"); - - case REF_ROADSTOPS: - if (_RoadStop_pool.AddBlockIfNeeded(index)) return RoadStop::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "RoadStop index out of range"); - - 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"); - - 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"); + 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: - /* 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; + case REF_VEHICLE: + if (Vehicle::IsValidID(index)) return Vehicle::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Vehicle"); - if (_Vehicle_pool.AddBlockIfNeeded(index)) return Vehicle::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Vehicle index out of range"); + case REF_STATION: + if (Station::IsValidID(index)) return Station::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Station"); + + case REF_TOWN: + if (Town::IsValidID(index)) return Town::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Town"); + + case REF_ROADSTOPS: + if (RoadStop::IsValidID(index)) return RoadStop::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid RoadStop"); + + case REF_ENGINE_RENEWS: + if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index); + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid EngineRenew"); + + case REF_CARGO_PACKET: + 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 38d95db292..cd1b9464c6 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 3006a50de2..76df7ce15a 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 715ded17a7..d85a5728bc 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 cd5cd187dd..6813c2c06d 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 1252f97933..dca315f96e 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 c28f6acace..5847279181 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 2058bd8196..3d498851c7 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 e8a8bf949d..48c1c92f10 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 83db910cee..f3e5fb9ad9 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)