Changeset - r25773:457e167f3c9e
src/order_backup.h
Show inline comments
 
@@ -36,7 +36,7 @@ static const uint32 MAKE_ORDER_BACKUP_FL
 
struct OrderBackup : OrderBackupPool::PoolItem<&_order_backup_pool>, BaseConsist {
 
private:
 
	friend SaveLoadTable GetOrderBackupDescription(); ///< Saving and loading of order backups.
 
	friend void Load_BKOR();   ///< Creating empty orders upon savegame loading.
 
	friend struct BKORChunkHandler; ///< Creating empty orders upon savegame loading.
 
	uint32 user;               ///< The user that requested the backup.
 
	TileIndex tile;            ///< Tile of the depot where the order was changed.
 
	GroupID group;             ///< The group the vehicle was part of.
src/order_base.h
Show inline comments
 
@@ -32,7 +32,7 @@ extern OrderListPool _orderlist_pool;
 
 */
 
struct Order : OrderPool::PoolItem<&_order_pool> {
 
private:
 
	friend void Load_VEHS();                                             ///< Loading of ancient vehicles.
 
	friend struct VEHSChunkHandler;                             ///< Loading of ancient vehicles.
 
	friend SaveLoadTable GetOrderDescription();                 ///< Saving and loading of orders.
 
	/* So we can use private/protected variables in the saveload code */
 
	friend class SlVehicleCommon;
src/saveload/ai_sl.cpp
Show inline comments
 
@@ -57,77 +57,81 @@ static void SaveReal_AIPL(int *index_ptr
 
	if (Company::IsValidAiID(index)) AI::Save(index);
 
}
 

	
 
static void Load_AIPL()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_ai_company_desc, _ai_company_sl_compat);
 

	
 
	/* Free all current data */
 
	for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
 
		AIConfig::GetConfig(c, AIConfig::SSS_FORCE_GAME)->Change(nullptr);
 
	}
 
struct AIPLChunkHandler : ChunkHandler {
 
	AIPLChunkHandler() : ChunkHandler('AIPL', CH_TABLE) {}
 

	
 
	CompanyID index;
 
	while ((index = (CompanyID)SlIterateArray()) != (CompanyID)-1) {
 
		if (index >= MAX_COMPANIES) SlErrorCorrupt("Too many AI configs");
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_ai_company_desc, _ai_company_sl_compat);
 

	
 
		_ai_saveload_is_random = false;
 
		_ai_saveload_version = -1;
 
		SlObject(nullptr, slt);
 

	
 
		if (_networking && !_network_server) {
 
			if (Company::IsValidAiID(index)) AIInstance::LoadEmpty();
 
			continue;
 
		/* Free all current data */
 
		for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
 
			AIConfig::GetConfig(c, AIConfig::SSS_FORCE_GAME)->Change(nullptr);
 
		}
 

	
 
		AIConfig *config = AIConfig::GetConfig(index, AIConfig::SSS_FORCE_GAME);
 
		if (_ai_saveload_name.empty()) {
 
			/* A random AI. */
 
			config->Change(nullptr, -1, false, true);
 
		} else {
 
			config->Change(_ai_saveload_name.c_str(), _ai_saveload_version, false, _ai_saveload_is_random);
 
			if (!config->HasScript()) {
 
				/* No version of the AI available that can load the data. Try to load the
 
				 * latest version of the AI instead. */
 
				config->Change(_ai_saveload_name.c_str(), -1, false, _ai_saveload_is_random);
 
		CompanyID index;
 
		while ((index = (CompanyID)SlIterateArray()) != (CompanyID)-1) {
 
			if (index >= MAX_COMPANIES) SlErrorCorrupt("Too many AI configs");
 

	
 
			_ai_saveload_is_random = false;
 
			_ai_saveload_version = -1;
 
			SlObject(nullptr, slt);
 

	
 
			if (_networking && !_network_server) {
 
				if (Company::IsValidAiID(index)) AIInstance::LoadEmpty();
 
				continue;
 
			}
 

	
 
			AIConfig *config = AIConfig::GetConfig(index, AIConfig::SSS_FORCE_GAME);
 
			if (_ai_saveload_name.empty()) {
 
				/* A random AI. */
 
				config->Change(nullptr, -1, false, true);
 
			} else {
 
				config->Change(_ai_saveload_name.c_str(), _ai_saveload_version, false, _ai_saveload_is_random);
 
				if (!config->HasScript()) {
 
					if (_ai_saveload_name.compare("%_dummy") != 0) {
 
					/* No version of the AI available that can load the data. Try to load the
 
					 * latest version of the AI instead. */
 
					config->Change(_ai_saveload_name.c_str(), -1, false, _ai_saveload_is_random);
 
					if (!config->HasScript()) {
 
						if (_ai_saveload_name.compare("%_dummy") != 0) {
 
							Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version);
 
							Debug(script, 0, "A random other AI will be loaded in its place.");
 
						} else {
 
							Debug(script, 0, "The savegame had no AIs available at the time of saving.");
 
							Debug(script, 0, "A random available AI will be loaded now.");
 
						}
 
					} else {
 
						Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version);
 
						Debug(script, 0, "A random other AI will be loaded in its place.");
 
					} else {
 
						Debug(script, 0, "The savegame had no AIs available at the time of saving.");
 
						Debug(script, 0, "A random available AI will be loaded now.");
 
						Debug(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible.");
 
					}
 
				} else {
 
					Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version);
 
					Debug(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible.");
 
					/* Make sure the AI doesn't get the saveload data, as it was not the
 
					 *  writer of the saveload data in the first place */
 
					_ai_saveload_version = -1;
 
				}
 
				/* Make sure the AI doesn't get the saveload data, as it was not the
 
				 *  writer of the saveload data in the first place */
 
				_ai_saveload_version = -1;
 
			}
 

	
 
			config->StringToSettings(_ai_saveload_settings);
 

	
 
			/* Start the AI directly if it was active in the savegame */
 
			if (Company::IsValidAiID(index)) {
 
				AI::StartNew(index, false);
 
				AI::Load(index, _ai_saveload_version);
 
			}
 
		}
 

	
 
		config->StringToSettings(_ai_saveload_settings);
 
	}
 

	
 
		/* Start the AI directly if it was active in the savegame */
 
		if (Company::IsValidAiID(index)) {
 
			AI::StartNew(index, false);
 
			AI::Load(index, _ai_saveload_version);
 
	void Save() const override
 
	{
 
		SlTableHeader(_ai_company_desc);
 

	
 
		for (int i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
 
			SlSetArrayIndex(i);
 
			SlAutolength((AutolengthProc *)SaveReal_AIPL, &i);
 
		}
 
	}
 
}
 

	
 
static void Save_AIPL()
 
{
 
	SlTableHeader(_ai_company_desc);
 
};
 

	
 
	for (int i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
 
		SlSetArrayIndex(i);
 
		SlAutolength((AutolengthProc *)SaveReal_AIPL, &i);
 
	}
 
}
 

	
 
static const ChunkHandler AIPL{ 'AIPL', Save_AIPL, Load_AIPL, nullptr, nullptr, CH_TABLE };
 
static const AIPLChunkHandler AIPL;
 
static const ChunkHandlerRef ai_chunk_handlers[] = {
 
	AIPL,
 
};
src/saveload/airport_sl.cpp
Show inline comments
 
@@ -14,28 +14,36 @@
 

	
 
#include "../safeguards.h"
 

	
 
static void Save_APID()
 
{
 
	Save_NewGRFMapping(_airport_mngr);
 
}
 
struct APIDChunkHandler : ChunkHandler {
 
	APIDChunkHandler() : ChunkHandler('APID', CH_TABLE) {}
 

	
 
static void Load_APID()
 
{
 
	Load_NewGRFMapping(_airport_mngr);
 
}
 
	void Save() const override
 
	{
 
		Save_NewGRFMapping(_airport_mngr);
 
	}
 

	
 
	void Load() const override
 
	{
 
		Load_NewGRFMapping(_airport_mngr);
 
	}
 
};
 

	
 
static void Save_ATID()
 
{
 
	Save_NewGRFMapping(_airporttile_mngr);
 
}
 
struct ATIDChunkHandler : ChunkHandler {
 
	ATIDChunkHandler() : ChunkHandler('ATID', CH_TABLE) {}
 

	
 
	void Save() const override
 
	{
 
		Save_NewGRFMapping(_airporttile_mngr);
 
	}
 

	
 
static void Load_ATID()
 
{
 
	Load_NewGRFMapping(_airporttile_mngr);
 
}
 
	void Load() const override
 
	{
 
		Load_NewGRFMapping(_airporttile_mngr);
 
	}
 
};
 

	
 
static const ChunkHandler ATID{ 'ATID', Save_ATID, Load_ATID, nullptr, nullptr, CH_TABLE };
 
static const ChunkHandler APID{ 'APID', Save_APID, Load_APID, nullptr, nullptr, CH_TABLE };
 
static const ATIDChunkHandler ATID;
 
static const APIDChunkHandler APID;
 
static const ChunkHandlerRef airport_chunk_handlers[] = {
 
	ATID,
 
	APID,
src/saveload/animated_tile_sl.cpp
Show inline comments
 
@@ -24,51 +24,50 @@ static const SaveLoad _animated_tile_des
 
	 SLEG_VECTOR("tiles", _animated_tiles, SLE_UINT32),
 
};
 

	
 
/**
 
 * Save the ANIT chunk.
 
 */
 
static void Save_ANIT()
 
{
 
	SlTableHeader(_animated_tile_desc);
 

	
 
	SlSetArrayIndex(0);
 
	SlGlobList(_animated_tile_desc);
 
}
 
struct ANITChunkHandler : ChunkHandler {
 
	ANITChunkHandler() : ChunkHandler('ANIT', CH_TABLE) {}
 

	
 
/**
 
 * Load the ANIT chunk; the chunk containing the animated tiles.
 
 */
 
static void Load_ANIT()
 
{
 
	/* Before version 80 we did NOT have a variable length animated tile table */
 
	if (IsSavegameVersionBefore(SLV_80)) {
 
		/* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */
 
		TileIndex anim_list[256];
 
		SlCopy(anim_list, 256, IsSavegameVersionBefore(SLV_6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32);
 
	void Save() const override
 
	{
 
		SlTableHeader(_animated_tile_desc);
 

	
 
		for (int i = 0; i < 256; i++) {
 
			if (anim_list[i] == 0) break;
 
			_animated_tiles.push_back(anim_list[i]);
 
		}
 
		return;
 
		SlSetArrayIndex(0);
 
		SlGlobList(_animated_tile_desc);
 
	}
 

	
 
	if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
 
		size_t count = SlGetFieldLength() / sizeof(_animated_tiles.front());
 
		_animated_tiles.clear();
 
		_animated_tiles.resize(_animated_tiles.size() + count);
 
		SlCopy(_animated_tiles.data(), count, SLE_UINT32);
 
		return;
 
	}
 
	void Load() const override
 
	{
 
		/* Before version 80 we did NOT have a variable length animated tile table */
 
		if (IsSavegameVersionBefore(SLV_80)) {
 
			/* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */
 
			TileIndex anim_list[256];
 
			SlCopy(anim_list, 256, IsSavegameVersionBefore(SLV_6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32);
 

	
 
			for (int i = 0; i < 256; i++) {
 
				if (anim_list[i] == 0) break;
 
				_animated_tiles.push_back(anim_list[i]);
 
			}
 
			return;
 
		}
 

	
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_animated_tile_desc, _animated_tile_sl_compat);
 
		if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
 
			size_t count = SlGetFieldLength() / sizeof(_animated_tiles.front());
 
			_animated_tiles.clear();
 
			_animated_tiles.resize(_animated_tiles.size() + count);
 
			SlCopy(_animated_tiles.data(), count, SLE_UINT32);
 
			return;
 
		}
 

	
 
	if (SlIterateArray() == -1) return;
 
	SlGlobList(slt);
 
	if (SlIterateArray() != -1) SlErrorCorrupt("Too many ANIT entries");
 
}
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_animated_tile_desc, _animated_tile_sl_compat);
 

	
 
static const ChunkHandler ANIT{ 'ANIT', Save_ANIT, Load_ANIT, nullptr, nullptr, CH_TABLE };
 
		if (SlIterateArray() == -1) return;
 
		SlGlobList(slt);
 
		if (SlIterateArray() != -1) SlErrorCorrupt("Too many ANIT entries");
 
	}
 
};
 

	
 

	
 
static const ANITChunkHandler ANIT;
 
static const ChunkHandlerRef animated_tile_chunk_handlers[] = {
 
	ANIT,
 
};
src/saveload/autoreplace_sl.cpp
Show inline comments
 
@@ -25,43 +25,50 @@ static const SaveLoad _engine_renew_desc
 
	SLE_CONDVAR(EngineRenew, replace_when_old, SLE_BOOL, SLV_175, SL_MAX_VERSION),
 
};
 

	
 
static void Save_ERNW()
 
{
 
	SlTableHeader(_engine_renew_desc);
 

	
 
	for (EngineRenew *er : EngineRenew::Iterate()) {
 
		SlSetArrayIndex(er->index);
 
		SlObject(er, _engine_renew_desc);
 
struct ERNWChunkHandler : ChunkHandler {
 
	ERNWChunkHandler() : ChunkHandler('ERNW', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 
}
 

	
 
static void Load_ERNW()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_renew_desc, _engine_renew_sl_compat);
 

	
 
	int index;
 
	void Save() const override
 
	{
 
		SlTableHeader(_engine_renew_desc);
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		EngineRenew *er = new (index) EngineRenew();
 
		SlObject(er, slt);
 

	
 
		/* Advanced vehicle lists, ungrouped vehicles got added */
 
		if (IsSavegameVersionBefore(SLV_60)) {
 
			er->group_id = ALL_GROUP;
 
		} else if (IsSavegameVersionBefore(SLV_71)) {
 
			if (er->group_id == DEFAULT_GROUP) er->group_id = ALL_GROUP;
 
		for (EngineRenew *er : EngineRenew::Iterate()) {
 
			SlSetArrayIndex(er->index);
 
			SlObject(er, _engine_renew_desc);
 
		}
 
	}
 
}
 

	
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_renew_desc, _engine_renew_sl_compat);
 

	
 
		int index;
 

	
 
		while ((index = SlIterateArray()) != -1) {
 
			EngineRenew *er = new (index) EngineRenew();
 
			SlObject(er, slt);
 

	
 
static void Ptrs_ERNW()
 
{
 
	for (EngineRenew *er : EngineRenew::Iterate()) {
 
		SlObject(er, _engine_renew_desc);
 
			/* Advanced vehicle lists, ungrouped vehicles got added */
 
			if (IsSavegameVersionBefore(SLV_60)) {
 
				er->group_id = ALL_GROUP;
 
			} else if (IsSavegameVersionBefore(SLV_71)) {
 
				if (er->group_id == DEFAULT_GROUP) er->group_id = ALL_GROUP;
 
			}
 
		}
 
	}
 
}
 

	
 
static const ChunkHandler ERNW{ 'ERNW', Save_ERNW, Load_ERNW, Ptrs_ERNW, nullptr, CH_TABLE };
 
	void FixPointers() const override
 
	{
 
		for (EngineRenew *er : EngineRenew::Iterate()) {
 
			SlObject(er, _engine_renew_desc);
 
		}
 
	}
 
};
 

	
 
static const ERNWChunkHandler ERNW;
 
static const ChunkHandlerRef autoreplace_chunk_handlers[] = {
 
	ERNW,
 
};
src/saveload/cargomonitor_sl.cpp
Show inline comments
 
@@ -43,92 +43,97 @@ static CargoMonitorID FixupCargoMonitor(
 
	return number;
 
}
 

	
 
/** Save the #_cargo_deliveries monitoring map. */
 
static void SaveDelivery()
 
{
 
	SlTableHeader(_cargomonitor_pair_desc);
 
/** #_cargo_deliveries monitoring map. */
 
struct CMDLChunkHandler : ChunkHandler {
 
	CMDLChunkHandler() : ChunkHandler('CMDL', CH_TABLE) {}
 

	
 
	TempStorage storage;
 
	void Save() const override
 
	{
 
		SlTableHeader(_cargomonitor_pair_desc);
 

	
 
		TempStorage storage;
 

	
 
	int i = 0;
 
	CargoMonitorMap::const_iterator iter = _cargo_deliveries.begin();
 
	while (iter != _cargo_deliveries.end()) {
 
		storage.number = iter->first;
 
		storage.amount = iter->second;
 
		int i = 0;
 
		CargoMonitorMap::const_iterator iter = _cargo_deliveries.begin();
 
		while (iter != _cargo_deliveries.end()) {
 
			storage.number = iter->first;
 
			storage.amount = iter->second;
 

	
 
		SlSetArrayIndex(i);
 
		SlObject(&storage, _cargomonitor_pair_desc);
 
			SlSetArrayIndex(i);
 
			SlObject(&storage, _cargomonitor_pair_desc);
 

	
 
		i++;
 
		iter++;
 
			i++;
 
			iter++;
 
		}
 
	}
 
}
 

	
 
/** Load the #_cargo_deliveries monitoring map. */
 
static void LoadDelivery()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat);
 

	
 
	TempStorage storage;
 
	bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR);
 
		TempStorage storage;
 
		bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR);
 

	
 
	ClearCargoDeliveryMonitoring();
 
	for (;;) {
 
		if (SlIterateArray() < 0) break;
 
		SlObject(&storage, slt);
 
		ClearCargoDeliveryMonitoring();
 
		for (;;) {
 
			if (SlIterateArray() < 0) break;
 
			SlObject(&storage, slt);
 

	
 
		if (fix) storage.number = FixupCargoMonitor(storage.number);
 
			if (fix) storage.number = FixupCargoMonitor(storage.number);
 

	
 
		std::pair<CargoMonitorID, uint32> p(storage.number, storage.amount);
 
		_cargo_deliveries.insert(p);
 
			std::pair<CargoMonitorID, uint32> p(storage.number, storage.amount);
 
			_cargo_deliveries.insert(p);
 
		}
 
	}
 
}
 
};
 

	
 
/** #_cargo_pickups monitoring map. */
 
struct CMPUChunkHandler : ChunkHandler {
 
