12 #include "../stdafx.h"
14 #include "../strings_type.h"
15 #include "../string_func.h"
16 #include "../settings_type.h"
17 #include "../fileio_func.h"
19 #include "table/strings.h"
26 #include "../safeguards.h"
28 static const int TTO_HEADER_SIZE = 41;
29 static const int TTD_HEADER_SIZE = 49;
31 uint32 _bump_assert_value;
39 static const byte type_mem_size[] = {0, 1, 1, 2, 2, 4, 4, 8};
40 byte length =
GB(type, 8, 8);
41 assert(length != 0 && length <
lengthof(type_mem_size));
42 return type_mem_size[length];
54 if (ls->buffer_cur >= ls->buffer_count) {
57 int count = (int)fread(ls->buffer, 1, BUFFER_SIZE, ls->file);
61 DEBUG(oldloader, 0,
"Read past end of file, loading failed");
62 throw std::exception();
65 ls->buffer_count = count;
69 return ls->buffer[ls->buffer_cur++];
85 if (ls->chunk_size == 0) {
93 ls->chunk_size = -new_byte + 1;
96 ls->chunk_size = new_byte + 1;
113 byte *base_ptr = (byte*)base;
122 byte *ptr = (byte*)chunk->ptr;
125 for (uint i = 0; i < chunk->amount; i++) {
127 if (GetOldChunkType(chunk->type) != 0) {
128 switch (GetOldChunkType(chunk->type)) {
135 if (!chunk->proc(ls, i))
return false;
139 DEBUG(oldloader, 4,
"Assert point: 0x%X / 0x%X", ls->total_read, chunk->offset + _bump_assert_value);
140 if (ls->total_read != chunk->offset + _bump_assert_value)
throw std::exception();
147 switch (GetOldChunkFileType(chunk->type)) {
148 case OC_FILE_I8: res = (int8)
ReadByte(ls);
break;
149 case OC_FILE_U8: res =
ReadByte(ls);
break;
150 case OC_FILE_I16: res = (int16)ReadUint16(ls);
break;
151 case OC_FILE_U16: res = ReadUint16(ls);
break;
152 case OC_FILE_I32: res = (int32)ReadUint32(ls);
break;
153 case OC_FILE_U32: res = ReadUint32(ls);
break;
154 default: NOT_REACHED();
158 if (base_ptr == NULL && chunk->ptr == NULL)
continue;
161 if (chunk->ptr == NULL) ptr = base_ptr + chunk->offset;
164 switch (GetOldChunkVarType(chunk->type)) {
165 case OC_VAR_I8: *(int8 *)ptr =
GB(res, 0, 8);
break;
166 case OC_VAR_U8: *(uint8 *)ptr =
GB(res, 0, 8);
break;
167 case OC_VAR_I16:*(int16 *)ptr =
GB(res, 0, 16);
break;
168 case OC_VAR_U16:*(uint16*)ptr =
GB(res, 0, 16);
break;
169 case OC_VAR_I32:*(int32 *)ptr = res;
break;
170 case OC_VAR_U32:*(uint32*)ptr = res;
break;
171 case OC_VAR_I64:*(int64 *)ptr = res;
break;
172 case OC_VAR_U64:*(uint64*)ptr = res;
break;
173 default: NOT_REACHED();
177 if (chunk->amount > 1 && chunk->ptr != NULL) ptr += CalcOldVarLen(chunk->type);
195 ls->decoding =
false;
199 ls->buffer_count = 0;
200 memset(ls->buffer, 0, BUFFER_SIZE);
202 _bump_assert_value = 0;
217 for (uint i = 0; i < len - 2; i++) {
224 uint16 sum2 = title[len - 2];
225 SB(sum2, 8, 8, title[len - 1]);
230 static inline bool CheckOldSavegameType(FILE *f,
char *temp,
const char *last, uint len)
232 assert(last - temp + 1 >= (
int)len);
234 if (fread(temp, 1, len, f) != len) {
240 temp[len - 2] =
'\0';
246 static SavegameType DetermineOldSavegameType(FILE *f,
char *title,
const char *last)
248 assert_compile(TTD_HEADER_SIZE >= TTO_HEADER_SIZE);
249 char temp[TTD_HEADER_SIZE] =
"Unknown";
255 if (pos >= 0 && !CheckOldSavegameType(f, temp,
lastof(temp), TTO_HEADER_SIZE)) {
257 if (fseek(f, pos, SEEK_SET) < 0 || !CheckOldSavegameType(f, temp,
lastof(temp), TTD_HEADER_SIZE)) {
266 default: title =
strecpy(title,
"(broken) ", last);
break;
268 title =
strecpy(title, temp, last);
276 bool LoadOldSaveGame(
const char *file)
280 DEBUG(oldloader, 3,
"Trying to load a TTD(Patch) savegame");
287 if (ls.file == NULL) {
288 DEBUG(oldloader, 0,
"Cannot open file '%s'", file);
292 SavegameType type = DetermineOldSavegameType(ls.file, NULL, NULL);
294 LoadOldMainProc *proc = NULL;
297 case SGT_TTO: proc = &LoadTTOMain;
break;
298 case SGT_TTD: proc = &LoadTTDMain;
break;
306 game_loaded = proc != NULL && proc(&ls);
322 void GetOldSaveGameName(
const char *file,
char *title,
const char *last)
331 DetermineOldSavegameType(f, title, last);