Go to the documentation of this file.
23 #include "../stdafx.h"
25 #include "../station_base.h"
26 #include "../thread.h"
28 #include "../network/network.h"
29 #include "../window_func.h"
30 #include "../strings_func.h"
31 #include "../core/endian_func.hpp"
32 #include "../vehicle_base.h"
33 #include "../company_func.h"
34 #include "../timer/timer_game_economy.h"
35 #include "../autoreplace_base.h"
36 #include "../roadstop_base.h"
37 #include "../linkgraph/linkgraph.h"
38 #include "../linkgraph/linkgraphjob.h"
39 #include "../statusbar_gui.h"
40 #include "../fileio_func.h"
41 #include "../gamelog.h"
42 #include "../string_func.h"
47 # include <emscripten.h>
50 #include "table/strings.h"
55 #include "../safeguards.h"
102 inline byte ReadByte()
104 if (this->bufp == this->bufe) {
105 size_t len = this->reader->Read(this->buf,
lengthof(this->buf));
109 this->bufp = this->
buf;
110 this->bufe = this->buf + len;
113 return *this->bufp++;
122 return this->read - (this->bufe - this->
bufp);
140 for (
auto p : this->blocks) {
152 if (this->buf == this->bufe) {
154 this->blocks.push_back(this->buf);
165 void Flush(std::shared_ptr<SaveFilter> writer)
173 writer->Write(this->blocks[i++], to_write);
202 std::shared_ptr<SaveFilter>
sf;
205 std::shared_ptr<LoadFilter>
lf;
257 _gamelog_chunk_handlers,
259 _misc_chunk_handlers,
260 _name_chunk_handlers,
261 _cheat_chunk_handlers,
262 _setting_chunk_handlers,
264 _waypoint_chunk_handlers,
265 _depot_chunk_handlers,
266 _order_chunk_handlers,
267 _industry_chunk_handlers,
268 _economy_chunk_handlers,
269 _subsidy_chunk_handlers,
270 _cargomonitor_chunk_handlers,
271 _goal_chunk_handlers,
272 _story_page_chunk_handlers,
273 _league_chunk_handlers,
274 _engine_chunk_handlers,
275 _town_chunk_handlers,
276 _sign_chunk_handlers,
277 _station_chunk_handlers,
278 _company_chunk_handlers,
280 _game_chunk_handlers,
281 _animated_tile_chunk_handlers,
282 _newgrf_chunk_handlers,
283 _group_chunk_handlers,
284 _cargopacket_chunk_handlers,
285 _autoreplace_chunk_handlers,
286 _labelmaps_chunk_handlers,
287 _linkgraph_chunk_handlers,
288 _airport_chunk_handlers,
289 _object_chunk_handlers,
290 _persistent_storage_chunk_handlers,
291 _water_region_chunk_handlers,
292 _randomizer_chunk_handlers,
295 static std::vector<ChunkHandlerRef> _chunk_handlers;
297 if (_chunk_handlers.empty()) {
298 for (
auto &chunk_handler_table : _chunk_handler_tables) {
299 for (
auto &chunk_handler : chunk_handler_table) {
300 _chunk_handlers.push_back(chunk_handler);
305 return _chunk_handlers;
319 Debug(sl, 3,
"Nulling pointers for {}", ch.GetName());
354 throw std::exception();
366 SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
380 if (_exit_game)
return;
392 if (proc ==
nullptr)
return;
419 static inline int SlReadUint16()
425 static inline uint32_t SlReadUint32()
427 uint32_t x = SlReadUint16() << 16;
428 return x | SlReadUint16();
431 static inline uint64_t SlReadUint64()
433 uint32_t x = SlReadUint32();
434 uint32_t y = SlReadUint32();
435 return (uint64_t)x << 32 | y;
438 static inline void SlWriteUint16(uint16_t v)
444 static inline void SlWriteUint32(uint32_t v)
446 SlWriteUint16(
GB(v, 16, 16));
447 SlWriteUint16(
GB(v, 0, 16));
450 static inline void SlWriteUint64(uint64_t x)
452 SlWriteUint32((uint32_t)(x >> 32));
453 SlWriteUint32((uint32_t)x);
510 if (i >= (1 << 14)) {
511 if (i >= (1 << 21)) {
512 if (i >= (1 << 28)) {
513 assert(i <= UINT32_MAX);
534 return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21)) + (i >= (1 << 28));
537 static inline uint SlReadSparseIndex()
542 static inline void SlWriteSparseIndex(uint index)
547 static inline uint SlReadArrayLength()
552 static inline void SlWriteArrayLength(
size_t length)
557 static inline uint SlGetArrayLength(
size_t length)
590 default: NOT_REACHED();
602 static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
607 return SlReadArrayLength();
611 assert(type <
lengthof(conv_mem_size));
612 return conv_mem_size[type];
624 static const byte conv_file_size[] = {0, 1, 1, 2, 2, 4, 4, 8, 8, 2};
627 case SLE_FILE_STRING:
628 return SlReadArrayLength();
632 if (type >=
lengthof(conv_file_size)) fmt::println(
"{}", type);
633 assert(type <
lengthof(conv_file_size));
634 return conv_file_size[type];
644 void SlSetArrayIndex(uint index)
647 _sl.array_index = index;
650 static size_t _next_offs;
660 if (_next_offs != 0 &&
_sl.
reader->GetSize() != _next_offs) {
661 SlErrorCorruptFmt(
"Invalid chunk size iterating array - expected to be at position {}, actually at {}", _next_offs,
_sl.
reader->GetSize());
665 uint length = SlReadArrayLength();
673 _next_offs =
_sl.
reader->GetSize() + length;
682 case CH_SPARSE_TABLE:
683 case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex();
break;
685 case CH_ARRAY: index =
_sl.array_index++;
break;
687 Debug(sl, 0,
"SlIterateArray error");
691 if (length != 0)
return index;
719 SlWriteArrayLength(length + 1);
728 assert(length < (1 << 28));
729 SlWriteUint32((uint32_t)((length & 0xFFFFFF) | ((length >> 24) << 28)));
735 SlWriteArrayLength(1);
737 SlWriteArrayLength(length + 1);
739 case CH_SPARSE_TABLE:
740 case CH_SPARSE_ARRAY:
741 SlWriteArrayLength(length + 1 + SlGetArrayLength(
_sl.array_index));
742 SlWriteSparseIndex(
_sl.array_index);
744 default: NOT_REACHED();
752 default: NOT_REACHED();
764 byte *p = (
byte *)ptr;
769 for (; length != 0; length--) *p++ =
SlReadByte();
774 default: NOT_REACHED();
794 case SLE_VAR_BL:
return (*(
const bool *)ptr != 0);
795 case SLE_VAR_I8:
return *(
const int8_t *)ptr;
796 case SLE_VAR_U8:
return *(
const byte *)ptr;
797 case SLE_VAR_I16:
return *(
const int16_t *)ptr;
798 case SLE_VAR_U16:
return *(
const uint16_t*)ptr;
799 case SLE_VAR_I32:
return *(
const int32_t *)ptr;
800 case SLE_VAR_U32:
return *(
const uint32_t*)ptr;
801 case SLE_VAR_I64:
return *(
const int64_t *)ptr;
802 case SLE_VAR_U64:
return *(
const uint64_t*)ptr;
804 default: NOT_REACHED();
818 case SLE_VAR_BL: *(
bool *)ptr = (val != 0);
break;
819 case SLE_VAR_I8: *(int8_t *)ptr = val;
break;
820 case SLE_VAR_U8: *(
byte *)ptr = val;
break;
821 case SLE_VAR_I16: *(int16_t *)ptr = val;
break;
822 case SLE_VAR_U16: *(uint16_t*)ptr = val;
break;
823 case SLE_VAR_I32: *(int32_t *)ptr = val;
break;
824 case SLE_VAR_U32: *(uint32_t*)ptr = val;
break;
825 case SLE_VAR_I64: *(int64_t *)ptr = val;
break;
826 case SLE_VAR_U64: *(uint64_t*)ptr = val;
break;
829 default: NOT_REACHED();
849 case SLE_FILE_I8: assert(x >= -128 && x <= 127);
SlWriteByte(x);
break;
850 case SLE_FILE_U8: assert(x >= 0 && x <= 255);
SlWriteByte(x);
break;
851 case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);
break;
853 case SLE_FILE_U16:assert(x >= 0 && x <= 65535); SlWriteUint16(x);
break;
855 case SLE_FILE_U32: SlWriteUint32((uint32_t)x);
break;
857 case SLE_FILE_U64: SlWriteUint64(x);
break;
858 default: NOT_REACHED();
867 case SLE_FILE_I8: x = (int8_t )
SlReadByte();
break;
868 case SLE_FILE_U8: x = (byte )
SlReadByte();
break;
869 case SLE_FILE_I16: x = (int16_t )SlReadUint16();
break;
870 case SLE_FILE_U16: x = (uint16_t)SlReadUint16();
break;
871 case SLE_FILE_I32: x = (int32_t )SlReadUint32();
break;
872 case SLE_FILE_U32: x = (uint32_t)SlReadUint32();
break;
873 case SLE_FILE_I64: x = (int64_t )SlReadUint64();
break;
874 case SLE_FILE_U64: x = (uint64_t)SlReadUint64();
break;
876 default: NOT_REACHED();
885 default: NOT_REACHED();
898 const std::string *str =
reinterpret_cast<const std::string *
>(ptr);
900 size_t len = str->length();
901 return len + SlGetArrayLength(len);
914 for (
size_t i = 0; i < str.size(); ) {
916 if (len == 0 || i + len > str.size())
break;
920 if (c == 0xE028 || c == 0xE02A)
Utf8Encode(&str[i], SCC_ENCODED);
932 std::string *str =
reinterpret_cast<std::string *
>(ptr);
936 size_t len = str->length();
937 SlWriteArrayLength(len);
938 SlCopyBytes(
const_cast<void *
>(
static_cast<const void *
>(str->c_str())), len);
944 size_t len = SlReadArrayLength();
966 default: NOT_REACHED();
990 if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
991 conv == SLE_INT32 || conv == SLE_UINT32) {
996 if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
997 for (uint i = 0; i < length; i++) {
998 ((int64_t*)
object)[i] = (int32_t)
BSWAP32(SlReadUint32());
1006 if (conv == SLE_INT8 || conv == SLE_UINT8) {
1009 byte *a = (
byte*)
object;
1012 for (; length != 0; length --) {
1027 void SlCopy(
void *
object,
size_t length, VarType conv)
1057 static void SlArray(
void *array,
size_t length, VarType conv)
1061 SlWriteArrayLength(length);
1068 size_t sv_length = SlReadArrayLength();
1072 }
else if (sv_length != length) {
1107 if (obj ==
nullptr)
return 0;
1122 default: NOT_REACHED();
1138 static_assert(
sizeof(
size_t) <=
sizeof(
void *));
1203 default: NOT_REACHED();
1226 *(
void **)ptr =
nullptr;
1228 default: NOT_REACHED();
1235 template <
template<
typename,
typename>
typename Tstorage,
typename Tvar,
typename Tallocator = std::allocator<Tvar>>
1237 typedef Tstorage<Tvar, Tallocator> SlStorageT;
1249 const SlStorageT *list =
static_cast<const SlStorageT *
>(storage);
1251 int type_size = SlGetArrayLength(list->size());
1253 return list->size() * item_size + type_size;
1256 static void SlSaveLoadMember(
SaveLoadType cmd, Tvar *item, VarType conv)
1276 SlStorageT *list =
static_cast<SlStorageT *
>(storage);
1280 SlWriteArrayLength(list->size());
1282 for (
auto &item : *list) {
1283 SlSaveLoadMember(cmd, &item, conv);
1293 default: NOT_REACHED();
1297 for (
size_t i = 0; i < length; i++) {
1298 Tvar &data = list->emplace_back();
1299 SlSaveLoadMember(cmd, &data, conv);
1305 for (
auto &item : *list) {
1306 SlSaveLoadMember(cmd, &item, conv);
1314 default: NOT_REACHED();
1363 default: NOT_REACHED();
1384 default: NOT_REACHED();
1396 case SLE_VAR_BL: NOT_REACHED();
1405 default: NOT_REACHED();
1417 case SLE_VAR_BL: NOT_REACHED();
1426 default: NOT_REACHED();
1445 for (
auto &sld : slt) {
1454 for (
auto &sld : slt) {
1475 for (
auto &sld : slt) {
1476 length += SlCalcObjMemberLength(
object, sld);
1481 size_t SlCalcObjMemberLength(
const void *
object,
const SaveLoad &sld)
1509 sld.
handler->Save(
const_cast<void *
>(
object));
1516 length += SlGetArrayLength(1);
1522 default: NOT_REACHED();
1527 static bool SlObjectMember(
void *
object,
const SaveLoad &sld)
1531 VarType conv =
GB(sld.
conv, 0, 8);
1550 default: NOT_REACHED();
1567 default: NOT_REACHED();
1581 default: NOT_REACHED();
1602 sld.
handler->LoadCheck(
object);
1615 sld.
handler->FixPointers(
object);
1619 default: NOT_REACHED();
1623 default: NOT_REACHED();
1640 SlWriteArrayLength(length);
1650 size_t length = SlReadArrayLength();
1669 for (
auto &sld : slt) {
1670 SlObjectMember(
object, sld);
1679 void Save(
void *)
const override
1684 void Load(
void *
object)
const override
1687 for (; length > 0; length--) {
1692 void LoadCheck(
void *
object)
const override
1722 std::vector<SaveLoad> saveloads;
1725 std::map<std::string, const SaveLoad *> key_lookup;
1726 for (
auto &sld : slt) {
1730 assert(key_lookup.find(sld.
name) == key_lookup.end());
1731 key_lookup[sld.
name] = &sld;
1742 auto sld_it = key_lookup.find(key);
1743 if (sld_it == key_lookup.end()) {
1747 std::shared_ptr<SaveLoadHandler> handler =
nullptr;
1750 case SLE_FILE_STRING:
1755 case SLE_FILE_STRUCT:
1758 handler = std::make_shared<SlSkipHandler>();
1777 if (correct_type != type) {
1778 Debug(sl, 1,
"Field type for '{}' was expected to be 0x{:02x} but 0x{:02x} was found", key, correct_type, type);
1781 saveloads.push_back(*sld_it->second);
1784 for (
auto &sld : saveloads) {
1800 for (
auto &sld : slt) {
1803 assert(!sld.
name.empty());
1817 for (
auto &sld : slt) {
1833 default: NOT_REACHED();
1836 return std::vector<SaveLoad>();
1858 std::vector<SaveLoad> saveloads;
1861 std::map<std::string, std::vector<const SaveLoad *>> key_lookup;
1862 for (
auto &sld : slt) {
1864 assert(!sld.
name.empty());
1866 key_lookup[sld.
name].push_back(&sld);
1869 for (
auto &slc : slct) {
1870 if (slc.name.empty()) {
1876 auto sld_it = key_lookup.find(slc.name);
1880 if (sld_it == key_lookup.end()) {
1883 Debug(sl, 0,
"internal error: saveload compatibility field '{}' not found", slc.name);
1886 for (
auto &sld : sld_it->second) {
1887 saveloads.push_back(*sld);
1892 for (
auto &sld : saveloads) {
1929 size_t start_pos =
_sl.
dumper->GetSize();
1930 size_t expected_offs = start_pos +
_sl.
obj_len;
1935 if (expected_offs !=
_sl.
dumper->GetSize()) {
1936 SlErrorCorruptFmt(
"Invalid chunk size when writing autolength block, expected {}, got {}",
_sl.
obj_len,
_sl.
dumper->GetSize() - start_pos);
1944 case CH_SPARSE_TABLE:
1948 case CH_SPARSE_ARRAY:
1980 _sl.array_index = 0;
1984 case CH_SPARSE_TABLE:
1985 case CH_SPARSE_ARRAY:
1991 size_t len = (
SlReadByte() << 16) | ((m >> 4) << 24);
1992 len += SlReadUint16();
1994 size_t start_pos =
_sl.
reader->GetSize();
1995 size_t endoffs = start_pos + len;
1999 SlErrorCorruptFmt(
"Invalid chunk size in RIFF in {} - expected {}, got {}", ch.GetName(), len,
_sl.
reader->GetSize() - start_pos);
2033 _sl.array_index = 0;
2036 case CH_SPARSE_TABLE:
2037 case CH_SPARSE_ARRAY:
2042 size_t len = (
SlReadByte() << 16) | ((m >> 4) << 24);
2043 len += SlReadUint16();
2045 size_t start_pos =
_sl.
reader->GetSize();
2046 size_t endoffs = start_pos + len;
2050 SlErrorCorruptFmt(
"Invalid chunk size in RIFF in {} - expected {}, got {}", ch.GetName(), len,
_sl.
reader->GetSize() - start_pos);
2071 SlWriteUint32(ch.
id);
2072 Debug(sl, 2,
"Saving chunk {}", ch.GetName());
2088 SlWriteArrayLength(0);
2090 case CH_SPARSE_TABLE:
2091 case CH_SPARSE_ARRAY:
2094 SlWriteArrayLength(0);
2096 default: NOT_REACHED();
2131 for (
id = SlReadUint32();
id != 0;
id = SlReadUint32()) {
2132 Debug(sl, 2,
"Loading chunk {:c}{:c}{:c}{:c}",
id >> 24,
id >> 16,
id >> 8,
id);
2146 for (
id = SlReadUint32();
id != 0;
id = SlReadUint32()) {
2147 Debug(sl, 2,
"Loading chunk {:c}{:c}{:c}{:c}",
id >> 24,
id >> 16,
id >> 8,
id);
2161 Debug(sl, 3,
"Fixing pointers for {}", ch.GetName());
2185 if (this->file !=
nullptr) {
2189 this->file =
nullptr;
2192 size_t Read(
byte *buf,
size_t size)
override
2195 if (this->file ==
nullptr)
return 0;
2197 return fread(buf, 1, size, this->file);
2202 clearerr(this->file);
2203 if (fseek(this->file, this->begin, SEEK_SET)) {
2204 Debug(sl, 1,
"Could not reset the file reading");
2227 void Write(
byte *buf,
size_t size)
override
2230 if (this->file ==
nullptr)
return;
2232 if (fwrite(buf, 1, size, this->file) != size)
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
2237 if (this->file !=
nullptr) {
2241 this->file =
nullptr;
2250 #include <lzo/lzo1x.h>
2263 if (lzo_init() != LZO_E_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize decompressor");
2266 size_t Read(
byte *buf,
size_t ssize)
override
2274 lzo_uint len = ssize;
2277 if (this->
chain->Read((
byte*)tmp,
sizeof(tmp)) !=
sizeof(tmp))
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE,
"File read failed");
2280 ((uint32_t*)out)[0] = size = tmp[1];
2283 tmp[0] = TO_BE32(tmp[0]);
2284 size = TO_BE32(size);
2290 if (this->
chain->Read(out +
sizeof(uint32_t), size) != size)
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
2293 if (tmp[0] != lzo_adler32(0, out, size +
sizeof(uint32_t)))
SlErrorCorrupt(
"Bad checksum");
2296 int ret = lzo1x_decompress_safe(out +
sizeof(uint32_t) * 1, size, buf, &len,
nullptr);
2297 if (ret != LZO_E_OK)
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
2310 if (lzo_init() != LZO_E_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize compressor");
2313 void Write(
byte *buf,
size_t size)
override
2315 const lzo_bytep in = buf;
2318 byte wrkmem[LZO1X_1_MEM_COMPRESS];
2324 lzo1x_1_compress(in, len, out +
sizeof(uint32_t) * 2, &outlen, wrkmem);
2325 ((uint32_t*)out)[1] = TO_BE32((uint32_t)outlen);
2326 ((uint32_t*)out)[0] = TO_BE32(lzo_adler32(0, out +
sizeof(uint32_t), outlen +
sizeof(uint32_t)));
2327 this->
chain->Write(out, outlen +
sizeof(uint32_t) * 2);
2352 size_t Read(
byte *buf,
size_t size)
override
2354 return this->chain->Read(buf, size);
2368 void Write(
byte *buf,
size_t size)
override
2370 this->chain->Write(buf, size);
2378 #if defined(WITH_ZLIB)
2392 memset(&this->z, 0,
sizeof(this->z));
2393 if (inflateInit(&this->z) != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize decompressor");
2399 inflateEnd(&this->z);
2402 size_t Read(
byte *buf,
size_t size)
override
2404 this->z.next_out = buf;
2405 this->z.avail_out = (uint)size;
2409 if (this->z.avail_in == 0) {
2411 this->z.avail_in = (uint)this->chain->Read(this->fread_buf,
sizeof(this->fread_buf));
2415 int r = inflate(&this->z, 0);
2416 if (r == Z_STREAM_END)
break;
2418 if (r != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"inflate() failed");
2419 }
while (this->z.avail_out != 0);
2421 return size - this->z.avail_out;
2437 memset(&this->z, 0,
sizeof(this->z));
2438 if (deflateInit(&this->z, compression_level) != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize compressor");
2444 deflateEnd(&this->z);
2456 this->z.next_in = p;
2457 this->z.avail_in = (uInt)len;
2460 this->z.avail_out =
sizeof(this->
fwrite_buf);
2469 int r = deflate(&this->z, mode);
2472 if ((n =
sizeof(this->fwrite_buf) - this->z.avail_out) != 0) {
2473 this->chain->Write(this->fwrite_buf, n);
2475 if (r == Z_STREAM_END)
break;
2477 if (r != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"zlib returned error code");
2478 }
while (this->z.avail_in || !this->z.avail_out);
2481 void Write(
byte *buf,
size_t size)
override
2489 this->chain->Finish();
2499 #if defined(WITH_LIBLZMA)
2522 if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize decompressor");
2528 lzma_end(&this->lzma);
2531 size_t Read(
byte *buf,
size_t size)
override
2533 this->lzma.next_out = buf;
2534 this->lzma.avail_out = size;
2538 if (this->lzma.avail_in == 0) {
2540 this->lzma.avail_in = this->chain->Read(this->fread_buf,
sizeof(this->fread_buf));
2544 lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
2545 if (r == LZMA_STREAM_END)
break;
2546 if (r != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"liblzma returned error code");
2547 }
while (this->lzma.avail_out != 0);
2549 return size - this->lzma.avail_out;
2565 if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize compressor");
2571 lzma_end(&this->lzma);
2583 this->lzma.next_in = p;
2584 this->lzma.avail_in = len;
2587 this->lzma.avail_out =
sizeof(this->
fwrite_buf);
2589 lzma_ret r = lzma_code(&this->lzma, action);
2592 if ((n =
sizeof(this->fwrite_buf) - this->lzma.avail_out) != 0) {
2593 this->chain->Write(this->fwrite_buf, n);
2595 if (r == LZMA_STREAM_END)
break;
2596 if (r != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"liblzma returned error code");
2597 }
while (this->lzma.avail_in || !this->lzma.avail_out);
2600 void Write(
byte *buf,
size_t size)
override
2607 this->
WriteLoop(
nullptr, 0, LZMA_FINISH);
2608 this->chain->Finish();
2623 std::shared_ptr<LoadFilter> (*
init_load)(std::shared_ptr<LoadFilter> chain);
2624 std::shared_ptr<SaveFilter> (*
init_write)(std::shared_ptr<SaveFilter> chain,
byte compression);
2633 #if defined(WITH_LZO)
2635 {
"lzo", TO_BE32X(
'OTTD'), CreateLoadFilter<LZOLoadFilter>, CreateSaveFilter<LZOSaveFilter>, 0, 0, 0},
2637 {
"lzo", TO_BE32X(
'OTTD'),
nullptr,
nullptr, 0, 0, 0},
2640 {
"none", TO_BE32X(
'OTTN'), CreateLoadFilter<NoCompLoadFilter>, CreateSaveFilter<NoCompSaveFilter>, 0, 0, 0},
2641 #if defined(WITH_ZLIB)
2645 {
"zlib", TO_BE32X(
'OTTZ'), CreateLoadFilter<ZlibLoadFilter>, CreateSaveFilter<ZlibSaveFilter>, 0, 6, 9},
2647 {
"zlib", TO_BE32X(
'OTTZ'),
nullptr,
nullptr, 0, 0, 0},
2649 #if defined(WITH_LIBLZMA)
2655 {
"lzma", TO_BE32X(
'OTTX'), CreateLoadFilter<LZMALoadFilter>, CreateSaveFilter<LZMASaveFilter>, 0, 2, 9},
2657 {
"lzma", TO_BE32X(
'OTTX'),
nullptr,
nullptr, 0, 0, 0},
2675 if (!full_name.empty()) {
2677 size_t separator = full_name.find(
':');
2678 bool has_comp_level = separator != std::string::npos;
2679 const std::string name(full_name, 0, has_comp_level ? separator : full_name.size());
2682 if (slf->init_write !=
nullptr && name.compare(slf->name) == 0) {
2683 *compression_level = slf->default_compression;
2684 if (has_comp_level) {
2685 const std::string complevel(full_name, separator + 1);
2689 long level = std::stol(complevel, &processed, 10);
2690 if (processed == 0 || level !=
Clamp(level, slf->min_compression, slf->max_compression)) {
2694 *compression_level = level;
2710 void InitializeGame(uint size_x, uint size_y,
bool reset_date,
bool reset_settings);
2712 extern bool LoadOldSaveGame(
const std::string &file);
2719 ResetTempEngineData();
2721 ResetOldWaypoints();
2752 #ifdef __EMSCRIPTEN__
2753 EM_ASM(
if (window[
"openttd_syncfs"]) openttd_syncfs());
2769 static std::string err_str;
2771 return err_str.c_str();
2794 _sl.
sf->Write((
byte*)hdr,
sizeof(hdr));
2811 if (
_sl.
error_str != STR_NETWORK_ERROR_LOSTCONNECTION) {
2826 void WaitTillSaved()
2848 _sl.
dumper = std::make_unique<MemoryDumper>();
2853 SaveViewportBeforeSaveGame();
2859 if (threaded)
Debug(sl, 1,
"Cannot create savegame thread, reverting to single-threaded mode...");
2880 return DoSave(writer, threaded);
2905 if (
_sl.
lf->Read((
byte*)hdr,
sizeof(hdr)) !=
sizeof(hdr))
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
2912 Debug(sl, 0,
"Unknown savegame type, trying to load it as the buggy format");
2924 if (fmt->
tag == TO_BE32X(
'OTTD'))
break;
2930 if (fmt->
tag == hdr[0]) {
2951 SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, fmt::format(
"Loader for '{}' is not available.", fmt->
name));
2964 InitializeGame(256, 256,
true,
true);
3036 return DoLoad(reader,
false);
3067 InitializeGame(256, 256,
true,
true);
3075 if (!LoadOldSaveGame(filename))
return SL_REINIT;
3101 default: NOT_REACHED();
3111 if (fh ==
nullptr) {
3112 SlError(fop ==
SLO_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
3119 return DoSave(std::make_shared<FileWriter>(fh), threaded);
3124 Debug(desync, 1,
"load: {}", filename);
3145 std::string filename;
3153 Debug(sl, 2,
"Autosaving to '{}'", filename);
3188 SetDParam(1, STR_SAVEGAME_DURATION_REALTIME);
3194 case 0:
SetDParam(1, STR_JUST_DATE_LONG);
break;
3195 case 1:
SetDParam(1, STR_JUST_DATE_TINY);
break;
3196 case 2:
SetDParam(1, STR_JUST_DATE_ISO);
break;
3197 default: NOT_REACHED();
3244 this->
name = item.name;
3245 this->
title = item.title;
3250 assert(this->load_description.has_value());
3251 return *this->load_description;
@ SL_NULL
Save null-bytes and load to nowhere.
byte fread_buf[MEMORY_CHUNK_SIZE]
Buffer for reading from the file.
static void SlLoadChunks()
Load all chunks.
static size_t SlCalcTableHeader(const SaveLoadTable &slt)
Calculate the size of the table header.
static void ResetSaveloadData()
Clear temporary data that is passed between various saveload phases.
static void SlSaveLoad(void *storage, VarType conv, SaveLoadType cmd=SL_VAR)
Internal templated helper to save/load a list-like type.
SaveLoadVersion
SaveLoad versions Previous savegame versions, the trunk revision where they were introduced and the r...
void SetMouseCursorBusy(bool busy)
Set or unset the ZZZ cursor.
SaveLoadVersion version_to
Save/load the variable before this savegame version.
FileWriter(FILE *file)
Create the file writer, so it writes to a specific file.
static bool SlIsObjectValidInSavegame(const SaveLoad &sld)
Are we going to save this object or not?
lzma_stream lzma
Stream state that we are writing to.
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
static const uint LZO_BUFFER_SIZE
Buffer size for the LZO compressor.
@ REF_ORDER
Load/save a reference to an order.
SaveLoadType
Type of data saved.
static void SlDeque(void *deque, VarType conv)
Save/load a std::deque.
static void SlLoadChunk(const ChunkHandler &ch)
Load a chunk of data (eg vehicles, stations, etc.)
bool checkable
True if the savegame could be checked by SL_LOAD_CHECK. (Old savegames are not checkable....
@ SLV_5
5.0 1429 5.1 1440 5.2 1525 0.3.6
void SetSaveLoadError(StringID str)
Set the error message from outside of the actual loading/saving of the game (AfterLoadGame and friend...
~ZlibLoadFilter()
Clean everything up.
static Titem * Get(size_t index)
Returns Titem with given index.
std::string error_msg
Data to pass to SetDParamStr when displaying error.
@ SAVE_DIR
Base directory for all savegames.
LZMASaveFilter(std::shared_ptr< SaveFilter > chain, byte compression_level)
Initialise this filter.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
static void SlArray(void *array, size_t length, VarType conv)
Save/Load the length of the array followed by the array of SL_VAR elements.
@ SVS_ALLOW_NEWLINE
Allow newlines; replaces '\r ' with ' ' during processing.
A connected component of a link graph.
static std::thread _save_thread
The thread we're using to compress and write a savegame.
@ SLE_VAR_STR
string pointer
Filter without any compression.
byte _sl_minor_version
the minor savegame version, DO NOT USE!
byte fread_buf[MEMORY_CHUNK_SIZE]
Buffer for reading from the file.
StringID RemapOldStringID(StringID s)
Remap a string ID from the old format to the new format.
void CSleep(int milliseconds)
Sleep on the current thread for a defined time.
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
std::span< const struct SaveLoad > SaveLoadTable
A table of SaveLoad entries.
@ REF_TOWN
Load/save a reference to a town.
void DoExitSave()
Do a save when exiting the game (_settings_client.gui.autosave_on_exit)
void ClearGRFConfigList(GRFConfig **config)
Clear a GRF Config list, freeing all nodes.
@ REF_ROADSTOPS
Load/save a reference to a bus/truck stop.
std::string title
Internal name of the game.
@ SLE_FILE_END
Used to mark end-of-header in tables.
size_t Read(byte *buf, size_t size) override
Read a given number of bytes from the savegame.
Gamelog _gamelog
Gamelog instance.
void SlSkipArray()
Skip an array or sparse array.
Class for calculation jobs to be run on link graphs.
SaveOrLoadResult SaveOrLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded)
Main Save or Load function where the high-level saveload functions are handled.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ SL_MIN_VERSION
First savegame version.
SaveLoadOperation
Operation performed on the file.
void SlCopy(void *object, size_t length, VarType conv)
Copy a list of SL_VARs to/from a savegame.
NoCompLoadFilter(std::shared_ptr< LoadFilter > chain)
Initialise this filter.
uint32_t _ttdp_version
version of TTDP savegame (if applicable)
std::string name
Name of the file.
long begin
The begin of the file.
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
LoadCheckData _load_check_data
Data loaded from save during SL_LOAD_CHECK.
bool AfterLoadGame()
Perform a (large) amount of savegame conversion magic in order to load older savegames and to fill th...
@ SLF_ALLOW_NEWLINE
Allow new lines in the strings.
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
static void SlSaveChunks()
Save all chunks.
@ SLA_LOAD_CHECK
partial loading into _load_check_data
@ SLV_END_PATCHPACKS
286 Last known patchpack to use a version just above ours.
@ SLO_CHECK
Load file for checking and/or preview.
std::string extra_msg
the error message
byte fwrite_buf[MEMORY_CHUNK_SIZE]
Buffer for writing to the file.
MemoryDumper()
Initialise our variables.
static void FixSCCEncoded(std::string &str)
Scan the string for old values of SCC_ENCODED and fix it to it's new, value.
static void StrMakeValid(T &dst, const char *str, const char *last, StringValidationSettings settings)
Copies the valid (UTF-8) characters from str up to last to the dst.
bool _do_autosave
are we doing an autosave at the moment?
size_t GetSize() const
Get the size of the memory dump made so far.
@ DFT_GAME_FILE
Save game or scenario file.
Deals with the type of the savegame, independent of extension.
GRFConfig * grfconfig
NewGrf configuration from save.
@ SLE_VAR_NULL
useful to write zeros in savegame.
size_t Read(byte *buf, size_t ssize) override
Read a given number of bytes from the savegame.
SaveLoadTable GetLoadDescription() const
Get the description for how to load the chunk.
ChunkType type
Type of the chunk.
A buffer for reading (and buffering) savegame data.
static DateFract date_fract
Fractional part of the day.
static Station * Get(size_t index)
Gets station with given index.
@ AUTOSAVE_DIR
Subdirectory of save for autosaves.
std::span< const struct SaveLoadCompat > SaveLoadCompatTable
A table of SaveLoadCompat entries.
ClientSettings _settings_client
The current settings for this game.
DetailedFileType GetDetailedFileType(FiosType fios_type)
Extract the detailed file type from a FiosType.
static void SlNullPointers()
Null all pointers (convert index -> nullptr)
static bool IsValidID(size_t index)
Tests whether given index is a valid index for station of this type.
std::shared_ptr< SaveFilter > chain
Chained to the (savegame) filters.
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
void Reset()
Resets and frees all memory allocated - used before loading or starting a new game.
Filter using Zlib compression.
Handlers and description of chunk.
VarType conv
Type of the variable to be saved; this field combines both FileVarType and MemVarType.
void WriteLoop(byte *p, size_t len, lzma_action action)
Helper loop for writing the data.
Owner
Enum for all companies/owners.
static byte SlCalcConvFileLen(VarType conv)
Return the size in bytes of a certain type of normal/atomic variable as it appears in a saved game.
SaveLoadAction
What are we currently doing?
Handler for saving/loading an object to/from disk.
static size_t SlCalcStdStringLen(const void *ptr)
Calculate the gross length of the string that it will occupy in the savegame.
@ NL_NONE
not working in NeedLength mode
void(* AsyncSaveFinishProc)()
Callback for when the savegame loading is finished.
void SlSetLength(size_t length)
Sets the length of either a RIFF object or the number of items in an array.
size_t Read(byte *buf, size_t size) override
Read a given number of bytes from the savegame.
z_stream z
Stream state we are writing to.
ZlibLoadFilter(std::shared_ptr< LoadFilter > chain)
Initialise this filter.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
static uint SlReadSimpleGamma()
Read in the header descriptor of an object or an array.
@ SLE_FILE_TYPE_MASK
Mask to get the file-type (and not any flags).
byte * buf
Buffer we're going to write to.
int64_t ReadValue(const void *ptr, VarType conv)
Return a signed-long version of the value of a setting.
void SlGlobList(const SaveLoadTable &slt)
Save or Load (a list of) global variables.
Filter without any compression.
@ REF_STATION
Load/save a reference to a station.
Filter without any compression.
static uint SlCalcConvMemLen(VarType conv)
Return the size in bytes of a certain type of normal/atomic variable as it appears in memory.
std::shared_ptr< LoadFilter > lf
Filter to read the savegame from.
AbstractFileType
The different abstract types of files that the system knows about.
static size_t ReferenceToInt(const void *obj, SLRefType rt)
Pointers cannot be saved to a savegame, so this functions gets the index of the item,...
AbstractFileType abstract_ftype
Abstract type of file (scenario, heightmap, etc).
byte buf[MEMORY_CHUNK_SIZE]
Buffer we're going to read from.
FILE * file
The file to write to.
@ SVS_ALLOW_CONTROL_CODE
Allow the special control codes.
@ BASE_DIR
Base directory for all subdirectories.
LoadFilter(std::shared_ptr< LoadFilter > chain)
Initialise this filter.
@ SL_SAVEBYTE
Save (but not load) a byte.
constexpr VarType GetVarMemType(VarType type)
Get the NumberType of a setting.
static void SaveFileDone()
Update the gui accordingly when saving is done and release locks on saveload.
@ SLF_ALLOW_CONTROL
Allow control codes in the strings.
Handler that is assigned when there is a struct read in the savegame which is not known to the code.
void WriteByte(byte b)
Write a single byte into the dumper.
@ SLE_FILE_HAS_LENGTH_FIELD
Bit stored in savegame to indicate field has a length field for each entry.
@ SLO_LOAD
File is being loaded.
static void SaveFileError()
Show a gui message when saving has failed.
GRFListCompatibility IsGoodGRFConfigList(GRFConfig *grfconfig)
Check if all GRFs in the GRF config from a savegame can be loaded.
SaveLoadVersion _sl_version
the major savegame version identifier
static void SlFixPointers()
Fix all pointers (convert index -> pointer)
static uint32_t BSWAP32(uint32_t x)
Perform a 32 bits endianness bitswap on x.
SavegameType
Types of save games.
const SaveLoadVersion SAVEGAME_VERSION
Current savegame version of OpenTTD.
ZlibSaveFilter(std::shared_ptr< SaveFilter > chain, byte compression_level)
Initialise this filter.
Filter using Zlib compression.
@ SLO_SAVE
File is being saved.
@ SBI_SAVELOAD_FINISH
finished saving
static void * IntToReference(size_t index, SLRefType rt)
Pointers cannot be loaded from a savegame, so this function gets the index from the savegame and retu...
void SlSaveLoadRef(void *ptr, VarType conv)
Handle conversion for references.
@ CH_TYPE_MASK
All ChunkType values have to be within this mask.
@ NL_CALCLENGTH
need to calculate the length
virtual void Save() const
Save the chunk.
@ CH_READONLY
Chunk is never saved.
static size_t SlCalcDequeLen(const void *deque, VarType conv)
Return the size in bytes of a std::deque.
void SlWriteByte(byte b)
Wrapper for writing a byte to the dumper.
bool IsSavegameVersionBefore(SaveLoadVersion major, byte minor=0)
Checks whether the savegame is below major.
@ SL_VAR
Save/load a variable.
void free(const void *ptr)
Version of the standard free that accepts const pointers.
std::string _savegame_format
how to compress savegames
FILE * FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
std::shared_ptr< SaveFilter > sf
Filter to write the savegame to.
void Write(byte *buf, size_t size) override
Write a given number of bytes into the savegame.
@ NL_WANTLENGTH
writing length and data
const char * GetSaveLoadErrorString()
Get the string representation of the error message.
size_t Read(byte *buf, size_t size) override
Read a given number of bytes from the savegame.
void SanitizeFilename(std::string &filename)
Sanitizes a filename, i.e.
static void SlCopyInternal(void *object, size_t length, VarType conv)
Internal function to save/Load a list of SL_VARs.
Class for pooled persistent storage of data.
SavegameType _savegame_type
type of savegame we are loading
static void SlLoadCheckChunks()
Load all chunks for savegame checking.
void Flush(std::shared_ptr< SaveFilter > writer)
Flush this dumper into a writer.
std::string CopyFromOldName(StringID id)
Copy and convert old custom names to UTF-8.
static void SlVector(void *vector, VarType conv)
Save/load a std::vector.
FILE * file
The file to read from.
@ SL_REINIT
error that was caught in the middle of updating game state, need to clear it. (can only happen during...
SaveLoadType cmd
The action to take with the saved/loaded type, All types need different action.
Deals with finding savegames.
ReadBuffer(std::shared_ptr< LoadFilter > reader)
Initialise our variables.
SLRefType
Type of reference (SLE_REF, SLE_CONDREF).
bool StartNewThread(std::thread *thr, const char *name, TFn &&_Fx, TArgs &&... _Ax)
Start a new thread.
static void SlSaveLoadConv(void *ptr, VarType conv)
Handle all conversion and typechecking of variables here.
void WriteLoop(byte *p, size_t len, int mode)
Helper loop for writing the data.
void Write(byte *buf, size_t size) override
Write a given number of bytes into the savegame.
void * GetVariableAddress(const void *object, const SaveLoad &sld)
Get the address of the variable.
std::optional< size_t > savegame_size
Size of the last saved savegame in bytes, or std::nullopt if not saved yet.
static const SaveLoadFormat * GetSavegameFormat(const std::string &full_name, byte *compression_level)
Return the savegameformat of the game.
void Write(byte *buf, size_t size) override
Write a given number of bytes into the savegame.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
static SaveOrLoadResult SaveFileToDisk(bool threaded)
We have written the whole game into memory, _memory_savegame, now find and appropriate compressor and...
static size_t SlCalcRefListLen(const void *list, VarType conv)
Return the size in bytes of a list.
std::string GenerateDefaultSaveName()
Get the default name for a savegame or screenshot.
bool keep_all_autosave
name the autosave in a different way
static const std::vector< ChunkHandlerRef > & ChunkHandlers()
@ SLV_SAVELOAD_LIST_LENGTH
293 PR#9374 Consistency in list length with SL_STRUCT / SL_STRUCTLIST / SL_DEQUE / SL_REFLIST.
@ SL_ARR
Save/load a fixed-size array of SL_VAR elements.
@ SLE_FILE_STRINGID
StringID offset into strings-array.
@ REF_STORAGE
Load/save a reference to a persistent storage.
@ SCENARIO_DIR
Base directory for all scenarios.
@ FT_INVALID
Invalid or unknown file type.
fluid_settings_t * settings
FluidSynth settings handle.
@ SLA_PTRS
fixing pointers
@ SL_MAX_VERSION
Highest possible saveload version.
static void SaveFileStart()
Update the gui accordingly when starting saving and set locks on saveload.
@ REF_ENGINE_RENEWS
Load/save a reference to an engine renewal (autoreplace).
@ DFT_OLD_GAME_FILE
Old save game or scenario file.
std::shared_ptr< LoadFilter > reader
The filter used to actually read.
@ REF_VEHICLE
Load/save a reference to a vehicle.
@ SL_REF
Save/load a reference.
@ SLV_4
4.0 1 4.1 122 0.3.3, 0.3.4 4.2 1222 0.3.5 4.3 1417 4.4 1426
void DoAutoOrNetsave(FiosNumberedSaveName &counter)
Create an autosave or netsave.
@ REF_CARGO_PACKET
Load/save a reference to a cargo packet.
@ SL_STRUCT
Save/load a struct.
@ SBI_SAVELOAD_START
started saving
lzma_stream lzma
Stream state that we are reading from.
byte * bufp
Location we're at reading the buffer.
void SlAutolength(AutolengthProc *proc, void *arg)
Do something of which I have no idea what it is :P.
Struct to store engine replacements.
@ REF_VEHICLE_OLD
Load/save an old-style reference to a vehicle (for pre-4.4 savegames).
LZOLoadFilter(std::shared_ptr< LoadFilter > chain)
Initialise this filter.
StringID error_str
the translatable error message to show
virtual void Load() const =0
Load the chunk.
GameSessionStats _game_session_stats
Statistics about the current session.
void Write(byte *buf, size_t size) override
Write a given number of bytes into the savegame.
virtual SaveLoadTable GetDescription() const override
Get the description of the fields in the savegame.
StringValidationSettings
Settings for the string validation.
size_t SlGetStructListLength(size_t limit)
Get the length of this list; if it exceeds the limit, error out.
std::shared_ptr< SaveLoadHandler > handler
Custom handler for Save/Load procs.
StringID error
Error message from loading. INVALID_STRING_ID if no error.
@ SL_VECTOR
Save/load a vector of SL_VAR elements.
static size_t SlCalcVectorLen(const void *vector, VarType conv)
Return the size in bytes of a std::vector.
byte * bufe
End of the buffer we write to.
bool expect_table_header
In the case of a table, if the header is saved/loaded.
static void SlLoadCheckChunk(const ChunkHandler &ch)
Load a chunk of data for checking savegames.
std::shared_ptr< LoadFilter > chain
Chained to the (savegame) filters.
@ REF_LINK_GRAPH_JOB
Load/save a reference to a link graph job.
z_stream z
Stream state we are reading from.
~LZMALoadFilter()
Clean everything up.
@ DFT_INVALID
Unknown or invalid file.
static SaveLoadParams _sl
Parameters used for/at saveload.
void StartAction(GamelogActionType at)
Stores information about new action, but doesn't allocate it Action is allocated only when there is a...
void StopAction()
Stops logging of any changes.
NeedLength need_length
working in NeedLength (Autolength) mode?
int8_t Utf8EncodedCharLen(char c)
Return the length of an UTF-8 encoded value based on a single char.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
SaveOrLoadResult SaveWithFilter(std::shared_ptr< SaveFilter > writer, bool threaded)
Save the game using a (writer) filter.
static size_t SlCalcLen(const void *storage, VarType conv, SaveLoadType cmd=SL_VAR)
Internal templated helper to return the size in bytes of a list-like type.
static uint8_t GetSavegameFileType(const SaveLoad &sld)
Return the type as saved/loaded inside the savegame.
bool threaded_saves
should we do threaded saves?
A savegame name automatically numbered.
@ REF_ORDERLIST
Load/save a reference to an orderlist.
The saveload struct, containing reader-writer functions, buffer, version, etc.
size_t Read(byte *buf, size_t size) override
Read a given number of bytes from the savegame.
size_t SlGetFieldLength()
Get the length of the current object.
static size_t SlCalcArrayLen(size_t length, VarType conv)
Return the size in bytes of a certain type of atomic array.
DetailedFileType
Kinds of files in each AbstractFileType.
void Clear()
Reset read data.
Template class to help with list-like types.
byte fwrite_buf[MEMORY_CHUNK_SIZE]
Buffer for writing to the file.
static const SaveLoadFormat _saveload_formats[]
The different saveload formats known/understood by OpenTTD.
@ SLV_START_PATCHPACKS
220 First known patchpack to use a version just above ours.
void Reset() override
Reset this filter to read from the beginning of the file.
@ SL_REFLIST
Save/load a list of SL_REF elements.
void Set(const FiosItem &item)
Set the title of the file.
uint8_t date_format_in_default_names
should the default savegame/screenshot name use long dates (31th Dec 2008), short dates (31-12-2008) ...
Interface for filtering a savegame till it is written.
static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
Called by save thread to tell we finished saving.
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
SaveLoadAction action
are we doing a save or a load atm.
#define endof(x)
Get the end element of an fixed size array.
FileToSaveLoad _file_to_saveload
File to save or load in the openttd loop.
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
static uint SlGetGammaLength(size_t i)
Return how many bytes used to encode a gamma value.
byte SlReadByte()
Wrapper for reading a byte from the buffer.
void Finish() override
Prepare everything to finish writing the savegame.
std::unique_ptr< MemoryDumper > dumper
Memory dumper to write the savegame to.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Filter using LZO compression.
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
size_t obj_len
the length of the current object we are busy with
~LZMASaveFilter()
Clean up what we allocated.
void SlSkipBytes(size_t length)
Read in bytes from the file/data structure but don't do anything with them, discarding them in effect...
Subdirectory
The different kinds of subdirectories OpenTTD uses.
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
static void SlWriteSimpleGamma(size_t i)
Write the header descriptor of an object or an array.
NoCompSaveFilter(std::shared_ptr< SaveFilter > chain, byte)
Initialise this filter.
SaveLoadVersion version_from
Save/load the variable starting from this savegame version.
GRFListCompatibility grf_compatibility
Summary state of NewGrfs, whether missing files or only compatible found.
SaveOrLoadResult
Save or load result codes.
@ WL_ERROR
Errors (eg. saving/loading failed)
FiosType
Elements of a file system that are recognized.
@ SLE_VAR_STRQ
string pointer enclosed in quotes
bool saveinprogress
Whether there is currently a save in progress.
std::unique_ptr< ReadBuffer > reader
Savegame reading buffer.
static constexpr TimerGameTick::Ticks TICKS_PER_SECOND
Estimation of how many ticks fit in a single second.
static void SlRefList(void *list, VarType conv)
Save/Load a list.
size_t read
The amount of read bytes so far from the filter.
GRFConfig * _grfconfig
First item in list of current GRF set up.
@ REF_LINK_GRAPH
Load/save a reference to a link graph.
@ SLO_INVALID
Unknown file operation.
@ SLA_NULL
null all pointers (on loading error)
static void SlStdString(void *ptr, VarType conv)
Save/Load a std::string.
Interface for filtering a savegame till it is loaded.
#define lengthof(x)
Return the length of an fixed size array.
bool error
did an error occur or not
Container for cargo from the same location and time.
@ SL_DEQUE
Save/load a deque of SL_VAR elements.
SaveOrLoadResult LoadWithFilter(std::shared_ptr< LoadFilter > reader)
Load the game using a (reader) filter.
uint32_t id
Unique ID (4 letters).
~FileReader()
Make sure everything is cleaned up.
void SlError(StringID string, const std::string &extra_msg)
Error handler.
AbstractFileType GetAbstractFileType(FiosType fios_type)
Extract the abstract file type from a FiosType.
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
static void SlCopyBytes(void *ptr, size_t length)
Save/Load bytes.
Filter using LZO compression.
static const size_t MEMORY_CHUNK_SIZE
Save in chunks of 128 KiB.
void ProcessAsyncSaveFinish()
Handle async save finishes.
std::vector< byte * > blocks
Buffer with blocks of allocated memory.
Yes, simply reading from a file.
int last_array_index
in the case of an array, the current and last positions
static size_t SlCalcRefLen()
Return the size in bytes of a reference (pointer)
void Finish() override
Prepare everything to finish writing the savegame.
size_t Utf8Encode(T buf, char32_t c)
Encode a unicode character and place it in the buffer.
static std::atomic< AsyncSaveFinishProc > _async_save_finish
Callback to call when the savegame loading is finished.
@ SL_ERROR
error that was caught before internal structures were modified
DetailedFileType detail_ftype
Concrete file type (PNG, BMP, old save, etc).
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
uint16_t length
(Conditional) length of the variable (eg. arrays) (max array size is 65536 elements).
@ WC_STATUS_BAR
Statusbar (at the bottom of your screen); Window numbers:
size_t GetSize() const
Get the size of the memory dump made so far.
A Stop for a Road Vehicle.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
std::string Extension()
Generate an extension for a savegame name.
std::string name
Name of this field (optional, used for tables).
void SlObject(void *object, const SaveLoadTable &slt)
Main SaveLoad function.
~ZlibSaveFilter()
Clean up what we allocated.
virtual void LoadCheck(size_t len=0) const
Load the chunk for game preview.
size_t Utf8Decode(char32_t *c, const char *s)
Decode and consume the next UTF-8 encoded character.
Filter using LZMA compression.
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
void SlSetStructListLength(size_t length)
Set the length of this list.
void SetMode(FiosType ft)
Set the mode and file type of the file to save or load based on the type of file entry at the file sy...
virtual SaveLoadCompatTable GetCompatDescription() const override
Get the pre-header description of the fields in the savegame.
void Write(byte *buf, size_t size) override
Write a given number of bytes into the savegame.
static void ClearSaveLoadState()
Clear/free saveload state.
static SaveOrLoadResult DoSave(std::shared_ptr< SaveFilter > writer, bool threaded)
Actually perform the saving of the savegame.
#define lastof(x)
Get the last element of an fixed size array.
@ SL_OK
completed successfully
@ SVS_REPLACE_WITH_QUESTION_MARK
Replace the unknown/bad bits with question marks.
std::string Filename()
Generate a savegame name and number according to _settings_client.gui.max_num_autosaves.
@ SL_STDSTR
Save/load a std::string.
LZOSaveFilter(std::shared_ptr< SaveFilter > chain, byte)
Initialise this filter.
static const lzma_stream _lzma_init
Have a copy of an initialised LZMA stream.
@ SLE_VAR_NAME
old custom name to be converted to a char pointer
LZMALoadFilter(std::shared_ptr< LoadFilter > chain)
Initialise this filter.
~FileWriter()
Make sure everything is cleaned up.
size_t SlCalcObjLength(const void *object, const SaveLoadTable &slt)
Calculate the size of an object.
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
void WriteValue(void *ptr, VarType conv, int64_t val)
Write the value of a setting.
FileReader(FILE *file)
Create the file reader, so it reads from a specific file.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
static void SlSaveChunk(const ChunkHandler &ch)
Save a chunk of data (eg.
GUISettings gui
settings related to the GUI
@ WL_CRITICAL
Critical errors, the MessageBox is shown in all cases.
static const ChunkHandler * SlFindChunkHandler(uint32_t id)
Find the ChunkHandler that will be used for processing the found chunk in the savegame or in memory.
void Finish() override
Prepare everything to finish writing the savegame.
SaveLoadOperation file_op
File operation to perform.
Yes, simply writing to a file.
byte * bufe
End of the buffer we can read from.
constexpr VarType GetVarFileType(VarType type)
Get the FileType of a setting.
Container for dumping the savegame (quickly) to memory.
@ SL_STRUCTLIST
Save/load a list of structs.
static SaveOrLoadResult DoLoad(std::shared_ptr< LoadFilter > reader, bool load_check)
Actually perform the loading of a "non-old" savegame.
static Date date
Current date in days (day counter).
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.