	CMPUChunkHandler() : ChunkHandler('CMPU', CH_TABLE) {}
 

	
 
/** Save the #_cargo_pickups monitoring map. */
 
static void SavePickup()
 
{
 
	SlTableHeader(_cargomonitor_pair_desc);
 
	void Save() const override
 
	{
 
		SlTableHeader(_cargomonitor_pair_desc);
 

	
 
	TempStorage storage;
 
		TempStorage storage;
 

	
 
	int i = 0;
 
	CargoMonitorMap::const_iterator iter = _cargo_pickups.begin();
 
	while (iter != _cargo_pickups.end()) {
 
		storage.number = iter->first;
 
		storage.amount = iter->second;
 
		int i = 0;
 
		CargoMonitorMap::const_iterator iter = _cargo_pickups.begin();
 
		while (iter != _cargo_pickups.end()) {
 
			storage.number = iter->first;
 
			storage.amount = iter->second;
 

	
 
		SlSetArrayIndex(i);
 
		SlObject(&storage, _cargomonitor_pair_desc);
 
			SlSetArrayIndex(i);
 
			SlObject(&storage, _cargomonitor_pair_desc);
 

	
 
		i++;
 
		iter++;
 
			i++;
 
			iter++;
 
		}
 
	}
 
}
 

	
 
/** Load the #_cargo_pickups monitoring map. */
 
static void LoadPickup()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat);
 

	
 
	TempStorage storage;
 
	bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR);
 
		TempStorage storage;
 
		bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR);
 

	
 
	ClearCargoPickupMonitoring();
 
	for (;;) {
 
		if (SlIterateArray() < 0) break;
 
		SlObject(&storage, slt);
 
		ClearCargoPickupMonitoring();
 
		for (;;) {
 
			if (SlIterateArray() < 0) break;
 
			SlObject(&storage, slt);
 

	
 
		if (fix) storage.number = FixupCargoMonitor(storage.number);
 
			if (fix) storage.number = FixupCargoMonitor(storage.number);
 

	
 
		std::pair<CargoMonitorID, uint32> p(storage.number, storage.amount);
 
		_cargo_pickups.insert(p);
 
			std::pair<CargoMonitorID, uint32> p(storage.number, storage.amount);
 
			_cargo_pickups.insert(p);
 
		}
 
	}
 
}
 
};
 

	
 
/** Chunk definition of the cargomonitoring maps. */
 
static const ChunkHandler CMDL{ 'CMDL', SaveDelivery, LoadDelivery, nullptr, nullptr, CH_TABLE };
 
static const ChunkHandler CMPU{ 'CMPU', SavePickup,   LoadPickup,   nullptr, nullptr, CH_TABLE };
 
static const CMDLChunkHandler CMDL;
 
static const CMPUChunkHandler CMPU;
 
static const ChunkHandlerRef cargomonitor_chunk_handlers[] = {
 
	CMDL,
 
	CMPU,
src/saveload/cargopacket_sl.cpp
Show inline comments
 
@@ -100,35 +100,33 @@ SaveLoadTable GetCargoPacketDesc()
 
	return _cargopacket_desc;
 
}
 

	
 
/**
 
 * Save the cargo packets.
 
 */
 
static void Save_CAPA()
 
{
 
	SlTableHeader(GetCargoPacketDesc());
 
struct CAPAChunkHandler : ChunkHandler {
 
	CAPAChunkHandler() : ChunkHandler('CAPA', CH_TABLE) {}
 

	
 
	for (CargoPacket *cp : CargoPacket::Iterate()) {
 
		SlSetArrayIndex(cp->index);
 
		SlObject(cp, GetCargoPacketDesc());
 
	void Save() const override
 
	{
 
		SlTableHeader(GetCargoPacketDesc());
 

	
 
		for (CargoPacket *cp : CargoPacket::Iterate()) {
 
			SlSetArrayIndex(cp->index);
 
			SlObject(cp, GetCargoPacketDesc());
 
		}
 
	}
 
}
 

	
 
/**
 
 * Load the cargo packets.
 
 */
 
static void Load_CAPA()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(GetCargoPacketDesc(), _cargopacket_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(GetCargoPacketDesc(), _cargopacket_sl_compat);
 

	
 
		int index;
 

	
 
	int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			CargoPacket *cp = new (index) CargoPacket();
 
			SlObject(cp, slt);
 
		}
 
	}
 
};
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		CargoPacket *cp = new (index) CargoPacket();
 
		SlObject(cp, slt);
 
	}
 
}
 

	
 
static const ChunkHandler CAPA{ 'CAPA', Save_CAPA, Load_CAPA, nullptr, nullptr, CH_TABLE };
 
static const CAPAChunkHandler CAPA;
 
static const ChunkHandlerRef cargopacket_chunk_handlers[] = {
 
	CAPA,
 
};
src/saveload/cheat_sl.cpp
Show inline comments
 
@@ -35,47 +35,46 @@ static const SaveLoad _cheats_desc[] = {
 
	SLE_VAR(Cheats, edit_max_hl.value, SLE_BOOL),
 
};
 

	
 
/**
 
 * Save the cheat values.
 
 */
 
static void Save_CHTS()
 
{
 
	SlTableHeader(_cheats_desc);
 

	
 
	SlSetArrayIndex(0);
 
	SlObject(&_cheats, _cheats_desc);
 
}
 
struct CHTSChunkHandler : ChunkHandler {
 
	CHTSChunkHandler() : ChunkHandler('CHTS', CH_TABLE) {}
 

	
 
/**
 
 * Load the cheat values.
 
 */
 
static void Load_CHTS()
 
{
 
	std::vector<SaveLoad> slt = SlCompatTableHeader(_cheats_desc, _cheats_sl_compat);
 

	
 
	if (IsSavegameVersionBefore(SLV_TABLE_CHUNKS)) {
 
		size_t count = SlGetFieldLength();
 
		std::vector<SaveLoad> oslt;
 
	void Save() const override
 
	{
 
		SlTableHeader(_cheats_desc);
 

	
 
		/* 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
 
		 * are stored for this savegame. So read only "count" SLE_BOOLs (and in
 
		 * result "count / 2" cheats). */
 
		for (auto &sld : slt) {
 
			count--;
 
			oslt.push_back(sld);
 

	
 
			if (count == 0) break;
 
		}
 
		slt = oslt;
 
		SlSetArrayIndex(0);
 
		SlObject(&_cheats, _cheats_desc);
 
	}
 

	
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
	SlObject(&_cheats, slt);
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many CHTS entries");
 
}
 
	void Load() const override
 
	{
 
		std::vector<SaveLoad> slt = SlCompatTableHeader(_cheats_desc, _cheats_sl_compat);
 

	
 
		if (IsSavegameVersionBefore(SLV_TABLE_CHUNKS)) {
 
			size_t count = SlGetFieldLength();
 
			std::vector<SaveLoad> oslt;
 

	
 
static const ChunkHandler CHTS{ 'CHTS', Save_CHTS, Load_CHTS, nullptr, nullptr, CH_TABLE };
 
			/* 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
 
			 * are stored for this savegame. So read only "count" SLE_BOOLs (and in
 
			 * result "count / 2" cheats). */
 
			for (auto &sld : slt) {
 
				count--;
 
				oslt.push_back(sld);
 

	
 
				if (count == 0) break;
 
			}
 
			slt = oslt;
 
		}
 

	
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
		SlObject(&_cheats, slt);
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many CHTS entries");
 
	}
 
};
 

	
 
static const CHTSChunkHandler CHTS;
 
static const ChunkHandlerRef cheat_chunk_handlers[] = {
 
	CHTS,
 
};
src/saveload/company_sl.cpp
Show inline comments
 
@@ -497,67 +497,76 @@ static const SaveLoad _company_desc[] = 
 
	SLEG_CONDSTRUCTLIST("liveries", SlCompanyLiveries,                               SLV_34, SL_MAX_VERSION),
 
};
 

	
 
static void Save_PLYR()
 
{
 
	SlTableHeader(_company_desc);
 
struct PLYRChunkHandler : ChunkHandler {
 
	PLYRChunkHandler() : ChunkHandler('PLYR', CH_TABLE)
 
	{
 
		this->load_check = true;
 
		this->fix_pointers = true;
 
	}
 

	
 
	for (Company *c : Company::Iterate()) {
 
		SlSetArrayIndex(c->index);
 
		SlObject(c, _company_desc);
 
	void Save() const override
 
	{
 
		SlTableHeader(_company_desc);
 

	
 
		for (Company *c : Company::Iterate()) {
 
			SlSetArrayIndex(c->index);
 
			SlObject(c, _company_desc);
 
		}
 
	}
 
}
 

	
 
static void Load_PLYR()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_company_desc, _company_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_company_desc, _company_sl_compat);
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		Company *c = new (index) Company();
 
		SlObject(c, slt);
 
		_company_colours[index] = (Colours)c->colour;
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			Company *c = new (index) Company();
 
			SlObject(c, slt);
 
			_company_colours[index] = (Colours)c->colour;
 
		}
 
	}
 
}
 

	
 

	
 
	void LoadCheck(size_t) const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_company_desc, _company_sl_compat);
 

	
 
static void Check_PLYR()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_company_desc, _company_sl_compat);
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			CompanyProperties *cprops = new CompanyProperties();
 
			SlObject(cprops, slt);
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		CompanyProperties *cprops = new CompanyProperties();
 
		SlObject(cprops, slt);
 
			/* We do not load old custom names */
 
			if (IsSavegameVersionBefore(SLV_84)) {
 
				if (GetStringTab(cprops->name_1) == TEXT_TAB_OLD_CUSTOM) {
 
					cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
 
				}
 

	
 
		/* We do not load old custom names */
 
		if (IsSavegameVersionBefore(SLV_84)) {
 
			if (GetStringTab(cprops->name_1) == TEXT_TAB_OLD_CUSTOM) {
 
				if (GetStringTab(cprops->president_name_1) == TEXT_TAB_OLD_CUSTOM) {
 
					cprops->president_name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
 
				}
 
			}
 

	
 
			if (cprops->name.empty() && !IsInsideMM(cprops->name_1, SPECSTR_COMPANY_NAME_START, SPECSTR_COMPANY_NAME_LAST + 1) &&
 
				cprops->name_1 != STR_GAME_SAVELOAD_NOT_AVAILABLE && cprops->name_1 != STR_SV_UNNAMED &&
 
				cprops->name_1 != SPECSTR_ANDCO_NAME && cprops->name_1 != SPECSTR_PRESIDENT_NAME &&
 
				cprops->name_1 != SPECSTR_SILLY_NAME) {
 
				cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
 
			}
 

	
 
			if (GetStringTab(cprops->president_name_1) == TEXT_TAB_OLD_CUSTOM) {
 
				cprops->president_name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
 
			}
 
			if (!_load_check_data.companies.Insert(index, cprops)) delete cprops;
 
		}
 

	
 
		if (cprops->name.empty() && !IsInsideMM(cprops->name_1, SPECSTR_COMPANY_NAME_START, SPECSTR_COMPANY_NAME_LAST + 1) &&
 
				cprops->name_1 != STR_GAME_SAVELOAD_NOT_AVAILABLE && cprops->name_1 != STR_SV_UNNAMED &&
 
				cprops->name_1 != SPECSTR_ANDCO_NAME && cprops->name_1 != SPECSTR_PRESIDENT_NAME &&
 
				cprops->name_1 != SPECSTR_SILLY_NAME) {
 
			cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
 
		}
 
	}
 

	
 
		if (!_load_check_data.companies.Insert(index, cprops)) delete cprops;
 
	void FixPointers() const override
 
	{
 
		for (Company *c : Company::Iterate()) {
 
			SlObject(c, _company_desc);
 
		}
 
	}
 
}
 
};
 

	
 
static void Ptrs_PLYR()
 
{
 
	for (Company *c : Company::Iterate()) {
 
		SlObject(c, _company_desc);
 
	}
 
}
 

	
 
static const ChunkHandler PLYR{ 'PLYR', Save_PLYR, Load_PLYR, Ptrs_PLYR, Check_PLYR, CH_TABLE };
 
static const PLYRChunkHandler PLYR;
 
static const ChunkHandlerRef company_chunk_handlers[] = {
 
	PLYR,
 
};
src/saveload/depot_sl.cpp
Show inline comments
 
@@ -29,40 +29,47 @@ static const SaveLoad _depot_desc[] = {
 
	 SLE_CONDVAR(Depot, build_date, SLE_INT32,                SLV_142, SL_MAX_VERSION),
 
};
 

	
 
static void Save_DEPT()
 
{
 
	SlTableHeader(_depot_desc);
 

	
 
	for (Depot *depot : Depot::Iterate()) {
 
		SlSetArrayIndex(depot->index);
 
		SlObject(depot, _depot_desc);
 
struct DEPTChunkHandler : ChunkHandler {
 
	DEPTChunkHandler() : ChunkHandler('DEPT', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 
}
 

	
 
	void Save() const override
 
	{
 
		SlTableHeader(_depot_desc);
 

	
 
static void Load_DEPT()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_depot_desc, _depot_sl_compat);
 
		for (Depot *depot : Depot::Iterate()) {
 
			SlSetArrayIndex(depot->index);
 
			SlObject(depot, _depot_desc);
 
		}
 
	}
 

	
 
	int index;
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_depot_desc, _depot_sl_compat);
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		Depot *depot = new (index) Depot();
 
		SlObject(depot, slt);
 
		int index;
 

	
 
		/* Set the town 'pointer' so we can restore it later. */
 
		if (IsSavegameVersionBefore(SLV_141)) depot->town = (Town *)(size_t)_town_index;
 
		while ((index = SlIterateArray()) != -1) {
 
			Depot *depot = new (index) Depot();
 
			SlObject(depot, slt);
 

	
 
			/* Set the town 'pointer' so we can restore it later. */
 
			if (IsSavegameVersionBefore(SLV_141)) depot->town = (Town *)(size_t)_town_index;
 
		}
 
	}
 
}
 

	
 
static void Ptrs_DEPT()
 
{
 
	for (Depot *depot : Depot::Iterate()) {
 
		SlObject(depot, _depot_desc);
 
		if (IsSavegameVersionBefore(SLV_141)) depot->town = Town::Get((size_t)depot->town);
 
	void FixPointers() const override
 
	{
 
		for (Depot *depot : Depot::Iterate()) {
 
			SlObject(depot, _depot_desc);
 
			if (IsSavegameVersionBefore(SLV_141)) depot->town = Town::Get((size_t)depot->town);
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler DEPT{ 'DEPT', Save_DEPT, Load_DEPT, Ptrs_DEPT, nullptr, CH_TABLE };
 
static const DEPTChunkHandler DEPT;
 
static const ChunkHandlerRef depot_chunk_handlers[] = {
 
	DEPT,
 
};
src/saveload/economy_sl.cpp
Show inline comments
 
@@ -18,22 +18,30 @@
 
#include "../safeguards.h"
 

	
 
/** Prices in pre 126 savegames */
 
static void Load_PRIC()
 
{
 
	/* Old games store 49 base prices, very old games store them as int32 */
 
	int vt = IsSavegameVersionBefore(SLV_65) ? SLE_FILE_I32 : SLE_FILE_I64;
 
	SlCopy(nullptr, 49, vt | SLE_VAR_NULL);
 
	SlCopy(nullptr, 49, SLE_FILE_U16 | SLE_VAR_NULL);
 
}
 
struct PRICChunkHandler : ChunkHandler {
 
	PRICChunkHandler() : ChunkHandler('PRIC', CH_READONLY) {}
 

	
 
	void Load() const override
 
	{
 
		/* Old games store 49 base prices, very old games store them as int32 */
 
		int vt = IsSavegameVersionBefore(SLV_65) ? SLE_FILE_I32 : SLE_FILE_I64;
 
		SlCopy(nullptr, 49, vt | SLE_VAR_NULL);
 
		SlCopy(nullptr, 49, SLE_FILE_U16 | SLE_VAR_NULL);
 
	}
 
};
 

	
 
/** Cargo payment rates in pre 126 savegames */
 
static void Load_CAPR()
 
{
 
	uint num_cargo = IsSavegameVersionBefore(SLV_55) ? 12 : IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO;
 
	int vt = IsSavegameVersionBefore(SLV_65) ? SLE_FILE_I32 : SLE_FILE_I64;
 
	SlCopy(nullptr, num_cargo, vt | SLE_VAR_NULL);
 
	SlCopy(nullptr, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL);
 
}
 
struct CAPRChunkHandler : ChunkHandler {
 
	CAPRChunkHandler() : ChunkHandler('CAPR', CH_READONLY) {}
 

	
 
	void Load() const override
 
	{
 
		uint num_cargo = IsSavegameVersionBefore(SLV_55) ? 12 : IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO;
 
		int vt = IsSavegameVersionBefore(SLV_65) ? SLE_FILE_I32 : SLE_FILE_I64;
 
		SlCopy(nullptr, num_cargo, vt | SLE_VAR_NULL);
 
		SlCopy(nullptr, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL);
 
	}
 
};
 

	
 
static const SaveLoad _economy_desc[] = {
 
	SLE_CONDVAR(Economy, old_max_loan_unround,          SLE_FILE_I32 | SLE_VAR_I64,  SL_MIN_VERSION, SLV_65),
 
@@ -49,25 +57,29 @@ static const SaveLoad _economy_desc[] = 
 
};
 

	
 
/** Economy variables */
 
static void Save_ECMY()
 
{
 
	SlTableHeader(_economy_desc);
 
struct ECMYChunkHandler : ChunkHandler {
 
	ECMYChunkHandler() : ChunkHandler('ECMY', CH_TABLE) {}
 

	
 
	SlSetArrayIndex(0);
 
	SlObject(&_economy, _economy_desc);
 
}
 
	void Save() const override
 
	{
 
		SlTableHeader(_economy_desc);
 

	
 
		SlSetArrayIndex(0);
 
		SlObject(&_economy, _economy_desc);
 
	}
 

	
 

	
 
/** Economy variables */
 
static void Load_ECMY()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_economy_desc, _economy_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_economy_desc, _economy_sl_compat);
 

	
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
	SlObject(&_economy, slt);
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many ECMY entries");
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
		SlObject(&_economy, slt);
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many ECMY entries");
 

	
 
	StartupIndustryDailyChanges(IsSavegameVersionBefore(SLV_102));  // old savegames will need to be initialized
 
}
 
		StartupIndustryDailyChanges(IsSavegameVersionBefore(SLV_102));  // old savegames will need to be initialized
 
	}
 
};
 

	
 
static const SaveLoad _cargopayment_desc[] = {
 
	    SLE_REF(CargoPayment, front,           REF_VEHICLE),
 
@@ -76,39 +88,46 @@ static const SaveLoad _cargopayment_desc
 
	SLE_CONDVAR(CargoPayment, visual_transfer, SLE_INT64, SLV_181, SL_MAX_VERSION),
 
};
 

	
 
static void Save_CAPY()
 
{
 
	SlTableHeader(_cargopayment_desc);
 

	
 
	for (CargoPayment *cp : CargoPayment::Iterate()) {
 
		SlSetArrayIndex(cp->index);
 
		SlObject(cp, _cargopayment_desc);
 
struct CAPYChunkHandler : ChunkHandler {
 
	CAPYChunkHandler() : ChunkHandler('CAPY', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 
}
 

	
 
	void Save() const override
 
	{
 
		SlTableHeader(_cargopayment_desc);
 

	
 
static void Load_CAPY()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargopayment_desc, _cargopayment_sl_compat);
 
		for (CargoPayment *cp : CargoPayment::Iterate()) {
 
			SlSetArrayIndex(cp->index);
 
			SlObject(cp, _cargopayment_desc);
 
		}
 
	}
 

	
 
	int index;
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargopayment_desc, _cargopayment_sl_compat);
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		CargoPayment *cp = new (index) CargoPayment();
 
		SlObject(cp, slt);
 
		int index;
 

	
 
		while ((index = SlIterateArray()) != -1) {
 
			CargoPayment *cp = new (index) CargoPayment();
 
			SlObject(cp, slt);
 
		}
 
	}
 
}
 

	
 
