56# include <emscripten.h>
67#if defined(WITH_LIBLZMA)
71#include "table/strings.h"
122 if (this->bufp == this->bufe) {
123 size_t len = this->reader->Read(this->buf,
lengthof(this->buf));
127 this->bufp = this->buf;
128 this->bufe = this->buf + len;
131 return *this->
bufp++;
140 return this->read - (this->bufe - this->bufp);
147 std::vector<std::unique_ptr<uint8_t[]>>
blocks{};
158 if (this->buf == this->bufe) {
159 this->buf = this->blocks.emplace_back(std::make_unique<uint8_t[]>(
MEMORY_CHUNK_SIZE)).get();
170 void Flush(std::shared_ptr<SaveFilter> writer)
178 writer->Write(this->blocks[i++].get(), to_write);
207 std::shared_ptr<SaveFilter>
sf;
210 std::shared_ptr<LoadFilter>
lf;
262 _gamelog_chunk_handlers,
264 _misc_chunk_handlers,
265 _name_chunk_handlers,
266 _cheat_chunk_handlers,
267 _setting_chunk_handlers,
269 _waypoint_chunk_handlers,
270 _depot_chunk_handlers,
271 _order_chunk_handlers,
272 _industry_chunk_handlers,
273 _economy_chunk_handlers,
274 _subsidy_chunk_handlers,
275 _cargomonitor_chunk_handlers,
276 _goal_chunk_handlers,
277 _story_page_chunk_handlers,
278 _league_chunk_handlers,
279 _engine_chunk_handlers,
280 _town_chunk_handlers,
281 _sign_chunk_handlers,
282 _station_chunk_handlers,
283 _company_chunk_handlers,
285 _game_chunk_handlers,
286 _animated_tile_chunk_handlers,
287 _newgrf_chunk_handlers,
288 _group_chunk_handlers,
289 _cargopacket_chunk_handlers,
290 _autoreplace_chunk_handlers,
291 _labelmaps_chunk_handlers,
292 _linkgraph_chunk_handlers,
293 _airport_chunk_handlers,
294 _object_chunk_handlers,
295 _persistent_storage_chunk_handlers,
296 _water_region_chunk_handlers,
297 _randomizer_chunk_handlers,
300 static std::vector<ChunkHandlerRef> _chunk_handlers;
302 if (_chunk_handlers.empty()) {
303 for (
auto &chunk_handler_table : _chunk_handler_tables) {
304 for (
auto &chunk_handler : chunk_handler_table) {
305 _chunk_handlers.push_back(chunk_handler);
310 return _chunk_handlers;
324 Debug(sl, 3,
"Nulling pointers for {}", ch.GetName());
346 _sl.error_str = string;
347 _sl.extra_msg = extra_msg;
359 throw std::exception();
371 SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
385 if (_exit_game)
return;
397 if (proc ==
nullptr)
return;
412 return _sl.reader->ReadByte();
421 _sl.dumper->WriteByte(b);
424static inline int SlReadUint16()
430static inline uint32_t SlReadUint32()
432 uint32_t x = SlReadUint16() << 16;
433 return x | SlReadUint16();
436static inline uint64_t SlReadUint64()
438 uint32_t x = SlReadUint32();
439 uint32_t y = SlReadUint32();
440 return static_cast<uint64_t
>(x) << 32 | y;
443static inline void SlWriteUint16(uint16_t v)
449static inline void SlWriteUint32(uint32_t v)
451 SlWriteUint16(
GB(v, 16, 16));
452 SlWriteUint16(
GB(v, 0, 16));
455static inline void SlWriteUint64(uint64_t x)
457 SlWriteUint32(
static_cast<uint32_t
>(x >> 32));
458 SlWriteUint32(
static_cast<uint32_t
>(x));
526 if (i >= (1 << 14)) {
527 if (i >= (1 << 21)) {
528 if (i >= (1 << 28)) {
529 assert(i <= UINT32_MAX);
533 SlWriteByte(
static_cast<uint8_t
>(0xE0 | (i >> 24)));
537 SlWriteByte(
static_cast<uint8_t
>(0xC0 | (i >> 16)));
541 SlWriteByte(
static_cast<uint8_t
>(0x80 | (i >> 8)));
554 return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21)) + (i >= (1 << 28));
557static inline uint SlReadSparseIndex()
562static inline void SlWriteSparseIndex(uint index)
567static inline uint SlReadArrayLength()
572static inline void SlWriteArrayLength(
size_t length)
577static inline uint SlGetArrayLength(
size_t length)
617 assert(!this->
IsEnd());
627 assert(!this->
IsEnd());
662 default: NOT_REACHED();
690 return SlReadArrayLength();
718 return SlReadArrayLength();
735void SlSetArrayIndex(uint index)
738 _sl.array_index = index;
741static size_t _next_offs;
751 if (_next_offs != 0 &&
_sl.reader->GetSize() != _next_offs) {
752 SlErrorCorruptFmt(
"Invalid chunk size iterating array - expected to be at position {}, actually at {}", _next_offs,
_sl.reader->GetSize());
756 uint length = SlReadArrayLength();
758 assert(!
_sl.expect_table_header);
763 _sl.obj_len = --length;
764 _next_offs =
_sl.reader->GetSize() + length;
766 if (
_sl.expect_table_header) {
767 _sl.expect_table_header =
false;
772 switch (
_sl.chunk_type) {
778 Debug(sl, 0,
"SlIterateArray error");
782 if (length != 0)
return index;
805 switch (
_sl.need_length) {
809 _sl.expect_table_header =
false;
810 SlWriteArrayLength(length + 1);
814 switch (
_sl.chunk_type) {
819 assert(length < (1 << 28));
820 SlWriteUint32((uint32_t)((length & 0xFFFFFF) | ((length >> 24) << 28)));
824 assert(
_sl.last_array_index <=
_sl.array_index);
825 while (++
_sl.last_array_index <=
_sl.array_index) {
826 SlWriteArrayLength(1);
828 SlWriteArrayLength(length + 1);
832 SlWriteArrayLength(length + 1 + SlGetArrayLength(
_sl.array_index));
833 SlWriteSparseIndex(
_sl.array_index);
835 default: NOT_REACHED();
840 _sl.obj_len +=
static_cast<int>(length);
843 default: NOT_REACHED();
855 uint8_t *p =
static_cast<uint8_t *
>(ptr);
857 switch (
_sl.action) {
860 for (; length != 0; length--) *p++ =
SlReadByte();
865 default: NOT_REACHED();
898 default: NOT_REACHED();
923 default: NOT_REACHED();
937 switch (
_sl.action) {
941 for (
auto it = label->rbegin(); it != label->rend(); it++)
SlWriteByte(*it);
946 for (
auto it = label->begin(); it != label->end(); it++)
SlWriteByte(*it);
955 assert(x >= -128 && x <= 127);
960 assert(x >= 0 && x <= 255);
965 assert(x >= -32768 && x <= 32767);
971 assert(x >= 0 && x <= 65535);
977 SlWriteUint32(
static_cast<uint32_t
>(x));
985 default: NOT_REACHED();
993 for (
auto it = label->rbegin(); it != label->rend(); it++) *it =
SlReadByte();
998 for (
auto it = label->begin(); it != label->end(); it++) *it =
SlReadByte();
1004 switch (conv.
file) {
1014 default: NOT_REACHED();
1023 default: NOT_REACHED();
1036 const std::string *str =
reinterpret_cast<const std::string *
>(ptr);
1038 size_t len = str->length();
1039 return len + SlGetArrayLength(len);
1053 if (str.empty())
return;
1065 bool is_encoded =
false;
1066 bool in_string =
false;
1067 bool need_type =
true;
1072 if (
auto r = consumer.
TryReadUtf8(); r.has_value()) {
1077 if (c ==
SCC_ENCODED || (fix_code && (c == 0xE028 || c == 0xE02A))) {
1085 if (!is_encoded)
return;
1088 in_string = !in_string;
1089 if (in_string && need_type) {
1097 if (!in_string && c ==
':') {
1098 builder.
PutUtf8(SCC_RECORD_SEPARATOR);
1111 str = std::move(result);
1120 if (str.empty())
return;
1148 str = std::move(result);
1170 std::string *str =
reinterpret_cast<std::string *
>(ptr);
1172 switch (
_sl.action) {
1174 size_t len = str->length();
1175 SlWriteArrayLength(len);
1176 SlCopyBytes(
const_cast<void *
>(
static_cast<const void *
>(str->data())), len);
1182 size_t len = SlReadArrayLength();
1201 default: NOT_REACHED();
1232 for (uint i = 0; i < length; i++) {
1233 static_cast<int64_t *
>(object)[i] =
std::byteswap(SlReadUint32());
1244 uint8_t *a =
static_cast<uint8_t *
>(object);
1247 for (; length != 0; length --) {
1295 switch (
_sl.action) {
1297 SlWriteArrayLength(length);
1304 size_t sv_length = SlReadArrayLength();
1308 }
else if (sv_length != length) {
1343 if (obj ==
nullptr)
return 0;
1357 default: NOT_REACHED();
1373 static_assert(
sizeof(size_t) <=
sizeof(
void *));
1432 default: NOT_REACHED();
1443 switch (
_sl.action) {
1452 *
static_cast<void **
>(ptr) =
IntToReference(*
static_cast<size_t *
>(ptr), conv.
ref);
1455 *
static_cast<void **
>(ptr) =
nullptr;
1457 default: NOT_REACHED();
1464template <
template <
typename,
typename>
typename Tstorage,
typename Tvar,
typename Tallocator = std::allocator<Tvar>>
1466 typedef Tstorage<Tvar, Tallocator> SlStorageT;
1479 const SlStorageT *list =
static_cast<const SlStorageT *
>(storage);
1481 int type_size = SlGetArrayLength(list->size());
1483 return list->size() * item_size + type_size;
1507 SlStorageT *list =
static_cast<SlStorageT *
>(storage);
1509 switch (
_sl.action) {
1511 SlWriteArrayLength(list->size());
1513 for (
auto &item : *list) {
1514 SlSaveLoadMember(cmd, &item, conv);
1525 default: NOT_REACHED();
1529 if constexpr (std::is_same_v<SlStorageT, std::vector<Tvar, Tallocator>>) {
1530 list->reserve(length);
1534 for (
size_t i = 0; i < length; i++) {
1535 Tvar &data = list->emplace_back();
1536 SlSaveLoadMember(cmd, &data, conv);
1542 for (
auto &item : *list) {
1543 SlSaveLoadMember(cmd, &item, conv);
1551 default: NOT_REACHED();
1636 default: NOT_REACHED();
1667 default: NOT_REACHED();
1690 for (
auto &sld : slt) {
1699 for (
auto &sld : slt) {
1720 for (
auto &sld : slt) {
1721 length += SlCalcObjMemberLength(
object, sld);
1726size_t SlCalcObjMemberLength(
const void *
object,
const SaveLoad &sld)
1746 size_t old_obj_len =
_sl.obj_len;
1754 sld.
handler->Save(
const_cast<void *
>(
object));
1755 size_t length =
_sl.obj_len;
1757 _sl.obj_len = old_obj_len;
1758 _sl.need_length = old_need_length;
1761 length += SlGetArrayLength(1);
1767 default: NOT_REACHED();
1772static bool SlObjectMember(
void *
object,
const SaveLoad &sld)
1794 default: NOT_REACHED();
1805 switch (
_sl.action) {
1811 default: NOT_REACHED();
1819 switch (
_sl.action) {
1825 default: NOT_REACHED();
1832 switch (
_sl.action) {
1846 sld.
handler->LoadCheck(
object);
1859 sld.
handler->FixPointers(
object);
1863 default: NOT_REACHED();
1867 default: NOT_REACHED();
1884 SlWriteArrayLength(length);
1894 size_t length = SlReadArrayLength();
1913 for (
auto &sld : slt) {
1914 SlObjectMember(
object, sld);
1928 void Load(
void *
object)
const override
1931 for (; length > 0; length--) {
1963 switch (
_sl.action) {
1966 std::vector<SaveLoad> saveloads;
1969 std::map<std::string, const SaveLoad *> key_lookup;
1970 for (
auto &sld : slt) {
1974 assert(key_lookup.find(sld.
name) == key_lookup.end());
1975 key_lookup[sld.
name] = &sld;
1981 if (type.
IsEnd())
break;
1986 auto sld_it = key_lookup.find(key);
1987 if (sld_it == key_lookup.end()) {
1991 std::shared_ptr<SaveLoadHandler> handler =
nullptr;
1993 switch (type.
Type()) {
2000 handler = std::make_shared<SlSkipHandler>();
2020 Debug(sl, 1,
"Field type for '{}' was expected to be 0x{:02x} but 0x{:02x} was found", key, correct_type.
storage, type.
storage);
2023 saveloads.emplace_back(*sld_it->second);
2026 for (
auto &sld : saveloads) {
2042 for (
auto &sld : slt) {
2045 assert(!sld.
name.empty());
2048 assert(!type.
IsEnd());
2059 for (
auto &sld : slt) {
2068 _sl.need_length = old_need_length;
2075 default: NOT_REACHED();
2078 return std::vector<SaveLoad>();
2100 std::vector<SaveLoad> saveloads;
2103 std::map<std::string_view, std::vector<const SaveLoad *>> key_lookup;
2104 for (
auto &sld : slt) {
2106 assert(!sld.
name.empty());
2108 key_lookup[sld.
name].push_back(&sld);
2111 for (
auto &slc : slct) {
2112 if (slc.name.empty()) {
2118 auto sld_it = key_lookup.find(slc.name);
2122 if (sld_it == key_lookup.end()) {
2125 Debug(sl, 0,
"internal error: saveload compatibility field '{}' not found", slc.name);
2128 for (
auto &sld : sld_it->second) {
2129 saveloads.push_back(*sld);
2134 for (
auto &sld : saveloads) {
2171 size_t start_pos =
_sl.dumper->GetSize();
2172 size_t expected_offs = start_pos +
_sl.obj_len;
2177 if (expected_offs !=
_sl.dumper->GetSize()) {
2178 SlErrorCorruptFmt(
"Invalid chunk size when writing autolength block, expected {}, got {}",
_sl.obj_len,
_sl.dumper->GetSize() - start_pos);
2184 switch (
_sl.chunk_type) {
2215 if (
_sl.expect_table_header) {
2219 switch (
_sl.chunk_type) {
2222 _sl.array_index = 0;
2233 size_t len = (
SlReadByte() << 16) | ((m >> 4) << 24);
2234 len += SlReadUint16();
2236 size_t start_pos =
_sl.reader->GetSize();
2237 size_t endoffs = start_pos + len;
2240 if (
_sl.reader->GetSize() != endoffs) {
2241 SlErrorCorruptFmt(
"Invalid chunk size in RIFF in {} - expected {}, got {}", ch.
GetName(), len,
_sl.reader->GetSize() - start_pos);
2268 if (
_sl.expect_table_header) {
2272 switch (
_sl.chunk_type) {
2275 _sl.array_index = 0;
2284 size_t len = (
SlReadByte() << 16) | ((m >> 4) << 24);
2285 len += SlReadUint16();
2287 size_t start_pos =
_sl.reader->GetSize();
2288 size_t endoffs = start_pos + len;
2291 if (
_sl.reader->GetSize() != endoffs) {
2292 SlErrorCorruptFmt(
"Invalid chunk size in RIFF in {} - expected {}, got {}", ch.
GetName(), len,
_sl.reader->GetSize() - start_pos);
2321 switch (
_sl.chunk_type) {
2327 _sl.last_array_index = 0;
2330 SlWriteArrayLength(0);
2336 SlWriteArrayLength(0);
2338 default: NOT_REACHED();
2371 Debug(sl, 2,
"Loading chunk {}",
id.AsString());
2383 Debug(sl, 2,
"Loading chunk {}",
id.AsString());
2397 Debug(sl, 3,
"Fixing pointers for {}", ch.GetName());
2421 if (this->file.has_value()) {
2426 size_t Read(uint8_t *buf,
size_t size)
override
2429 if (!this->file.has_value())
return 0;
2431 return fread(buf, 1, size, *this->file);
2436 clearerr(*this->file);
2437 if (fseek(*this->file, this->begin, SEEK_SET)) {
2438 Debug(sl, 1,
"Could not reset the file reading");
2461 void Write(
const uint8_t *buf,
size_t size)
override
2464 if (!this->file.has_value())
return;
2466 if (fwrite(buf, 1, size, *this->file) != size)
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
2471 if (this->file.has_value()) {
2495 if (lzo_init() != LZO_E_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize decompressor");
2498 size_t Read(uint8_t *buf,
size_t ssize)
override
2506 lzo_uint len = ssize;
2509 if (this->
chain->Read((uint8_t*)tmp,
sizeof(tmp)) !=
sizeof(tmp))
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE,
"File read failed");
2512 ((uint32_t*)out)[0] = size = tmp[1];
2515 tmp[0] = TO_BE32(tmp[0]);
2516 size = TO_BE32(size);
2522 if (this->
chain->Read(out +
sizeof(uint32_t), size) != size)
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
2525 if (tmp[0] != lzo_adler32(0, out, size +
sizeof(uint32_t)))
SlErrorCorrupt(
"Bad checksum");
2528 int ret = lzo1x_decompress_safe(out +
sizeof(uint32_t) * 1, size, buf, &len,
nullptr);
2529 if (ret != LZO_E_OK)
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
2542 if (lzo_init() != LZO_E_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize compressor");
2545 void Write(
const uint8_t *buf,
size_t size)
override
2547 const lzo_bytep in = buf;
2550 uint8_t wrkmem[LZO1X_1_MEM_COMPRESS];
2556 lzo1x_1_compress(in, len, out +
sizeof(uint32_t) * 2, &outlen, wrkmem);
2557 ((uint32_t*)out)[1] = TO_BE32(
static_cast<uint32_t
>(outlen));
2558 ((uint32_t*)out)[0] = TO_BE32(lzo_adler32(0, out +
sizeof(uint32_t), outlen +
sizeof(uint32_t)));
2559 this->
chain->Write(out, outlen +
sizeof(uint32_t) * 2);
2584 size_t Read(uint8_t *buf,
size_t size)
override
2586 return this->
chain->Read(buf, size);
2600 void Write(
const uint8_t *buf,
size_t size)
override
2602 this->
chain->Write(buf, size);
2610#if defined(WITH_ZLIB)
2623 if (inflateInit(&this->z) != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize decompressor");
2629 inflateEnd(&this->z);
2632 size_t Read(uint8_t *buf,
size_t size)
override
2634 this->z.next_out = buf;
2635 this->z.avail_out =
static_cast<uint
>(size);
2639 if (this->z.avail_in == 0) {
2640 this->z.next_in = this->fread_buf;
2641 this->z.avail_in =
static_cast<uint
>(this->
chain->Read(this->fread_buf,
sizeof(this->fread_buf)));
2645 int r = inflate(&this->z, 0);
2646 if (r == Z_STREAM_END)
break;
2648 if (r != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"inflate() failed");
2649 }
while (this->z.avail_out != 0);
2651 return size - this->z.avail_out;
2667 if (deflateInit(&this->z, compression_level) != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize compressor");
2673 deflateEnd(&this->z);
2685 this->z.next_in =
const_cast<uint8_t *
>(p);
2686 this->z.avail_in =
static_cast<uInt
>(len);
2688 this->z.next_out = this->fwrite_buf;
2689 this->z.avail_out =
sizeof(this->fwrite_buf);
2698 int r = deflate(&this->z, mode);
2701 if ((n =
sizeof(this->fwrite_buf) - this->z.avail_out) != 0) {
2702 this->
chain->Write(this->fwrite_buf, n);
2704 if (r == Z_STREAM_END)
break;
2706 if (r != Z_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"zlib returned error code");
2707 }
while (this->z.avail_in || !this->z.avail_out);
2710 void Write(
const uint8_t *buf,
size_t size)
override
2718 this->
chain->Finish();
2728#if defined(WITH_LIBLZMA)
2750 if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize decompressor");
2756 lzma_end(&this->lzma);
2759 size_t Read(uint8_t *buf,
size_t size)
override
2761 this->lzma.next_out = buf;
2762 this->lzma.avail_out = size;
2766 if (this->lzma.avail_in == 0) {
2767 this->lzma.next_in = this->fread_buf;
2768 this->lzma.avail_in = this->
chain->Read(this->fread_buf,
sizeof(this->fread_buf));
2772 lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
2773 if (r == LZMA_STREAM_END)
break;
2774 if (r != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"liblzma returned error code");
2775 }
while (this->lzma.avail_out != 0);
2777 return size - this->lzma.avail_out;
2793 if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"cannot initialize compressor");
2799 lzma_end(&this->lzma);
2808 void WriteLoop(
const uint8_t *p,
size_t len, lzma_action action)
2811 this->lzma.next_in = p;
2812 this->lzma.avail_in = len;
2814 this->lzma.next_out = this->fwrite_buf;
2815 this->lzma.avail_out =
sizeof(this->fwrite_buf);
2817 lzma_ret r = lzma_code(&this->lzma, action);
2820 if ((n =
sizeof(this->fwrite_buf) - this->lzma.avail_out) != 0) {
2821 this->
chain->Write(this->fwrite_buf, n);
2823 if (r == LZMA_STREAM_END)
break;
2824 if (r != LZMA_OK)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"liblzma returned error code");
2825 }
while (this->lzma.avail_in || !this->lzma.avail_out);
2828 void Write(
const uint8_t *buf,
size_t size)
override
2835 this->
WriteLoop(
nullptr, 0, LZMA_FINISH);
2836 this->
chain->Finish();
2851 std::shared_ptr<LoadFilter> (*
init_load)(std::shared_ptr<LoadFilter> chain);
2852 std::shared_ptr<SaveFilter> (*
init_write)(std::shared_ptr<SaveFilter> chain, uint8_t compression);
2869#if defined(WITH_LZO)
2877#if defined(WITH_ZLIB)
2885#if defined(WITH_LIBLZMA)
2907 if (it == std::rend(
_saveload_formats))
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR,
"no writeable savegame formats");
2911 if (!full_name.empty()) {
2913 size_t separator = full_name.find(
':');
2914 bool has_comp_level = separator != std::string::npos;
2915 std::string_view name = has_comp_level ? full_name.substr(0, separator) : full_name;
2918 if (slf.init_write !=
nullptr && name == slf.name) {
2919 if (has_comp_level) {
2920 auto complevel = full_name.substr(separator + 1);
2924 if (!level.has_value() || *level !=
Clamp(*level, slf.min_compression, slf.max_compression)) {
2927 GetEncodedString(STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL, complevel),
2930 return {slf, *level};
2933 return {slf, slf.default_compression};
2946void InitializeGame(uint size_x, uint size_y,
bool reset_date,
bool reset_settings);
2948extern bool LoadOldSaveGame(std::string_view file);
2974 ResetTempEngineData();
2975 ClearRailTypeLabelList();
2976 ClearRoadTypeLabelList();
2977 ResetOldWaypoints();
2986 _sl.dumper =
nullptr;
2988 _sl.reader =
nullptr;
2998 _sl.saveinprogress =
true;
3007 _sl.saveinprogress =
false;
3009#ifdef __EMSCRIPTEN__
3010 EM_ASM(
if (window[
"openttd_syncfs"]) openttd_syncfs());
3020 _sl.error_str = str;
3060 _sl.sf->Write(fmt.tag.data(), fmt.tag.size());
3063 _sl.sf->Write(
reinterpret_cast<uint8_t *
>(&version),
sizeof(version));
3065 _sl.sf = fmt.init_write(
_sl.sf, compression);
3066 _sl.dumper->Flush(
_sl.sf);
3080 if (
_sl.error_str != STR_NETWORK_ERROR_LOSTCONNECTION) {
3114 assert(!
_sl.saveinprogress);
3116 _sl.dumper = std::make_unique<MemoryDumper>();
3117 _sl.sf = std::move(writer);
3121 SaveViewportBeforeSaveGame();
3127 if (threaded)
Debug(sl, 1,
"Cannot create savegame thread, reverting to single-threaded mode...");
3148 return DoSave(std::move(writer), threaded);
3182 Debug(sl, 0,
"Unknown savegame type, trying to load it as the buggy format");
3206 _sl.lf = std::move(reader);
3216 if (
_sl.lf->Read(tag.data(), tag.size()) != tag.size())
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
3219 if (
_sl.lf->Read(
reinterpret_cast<uint8_t*
>(&version),
sizeof(version)) !=
sizeof(version))
SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
3225 if (fmt->init_load ==
nullptr) {
3226 SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, fmt::format(
"Loader for '{}' is not available.", fmt->name));
3229 _sl.lf = fmt->init_load(
_sl.lf);
3230 _sl.reader = std::make_unique<ReadBuffer>(
_sl.lf);
3239 InitializeGame(256, 256,
true,
true);
3311 return DoLoad(std::move(reader),
false);
3343 InitializeGame(256, 256,
true,
true);
3377 default: NOT_REACHED();
3387 if (!fh.has_value()) {
3395 return DoSave(std::make_shared<FileWriter>(std::move(*fh)), threaded);
3400 Debug(desync, 1,
"load: {}", filename);
3419 std::string filename;
3427 Debug(sl, 2,
"Autosaving to '{}'", filename);
3457 std::array<StringParameter, 4> params{};
3458 auto it = params.begin();
3465 *it++ = STR_SAVEGAME_DURATION_REALTIME;
3466 *it++ = play_time / 60 / 60;
3467 *it++ = (play_time / 60) % 60;
3471 case 0: *it++ = STR_JUST_DATE_LONG;
break;
3472 case 1: *it++ = STR_JUST_DATE_TINY;
break;
3473 case 2: *it++ = STR_JUST_DATE_ISO;
break;
3474 default: NOT_REACHED();
3494 this->
ftype = FIOS_TYPE_INVALID;
3509 this->
name = item.name;
3510 this->
title = item.title;
Base class for autoreplaces/autorenews.
constexpr T AssignBit(T &x, const uint8_t y, bool value)
Assigns a bit in a variable.
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr enable_if_t< is_integral_v< T >, T > byteswap(T x) noexcept
Custom implementation of std::byteswap; remove once we build with C++23.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
void PutUtf8(char32_t c)
Append UTF-8 char.
void Put(std::string_view str)
Append string.
void PutIntegerBase(T value, int base)
Append integer 'value' in given number 'base'.
Container for an encoded string, created by GetEncodedString.
Class for calculation jobs to be run on link graphs.
A connected component of a link graph.
Handler for saving/loading an object to/from disk.
std::optional< std::vector< SaveLoad > > load_description
Description derived from savegame being loaded.
SaveLoadTable GetLoadDescription() const
Get the description for how to load the chunk.
Handler that is assigned when there is a struct read in the savegame which is not known to the code.
SaveLoadCompatTable GetCompatDescription() const override
Get the pre-header description of the fields in the savegame.
SaveLoadTable GetDescription() const override
Get the description of the fields in the savegame.
void LoadCheck(void *object) const override
Similar to load, but used only to validate savegames.
void Load(void *object) const override
Load the object from disk.
void Save(void *) const override
Save the object to disk.
Template class to help with list-like types.
static size_t SlCalcLen(const void *storage, VarType conv, SaveLoadType cmd=SaveLoadType::Variable)
Internal templated helper to return the size in bytes of a list-like type.
static void SlSaveLoad(void *storage, VarType conv, SaveLoadType cmd=SaveLoadType::Variable)
Internal templated helper to save/load a list-like type.
Compose data into a growing std::string.
Parse data from a string / buffer.
std::optional< T > TryReadIntegerBase(int base, bool clamp=false)
Try to read and parse an integer in number 'base', and then advance the reader.
@ READ_ONE_SEPARATOR
Read one separator, and include it in the result.
bool AnyBytesLeft() const noexcept
Check whether any bytes left to read.
std::optional< char32_t > TryReadUtf8()
Try to read a UTF-8 character, and then advance reader.
T ReadIntegerBase(int base, T def=0, bool clamp=false)
Read and parse an integer in number 'base', and advance the reader.
bool ReadUtf8If(char32_t c)
Check whether the next UTF-8 char matches 'c', and skip it.
std::string_view ReadUntilUtf8(char32_t c, SeparatorUsage sep)
Read data until the first occurrence of UTF-8 char 'c', and advance reader.
static constexpr TimerGameTick::Ticks TICKS_PER_SECOND
Estimation of how many ticks fit in a single second.
static Date date
Current date in days (day counter).
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
static DateFract date_fract
Fractional part of the day.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
@ SCC_ENCODED
Encoded string marker and sub-string parameter.
@ SCC_ENCODED_NUMERIC
Encoded numeric parameter.
@ SCC_ENCODED_STRING
Encoded string parameter.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Function to handling different endian machines.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Functions related to errors.
@ Critical
Critical errors, the MessageBox is shown in all cases.
@ Error
Errors (eg. saving/loading failed).
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
void SanitizeFilename(std::string &filename)
Sanitizes a filename, i.e.
std::optional< FileHandle > FioFOpenFile(std::string_view filename, std::string_view mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
Functions for standard in/out file operations.
SaveLoadOperation
Operation performed on the file.
@ Check
Load file for checking and/or preview.
@ Invalid
Unknown file operation.
@ Save
File is being saved.
@ Load
File is being loaded.
DetailedFileType
Kinds of files in each AbstractFileType.
@ OldGameFile
Old save game or scenario file.
@ GameFile
Save game or scenario file.
Subdirectory
The different kinds of subdirectories OpenTTD uses.
@ Base
Base directory for all subdirectories.
@ Autosave
Subdirectory of save for autosaves.
@ Scenario
Base directory for all scenarios.
@ Save
Base directory for all savegames.
@ Invalid
Invalid or unknown file type.
Declarations for savegames operations.
LoadCheckData _load_check_data
Data loaded from save during SL_LOAD_CHECK.
fluid_settings_t * settings
FluidSynth settings handle.
uint32_t _ttdp_version
version of TTDP savegame (if applicable)
SaveLoadVersion _sl_version
the major savegame version identifier
uint8_t _sl_minor_version
the minor savegame version, DO NOT USE!
Gamelog _gamelog
Gamelog instance.
SavegameType _savegame_type
type of savegame we are loading
const SaveLoadVersion SAVEGAME_VERSION
current savegame version
Functions to be called to log fundamental changes to the game.
void SetMouseCursorBusy(bool busy)
Set or unset the ZZZ cursor.
GameSessionStats _game_session_stats
Statistics about the current session.
Declaration of link graph classes used for cargo distribution.
Declaration of link graph job classes used for cargo distribution.
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
bool _networking
are we in networking mode?
bool _network_server
network-server is active
Basic functions/variables used all over the place.
GRFConfigList _grfconfig
First item in list of current GRF set up.
GRFListCompatibility IsGoodGRFConfigList(GRFConfigList &grfconfig)
Check if all GRFs in the GRF config from a savegame can be loaded.
void ClearGRFConfigList(GRFConfigList &config)
Clear a GRF Config list, freeing all nodes.
NewGRF handling of rail types.
NewGRF handling of road types.
uint8_t ReadByte(LoadgameState &ls)
Reads a byte from the buffer and decompress if needed.
Base class for roadstops.
A number of safeguards to prevent using unsafe methods.
static void SlRefVector(void *vector, VarType conv)
Save/Load a vector.
static const uint LZO_BUFFER_SIZE
Buffer size for the LZO compressor.
void SlError(StringID string, const std::string &extra_msg)
Error handler.
void ProcessAsyncSaveFinish()
Handle async save finishes.
void FixSCCEncodedNegative(std::string &str)
Scan the string for SCC_ENCODED_NUMERIC with negative values, and reencode them as uint64_t.
static const lzma_stream _lzma_init
Have a copy of an initialised LZMA stream.
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...
static SaveLoadResult DoSave(std::shared_ptr< SaveFilter > writer, bool threaded)
Actually perform the saving of the savegame.
static const SaveLoadFormat _saveload_formats[]
The different saveload formats known/understood by OpenTTD.
std::string _savegame_format
how to compress savegames
static void SaveFileDone()
Update the gui accordingly when saving is done and release locks on saveload.
SaveLoadVersion _sl_version
the major savegame version identifier
static SavegameFileType GetSavegameFileType(const SaveLoad &sld)
Return the type as saved/loaded inside the savegame.
SaveLoadResult SaveOrLoad(std::string_view filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded)
Main Save or Load function where the high-level saveload functions are handled.
static uint32_t ReferenceToInt(const void *obj, SLRefType rt)
Pointers cannot be saved to a savegame, so this functions gets the index of the item,...
static const std::vector< ChunkHandlerRef > & ChunkHandlers()
static size_t SlCalcRefVectorLen(const void *vector, VarType conv)
Return the size in bytes of a vector.
static void ResetSaveloadData()
Clear temporary data that is passed between various saveload phases.
static void SlWriteSimpleGamma(size_t i)
Write the header descriptor of an object or an array.
static size_t SlCalcTableHeader(const SaveLoadTable &slt)
Calculate the size of the table header.
static void ClearSaveLoadState()
Clear/free saveload state.
bool _do_autosave
are we doing an autosave at the moment?
static std::atomic< AsyncSaveFinishProc > _async_save_finish
Callback to call when the savegame loading is finished.
static std::thread _save_thread
The thread we're using to compress and write a savegame.
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
static void ResetSettings()
Reset all settings to their default, so any settings missing in the savegame are their default,...
void SlWriteByte(uint8_t b)
Wrapper for writing a byte to the dumper.
size_t SlGetStructListLength(size_t limit)
Get the length of this list; if it exceeds the limit, error out.
Label< struct SaveLoadFormatLabelTag > SaveLoadFormatTag
Unique 4-letter tag for the different saveload formats.
static SaveLoadResult DoLoad(std::shared_ptr< LoadFilter > reader, bool load_check)
Actually perform the loading of a "non-old" savegame.
SaveLoadResult SaveWithFilter(std::shared_ptr< SaveFilter > writer, bool threaded)
Save the game using a (writer) filter.
static size_t SlCalcArrayLen(size_t length, VarType conv)
Return the size in bytes of a certain type of atomic array.
void(* AsyncSaveFinishProc)()
Callback for when the savegame loading is finished.
static const SaveLoadFormatTag SAVEGAME_TAG_LZMA
Tag for a game with lzma compression.
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
static const SaveLoadFormatTag SAVEGAME_TAG_LZO
Tag for a game compressed with LZO.
static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
Called by save thread to tell we finished saving.
void SetSaveLoadError(StringID str)
Set the error message from outside of the actual loading/saving of the game (AfterLoadGame and friend...
void SlCopy(void *object, size_t length, VarType conv)
Copy a list of SaveLoadType::Variables to/from a savegame.
size_t SlGetFieldLength()
Get the length of the current object.
void DoAutoOrNetsave(FiosNumberedSaveName &counter)
Create an autosave or netsave.
static size_t SlCalcRefLen()
Return the size in bytes of a reference (pointer).
@ WantLength
writing length and data
@ None
not working in NeedLength mode
@ CalcLength
need to calculate the length
static void SaveFileStart()
Update the gui accordingly when starting saving and set locks on saveload.
static void SlNullPointers()
Null all pointers (convert index -> nullptr).
static void SlStdString(void *ptr, VarType conv)
Save/Load a std::string.
static size_t SlCalcRefListLen(const void *list, VarType conv)
Return the size in bytes of a list.
static bool SlIsObjectValidInSavegame(const SaveLoad &sld)
Are we going to save this object or not?
EncodedString GetSaveLoadErrorType()
Return the appropriate initial string for an error depending on whether we are saving or loading.
void SlSaveLoadRef(void *ptr, VarType conv)
Handle conversion for references.
static void SlFixPointers()
Fix all pointers (convert index -> pointer).
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
void SlSkipArray()
Skip an array or sparse array.
static void SlLoadChunk(const ChunkHandler &ch)
Load a chunk of data (eg vehicles, stations, etc.).
static void SlLoadCheckChunks()
Load all chunks for savegame checking.
static size_t SlCalcStdStringLen(const void *ptr)
Calculate the gross length of the string that it will occupy in the savegame.
static uint SlReadSimpleGamma()
Read in the header descriptor of an object or an array.
SaveLoadAction
What are we currently doing?
@ Null
null all pointers (on loading error)
@ LoadCheck
partial loading into _load_check_data
static void SlCopyBytes(void *ptr, size_t length)
Save/Load bytes.
static ChunkId SlReadChunkId()
Read the ChunkId.
static void SlCopyInternal(void *object, size_t length, VarType conv)
Internal function to save/Load a list of SaveLoadType::Variables.
static void SlArray(void *array, size_t length, VarType conv)
Save/Load the length of the array followed by the array of SaveLoadType::Variable elements.
static void SlSaveLoadConv(void *ptr, VarType conv)
Handle all conversion and typechecking of variables here.
static const SaveLoadFormatTag SAVEGAME_TAG_NONE
Tag for a game without compression.
void WriteValue(void *ptr, VarMemType conv, int64_t val)
Write the value of a setting.
FileToSaveLoad _file_to_saveload
File to save or load in the openttd loop.
static void SlLoadCheckChunk(const ChunkHandler &ch)
Load a chunk of data for checking savegames.
void SlSetLength(size_t length)
Sets the length of either a RIFF object or the number of items in an array.
uint8_t SlReadByte()
Wrapper for reading a byte from the buffer.
void ClearOldOrders()
Clear all old orders.
static SaveLoadParams _sl
Parameters used for/at saveload.
void DoExitSave()
Do a save when exiting the game (_settings_client.gui.autosave_on_exit).
static void SlLoadChunks()
Load all chunks.
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.
static void SlSaveChunk(const ChunkHandler &ch)
Save a chunk of data (eg.
size_t SlCalcObjLength(const void *object, const SaveLoadTable &slt)
Calculate the size of an object.
void SlObject(void *object, const SaveLoadTable &slt)
Main SaveLoad function.
EncodedString GetSaveLoadErrorMessage()
Return the description of the error.
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
bool AfterLoadGame()
Perform a (large) amount of savegame conversion magic in order to load older savegames and to fill th...
SaveLoadResult LoadWithFilter(std::shared_ptr< LoadFilter > reader)
Load the game using a (reader) filter.
static void SlVector(void *vector, VarType conv)
Save/load a std::vector.
static void SaveFileError()
Show a gui message when saving has failed.
static SaveLoadResult SaveFileToDisk(bool threaded)
We have written the whole game into memory, _memory_savegame, now find and appropriate compressor and...
void SlGlobList(const SaveLoadTable &slt)
Save or Load (a list of) global variables.
static std::pair< const SaveLoadFormat &, uint8_t > GetSavegameFormat(std::string_view full_name)
Return the savegameformat of the game.
static uint SlCalcConvMemLen(VarMemType conv)
Return the size in bytes of a certain type of normal/atomic variable as it appears in memory.
void FixSCCEncoded(std::string &str, bool fix_code)
Scan the string for old values of SCC_ENCODED and fix it to it's new, value.
static void SlSaveChunks()
Save all chunks.
std::string GenerateDefaultSaveName()
Get the default name for a savegame or screenshot.
static const size_t MEMORY_CHUNK_SIZE
Save in chunks of 128 KiB.
int64_t ReadValue(const void *ptr, VarMemType conv)
Return a signed-long version of the value of a setting.
void SlAutolength(AutolengthProc *proc, int arg)
Do something of which I have no idea what it is :P.
void SlReadString(std::string &str, size_t length)
Read the given amount of bytes from the buffer into the string.
static const SaveLoadFormatTag SAVEGAME_TAG_ZLIB
Tag for a game with zlib compression.
static const ChunkHandler * SlFindChunkHandler(ChunkId id)
Find the ChunkHandler that will be used for processing the found chunk in the savegame or in memory.
void SlSetStructListLength(size_t length)
Set the length of this list.
static uint SlGetGammaLength(size_t i)
Return how many bytes used to encode a gamma value.
static const SaveLoadFormat * DetermineSaveLoadFormat(SaveLoadFormatTag tag, uint32_t raw_version)
Determines the SaveLoadFormat that is connected to the given tag.
static size_t SlCalcVectorLen(const void *vector, VarType conv)
Return the size in bytes of a std::vector.
static void SlRefList(void *list, VarType conv)
Save/Load a list.
VarMemType
The types/structures of data we have in memory.
@ U64
A 64 bit unsigned int.
@ Name
old custom name to be converted to a string pointer
@ LabelForward
A 4 character Label, stored as-is.
@ U8
A 8 bit unsigned int.
@ LabelReverse
A 4 character Label, stored in reverse.
@ StrQ
string pointer enclosed in quotes
@ Null
useful to write zeros in savegame.
@ I16
A 16 bit signed int.
@ U32
A 32 bit unsigned int.
@ I32
A 32 bit signed int.
@ I64
A 64 bit signed int.
@ U16
A 16 bit unsigned int.
VarFileType
The types/structures of data that can be stored in the file.
@ U64
A 64 bit unsigned int.
@ U8
A 8 bit unsigned int.
@ Struct
An arbitrary structure.
@ I16
A 16 bit signed int.
@ U32
A 32 bit unsigned int.
@ StringID
StringID offset into strings-array.
@ I32
A 32 bit signed int.
@ I64
A 64 bit signed int.
@ U16
A 16 bit unsigned int.
SavegameType
Types of save games.
void SlSkipBytes(size_t length)
Read in bytes from the file/data structure but don't do anything with them, discarding them in effect...
SLRefType
Type of reference (SLE_REF, SLE_CONDREF).
@ LinkGraph
Load/save a reference to a link graph.
@ CargoPacket
Load/save a reference to a cargo packet.
@ OrderList
Load/save a reference to an orderlist.
@ Station
Load/save a reference to a station.
@ OldVehicle
Load/save an old-style reference to a vehicle (for pre-4.4 savegames).
@ Storage
Load/save a reference to a persistent storage.
@ EngineRenew
Load/save a reference to an engine renewal (autoreplace).
@ Town
Load/save a reference to a town.
@ LinkGraphJob
Load/save a reference to a link graph job.
@ Vehicle
Load/save a reference to a vehicle.
@ RoadStop
Load/save a reference to a bus/truck stop.
void * GetVariableAddress(const void *object, const SaveLoad &sld)
Get the address of the variable.
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
SaveLoadType
Type of data saved.
@ ReferenceList
Save/load a list of SaveLoadType::Reference elements.
@ String
Save/load a std::string.
@ Array
Save/load a fixed-size array of SaveLoadType::Variable elements.
@ Variable
Save/load a variable.
@ Vector
Save/load a vector of SaveLoadType::Variable elements.
@ Reference
Save/load a reference.
@ StructList
Save/load a list of structs.
@ Struct
Save/load a struct.
@ Null
Save null-bytes and load to nowhere.
@ SaveByte
Save (but not load) a byte.
@ ReferenceVector
Save/load a vector of SaveLoadType::Reference elements.
std::span< const struct SaveLoadCompat > SaveLoadCompatTable
A table of SaveLoadCompat entries.
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
SaveLoadVersion
SaveLoad versions Previous savegame versions, the trunk revision where they were introduced and the r...
@ EndPatchpacks
Saveload version: 286 Last known patchpack to use a version just above ours.
@ MoveSccEncoded
Saveload version: 169, SVN revision: 23816 Move SCC_ENCODED to the first StringControlCode.
@ TownTolerancePauseMode
Saveload version: 4.0, SVN revision: 1 Town council tolerance and pause mode.
@ MoreCargoPackets
Saveload version: 69, SVN revision: 10319 Allow more than ~65k cargo packets.
@ EncodedStringFormat
Saveload version: 350, GitHub pull request: 13499 Encoded String format changed.
@ FixSccEncodedNegative
Saveload version: 353, GitHub pull request: 14049 Fix encoding of negative parameters.
@ MinVersion
First savegame version.
@ SaveloadListLength
Saveload version: 293, GitHub pull request: 9374 Consistency in list length with SaveLoadType::Struc...
@ MaxVersion
Highest possible saveload version.
@ StartPatchpacks
Saveload version: 220 First known patchpack to use a version just above ours.
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
ChunkType
Type of a chunk.
@ SparseTable
A SparseArray with a header describing the elements.
@ ReadOnly
Chunk is never saved.
@ Array
Contiguous array of elements starting at index 0.
@ Table
An Array with a header describing the elements.
@ FileTypeMask
All ChunkType values that are saved in the file have to be within this mask.
@ Riff
4 bits store the chunk type, 28 bits the number of bytes.
@ SparseArray
Array of elements with index for each element.
Label< struct ChunkIdTag > ChunkId
Label/unique identifier for each of the chunks in the savegame.
void SlErrorCorruptFmt(const fmt::format_string< Args... > format, Args &&... fmt_args)
Issue an SlErrorCorrupt with a format string.
Declaration of filters used for saving and loading savegames.
std::shared_ptr< SaveFilter > CreateSaveFilter(std::shared_ptr< SaveFilter > chain, uint8_t compression_level)
Instantiator for a save filter.
std::shared_ptr< LoadFilter > CreateLoadFilter(std::shared_ptr< LoadFilter > chain)
Instantiator for a load filter.
Declaration of functions used in more save/load files.
StringID RemapOldStringID(StringID s)
Remap a string ID from the old format to the new format.
std::string CopyFromOldName(StringID id)
Copy and convert old custom names to UTF-8.
SaveLoadResult
Save or load result codes.
@ Error
error that was caught before internal structures were modified
@ Ok
completed successfully
@ ReInit
error that was caught in the middle of updating game state, need to clear it. (can only happen during...
std::span< const struct SaveLoad > SaveLoadTable
A table of SaveLoad entries.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
SettingTable GetSaveLoadSettingTable()
Create a single table with all settings that should be stored/loaded in the savegame.
ClientSettings _settings_client
The current settings for this game.
Functions and types used internally for the settings configurations.
@ NotInSave
Do not save with savegame, basically client-based.
@ NoNetworkSync
Do not synchronize over network (but it is saved if SettingFlag::NotInSave is not set).
static constexpr const SettingDesc * GetSettingDesc(const SettingVariant &desc)
Helper to convert the type of the iterated settings description to a pointer to it.
Base classes/functions for stations.
Functions, definitions and such used only by the GUI.
@ SBI_SAVELOAD_FINISH
finished saving
@ SBI_SAVELOAD_START
started saving
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
void StrMakeValidInPlace(char *str, StringValidationSettings settings)
Scans the string for invalid characters and replaces them with a question mark '?
Compose strings from textual and binary data.
static std::optional< T > ParseInteger(std::string_view arg, int base=10, bool clamp=false)
Change a string into its number representation.
Functions related to low-level strings.
@ ReplaceWithQuestionMark
Replace the unknown/bad bits with question marks.
@ AllowControlCode
Allow the special control codes.
EnumBitSet< StringValidationSetting, uint8_t > StringValidationSettings
Bitset of StringValidationSetting elements.
void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters &args, uint case_index, bool game_script)
Get a parsed string with most special stringcodes replaced by the string parameters.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Functions related to OTTD's strings.
Types related to strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Base for a four character label/tag/id.
constexpr bool Empty() const
Check whether the label is empty.
Container for cargo from the same location and time.
Handlers and description of chunk.
ChunkType type
Type of the chunk.
virtual void LoadCheck(size_t len=0) const
Load the chunk for game preview.
ChunkId id
Unique ID (4 letters).
std::string GetName() const
Get the name of this chunk.
virtual void Load() const =0
Load the chunk.
virtual void Save() const
Save the chunk.
Struct to store engine replacements.
size_t Read(uint8_t *buf, size_t size) override
Read a given number of bytes from the savegame.
void Reset() override
Reset this filter to read from the beginning of the file.
~FileReader() override
Make sure everything is cleaned up.
FileReader(FileHandle &&file)
Create the file reader, so it reads from a specific file.
long begin
The begin of the file.
std::optional< FileHandle > file
The file to read from.
Deals with the type of the savegame, independent of extension.
void SetMode(const FiosType &ft, SaveLoadOperation fop=SaveLoadOperation::Load)
Set the mode and file type of the file to save or load.
SaveLoadOperation file_op
File operation to perform.
std::string name
Name of the file.
EncodedString title
Internal name of the game.
void Set(const FiosItem &item)
Set the mode, title and name of the file.
std::optional< FileHandle > file
The file to write to.
void Write(const uint8_t *buf, size_t size) override
Write a given number of bytes into the savegame.
~FileWriter() override
Make sure everything is cleaned up.
FileWriter(FileHandle &&file)
Create the file writer, so it writes to a specific file.
void Finish() override
Prepare everything to finish writing the savegame.
Deals with finding savegames.
A savegame name automatically numbered.
std::string Filename()
Generate a savegame name and number according to _settings_client.gui.max_num_autosaves.
std::string Extension()
Generate an extension for a savegame name.
Elements of a file system that are recognized.
AbstractFileType abstract
Abstract file type.
lzma_stream lzma
Stream state that we are reading from.
size_t Read(uint8_t *buf, size_t size) override
Read a given number of bytes from the savegame.
~LZMALoadFilter() override
Clean everything up.
uint8_t fread_buf[MEMORY_CHUNK_SIZE]
Buffer for reading from the file.
LZMALoadFilter(std::shared_ptr< LoadFilter > chain)
Initialise this filter.
~LZMASaveFilter() override
Clean up what we allocated.
void WriteLoop(const uint8_t *p, size_t len, lzma_action action)
Helper loop for writing the data.
void Write(const uint8_t *buf, size_t size) override
Write a given number of bytes into the savegame.
void Finish() override
Prepare everything to finish writing the savegame.
LZMASaveFilter(std::shared_ptr< SaveFilter > chain, uint8_t compression_level)
Initialise this filter.
lzma_stream lzma
Stream state that we are writing to.
uint8_t fwrite_buf[MEMORY_CHUNK_SIZE]
Buffer for writing to the file.
LZOLoadFilter(std::shared_ptr< LoadFilter > chain)
Initialise this filter.
size_t Read(uint8_t *buf, size_t ssize) override
Read a given number of bytes from the savegame.
void Write(const uint8_t *buf, size_t size) override
Write a given number of bytes into the savegame.
LZOSaveFilter(std::shared_ptr< SaveFilter > chain, uint8_t)
Initialise this filter.
A four character label/tag/id.
std::shared_ptr< LoadFilter > chain
Chained to the (savegame) filters.
LoadFilter(std::shared_ptr< LoadFilter > chain)
Initialise this filter.
Container for dumping the savegame (quickly) to memory.
uint8_t * buf
Buffer we're going to write to.
void WriteByte(uint8_t b)
Write a single byte into the dumper.
std::vector< std::unique_ptr< uint8_t[]> > blocks
Buffer with blocks of allocated memory.
uint8_t * bufe
End of the buffer we write to.
size_t GetSize() const
Get the size of the memory dump made so far.
void Flush(std::shared_ptr< SaveFilter > writer)
Flush this dumper into a writer.
NoCompLoadFilter(std::shared_ptr< LoadFilter > chain)
Initialise this filter.
size_t Read(uint8_t *buf, size_t size) override
Read a given number of bytes from the savegame.
void Write(const uint8_t *buf, size_t size) override
Write a given number of bytes into the savegame.
NoCompSaveFilter(std::shared_ptr< SaveFilter > chain, uint8_t)
Initialise this filter.
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Class for pooled persistent storage of data.
static Pool::IterateWrapper< Company > Iterate(size_t from=0)
static OrderList * Get(auto index)
static bool IsValidID(auto index)
uint8_t * bufp
Location we're at reading the buffer.
ReadBuffer(std::shared_ptr< LoadFilter > reader)
Initialise our variables.
size_t read
The amount of read bytes so far from the filter.
size_t GetSize() const
Get the size of the memory dump made so far.
std::shared_ptr< LoadFilter > reader
The filter used to actually read.
uint8_t buf[MEMORY_CHUNK_SIZE]
Buffer we're going to read from.
uint8_t * bufe
End of the buffer we can read from.
A Stop for a Road Vehicle.
SaveFilter(std::shared_ptr< SaveFilter > chain)
Initialise this filter.
std::shared_ptr< SaveFilter > chain
Chained to the (savegame) filters.
The saveload struct, containing reader-writer functions, buffer, version, etc.
std::unique_ptr< ReadBuffer > reader
Savegame reading buffer.
std::shared_ptr< SaveFilter > sf
Filter to write the savegame to.
ChunkType chunk_type
The type of chunk we are reading or writing.
std::unique_ptr< MemoryDumper > dumper
Memory dumper to write the savegame to.
StringID error_str
the translatable error message to show
SaveLoadAction action
are we doing a save or a load atm.
std::string extra_msg
the error message
NeedLength need_length
working in NeedLength (Autolength) mode?
bool saveinprogress
Whether there is currently a save in progress.
std::shared_ptr< LoadFilter > lf
Filter to read the savegame from.
bool expect_table_header
In the case of a table, if the header is saved/loaded.
size_t obj_len
the length of the current object we are busy with
bool error
did an error occur or not
int last_array_index
in the case of an array, the current and last positions
uint16_t length
(Conditional) length of the variable (eg. arrays) (max array size is 65536 elements).
std::shared_ptr< SaveLoadHandler > handler
Custom handler for Save/Load procs.
SaveLoadVersion version_to
Save/load the variable before this savegame version.
SaveLoadType cmd
The action to take with the saved/loaded type, All types need different action.
std::string name
Name of this field (optional, used for tables).
VarType conv
Type of the variable to be saved; this field combines both FileVarType and MemVarType.
SaveLoadVersion version_from
Save/load the variable starting from this savegame version.
Container/wrapper for the file type that is used in tables in the save game.
uint8_t storage
Actual storage of the file type.
constexpr VarFileType Type() const
Get the VarType for this field.
SavegameFileType(VarFileType file_type, bool has_field_length=false)
Create the type.
constexpr bool HasFieldLength() const
Does this field have a length?
constexpr bool IsEnd() const
Is this the end-of-table marker?
static constexpr uint8_t HAS_FIELD_LENGTH_BIT
Set this bit to denote the type has a field length.
SavegameFileType()
Create an end-of-table marker.
Properties of config file settings.
SettingFlags flags
Handles how a setting would show up in the GUI (text/currency, etc.).
virtual void ResetToDefault(void *object) const =0
Reset the setting to its default value.
static bool IsValidID(auto index)
static Station * Get(auto index)
Container of a variable's characteristics about a variable's storage.
SLRefType ref
The reference type.
VarMemType mem
The way of storing data in memory.
StringValidationSettings string_validation_settings
Any settings related to validation of the strings.
VarFileType file
The way of storing data in the file.
static constexpr VarType U16
Store a 16 bits unsigned int.
static constexpr VarType U8
Store a 8 bits unsigned int.
static constexpr VarType STR
Store string.
static constexpr VarType LABEL_REVERSE
Store a Label in reverse.
static constexpr VarType I16
Store a 16 bits signed int.
static constexpr VarType I8
Store a 8 bits signed int.
static constexpr VarType U32
Store a 32 bits unsigned int.
static constexpr VarType STRINGID
Store a StringID.
static constexpr VarType LABEL_FORWARD
Store a Label as-is.
static constexpr VarType I32
Store a 32 bits signed int.
size_t Read(uint8_t *buf, size_t size) override
Read a given number of bytes from the savegame.
ZlibLoadFilter(std::shared_ptr< LoadFilter > chain)
Initialise this filter.
uint8_t fread_buf[MEMORY_CHUNK_SIZE]
Buffer for reading from the file.
~ZlibLoadFilter() override
Clean everything up.
z_stream z
Stream state we are reading from.
z_stream z
Stream state we are writing to.
void Write(const uint8_t *buf, size_t size) override
Write a given number of bytes into the savegame.
uint8_t fwrite_buf[MEMORY_CHUNK_SIZE]
Buffer for writing to the file.
~ZlibSaveFilter() override
Clean up what we allocated.
void Finish() override
Prepare everything to finish writing the savegame.
ZlibSaveFilter(std::shared_ptr< SaveFilter > chain, uint8_t compression_level)
Initialise this filter.
void WriteLoop(const uint8_t *p, size_t len, int mode)
Helper loop for writing the data.
void CSleep(int milliseconds)
Sleep on the current thread for a defined time.
bool StartNewThread(std::thread *thr, std::string_view name, TFn &&_Fx, TArgs &&... _Ax)
Start a new thread.
Definition of the game-economy-timer.
Base class for all vehicles.
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-...
Window functions not directly related to making/drawing windows.