41 |
41 |
42 uint32 _ttdp_version; ///< version of TTDP savegame (if applicable) |
42 uint32 _ttdp_version; ///< version of TTDP savegame (if applicable) |
43 uint16 _sl_version; ///< the major savegame version identifier |
43 uint16 _sl_version; ///< the major savegame version identifier |
44 byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! |
44 byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! |
45 |
45 |
46 typedef void WriterProc(uint len); |
46 typedef void WriterProc(size_t len); |
47 typedef uint ReaderProc(); |
47 typedef size_t ReaderProc(); |
48 |
48 |
49 /** The saveload struct, containing reader-writer functions, bufffer, version, etc. */ |
49 /** The saveload struct, containing reader-writer functions, bufffer, version, etc. */ |
50 static struct { |
50 static struct { |
51 bool save; ///< are we doing a save or a load atm. True when saving |
51 bool save; ///< are we doing a save or a load atm. True when saving |
52 byte need_length; ///< ??? |
52 byte need_length; ///< ??? |
53 byte block_mode; ///< ??? |
53 byte block_mode; ///< ??? |
54 bool error; ///< did an error occur or not |
54 bool error; ///< did an error occur or not |
55 |
55 |
56 int obj_len; ///< the length of the current object we are busy with |
56 size_t obj_len; ///< the length of the current object we are busy with |
57 int array_index, last_array_index; ///< in the case of an array, the current and last positions |
57 int array_index, last_array_index; ///< in the case of an array, the current and last positions |
58 |
58 |
59 uint32 offs_base; ///< the offset in number of bytes since we started writing data (eg uncompressed savegame size) |
59 size_t offs_base; ///< the offset in number of bytes since we started writing data (eg uncompressed savegame size) |
60 |
60 |
61 WriterProc *write_bytes; ///< savegame writer function |
61 WriterProc *write_bytes; ///< savegame writer function |
62 ReaderProc *read_bytes; ///< savegame loader function |
62 ReaderProc *read_bytes; ///< savegame loader function |
63 |
63 |
64 const ChunkHandler* const *chs; ///< the chunk of data that is being processed atm (vehicles, signs, etc.) |
64 const ChunkHandler* const *chs; ///< the chunk of data that is being processed atm (vehicles, signs, etc.) |
121 /** |
121 /** |
122 * Fill the input buffer by reading from the file with the given reader |
122 * Fill the input buffer by reading from the file with the given reader |
123 */ |
123 */ |
124 static void SlReadFill() |
124 static void SlReadFill() |
125 { |
125 { |
126 uint len = _sl.read_bytes(); |
126 size_t len = _sl.read_bytes(); |
127 if (len == 0) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unexpected end of chunk"); |
127 if (len == 0) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unexpected end of chunk"); |
128 |
128 |
129 _sl.bufp = _sl.buf; |
129 _sl.bufp = _sl.buf; |
130 _sl.bufe = _sl.buf + len; |
130 _sl.bufe = _sl.buf + len; |
131 _sl.offs_base += len; |
131 _sl.offs_base += len; |
132 } |
132 } |
133 |
133 |
134 static inline uint32 SlGetOffs() {return _sl.offs_base - (_sl.bufe - _sl.bufp);} |
134 static inline size_t SlGetOffs() {return _sl.offs_base - (_sl.bufe - _sl.bufp);} |
135 |
135 |
136 /** Return the size in bytes of a certain type of normal/atomic variable |
136 /** Return the size in bytes of a certain type of normal/atomic variable |
137 * as it appears in memory. See VarTypes |
137 * as it appears in memory. See VarTypes |
138 * @param conv VarType type of variable that is used for calculating the size |
138 * @param conv VarType type of variable that is used for calculating the size |
139 * @return Return the size of this type in bytes */ |
139 * @return Return the size of this type in bytes */ |
281 * 110xxxxx xxxxxxxx xxxxxxxx |
281 * 110xxxxx xxxxxxxx xxxxxxxx |
282 * 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx |
282 * 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx |
283 * @param i Index being written |
283 * @param i Index being written |
284 */ |
284 */ |
285 |
285 |
286 static void SlWriteSimpleGamma(uint i) |
286 static void SlWriteSimpleGamma(size_t i) |
287 { |
287 { |
288 if (i >= (1 << 7)) { |
288 if (i >= (1 << 7)) { |
289 if (i >= (1 << 14)) { |
289 if (i >= (1 << 14)) { |
290 if (i >= (1 << 21)) { |
290 if (i >= (1 << 21)) { |
291 assert(i < (1 << 28)); |
291 assert(i < (1 << 28)); |
292 SlWriteByte((byte)0xE0 | (i >> 24)); |
292 SlWriteByte((byte)(0xE0 | (i >> 24))); |
293 SlWriteByte((byte)(i >> 16)); |
293 SlWriteByte((byte)(i >> 16)); |
294 } else { |
294 } else { |
295 SlWriteByte((byte)0xC0 | (i >> 16)); |
295 SlWriteByte((byte)(0xC0 | (i >> 16))); |
296 } |
296 } |
297 SlWriteByte((byte)(i >> 8)); |
297 SlWriteByte((byte)(i >> 8)); |
298 } else { |
298 } else { |
299 SlWriteByte((byte)(0x80 | (i >> 8))); |
299 SlWriteByte((byte)(0x80 | (i >> 8))); |
300 } |
300 } |
301 } |
301 } |
302 SlWriteByte(i); |
302 SlWriteByte((byte)i); |
303 } |
303 } |
304 |
304 |
305 /** Return how many bytes used to encode a gamma value */ |
305 /** Return how many bytes used to encode a gamma value */ |
306 static inline uint SlGetGammaLength(uint i) |
306 static inline uint SlGetGammaLength(size_t i) |
307 { |
307 { |
308 return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21)); |
308 return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21)); |
309 } |
309 } |
310 |
310 |
311 static inline uint SlReadSparseIndex() {return SlReadSimpleGamma();} |
311 static inline uint SlReadSparseIndex() {return SlReadSimpleGamma();} |
312 static inline void SlWriteSparseIndex(uint index) {SlWriteSimpleGamma(index);} |
312 static inline void SlWriteSparseIndex(uint index) {SlWriteSimpleGamma(index);} |
313 |
313 |
314 static inline uint SlReadArrayLength() {return SlReadSimpleGamma();} |
314 static inline uint SlReadArrayLength() {return SlReadSimpleGamma();} |
315 static inline void SlWriteArrayLength(uint length) {SlWriteSimpleGamma(length);} |
315 static inline void SlWriteArrayLength(size_t length) {SlWriteSimpleGamma(length);} |
316 static inline uint SlGetArrayLength(uint length) {return SlGetGammaLength(length);} |
316 static inline uint SlGetArrayLength(size_t length) {return SlGetGammaLength(length);} |
317 |
317 |
318 void SlSetArrayIndex(uint index) |
318 void SlSetArrayIndex(uint index) |
319 { |
319 { |
320 _sl.need_length = NL_WANTLENGTH; |
320 _sl.need_length = NL_WANTLENGTH; |
321 _sl.array_index = index; |
321 _sl.array_index = index; |
322 } |
322 } |
323 |
323 |
324 static uint32 _next_offs; |
324 static size_t _next_offs; |
325 |
325 |
326 /** |
326 /** |
327 * Iterate through the elements of an array and read the whole thing |
327 * Iterate through the elements of an array and read the whole thing |
328 * @return The index of the object, or -1 if we have reached the end of current block |
328 * @return The index of the object, or -1 if we have reached the end of current block |
329 */ |
329 */ |
373 case CH_RIFF: |
373 case CH_RIFF: |
374 /* Ugly encoding of >16M RIFF chunks |
374 /* Ugly encoding of >16M RIFF chunks |
375 * The lower 24 bits are normal |
375 * The lower 24 bits are normal |
376 * The uppermost 4 bits are bits 24:27 */ |
376 * The uppermost 4 bits are bits 24:27 */ |
377 assert(length < (1 << 28)); |
377 assert(length < (1 << 28)); |
378 SlWriteUint32((length & 0xFFFFFF) | ((length >> 24) << 28)); |
378 SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28))); |
379 break; |
379 break; |
380 case CH_ARRAY: |
380 case CH_ARRAY: |
381 assert(_sl.last_array_index <= _sl.array_index); |
381 assert(_sl.last_array_index <= _sl.array_index); |
382 while (++_sl.last_array_index <= _sl.array_index) |
382 while (++_sl.last_array_index <= _sl.array_index) |
383 SlWriteArrayLength(1); |
383 SlWriteArrayLength(1); |
420 { |
420 { |
421 for (; length != 0; length--) SlReadByte(); |
421 for (; length != 0; length--) SlReadByte(); |
422 } |
422 } |
423 |
423 |
424 /* Get the length of the current object */ |
424 /* Get the length of the current object */ |
425 uint SlGetFieldLength() {return _sl.obj_len;} |
425 size_t SlGetFieldLength() {return _sl.obj_len;} |
426 |
426 |
427 /** Return a signed-long version of the value of a setting |
427 /** Return a signed-long version of the value of a setting |
428 * @param ptr pointer to the variable |
428 * @param ptr pointer to the variable |
429 * @param conv type of variable, can be a non-clean |
429 * @param conv type of variable, can be a non-clean |
430 * type, eg one with other flags because it is parsed |
430 * type, eg one with other flags because it is parsed |
626 /** |
626 /** |
627 * Return the size in bytes of a certain type of atomic array |
627 * Return the size in bytes of a certain type of atomic array |
628 * @param length The length of the array counted in elements |
628 * @param length The length of the array counted in elements |
629 * @param conv VarType type of the variable that is used in calculating the size |
629 * @param conv VarType type of the variable that is used in calculating the size |
630 */ |
630 */ |
631 static inline size_t SlCalcArrayLen(uint length, VarType conv) |
631 static inline size_t SlCalcArrayLen(size_t length, VarType conv) |
632 { |
632 { |
633 return SlCalcConvFileLen(conv) * length; |
633 return SlCalcConvFileLen(conv) * length; |
634 } |
634 } |
635 |
635 |
636 /** |
636 /** |
637 * Save/Load an array. |
637 * Save/Load an array. |
638 * @param array The array being manipulated |
638 * @param array The array being manipulated |
639 * @param length The length of the array in elements |
639 * @param length The length of the array in elements |
640 * @param conv VarType type of the atomic array (int, byte, uint64, etc.) |
640 * @param conv VarType type of the atomic array (int, byte, uint64, etc.) |
641 */ |
641 */ |
642 void SlArray(void *array, uint length, VarType conv) |
642 void SlArray(void *array, size_t length, VarType conv) |
643 { |
643 { |
644 /* Automatically calculate the length? */ |
644 /* Automatically calculate the length? */ |
645 if (_sl.need_length != NL_NONE) { |
645 if (_sl.need_length != NL_NONE) { |
646 SlSetLength(SlCalcArrayLen(length, conv)); |
646 SlSetLength(SlCalcArrayLen(length, conv)); |
647 /* Determine length only? */ |
647 /* Determine length only? */ |
882 * @param proc The callback procedure that is called |
882 * @param proc The callback procedure that is called |
883 * @param arg The variable that will be used for the callback procedure |
883 * @param arg The variable that will be used for the callback procedure |
884 */ |
884 */ |
885 void SlAutolength(AutolengthProc *proc, void *arg) |
885 void SlAutolength(AutolengthProc *proc, void *arg) |
886 { |
886 { |
887 uint32 offs; |
887 size_t offs; |
888 |
888 |
889 assert(_sl.save); |
889 assert(_sl.save); |
890 |
890 |
891 /* Tell it to calculate the length */ |
891 /* Tell it to calculate the length */ |
892 _sl.need_length = NL_CALCLENGTH; |
892 _sl.need_length = NL_CALCLENGTH; |
1083 return len; |
1083 return len; |
1084 } |
1084 } |
1085 |
1085 |
1086 /* p contains the pointer to the buffer, len contains the pointer to the length. |
1086 /* p contains the pointer to the buffer, len contains the pointer to the length. |
1087 * len bytes will be written, p and l will be updated to reflect the next buffer. */ |
1087 * len bytes will be written, p and l will be updated to reflect the next buffer. */ |
1088 static void WriteLZO(uint size) |
1088 static void WriteLZO(size_t size) |
1089 { |
1089 { |
1090 byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8]; |
1090 byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8]; |
1091 byte wrkmem[sizeof(byte*)*4096]; |
1091 byte wrkmem[sizeof(byte*)*4096]; |
1092 uint outlen; |
1092 uint outlen; |
1093 |
1093 |
1094 lzo1x_1_compress(_sl.buf, size, out + sizeof(uint32)*2, &outlen, wrkmem); |
1094 lzo1x_1_compress(_sl.buf, (lzo_uint)size, out + sizeof(uint32)*2, &outlen, wrkmem); |
1095 ((uint32*)out)[1] = TO_BE32(outlen); |
1095 ((uint32*)out)[1] = TO_BE32(outlen); |
1096 ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32))); |
1096 ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32))); |
1097 if (fwrite(out, outlen + sizeof(uint32)*2, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE); |
1097 if (fwrite(out, outlen + sizeof(uint32)*2, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE); |
1098 } |
1098 } |
1099 |
1099 |
1110 } |
1110 } |
1111 |
1111 |
1112 /********************************************* |
1112 /********************************************* |
1113 ******** START OF NOCOMP CODE (uncompressed)* |
1113 ******** START OF NOCOMP CODE (uncompressed)* |
1114 *********************************************/ |
1114 *********************************************/ |
1115 static uint ReadNoComp() |
1115 static size_t ReadNoComp() |
1116 { |
1116 { |
1117 return fread(_sl.buf, 1, LZO_SIZE, _sl.fh); |
1117 return fread(_sl.buf, 1, LZO_SIZE, _sl.fh); |
1118 } |
1118 } |
1119 |
1119 |
1120 static void WriteNoComp(uint size) |
1120 static void WriteNoComp(size_t size) |
1121 { |
1121 { |
1122 if (fwrite(_sl.buf, 1, size, _sl.fh) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE); |
1122 if (fwrite(_sl.buf, 1, size, _sl.fh) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE); |
1123 } |
1123 } |
1124 |
1124 |
1125 static bool InitNoComp() |
1125 static bool InitNoComp() |
1168 static void UnInitMem() |
1168 static void UnInitMem() |
1169 { |
1169 { |
1170 _Savegame_pool.CleanPool(); |
1170 _Savegame_pool.CleanPool(); |
1171 } |
1171 } |
1172 |
1172 |
1173 static void WriteMem(uint size) |
1173 static void WriteMem(size_t size) |
1174 { |
1174 { |
1175 _ts.count += size; |
1175 _ts.count += (uint)size; |
1176 /* Allocate new block and new buffer-pointer */ |
1176 /* Allocate new block and new buffer-pointer */ |
1177 _Savegame_pool.AddBlockIfNeeded(_ts.count); |
1177 _Savegame_pool.AddBlockIfNeeded(_ts.count); |
1178 _sl.buf = GetSavegame(_ts.count); |
1178 _sl.buf = GetSavegame(_ts.count); |
1179 } |
1179 } |
1180 |
1180 |
1235 _sl.bufsize = 4096; |
1235 _sl.bufsize = 4096; |
1236 _sl.buf = _sl.buf_ori = MallocT<byte>(4096); // also contains fread buffer |
1236 _sl.buf = _sl.buf_ori = MallocT<byte>(4096); // also contains fread buffer |
1237 return true; |
1237 return true; |
1238 } |
1238 } |
1239 |
1239 |
1240 static void WriteZlibLoop(z_streamp z, byte *p, uint len, int mode) |
1240 static void WriteZlibLoop(z_streamp z, byte *p, size_t len, int mode) |
1241 { |
1241 { |
1242 byte buf[1024]; // output buffer |
1242 byte buf[1024]; // output buffer |
1243 int r; |
1243 int r; |
1244 uint n; |
1244 uint n; |
1245 z->next_in = p; |
1245 z->next_in = p; |
1246 z->avail_in = len; |
1246 z->avail_in = (uInt)len; |
1247 do { |
1247 do { |
1248 z->next_out = buf; |
1248 z->next_out = buf; |
1249 z->avail_out = sizeof(buf); |
1249 z->avail_out = sizeof(buf); |
1250 r = deflate(z, mode); |
1250 r = deflate(z, mode); |
1251 /* bytes were emitted? */ |
1251 /* bytes were emitted? */ |
1256 break; |
1256 break; |
1257 if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code"); |
1257 if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code"); |
1258 } while (z->avail_in || !z->avail_out); |
1258 } while (z->avail_in || !z->avail_out); |
1259 } |
1259 } |
1260 |
1260 |
1261 static void WriteZlib(uint len) |
1261 static void WriteZlib(size_t len) |
1262 { |
1262 { |
1263 WriteZlibLoop(&_z, _sl.buf, len, 0); |
1263 WriteZlibLoop(&_z, _sl.buf, len, 0); |
1264 } |
1264 } |
1265 |
1265 |
1266 static void UninitWriteZlib() |
1266 static void UninitWriteZlib() |