static void Ptrs_CAPY()
 
{
 
	for (CargoPayment *cp : CargoPayment::Iterate()) {
 
		SlObject(cp, _cargopayment_desc);
 
	void FixPointers() const override
 
	{
 
		for (CargoPayment *cp : CargoPayment::Iterate()) {
 
			SlObject(cp, _cargopayment_desc);
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler CAPY{ 'CAPY', Save_CAPY, Load_CAPY, Ptrs_CAPY, nullptr, CH_TABLE };
 
static const ChunkHandler PRIC{ 'PRIC', nullptr,   Load_PRIC, nullptr,   nullptr, CH_READONLY };
 
static const ChunkHandler CAPR{ 'CAPR', nullptr,   Load_CAPR, nullptr,   nullptr, CH_READONLY };
 
static const ChunkHandler ECMY{ 'ECMY', Save_ECMY, Load_ECMY, nullptr,   nullptr, CH_TABLE };
 
static const CAPYChunkHandler CAPY;
 
static const PRICChunkHandler PRIC;
 
static const CAPRChunkHandler CAPR;
 
static const ECMYChunkHandler ECMY;
 
static const ChunkHandlerRef economy_chunk_handlers[] = {
 
	CAPY,
 
	PRIC,
src/saveload/engine_sl.cpp
Show inline comments
 
@@ -80,37 +80,41 @@ Engine *GetTempDataEngine(EngineID index
 
	}
 
}
 

	
 
static void Save_ENGN()
 
{
 
	SlTableHeader(_engine_desc);
 

	
 
	for (Engine *e : Engine::Iterate()) {
 
		SlSetArrayIndex(e->index);
 
		SlObject(e, _engine_desc);
 
	}
 
}
 

	
 
static void Load_ENGN()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_desc, _engine_sl_compat);
 
struct ENGNChunkHandler : ChunkHandler {
 
	ENGNChunkHandler() : ChunkHandler('ENGN', CH_TABLE) {}
 

	
 
	/* As engine data is loaded before engines are initialized we need to load
 
	 * this information into a temporary array. This is then copied into the
 
	 * engine pool after processing NewGRFs by CopyTempEngineData(). */
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		Engine *e = GetTempDataEngine(index);
 
		SlObject(e, slt);
 
	void Save() const override
 
	{
 
		SlTableHeader(_engine_desc);
 

	
 
		if (IsSavegameVersionBefore(SLV_179)) {
 
			/* preview_company_rank was replaced with preview_company and preview_asked.
 
			 * Just cancel any previews. */
 
			e->flags &= ~4; // ENGINE_OFFER_WINDOW_OPEN
 
			e->preview_company = INVALID_COMPANY;
 
			e->preview_asked = (CompanyMask)-1;
 
		for (Engine *e : Engine::Iterate()) {
 
			SlSetArrayIndex(e->index);
 
			SlObject(e, _engine_desc);
 
		}
 
	}
 
}
 

	
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_desc, _engine_sl_compat);
 

	
 
		/* As engine data is loaded before engines are initialized we need to load
 
		 * this information into a temporary array. This is then copied into the
 
		 * engine pool after processing NewGRFs by CopyTempEngineData(). */
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			Engine *e = GetTempDataEngine(index);
 
			SlObject(e, slt);
 

	
 
			if (IsSavegameVersionBefore(SLV_179)) {
 
				/* preview_company_rank was replaced with preview_company and preview_asked.
 
				 * Just cancel any previews. */
 
				e->flags &= ~4; // ENGINE_OFFER_WINDOW_OPEN
 
				e->preview_company = INVALID_COMPANY;
 
				e->preview_asked = (CompanyMask)-1;
 
			}
 
		}
 
	}
 
};
 

	
 
/**
 
 * Copy data from temporary engine array into the real engine pool.
 
@@ -152,20 +156,24 @@ void ResetTempEngineData()
 
	_temp_engine.clear();
 
}
 

	
 
static void Load_ENGS()
 
{
 
	/* Load old separate String ID list into a temporary array. This
 
	 * was always 256 entries. */
 
	StringID names[256];
 
struct ENGSChunkHandler : ChunkHandler {
 
	ENGSChunkHandler() : ChunkHandler('ENGS', CH_READONLY) {}
 

	
 
	void Load() const override
 
	{
 
		/* Load old separate String ID list into a temporary array. This
 
		 * was always 256 entries. */
 
		StringID names[256];
 

	
 
	SlCopy(names, lengthof(names), SLE_STRINGID);
 
		SlCopy(names, lengthof(names), SLE_STRINGID);
 

	
 
	/* Copy each string into the temporary engine array. */
 
	for (EngineID engine = 0; engine < lengthof(names); engine++) {
 
		Engine *e = GetTempDataEngine(engine);
 
		e->name = CopyFromOldName(names[engine]);
 
		/* Copy each string into the temporary engine array. */
 
		for (EngineID engine = 0; engine < lengthof(names); engine++) {
 
			Engine *e = GetTempDataEngine(engine);
 
			e->name = CopyFromOldName(names[engine]);
 
		}
 
	}
 
}
 
};
 

	
 
/** Save and load the mapping between the engine id in the pool, and the grf file it came from. */
 
static const SaveLoad _engine_id_mapping_desc[] = {
 
@@ -175,33 +183,37 @@ static const SaveLoad _engine_id_mapping
 
	SLE_VAR(EngineIDMapping, substitute_id, SLE_UINT8),
 
};
 

	
 
static void Save_EIDS()
 
{
 
	SlTableHeader(_engine_id_mapping_desc);
 
struct EIDSChunkHandler : ChunkHandler {
 
	EIDSChunkHandler() : ChunkHandler('EIDS', CH_TABLE) {}
 

	
 
	void Save() const override
 
	{
 
		SlTableHeader(_engine_id_mapping_desc);
 

	
 
	uint index = 0;
 
	for (EngineIDMapping &eid : _engine_mngr) {
 
		SlSetArrayIndex(index);
 
		SlObject(&eid, _engine_id_mapping_desc);
 
		index++;
 
		uint index = 0;
 
		for (EngineIDMapping &eid : _engine_mngr) {
 
			SlSetArrayIndex(index);
 
			SlObject(&eid, _engine_id_mapping_desc);
 
			index++;
 
		}
 
	}
 
}
 

	
 
static void Load_EIDS()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_id_mapping_desc, _engine_id_mapping_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_id_mapping_desc, _engine_id_mapping_sl_compat);
 

	
 
	_engine_mngr.clear();
 
		_engine_mngr.clear();
 

	
 
	while (SlIterateArray() != -1) {
 
		EngineIDMapping *eid = &_engine_mngr.emplace_back();
 
		SlObject(eid, slt);
 
		while (SlIterateArray() != -1) {
 
			EngineIDMapping *eid = &_engine_mngr.emplace_back();
 
			SlObject(eid, slt);
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler EIDS{ 'EIDS', Save_EIDS, Load_EIDS, nullptr, nullptr, CH_TABLE };
 
static const ChunkHandler ENGN{ 'ENGN', Save_ENGN, Load_ENGN, nullptr, nullptr, CH_TABLE };
 
static const ChunkHandler ENGS{ 'ENGS', nullptr,   Load_ENGS, nullptr, nullptr, CH_READONLY };
 
static const EIDSChunkHandler EIDS;
 
static const ENGNChunkHandler ENGN;
 
static const ENGSChunkHandler ENGS;
 
static const ChunkHandlerRef engine_chunk_handlers[] = {
 
	EIDS,
 
	ENGN,
src/saveload/game_sl.cpp
Show inline comments
 
@@ -54,64 +54,68 @@ static void SaveReal_GSDT(int *index_ptr
 
	Game::Save();
 
}
 

	
 
static void Load_GSDT()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_game_script_desc, _game_script_sl_compat);
 
struct GSDTChunkHandler : ChunkHandler {
 
	GSDTChunkHandler() : ChunkHandler('GSDT', CH_TABLE) {}
 

	
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_game_script_desc, _game_script_sl_compat);
 

	
 
		/* Free all current data */
 
		GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME)->Change(nullptr);
 

	
 
	/* Free all current data */
 
	GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME)->Change(nullptr);
 
		if (SlIterateArray() == -1) return;
 

	
 
		_game_saveload_version = -1;
 
		SlObject(nullptr, slt);
 

	
 
		if (_networking && !_network_server) {
 
			GameInstance::LoadEmpty();
 
			if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs");
 
			return;
 
		}
 

	
 
	if (SlIterateArray() == -1) return;
 

	
 
	_game_saveload_version = -1;
 
	SlObject(nullptr, slt);
 
		GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME);
 
		if (!_game_saveload_name.empty()) {
 
			config->Change(_game_saveload_name.c_str(), _game_saveload_version, false, _game_saveload_is_random);
 
			if (!config->HasScript()) {
 
				/* No version of the GameScript available that can load the data. Try to load the
 
				 * latest version of the GameScript instead. */
 
				config->Change(_game_saveload_name.c_str(), -1, false, _game_saveload_is_random);
 
				if (!config->HasScript()) {
 
					if (_game_saveload_name.compare("%_dummy") != 0) {
 
						Debug(script, 0, "The savegame has an GameScript by the name '{}', version {} which is no longer available.", _game_saveload_name, _game_saveload_version);
 
						Debug(script, 0, "This game will continue to run without GameScript.");
 
					} else {
 
						Debug(script, 0, "The savegame had no GameScript available at the time of saving.");
 
						Debug(script, 0, "This game will continue to run without GameScript.");
 
					}
 
				} else {
 
					Debug(script, 0, "The savegame has an GameScript by the name '{}', version {} which is no longer available.", _game_saveload_name, _game_saveload_version);
 
					Debug(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible.");
 
				}
 
				/* Make sure the GameScript doesn't get the saveload data, as it was not the
 
				 *  writer of the saveload data in the first place */
 
				_game_saveload_version = -1;
 
			}
 
		}
 

	
 
	if (_networking && !_network_server) {
 
		GameInstance::LoadEmpty();
 
		config->StringToSettings(_game_saveload_settings);
 

	
 
		/* Start the GameScript directly if it was active in the savegame */
 
		Game::StartNew();
 
		Game::Load(_game_saveload_version);
 

	
 
		if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs");
 
		return;
 
	}
 

	
 
	GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME);
 
	if (!_game_saveload_name.empty()) {
 
		config->Change(_game_saveload_name.c_str(), _game_saveload_version, false, _game_saveload_is_random);
 
		if (!config->HasScript()) {
 
			/* No version of the GameScript available that can load the data. Try to load the
 
			 * latest version of the GameScript instead. */
 
			config->Change(_game_saveload_name.c_str(), -1, false, _game_saveload_is_random);
 
			if (!config->HasScript()) {
 
				if (_game_saveload_name.compare("%_dummy") != 0) {
 
					Debug(script, 0, "The savegame has an GameScript by the name '{}', version {} which is no longer available.", _game_saveload_name, _game_saveload_version);
 
					Debug(script, 0, "This game will continue to run without GameScript.");
 
				} else {
 
					Debug(script, 0, "The savegame had no GameScript available at the time of saving.");
 
					Debug(script, 0, "This game will continue to run without GameScript.");
 
				}
 
			} else {
 
				Debug(script, 0, "The savegame has an GameScript by the name '{}', version {} which is no longer available.", _game_saveload_name, _game_saveload_version);
 
				Debug(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible.");
 
			}
 
			/* Make sure the GameScript doesn't get the saveload data, as it was not the
 
			 *  writer of the saveload data in the first place */
 
			_game_saveload_version = -1;
 
		}
 
	void Save() const override
 
	{
 
		SlTableHeader(_game_script_desc);
 
		SlSetArrayIndex(0);
 
		SlAutolength((AutolengthProc *)SaveReal_GSDT, nullptr);
 
	}
 

	
 
	config->StringToSettings(_game_saveload_settings);
 

	
 
	/* Start the GameScript directly if it was active in the savegame */
 
	Game::StartNew();
 
	Game::Load(_game_saveload_version);
 

	
 
	if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs");
 
}
 

	
 
static void Save_GSDT()
 
{
 
	SlTableHeader(_game_script_desc);
 
	SlSetArrayIndex(0);
 
	SlAutolength((AutolengthProc *)SaveReal_GSDT, nullptr);
 
}
 
};
 

	
 
extern GameStrings *_current_data;
 

	
 
@@ -152,44 +156,48 @@ static const SaveLoad _game_language_des
 
	SLEG_STRUCTLIST("strings", SlGameLanguageString),
 
};
 

	
 
static void Load_GSTR()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_game_language_desc, _game_language_sl_compat);
 
struct GSTRChunkHandler : ChunkHandler {
 
	GSTRChunkHandler() : ChunkHandler('GSTR', CH_TABLE) {}
 

	
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_game_language_desc, _game_language_sl_compat);
 

	
 
		delete _current_data;
 
		_current_data = new GameStrings();
 

	
 
	delete _current_data;
 
	_current_data = new GameStrings();
 
		while (SlIterateArray() != -1) {
 
			LanguageStrings ls;
 
			SlObject(&ls, slt);
 
			_current_data->raw_strings.push_back(std::move(ls));
 
		}
 

	
 
	while (SlIterateArray() != -1) {
 
		LanguageStrings ls;
 
		SlObject(&ls, slt);
 
		_current_data->raw_strings.push_back(std::move(ls));
 
		/* If there were no strings in the savegame, set GameStrings to nullptr */
 
		if (_current_data->raw_strings.size() == 0) {
 
			delete _current_data;
 
			_current_data = nullptr;
 
			return;
 
		}
 

	
 
		_current_data->Compile();
 
		ReconsiderGameScriptLanguage();
 
	}
 

	
 
	/* If there were no strings in the savegame, set GameStrings to nullptr */
 
	if (_current_data->raw_strings.size() == 0) {
 
		delete _current_data;
 
		_current_data = nullptr;
 
		return;
 
	}
 
	void Save() const override
 
	{
 
		SlTableHeader(_game_language_desc);
 

	
 
	_current_data->Compile();
 
	ReconsiderGameScriptLanguage();
 
}
 
		if (_current_data == nullptr) return;
 

	
 
static void Save_GSTR()
 
{
 
	SlTableHeader(_game_language_desc);
 

	
 
	if (_current_data == nullptr) return;
 
		for (uint i = 0; i < _current_data->raw_strings.size(); i++) {
 
			SlSetArrayIndex(i);
 
			SlObject(&_current_data->raw_strings[i], _game_language_desc);
 
		}
 
	}
 
};
 

	
 
	for (uint i = 0; i < _current_data->raw_strings.size(); i++) {
 
		SlSetArrayIndex(i);
 
		SlObject(&_current_data->raw_strings[i], _game_language_desc);
 
	}
 
}
 

	
 
static const ChunkHandler GSTR{ 'GSTR', Save_GSTR, Load_GSTR, nullptr, nullptr, CH_TABLE };
 
static const ChunkHandler GSDT{ 'GSDT', Save_GSDT, Load_GSDT, nullptr, nullptr, CH_TABLE };
 
static const GSTRChunkHandler GSTR;
 
static const GSDTChunkHandler GSDT;
 
static const ChunkHandlerRef game_chunk_handlers[] = {
 
	GSTR,
 
	GSDT,
src/saveload/gamelog_sl.cpp
Show inline comments
 
@@ -347,61 +347,68 @@ static const SaveLoad _gamelog_desc[] = 
 
	SLEG_STRUCTLIST("action", SlGamelogAction),
 
};
 

	
 
static void Load_GLOG_common(LoggedAction *&gamelog_action, uint &gamelog_actions)
 
{
 
	assert(gamelog_action == nullptr);
 
	assert(gamelog_actions == 0);
 
struct GLOGChunkHandler : ChunkHandler {
 
	GLOGChunkHandler() : ChunkHandler('GLOG', CH_TABLE)
 
	{
 
		this->load_check = true;
 
	}
 

	
 
	void LoadCommon(LoggedAction *&gamelog_action, uint &gamelog_actions) const
 
	{
 
		assert(gamelog_action == nullptr);
 
		assert(gamelog_actions == 0);
 

	
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_gamelog_desc, _gamelog_sl_compat);
 

	
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_gamelog_desc, _gamelog_sl_compat);
 
		if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
 
			byte type;
 
			while ((type = SlReadByte()) != GLAT_NONE) {
 
				if (type >= GLAT_END) SlErrorCorrupt("Invalid gamelog action type");
 

	
 
	if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
 
		byte type;
 
		while ((type = SlReadByte()) != GLAT_NONE) {
 
			if (type >= GLAT_END) SlErrorCorrupt("Invalid gamelog action type");
 
				gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1);
 
				LoggedAction *la = &gamelog_action[gamelog_actions++];
 
				memset(la, 0, sizeof(*la));
 

	
 
				la->at = (GamelogActionType)type;
 
				SlObject(la, slt);
 
			}
 
			return;
 
		}
 

	
 
		while (SlIterateArray() != -1) {
 
			gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1);
 
			LoggedAction *la = &gamelog_action[gamelog_actions++];
 
			memset(la, 0, sizeof(*la));
 

	
 
			la->at = (GamelogActionType)type;
 
			SlObject(la, slt);
 
		}
 
		return;
 
	}
 

	
 
	while (SlIterateArray() != -1) {
 
		gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1);
 
		LoggedAction *la = &gamelog_action[gamelog_actions++];
 
		memset(la, 0, sizeof(*la));
 
	void Save() const override
 
	{
 
		SlTableHeader(_gamelog_desc);
 

	
 
		const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
 

	
 
		SlObject(la, slt);
 
		uint i = 0;
 
		for (LoggedAction *la = _gamelog_action; la != laend; la++, i++) {
 
			SlSetArrayIndex(i);
 
			SlObject(la, _gamelog_desc);
 
		}
 
	}
 
}
 

	
 
