Saveload: Remove intermediate copy in map individual chunk save/load
This commit is contained in:
		@@ -54,17 +54,12 @@ static void Check_MAPS()
 | 
			
		||||
	_load_check_data.map_size_y = _map_dim_y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const uint MAP_SL_BUF_SIZE = 4096;
 | 
			
		||||
 | 
			
		||||
static void Load_MAPT()
 | 
			
		||||
{
 | 
			
		||||
	std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
	for (TileIndex i = 0; i != size;) {
 | 
			
		||||
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 | 
			
		||||
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type = buf[j];
 | 
			
		||||
	}
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
 | 
			
		||||
		_m[i++].type = val;
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Check_MAPH_common()
 | 
			
		||||
@@ -88,128 +83,101 @@ static void Load_MAPH()
 | 
			
		||||
	if (SlXvIsFeaturePresent(XSLFI_CHILLPP)) {
 | 
			
		||||
		if (SlGetFieldLength() != 0) {
 | 
			
		||||
			_sl_xv_feature_versions[XSLFI_HEIGHT_8_BIT] = 2;
 | 
			
		||||
			std::array<uint16_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
			TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
			for (TileIndex i = 0; i != size;) {
 | 
			
		||||
				SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 | 
			
		||||
				for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j];
 | 
			
		||||
			}
 | 
			
		||||
			TileIndex i = 0;
 | 
			
		||||
			ReadBuffer::GetCurrent()->ReadUint16sToHandler(MapSize(), [&](uint16_t val) {
 | 
			
		||||
				_m[i++].height = val;
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
	for (TileIndex i = 0; i != size;) {
 | 
			
		||||
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 | 
			
		||||
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j];
 | 
			
		||||
	}
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
 | 
			
		||||
		_m[i++].height = val;
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Load_MAP1()
 | 
			
		||||
{
 | 
			
		||||
	std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
	for (TileIndex i = 0; i != size;) {
 | 
			
		||||
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 | 
			
		||||
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m1 = buf[j];
 | 
			
		||||
	}
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
 | 
			
		||||
		_m[i++].m1 = val;
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Load_MAP2()
 | 
			
		||||
{
 | 
			
		||||
	std::array<uint16_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
	for (TileIndex i = 0; i != size;) {
 | 
			
		||||
		SlArray(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];
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	if (IsSavegameVersionBefore(SLV_5)) {
 | 
			
		||||
		/* In those versions the m2 was 8 bits */
 | 
			
		||||
		ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
 | 
			
		||||
			_m[i++].m2 = val;
 | 
			
		||||
		});
 | 
			
		||||
	} else {
 | 
			
		||||
		ReadBuffer::GetCurrent()->ReadUint16sToHandler(MapSize(), [&](uint16_t val) {
 | 
			
		||||
			_m[i++].m2 = val;
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Load_MAP3()
 | 
			
		||||
{
 | 
			
		||||
	std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
	for (TileIndex i = 0; i != size;) {
 | 
			
		||||
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 | 
			
		||||
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m3 = buf[j];
 | 
			
		||||
	}
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
 | 
			
		||||
		_m[i++].m3 = val;
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Load_MAP4()
 | 
			
		||||
{
 | 
			
		||||
	std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
	for (TileIndex i = 0; i != size;) {
 | 
			
		||||
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 | 
			
		||||
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m4 = buf[j];
 | 
			
		||||
	}
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
 | 
			
		||||
		_m[i++].m4 = val;
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Load_MAP5()
 | 
			
		||||
{
 | 
			
		||||
	std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
	for (TileIndex i = 0; i != size;) {
 | 
			
		||||
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 | 
			
		||||
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m5 = buf[j];
 | 
			
		||||
	}
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
 | 
			
		||||
		_m[i++].m5 = val;
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Load_MAP6()
 | 
			
		||||
{
 | 
			
		||||
	std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	if (IsSavegameVersionBefore(SLV_42)) {
 | 
			
		||||
		for (TileIndex i = 0; i != size;) {
 | 
			
		||||
			/* 1024, otherwise we overflow on 64x64 maps! */
 | 
			
		||||
			SlArray(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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		ReadBuffer::GetCurrent()->ReadBytesToHandler(size / 4, [&](uint8_t val) {
 | 
			
		||||
			_me[i++].m6 = GB(val, 0, 2);
 | 
			
		||||
			_me[i++].m6 = GB(val, 2, 2);
 | 
			
		||||
			_me[i++].m6 = GB(val, 4, 2);
 | 
			
		||||
			_me[i++].m6 = GB(val, 6, 2);
 | 
			
		||||
		});
 | 
			
		||||
	} else {
 | 
			
		||||
		for (TileIndex i = 0; i != size;) {
 | 
			
		||||
			SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 | 
			
		||||
			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m6 = buf[j];
 | 
			
		||||
		}
 | 
			
		||||
		ReadBuffer::GetCurrent()->ReadBytesToHandler(size, [&](uint8_t val) {
 | 
			
		||||
			_me[i++].m6 = val;
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Load_MAP7()
 | 
			
		||||
{
 | 
			
		||||
	std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
	for (TileIndex i = 0; i != size;) {
 | 
			
		||||
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
 | 
			
		||||
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m7 = buf[j];
 | 
			
		||||
	}
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
 | 
			
		||||
		_me[i++].m7 = val;
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Load_MAP8()
 | 
			
		||||
{
 | 
			
		||||
	std::array<uint16_t, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
 | 
			
		||||
	for (TileIndex i = 0; i != size;) {
 | 
			
		||||
		SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
 | 
			
		||||
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m8 = buf[j];
 | 
			
		||||
	}
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	ReadBuffer::GetCurrent()->ReadUint16sToHandler(MapSize(), [&](uint16_t val) {
 | 
			
		||||
		_me[i++].m8 = val;
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Load_WMAP()
 | 
			
		||||
@@ -347,33 +315,25 @@ struct MAP8 {
 | 
			
		||||
	static const FieldT &GetField(TileIndex t) { return _me[t].m8; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct MAP_VarType {};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct MAP_VarType<uint8_t>
 | 
			
		||||
{
 | 
			
		||||
	static const VarType var_type = SLE_UINT8;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct MAP_VarType<uint16_t>
 | 
			
		||||
{
 | 
			
		||||
	static const VarType var_type = SLE_UINT16;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
static void Save_MAP()
 | 
			
		||||
{
 | 
			
		||||
	assert(_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 0);
 | 
			
		||||
 | 
			
		||||
	std::array<typename T::FieldT, MAP_SL_BUF_SIZE> buf;
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
	static_assert(std::is_same_v<typename T::FieldT, uint8_t> || std::is_same_v<typename T::FieldT, uint16_t>);
 | 
			
		||||
 | 
			
		||||
	TileIndex size = MapSize();
 | 
			
		||||
	SlSetLength(size * sizeof(typename T::FieldT));
 | 
			
		||||
	for (TileIndex i = 0; i != size;) {
 | 
			
		||||
		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = T::GetField(i++);
 | 
			
		||||
		SlArray(buf.data(), MAP_SL_BUF_SIZE, MAP_VarType<typename T::FieldT>::var_type);
 | 
			
		||||
 | 
			
		||||
	TileIndex i = 0;
 | 
			
		||||
	if constexpr (std::is_same_v<typename T::FieldT, uint8_t>) {
 | 
			
		||||
		MemoryDumper::GetCurrent()->WriteBytesFromHandler(size, [&]() -> uint8_t {
 | 
			
		||||
			return T::GetField(i++);
 | 
			
		||||
		});
 | 
			
		||||
	} else {
 | 
			
		||||
		MemoryDumper::GetCurrent()->WriteUint16sFromHandler(size, [&]() -> uint16_t {
 | 
			
		||||
			return T::GetField(i++);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -139,6 +139,34 @@ struct ReadBuffer {
 | 
			
		||||
		this->CopyBytes(buffer.data(), buffer.size());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template <typename F>
 | 
			
		||||
	inline void ReadBytesToHandler(size_t length, F handler)
 | 
			
		||||
	{
 | 
			
		||||
		while (length) {
 | 
			
		||||
			if (unlikely(this->bufp == this->bufe)) {
 | 
			
		||||
				this->AcquireBytes();
 | 
			
		||||
			}
 | 
			
		||||
			size_t to_copy = std::min<size_t>(this->bufe - this->bufp, length);
 | 
			
		||||
			for (size_t i = 0; i < to_copy; i++) {
 | 
			
		||||
				handler(this->RawReadByte());
 | 
			
		||||
			}
 | 
			
		||||
			length -= to_copy;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template <typename F>
 | 
			
		||||
	inline void ReadUint16sToHandler(size_t length, F handler)
 | 
			
		||||
	{
 | 
			
		||||
		while (length) {
 | 
			
		||||
			this->CheckBytes(2);
 | 
			
		||||
			size_t to_copy = std::min<size_t>((this->bufe - this->bufp) / 2, length);
 | 
			
		||||
			for (size_t i = 0; i < to_copy; i++) {
 | 
			
		||||
				handler(this->RawReadUint16());
 | 
			
		||||
			}
 | 
			
		||||
			length -= to_copy;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Get the size of the memory dump made so far.
 | 
			
		||||
	 * @return The size.
 | 
			
		||||
@@ -274,6 +302,33 @@ struct MemoryDumper {
 | 
			
		||||
		this->buf += 8;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template <typename F>
 | 
			
		||||
	inline void WriteBytesFromHandler(size_t length, F handler)
 | 
			
		||||
	{
 | 
			
		||||
		while (length) {
 | 
			
		||||
			this->CheckBytes(1);
 | 
			
		||||
			size_t to_copy = std::min<size_t>(this->bufe - this->buf, length);
 | 
			
		||||
			for (size_t i = 0; i < to_copy; i++) {
 | 
			
		||||
				this->RawWriteByte(handler());
 | 
			
		||||
			}
 | 
			
		||||
			length -= to_copy;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template <typename F>
 | 
			
		||||
	inline void WriteUint16sFromHandler(size_t length, F handler)
 | 
			
		||||
	{
 | 
			
		||||
		while (length) {
 | 
			
		||||
			this->CheckBytes(2);
 | 
			
		||||
			size_t to_copy = std::min<size_t>((this->bufe - this->buf) / 2, length);
 | 
			
		||||
			for (size_t i = 0; i < to_copy; i++) {
 | 
			
		||||
				this->RawWriteUint16(handler());
 | 
			
		||||
			}
 | 
			
		||||
			length -= to_copy;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	void Flush(SaveFilter &writer);
 | 
			
		||||
	size_t GetSize() const;
 | 
			
		||||
	void StartAutoLength();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user