OpenTTD Source
20240917-master-g9ab0a47812
|
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 uint8_t 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);
129 std::vector<std::unique_ptr<uint8_t[]>>
blocks{};
140 if (this->buf == this->bufe) {
152 void Flush(std::shared_ptr<SaveFilter> writer)
160 writer->Write(this->
blocks[i++].get(), to_write);
173 return this->
blocks.size() * MEMORY_CHUNK_SIZE - (this->bufe - this->
buf);
189 std::shared_ptr<SaveFilter>
sf;
192 std::shared_ptr<LoadFilter>
lf;
244 _gamelog_chunk_handlers,
246 _misc_chunk_handlers,
247 _name_chunk_handlers,
248 _cheat_chunk_handlers,
249 _setting_chunk_handlers,
251 _waypoint_chunk_handlers,
252 _depot_chunk_handlers,
253 _order_chunk_handlers,
254 _industry_chunk_handlers,
255 _economy_chunk_handlers,
256 _subsidy_chunk_handlers,
257 _cargomonitor_chunk_handlers,
258 _goal_chunk_handlers,
259 _story_page_chunk_handlers,
260 _league_chunk_handlers,
261 _engine_chunk_handlers,
262 _town_chunk_handlers,
263 _sign_chunk_handlers,
264 _station_chunk_handlers,
265 _company_chunk_handlers,
267 _game_chunk_handlers,
268 _animated_tile_chunk_handlers,
269 _newgrf_chunk_handlers,
270 _group_chunk_handlers,
271 _cargopacket_chunk_handlers,
272 _autoreplace_chunk_handlers,
273 _labelmaps_chunk_handlers,
274 _linkgraph_chunk_handlers,
275 _airport_chunk_handlers,
276 _object_chunk_handlers,
277 _persistent_storage_chunk_handlers,
278 _water_region_chunk_handlers,
279 _randomizer_chunk_handlers,
282 static std::vector<ChunkHandlerRef> _chunk_handlers;
284 if (_chunk_handlers.empty()) {
285 for (
auto &chunk_handler_table : _chunk_handler_tables) {
286 for (
auto &chunk_handler : chunk_handler_table) {
287 _chunk_handlers.push_back(chunk_handler);
292 return _chunk_handlers;
306 Debug(sl, 3,
"Nulling pointers for {}", ch.GetName());
341 throw std::exception();
353 SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
367 if (_exit_game)
return;
379 if (proc ==
nullptr)
return;
406 static inline int SlReadUint16()
412 static inline uint32_t SlReadUint32()
414 uint32_t x = SlReadUint16() << 16;
415 return x | SlReadUint16();
418 static inline uint64_t SlReadUint64()
420 uint32_t x = SlReadUint32();
421 uint32_t y = SlReadUint32();
422 return (uint64_t)x << 32 | y;
425 static inline void SlWriteUint16(uint16_t v)
431 static inline void SlWriteUint32(uint32_t v)
433 SlWriteUint16(
GB(v, 16, 16));
434 SlWriteUint16(
GB(v, 0, 16));
437 static inline void SlWriteUint64(uint64_t x)
439 SlWriteUint32((uint32_t)(x >> 32));
440 SlWriteUint32((uint32_t)x);
497 if (i >= (1 << 14)) {
498 if (i >= (1 << 21)) {
499 if (i >= (1 << 28)) {
500 assert(i <= UINT32_MAX);
521 return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21)) + (i >= (1 << 28));
524 static inline uint SlReadSparseIndex()
529 static inline void SlWriteSparseIndex(uint index)
534 static inline uint SlReadArrayLength()
539 static inline void SlWriteArrayLength(
size_t length)
544 static inline uint SlGetArrayLength(
size_t length)
577 default: NOT_REACHED();
590 case SLE_VAR_BL:
return sizeof(bool);
591 case SLE_VAR_I8:
return sizeof(int8_t);
592 case SLE_VAR_U8:
return sizeof(uint8_t);
593 case SLE_VAR_I16:
return sizeof(int16_t);
594 case SLE_VAR_U16:
return sizeof(uint16_t);
595 case SLE_VAR_I32:
return sizeof(int32_t);
596 case SLE_VAR_U32:
return sizeof(uint32_t);
597 case SLE_VAR_I64:
return sizeof(int64_t);
598 case SLE_VAR_U64:
return sizeof(uint64_t);
603 return SlReadArrayLength();
621 case SLE_FILE_I8:
return sizeof(int8_t);
622 case SLE_FILE_U8:
return sizeof(uint8_t);
623 case SLE_FILE_I16:
return sizeof(int16_t);
624 case SLE_FILE_U16:
return sizeof(uint16_t);
625 case SLE_FILE_I32:
return sizeof(int32_t);
626 case SLE_FILE_U32:
return sizeof(uint32_t);
627 case SLE_FILE_I64:
return sizeof(int64_t);
628 case SLE_FILE_U64:
return sizeof(uint64_t);
631 case SLE_FILE_STRING:
632 return SlReadArrayLength();
634 case SLE_FILE_STRUCT:
646 void SlSetArrayIndex(uint index)
649 _sl.array_index = index;
652 static size_t _next_offs;
662 if (_next_offs != 0 &&
_sl.
reader->GetSize() != _next_offs) {
663 SlErrorCorruptFmt(
"Invalid chunk size iterating array - expected to be at position {}, actually at {}", _next_offs,
_sl.
reader->GetSize());
667 uint length = SlReadArrayLength();
675 _next_offs =
_sl.
reader->GetSize() + length;
684 case CH_SPARSE_TABLE:
685 case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex();
break;
687 case CH_ARRAY: index =
_sl.array_index++;
break;
689 Debug(sl, 0,
"SlIterateArray error");
693 if (length != 0)
return index;
721 SlWriteArrayLength(length + 1);
730 assert(length < (1 << 28));
731 SlWriteUint32((uint32_t)((length & 0xFFFFFF) | ((length >> 24) << 28)));
737 SlWriteArrayLength(1);
739 SlWriteArrayLength(length + 1);
741 case CH_SPARSE_TABLE:
742 case CH_SPARSE_ARRAY:
743 SlWriteArrayLength(length + 1 + SlGetArrayLength(
_sl.array_index));
744 SlWriteSparseIndex(
_sl.array_index);
746 default: NOT_REACHED();
754 default: NOT_REACHED();
766 uint8_t *p = (uint8_t *)ptr;
771 for (; length != 0; length--) *p++ =
SlReadByte();
776 default: NOT_REACHED();
796 case SLE_VAR_BL:
return (*(
const bool *)ptr != 0);
797 case SLE_VAR_I8:
return *(
const int8_t *)ptr;
798 case SLE_VAR_U8:
return *(
const uint8_t *)ptr;
799 case SLE_VAR_I16:
return *(
const int16_t *)ptr;
800 case SLE_VAR_U16:
return *(
const uint16_t*)ptr;
801 case SLE_VAR_I32:
return *(
const int32_t *)ptr;
802 case SLE_VAR_U32:
return *(
const uint32_t*)ptr;
803 case SLE_VAR_I64:
return *(
const int64_t *)ptr;
804 case SLE_VAR_U64:
return *(
const uint64_t*)ptr;
806 default: NOT_REACHED();
820 case SLE_VAR_BL: *(
bool *)ptr = (val != 0);
break;
821 case SLE_VAR_I8: *(int8_t *)ptr = val;
break;
822 case SLE_VAR_U8: *(uint8_t *)ptr = val;
break;
823 case SLE_VAR_I16: *(int16_t *)ptr = val;
break;
824 case SLE_VAR_U16: *(uint16_t*)ptr = val;
break;
825 case SLE_VAR_I32: *(int32_t *)ptr = val;
break;
826 case SLE_VAR_U32: *(uint32_t*)ptr = val;
break;
827 case SLE_VAR_I64: *(int64_t *)ptr = val;
break;
828 case SLE_VAR_U64: *(uint64_t*)ptr = val;
break;
831 default: NOT_REACHED();
851 case SLE_FILE_I8: assert(x >= -128 && x <= 127);
SlWriteByte(x);
break;
852 case SLE_FILE_U8: assert(x >= 0 && x <= 255);
SlWriteByte(x);
break;
853 case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);
break;
855 case SLE_FILE_U16:assert(x >= 0 && x <= 65535); SlWriteUint16(x);
break;
857 case SLE_FILE_U32: SlWriteUint32((uint32_t)x);
break;
859 case SLE_FILE_U64: SlWriteUint64(x);
break;
860 default: NOT_REACHED();
869 case SLE_FILE_I8: x = (int8_t )
SlReadByte();
break;
870 case SLE_FILE_U8: x = (uint8_t )
SlReadByte();
break;
871 case SLE_FILE_I16: x = (int16_t )SlReadUint16();
break;
872 case SLE_FILE_U16: x = (uint16_t)SlReadUint16();
break;
873 case SLE_FILE_I32: x = (int32_t )SlReadUint32();
break;
874 case SLE_FILE_U32: x = (uint32_t)SlReadUint32();
break;
875 case SLE_FILE_I64: x = (int64_t )SlReadUint64();
break;
876 case SLE_FILE_U64: x = (uint64_t)SlReadUint64();
break;
878 default: NOT_REACHED();
887 default: NOT_REACHED();
900 const std::string *str =
reinterpret_cast<const std::string *
>(ptr);
902 size_t len = str->length();
903 return len + SlGetArrayLength(len);
916 for (
size_t i = 0; i < str.size(); ) {
918 if (len == 0 || i + len > str.size())
break;
922 if (c == 0xE028 || c == 0xE02A)
Utf8Encode(&str[i], SCC_ENCODED);
934 std::string *str =
reinterpret_cast<std::string *
>(ptr);
938 size_t len = str->length();
939 SlWriteArrayLength(len);
940 SlCopyBytes(
const_cast<void *
>(
static_cast<const void *
>(str->c_str())), len);
946 size_t len = SlReadArrayLength();
968 default: NOT_REACHED();
992 if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
993 conv == SLE_INT32 || conv == SLE_UINT32) {
998 if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
999 for (uint i = 0; i < length; i++) {
1000 ((int64_t*)
object)[i] = (int32_t)
BSWAP32(SlReadUint32());
1008 if (conv == SLE_INT8 || conv == SLE_UINT8) {
1011 uint8_t *a = (uint8_t*)
object;
1014 for (; length != 0; length --) {
1029 void SlCopy(
void *
object,
size_t length, VarType conv)
1059 static void SlArray(
void *array,
size_t length, VarType conv)
1063 SlWriteArrayLength(length);
1070 size_t sv_length = SlReadArrayLength();
1074 }
else if (sv_length != length) {
1109 if (obj ==
nullptr)
return 0;
1124 default: NOT_REACHED();
1140 static_assert(
sizeof(
size_t) <=
sizeof(
void *));
1205 default: NOT_REACHED();
1228 *(
void **)ptr =
nullptr;
1230 default: NOT_REACHED();
1237 template <
template<
typename,
typename>
typename Tstorage,
typename Tvar,
typename Tallocator = std::allocator<Tvar>>
1239 typedef Tstorage<Tvar, Tallocator> SlStorageT;
1251 const SlStorageT *list =
static_cast<const SlStorageT *
>(storage);
1253 int type_size = SlGetArrayLength(list->size());
1255 return list->size() * item_size + type_size;
1258 static void SlSaveLoadMember(
SaveLoadType cmd, Tvar *item, VarType conv)
1279 SlStorageT *list =
static_cast<SlStorageT *
>(storage);
1283 SlWriteArrayLength(list->size());
1285 for (
auto &item : *list) {
1286 SlSaveLoadMember(cmd, &item, conv);
1296 case SL_STDSTR: length = SlReadArrayLength();
break;
1297 default: NOT_REACHED();
1301 for (
size_t i = 0; i < length; i++) {
1302 Tvar &data = list->emplace_back();
1303 SlSaveLoadMember(cmd, &data, conv);
1309 for (
auto &item : *list) {
1310 SlSaveLoadMember(cmd, &item, conv);
1318 default: NOT_REACHED();
1373 default: NOT_REACHED();
1404 default: NOT_REACHED();
1416 case SLE_VAR_BL: NOT_REACHED();
1431 default: NOT_REACHED();
1443 case SLE_VAR_BL: NOT_REACHED();
1462 default: NOT_REACHED();
1481 for (
auto &sld : slt) {
1490 for (
auto &sld : slt) {
1511 for (
auto &sld : slt) {
1512 length += SlCalcObjMemberLength(
object, sld);
1517 size_t SlCalcObjMemberLength(
const void *
object,
const SaveLoad &sld)
1545 sld.
handler->Save(
const_cast<void *
>(
object));
1552 length += SlGetArrayLength(1);
1558 default: NOT_REACHED();
1563 static bool SlObjectMember(
void *
object,
const SaveLoad &sld)
1567 VarType conv =
GB(sld.
conv, 0, 8);
1586 default: NOT_REACHED();
1603 default: NOT_REACHED();
1617 default: NOT_REACHED();
1638 sld.
handler->LoadCheck(
object);
1651 sld.
handler->FixPointers(
object);
1655 default: NOT_REACHED();
1659 default: NOT_REACHED();
1676 SlWriteArrayLength(length);
1686 size_t length = SlReadArrayLength();
1705 for (
auto &sld : slt) {
1706 SlObjectMember(
object, sld);
1715 void Save(
void *)
const override
1720 void Load(
void *
object)
const override
1723 for (; length > 0; length--) {
1728 void LoadCheck(
void *
object)
const override
1758 std::vector<SaveLoad> saveloads;
1761 std::map<std::string, const SaveLoad *> key_lookup;
1762 for (
auto &sld : slt) {
1766 assert(key_lookup.find(sld.
name) == key_lookup.end());
1767 key_lookup[sld.
name] = &sld;
1778 auto sld_it = key_lookup.find(key);
1779 if (sld_it == key_lookup.end()) {
1783 std::shared_ptr<SaveLoadHandler> handler =
nullptr;
1786 case SLE_FILE_STRING:
1791 case SLE_FILE_STRUCT:
1794 handler = std::make_shared<SlSkipHandler>();
1813 if (correct_type != type) {
1814 Debug(sl, 1,
"Field type for '{}' was expected to be 0x{:02x} but 0x{:02x} was found", key, correct_type, type);
1817 saveloads.push_back(*sld_it->second);
1820 for (
auto &sld : saveloads) {
1836 for (
auto &sld : slt) {
1839 assert(!sld.
name.empty());
1853 for (
auto &sld : slt) {
1869 default: NOT_REACHED();
1872 return std::vector<SaveLoad>();
1894 std::vector<SaveLoad> saveloads;
1897 std::map<std::string, std::vector<const SaveLoad *>> key_lookup;
1898 for (
auto &sld : slt) {
1900 assert(!sld.
name.empty());
1902 key_lookup[sld.
name].push_back(&sld);
1905 for (
auto &slc : slct) {
1906 if (slc.name.empty()) {
1912 auto sld_it = key_lookup.find(slc.name);
1916 if (sld_it == key_lookup.end()) {
1919 Debug(sl, 0,
"internal error: saveload compatibility field '{}' not found", slc.name);
1922 for (
auto &sld : sld_it->second) {
1923 saveloads.push_back(*sld);
1928 for (
auto &sld : saveloads) {
1965 size_t start_pos =
_sl.
dumper->GetSize();
1966 size_t expected_offs = start_pos +
_sl.
obj_len;
1971 if (expected_offs !=
_sl.
dumper->GetSize()) {
1972 SlErrorCorruptFmt(
"Invalid chunk size when writing autolength block, expected {}, got {}",
_sl.
obj_len,
_sl.
dumper->GetSize() - start_pos);
1980 case CH_SPARSE_TABLE:
1984 case CH_SPARSE_ARRAY:
2016 _sl.array_index = 0;
2020 case CH_SPARSE_TABLE:
2021 case CH_SPARSE_ARRAY:
2027 size_t len = (
SlReadByte() << 16) | ((m >> 4) << 24);
2028 len += SlReadUint16();
2030 size_t start_pos =
_sl.
reader->GetSize();
2031 size_t endoffs = start_pos + len;
2035 SlErrorCorruptFmt(
"Invalid chunk size in RIFF in {} - expected {}, got {}", ch.GetName(), len,
_sl.
reader->GetSize() - start_pos);
2069 _sl.array_index = 0;
2072 case CH_SPARSE_TABLE:
2073 case CH_SPARSE_ARRAY:
2078 size_t len = (
SlReadByte() << 16) | ((m >> 4) << 24);
2079 len += SlReadUint16();
2081 size_t start_pos =
_sl.
reader->GetSize();
2082 size_t endoffs = start_pos + len;
2086 SlErrorCorruptFmt(
"Invalid chunk size in RIFF in {} - expected {}, got {}", ch.GetName(), len,
_sl.
reader->GetSize() - start_pos);
2107 SlWriteUint32(ch.
id);
2108 Debug(sl, 2,
"Saving chunk {}", ch.GetName());
2124 SlWriteArrayLength(0);
2126 case CH_SPARSE_TABLE:
2127 case CH_SPARSE_ARRAY:
2130 SlWriteArrayLength(0);
2132 default: NOT_REACHED();
2167 for (
id = SlReadUint32();
id != 0;
id = SlReadUint32()) {
2168 Debug(sl, 2,
"Loading chunk {:c}{:c}{:c}{:c}",
id >> 24,
id >> 16,
id >> 8,
id);
2182 for (
id = SlReadUint32();
id != 0;
id = SlReadUint32()) {
2183 Debug(sl, 2,
"Loading chunk {:c}{:c}{:c}{:c}",
id >> 24,
id >> 16,
id >> 8,
id);
2197 Debug(sl, 3,
"Fixing pointers for {}", ch.GetName());
2221 if (this->file.has_value()) {
2226 size_t Read(uint8_t *buf,
size_t size)
override
2229 if (!this->file.has_value())
return 0;
2231 return fread(buf, 1, size, *this->file);
2236 clearerr(*this->file);
2237 if (fseek(*this->file, this->begin, SEEK_SET)) {
2238 Debug(sl, 1,
"Could not reset the file reading");
2261 void Write(uint8_t *buf,
size_t size)
override
2264 if (!this->file.has_value())
return;
2266 if (fwrite(buf, 1, size, *this->file) != size)
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
2271 if (this->file.has_value()) {
2283 #include <lzo/lzo1x.h>
2296 if (lzo_init() != LZO_E_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize decompressor");
2299 size_t Read(uint8_t *buf,
size_t ssize)
override
2307 lzo_uint len = ssize;
2310 if (this->
chain->Read((uint8_t*)tmp,
sizeof(tmp)) !=
sizeof(tmp))
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE,
"File read failed");
2313 ((uint32_t*)out)[0] = size = tmp[1];
2316 tmp[0] = TO_BE32(tmp[0]);
2317 size = TO_BE32(size);
2323 if (this->
chain->Read(out +
sizeof(uint32_t), size) != size)
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
2326 if (tmp[0] != lzo_adler32(0, out, size +
sizeof(uint32_t)))
SlErrorCorrupt(
"Bad checksum");
2329 int ret = lzo1x_decompress_safe(out +
sizeof(uint32_t) * 1, size, buf, &len,
nullptr);
2330 if (ret != LZO_E_OK)
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
2343 if (lzo_init() != LZO_E_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize compressor");
2346 void Write(uint8_t *buf,
size_t size)
override
2348 const lzo_bytep in = buf;
2351 uint8_t wrkmem[LZO1X_1_MEM_COMPRESS];
2357 lzo1x_1_compress(in, len, out +
sizeof(uint32_t) * 2, &outlen, wrkmem);
2358 ((uint32_t*)out)[1] = TO_BE32((uint32_t)outlen);
2359 ((uint32_t*)out)[0] = TO_BE32(lzo_adler32(0, out +
sizeof(uint32_t), outlen +
sizeof(uint32_t)));
2360 this->
chain->Write(out, outlen +
sizeof(uint32_t) * 2);
2385 size_t Read(uint8_t *buf,
size_t size)
override
2387 return this->chain->Read(buf, size);
2401 void Write(uint8_t *buf,
size_t size)
override
2403 this->chain->Write(buf, size);
2411 #if defined(WITH_ZLIB)
2425 memset(&this->z, 0,
sizeof(this->z));
2426 if (inflateInit(&this->z) != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize decompressor");
2432 inflateEnd(&this->z);
2435 size_t Read(uint8_t *buf,
size_t size)
override
2437 this->z.next_out = buf;
2438 this->z.avail_out = (uint)size;
2442 if (this->z.avail_in == 0) {
2444 this->z.avail_in = (uint)this->chain->Read(this->fread_buf,
sizeof(this->fread_buf));
2448 int r = inflate(&this->z, 0);
2449 if (r == Z_STREAM_END)
break;
2451 if (r != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"inflate() failed");
2452 }
while (this->z.avail_out != 0);
2454 return size - this->z.avail_out;
2470 memset(&this->z, 0,
sizeof(this->z));
2471 if (deflateInit(&this->z, compression_level) != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize compressor");
2477 deflateEnd(&this->z);
2489 this->z.next_in = p;
2490 this->z.avail_in = (uInt)len;
2493 this->z.avail_out =
sizeof(this->
fwrite_buf);
2502 int r = deflate(&this->z, mode);
2505 if ((n =
sizeof(this->fwrite_buf) - this->z.avail_out) != 0) {
2506 this->chain->Write(this->fwrite_buf, n);
2508 if (r == Z_STREAM_END)
break;
2510 if (r != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"zlib returned error code");
2511 }
while (this->z.avail_in || !this->z.avail_out);
2514 void Write(uint8_t *buf,
size_t size)
override
2522 this->chain->Finish();
2532 #if defined(WITH_LIBLZMA)
2555 if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize decompressor");
2561 lzma_end(&this->lzma);
2564 size_t Read(uint8_t *buf,
size_t size)
override
2566 this->lzma.next_out = buf;
2567 this->lzma.avail_out = size;
2571 if (this->lzma.avail_in == 0) {
2573 this->lzma.avail_in = this->chain->Read(this->fread_buf,
sizeof(this->fread_buf));
2577 lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
2578 if (r == LZMA_STREAM_END)
break;
2579 if (r != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"liblzma returned error code");
2580 }
while (this->lzma.avail_out != 0);
2582 return size - this->lzma.avail_out;
2598 if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize compressor");
2604 lzma_end(&this->lzma);
2616 this->lzma.next_in = p;
2617 this->lzma.avail_in = len;
2620 this->lzma.avail_out =
sizeof(this->
fwrite_buf);
2622 lzma_ret r = lzma_code(&this->lzma, action);
2625 if ((n =
sizeof(this->fwrite_buf) - this->lzma.avail_out) != 0) {
2626 this->chain->Write(this->fwrite_buf, n);
2628 if (r == LZMA_STREAM_END)
break;
2629 if (r != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"liblzma returned error code");
2630 }
while (this->lzma.avail_in || !this->lzma.avail_out);
2633 void Write(uint8_t *buf,
size_t size)
override
2640 this->
WriteLoop(
nullptr, 0, LZMA_FINISH);
2641 this->chain->Finish();
2656 std::shared_ptr<LoadFilter> (*
init_load)(std::shared_ptr<LoadFilter> chain);
2657 std::shared_ptr<SaveFilter> (*
init_write)(std::shared_ptr<SaveFilter> chain, uint8_t compression);
2664 static const uint32_t SAVEGAME_TAG_LZO = TO_BE32X(
'OTTD');
2665 static const uint32_t SAVEGAME_TAG_NONE = TO_BE32X(
'OTTN');
2666 static const uint32_t SAVEGAME_TAG_ZLIB = TO_BE32X(
'OTTZ');
2667 static const uint32_t SAVEGAME_TAG_LZMA = TO_BE32X(
'OTTX');
2671 #if defined(WITH_LZO)
2673 {
"lzo", SAVEGAME_TAG_LZO, CreateLoadFilter<LZOLoadFilter>, CreateSaveFilter<LZOSaveFilter>, 0, 0, 0},
2675 {
"lzo", SAVEGAME_TAG_LZO,
nullptr,
nullptr, 0, 0, 0},
2678 {
"none", SAVEGAME_TAG_NONE, CreateLoadFilter<NoCompLoadFilter>, CreateSaveFilter<NoCompSaveFilter>, 0, 0, 0},
2679 #if defined(WITH_ZLIB)
2683 {
"zlib", SAVEGAME_TAG_ZLIB, CreateLoadFilter<ZlibLoadFilter>, CreateSaveFilter<ZlibSaveFilter>, 0, 6, 9},
2685 {
"zlib", SAVEGAME_TAG_ZLIB,
nullptr,
nullptr, 0, 0, 0},
2687 #if defined(WITH_LIBLZMA)
2693 {
"lzma", SAVEGAME_TAG_LZMA, CreateLoadFilter<LZMALoadFilter>, CreateSaveFilter<LZMASaveFilter>, 0, 2, 9},
2695 {
"lzma", SAVEGAME_TAG_LZMA,
nullptr,
nullptr, 0, 0, 0},
2709 if (it == std::rend(
_saveload_formats))
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"no writeable savegame formats");
2713 if (!full_name.empty()) {
2715 size_t separator = full_name.find(
':');
2716 bool has_comp_level = separator != std::string::npos;
2717 const std::string name(full_name, 0, has_comp_level ? separator : full_name.size());
2720 if (slf.init_write !=
nullptr && name.compare(slf.name) == 0) {
2721 if (has_comp_level) {
2722 const std::string complevel(full_name, separator + 1);
2726 long level = std::stol(complevel, &processed, 10);
2727 if (processed == 0 || level !=
Clamp(level, slf.min_compression, slf.max_compression)) {
2731 return {slf, ClampTo<uint8_t>(level)};
2734 return {slf, slf.default_compression};
2746 void InitializeGame(uint size_x, uint size_y,
bool reset_date,
bool reset_settings);
2748 extern bool LoadOldSaveGame(
const std::string &file);
2755 ResetTempEngineData();
2757 ResetOldWaypoints();
2788 #ifdef __EMSCRIPTEN__
2789 EM_ASM(
if (window[
"openttd_syncfs"]) openttd_syncfs());
2802 return _sl.
action ==
SLA_SAVE ? STR_ERROR_GAME_SAVE_FAILED : STR_ERROR_GAME_LOAD_FAILED;
2830 _sl.
sf->Write((uint8_t*)hdr,
sizeof(hdr));
2832 _sl.
sf = fmt.init_write(
_sl.
sf, compression);
2847 if (
_sl.
error_str != STR_NETWORK_ERROR_LOSTCONNECTION) {
2862 void WaitTillSaved()
2884 _sl.
dumper = std::make_unique<MemoryDumper>();
2889 SaveViewportBeforeSaveGame();
2895 if (threaded)
Debug(sl, 1,
"Cannot create savegame thread, reverting to single-threaded mode...");
2916 return DoSave(writer, threaded);
2950 Debug(sl, 0,
"Unknown savegame type, trying to load it as the buggy format");
2984 if (
_sl.
lf->Read((uint8_t*)hdr,
sizeof(hdr)) !=
sizeof(hdr))
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
2991 SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, fmt::format(
"Loader for '{}' is not available.", fmt->
name));
3004 InitializeGame(256, 256,
true,
true);
3076 return DoLoad(reader,
false);
3107 InitializeGame(256, 256,
true,
true);
3115 if (!LoadOldSaveGame(filename))
return SL_REINIT;
3141 default: NOT_REACHED();
3151 if (!fh.has_value()) {
3152 SlError(fop ==
SLO_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
3159 return DoSave(std::make_shared<FileWriter>(std::move(*fh)), threaded);
3164 Debug(desync, 1,
"load: {}", filename);
3165 return DoLoad(std::make_shared<FileReader>(std::move(*fh)), fop ==
SLO_CHECK);
3185 std::string filename;
3193 Debug(sl, 2,
"Autosaving to '{}'", filename);
3228 SetDParam(1, STR_SAVEGAME_DURATION_REALTIME);
3234 case 0:
SetDParam(1, STR_JUST_DATE_LONG);
break;
3235 case 1:
SetDParam(1, STR_JUST_DATE_TINY);
break;
3236 case 2:
SetDParam(1, STR_JUST_DATE_ISO);
break;
3237 default: NOT_REACHED();
3284 this->
name = item.name;
3285 this->
title = item.title;
3290 assert(this->load_description.has_value());
3291 return *this->load_description;
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.
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.
@ SL_VAR
Save/load a variable.
@ REF_ORDER
Load/save a reference to an order.
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.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
@ SL_NULL
Save null-bytes and load to nowhere.
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
void Write(uint8_t *buf, size_t size) override
Write a given number of bytes into the savegame.
Filter without any compression.
static uint8_t SlCalcConvFileLen(VarType conv)
Return the size in bytes of a certain type of normal/atomic variable as it appears in a saved game.
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.
@ SL_REF
Save/load a reference.
void Write(uint8_t *buf, size_t size) override
Write a given number of bytes into the savegame.
@ REF_ROADSTOPS
Load/save a reference to a bus/truck stop.
std::string title
Internal name of the game.
@ SL_STDSTR
Save/load a std::string.
uint8_t fread_buf[MEMORY_CHUNK_SIZE]
Buffer for reading from the file.
@ SLE_FILE_END
Used to mark end-of-header in tables.
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.
@ SL_ARR
Save/load a fixed-size array of SL_VAR elements.
long begin
The begin of the file.
void Write(uint8_t *buf, size_t size) override
Write a given number of bytes into the savegame.
void WriteByte(uint8_t b)
Write a single byte into the dumper.
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...
Owner
Enum for all companies/owners.
@ 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
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.
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)
uint8_t * bufe
End of the buffer we write to.
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.
@ SL_DEQUE
Save/load a deque of SL_VAR elements.
SaveLoadAction
What are we currently doing?
@ SL_SAVEBYTE
Save (but not load) a byte.
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.
void Write(uint8_t *buf, size_t size) override
Write a given number of bytes into 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).
static const SaveLoadFormat * DetermineSaveLoadFormat(uint32_t tag, uint32_t raw_version)
Determines the SaveLoadFormat that is connected to the given tag.
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.
void SlWriteByte(uint8_t b)
Wrapper for writing a byte to the dumper.
void WriteLoop(uint8_t *p, size_t len, lzma_action action)
Helper loop for writing the data.
Filter without any compression.
@ REF_STATION
Load/save a reference to a station.
Filter without any compression.
size_t Read(uint8_t *buf, size_t size) override
Read a given number of bytes from the savegame.
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).
@ 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.
void Write(uint8_t *buf, size_t size) override
Write a given number of bytes into the savegame.
FileReader(FileHandle &&file)
Create the file reader, so it reads from a specific file.
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.
@ 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.
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.
LZOSaveFilter(std::shared_ptr< SaveFilter > chain, uint8_t)
Initialise this filter.
@ 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.
std::string _savegame_format
how to compress savegames
std::shared_ptr< SaveFilter > sf
Filter to write the savegame to.
SaveLoadType
Type of data saved.
@ NL_WANTLENGTH
writing length and data
uint8_t buf[MEMORY_CHUNK_SIZE]
Buffer we're going to read from.
size_t Read(uint8_t *buf, size_t ssize) 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.
static std::pair< const SaveLoadFormat &, uint8_t > GetSavegameFormat(const std::string &full_name)
Return the savegameformat of the game.
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.
@ 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.
size_t Read(uint8_t *buf, size_t size) override
Read a given number of bytes from the savegame.
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 * 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.
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()
#define lengthof(array)
Return the length of an fixed size array.
@ SLV_SAVELOAD_LIST_LENGTH
293 PR#9374 Consistency in list length with SL_STRUCT / SL_STRUCTLIST / SL_DEQUE / SL_REFLIST.
@ 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).
std::optional< FileHandle > file
The file to write to.
@ SL_VECTOR
Save/load a vector of SL_VAR elements.
@ 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.
@ 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.
@ SBI_SAVELOAD_START
started saving
lzma_stream lzma
Stream state that we are reading from.
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
void SlAutolength(AutolengthProc *proc, int arg)
Do something of which I have no idea what it is :P.
virtual void Load() const =0
Load the chunk.
GameSessionStats _game_session_stats
Statistics about the current session.
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.
std::optional< FileHandle > file
The file to read from.
ZlibSaveFilter(std::shared_ptr< SaveFilter > chain, uint8_t compression_level)
Initialise this filter.
static size_t SlCalcVectorLen(const void *vector, VarType conv)
Return the size in bytes of a std::vector.
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.
uint8_t fwrite_buf[MEMORY_CHUNK_SIZE]
Buffer for writing to the file.
~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.
uint8_t _sl_minor_version
the minor savegame version, DO NOT USE!
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 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.
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.
uint8_t SlReadByte()
Wrapper for reading a byte from the buffer.
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.
StringID GetSaveLoadErrorType()
Return the appropriate initial string for an error depending on whether we are saving or loading.
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.
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.
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.
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.
FileWriter(FileHandle &&file)
Create the file writer, so it writes to a specific file.
std::optional< FileHandle > FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
@ 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.
size_t Read(uint8_t *buf, size_t size) override
Read a given number of bytes from the savegame.
size_t Read(uint8_t *buf, size_t size) override
Read a given number of bytes from the savegame.
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.
uint8_t fwrite_buf[MEMORY_CHUNK_SIZE]
Buffer for writing to the file.
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.
bool error
did an error occur or not
Container for cargo from the same location and time.
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.
Yes, simply reading from a file.
@ SL_REFLIST
Save/load a list of SL_REF elements.
uint8_t * bufe
End of the buffer we can read from.
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)
StringID GetSaveLoadErrorMessage()
Return the description of the error.
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.
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
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.
@ SL_STRUCTLIST
Save/load a list of structs.
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.
uint8_t * bufp
Location we're at reading the buffer.
static void ClearSaveLoadState()
Clear/free saveload state.
static SaveOrLoadResult DoSave(std::shared_ptr< SaveFilter > writer, bool threaded)
Actually perform the saving of the savegame.
uint8_t fread_buf[MEMORY_CHUNK_SIZE]
Buffer for reading from the file.
std::vector< std::unique_ptr< uint8_t[]> > blocks
Buffer with blocks of allocated memory.
@ 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.
static const lzma_stream _lzma_init
Have a copy of an initialised LZMA stream.
void WriteLoop(uint8_t *p, size_t len, int mode)
Helper loop for writing the data.
@ 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.
@ SL_STRUCT
Save/load a struct.
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.
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.
constexpr VarType GetVarFileType(VarType type)
Get the FileType of a setting.
uint8_t * buf
Buffer we're going to write to.
Container for dumping the savegame (quickly) to memory.
static SaveOrLoadResult DoLoad(std::shared_ptr< LoadFilter > reader, bool load_check)
Actually perform the loading of a "non-old" savegame.
LZMASaveFilter(std::shared_ptr< SaveFilter > chain, uint8_t compression_level)
Initialise this filter.
static Date date
Current date in days (day counter).
NoCompSaveFilter(std::shared_ptr< SaveFilter > chain, uint8_t)
Initialise this filter.
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.