static void Save_GLOG()
 
{
 
	SlTableHeader(_gamelog_desc);
 

	
 
	const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
 

	
 
	uint i = 0;
 
	for (LoggedAction *la = _gamelog_action; la != laend; la++, i++) {
 
		SlSetArrayIndex(i);
 
		SlObject(la, _gamelog_desc);
 
	void Load() const override
 
	{
 
		this->LoadCommon(_gamelog_action, _gamelog_actions);
 
	}
 
}
 

	
 
static void Load_GLOG()
 
{
 
	Load_GLOG_common(_gamelog_action, _gamelog_actions);
 
}
 
	void LoadCheck(size_t) const override
 
	{
 
		this->LoadCommon(_load_check_data.gamelog_action, _load_check_data.gamelog_actions);
 
	}
 
};
 

	
 
static void Check_GLOG()
 
{
 
	Load_GLOG_common(_load_check_data.gamelog_action, _load_check_data.gamelog_actions);
 
}
 

	
 
static const ChunkHandler GLOG{ 'GLOG', Save_GLOG, Load_GLOG, nullptr, Check_GLOG, CH_TABLE };
 
static const GLOGChunkHandler GLOG;
 
static const ChunkHandlerRef gamelog_chunk_handlers[] = {
 
	GLOG,
 
};
src/saveload/goal_sl.cpp
Show inline comments
 
@@ -25,28 +25,32 @@ static const SaveLoad _goals_desc[] = {
 
	SLE_CONDVAR(Goal, completed, SLE_BOOL, SLV_182, SL_MAX_VERSION),
 
};
 

	
 
static void Save_GOAL()
 
{
 
	SlTableHeader(_goals_desc);
 
struct GOALChunkHandler : ChunkHandler {
 
	GOALChunkHandler() : ChunkHandler('GOAL', CH_TABLE) {}
 

	
 
	for (Goal *s : Goal::Iterate()) {
 
		SlSetArrayIndex(s->index);
 
		SlObject(s, _goals_desc);
 
	void Save() const override
 
	{
 
		SlTableHeader(_goals_desc);
 

	
 
		for (Goal *s : Goal::Iterate()) {
 
			SlSetArrayIndex(s->index);
 
			SlObject(s, _goals_desc);
 
		}
 
	}
 
}
 

	
 
static void Load_GOAL()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_goals_desc, _goals_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_goals_desc, _goals_sl_compat);
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		Goal *s = new (index) Goal();
 
		SlObject(s, slt);
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			Goal *s = new (index) Goal();
 
			SlObject(s, slt);
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler GOAL{ 'GOAL', Save_GOAL, Load_GOAL, nullptr, nullptr, CH_TABLE };
 
static const GOALChunkHandler GOAL;
 
static const ChunkHandlerRef goal_chunk_handlers[] = {
 
	GOAL,
 
};
src/saveload/group_sl.cpp
Show inline comments
 
@@ -28,38 +28,42 @@ static const SaveLoad _group_desc[] = {
 
	 SLE_CONDVAR(Group, parent,             SLE_UINT16,                    SLV_189, SL_MAX_VERSION),
 
};
 

	
 
static void Save_GRPS()
 
{
 
	SlTableHeader(_group_desc);
 
struct GRPSChunkHandler : ChunkHandler {
 
	GRPSChunkHandler() : ChunkHandler('GRPS', CH_TABLE) {}
 

	
 
	for (Group *g : Group::Iterate()) {
 
		SlSetArrayIndex(g->index);
 
		SlObject(g, _group_desc);
 
	void Save() const override
 
	{
 
		SlTableHeader(_group_desc);
 

	
 
		for (Group *g : Group::Iterate()) {
 
			SlSetArrayIndex(g->index);
 
			SlObject(g, _group_desc);
 
		}
 
	}
 
}
 

	
 

	
 
static void Load_GRPS()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_group_desc, _group_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_group_desc, _group_sl_compat);
 

	
 
	int index;
 
		int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		Group *g = new (index) Group();
 
		SlObject(g, slt);
 
		while ((index = SlIterateArray()) != -1) {
 
			Group *g = new (index) Group();
 
			SlObject(g, slt);
 

	
 
			if (IsSavegameVersionBefore(SLV_189)) g->parent = INVALID_GROUP;
 

	
 
		if (IsSavegameVersionBefore(SLV_189)) g->parent = INVALID_GROUP;
 

	
 
		if (IsSavegameVersionBefore(SLV_GROUP_LIVERIES)) {
 
			const Company *c = Company::Get(g->owner);
 
			g->livery.colour1 = c->livery[LS_DEFAULT].colour1;
 
			g->livery.colour2 = c->livery[LS_DEFAULT].colour2;
 
			if (IsSavegameVersionBefore(SLV_GROUP_LIVERIES)) {
 
				const Company *c = Company::Get(g->owner);
 
				g->livery.colour1 = c->livery[LS_DEFAULT].colour1;
 
				g->livery.colour2 = c->livery[LS_DEFAULT].colour2;
 
			}
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler GRPS{ 'GRPS', Save_GRPS, Load_GRPS, nullptr, nullptr, CH_TABLE };
 
static const GRPSChunkHandler GRPS;
 
static const ChunkHandlerRef group_chunk_handlers[] = {
 
	GRPS,
 
};
src/saveload/industry_sl.cpp
Show inline comments
 
@@ -74,90 +74,108 @@ static const SaveLoad _industry_desc[] =
 
	SLE_CONDSSTR(Industry, text,     SLE_STR | SLF_ALLOW_CONTROL,     SLV_INDUSTRY_TEXT, SL_MAX_VERSION),
 
};
 

	
 
static void Save_INDY()
 
{
 
	SlTableHeader(_industry_desc);
 
struct INDYChunkHandler : ChunkHandler {
 
	INDYChunkHandler() : ChunkHandler('INDY', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 

	
 
	/* Write the industries */
 
	for (Industry *ind : Industry::Iterate()) {
 
		SlSetArrayIndex(ind->index);
 
		SlObject(ind, _industry_desc);
 
	}
 
}
 
	void Save() const override
 
	{
 
		SlTableHeader(_industry_desc);
 

	
 
static void Save_IIDS()
 
{
 
	Save_NewGRFMapping(_industry_mngr);
 
}
 
		/* Write the industries */
 
		for (Industry *ind : Industry::Iterate()) {
 
			SlSetArrayIndex(ind->index);
 
			SlObject(ind, _industry_desc);
 
		}
 
	}
 

	
 
static void Save_TIDS()
 
{
 
	Save_NewGRFMapping(_industile_mngr);
 
}
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_industry_desc, _industry_sl_compat);
 

	
 
		int index;
 

	
 
static void Load_INDY()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_industry_desc, _industry_sl_compat);
 
		Industry::ResetIndustryCounts();
 

	
 
	int index;
 

	
 
	Industry::ResetIndustryCounts();
 
		while ((index = SlIterateArray()) != -1) {
 
			Industry *i = new (index) Industry();
 
			SlObject(i, slt);
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		Industry *i = new (index) Industry();
 
		SlObject(i, slt);
 
			/* Before savegame version 161, persistent storages were not stored in a pool. */
 
			if (IsSavegameVersionBefore(SLV_161) && !IsSavegameVersionBefore(SLV_76)) {
 
				/* Store the old persistent storage. The GRFID will be added later. */
 
				assert(PersistentStorage::CanAllocateItem());
 
				i->psa = new PersistentStorage(0, 0, 0);
 
				memcpy(i->psa->storage, _old_ind_persistent_storage.storage, sizeof(_old_ind_persistent_storage.storage));
 
			}
 
			Industry::IncIndustryTypeCount(i->type);
 
		}
 
	}
 

	
 
		/* Before savegame version 161, persistent storages were not stored in a pool. */
 
		if (IsSavegameVersionBefore(SLV_161) && !IsSavegameVersionBefore(SLV_76)) {
 
			/* Store the old persistent storage. The GRFID will be added later. */
 
			assert(PersistentStorage::CanAllocateItem());
 
			i->psa = new PersistentStorage(0, 0, 0);
 
			memcpy(i->psa->storage, _old_ind_persistent_storage.storage, sizeof(_old_ind_persistent_storage.storage));
 
	void FixPointers() const override
 
	{
 
		for (Industry *i : Industry::Iterate()) {
 
			SlObject(i, _industry_desc);
 
		}
 
		Industry::IncIndustryTypeCount(i->type);
 
	}
 
}
 
};
 

	
 
struct IIDSChunkHandler : ChunkHandler {
 
	IIDSChunkHandler() : ChunkHandler('IIDS', CH_TABLE) {}
 

	
 
static void Load_IIDS()
 
{
 
	Load_NewGRFMapping(_industry_mngr);
 
}
 
	void Save() const override
 
	{
 
		Save_NewGRFMapping(_industry_mngr);
 
	}
 

	
 
	void Load() const override
 
	{
 
		Load_NewGRFMapping(_industry_mngr);
 
	}
 
};
 

	
 
static void Load_TIDS()
 
{
 
	Load_NewGRFMapping(_industile_mngr);
 
}
 
struct TIDSChunkHandler : ChunkHandler {
 
	TIDSChunkHandler() : ChunkHandler('TIDS', CH_TABLE) {}
 

	
 
static void Ptrs_INDY()
 
{
 
	for (Industry *i : Industry::Iterate()) {
 
		SlObject(i, _industry_desc);
 
	void Save() const override
 
	{
 
		Save_NewGRFMapping(_industile_mngr);
 
	}
 
}
 

	
 
	void Load() const override
 
	{
 
		Load_NewGRFMapping(_industile_mngr);
 
	}
 
};
 

	
 
/** Description of the data to save and load in #IndustryBuildData. */
 
static const SaveLoad _industry_builder_desc[] = {
 
	SLEG_VAR("wanted_inds", _industry_builder.wanted_inds, SLE_UINT32),
 
};
 

	
 
/** Save industry builder. */
 
static void Save_IBLD()
 
{
 
	SlTableHeader(_industry_builder_desc);
 
/** Industry builder. */
 
struct IBLDChunkHandler : ChunkHandler {
 
	IBLDChunkHandler() : ChunkHandler('IBLD', CH_TABLE) {}
 

	
 
	SlSetArrayIndex(0);
 
	SlGlobList(_industry_builder_desc);
 
}
 
	void Save() const override
 
	{
 
		SlTableHeader(_industry_builder_desc);
 

	
 
/** Load industry builder. */
 
static void Load_IBLD()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_industry_builder_desc, _industry_builder_sl_compat);
 
		SlSetArrayIndex(0);
 
		SlGlobList(_industry_builder_desc);
 
	}
 

	
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
	SlGlobList(slt);
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many IBLD entries");
 
}
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_industry_builder_desc, _industry_builder_sl_compat);
 

	
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
		SlGlobList(slt);
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many IBLD entries");
 
	}
 
};
 

	
 
/** Description of the data to save and load in #IndustryTypeBuildData. */
 
static const SaveLoad _industrytype_builder_desc[] = {
 
@@ -168,37 +186,40 @@ static const SaveLoad _industrytype_buil
 
	SLE_VAR(IndustryTypeBuildData, wait_count,   SLE_UINT16),
 
};
 

	
 
/** Save industry-type build data. */
 
static void Save_ITBL()
 
{
 
	SlTableHeader(_industrytype_builder_desc);
 
/** Industry-type build data. */
 
struct ITBLChunkHandler : ChunkHandler {
 
	ITBLChunkHandler() : ChunkHandler('ITBL', CH_TABLE) {}
 

	
 
	for (int i = 0; i < NUM_INDUSTRYTYPES; i++) {
 
		SlSetArrayIndex(i);
 
		SlObject(_industry_builder.builddata + i, _industrytype_builder_desc);
 
	void Save() const override
 
	{
 
		SlTableHeader(_industrytype_builder_desc);
 

	
 
		for (int i = 0; i < NUM_INDUSTRYTYPES; i++) {
 
			SlSetArrayIndex(i);
 
			SlObject(_industry_builder.builddata + i, _industrytype_builder_desc);
 
		}
 
	}
 
}
 

	
 
/** Load industry-type build data. */
 
static void Load_ITBL()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_industrytype_builder_desc, _industrytype_builder_sl_compat);
 

	
 
	for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
 
		_industry_builder.builddata[it].Reset();
 
	}
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		if ((uint)index >= NUM_INDUSTRYTYPES) SlErrorCorrupt("Too many industry builder datas");
 
		SlObject(_industry_builder.builddata + index, slt);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_industrytype_builder_desc, _industrytype_builder_sl_compat);
 

	
 
		for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
 
			_industry_builder.builddata[it].Reset();
 
		}
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			if ((uint)index >= NUM_INDUSTRYTYPES) SlErrorCorrupt("Too many industry builder datas");
 
			SlObject(_industry_builder.builddata + index, slt);
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler INDY{ 'INDY', Save_INDY, Load_INDY, Ptrs_INDY, nullptr, CH_TABLE };
 
static const ChunkHandler IIDS{ 'IIDS', Save_IIDS, Load_IIDS, nullptr,   nullptr, CH_TABLE };
 
static const ChunkHandler TIDS{ 'TIDS', Save_TIDS, Load_TIDS, nullptr,   nullptr, CH_TABLE };
 
static const ChunkHandler IBLD{ 'IBLD', Save_IBLD, Load_IBLD, nullptr,   nullptr, CH_TABLE };
 
static const ChunkHandler ITBL{ 'ITBL', Save_ITBL, Load_ITBL, nullptr,   nullptr, CH_TABLE };
 
static const INDYChunkHandler INDY;
 
static const IIDSChunkHandler IIDS;
 
static const TIDSChunkHandler TIDS;
 
static const IBLDChunkHandler IBLD;
 
static const ITBLChunkHandler ITBL;
 
static const ChunkHandlerRef industry_chunk_handlers[] = {
 
	INDY,
 
	IIDS,
src/saveload/labelmaps_sl.cpp
Show inline comments
 
@@ -99,35 +99,39 @@ static const SaveLoad _label_object_desc
 
	SLE_VAR(LabelObject, label, SLE_UINT32),
 
};
 

	
 
static void Save_RAIL()
 
{
 
	SlTableHeader(_label_object_desc);
 
struct RAILChunkHandler : ChunkHandler {
 
	RAILChunkHandler() : ChunkHandler('RAIL', CH_TABLE) {}
 

	
 
	LabelObject lo;
 
	void Save() const override
 
	{
 
		SlTableHeader(_label_object_desc);
 

	
 
	for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) {
 
		lo.label = GetRailTypeInfo(r)->label;
 
		LabelObject lo;
 

	
 
		for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) {
 
			lo.label = GetRailTypeInfo(r)->label;
 

	
 
		SlSetArrayIndex(r);
 
		SlObject(&lo, _label_object_desc);
 
			SlSetArrayIndex(r);
 
			SlObject(&lo, _label_object_desc);
 
		}
 
	}
 
}
 

	
 
static void Load_RAIL()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_label_object_desc, _label_object_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_label_object_desc, _label_object_sl_compat);
 

	
 
	ResetLabelMaps();
 
		ResetLabelMaps();
 

	
 
	LabelObject lo;
 
		LabelObject lo;
 

	
 
	while (SlIterateArray() != -1) {
 
		SlObject(&lo, slt);
 
		_railtype_list.push_back((RailTypeLabel)lo.label);
 
		while (SlIterateArray() != -1) {
 
			SlObject(&lo, slt);
 
			_railtype_list.push_back((RailTypeLabel)lo.label);
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler RAIL{ 'RAIL', Save_RAIL, Load_RAIL, nullptr, nullptr, CH_TABLE };
 
static const RAILChunkHandler RAIL;
 
static const ChunkHandlerRef labelmaps_chunk_handlers[] = {
 
	RAIL,
 
};
src/saveload/linkgraph_sl.cpp
Show inline comments
 
@@ -242,93 +242,96 @@ void AfterLoadLinkGraphs()
 
}
 

	
 
/**
 
 * Save all link graphs.
 
 * All link graphs.
 
 */
 
static void Save_LGRP()
 
{
 
	SlTableHeader(GetLinkGraphDesc());
 
struct LGRPChunkHandler : ChunkHandler {
 
	LGRPChunkHandler() : ChunkHandler('LGRP', CH_TABLE) {}
 

	
 
	for (LinkGraph *lg : LinkGraph::Iterate()) {
 
		SlSetArrayIndex(lg->index);
 
		SlObject(lg, GetLinkGraphDesc());
 
	}
 
}
 

	
 
/**
 
 * Load all link graphs.
 
 */
 
static void Load_LGRP()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphDesc(), _linkgraph_sl_compat);
 
	void Save() const override
 
	{
 
		SlTableHeader(GetLinkGraphDesc());
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		LinkGraph *lg = new (index) LinkGraph();
 
		SlObject(lg, slt);
 
		for (LinkGraph *lg : LinkGraph::Iterate()) {
 
			SlSetArrayIndex(lg->index);
 
			SlObject(lg, GetLinkGraphDesc());
 
		}
 
	}
 
}
 

	
 
/**
 
 * Save all link graph jobs.
 
 */
 
static void Save_LGRJ()
 
{
 
	SlTableHeader(GetLinkGraphJobDesc());
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphDesc(), _linkgraph_sl_compat);
 

	
 
	for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
 
		SlSetArrayIndex(lgj->index);
 
		SlObject(lgj, GetLinkGraphJobDesc());
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			LinkGraph *lg = new (index) LinkGraph();
 
			SlObject(lg, slt);
 
		}
 
	}
 
}
 
};
 

	
 
/**
 
 * Load all link graph jobs.
 
 * All link graph jobs.
 
 */
 
static void Load_LGRJ()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphJobDesc(), _linkgraph_job_sl_compat);
 
struct LGRJChunkHandler : ChunkHandler {
 
	LGRJChunkHandler() : ChunkHandler('LGRJ', CH_TABLE) {}
 

	
 
	void Save() const override
 
	{
 
		SlTableHeader(GetLinkGraphJobDesc());
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		LinkGraphJob *lgj = new (index) LinkGraphJob();
 
		SlObject(lgj, slt);
 
		for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
 
			SlSetArrayIndex(lgj->index);
 
			SlObject(lgj, GetLinkGraphJobDesc());
 
		}
 
	}
 
}
 

	
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphJobDesc(), _linkgraph_job_sl_compat);
 

	
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			LinkGraphJob *lgj = new (index) LinkGraphJob();
 
			SlObject(lgj, slt);
 
		}
 
	}
 
};
 

	
 
