Changeset - r25698:2dd339d9890b
[Not reviewed]
master
0 10 0
Patric Stout - 3 years ago 2021-06-12 12:49:51
truebrain@openttd.org
Change: prefix SL_ARR with the length of the array

This means that during loading we can validate that what is saved
is also that what is expected. Additionally, this makes all list
types similar to how they are stored on disk:
First a gamma to indicate length, followed by the data.
The size still depends on the type.
10 files changed with 117 insertions and 69 deletions:
0 comments (0 inline, 0 general)
src/saveload/animated_tile_sl.cpp
Show inline comments
 
@@ -21,37 +21,37 @@ extern std::vector<TileIndex> _animated_
 
/**
 
 * Save the ANIT chunk.
 
 */
 
static void Save_ANIT()
 
{
 
	SlSetLength(_animated_tiles.size() * sizeof(_animated_tiles.front()));
 
	SlArray(_animated_tiles.data(), _animated_tiles.size(), SLE_UINT32);
 
	SlCopy(_animated_tiles.data(), _animated_tiles.size(), SLE_UINT32);
 
}
 

	
 
/**
 
 * 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];
 
		SlArray(anim_list, 256, IsSavegameVersionBefore(SLV_6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32);
 
		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;
 
	}
 

	
 
	uint count = (uint)SlGetFieldLength() / sizeof(_animated_tiles.front());
 
	_animated_tiles.clear();
 
	_animated_tiles.resize(_animated_tiles.size() + count);
 
	SlArray(_animated_tiles.data(), count, SLE_UINT32);
 
	SlCopy(_animated_tiles.data(), count, SLE_UINT32);
 
}
 

	
 
/**
 
 * "Definition" imported by the saveload code to be able to load and save
 
 * the animated tile table.
 
 */
src/saveload/economy_sl.cpp
Show inline comments
 
@@ -17,23 +17,23 @@
 

	
 
/** 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;
 
	SlArray(nullptr, 49, vt | SLE_VAR_NULL);
 
	SlArray(nullptr, 49, SLE_FILE_U16 | SLE_VAR_NULL);
 
	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;
 
	SlArray(nullptr, num_cargo, vt | SLE_VAR_NULL);
 
	SlArray(nullptr, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL);
 
	SlCopy(nullptr, num_cargo, vt | SLE_VAR_NULL);
 
	SlCopy(nullptr, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL);
 
}
 

	
 
static const SaveLoad _economy_desc[] = {
 
	SLE_CONDNULL(4,                                                                  SL_MIN_VERSION, SLV_65),             // max_loan
 
	SLE_CONDNULL(8,                                                                 SLV_65, SLV_144), // max_loan
 
	SLE_CONDVAR(Economy, old_max_loan_unround,          SLE_FILE_I32 | SLE_VAR_I64,  SL_MIN_VERSION, SLV_65),
src/saveload/engine_sl.cpp
Show inline comments
 
@@ -153,13 +153,13 @@ void ResetTempEngineData()
 
static void Load_ENGS()
 
{
 
	/* Load old separate String ID list into a temporary array. This
 
	 * was always 256 entries. */
 
	StringID names[256];
 

	
 
	SlArray(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]);
 
	}
src/saveload/map_sl.cpp
Show inline comments
 
@@ -50,82 +50,82 @@ static const uint MAP_SL_BUF_SIZE = 4096
 
static void Load_MAPT()
 
{
 
	std::array<byte, MAP_SL_BUF_SIZE> buf;
 
	TileIndex size = MapSize();
 

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

	
 
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;
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	}
 
}
 

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

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

	
 
static void Save_MAPH()
 
{
 
	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;
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	}
 
}
 

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

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		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;
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	}
 
}
 

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

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlArray(buf.data(), MAP_SL_BUF_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];
 
	}
 
}
 
