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;
111 byte *base_ptr = (
byte*)base;
120 byte *ptr = (
byte*)chunk->ptr;
123 for (uint i = 0; i < chunk->amount; i++) {
125 if (GetOldChunkType(chunk->type) != 0) {
126 switch (GetOldChunkType(chunk->type)) {
133 if (!chunk->proc(ls, i))
return false;
137 DEBUG(oldloader, 4,
"Assert point: 0x%X / 0x%X", ls->total_read, chunk->offset + _bump_assert_value);
138 if (ls->total_read != chunk->offset + _bump_assert_value)
throw std::exception();
145 switch (GetOldChunkFileType(chunk->type)) {
146 case OC_FILE_I8: res = (int8)
ReadByte(ls);
break;
147 case OC_FILE_U8: res =
ReadByte(ls);
break;
148 case OC_FILE_I16: res = (int16)ReadUint16(ls);
break;
149 case OC_FILE_U16: res = ReadUint16(ls);
break;
150 case OC_FILE_I32: res = (int32)ReadUint32(ls);
break;
151 case OC_FILE_U32: res = ReadUint32(ls);
break;
152 default: NOT_REACHED();
156 if (base_ptr ==
nullptr && chunk->ptr ==
nullptr)
continue;
159 if (chunk->ptr ==
nullptr) ptr = base_ptr + chunk->offset;
162 switch (GetOldChunkVarType(chunk->type)) {
163 case OC_VAR_I8: *(int8 *)ptr =
GB(res, 0, 8);
break;
164 case OC_VAR_U8: *(uint8 *)ptr =
GB(res, 0, 8);
break;
165 case OC_VAR_I16:*(int16 *)ptr =
GB(res, 0, 16);
break;
166 case OC_VAR_U16:*(uint16*)ptr =
GB(res, 0, 16);
break;
167 case OC_VAR_I32:*(int32 *)ptr = res;
break;
168 case OC_VAR_U32:*(uint32*)ptr = res;
break;
169 case OC_VAR_I64:*(int64 *)ptr = res;
break;
170 case OC_VAR_U64:*(uint64*)ptr = res;
break;
171 default: NOT_REACHED();
175 if (chunk->amount > 1 && chunk->ptr !=
nullptr) ptr += CalcOldVarLen(chunk->type);
193 ls->decoding =
false;
197 ls->buffer_count = 0;
198 memset(ls->buffer, 0, BUFFER_SIZE);
200 _bump_assert_value = 0;
215 for (uint i = 0; i < len - 2; i++) {
222 uint16 sum2 = title[len - 2];
223 SB(sum2, 8, 8, title[len - 1]);
228 static inline bool CheckOldSavegameType(FILE *f,
char *temp,
const char *last, uint len)
230 assert(last - temp + 1 >= (
int)len);
232 if (fread(temp, 1, len, f) != len) {
238 temp[len - 2] =
'\0';
244 static SavegameType DetermineOldSavegameType(FILE *f,
char *title,
const char *last)
246 static_assert(TTD_HEADER_SIZE >= TTO_HEADER_SIZE);
247 char temp[TTD_HEADER_SIZE] =
"Unknown";
253 if (pos >= 0 && !CheckOldSavegameType(f, temp,
lastof(temp), TTO_HEADER_SIZE)) {
255 if (fseek(f, pos, SEEK_SET) < 0 || !CheckOldSavegameType(f, temp,
lastof(temp), TTD_HEADER_SIZE)) {
260 if (title !=
nullptr) {
264 default: title =
strecpy(title,
"(broken) ", last);
break;
274 bool LoadOldSaveGame(
const std::string &file)
278 DEBUG(oldloader, 3,
"Trying to load a TTD(Patch) savegame");
285 if (ls.file ==
nullptr) {
286 DEBUG(oldloader, 0,
"Cannot open file '%s'", file.c_str());
290 SavegameType type = DetermineOldSavegameType(ls.file,
nullptr,
nullptr);
292 LoadOldMainProc *proc =
nullptr;
295 case SGT_TTO: proc = &LoadTTOMain;
break;
296 case SGT_TTD: proc = &LoadTTDMain;
break;
304 game_loaded = proc !=
nullptr && proc(&ls);
320 void GetOldSaveGameName(
const std::string &file,
char *title,
const char *last)
329 DetermineOldSavegameType(f, title, last);