mirror of https://github.com/OpenTTD/OpenTTD
(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 pointersrelease/1.0
parent
83dc6ef6e6
commit
570af0ce44
|
@ -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(); }
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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");
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ struct ChunkHandler {
|
|||
uint32 id;
|
||||
ChunkSaveLoadProc *save_proc;
|
||||
ChunkSaveLoadProc *load_proc;
|
||||
ChunkSaveLoadProc *ptrs_proc;
|
||||
uint32 flags;
|
||||
};
|
||||
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue