Saveload: Remove intermediate copy in map individual chunk save/load

This commit is contained in:
Jonathan G Rennison
2024-07-14 00:08:42 +01:00
parent f739710ad3
commit 159e68c4dc
2 changed files with 123 additions and 108 deletions

View File

@@ -54,17 +54,12 @@ static void Check_MAPS()
_load_check_data.map_size_y = _map_dim_y; _load_check_data.map_size_y = _map_dim_y;
} }
static const uint MAP_SL_BUF_SIZE = 4096;
static void Load_MAPT() static void Load_MAPT()
{ {
std::array<uint8_t, MAP_SL_BUF_SIZE> buf; TileIndex i = 0;
TileIndex size = MapSize(); ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
_m[i++].type = val;
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];
}
} }
static void Check_MAPH_common() static void Check_MAPH_common()
@@ -88,128 +83,101 @@ static void Load_MAPH()
if (SlXvIsFeaturePresent(XSLFI_CHILLPP)) { if (SlXvIsFeaturePresent(XSLFI_CHILLPP)) {
if (SlGetFieldLength() != 0) { if (SlGetFieldLength() != 0) {
_sl_xv_feature_versions[XSLFI_HEIGHT_8_BIT] = 2; _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;) { TileIndex i = 0;
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); ReadBuffer::GetCurrent()->ReadUint16sToHandler(MapSize(), [&](uint16_t val) {
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j]; _m[i++].height = val;
} });
} }
return; return;
} }
std::array<uint8_t, MAP_SL_BUF_SIZE> buf; TileIndex i = 0;
TileIndex size = MapSize(); ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
_m[i++].height = val;
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];
}
} }
static void Load_MAP1() static void Load_MAP1()
{ {
std::array<uint8_t, MAP_SL_BUF_SIZE> buf; TileIndex i = 0;
TileIndex size = MapSize(); ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
_m[i++].m1 = val;
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];
}
} }
static void Load_MAP2() static void Load_MAP2()
{ {
std::array<uint16_t, MAP_SL_BUF_SIZE> buf; TileIndex i = 0;
TileIndex size = MapSize(); if (IsSavegameVersionBefore(SLV_5)) {
/* In those versions the m2 was 8 bits */
for (TileIndex i = 0; i != size;) { ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
SlArray(buf.data(), MAP_SL_BUF_SIZE, _m[i++].m2 = val;
/* In those versions the m2 was 8 bits */ });
IsSavegameVersionBefore(SLV_5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16 } else {
); ReadBuffer::GetCurrent()->ReadUint16sToHandler(MapSize(), [&](uint16_t val) {
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m2 = buf[j]; _m[i++].m2 = val;
});
} }
} }
static void Load_MAP3() static void Load_MAP3()
{ {
std::array<uint8_t, MAP_SL_BUF_SIZE> buf; TileIndex i = 0;
TileIndex size = MapSize(); ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
_m[i++].m3 = val;
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];
}
} }
static void Load_MAP4() static void Load_MAP4()
{ {
std::array<uint8_t, MAP_SL_BUF_SIZE> buf; TileIndex i = 0;
TileIndex size = MapSize(); ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
_m[i++].m4 = val;
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];
}
} }
static void Load_MAP5() static void Load_MAP5()
{ {
std::array<uint8_t, MAP_SL_BUF_SIZE> buf; TileIndex i = 0;
TileIndex size = MapSize(); ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
_m[i++].m5 = val;
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];
}
} }
static void Load_MAP6() static void Load_MAP6()
{ {
std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
TileIndex size = MapSize(); TileIndex size = MapSize();
TileIndex i = 0;
if (IsSavegameVersionBefore(SLV_42)) { if (IsSavegameVersionBefore(SLV_42)) {
for (TileIndex i = 0; i != size;) { ReadBuffer::GetCurrent()->ReadBytesToHandler(size / 4, [&](uint8_t val) {
/* 1024, otherwise we overflow on 64x64 maps! */ _me[i++].m6 = GB(val, 0, 2);
SlArray(buf.data(), 1024, SLE_UINT8); _me[i++].m6 = GB(val, 2, 2);
for (uint j = 0; j != 1024; j++) { _me[i++].m6 = GB(val, 4, 2);
_me[i++].m6 = GB(buf[j], 0, 2); _me[i++].m6 = GB(val, 6, 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 { } else {
for (TileIndex i = 0; i != size;) { ReadBuffer::GetCurrent()->ReadBytesToHandler(size, [&](uint8_t val) {
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); _me[i++].m6 = val;
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m6 = buf[j]; });
}
} }
} }
static void Load_MAP7() static void Load_MAP7()
{ {
std::array<uint8_t, MAP_SL_BUF_SIZE> buf; TileIndex i = 0;
TileIndex size = MapSize(); ReadBuffer::GetCurrent()->ReadBytesToHandler(MapSize(), [&](uint8_t val) {
_me[i++].m7 = val;
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];
}
} }
static void Load_MAP8() static void Load_MAP8()
{ {
std::array<uint16_t, MAP_SL_BUF_SIZE> buf; TileIndex i = 0;
TileIndex size = MapSize(); ReadBuffer::GetCurrent()->ReadUint16sToHandler(MapSize(), [&](uint16_t val) {
_me[i++].m8 = val;
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];
}
} }
static void Load_WMAP() static void Load_WMAP()
@@ -347,33 +315,25 @@ struct MAP8 {
static const FieldT &GetField(TileIndex t) { return _me[t].m8; } 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> template <typename T>
static void Save_MAP() static void Save_MAP()
{ {
assert(_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 0); assert(_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 0);
std::array<typename T::FieldT, MAP_SL_BUF_SIZE> buf; static_assert(std::is_same_v<typename T::FieldT, uint8_t> || std::is_same_v<typename T::FieldT, uint16_t>);
TileIndex size = MapSize();
TileIndex size = MapSize();
SlSetLength(size * sizeof(typename T::FieldT)); 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++); TileIndex i = 0;
SlArray(buf.data(), MAP_SL_BUF_SIZE, MAP_VarType<typename T::FieldT>::var_type); 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++);
});
} }
} }

View File

@@ -139,6 +139,34 @@ struct ReadBuffer {
this->CopyBytes(buffer.data(), buffer.size()); 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. * Get the size of the memory dump made so far.
* @return The size. * @return The size.
@@ -274,6 +302,33 @@ struct MemoryDumper {
this->buf += 8; 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); void Flush(SaveFilter &writer);
size_t GetSize() const; size_t GetSize() const;
void StartAutoLength(); void StartAutoLength();