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;
38 static const byte type_mem_size[] = {0, 1, 1, 2, 2, 4, 4, 8};
39 byte length =
GB(type, 8, 8);
40 assert(length != 0 && length <
lengthof(type_mem_size));
41 return type_mem_size[length];
53 if (ls->buffer_cur >= ls->buffer_count) {
56 int count = (int)fread(ls->buffer, 1, BUFFER_SIZE, ls->file);
60 Debug(oldloader, 0,
"Read past end of file, loading failed");
61 throw std::exception();
64 ls->buffer_count = count;
68 return ls->buffer[ls->buffer_cur++];
84 if (ls->chunk_size == 0) {
92 ls->chunk_size = -new_byte + 1;
95 ls->chunk_size = new_byte + 1;
119 byte *ptr = (
byte*)chunk->ptr;
122 for (uint i = 0; i < chunk->amount; i++) {
124 if (GetOldChunkType(chunk->type) != 0) {
125 switch (GetOldChunkType(chunk->type)) {
132 if (!chunk->proc(ls, i))
return false;
136 Debug(oldloader, 4,
"Assert point: 0x{:X} / 0x{:X}", ls->total_read, (uint)(
size_t)chunk->ptr + _bump_assert_value);
137 if (ls->total_read != (
size_t)chunk->ptr + _bump_assert_value)
throw std::exception();
144 switch (GetOldChunkFileType(chunk->type)) {
145 case OC_FILE_I8: res = (int8_t)
ReadByte(ls);
break;
146 case OC_FILE_U8: res =
ReadByte(ls);
break;
147 case OC_FILE_I16: res = (int16_t)ReadUint16(ls);
break;
148 case OC_FILE_U16: res = ReadUint16(ls);
break;
149 case OC_FILE_I32: res = (int32_t)ReadUint32(ls);
break;
150 case OC_FILE_U32: res = ReadUint32(ls);
break;
151 default: NOT_REACHED();
155 if (base ==
nullptr && chunk->ptr ==
nullptr)
continue;
158 if (chunk->ptr ==
nullptr) ptr = (
byte *)chunk->offset(base);
161 switch (GetOldChunkVarType(chunk->type)) {
162 case OC_VAR_I8: *(int8_t *)ptr =
GB(res, 0, 8);
break;
163 case OC_VAR_U8: *(uint8_t *)ptr =
GB(res, 0, 8);
break;
164 case OC_VAR_I16:*(int16_t *)ptr =
GB(res, 0, 16);
break;
165 case OC_VAR_U16:*(uint16_t*)ptr =
GB(res, 0, 16);
break;
166 case OC_VAR_I32:*(int32_t *)ptr = res;
break;
167 case OC_VAR_U32:*(uint32_t*)ptr = res;
break;
168 case OC_VAR_I64:*(int64_t *)ptr = res;
break;
169 case OC_VAR_U64:*(uint64_t*)ptr = res;
break;
170 default: NOT_REACHED();
174 if (chunk->amount > 1 && chunk->ptr !=
nullptr) ptr += CalcOldVarLen(chunk->type);
192 ls->decoding =
false;
196 ls->buffer_count = 0;
197 memset(ls->buffer, 0, BUFFER_SIZE);
199 _bump_assert_value = 0;
215 sum = std::rotl(sum, 1);
226 static std::tuple<SavegameType, std::string> DetermineOldSavegameTypeAndName(FILE *f)
229 char buffer[std::max(TTO_HEADER_SIZE, TTD_HEADER_SIZE)];
231 return {
SGT_INVALID,
"(broken) Unable to read file" };
234 if (
VerifyOldNameChecksum(buffer, TTO_HEADER_SIZE) && fseek(f, pos + TTO_HEADER_SIZE, SEEK_SET) == 0) {
238 if (
VerifyOldNameChecksum(buffer, TTD_HEADER_SIZE) && fseek(f, pos + TTD_HEADER_SIZE, SEEK_SET) == 0) {
247 bool LoadOldSaveGame(
const std::string &file)
251 Debug(oldloader, 3,
"Trying to load a TTD(Patch) savegame");
258 if (ls.file ==
nullptr) {
259 Debug(oldloader, 0,
"Cannot open file '{}'", file);
264 std::tie(type, std::ignore) = DetermineOldSavegameTypeAndName(ls.file);
266 LoadOldMainProc *proc =
nullptr;
269 case SGT_TTO: proc = &LoadTTOMain;
break;
270 case SGT_TTD: proc = &LoadTTDMain;
break;
272 Debug(oldloader, 0,
"Unknown savegame type; cannot be loaded");
280 game_loaded = proc !=
nullptr && proc(&ls);
296 std::string GetOldSaveGameName(
const std::string &file)
299 if (f ==
nullptr)
return {};
302 std::tie(std::ignore, name) = DetermineOldSavegameTypeAndName(f);