# saveload.cpp

Go to the documentation of this file.

    00001 /* $Id: saveload.cpp 21047 2010-10-27 20:15:18Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00023 #include "../stdafx.h"
    00024 #include "../debug.h"
    00025 #include "../station_base.h"
    00026 #include "../thread/thread.h"
    00027 #include "../town.h"
    00028 #include "../network/network.h"
    00029 #include "../variables.h"
    00030 #include "../window_func.h"
    00031 #include "../strings_func.h"
    00032 #include "../core/endian_func.hpp"
    00033 #include "../vehicle_base.h"
    00034 #include "../company_func.h"
    00035 #include "../date_func.h"
    00036 #include "../autoreplace_base.h"
    00037 #include "../roadstop_base.h"
    00038 #include "../statusbar_gui.h"
    00039 #include "../fileio_func.h"
    00040 #include "../gamelog.h"
    00041 #include "../string_func.h"
    00042 #include "../engine_base.h"
    00043 #include "../company_base.h"
    00044
    00045 #include "table/strings.h"
    00046
    00047 #include "saveload_internal.h"
    00048
    00049 extern const uint16 SAVEGAME_VERSION = 138;
    00050
    00051 SavegameType _savegame_type;
    00052
    00053 uint32 _ttdp_version;
    00054 uint16 _sl_version;
    00055 byte   _sl_minor_version;
    00056 char _savegame_format[8];
    00057
    00058 typedef void WriterProc(size_t len);
    00059 typedef size_t ReaderProc();
    00060
    00062 enum SaveLoadAction {
    00063   SLA_LOAD,
    00064   SLA_SAVE,
    00065   SLA_PTRS,
    00066   SLA_NULL,
    00067 };
    00068
    00069 enum NeedLength {
    00070   NL_NONE = 0,
    00071   NL_WANTLENGTH = 1,
    00072   NL_CALCLENGTH = 2,
    00073 };
    00074
    00076 struct SaveLoadParams {
    00077   SaveLoadAction action;
    00078   NeedLength need_length;
    00079   byte block_mode;
    00080   bool error;
    00081
    00082   size_t obj_len;
    00083   int array_index, last_array_index;
    00084
    00085   size_t offs_base;
    00086
    00087   WriterProc *write_bytes;
    00088   ReaderProc *read_bytes;
    00089
    00090   /* When saving/loading savegames, they are always saved to a temporary memory-place
    00091    * to be flushed to file (save) or to final place (load) when full. */
    00092   byte *bufp, *bufe;
    00093
    00094   /* these 3 may be used by compressor/decompressors. */
    00095   byte *buf;
    00096   byte *buf_ori;
    00097   uint bufsize;
    00098   FILE *fh;
    00099
    00100   void (*excpt_uninit)();
    00101   StringID error_str;
    00102   char *extra_msg;
    00103 };
    00104
    00105 /* these define the chunks */
    00106 extern const ChunkHandler _gamelog_chunk_handlers[];
    00107 extern const ChunkHandler _map_chunk_handlers[];
    00108 extern const ChunkHandler _misc_chunk_handlers[];
    00109 extern const ChunkHandler _name_chunk_handlers[];
    00110 extern const ChunkHandler _cheat_chunk_handlers[] ;
    00111 extern const ChunkHandler _setting_chunk_handlers[];
    00112 extern const ChunkHandler _company_chunk_handlers[];
    00113 extern const ChunkHandler _engine_chunk_handlers[];
    00114 extern const ChunkHandler _veh_chunk_handlers[];
    00115 extern const ChunkHandler _waypoint_chunk_handlers[];
    00116 extern const ChunkHandler _depot_chunk_handlers[];
    00117 extern const ChunkHandler _order_chunk_handlers[];
    00118 extern const ChunkHandler _town_chunk_handlers[];
    00119 extern const ChunkHandler _sign_chunk_handlers[];
    00120 extern const ChunkHandler _station_chunk_handlers[];
    00121 extern const ChunkHandler _industry_chunk_handlers[];
    00122 extern const ChunkHandler _economy_chunk_handlers[];
    00123 extern const ChunkHandler _subsidy_chunk_handlers[];
    00124 extern const ChunkHandler _ai_chunk_handlers[];
    00125 extern const ChunkHandler _animated_tile_chunk_handlers[];
    00126 extern const ChunkHandler _newgrf_chunk_handlers[];
    00127 extern const ChunkHandler _group_chunk_handlers[];
    00128 extern const ChunkHandler _cargopacket_chunk_handlers[];
    00129 extern const ChunkHandler _autoreplace_chunk_handlers[];
    00130 extern const ChunkHandler _labelmaps_chunk_handlers[];
    00131
    00132 static const ChunkHandler * const _chunk_handlers[] = {
    00133   _gamelog_chunk_handlers,
    00134   _map_chunk_handlers,
    00135   _misc_chunk_handlers,
    00136   _name_chunk_handlers,
    00137   _cheat_chunk_handlers,
    00138   _setting_chunk_handlers,
    00139   _veh_chunk_handlers,
    00140   _waypoint_chunk_handlers,
    00141   _depot_chunk_handlers,
    00142   _order_chunk_handlers,
    00143   _industry_chunk_handlers,
    00144   _economy_chunk_handlers,
    00145   _subsidy_chunk_handlers,
    00146   _engine_chunk_handlers,
    00147   _town_chunk_handlers,
    00148   _sign_chunk_handlers,
    00149   _station_chunk_handlers,
    00150   _company_chunk_handlers,
    00151   _ai_chunk_handlers,
    00152   _animated_tile_chunk_handlers,
    00153   _newgrf_chunk_handlers,
    00154   _group_chunk_handlers,
    00155   _cargopacket_chunk_handlers,
    00156   _autoreplace_chunk_handlers,
    00157   _labelmaps_chunk_handlers,
    00158   NULL,
    00159 };
    00160
    00165 #define FOR_ALL_CHUNK_HANDLERS(ch) \
    00166   for (const ChunkHandler * const *chsc = _chunk_handlers; *chsc != NULL; chsc++) \
    00167     for (const ChunkHandler *ch = *chsc; ch != NULL; ch = (ch->flags & CH_LAST) ? NULL : ch + 1)
    00168
    00169 static SaveLoadParams _sl;
    00170
    00172 static void SlNullPointers()
    00173 {
    00174   _sl.action = SLA_NULL;
    00175
    00176   DEBUG(sl, 1, "Nulling pointers");
    00177
    00178   FOR_ALL_CHUNK_HANDLERS(ch) {
    00179     if (ch->ptrs_proc != NULL) {
    00180       DEBUG(sl, 2, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    00181       ch->ptrs_proc();
    00182     }
    00183   }
    00184
    00185   DEBUG(sl, 1, "All pointers nulled");
    00186
    00187   assert(_sl.action == SLA_NULL);
    00188 }
    00189
    00193 static void NORETURN SlError(StringID string, const char *extra_msg = NULL)
    00194 {
    00195   _sl.error_str = string;
    00196   free(_sl.extra_msg);
    00197   _sl.extra_msg = (extra_msg == NULL) ? NULL : strdup(extra_msg);
    00198   /* We have to NULL all pointers here; we might be in a state where
    00199    * the pointers are actually filled with indices, which means that
    00200    * when we access them during cleaning the pool dereferences of
    00201    * those indices will be made with segmentation faults as result. */
    00202   if (_sl.action == SLA_LOAD || _sl.action == SLA_PTRS) SlNullPointers();
    00203   throw std::exception();
    00204 }
    00205
    00213 void NORETURN SlErrorCorrupt(const char *msg)
    00214 {
    00215   SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
    00216 }
    00217
    00218 typedef void (*AsyncSaveFinishProc)();
    00219 static AsyncSaveFinishProc _async_save_finish = NULL;
    00220 static ThreadObject *_save_thread;
    00221
    00225 static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
    00226 {
    00227   if (_exit_game) return;
    00228   while (_async_save_finish != NULL) CSleep(10);
    00229
    00230   _async_save_finish = proc;
    00231 }
    00232
    00236 void ProcessAsyncSaveFinish()
    00237 {
    00238   if (_async_save_finish == NULL) return;
    00239
    00240   _async_save_finish();
    00241
    00242   _async_save_finish = NULL;
    00243
    00244   if (_save_thread != NULL) {
    00245     _save_thread->Join();
    00246     delete _save_thread;
    00247     _save_thread = NULL;
    00248   }
    00249 }
    00250
    00254 static void SlReadFill()
    00255 {
    00256   size_t len = _sl.read_bytes();
    00257   if (len == 0) SlErrorCorrupt("Unexpected end of chunk");
    00258
    00259   _sl.bufp = _sl.buf;
    00260   _sl.bufe = _sl.buf + len;
    00261   _sl.offs_base += len;
    00262 }
    00263
    00264 static inline size_t SlGetOffs() {return _sl.offs_base - (_sl.bufe - _sl.bufp);}
    00265 static inline uint SlReadArrayLength();
    00266
    00271 static inline uint SlCalcConvMemLen(VarType conv)
    00272 {
    00273   static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
    00274   byte length = GB(conv, 4, 4);
    00275
    00276   switch (length << 4) {
    00277     case SLE_VAR_STRB:
    00278     case SLE_VAR_STRBQ:
    00279     case SLE_VAR_STR:
    00280     case SLE_VAR_STRQ:
    00281       return SlReadArrayLength();
    00282
    00283     default:
    00284       assert(length < lengthof(conv_mem_size));
    00285       return conv_mem_size[length];
    00286   }
    00287 }
    00288
    00293 static inline byte SlCalcConvFileLen(VarType conv)
    00294 {
    00295   static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
    00296   byte length = GB(conv, 0, 4);
    00297   assert(length < lengthof(conv_file_size));
    00298   return conv_file_size[length];
    00299 }
    00300
    00302 static inline size_t SlCalcRefLen() {return CheckSavegameVersion(69) ? 2 : 4;}
    00303
    00308 static void SlWriteFill()
    00309 {
    00310   /* flush the buffer to disk (the writer) */
    00311   if (_sl.bufp != NULL) {
    00312     uint len = _sl.bufp - _sl.buf;
    00313     _sl.offs_base += len;
    00314     if (len) _sl.write_bytes(len);
    00315   }
    00316
    00317   /* All the data from the buffer has been written away, rewind to the beginning
    00318    * to start reading in more data */
    00319   _sl.bufp = _sl.buf;
    00320   _sl.bufe = _sl.buf + _sl.bufsize;
    00321 }
    00322
    00327 static inline byte SlReadByteInternal()
    00328 {
    00329   if (_sl.bufp == _sl.bufe) SlReadFill();
    00330   return *_sl.bufp++;
    00331 }
    00332
    00334 byte SlReadByte() {return SlReadByteInternal();}
    00335
    00340 static inline void SlWriteByteInternal(byte b)
    00341 {
    00342   if (_sl.bufp == _sl.bufe) SlWriteFill();
    00343   *_sl.bufp++ = b;
    00344 }
    00345
    00347 void SlWriteByte(byte b) {SlWriteByteInternal(b);}
    00348
    00349 static inline int SlReadUint16()
    00350 {
    00351   int x = SlReadByte() << 8;
    00352   return x | SlReadByte();
    00353 }
    00354
    00355 static inline uint32 SlReadUint32()
    00356 {
    00357   uint32 x = SlReadUint16() << 16;
    00358   return x | SlReadUint16();
    00359 }
    00360
    00361 static inline uint64 SlReadUint64()
    00362 {
    00363   uint32 x = SlReadUint32();
    00364   uint32 y = SlReadUint32();
    00365   return (uint64)x << 32 | y;
    00366 }
    00367
    00368 static inline void SlWriteUint16(uint16 v)
    00369 {
    00370   SlWriteByte(GB(v, 8, 8));
    00371   SlWriteByte(GB(v, 0, 8));
    00372 }
    00373
    00374 static inline void SlWriteUint32(uint32 v)
    00375 {
    00376   SlWriteUint16(GB(v, 16, 16));
    00377   SlWriteUint16(GB(v,  0, 16));
    00378 }
    00379
    00380 static inline void SlWriteUint64(uint64 x)
    00381 {
    00382   SlWriteUint32((uint32)(x >> 32));
    00383   SlWriteUint32((uint32)x);
    00384 }
    00385
    00395 static uint SlReadSimpleGamma()
    00396 {
    00397   uint i = SlReadByte();
    00398   if (HasBit(i, 7)) {
    00399     i &= ~0x80;
    00400     if (HasBit(i, 6)) {
    00401       i &= ~0x40;
    00402       if (HasBit(i, 5)) {
    00403         i &= ~0x20;
    00404         if (HasBit(i, 4))
    00405           SlErrorCorrupt("Unsupported gamma");
    00406         i = (i << 8) | SlReadByte();
    00407       }
    00408       i = (i << 8) | SlReadByte();
    00409     }
    00410     i = (i << 8) | SlReadByte();
    00411   }
    00412   return i;
    00413 }
    00414
    00427 static void SlWriteSimpleGamma(size_t i)
    00428 {
    00429   if (i >= (1 << 7)) {
    00430     if (i >= (1 << 14)) {
    00431       if (i >= (1 << 21)) {
    00432         assert(i < (1 << 28));
    00433         SlWriteByte((byte)(0xE0 | (i >> 24)));
    00434         SlWriteByte((byte)(i >> 16));
    00435       } else {
    00436         SlWriteByte((byte)(0xC0 | (i >> 16)));
    00437       }
    00438       SlWriteByte((byte)(i >> 8));
    00439     } else {
    00440       SlWriteByte((byte)(0x80 | (i >> 8)));
    00441     }
    00442   }
    00443   SlWriteByte((byte)i);
    00444 }
    00445
    00447 static inline uint SlGetGammaLength(size_t i)
    00448 {
    00449   return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21));
    00450 }
    00451
    00452 static inline uint SlReadSparseIndex() {return SlReadSimpleGamma();}
    00453 static inline void SlWriteSparseIndex(uint index) {SlWriteSimpleGamma(index);}
    00454
    00455 static inline uint SlReadArrayLength() {return SlReadSimpleGamma();}
    00456 static inline void SlWriteArrayLength(size_t length) {SlWriteSimpleGamma(length);}
    00457 static inline uint SlGetArrayLength(size_t length) {return SlGetGammaLength(length);}
    00458
    00459 void SlSetArrayIndex(uint index)
    00460 {
    00461   _sl.need_length = NL_WANTLENGTH;
    00462   _sl.array_index = index;
    00463 }
    00464
    00465 static size_t _next_offs;
    00466
    00471 int SlIterateArray()
    00472 {
    00473   int index;
    00474
    00475   /* After reading in the whole array inside the loop
    00476    * we must have read in all the data, so we must be at end of current block. */
    00477   if (_next_offs != 0 && SlGetOffs() != _next_offs) SlErrorCorrupt("Invalid chunk size");
    00478
    00479   while (true) {
    00480     uint length = SlReadArrayLength();
    00481     if (length == 0) {
    00482       _next_offs = 0;
    00483       return -1;
    00484     }
    00485
    00486     _sl.obj_len = --length;
    00487     _next_offs = SlGetOffs() + length;
    00488
    00489     switch (_sl.block_mode) {
    00490       case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
    00491       case CH_ARRAY:        index = _sl.array_index++; break;
    00492       default:
    00493         DEBUG(sl, 0, "SlIterateArray error");
    00494         return -1; // error
    00495     }
    00496
    00497     if (length != 0) return index;
    00498   }
    00499 }
    00500
    00506 void SlSetLength(size_t length)
    00507 {
    00508   assert(_sl.action == SLA_SAVE);
    00509
    00510   switch (_sl.need_length) {
    00511     case NL_WANTLENGTH:
    00512       _sl.need_length = NL_NONE;
    00513       switch (_sl.block_mode) {
    00514         case CH_RIFF:
    00515           /* Ugly encoding of >16M RIFF chunks
    00516            * The lower 24 bits are normal
    00517            * The uppermost 4 bits are bits 24:27 */
    00518           assert(length < (1 << 28));
    00519           SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
    00520           break;
    00521         case CH_ARRAY:
    00522           assert(_sl.last_array_index <= _sl.array_index);
    00523           while (++_sl.last_array_index <= _sl.array_index)
    00524             SlWriteArrayLength(1);
    00525           SlWriteArrayLength(length + 1);
    00526           break;
    00527         case CH_SPARSE_ARRAY:
    00528           SlWriteArrayLength(length + 1 + SlGetArrayLength(_sl.array_index)); // Also include length of sparse index.
    00529           SlWriteSparseIndex(_sl.array_index);
    00530           break;
    00531         default: NOT_REACHED();
    00532       }
    00533       break;
    00534
    00535     case NL_CALCLENGTH:
    00536       _sl.obj_len += (int)length;
    00537       break;
    00538
    00539     default: NOT_REACHED();
    00540   }
    00541 }
    00542
    00549 static void SlCopyBytes(void *ptr, size_t length)
    00550 {
    00551   byte *p = (byte *)ptr;
    00552
    00553   switch (_sl.action) {
    00554     case SLA_LOAD:
    00555       for (; length != 0; length--) { *p++ = SlReadByteInternal(); }
    00556       break;
    00557     case SLA_SAVE:
    00558       for (; length != 0; length--) { SlWriteByteInternal(*p++); }
    00559       break;
    00560     default: NOT_REACHED();
    00561   }
    00562 }
    00563
    00568 static inline void SlSkipBytes(size_t length)
    00569 {
    00570   for (; length != 0; length--) SlReadByte();
    00571 }
    00572
    00573 /* Get the length of the current object */
    00574 size_t SlGetFieldLength() {return _sl.obj_len;}
    00575
    00581 int64 ReadValue(const void *ptr, VarType conv)
    00582 {
    00583   switch (GetVarMemType(conv)) {
    00584     case SLE_VAR_BL:  return (*(bool *)ptr != 0);
    00585     case SLE_VAR_I8:  return *(int8  *)ptr;
    00586     case SLE_VAR_U8:  return *(byte  *)ptr;
    00587     case SLE_VAR_I16: return *(int16 *)ptr;
    00588     case SLE_VAR_U16: return *(uint16*)ptr;
    00589     case SLE_VAR_I32: return *(int32 *)ptr;
    00590     case SLE_VAR_U32: return *(uint32*)ptr;
    00591     case SLE_VAR_I64: return *(int64 *)ptr;
    00592     case SLE_VAR_U64: return *(uint64*)ptr;
    00593     case SLE_VAR_NULL:return 0;
    00594     default: NOT_REACHED();
    00595   }
    00596 }
    00597
    00603 void WriteValue(void *ptr, VarType conv, int64 val)
    00604 {
    00605   switch (GetVarMemType(conv)) {
    00606     case SLE_VAR_BL:  *(bool  *)ptr = (val != 0);  break;
    00607     case SLE_VAR_I8:  *(int8  *)ptr = val; break;
    00608     case SLE_VAR_U8:  *(byte  *)ptr = val; break;
    00609     case SLE_VAR_I16: *(int16 *)ptr = val; break;
    00610     case SLE_VAR_U16: *(uint16*)ptr = val; break;
    00611     case SLE_VAR_I32: *(int32 *)ptr = val; break;
    00612     case SLE_VAR_U32: *(uint32*)ptr = val; break;
    00613     case SLE_VAR_I64: *(int64 *)ptr = val; break;
    00614     case SLE_VAR_U64: *(uint64*)ptr = val; break;
    00615     case SLE_VAR_NAME: *(char**)ptr = CopyFromOldName(val); break;
    00616     case SLE_VAR_NULL: break;
    00617     default: NOT_REACHED();
    00618   }
    00619 }
    00620
    00629 static void SlSaveLoadConv(void *ptr, VarType conv)
    00630 {
    00631   switch (_sl.action) {
    00632     case SLA_SAVE: {
    00633       int64 x = ReadValue(ptr, conv);
    00634
    00635       /* Write the value to the file and check if its value is in the desired range */
    00636       switch (GetVarFileType(conv)) {
    00637         case SLE_FILE_I8: assert(x >= -128 && x <= 127);     SlWriteByte(x);break;
    00638         case SLE_FILE_U8: assert(x >= 0 && x <= 255);        SlWriteByte(x);break;
    00639         case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break;
    00640         case SLE_FILE_STRINGID:
    00641         case SLE_FILE_U16:assert(x >= 0 && x <= 65535);      SlWriteUint16(x);break;
    00642         case SLE_FILE_I32:
    00643         case SLE_FILE_U32:                                   SlWriteUint32((uint32)x);break;
    00644         case SLE_FILE_I64:
    00645         case SLE_FILE_U64:                                   SlWriteUint64(x);break;
    00646         default: NOT_REACHED();
    00647       }
    00648       break;
    00649     }
    00650     case SLA_LOAD: {
    00651       int64 x;
    00652       /* Read a value from the file */
    00653       switch (GetVarFileType(conv)) {
    00654         case SLE_FILE_I8:  x = (int8  )SlReadByte();   break;
    00655         case SLE_FILE_U8:  x = (byte  )SlReadByte();   break;
    00656         case SLE_FILE_I16: x = (int16 )SlReadUint16(); break;
    00657         case SLE_FILE_U16: x = (uint16)SlReadUint16(); break;
    00658         case SLE_FILE_I32: x = (int32 )SlReadUint32(); break;
    00659         case SLE_FILE_U32: x = (uint32)SlReadUint32(); break;
    00660         case SLE_FILE_I64: x = (int64 )SlReadUint64(); break;
    00661         case SLE_FILE_U64: x = (uint64)SlReadUint64(); break;
    00662         case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break;
    00663         default: NOT_REACHED();
    00664       }
    00665
    00666       /* Write The value to the struct. These ARE endian safe. */
    00667       WriteValue(ptr, conv, x);
    00668       break;
    00669     }
    00670     case SLA_PTRS: break;
    00671     case SLA_NULL: break;
    00672     default: NOT_REACHED();
    00673   }
    00674 }
    00675
    00683 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
    00684 {
    00685   if (ptr == NULL) return 0;
    00686   return min(strlen(ptr), length - 1);
    00687 }
    00688
    00696 static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
    00697 {
    00698   size_t len;
    00699   const char *str;
    00700
    00701   switch (GetVarMemType(conv)) {
    00702     default: NOT_REACHED();
    00703     case SLE_VAR_STR:
    00704     case SLE_VAR_STRQ:
    00705       str = *(const char**)ptr;
    00706       len = SIZE_MAX;
    00707       break;
    00708     case SLE_VAR_STRB:
    00709     case SLE_VAR_STRBQ:
    00710       str = (const char*)ptr;
    00711       len = length;
    00712       break;
    00713   }
    00714
    00715   len = SlCalcNetStringLen(str, len);
    00716   return len + SlGetArrayLength(len); // also include the length of the index
    00717 }
    00718
    00724 static void SlString(void *ptr, size_t length, VarType conv)
    00725 {
    00726   switch (_sl.action) {
    00727     case SLA_SAVE: {
    00728       size_t len;
    00729       switch (GetVarMemType(conv)) {
    00730         default: NOT_REACHED();
    00731         case SLE_VAR_STRB:
    00732         case SLE_VAR_STRBQ:
    00733           len = SlCalcNetStringLen((char *)ptr, length);
    00734           break;
    00735         case SLE_VAR_STR:
    00736         case SLE_VAR_STRQ:
    00737           ptr = *(char **)ptr;
    00738           len = SlCalcNetStringLen((char *)ptr, SIZE_MAX);
    00739           break;
    00740       }
    00741
    00742       SlWriteArrayLength(len);
    00743       SlCopyBytes(ptr, len);
    00744       break;
    00745     }
    00746     case SLA_LOAD: {
    00747       size_t len = SlReadArrayLength();
    00748
    00749       switch (GetVarMemType(conv)) {
    00750         default: NOT_REACHED();
    00751         case SLE_VAR_STRB:
    00752         case SLE_VAR_STRBQ:
    00753           if (len >= length) {
    00754             DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
    00755             SlCopyBytes(ptr, length);
    00756             SlSkipBytes(len - length);
    00757             len = length - 1;
    00758           } else {
    00759             SlCopyBytes(ptr, len);
    00760           }
    00761           break;
    00762         case SLE_VAR_STR:
    00763         case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate
    00764           free(*(char **)ptr);
    00765           if (len == 0) {
    00766             *(char **)ptr = NULL;
    00767           } else {
    00768             *(char **)ptr = MallocT<char>(len + 1); // terminating '\0'
    00769             ptr = *(char **)ptr;
    00770             SlCopyBytes(ptr, len);
    00771           }
    00772           break;
    00773       }
    00774
    00775       ((char *)ptr)[len] = '\0'; // properly terminate the string
    00776       str_validate((char *)ptr, (char *)ptr + len);
    00777       break;
    00778     }
    00779     case SLA_PTRS: break;
    00780     case SLA_NULL: break;
    00781     default: NOT_REACHED();
    00782   }
    00783 }
    00784
    00790 static inline size_t SlCalcArrayLen(size_t length, VarType conv)
    00791 {
    00792   return SlCalcConvFileLen(conv) * length;
    00793 }
    00794
    00801 void SlArray(void *array, size_t length, VarType conv)
    00802 {
    00803   if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
    00804
    00805   /* Automatically calculate the length? */
    00806   if (_sl.need_length != NL_NONE) {
    00807     SlSetLength(SlCalcArrayLen(length, conv));
    00808     /* Determine length only? */
    00809     if (_sl.need_length == NL_CALCLENGTH) return;
    00810   }
    00811
    00812   /* NOTICE - handle some buggy stuff, in really old versions everything was saved
    00813    * as a byte-type. So detect this, and adjust array size accordingly */
    00814   if (_sl.action != SLA_SAVE && _sl_version == 0) {
    00815     /* all arrays except difficulty settings */
    00816     if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
    00817         conv == SLE_INT32 || conv == SLE_UINT32) {
    00818       SlCopyBytes(array, length * SlCalcConvFileLen(conv));
    00819       return;
    00820     }
    00821     /* used for conversion of Money 32bit->64bit */
    00822     if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
    00823       for (uint i = 0; i < length; i++) {
    00824         ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
    00825       }
    00826       return;
    00827     }
    00828   }
    00829
    00830   /* If the size of elements is 1 byte both in file and memory, no special
    00831    * conversion is needed, use specialized copy-copy function to speed up things */
    00832   if (conv == SLE_INT8 || conv == SLE_UINT8) {
    00833     SlCopyBytes(array, length);
    00834   } else {
    00835     byte *a = (byte*)array;
    00836     byte mem_size = SlCalcConvMemLen(conv);
    00837
    00838     for (; length != 0; length --) {
    00839       SlSaveLoadConv(a, conv);
    00840       a += mem_size; // get size
    00841     }
    00842   }
    00843 }
    00844
    00845
    00846 static size_t ReferenceToInt(const void *obj, SLRefType rt);
    00847 static void *IntToReference(size_t index, SLRefType rt);
    00848
    00849
    00854 static inline size_t SlCalcListLen(const void *list)
    00855 {
    00856   std::list<void *> *l = (std::list<void *> *) list;
    00857
    00858   int type_size = CheckSavegameVersion(69) ? 2 : 4;
    00859   /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
    00860    * of the list */
    00861   return l->size() * type_size + type_size;
    00862 }
    00863
    00864
    00870 static void SlList(void *list, SLRefType conv)
    00871 {
    00872   /* Automatically calculate the length? */
    00873   if (_sl.need_length != NL_NONE) {
    00874     SlSetLength(SlCalcListLen(list));
    00875     /* Determine length only? */
    00876     if (_sl.need_length == NL_CALCLENGTH) return;
    00877   }
    00878
    00879   typedef std::list<void *> PtrList;
    00880   PtrList *l = (PtrList *)list;
    00881
    00882   switch (_sl.action) {
    00883     case SLA_SAVE: {
    00884       SlWriteUint32((uint32)l->size());
    00885
    00886       PtrList::iterator iter;
    00887       for (iter = l->begin(); iter != l->end(); ++iter) {
    00888         void *ptr = *iter;
    00889         SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
    00890       }
    00891       break;
    00892     }
    00893     case SLA_LOAD: {
    00894       size_t length = CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32();
    00895
    00896       /* Load each reference and push to the end of the list */
    00897       for (size_t i = 0; i < length; i++) {
    00898         size_t data = CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32();
    00899         l->push_back((void *)data);
    00900       }
    00901       break;
    00902     }
    00903     case SLA_PTRS: {
    00904       PtrList temp = *l;
    00905
    00906       l->clear();
    00907       PtrList::iterator iter;
    00908       for (iter = temp.begin(); iter != temp.end(); ++iter) {
    00909         void *ptr = IntToReference((size_t)*iter, conv);
    00910         l->push_back(ptr);
    00911       }
    00912       break;
    00913     }
    00914     case SLA_NULL:
    00915       l->clear();
    00916       break;
    00917     default: NOT_REACHED();
    00918   }
    00919 }
    00920
    00921
    00923 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
    00924 {
    00925   if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
    00926   if (sld->conv & SLF_SAVE_NO) return false;
    00927
    00928   return true;
    00929 }
    00930
    00934 static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
    00935 {
    00936   if ((sld->conv & SLF_NETWORK_NO) && _sl.action != SLA_SAVE && _networking && !_network_server) {
    00937     SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
    00938     return true;
    00939   }
    00940
    00941   return false;
    00942 }
    00943
    00950 size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
    00951 {
    00952   size_t length = 0;
    00953
    00954   /* Need to determine the length and write a length tag. */
    00955   for (; sld->cmd != SL_END; sld++) {
    00956     length += SlCalcObjMemberLength(object, sld);
    00957   }
    00958   return length;
    00959 }
    00960
    00961 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
    00962 {
    00963   assert(_sl.action == SLA_SAVE);
    00964
    00965   switch (sld->cmd) {
    00966     case SL_VAR:
    00967     case SL_REF:
    00968     case SL_ARR:
    00969     case SL_STR:
    00970     case SL_LST:
    00971       /* CONDITIONAL saveload types depend on the savegame version */
    00972       if (!SlIsObjectValidInSavegame(sld)) break;
    00973
    00974       switch (sld->cmd) {
    00975         case SL_VAR: return SlCalcConvFileLen(sld->conv);
    00976         case SL_REF: return SlCalcRefLen();
    00977         case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
    00978         case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
    00979         case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
    00980         default: NOT_REACHED();
    00981       }
    00982       break;
    00983     case SL_WRITEBYTE: return 1; // a byte is logically of size 1
    00984     case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
    00985     case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
    00986     default: NOT_REACHED();
    00987   }
    00988   return 0;
    00989 }
    00990
    00991
    00992 bool SlObjectMember(void *ptr, const SaveLoad *sld)
    00993 {
    00994   VarType conv = GB(sld->conv, 0, 8);
    00995   switch (sld->cmd) {
    00996     case SL_VAR:
    00997     case SL_REF:
    00998     case SL_ARR:
    00999     case SL_STR:
    01000     case SL_LST:
    01001       /* CONDITIONAL saveload types depend on the savegame version */
    01002       if (!SlIsObjectValidInSavegame(sld)) return false;
    01003       if (SlSkipVariableOnLoad(sld)) return false;
    01004
    01005       switch (sld->cmd) {
    01006         case SL_VAR: SlSaveLoadConv(ptr, conv); break;
    01007         case SL_REF: // Reference variable, translate
    01008           switch (_sl.action) {
    01009             case SLA_SAVE:
    01010               SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv));
    01011               break;
    01012             case SLA_LOAD:
    01013               *(size_t *)ptr = CheckSavegameVersion(69) ? SlReadUint16() : SlReadUint32();
    01014               break;
    01015             case SLA_PTRS:
    01016               *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv);
    01017               break;
    01018             case SLA_NULL:
    01019               *(void **)ptr = NULL;
    01020               break;
    01021             default: NOT_REACHED();
    01022           }
    01023           break;
    01024         case SL_ARR: SlArray(ptr, sld->length, conv); break;
    01025         case SL_STR: SlString(ptr, sld->length, conv); break;
    01026         case SL_LST: SlList(ptr, (SLRefType)conv); break;
    01027         default: NOT_REACHED();
    01028       }
    01029       break;
    01030
    01031     /* SL_WRITEBYTE translates a value of a variable to another one upon
    01032      * saving or loading.
    01033      * XXX - variable renaming abuse
    01034      * game_value: the value of the variable ingame is abused by sld->version_from
    01035      * file_value: the value of the variable in the savegame is abused by sld->version_to */
    01036     case SL_WRITEBYTE:
    01037       switch (_sl.action) {
    01038         case SLA_SAVE: SlWriteByte(sld->version_to); break;
    01039         case SLA_LOAD: *(byte *)ptr = sld->version_from; break;
    01040         case SLA_PTRS: break;
    01041         case SLA_NULL: break;
    01042         default: NOT_REACHED();
    01043       }
    01044       break;
    01045
    01046     /* SL_VEH_INCLUDE loads common code for vehicles */
    01047     case SL_VEH_INCLUDE:
    01048       SlObject(ptr, GetVehicleDescription(VEH_END));
    01049       break;
    01050
    01051     case SL_ST_INCLUDE:
    01052       SlObject(ptr, GetBaseStationDescription());
    01053       break;
    01054
    01055     default: NOT_REACHED();
    01056   }
    01057   return true;
    01058 }
    01059
    01065 void SlObject(void *object, const SaveLoad *sld)
    01066 {
    01067   /* Automatically calculate the length? */
    01068   if (_sl.need_length != NL_NONE) {
    01069     SlSetLength(SlCalcObjLength(object, sld));
    01070     if (_sl.need_length == NL_CALCLENGTH) return;
    01071   }
    01072
    01073   for (; sld->cmd != SL_END; sld++) {
    01074     void *ptr = sld->global ? sld->address : GetVariableAddress(object, sld);
    01075     SlObjectMember(ptr, sld);
    01076   }
    01077 }
    01078
    01083 void SlGlobList(const SaveLoadGlobVarList *sldg)
    01084 {
    01085   SlObject(NULL, (const SaveLoad*)sldg);
    01086 }
    01087
    01093 void SlAutolength(AutolengthProc *proc, void *arg)
    01094 {
    01095   size_t offs;
    01096
    01097   assert(_sl.action == SLA_SAVE);
    01098
    01099   /* Tell it to calculate the length */
    01100   _sl.need_length = NL_CALCLENGTH;
    01101   _sl.obj_len = 0;
    01102   proc(arg);
    01103
    01104   /* Setup length */
    01105   _sl.need_length = NL_WANTLENGTH;
    01106   SlSetLength(_sl.obj_len);
    01107
    01108   offs = SlGetOffs() + _sl.obj_len;
    01109
    01110   /* And write the stuff */
    01111   proc(arg);
    01112
    01113   if (offs != SlGetOffs()) SlErrorCorrupt("Invalid chunk size");
    01114 }
    01115
    01120 static void SlLoadChunk(const ChunkHandler *ch)
    01121 {
    01122   byte m = SlReadByte();
    01123   size_t len;
    01124   size_t endoffs;
    01125
    01126   _sl.block_mode = m;
    01127   _sl.obj_len = 0;
    01128
    01129   switch (m) {
    01130     case CH_ARRAY:
    01131       _sl.array_index = 0;
    01132       ch->load_proc();
    01133       break;
    01134     case CH_SPARSE_ARRAY:
    01135       ch->load_proc();
    01136       break;
    01137     default:
    01138       if ((m & 0xF) == CH_RIFF) {
    01139         /* Read length */
    01140         len = (SlReadByte() << 16) | ((m >> 4) << 24);
    01141         len += SlReadUint16();
    01142         _sl.obj_len = len;
    01143         endoffs = SlGetOffs() + len;
    01144         ch->load_proc();
    01145         if (SlGetOffs() != endoffs) SlErrorCorrupt("Invalid chunk size");
    01146       } else {
    01147         SlErrorCorrupt("Invalid chunk type");
    01148       }
    01149       break;
    01150   }
    01151 }
    01152
    01153 /* Stub Chunk handlers to only calculate length and do nothing else */
    01154 static ChunkSaveLoadProc *_tmp_proc_1;
    01155 static inline void SlStubSaveProc2(void *arg) {_tmp_proc_1();}
    01156 static void SlStubSaveProc() {SlAutolength(SlStubSaveProc2, NULL);}
    01157
    01162 static void SlSaveChunk(const ChunkHandler *ch)
    01163 {
    01164   ChunkSaveLoadProc *proc = ch->save_proc;
    01165
    01166   /* Don't save any chunk information if there is no save handler. */
    01167   if (proc == NULL) return;
    01168
    01169   SlWriteUint32(ch->id);
    01170   DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    01171
    01172   if (ch->flags & CH_AUTO_LENGTH) {
    01173     /* Need to calculate the length. Solve that by calling SlAutoLength in the save_proc. */
    01174     _tmp_proc_1 = proc;
    01175     proc = SlStubSaveProc;
    01176   }
    01177
    01178   _sl.block_mode = ch->flags & CH_TYPE_MASK;
    01179   switch (ch->flags & CH_TYPE_MASK) {
    01180     case CH_RIFF:
    01181       _sl.need_length = NL_WANTLENGTH;
    01182       proc();
    01183       break;
    01184     case CH_ARRAY:
    01185       _sl.last_array_index = 0;
    01186       SlWriteByte(CH_ARRAY);
    01187       proc();
    01188       SlWriteArrayLength(0); // Terminate arrays
    01189       break;
    01190     case CH_SPARSE_ARRAY:
    01191       SlWriteByte(CH_SPARSE_ARRAY);
    01192       proc();
    01193       SlWriteArrayLength(0); // Terminate arrays
    01194       break;
    01195     default: NOT_REACHED();
    01196   }
    01197 }
    01198
    01200 static void SlSaveChunks()
    01201 {
    01202   FOR_ALL_CHUNK_HANDLERS(ch) {
    01203     SlSaveChunk(ch);
    01204   }
    01205
    01206   /* Terminator */
    01207   SlWriteUint32(0);
    01208 }
    01209
    01215 static const ChunkHandler *SlFindChunkHandler(uint32 id)
    01216 {
    01217   FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch;
    01218   return NULL;
    01219 }
    01220
    01222 static void SlLoadChunks()
    01223 {
    01224   uint32 id;
    01225   const ChunkHandler *ch;
    01226
    01227   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
    01228     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
    01229
    01230     ch = SlFindChunkHandler(id);
    01231     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
    01232     SlLoadChunk(ch);
    01233   }
    01234 }
    01235
    01237 static void SlFixPointers()
    01238 {
    01239   _sl.action = SLA_PTRS;
    01240
    01241   DEBUG(sl, 1, "Fixing pointers");
    01242
    01243   FOR_ALL_CHUNK_HANDLERS(ch) {
    01244     if (ch->ptrs_proc != NULL) {
    01245       DEBUG(sl, 2, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    01246       ch->ptrs_proc();
    01247     }
    01248   }
    01249
    01250   DEBUG(sl, 1, "All pointers fixed");
    01251
    01252   assert(_sl.action == SLA_PTRS);
    01253 }
    01254
    01255 /*******************************************
    01256  ********** START OF LZO CODE **************
    01257  *******************************************/
    01258
    01259 #ifdef WITH_LZO
    01260 #include <lzo/lzo1x.h>
    01261
    01263 static const uint LZO_BUFFER_SIZE = 8192;
    01264
    01265 static size_t ReadLZO()
    01266 {
    01267   /* Buffer size is from the LZO docs plus the chunk header size. */
    01268   byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
    01269   uint32 tmp[2];
    01270   uint32 size;
    01271   lzo_uint len;
    01272
    01273   /* Read header*/
    01274   if (fread(tmp, sizeof(tmp), 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE, "File read failed");
    01275
    01276   /* Check if size is bad */
    01277   ((uint32*)out)[0] = size = tmp[1];
    01278
    01279   if (_sl_version != 0) {
    01280     tmp[0] = TO_BE32(tmp[0]);
    01281     size = TO_BE32(size);
    01282   }
    01283
    01284   if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size");
    01285
    01286   /* Read block */
    01287   if (fread(out + sizeof(uint32), size, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    01288
    01289   /* Verify checksum */
    01290   if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
    01291
    01292   /* Decompress */
    01293   lzo1x_decompress(out + sizeof(uint32) * 1, size, _sl.buf, &len, NULL);
    01294   return len;
    01295 }
    01296
    01297 static void WriteLZO(size_t size)
    01298 {
    01299   const lzo_bytep in = _sl.buf;
    01300   /* Buffer size is from the LZO docs plus the chunk header size. */
    01301   byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
    01302   byte wrkmem[LZO1X_1_MEM_COMPRESS];
    01303   lzo_uint outlen;
    01304
    01305   do {
    01306     /* Compress up to LZO_BUFFER_SIZE bytes at once. */
    01307     lzo_uint len = size > LZO_BUFFER_SIZE ? LZO_BUFFER_SIZE : (lzo_uint)size;
    01308     lzo1x_1_compress(in, len, out + sizeof(uint32) * 2, &outlen, wrkmem);
    01309     ((uint32*)out)[1] = TO_BE32((uint32)outlen);
    01310     ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
    01311     if (fwrite(out, outlen + sizeof(uint32) * 2, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
    01312
    01313     /* Move to next data chunk. */
    01314     size -= len;
    01315     in += len;
    01316   } while (size > 0);
    01317 }
    01318
    01319 static bool InitLZO(byte compression)
    01320 {
    01321   if (lzo_init() != LZO_E_OK) return false;
    01322   _sl.bufsize = LZO_BUFFER_SIZE;
    01323   _sl.buf = _sl.buf_ori = MallocT<byte>(LZO_BUFFER_SIZE);
    01324   return true;
    01325 }
    01326
    01327 static void UninitLZO()
    01328 {
    01329   free(_sl.buf_ori);
    01330 }
    01331
    01332 #endif /* WITH_LZO */
    01333
    01334 /*********************************************
    01335  ******** START OF NOCOMP CODE (uncompressed)*
    01336  *********************************************/
    01337
    01339 static const uint NOCOMP_BUFFER_SIZE = 8192;
    01340
    01341 static size_t ReadNoComp()
    01342 {
    01343   return fread(_sl.buf, 1, NOCOMP_BUFFER_SIZE, _sl.fh);
    01344 }
    01345
    01346 static void WriteNoComp(size_t size)
    01347 {
    01348   if (fwrite(_sl.buf, 1, size, _sl.fh) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
    01349 }
    01350
    01351 static bool InitNoComp(byte compression)
    01352 {
    01353   _sl.bufsize = NOCOMP_BUFFER_SIZE;
    01354   _sl.buf = _sl.buf_ori = MallocT<byte>(NOCOMP_BUFFER_SIZE);
    01355   return true;
    01356 }
    01357
    01358 static void UninitNoComp()
    01359 {
    01360   free(_sl.buf_ori);
    01361 }
    01362
    01363 /********************************************
    01364  ********** START OF MEMORY CODE (in ram)****
    01365  ********************************************/
    01366
    01367 #include "../gui.h"
    01368
    01369 struct ThreadedSave {
    01370   uint count;
    01371   byte ff_state;
    01372   bool saveinprogress;
    01373   CursorID cursor;
    01374 };
    01375
    01377 static const int MEMORY_CHUNK_SIZE = 128 * 1024;
    01379 static AutoFreeSmallVector<byte *, 16> _memory_savegame;
    01380
    01381 static ThreadedSave _ts;
    01382
    01383 static void WriteMem(size_t size)
    01384 {
    01385   _ts.count += (uint)size;
    01386
    01387   _sl.buf = CallocT<byte>(MEMORY_CHUNK_SIZE);
    01388   *_memory_savegame.Append() = _sl.buf;
    01389 }
    01390
    01391 static void UnInitMem()
    01392 {
    01393   _memory_savegame.Clear();
    01394 }
    01395
    01396 static bool InitMem()
    01397 {
    01398   _ts.count = 0;
    01399   _sl.bufsize = MEMORY_CHUNK_SIZE;
    01400
    01401   UnInitMem();
    01402   WriteMem(0);
    01403   return true;
    01404 }
    01405
    01406 /********************************************
    01407  ********** START OF ZLIB CODE **************
    01408  ********************************************/
    01409
    01410 #if defined(WITH_ZLIB)
    01411 #include <zlib.h>
    01412
    01414 static const uint ZLIB_BUFFER_SIZE = 8192;
    01415
    01416 static z_stream _z;
    01417
    01418 static bool InitReadZlib(byte compression)
    01419 {
    01420   memset(&_z, 0, sizeof(_z));
    01421   if (inflateInit(&_z) != Z_OK) return false;
    01422
    01423   _sl.bufsize = ZLIB_BUFFER_SIZE;
    01424   _sl.buf = _sl.buf_ori = MallocT<byte>(ZLIB_BUFFER_SIZE + ZLIB_BUFFER_SIZE); // also contains fread buffer
    01425   return true;
    01426 }
    01427
    01428 static size_t ReadZlib()
    01429 {
    01430   int r;
    01431
    01432   _z.next_out = _sl.buf;
    01433   _z.avail_out = ZLIB_BUFFER_SIZE;
    01434
    01435   do {
    01436     /* read more bytes from the file? */
    01437     if (_z.avail_in == 0) {
    01438       _z.avail_in = (uint)fread(_z.next_in = _sl.buf + ZLIB_BUFFER_SIZE, 1, ZLIB_BUFFER_SIZE, _sl.fh);
    01439     }
    01440
    01441     /* inflate the data */
    01442     r = inflate(&_z, 0);
    01443     if (r == Z_STREAM_END)
    01444       break;
    01445
    01446     if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "inflate() failed");
    01447   } while (_z.avail_out);
    01448
    01449   return ZLIB_BUFFER_SIZE - _z.avail_out;
    01450 }
    01451
    01452 static void UninitReadZlib()
    01453 {
    01454   inflateEnd(&_z);
    01455   free(_sl.buf_ori);
    01456 }
    01457
    01458 static bool InitWriteZlib(byte compression)
    01459 {
    01460   memset(&_z, 0, sizeof(_z));
    01461   if (deflateInit(&_z, compression) != Z_OK) return false;
    01462
    01463   _sl.bufsize = ZLIB_BUFFER_SIZE;
    01464   _sl.buf = _sl.buf_ori = MallocT<byte>(ZLIB_BUFFER_SIZE);
    01465   return true;
    01466 }
    01467
    01468 static void WriteZlibLoop(z_streamp z, byte *p, size_t len, int mode)
    01469 {
    01470   byte buf[ZLIB_BUFFER_SIZE]; // output buffer
    01471   int r;
    01472   uint n;
    01473   z->next_in = p;
    01474   z->avail_in = (uInt)len;
    01475   do {
    01476     z->next_out = buf;
    01477     z->avail_out = sizeof(buf);
    01478
    01486     r = deflate(z, mode);
    01487
    01488     /* bytes were emitted? */
    01489     if ((n = sizeof(buf) - z->avail_out) != 0) {
    01490       if (fwrite(buf, n, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
    01491     }
    01492     if (r == Z_STREAM_END)
    01493       break;
    01494     if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code");
    01495   } while (z->avail_in || !z->avail_out);
    01496 }
    01497
    01498 static void WriteZlib(size_t len)
    01499 {
    01500   WriteZlibLoop(&_z, _sl.buf, len, 0);
    01501 }
    01502
    01503 static void UninitWriteZlib()
    01504 {
    01505   /* flush any pending output. */
    01506   if (_sl.fh) WriteZlibLoop(&_z, NULL, 0, Z_FINISH);
    01507   deflateEnd(&_z);
    01508   free(_sl.buf_ori);
    01509 }
    01510
    01511 #endif /* WITH_ZLIB */
    01512
    01513 /*******************************************
    01514  ************* END OF CODE *****************
    01515  *******************************************/
    01516
    01527 static size_t ReferenceToInt(const void *obj, SLRefType rt)
    01528 {
    01529   assert(_sl.action == SLA_SAVE);
    01530
    01531   if (obj == NULL) return 0;
    01532
    01533   switch (rt) {
    01534     case REF_VEHICLE_OLD: // Old vehicles we save as new onces
    01535     case REF_VEHICLE:   return ((const  Vehicle*)obj)->index + 1;
    01536     case REF_STATION:   return ((const  Station*)obj)->index + 1;
    01537     case REF_TOWN:      return ((const     Town*)obj)->index + 1;
    01538     case REF_ORDER:     return ((const    Order*)obj)->index + 1;
    01539     case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
    01540     case REF_ENGINE_RENEWS: return ((const EngineRenew*)obj)->index + 1;
    01541     case REF_CARGO_PACKET:  return ((const CargoPacket*)obj)->index + 1;
    01542     case REF_ORDERLIST:     return ((const   OrderList*)obj)->index + 1;
    01543     default: NOT_REACHED();
    01544   }
    01545 }
    01546
    01557 static void *IntToReference(size_t index, SLRefType rt)
    01558 {
    01559   assert_compile(sizeof(size_t) <= sizeof(void *));
    01560
    01561   assert(_sl.action == SLA_PTRS);
    01562
    01563   /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE,
    01564    * and should be loaded like that */
    01565   if (rt == REF_VEHICLE_OLD && !CheckSavegameVersionOldStyle(4, 4)) {
    01566     rt = REF_VEHICLE;
    01567   }
    01568
    01569   /* No need to look up NULL pointers, just return immediately */
    01570   if (index == (rt == REF_VEHICLE_OLD ? 0xFFFF : 0)) return NULL;
    01571
    01572   /* Correct index. Old vehicles were saved differently:
    01573    * invalid vehicle was 0xFFFF, now we use 0x0000 for everything invalid. */
    01574   if (rt != REF_VEHICLE_OLD) index--;
    01575
    01576   switch (rt) {
    01577     case REF_ORDERLIST:
    01578       if (OrderList::IsValidID(index)) return OrderList::Get(index);
    01579       SlErrorCorrupt("Referencing invalid OrderList");
    01580
    01581     case REF_ORDER:
    01582       if (Order::IsValidID(index)) return Order::Get(index);
    01583       /* in old versions, invalid order was used to mark end of order list */
    01584       if (CheckSavegameVersionOldStyle(5, 2)) return NULL;
    01585       SlErrorCorrupt("Referencing invalid Order");
    01586
    01587     case REF_VEHICLE_OLD:
    01588     case REF_VEHICLE:
    01589       if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
    01590       SlErrorCorrupt("Referencing invalid Vehicle");
    01591
    01592     case REF_STATION:
    01593       if (Station::IsValidID(index)) return Station::Get(index);
    01594       SlErrorCorrupt("Referencing invalid Station");
    01595
    01596     case REF_TOWN:
    01597       if (Town::IsValidID(index)) return Town::Get(index);
    01598       SlErrorCorrupt("Referencing invalid Town");
    01599
    01600     case REF_ROADSTOPS:
    01601       if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
    01602       SlErrorCorrupt("Referencing invalid RoadStop");
    01603
    01604     case REF_ENGINE_RENEWS:
    01605       if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
    01606       SlErrorCorrupt("Referencing invalid EngineRenew");
    01607
    01608     case REF_CARGO_PACKET:
    01609       if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
    01610       SlErrorCorrupt("Referencing invalid CargoPacket");
    01611
    01612     default: NOT_REACHED();
    01613   }
    01614 }
    01615
    01617 struct SaveLoadFormat {
    01618   const char *name;
    01619   uint32 tag;
    01620
    01621   bool (*init_read)(byte compression);
    01622   ReaderProc *reader;
    01623   void (*uninit_read)();
    01624
    01625   bool (*init_write)(byte compression);
    01626   WriterProc *writer;
    01627   void (*uninit_write)();
    01628
    01629   byte min_compression;
    01630   byte default_compression;
    01631   byte max_compression;
    01632 };
    01633
    01634 static const SaveLoadFormat _saveload_formats[] = {
    01635 #if defined(WITH_LZO)
    01636   {"lzo",    TO_BE32X('OTTD'), InitLZO,      ReadLZO,    UninitLZO,      InitLZO,       WriteLZO,    UninitLZO,       0, 0, 0},
    01637 #else
    01638   {"lzo",    TO_BE32X('OTTD'), NULL,         NULL,       NULL,           NULL,          NULL,        NULL,            0, 0, 0},
    01639 #endif
    01640   {"none",   TO_BE32X('OTTN'), InitNoComp,   ReadNoComp, UninitNoComp,   InitNoComp,    WriteNoComp, UninitNoComp,    0, 0, 0},
    01641 #if defined(WITH_ZLIB)
    01642   {"zlib",   TO_BE32X('OTTZ'), InitReadZlib, ReadZlib,   UninitReadZlib, InitWriteZlib, WriteZlib,   UninitWriteZlib, 0, 6, 9},
    01643 #else
    01644   {"zlib",   TO_BE32X('OTTZ'), NULL,         NULL,       NULL,           NULL,          NULL,        NULL,            0, 0, 0},
    01645 #endif
    01646   {"lzma",   TO_BE32X('OTTX'), NULL,         NULL,       NULL,           NULL,          NULL,        NULL,            0, 0, 0},
    01647 };
    01648
    01656 static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
    01657 {
    01658   const SaveLoadFormat *def = lastof(_saveload_formats);
    01659
    01660   /* find default savegame format, the highest one with which files can be written */
    01661   while (!def->init_write) def--;
    01662
    01663   if (!StrEmpty(s)) {
    01664     /* Get the ":..." of the compression level out of the way */
    01665     char *complevel = strrchr(s, ':');
    01666     if (complevel != NULL) *complevel = '\0';
    01667
    01668     for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
    01669       if (slf->init_write != NULL && strcmp(s, slf->name) == 0) {
    01670         *compression_level = slf->default_compression;
    01671         if (complevel != NULL) {
    01672           /* There is a compression level in the string.
    01673            * First restore the : we removed to do proper name matching,
    01674            * then move the the begin of the actual version. */
    01675           *complevel = ':';
    01676           complevel++;
    01677
    01678           /* Get the version and determine whether all went fine. */
    01679           char *end;
    01680           long level = strtol(complevel, &end, 10);
    01681           if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) {
    01682             ShowInfoF("Compression level '%s' is not valid.", complevel);
    01683           } else {
    01684             *compression_level = level;
    01685           }
    01686         }
    01687         return slf;
    01688       }
    01689     }
    01690
    01691     ShowInfoF("Savegame format '%s' is not available. Reverting to '%s'.", s, def->name);
    01692
    01693     /* Restore the string by adding the : back */
    01694     if (complevel != NULL) *complevel = ':';
    01695   }
    01696   *compression_level = def->default_compression;
    01697   return def;
    01698 }
    01699
    01700 /* actual loader/saver function */
    01701 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings);
    01702 extern bool AfterLoadGame();
    01703 extern bool LoadOldSaveGame(const char *file);
    01704
    01706 static inline SaveOrLoadResult AbortSaveLoad()
    01707 {
    01708   if (_sl.fh != NULL) fclose(_sl.fh);
    01709
    01710   _sl.fh = NULL;
    01711   return SL_ERROR;
    01712 }
    01713
    01717 static void SaveFileStart()
    01718 {
    01719   _ts.ff_state = _fast_forward;
    01720   _fast_forward = 0;
    01721   if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
    01722
    01723   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START);
    01724   _ts.saveinprogress = true;
    01725 }
    01726
    01729 static void SaveFileDone()
    01730 {
    01731   if (_game_mode != GM_MENU) _fast_forward = _ts.ff_state;
    01732   if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
    01733
    01734   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
    01735   _ts.saveinprogress = false;
    01736 }
    01737
    01739 void SetSaveLoadError(StringID str)
    01740 {
    01741   _sl.error_str = str;
    01742 }
    01743
    01745 const char *GetSaveLoadErrorString()
    01746 {
    01747   SetDParam(0, _sl.error_str);
    01748   SetDParamStr(1, _sl.extra_msg);
    01749
    01750   static char err_str[512];
    01751   GetString(err_str, _sl.action == SLA_SAVE ? STR_ERROR_GAME_SAVE_FAILED : STR_ERROR_GAME_LOAD_FAILED, lastof(err_str));
    01752   return err_str;
    01753 }
    01754
    01756 static void SaveFileError()
    01757 {
    01758   SetDParamStr(0, GetSaveLoadErrorString());
    01759   ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, 0, 0);
    01760   SaveFileDone();
    01761 }
    01762
    01766 static SaveOrLoadResult SaveFileToDisk(bool threaded)
    01767 {
    01768   _sl.excpt_uninit = NULL;
    01769   try {
    01770     byte compression;
    01771     const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format, &compression);
    01772
    01773     /* We have written our stuff to memory, now write it to file! */
    01774     uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) };
    01775     if (fwrite(hdr, sizeof(hdr), 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
    01776
    01777     if (!fmt->init_write(compression)) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    01778
    01779     {
    01780       uint i;
    01781
    01782       if (_ts.count != _sl.offs_base) SlErrorCorrupt("Unexpected size of chunk");
    01783       for (i = 0; i != _memory_savegame.Length() - 1; i++) {
    01784         _sl.buf = _memory_savegame[i];
    01785         fmt->writer(MEMORY_CHUNK_SIZE);
    01786       }
    01787
    01788       /* The last block is (almost) always not fully filled, so only write away
    01789        * as much data as it is in there */
    01790       _sl.buf = _memory_savegame[i];
    01791       fmt->writer(_ts.count % MEMORY_CHUNK_SIZE);
    01792     }
    01793
    01794     fmt->uninit_write();
    01795     if (_ts.count != _sl.offs_base) SlErrorCorrupt("Unexpected size of chunk");
    01796     UnInitMem();
    01797     fclose(_sl.fh);
    01798
    01799     if (threaded) SetAsyncSaveFinish(SaveFileDone);
    01800
    01801     return SL_OK;
    01802   }
    01803   catch (...) {
    01804     AbortSaveLoad();
    01805     if (_sl.excpt_uninit != NULL) _sl.excpt_uninit();
    01806
    01807     /* Skip the "colour" character */
    01808     DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
    01809
    01810     if (threaded) {
    01811       SetAsyncSaveFinish(SaveFileError);
    01812     } else {
    01813       SaveFileError();
    01814     }
    01815     return SL_ERROR;
    01816   }
    01817 }
    01818
    01819 static void SaveFileToDiskThread(void *arg)
    01820 {
    01821   SaveFileToDisk(true);
    01822 }
    01823
    01824 void WaitTillSaved()
    01825 {
    01826   if (_save_thread == NULL) return;
    01827
    01828   _save_thread->Join();
    01829   delete _save_thread;
    01830   _save_thread = NULL;
    01831 }
    01832
    01842 SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
    01843 {
    01844   uint32 hdr[2];
    01845
    01846   /* An instance of saving is already active, so don't go saving again */
    01847   if (_ts.saveinprogress && mode == SL_SAVE) {
    01848     /* if not an autosave, but a user action, show error message */
    01849     if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, 0, 0);
    01850     return SL_OK;
    01851   }
    01852   WaitTillSaved();
    01853
    01854   _next_offs = 0;
    01855
    01856   /* Load a TTDLX or TTDPatch game */
    01857   if (mode == SL_OLD_LOAD) {
    01858     _engine_mngr.ResetToDefaultMapping();
    01859     InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
    01860
    01861     /* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
    01862      * and if so a new NewGRF list will be made in LoadOldSaveGame.
    01863      * Note: this is done here because AfterLoadGame is also called
    01864      * for OTTD savegames which have their own NewGRF logic. */
    01865     ClearGRFConfigList(&_grfconfig);
    01866     GamelogReset();
    01867     if (!LoadOldSaveGame(filename)) return SL_REINIT;
    01868     _sl_version = 0;
    01869     _sl_minor_version = 0;
    01870     GamelogStartAction(GLAT_LOAD);
    01871     if (!AfterLoadGame()) {
    01872       GamelogStopAction();
    01873       return SL_REINIT;
    01874     }
    01875     GamelogStopAction();
    01876     return SL_OK;
    01877   }
    01878
    01879   _sl.excpt_uninit = NULL;
    01880   _sl.bufe = _sl.bufp = NULL;
    01881   _sl.offs_base = 0;
    01882   _sl.action = (mode != 0) ? SLA_SAVE : SLA_LOAD;
    01883
    01884   try {
    01885     _sl.fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
    01886
    01887     /* Make it a little easier to load savegames from the console */
    01888     if (_sl.fh == NULL && mode == SL_LOAD) _sl.fh = FioFOpenFile(filename, "rb", SAVE_DIR);
    01889     if (_sl.fh == NULL && mode == SL_LOAD) _sl.fh = FioFOpenFile(filename, "rb", BASE_DIR);
    01890
    01891     if (_sl.fh == NULL) {
    01892       SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    01893     }
    01894
    01895     /* General tactic is to first save the game to memory, then use an available writer
    01896      * to write it to file, either in threaded mode if possible, or single-threaded */
    01897     if (mode == SL_SAVE) { // SAVE game
    01898       DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
    01899
    01900       _sl.write_bytes = WriteMem;
    01901       _sl.excpt_uninit = UnInitMem;
    01902       InitMem();
    01903
    01904       _sl_version = SAVEGAME_VERSION;
    01905
    01906       SaveViewportBeforeSaveGame();
    01907       SlSaveChunks();
    01908       SlWriteFill(); // flush the save buffer
    01909
    01910       SaveFileStart();
    01911       if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
    01912       if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
    01913         if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
    01914
    01915         SaveOrLoadResult result = SaveFileToDisk(false);
    01916         SaveFileDone();
    01917
    01918         return result;
    01919       }
    01920     } else { // LOAD game
    01921       assert(mode == SL_LOAD);
    01922       DEBUG(desync, 1, "load: %s", filename);
    01923
    01924       /* Can't fseek to 0 as in tar files that is not correct */
    01925       long pos = ftell(_sl.fh);
    01926       if (fread(hdr, sizeof(hdr), 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    01927
    01928       /* see if we have any loader for this type. */
    01929       const SaveLoadFormat *fmt = _saveload_formats;
    01930       for (;;) {
    01931         /* No loader found, treat as version 0 and use LZO format */
    01932         if (fmt == endof(_saveload_formats)) {
    01933           DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format");
    01934           clearerr(_sl.fh);
    01935           fseek(_sl.fh, pos, SEEK_SET);
    01936           _sl_version = 0;
    01937           _sl_minor_version = 0;
    01938
    01939           /* Try to find the LZO savegame format; it uses 'OTTD' as tag. */
    01940           fmt = _saveload_formats;
    01941           for (;;) {
    01942             if (fmt == endof(_saveload_formats)) {
    01943               /* Who removed LZO support? Bad bad boy! */
    01944               NOT_REACHED();
    01945             }
    01946             if (fmt->tag == TO_BE32X('OTTD')) break;
    01947             fmt++;
    01948           }
    01949           break;
    01950         }
    01951
    01952         if (fmt->tag == hdr[0]) {
    01953           /* check version number */
    01954           _sl_version = TO_BE32(hdr[1]) >> 16;
    01955           /* Minor is not used anymore from version 18.0, but it is still needed
    01956            * in versions before that (4 cases) which can't be removed easy.
    01957            * Therefor it is loaded, but never saved (or, it saves a 0 in any scenario).
    01958            * So never EVER use this minor version again. -- TrueLight -- 22-11-2005 */
    01959           _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
    01960
    01961           DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
    01962
    01963           /* Is the version higher than the current? */
    01964           if (_sl_version > SAVEGAME_VERSION) SlError(STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME);
    01965           break;
    01966         }
    01967
    01968         fmt++;
    01969       }
    01970
    01971       _sl.read_bytes = fmt->reader;
    01972       _sl.excpt_uninit = fmt->uninit_read;
    01973
    01974       /* loader for this savegame type is not implemented? */
    01975       if (fmt->init_read == NULL) {
    01976         char err_str[64];
    01977         snprintf(err_str, lengthof(err_str), "Loader for '%s' is not available.", fmt->name);
    01978         SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
    01979       }
    01980
    01981       if (!fmt->init_read(0)) {
    01982         char err_str[64];
    01983         snprintf(err_str, lengthof(err_str), "Initializing loader '%s' failed", fmt->name);
    01984         SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
    01985       }
    01986
    01987       _engine_mngr.ResetToDefaultMapping();
    01988
    01989       /* Old maps were hardcoded to 256x256 and thus did not contain
    01990        * any mapsize information. Pre-initialize to 256x256 to not to
    01991        * confuse old games */
    01992       InitializeGame(256, 256, true, true);
    01993
    01994       GamelogReset();
    01995
    01996       if (CheckSavegameVersion(4)) {
    01997         /*
    01998          * NewGRFs were introduced between 0.3,4 and 0.3.5, which both
    01999          * shared savegame version 4. Anything before that 'obviously'
    02000          * does not have any NewGRFs. Between the introduction and
    02001          * savegame version 41 (just before 0.5) the NewGRF settings
    02002          * were not stored in the savegame and they were loaded by
    02003          * using the settings from the main menu.
    02004          * So, to recap:
    02005          * - savegame version  <  4:  do not load any NewGRFs.
    02006          * - savegame version >= 41:  load NewGRFs from savegame, which is
    02007          *                            already done at this stage by
    02008          *                            overwriting the main menu settings.
    02009          * - other savegame versions: use main menu settings.
    02010          *
    02011          * This means that users *can* crash savegame version 4..40
    02012          * savegames if they set incompatible NewGRFs in the main menu,
    02013          * but can't crash anymore for savegame version < 4 savegames.
    02014          *
    02015          * Note: this is done here because AfterLoadGame is also called
    02016          * for TTO/TTD/TTDP savegames which have their own NewGRF logic.
    02017          */
    02018         ClearGRFConfigList(&_grfconfig);
    02019       }
    02020
    02021       SlLoadChunks();
    02022       SlFixPointers();
    02023       fmt->uninit_read();
    02024       fclose(_sl.fh);
    02025
    02026       GamelogStartAction(GLAT_LOAD);
    02027
    02028       _savegame_type = SGT_OTTD;
    02029
    02030       /* After loading fix up savegame for any internal changes that
    02031        * might've occured since then. If it fails, load back the old game */
    02032       if (!AfterLoadGame()) {
    02033         GamelogStopAction();
    02034         return SL_REINIT;
    02035       }
    02036
    02037       GamelogStopAction();
    02038     }
    02039
    02040     return SL_OK;
    02041   }
    02042   catch (...) {
    02043     AbortSaveLoad();
    02044
    02045     /* deinitialize compressor. */
    02046     if (_sl.excpt_uninit != NULL) _sl.excpt_uninit();
    02047
    02048     /* Skip the "colour" character */
    02049     DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
    02050
    02051     /* A saver/loader exception!! reinitialize all variables to prevent crash! */
    02052     return (mode == SL_LOAD) ? SL_REINIT : SL_ERROR;
    02053   }
    02054 }
    02055
    02057 void DoExitSave()
    02058 {
    02059   SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
    02060 }
    02061
    02067 void GenerateDefaultSaveName(char *buf, const char *last)
    02068 {
    02069   /* Check if we have a name for this map, which is the name of the first
    02070    * available company. When there's no company available we'll use
    02071    * 'Spectator' as "company" name. */
    02072   CompanyID cid = _local_company;
    02073   if (!Company::IsValidID(cid)) {
    02074     const Company *c;
    02075     FOR_ALL_COMPANIES(c) {
    02076       cid = c->index;
    02077       break;
    02078     }
    02079   }
    02080
    02081   SetDParam(0, cid);
    02082
    02083   /* Insert current date */
    02084   switch (_settings_client.gui.date_format_in_default_names) {
    02085     case 0: SetDParam(1, STR_JUST_DATE_LONG); break;
    02086     case 1: SetDParam(1, STR_JUST_DATE_TINY); break;
    02087     case 2: SetDParam(1, STR_JUST_DATE_ISO); break;
    02088     default: NOT_REACHED();
    02089   }
    02090   SetDParam(2, _date);
    02091
    02092   /* Get the correct string (special string for when there's not company) */
    02093   GetString(buf, !Company::IsValidID(cid) ? STR_SAVEGAME_NAME_SPECTATOR : STR_SAVEGAME_NAME_DEFAULT, last);
    02094   SanitizeFilename(buf);
    02095 }
    02096
    02097 #if 0
    02098
    02104 int GetSavegameType(char *file)
    02105 {
    02106   const SaveLoadFormat *fmt;
    02107   uint32 hdr;
    02108   FILE *f;
    02109   int mode = SL_OLD_LOAD;
    02110
    02111   f = fopen(file, "rb");
    02112   if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
    02113     DEBUG(sl, 0, "Savegame is obsolete or invalid format");
    02114     mode = SL_LOAD; // don't try to get filename, just show name as it is written
    02115   } else {
    02116     /* see if we have any loader for this type. */
    02117     for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
    02118       if (fmt->tag == hdr) {
    02119         mode = SL_LOAD; // new type of savegame
    02120         break;
    02121       }
    02122     }
    02123   }
    02124
    02125   fclose(f);
    02126   return mode;
    02127 }
    02128 #endif