29 #include "network/network.h" |
27 #include "network/network.h" |
30 #include "variables.h" |
28 #include "variables.h" |
31 #include <setjmp.h> |
29 #include <setjmp.h> |
32 |
30 |
33 extern const uint16 SAVEGAME_VERSION = 47; |
31 extern const uint16 SAVEGAME_VERSION = 47; |
34 uint16 _sl_version; /// the major savegame version identifier |
32 uint16 _sl_version; ///< the major savegame version identifier |
35 byte _sl_minor_version; /// the minor savegame version, DO NOT USE! |
33 byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! |
36 |
34 |
37 typedef void WriterProc(uint len); |
35 typedef void WriterProc(uint len); |
38 typedef uint ReaderProc(void); |
36 typedef uint ReaderProc(void); |
39 |
37 |
40 /** The saveload struct, containing reader-writer functions, bufffer, version, etc. */ |
38 /** The saveload struct, containing reader-writer functions, bufffer, version, etc. */ |
41 static struct { |
39 static struct { |
42 bool save; /// are we doing a save or a load atm. True when saving |
40 bool save; ///< are we doing a save or a load atm. True when saving |
43 byte need_length; /// ??? |
41 byte need_length; ///< ??? |
44 byte block_mode; /// ??? |
42 byte block_mode; ///< ??? |
45 bool error; /// did an error occur or not |
43 bool error; ///< did an error occur or not |
46 |
44 |
47 int obj_len; /// the length of the current object we are busy with |
45 int obj_len; ///< the length of the current object we are busy with |
48 int array_index, last_array_index; /// in the case of an array, the current and last positions |
46 int array_index, last_array_index; ///< in the case of an array, the current and last positions |
49 |
47 |
50 uint32 offs_base; /// the offset in number of bytes since we started writing data (eg uncompressed savegame size) |
48 uint32 offs_base; ///< the offset in number of bytes since we started writing data (eg uncompressed savegame size) |
51 |
49 |
52 WriterProc *write_bytes; /// savegame writer function |
50 WriterProc *write_bytes; ///< savegame writer function |
53 ReaderProc *read_bytes; /// savegame loader function |
51 ReaderProc *read_bytes; ///< savegame loader function |
54 |
52 |
55 const ChunkHandler* const *chs; /// the chunk of data that is being processed atm (vehicles, signs, etc.) |
53 const ChunkHandler* const *chs; ///< the chunk of data that is being processed atm (vehicles, signs, etc.) |
56 const SaveLoad* const *includes; /// the internal layouf of the given chunk |
54 const SaveLoad* const *includes; ///< the internal layouf of the given chunk |
57 |
55 |
58 /** When saving/loading savegames, they are always saved to a temporary memory-place |
56 /* When saving/loading savegames, they are always saved to a temporary memory-place |
59 * to be flushed to file (save) or to final place (load) when full. */ |
57 * to be flushed to file (save) or to final place (load) when full. */ |
60 byte *bufp, *bufe; /// bufp(ointer) gives the current position in the buffer bufe(nd) gives the end of the buffer |
58 byte *bufp, *bufe; ///< bufp(ointer) gives the current position in the buffer bufe(nd) gives the end of the buffer |
61 |
59 |
62 // these 3 may be used by compressor/decompressors. |
60 /* these 3 may be used by compressor/decompressors. */ |
63 byte *buf; /// pointer to temporary memory to read/write, initialized by SaveLoadFormat->initread/write |
61 byte *buf; ///< pointer to temporary memory to read/write, initialized by SaveLoadFormat->initread/write |
64 byte *buf_ori; /// pointer to the original memory location of buf, used to free it afterwards |
62 byte *buf_ori; ///< pointer to the original memory location of buf, used to free it afterwards |
65 uint bufsize; /// the size of the temporary memory *buf |
63 uint bufsize; ///< the size of the temporary memory *buf |
66 FILE *fh; /// the file from which is read or written to |
64 FILE *fh; ///< the file from which is read or written to |
67 |
65 |
68 void (*excpt_uninit)(void); /// the function to execute on any encountered error |
66 void (*excpt_uninit)(void); ///< the function to execute on any encountered error |
69 const char *excpt_msg; /// the error message |
67 const char *excpt_msg; ///< the error message |
70 jmp_buf excpt; /// @todo used to jump to "exception handler"; really ugly |
68 jmp_buf excpt; ///< @todo used to jump to "exception handler"; really ugly |
71 } _sl; |
69 } _sl; |
72 |
70 |
73 |
71 |
74 enum NeedLengthValues {NL_NONE = 0, NL_WANTLENGTH = 1, NL_CALCLENGTH = 2}; |
72 enum NeedLengthValues {NL_NONE = 0, NL_WANTLENGTH = 1, NL_CALCLENGTH = 2}; |
75 |
73 |
87 } |
85 } |
88 |
86 |
89 static inline uint32 SlGetOffs(void) {return _sl.offs_base - (_sl.bufe - _sl.bufp);} |
87 static inline uint32 SlGetOffs(void) {return _sl.offs_base - (_sl.bufe - _sl.bufp);} |
90 |
88 |
91 /** Return the size in bytes of a certain type of normal/atomic variable |
89 /** Return the size in bytes of a certain type of normal/atomic variable |
92 * as it appears in memory. @see VarTypes |
90 * as it appears in memory. See VarTypes |
93 * @param conv @VarType type of variable that is used for calculating the size |
91 * @param conv VarType type of variable that is used for calculating the size |
94 * @return Return the size of this type in bytes */ |
92 * @return Return the size of this type in bytes */ |
95 static inline byte SlCalcConvMemLen(VarType conv) |
93 static inline byte SlCalcConvMemLen(VarType conv) |
96 { |
94 { |
97 static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0}; |
95 static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0}; |
98 byte length = GB(conv, 4, 4); |
96 byte length = GB(conv, 4, 4); |
99 assert(length < lengthof(conv_mem_size)); |
97 assert(length < lengthof(conv_mem_size)); |
100 return conv_mem_size[length]; |
98 return conv_mem_size[length]; |
101 } |
99 } |
102 |
100 |
103 /** Return the size in bytes of a certain type of normal/atomic variable |
101 /** Return the size in bytes of a certain type of normal/atomic variable |
104 * as it appears in a saved game. @see VarTypes |
102 * as it appears in a saved game. See VarTypes |
105 * @param conv @VarType type of variable that is used for calculating the size |
103 * @param conv VarType type of variable that is used for calculating the size |
106 * @return Return the size of this type in bytes */ |
104 * @return Return the size of this type in bytes */ |
107 static inline byte SlCalcConvFileLen(VarType conv) |
105 static inline byte SlCalcConvFileLen(VarType conv) |
108 { |
106 { |
109 static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2}; |
107 static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2}; |
110 byte length = GB(conv, 0, 4); |
108 byte length = GB(conv, 0, 4); |
111 assert(length < lengthof(conv_file_size)); |
109 assert(length < lengthof(conv_file_size)); |
112 return conv_file_size[length]; |
110 return conv_file_size[length]; |
113 } |
111 } |
114 |
112 |
115 /* Return the size in bytes of a reference (pointer) */ |
113 /** Return the size in bytes of a reference (pointer) */ |
116 static inline size_t SlCalcRefLen(void) {return 2;} |
114 static inline size_t SlCalcRefLen(void) {return 2;} |
117 |
115 |
118 /** Flush the output buffer by writing to disk with the given reader. |
116 /** Flush the output buffer by writing to disk with the given reader. |
119 * If the buffer pointer has not yet been set up, set it up now. Usually |
117 * If the buffer pointer has not yet been set up, set it up now. Usually |
120 * only called when the buffer is full, or there is no more data to be processed |
118 * only called when the buffer is full, or there is no more data to be processed |
121 */ |
119 */ |
122 static void SlWriteFill(void) |
120 static void SlWriteFill(void) |
123 { |
121 { |
124 // flush the buffer to disk (the writer) |
122 /* flush the buffer to disk (the writer) */ |
125 if (_sl.bufp != NULL) { |
123 if (_sl.bufp != NULL) { |
126 uint len = _sl.bufp - _sl.buf; |
124 uint len = _sl.bufp - _sl.buf; |
127 _sl.offs_base += len; |
125 _sl.offs_base += len; |
128 if (len) _sl.write_bytes(len); |
126 if (len) _sl.write_bytes(len); |
129 } |
127 } |
130 |
128 |
131 /* All the data from the buffer has been written away, rewind to the beginning |
129 /* All the data from the buffer has been written away, rewind to the beginning |
132 * to start reading in more data */ |
130 * to start reading in more data */ |
133 _sl.bufp = _sl.buf; |
131 _sl.bufp = _sl.buf; |
134 _sl.bufe = _sl.buf + _sl.bufsize; |
132 _sl.bufe = _sl.buf + _sl.bufsize; |
135 } |
133 } |
136 |
134 |
137 /** Error handler, calls longjmp to simulate an exception. |
135 /** Error handler, calls longjmp to simulate an exception. |
437 * Handle all conversion and typechecking of variables here. |
435 * Handle all conversion and typechecking of variables here. |
438 * In the case of saving, read in the actual value from the struct |
436 * In the case of saving, read in the actual value from the struct |
439 * and then write them to file, endian safely. Loading a value |
437 * and then write them to file, endian safely. Loading a value |
440 * goes exactly the opposite way |
438 * goes exactly the opposite way |
441 * @param ptr The object being filled/read |
439 * @param ptr The object being filled/read |
442 * @param conv @VarType type of the current element of the struct |
440 * @param conv VarType type of the current element of the struct |
443 */ |
441 */ |
444 static void SlSaveLoadConv(void *ptr, VarType conv) |
442 static void SlSaveLoadConv(void *ptr, VarType conv) |
445 { |
443 { |
446 int64 x = 0; |
444 int64 x = 0; |
447 |
445 |
448 if (_sl.save) { /* SAVE values */ |
446 if (_sl.save) { // SAVE values |
449 /* Read a value from the struct. These ARE endian safe. */ |
447 /* Read a value from the struct. These ARE endian safe. */ |
450 x = ReadValue(ptr, conv); |
448 x = ReadValue(ptr, conv); |
451 |
449 |
452 /* Write the value to the file and check if its value is in the desired range */ |
450 /* Write the value to the file and check if its value is in the desired range */ |
453 switch (GetVarFileType(conv)) { |
451 switch (GetVarFileType(conv)) { |
579 } |
577 } |
580 |
578 |
581 /** |
579 /** |
582 * Return the size in bytes of a certain type of atomic array |
580 * Return the size in bytes of a certain type of atomic array |
583 * @param length The length of the array counted in elements |
581 * @param length The length of the array counted in elements |
584 * @param conv @VarType type of the variable that is used in calculating the size |
582 * @param conv VarType type of the variable that is used in calculating the size |
585 */ |
583 */ |
586 static inline size_t SlCalcArrayLen(uint length, VarType conv) |
584 static inline size_t SlCalcArrayLen(uint length, VarType conv) |
587 { |
585 { |
588 return SlCalcConvFileLen(conv) * length; |
586 return SlCalcConvFileLen(conv) * length; |
589 } |
587 } |
590 |
588 |
591 /** |
589 /** |
592 * Save/Load an array. |
590 * Save/Load an array. |
593 * @param array The array being manipulated |
591 * @param array The array being manipulated |
594 * @param length The length of the array in elements |
592 * @param length The length of the array in elements |
595 * @param conv @VarType type of the atomic array (int, byte, uint64, etc.) |
593 * @param conv VarType type of the atomic array (int, byte, uint64, etc.) |
596 */ |
594 */ |
597 void SlArray(void *array, uint length, VarType conv) |
595 void SlArray(void *array, uint length, VarType conv) |
598 { |
596 { |
599 // Automatically calculate the length? |
597 /* Automatically calculate the length? */ |
600 if (_sl.need_length != NL_NONE) { |
598 if (_sl.need_length != NL_NONE) { |
601 SlSetLength(SlCalcArrayLen(length, conv)); |
599 SlSetLength(SlCalcArrayLen(length, conv)); |
602 // Determine length only? |
600 /* Determine length only? */ |
603 if (_sl.need_length == NL_CALCLENGTH) return; |
601 if (_sl.need_length == NL_CALCLENGTH) return; |
604 } |
602 } |
605 |
603 |
606 /* NOTICE - handle some buggy stuff, in really old versions everything was saved |
604 /* NOTICE - handle some buggy stuff, in really old versions everything was saved |
607 * as a byte-type. So detect this, and adjust array size accordingly */ |
605 * as a byte-type. So detect this, and adjust array size accordingly */ |
709 if (!SlIsObjectValidInSavegame(sld)) return false; |
707 if (!SlIsObjectValidInSavegame(sld)) return false; |
710 if (SlSkipVariableOnLoad(sld)) return false; |
708 if (SlSkipVariableOnLoad(sld)) return false; |
711 |
709 |
712 switch (sld->cmd) { |
710 switch (sld->cmd) { |
713 case SL_VAR: SlSaveLoadConv(ptr, conv); break; |
711 case SL_VAR: SlSaveLoadConv(ptr, conv); break; |
714 case SL_REF: /* Reference variable, translate */ |
712 case SL_REF: // Reference variable, translate |
715 /// @todo XXX - another artificial limitof 65K elements of pointers? |
713 /* @todo XXX - another artificial limitof 65K elements of pointers? */ |
716 if (_sl.save) { // XXX - read/write pointer as uint16? What is with higher indeces? |
714 if (_sl.save) { // XXX - read/write pointer as uint16? What is with higher indeces? |
717 SlWriteUint16(ReferenceToInt(*(void**)ptr, (SLRefType)conv)); |
715 SlWriteUint16(ReferenceToInt(*(void**)ptr, (SLRefType)conv)); |
718 } else { |
716 } else { |
719 *(void**)ptr = IntToReference(SlReadUint16(), (SLRefType)conv); |
717 *(void**)ptr = IntToReference(SlReadUint16(), (SLRefType)conv); |
720 } |
718 } |
961 byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8]; |
959 byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8]; |
962 uint32 tmp[2]; |
960 uint32 tmp[2]; |
963 uint32 size; |
961 uint32 size; |
964 uint len; |
962 uint len; |
965 |
963 |
966 // Read header |
964 /* Read header*/ |
967 if (fread(tmp, sizeof(tmp), 1, _sl.fh) != 1) SlError("file read failed"); |
965 if (fread(tmp, sizeof(tmp), 1, _sl.fh) != 1) SlError("file read failed"); |
968 |
966 |
969 // Check if size is bad |
967 /* Check if size is bad */ |
970 ((uint32*)out)[0] = size = tmp[1]; |
968 ((uint32*)out)[0] = size = tmp[1]; |
971 |
969 |
972 if (_sl_version != 0) { |
970 if (_sl_version != 0) { |
973 tmp[0] = TO_BE32(tmp[0]); |
971 tmp[0] = TO_BE32(tmp[0]); |
974 size = TO_BE32(size); |
972 size = TO_BE32(size); |
975 } |
973 } |
976 |
974 |
977 if (size >= sizeof(out)) SlError("inconsistent size"); |
975 if (size >= sizeof(out)) SlError("inconsistent size"); |
978 |
976 |
979 // Read block |
977 /* Read block */ |
980 if (fread(out + sizeof(uint32), size, 1, _sl.fh) != 1) SlError("file read failed"); |
978 if (fread(out + sizeof(uint32), size, 1, _sl.fh) != 1) SlError("file read failed"); |
981 |
979 |
982 // Verify checksum |
980 /* Verify checksum */ |
983 if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlError("bad checksum"); |
981 if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlError("bad checksum"); |
984 |
982 |
985 // Decompress |
983 /* Decompress */ |
986 lzo1x_decompress(out + sizeof(uint32)*1, size, _sl.buf, &len, NULL); |
984 lzo1x_decompress(out + sizeof(uint32)*1, size, _sl.buf, &len, NULL); |
987 return len; |
985 return len; |
988 } |
986 } |
989 |
987 |
990 // p contains the pointer to the buffer, len contains the pointer to the length. |
988 /* p contains the pointer to the buffer, len contains the pointer to the length. |
991 // len bytes will be written, p and l will be updated to reflect the next buffer. |
989 * len bytes will be written, p and l will be updated to reflect the next buffer. */ |
992 static void WriteLZO(uint size) |
990 static void WriteLZO(uint size) |
993 { |
991 { |
994 byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8]; |
992 byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8]; |
995 byte wrkmem[sizeof(byte*)*4096]; |
993 byte wrkmem[sizeof(byte*)*4096]; |
996 uint outlen; |
994 uint outlen; |
1170 WriteZlibLoop(&_z, _sl.buf, len, 0); |
1168 WriteZlibLoop(&_z, _sl.buf, len, 0); |
1171 } |
1169 } |
1172 |
1170 |
1173 static void UninitWriteZlib(void) |
1171 static void UninitWriteZlib(void) |
1174 { |
1172 { |
1175 // flush any pending output. |
1173 /* flush any pending output. */ |
1176 if (_sl.fh) WriteZlibLoop(&_z, NULL, 0, Z_FINISH); |
1174 if (_sl.fh) WriteZlibLoop(&_z, NULL, 0, Z_FINISH); |
1177 deflateEnd(&_z); |
1175 deflateEnd(&_z); |
1178 free(_sl.buf_ori); |
1176 free(_sl.buf_ori); |
1179 } |
1177 } |
1180 |
1178 |
1181 #endif /* WITH_ZLIB */ |
1179 #endif /* WITH_ZLIB */ |
1182 |
1180 |
1183 //******************************************* |
1181 /******************************************* |
1184 //************* END OF CODE ***************** |
1182 ************* END OF CODE ***************** |
1185 //******************************************* |
1183 *******************************************/ |
1186 |
1184 |
1187 // these define the chunks |
1185 /* these define the chunks */ |
1188 extern const ChunkHandler _misc_chunk_handlers[]; |
1186 extern const ChunkHandler _misc_chunk_handlers[]; |
1189 extern const ChunkHandler _setting_chunk_handlers[]; |
1187 extern const ChunkHandler _setting_chunk_handlers[]; |
1190 extern const ChunkHandler _player_chunk_handlers[]; |
1188 extern const ChunkHandler _player_chunk_handlers[]; |
1191 extern const ChunkHandler _engine_chunk_handlers[]; |
1189 extern const ChunkHandler _engine_chunk_handlers[]; |
1192 extern const ChunkHandler _veh_chunk_handlers[]; |
1190 extern const ChunkHandler _veh_chunk_handlers[]; |
1231 * the index of the item, and if not available, it hussles with |
1229 * the index of the item, and if not available, it hussles with |
1232 * pointers (looks really bad :() |
1230 * pointers (looks really bad :() |
1233 * Remember that a NULL item has value 0, and all |
1231 * Remember that a NULL item has value 0, and all |
1234 * indeces have +1, so vehicle 0 is saved as index 1. |
1232 * indeces have +1, so vehicle 0 is saved as index 1. |
1235 * @param obj The object that we want to get the index of |
1233 * @param obj The object that we want to get the index of |
1236 * @param rt @SLRefType type of the object the index is being sought of |
1234 * @param rt SLRefType type of the object the index is being sought of |
1237 * @return Return the pointer converted to an index of the type pointed to |
1235 * @return Return the pointer converted to an index of the type pointed to |
1238 */ |
1236 */ |
1239 static uint ReferenceToInt(const void *obj, SLRefType rt) |
1237 static uint ReferenceToInt(const void *obj, SLRefType rt) |
1240 { |
1238 { |
1241 if (obj == NULL) return 0; |
1239 if (obj == NULL) return 0; |
1259 * gets the index from the savegame and returns the appropiate |
1257 * gets the index from the savegame and returns the appropiate |
1260 * pointer from the already loaded base. |
1258 * pointer from the already loaded base. |
1261 * Remember that an index of 0 is a NULL pointer so all indeces |
1259 * Remember that an index of 0 is a NULL pointer so all indeces |
1262 * are +1 so vehicle 0 is saved as 1. |
1260 * are +1 so vehicle 0 is saved as 1. |
1263 * @param index The index that is being converted to a pointer |
1261 * @param index The index that is being converted to a pointer |
1264 * @param rt @SLRefType type of the object the pointer is sought of |
1262 * @param rt SLRefType type of the object the pointer is sought of |
1265 * @return Return the index converted to a pointer of any type |
1263 * @return Return the index converted to a pointer of any type |
1266 */ |
1264 */ |
1267 static void *IntToReference(uint index, SLRefType rt) |
1265 static void *IntToReference(uint index, SLRefType rt) |
1268 { |
1266 { |
1269 /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE, |
1267 /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE, |
1327 return NULL; |
1325 return NULL; |
1328 } |
1326 } |
1329 |
1327 |
1330 /** The format for a reader/writer type of a savegame */ |
1328 /** The format for a reader/writer type of a savegame */ |
1331 typedef struct { |
1329 typedef struct { |
1332 const char *name; /// name of the compressor/decompressor (debug-only) |
1330 const char *name; ///< name of the compressor/decompressor (debug-only) |
1333 uint32 tag; /// the 4-letter tag by which it is identified in the savegame |
1331 uint32 tag; ///< the 4-letter tag by which it is identified in the savegame |
1334 |
1332 |
1335 bool (*init_read)(void); /// function executed upon initalization of the loader |
1333 bool (*init_read)(void); ///< function executed upon initalization of the loader |
1336 ReaderProc *reader; /// function that loads the data from the file |
1334 ReaderProc *reader; ///< function that loads the data from the file |
1337 void (*uninit_read)(void); /// function executed when reading is finished |
1335 void (*uninit_read)(void); ///< function executed when reading is finished |
1338 |
1336 |
1339 bool (*init_write)(void); /// function executed upon intialization of the saver |
1337 bool (*init_write)(void); ///< function executed upon intialization of the saver |
1340 WriterProc *writer; /// function that saves the data to the file |
1338 WriterProc *writer; ///< function that saves the data to the file |
1341 void (*uninit_write)(void); /// function executed when writing is done |
1339 void (*uninit_write)(void); ///< function executed when writing is done |
1342 } SaveLoadFormat; |
1340 } SaveLoadFormat; |
1343 |
1341 |
1344 static const SaveLoadFormat _saveload_formats[] = { |
1342 static const SaveLoadFormat _saveload_formats[] = { |
1345 {"memory", 0, NULL, NULL, NULL, InitMem, WriteMem, UnInitMem}, |
1343 {"memory", 0, NULL, NULL, NULL, InitMem, WriteMem, UnInitMem}, |
1346 {"lzo", TO_BE32X('OTTD'), InitLZO, ReadLZO, UninitLZO, InitLZO, WriteLZO, UninitLZO}, |
1344 {"lzo", TO_BE32X('OTTD'), InitLZO, ReadLZO, UninitLZO, InitLZO, WriteLZO, UninitLZO}, |
1354 |
1352 |
1355 /** |
1353 /** |
1356 * Return the savegameformat of the game. Whether it was create with ZLIB compression |
1354 * Return the savegameformat of the game. Whether it was create with ZLIB compression |
1357 * uncompressed, or another type |
1355 * uncompressed, or another type |
1358 * @param s Name of the savegame format. If NULL it picks the first available one |
1356 * @param s Name of the savegame format. If NULL it picks the first available one |
1359 * @return Pointer to @SaveLoadFormat struct giving all characteristics of this type of savegame |
1357 * @return Pointer to SaveLoadFormat struct giving all characteristics of this type of savegame |
1360 */ |
1358 */ |
1361 static const SaveLoadFormat *GetSavegameFormat(const char *s) |
1359 static const SaveLoadFormat *GetSavegameFormat(const char *s) |
1362 { |
1360 { |
1363 const SaveLoadFormat *def = endof(_saveload_formats) - 1; |
1361 const SaveLoadFormat *def = endof(_saveload_formats) - 1; |
1364 |
1362 |
1365 // find default savegame format, the highest one with which files can be written |
1363 /* find default savegame format, the highest one with which files can be written */ |
1366 while (!def->init_write) def--; |
1364 while (!def->init_write) def--; |
1367 |
1365 |
1368 if (s != NULL && s[0] != '\0') { |
1366 if (s != NULL && s[0] != '\0') { |
1369 const SaveLoadFormat *slf; |
1367 const SaveLoadFormat *slf; |
1370 for (slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) { |
1368 for (slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) { |
1588 if (fread(hdr, sizeof(hdr), 1, _sl.fh) != 1) { |
1586 if (fread(hdr, sizeof(hdr), 1, _sl.fh) != 1) { |
1589 DEBUG(sl, 0, "Cannot read savegame header, aborting"); |
1587 DEBUG(sl, 0, "Cannot read savegame header, aborting"); |
1590 return AbortSaveLoad(); |
1588 return AbortSaveLoad(); |
1591 } |
1589 } |
1592 |
1590 |
1593 // see if we have any loader for this type. |
1591 /* see if we have any loader for this type. */ |
1594 for (fmt = _saveload_formats; ; fmt++) { |
1592 for (fmt = _saveload_formats; ; fmt++) { |
1595 /* No loader found, treat as version 0 and use LZO format */ |
1593 /* No loader found, treat as version 0 and use LZO format */ |
1596 if (fmt == endof(_saveload_formats)) { |
1594 if (fmt == endof(_saveload_formats)) { |
1597 DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format"); |
1595 DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format"); |
1598 #if defined(WINCE) |
1596 #if defined(WINCE) |
1607 fmt = _saveload_formats + 1; // LZO |
1605 fmt = _saveload_formats + 1; // LZO |
1608 break; |
1606 break; |
1609 } |
1607 } |
1610 |
1608 |
1611 if (fmt->tag == hdr[0]) { |
1609 if (fmt->tag == hdr[0]) { |
1612 // check version number |
1610 /* check version number */ |
1613 _sl_version = TO_BE32(hdr[1]) >> 16; |
1611 _sl_version = TO_BE32(hdr[1]) >> 16; |
1614 /* Minor is not used anymore from version 18.0, but it is still needed |
1612 /* Minor is not used anymore from version 18.0, but it is still needed |
1615 * in versions before that (4 cases) which can't be removed easy. |
1613 * in versions before that (4 cases) which can't be removed easy. |
1616 * Therefor it is loaded, but never saved (or, it saves a 0 in any scenario). |
1614 * Therefor it is loaded, but never saved (or, it saves a 0 in any scenario). |
1617 * So never EVER use this minor version again. -- TrueLight -- 22-11-2005 */ |
1615 * So never EVER use this minor version again. -- TrueLight -- 22-11-2005 */ |
1618 _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF; |
1616 _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF; |
1619 |
1617 |
1620 DEBUG(sl, 1, "Loading savegame version %d", _sl_version); |
1618 DEBUG(sl, 1, "Loading savegame version %d", _sl_version); |
1621 |
1619 |
1622 /* Is the version higher than the current? */ |
1620 /* Is the version higher than the current? */ |
1684 f = fopen(file, "rb"); |
1682 f = fopen(file, "rb"); |
1685 if (fread(&hdr, sizeof(hdr), 1, f) != 1) { |
1683 if (fread(&hdr, sizeof(hdr), 1, f) != 1) { |
1686 DEBUG(sl, 0, "Savegame is obsolete or invalid format"); |
1684 DEBUG(sl, 0, "Savegame is obsolete or invalid format"); |
1687 mode = SL_LOAD; // don't try to get filename, just show name as it is written |
1685 mode = SL_LOAD; // don't try to get filename, just show name as it is written |
1688 } else { |
1686 } else { |
1689 // see if we have any loader for this type. |
1687 /* see if we have any loader for this type. */ |
1690 for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) { |
1688 for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) { |
1691 if (fmt->tag == hdr) { |
1689 if (fmt->tag == hdr) { |
1692 mode = SL_LOAD; // new type of savegame |
1690 mode = SL_LOAD; // new type of savegame |
1693 break; |
1691 break; |
1694 } |
1692 } |