@@ -135,104 +135,104 @@ static void Save_MAP2()
 
	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;
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
	}
 
}
 

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

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

	
 
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;
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	}
 
}
 

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

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

	
 
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;
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	}
 
}
 

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

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

	
 
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;
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	}
 
}
 

	
 
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! */
 
			SlArray(buf.data(), 1024, SLE_UINT8);
 
			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;) {
 
			SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
			SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m6 = buf[j];
 
		}
 
	}
 
}
 

	
 
static void Save_MAP6()
 
@@ -240,59 +240,59 @@ 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;
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	}
 
}
 

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

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		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;
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 
	}
 
}
 

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

	
 
	for (TileIndex i = 0; i != size;) {
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
		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();
 

	
 
	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;
 
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
		SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 
	}
 
}
 

	
 

	
 
static const ChunkHandler map_chunk_handlers[] = {
 
	{ 'MAPS', Save_MAPS, Load_MAPS, nullptr, Check_MAPS, CH_RIFF },
src/saveload/order_sl.cpp
Show inline comments
 
@@ -138,25 +138,25 @@ static void Load_ORDR()
 
		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);
 

	
 
			SlArray(orders, len, SLE_UINT16);
 
			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);
 

	
 
			SlArray(orders, len, SLE_UINT32);
 
			SlCopy(orders, len, SLE_UINT32);
 

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

	
 
			free(orders);
src/saveload/saveload.cpp
Show inline comments
 
@@ -1040,77 +1040,125 @@ static void SlStdString(void *ptr, VarTy
 
		case SLA_NULL: break;
 
		default: NOT_REACHED();
 
	}
 
}
 

	
 
/**
 
 * Return the size in bytes of a certain type of atomic array
 
 * @param length The length of the array counted in elements
 
 * @param conv VarType type of the variable that is used in calculating the size
 
 * Internal function to save/Load a list of SL_VARs.
 
 * SlCopy() and SlArray() are very similar, with the exception of the header.
 
 * This function represents the common part.
 
 * @param object The object being manipulated.
 
 * @param length The length of the object in elements
 
 * @param conv VarType type of the items.
 
 */
 
static inline size_t SlCalcArrayLen(size_t length, VarType conv)
 
static void SlCopyInternal(void *object, size_t length, VarType conv)
 
{
 
	return SlCalcConvFileLen(conv) * length;
 
}
 

	
 
/**
 
 * Save/Load an array.
 
 * @param array The array being manipulated
 
 * @param length The length of the array in elements
 
 * @param conv VarType type of the atomic array (int, byte, uint64, etc.)
 
 */
 
void SlArray(void *array, size_t length, VarType conv)
 
{
 
	if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
 

	
 
	/* Automatically calculate the length? */
 
	if (_sl.need_length != NL_NONE) {
 
		SlSetLength(SlCalcArrayLen(length, conv));
 
		/* Determine length only? */
 
		if (_sl.need_length == NL_CALCLENGTH) return;
 
	}
 

	
 
	if (GetVarMemType(conv) == SLE_VAR_NULL) {
 
		assert(_sl.action != SLA_SAVE); // Use SL_NULL if you want to write null-bytes
 
		SlSkipBytes(SlCalcArrayLen(length, conv));
 
		SlSkipBytes(length * SlCalcConvFileLen(conv));
 
		return;
 
	}
 

	
 
	/* NOTICE - handle some buggy stuff, in really old versions everything was saved
 
	 * as a byte-type. So detect this, and adjust array size accordingly */
 
	 * as a byte-type. So detect this, and adjust object size accordingly */
 
	if (_sl.action != SLA_SAVE && _sl_version == 0) {
 
		/* all arrays except difficulty settings */
 
		/* all objects except difficulty settings */
 
		if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
 
				conv == SLE_INT32 || conv == SLE_UINT32) {
 
			SlCopyBytes(array, length * SlCalcConvFileLen(conv));
 
			SlCopyBytes(object, length * SlCalcConvFileLen(conv));
 
			return;
 
		}
 
		/* used for conversion of Money 32bit->64bit */
 
		if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
 
			for (uint i = 0; i < length; i++) {
 
				((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
 
				((int64*)object)[i] = (int32)BSWAP32(SlReadUint32());
 
			}
 
			return;
 
		}
 
	}
 

	
 
	/* If the size of elements is 1 byte both in file and memory, no special
 
	 * conversion is needed, use specialized copy-copy function to speed up things */
 
	if (conv == SLE_INT8 || conv == SLE_UINT8) {
 
		SlCopyBytes(array, length);
 
		SlCopyBytes(object, length);
 
	} else {
 
		byte *a = (byte*)array;
 
		byte *a = (byte*)object;
 
		byte mem_size = SlCalcConvMemLen(conv);
 

	
 
		for (; length != 0; length --) {
 
			SlSaveLoadConv(a, conv);
 
			a += mem_size; // get size
 
		}
 
	}
 
}
 

	
 
