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);
GameSettings _settings_game
Game settings of a running game or the scenario editor.
static T ROL(const T x, const uint8 n)
ROtate x Left by n.
-//- TTO (default is neither of these)
chunk is valid ONLY for TTD savegames
TTD savegame (can be detected incorrectly)
#define lastof(x)
Get the last element of an fixed size array.
SavegameType
Types of save games.
static T SB(T &x, const uint8 s, const uint8 n, const U d)
Set n bits in x starting at bit s to d.
static bool VerifyOldNameChecksum(char *title, uint len)
Verifies the title has a valid checksum.
OldChunkType type
Type of field.
bool freeform_edges
allow terraforming the tiles at the map edges
static void InitLoading(LoadgameState *ls)
Initialize some data before reading.
void str_validate(char *str, const char *last, StringValidationSettings settings)
Scans the string for valid characters and if it finds invalid ones, replaces them with a question mar...
byte ReadByte(LoadgameState *ls)
Reads a byte from the buffer and decompress if needed.
FILE * FioFOpenFile(const char *filename, const char *mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
A path without any base directory.
SavegameType _savegame_type
type of savegame we are loading
void SetSaveLoadError(StringID str)
Set the error message from outside of the actual loading/saving of the game (AfterLoadGame and friend...
bool LoadChunk(LoadgameState *ls, void *base, const OldChunks *chunks)
Loads a chunk from the old savegame.
#define lengthof(x)
Return the length of an fixed size array.
PauseModeByte _pause_mode
The current pause mode.
Declarations of strctures and function used in loader of old savegames.
#define DEBUG(name, level,...)
Output a line of debugging information.
broken savegame (used internally)
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
End of the whole chunk, all 32 bits set to zero.
ConstructionSettings construction
construction of things in-game
Declaration of functions used in more save/load files.
static byte ReadByteFromFile(LoadgameState *ls)
Reads a byte from a file (do not call yourself, use ReadByte())
Dereference the pointer once before writing to it, so we do not have to use big static arrays...