10 #include "../stdafx.h"
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"
25 static const int TTO_HEADER_SIZE = 41;
26 static const int TTD_HEADER_SIZE = 49;
30 uint32_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);
238 static 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) {
259 bool 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);
276 std::tie(type, std::ignore) = DetermineOldSavegameTypeAndName(*ls.file);
278 LoadOldMainProc *proc =
nullptr;
281 case SGT_TTO: proc = &LoadTTOMain;
break;
282 case SGT_TTD: proc = &LoadTTDMain;
break;
284 Debug(oldloader, 0,
"Unknown savegame type; cannot be loaded");
292 game_loaded = proc !=
nullptr && proc(&ls);
308 std::string GetOldSaveGameName(
const std::string &file)
311 if (!f.has_value())
return {};
314 std::tie(std::ignore, name) = DetermineOldSavegameTypeAndName(*f);