diff --git a/src/sl/map_sl.cpp b/src/sl/map_sl.cpp index c0c9cf28c0..9f62cfd1f0 100644 --- a/src/sl/map_sl.cpp +++ b/src/sl/map_sl.cpp @@ -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 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 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 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 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 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 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 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 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 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 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 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 -struct MAP_VarType {}; - -template <> -struct MAP_VarType -{ - static const VarType var_type = SLE_UINT8; -}; - -template <> -struct MAP_VarType -{ - static const VarType var_type = SLE_UINT16; -}; - template static void Save_MAP() { assert(_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 0); - std::array buf; - TileIndex size = MapSize(); + static_assert(std::is_same_v || std::is_same_v); + 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::var_type); + + TileIndex i = 0; + if constexpr (std::is_same_v) { + MemoryDumper::GetCurrent()->WriteBytesFromHandler(size, [&]() -> uint8_t { + return T::GetField(i++); + }); + } else { + MemoryDumper::GetCurrent()->WriteUint16sFromHandler(size, [&]() -> uint16_t { + return T::GetField(i++); + }); } } diff --git a/src/sl/saveload_buffer.h b/src/sl/saveload_buffer.h index 1e18790f30..c45eb6ae67 100644 --- a/src/sl/saveload_buffer.h +++ b/src/sl/saveload_buffer.h @@ -139,6 +139,34 @@ struct ReadBuffer { this->CopyBytes(buffer.data(), buffer.size()); } + template + inline void ReadBytesToHandler(size_t length, F handler) + { + while (length) { + if (unlikely(this->bufp == this->bufe)) { + this->AcquireBytes(); + } + size_t to_copy = std::min(this->bufe - this->bufp, length); + for (size_t i = 0; i < to_copy; i++) { + handler(this->RawReadByte()); + } + length -= to_copy; + } + } + + template + inline void ReadUint16sToHandler(size_t length, F handler) + { + while (length) { + this->CheckBytes(2); + size_t to_copy = std::min((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 + inline void WriteBytesFromHandler(size_t length, F handler) + { + while (length) { + this->CheckBytes(1); + size_t to_copy = std::min(this->bufe - this->buf, length); + for (size_t i = 0; i < to_copy; i++) { + this->RawWriteByte(handler()); + } + length -= to_copy; + } + } + + template + inline void WriteUint16sFromHandler(size_t length, F handler) + { + while (length) { + this->CheckBytes(2); + size_t to_copy = std::min((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();