# saveload.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    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
    00024 #include "../stdafx.h"
    00025 #include "../debug.h"
    00026 #include "../station_base.h"
    00027 #include "../thread/thread.h"
    00028 #include "../town.h"
    00029 #include "../network/network.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 "../fios.h"
    00044 #include "../gui.h"
    00045
    00046 #include "table/strings.h"
    00047
    00048 #include "saveload_internal.h"
    00049 #include "saveload_filter.h"
    00050
    00051 /*
    00052  * Previous savegame versions, the trunk revision where they were
    00053  * introduced and the released version that had that particular
    00054  * savegame version.
    00055  * Up to savegame version 18 there is a minor version as well.
    00056  *
    00057  *    1.0         0.1.x, 0.2.x
    00058  *    2.0         0.3.0
    00059  *    2.1         0.3.1, 0.3.2
    00060  *    3.x         lost
    00061  *    4.0     1
    00062  *    4.1   122   0.3.3, 0.3.4
    00063  *    4.2  1222   0.3.5
    00064  *    4.3  1417
    00065  *    4.4  1426
    00066  *    5.0  1429
    00067  *    5.1  1440
    00068  *    5.2  1525   0.3.6
    00069  *    6.0  1721
    00070  *    6.1  1768
    00071  *    7.0  1770
    00072  *    8.0  1786
    00073  *    9.0  1909
    00074  *   10.0  2030
    00075  *   11.0  2033
    00076  *   11.1  2041
    00077  *   12.1  2046
    00078  *   13.1  2080   0.4.0, 0.4.0.1
    00079  *   14.0  2441
    00080  *   15.0  2499
    00081  *   16.0  2817
    00082  *   16.1  3155
    00083  *   17.0  3212
    00084  *   17.1  3218
    00085  *   18    3227
    00086  *   19    3396
    00087  *   20    3403
    00088  *   21    3472   0.4.x
    00089  *   22    3726
    00090  *   23    3915
    00091  *   24    4150
    00092  *   25    4259
    00093  *   26    4466
    00094  *   27    4757
    00095  *   28    4987
    00096  *   29    5070
    00097  *   30    5946
    00098  *   31    5999
    00099  *   32    6001
    00100  *   33    6440
    00101  *   34    6455
    00102  *   35    6602
    00103  *   36    6624
    00104  *   37    7182
    00105  *   38    7195
    00106  *   39    7269
    00107  *   40    7326
    00108  *   41    7348   0.5.x
    00109  *   42    7573
    00110  *   43    7642
    00111  *   44    8144
    00112  *   45    8501
    00113  *   46    8705
    00114  *   47    8735
    00115  *   48    8935
    00116  *   49    8969
    00117  *   50    8973
    00118  *   51    8978
    00119  *   52    9066
    00120  *   53    9316
    00121  *   54    9613
    00122  *   55    9638
    00123  *   56    9667
    00124  *   57    9691
    00125  *   58    9762
    00126  *   59    9779
    00127  *   60    9874
    00128  *   61    9892
    00129  *   62    9905
    00130  *   63    9956
    00131  *   64   10006
    00132  *   65   10210
    00133  *   66   10211
    00134  *   67   10236
    00135  *   68   10266
    00136  *   69   10319
    00137  *   70   10541
    00138  *   71   10567
    00139  *   72   10601
    00140  *   73   10903
    00141  *   74   11030
    00142  *   75   11107
    00143  *   76   11139
    00144  *   77   11172
    00145  *   78   11176
    00146  *   79   11188
    00147  *   80   11228
    00148  *   81   11244
    00149  *   82   11410
    00150  *   83   11589
    00151  *   84   11822
    00152  *   85   11874
    00153  *   86   12042
    00154  *   87   12129
    00155  *   88   12134
    00156  *   89   12160
    00157  *   90   12293
    00158  *   91   12347
    00159  *   92   12381   0.6.x
    00160  *   93   12648
    00161  *   94   12816
    00162  *   95   12924
    00163  *   96   13226
    00164  *   97   13256
    00165  *   98   13375
    00166  *   99   13838
    00167  *  100   13952
    00168  *  101   14233
    00169  *  102   14332
    00170  *  103   14598
    00171  *  104   14735
    00172  *  105   14803
    00173  *  106   14919
    00174  *  107   15027
    00175  *  108   15045
    00176  *  109   15075
    00177  *  110   15148
    00178  *  111   15190
    00179  *  112   15290
    00180  *  113   15340
    00181  *  114   15601
    00182  *  115   15695
    00183  *  116   15893   0.7.x
    00184  *  117   16037
    00185  *  118   16129
    00186  *  119   16242
    00187  *  120   16439
    00188  *  121   16694
    00189  *  122   16855
    00190  *  123   16909
    00191  *  124   16993
    00192  *  125   17113
    00193  *  126   17433
    00194  *  127   17439
    00195  *  128   18281
    00196  *  129   18292
    00197  *  130   18404
    00198  *  131   18481
    00199  *  132   18522
    00200  *  133   18674
    00201  *  134   18703
    00202  *  135   18719
    00203  *  136   18764
    00204  *  137   18912
    00205  *  138   18942   1.0.x
    00206  *  139   19346
    00207  *  140   19382
    00208  *  141   19799
    00209  *  142   20003
    00210  *  143   20048
    00211  *  144   20334
    00212  *  145   20376
    00213  *  146   20446
    00214  *  147   20621
    00215  *  148   20659
    00216  *  149   20832
    00217  *  150   20857
    00218  *  151   20918
    00219  *  152   21171
    00220  *  153   21263
    00221  *  154   21426
    00222  *  155   21453
    00223  *  156   21728
    00224  *  157   21862
    00225  *  158   21933
    00226  *  159   21962
    00227  *  160   21974
    00228  */
    00229 extern const uint16 SAVEGAME_VERSION = 160;
    00230
    00231 SavegameType _savegame_type;
    00232
    00233 uint32 _ttdp_version;
    00234 uint16 _sl_version;
    00235 byte   _sl_minor_version;
    00236 char _savegame_format[8];
    00237 bool _do_autosave;
    00238
    00240 enum SaveLoadAction {
    00241   SLA_LOAD,
    00242   SLA_SAVE,
    00243   SLA_PTRS,
    00244   SLA_NULL,
    00245   SLA_LOAD_CHECK,
    00246 };
    00247
    00248 enum NeedLength {
    00249   NL_NONE = 0,
    00250   NL_WANTLENGTH = 1,
    00251   NL_CALCLENGTH = 2,
    00252 };
    00253
    00255 static const size_t MEMORY_CHUNK_SIZE = 128 * 1024;
    00256
    00258 struct ReadBuffer {
    00259   byte buf[MEMORY_CHUNK_SIZE];
    00260   byte *bufp;
    00261   byte *bufe;
    00262   LoadFilter *reader;
    00263   size_t read;
    00264
    00269   ReadBuffer(LoadFilter *reader) : bufp(NULL), bufe(NULL), reader(reader), read(0)
    00270   {
    00271   }
    00272
    00273   FORCEINLINE byte ReadByte()
    00274   {
    00275     if (this->bufp == this->bufe) {
    00276       size_t len = this->reader->Read(this->buf, lengthof(this->buf));
    00277       if (len == 0) SlErrorCorrupt("Unexpected end of chunk");
    00278
    00279       this->read += len;
    00280       this->bufp = this->buf;
    00281       this->bufe = this->buf + len;
    00282     }
    00283
    00284     return *this->bufp++;
    00285   }
    00286
    00291   size_t GetSize() const
    00292   {
    00293     return this->read - (this->bufe - this->bufp);
    00294   }
    00295 };
    00296
    00297
    00299 struct MemoryDumper {
    00300   AutoFreeSmallVector<byte *, 16> blocks;
    00301   byte *buf;
    00302   byte *bufe;
    00303
    00305   MemoryDumper() : buf(NULL), bufe(NULL)
    00306   {
    00307   }
    00308
    00313   FORCEINLINE void WriteByte(byte b)
    00314   {
    00315     /* Are we at the end of this chunk? */
    00316     if (this->buf == this->bufe) {
    00317       this->buf = CallocT<byte>(MEMORY_CHUNK_SIZE);
    00318       *this->blocks.Append() = this->buf;
    00319       this->bufe = this->buf + MEMORY_CHUNK_SIZE;
    00320     }
    00321
    00322     *this->buf++ = b;
    00323   }
    00324
    00329   void Flush(SaveFilter *writer)
    00330   {
    00331     uint i = 0;
    00332     size_t t = this->GetSize();
    00333
    00334     while (t > 0) {
    00335       size_t to_write = min(MEMORY_CHUNK_SIZE, t);
    00336
    00337       writer->Write(this->blocks[i++], to_write);
    00338       t -= to_write;
    00339     }
    00340
    00341     writer->Finish();
    00342   }
    00343
    00348   size_t GetSize() const
    00349   {
    00350     return this->blocks.Length() * MEMORY_CHUNK_SIZE - (this->bufe - this->buf);
    00351   }
    00352 };
    00353
    00355 struct SaveLoadParams {
    00356   SaveLoadAction action;
    00357   NeedLength need_length;
    00358   byte block_mode;
    00359   bool error;
    00360
    00361   size_t obj_len;
    00362   int array_index, last_array_index;
    00363
    00364   MemoryDumper *dumper;
    00365   SaveFilter *sf;
    00366
    00367   ReadBuffer *reader;
    00368   LoadFilter *lf;
    00369
    00370   StringID error_str;
    00371   char *extra_msg;
    00372
    00373   byte ff_state;
    00374   bool saveinprogress;
    00375 };
    00376
    00377 static SaveLoadParams _sl;
    00378
    00379 /* these define the chunks */
    00380 extern const ChunkHandler _gamelog_chunk_handlers[];
    00381 extern const ChunkHandler _map_chunk_handlers[];
    00382 extern const ChunkHandler _misc_chunk_handlers[];
    00383 extern const ChunkHandler _name_chunk_handlers[];
    00384 extern const ChunkHandler _cheat_chunk_handlers[] ;
    00385 extern const ChunkHandler _setting_chunk_handlers[];
    00386 extern const ChunkHandler _company_chunk_handlers[];
    00387 extern const ChunkHandler _engine_chunk_handlers[];
    00388 extern const ChunkHandler _veh_chunk_handlers[];
    00389 extern const ChunkHandler _waypoint_chunk_handlers[];
    00390 extern const ChunkHandler _depot_chunk_handlers[];
    00391 extern const ChunkHandler _order_chunk_handlers[];
    00392 extern const ChunkHandler _town_chunk_handlers[];
    00393 extern const ChunkHandler _sign_chunk_handlers[];
    00394 extern const ChunkHandler _station_chunk_handlers[];
    00395 extern const ChunkHandler _industry_chunk_handlers[];
    00396 extern const ChunkHandler _economy_chunk_handlers[];
    00397 extern const ChunkHandler _subsidy_chunk_handlers[];
    00398 extern const ChunkHandler _ai_chunk_handlers[];
    00399 extern const ChunkHandler _animated_tile_chunk_handlers[];
    00400 extern const ChunkHandler _newgrf_chunk_handlers[];
    00401 extern const ChunkHandler _group_chunk_handlers[];
    00402 extern const ChunkHandler _cargopacket_chunk_handlers[];
    00403 extern const ChunkHandler _autoreplace_chunk_handlers[];
    00404 extern const ChunkHandler _labelmaps_chunk_handlers[];
    00405 extern const ChunkHandler _airport_chunk_handlers[];
    00406 extern const ChunkHandler _object_chunk_handlers[];
    00407
    00409 static const ChunkHandler * const _chunk_handlers[] = {
    00410   _gamelog_chunk_handlers,
    00411   _map_chunk_handlers,
    00412   _misc_chunk_handlers,
    00413   _name_chunk_handlers,
    00414   _cheat_chunk_handlers,
    00415   _setting_chunk_handlers,
    00416   _veh_chunk_handlers,
    00417   _waypoint_chunk_handlers,
    00418   _depot_chunk_handlers,
    00419   _order_chunk_handlers,
    00420   _industry_chunk_handlers,
    00421   _economy_chunk_handlers,
    00422   _subsidy_chunk_handlers,
    00423   _engine_chunk_handlers,
    00424   _town_chunk_handlers,
    00425   _sign_chunk_handlers,
    00426   _station_chunk_handlers,
    00427   _company_chunk_handlers,
    00428   _ai_chunk_handlers,
    00429   _animated_tile_chunk_handlers,
    00430   _newgrf_chunk_handlers,
    00431   _group_chunk_handlers,
    00432   _cargopacket_chunk_handlers,
    00433   _autoreplace_chunk_handlers,
    00434   _labelmaps_chunk_handlers,
    00435   _airport_chunk_handlers,
    00436   _object_chunk_handlers,
    00437   NULL,
    00438 };
    00439
    00444 #define FOR_ALL_CHUNK_HANDLERS(ch) \
    00445   for (const ChunkHandler * const *chsc = _chunk_handlers; *chsc != NULL; chsc++) \
    00446     for (const ChunkHandler *ch = *chsc; ch != NULL; ch = (ch->flags & CH_LAST) ? NULL : ch + 1)
    00447
    00449 static void SlNullPointers()
    00450 {
    00451   _sl.action = SLA_NULL;
    00452
    00453   /* We don't want any savegame conversion code to run
    00454    * during NULLing; especially those that try to get
    00455    * pointers from other pools. */
    00456   _sl_version = SAVEGAME_VERSION;
    00457
    00458   DEBUG(sl, 1, "Nulling pointers");
    00459
    00460   FOR_ALL_CHUNK_HANDLERS(ch) {
    00461     if (ch->ptrs_proc != NULL) {
    00462       DEBUG(sl, 2, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    00463       ch->ptrs_proc();
    00464     }
    00465   }
    00466
    00467   DEBUG(sl, 1, "All pointers nulled");
    00468
    00469   assert(_sl.action == SLA_NULL);
    00470 }
    00471
    00480 void NORETURN SlError(StringID string, const char *extra_msg)
    00481 {
    00482   /* Distinguish between loading into _load_check_data vs. normal save/load. */
    00483   if (_sl.action == SLA_LOAD_CHECK) {
    00484     _load_check_data.error = string;
    00485     free(_load_check_data.error_data);
    00486     _load_check_data.error_data = (extra_msg == NULL) ? NULL : strdup(extra_msg);
    00487   } else {
    00488     _sl.error_str = string;
    00489     free(_sl.extra_msg);
    00490     _sl.extra_msg = (extra_msg == NULL) ? NULL : strdup(extra_msg);
    00491     /* We have to NULL all pointers here; we might be in a state where
    00492      * the pointers are actually filled with indices, which means that
    00493      * when we access them during cleaning the pool dereferences of
    00494      * those indices will be made with segmentation faults as result. */
    00495   }
    00496   if (_sl.action == SLA_LOAD || _sl.action == SLA_PTRS) SlNullPointers();
    00497   throw std::exception();
    00498 }
    00499
    00507 void NORETURN SlErrorCorrupt(const char *msg)
    00508 {
    00509   SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
    00510 }
    00511
    00512
    00513 typedef void (*AsyncSaveFinishProc)();
    00514 static AsyncSaveFinishProc _async_save_finish = NULL;
    00515 static ThreadObject *_save_thread;
    00516
    00521 static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
    00522 {
    00523   if (_exit_game) return;
    00524   while (_async_save_finish != NULL) CSleep(10);
    00525
    00526   _async_save_finish = proc;
    00527 }
    00528
    00532 void ProcessAsyncSaveFinish()
    00533 {
    00534   if (_async_save_finish == NULL) return;
    00535
    00536   _async_save_finish();
    00537
    00538   _async_save_finish = NULL;
    00539
    00540   if (_save_thread != NULL) {
    00541     _save_thread->Join();
    00542     delete _save_thread;
    00543     _save_thread = NULL;
    00544   }
    00545 }
    00546
    00551 byte SlReadByte()
    00552 {
    00553   return _sl.reader->ReadByte();
    00554 }
    00555
    00560 void SlWriteByte(byte b)
    00561 {
    00562   _sl.dumper->WriteByte(b);
    00563 }
    00564
    00565 static inline int SlReadUint16()
    00566 {
    00567   int x = SlReadByte() << 8;
    00568   return x | SlReadByte();
    00569 }
    00570
    00571 static inline uint32 SlReadUint32()
    00572 {
    00573   uint32 x = SlReadUint16() << 16;
    00574   return x | SlReadUint16();
    00575 }
    00576
    00577 static inline uint64 SlReadUint64()
    00578 {
    00579   uint32 x = SlReadUint32();
    00580   uint32 y = SlReadUint32();
    00581   return (uint64)x << 32 | y;
    00582 }
    00583
    00584 static inline void SlWriteUint16(uint16 v)
    00585 {
    00586   SlWriteByte(GB(v, 8, 8));
    00587   SlWriteByte(GB(v, 0, 8));
    00588 }
    00589
    00590 static inline void SlWriteUint32(uint32 v)
    00591 {
    00592   SlWriteUint16(GB(v, 16, 16));
    00593   SlWriteUint16(GB(v,  0, 16));
    00594 }
    00595
    00596 static inline void SlWriteUint64(uint64 x)
    00597 {
    00598   SlWriteUint32((uint32)(x >> 32));
    00599   SlWriteUint32((uint32)x);
    00600 }
    00601
    00607 static inline void SlSkipBytes(size_t length)
    00608 {
    00609   for (; length != 0; length--) SlReadByte();
    00610 }
    00611
    00621 static uint SlReadSimpleGamma()
    00622 {
    00623   uint i = SlReadByte();
    00624   if (HasBit(i, 7)) {
    00625     i &= ~0x80;
    00626     if (HasBit(i, 6)) {
    00627       i &= ~0x40;
    00628       if (HasBit(i, 5)) {
    00629         i &= ~0x20;
    00630         if (HasBit(i, 4)) {
    00631           SlErrorCorrupt("Unsupported gamma");
    00632         }
    00633         i = (i << 8) | SlReadByte();
    00634       }
    00635       i = (i << 8) | SlReadByte();
    00636     }
    00637     i = (i << 8) | SlReadByte();
    00638   }
    00639   return i;
    00640 }
    00641
    00654 static void SlWriteSimpleGamma(size_t i)
    00655 {
    00656   if (i >= (1 << 7)) {
    00657     if (i >= (1 << 14)) {
    00658       if (i >= (1 << 21)) {
    00659         assert(i < (1 << 28));
    00660         SlWriteByte((byte)(0xE0 | (i >> 24)));
    00661         SlWriteByte((byte)(i >> 16));
    00662       } else {
    00663         SlWriteByte((byte)(0xC0 | (i >> 16)));
    00664       }
    00665       SlWriteByte((byte)(i >> 8));
    00666     } else {
    00667       SlWriteByte((byte)(0x80 | (i >> 8)));
    00668     }
    00669   }
    00670   SlWriteByte((byte)i);
    00671 }
    00672
    00674 static inline uint SlGetGammaLength(size_t i)
    00675 {
    00676   return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21));
    00677 }
    00678
    00679 static inline uint SlReadSparseIndex()
    00680 {
    00681   return SlReadSimpleGamma();
    00682 }
    00683
    00684 static inline void SlWriteSparseIndex(uint index)
    00685 {
    00686   SlWriteSimpleGamma(index);
    00687 }
    00688
    00689 static inline uint SlReadArrayLength()
    00690 {
    00691   return SlReadSimpleGamma();
    00692 }
    00693
    00694 static inline void SlWriteArrayLength(size_t length)
    00695 {
    00696   SlWriteSimpleGamma(length);
    00697 }
    00698
    00699 static inline uint SlGetArrayLength(size_t length)
    00700 {
    00701   return SlGetGammaLength(length);
    00702 }
    00703
    00710 static inline uint SlCalcConvMemLen(VarType conv)
    00711 {
    00712   static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
    00713   byte length = GB(conv, 4, 4);
    00714
    00715   switch (length << 4) {
    00716     case SLE_VAR_STRB:
    00717     case SLE_VAR_STRBQ:
    00718     case SLE_VAR_STR:
    00719     case SLE_VAR_STRQ:
    00720       return SlReadArrayLength();
    00721
    00722     default:
    00723       assert(length < lengthof(conv_mem_size));
    00724       return conv_mem_size[length];
    00725   }
    00726 }
    00727
    00734 static inline byte SlCalcConvFileLen(VarType conv)
    00735 {
    00736   static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
    00737   byte length = GB(conv, 0, 4);
    00738   assert(length < lengthof(conv_file_size));
    00739   return conv_file_size[length];
    00740 }
    00741
    00743 static inline size_t SlCalcRefLen()
    00744 {
    00745   return IsSavegameVersionBefore(69) ? 2 : 4;
    00746 }
    00747
    00748 void SlSetArrayIndex(uint index)
    00749 {
    00750   _sl.need_length = NL_WANTLENGTH;
    00751   _sl.array_index = index;
    00752 }
    00753
    00754 static size_t _next_offs;
    00755
    00760 int SlIterateArray()
    00761 {
    00762   int index;
    00763
    00764   /* After reading in the whole array inside the loop
    00765    * we must have read in all the data, so we must be at end of current block. */
    00766   if (_next_offs != 0 && _sl.reader->GetSize() != _next_offs) SlErrorCorrupt("Invalid chunk size");
    00767
    00768   while (true) {
    00769     uint length = SlReadArrayLength();
    00770     if (length == 0) {
    00771       _next_offs = 0;
    00772       return -1;
    00773     }
    00774
    00775     _sl.obj_len = --length;
    00776     _next_offs = _sl.reader->GetSize() + length;
    00777
    00778     switch (_sl.block_mode) {
    00779       case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
    00780       case CH_ARRAY:        index = _sl.array_index++; break;
    00781       default:
    00782         DEBUG(sl, 0, "SlIterateArray error");
    00783         return -1; // error
    00784     }
    00785
    00786     if (length != 0) return index;
    00787   }
    00788 }
    00789
    00793 void SlSkipArray()
    00794 {
    00795   while (SlIterateArray() != -1) {
    00796     SlSkipBytes(_next_offs - _sl.reader->GetSize());
    00797   }
    00798 }
    00799
    00805 void SlSetLength(size_t length)
    00806 {
    00807   assert(_sl.action == SLA_SAVE);
    00808
    00809   switch (_sl.need_length) {
    00810     case NL_WANTLENGTH:
    00811       _sl.need_length = NL_NONE;
    00812       switch (_sl.block_mode) {
    00813         case CH_RIFF:
    00814           /* Ugly encoding of >16M RIFF chunks
    00815            * The lower 24 bits are normal
    00816            * The uppermost 4 bits are bits 24:27 */
    00817           assert(length < (1 << 28));
    00818           SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
    00819           break;
    00820         case CH_ARRAY:
    00821           assert(_sl.last_array_index <= _sl.array_index);
    00822           while (++_sl.last_array_index <= _sl.array_index) {
    00823             SlWriteArrayLength(1);
    00824           }
    00825           SlWriteArrayLength(length + 1);
    00826           break;
    00827         case CH_SPARSE_ARRAY:
    00828           SlWriteArrayLength(length + 1 + SlGetArrayLength(_sl.array_index)); // Also include length of sparse index.
    00829           SlWriteSparseIndex(_sl.array_index);
    00830           break;
    00831         default: NOT_REACHED();
    00832       }
    00833       break;
    00834
    00835     case NL_CALCLENGTH:
    00836       _sl.obj_len += (int)length;
    00837       break;
    00838
    00839     default: NOT_REACHED();
    00840   }
    00841 }
    00842
    00849 static void SlCopyBytes(void *ptr, size_t length)
    00850 {
    00851   byte *p = (byte *)ptr;
    00852
    00853   switch (_sl.action) {
    00854     case SLA_LOAD_CHECK:
    00855     case SLA_LOAD:
    00856       for (; length != 0; length--) *p++ = SlReadByte();
    00857       break;
    00858     case SLA_SAVE:
    00859       for (; length != 0; length--) SlWriteByte(*p++);
    00860       break;
    00861     default: NOT_REACHED();
    00862   }
    00863 }
    00864
    00866 size_t SlGetFieldLength()
    00867 {
    00868   return _sl.obj_len;
    00869 }
    00870
    00878 int64 ReadValue(const void *ptr, VarType conv)
    00879 {
    00880   switch (GetVarMemType(conv)) {
    00881     case SLE_VAR_BL:  return (*(bool *)ptr != 0);
    00882     case SLE_VAR_I8:  return *(int8  *)ptr;
    00883     case SLE_VAR_U8:  return *(byte  *)ptr;
    00884     case SLE_VAR_I16: return *(int16 *)ptr;
    00885     case SLE_VAR_U16: return *(uint16*)ptr;
    00886     case SLE_VAR_I32: return *(int32 *)ptr;
    00887     case SLE_VAR_U32: return *(uint32*)ptr;
    00888     case SLE_VAR_I64: return *(int64 *)ptr;
    00889     case SLE_VAR_U64: return *(uint64*)ptr;
    00890     case SLE_VAR_NULL:return 0;
    00891     default: NOT_REACHED();
    00892   }
    00893 }
    00894
    00902 void WriteValue(void *ptr, VarType conv, int64 val)
    00903 {
    00904   switch (GetVarMemType(conv)) {
    00905     case SLE_VAR_BL:  *(bool  *)ptr = (val != 0);  break;
    00906     case SLE_VAR_I8:  *(int8  *)ptr = val; break;
    00907     case SLE_VAR_U8:  *(byte  *)ptr = val; break;
    00908     case SLE_VAR_I16: *(int16 *)ptr = val; break;
    00909     case SLE_VAR_U16: *(uint16*)ptr = val; break;
    00910     case SLE_VAR_I32: *(int32 *)ptr = val; break;
    00911     case SLE_VAR_U32: *(uint32*)ptr = val; break;
    00912     case SLE_VAR_I64: *(int64 *)ptr = val; break;
    00913     case SLE_VAR_U64: *(uint64*)ptr = val; break;
    00914     case SLE_VAR_NAME: *(char**)ptr = CopyFromOldName(val); break;
    00915     case SLE_VAR_NULL: break;
    00916     default: NOT_REACHED();
    00917   }
    00918 }
    00919
    00928 static void SlSaveLoadConv(void *ptr, VarType conv)
    00929 {
    00930   switch (_sl.action) {
    00931     case SLA_SAVE: {
    00932       int64 x = ReadValue(ptr, conv);
    00933
    00934       /* Write the value to the file and check if its value is in the desired range */
    00935       switch (GetVarFileType(conv)) {
    00936         case SLE_FILE_I8: assert(x >= -128 && x <= 127);     SlWriteByte(x);break;
    00937         case SLE_FILE_U8: assert(x >= 0 && x <= 255);        SlWriteByte(x);break;
    00938         case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break;
    00939         case SLE_FILE_STRINGID:
    00940         case SLE_FILE_U16:assert(x >= 0 && x <= 65535);      SlWriteUint16(x);break;
    00941         case SLE_FILE_I32:
    00942         case SLE_FILE_U32:                                   SlWriteUint32((uint32)x);break;
    00943         case SLE_FILE_I64:
    00944         case SLE_FILE_U64:                                   SlWriteUint64(x);break;
    00945         default: NOT_REACHED();
    00946       }
    00947       break;
    00948     }
    00949     case SLA_LOAD_CHECK:
    00950     case SLA_LOAD: {
    00951       int64 x;
    00952       /* Read a value from the file */
    00953       switch (GetVarFileType(conv)) {
    00954         case SLE_FILE_I8:  x = (int8  )SlReadByte();   break;
    00955         case SLE_FILE_U8:  x = (byte  )SlReadByte();   break;
    00956         case SLE_FILE_I16: x = (int16 )SlReadUint16(); break;
    00957         case SLE_FILE_U16: x = (uint16)SlReadUint16(); break;
    00958         case SLE_FILE_I32: x = (int32 )SlReadUint32(); break;
    00959         case SLE_FILE_U32: x = (uint32)SlReadUint32(); break;
    00960         case SLE_FILE_I64: x = (int64 )SlReadUint64(); break;
    00961         case SLE_FILE_U64: x = (uint64)SlReadUint64(); break;
    00962         case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break;
    00963         default: NOT_REACHED();
    00964       }
    00965
    00966       /* Write The value to the struct. These ARE endian safe. */
    00967       WriteValue(ptr, conv, x);
    00968       break;
    00969     }
    00970     case SLA_PTRS: break;
    00971     case SLA_NULL: break;
    00972     default: NOT_REACHED();
    00973   }
    00974 }
    00975
    00985 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
    00986 {
    00987   if (ptr == NULL) return 0;
    00988   return min(strlen(ptr), length - 1);
    00989 }
    00990
    01000 static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
    01001 {
    01002   size_t len;
    01003   const char *str;
    01004
    01005   switch (GetVarMemType(conv)) {
    01006     default: NOT_REACHED();
    01007     case SLE_VAR_STR:
    01008     case SLE_VAR_STRQ:
    01009       str = *(const char**)ptr;
    01010       len = SIZE_MAX;
    01011       break;
    01012     case SLE_VAR_STRB:
    01013     case SLE_VAR_STRBQ:
    01014       str = (const char*)ptr;
    01015       len = length;
    01016       break;
    01017   }
    01018
    01019   len = SlCalcNetStringLen(str, len);
    01020   return len + SlGetArrayLength(len); // also include the length of the index
    01021 }
    01022
    01029 static void SlString(void *ptr, size_t length, VarType conv)
    01030 {
    01031   switch (_sl.action) {
    01032     case SLA_SAVE: {
    01033       size_t len;
    01034       switch (GetVarMemType(conv)) {
    01035         default: NOT_REACHED();
    01036         case SLE_VAR_STRB:
    01037         case SLE_VAR_STRBQ:
    01038           len = SlCalcNetStringLen((char *)ptr, length);
    01039           break;
    01040         case SLE_VAR_STR:
    01041         case SLE_VAR_STRQ:
    01042           ptr = *(char **)ptr;
    01043           len = SlCalcNetStringLen((char *)ptr, SIZE_MAX);
    01044           break;
    01045       }
    01046
    01047       SlWriteArrayLength(len);
    01048       SlCopyBytes(ptr, len);
    01049       break;
    01050     }
    01051     case SLA_LOAD_CHECK:
    01052     case SLA_LOAD: {
    01053       size_t len = SlReadArrayLength();
    01054
    01055       switch (GetVarMemType(conv)) {
    01056         default: NOT_REACHED();
    01057         case SLE_VAR_STRB:
    01058         case SLE_VAR_STRBQ:
    01059           if (len >= length) {
    01060             DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
    01061             SlCopyBytes(ptr, length);
    01062             SlSkipBytes(len - length);
    01063             len = length - 1;
    01064           } else {
    01065             SlCopyBytes(ptr, len);
    01066           }
    01067           break;
    01068         case SLE_VAR_STR:
    01069         case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate
    01070           free(*(char **)ptr);
    01071           if (len == 0) {
    01072             *(char **)ptr = NULL;
    01073           } else {
    01074             *(char **)ptr = MallocT<char>(len + 1); // terminating '\0'
    01075             ptr = *(char **)ptr;
    01076             SlCopyBytes(ptr, len);
    01077           }
    01078           break;
    01079       }
    01080
    01081       ((char *)ptr)[len] = '\0'; // properly terminate the string
    01082       str_validate((char *)ptr, (char *)ptr + len);
    01083       break;
    01084     }
    01085     case SLA_PTRS: break;
    01086     case SLA_NULL: break;
    01087     default: NOT_REACHED();
    01088   }
    01089 }
    01090
    01096 static inline size_t SlCalcArrayLen(size_t length, VarType conv)
    01097 {
    01098   return SlCalcConvFileLen(conv) * length;
    01099 }
    01100
    01107 void SlArray(void *array, size_t length, VarType conv)
    01108 {
    01109   if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
    01110
    01111   /* Automatically calculate the length? */
    01112   if (_sl.need_length != NL_NONE) {
    01113     SlSetLength(SlCalcArrayLen(length, conv));
    01114     /* Determine length only? */
    01115     if (_sl.need_length == NL_CALCLENGTH) return;
    01116   }
    01117
    01118   /* NOTICE - handle some buggy stuff, in really old versions everything was saved
    01119    * as a byte-type. So detect this, and adjust array size accordingly */
    01120   if (_sl.action != SLA_SAVE && _sl_version == 0) {
    01121     /* all arrays except difficulty settings */
    01122     if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
    01123         conv == SLE_INT32 || conv == SLE_UINT32) {
    01124       SlCopyBytes(array, length * SlCalcConvFileLen(conv));
    01125       return;
    01126     }
    01127     /* used for conversion of Money 32bit->64bit */
    01128     if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
    01129       for (uint i = 0; i < length; i++) {
    01130         ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
    01131       }
    01132       return;
    01133     }
    01134   }
    01135
    01136   /* If the size of elements is 1 byte both in file and memory, no special
    01137    * conversion is needed, use specialized copy-copy function to speed up things */
    01138   if (conv == SLE_INT8 || conv == SLE_UINT8) {
    01139     SlCopyBytes(array, length);
    01140   } else {
    01141     byte *a = (byte*)array;
    01142     byte mem_size = SlCalcConvMemLen(conv);
    01143
    01144     for (; length != 0; length --) {
    01145       SlSaveLoadConv(a, conv);
    01146       a += mem_size; // get size
    01147     }
    01148   }
    01149 }
    01150
    01151
    01162 static size_t ReferenceToInt(const void *obj, SLRefType rt)
    01163 {
    01164   assert(_sl.action == SLA_SAVE);
    01165
    01166   if (obj == NULL) return 0;
    01167
    01168   switch (rt) {
    01169     case REF_VEHICLE_OLD: // Old vehicles we save as new onces
    01170     case REF_VEHICLE:   return ((const  Vehicle*)obj)->index + 1;
    01171     case REF_STATION:   return ((const  Station*)obj)->index + 1;
    01172     case REF_TOWN:      return ((const     Town*)obj)->index + 1;
    01173     case REF_ORDER:     return ((const    Order*)obj)->index + 1;
    01174     case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
    01175     case REF_ENGINE_RENEWS: return ((const EngineRenew*)obj)->index + 1;
    01176     case REF_CARGO_PACKET:  return ((const CargoPacket*)obj)->index + 1;
    01177     case REF_ORDERLIST:     return ((const   OrderList*)obj)->index + 1;
    01178     default: NOT_REACHED();
    01179   }
    01180 }
    01181
    01192 static void *IntToReference(size_t index, SLRefType rt)
    01193 {
    01194   assert_compile(sizeof(size_t) <= sizeof(void *));
    01195
    01196   assert(_sl.action == SLA_PTRS);
    01197
    01198   /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE,
    01199    * and should be loaded like that */
    01200   if (rt == REF_VEHICLE_OLD && !IsSavegameVersionBefore(4, 4)) {
    01201     rt = REF_VEHICLE;
    01202   }
    01203
    01204   /* No need to look up NULL pointers, just return immediately */
    01205   if (index == (rt == REF_VEHICLE_OLD ? 0xFFFF : 0)) return NULL;
    01206
    01207   /* Correct index. Old vehicles were saved differently:
    01208    * invalid vehicle was 0xFFFF, now we use 0x0000 for everything invalid. */
    01209   if (rt != REF_VEHICLE_OLD) index--;
    01210
    01211   switch (rt) {
    01212     case REF_ORDERLIST:
    01213       if (OrderList::IsValidID(index)) return OrderList::Get(index);
    01214       SlErrorCorrupt("Referencing invalid OrderList");
    01215
    01216     case REF_ORDER:
    01217       if (Order::IsValidID(index)) return Order::Get(index);
    01218       /* in old versions, invalid order was used to mark end of order list */
    01219       if (IsSavegameVersionBefore(5, 2)) return NULL;
    01220       SlErrorCorrupt("Referencing invalid Order");
    01221
    01222     case REF_VEHICLE_OLD:
    01223     case REF_VEHICLE:
    01224       if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
    01225       SlErrorCorrupt("Referencing invalid Vehicle");
    01226
    01227     case REF_STATION:
    01228       if (Station::IsValidID(index)) return Station::Get(index);
    01229       SlErrorCorrupt("Referencing invalid Station");
    01230
    01231     case REF_TOWN:
    01232       if (Town::IsValidID(index)) return Town::Get(index);
    01233       SlErrorCorrupt("Referencing invalid Town");
    01234
    01235     case REF_ROADSTOPS:
    01236       if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
    01237       SlErrorCorrupt("Referencing invalid RoadStop");
    01238
    01239     case REF_ENGINE_RENEWS:
    01240       if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
    01241       SlErrorCorrupt("Referencing invalid EngineRenew");
    01242
    01243     case REF_CARGO_PACKET:
    01244       if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
    01245       SlErrorCorrupt("Referencing invalid CargoPacket");
    01246
    01247     default: NOT_REACHED();
    01248   }
    01249 }
    01250
    01255 static inline size_t SlCalcListLen(const void *list)
    01256 {
    01257   std::list<void *> *l = (std::list<void *> *) list;
    01258
    01259   int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
    01260   /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
    01261    * of the list */
    01262   return l->size() * type_size + type_size;
    01263 }
    01264
    01265
    01271 static void SlList(void *list, SLRefType conv)
    01272 {
    01273   /* Automatically calculate the length? */
    01274   if (_sl.need_length != NL_NONE) {
    01275     SlSetLength(SlCalcListLen(list));
    01276     /* Determine length only? */
    01277     if (_sl.need_length == NL_CALCLENGTH) return;
    01278   }
    01279
    01280   typedef std::list<void *> PtrList;
    01281   PtrList *l = (PtrList *)list;
    01282
    01283   switch (_sl.action) {
    01284     case SLA_SAVE: {
    01285       SlWriteUint32((uint32)l->size());
    01286
    01287       PtrList::iterator iter;
    01288       for (iter = l->begin(); iter != l->end(); ++iter) {
    01289         void *ptr = *iter;
    01290         SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
    01291       }
    01292       break;
    01293     }
    01294     case SLA_LOAD_CHECK:
    01295     case SLA_LOAD: {
    01296       size_t length = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01297
    01298       /* Load each reference and push to the end of the list */
    01299       for (size_t i = 0; i < length; i++) {
    01300         size_t data = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01301         l->push_back((void *)data);
    01302       }
    01303       break;
    01304     }
    01305     case SLA_PTRS: {
    01306       PtrList temp = *l;
    01307
    01308       l->clear();
    01309       PtrList::iterator iter;
    01310       for (iter = temp.begin(); iter != temp.end(); ++iter) {
    01311         void *ptr = IntToReference((size_t)*iter, conv);
    01312         l->push_back(ptr);
    01313       }
    01314       break;
    01315     }
    01316     case SLA_NULL:
    01317       l->clear();
    01318       break;
    01319     default: NOT_REACHED();
    01320   }
    01321 }
    01322
    01323
    01325 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
    01326 {
    01327   if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
    01328   if (sld->conv & SLF_SAVE_NO) return false;
    01329
    01330   return true;
    01331 }
    01332
    01338 static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
    01339 {
    01340   if ((sld->conv & SLF_NETWORK_NO) && _sl.action != SLA_SAVE && _networking && !_network_server) {
    01341     SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
    01342     return true;
    01343   }
    01344
    01345   return false;
    01346 }
    01347
    01354 size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
    01355 {
    01356   size_t length = 0;
    01357
    01358   /* Need to determine the length and write a length tag. */
    01359   for (; sld->cmd != SL_END; sld++) {
    01360     length += SlCalcObjMemberLength(object, sld);
    01361   }
    01362   return length;
    01363 }
    01364
    01365 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
    01366 {
    01367   assert(_sl.action == SLA_SAVE);
    01368
    01369   switch (sld->cmd) {
    01370     case SL_VAR:
    01371     case SL_REF:
    01372     case SL_ARR:
    01373     case SL_STR:
    01374     case SL_LST:
    01375       /* CONDITIONAL saveload types depend on the savegame version */
    01376       if (!SlIsObjectValidInSavegame(sld)) break;
    01377
    01378       switch (sld->cmd) {
    01379         case SL_VAR: return SlCalcConvFileLen(sld->conv);
    01380         case SL_REF: return SlCalcRefLen();
    01381         case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
    01382         case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
    01383         case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
    01384         default: NOT_REACHED();
    01385       }
    01386       break;
    01387     case SL_WRITEBYTE: return 1; // a byte is logically of size 1
    01388     case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
    01389     case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
    01390     default: NOT_REACHED();
    01391   }
    01392   return 0;
    01393 }
    01394
    01395
    01396 bool SlObjectMember(void *ptr, const SaveLoad *sld)
    01397 {
    01398   VarType conv = GB(sld->conv, 0, 8);
    01399   switch (sld->cmd) {
    01400     case SL_VAR:
    01401     case SL_REF:
    01402     case SL_ARR:
    01403     case SL_STR:
    01404     case SL_LST:
    01405       /* CONDITIONAL saveload types depend on the savegame version */
    01406       if (!SlIsObjectValidInSavegame(sld)) return false;
    01407       if (SlSkipVariableOnLoad(sld)) return false;
    01408
    01409       switch (sld->cmd) {
    01410         case SL_VAR: SlSaveLoadConv(ptr, conv); break;
    01411         case SL_REF: // Reference variable, translate
    01412           switch (_sl.action) {
    01413             case SLA_SAVE:
    01414               SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv));
    01415               break;
    01416             case SLA_LOAD_CHECK:
    01417             case SLA_LOAD:
    01418               *(size_t *)ptr = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01419               break;
    01420             case SLA_PTRS:
    01421               *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv);
    01422               break;
    01423             case SLA_NULL:
    01424               *(void **)ptr = NULL;
    01425               break;
    01426             default: NOT_REACHED();
    01427           }
    01428           break;
    01429         case SL_ARR: SlArray(ptr, sld->length, conv); break;
    01430         case SL_STR: SlString(ptr, sld->length, conv); break;
    01431         case SL_LST: SlList(ptr, (SLRefType)conv); break;
    01432         default: NOT_REACHED();
    01433       }
    01434       break;
    01435
    01436     /* SL_WRITEBYTE translates a value of a variable to another one upon
    01437      * saving or loading.
    01438      * XXX - variable renaming abuse
    01439      * game_value: the value of the variable ingame is abused by sld->version_from
    01440      * file_value: the value of the variable in the savegame is abused by sld->version_to */
    01441     case SL_WRITEBYTE:
    01442       switch (_sl.action) {
    01443         case SLA_SAVE: SlWriteByte(sld->version_to); break;
    01444         case SLA_LOAD_CHECK:
    01445         case SLA_LOAD: *(byte *)ptr = sld->version_from; break;
    01446         case SLA_PTRS: break;
    01447         case SLA_NULL: break;
    01448         default: NOT_REACHED();
    01449       }
    01450       break;
    01451
    01452     /* SL_VEH_INCLUDE loads common code for vehicles */
    01453     case SL_VEH_INCLUDE:
    01454       SlObject(ptr, GetVehicleDescription(VEH_END));
    01455       break;
    01456
    01457     case SL_ST_INCLUDE:
    01458       SlObject(ptr, GetBaseStationDescription());
    01459       break;
    01460
    01461     default: NOT_REACHED();
    01462   }
    01463   return true;
    01464 }
    01465
    01471 void SlObject(void *object, const SaveLoad *sld)
    01472 {
    01473   /* Automatically calculate the length? */
    01474   if (_sl.need_length != NL_NONE) {
    01475     SlSetLength(SlCalcObjLength(object, sld));
    01476     if (_sl.need_length == NL_CALCLENGTH) return;
    01477   }
    01478
    01479   for (; sld->cmd != SL_END; sld++) {
    01480     void *ptr = sld->global ? sld->address : GetVariableAddress(object, sld);
    01481     SlObjectMember(ptr, sld);
    01482   }
    01483 }
    01484
    01489 void SlGlobList(const SaveLoadGlobVarList *sldg)
    01490 {
    01491   SlObject(NULL, (const SaveLoad*)sldg);
    01492 }
    01493
    01499 void SlAutolength(AutolengthProc *proc, void *arg)
    01500 {
    01501   size_t offs;
    01502
    01503   assert(_sl.action == SLA_SAVE);
    01504
    01505   /* Tell it to calculate the length */
    01506   _sl.need_length = NL_CALCLENGTH;
    01507   _sl.obj_len = 0;
    01508   proc(arg);
    01509
    01510   /* Setup length */
    01511   _sl.need_length = NL_WANTLENGTH;
    01512   SlSetLength(_sl.obj_len);
    01513
    01514   offs = _sl.dumper->GetSize() + _sl.obj_len;
    01515
    01516   /* And write the stuff */
    01517   proc(arg);
    01518
    01519   if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
    01520 }
    01521
    01526 static void SlLoadChunk(const ChunkHandler *ch)
    01527 {
    01528   byte m = SlReadByte();
    01529   size_t len;
    01530   size_t endoffs;
    01531
    01532   _sl.block_mode = m;
    01533   _sl.obj_len = 0;
    01534
    01535   switch (m) {
    01536     case CH_ARRAY:
    01537       _sl.array_index = 0;
    01538       ch->load_proc();
    01539       break;
    01540     case CH_SPARSE_ARRAY:
    01541       ch->load_proc();
    01542       break;
    01543     default:
    01544       if ((m & 0xF) == CH_RIFF) {
    01545         /* Read length */
    01546         len = (SlReadByte() << 16) | ((m >> 4) << 24);
    01547         len += SlReadUint16();
    01548         _sl.obj_len = len;
    01549         endoffs = _sl.reader->GetSize() + len;
    01550         ch->load_proc();
    01551         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
    01552       } else {
    01553         SlErrorCorrupt("Invalid chunk type");
    01554       }
    01555       break;
    01556   }
    01557 }
    01558
    01564 static void SlLoadCheckChunk(const ChunkHandler *ch)
    01565 {
    01566   byte m = SlReadByte();
    01567   size_t len;
    01568   size_t endoffs;
    01569
    01570   _sl.block_mode = m;
    01571   _sl.obj_len = 0;
    01572
    01573   switch (m) {
    01574     case CH_ARRAY:
    01575       _sl.array_index = 0;
    01576       if (ch->load_check_proc) {
    01577         ch->load_check_proc();
    01578       } else {
    01579         SlSkipArray();
    01580       }
    01581       break;
    01582     case CH_SPARSE_ARRAY:
    01583       if (ch->load_check_proc) {
    01584         ch->load_check_proc();
    01585       } else {
    01586         SlSkipArray();
    01587       }
    01588       break;
    01589     default:
    01590       if ((m & 0xF) == CH_RIFF) {
    01591         /* Read length */
    01592         len = (SlReadByte() << 16) | ((m >> 4) << 24);
    01593         len += SlReadUint16();
    01594         _sl.obj_len = len;
    01595         endoffs = _sl.reader->GetSize() + len;
    01596         if (ch->load_check_proc) {
    01597           ch->load_check_proc();
    01598         } else {
    01599           SlSkipBytes(len);
    01600         }
    01601         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
    01602       } else {
    01603         SlErrorCorrupt("Invalid chunk type");
    01604       }
    01605       break;
    01606   }
    01607 }
    01608
    01613 static ChunkSaveLoadProc *_stub_save_proc;
    01614
    01620 static inline void SlStubSaveProc2(void *arg)
    01621 {
    01622   _stub_save_proc();
    01623 }
    01624
    01630 static void SlStubSaveProc()
    01631 {
    01632   SlAutolength(SlStubSaveProc2, NULL);
    01633 }
    01634
    01640 static void SlSaveChunk(const ChunkHandler *ch)
    01641 {
    01642   ChunkSaveLoadProc *proc = ch->save_proc;
    01643
    01644   /* Don't save any chunk information if there is no save handler. */
    01645   if (proc == NULL) return;
    01646
    01647   SlWriteUint32(ch->id);
    01648   DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    01649
    01650   if (ch->flags & CH_AUTO_LENGTH) {
    01651     /* Need to calculate the length. Solve that by calling SlAutoLength in the save_proc. */
    01652     _stub_save_proc = proc;
    01653     proc = SlStubSaveProc;
    01654   }
    01655
    01656   _sl.block_mode = ch->flags & CH_TYPE_MASK;
    01657   switch (ch->flags & CH_TYPE_MASK) {
    01658     case CH_RIFF:
    01659       _sl.need_length = NL_WANTLENGTH;
    01660       proc();
    01661       break;
    01662     case CH_ARRAY:
    01663       _sl.last_array_index = 0;
    01664       SlWriteByte(CH_ARRAY);
    01665       proc();
    01666       SlWriteArrayLength(0); // Terminate arrays
    01667       break;
    01668     case CH_SPARSE_ARRAY:
    01669       SlWriteByte(CH_SPARSE_ARRAY);
    01670       proc();
    01671       SlWriteArrayLength(0); // Terminate arrays
    01672       break;
    01673     default: NOT_REACHED();
    01674   }
    01675 }
    01676
    01678 static void SlSaveChunks()
    01679 {
    01680   FOR_ALL_CHUNK_HANDLERS(ch) {
    01681     SlSaveChunk(ch);
    01682   }
    01683
    01684   /* Terminator */
    01685   SlWriteUint32(0);
    01686 }
    01687
    01694 static const ChunkHandler *SlFindChunkHandler(uint32 id)
    01695 {
    01696   FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch;
    01697   return NULL;
    01698 }
    01699
    01701 static void SlLoadChunks()
    01702 {
    01703   uint32 id;
    01704   const ChunkHandler *ch;
    01705
    01706   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
    01707     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
    01708
    01709     ch = SlFindChunkHandler(id);
    01710     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
    01711     SlLoadChunk(ch);
    01712   }
    01713 }
    01714
    01716 static void SlLoadCheckChunks()
    01717 {
    01718   uint32 id;
    01719   const ChunkHandler *ch;
    01720
    01721   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
    01722     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
    01723
    01724     ch = SlFindChunkHandler(id);
    01725     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
    01726     SlLoadCheckChunk(ch);
    01727   }
    01728 }
    01729
    01731 static void SlFixPointers()
    01732 {
    01733   _sl.action = SLA_PTRS;
    01734
    01735   DEBUG(sl, 1, "Fixing pointers");
    01736
    01737   FOR_ALL_CHUNK_HANDLERS(ch) {
    01738     if (ch->ptrs_proc != NULL) {
    01739       DEBUG(sl, 2, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    01740       ch->ptrs_proc();
    01741     }
    01742   }
    01743
    01744   DEBUG(sl, 1, "All pointers fixed");
    01745
    01746   assert(_sl.action == SLA_PTRS);
    01747 }
    01748
    01749
    01751 struct FileReader : LoadFilter {
    01752   FILE *file;
    01753   long begin;
    01754
    01759   FileReader(FILE *file) : LoadFilter(NULL), file(file), begin(ftell(file))
    01760   {
    01761   }
    01762
    01764   ~FileReader()
    01765   {
    01766     if (this->file != NULL) fclose(this->file);
    01767     this->file = NULL;
    01768
    01769     /* Make sure we don't double free. */
    01770     _sl.sf = NULL;
    01771   }
    01772
    01773   /* virtual */ size_t Read(byte *buf, size_t size)
    01774   {
    01775     /* We're in the process of shutting down, i.e. in "failure" mode. */
    01776     if (this->file == NULL) return 0;
    01777
    01778     return fread(buf, 1, size, this->file);
    01779   }
    01780
    01781   /* virtual */ void Reset()
    01782   {
    01783     clearerr(this->file);
    01784     fseek(this->file, this->begin, SEEK_SET);
    01785   }
    01786 };
    01787
    01789 struct FileWriter : SaveFilter {
    01790   FILE *file;
    01791
    01796   FileWriter(FILE *file) : SaveFilter(NULL), file(file)
    01797   {
    01798   }
    01799
    01801   ~FileWriter()
    01802   {
    01803     this->Finish();
    01804
    01805     /* Make sure we don't double free. */
    01806     _sl.sf = NULL;
    01807   }
    01808
    01809   /* virtual */ void Write(byte *buf, size_t size)
    01810   {
    01811     /* We're in the process of shutting down, i.e. in "failure" mode. */
    01812     if (this->file == NULL) return;
    01813
    01814     if (fwrite(buf, 1, size, this->file) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
    01815   }
    01816
    01817   /* virtual */ void Finish()
    01818   {
    01819     if (this->file != NULL) fclose(this->file);
    01820     this->file = NULL;
    01821   }
    01822 };
    01823
    01824 /*******************************************
    01825  ********** START OF LZO CODE **************
    01826  *******************************************/
    01827
    01828 #ifdef WITH_LZO
    01829 #include <lzo/lzo1x.h>
    01830
    01832 static const uint LZO_BUFFER_SIZE = 8192;
    01833
    01835 struct LZOLoadFilter : LoadFilter {
    01840   LZOLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    01841   {
    01842     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    01843   }
    01844
    01845   /* virtual */ size_t Read(byte *buf, size_t ssize)
    01846   {
    01847     assert(ssize >= LZO_BUFFER_SIZE);
    01848
    01849     /* Buffer size is from the LZO docs plus the chunk header size. */
    01850     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
    01851     uint32 tmp[2];
    01852     uint32 size;
    01853     lzo_uint len;
    01854
    01855     /* Read header*/
    01856     if (this->chain->Read((byte*)tmp, sizeof(tmp)) != sizeof(tmp)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE, "File read failed");
    01857
    01858     /* Check if size is bad */
    01859     ((uint32*)out)[0] = size = tmp[1];
    01860
    01861     if (_sl_version != 0) {
    01862       tmp[0] = TO_BE32(tmp[0]);
    01863       size = TO_BE32(size);
    01864     }
    01865
    01866     if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size");
    01867
    01868     /* Read block */
    01869     if (this->chain->Read(out + sizeof(uint32), size) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    01870
    01871     /* Verify checksum */
    01872     if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
    01873
    01874     /* Decompress */
    01875     lzo1x_decompress(out + sizeof(uint32) * 1, size, buf, &len, NULL);
    01876     return len;
    01877   }
    01878 };
    01879
    01881 struct LZOSaveFilter : SaveFilter {
    01887   LZOSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    01888   {
    01889     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    01890   }
    01891
    01892   /* virtual */ void Write(byte *buf, size_t size)
    01893   {
    01894     const lzo_bytep in = buf;
    01895     /* Buffer size is from the LZO docs plus the chunk header size. */
    01896     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
    01897     byte wrkmem[LZO1X_1_MEM_COMPRESS];
    01898     lzo_uint outlen;
    01899
    01900     do {
    01901       /* Compress up to LZO_BUFFER_SIZE bytes at once. */
    01902       lzo_uint len = size > LZO_BUFFER_SIZE ? LZO_BUFFER_SIZE : (lzo_uint)size;
    01903       lzo1x_1_compress(in, len, out + sizeof(uint32) * 2, &outlen, wrkmem);
    01904       ((uint32*)out)[1] = TO_BE32((uint32)outlen);
    01905       ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
    01906       this->chain->Write(out, outlen + sizeof(uint32) * 2);
    01907
    01908       /* Move to next data chunk. */
    01909       size -= len;
    01910       in += len;
    01911     } while (size > 0);
    01912   }
    01913 };
    01914
    01915 #endif /* WITH_LZO */
    01916
    01917 /*********************************************
    01918  ******** START OF NOCOMP CODE (uncompressed)*
    01919  *********************************************/
    01920
    01922 struct NoCompLoadFilter : LoadFilter {
    01927   NoCompLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    01928   {
    01929   }
    01930
    01931   /* virtual */ size_t Read(byte *buf, size_t size)
    01932   {
    01933     return this->chain->Read(buf, size);
    01934   }
    01935 };
    01936
    01938 struct NoCompSaveFilter : SaveFilter {
    01944   NoCompSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    01945   {
    01946   }
    01947
    01948   /* virtual */ void Write(byte *buf, size_t size)
    01949   {
    01950     this->chain->Write(buf, size);
    01951   }
    01952 };
    01953
    01954 /********************************************
    01955  ********** START OF ZLIB CODE **************
    01956  ********************************************/
    01957
    01958 #if defined(WITH_ZLIB)
    01959 #include <zlib.h>
    01960
    01962 struct ZlibLoadFilter : LoadFilter {
    01963   z_stream z;
    01964   byte fread_buf[MEMORY_CHUNK_SIZE];
    01965
    01970   ZlibLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    01971   {
    01972     memset(&this->z, 0, sizeof(this->z));
    01973     if (inflateInit(&this->z) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    01974   }
    01975
    01977   ~ZlibLoadFilter()
    01978   {
    01979     inflateEnd(&this->z);
    01980   }
    01981
    01982   /* virtual */ size_t Read(byte *buf, size_t size)
    01983   {
    01984     this->z.next_out  = buf;
    01985     this->z.avail_out = (uint)size;
    01986
    01987     do {
    01988       /* read more bytes from the file? */
    01989       if (this->z.avail_in == 0) {
    01990         this->z.next_in = this->fread_buf;
    01991         this->z.avail_in = (uint)this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
    01992       }
    01993
    01994       /* inflate the data */
    01995       int r = inflate(&this->z, 0);
    01996       if (r == Z_STREAM_END) break;
    01997
    01998       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "inflate() failed");
    01999     } while (this->z.avail_out != 0);
    02000
    02001     return size - this->z.avail_out;
    02002   }
    02003 };
    02004
    02006 struct ZlibSaveFilter : SaveFilter {
    02007   z_stream z;
    02008
    02014   ZlibSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    02015   {
    02016     memset(&this->z, 0, sizeof(this->z));
    02017     if (deflateInit(&this->z, compression_level) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    02018   }
    02019
    02021   ~ZlibSaveFilter()
    02022   {
    02023     deflateEnd(&this->z);
    02024   }
    02025
    02032   void WriteLoop(byte *p, size_t len, int mode)
    02033   {
    02034     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
    02035     uint n;
    02036     this->z.next_in = p;
    02037     this->z.avail_in = (uInt)len;
    02038     do {
    02039       this->z.next_out = buf;
    02040       this->z.avail_out = sizeof(buf);
    02041
    02049       int r = deflate(&this->z, mode);
    02050
    02051       /* bytes were emitted? */
    02052       if ((n = sizeof(buf) - this->z.avail_out) != 0) {
    02053         this->chain->Write(buf, n);
    02054       }
    02055       if (r == Z_STREAM_END) break;
    02056
    02057       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code");
    02058     } while (this->z.avail_in || !this->z.avail_out);
    02059   }
    02060
    02061   /* virtual */ void Write(byte *buf, size_t size)
    02062   {
    02063     this->WriteLoop(buf, size, 0);
    02064   }
    02065
    02066   /* virtual */ void Finish()
    02067   {
    02068     this->WriteLoop(NULL, 0, Z_FINISH);
    02069     this->chain->Finish();
    02070   }
    02071 };
    02072
    02073 #endif /* WITH_ZLIB */
    02074
    02075 /********************************************
    02076  ********** START OF LZMA CODE **************
    02077  ********************************************/
    02078
    02079 #if defined(WITH_LZMA)
    02080 #include <lzma.h>
    02081
    02088 static const lzma_stream _lzma_init = LZMA_STREAM_INIT;
    02089
    02091 struct LZMALoadFilter : LoadFilter {
    02092   lzma_stream lzma;
    02093   byte fread_buf[MEMORY_CHUNK_SIZE];
    02094
    02099   LZMALoadFilter(LoadFilter *chain) : LoadFilter(chain), lzma(_lzma_init)
    02100   {
    02101     /* Allow saves up to 256 MB uncompressed */
    02102     if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    02103   }
    02104
    02106   ~LZMALoadFilter()
    02107   {
    02108     lzma_end(&this->lzma);
    02109   }
    02110
    02111   /* virtual */ size_t Read(byte *buf, size_t size)
    02112   {
    02113     this->lzma.next_out  = buf;
    02114     this->lzma.avail_out = size;
    02115
    02116     do {
    02117       /* read more bytes from the file? */
    02118       if (this->lzma.avail_in == 0) {
    02119         this->lzma.next_in  = this->fread_buf;
    02120         this->lzma.avail_in = this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
    02121       }
    02122
    02123       /* inflate the data */
    02124       lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
    02125       if (r == LZMA_STREAM_END) break;
    02126       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
    02127     } while (this->lzma.avail_out != 0);
    02128
    02129     return size - this->lzma.avail_out;
    02130   }
    02131 };
    02132
    02134 struct LZMASaveFilter : SaveFilter {
    02135   lzma_stream lzma;
    02136
    02142   LZMASaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain), lzma(_lzma_init)
    02143   {
    02144     if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    02145   }
    02146
    02148   ~LZMASaveFilter()
    02149   {
    02150     lzma_end(&this->lzma);
    02151   }
    02152
    02159   void WriteLoop(byte *p, size_t len, lzma_action action)
    02160   {
    02161     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
    02162     size_t n;
    02163     this->lzma.next_in = p;
    02164     this->lzma.avail_in = len;
    02165     do {
    02166       this->lzma.next_out = buf;
    02167       this->lzma.avail_out = sizeof(buf);
    02168
    02169       lzma_ret r = lzma_code(&this->lzma, action);
    02170
    02171       /* bytes were emitted? */
    02172       if ((n = sizeof(buf) - this->lzma.avail_out) != 0) {
    02173         this->chain->Write(buf, n);
    02174       }
    02175       if (r == LZMA_STREAM_END) break;
    02176       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
    02177     } while (this->lzma.avail_in || !this->lzma.avail_out);
    02178   }
    02179
    02180   /* virtual */ void Write(byte *buf, size_t size)
    02181   {
    02182     this->WriteLoop(buf, size, LZMA_RUN);
    02183   }
    02184
    02185   /* virtual */ void Finish()
    02186   {
    02187     this->WriteLoop(NULL, 0, LZMA_FINISH);
    02188     this->chain->Finish();
    02189   }
    02190 };
    02191
    02192 #endif /* WITH_LZMA */
    02193
    02194 /*******************************************
    02195  ************* END OF CODE *****************
    02196  *******************************************/
    02197
    02199 struct SaveLoadFormat {
    02200   const char *name;
    02201   uint32 tag;
    02202
    02203   LoadFilter *(*init_load)(LoadFilter *chain);
    02204   SaveFilter *(*init_write)(SaveFilter *chain, byte compression);
    02205
    02206   byte min_compression;
    02207   byte default_compression;
    02208   byte max_compression;
    02209 };
    02210
    02212 static const SaveLoadFormat _saveload_formats[] = {
    02213 #if defined(WITH_LZO)
    02214   /* Roughly 75% larger than zlib level 6 at only ~7% of the CPU usage. */
    02215   {"lzo",    TO_BE32X('OTTD'), CreateLoadFilter<LZOLoadFilter>,    CreateSaveFilter<LZOSaveFilter>,    0, 0, 0},
    02216 #else
    02217   {"lzo",    TO_BE32X('OTTD'), NULL,                               NULL,                               0, 0, 0},
    02218 #endif
    02219   /* Roughly 5 times larger at only 1% of the CPU usage over zlib level 6. */
    02220   {"none",   TO_BE32X('OTTN'), CreateLoadFilter<NoCompLoadFilter>, CreateSaveFilter<NoCompSaveFilter>, 0, 0, 0},
    02221 #if defined(WITH_ZLIB)
    02222   /* After level 6 the speed reduction is significant (1.5x to 2.5x slower per level), but the reduction in filesize is
    02223    * fairly insignificant (~1% for each step). Lower levels become ~5-10% bigger by each level than level 6 while level
    02224    * 1 is "only" 3 times as fast. Level 0 results in uncompressed savegames at about 8 times the cost of "none". */
    02225   {"zlib",   TO_BE32X('OTTZ'), CreateLoadFilter<ZlibLoadFilter>,   CreateSaveFilter<ZlibSaveFilter>,   0, 6, 9},
    02226 #else
    02227   {"zlib",   TO_BE32X('OTTZ'), NULL,                               NULL,                               0, 0, 0},
    02228 #endif
    02229 #if defined(WITH_LZMA)
    02230   /* Level 2 compression is speed wise as fast as zlib level 6 compression (old default), but results in ~10% smaller saves.
    02231    * Higher compression levels are possible, and might improve savegame size by up to 25%, but are also up to 10 times slower.
    02232    * The next significant reduction in file size is at level 4, but that is already 4 times slower. Level 3 is primarily 50%
    02233    * slower while not improving the filesize, while level 0 and 1 are faster, but don't reduce savegame size much.
    02234    * It's OTTX and not e.g. OTTL because liblzma is part of xz-utils and .tar.xz is prefered over .tar.lzma. */
    02235   {"lzma",   TO_BE32X('OTTX'), CreateLoadFilter<LZMALoadFilter>,   CreateSaveFilter<LZMASaveFilter>,   0, 2, 9},
    02236 #else
    02237   {"lzma",   TO_BE32X('OTTX'), NULL,                               NULL,                               0, 0, 0},
    02238 #endif
    02239 };
    02240
    02248 static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
    02249 {
    02250   const SaveLoadFormat *def = lastof(_saveload_formats);
    02251
    02252   /* find default savegame format, the highest one with which files can be written */
    02253   while (!def->init_write) def--;
    02254
    02255   if (!StrEmpty(s)) {
    02256     /* Get the ":..." of the compression level out of the way */
    02257     char *complevel = strrchr(s, ':');
    02258     if (complevel != NULL) *complevel = '\0';
    02259
    02260     for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
    02261       if (slf->init_write != NULL && strcmp(s, slf->name) == 0) {
    02262         *compression_level = slf->default_compression;
    02263         if (complevel != NULL) {
    02264           /* There is a compression level in the string.
    02265            * First restore the : we removed to do proper name matching,
    02266            * then move the the begin of the actual version. */
    02267           *complevel = ':';
    02268           complevel++;
    02269
    02270           /* Get the version and determine whether all went fine. */
    02271           char *end;
    02272           long level = strtol(complevel, &end, 10);
    02273           if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) {
    02274             ShowInfoF("Compression level '%s' is not valid.", complevel);
    02275           } else {
    02276             *compression_level = level;
    02277           }
    02278         }
    02279         return slf;
    02280       }
    02281     }
    02282
    02283     ShowInfoF("Savegame format '%s' is not available. Reverting to '%s'.", s, def->name);
    02284
    02285     /* Restore the string by adding the : back */
    02286     if (complevel != NULL) *complevel = ':';
    02287   }
    02288   *compression_level = def->default_compression;
    02289   return def;
    02290 }
    02291
    02292 /* actual loader/saver function */
    02293 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings);
    02294 extern bool AfterLoadGame();
    02295 extern bool LoadOldSaveGame(const char *file);
    02296
    02300 static inline void ClearSaveLoadState()
    02301 {
    02302   delete _sl.dumper;
    02303   _sl.dumper = NULL;
    02304
    02305   delete _sl.sf;
    02306   _sl.sf = NULL;
    02307
    02308   delete _sl.reader;
    02309   _sl.reader = NULL;
    02310
    02311   delete _sl.lf;
    02312   _sl.lf = NULL;
    02313 }
    02314
    02320 static void SaveFileStart()
    02321 {
    02322   _sl.ff_state = _fast_forward;
    02323   _fast_forward = 0;
    02324   if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
    02325
    02326   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START);
    02327   _sl.saveinprogress = true;
    02328 }
    02329
    02331 static void SaveFileDone()
    02332 {
    02333   if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state;
    02334   if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
    02335
    02336   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
    02337   _sl.saveinprogress = false;
    02338 }
    02339
    02341 void SetSaveLoadError(StringID str)
    02342 {
    02343   _sl.error_str = str;
    02344 }
    02345
    02347 const char *GetSaveLoadErrorString()
    02348 {
    02349   SetDParam(0, _sl.error_str);
    02350   SetDParamStr(1, _sl.extra_msg);
    02351
    02352   static char err_str[512];
    02353   GetString(err_str, _sl.action == SLA_SAVE ? STR_ERROR_GAME_SAVE_FAILED : STR_ERROR_GAME_LOAD_FAILED, lastof(err_str));
    02354   return err_str;
    02355 }
    02356
    02358 static void SaveFileError()
    02359 {
    02360   SetDParamStr(0, GetSaveLoadErrorString());
    02361   ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
    02362   SaveFileDone();
    02363 }
    02364
    02369 static SaveOrLoadResult SaveFileToDisk(bool threaded)
    02370 {
    02371   try {
    02372     byte compression;
    02373     const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format, &compression);
    02374
    02375     /* We have written our stuff to memory, now write it to file! */
    02376     uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) };
    02377     _sl.sf->Write((byte*)hdr, sizeof(hdr));
    02378
    02379     _sl.sf = fmt->init_write(_sl.sf, compression);
    02380     _sl.dumper->Flush(_sl.sf);
    02381
    02382     ClearSaveLoadState();
    02383
    02384     if (threaded) SetAsyncSaveFinish(SaveFileDone);
    02385
    02386     return SL_OK;
    02387   } catch (...) {
    02388     ClearSaveLoadState();
    02389
    02390     AsyncSaveFinishProc asfp = SaveFileDone;
    02391
    02392     /* We don't want to shout when saving is just
    02393      * cancelled due to a client disconnecting. */
    02394     if (_sl.error_str != STR_NETWORK_ERROR_LOSTCONNECTION) {
    02395       /* Skip the "colour" character */
    02396       DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
    02397       asfp = SaveFileError;
    02398     }
    02399
    02400     if (threaded) {
    02401       SetAsyncSaveFinish(asfp);
    02402     } else {
    02403       asfp();
    02404     }
    02405     return SL_ERROR;
    02406   }
    02407 }
    02408
    02410 static void SaveFileToDiskThread(void *arg)
    02411 {
    02412   SaveFileToDisk(true);
    02413 }
    02414
    02415 void WaitTillSaved()
    02416 {
    02417   if (_save_thread == NULL) return;
    02418
    02419   _save_thread->Join();
    02420   delete _save_thread;
    02421   _save_thread = NULL;
    02422 }
    02423
    02432 static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
    02433 {
    02434   assert(!_sl.saveinprogress);
    02435
    02436   _sl.dumper = new MemoryDumper();
    02437   _sl.sf = writer;
    02438
    02439   _sl_version = SAVEGAME_VERSION;
    02440
    02441   SaveViewportBeforeSaveGame();
    02442   SlSaveChunks();
    02443
    02444   SaveFileStart();
    02445   if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
    02446     if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
    02447
    02448     SaveOrLoadResult result = SaveFileToDisk(false);
    02449     SaveFileDone();
    02450
    02451     return result;
    02452   }
    02453
    02454   return SL_OK;
    02455 }
    02456
    02463 SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
    02464 {
    02465   try {
    02466     _sl.action = SLA_SAVE;
    02467     return DoSave(writer, threaded);
    02468   } catch (...) {
    02469     ClearSaveLoadState();
    02470     return SL_ERROR;
    02471   }
    02472 }
    02473
    02480 static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
    02481 {
    02482   _sl.lf = reader;
    02483
    02484   if (load_check) {
    02485     /* Clear previous check data */
    02486     _load_check_data.Clear();
    02487     /* Mark SL_LOAD_CHECK as supported for this savegame. */
    02488     _load_check_data.checkable = true;
    02489   }
    02490
    02491   uint32 hdr[2];
    02492   if (_sl.lf->Read((byte*)hdr, sizeof(hdr)) != sizeof(hdr)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    02493
    02494   /* see if we have any loader for this type. */
    02495   const SaveLoadFormat *fmt = _saveload_formats;
    02496   for (;;) {
    02497     /* No loader found, treat as version 0 and use LZO format */
    02498     if (fmt == endof(_saveload_formats)) {
    02499       DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format");
    02500       _sl.lf->Reset();
    02501       _sl_version = 0;
    02502       _sl_minor_version = 0;
    02503
    02504       /* Try to find the LZO savegame format; it uses 'OTTD' as tag. */
    02505       fmt = _saveload_formats;
    02506       for (;;) {
    02507         if (fmt == endof(_saveload_formats)) {
    02508           /* Who removed LZO support? Bad bad boy! */
    02509           NOT_REACHED();
    02510         }
    02511         if (fmt->tag == TO_BE32X('OTTD')) break;
    02512         fmt++;
    02513       }
    02514       break;
    02515     }
    02516
    02517     if (fmt->tag == hdr[0]) {
    02518       /* check version number */
    02519       _sl_version = TO_BE32(hdr[1]) >> 16;
    02520       /* Minor is not used anymore from version 18.0, but it is still needed
    02521        * in versions before that (4 cases) which can't be removed easy.
    02522        * Therefor it is loaded, but never saved (or, it saves a 0 in any scenario).
    02523        * So never EVER use this minor version again. -- TrueLight -- 22-11-2005 */
    02524       _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
    02525
    02526       DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
    02527
    02528       /* Is the version higher than the current? */
    02529       if (_sl_version > SAVEGAME_VERSION) SlError(STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME);
    02530       break;
    02531     }
    02532
    02533     fmt++;
    02534   }
    02535
    02536   /* loader for this savegame type is not implemented? */
    02537   if (fmt->init_load == NULL) {
    02538     char err_str[64];
    02539     snprintf(err_str, lengthof(err_str), "Loader for '%s' is not available.", fmt->name);
    02540     SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
    02541   }
    02542
    02543   _sl.lf = fmt->init_load(_sl.lf);
    02544   _sl.reader = new ReadBuffer(_sl.lf);
    02545   _next_offs = 0;
    02546
    02547   if (!load_check) {
    02548     _engine_mngr.ResetToDefaultMapping();
    02549
    02550     /* Old maps were hardcoded to 256x256 and thus did not contain
    02551      * any mapsize information. Pre-initialize to 256x256 to not to
    02552      * confuse old games */
    02553     InitializeGame(256, 256, true, true);
    02554
    02555     GamelogReset();
    02556
    02557     if (IsSavegameVersionBefore(4)) {
    02558       /*
    02559        * NewGRFs were introduced between 0.3,4 and 0.3.5, which both
    02560        * shared savegame version 4. Anything before that 'obviously'
    02561        * does not have any NewGRFs. Between the introduction and
    02562        * savegame version 41 (just before 0.5) the NewGRF settings
    02563        * were not stored in the savegame and they were loaded by
    02564        * using the settings from the main menu.
    02565        * So, to recap:
    02566        * - savegame version  <  4:  do not load any NewGRFs.
    02567        * - savegame version >= 41:  load NewGRFs from savegame, which is
    02568        *                            already done at this stage by
    02569        *                            overwriting the main menu settings.
    02570        * - other savegame versions: use main menu settings.
    02571        *
    02572        * This means that users *can* crash savegame version 4..40
    02573        * savegames if they set incompatible NewGRFs in the main menu,
    02574        * but can't crash anymore for savegame version < 4 savegames.
    02575        *
    02576        * Note: this is done here because AfterLoadGame is also called
    02577        * for TTO/TTD/TTDP savegames which have their own NewGRF logic.
    02578        */
    02579       ClearGRFConfigList(&_grfconfig);
    02580     }
    02581   }
    02582
    02583   if (load_check) {
    02584     /* Load chunks into _load_check_data.
    02585      * No pools are loaded. References are not possible, and thus do not need resolving. */
    02586     SlLoadCheckChunks();
    02587   } else {
    02588     /* Load chunks and resolve references */
    02589     SlLoadChunks();
    02590     SlFixPointers();
    02591   }
    02592
    02593   ClearSaveLoadState();
    02594
    02595   _savegame_type = SGT_OTTD;
    02596
    02597   if (load_check) {
    02598     /* The only part from AfterLoadGame() we need */
    02599     _load_check_data.grf_compatibility = IsGoodGRFConfigList(_load_check_data.grfconfig);
    02600   } else {
    02601     GamelogStartAction(GLAT_LOAD);
    02602
    02603     /* After loading fix up savegame for any internal changes that
    02604      * might have occurred since then. If it fails, load back the old game. */
    02605     if (!AfterLoadGame()) {
    02606       GamelogStopAction();
    02607       return SL_REINIT;
    02608     }
    02609
    02610     GamelogStopAction();
    02611   }
    02612
    02613   return SL_OK;
    02614 }
    02615
    02621 SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
    02622 {
    02623   try {
    02624     _sl.action = SLA_LOAD;
    02625     return DoLoad(reader, false);
    02626   } catch (...) {
    02627     ClearSaveLoadState();
    02628     return SL_REINIT;
    02629   }
    02630 }
    02631
    02641 SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
    02642 {
    02643   /* An instance of saving is already active, so don't go saving again */
    02644   if (_sl.saveinprogress && mode == SL_SAVE && threaded) {
    02645     /* if not an autosave, but a user action, show error message */
    02646     if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
    02647     return SL_OK;
    02648   }
    02649   WaitTillSaved();
    02650
    02651   /* Load a TTDLX or TTDPatch game */
    02652   if (mode == SL_OLD_LOAD) {
    02653     _engine_mngr.ResetToDefaultMapping();
    02654     InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
    02655
    02656     /* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
    02657      * and if so a new NewGRF list will be made in LoadOldSaveGame.
    02658      * Note: this is done here because AfterLoadGame is also called
    02659      * for OTTD savegames which have their own NewGRF logic. */
    02660     ClearGRFConfigList(&_grfconfig);
    02661     GamelogReset();
    02662     if (!LoadOldSaveGame(filename)) return SL_REINIT;
    02663     _sl_version = 0;
    02664     _sl_minor_version = 0;
    02665     GamelogStartAction(GLAT_LOAD);
    02666     if (!AfterLoadGame()) {
    02667       GamelogStopAction();
    02668       return SL_REINIT;
    02669     }
    02670     GamelogStopAction();
    02671     return SL_OK;
    02672   }
    02673
    02674   switch (mode) {
    02675     case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
    02676     case SL_LOAD: _sl.action = SLA_LOAD; break;
    02677     case SL_SAVE: _sl.action = SLA_SAVE; break;
    02678     default: NOT_REACHED();
    02679   }
    02680
    02681   try {
    02682     FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
    02683
    02684     /* Make it a little easier to load savegames from the console */
    02685     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
    02686     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
    02687
    02688     if (fh == NULL) {
    02689       SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    02690     }
    02691
    02692     if (mode == SL_SAVE) { // SAVE game
    02693       DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
    02694       if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
    02695
    02696       return DoSave(new FileWriter(fh), threaded);
    02697     }
    02698
    02699     /* LOAD game */
    02700     assert(mode == SL_LOAD || mode == SL_LOAD_CHECK);
    02701     DEBUG(desync, 1, "load: %s", filename);
    02702     return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK);
    02703   } catch (...) {
    02704     ClearSaveLoadState();
    02705
    02706     /* Skip the "colour" character */
    02707     if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
    02708
    02709     /* A saver/loader exception!! reinitialize all variables to prevent crash! */
    02710     return (mode == SL_LOAD) ? SL_REINIT : SL_ERROR;
    02711   }
    02712 }
    02713
    02715 void DoExitSave()
    02716 {
    02717   SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
    02718 }
    02719
    02725 void GenerateDefaultSaveName(char *buf, const char *last)
    02726 {
    02727   /* Check if we have a name for this map, which is the name of the first
    02728    * available company. When there's no company available we'll use
    02729    * 'Spectator' as "company" name. */
    02730   CompanyID cid = _local_company;
    02731   if (!Company::IsValidID(cid)) {
    02732     const Company *c;
    02733     FOR_ALL_COMPANIES(c) {
    02734       cid = c->index;
    02735       break;
    02736     }
    02737   }
    02738
    02739   SetDParam(0, cid);
    02740
    02741   /* Insert current date */
    02742   switch (_settings_client.gui.date_format_in_default_names) {
    02743     case 0: SetDParam(1, STR_JUST_DATE_LONG); break;
    02744     case 1: SetDParam(1, STR_JUST_DATE_TINY); break;
    02745     case 2: SetDParam(1, STR_JUST_DATE_ISO); break;
    02746     default: NOT_REACHED();
    02747   }
    02748   SetDParam(2, _date);
    02749
    02750   /* Get the correct string (special string for when there's not company) */
    02751   GetString(buf, !Company::IsValidID(cid) ? STR_SAVEGAME_NAME_SPECTATOR : STR_SAVEGAME_NAME_DEFAULT, last);
    02752   SanitizeFilename(buf);
    02753 }
    02754
    02755 #if 0
    02756
    02762 int GetSavegameType(char *file)
    02763 {
    02764   const SaveLoadFormat *fmt;
    02765   uint32 hdr;
    02766   FILE *f;
    02767   int mode = SL_OLD_LOAD;
    02768
    02769   f = fopen(file, "rb");
    02770   if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
    02771     DEBUG(sl, 0, "Savegame is obsolete or invalid format");
    02772     mode = SL_LOAD; // don't try to get filename, just show name as it is written
    02773   } else {
    02774     /* see if we have any loader for this type. */
    02775     for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
    02776       if (fmt->tag == hdr) {
    02777         mode = SL_LOAD; // new type of savegame
    02778         break;
    02779       }
    02780     }
    02781   }
    02782
    02783   fclose(f);
    02784   return mode;
    02785 }
    02786 #endif