/**
 
 * Save the link graph schedule.
 
 * Link graph schedule.
 
 */
 
static void Save_LGRS()
 
{
 
	SlTableHeader(GetLinkGraphScheduleDesc());
 
struct LGRSChunkHandler : ChunkHandler {
 
	LGRSChunkHandler() : ChunkHandler('LGRS', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 

	
 
	SlSetArrayIndex(0);
 
	SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
 
}
 
	void Save() const override
 
	{
 
		SlTableHeader(GetLinkGraphScheduleDesc());
 

	
 
/**
 
 * Load the link graph schedule.
 
 */
 
static void Load_LGRS()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphScheduleDesc(), _linkgraph_schedule_sl_compat);
 
		SlSetArrayIndex(0);
 
		SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
 
	}
 

	
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
	SlObject(&LinkGraphSchedule::instance, slt);
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many LGRS entries");
 
}
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphScheduleDesc(), _linkgraph_schedule_sl_compat);
 

	
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
		SlObject(&LinkGraphSchedule::instance, slt);
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many LGRS entries");
 
	}
 

	
 
/**
 
 * Substitute pointers in link graph schedule.
 
 */
 
static void Ptrs_LGRS()
 
{
 
	SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
 
}
 
	void FixPointers() const override
 
	{
 
		SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
 
	}
 
};
 

	
 
static const ChunkHandler LGRP{ 'LGRP', Save_LGRP, Load_LGRP, nullptr,   nullptr, CH_TABLE };
 
static const ChunkHandler LGRJ{ 'LGRJ', Save_LGRJ, Load_LGRJ, nullptr,   nullptr, CH_TABLE };
 
static const ChunkHandler LGRS{ 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, nullptr, CH_TABLE };
 
static const LGRPChunkHandler LGRP;
 
static const LGRJChunkHandler LGRJ;
 
static const LGRSChunkHandler LGRS;
 
static const ChunkHandlerRef linkgraph_chunk_handlers[] = {
 
	LGRP,
 
	LGRJ,
src/saveload/map_sl.cpp
Show inline comments
 
@@ -27,299 +27,346 @@ static const SaveLoad _map_desc[] = {
 
	SLEG_CONDVAR("dim_y", _map_dim_y, SLE_UINT32, SLV_6, SL_MAX_VERSION),
 
};
 

	
 
static void Save_MAPS()
 
{
 
	SlTableHeader(_map_desc);
 

	
 
	_map_dim_x = MapSizeX();
 
	_map_dim_y = MapSizeY();
 
struct MAPSChunkHandler : ChunkHandler {
 
	MAPSChunkHandler() : ChunkHandler('MAPS', CH_TABLE)
 
	{
 
		this->load_check = true;
 
	}
 

	
 
	SlSetArrayIndex(0);
 
	SlGlobList(_map_desc);
 
}
 
	void Save() const override
 
	{
 
		SlTableHeader(_map_desc);
 

	
 
static void Load_MAPS()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_map_desc, _map_sl_compat);
 
		_map_dim_x = MapSizeX();
 
		_map_dim_y = MapSizeY();
 

	
 
		SlSetArrayIndex(0);
 
		SlGlobList(_map_desc);
 
	}
 

	
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
	SlGlobList(slt);
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_map_desc, _map_sl_compat);
 

	
 
	AllocateMap(_map_dim_x, _map_dim_y);
 
}
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
		SlGlobList(slt);
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
 

	
 
		AllocateMap(_map_dim_x, _map_dim_y);
 
	}
 

	
 
static void Check_MAPS()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_map_desc, _map_sl_compat);
 
	void LoadCheck(size_t) const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_map_desc, _map_sl_compat);
 

	
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
	SlGlobList(slt);
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
		SlGlobList(slt);
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
 

	
 
	_load_check_data.map_size_x = _map_dim_x;
 
	_load_check_data.map_size_y = _map_dim_y;
 
}
 
		_load_check_data.map_size_x = _map_dim_x;
 
		_load_check_data.map_size_y = _map_dim_y;
 
	}
 
};
 

	
 
static const uint MAP_SL_BUF_SIZE = 4096;
 

	
 
static void Load_MAPT()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
struct MAPTChunkHandler : ChunkHandler {
 
	MAPTChunkHandler() : ChunkHandler('MAPT', CH_RIFF) {}
 

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type = buf[j];
 
	}
 
}
 
	void Load() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
static void Save_MAPT()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 

	
 
	SlSetLength(size);
 
	for (TileIndex i = 0; i != size;) {
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type;
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		for (TileIndex i = 0; i != size;) {
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type = buf[j];
 
		}
 
	}
 
}
 

	
 
	void Save() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
static void Load_MAPH()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j];
 
		SlSetLength(size);
 
		for (TileIndex i = 0; i != size;) {
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type;
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		}
 
	}
 
}
 
};
 

	
 
struct MAPHChunkHandler : ChunkHandler {
 
	MAPHChunkHandler() : ChunkHandler('MAPH', CH_RIFF) {}
 

	
 
static void Save_MAPH()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
	void Load() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
	SlSetLength(size);
 
	for (TileIndex i = 0; i != size;) {
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].height;
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		for (TileIndex i = 0; i != size;) {
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j];
 
		}
 
	}
 
}
 

	
 
	void Save() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
static void Load_MAP1()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
		SlSetLength(size);
 
		for (TileIndex i = 0; i != size;) {
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].height;
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		}
 
	}
 
};
 

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m1 = buf[j];
 
struct MAPOChunkHandler : ChunkHandler {
 
	MAPOChunkHandler() : ChunkHandler('MAPO', CH_RIFF) {}
 

	
 
	void Load() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
		for (TileIndex i = 0; i != size;) {
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m1 = buf[j];
 
		}
 
	}
 
}
 

	
 
static void Save_MAP1()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 

	
 
	SlSetLength(size);
 
	for (TileIndex i = 0; i != size;) {
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m1;
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	void Save() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
		SlSetLength(size);
 
		for (TileIndex i = 0; i != size;) {
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m1;
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		}
 
	}
 
}
 
};
 

	
 
static void Load_MAP2()
 
{
 
	std::array<uint16, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
struct MAP2ChunkHandler : ChunkHandler {
 
	MAP2ChunkHandler() : ChunkHandler('MAP2', CH_RIFF) {}
 

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE,
 
			/* In those versions the m2 was 8 bits */
 
			IsSavegameVersionBefore(SLV_5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16
 
		);
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m2 = buf[j];
 
	void Load() const override
 
	{
 
		std::array<uint16, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
		for (TileIndex i = 0; i != size;) {
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE,
 
				/* In those versions the m2 was 8 bits */
 
				IsSavegameVersionBefore(SLV_5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16
 
			);
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m2 = buf[j];
 
		}
 
	}
 
}
 

	
 
static void Save_MAP2()
 
{
 
	std::array<uint16, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
	void Save() const override
 
	{
 
		std::array<uint16, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
	SlSetLength(size * sizeof(uint16));
 
	for (TileIndex i = 0; i != size;) {
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m2;
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
		SlSetLength(size * sizeof(uint16));
 
		for (TileIndex i = 0; i != size;) {
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m2;
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
		}
 
	}
 
}
 
};
 

	
 
struct M3LOChunkHandler : ChunkHandler {
 
	M3LOChunkHandler() : ChunkHandler('M3LO', CH_RIFF) {}
 

	
 
static void Load_MAP3()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
	void Load() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m3 = buf[j];
 
		for (TileIndex i = 0; i != size;) {
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m3 = buf[j];
 
		}
 
	}
 
}
 

	
 
	void Save() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
static void Save_MAP3()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 

	
 
	SlSetLength(size);
 
	for (TileIndex i = 0; i != size;) {
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m3;
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		SlSetLength(size);
 
		for (TileIndex i = 0; i != size;) {
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m3;
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		}
 
	}
 
}
 
};
 

	
 
struct M3HIChunkHandler : ChunkHandler {
 
	M3HIChunkHandler() : ChunkHandler('M3HI', CH_RIFF) {}
 

	
 
	void Load() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
static void Load_MAP4()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
		for (TileIndex i = 0; i != size;) {
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m4 = buf[j];
 
		}
 
	}
 

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m4 = buf[j];
 
	}
 
}
 
	void Save() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
static void Save_MAP4()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 

	
 
	SlSetLength(size);
 
	for (TileIndex i = 0; i != size;) {
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m4;
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		SlSetLength(size);
 
		for (TileIndex i = 0; i != size;) {
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m4;
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		}
 
	}
 
}
 
};
 

	
 
struct MAP5ChunkHandler : ChunkHandler {
 
	MAP5ChunkHandler() : ChunkHandler('MAP5', CH_RIFF) {}
 

	
 
	void Load() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
static void Load_MAP5()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
		for (TileIndex i = 0; i != size;) {
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m5 = buf[j];
 
		}
 
	}
 

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m5 = buf[j];
 
	}
 
}
 
	void Save() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
static void Save_MAP5()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
		SlSetLength(size);
 
		for (TileIndex i = 0; i != size;) {
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m5;
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		}
 
	}
 
};
 

	
 
	SlSetLength(size);
 
	for (TileIndex i = 0; i != size;) {
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m5;
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	}
 
}
 
struct MAPEChunkHandler : ChunkHandler {
 
	MAPEChunkHandler() : ChunkHandler('MAPE', CH_RIFF) {}
 

	
 
	void Load() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
static void Load_MAP6()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 

	
 
	if (IsSavegameVersionBefore(SLV_42)) {
 
		for (TileIndex i = 0; i != size;) {
 
			/* 1024, otherwise we overflow on 64x64 maps! */
 
			SlCopy(buf.data(), 1024, SLE_UINT8);
 
			for (uint j = 0; j != 1024; j++) {
 
				_me[i++].m6 = GB(buf[j], 0, 2);
 
				_me[i++].m6 = GB(buf[j], 2, 2);
 
				_me[i++].m6 = GB(buf[j], 4, 2);
 
				_me[i++].m6 = GB(buf[j], 6, 2);
 
		if (IsSavegameVersionBefore(SLV_42)) {
 
			for (TileIndex i = 0; i != size;) {
 
				/* 1024, otherwise we overflow on 64x64 maps! */
 
				SlCopy(buf.data(), 1024, SLE_UINT8);
 
				for (uint j = 0; j != 1024; j++) {
 
					_me[i++].m6 = GB(buf[j], 0, 2);
 
					_me[i++].m6 = GB(buf[j], 2, 2);
 
					_me[i++].m6 = GB(buf[j], 4, 2);
 
					_me[i++].m6 = GB(buf[j], 6, 2);
 
				}
 
			}
 
		} else {
 
			for (TileIndex i = 0; i != size;) {
 
				SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
				for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m6 = buf[j];
 
			}
 
		}
 
	} else {
 
	}
 

	
 
	void Save() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
		SlSetLength(size);
 
		for (TileIndex i = 0; i != size;) {
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m6;
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		}
 
	}
 
};
 

	
 
struct MAP7ChunkHandler : ChunkHandler {
 
	MAP7ChunkHandler() : ChunkHandler('MAP7', CH_RIFF) {}
 

	
 
	void Load() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
		for (TileIndex i = 0; i != size;) {
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m6 = buf[j];
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m7 = buf[j];
 
		}
 
	}
 

	
 
	void Save() const override
 
	{
 
		std::array<byte, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
		SlSetLength(size);
 
		for (TileIndex i = 0; i != size;) {
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m7;
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		}
 
	}
 
}
 

	
 
static void Save_MAP6()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
};
 

	
 
	SlSetLength(size);
 
	for (TileIndex i = 0; i != size;) {
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m6;
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	}
 
}
 
struct MAP8ChunkHandler : ChunkHandler {
 
	MAP8ChunkHandler() : ChunkHandler('MAP8', CH_RIFF) {}
 

	
 
static void Load_MAP7()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
	void Load() const override
 
	{
 
		std::array<uint16, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m7 = buf[j];
 
	}
 
}
 

	
 
static void Save_MAP7()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 

	
 
	SlSetLength(size);
 
	for (TileIndex i = 0; i != size;) {
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m7;
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		for (TileIndex i = 0; i != size;) {
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m8 = buf[j];
 
		}
 
	}
 
}
 

	
 
static void Load_MAP8()
 
{
 
	std::array<uint16, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m8 = buf[j];
 
	}
 
}
 

	
 
static void Save_MAP8()
 
