12#include "../strings_type.h"
13#include "../string_func.h"
14#include "../settings_type.h"
15#include "../fileio_func.h"
17#include "table/strings.h"
23#include "../safeguards.h"
25static const int TTO_HEADER_SIZE = 41;
26static const int TTD_HEADER_SIZE = 49;
30uint32_t _bump_assert_value;
43 switch (GetOldChunkVarType(type)) {
44 case OC_VAR_I8:
return sizeof(int8_t);
45 case OC_VAR_U8:
return sizeof(uint8_t);
46 case OC_VAR_I16:
return sizeof(int16_t);
47 case OC_VAR_U16:
return sizeof(uint16_t);
48 case OC_VAR_I32:
return sizeof(int32_t);
49 case OC_VAR_U32:
return sizeof(uint32_t);
50 case OC_VAR_I64:
return sizeof(int64_t);
51 case OC_VAR_U64:
return sizeof(uint64_t);
52 default: NOT_REACHED();
65 if (ls.buffer_cur >= ls.buffer_count) {
68 int count =
static_cast<int>(fread(ls.buffer.data(), 1, ls.buffer.size(), *ls.file));
72 Debug(oldloader, 0,
"Read past end of file, loading failed");
73 throw std::exception();
76 ls.buffer_count = count;
80 return ls.buffer[ls.buffer_cur++];
96 if (ls.chunk_size == 0) {
104 ls.chunk_size = -new_byte + 1;
107 ls.chunk_size = new_byte + 1;
131 uint8_t *ptr = (uint8_t*)chunk->ptr;
133 for (uint i = 0; i < chunk->amount; i++) {
135 if (GetOldChunkType(chunk->type) != 0) {
136 switch (GetOldChunkType(chunk->type)) {
143 if (!chunk->proc(ls, i))
return false;
147 Debug(oldloader, 4,
"Assert point: 0x{:X} / 0x{:X}", ls.total_read,
reinterpret_cast<size_t>(chunk->ptr) + _bump_assert_value);
148 if (ls.total_read !=
reinterpret_cast<size_t>(chunk->ptr) + _bump_assert_value)
throw std::exception();
155 switch (GetOldChunkFileType(chunk->type)) {
156 case OC_FILE_I8: res = (int8_t)
ReadByte(ls);
break;
157 case OC_FILE_U8: res =
ReadByte(ls);
break;
158 case OC_FILE_I16: res = (int16_t)ReadUint16(ls);
break;
159 case OC_FILE_U16: res = ReadUint16(ls);
break;
160 case OC_FILE_I32: res = (int32_t)ReadUint32(ls);
break;
161 case OC_FILE_U32: res = ReadUint32(ls);
break;
162 default: NOT_REACHED();
166 if (base ==
nullptr && chunk->ptr ==
nullptr)
continue;
169 if (chunk->ptr ==
nullptr) ptr = (uint8_t *)chunk->offset(base);
172 switch (GetOldChunkVarType(chunk->type)) {
173 case OC_VAR_I8: *(int8_t *)ptr =
GB(res, 0, 8);
break;
174 case OC_VAR_U8: *(uint8_t *)ptr =
GB(res, 0, 8);
break;
175 case OC_VAR_I16:*(int16_t *)ptr =
GB(res, 0, 16);
break;
176 case OC_VAR_U16:*(uint16_t*)ptr =
GB(res, 0, 16);
break;
177 case OC_VAR_I32:*(int32_t *)ptr = res;
break;
178 case OC_VAR_U32:*(uint32_t*)ptr = res;
break;
179 case OC_VAR_I64:*(int64_t *)ptr = res;
break;
180 case OC_VAR_U64:*(uint64_t*)ptr = res;
break;
181 default: NOT_REACHED();
185 if (chunk->amount > 1 && chunk->ptr !=
nullptr) ptr +=
CalcOldVarLen(chunk->type);
204 sum = std::rotl(sum, 1);
215static std::tuple<SavegameType, std::string> DetermineOldSavegameTypeAndName(
FileHandle &f)
218 char buffer[std::max(TTO_HEADER_SIZE, TTD_HEADER_SIZE)];
220 return {
SGT_INVALID,
"(broken) Unable to read file" };
223 if (
VerifyOldNameChecksum(buffer, TTO_HEADER_SIZE) && fseek(f, pos + TTO_HEADER_SIZE, SEEK_SET) == 0) {
227 if (
VerifyOldNameChecksum(buffer, TTD_HEADER_SIZE) && fseek(f, pos + TTD_HEADER_SIZE, SEEK_SET) == 0) {
236bool LoadOldSaveGame(
const std::string &file)
240 Debug(oldloader, 3,
"Trying to load a TTD(Patch) savegame");
242 _bump_assert_value = 0;
248 if (!ls.file.has_value()) {
249 Debug(oldloader, 0,
"Cannot open file '{}'", file);
255 std::tie(type, std::ignore) = DetermineOldSavegameTypeAndName(*ls.file);
257 LoadOldMainProc *proc =
nullptr;
260 case SGT_TTO: proc = &LoadTTOMain;
break;
261 case SGT_TTD: proc = &LoadTTDMain;
break;
263 Debug(oldloader, 0,
"Unknown savegame type; cannot be loaded");
271 game_loaded = proc !=
nullptr && proc(ls);
287std::string GetOldSaveGameName(
const std::string &file)
290 if (!f.has_value())
return {};
293 std::tie(std::ignore, name) = DetermineOldSavegameTypeAndName(*f);
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
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.
@ NO_DIRECTORY
A path without any base directory.
SavegameType _savegame_type
type of savegame we are loading
PauseModes _pause_mode
The current pause mode.
static bool VerifyOldNameChecksum(char *title, uint len)
Verifies the title has a valid checksum.
static const int HEADER_CHECKSUM_SIZE
The size of the checksum in the name/header of the TTD/TTO savegames.
static uint8_t CalcOldVarLen(OldChunkType type)
Return expected size in bytes of a OldChunkType.
static uint8_t ReadByteFromFile(LoadgameState &ls)
Reads a byte from a file (do not call yourself, use ReadByte())
bool LoadChunk(LoadgameState &ls, void *base, const OldChunks *chunks)
Loads a chunk from the old savegame.
uint8_t ReadByte(LoadgameState &ls)
Reads a byte from the buffer and decompress if needed.
Declarations of structures and functions used in loader of old savegames.
@ OC_END
End of the whole chunk, all 32 bits set to zero.
@ OC_TTO
-//- TTO (default is neither of these)
@ OC_TTD
chunk is valid ONLY for TTD savegames
@ SaveLoad
A game paused for saving/loading.
void SetSaveLoadError(StringID str)
Set the error message from outside of the actual loading/saving of the game (AfterLoadGame and friend...
SavegameType
Types of save games.
@ SGT_TTD
TTD savegame (can be detected incorrectly)
@ SGT_INVALID
broken savegame (used internally)
Declaration of functions used in more save/load files.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
#define lengthof(array)
Return the length of an fixed size array.
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 freeform_edges
allow terraforming the tiles at the map edges
ConstructionSettings construction
construction of things in-game
OldChunkType type
Type of field.