/**
 
 * Copy a list of SL_VARs to/from a savegame.
 
 * These entries are copied as-is, and you as caller have to make sure things
 
 * like length-fields are calculated correctly.
 
 * @param object The object being manipulated.
 
 * @param length The length of the object in elements
 
 * @param conv VarType type of the items.
 
 */
 
void SlCopy(void *object, size_t length, VarType conv)
 
{
 
	if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
 

	
 
	/* Automatically calculate the length? */
 
	if (_sl.need_length != NL_NONE) {
 
		SlSetLength(length * SlCalcConvFileLen(conv));
 
		/* Determine length only? */
 
		if (_sl.need_length == NL_CALCLENGTH) return;
 
	}
 

	
 
	SlCopyInternal(object, length, conv);
 
}
 

	
 
/**
 
 * Return the size in bytes of a certain type of atomic array
 
 * @param length The length of the array counted in elements
 
 * @param conv VarType type of the variable that is used in calculating the size
 
 */
 
static inline size_t SlCalcArrayLen(size_t length, VarType conv)
 
{
 
	return SlCalcConvFileLen(conv) * length + SlGetArrayLength(length);
 
}
 

	
 
/**
 
 * Save/Load the length of the array followed by the array of SL_VAR elements.
 
 * @param array The array being manipulated
 
 * @param length The length of the array in elements
 
 * @param conv VarType type of the atomic array (int, byte, uint64, etc.)
 
 */
 
static void SlArray(void *array, size_t length, VarType conv)
 
{
 
	switch (_sl.action) {
 
		case SLA_SAVE:
 
			SlWriteArrayLength(length);
 
			SlCopyInternal(array, length, conv);
 
			return;
 

	
 
		case SLA_LOAD_CHECK:
 
		case SLA_LOAD: {
 
			if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) {
 
				size_t sv_length = SlReadArrayLength();
 
				if (sv_length != length) SlErrorCorrupt("Fixed-length array is of wrong length");
 
			}
 

	
 
			SlCopyInternal(array, length, conv);
 
			return;
 
		}
 

	
 
		case SLA_PTRS:
 
		case SLA_NULL:
 
			return;
 

	
 
		default:
 
			NOT_REACHED();
 
	}
 
}
 

	
 
/**
 
 * Pointers cannot be saved to a savegame, so this functions gets
 
 * the index of the item, and if not available, it hussles with
 
 * pointers (looks really bad :()
 
 * Remember that a nullptr item has value 0, and all
src/saveload/saveload.h
Show inline comments
 
@@ -1005,13 +1005,13 @@ size_t SlCalcObjMemberLength(const void 
 
size_t SlCalcObjLength(const void *object, const SaveLoadTable &slt);
 

	
 
byte SlReadByte();
 
void SlWriteByte(byte b);
 

	
 
void SlGlobList(const SaveLoadTable &slt);
 
void SlArray(void *array, size_t length, VarType conv);
 
void SlCopy(void *object, size_t length, VarType conv);
 
void SlObject(void *object, const SaveLoadTable &slt);
 
void NORETURN SlError(StringID string, const char *extra_msg = nullptr);
 
void NORETURN SlErrorCorrupt(const char *msg);
 
void NORETURN SlErrorCorruptFmt(const char *format, ...) WARN_FORMAT(1, 2);
 

	
 
bool SaveloadCrashWithMissingNewGRFs();
src/saveload/strings_sl.cpp
Show inline comments
 
@@ -121,13 +121,13 @@ static void Load_NAME()
 
	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");
 

	
 
		SlArray(&_old_name_array[LEN_OLD_STRINGS * index], SlGetFieldLength(), SLE_UINT8);
 
		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';
 
	}
 
}
 

	
 
/** Chunk handlers related to strings. */
src/script/script_instance.cpp
Show inline comments
 
