diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1450,6 +1450,27 @@ size_t SlCalcObjMemberLength(const void case SL_WRITEBYTE: return 1; // a byte is logically of size 1 case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END)); case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription()); + case SL_STRUCT: + case SL_STRUCTLIST: { + if (!SlIsObjectValidInSavegame(sld)) break; + + NeedLength old_need_length = _sl.need_length; + size_t old_obj_len = _sl.obj_len; + + _sl.need_length = NL_CALCLENGTH; + _sl.obj_len = 0; + + /* Pretend that we are saving to collect the object size. Other + * means are difficult, as we don't know the length of the list we + * are about to store. */ + sld.handler->Save(const_cast(object)); + size_t length = _sl.obj_len; + + _sl.obj_len = old_obj_len; + _sl.need_length = old_need_length; + + return length; + } default: NOT_REACHED(); } return 0; @@ -1505,8 +1526,6 @@ size_t SlCalcObjMemberLength(const void static bool SlObjectMember(void *object, const SaveLoad &sld) { - void *ptr = GetVariableAddress(object, sld); - assert(IsVariableSizeRight(sld)); VarType conv = GB(sld.conv, 0, 8); @@ -1517,10 +1536,12 @@ static bool SlObjectMember(void *object, case SL_STR: case SL_REFLIST: case SL_DEQUE: - case SL_STDSTR: + case SL_STDSTR: { /* CONDITIONAL saveload types depend on the savegame version */ if (!SlIsObjectValidInSavegame(sld)) return false; + void *ptr = GetVariableAddress(object, sld); + switch (sld.cmd) { case SL_VAR: SlSaveLoadConv(ptr, conv); break; case SL_REF: SlSaveLoadRef(ptr, conv); break; @@ -1532,11 +1553,14 @@ static bool SlObjectMember(void *object, default: NOT_REACHED(); } break; + } /* SL_WRITEBYTE writes a value to the savegame to identify the type of an object. * When loading, the value is read explicitly with SlReadByte() to determine which * object description to use. */ - case SL_WRITEBYTE: + case SL_WRITEBYTE: { + void *ptr = GetVariableAddress(object, sld); + switch (_sl.action) { case SLA_SAVE: SlWriteByte(*(uint8 *)ptr); break; case SLA_LOAD_CHECK: @@ -1546,15 +1570,34 @@ static bool SlObjectMember(void *object, default: NOT_REACHED(); } break; + } /* SL_VEH_INCLUDE loads common code for vehicles */ - case SL_VEH_INCLUDE: + case SL_VEH_INCLUDE: { + void *ptr = GetVariableAddress(object, sld); SlObject(ptr, GetVehicleDescription(VEH_END)); break; - - case SL_ST_INCLUDE: + } + + case SL_ST_INCLUDE: { + void *ptr = GetVariableAddress(object, sld); SlObject(ptr, GetBaseStationDescription()); break; + } + + case SL_STRUCT: + case SL_STRUCTLIST: + if (!SlIsObjectValidInSavegame(sld)) return false; + + switch (_sl.action) { + case SLA_SAVE: sld.handler->Save(object); break; + case SLA_LOAD_CHECK: sld.handler->LoadCheck(object); break; + case SLA_LOAD: sld.handler->Load(object); break; + case SLA_PTRS: sld.handler->FixPointers(object); break; + case SLA_NULL: break; + default: NOT_REACHED(); + } + break; default: NOT_REACHED(); }