src/saveload.cpp
changeset 10751 ebd94f2d6385
parent 10708 5f1e9cffcfa5
child 10770 c1e1fb4bd561
equal deleted inserted replaced
10749:b8ac8a8e27c4 10751:ebd94f2d6385
    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);
   388 			SlWriteSparseIndex(_sl.array_index);
   388 			SlWriteSparseIndex(_sl.array_index);
   389 			break;
   389 			break;
   390 		default: NOT_REACHED();
   390 		default: NOT_REACHED();
   391 		} break;
   391 		} break;
   392 	case NL_CALCLENGTH:
   392 	case NL_CALCLENGTH:
   393 		_sl.obj_len += length;
   393 		_sl.obj_len += (int)length;
   394 		break;
   394 		break;
   395 	}
   395 	}
   396 }
   396 }
   397 
   397 
   398 /**
   398 /**
   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? */
   708 	}
   708 	}
   709 
   709 
   710 	std::list<void *> *l = (std::list<void *> *) list;
   710 	std::list<void *> *l = (std::list<void *> *) list;
   711 
   711 
   712 	if (_sl.save) {
   712 	if (_sl.save) {
   713 		SlWriteUint32(l->size());
   713 		SlWriteUint32((uint32)l->size());
   714 
   714 
   715 		std::list<void *>::iterator iter;
   715 		std::list<void *>::iterator iter;
   716 		for (iter = l->begin(); iter != l->end(); ++iter) {
   716 		for (iter = l->begin(); iter != l->end(); ++iter) {
   717 			void *ptr = *iter;
   717 			void *ptr = *iter;
   718 			SlWriteUint32(ReferenceToInt(ptr, conv));
   718 			SlWriteUint32(ReferenceToInt(ptr, conv));
   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;
   910  * @param ch The chunkhandler that will be used for the operation
   910  * @param ch The chunkhandler that will be used for the operation
   911  */
   911  */
   912 static void SlLoadChunk(const ChunkHandler *ch)
   912 static void SlLoadChunk(const ChunkHandler *ch)
   913 {
   913 {
   914 	byte m = SlReadByte();
   914 	byte m = SlReadByte();
   915 	uint32 len;
   915 	size_t len;
   916 	uint32 endoffs;
   916 	size_t endoffs;
   917 
   917 
   918 	_sl.block_mode = m;
   918 	_sl.block_mode = m;
   919 	_sl.obj_len = 0;
   919 	_sl.obj_len = 0;
   920 
   920 
   921 	switch (m) {
   921 	switch (m) {
  1050  *******************************************/
  1050  *******************************************/
  1051 #define LZO_SIZE 8192
  1051 #define LZO_SIZE 8192
  1052 
  1052 
  1053 #include "minilzo.h"
  1053 #include "minilzo.h"
  1054 
  1054 
  1055 static uint ReadLZO()
  1055 static size_t ReadLZO()
  1056 {
  1056 {
  1057 	byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8];
  1057 	byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8];
  1058 	uint32 tmp[2];
  1058 	uint32 tmp[2];
  1059 	uint32 size;
  1059 	uint32 size;
  1060 	uint len;
  1060 	uint len;
  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 
  1195 	_sl.bufsize = 4096;
  1195 	_sl.bufsize = 4096;
  1196 	_sl.buf = _sl.buf_ori = MallocT<byte>(4096 + 4096); // also contains fread buffer
  1196 	_sl.buf = _sl.buf_ori = MallocT<byte>(4096 + 4096); // also contains fread buffer
  1197 	return true;
  1197 	return true;
  1198 }
  1198 }
  1199 
  1199 
  1200 static uint ReadZlib()
  1200 static size_t ReadZlib()
  1201 {
  1201 {
  1202 	int r;
  1202 	int r;
  1203 
  1203 
  1204 	_z.next_out = _sl.buf;
  1204 	_z.next_out = _sl.buf;
  1205 	_z.avail_out = 4096;
  1205 	_z.avail_out = 4096;
  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()