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"
24 #include "../safeguards.h"
26 static const int TTO_HEADER_SIZE = 41;
27 static const int TTD_HEADER_SIZE = 49;
29 uint32 _bump_assert_value;
37 static const byte type_mem_size[] = {0, 1, 1, 2, 2, 4, 4, 8};
38 byte length =
GB(type, 8, 8);
39 assert(length != 0 && length <
lengthof(type_mem_size));
40 return type_mem_size[length];
52 if (ls->buffer_cur >= ls->buffer_count) {
55 int count = (int)fread(ls->buffer, 1, BUFFER_SIZE, ls->file);
59 DEBUG(oldloader, 0,
"Read past end of file, loading failed");
60 throw std::exception();
63 ls->buffer_count = count;
67 return ls->buffer[ls->buffer_cur++];
83 if (ls->chunk_size == 0) {
91 ls->chunk_size = -new_byte + 1;
94 ls->chunk_size = new_byte + 1;
118 byte *ptr = (
byte*)chunk->ptr;
121 for (uint i = 0; i < chunk->amount; i++) {
123 if (GetOldChunkType(chunk->type) != 0) {
124 switch (GetOldChunkType(chunk->type)) {
131 if (!chunk->proc(ls, i))
return false;
135 DEBUG(oldloader, 4,
"Assert point: 0x%X / 0x%X", ls->total_read, (uint)(
size_t)chunk->ptr + _bump_assert_value);
136 if (ls->total_read != (
size_t)chunk->ptr + _bump_assert_value)
throw std::exception();
143 switch (GetOldChunkFileType(chunk->type)) {
144 case OC_FILE_I8: res = (int8)
ReadByte(ls);
break;
145 case OC_FILE_U8: res =
ReadByte(ls);
break;
146 case OC_FILE_I16: res = (int16)ReadUint16(ls);
break;
147 case OC_FILE_U16: res = ReadUint16(ls);
break;
148 case OC_FILE_I32: res = (int32)ReadUint32(ls);
break;
149 case OC_FILE_U32: res = ReadUint32(ls);
break;
150 default: NOT_REACHED();
154 if (base ==
nullptr && chunk->ptr ==
nullptr)
continue;
157 if (chunk->ptr ==
nullptr) ptr = (
byte *)chunk->offset(base);
160 switch (GetOldChunkVarType(chunk->type)) {
161 case OC_VAR_I8: *(int8 *)ptr =
GB(res, 0, 8);
break;
162 case OC_VAR_U8: *(uint8 *)ptr =
GB(res, 0, 8);
break;
163 case OC_VAR_I16:*(int16 *)ptr =
GB(res, 0, 16);
break;
164 case OC_VAR_U16:*(uint16*)ptr =
GB(res, 0, 16);
break;
165 case OC_VAR_I32:*(int32 *)ptr = res;
break;
166 case OC_VAR_U32:*(uint32*)ptr = res;
break;
167 case OC_VAR_I64:*(int64 *)ptr = res;
break;
168 case OC_VAR_U64:*(uint64*)ptr = res;
break;
169 default: NOT_REACHED();
173 if (chunk->amount > 1 && chunk->ptr !=
nullptr) ptr += CalcOldVarLen(chunk->type);
191 ls->decoding =
false;
195 ls->buffer_count = 0;
196 memset(ls->buffer, 0, BUFFER_SIZE);
198 _bump_assert_value = 0;
213 for (uint i = 0; i < len - 2; i++) {
220 uint16 sum2 = title[len - 2];
221 SB(sum2, 8, 8, title[len - 1]);
226 static inline bool CheckOldSavegameType(FILE *f,
char *temp,
const char *last, uint len)
228 assert(last - temp + 1 >= (
int)len);
230 if (fread(temp, 1, len, f) != len) {
236 temp[len - 2] =
'\0';
242 static SavegameType DetermineOldSavegameType(FILE *f,
char *title,
const char *last)
244 static_assert(TTD_HEADER_SIZE >= TTO_HEADER_SIZE);
245 char temp[TTD_HEADER_SIZE] =
"Unknown";
251 if (pos >= 0 && !CheckOldSavegameType(f, temp,
lastof(temp), TTO_HEADER_SIZE)) {
253 if (fseek(f, pos, SEEK_SET) < 0 || !CheckOldSavegameType(f, temp,
lastof(temp), TTD_HEADER_SIZE)) {
258 if (title !=
nullptr) {
262 default: title =
strecpy(title,
"(broken) ", last);
break;
272 bool LoadOldSaveGame(
const std::string &file)
276 DEBUG(oldloader, 3,
"Trying to load a TTD(Patch) savegame");
283 if (ls.file ==
nullptr) {
284 DEBUG(oldloader, 0,
"Cannot open file '%s'", file.c_str());
288 SavegameType type = DetermineOldSavegameType(ls.file,
nullptr,
nullptr);
290 LoadOldMainProc *proc =
nullptr;
293 case SGT_TTO: proc = &LoadTTOMain;
break;
294 case SGT_TTD: proc = &LoadTTDMain;
break;
302 game_loaded = proc !=
nullptr && proc(&ls);
318 void GetOldSaveGameName(
const std::string &file,
char *title,
const char *last)
327 DetermineOldSavegameType(f, title, last);