src/saveload.cpp
branchcustombridgeheads
changeset 5649 55c8267c933f
parent 5643 3778051e8095
child 5650 aefc131bf5ce
equal deleted inserted replaced
5648:1608018c5ff2 5649:55c8267c933f
       
     1 /* $Id$ */
       
     2 
       
     3 /** @file
       
     4  * All actions handling saving and loading goes on in this file. The general actions
       
     5  * are as follows for saving a game (loading is analogous):
       
     6  * <ol>
       
     7  * <li>initialize the writer by creating a temporary memory-buffer for it
       
     8  * <li>go through all to-be saved elements, each 'chunk' (ChunkHandler) prefixed by a label
       
     9  * <li>use their description array (SaveLoad) to know what elements to save and in what version
       
    10  *    of the game it was active (used when loading)
       
    11  * <li>write all data byte-by-byte to the temporary buffer so it is endian-safe
       
    12  * <li>when the buffer is full; flush it to the output (eg save to file) (_sl.buf, _sl.bufp, _sl.bufe)
       
    13  * <li>repeat this until everything is done, and flush any remaining output to file
       
    14  * </ol>
       
    15  * @see ChunkHandler
       
    16  * @see SaveLoad
       
    17  */
       
    18 #include "stdafx.h"
       
    19 #include "openttd.h"
       
    20 #include "debug.h"
       
    21 #include "functions.h"
       
    22 #include "hal.h"
       
    23 #include "vehicle.h"
       
    24 #include "station.h"
       
    25 #include "thread.h"
       
    26 #include "town.h"
       
    27 #include "player.h"
       
    28 #include "saveload.h"
       
    29 #include "network/network.h"
       
    30 #include "variables.h"
       
    31 #include <setjmp.h>
       
    32 
       
    33 const uint16 SAVEGAME_VERSION = 43;
       
    34 uint16 _sl_version;       /// the major savegame version identifier
       
    35 byte   _sl_minor_version; /// the minor savegame version, DO NOT USE!
       
    36 
       
    37 typedef void WriterProc(uint len);
       
    38 typedef uint ReaderProc(void);
       
    39 
       
    40 /** The saveload struct, containing reader-writer functions, bufffer, version, etc. */
       
    41 static struct {
       
    42 	bool save;                           /// are we doing a save or a load atm. True when saving
       
    43 	byte need_length;                    /// ???
       
    44 	byte block_mode;                     /// ???
       
    45 	bool error;                          /// did an error occur or not
       
    46 
       
    47 	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
       
    49 
       
    50 	uint32 offs_base;                    /// the offset in number of bytes since we started writing data (eg uncompressed savegame size)
       
    51 
       
    52 	WriterProc *write_bytes;             /// savegame writer function
       
    53 	ReaderProc *read_bytes;              /// savegame loader function
       
    54 
       
    55 	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
       
    57 
       
    58 	/** 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. */
       
    60 	byte *bufp, *bufe;                   /// bufp(ointer) gives the current position in the buffer bufe(nd) gives the end of the buffer
       
    61 
       
    62 	// these 3 may be used by compressor/decompressors.
       
    63 	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
       
    65 	uint bufsize;                        /// the size of the temporary memory *buf
       
    66 	FILE *fh;                            /// the file from which is read or written to
       
    67 
       
    68 	void (*excpt_uninit)(void);          /// the function to execute on any encountered error
       
    69 	const char *excpt_msg;               /// the error message
       
    70 	jmp_buf excpt;                       /// @todo used to jump to "exception handler";  really ugly
       
    71 } _sl;
       
    72 
       
    73 
       
    74 enum NeedLengthValues {NL_NONE = 0, NL_WANTLENGTH = 1, NL_CALCLENGTH = 2};
       
    75 
       
    76 /**
       
    77  * Fill the input buffer by reading from the file with the given reader
       
    78  */
       
    79 static void SlReadFill(void)
       
    80 {
       
    81 	uint len = _sl.read_bytes();
       
    82 	assert(len != 0);
       
    83 
       
    84 	_sl.bufp = _sl.buf;
       
    85 	_sl.bufe = _sl.buf + len;
       
    86 	_sl.offs_base += len;
       
    87 }
       
    88 
       
    89 static inline uint32 SlGetOffs(void) {return _sl.offs_base - (_sl.bufe - _sl.bufp);}
       
    90 
       
    91 /** Return the size in bytes of a certain type of normal/atomic variable
       
    92  * as it appears in memory. @see VarTypes
       
    93  * @param conv @VarType type of variable that is used for calculating the size
       
    94  * @return Return the size of this type in bytes */
       
    95 static inline byte SlCalcConvMemLen(VarType conv)
       
    96 {
       
    97 	static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
       
    98 	byte length = GB(conv, 4, 4);
       
    99 	assert(length < lengthof(conv_mem_size));
       
   100 	return conv_mem_size[length];
       
   101 }
       
   102 
       
   103 /** Return the size in bytes of a certain type of normal/atomic variable
       
   104  * as it appears in a saved game. @see VarTypes
       
   105  * @param conv @VarType type of variable that is used for calculating the size
       
   106  * @return Return the size of this type in bytes */
       
   107 static inline byte SlCalcConvFileLen(VarType conv)
       
   108 {
       
   109 	static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
       
   110 	byte length = GB(conv, 0, 4);
       
   111 	assert(length < lengthof(conv_file_size));
       
   112 	return conv_file_size[length];
       
   113 }
       
   114 
       
   115 /* Return the size in bytes of a reference (pointer) */
       
   116 static inline size_t SlCalcRefLen(void) {return 2;}
       
   117 
       
   118 /** 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
       
   120  * only called when the buffer is full, or there is no more data to be processed
       
   121  */
       
   122 static void SlWriteFill(void)
       
   123 {
       
   124 	// flush the buffer to disk (the writer)
       
   125 	if (_sl.bufp != NULL) {
       
   126 		uint len = _sl.bufp - _sl.buf;
       
   127 		_sl.offs_base += len;
       
   128 		if (len) _sl.write_bytes(len);
       
   129 	}
       
   130 
       
   131 	/* All the data from the buffer has been written away, rewind to the beginning
       
   132 	* to start reading in more data */
       
   133 	_sl.bufp = _sl.buf;
       
   134 	_sl.bufe = _sl.buf + _sl.bufsize;
       
   135 }
       
   136 
       
   137 /** Error handler, calls longjmp to simulate an exception.
       
   138  * @todo this was used to have a central place to handle errors, but it is
       
   139  * pretty ugly, and seriously interferes with any multithreaded approaches */
       
   140 static void NORETURN SlError(const char *msg)
       
   141 {
       
   142 	_sl.excpt_msg = msg;
       
   143 	longjmp(_sl.excpt, 0);
       
   144 }
       
   145 
       
   146 /** Read in a single byte from file. If the temporary buffer is full,
       
   147  * flush it to its final destination
       
   148  * @return return the read byte from file
       
   149  */
       
   150 static inline byte SlReadByteInternal(void)
       
   151 {
       
   152 	if (_sl.bufp == _sl.bufe) SlReadFill();
       
   153 	return *_sl.bufp++;
       
   154 }
       
   155 
       
   156 /** Wrapper for SlReadByteInternal */
       
   157 byte SlReadByte(void) {return SlReadByteInternal();}
       
   158 
       
   159 /** Write away a single byte from memory. If the temporary buffer is full,
       
   160  * flush it to its destination (file)
       
   161  * @param b the byte that is currently written
       
   162  */
       
   163 static inline void SlWriteByteInternal(byte b)
       
   164 {
       
   165 	if (_sl.bufp == _sl.bufe) SlWriteFill();
       
   166 	*_sl.bufp++ = b;
       
   167 }
       
   168 
       
   169 /** Wrapper for SlWriteByteInternal */
       
   170 void SlWriteByte(byte b) {SlWriteByteInternal(b);}
       
   171 
       
   172 static inline int SlReadUint16(void)
       
   173 {
       
   174 	int x = SlReadByte() << 8;
       
   175 	return x | SlReadByte();
       
   176 }
       
   177 
       
   178 static inline uint32 SlReadUint32(void)
       
   179 {
       
   180 	uint32 x = SlReadUint16() << 16;
       
   181 	return x | SlReadUint16();
       
   182 }
       
   183 
       
   184 static inline uint64 SlReadUint64(void)
       
   185 {
       
   186 	uint32 x = SlReadUint32();
       
   187 	uint32 y = SlReadUint32();
       
   188 	return (uint64)x << 32 | y;
       
   189 }
       
   190 
       
   191 static inline void SlWriteUint16(uint16 v)
       
   192 {
       
   193 	SlWriteByte(GB(v, 8, 8));
       
   194 	SlWriteByte(GB(v, 0, 8));
       
   195 }
       
   196 
       
   197 static inline void SlWriteUint32(uint32 v)
       
   198 {
       
   199 	SlWriteUint16(GB(v, 16, 16));
       
   200 	SlWriteUint16(GB(v,  0, 16));
       
   201 }
       
   202 
       
   203 static inline void SlWriteUint64(uint64 x)
       
   204 {
       
   205 	SlWriteUint32((uint32)(x >> 32));
       
   206 	SlWriteUint32((uint32)x);
       
   207 }
       
   208 
       
   209 /**
       
   210  * Read in the header descriptor of an object or an array.
       
   211  * If the highest bit is set (7), then the index is bigger than 127
       
   212  * elements, so use the next byte to read in the real value.
       
   213  * The actual value is then both bytes added with the first shifted
       
   214  * 8 bits to the left, and dropping the highest bit (which only indicated a big index).
       
   215  * x = ((x & 0x7F) << 8) + SlReadByte();
       
   216  * @return Return the value of the index
       
   217  */
       
   218 static uint SlReadSimpleGamma(void)
       
   219 {
       
   220 	uint i = SlReadByte();
       
   221 	if (HASBIT(i, 7)) {
       
   222 		i &= ~0x80;
       
   223 		if (HASBIT(i, 6)) {
       
   224 			i &= ~0x40;
       
   225 			if (HASBIT(i, 5)) {
       
   226 				i &= ~0x20;
       
   227 				if (HASBIT(i, 4))
       
   228 					SlError("Unsupported gamma");
       
   229 				i = (i << 8) | SlReadByte();
       
   230 			}
       
   231 			i = (i << 8) | SlReadByte();
       
   232 		}
       
   233 		i = (i << 8) | SlReadByte();
       
   234 	}
       
   235 	return i;
       
   236 }
       
   237 
       
   238 /**
       
   239  * Write the header descriptor of an object or an array.
       
   240  * If the element is bigger than 127, use 2 bytes for saving
       
   241  * and use the highest byte of the first written one as a notice
       
   242  * that the length consists of 2 bytes, etc.. like this:
       
   243  * 0xxxxxxx
       
   244  * 10xxxxxx xxxxxxxx
       
   245  * 110xxxxx xxxxxxxx xxxxxxxx
       
   246  * 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx
       
   247  * @param i Index being written
       
   248  */
       
   249 
       
   250 static void SlWriteSimpleGamma(uint i)
       
   251 {
       
   252 	if (i >= (1 << 7)) {
       
   253 		if (i >= (1 << 14)) {
       
   254 			if (i >= (1 << 21)) {
       
   255 				assert(i < (1 << 28));
       
   256 				SlWriteByte((byte)0xE0 | (i>>24));
       
   257 				SlWriteByte((byte)(i>>16));
       
   258 			} else {
       
   259 				SlWriteByte((byte)0xC0 | (i>>16));
       
   260 			}
       
   261 			SlWriteByte((byte)(i>>8));
       
   262 		} else {
       
   263 			SlWriteByte((byte)(0x80 | (i>>8)));
       
   264 		}
       
   265 	}
       
   266 	SlWriteByte(i);
       
   267 }
       
   268 
       
   269 /** Return how many bytes used to encode a gamma value */
       
   270 static inline uint SlGetGammaLength(uint i) {
       
   271 	return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21));
       
   272 }
       
   273 
       
   274 static inline uint SlReadSparseIndex(void) {return SlReadSimpleGamma();}
       
   275 static inline void SlWriteSparseIndex(uint index) {SlWriteSimpleGamma(index);}
       
   276 
       
   277 static inline uint SlReadArrayLength(void) {return SlReadSimpleGamma();}
       
   278 static inline void SlWriteArrayLength(uint length) {SlWriteSimpleGamma(length);}
       
   279 static inline uint SlGetArrayLength(uint length) {return SlGetGammaLength(length);}
       
   280 
       
   281 void SlSetArrayIndex(uint index)
       
   282 {
       
   283 	_sl.need_length = NL_WANTLENGTH;
       
   284 	_sl.array_index = index;
       
   285 }
       
   286 
       
   287 /**
       
   288  * Iterate through the elements of an array and read the whole thing
       
   289  * @return The index of the object, or -1 if we have reached the end of current block
       
   290  */
       
   291 int SlIterateArray(void)
       
   292 {
       
   293 	int index;
       
   294 	static uint32 next_offs;
       
   295 
       
   296 	/* After reading in the whole array inside the loop
       
   297 	 * we must have read in all the data, so we must be at end of current block. */
       
   298 	assert(next_offs == 0 || SlGetOffs() == next_offs);
       
   299 
       
   300 	while (true) {
       
   301 		uint length = SlReadArrayLength();
       
   302 		if (length == 0) {
       
   303 			next_offs = 0;
       
   304 			return -1;
       
   305 		}
       
   306 
       
   307 		_sl.obj_len = --length;
       
   308 		next_offs = SlGetOffs() + length;
       
   309 
       
   310 		switch (_sl.block_mode) {
       
   311 		case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
       
   312 		case CH_ARRAY:        index = _sl.array_index++; break;
       
   313 		default:
       
   314 			DEBUG(sl, 0, "SlIterateArray error");
       
   315 			return -1; // error
       
   316 		}
       
   317 
       
   318 		if (length != 0) return index;
       
   319 	}
       
   320 }
       
   321 
       
   322 /**
       
   323  * Sets the length of either a RIFF object or the number of items in an array.
       
   324  * This lets us load an object or an array of arbitrary size
       
   325  * @param length The length of the sought object/array
       
   326  */
       
   327 void SlSetLength(size_t length)
       
   328 {
       
   329 	assert(_sl.save);
       
   330 
       
   331 	switch (_sl.need_length) {
       
   332 	case NL_WANTLENGTH:
       
   333 		_sl.need_length = NL_NONE;
       
   334 		switch (_sl.block_mode) {
       
   335 		case CH_RIFF:
       
   336 			// Ugly encoding of >16M RIFF chunks
       
   337 			// The lower 24 bits are normal
       
   338 			// The uppermost 4 bits are bits 24:27
       
   339 			assert(length < (1<<28));
       
   340 			SlWriteUint32((length & 0xFFFFFF) | ((length >> 24) << 28));
       
   341 			break;
       
   342 		case CH_ARRAY:
       
   343 			assert(_sl.last_array_index <= _sl.array_index);
       
   344 			while (++_sl.last_array_index <= _sl.array_index)
       
   345 				SlWriteArrayLength(1);
       
   346 			SlWriteArrayLength(length + 1);
       
   347 			break;
       
   348 		case CH_SPARSE_ARRAY:
       
   349 			SlWriteArrayLength(length + 1 + SlGetArrayLength(_sl.array_index)); // Also include length of sparse index.
       
   350 			SlWriteSparseIndex(_sl.array_index);
       
   351 			break;
       
   352 		default: NOT_REACHED();
       
   353 		} break;
       
   354 	case NL_CALCLENGTH:
       
   355 		_sl.obj_len += length;
       
   356 		break;
       
   357 	}
       
   358 }
       
   359 
       
   360 /**
       
   361  * Save/Load bytes. These do not need to be converted to Little/Big Endian
       
   362  * so directly write them or read them to/from file
       
   363  * @param ptr The source or destination of the object being manipulated
       
   364  * @param length number of bytes this fast CopyBytes lasts
       
   365  */
       
   366 static void SlCopyBytes(void *ptr, size_t length)
       
   367 {
       
   368 	byte *p = (byte*)ptr;
       
   369 
       
   370 	if (_sl.save) {
       
   371 		for (; length != 0; length--) {SlWriteByteInternal(*p++);}
       
   372 	} else {
       
   373 		for (; length != 0; length--) {*p++ = SlReadByteInternal();}
       
   374 	}
       
   375 }
       
   376 
       
   377 /** Read in bytes from the file/data structure but don't do
       
   378  * anything with them, discarding them in effect
       
   379  * @param length The amount of bytes that is being treated this way
       
   380  */
       
   381 static inline void SlSkipBytes(size_t length)
       
   382 {
       
   383 	for (; length != 0; length--) SlReadByte();
       
   384 }
       
   385 
       
   386 /* Get the length of the current object */
       
   387 uint SlGetFieldLength(void) {return _sl.obj_len;}
       
   388 
       
   389 /** Return a signed-long version of the value of a setting
       
   390  * @param ptr pointer to the variable
       
   391  * @param conv type of variable, can be a non-clean
       
   392  * type, eg one with other flags because it is parsed
       
   393  * @return returns the value of the pointer-setting */
       
   394 int64 ReadValue(const void *ptr, VarType conv)
       
   395 {
       
   396 	switch (GetVarMemType(conv)) {
       
   397 	case SLE_VAR_BL:  return (*(bool*)ptr != 0);
       
   398 	case SLE_VAR_I8:  return *(int8*  )ptr;
       
   399 	case SLE_VAR_U8:  return *(byte*  )ptr;
       
   400 	case SLE_VAR_I16: return *(int16* )ptr;
       
   401 	case SLE_VAR_U16: return *(uint16*)ptr;
       
   402 	case SLE_VAR_I32: return *(int32* )ptr;
       
   403 	case SLE_VAR_U32: return *(uint32*)ptr;
       
   404 	case SLE_VAR_I64: return *(int64* )ptr;
       
   405 	case SLE_VAR_U64: return *(uint64*)ptr;
       
   406 	case SLE_VAR_NULL:return 0;
       
   407 	default: NOT_REACHED();
       
   408 	}
       
   409 
       
   410 	/* useless, but avoids compiler warning this way */
       
   411 	return 0;
       
   412 }
       
   413 
       
   414 /** Write the value of a setting
       
   415  * @param ptr pointer to the variable
       
   416  * @param conv type of variable, can be a non-clean type, eg
       
   417  * with other flags. It is parsed upon read
       
   418  * @param var the new value being given to the variable */
       
   419 void WriteValue(void *ptr, VarType conv, int64 val)
       
   420 {
       
   421 	switch (GetVarMemType(conv)) {
       
   422 	case SLE_VAR_BL:  *(bool  *)ptr = (val != 0);  break;
       
   423 	case SLE_VAR_I8:  *(int8  *)ptr = val; break;
       
   424 	case SLE_VAR_U8:  *(byte  *)ptr = val; break;
       
   425 	case SLE_VAR_I16: *(int16 *)ptr = val; break;
       
   426 	case SLE_VAR_U16: *(uint16*)ptr = val; break;
       
   427 	case SLE_VAR_I32: *(int32 *)ptr = val; break;
       
   428 	case SLE_VAR_U32: *(uint32*)ptr = val; break;
       
   429 	case SLE_VAR_I64: *(int64 *)ptr = val; break;
       
   430 	case SLE_VAR_U64: *(uint64*)ptr = val; break;
       
   431 	case SLE_VAR_NULL: break;
       
   432 	default: NOT_REACHED();
       
   433 	}
       
   434 }
       
   435 
       
   436 /**
       
   437  * Handle all conversion and typechecking of variables here.
       
   438  * 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
       
   440  * goes exactly the opposite way
       
   441  * @param ptr The object being filled/read
       
   442  * @param conv @VarType type of the current element of the struct
       
   443  */
       
   444 static void SlSaveLoadConv(void *ptr, VarType conv)
       
   445 {
       
   446 	int64 x = 0;
       
   447 
       
   448 	if (_sl.save) { /* SAVE values */
       
   449 		/* Read a value from the struct. These ARE endian safe. */
       
   450 		x = ReadValue(ptr, conv);
       
   451 
       
   452 		/* Write the value to the file and check if its value is in the desired range */
       
   453 		switch (GetVarFileType(conv)) {
       
   454 		case SLE_FILE_I8: assert(x >= -128 && x <= 127);     SlWriteByte(x);break;
       
   455 		case SLE_FILE_U8: assert(x >= 0 && x <= 255);        SlWriteByte(x);break;
       
   456 		case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break;
       
   457 		case SLE_FILE_STRINGID:
       
   458 		case SLE_FILE_U16:assert(x >= 0 && x <= 65535);      SlWriteUint16(x);break;
       
   459 		case SLE_FILE_I32:
       
   460 		case SLE_FILE_U32:                                   SlWriteUint32((uint32)x);break;
       
   461 		case SLE_FILE_I64:
       
   462 		case SLE_FILE_U64:                                   SlWriteUint64(x);break;
       
   463 		default: NOT_REACHED();
       
   464 		}
       
   465 	} else { /* LOAD values */
       
   466 
       
   467 		/* Read a value from the file */
       
   468 		switch (GetVarFileType(conv)) {
       
   469 		case SLE_FILE_I8:  x = (int8  )SlReadByte();   break;
       
   470 		case SLE_FILE_U8:  x = (byte  )SlReadByte();   break;
       
   471 		case SLE_FILE_I16: x = (int16 )SlReadUint16(); break;
       
   472 		case SLE_FILE_U16: x = (uint16)SlReadUint16(); break;
       
   473 		case SLE_FILE_I32: x = (int32 )SlReadUint32(); break;
       
   474 		case SLE_FILE_U32: x = (uint32)SlReadUint32(); break;
       
   475 		case SLE_FILE_I64: x = (int64 )SlReadUint64(); break;
       
   476 		case SLE_FILE_U64: x = (uint64)SlReadUint64(); break;
       
   477 		case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break;
       
   478 		default: NOT_REACHED();
       
   479 		}
       
   480 
       
   481 		/* Write The value to the struct. These ARE endian safe. */
       
   482 		WriteValue(ptr, conv, x);
       
   483 	}
       
   484 }
       
   485 
       
   486 /** Calculate the net length of a string. This is in almost all cases
       
   487  * just strlen(), but if the string is not properly terminated, we'll
       
   488  * resort to the maximum length of the buffer.
       
   489  * @param ptr pointer to the stringbuffer
       
   490  * @param length maximum length of the string (buffer). If -1 we don't care
       
   491  * about a maximum length, but take string length as it is.
       
   492  * @return return the net length of the string */
       
   493 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
       
   494 {
       
   495 	return minu(strlen(ptr), length - 1);
       
   496 }
       
   497 
       
   498 /** Calculate the gross length of the string that it
       
   499  * will occupy in the savegame. This includes the real length, returned
       
   500  * by SlCalcNetStringLen and the length that the index will occupy.
       
   501  * @param ptr pointer to the stringbuffer
       
   502  * @param length maximum length of the string (buffer size, etc.)
       
   503  * @return return the gross length of the string */
       
   504 static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
       
   505 {
       
   506 	size_t len;
       
   507 	const char *str;
       
   508 
       
   509 	switch (GetVarMemType(conv)) {
       
   510 		default: NOT_REACHED();
       
   511 		case SLE_VAR_STR:
       
   512 		case SLE_VAR_STRQ:
       
   513 			str = *(const char**)ptr;
       
   514 			len = -1;
       
   515 			break;
       
   516 		case SLE_VAR_STRB:
       
   517 		case SLE_VAR_STRBQ:
       
   518 			str = (const char*)ptr;
       
   519 			len = length;
       
   520 			break;
       
   521 	}
       
   522 
       
   523 	len = SlCalcNetStringLen(str, len);
       
   524 	return len + SlGetArrayLength(len); // also include the length of the index
       
   525 }
       
   526 
       
   527 /**
       
   528  * Save/Load a string.
       
   529  * @param ptr the string being manipulated
       
   530  * @param the length of the string (full length)
       
   531  * @param conv must be SLE_FILE_STRING */
       
   532 static void SlString(void *ptr, size_t length, VarType conv)
       
   533 {
       
   534 	size_t len;
       
   535 
       
   536 	if (_sl.save) { /* SAVE string */
       
   537 		switch (GetVarMemType(conv)) {
       
   538 			default: NOT_REACHED();
       
   539 			case SLE_VAR_STRB:
       
   540 			case SLE_VAR_STRBQ:
       
   541 				len = SlCalcNetStringLen(ptr, length);
       
   542 				break;
       
   543 			case SLE_VAR_STR:
       
   544 			case SLE_VAR_STRQ:
       
   545 				ptr = *(char**)ptr;
       
   546 				len = SlCalcNetStringLen(ptr, -1);
       
   547 				break;
       
   548 		}
       
   549 
       
   550 		SlWriteArrayLength(len);
       
   551 		SlCopyBytes(ptr, len);
       
   552 	} else { /* LOAD string */
       
   553 		len = SlReadArrayLength();
       
   554 
       
   555 		switch (GetVarMemType(conv)) {
       
   556 			default: NOT_REACHED();
       
   557 			case SLE_VAR_STRB:
       
   558 			case SLE_VAR_STRBQ:
       
   559 				if (len >= length) {
       
   560 					DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
       
   561 					SlCopyBytes(ptr, length);
       
   562 					SlSkipBytes(len - length);
       
   563 					len = length - 1;
       
   564 				} else {
       
   565 					SlCopyBytes(ptr, len);
       
   566 				}
       
   567 				break;
       
   568 			case SLE_VAR_STR:
       
   569 			case SLE_VAR_STRQ: /* Malloc'd string, free previous incarnation, and allocate */
       
   570 				free(*(char**)ptr);
       
   571 				*(char**)ptr = malloc(len + 1); // terminating '\0'
       
   572 				ptr = *(char**)ptr;
       
   573 				SlCopyBytes(ptr, len);
       
   574 				break;
       
   575 		}
       
   576 
       
   577 		((char*)ptr)[len] = '\0'; // properly terminate the string
       
   578 	}
       
   579 }
       
   580 
       
   581 /**
       
   582  * Return the size in bytes of a certain type of atomic array
       
   583  * @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
       
   585  */
       
   586 static inline size_t SlCalcArrayLen(uint length, VarType conv)
       
   587 {
       
   588 	return SlCalcConvFileLen(conv) * length;
       
   589 }
       
   590 
       
   591 /**
       
   592  * Save/Load an array.
       
   593  * @param array The array being manipulated
       
   594  * @param length The length of the array in elements
       
   595  * @param conv @VarType type of the atomic array (int, byte, uint64, etc.)
       
   596  */
       
   597 void SlArray(void *array, uint length, VarType conv)
       
   598 {
       
   599 	// Automatically calculate the length?
       
   600 	if (_sl.need_length != NL_NONE) {
       
   601 		SlSetLength(SlCalcArrayLen(length, conv));
       
   602 		// Determine length only?
       
   603 		if (_sl.need_length == NL_CALCLENGTH) return;
       
   604 	}
       
   605 
       
   606 	/* 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 */
       
   608 	if (!_sl.save && _sl_version == 0) {
       
   609 		if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
       
   610 				conv == SLE_INT32 || conv == SLE_UINT32) {
       
   611 			length *= SlCalcConvFileLen(conv);
       
   612 			conv = SLE_INT8;
       
   613 		}
       
   614 	}
       
   615 
       
   616 	/* If the size of elements is 1 byte both in file and memory, no special
       
   617 	 * conversion is needed, use specialized copy-copy function to speed up things */
       
   618 	if (conv == SLE_INT8 || conv == SLE_UINT8) {
       
   619 		SlCopyBytes(array, length);
       
   620 	} else {
       
   621 		byte *a = (byte*)array;
       
   622 		byte mem_size = SlCalcConvMemLen(conv);
       
   623 
       
   624 		for (; length != 0; length --) {
       
   625 			SlSaveLoadConv(a, conv);
       
   626 			a += mem_size; // get size
       
   627 		}
       
   628 	}
       
   629 }
       
   630 
       
   631 /* Are we going to save this object or not? */
       
   632 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
       
   633 {
       
   634 	if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
       
   635 	if (sld->conv & SLF_SAVE_NO) return false;
       
   636 
       
   637 	return true;
       
   638 }
       
   639 
       
   640 /** Are we going to load this variable when loading a savegame or not?
       
   641  * @note If the variable is skipped it is skipped in the savegame
       
   642  * bytestream itself as well, so there is no need to skip it somewhere else */
       
   643 static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
       
   644 {
       
   645 	if ((sld->conv & SLF_NETWORK_NO) && !_sl.save && _networking && !_network_server) {
       
   646 		SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
       
   647 		return true;
       
   648 	}
       
   649 
       
   650 	return false;
       
   651 }
       
   652 
       
   653 /**
       
   654  * Calculate the size of an object.
       
   655  * @param sld The @SaveLoad description of the object so we know how to manipulate it
       
   656  */
       
   657 static size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
       
   658 {
       
   659 	size_t length = 0;
       
   660 
       
   661 	// Need to determine the length and write a length tag.
       
   662 	for (; sld->cmd != SL_END; sld++) {
       
   663 		length += SlCalcObjMemberLength(object, sld);
       
   664 	}
       
   665 	return length;
       
   666 }
       
   667 
       
   668 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
       
   669 {
       
   670 	assert(_sl.save);
       
   671 
       
   672 	switch (sld->cmd) {
       
   673 		case SL_VAR:
       
   674 		case SL_REF:
       
   675 		case SL_ARR:
       
   676 		case SL_STR:
       
   677 			/* CONDITIONAL saveload types depend on the savegame version */
       
   678 			if (!SlIsObjectValidInSavegame(sld)) break;
       
   679 
       
   680 			switch (sld->cmd) {
       
   681 			case SL_VAR: return SlCalcConvFileLen(sld->conv);
       
   682 			case SL_REF: return SlCalcRefLen();
       
   683 			case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
       
   684 			case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
       
   685 			default: NOT_REACHED();
       
   686 			}
       
   687 			break;
       
   688 		case SL_WRITEBYTE: return 1; // a byte is logically of size 1
       
   689 		case SL_INCLUDE: return SlCalcObjLength(object, _sl.includes[sld->version_from]);
       
   690 		default: NOT_REACHED();
       
   691 	}
       
   692 	return 0;
       
   693 }
       
   694 
       
   695 
       
   696 static uint ReferenceToInt(const void* obj, SLRefType rt);
       
   697 static void* IntToReference(uint index, SLRefType rt);
       
   698 
       
   699 
       
   700 bool SlObjectMember(void *ptr, const SaveLoad *sld)
       
   701 {
       
   702 	VarType conv = GB(sld->conv, 0, 8);
       
   703 	switch (sld->cmd) {
       
   704 	case SL_VAR:
       
   705 	case SL_REF:
       
   706 	case SL_ARR:
       
   707 	case SL_STR:
       
   708 		/* CONDITIONAL saveload types depend on the savegame version */
       
   709 		if (!SlIsObjectValidInSavegame(sld)) return false;
       
   710 		if (SlSkipVariableOnLoad(sld)) return false;
       
   711 
       
   712 		switch (sld->cmd) {
       
   713 		case SL_VAR: SlSaveLoadConv(ptr, conv); break;
       
   714 		case SL_REF: /* Reference variable, translate */
       
   715 			/// @todo XXX - another artificial limitof 65K elements of pointers?
       
   716 			if (_sl.save) { // XXX - read/write pointer as uint16? What is with higher indeces?
       
   717 				SlWriteUint16(ReferenceToInt(*(void**)ptr, conv));
       
   718 			} else {
       
   719 				*(void**)ptr = IntToReference(SlReadUint16(), conv);
       
   720 			}
       
   721 			break;
       
   722 		case SL_ARR: SlArray(ptr, sld->length, conv); break;
       
   723 		case SL_STR: SlString(ptr, sld->length, conv); break;
       
   724 		default: NOT_REACHED();
       
   725 		}
       
   726 		break;
       
   727 
       
   728 	/* SL_WRITEBYTE translates a value of a variable to another one upon
       
   729    * saving or loading.
       
   730    * XXX - variable renaming abuse
       
   731    * game_value: the value of the variable ingame is abused by sld->version_from
       
   732    * file_value: the value of the variable in the savegame is abused by sld->version_to */
       
   733 	case SL_WRITEBYTE:
       
   734 		if (_sl.save) {
       
   735 			SlWriteByte(sld->version_to);
       
   736 		} else {
       
   737 			*(byte*)ptr = sld->version_from;
       
   738 		}
       
   739 		break;
       
   740 
       
   741 	/* SL_INCLUDE loads common code for a type
       
   742 	 * XXX - variable renaming abuse
       
   743 	 * include_index: common code to include from _desc_includes[], abused by sld->version_from */
       
   744 	case SL_INCLUDE:
       
   745 		SlObject(ptr, _sl.includes[sld->version_from]);
       
   746 		break;
       
   747 	default: NOT_REACHED();
       
   748 	}
       
   749 	return true;
       
   750 }
       
   751 
       
   752 /**
       
   753  * Main SaveLoad function.
       
   754  * @param object The object that is being saved or loaded
       
   755  * @param sld The @SaveLoad description of the object so we know how to manipulate it
       
   756  */
       
   757 void SlObject(void *object, const SaveLoad *sld)
       
   758 {
       
   759 	// Automatically calculate the length?
       
   760 	if (_sl.need_length != NL_NONE) {
       
   761 		SlSetLength(SlCalcObjLength(object, sld));
       
   762 		if (_sl.need_length == NL_CALCLENGTH) return;
       
   763 	}
       
   764 
       
   765 	for (; sld->cmd != SL_END; sld++) {
       
   766 		void *ptr = GetVariableAddress(object, sld);
       
   767 		SlObjectMember(ptr, sld);
       
   768 	}
       
   769 }
       
   770 
       
   771 /**
       
   772  * Save or Load (a list of) global variables
       
   773  * @param desc The global variable that is being loaded or saved
       
   774  */
       
   775 void SlGlobList(const SaveLoadGlobVarList *sldg)
       
   776 {
       
   777 	if (_sl.need_length != NL_NONE) {
       
   778 		SlSetLength(SlCalcObjLength(NULL, (const SaveLoad*)sldg));
       
   779 		if (_sl.need_length == NL_CALCLENGTH) return;
       
   780 	}
       
   781 
       
   782 	for (; sldg->cmd != SL_END; sldg++) {
       
   783 		SlObjectMember(sldg->address, (const SaveLoad*)sldg);
       
   784 	}
       
   785 }
       
   786 
       
   787 /**
       
   788  * Do something of which I have no idea what it is :P
       
   789  * @param proc The callback procedure that is called
       
   790  * @param arg The variable that will be used for the callback procedure
       
   791  */
       
   792 void SlAutolength(AutolengthProc *proc, void *arg)
       
   793 {
       
   794 	uint32 offs;
       
   795 
       
   796 	assert(_sl.save);
       
   797 
       
   798 	// Tell it to calculate the length
       
   799 	_sl.need_length = NL_CALCLENGTH;
       
   800 	_sl.obj_len = 0;
       
   801 	proc(arg);
       
   802 
       
   803 	// Setup length
       
   804 	_sl.need_length = NL_WANTLENGTH;
       
   805 	SlSetLength(_sl.obj_len);
       
   806 
       
   807 	offs = SlGetOffs() + _sl.obj_len;
       
   808 
       
   809 	// And write the stuff
       
   810 	proc(arg);
       
   811 
       
   812 	assert(offs == SlGetOffs());
       
   813 }
       
   814 
       
   815 /**
       
   816  * Load a chunk of data (eg vehicles, stations, etc.)
       
   817  * @param ch The chunkhandler that will be used for the operation
       
   818  */
       
   819 static void SlLoadChunk(const ChunkHandler *ch)
       
   820 {
       
   821 	byte m = SlReadByte();
       
   822 	size_t len;
       
   823 	uint32 endoffs;
       
   824 
       
   825 	_sl.block_mode = m;
       
   826 	_sl.obj_len = 0;
       
   827 
       
   828 	switch (m) {
       
   829 	case CH_ARRAY:
       
   830 		_sl.array_index = 0;
       
   831 		ch->load_proc();
       
   832 		break;
       
   833 	case CH_SPARSE_ARRAY:
       
   834 		ch->load_proc();
       
   835 		break;
       
   836 	default:
       
   837 		if ((m & 0xF) == CH_RIFF) {
       
   838 			// Read length
       
   839 			len = (SlReadByte() << 16) | ((m >> 4) << 24);
       
   840 			len += SlReadUint16();
       
   841 			_sl.obj_len = len;
       
   842 			endoffs = SlGetOffs() + len;
       
   843 			ch->load_proc();
       
   844 			assert(SlGetOffs() == endoffs);
       
   845 		} else {
       
   846 			SlError("Invalid chunk type");
       
   847 		}
       
   848 		break;
       
   849 	}
       
   850 }
       
   851 
       
   852 /* Stub Chunk handlers to only calculate length and do nothing else */
       
   853 static ChunkSaveLoadProc *_tmp_proc_1;
       
   854 static inline void SlStubSaveProc2(void *arg) {_tmp_proc_1();}
       
   855 static void SlStubSaveProc(void) {SlAutolength(SlStubSaveProc2, NULL);}
       
   856 
       
   857 /** Save a chunk of data (eg. vehicles, stations, etc.). Each chunk is
       
   858  * prefixed by an ID identifying it, followed by data, and terminator where appropiate
       
   859  * @param ch The chunkhandler that will be used for the operation
       
   860  */
       
   861 static void SlSaveChunk(const ChunkHandler *ch)
       
   862 {
       
   863 	ChunkSaveLoadProc *proc = ch->save_proc;
       
   864 
       
   865 	SlWriteUint32(ch->id);
       
   866 	DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
       
   867 
       
   868 	if (ch->flags & CH_AUTO_LENGTH) {
       
   869 		// Need to calculate the length. Solve that by calling SlAutoLength in the save_proc.
       
   870 		_tmp_proc_1 = proc;
       
   871 		proc = SlStubSaveProc;
       
   872 	}
       
   873 
       
   874 	_sl.block_mode = ch->flags & CH_TYPE_MASK;
       
   875 	switch (ch->flags & CH_TYPE_MASK) {
       
   876 	case CH_RIFF:
       
   877 		_sl.need_length = NL_WANTLENGTH;
       
   878 		proc();
       
   879 		break;
       
   880 	case CH_ARRAY:
       
   881 		_sl.last_array_index = 0;
       
   882 		SlWriteByte(CH_ARRAY);
       
   883 		proc();
       
   884 		SlWriteArrayLength(0); // Terminate arrays
       
   885 		break;
       
   886 	case CH_SPARSE_ARRAY:
       
   887 		SlWriteByte(CH_SPARSE_ARRAY);
       
   888 		proc();
       
   889 		SlWriteArrayLength(0); // Terminate arrays
       
   890 		break;
       
   891 	default: NOT_REACHED();
       
   892 	}
       
   893 }
       
   894 
       
   895 /** Save all chunks */
       
   896 static void SlSaveChunks(void)
       
   897 {
       
   898 	const ChunkHandler *ch;
       
   899 	const ChunkHandler* const *chsc;
       
   900 	uint p;
       
   901 
       
   902 	for (p = 0; p != CH_NUM_PRI_LEVELS; p++) {
       
   903 		for (chsc = _sl.chs; (ch = *chsc++) != NULL;) {
       
   904 			while (true) {
       
   905 				if (((ch->flags >> CH_PRI_SHL) & (CH_NUM_PRI_LEVELS - 1)) == p)
       
   906 					SlSaveChunk(ch);
       
   907 				if (ch->flags & CH_LAST)
       
   908 					break;
       
   909 				ch++;
       
   910 			}
       
   911 		}
       
   912 	}
       
   913 
       
   914 	// Terminator
       
   915 	SlWriteUint32(0);
       
   916 }
       
   917 
       
   918 /** Find the ChunkHandler that will be used for processing the found
       
   919  * chunk in the savegame or in memory
       
   920  * @param id the chunk in question
       
   921  * @return returns the appropiate chunkhandler
       
   922  */
       
   923 static const ChunkHandler *SlFindChunkHandler(uint32 id)
       
   924 {
       
   925 	const ChunkHandler *ch;
       
   926 	const ChunkHandler *const *chsc;
       
   927 	for (chsc = _sl.chs; (ch=*chsc++) != NULL;) {
       
   928 		for (;;) {
       
   929 			if (ch->id == id) return ch;
       
   930 			if (ch->flags & CH_LAST) break;
       
   931 			ch++;
       
   932 		}
       
   933 	}
       
   934 	return NULL;
       
   935 }
       
   936 
       
   937 /** Load all chunks */
       
   938 static void SlLoadChunks(void)
       
   939 {
       
   940 	uint32 id;
       
   941 	const ChunkHandler *ch;
       
   942 
       
   943 	for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
       
   944 		DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
       
   945 
       
   946 		ch = SlFindChunkHandler(id);
       
   947 		if (ch == NULL) SlError("found unknown tag in savegame (sync error)");
       
   948 		SlLoadChunk(ch);
       
   949 	}
       
   950 }
       
   951 
       
   952 //*******************************************
       
   953 //********** START OF LZO CODE **************
       
   954 //*******************************************
       
   955 #define LZO_SIZE 8192
       
   956 
       
   957 #include "minilzo.h"
       
   958 
       
   959 static uint ReadLZO(void)
       
   960 {
       
   961 	byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8];
       
   962 	uint32 tmp[2];
       
   963 	uint32 size;
       
   964 	uint len;
       
   965 
       
   966 	// Read header
       
   967 	if (fread(tmp, sizeof(tmp), 1, _sl.fh) != 1) SlError("file read failed");
       
   968 
       
   969 	// Check if size is bad
       
   970 	((uint32*)out)[0] = size = tmp[1];
       
   971 
       
   972 	if (_sl_version != 0) {
       
   973 		tmp[0] = TO_BE32(tmp[0]);
       
   974 		size = TO_BE32(size);
       
   975 	}
       
   976 
       
   977 	if (size >= sizeof(out)) SlError("inconsistent size");
       
   978 
       
   979 	// Read block
       
   980 	if (fread(out + sizeof(uint32), size, 1, _sl.fh) != 1) SlError("file read failed");
       
   981 
       
   982 	// Verify checksum
       
   983 	if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlError("bad checksum");
       
   984 
       
   985 	// Decompress
       
   986 	lzo1x_decompress(out + sizeof(uint32)*1, size, _sl.buf, &len, NULL);
       
   987 	return len;
       
   988 }
       
   989 
       
   990 // 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.
       
   992 static void WriteLZO(uint size)
       
   993 {
       
   994 	byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8];
       
   995 	byte wrkmem[sizeof(byte*)*4096];
       
   996 	uint outlen;
       
   997 
       
   998 	lzo1x_1_compress(_sl.buf, size, out + sizeof(uint32)*2, &outlen, wrkmem);
       
   999 	((uint32*)out)[1] = TO_BE32(outlen);
       
  1000 	((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
       
  1001 	if (fwrite(out, outlen + sizeof(uint32)*2, 1, _sl.fh) != 1) SlError("file write failed");
       
  1002 }
       
  1003 
       
  1004 static bool InitLZO(void)
       
  1005 {
       
  1006 	_sl.bufsize = LZO_SIZE;
       
  1007 	_sl.buf = _sl.buf_ori = (byte*)malloc(LZO_SIZE);
       
  1008 	return true;
       
  1009 }
       
  1010 
       
  1011 static void UninitLZO(void)
       
  1012 {
       
  1013 	free(_sl.buf_ori);
       
  1014 }
       
  1015 
       
  1016 //*********************************************
       
  1017 //******** START OF NOCOMP CODE (uncompressed)*
       
  1018 //*********************************************
       
  1019 static uint ReadNoComp(void)
       
  1020 {
       
  1021 	return fread(_sl.buf, 1, LZO_SIZE, _sl.fh);
       
  1022 }
       
  1023 
       
  1024 static void WriteNoComp(uint size)
       
  1025 {
       
  1026 	fwrite(_sl.buf, 1, size, _sl.fh);
       
  1027 }
       
  1028 
       
  1029 static bool InitNoComp(void)
       
  1030 {
       
  1031 	_sl.bufsize = LZO_SIZE;
       
  1032 	_sl.buf = _sl.buf_ori =(byte*)malloc(LZO_SIZE);
       
  1033 	return true;
       
  1034 }
       
  1035 
       
  1036 static void UninitNoComp(void)
       
  1037 {
       
  1038 	free(_sl.buf_ori);
       
  1039 }
       
  1040 
       
  1041 //********************************************
       
  1042 //********** START OF MEMORY CODE (in ram)****
       
  1043 //********************************************
       
  1044 
       
  1045 #include "table/strings.h"
       
  1046 #include "table/sprites.h"
       
  1047 #include "gfx.h"
       
  1048 #include "gui.h"
       
  1049 
       
  1050 typedef struct ThreadedSave {
       
  1051 	uint count;
       
  1052 	bool ff_state;
       
  1053 	bool saveinprogress;
       
  1054 	CursorID cursor;
       
  1055 } ThreadedSave;
       
  1056 
       
  1057 /* A maximum size of of 128K * 500 = 64.000KB savegames */
       
  1058 STATIC_OLD_POOL(Savegame, byte, 17, 500, NULL, NULL)
       
  1059 static ThreadedSave _ts;
       
  1060 
       
  1061 static bool InitMem(void)
       
  1062 {
       
  1063 	_ts.count = 0;
       
  1064 
       
  1065 	CleanPool(&_Savegame_pool);
       
  1066 	AddBlockToPool(&_Savegame_pool);
       
  1067 
       
  1068 	/* A block from the pool is a contigious area of memory, so it is safe to write to it sequentially */
       
  1069 	_sl.bufsize = GetSavegamePoolSize();
       
  1070 	_sl.buf = GetSavegame(_ts.count);
       
  1071 	return true;
       
  1072 }
       
  1073 
       
  1074 static void UnInitMem(void)
       
  1075 {
       
  1076 	CleanPool(&_Savegame_pool);
       
  1077 }
       
  1078 
       
  1079 static void WriteMem(uint size)
       
  1080 {
       
  1081 	_ts.count += size;
       
  1082 	/* Allocate new block and new buffer-pointer */
       
  1083 	AddBlockIfNeeded(&_Savegame_pool, _ts.count);
       
  1084 	_sl.buf = GetSavegame(_ts.count);
       
  1085 }
       
  1086 
       
  1087 //********************************************
       
  1088 //********** START OF ZLIB CODE **************
       
  1089 //********************************************
       
  1090 
       
  1091 #if defined(WITH_ZLIB)
       
  1092 #include <zlib.h>
       
  1093 
       
  1094 static z_stream _z;
       
  1095 
       
  1096 static bool InitReadZlib(void)
       
  1097 {
       
  1098 	memset(&_z, 0, sizeof(_z));
       
  1099 	if (inflateInit(&_z) != Z_OK) return false;
       
  1100 
       
  1101 	_sl.bufsize = 4096;
       
  1102 	_sl.buf = _sl.buf_ori = (byte*)malloc(4096 + 4096); // also contains fread buffer
       
  1103 	return true;
       
  1104 }
       
  1105 
       
  1106 static uint ReadZlib(void)
       
  1107 {
       
  1108 	int r;
       
  1109 
       
  1110 	_z.next_out = _sl.buf;
       
  1111 	_z.avail_out = 4096;
       
  1112 
       
  1113 	do {
       
  1114 		// read more bytes from the file?
       
  1115 		if (_z.avail_in == 0) {
       
  1116 			_z.avail_in = fread(_z.next_in = _sl.buf + 4096, 1, 4096, _sl.fh);
       
  1117 		}
       
  1118 
       
  1119 		// inflate the data
       
  1120 		r = inflate(&_z, 0);
       
  1121 		if (r == Z_STREAM_END)
       
  1122 			break;
       
  1123 
       
  1124 		if (r != Z_OK)
       
  1125 			SlError("inflate() failed");
       
  1126 	} while (_z.avail_out);
       
  1127 
       
  1128 	return 4096 - _z.avail_out;
       
  1129 }
       
  1130 
       
  1131 static void UninitReadZlib(void)
       
  1132 {
       
  1133 	inflateEnd(&_z);
       
  1134 	free(_sl.buf_ori);
       
  1135 }
       
  1136 
       
  1137 static bool InitWriteZlib(void)
       
  1138 {
       
  1139 	memset(&_z, 0, sizeof(_z));
       
  1140 	if (deflateInit(&_z, 6) != Z_OK) return false;
       
  1141 
       
  1142 	_sl.bufsize = 4096;
       
  1143 	_sl.buf = _sl.buf_ori = (byte*)malloc(4096); // also contains fread buffer
       
  1144 	return true;
       
  1145 }
       
  1146 
       
  1147 static void WriteZlibLoop(z_streamp z, byte *p, uint len, int mode)
       
  1148 {
       
  1149 	byte buf[1024]; // output buffer
       
  1150 	int r;
       
  1151 	uint n;
       
  1152 	z->next_in = p;
       
  1153 	z->avail_in = len;
       
  1154 	do {
       
  1155 		z->next_out = buf;
       
  1156 		z->avail_out = sizeof(buf);
       
  1157 		r = deflate(z, mode);
       
  1158 			// bytes were emitted?
       
  1159 		if ((n=sizeof(buf) - z->avail_out) != 0) {
       
  1160 			if (fwrite(buf, n, 1, _sl.fh) != 1) SlError("file write error");
       
  1161 		}
       
  1162 		if (r == Z_STREAM_END)
       
  1163 			break;
       
  1164 		if (r != Z_OK) SlError("zlib returned error code");
       
  1165 	} while (z->avail_in || !z->avail_out);
       
  1166 }
       
  1167 
       
  1168 static void WriteZlib(uint len)
       
  1169 {
       
  1170 	WriteZlibLoop(&_z, _sl.buf, len, 0);
       
  1171 }
       
  1172 
       
  1173 static void UninitWriteZlib(void)
       
  1174 {
       
  1175 	// flush any pending output.
       
  1176 	if (_sl.fh) WriteZlibLoop(&_z, NULL, 0, Z_FINISH);
       
  1177 	deflateEnd(&_z);
       
  1178 	free(_sl.buf_ori);
       
  1179 }
       
  1180 
       
  1181 #endif /* WITH_ZLIB */
       
  1182 
       
  1183 //*******************************************
       
  1184 //************* END OF CODE *****************
       
  1185 //*******************************************
       
  1186 
       
  1187 // these define the chunks
       
  1188 extern const ChunkHandler _misc_chunk_handlers[];
       
  1189 extern const ChunkHandler _setting_chunk_handlers[];
       
  1190 extern const ChunkHandler _player_chunk_handlers[];
       
  1191 extern const ChunkHandler _engine_chunk_handlers[];
       
  1192 extern const ChunkHandler _veh_chunk_handlers[];
       
  1193 extern const ChunkHandler _waypoint_chunk_handlers[];
       
  1194 extern const ChunkHandler _depot_chunk_handlers[];
       
  1195 extern const ChunkHandler _order_chunk_handlers[];
       
  1196 extern const ChunkHandler _town_chunk_handlers[];
       
  1197 extern const ChunkHandler _sign_chunk_handlers[];
       
  1198 extern const ChunkHandler _station_chunk_handlers[];
       
  1199 extern const ChunkHandler _industry_chunk_handlers[];
       
  1200 extern const ChunkHandler _economy_chunk_handlers[];
       
  1201 extern const ChunkHandler _animated_tile_chunk_handlers[];
       
  1202 extern const ChunkHandler _newgrf_chunk_handlers[];
       
  1203 
       
  1204 static const ChunkHandler * const _chunk_handlers[] = {
       
  1205 	_misc_chunk_handlers,
       
  1206 	_setting_chunk_handlers,
       
  1207 	_veh_chunk_handlers,
       
  1208 	_waypoint_chunk_handlers,
       
  1209 	_depot_chunk_handlers,
       
  1210 	_order_chunk_handlers,
       
  1211 	_industry_chunk_handlers,
       
  1212 	_economy_chunk_handlers,
       
  1213 	_engine_chunk_handlers,
       
  1214 	_town_chunk_handlers,
       
  1215 	_sign_chunk_handlers,
       
  1216 	_station_chunk_handlers,
       
  1217 	_player_chunk_handlers,
       
  1218 	_animated_tile_chunk_handlers,
       
  1219 	_newgrf_chunk_handlers,
       
  1220 	NULL,
       
  1221 };
       
  1222 
       
  1223 // used to include a vehicle desc in another desc.
       
  1224 extern const SaveLoad _common_veh_desc[];
       
  1225 static const SaveLoad* const _desc_includes[] = {
       
  1226 	_common_veh_desc
       
  1227 };
       
  1228 
       
  1229 /**
       
  1230  * Pointers cannot be saved to a savegame, so this functions gets
       
  1231  * the index of the item, and if not available, it hussles with
       
  1232  * pointers (looks really bad :()
       
  1233  * Remember that a NULL item has value 0, and all
       
  1234  * indeces have +1, so vehicle 0 is saved as index 1.
       
  1235  * @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
       
  1237  * @return Return the pointer converted to an index of the type pointed to
       
  1238  */
       
  1239 static uint ReferenceToInt(const void *obj, SLRefType rt)
       
  1240 {
       
  1241 	if (obj == NULL) return 0;
       
  1242 
       
  1243 	switch (rt) {
       
  1244 		case REF_VEHICLE_OLD: // Old vehicles we save as new onces
       
  1245 		case REF_VEHICLE:   return ((const  Vehicle*)obj)->index + 1;
       
  1246 		case REF_STATION:   return ((const  Station*)obj)->index + 1;
       
  1247 		case REF_TOWN:      return ((const     Town*)obj)->index + 1;
       
  1248 		case REF_ORDER:     return ((const    Order*)obj)->index + 1;
       
  1249 		case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
       
  1250 		case REF_ENGINE_RENEWS: return ((const EngineRenew*)obj)->index + 1;
       
  1251 		default: NOT_REACHED();
       
  1252 	}
       
  1253 
       
  1254 	return 0; // avoid compiler warning
       
  1255 }
       
  1256 
       
  1257 /**
       
  1258  * Pointers cannot be loaded from a savegame, so this function
       
  1259  * gets the index from the savegame and returns the appropiate
       
  1260  * pointer from the already loaded base.
       
  1261  * Remember that an index of 0 is a NULL pointer so all indeces
       
  1262  * are +1 so vehicle 0 is saved as 1.
       
  1263  * @param index The index that is being converted to a pointer
       
  1264  * @param rt @SLRefType type of the object the pointer is sought of
       
  1265  * @return Return the index converted to a pointer of any type
       
  1266  */
       
  1267 static void *IntToReference(uint index, SLRefType rt)
       
  1268 {
       
  1269 	/* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE,
       
  1270 	 * and should be loaded like that */
       
  1271 	if (rt == REF_VEHICLE_OLD && !CheckSavegameVersionOldStyle(4, 4))
       
  1272 		rt = REF_VEHICLE;
       
  1273 
       
  1274 	/* No need to look up NULL pointers, just return immediately */
       
  1275 	if (rt != REF_VEHICLE_OLD && index == 0)
       
  1276 		return NULL;
       
  1277 
       
  1278 	index--; // correct for the NULL index
       
  1279 
       
  1280 	switch (rt) {
       
  1281 		case REF_ORDER: {
       
  1282 			if (!AddBlockIfNeeded(&_Order_pool, index))
       
  1283 				error("Orders: failed loading savegame: too many orders");
       
  1284 			return GetOrder(index);
       
  1285 		}
       
  1286 		case REF_VEHICLE: {
       
  1287 			if (!AddBlockIfNeeded(&_Vehicle_pool, index))
       
  1288 				error("Vehicles: failed loading savegame: too many vehicles");
       
  1289 			return GetVehicle(index);
       
  1290 		}
       
  1291 		case REF_STATION: {
       
  1292 			if (!AddBlockIfNeeded(&_Station_pool, index))
       
  1293 				error("Stations: failed loading savegame: too many stations");
       
  1294 			return GetStation(index);
       
  1295 		}
       
  1296 		case REF_TOWN: {
       
  1297 			if (!AddBlockIfNeeded(&_Town_pool, index))
       
  1298 				error("Towns: failed loading savegame: too many towns");
       
  1299 			return GetTown(index);
       
  1300 		}
       
  1301 		case REF_ROADSTOPS: {
       
  1302 			if (!AddBlockIfNeeded(&_RoadStop_pool, index))
       
  1303 				error("RoadStops: failed loading savegame: too many RoadStops");
       
  1304 			return GetRoadStop(index);
       
  1305 		}
       
  1306 		case REF_ENGINE_RENEWS: {
       
  1307 			if (!AddBlockIfNeeded(&_EngineRenew_pool, index))
       
  1308 				error("EngineRenews: failed loading savegame: too many EngineRenews");
       
  1309 			return GetEngineRenew(index);
       
  1310 		}
       
  1311 
       
  1312 		case REF_VEHICLE_OLD: {
       
  1313 			/* Old vehicles were saved differently:
       
  1314 			 * invalid vehicle was 0xFFFF,
       
  1315 			 * and the index was not - 1.. correct for this */
       
  1316 			index++;
       
  1317 			if (index == INVALID_VEHICLE)
       
  1318 				return NULL;
       
  1319 
       
  1320 			if (!AddBlockIfNeeded(&_Vehicle_pool, index))
       
  1321 				error("Vehicles: failed loading savegame: too many vehicles");
       
  1322 			return GetVehicle(index);
       
  1323 		}
       
  1324 		default: NOT_REACHED();
       
  1325 	}
       
  1326 
       
  1327 	return NULL;
       
  1328 }
       
  1329 
       
  1330 /** The format for a reader/writer type of a savegame */
       
  1331 typedef struct {
       
  1332 	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
       
  1334 
       
  1335 	bool (*init_read)(void);    /// function executed upon initalization of the loader
       
  1336 	ReaderProc *reader;         /// function that loads the data from the file
       
  1337 	void (*uninit_read)(void);  /// function executed when reading is finished
       
  1338 
       
  1339 	bool (*init_write)(void);   /// function executed upon intialization of the saver
       
  1340 	WriterProc *writer;         /// function that saves the data to the file
       
  1341 	void (*uninit_write)(void); /// function executed when writing is done
       
  1342 } SaveLoadFormat;
       
  1343 
       
  1344 static const SaveLoadFormat _saveload_formats[] = {
       
  1345 	{"memory", 0,                NULL,         NULL,       NULL,           InitMem,       WriteMem,    UnInitMem},
       
  1346 	{"lzo",    TO_BE32X('OTTD'), InitLZO,      ReadLZO,    UninitLZO,      InitLZO,       WriteLZO,    UninitLZO},
       
  1347 	{"none",   TO_BE32X('OTTN'), InitNoComp,   ReadNoComp, UninitNoComp,   InitNoComp,    WriteNoComp, UninitNoComp},
       
  1348 #if defined(WITH_ZLIB)
       
  1349 	{"zlib",   TO_BE32X('OTTZ'), InitReadZlib, ReadZlib,   UninitReadZlib, InitWriteZlib, WriteZlib,   UninitWriteZlib},
       
  1350 #else
       
  1351 	{"zlib",   TO_BE32X('OTTZ'), NULL,         NULL,       NULL,           NULL,          NULL,        NULL},
       
  1352 #endif
       
  1353 };
       
  1354 
       
  1355 /**
       
  1356  * Return the savegameformat of the game. Whether it was create with ZLIB compression
       
  1357  * uncompressed, or another type
       
  1358  * @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
       
  1360  */
       
  1361 static const SaveLoadFormat *GetSavegameFormat(const char *s)
       
  1362 {
       
  1363 	const SaveLoadFormat *def = endof(_saveload_formats) - 1;
       
  1364 
       
  1365 	// find default savegame format, the highest one with which files can be written
       
  1366 	while (!def->init_write) def--;
       
  1367 
       
  1368 	if (s != NULL && s[0] != '\0') {
       
  1369 		const SaveLoadFormat *slf;
       
  1370 		for (slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
       
  1371 			if (slf->init_write != NULL && strcmp(s, slf->name) == 0)
       
  1372 				return slf;
       
  1373 		}
       
  1374 
       
  1375 		ShowInfoF("Savegame format '%s' is not available. Reverting to '%s'.", s, def->name);
       
  1376 	}
       
  1377 	return def;
       
  1378 }
       
  1379 
       
  1380 // actual loader/saver function
       
  1381 void InitializeGame(int mode, uint size_x, uint size_y);
       
  1382 extern bool AfterLoadGame(void);
       
  1383 extern void BeforeSaveGame(void);
       
  1384 extern bool LoadOldSaveGame(const char *file);
       
  1385 
       
  1386 /** Small helper function to close the to be loaded savegame an signal error */
       
  1387 static inline SaveOrLoadResult AbortSaveLoad(void)
       
  1388 {
       
  1389 	if (_sl.fh != NULL) fclose(_sl.fh);
       
  1390 
       
  1391 	_sl.fh = NULL;
       
  1392 	return SL_ERROR;
       
  1393 }
       
  1394 
       
  1395 /** Update the gui accordingly when starting saving
       
  1396  * and set locks on saveload. Also turn off fast-forward cause with that
       
  1397  * saving takes Aaaaages */
       
  1398 void SaveFileStart(void)
       
  1399 {
       
  1400 	_ts.ff_state = _fast_forward;
       
  1401 	_fast_forward = false;
       
  1402 	if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ);
       
  1403 
       
  1404 	SendWindowMessage(WC_STATUS_BAR, 0, true, 0, 0);
       
  1405 	_ts.saveinprogress = true;
       
  1406 }
       
  1407 
       
  1408 /** Update the gui accordingly when saving is done and release locks
       
  1409  * on saveload */
       
  1410 void SaveFileDone(void)
       
  1411 {
       
  1412 	_fast_forward = _ts.ff_state;
       
  1413 	if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE);
       
  1414 
       
  1415 	SendWindowMessage(WC_STATUS_BAR, 0, false, 0, 0);
       
  1416 	_ts.saveinprogress = false;
       
  1417 }
       
  1418 
       
  1419 /** Show a gui message when saving has failed */
       
  1420 void SaveFileError(void)
       
  1421 {
       
  1422 	ShowErrorMessage(STR_4007_GAME_SAVE_FAILED, STR_NULL, 0, 0);
       
  1423 	SaveFileDone();
       
  1424 }
       
  1425 
       
  1426 static OTTDThread* save_thread;
       
  1427 
       
  1428 /** We have written the whole game into memory, _Savegame_pool, now find
       
  1429  * and appropiate compressor and start writing to file.
       
  1430  */
       
  1431 static void* SaveFileToDisk(void *arg)
       
  1432 {
       
  1433 	const SaveLoadFormat *fmt;
       
  1434 	uint32 hdr[2];
       
  1435 
       
  1436 	/* XXX - Setup setjmp error handler if an error occurs anywhere deep during
       
  1437 	 * loading/saving execute a longjmp() and continue execution here */
       
  1438 	if (setjmp(_sl.excpt)) {
       
  1439 		AbortSaveLoad();
       
  1440 		_sl.excpt_uninit();
       
  1441 
       
  1442 		fprintf(stderr, "Save game failed: %s.", _sl.excpt_msg);
       
  1443 		if (arg != NULL) {
       
  1444 			OTTD_SendThreadMessage(MSG_OTTD_SAVETHREAD_ERROR);
       
  1445 		} else {
       
  1446 			SaveFileError();
       
  1447 		}
       
  1448 		return NULL;
       
  1449 	}
       
  1450 
       
  1451 	fmt = GetSavegameFormat(_savegame_format);
       
  1452 
       
  1453 	/* We have written our stuff to memory, now write it to file! */
       
  1454 	hdr[0] = fmt->tag;
       
  1455 	hdr[1] = TO_BE32(SAVEGAME_VERSION << 16);
       
  1456 	if (fwrite(hdr, sizeof(hdr), 1, _sl.fh) != 1) SlError("file write failed");
       
  1457 
       
  1458 	if (!fmt->init_write()) SlError("cannot initialize compressor");
       
  1459 
       
  1460 	{
       
  1461 		uint i;
       
  1462 		uint count = 1 << Savegame_POOL_BLOCK_SIZE_BITS;
       
  1463 
       
  1464 		assert(_ts.count == _sl.offs_base);
       
  1465 		for (i = 0; i != _Savegame_pool.current_blocks - 1; i++) {
       
  1466 			_sl.buf = _Savegame_pool.blocks[i];
       
  1467 			fmt->writer(count);
       
  1468 		}
       
  1469 
       
  1470 		/* The last block is (almost) always not fully filled, so only write away
       
  1471 		 * as much data as it is in there */
       
  1472 		_sl.buf = _Savegame_pool.blocks[i];
       
  1473 		fmt->writer(_ts.count - (i * count));
       
  1474 	}
       
  1475 
       
  1476 	fmt->uninit_write();
       
  1477 	assert(_ts.count == _sl.offs_base);
       
  1478 	GetSavegameFormat("memory")->uninit_write(); // clean the memorypool
       
  1479 	fclose(_sl.fh);
       
  1480 
       
  1481 	if (arg != NULL) OTTD_SendThreadMessage(MSG_OTTD_SAVETHREAD_DONE);
       
  1482 	return NULL;
       
  1483 }
       
  1484 
       
  1485 void WaitTillSaved(void)
       
  1486 {
       
  1487 	OTTDJoinThread(save_thread);
       
  1488 	save_thread = NULL;
       
  1489 }
       
  1490 
       
  1491 /**
       
  1492  * Main Save or Load function where the high-level saveload functions are
       
  1493  * handled. It opens the savegame, selects format and checks versions
       
  1494  * @param filename The name of the savegame being created/loaded
       
  1495  * @param mode Save or load. Load can also be a TTD(Patch) game. Use SL_LOAD, SL_OLD_LOAD or SL_SAVE
       
  1496  * @return Return the results of the action. SL_OK, SL_ERROR or SL_REINIT ("unload" the game)
       
  1497  */
       
  1498 SaveOrLoadResult SaveOrLoad(const char *filename, int mode)
       
  1499 {
       
  1500 	uint32 hdr[2];
       
  1501 	const SaveLoadFormat *fmt;
       
  1502 
       
  1503 	/* An instance of saving is already active, so don't go saving again */
       
  1504 	if (_ts.saveinprogress && mode == SL_SAVE) {
       
  1505 		// if not an autosave, but a user action, show error message
       
  1506 		if (!_do_autosave) ShowErrorMessage(INVALID_STRING_ID, STR_SAVE_STILL_IN_PROGRESS, 0, 0);
       
  1507 		return SL_OK;
       
  1508 	}
       
  1509 	WaitTillSaved();
       
  1510 
       
  1511 	/* Load a TTDLX or TTDPatch game */
       
  1512 	if (mode == SL_OLD_LOAD) {
       
  1513 		InitializeGame(IG_DATE_RESET, 256, 256); // set a mapsize of 256x256 for TTDPatch games or it might get confused
       
  1514 		if (!LoadOldSaveGame(filename)) return SL_REINIT;
       
  1515 		_sl_version = 0;
       
  1516 		AfterLoadGame();
       
  1517 		return SL_OK;
       
  1518 	}
       
  1519 
       
  1520 	_sl.fh = (mode == SL_SAVE) ? fopen(filename, "wb") : fopen(filename, "rb");
       
  1521 	if (_sl.fh == NULL) {
       
  1522 		DEBUG(sl, 0, "Cannot open savegame '%s' for saving/loading.", filename);
       
  1523 		return SL_ERROR;
       
  1524 	}
       
  1525 
       
  1526 	_sl.bufe = _sl.bufp = NULL;
       
  1527 	_sl.offs_base = 0;
       
  1528 	_sl.save = mode;
       
  1529 	_sl.includes = _desc_includes;
       
  1530 	_sl.chs = _chunk_handlers;
       
  1531 
       
  1532 	/* XXX - Setup setjmp error handler if an error occurs anywhere deep during
       
  1533 	 * loading/saving execute a longjmp() and continue execution here */
       
  1534 	if (setjmp(_sl.excpt)) {
       
  1535 		AbortSaveLoad();
       
  1536 
       
  1537 		// deinitialize compressor.
       
  1538 		_sl.excpt_uninit();
       
  1539 
       
  1540 		/* A saver/loader exception!! reinitialize all variables to prevent crash! */
       
  1541 		if (mode == SL_LOAD) {
       
  1542 			ShowInfoF("Load game failed: %s.", _sl.excpt_msg);
       
  1543 			return SL_REINIT;
       
  1544 		}
       
  1545 
       
  1546 		ShowInfoF("Save game failed: %s.", _sl.excpt_msg);
       
  1547 		return SL_ERROR;
       
  1548 	}
       
  1549 
       
  1550 	/* General tactic is to first save the game to memory, then use an available writer
       
  1551 	 * to write it to file, either in threaded mode if possible, or single-threaded */
       
  1552 	if (mode == SL_SAVE) { /* SAVE game */
       
  1553 		fmt = GetSavegameFormat("memory"); // write to memory
       
  1554 
       
  1555 		_sl.write_bytes = fmt->writer;
       
  1556 		_sl.excpt_uninit = fmt->uninit_write;
       
  1557 		if (!fmt->init_write()) {
       
  1558 			DEBUG(sl, 0, "Initializing writer '%s' failed.", fmt->name);
       
  1559 			return AbortSaveLoad();
       
  1560 		}
       
  1561 
       
  1562 		_sl_version = SAVEGAME_VERSION;
       
  1563 
       
  1564 		BeforeSaveGame();
       
  1565 		SlSaveChunks();
       
  1566 		SlWriteFill(); // flush the save buffer
       
  1567 
       
  1568 		SaveFileStart();
       
  1569 		if (_network_server ||
       
  1570 					(save_thread = OTTDCreateThread(&SaveFileToDisk, (void*)"")) == NULL) {
       
  1571 			DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
       
  1572 			SaveFileToDisk(NULL);
       
  1573 			SaveFileDone();
       
  1574 		}
       
  1575 
       
  1576 	} else { /* LOAD game */
       
  1577 		assert(mode == SL_LOAD);
       
  1578 
       
  1579 		if (fread(hdr, sizeof(hdr), 1, _sl.fh) != 1) {
       
  1580 			DEBUG(sl, 0, "Cannot read savegame header, aborting");
       
  1581 			return AbortSaveLoad();
       
  1582 		}
       
  1583 
       
  1584 		// see if we have any loader for this type.
       
  1585 		for (fmt = _saveload_formats; ; fmt++) {
       
  1586 			/* No loader found, treat as version 0 and use LZO format */
       
  1587 			if (fmt == endof(_saveload_formats)) {
       
  1588 				DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format");
       
  1589 				rewind(_sl.fh);
       
  1590 				_sl_version = 0;
       
  1591 				_sl_minor_version = 0;
       
  1592 				fmt = _saveload_formats + 1; // LZO
       
  1593 				break;
       
  1594 			}
       
  1595 
       
  1596 			if (fmt->tag == hdr[0]) {
       
  1597 				// check version number
       
  1598 				_sl_version = TO_BE32(hdr[1]) >> 16;
       
  1599 				/* Minor is not used anymore from version 18.0, but it is still needed
       
  1600 				 *  in versions before that (4 cases) which can't be removed easy.
       
  1601 				 *  Therefor it is loaded, but never saved (or, it saves a 0 in any scenario).
       
  1602 				 *  So never EVER use this minor version again. -- TrueLight -- 22-11-2005 */
       
  1603 				_sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
       
  1604 
       
  1605 				DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
       
  1606 
       
  1607 				/* Is the version higher than the current? */
       
  1608 				if (_sl_version > SAVEGAME_VERSION) {
       
  1609 					DEBUG(sl, 0, "Savegame version invalid");
       
  1610 					return AbortSaveLoad();
       
  1611 				}
       
  1612 				break;
       
  1613 			}
       
  1614 		}
       
  1615 
       
  1616 		_sl.read_bytes = fmt->reader;
       
  1617 		_sl.excpt_uninit = fmt->uninit_read;
       
  1618 
       
  1619 		// loader for this savegame type is not implemented?
       
  1620 		if (fmt->init_read == NULL) {
       
  1621 			ShowInfoF("Loader for '%s' is not available.", fmt->name);
       
  1622 			return AbortSaveLoad();
       
  1623 		}
       
  1624 
       
  1625 		if (!fmt->init_read()) {
       
  1626 			DEBUG(sl, 0, "Initializing loader '%s' failed", fmt->name);
       
  1627 			return AbortSaveLoad();
       
  1628 		}
       
  1629 
       
  1630 		/* Old maps were hardcoded to 256x256 and thus did not contain
       
  1631 		 * any mapsize information. Pre-initialize to 256x256 to not to
       
  1632 		 * confuse old games */
       
  1633 		InitializeGame(IG_DATE_RESET, 256, 256);
       
  1634 
       
  1635 		SlLoadChunks();
       
  1636 		fmt->uninit_read();
       
  1637 		fclose(_sl.fh);
       
  1638 
       
  1639 		/* After loading fix up savegame for any internal changes that
       
  1640 		 * might've occured since then. If it fails, load back the old game */
       
  1641 		if (!AfterLoadGame()) return SL_REINIT;
       
  1642 	}
       
  1643 
       
  1644 	return SL_OK;
       
  1645 }
       
  1646 
       
  1647 /** Do a save when exiting the game (patch option) _patches.autosave_on_exit */
       
  1648 void DoExitSave(void)
       
  1649 {
       
  1650 	char buf[200];
       
  1651 	snprintf(buf, sizeof(buf), "%s%sexit.sav", _paths.autosave_dir, PATHSEP);
       
  1652 	SaveOrLoad(buf, SL_SAVE);
       
  1653 }
       
  1654 
       
  1655 #if 0
       
  1656 /**
       
  1657  * Function to get the type of the savegame by looking at the file header.
       
  1658  * NOTICE: Not used right now, but could be used if extensions of savegames are garbled
       
  1659  * @param file Savegame to be checked
       
  1660  * @return SL_OLD_LOAD or SL_LOAD of the file
       
  1661  */
       
  1662 int GetSavegameType(char *file)
       
  1663 {
       
  1664 	const SaveLoadFormat *fmt;
       
  1665 	uint32 hdr;
       
  1666 	FILE *f;
       
  1667 	int mode = SL_OLD_LOAD;
       
  1668 
       
  1669 	f = fopen(file, "rb");
       
  1670 	if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
       
  1671 		DEBUG(sl, 0, "Savegame is obsolete or invalid format");
       
  1672 		mode = SL_LOAD; // don't try to get filename, just show name as it is written
       
  1673 	} else {
       
  1674 		// see if we have any loader for this type.
       
  1675 		for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
       
  1676 			if (fmt->tag == hdr) {
       
  1677 				mode = SL_LOAD; // new type of savegame
       
  1678 				break;
       
  1679 			}
       
  1680 		}
       
  1681 	}
       
  1682 
       
  1683 	fclose(f);
       
  1684 	return mode;
       
  1685 }
       
  1686 #endif