12#include "../strings_type.h"
13#include "../string_func.h"
14#include "../settings_type.h"
15#include "../fileio_func.h"
19#include "table/strings.h"
21#include "../safeguards.h"
23static const int TTO_HEADER_SIZE = 41;
24static const int TTD_HEADER_SIZE = 49;
28uint32_t _bump_assert_value;
41 switch (GetOldChunkVarType(type)) {
42 case OC_VAR_I8:
return sizeof(int8_t);
43 case OC_VAR_U8:
return sizeof(uint8_t);
44 case OC_VAR_I16:
return sizeof(int16_t);
45 case OC_VAR_U16:
return sizeof(uint16_t);
46 case OC_VAR_I32:
return sizeof(int32_t);
47 case OC_VAR_U32:
return sizeof(uint32_t);
48 case OC_VAR_I64:
return sizeof(int64_t);
49 case OC_VAR_U64:
return sizeof(uint64_t);
50 default: NOT_REACHED();
63 if (ls.buffer_cur >= ls.buffer_count) {
66 int count =
static_cast<int>(fread(ls.buffer.data(), 1, ls.buffer.size(), *ls.file));
70 Debug(oldloader, 0,
"Read past end of file, loading failed");
71 throw std::exception();
74 ls.buffer_count = count;
78 return ls.buffer[ls.buffer_cur++];
94 if (ls.chunk_size == 0) {
102 ls.chunk_size = -new_byte + 1;
105 ls.chunk_size = new_byte + 1;
129 uint8_t *ptr = (uint8_t*)chunk->ptr;
131 for (uint i = 0; i < chunk->amount; i++) {
133 if (GetOldChunkType(chunk->type) != 0) {
134 switch (GetOldChunkType(chunk->type)) {
141 if (!chunk->proc(ls, i))
return false;
145 Debug(oldloader, 4,
"Assert point: 0x{:X} / 0x{:X}", ls.total_read,
reinterpret_cast<size_t>(chunk->ptr) + _bump_assert_value);
146 if (ls.total_read !=
reinterpret_cast<size_t>(chunk->ptr) + _bump_assert_value)
throw std::exception();
153 switch (GetOldChunkFileType(chunk->type)) {
154 case OC_FILE_I8: res = (int8_t)
ReadByte(ls);
break;
155 case OC_FILE_U8: res =
ReadByte(ls);
break;
156 case OC_FILE_I16: res = (int16_t)ReadUint16(ls);
break;
157 case OC_FILE_U16: res = ReadUint16(ls);
break;
158 case OC_FILE_I32: res = (int32_t)ReadUint32(ls);
break;
159 case OC_FILE_U32: res = ReadUint32(ls);
break;
160 default: NOT_REACHED();
164 if (base ==
nullptr && chunk->ptr ==
nullptr)
continue;
167 if (chunk->ptr ==
nullptr) ptr = (uint8_t *)chunk->offset(base);
170 switch (GetOldChunkVarType(chunk->type)) {
171 case OC_VAR_I8: *(int8_t *)ptr =
GB(res, 0, 8);
break;
172 case OC_VAR_U8: *(uint8_t *)ptr =
GB(res, 0, 8);
break;
173 case OC_VAR_I16:*(int16_t *)ptr =
GB(res, 0, 16);
break;
174 case OC_VAR_U16:*(uint16_t*)ptr =
GB(res, 0, 16);
break;
175 case OC_VAR_I32:*(int32_t *)ptr = res;
break;
176 case OC_VAR_U32:*(uint32_t*)ptr = res;
break;
177 case OC_VAR_I64:*(int64_t *)ptr = res;
break;
178 case OC_VAR_U64:*(uint64_t*)ptr = res;
break;
179 default: NOT_REACHED();
183 if (chunk->amount > 1 && chunk->ptr !=
nullptr) ptr +=
CalcOldVarLen(chunk->type);
202 sum = std::rotl(sum, 1);
213static std::tuple<SavegameType, std::string> DetermineOldSavegameTypeAndName(
FileHandle &f)
216 char buffer[std::max(TTO_HEADER_SIZE, TTD_HEADER_SIZE)];
218 return {
SGT_INVALID,
"(broken) Unable to read file" };
221 if (
VerifyOldNameChecksum(buffer, TTO_HEADER_SIZE) && fseek(f, pos + TTO_HEADER_SIZE, SEEK_SET) == 0) {
225 if (
VerifyOldNameChecksum(buffer, TTD_HEADER_SIZE) && fseek(f, pos + TTD_HEADER_SIZE, SEEK_SET) == 0) {
234bool LoadOldSaveGame(std::string_view file)
238 Debug(oldloader, 3,
"Trying to load a TTD(Patch) savegame");
240 _bump_assert_value = 0;
246 if (!ls.file.has_value()) {
247 Debug(oldloader, 0,
"Cannot open file '{}'", file);
253 std::tie(type, std::ignore) = DetermineOldSavegameTypeAndName(*ls.file);
255 LoadOldMainProc *proc =
nullptr;
258 case SGT_TTO: proc = &LoadTTOMain;
break;
259 case SGT_TTD: proc = &LoadTTDMain;
break;
261 Debug(oldloader, 0,
"Unknown savegame type; cannot be loaded");
269 game_loaded = proc !=
nullptr && proc(ls);
285std::string GetOldSaveGameName(std::string_view file)
288 if (!f.has_value())
return {};
291 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(std::string_view filename, std::string_view 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(Builder &builder, StringConsumer &consumer, StringValidationSettings settings)
Copies the valid (UTF-8) characters from consumer to the builder.
bool freeform_edges
allow terraforming the tiles at the map edges
ConstructionSettings construction
construction of things in-game
OldChunkType type
Type of field.