{
 
	std::array<uint16, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 
	void Save() const override
 
	{
 
		std::array<uint16, MAP_SL_BUF_SIZE> buf;
 
		TileIndex size = MapSize();
 

	
 
	SlSetLength(size * sizeof(uint16));
 
	for (TileIndex i = 0; i != size;) {
 
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m8;
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
		SlSetLength(size * sizeof(uint16));
 
		for (TileIndex i = 0; i != size;) {
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m8;
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler MAPS{ 'MAPS', Save_MAPS, Load_MAPS, nullptr, Check_MAPS, CH_TABLE };
 
static const ChunkHandler MAPT{ 'MAPT', Save_MAPT, Load_MAPT, nullptr, nullptr,    CH_RIFF };
 
static const ChunkHandler MAPH{ 'MAPH', Save_MAPH, Load_MAPH, nullptr, nullptr,    CH_RIFF };
 
static const ChunkHandler MAPO{ 'MAPO', Save_MAP1, Load_MAP1, nullptr, nullptr,    CH_RIFF };
 
static const ChunkHandler MAP2{ 'MAP2', Save_MAP2, Load_MAP2, nullptr, nullptr,    CH_RIFF };
 
static const ChunkHandler M3LO{ 'M3LO', Save_MAP3, Load_MAP3, nullptr, nullptr,    CH_RIFF };
 
static const ChunkHandler M3HI{ 'M3HI', Save_MAP4, Load_MAP4, nullptr, nullptr,    CH_RIFF };
 
static const ChunkHandler MAP5{ 'MAP5', Save_MAP5, Load_MAP5, nullptr, nullptr,    CH_RIFF };
 
static const ChunkHandler MAPE{ 'MAPE', Save_MAP6, Load_MAP6, nullptr, nullptr,    CH_RIFF };
 
static const ChunkHandler MAP7{ 'MAP7', Save_MAP7, Load_MAP7, nullptr, nullptr,    CH_RIFF };
 
static const ChunkHandler MAP8{ 'MAP8', Save_MAP8, Load_MAP8, nullptr, nullptr,    CH_RIFF };
 
static const MAPSChunkHandler MAPS;
 
static const MAPTChunkHandler MAPT;
 
static const MAPHChunkHandler MAPH;
 
static const MAPOChunkHandler MAPO;
 
static const MAP2ChunkHandler MAP2;
 
static const M3LOChunkHandler M3LO;
 
static const M3HIChunkHandler M3HI;
 
static const MAP5ChunkHandler MAP5;
 
static const MAPEChunkHandler MAPE;
 
static const MAP7ChunkHandler MAP7;
 
static const MAP8ChunkHandler MAP8;
 
static const ChunkHandlerRef map_chunk_handlers[] = {
 
	MAPS,
 
	MAPT,
src/saveload/misc_sl.cpp
Show inline comments
 
@@ -95,37 +95,44 @@ static const SaveLoad _date_check_desc[]
 

	
 
/* Save load date related variables as well as persistent tick counters
 
 * XXX: currently some unrelated stuff is just put here */
 
static void Save_DATE()
 
{
 
	SlTableHeader(_date_desc);
 
struct DATEChunkHandler : ChunkHandler {
 
	DATEChunkHandler() : ChunkHandler('DATE', CH_TABLE)
 
	{
 
		this->load_check = true;
 
	}
 

	
 
	SlSetArrayIndex(0);
 
	SlGlobList(_date_desc);
 
}
 
	void Save() const override
 
	{
 
		SlTableHeader(_date_desc);
 

	
 
static void Load_DATE_common(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
 
{
 
	const std::vector<SaveLoad> oslt = SlCompatTableHeader(slt, slct);
 
		SlSetArrayIndex(0);
 
		SlGlobList(_date_desc);
 
	}
 

	
 
	void LoadCommon(const SaveLoadTable &slt, const SaveLoadCompatTable &slct) const
 
	{
 
		const std::vector<SaveLoad> oslt = SlCompatTableHeader(slt, slct);
 

	
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
	SlGlobList(oslt);
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries");
 
}
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
		SlGlobList(oslt);
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries");
 
	}
 

	
 
static void Load_DATE()
 
{
 
	Load_DATE_common(_date_desc, _date_sl_compat);
 
}
 
	void Load() const override
 
	{
 
		this->LoadCommon(_date_desc, _date_sl_compat);
 
	}
 

	
 
static void Check_DATE()
 
{
 
	Load_DATE_common(_date_check_desc, _date_check_sl_compat);
 

	
 
	void LoadCheck(size_t) const override
 
	{
 
		this->LoadCommon(_date_check_desc, _date_check_sl_compat);
 

	
 
	if (IsSavegameVersionBefore(SLV_31)) {
 
		_load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
 
		if (IsSavegameVersionBefore(SLV_31)) {
 
			_load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
 
		}
 
	}
 
}
 

	
 
};
 

	
 
static const SaveLoad _view_desc[] = {
 
	SLEG_CONDVAR("x",    _saved_scrollpos_x,    SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
 
@@ -135,25 +142,29 @@ static const SaveLoad _view_desc[] = {
 
	    SLEG_VAR("zoom", _saved_scrollpos_zoom, SLE_UINT8),
 
};
 

	
 
static void Save_VIEW()
 
{
 
	SlTableHeader(_view_desc);
 
struct VIEWChunkHandler : ChunkHandler {
 
	VIEWChunkHandler() : ChunkHandler('VIEW', CH_TABLE) {}
 

	
 
	SlSetArrayIndex(0);
 
	SlGlobList(_view_desc);
 
}
 
	void Save() const override
 
	{
 
		SlTableHeader(_view_desc);
 

	
 
		SlSetArrayIndex(0);
 
		SlGlobList(_view_desc);
 
	}
 

	
 
static void Load_VIEW()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_view_desc, _view_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_view_desc, _view_sl_compat);
 

	
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
	SlGlobList(slt);
 
	if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries");
 
}
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
 
		SlGlobList(slt);
 
		if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries");
 
	}
 
};
 

	
 
static const ChunkHandler DATE{ 'DATE', Save_DATE, Load_DATE, nullptr, Check_DATE, CH_TABLE };
 
static const ChunkHandler VIEW{ 'VIEW', Save_VIEW, Load_VIEW, nullptr, nullptr,    CH_TABLE };
 
static const DATEChunkHandler DATE;
 
static const VIEWChunkHandler VIEW;
 
static const ChunkHandlerRef misc_chunk_handlers[] = {
 
	DATE,
 
	VIEW,
src/saveload/newgrf_sl.cpp
Show inline comments
 
@@ -73,55 +73,62 @@ static const SaveLoad _grfconfig_desc[] 
 
};
 

	
 

	
 
static void Save_NGRF()
 
{
 
	SlTableHeader(_grfconfig_desc);
 

	
 
	int index = 0;
 
struct NGRFChunkHandler : ChunkHandler {
 
	NGRFChunkHandler() : ChunkHandler('NGRF', CH_TABLE)
 
	{
 
		this->load_check = true;
 
	}
 

	
 
	for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
 
		if (HasBit(c->flags, GCF_STATIC)) continue;
 
		SlSetArrayIndex(index++);
 
		SlObject(c, _grfconfig_desc);
 
	void Save() const override
 
	{
 
		SlTableHeader(_grfconfig_desc);
 

	
 
		int index = 0;
 

	
 
		for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
 
			if (HasBit(c->flags, GCF_STATIC)) continue;
 
			SlSetArrayIndex(index++);
 
			SlObject(c, _grfconfig_desc);
 
		}
 
	}
 
}
 

	
 

	
 
static void Load_NGRF_common(GRFConfig *&grfconfig)
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_grfconfig_desc, _grfconfig_sl_compat);
 
	void LoadCommon(GRFConfig *&grfconfig) const
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_grfconfig_desc, _grfconfig_sl_compat);
 

	
 
	ClearGRFConfigList(&grfconfig);
 
	while (SlIterateArray() != -1) {
 
		GRFConfig *c = new GRFConfig();
 
		SlObject(c, slt);
 
		if (IsSavegameVersionBefore(SLV_101)) c->SetSuitablePalette();
 
		AppendToGRFConfigList(&grfconfig, c);
 
		ClearGRFConfigList(&grfconfig);
 
		while (SlIterateArray() != -1) {
 
			GRFConfig *c = new GRFConfig();
 
			SlObject(c, slt);
 
			if (IsSavegameVersionBefore(SLV_101)) c->SetSuitablePalette();
 
			AppendToGRFConfigList(&grfconfig, c);
 
		}
 
	}
 
}
 

	
 
static void Load_NGRF()
 
{
 
	Load_NGRF_common(_grfconfig);
 
	void Load() const override
 
	{
 
		this->LoadCommon(_grfconfig);
 

	
 
	if (_game_mode == GM_MENU) {
 
		/* Intro game must not have NewGRF. */
 
		if (_grfconfig != nullptr) SlErrorCorrupt("The intro game must not use NewGRF");
 
		if (_game_mode == GM_MENU) {
 
			/* Intro game must not have NewGRF. */
 
			if (_grfconfig != nullptr) SlErrorCorrupt("The intro game must not use NewGRF");
 

	
 
		/* Activate intro NewGRFs (townnames) */
 
		ResetGRFConfig(false);
 
	} else {
 
		/* Append static NewGRF configuration */
 
		AppendStaticGRFConfigs(&_grfconfig);
 
			/* Activate intro NewGRFs (townnames) */
 
			ResetGRFConfig(false);
 
		} else {
 
			/* Append static NewGRF configuration */
 
			AppendStaticGRFConfigs(&_grfconfig);
 
		}
 
	}
 
}
 

	
 
static void Check_NGRF()
 
{
 
	Load_NGRF_common(_load_check_data.grfconfig);
 
}
 
	void LoadCheck(size_t) const override
 
	{
 
		this->LoadCommon(_load_check_data.grfconfig);
 
	}
 
};
 

	
 
static const ChunkHandler NGRF{ 'NGRF', Save_NGRF, Load_NGRF, nullptr, Check_NGRF, CH_TABLE };
 
static const NGRFChunkHandler NGRF;
 
static const ChunkHandlerRef newgrf_chunk_handlers[] = {
 
	NGRF,
 
};
src/saveload/object_sl.cpp
Show inline comments
 
@@ -29,51 +29,62 @@ static const SaveLoad _object_desc[] = {
 
	SLE_CONDVAR(Object, type,                       SLE_UINT16,                 SLV_186, SL_MAX_VERSION),
 
};
 

	
 
static void Save_OBJS()
 
{
 
	SlTableHeader(_object_desc);
 
struct OBJSChunkHandler : ChunkHandler {
 
	OBJSChunkHandler() : ChunkHandler('OBJS', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 

	
 
	/* Write the objects */
 
	for (Object *o : Object::Iterate()) {
 
		SlSetArrayIndex(o->index);
 
		SlObject(o, _object_desc);
 
	}
 
}
 

	
 
static void Load_OBJS()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_object_desc, _object_sl_compat);
 
	void Save() const override
 
	{
 
		SlTableHeader(_object_desc);
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		Object *o = new (index) Object();
 
		SlObject(o, slt);
 
		/* Write the objects */
 
		for (Object *o : Object::Iterate()) {
 
			SlSetArrayIndex(o->index);
 
			SlObject(o, _object_desc);
 
		}
 
	}
 
}
 

	
 
static void Ptrs_OBJS()
 
{
 
	for (Object *o : Object::Iterate()) {
 
		SlObject(o, _object_desc);
 
		if (IsSavegameVersionBefore(SLV_148) && !IsTileType(o->location.tile, MP_OBJECT)) {
 
			/* Due to a small bug stale objects could remain. */
 
			delete o;
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_object_desc, _object_sl_compat);
 

	
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			Object *o = new (index) Object();
 
			SlObject(o, slt);
 
		}
 
	}
 
}
 

	
 
static void Save_OBID()
 
{
 
	Save_NewGRFMapping(_object_mngr);
 
}
 
	void FixPointers() const override
 
	{
 
		for (Object *o : Object::Iterate()) {
 
			SlObject(o, _object_desc);
 
			if (IsSavegameVersionBefore(SLV_148) && !IsTileType(o->location.tile, MP_OBJECT)) {
 
				/* Due to a small bug stale objects could remain. */
 
				delete o;
 
			}
 
		}
 
	}
 
};
 

	
 
static void Load_OBID()
 
{
 
	Load_NewGRFMapping(_object_mngr);
 
}
 
struct OBIDChunkHandler : ChunkHandler {
 
	OBIDChunkHandler() : ChunkHandler('OBID', CH_TABLE) {}
 

	
 
	void Save() const override
 
	{
 
		Save_NewGRFMapping(_object_mngr);
 
	}
 

	
 
static const ChunkHandler OBID{ 'OBID', Save_OBID, Load_OBID, nullptr,   nullptr, CH_TABLE };
 
static const ChunkHandler OBJS{ 'OBJS', Save_OBJS, Load_OBJS, Ptrs_OBJS, nullptr, CH_TABLE };
 
	void Load() const override
 
	{
 
		Load_NewGRFMapping(_object_mngr);
 
	}
 
};
 

	
 
static const OBIDChunkHandler OBID;
 
static const OBJSChunkHandler OBJS;
 
static const ChunkHandlerRef object_chunk_handlers[] = {
 
	OBID,
 
	OBJS,
src/saveload/order_sl.cpp
Show inline comments
 
@@ -118,85 +118,92 @@ SaveLoadTable GetOrderDescription()
 
	return _order_desc;
 
}
 

	
 
static void Save_ORDR()
 
{
 
	const SaveLoadTable slt = GetOrderDescription();
 
	SlTableHeader(slt);
 

	
 
	for (Order *order : Order::Iterate()) {
 
		SlSetArrayIndex(order->index);
 
		SlObject(order, slt);
 
struct ORDRChunkHandler : ChunkHandler {
 
	ORDRChunkHandler() : ChunkHandler('ORDR', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 
}
 

	
 
static void Load_ORDR()
 
{
 
	if (IsSavegameVersionBefore(SLV_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) */
 
		size_t len = SlGetFieldLength();
 

	
 
		if (IsSavegameVersionBefore(SLV_5)) {
 
			/* Pre-version 5 had another layout for orders
 
			 * (uint16 instead of uint32) */
 
			len /= sizeof(uint16);
 
			uint16 *orders = MallocT<uint16>(len + 1);
 

	
 
			SlCopy(orders, len, SLE_UINT16);
 

	
 
			for (size_t i = 0; i < len; ++i) {
 
				Order *o = new (i) Order();
 
				o->AssignOrder(UnpackVersion4Order(orders[i]));
 
			}
 

	
 
			free(orders);
 
		} else if (IsSavegameVersionBefore(SLV_5, 2)) {
 
			len /= sizeof(uint32);
 
			uint32 *orders = MallocT<uint32>(len + 1);
 

	
 
			SlCopy(orders, len, SLE_UINT32);
 

	
 
			for (size_t i = 0; i < len; ++i) {
 
				new (i) Order(orders[i]);
 
			}
 

	
 
			free(orders);
 
		}
 
	void Save() const override
 
	{
 
		const SaveLoadTable slt = GetOrderDescription();
 
		SlTableHeader(slt);
 

	
 
		/* Update all the next pointer */
 
		for (Order *o : Order::Iterate()) {
 
			size_t order_index = o->index;
 
			/* Delete invalid orders */
 
			if (o->IsType(OT_NOTHING)) {
 
				delete o;
 
				continue;
 
			}
 
			/* The orders were built like this:
 
			 * While the order is valid, set the previous will get its next pointer set */
 
			Order *prev = Order::GetIfValid(order_index - 1);
 
			if (prev != nullptr) prev->next = o;
 
		}
 
	} else {
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderDescription(), _order_sl_compat);
 

	
 
		int index;
 

	
 
		while ((index = SlIterateArray()) != -1) {
 
			Order *order = new (index) Order();
 
		for (Order *order : Order::Iterate()) {
 
			SlSetArrayIndex(order->index);
 
			SlObject(order, slt);
 
		}
 
	}
 
}
 

	
 
	void Load() const override
 
	{
 
		if (IsSavegameVersionBefore(SLV_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) */
 
			size_t len = SlGetFieldLength();
 

	
 
			if (IsSavegameVersionBefore(SLV_5)) {
 
				/* Pre-version 5 had another layout for orders
 
				 * (uint16 instead of uint32) */
 
				len /= sizeof(uint16);
 
				uint16 *orders = MallocT<uint16>(len + 1);
 

	
 
				SlCopy(orders, len, SLE_UINT16);
 

	
 
				for (size_t i = 0; i < len; ++i) {
 
					Order *o = new (i) Order();
 
					o->AssignOrder(UnpackVersion4Order(orders[i]));
 
				}
 

	
 
				free(orders);
 
			} else if (IsSavegameVersionBefore(SLV_5, 2)) {
 
				len /= sizeof(uint32);
 
				uint32 *orders = MallocT<uint32>(len + 1);
 

	
 
				SlCopy(orders, len, SLE_UINT32);
 

	
 
				for (size_t i = 0; i < len; ++i) {
 
					new (i) Order(orders[i]);
 
				}
 

	
 
				free(orders);
 
			}
 

	
 
static void Ptrs_ORDR()
 
{
 
	/* Orders from old savegames have pointers corrected in Load_ORDR */
 
	if (IsSavegameVersionBefore(SLV_5, 2)) return;
 
			/* Update all the next pointer */
 
			for (Order *o : Order::Iterate()) {
 
				size_t order_index = o->index;
 
				/* Delete invalid orders */
 
				if (o->IsType(OT_NOTHING)) {
 
					delete o;
 
					continue;
 
				}
 
				/* The orders were built like this:
 
				 * While the order is valid, set the previous will get its next pointer set */
 
				Order *prev = Order::GetIfValid(order_index - 1);
 
				if (prev != nullptr) prev->next = o;
 
			}
 
		} else {
 
			const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderDescription(), _order_sl_compat);
 

	
 
			int index;
 

	
 
	for (Order *o : Order::Iterate()) {
 
		SlObject(o, GetOrderDescription());
 
			while ((index = SlIterateArray()) != -1) {
 
				Order *order = new (index) Order();
 
				SlObject(order, slt);
 
			}
 
		}
 
	}
 
}
 

	
 
	void FixPointers() const override
 
	{
 
		/* Orders from old savegames have pointers corrected in Load_ORDR */
 
		if (IsSavegameVersionBefore(SLV_5, 2)) return;
 

	
 
		for (Order *o : Order::Iterate()) {
 
			SlObject(o, GetOrderDescription());
 
		}
 
	}
 
};
 

	
 
SaveLoadTable GetOrderListDescription()
 
{
 
@@ -207,37 +214,44 @@ SaveLoadTable GetOrderListDescription()
 
	return _orderlist_desc;
 
}
 

	
 
static void Save_ORDL()
 
{
 
	const SaveLoadTable slt = GetOrderListDescription();
 
	SlTableHeader(slt);
 

	
 
	for (OrderList *list : OrderList::Iterate()) {
 
		SlSetArrayIndex(list->index);
 
		SlObject(list, slt);
 
struct ORDLChunkHandler : ChunkHandler {
 
	ORDLChunkHandler() : ChunkHandler('ORDL', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 
}
 

	
 
static void Load_ORDL()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderListDescription(), _orderlist_sl_compat);
 
	void Save() const override
 
	{
 
		const SaveLoadTable slt = GetOrderListDescription();
 
		SlTableHeader(slt);
 

	
 
	int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		/* set num_orders to 0 so it's a valid OrderList */
 
		OrderList *list = new (index) OrderList(0);
 
		SlObject(list, slt);
 
		for (OrderList *list : OrderList::Iterate()) {
 
			SlSetArrayIndex(list->index);
 
			SlObject(list, slt);
 
		}
 
	}
 

	
 
}
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderListDescription(), _orderlist_sl_compat);
 

	
 
		int index;
 

	
 
static void Ptrs_ORDL()
 
{
 
	for (OrderList *list : OrderList::Iterate()) {
 
		SlObject(list, GetOrderListDescription());
 
		while ((index = SlIterateArray()) != -1) {
 
			/* set num_orders to 0 so it's a valid OrderList */
 
			OrderList *list = new (index) OrderList(0);
 
			SlObject(list, slt);
 
		}
 

	
 
	}
 
}
 

	
 
	void FixPointers() const override
 
	{
 
		for (OrderList *list : OrderList::Iterate()) {
 
			SlObject(list, GetOrderListDescription());
 
		}
 
	}
 
};
 

	
 
SaveLoadTable GetOrderBackupDescription()
 
{
 
@@ -262,45 +276,52 @@ SaveLoadTable GetOrderBackupDescription(
 
	return _order_backup_desc;
 
}
 

	
 
static void Save_BKOR()
 
{
 
	const SaveLoadTable slt = GetOrderBackupDescription();
 
	SlTableHeader(slt);
 
struct BKORChunkHandler : ChunkHandler {
 
	BKORChunkHandler() : ChunkHandler('BKOR', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 

	
 
	/* We only save this when we're a network server
 
	 * as we want this information on our clients. For
 
	 * normal games this information isn't needed. */
 
	if (!_networking || !_network_server) return;
 
	void Save() const override
 
	{
 
		const SaveLoadTable slt = GetOrderBackupDescription();
 
		SlTableHeader(slt);
 

	
 
	for (OrderBackup *ob : OrderBackup::Iterate()) {
 
		SlSetArrayIndex(ob->index);
 
		SlObject(ob, slt);
 
		/* We only save this when we're a network server
 
		 * as we want this information on our clients. For
 
		 * normal games this information isn't needed. */
 
		if (!_networking || !_network_server) return;
 

	
 
		for (OrderBackup *ob : OrderBackup::Iterate()) {
 
			SlSetArrayIndex(ob->index);
 
			SlObject(ob, slt);
 
		}
 
	}
 
}
 

	
 
void Load_BKOR()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderBackupDescription(), _order_backup_sl_compat);
 

	
 
	int index;
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderBackupDescription(), _order_backup_sl_compat);
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		/* set num_orders to 0 so it's a valid OrderList */
 
		OrderBackup *ob = new (index) OrderBackup();
 
		SlObject(ob, slt);
 
	}
 
}
 
		int index;
 

	
 
static void Ptrs_BKOR()
 
{
 
	for (OrderBackup *ob : OrderBackup::Iterate()) {
 
		SlObject(ob, GetOrderBackupDescription());
 
		while ((index = SlIterateArray()) != -1) {
 
			/* set num_orders to 0 so it's a valid OrderList */
 
			OrderBackup *ob = new (index) OrderBackup();
 
			SlObject(ob, slt);
 
		}
 
	}
 
}
 

	
 
static const ChunkHandler BKOR{ 'BKOR', Save_BKOR, Load_BKOR, Ptrs_BKOR, nullptr, CH_TABLE };
 
static const ChunkHandler ORDR{ 'ORDR', Save_ORDR, Load_ORDR, Ptrs_ORDR, nullptr, CH_TABLE };
 
static const ChunkHandler ORDL{ 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, nullptr, CH_TABLE };
 
	void FixPointers() const override
 
	{
 
		for (OrderBackup *ob : OrderBackup::Iterate()) {
 
			SlObject(ob, GetOrderBackupDescription());
 
		}
 
	}
 
};
 

	
 
static const BKORChunkHandler BKOR;
 
static const ORDRChunkHandler ORDR;
 
static const ORDLChunkHandler ORDL;
 
static const ChunkHandlerRef order_chunk_handlers[] = {
 
	BKOR,
 
	ORDR,
src/saveload/settings_sl.cpp
Show inline comments
 
@@ -142,36 +142,47 @@ static void SaveSettings(const SettingTa
 
	SlObject(object, slt);
 
}
 

	
 
static void Load_OPTS()
 
{
 
	/* Copy over default setting since some might not get loaded in
 
	 * a networking environment. This ensures for example that the local
 
	 * autosave-frequency stays when joining a network-server */
 
	PrepareOldDiffCustom();
 
	LoadSettings(_gameopt_settings, &_settings_game, _gameopt_sl_compat);
 
	HandleOldDiffCustom(true);
 
}
 
struct OPTSChunkHandler : ChunkHandler {
 
	OPTSChunkHandler() : ChunkHandler('OPTS', CH_READONLY) {}
 

	
 
	void Load() const override
 
	{
 
		/* Copy over default setting since some might not get loaded in
 
		 * a networking environment. This ensures for example that the local
 
		 * autosave-frequency stays when joining a network-server */
 
		PrepareOldDiffCustom();
 
		LoadSettings(_gameopt_settings, &_settings_game, _gameopt_sl_compat);
 
		HandleOldDiffCustom(true);
 
	}
 
};
 

	
 
struct PATSChunkHandler : ChunkHandler {
 
	PATSChunkHandler() : ChunkHandler('PATS', CH_TABLE)
 
	{
 
		this->load_check = true;
 
	}
 

	
 
static void Load_PATS()
 
{
 
	/* Copy over default setting since some might not get loaded in
 
	 * a networking environment. This ensures for example that the local
 
	 * currency setting stays when joining a network-server */
 
	LoadSettings(_settings, &_settings_game, _settings_sl_compat);
 
}
 
	void Load() const override
 
	{
 
		/* Copy over default setting since some might not get loaded in
 
		 * a networking environment. This ensures for example that the local
 
		 * currency setting stays when joining a network-server */
 
		LoadSettings(_settings, &_settings_game, _settings_sl_compat);
 
	}
 

	
 
static void Check_PATS()
 
{
 
	LoadSettings(_settings, &_load_check_data.settings, _settings_sl_compat);
 
}
 
	void LoadCheck(size_t) const override
 
	{
 
		LoadSettings(_settings, &_load_check_data.settings, _settings_sl_compat);
 
	}
 

	
 
static void Save_PATS()
 
{
 
	SaveSettings(_settings, &_settings_game);
 
}
 
	void Save() const override
 
	{
 
		SaveSettings(_settings, &_settings_game);
 
	}
 
};
 

	
 
static const ChunkHandler OPTS{ 'OPTS', nullptr,   Load_OPTS, nullptr, nullptr,    CH_READONLY };
 
static const ChunkHandler PATS{ 'PATS', Save_PATS, Load_PATS, nullptr, Check_PATS, CH_TABLE };
 
static const OPTSChunkHandler OPTS;
 
static const PATSChunkHandler PATS;
 
static const ChunkHandlerRef setting_chunk_handlers[] = {
 
	OPTS,
 
	PATS,
src/saveload/signs_sl.cpp
Show inline comments
 
@@ -30,44 +30,46 @@ static const SaveLoad _sign_desc[] = {
 
	SLE_CONDVAR(Sign, z,     SLE_INT32,                SLV_164, SL_MAX_VERSION),
 
};
 

	
 
/** Save all signs */
 
static void Save_SIGN()
 
{
 
	SlTableHeader(_sign_desc);
 

	
 
	for (Sign *si : Sign::Iterate()) {
 
		SlSetArrayIndex(si->index);
 
		SlObject(si, _sign_desc);
 
	}
 
}
 

	
 
/** Load all signs */
 
static void Load_SIGN()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_sign_desc, _sign_sl_compat);
 
struct SIGNChunkHandler : ChunkHandler {
 
	SIGNChunkHandler() : ChunkHandler('SIGN', CH_TABLE) {}
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		Sign *si = new (index) Sign();
 
		SlObject(si, slt);
 
		/* Before version 6.1, signs didn't have owner.
 
		 * Before version 83, invalid signs were determined by si->str == 0.
 
		 * Before version 103, owner could be a bankrupted company.
 
		 *  - we can't use IsValidCompany() now, so this is fixed in AfterLoadGame()
 
		 * All signs that were saved are valid (including those with just 'Sign' and INVALID_OWNER).
 
		 *  - so set owner to OWNER_NONE if needed (signs from pre-version 6.1 would be lost) */
 
		if (IsSavegameVersionBefore(SLV_6, 1) || (IsSavegameVersionBefore(SLV_83) && si->owner == INVALID_OWNER)) {
 
			si->owner = OWNER_NONE;
 
		}
 
	void Save() const override
 
	{
 
		SlTableHeader(_sign_desc);
 

	
 
		/* Signs placed in scenario editor shall now be OWNER_DEITY */
 
		if (IsSavegameVersionBefore(SLV_171) && si->owner == OWNER_NONE && _file_to_saveload.abstract_ftype == FT_SCENARIO) {
 
			si->owner = OWNER_DEITY;
 
		for (Sign *si : Sign::Iterate()) {
 
			SlSetArrayIndex(si->index);
 
			SlObject(si, _sign_desc);
 
		}
 
	}
 
}
 

	
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_sign_desc, _sign_sl_compat);
 

	
 
static const ChunkHandler SIGN{ 'SIGN', Save_SIGN, Load_SIGN, nullptr, nullptr, CH_TABLE };
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			Sign *si = new (index) Sign();
 
			SlObject(si, slt);
 
			/* Before version 6.1, signs didn't have owner.
 
			 * Before version 83, invalid signs were determined by si->str == 0.
 
			 * Before version 103, owner could be a bankrupted company.
 
			 *  - we can't use IsValidCompany() now, so this is fixed in AfterLoadGame()
 
			 * All signs that were saved are valid (including those with just 'Sign' and INVALID_OWNER).
 
			 *  - so set owner to OWNER_NONE if needed (signs from pre-version 6.1 would be lost) */
 
			if (IsSavegameVersionBefore(SLV_6, 1) || (IsSavegameVersionBefore(SLV_83) && si->owner == INVALID_OWNER)) {
 
				si->owner = OWNER_NONE;
 
			}
 

	
 
			/* Signs placed in scenario editor shall now be OWNER_DEITY */
 
			if (IsSavegameVersionBefore(SLV_171) && si->owner == OWNER_NONE && _file_to_saveload.abstract_ftype == FT_SCENARIO) {
 
				si->owner = OWNER_DEITY;
 
			}
 
		}
 
	}
 
};
 

	
 
