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, 1, 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;
106 ls->decoding =
false;
107 ls->chunk_size = new_byte + 1;
131 uint8_t *ptr = (uint8_t*)chunk->ptr;
134 for (uint i = 0; i < chunk->amount; i++) {
136 if (GetOldChunkType(chunk->type) != 0) {
137 switch (GetOldChunkType(chunk->type)) {
144 if (!chunk->proc(ls, i))
return false;
148 Debug(oldloader, 4,
"Assert point: 0x{:X} / 0x{:X}", ls->total_read, (uint)(
size_t)chunk->ptr + _bump_assert_value);
149 if (ls->total_read != (
size_t)chunk->ptr + _bump_assert_value)
throw std::exception();
156 switch (GetOldChunkFileType(chunk->type)) {
157 case OC_FILE_I8: res = (int8_t)
ReadByte(ls);
break;
158 case OC_FILE_U8: res =
ReadByte(ls);
break;
159 case OC_FILE_I16: res = (int16_t)ReadUint16(ls);
break;
160 case OC_FILE_U16: res = ReadUint16(ls);
break;
161 case OC_FILE_I32: res = (int32_t)ReadUint32(ls);
break;
162 case OC_FILE_U32: res = ReadUint32(ls);
break;
163 default: NOT_REACHED();
167 if (base ==
nullptr && chunk->ptr ==
nullptr)
continue;
170 if (chunk->ptr ==
nullptr) ptr = (uint8_t *)chunk->offset(base);
173 switch (GetOldChunkVarType(chunk->type)) {
174 case OC_VAR_I8: *(int8_t *)ptr =
GB(res, 0, 8);
break;
175 case OC_VAR_U8: *(uint8_t *)ptr =
GB(res, 0, 8);
break;
176 case OC_VAR_I16:*(int16_t *)ptr =
GB(res, 0, 16);
break;
177 case OC_VAR_U16:*(uint16_t*)ptr =
GB(res, 0, 16);
break;
178 case OC_VAR_I32:*(int32_t *)ptr = res;
break;
179 case OC_VAR_U32:*(uint32_t*)ptr = res;
break;
180 case OC_VAR_I64:*(int64_t *)ptr = res;
break;
181 case OC_VAR_U64:*(uint64_t*)ptr = res;
break;
182 default: NOT_REACHED();
186 if (chunk->amount > 1 && chunk->ptr !=
nullptr) ptr +=
CalcOldVarLen(chunk->type);
204 ls->decoding =
false;
208 ls->buffer_count = 0;
209 memset(ls->buffer, 0, BUFFER_SIZE);
211 _bump_assert_value = 0;
227 sum = std::rotl(sum, 1);
238static std::tuple<SavegameType, std::string> DetermineOldSavegameTypeAndName(
FileHandle &f)
241 char buffer[std::max(TTO_HEADER_SIZE, TTD_HEADER_SIZE)];
243 return {
SGT_INVALID,
"(broken) Unable to read file" };
246 if (
VerifyOldNameChecksum(buffer, TTO_HEADER_SIZE) && fseek(f, pos + TTO_HEADER_SIZE, SEEK_SET) == 0) {
250 if (
VerifyOldNameChecksum(buffer, TTD_HEADER_SIZE) && fseek(f, pos + TTD_HEADER_SIZE, SEEK_SET) == 0) {
259bool LoadOldSaveGame(
const std::string &file)
263 Debug(oldloader, 3,
"Trying to load a TTD(Patch) savegame");
270 if (!ls.file.has_value()) {
271 Debug(oldloader, 0,
"Cannot open file '{}'", file);
277 std::tie(type, std::ignore) = DetermineOldSavegameTypeAndName(*ls.file);
279 LoadOldMainProc *proc =
nullptr;
282 case SGT_TTO: proc = &LoadTTOMain;
break;
283 case SGT_TTD: proc = &LoadTTDMain;
break;
285 Debug(oldloader, 0,
"Unknown savegame type; cannot be loaded");
293 game_loaded = proc !=
nullptr && proc(&ls);
309std::string GetOldSaveGameName(
const std::string &file)
312 if (!f.has_value())
return {};
315 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,...)
Ouptut 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
PauseMode _pause_mode
The current pause mode.
uint8_t ReadByte(LoadgameState *ls)
Reads a byte from the buffer and decompress if needed.
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.
bool LoadChunk(LoadgameState *ls, void *base, const OldChunks *chunks)
Loads a chunk from the old savegame.
static void InitLoading(LoadgameState *ls)
Initialize some data before reading.
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())
Declarations of strctures and function used in loader of old savegames.
@ OC_END
End of the whole chunk, all 32 bits set to zero.
@ OC_DEREFERENCE_POINTER
Dereference the pointer once before writing to it, so we do not have to use big static arrays.
@ OC_TTO
-//- TTO (default is neither of these)
@ OC_TTD
chunk is valid ONLY for TTD savegames
@ PM_PAUSED_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.