@@ -362,13 +362,13 @@ static const SaveLoad _script_byte[] = {
 
				SlObject(nullptr, _script_byte);
 
			}
 
			SQInteger res;
 
			sq_getinteger(vm, index, &res);
 
			if (!test) {
 
				int value = (int)res;
 
				SlArray(&value, 1, SLE_INT32);
 
				SlCopy(&value, 1, SLE_INT32);
 
			}
 
			return true;
 
		}
 

	
 
		case OT_STRING: {
 
			if (!test) {
 
@@ -382,13 +382,13 @@ static const SaveLoad _script_byte[] = {
 
				ScriptLog::Error("Maximum string length is 254 chars. No data saved.");
 
				return false;
 
			}
 
			if (!test) {
 
				_script_sl_byte = (byte)len;
 
				SlObject(nullptr, _script_byte);
 
				SlArray(const_cast<char *>(buf), len, SLE_CHAR);
 
				SlCopy(const_cast<char *>(buf), len, SLE_CHAR);
 
			}
 
			return true;
 
		}
 

	
 
		case OT_ARRAY: {
 
			if (!test) {
 
@@ -562,21 +562,21 @@ bool ScriptInstance::IsPaused()
 
/* static */ bool ScriptInstance::LoadObjects(HSQUIRRELVM vm)
 
{
 
	SlObject(nullptr, _script_byte);
 
	switch (_script_sl_byte) {
 
		case SQSL_INT: {
 
			int value;
 
			SlArray(&value, 1, SLE_INT32);
 
			SlCopy(&value, 1, SLE_INT32);
 
			if (vm != nullptr) sq_pushinteger(vm, (SQInteger)value);
 
			return true;
 
		}
 

	
 
		case SQSL_STRING: {
 
			SlObject(nullptr, _script_byte);
 
			static char buf[std::numeric_limits<decltype(_script_sl_byte)>::max()];
 
			SlArray(buf, _script_sl_byte, SLE_CHAR);
 
			SlCopy(buf, _script_sl_byte, SLE_CHAR);
 
			StrMakeValidInPlace(buf, buf + _script_sl_byte);
 
			if (vm != nullptr) sq_pushstring(vm, buf, -1);
 
			return true;
 
		}
 

	
 
		case SQSL_ARRAY: {
src/table/settings/gameopt_settings.ini
Show inline comments
 
@@ -38,13 +38,13 @@ static const SettingTable _gameopt_setti
 
 * town attitude towards demolishing. Needs special handling because some dimwit thought
 
 * it funny to have the GameDifficulty struct be an array while it is a struct of
 
 * same-sized members
 
 * XXX - To save file-space and since values are never bigger than about 10? only
 
 * save the first 16 bits in the savegame. Question is why the values are still int32
 
 * and why not byte for example?
 
 * 'SLE_FILE_I16 | SLE_VAR_U16' in "diff_custom" is needed to get around SlArray() hack
 
 * 'SLE_FILE_I16 | SLE_VAR_U16' in "diff_custom" is needed to get around SlCopy() hack
 
 * for savegames version 0 - though it is an array, it has to go through the byteswap process */
 
[post-amble]
 
};
 
[templates]
 
SDTG_LIST    =  SDTG_LIST($name,              $type, $flags, $var, $def, $length, $from, $to, $cat, $extra, $startup),
 
SDTG_VAR     =   SDTG_VAR($name,              $type, $flags, $var, $def, $min, $max, $interval,  $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup),
0 comments (0 inline, 0 general)