static const SIGNChunkHandler SIGN;
 
static const ChunkHandlerRef sign_chunk_handlers[] = {
 
	SIGN,
 
};
src/saveload/station_sl.cpp
Show inline comments
 
@@ -484,34 +484,41 @@ static const SaveLoad _old_station_desc[
 
	SLEG_CONDSTRUCTLIST("speclist", SlStationSpecList,                           SLV_27, SL_MAX_VERSION),
 
};
 

	
 
static void Load_STNS()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_old_station_desc, _old_station_sl_compat);
 
struct STNSChunkHandler : ChunkHandler {
 
	STNSChunkHandler() : ChunkHandler('STNS', CH_READONLY)
 
	{
 
		this->fix_pointers = true;
 
	}
 

	
 
	_cargo_source_xy = 0;
 
	_cargo_days = 0;
 
	_cargo_feeder_share = 0;
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_old_station_desc, _old_station_sl_compat);
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		Station *st = new (index) Station();
 
		_cargo_source_xy = 0;
 
		_cargo_days = 0;
 
		_cargo_feeder_share = 0;
 

	
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			Station *st = new (index) Station();
 

	
 
		_waiting_acceptance = 0;
 
		SlObject(st, slt);
 
			_waiting_acceptance = 0;
 
			SlObject(st, slt);
 
		}
 
	}
 
}
 

	
 
static void Ptrs_STNS()
 
{
 
	/* From SLV_123 we store stations in STNN; before that in STNS. So do not
 
	 * fix pointers when the version is SLV_123 or up, as that would fix
 
	 * pointers twice: once in STNN chunk and once here. */
 
	if (!IsSavegameVersionBefore(SLV_123)) return;
 
	void FixPointers() const override
 
	{
 
		/* From SLV_123 we store stations in STNN; before that in STNS. So do not
 
		 * fix pointers when the version is SLV_123 or up, as that would fix
 
		 * pointers twice: once in STNN chunk and once here. */
 
		if (!IsSavegameVersionBefore(SLV_123)) return;
 

	
 
	for (Station *st : Station::Iterate()) {
 
		SlObject(st, _old_station_desc);
 
		for (Station *st : Station::Iterate()) {
 
			SlObject(st, _old_station_desc);
 
		}
 
	}
 
}
 
};
 

	
 
/**
 
 * SaveLoad handler for the BaseStation, which all other stations / waypoints
 
@@ -651,77 +658,92 @@ static const SaveLoad _station_desc[] = 
 
	SLEG_CONDSTRUCTLIST("speclist", SlStationSpecList, SLV_27, SL_MAX_VERSION),
 
};
 

	
 
static void Save_STNN()
 
{
 
	SlTableHeader(_station_desc);
 
struct STNNChunkHandler : ChunkHandler {
 
	STNNChunkHandler() : ChunkHandler('STNN', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 

	
 
	/* Write the stations */
 
	for (BaseStation *st : BaseStation::Iterate()) {
 
		SlSetArrayIndex(st->index);
 
		SlObject(st, _station_desc);
 
	}
 
}
 

	
 
static void Load_STNN()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_station_desc, _station_sl_compat);
 

	
 
	_old_num_flows = 0;
 
	void Save() const override
 
	{
 
		SlTableHeader(_station_desc);
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0;
 
		/* Write the stations */
 
		for (BaseStation *st : BaseStation::Iterate()) {
 
			SlSetArrayIndex(st->index);
 
			SlObject(st, _station_desc);
 
		}
 
	}
 

	
 
		BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station();
 
		SlObject(bst, slt);
 
	}
 
}
 

	
 
static void Ptrs_STNN()
 
{
 
	/* From SLV_123 we store stations in STNN; before that in STNS. So do not
 
	 * fix pointers when the version is below SLV_123, as that would fix
 
	 * pointers twice: once in STNS chunk and once here. */
 
	if (IsSavegameVersionBefore(SLV_123)) return;
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_station_desc, _station_sl_compat);
 

	
 
		_old_num_flows = 0;
 

	
 
	for (BaseStation *bst : BaseStation::Iterate()) {
 
		SlObject(bst, _station_desc);
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0;
 

	
 
			BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station();
 
			SlObject(bst, slt);
 
		}
 
	}
 
}
 

	
 
static void Save_ROADSTOP()
 
{
 
	SlTableHeader(_roadstop_desc);
 
	void FixPointers() const override
 
	{
 
		/* From SLV_123 we store stations in STNN; before that in STNS. So do not
 
		 * fix pointers when the version is below SLV_123, as that would fix
 
		 * pointers twice: once in STNS chunk and once here. */
 
		if (IsSavegameVersionBefore(SLV_123)) return;
 

	
 
	for (RoadStop *rs : RoadStop::Iterate()) {
 
		SlSetArrayIndex(rs->index);
 
		SlObject(rs, _roadstop_desc);
 
		for (BaseStation *bst : BaseStation::Iterate()) {
 
			SlObject(bst, _station_desc);
 
		}
 
	}
 
}
 
};
 

	
 
static void Load_ROADSTOP()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_roadstop_desc, _roadstop_sl_compat);
 
struct ROADChunkHandler : ChunkHandler {
 
	ROADChunkHandler() : ChunkHandler('ROAD', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 

	
 
	int index;
 
	void Save() const override
 
	{
 
		SlTableHeader(_roadstop_desc);
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		RoadStop *rs = new (index) RoadStop(INVALID_TILE);
 
		for (RoadStop *rs : RoadStop::Iterate()) {
 
			SlSetArrayIndex(rs->index);
 
			SlObject(rs, _roadstop_desc);
 
		}
 
	}
 

	
 
		SlObject(rs, slt);
 
	}
 
}
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_roadstop_desc, _roadstop_sl_compat);
 

	
 
		int index;
 

	
 
		while ((index = SlIterateArray()) != -1) {
 
			RoadStop *rs = new (index) RoadStop(INVALID_TILE);
 

	
 
static void Ptrs_ROADSTOP()
 
{
 
	for (RoadStop *rs : RoadStop::Iterate()) {
 
		SlObject(rs, _roadstop_desc);
 
			SlObject(rs, slt);
 
		}
 
	}
 
}
 

	
 
static const ChunkHandler STNS{ 'STNS', nullptr,       Load_STNS,     Ptrs_STNS,     nullptr, CH_READONLY };
 
static const ChunkHandler STNN{ 'STNN', Save_STNN,     Load_STNN,     Ptrs_STNN,     nullptr, CH_TABLE };
 
static const ChunkHandler ROAD{ 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, nullptr, CH_TABLE };
 
	void FixPointers() const override
 
	{
 
		for (RoadStop *rs : RoadStop::Iterate()) {
 
			SlObject(rs, _roadstop_desc);
 
		}
 
	}
 
};
 

	
 
static const STNSChunkHandler STNS;
 
static const STNNChunkHandler STNN;
 
static const ROADChunkHandler ROAD;
 
static const ChunkHandlerRef station_chunk_handlers[] = {
 
	STNS,
 
	STNN,
src/saveload/storage_sl.cpp
Show inline comments
 
@@ -23,34 +23,37 @@ static const SaveLoad _storage_desc[] = 
 
	 SLE_CONDARR(PersistentStorage, storage,  SLE_UINT32, 256,           SLV_EXTEND_PERSISTENT_STORAGE, SL_MAX_VERSION),
 
};
 

	
 
/** Load persistent storage data. */
 
static void Load_PSAC()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_storage_desc, _storage_sl_compat);
 

	
 
	int index;
 
/** Persistent storage data. */
 
struct PSACChunkHandler : ChunkHandler {
 
	PSACChunkHandler() : ChunkHandler('PSAC', CH_TABLE) {}
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		assert(PersistentStorage::CanAllocateItem());
 
		PersistentStorage *ps = new (index) PersistentStorage(0, 0, 0);
 
		SlObject(ps, slt);
 
	}
 
}
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_storage_desc, _storage_sl_compat);
 

	
 
		int index;
 

	
 
/** Save persistent storage data. */
 
static void Save_PSAC()
 
{
 
	SlTableHeader(_storage_desc);
 
		while ((index = SlIterateArray()) != -1) {
 
			assert(PersistentStorage::CanAllocateItem());
 
			PersistentStorage *ps = new (index) PersistentStorage(0, 0, 0);
 
			SlObject(ps, slt);
 
		}
 
	}
 

	
 
	void Save() const override
 
	{
 
		SlTableHeader(_storage_desc);
 

	
 
	/* Write the industries */
 
	for (PersistentStorage *ps : PersistentStorage::Iterate()) {
 
		ps->ClearChanges();
 
		SlSetArrayIndex(ps->index);
 
		SlObject(ps, _storage_desc);
 
		/* Write the industries */
 
		for (PersistentStorage *ps : PersistentStorage::Iterate()) {
 
			ps->ClearChanges();
 
			SlSetArrayIndex(ps->index);
 
			SlObject(ps, _storage_desc);
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler PSAC{ 'PSAC', Save_PSAC, Load_PSAC, nullptr, nullptr, CH_TABLE };
 
static const PSACChunkHandler PSAC;
 
static const ChunkHandlerRef persistent_storage_chunk_handlers[] = {
 
	PSAC,
 
};
src/saveload/story_sl.cpp
Show inline comments
 
@@ -38,34 +38,38 @@ static const SaveLoad _story_page_elemen
 
	    SLE_STR(StoryPageElement, text,          SLE_STR | SLF_ALLOW_CONTROL, 0),
 
};
 

	
 
static void Save_STORY_PAGE_ELEMENT()
 
{
 
	SlTableHeader(_story_page_elements_desc);
 

	
 
	for (StoryPageElement *s : StoryPageElement::Iterate()) {
 
		SlSetArrayIndex(s->index);
 
		SlObject(s, _story_page_elements_desc);
 
	}
 
}
 
struct STPEChunkHandler : ChunkHandler {
 
	STPEChunkHandler() : ChunkHandler('STPE', CH_TABLE) {}
 

	
 
static void Load_STORY_PAGE_ELEMENT()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_story_page_elements_desc, _story_page_elements_sl_compat);
 
	void Save() const override
 
	{
 
		SlTableHeader(_story_page_elements_desc);
 

	
 
	int index;
 
	uint32 max_sort_value = 0;
 
	while ((index = SlIterateArray()) != -1) {
 
		StoryPageElement *s = new (index) StoryPageElement();
 
		SlObject(s, slt);
 
		if (s->sort_value > max_sort_value) {
 
			max_sort_value = s->sort_value;
 
		for (StoryPageElement *s : StoryPageElement::Iterate()) {
 
			SlSetArrayIndex(s->index);
 
			SlObject(s, _story_page_elements_desc);
 
		}
 
	}
 
	/* Update the next sort value, so that the next
 
	 * created page is shown after all existing pages.
 
	 */
 
	_story_page_element_next_sort_value = max_sort_value + 1;
 
}
 

	
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_story_page_elements_desc, _story_page_elements_sl_compat);
 

	
 
		int index;
 
		uint32 max_sort_value = 0;
 
		while ((index = SlIterateArray()) != -1) {
 
			StoryPageElement *s = new (index) StoryPageElement();
 
			SlObject(s, slt);
 
			if (s->sort_value > max_sort_value) {
 
				max_sort_value = s->sort_value;
 
			}
 
		}
 
		/* Update the next sort value, so that the next
 
		 * created page is shown after all existing pages.
 
		 */
 
		_story_page_element_next_sort_value = max_sort_value + 1;
 
	}
 
};
 

	
 
static const SaveLoad _story_pages_desc[] = {
 
	SLE_CONDVAR(StoryPage, sort_value, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION,   SLV_185),
 
@@ -76,37 +80,41 @@ static const SaveLoad _story_pages_desc[
 
	    SLE_STR(StoryPage, title,      SLE_STR | SLF_ALLOW_CONTROL, 0),
 
};
 

	
 
static void Save_STORY_PAGE()
 
{
 
	SlTableHeader(_story_pages_desc);
 

	
 
	for (StoryPage *s : StoryPage::Iterate()) {
 
		SlSetArrayIndex(s->index);
 
		SlObject(s, _story_pages_desc);
 
	}
 
}
 
struct STPAChunkHandler : ChunkHandler {
 
	STPAChunkHandler() : ChunkHandler('STPA', CH_TABLE) {}
 

	
 
static void Load_STORY_PAGE()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_story_pages_desc, _story_pages_sl_compat);
 
	void Save() const override
 
	{
 
		SlTableHeader(_story_pages_desc);
 

	
 
	int index;
 
	uint32 max_sort_value = 0;
 
	while ((index = SlIterateArray()) != -1) {
 
		StoryPage *s = new (index) StoryPage();
 
		SlObject(s, slt);
 
		if (s->sort_value > max_sort_value) {
 
			max_sort_value = s->sort_value;
 
		for (StoryPage *s : StoryPage::Iterate()) {
 
			SlSetArrayIndex(s->index);
 
			SlObject(s, _story_pages_desc);
 
		}
 
	}
 
	/* Update the next sort value, so that the next
 
	 * created page is shown after all existing pages.
 
	 */
 
	_story_page_next_sort_value = max_sort_value + 1;
 
}
 

	
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_story_pages_desc, _story_pages_sl_compat);
 

	
 
static const ChunkHandler STPE{ 'STPE', Save_STORY_PAGE_ELEMENT, Load_STORY_PAGE_ELEMENT, nullptr, nullptr, CH_TABLE };
 
static const ChunkHandler STPA{ 'STPA', Save_STORY_PAGE,         Load_STORY_PAGE,         nullptr, nullptr, CH_TABLE };
 
		int index;
 
		uint32 max_sort_value = 0;
 
		while ((index = SlIterateArray()) != -1) {
 
			StoryPage *s = new (index) StoryPage();
 
			SlObject(s, slt);
 
			if (s->sort_value > max_sort_value) {
 
				max_sort_value = s->sort_value;
 
			}
 
		}
 
		/* Update the next sort value, so that the next
 
		 * created page is shown after all existing pages.
 
		 */
 
		_story_page_next_sort_value = max_sort_value + 1;
 
	}
 
};
 

	
 
