mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-11 13:10:45 +00:00
Saveload: Refactor interface for memory dumper raw write functions
This commit is contained in:
parent
d0cbc48f7d
commit
22a6dc642d
@ -261,23 +261,27 @@ static void Save_WMAP()
|
||||
dumper->CopyBytes((uint8_t *) _m, size * 8);
|
||||
dumper->CopyBytes((uint8_t *) _me, size * 4);
|
||||
#else
|
||||
for (TileIndex i = 0; i != size; i++) {
|
||||
dumper->CheckBytes(8);
|
||||
dumper->RawWriteByte(_m[i].type);
|
||||
dumper->RawWriteByte(_m[i].height);
|
||||
dumper->RawWriteByte(GB(_m[i].m2, 0, 8));
|
||||
dumper->RawWriteByte(GB(_m[i].m2, 8, 8));
|
||||
dumper->RawWriteByte(_m[i].m1);
|
||||
dumper->RawWriteByte(_m[i].m3);
|
||||
dumper->RawWriteByte(_m[i].m4);
|
||||
dumper->RawWriteByte(_m[i].m5);
|
||||
Tile *m_start = _m;
|
||||
Tile *m_end = _m + size;
|
||||
for (Tile *m = m_start; m != m_end; m++) {
|
||||
RawMemoryDumper dump = dumper->RawWriteBytes(8);
|
||||
dump.RawWriteByte(m->type);
|
||||
dump.RawWriteByte(m->height);
|
||||
dump.RawWriteByte(GB(m->m2, 0, 8));
|
||||
dump.RawWriteByte(GB(m->m2, 8, 8));
|
||||
dump.RawWriteByte(m->m1);
|
||||
dump.RawWriteByte(m->m3);
|
||||
dump.RawWriteByte(m->m4);
|
||||
dump.RawWriteByte(m->m5);
|
||||
}
|
||||
for (TileIndex i = 0; i != size; i++) {
|
||||
dumper->CheckBytes(4);
|
||||
dumper->RawWriteByte(_me[i].m6);
|
||||
dumper->RawWriteByte(_me[i].m7);
|
||||
dumper->RawWriteByte(GB(_me[i].m8, 0, 8));
|
||||
dumper->RawWriteByte(GB(_me[i].m8, 8, 8));
|
||||
TileExtended *me_start = _me;
|
||||
TileExtended *me_end = _me + size;
|
||||
for (TileExtended *me = me_start; me != me_end; me++) {
|
||||
RawMemoryDumper dump = dumper->RawWriteBytes(4);
|
||||
dump.RawWriteByte(me->m6);
|
||||
dump.RawWriteByte(me->m7);
|
||||
dump.RawWriteByte(GB(me->m8, 0, 8));
|
||||
dump.RawWriteByte(GB(me->m8, 8, 8));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -643,20 +643,17 @@ void SlWriteByte(uint8_t b)
|
||||
|
||||
void SlWriteUint16(uint16_t v)
|
||||
{
|
||||
_sl.dumper->CheckBytes(2);
|
||||
_sl.dumper->RawWriteUint16(v);
|
||||
_sl.dumper->RawWriteBytes(2).RawWriteUint16(v);
|
||||
}
|
||||
|
||||
void SlWriteUint32(uint32_t v)
|
||||
{
|
||||
_sl.dumper->CheckBytes(4);
|
||||
_sl.dumper->RawWriteUint32(v);
|
||||
_sl.dumper->RawWriteBytes(4).RawWriteUint32(v);
|
||||
}
|
||||
|
||||
void SlWriteUint64(uint64_t v)
|
||||
{
|
||||
_sl.dumper->CheckBytes(8);
|
||||
_sl.dumper->RawWriteUint64(v);
|
||||
_sl.dumper->RawWriteBytes(8).RawWriteUint64(v);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -731,27 +728,35 @@ uint SlReadSimpleGamma()
|
||||
*/
|
||||
|
||||
void SlWriteSimpleGamma(size_t i)
|
||||
{
|
||||
MemoryDumper *dumper = MemoryDumper::GetCurrent();
|
||||
RawMemoryDumper raw_dumper = dumper->BorrowRawWriteBytes(SlGetMaxGammaLength());
|
||||
raw_dumper.RawWriteSimpleGamma(i);
|
||||
dumper->ReturnRawWriteBytes(raw_dumper);
|
||||
}
|
||||
|
||||
void RawMemoryDumper::RawWriteSimpleGamma(size_t i)
|
||||
{
|
||||
if (i >= (1 << 7)) {
|
||||
if (i >= (1 << 14)) {
|
||||
if (i >= (1 << 21)) {
|
||||
if (i >= (1 << 28)) {
|
||||
assert(i <= UINT32_MAX); // We can only support 32 bits for now.
|
||||
SlWriteByte((uint8_t)(0xF0));
|
||||
SlWriteByte((uint8_t)(i >> 24));
|
||||
*this->buf++ = ((uint8_t)(0xF0));
|
||||
*this->buf++ = ((uint8_t)(i >> 24));
|
||||
} else {
|
||||
SlWriteByte((uint8_t)(0xE0 | (i >> 24)));
|
||||
*this->buf++ = ((uint8_t)(0xE0 | (i >> 24)));
|
||||
}
|
||||
SlWriteByte((uint8_t)(i >> 16));
|
||||
*this->buf++ = ((uint8_t)(i >> 16));
|
||||
} else {
|
||||
SlWriteByte((uint8_t)(0xC0 | (i >> 16)));
|
||||
*this->buf++ = ((uint8_t)(0xC0 | (i >> 16)));
|
||||
}
|
||||
SlWriteByte((uint8_t)(i >> 8));
|
||||
*this->buf++ = ((uint8_t)(i >> 8));
|
||||
} else {
|
||||
SlWriteByte((uint8_t)(0x80 | (i >> 8)));
|
||||
*this->buf++ = ((uint8_t)(0x80 | (i >> 8)));
|
||||
}
|
||||
}
|
||||
SlWriteByte((uint8_t)i);
|
||||
*this->buf++ = ((uint8_t)i);
|
||||
}
|
||||
|
||||
/** Return how many bytes used to encode a gamma value */
|
||||
@ -2076,8 +2081,7 @@ bool SlObjectMemberGeneric(void *object, const SaveLoad &sld)
|
||||
sld.struct_handler->Save(object);
|
||||
if (offset == _sl.dumper->GetWriteOffsetGeneric()) {
|
||||
/* Nothing was actaully written, so it's safe to change the 1 above to 0 */
|
||||
_sl.dumper->UnWriteByte(); // This is fine iff nothing has been written since the WriteByte(1)
|
||||
_sl.dumper->RawWriteByte(0);
|
||||
_sl.dumper->ReplaceLastWrittenByte(0); // This is fine iff nothing has been written since the WriteByte(1)
|
||||
}
|
||||
} else {
|
||||
sld.struct_handler->Save(object);
|
||||
|
@ -213,6 +213,77 @@ struct ReadBuffer {
|
||||
};
|
||||
|
||||
|
||||
namespace SlSerialise {
|
||||
inline void RawWriteUint16At(uint8_t *b, uint16_t v)
|
||||
{
|
||||
#if OTTD_ALIGNMENT == 0
|
||||
*((unaligned_uint16 *)b) = TO_BE16(v);
|
||||
#else
|
||||
b[0] = GB(v, 8, 8);
|
||||
b[1] = GB(v, 0, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void RawWriteUint32At(uint8_t *b, uint32_t v)
|
||||
{
|
||||
#if OTTD_ALIGNMENT == 0
|
||||
*((unaligned_uint32 *)b) = TO_BE32(v);
|
||||
#else
|
||||
b[0] = GB(v, 24, 8);
|
||||
b[1] = GB(v, 16, 8);
|
||||
b[2] = GB(v, 8, 8);
|
||||
b[3] = GB(v, 0, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void RawWriteUint64At(uint8_t *b, uint64_t v)
|
||||
{
|
||||
#if OTTD_ALIGNMENT == 0
|
||||
*((unaligned_uint64 *)b) = TO_BE64(v);
|
||||
#else
|
||||
b[0] = GB(v, 56, 8);
|
||||
b[1] = GB(v, 48, 8);
|
||||
b[2] = GB(v, 40, 8);
|
||||
b[3] = GB(v, 32, 8);
|
||||
b[4] = GB(v, 24, 8);
|
||||
b[5] = GB(v, 16, 8);
|
||||
b[6] = GB(v, 8, 8);
|
||||
b[7] = GB(v, 0, 8);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
struct RawMemoryDumper {
|
||||
uint8_t *buf; ///< Buffer we're going to write to.
|
||||
|
||||
RawMemoryDumper(uint8_t *b) : buf(b) {}
|
||||
|
||||
inline void RawWriteByte(uint8_t b)
|
||||
{
|
||||
*this->buf++ = b;
|
||||
}
|
||||
|
||||
inline void RawWriteUint16(uint16_t v)
|
||||
{
|
||||
SlSerialise::RawWriteUint16At(this->buf, v);
|
||||
this->buf += 2;
|
||||
}
|
||||
|
||||
inline void RawWriteUint32(uint32_t v)
|
||||
{
|
||||
SlSerialise::RawWriteUint32At(this->buf, v);
|
||||
this->buf += 4;
|
||||
}
|
||||
|
||||
inline void RawWriteUint64(uint64_t v)
|
||||
{
|
||||
SlSerialise::RawWriteUint64At(this->buf, v);
|
||||
this->buf += 8;
|
||||
}
|
||||
|
||||
void RawWriteSimpleGamma(size_t i);
|
||||
};
|
||||
|
||||
/** Container for dumping the savegame (quickly) to memory. */
|
||||
struct MemoryDumper {
|
||||
struct BufferInfo {
|
||||
@ -236,44 +307,6 @@ struct MemoryDumper {
|
||||
uint8_t *saved_buf = nullptr;
|
||||
uint8_t *saved_bufe = nullptr;
|
||||
|
||||
static inline void RawWriteUint16At(uint8_t *b, uint16_t v)
|
||||
{
|
||||
#if OTTD_ALIGNMENT == 0
|
||||
*((unaligned_uint16 *)b) = TO_BE16(v);
|
||||
#else
|
||||
b[0] = GB(v, 8, 8);
|
||||
b[1] = GB(v, 0, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void RawWriteUint32At(uint8_t *b, uint32_t v)
|
||||
{
|
||||
#if OTTD_ALIGNMENT == 0
|
||||
*((unaligned_uint32 *)b) = TO_BE32(v);
|
||||
#else
|
||||
b[0] = GB(v, 24, 8);
|
||||
b[1] = GB(v, 16, 8);
|
||||
b[2] = GB(v, 8, 8);
|
||||
b[3] = GB(v, 0, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void RawWriteUint64At(uint8_t *b, uint64_t v)
|
||||
{
|
||||
#if OTTD_ALIGNMENT == 0
|
||||
*((unaligned_uint64 *)b) = TO_BE64(v);
|
||||
#else
|
||||
b[0] = GB(v, 56, 8);
|
||||
b[1] = GB(v, 48, 8);
|
||||
b[2] = GB(v, 40, 8);
|
||||
b[3] = GB(v, 32, 8);
|
||||
b[4] = GB(v, 24, 8);
|
||||
b[5] = GB(v, 16, 8);
|
||||
b[6] = GB(v, 8, 8);
|
||||
b[7] = GB(v, 0, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
MemoryDumper()
|
||||
{
|
||||
const size_t size = 8192;
|
||||
@ -330,32 +363,28 @@ struct MemoryDumper {
|
||||
}
|
||||
|
||||
/** For limited/special purposes only */
|
||||
inline void UnWriteByte()
|
||||
inline void ReplaceLastWrittenByte(uint8_t b)
|
||||
{
|
||||
this->buf--;
|
||||
*(this->buf - 1) = b;
|
||||
}
|
||||
|
||||
inline void RawWriteByte(uint8_t b)
|
||||
inline RawMemoryDumper RawWriteBytes(size_t bytes)
|
||||
{
|
||||
*this->buf++ = b;
|
||||
this->CheckBytes(bytes);
|
||||
RawMemoryDumper raw_dumper(this->buf);
|
||||
this->buf += bytes;
|
||||
return raw_dumper;
|
||||
}
|
||||
|
||||
inline void RawWriteUint16(uint16_t v)
|
||||
inline RawMemoryDumper BorrowRawWriteBytes(size_t bytes)
|
||||
{
|
||||
RawWriteUint16At(this->buf, v);
|
||||
this->buf += 2;
|
||||
this->CheckBytes(bytes);
|
||||
return RawMemoryDumper(this->buf);
|
||||
}
|
||||
|
||||
inline void RawWriteUint32(uint32_t v)
|
||||
inline void ReturnRawWriteBytes(RawMemoryDumper raw_dumper)
|
||||
{
|
||||
RawWriteUint32At(this->buf, v);
|
||||
this->buf += 4;
|
||||
}
|
||||
|
||||
inline void RawWriteUint64(uint64_t v)
|
||||
{
|
||||
RawWriteUint64At(this->buf, v);
|
||||
this->buf += 8;
|
||||
this->buf = raw_dumper.buf;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
@ -382,7 +411,7 @@ struct MemoryDumper {
|
||||
size_t to_copy = std::min<size_t>((this->bufe - this->buf) / 2, length);
|
||||
uint8_t *b = this->buf;
|
||||
for (size_t i = 0; i < to_copy; i++) {
|
||||
RawWriteUint16At(b, handler());
|
||||
SlSerialise::RawWriteUint16At(b, handler());
|
||||
b += 2;
|
||||
}
|
||||
this->buf = b;
|
||||
|
@ -304,10 +304,13 @@ struct StationGoodsFlowStructHandler final : public TypedSaveLoadStructHandler<S
|
||||
|
||||
for (const FlowStat &stat : ged->flows) {
|
||||
uint32_t sum_shares = 0;
|
||||
dumper->CheckBytes(2 + 2);
|
||||
dumper->RawWriteUint16(stat.GetOrigin());
|
||||
dumper->RawWriteUint16(stat.GetRawFlags());
|
||||
SlWriteSimpleGamma(stat.size());
|
||||
|
||||
RawMemoryDumper dump = dumper->BorrowRawWriteBytes(2 + 2 + SlGetMaxGammaLength());
|
||||
dump.RawWriteUint16(stat.GetOrigin());
|
||||
dump.RawWriteUint16(stat.GetRawFlags());
|
||||
dump.RawWriteSimpleGamma(stat.size());
|
||||
dumper->ReturnRawWriteBytes(dump);
|
||||
|
||||
for (const auto &it : stat) {
|
||||
StationID via = it.second;
|
||||
uint32_t share = it.first - sum_shares;
|
||||
@ -316,10 +319,10 @@ struct StationGoodsFlowStructHandler final : public TypedSaveLoadStructHandler<S
|
||||
dbg_assert(share > 0);
|
||||
|
||||
/* This is performance-sensitive, manually unroll */
|
||||
dumper->CheckBytes(2 + 4 + 1);
|
||||
dumper->RawWriteUint16(via);
|
||||
dumper->RawWriteUint32(share);
|
||||
dumper->RawWriteByte(restricted ? 1 : 0);
|
||||
dump = dumper->RawWriteBytes(2 + 4 + 1);
|
||||
dump.RawWriteUint16(via);
|
||||
dump.RawWriteUint32(share);
|
||||
dump.RawWriteByte(restricted ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -670,18 +673,20 @@ struct StationCargoHistoryStructHandler final : public TypedSaveLoadStructHandle
|
||||
void Save(Station *st) const override
|
||||
{
|
||||
MemoryDumper *dumper = MemoryDumper::GetCurrent();
|
||||
SlWriteUint64(st->station_cargo_history_cargoes);
|
||||
SlWriteSimpleGamma(st->station_cargo_history.size() * MAX_STATION_CARGO_HISTORY_DAYS);
|
||||
RawMemoryDumper dump = dumper->BorrowRawWriteBytes(8 + SlGetMaxGammaLength() + (st->station_cargo_history.size() * MAX_STATION_CARGO_HISTORY_DAYS * 2));
|
||||
|
||||
dump.RawWriteUint64(st->station_cargo_history_cargoes);
|
||||
dump.RawWriteSimpleGamma(st->station_cargo_history.size() * MAX_STATION_CARGO_HISTORY_DAYS);
|
||||
|
||||
dumper->CheckBytes(st->station_cargo_history.size() * MAX_STATION_CARGO_HISTORY_DAYS * 2);
|
||||
for (const auto &history : st->station_cargo_history) {
|
||||
uint i = st->station_cargo_history_offset;
|
||||
do {
|
||||
dumper->RawWriteUint16(history[i]);
|
||||
dump.RawWriteUint16(history[i]);
|
||||
i++;
|
||||
if (i == MAX_STATION_CARGO_HISTORY_DAYS) i = 0;
|
||||
} while (i != st->station_cargo_history_offset);
|
||||
}
|
||||
dumper->ReturnRawWriteBytes(dump);
|
||||
}
|
||||
|
||||
void Load(Station *st) const override
|
||||
|
Loading…
Reference in New Issue
Block a user