Saveload: Table format sub-struct support
This commit is contained in:
@@ -18,7 +18,7 @@ static const NamedSaveLoad _long_bridge_signal_storage_desc[] = {
|
|||||||
|
|
||||||
static void Load_XBSS()
|
static void Load_XBSS()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeaderOrRiff(_long_bridge_signal_storage_desc);
|
SaveLoadTableData slt = SlTableHeaderOrRiff(_long_bridge_signal_storage_desc);
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
@@ -29,7 +29,7 @@ static void Load_XBSS()
|
|||||||
|
|
||||||
static void Save_XBSS()
|
static void Save_XBSS()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(_long_bridge_signal_storage_desc);
|
SaveLoadTableData slt = SlTableHeader(_long_bridge_signal_storage_desc);
|
||||||
|
|
||||||
for (auto &it : _long_bridge_signal_sim_map) {
|
for (auto &it : _long_bridge_signal_sim_map) {
|
||||||
LongBridgeSignalStorage &lbss = it.second;
|
LongBridgeSignalStorage &lbss = it.second;
|
||||||
|
@@ -181,7 +181,7 @@ NamedSaveLoadTable GetCargoPacketDesc()
|
|||||||
*/
|
*/
|
||||||
static void Save_CAPA()
|
static void Save_CAPA()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(GetCargoPacketDesc());
|
SaveLoadTableData slt = SlTableHeader(GetCargoPacketDesc());
|
||||||
|
|
||||||
for (CargoPacket *cp : CargoPacket::Iterate()) {
|
for (CargoPacket *cp : CargoPacket::Iterate()) {
|
||||||
SlSetArrayIndex(cp->index);
|
SlSetArrayIndex(cp->index);
|
||||||
@@ -194,7 +194,7 @@ static void Save_CAPA()
|
|||||||
*/
|
*/
|
||||||
static void Load_CAPA()
|
static void Load_CAPA()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeaderOrRiff(GetCargoPacketDesc());
|
SaveLoadTableData slt = SlTableHeaderOrRiff(GetCargoPacketDesc());
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
|
@@ -80,7 +80,7 @@ std::vector<NamedSaveLoad> GetCheatsDesc(bool save) {
|
|||||||
*/
|
*/
|
||||||
static void Save_CHTS()
|
static void Save_CHTS()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(GetCheatsDesc(true));
|
SaveLoadTableData slt = SlTableHeader(GetCheatsDesc(true));
|
||||||
|
|
||||||
SlSetArrayIndex(0);
|
SlSetArrayIndex(0);
|
||||||
SlObjectSaveFiltered(&_cheats, slt);
|
SlObjectSaveFiltered(&_cheats, slt);
|
||||||
@@ -105,7 +105,7 @@ static void Load_CHTS()
|
|||||||
};
|
};
|
||||||
|
|
||||||
UnknownCheatHandler uch{};
|
UnknownCheatHandler uch{};
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(GetCheatsDesc(false), &uch);
|
SaveLoadTableData slt = SlTableHeader(GetCheatsDesc(false), &uch);
|
||||||
|
|
||||||
if (SlIterateArray() == -1) return;
|
if (SlIterateArray() == -1) return;
|
||||||
SlObjectLoadFiltered(&_cheats, slt);
|
SlObjectLoadFiltered(&_cheats, slt);
|
||||||
@@ -114,7 +114,7 @@ static void Load_CHTS()
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
size_t count = SlGetFieldLength();
|
size_t count = SlGetFieldLength();
|
||||||
std::vector<SaveLoad> slt = SlTableHeaderOrRiff(GetCheatsDesc(false));
|
SaveLoadTableData slt = SlTableHeaderOrRiff(GetCheatsDesc(false));
|
||||||
|
|
||||||
/* Cheats were added over the years without a savegame bump. They are
|
/* 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
|
* stored as 2 SLE_BOOLs per entry. "count" indicates how many SLE_BOOLs
|
||||||
|
@@ -85,7 +85,7 @@ static void Load_DBGD()
|
|||||||
NSLT("config", SLEG_SSTR(_loadgame_DBGC_data, SLE_STR | SLF_ALLOW_CONTROL | SLF_ALLOW_NEWLINE)),
|
NSLT("config", SLEG_SSTR(_loadgame_DBGC_data, SLE_STR | SLF_ALLOW_CONTROL | SLF_ALLOW_NEWLINE)),
|
||||||
NSLT("log", SLEG_SSTR(_loadgame_DBGL_data, SLE_STR | SLF_ALLOW_CONTROL | SLF_ALLOW_NEWLINE)),
|
NSLT("log", SLEG_SSTR(_loadgame_DBGL_data, SLE_STR | SLF_ALLOW_CONTROL | SLF_ALLOW_NEWLINE)),
|
||||||
};
|
};
|
||||||
SlLoadTableOrRiffFiltered(nsl);
|
SlLoadTableObjectChunk(nsl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Check_DBGD()
|
static void Check_DBGD()
|
||||||
@@ -99,7 +99,7 @@ static void Check_DBGD()
|
|||||||
NSLT("config", SLEG_SSTR(_load_check_data.debug_config_data, SLE_STR | SLF_ALLOW_CONTROL | SLF_ALLOW_NEWLINE)),
|
NSLT("config", SLEG_SSTR(_load_check_data.debug_config_data, SLE_STR | SLF_ALLOW_CONTROL | SLF_ALLOW_NEWLINE)),
|
||||||
NSLT("log", SLEG_SSTR(_load_check_data.debug_log_data, SLE_STR | SLF_ALLOW_CONTROL | SLF_ALLOW_NEWLINE)),
|
NSLT("log", SLEG_SSTR(_load_check_data.debug_log_data, SLE_STR | SLF_ALLOW_CONTROL | SLF_ALLOW_NEWLINE)),
|
||||||
};
|
};
|
||||||
SlLoadTableOrRiffFiltered(nsl);
|
SlLoadTableObjectChunk(nsl);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const ChunkHandler debug_chunk_handlers[] = {
|
extern const ChunkHandler debug_chunk_handlers[] = {
|
||||||
|
@@ -167,7 +167,7 @@ static const NamedSaveLoad _industrytype_builder_desc[] = {
|
|||||||
/** Save industry-type build data. */
|
/** Save industry-type build data. */
|
||||||
static void Save_ITBL()
|
static void Save_ITBL()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> sld = SlTableHeader(_industrytype_builder_desc);
|
SaveLoadTableData sld = SlTableHeader(_industrytype_builder_desc);
|
||||||
|
|
||||||
for (int i = 0; i < NUM_INDUSTRYTYPES; i++) {
|
for (int i = 0; i < NUM_INDUSTRYTYPES; i++) {
|
||||||
SlSetArrayIndex(i);
|
SlSetArrayIndex(i);
|
||||||
@@ -178,7 +178,7 @@ static void Save_ITBL()
|
|||||||
/** Load industry-type build data. */
|
/** Load industry-type build data. */
|
||||||
static void Load_ITBL()
|
static void Load_ITBL()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> sld = SlTableHeaderOrRiff(_industrytype_builder_desc);
|
SaveLoadTableData sld = SlTableHeaderOrRiff(_industrytype_builder_desc);
|
||||||
|
|
||||||
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
|
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
|
||||||
_industry_builder.builddata[it].Reset();
|
_industry_builder.builddata[it].Reset();
|
||||||
|
@@ -36,7 +36,7 @@ static const NamedSaveLoad _newgrf_mapping_desc_new[] = {
|
|||||||
*/
|
*/
|
||||||
void Save_NewGRFMapping(const OverrideManagerBase &mapping)
|
void Save_NewGRFMapping(const OverrideManagerBase &mapping)
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> sld = SlTableHeader(_newgrf_mapping_desc_new);
|
SaveLoadTableData sld = SlTableHeader(_newgrf_mapping_desc_new);
|
||||||
|
|
||||||
for (uint i = 0; i < mapping.GetMaxMapping(); i++) {
|
for (uint i = 0; i < mapping.GetMaxMapping(); i++) {
|
||||||
if (mapping.mappings[i].grfid == 0 &&
|
if (mapping.mappings[i].grfid == 0 &&
|
||||||
@@ -60,7 +60,7 @@ void Load_NewGRFMapping(OverrideManagerBase &mapping)
|
|||||||
uint max_id = mapping.GetMaxMapping();
|
uint max_id = mapping.GetMaxMapping();
|
||||||
|
|
||||||
SaveLoadTable slt;
|
SaveLoadTable slt;
|
||||||
std::vector<SaveLoad> sld;
|
SaveLoadTableData sld;
|
||||||
|
|
||||||
if (SlXvIsFeaturePresent(XSLFI_NEWGRF_ENTITY_EXTRA) || SlIsTableChunk()) {
|
if (SlXvIsFeaturePresent(XSLFI_NEWGRF_ENTITY_EXTRA) || SlIsTableChunk()) {
|
||||||
sld = SlTableHeaderOrRiff(_newgrf_mapping_desc_new);
|
sld = SlTableHeaderOrRiff(_newgrf_mapping_desc_new);
|
||||||
@@ -91,7 +91,7 @@ static const NamedSaveLoad _grfconfig_desc[] = {
|
|||||||
|
|
||||||
static void Save_NGRF()
|
static void Save_NGRF()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> sld = SlTableHeader(_grfconfig_desc);
|
SaveLoadTableData sld = SlTableHeader(_grfconfig_desc);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
|
for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
|
||||||
@@ -108,7 +108,7 @@ static void Load_NGRF_common(GRFConfig *&grfconfig)
|
|||||||
if (SlXvIsFeaturePresent(XSLFI_TABLE_NEWGRF_SL, 1, 1)) {
|
if (SlXvIsFeaturePresent(XSLFI_TABLE_NEWGRF_SL, 1, 1)) {
|
||||||
SlLoadTableWithArrayLengthPrefixesMissing();
|
SlLoadTableWithArrayLengthPrefixesMissing();
|
||||||
}
|
}
|
||||||
std::vector<SaveLoad> sld = SlTableHeaderOrRiff(_grfconfig_desc);
|
SaveLoadTableData sld = SlTableHeaderOrRiff(_grfconfig_desc);
|
||||||
ClearGRFConfigList(&grfconfig);
|
ClearGRFConfigList(&grfconfig);
|
||||||
while (SlIterateArray() != -1) {
|
while (SlIterateArray() != -1) {
|
||||||
GRFConfig *c = new GRFConfig();
|
GRFConfig *c = new GRFConfig();
|
||||||
|
@@ -21,7 +21,7 @@ static const NamedSaveLoad _new_signal_style_mapping_desc[] = {
|
|||||||
|
|
||||||
static void Save_NSID()
|
static void Save_NSID()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(_new_signal_style_mapping_desc);
|
SaveLoadTableData slt = SlTableHeader(_new_signal_style_mapping_desc);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (NewSignalStyleMapping &it : _new_signal_style_mapping) {
|
for (NewSignalStyleMapping &it : _new_signal_style_mapping) {
|
||||||
@@ -35,7 +35,7 @@ static void Load_NSID()
|
|||||||
_new_signal_style_mapping.fill({});
|
_new_signal_style_mapping.fill({});
|
||||||
|
|
||||||
if (SlIsTableChunk()) {
|
if (SlIsTableChunk()) {
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(_new_signal_style_mapping_desc);
|
SaveLoadTableData slt = SlTableHeader(_new_signal_style_mapping_desc);
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
|
@@ -230,6 +230,19 @@ size_t MemoryDumper::GetSize() const
|
|||||||
return this->completed_block_bytes + (this->bufe ? (MEMORY_CHUNK_SIZE - (this->bufe - this->buf)) : 0);
|
return this->completed_block_bytes + (this->bufe ? (MEMORY_CHUNK_SIZE - (this->bufe - this->buf)) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size of the memory dump made so far.
|
||||||
|
* @return The size.
|
||||||
|
*/
|
||||||
|
size_t MemoryDumper::GetWriteOffsetGeneric() const
|
||||||
|
{
|
||||||
|
if (this->saved_buf != nullptr) {
|
||||||
|
return this->buf - this->autolen_buf;
|
||||||
|
} else {
|
||||||
|
return this->GetSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum SaveLoadBlockFlags {
|
enum SaveLoadBlockFlags {
|
||||||
SLBF_TABLE_ARRAY_LENGTH_PREFIX_MISSING, ///< Table chunk arrays were incorrectly saved without the length prefix, skip reading the length prefix on load
|
SLBF_TABLE_ARRAY_LENGTH_PREFIX_MISSING, ///< Table chunk arrays were incorrectly saved without the length prefix, skip reading the length prefix on load
|
||||||
};
|
};
|
||||||
@@ -1886,6 +1899,11 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld)
|
|||||||
case SL_WRITEBYTE: return 1; // a uint8_t is logically of size 1
|
case SL_WRITEBYTE: return 1; // a uint8_t is logically of size 1
|
||||||
case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
|
case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
|
||||||
case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
|
case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
|
||||||
|
|
||||||
|
case SL_STRUCT:
|
||||||
|
case SL_STRUCTLIST:
|
||||||
|
NOT_REACHED(); // SlAutolength or similar should be used for sub-structs
|
||||||
|
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1906,6 +1924,8 @@ static void SlFilterObjectMember(const SaveLoad &sld, std::vector<SaveLoad> &sav
|
|||||||
case SL_RING:
|
case SL_RING:
|
||||||
case SL_STDSTR:
|
case SL_STDSTR:
|
||||||
case SL_VARVEC:
|
case SL_VARVEC:
|
||||||
|
case SL_STRUCT:
|
||||||
|
case SL_STRUCTLIST:
|
||||||
/* CONDITIONAL saveload types depend on the savegame version */
|
/* CONDITIONAL saveload types depend on the savegame version */
|
||||||
if (!SlIsObjectValidInSavegame(sld)) return;
|
if (!SlIsObjectValidInSavegame(sld)) return;
|
||||||
|
|
||||||
@@ -1921,6 +1941,8 @@ static void SlFilterObjectMember(const SaveLoad &sld, std::vector<SaveLoad> &sav
|
|||||||
case SL_REFLIST:
|
case SL_REFLIST:
|
||||||
case SL_PTRRING:
|
case SL_PTRRING:
|
||||||
case SL_VEC:
|
case SL_VEC:
|
||||||
|
case SL_STRUCT:
|
||||||
|
case SL_STRUCTLIST:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* non-ptr types do not require SLA_PTRS or SLA_NULL actions */
|
/* non-ptr types do not require SLA_PTRS or SLA_NULL actions */
|
||||||
@@ -2032,6 +2054,51 @@ bool SlObjectMemberGeneric(void *object, const SaveLoad &sld)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SL_STRUCT:
|
||||||
|
case SL_STRUCTLIST:
|
||||||
|
switch (action) {
|
||||||
|
case SLA_SAVE: {
|
||||||
|
if (sld.cmd == SL_STRUCT) {
|
||||||
|
/* Number of structs written in the savegame: write a value of 1, change to zero later if nothing after this was written */
|
||||||
|
_sl.dumper->WriteByte(1);
|
||||||
|
size_t offset = _sl.dumper->GetWriteOffsetGeneric();
|
||||||
|
sld.struct_handler->Save(object);
|
||||||
|
if (offset == _sl.dumper->GetWriteOffsetGeneric()) {
|
||||||
|
/* Nothing was actaully written, so it's safe to change the 1 above to 0 */
|
||||||
|
_sl.dumper->UnWriteByte(); // This is fine iff nothing has been written since the WriteByte(1)
|
||||||
|
_sl.dumper->RawWriteByte(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sld.struct_handler->Save(object);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SLA_LOAD_CHECK: {
|
||||||
|
if (sld.cmd == SL_STRUCT && SlIsTableChunk()) {
|
||||||
|
if (SlGetStructListLength(1) == 0) break;
|
||||||
|
}
|
||||||
|
sld.struct_handler->LoadCheck(object);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SLA_LOAD: {
|
||||||
|
if (sld.cmd == SL_STRUCT && SlIsTableChunk()) {
|
||||||
|
if (SlGetStructListLength(1) == 0) break;
|
||||||
|
}
|
||||||
|
sld.struct_handler->Load(object);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SLA_PTRS:
|
||||||
|
sld.struct_handler->FixPointers(object);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SLA_NULL: break;
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
/* SL_WRITEBYTE writes a value to the savegame to identify the type of an object.
|
/* 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
|
* When loading, the value is read explicitly with SlReadByte() to determine which
|
||||||
* object description to use. */
|
* object description to use. */
|
||||||
@@ -2141,34 +2208,18 @@ bool SlIsTableChunk()
|
|||||||
|
|
||||||
void SlSkipTableHeader()
|
void SlSkipTableHeader()
|
||||||
{
|
{
|
||||||
|
uint sub_tables = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
uint8_t type = SlReadByte();
|
uint8_t type = SlReadByte();
|
||||||
if (type == SLE_FILE_END) break;
|
if (type == SLE_FILE_END) break;
|
||||||
|
|
||||||
|
if ((type & SLE_FILE_TYPE_MASK) == SLE_FILE_STRUCT) sub_tables++;
|
||||||
|
|
||||||
SlString(nullptr, 0, SLE_FILE_STRING | SLE_VAR_NULL);
|
SlString(nullptr, 0, SLE_FILE_STRING | SLE_VAR_NULL);
|
||||||
}
|
}
|
||||||
}
|
for (uint i = 0; i < sub_tables; i++) {
|
||||||
|
SlSkipTableHeader();
|
||||||
/**
|
|
||||||
* Calculate the size of the table header.
|
|
||||||
* @param slt The SaveLoad table with objects to save/load.
|
|
||||||
* @return size of given object.
|
|
||||||
*/
|
|
||||||
static size_t SlCalcTableHeader(const NamedSaveLoadTable &slt)
|
|
||||||
{
|
|
||||||
size_t length = 0;
|
|
||||||
|
|
||||||
for (auto &nsld : slt) {
|
|
||||||
if (StrEmpty(nsld.name) || !SlIsObjectValidInSavegame(nsld.save_load)) continue;
|
|
||||||
|
|
||||||
length += 1 + SlCalcStringLen(&nsld.name, 0, SLE_STR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
length++; // End-of-list entry.
|
|
||||||
|
|
||||||
/* SL_STRUCTLIST, SL_STRUCT not currently implemented */
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2198,22 +2249,55 @@ static uint8_t GetSavegameTableFileType(const SaveLoad &sld)
|
|||||||
case SL_WRITEBYTE:
|
case SL_WRITEBYTE:
|
||||||
return SLE_FILE_U8;
|
return SLE_FILE_U8;
|
||||||
|
|
||||||
|
case SL_STRUCT:
|
||||||
|
case SL_STRUCTLIST:
|
||||||
|
return SLE_FILE_STRUCT | SLE_FILE_HAS_LENGTH_FIELD;
|
||||||
|
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler that is assigned when there is a struct read in the savegame which
|
||||||
|
* is not known to the code. This means we are going to skip it.
|
||||||
|
*/
|
||||||
|
class SaveLoadSkipStructHandler : public SaveLoadStructHandler {
|
||||||
|
void Save(void *) const override
|
||||||
|
{
|
||||||
|
NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load(void *object) const override
|
||||||
|
{
|
||||||
|
size_t length = SlGetStructListLength(UINT32_MAX);
|
||||||
|
for (; length > 0; length--) {
|
||||||
|
SlObjectLoadFiltered(object, this->GetLoadDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadCheck(void *object) const override
|
||||||
|
{
|
||||||
|
this->Load(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedSaveLoadTable GetDescription() const override
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save or Load a table header.
|
* Save or Load a table header.
|
||||||
* @note a table-header can never contain more than 65535 fields.
|
* @note a table-header can never contain more than 65535 fields.
|
||||||
* @param slt The NamedSaveLoad table with objects to save/load.
|
* @param slt The NamedSaveLoad table with objects to save/load.
|
||||||
* @return The ordered SaveLoad array to use.
|
* @return The ordered SaveLoad array to use.
|
||||||
*/
|
*/
|
||||||
std::vector<SaveLoad> SlTableHeader(const NamedSaveLoadTable &slt, TableHeaderSpecialHandler *special_handler)
|
SaveLoadTableData SlTableHeader(const NamedSaveLoadTable &slt, TableHeaderSpecialHandler *special_handler)
|
||||||
{
|
{
|
||||||
/* You can only use SlTableHeader if you are a CH_TABLE. */
|
/* You can only use SlTableHeader if you are a CH_TABLE. */
|
||||||
assert(_sl.block_mode == CH_TABLE || _sl.block_mode == CH_SPARSE_TABLE);
|
assert(_sl.block_mode == CH_TABLE || _sl.block_mode == CH_SPARSE_TABLE);
|
||||||
|
|
||||||
std::vector<SaveLoad> saveloads;
|
SaveLoadTableData saveloads;
|
||||||
|
|
||||||
switch (_sl.action) {
|
switch (_sl.action) {
|
||||||
case SLA_LOAD_CHECK:
|
case SLA_LOAD_CHECK:
|
||||||
@@ -2261,15 +2345,20 @@ std::vector<SaveLoad> SlTableHeader(const NamedSaveLoadTable &slt, TableHeaderSp
|
|||||||
DEBUG(sl, _sl.action == SLA_LOAD ? 2 : 6, "Field '%s' of type 0x%02X not found, skipping", key.c_str(), type);
|
DEBUG(sl, _sl.action == SLA_LOAD ? 2 : 6, "Field '%s' of type 0x%02X not found, skipping", key.c_str(), type);
|
||||||
|
|
||||||
SaveLoadType saveload_type;
|
SaveLoadType saveload_type;
|
||||||
|
SaveLoadStructHandler *struct_handler = nullptr;
|
||||||
switch (type & SLE_FILE_TYPE_MASK) {
|
switch (type & SLE_FILE_TYPE_MASK) {
|
||||||
case SLE_FILE_STRING:
|
case SLE_FILE_STRING:
|
||||||
/* Strings are always marked with SLE_FILE_HAS_LENGTH_FIELD, as they are a list of chars. */
|
/* Strings are always marked with SLE_FILE_HAS_LENGTH_FIELD, as they are a list of chars. */
|
||||||
saveload_type = SL_STDSTR;
|
saveload_type = SL_STDSTR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SLE_FILE_STRUCT:
|
case SLE_FILE_STRUCT: {
|
||||||
SlErrorCorrupt("SLE_FILE_STRUCT not supported yet");
|
saveload_type = SL_STRUCTLIST;
|
||||||
|
auto handler = std::make_unique<SaveLoadSkipStructHandler>();
|
||||||
|
struct_handler = handler.get();
|
||||||
|
saveloads.struct_handlers.push_back(std::move(handler));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
saveload_type = (type & SLE_FILE_HAS_LENGTH_FIELD) ? SL_ARR : SL_VAR;
|
saveload_type = (type & SLE_FILE_HAS_LENGTH_FIELD) ? SL_ARR : SL_VAR;
|
||||||
@@ -2277,7 +2366,7 @@ std::vector<SaveLoad> SlTableHeader(const NamedSaveLoadTable &slt, TableHeaderSp
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We don't know this field, so read to nothing. */
|
/* We don't know this field, so read to nothing. */
|
||||||
saveloads.push_back({ true, saveload_type, ((VarType)type & SLE_FILE_TYPE_MASK) | SLE_VAR_NULL, 1, SL_MIN_VERSION, SL_MAX_VERSION, SLTAG_TABLE_UNKNOWN, nullptr, SlXvFeatureTest() });
|
saveloads.push_back({ true, saveload_type, ((VarType)type & SLE_FILE_TYPE_MASK) | SLE_VAR_NULL, 1, SL_MIN_VERSION, SL_MAX_VERSION, SLTAG_TABLE_UNKNOWN, nullptr, SlXvFeatureTest(), struct_handler });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2292,17 +2381,28 @@ std::vector<SaveLoad> SlTableHeader(const NamedSaveLoadTable &slt, TableHeaderSp
|
|||||||
SlErrorCorrupt("Field type is different than expected");
|
SlErrorCorrupt("Field type is different than expected");
|
||||||
}
|
}
|
||||||
saveloads.push_back(*sld_it->save_load);
|
saveloads.push_back(*sld_it->save_load);
|
||||||
|
|
||||||
|
if ((type & SLE_FILE_TYPE_MASK) == SLE_FILE_STRUCT) {
|
||||||
|
std::unique_ptr<SaveLoadStructHandler> handler = saveloads.back().struct_handler_factory();
|
||||||
|
saveloads.back().struct_handler = handler.get();
|
||||||
|
saveloads.struct_handlers.push_back(std::move(handler));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SL_STRUCTLIST, SL_STRUCT not currently implemented */
|
for (auto &sld : saveloads) {
|
||||||
|
if (sld.cmd == SL_STRUCTLIST || sld.cmd == SL_STRUCT) {
|
||||||
|
sld.struct_handler->table_data = SlTableHeader(sld.struct_handler->GetDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SLA_SAVE: {
|
case SLA_SAVE: {
|
||||||
/* Automatically calculate the length? */
|
const NeedLength orig_need_length = _sl.need_length;
|
||||||
if (_sl.need_length != NL_NONE) {
|
if (orig_need_length != NL_NONE) {
|
||||||
SlSetLength(SlCalcTableHeader(slt));
|
_sl.need_length = NL_NONE;
|
||||||
|
_sl.dumper->StartAutoLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &nsld : slt) {
|
for (auto &nsld : slt) {
|
||||||
@@ -2319,7 +2419,21 @@ std::vector<SaveLoad> SlTableHeader(const NamedSaveLoadTable &slt, TableHeaderSp
|
|||||||
/* Add an end-of-header marker. */
|
/* Add an end-of-header marker. */
|
||||||
SlWriteByte(SLE_FILE_END);
|
SlWriteByte(SLE_FILE_END);
|
||||||
|
|
||||||
/* SL_STRUCTLIST, SL_STRUCT not currently implemented */
|
for (auto &sld : saveloads) {
|
||||||
|
if (sld.cmd == SL_STRUCTLIST || sld.cmd == SL_STRUCT) {
|
||||||
|
std::unique_ptr<SaveLoadStructHandler> handler = sld.struct_handler_factory();
|
||||||
|
sld.struct_handler = handler.get();
|
||||||
|
sld.struct_handler->table_data = SlTableHeader(sld.struct_handler->GetDescription());
|
||||||
|
saveloads.struct_handlers.push_back(std::move(handler));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orig_need_length != NL_NONE) {
|
||||||
|
auto result = _sl.dumper->StopAutoLength();
|
||||||
|
_sl.need_length = orig_need_length;
|
||||||
|
SlSetLength(result.size());
|
||||||
|
_sl.dumper->CopyBytes(result);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2330,11 +2444,11 @@ std::vector<SaveLoad> SlTableHeader(const NamedSaveLoadTable &slt, TableHeaderSp
|
|||||||
return saveloads;
|
return saveloads;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SaveLoad> SlTableHeaderOrRiff(const NamedSaveLoadTable &slt)
|
SaveLoadTableData SlTableHeaderOrRiff(const NamedSaveLoadTable &slt)
|
||||||
{
|
{
|
||||||
if (SlIsTableChunk()) return SlTableHeader(slt);
|
if (SlIsTableChunk()) return SlTableHeader(slt);
|
||||||
|
|
||||||
std::vector<SaveLoad> saveloads;
|
SaveLoadTableData saveloads;
|
||||||
for (auto &nsld : slt) {
|
for (auto &nsld : slt) {
|
||||||
if ((nsld.nsl_flags & NSLF_TABLE_ONLY) != 0) continue;
|
if ((nsld.nsl_flags & NSLF_TABLE_ONLY) != 0) continue;
|
||||||
SlFilterObjectMember(nsld.save_load, saveloads);
|
SlFilterObjectMember(nsld.save_load, saveloads);
|
||||||
@@ -2363,6 +2477,28 @@ void SlLoadTableWithArrayLengthPrefixesMissing()
|
|||||||
SetBit(_sl.block_flags, SLBF_TABLE_ARRAY_LENGTH_PREFIX_MISSING);
|
SetBit(_sl.block_flags, SLBF_TABLE_ARRAY_LENGTH_PREFIX_MISSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the length of this list.
|
||||||
|
* @param The length of the list.
|
||||||
|
*/
|
||||||
|
void SlSetStructListLength(size_t length)
|
||||||
|
{
|
||||||
|
SlWriteArrayLength(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the length of this list; if it exceeds the limit, error out.
|
||||||
|
* @param limit The maximum size the list can be.
|
||||||
|
* @return The length of the list.
|
||||||
|
*/
|
||||||
|
size_t SlGetStructListLength(size_t limit)
|
||||||
|
{
|
||||||
|
size_t length = SlReadArrayLength();
|
||||||
|
if (length > limit) SlErrorCorrupt("List exceeds storage size");
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
void SlSkipChunkContents()
|
void SlSkipChunkContents()
|
||||||
{
|
{
|
||||||
if (SlIsTableChunk()) SlSkipTableHeader();
|
if (SlIsTableChunk()) SlSkipTableHeader();
|
||||||
|
@@ -1092,12 +1092,15 @@ struct TableHeaderSpecialHandler {
|
|||||||
|
|
||||||
bool SlIsTableChunk();
|
bool SlIsTableChunk();
|
||||||
void SlSkipTableHeader();
|
void SlSkipTableHeader();
|
||||||
std::vector<SaveLoad> SlTableHeader(const NamedSaveLoadTable &slt, TableHeaderSpecialHandler *special_handler = nullptr);
|
SaveLoadTableData SlTableHeader(const NamedSaveLoadTable &slt, TableHeaderSpecialHandler *special_handler = nullptr);
|
||||||
std::vector<SaveLoad> SlTableHeaderOrRiff(const NamedSaveLoadTable &slt);
|
SaveLoadTableData SlTableHeaderOrRiff(const NamedSaveLoadTable &slt);
|
||||||
void SlSaveTableObjectChunk(const SaveLoadTable &slt);
|
void SlSaveTableObjectChunk(const SaveLoadTable &slt);
|
||||||
void SlLoadTableOrRiffFiltered(const SaveLoadTable &slt);
|
void SlLoadTableOrRiffFiltered(const SaveLoadTable &slt);
|
||||||
void SlLoadTableWithArrayLengthPrefixesMissing();
|
void SlLoadTableWithArrayLengthPrefixesMissing();
|
||||||
|
|
||||||
|
void SlSetStructListLength(size_t length);
|
||||||
|
size_t SlGetStructListLength(size_t limit);
|
||||||
|
|
||||||
void SlSkipChunkContents();
|
void SlSkipChunkContents();
|
||||||
|
|
||||||
inline void SlSaveTableObjectChunk(const NamedSaveLoadTable &slt)
|
inline void SlSaveTableObjectChunk(const NamedSaveLoadTable &slt)
|
||||||
@@ -1105,6 +1108,16 @@ inline void SlSaveTableObjectChunk(const NamedSaveLoadTable &slt)
|
|||||||
SlSaveTableObjectChunk(SlTableHeader(slt));
|
SlSaveTableObjectChunk(SlTableHeader(slt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void SlLoadTableObjectChunk(const NamedSaveLoadTable &slt)
|
||||||
|
{
|
||||||
|
SlLoadTableOrRiffFiltered(SlTableHeader(slt));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SlLoadTableObjectChunk(const SaveLoadTable &slt)
|
||||||
|
{
|
||||||
|
SlLoadTableOrRiffFiltered(slt);
|
||||||
|
}
|
||||||
|
|
||||||
inline void SlLoadTableOrRiffFiltered(const NamedSaveLoadTable &slt)
|
inline void SlLoadTableOrRiffFiltered(const NamedSaveLoadTable &slt)
|
||||||
{
|
{
|
||||||
SlLoadTableOrRiffFiltered(SlTableHeaderOrRiff(slt));
|
SlLoadTableOrRiffFiltered(SlTableHeaderOrRiff(slt));
|
||||||
|
@@ -256,6 +256,12 @@ struct MemoryDumper {
|
|||||||
this->CopyBytes(buffer.data(), buffer.size());
|
this->CopyBytes(buffer.data(), buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** For limited/special purposes only */
|
||||||
|
inline void UnWriteByte()
|
||||||
|
{
|
||||||
|
this->buf--;
|
||||||
|
}
|
||||||
|
|
||||||
inline void RawWriteByte(uint8_t b)
|
inline void RawWriteByte(uint8_t b)
|
||||||
{
|
{
|
||||||
*this->buf++ = b;
|
*this->buf++ = b;
|
||||||
@@ -331,6 +337,7 @@ struct MemoryDumper {
|
|||||||
|
|
||||||
void Flush(SaveFilter &writer);
|
void Flush(SaveFilter &writer);
|
||||||
size_t GetSize() const;
|
size_t GetSize() const;
|
||||||
|
size_t GetWriteOffsetGeneric() const;
|
||||||
void StartAutoLength();
|
void StartAutoLength();
|
||||||
std::span<uint8_t> StopAutoLength();
|
std::span<uint8_t> StopAutoLength();
|
||||||
bool IsAutoLengthActive() const { return this->saved_buf != nullptr; }
|
bool IsAutoLengthActive() const { return this->saved_buf != nullptr; }
|
||||||
|
@@ -104,25 +104,29 @@ typedef uint32_t VarType;
|
|||||||
/** Type of data saved. */
|
/** Type of data saved. */
|
||||||
enum SaveLoadTypes {
|
enum SaveLoadTypes {
|
||||||
SL_VAR = 0, ///< Save/load a variable.
|
SL_VAR = 0, ///< Save/load a variable.
|
||||||
SL_REF = 1, ///< Save/load a reference.
|
SL_REF, ///< Save/load a reference.
|
||||||
SL_ARR = 2, ///< Save/load a fixed-size array of #SL_VAR elements.
|
SL_ARR, ///< Save/load a fixed-size array of #SL_VAR elements.
|
||||||
SL_STR = 3, ///< Save/load a string.
|
SL_STR, ///< Save/load a string.
|
||||||
SL_REFLIST = 4, ///< Save/load a list of #SL_REF elements.
|
SL_REFLIST, ///< Save/load a list of #SL_REF elements.
|
||||||
SL_RING = 5, ///< Save/load a ring of #SL_VAR elements.
|
SL_RING, ///< Save/load a ring of #SL_VAR elements.
|
||||||
SL_VEC = 6, ///< Save/load a vector of #SL_REF elements.
|
SL_VEC, ///< Save/load a vector of #SL_REF elements.
|
||||||
SL_STDSTR = 7, ///< Save/load a std::string.
|
SL_STDSTR, ///< Save/load a std::string.
|
||||||
|
SL_PTRRING, ///< Save/load a ring of #SL_REF elements.
|
||||||
|
SL_VARVEC, ///< Save/load a primitive type vector.
|
||||||
|
|
||||||
|
SL_STRUCT, ///< Save/load a struct.
|
||||||
|
SL_STRUCTLIST, ///< Save/load a list of structs.
|
||||||
|
|
||||||
/* non-normal save-load types */
|
/* non-normal save-load types */
|
||||||
SL_WRITEBYTE = 8,
|
SL_WRITEBYTE,
|
||||||
SL_VEH_INCLUDE = 9,
|
SL_VEH_INCLUDE,
|
||||||
SL_ST_INCLUDE = 10,
|
SL_ST_INCLUDE,
|
||||||
|
|
||||||
SL_PTRRING = 13, ///< Save/load a ring of #SL_REF elements.
|
|
||||||
SL_VARVEC = 14, ///< Save/load a primitive type vector.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint8_t SaveLoadType; ///< Save/load type. @see SaveLoadTypes
|
typedef uint8_t SaveLoadType; ///< Save/load type. @see SaveLoadTypes
|
||||||
|
|
||||||
|
using SaveLoadStructHandlerFactory = std::unique_ptr<struct SaveLoadStructHandler> (*)();
|
||||||
|
|
||||||
/** SaveLoad type struct. Do NOT use this directly but use the SLE_ macros defined just below! */
|
/** SaveLoad type struct. Do NOT use this directly but use the SLE_ macros defined just below! */
|
||||||
struct SaveLoad {
|
struct SaveLoad {
|
||||||
bool global; ///< should we load a global variable or a non-global one
|
bool global; ///< should we load a global variable or a non-global one
|
||||||
@@ -132,12 +136,18 @@ struct SaveLoad {
|
|||||||
SaveLoadVersion version_from; ///< save/load the variable starting from this savegame version
|
SaveLoadVersion version_from; ///< save/load the variable starting from this savegame version
|
||||||
SaveLoadVersion version_to; ///< save/load the variable until this savegame version
|
SaveLoadVersion version_to; ///< save/load the variable until this savegame version
|
||||||
uint16_t label_tag; ///< for labelling purposes
|
uint16_t label_tag; ///< for labelling purposes
|
||||||
|
|
||||||
|
union {
|
||||||
/* NOTE: This element either denotes the address of the variable for a global
|
/* NOTE: This element either denotes the address of the variable for a global
|
||||||
* variable, or the offset within a struct which is then bound to a variable
|
* variable, or the offset within a struct which is then bound to a variable
|
||||||
* during runtime. Decision on which one to use is controlled by the function
|
* during runtime. Decision on which one to use is controlled by the function
|
||||||
* that is called to save it. address: global=true, offset: global=false */
|
* that is called to save it. address: global=true, offset: global=false */
|
||||||
void *address; ///< address of variable OR offset of variable in the struct (max offset is 65536)
|
void *address; ///< address of variable OR offset of variable in the struct (max offset is 65536)
|
||||||
|
SaveLoadStructHandlerFactory struct_handler_factory; ///< factory function pointer for SaveLoadStructHandler
|
||||||
|
};
|
||||||
|
|
||||||
SlXvFeatureTest ext_feature_test; ///< extended feature test
|
SlXvFeatureTest ext_feature_test; ///< extended feature test
|
||||||
|
SaveLoadStructHandler *struct_handler = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr SaveLoad SLTAG(uint16_t label_tag, SaveLoad save_load)
|
inline constexpr SaveLoad SLTAG(uint16_t label_tag, SaveLoad save_load)
|
||||||
@@ -175,4 +185,95 @@ inline constexpr NamedSaveLoad NSLT(const char *name, SaveLoad save_load)
|
|||||||
return { name, save_load, NSLF_TABLE_ONLY };
|
return { name, save_load, NSLF_TABLE_ONLY };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline constexpr NamedSaveLoad NSLT_STRUCT(const char *name, SaveLoadStructHandlerFactory factory, SaveLoadVersion from = SL_MIN_VERSION, SaveLoadVersion to = SL_MAX_VERSION, SlXvFeatureTest extver = {})
|
||||||
|
{
|
||||||
|
return { name, SaveLoad { true, SL_STRUCT, SLE_FILE_STRUCT, 0, from, to, SLTAG_DEFAULT, { .struct_handler_factory = factory }, extver }, NSLF_TABLE_ONLY };
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr NamedSaveLoad NSLT_STRUCT(const char *name, SaveLoadVersion from = SL_MIN_VERSION, SaveLoadVersion to = SL_MAX_VERSION, SlXvFeatureTest extver = {})
|
||||||
|
{
|
||||||
|
SaveLoadStructHandlerFactory factory = []() -> std::unique_ptr<struct SaveLoadStructHandler> {
|
||||||
|
return std::make_unique<T>();
|
||||||
|
};
|
||||||
|
return NSLT_STRUCT(name, factory, from, to, extver);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr NamedSaveLoad NSLT_STRUCTLIST(const char *name, SaveLoadStructHandlerFactory factory, SaveLoadVersion from = SL_MIN_VERSION, SaveLoadVersion to = SL_MAX_VERSION, SlXvFeatureTest extver = {})
|
||||||
|
{
|
||||||
|
return { name, SaveLoad { true, SL_STRUCTLIST, SLE_FILE_STRUCT, 0, from, to, SLTAG_DEFAULT, { .struct_handler_factory = factory }, extver }, NSLF_TABLE_ONLY };
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr NamedSaveLoad NSLT_STRUCTLIST(const char *name, SaveLoadVersion from = SL_MIN_VERSION, SaveLoadVersion to = SL_MAX_VERSION, SlXvFeatureTest extver = {})
|
||||||
|
{
|
||||||
|
SaveLoadStructHandlerFactory factory = []() -> std::unique_ptr<struct SaveLoadStructHandler> {
|
||||||
|
return std::make_unique<T>();
|
||||||
|
};
|
||||||
|
return NSLT_STRUCTLIST(name, factory, from, to, extver);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SaveLoadTableData : public std::vector<SaveLoad> {
|
||||||
|
std::vector<std::unique_ptr<struct SaveLoadStructHandler>> struct_handlers;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Handler for saving/loading a SL_STRUCT/SL_STRUCTLIST. */
|
||||||
|
class SaveLoadStructHandler {
|
||||||
|
public:
|
||||||
|
SaveLoadTableData table_data;
|
||||||
|
|
||||||
|
virtual ~SaveLoadStructHandler() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the (static) description of the fields in the savegame.
|
||||||
|
*/
|
||||||
|
virtual NamedSaveLoadTable GetDescription() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the (current) description of the fields in the savegame.
|
||||||
|
*/
|
||||||
|
SaveLoadTable GetLoadDescription() const { return this->table_data; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the object to disk.
|
||||||
|
* @param object The object to store.
|
||||||
|
*/
|
||||||
|
virtual void Save([[maybe_unused]] void *object) const {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the object from disk.
|
||||||
|
* @param object The object to load.
|
||||||
|
*/
|
||||||
|
virtual void Load([[maybe_unused]] void *object) const {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to load, but used only to validate savegames.
|
||||||
|
* @param object The object to load.
|
||||||
|
*/
|
||||||
|
virtual void LoadCheck([[maybe_unused]] void *object) const {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A post-load callback to fix #SL_REF integers into pointers.
|
||||||
|
* @param object The object to fix.
|
||||||
|
*/
|
||||||
|
virtual void FixPointers([[maybe_unused]] void *object) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class TImpl, class TObject>
|
||||||
|
class TypedSaveLoadStructHandler : public SaveLoadStructHandler {
|
||||||
|
public:
|
||||||
|
void Save([[maybe_unused]] TObject *object) const {}
|
||||||
|
void Save(void *object) const override { static_cast<const TImpl *>(this)->Save(static_cast<TObject *>(object)); }
|
||||||
|
|
||||||
|
void Load([[maybe_unused]] TObject *object) const {}
|
||||||
|
void Load(void *object) const override { static_cast<const TImpl *>(this)->Load(static_cast<TObject *>(object)); }
|
||||||
|
|
||||||
|
void LoadCheck([[maybe_unused]] TObject *object) const {}
|
||||||
|
void LoadCheck(void *object) const override { static_cast<const TImpl *>(this)->LoadCheck(static_cast<TObject *>(object)); }
|
||||||
|
|
||||||
|
void FixPointers([[maybe_unused]] TObject *object) const {}
|
||||||
|
void FixPointers(void *object) const override { static_cast<const TImpl *>(this)->FixPointers(static_cast<TObject *>(object)); }
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* SL_SAVELOAD_TYPES_H */
|
#endif /* SL_SAVELOAD_TYPES_H */
|
||||||
|
@@ -23,7 +23,7 @@ static const NamedSaveLoad _trace_restrict_mapping_desc[] = {
|
|||||||
*/
|
*/
|
||||||
static void Load_TRRM()
|
static void Load_TRRM()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeaderOrRiff(_trace_restrict_mapping_desc);
|
SaveLoadTableData slt = SlTableHeaderOrRiff(_trace_restrict_mapping_desc);
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
@@ -37,7 +37,7 @@ static void Load_TRRM()
|
|||||||
*/
|
*/
|
||||||
static void Save_TRRM()
|
static void Save_TRRM()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(_trace_restrict_mapping_desc);
|
SaveLoadTableData slt = SlTableHeader(_trace_restrict_mapping_desc);
|
||||||
|
|
||||||
for (TraceRestrictMapping::iterator iter = _tracerestrictprogram_mapping.begin();
|
for (TraceRestrictMapping::iterator iter = _tracerestrictprogram_mapping.begin();
|
||||||
iter != _tracerestrictprogram_mapping.end(); ++iter) {
|
iter != _tracerestrictprogram_mapping.end(); ++iter) {
|
||||||
@@ -55,7 +55,7 @@ static const NamedSaveLoad _trace_restrict_program_desc[] = {
|
|||||||
*/
|
*/
|
||||||
static void Load_TRRP()
|
static void Load_TRRP()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeaderOrRiff(_trace_restrict_program_desc);
|
SaveLoadTableData slt = SlTableHeaderOrRiff(_trace_restrict_program_desc);
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
@@ -111,7 +111,7 @@ static void Load_TRRP()
|
|||||||
*/
|
*/
|
||||||
static void Save_TRRP()
|
static void Save_TRRP()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(_trace_restrict_program_desc);
|
SaveLoadTableData slt = SlTableHeader(_trace_restrict_program_desc);
|
||||||
|
|
||||||
for (TraceRestrictProgram *prog : TraceRestrictProgram::Iterate()) {
|
for (TraceRestrictProgram *prog : TraceRestrictProgram::Iterate()) {
|
||||||
SlSetArrayIndex(prog->index);
|
SlSetArrayIndex(prog->index);
|
||||||
@@ -132,7 +132,7 @@ static const NamedSaveLoad _trace_restrict_slot_desc[] = {
|
|||||||
*/
|
*/
|
||||||
static void Load_TRRS()
|
static void Load_TRRS()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeaderOrRiff(_trace_restrict_slot_desc);
|
SaveLoadTableData slt = SlTableHeaderOrRiff(_trace_restrict_slot_desc);
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
@@ -147,7 +147,7 @@ static void Load_TRRS()
|
|||||||
*/
|
*/
|
||||||
static void Save_TRRS()
|
static void Save_TRRS()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(_trace_restrict_slot_desc);
|
SaveLoadTableData slt = SlTableHeader(_trace_restrict_slot_desc);
|
||||||
|
|
||||||
for (TraceRestrictSlot *slot : TraceRestrictSlot::Iterate()) {
|
for (TraceRestrictSlot *slot : TraceRestrictSlot::Iterate()) {
|
||||||
SlSetArrayIndex(slot->index);
|
SlSetArrayIndex(slot->index);
|
||||||
@@ -166,7 +166,7 @@ static const NamedSaveLoad _trace_restrict_counter_desc[] = {
|
|||||||
*/
|
*/
|
||||||
static void Load_TRRC()
|
static void Load_TRRC()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeaderOrRiff(_trace_restrict_counter_desc);
|
SaveLoadTableData slt = SlTableHeaderOrRiff(_trace_restrict_counter_desc);
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
@@ -180,7 +180,7 @@ static void Load_TRRC()
|
|||||||
*/
|
*/
|
||||||
static void Save_TRRC()
|
static void Save_TRRC()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(_trace_restrict_counter_desc);
|
SaveLoadTableData slt = SlTableHeader(_trace_restrict_counter_desc);
|
||||||
|
|
||||||
for (TraceRestrictCounter *ctr : TraceRestrictCounter::Iterate()) {
|
for (TraceRestrictCounter *ctr : TraceRestrictCounter::Iterate()) {
|
||||||
SlSetArrayIndex(ctr->index);
|
SlSetArrayIndex(ctr->index);
|
||||||
|
@@ -25,7 +25,7 @@ static const NamedSaveLoad _train_speed_adaptation_map_desc[] = {
|
|||||||
static void Load_TSAS()
|
static void Load_TSAS()
|
||||||
{
|
{
|
||||||
const bool table_mode = SlIsTableChunk();
|
const bool table_mode = SlIsTableChunk();
|
||||||
std::vector<SaveLoad> slt = SlTableHeaderOrRiff(_train_speed_adaptation_map_desc);
|
SaveLoadTableData slt = SlTableHeaderOrRiff(_train_speed_adaptation_map_desc);
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
SignalSpeedType data;
|
SignalSpeedType data;
|
||||||
@@ -40,7 +40,7 @@ static void Load_TSAS()
|
|||||||
|
|
||||||
static void Save_TSAS()
|
static void Save_TSAS()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(_train_speed_adaptation_map_desc);
|
SaveLoadTableData slt = SlTableHeader(_train_speed_adaptation_map_desc);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (auto &it : _signal_speeds) {
|
for (auto &it : _signal_speeds) {
|
||||||
|
@@ -25,7 +25,7 @@ static const NamedSaveLoad _tunnel_desc[] = {
|
|||||||
|
|
||||||
static void Save_TUNN()
|
static void Save_TUNN()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeader(_tunnel_desc);
|
SaveLoadTableData slt = SlTableHeader(_tunnel_desc);
|
||||||
|
|
||||||
for (Tunnel *tunnel : Tunnel::Iterate()) {
|
for (Tunnel *tunnel : Tunnel::Iterate()) {
|
||||||
SlSetArrayIndex(tunnel->index);
|
SlSetArrayIndex(tunnel->index);
|
||||||
@@ -35,7 +35,7 @@ static void Save_TUNN()
|
|||||||
|
|
||||||
static void Load_TUNN()
|
static void Load_TUNN()
|
||||||
{
|
{
|
||||||
std::vector<SaveLoad> slt = SlTableHeaderOrRiff(_tunnel_desc);
|
SaveLoadTableData slt = SlTableHeaderOrRiff(_tunnel_desc);
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
|
Reference in New Issue
Block a user