static const STPEChunkHandler STPE;
 
static const STPAChunkHandler STPA;
 
static const ChunkHandlerRef story_page_chunk_handlers[] = {
 
	STPE,
 
	STPA,
src/saveload/strings_sl.cpp
Show inline comments
 
@@ -113,24 +113,25 @@ void InitializeOldNames()
 
	_old_name_array = CallocT<char>(NUM_OLD_STRINGS * LEN_OLD_STRINGS); // 200 * 24 would be enough for TTO savegames
 
}
 

	
 
/**
 
 * Load the NAME chunk.
 
 */
 
static void Load_NAME()
 
{
 
	int index;
 
struct NAMEChunkHandler : ChunkHandler {
 
	NAMEChunkHandler() : ChunkHandler('NAME', CH_READONLY) {}
 

	
 
	void Load() const override
 
	{
 
		int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		if (index >= NUM_OLD_STRINGS) SlErrorCorrupt("Invalid old name index");
 
		if (SlGetFieldLength() > (uint)LEN_OLD_STRINGS) SlErrorCorrupt("Invalid old name length");
 
		while ((index = SlIterateArray()) != -1) {
 
			if (index >= NUM_OLD_STRINGS) SlErrorCorrupt("Invalid old name index");
 
			if (SlGetFieldLength() > (uint)LEN_OLD_STRINGS) SlErrorCorrupt("Invalid old name length");
 

	
 
		SlCopy(&_old_name_array[LEN_OLD_STRINGS * index], SlGetFieldLength(), SLE_UINT8);
 
		/* Make sure the old name is null terminated */
 
		_old_name_array[LEN_OLD_STRINGS * index + LEN_OLD_STRINGS - 1] = '\0';
 
			SlCopy(&_old_name_array[LEN_OLD_STRINGS * index], SlGetFieldLength(), SLE_UINT8);
 
			/* Make sure the old name is null terminated */
 
			_old_name_array[LEN_OLD_STRINGS * index + LEN_OLD_STRINGS - 1] = '\0';
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler NAME{ 'NAME', nullptr, Load_NAME, nullptr, nullptr, CH_READONLY };
 
static const NAMEChunkHandler NAME;
 
static const ChunkHandlerRef name_chunk_handlers[] = {
 
	NAME,
 
};
src/saveload/subsidy_sl.cpp
Show inline comments
 
@@ -29,28 +29,32 @@ static const SaveLoad _subsidies_desc[] 
 
	SLE_CONDVAR(Subsidy, dst,        SLE_UINT16,                                      SLV_5, SL_MAX_VERSION),
 
};
 

	
 
static void Save_SUBS()
 
{
 
	SlTableHeader(_subsidies_desc);
 
struct SUBSChunkHandler : ChunkHandler {
 
	SUBSChunkHandler() : ChunkHandler('SUBS', CH_TABLE) {}
 

	
 
	for (Subsidy *s : Subsidy::Iterate()) {
 
		SlSetArrayIndex(s->index);
 
		SlObject(s, _subsidies_desc);
 
	void Save() const override
 
	{
 
		SlTableHeader(_subsidies_desc);
 

	
 
		for (Subsidy *s : Subsidy::Iterate()) {
 
			SlSetArrayIndex(s->index);
 
			SlObject(s, _subsidies_desc);
 
		}
 
	}
 
}
 

	
 
static void Load_SUBS()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_subsidies_desc, _subsidies_sl_compat);
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_subsidies_desc, _subsidies_sl_compat);
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		Subsidy *s = new (index) Subsidy();
 
		SlObject(s, slt);
 
		int index;
 
		while ((index = SlIterateArray()) != -1) {
 
			Subsidy *s = new (index) Subsidy();
 
			SlObject(s, slt);
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler SUBS{ 'SUBS', Save_SUBS, Load_SUBS, nullptr, nullptr, CH_TABLE };
 
static const SUBSChunkHandler SUBS;
 
static const ChunkHandlerRef subsidy_chunk_handlers[] = {
 
	SUBS,
 
};
src/saveload/town_sl.cpp
Show inline comments
 
@@ -272,54 +272,64 @@ static const SaveLoad _town_desc[] = {
 
	SLEG_CONDSTRUCTLIST("acceptance_matrix", SlTownAcceptanceMatrix,   SLV_166, SLV_REMOVE_TOWN_CARGO_CACHE),
 
};
 

	
 
static void Save_HIDS()
 
{
 
	Save_NewGRFMapping(_house_mngr);
 
}
 
struct HIDSChunkHandler : ChunkHandler {
 
	HIDSChunkHandler() : ChunkHandler('HIDS', CH_TABLE) {}
 

	
 
static void Load_HIDS()
 
{
 
	Load_NewGRFMapping(_house_mngr);
 
}
 
	void Save() const override
 
	{
 
		Save_NewGRFMapping(_house_mngr);
 
	}
 

	
 
static void Save_TOWN()
 
{
 
	SlTableHeader(_town_desc);
 
	void Load() const override
 
	{
 
		Load_NewGRFMapping(_house_mngr);
 
	}
 
};
 

	
 
	for (Town *t : Town::Iterate()) {
 
		SlSetArrayIndex(t->index);
 
		SlObject(t, _town_desc);
 
struct CITYChunkHandler : ChunkHandler {
 
	CITYChunkHandler() : ChunkHandler('CITY', CH_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 
}
 

	
 
static void Load_TOWN()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_town_desc, _town_sl_compat);
 

	
 
	int index;
 
	void Save() const override
 
	{
 
		SlTableHeader(_town_desc);
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		Town *t = new (index) Town();
 
		SlObject(t, slt);
 

	
 
		if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GetStringTab(t->townnametype) != TEXT_TAB_OLD_CUSTOM) {
 
			SlErrorCorrupt("Invalid town name generator");
 
		for (Town *t : Town::Iterate()) {
 
			SlSetArrayIndex(t->index);
 
			SlObject(t, _town_desc);
 
		}
 
	}
 
}
 

	
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_town_desc, _town_sl_compat);
 

	
 
/** Fix pointers when loading town data. */
 
static void Ptrs_TOWN()
 
{
 
	if (IsSavegameVersionBefore(SLV_161)) return;
 
		int index;
 

	
 
		while ((index = SlIterateArray()) != -1) {
 
			Town *t = new (index) Town();
 
			SlObject(t, slt);
 

	
 
	for (Town *t : Town::Iterate()) {
 
		SlObject(t, _town_desc);
 
			if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GetStringTab(t->townnametype) != TEXT_TAB_OLD_CUSTOM) {
 
				SlErrorCorrupt("Invalid town name generator");
 
			}
 
		}
 
	}
 
}
 

	
 
	void FixPointers() const override
 
	{
 
		if (IsSavegameVersionBefore(SLV_161)) return;
 

	
 
static const ChunkHandler HIDS{ 'HIDS', Save_HIDS, Load_HIDS, nullptr,   nullptr, CH_TABLE };
 
static const ChunkHandler CITY{ 'CITY', Save_TOWN, Load_TOWN, Ptrs_TOWN, nullptr, CH_TABLE };
 
		for (Town *t : Town::Iterate()) {
 
			SlObject(t, _town_desc);
 
		}
 
	}
 
};
 

	
 
static const HIDSChunkHandler HIDS;
 
static const CITYChunkHandler CITY;
 
static const ChunkHandlerRef town_chunk_handlers[] = {
 
	HIDS,
 
	CITY,
src/saveload/vehicle_sl.cpp
Show inline comments
 
@@ -994,77 +994,82 @@ const static SaveLoad _vehicle_desc[] = 
 
	SLEG_STRUCT("disaster", SlVehicleDisaster),
 
};
 

	
 
/** Will be called when the vehicles need to be saved. */
 
static void Save_VEHS()
 
{
 
	SlTableHeader(_vehicle_desc);
 
struct VEHSChunkHandler : ChunkHandler {
 
	VEHSChunkHandler() : ChunkHandler('VEHS', CH_SPARSE_TABLE)
 
	{
 
		this->fix_pointers = true;
 
	}
 

	
 
	/* Write the vehicles */
 
	for (Vehicle *v : Vehicle::Iterate()) {
 
		SlSetArrayIndex(v->index);
 
		SlObject(v, _vehicle_desc);
 
	}
 
}
 

	
 
/** Will be called when vehicles need to be loaded. */
 
void Load_VEHS()
 
{
 
	const std::vector<SaveLoad> slt = SlCompatTableHeader(_vehicle_desc, _vehicle_sl_compat);
 
	void Save() const override
 
	{
 
		SlTableHeader(_vehicle_desc);
 

	
 
	int index;
 

	
 
	_cargo_count = 0;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		Vehicle *v;
 
		VehicleType vtype = (VehicleType)SlReadByte();
 
		/* Write the vehicles */
 
		for (Vehicle *v : Vehicle::Iterate()) {
 
			SlSetArrayIndex(v->index);
 
			SlObject(v, _vehicle_desc);
 
		}
 
	}
 

	
 
		switch (vtype) {
 
			case VEH_TRAIN:    v = new (index) Train();           break;
 
			case VEH_ROAD:     v = new (index) RoadVehicle();     break;
 
			case VEH_SHIP:     v = new (index) Ship();            break;
 
			case VEH_AIRCRAFT: v = new (index) Aircraft();        break;
 
			case VEH_EFFECT:   v = new (index) EffectVehicle();   break;
 
			case VEH_DISASTER: v = new (index) DisasterVehicle(); break;
 
			case VEH_INVALID: // Savegame shouldn't contain invalid vehicles
 
			default: SlErrorCorrupt("Invalid vehicle type");
 
		}
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_vehicle_desc, _vehicle_sl_compat);
 

	
 
		int index;
 

	
 
		_cargo_count = 0;
 

	
 
		while ((index = SlIterateArray()) != -1) {
 
			Vehicle *v;
 
			VehicleType vtype = (VehicleType)SlReadByte();
 

	
 
		SlObject(v, slt);
 
			switch (vtype) {
 
				case VEH_TRAIN:    v = new (index) Train();           break;
 
				case VEH_ROAD:     v = new (index) RoadVehicle();     break;
 
				case VEH_SHIP:     v = new (index) Ship();            break;
 
				case VEH_AIRCRAFT: v = new (index) Aircraft();        break;
 
				case VEH_EFFECT:   v = new (index) EffectVehicle();   break;
 
				case VEH_DISASTER: v = new (index) DisasterVehicle(); break;
 
				case VEH_INVALID: // Savegame shouldn't contain invalid vehicles
 
				default: SlErrorCorrupt("Invalid vehicle type");
 
			}
 

	
 
		if (_cargo_count != 0 && IsCompanyBuildableVehicleType(v) && CargoPacket::CanAllocateItem()) {
 
			/* Don't construct the packet with station here, because that'll fail with old savegames */
 
			CargoPacket *cp = new CargoPacket(_cargo_count, _cargo_days, _cargo_source, _cargo_source_xy, _cargo_loaded_at_xy, _cargo_feeder_share);
 
			v->cargo.Append(cp);
 
		}
 
			SlObject(v, slt);
 

	
 
		/* Old savegames used 'last_station_visited = 0xFF' */
 
		if (IsSavegameVersionBefore(SLV_5) && v->last_station_visited == 0xFF) {
 
			v->last_station_visited = INVALID_STATION;
 
		}
 
			if (_cargo_count != 0 && IsCompanyBuildableVehicleType(v) && CargoPacket::CanAllocateItem()) {
 
				/* Don't construct the packet with station here, because that'll fail with old savegames */
 
				CargoPacket *cp = new CargoPacket(_cargo_count, _cargo_days, _cargo_source, _cargo_source_xy, _cargo_loaded_at_xy, _cargo_feeder_share);
 
				v->cargo.Append(cp);
 
			}
 

	
 
		if (IsSavegameVersionBefore(SLV_182)) v->last_loading_station = INVALID_STATION;
 
			/* Old savegames used 'last_station_visited = 0xFF' */
 
			if (IsSavegameVersionBefore(SLV_5) && v->last_station_visited == 0xFF) {
 
				v->last_station_visited = INVALID_STATION;
 
			}
 

	
 
		if (IsSavegameVersionBefore(SLV_5)) {
 
			/* Convert the current_order.type (which is a mix of type and flags, because
 
			 *  in those versions, they both were 4 bits big) to type and flags */
 
			v->current_order.flags = GB(v->current_order.type, 4, 4);
 
			v->current_order.type &= 0x0F;
 
			if (IsSavegameVersionBefore(SLV_182)) v->last_loading_station = INVALID_STATION;
 

	
 
			if (IsSavegameVersionBefore(SLV_5)) {
 
				/* Convert the current_order.type (which is a mix of type and flags, because
 
				 *  in those versions, they both were 4 bits big) to type and flags */
 
				v->current_order.flags = GB(v->current_order.type, 4, 4);
 
				v->current_order.type &= 0x0F;
 
			}
 

	
 
			/* Advanced vehicle lists got added */
 
			if (IsSavegameVersionBefore(SLV_60)) v->group_id = DEFAULT_GROUP;
 
		}
 

	
 
		/* Advanced vehicle lists got added */
 
		if (IsSavegameVersionBefore(SLV_60)) v->group_id = DEFAULT_GROUP;
 
	}
 
}
 

	
 
void Ptrs_VEHS()
 
{
 
	for (Vehicle *v : Vehicle::Iterate()) {
 
		SlObject(v, _vehicle_desc);
 
	void FixPointers() const override
 
	{
 
		for (Vehicle *v : Vehicle::Iterate()) {
 
			SlObject(v, _vehicle_desc);
 
		}
 
	}
 
}
 
};
 

	
 
static const ChunkHandler VEHS{ 'VEHS', Save_VEHS, Load_VEHS, Ptrs_VEHS, nullptr, CH_SPARSE_TABLE };
 
static const VEHSChunkHandler VEHS;
 
static const ChunkHandlerRef veh_chunk_handlers[] = {
 
	VEHS,
 
};
src/saveload/waypoint_sl.cpp
Show inline comments
 
@@ -182,49 +182,56 @@ static const SaveLoad _old_waypoint_desc
 
	SLE_CONDVAR(OldWaypoint, owner,      SLE_UINT8,                 SLV_101, SL_MAX_VERSION),
 
};
 

	
 
static void Load_WAYP()
 
{
 
	/* Precaution for when loading failed and it didn't get cleared */
 
	ResetOldWaypoints();
 

	
 
	int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		OldWaypoint *wp = &_old_waypoints.emplace_back();
 

	
 
		wp->index = index;
 
		SlObject(wp, _old_waypoint_desc);
 
struct CHKPChunkHandler : ChunkHandler {
 
	CHKPChunkHandler() : ChunkHandler('CHKP', CH_READONLY)
 
	{
 
		this->fix_pointers = true;
 
	}
 
}
 

	
 
static void Ptrs_WAYP()
 
{
 
	for (OldWaypoint &wp : _old_waypoints) {
 
		SlObject(&wp, _old_waypoint_desc);
 
	void Load() const override
 
	{
 
		/* Precaution for when loading failed and it didn't get cleared */
 
		ResetOldWaypoints();
 

	
 
		if (IsSavegameVersionBefore(SLV_12)) {
 
			wp.town_cn = (wp.string_id & 0xC000) == 0xC000 ? (wp.string_id >> 8) & 0x3F : 0;
 
			wp.town = ClosestTownFromTile(wp.xy, UINT_MAX);
 
		} else if (IsSavegameVersionBefore(SLV_122)) {
 
			/* Only for versions 12 .. 122 */
 
			if (!Town::IsValidID(wp.town_index)) {
 
				/* Upon a corrupted waypoint we'll likely get here. The next step will be to
 
				 * loop over all Ptrs procs to nullptr the pointers. However, we don't know
 
				 * whether we're in the nullptr or "normal" Ptrs proc. So just clear the list
 
				 * of old waypoints we constructed and then this waypoint (and the other
 
				 * possibly corrupt ones) will not be queried in the nullptr Ptrs proc run. */
 
				_old_waypoints.clear();
 
				SlErrorCorrupt("Referencing invalid Town");
 
			}
 
			wp.town = Town::Get(wp.town_index);
 
		}
 
		if (IsSavegameVersionBefore(SLV_84)) {
 
			wp.name = CopyFromOldName(wp.string_id);
 
		int index;
 

	
 
		while ((index = SlIterateArray()) != -1) {
 
			OldWaypoint *wp = &_old_waypoints.emplace_back();
 

	
 
			wp->index = index;
 
			SlObject(wp, _old_waypoint_desc);
 
		}
 
	}
 
}
 

	
 
	void FixPointers() const override
 
	{
 
		for (OldWaypoint &wp : _old_waypoints) {
 
			SlObject(&wp, _old_waypoint_desc);
 

	
 
static const ChunkHandler CHKP{ 'CHKP', nullptr, Load_WAYP, Ptrs_WAYP, nullptr, CH_READONLY };
 
			if (IsSavegameVersionBefore(SLV_12)) {
 
				wp.town_cn = (wp.string_id & 0xC000) == 0xC000 ? (wp.string_id >> 8) & 0x3F : 0;
 
				wp.town = ClosestTownFromTile(wp.xy, UINT_MAX);
 
			} else if (IsSavegameVersionBefore(SLV_122)) {
 
				/* Only for versions 12 .. 122 */
 
				if (!Town::IsValidID(wp.town_index)) {
 
					/* Upon a corrupted waypoint we'll likely get here. The next step will be to
 
					 * loop over all Ptrs procs to nullptr the pointers. However, we don't know
 
					 * whether we're in the nullptr or "normal" Ptrs proc. So just clear the list
 
					 * of old waypoints we constructed and then this waypoint (and the other
 
					 * possibly corrupt ones) will not be queried in the nullptr Ptrs proc run. */
 
					_old_waypoints.clear();
 
					SlErrorCorrupt("Referencing invalid Town");
 
				}
 
				wp.town = Town::Get(wp.town_index);
 
			}
 
			if (IsSavegameVersionBefore(SLV_84)) {
 
				wp.name = CopyFromOldName(wp.string_id);
 
			}
 
		}
 
	}
 
};
 

	
 
static const CHKPChunkHandler CHKP;
 
static const ChunkHandlerRef waypoint_chunk_handlers[] = {
 
	CHKP,
 
};
0 comments (0 inline, 0 general)