# 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 "../linkgraph/linkgraphjob.h"
    00039 #include "../statusbar_gui.h"
    00040 #include "../fileio_func.h"
    00041 #include "../gamelog.h"
    00042 #include "../string_func.h"
    00043 #include "../fios.h"
    00044 #include "../error.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   1.1.x
    00228  *  161   22567
    00229  *  162   22713
    00230  *  163   22767
    00231  *  164   23290
    00232  *  165   23304
    00233  *  166   23415
    00234  *  167   23504
    00235  *  168   23637
    00236  *  169   23816
    00237  *  170   23826
    00238  *  171   23835
    00239  *  172   23947
    00240  *  173   23967   1.2.0-RC1
    00241  *  174   23973   1.2.x
    00242  *  175   24136
    00243  *  176   24446
    00244  *  177   24619
    00245  *  178   24789
    00246  *  179   24810
    00247  *  180   24998   1.3.x
    00248  *  181   25012
    00249  */
    00250 extern const uint16 SAVEGAME_VERSION = SL_EXT_RATING;
    00251
    00252 SavegameType _savegame_type;
    00253
    00254 uint32 _ttdp_version;
    00255 uint16 _sl_version;
    00256 byte   _sl_minor_version;
    00257 char _savegame_format[8];
    00258 bool _do_autosave;
    00259
    00261 enum SaveLoadAction {
    00262   SLA_LOAD,
    00263   SLA_SAVE,
    00264   SLA_PTRS,
    00265   SLA_NULL,
    00266   SLA_LOAD_CHECK,
    00267 };
    00268
    00269 enum NeedLength {
    00270   NL_NONE = 0,
    00271   NL_WANTLENGTH = 1,
    00272   NL_CALCLENGTH = 2,
    00273 };
    00274
    00276 static const size_t MEMORY_CHUNK_SIZE = 128 * 1024;
    00277
    00279 struct ReadBuffer {
    00280   byte buf[MEMORY_CHUNK_SIZE];
    00281   byte *bufp;
    00282   byte *bufe;
    00283   LoadFilter *reader;
    00284   size_t read;
    00285
    00290   ReadBuffer(LoadFilter *reader) : bufp(NULL), bufe(NULL), reader(reader), read(0)
    00291   {
    00292   }
    00293
    00294   inline byte ReadByte()
    00295   {
    00296     if (this->bufp == this->bufe) {
    00297       size_t len = this->reader->Read(this->buf, lengthof(this->buf));
    00298       if (len == 0) SlErrorCorrupt("Unexpected end of chunk");
    00299
    00300       this->read += len;
    00301       this->bufp = this->buf;
    00302       this->bufe = this->buf + len;
    00303     }
    00304
    00305     return *this->bufp++;
    00306   }
    00307
    00312   size_t GetSize() const
    00313   {
    00314     return this->read - (this->bufe - this->bufp);
    00315   }
    00316 };
    00317
    00318
    00320 struct MemoryDumper {
    00321   AutoFreeSmallVector<byte *, 16> blocks;
    00322   byte *buf;
    00323   byte *bufe;
    00324
    00326   MemoryDumper() : buf(NULL), bufe(NULL)
    00327   {
    00328   }
    00329
    00334   inline void WriteByte(byte b)
    00335   {
    00336     /* Are we at the end of this chunk? */
    00337     if (this->buf == this->bufe) {
    00338       this->buf = CallocT<byte>(MEMORY_CHUNK_SIZE);
    00339       *this->blocks.Append() = this->buf;
    00340       this->bufe = this->buf + MEMORY_CHUNK_SIZE;
    00341     }
    00342
    00343     *this->buf++ = b;
    00344   }
    00345
    00350   void Flush(SaveFilter *writer)
    00351   {
    00352     uint i = 0;
    00353     size_t t = this->GetSize();
    00354
    00355     while (t > 0) {
    00356       size_t to_write = min(MEMORY_CHUNK_SIZE, t);
    00357
    00358       writer->Write(this->blocks[i++], to_write);
    00359       t -= to_write;
    00360     }
    00361
    00362     writer->Finish();
    00363   }
    00364
    00369   size_t GetSize() const
    00370   {
    00371     return this->blocks.Length() * MEMORY_CHUNK_SIZE - (this->bufe - this->buf);
    00372   }
    00373 };
    00374
    00376 struct SaveLoadParams {
    00377   SaveLoadAction action;
    00378   NeedLength need_length;
    00379   byte block_mode;
    00380   bool error;
    00381
    00382   size_t obj_len;
    00383   int array_index, last_array_index;
    00384
    00385   MemoryDumper *dumper;
    00386   SaveFilter *sf;
    00387
    00388   ReadBuffer *reader;
    00389   LoadFilter *lf;
    00390
    00391   StringID error_str;
    00392   char *extra_msg;
    00393
    00394   byte ff_state;
    00395   bool saveinprogress;
    00396 };
    00397
    00398 static SaveLoadParams _sl;
    00399
    00400 /* these define the chunks */
    00401 extern const ChunkHandler _gamelog_chunk_handlers[];
    00402 extern const ChunkHandler _map_chunk_handlers[];
    00403 extern const ChunkHandler _misc_chunk_handlers[];
    00404 extern const ChunkHandler _name_chunk_handlers[];
    00405 extern const ChunkHandler _cheat_chunk_handlers[] ;
    00406 extern const ChunkHandler _setting_chunk_handlers[];
    00407 extern const ChunkHandler _company_chunk_handlers[];
    00408 extern const ChunkHandler _engine_chunk_handlers[];
    00409 extern const ChunkHandler _veh_chunk_handlers[];
    00410 extern const ChunkHandler _waypoint_chunk_handlers[];
    00411 extern const ChunkHandler _depot_chunk_handlers[];
    00412 extern const ChunkHandler _order_chunk_handlers[];
    00413 extern const ChunkHandler _town_chunk_handlers[];
    00414 extern const ChunkHandler _sign_chunk_handlers[];
    00415 extern const ChunkHandler _station_chunk_handlers[];
    00416 extern const ChunkHandler _industry_chunk_handlers[];
    00417 extern const ChunkHandler _economy_chunk_handlers[];
    00418 extern const ChunkHandler _subsidy_chunk_handlers[];
    00419 extern const ChunkHandler _cargomonitor_chunk_handlers[];
    00420 extern const ChunkHandler _goal_chunk_handlers[];
    00421 extern const ChunkHandler _ai_chunk_handlers[];
    00422 extern const ChunkHandler _game_chunk_handlers[];
    00423 extern const ChunkHandler _animated_tile_chunk_handlers[];
    00424 extern const ChunkHandler _newgrf_chunk_handlers[];
    00425 extern const ChunkHandler _group_chunk_handlers[];
    00426 extern const ChunkHandler _cargopacket_chunk_handlers[];
    00427 extern const ChunkHandler _autoreplace_chunk_handlers[];
    00428 extern const ChunkHandler _labelmaps_chunk_handlers[];
    00429 extern const ChunkHandler _linkgraph_chunk_handlers[];
    00430 extern const ChunkHandler _airport_chunk_handlers[];
    00431 extern const ChunkHandler _object_chunk_handlers[];
    00432 extern const ChunkHandler _persistent_storage_chunk_handlers[];
    00433
    00435 static const ChunkHandler * const _chunk_handlers[] = {
    00436   _gamelog_chunk_handlers,
    00437   _map_chunk_handlers,
    00438   _misc_chunk_handlers,
    00439   _name_chunk_handlers,
    00440   _cheat_chunk_handlers,
    00441   _setting_chunk_handlers,
    00442   _veh_chunk_handlers,
    00443   _waypoint_chunk_handlers,
    00444   _depot_chunk_handlers,
    00445   _order_chunk_handlers,
    00446   _industry_chunk_handlers,
    00447   _economy_chunk_handlers,
    00448   _subsidy_chunk_handlers,
    00449   _cargomonitor_chunk_handlers,
    00450   _goal_chunk_handlers,
    00451   _engine_chunk_handlers,
    00452   _town_chunk_handlers,
    00453   _sign_chunk_handlers,
    00454   _station_chunk_handlers,
    00455   _company_chunk_handlers,
    00456   _ai_chunk_handlers,
    00457   _game_chunk_handlers,
    00458   _animated_tile_chunk_handlers,
    00459   _newgrf_chunk_handlers,
    00460   _group_chunk_handlers,
    00461   _cargopacket_chunk_handlers,
    00462   _autoreplace_chunk_handlers,
    00463   _labelmaps_chunk_handlers,
    00464   _linkgraph_chunk_handlers,
    00465   _airport_chunk_handlers,
    00466   _object_chunk_handlers,
    00467   _persistent_storage_chunk_handlers,
    00468   NULL,
    00469 };
    00470
    00475 #define FOR_ALL_CHUNK_HANDLERS(ch) \
    00476   for (const ChunkHandler * const *chsc = _chunk_handlers; *chsc != NULL; chsc++) \
    00477     for (const ChunkHandler *ch = *chsc; ch != NULL; ch = (ch->flags & CH_LAST) ? NULL : ch + 1)
    00478
    00480 static void SlNullPointers()
    00481 {
    00482   _sl.action = SLA_NULL;
    00483
    00484   /* We don't want any savegame conversion code to run
    00485    * during NULLing; especially those that try to get
    00486    * pointers from other pools. */
    00487   _sl_version = SAVEGAME_VERSION;
    00488
    00489   DEBUG(sl, 1, "Nulling pointers");
    00490
    00491   FOR_ALL_CHUNK_HANDLERS(ch) {
    00492     if (ch->ptrs_proc != NULL) {
    00493       DEBUG(sl, 2, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    00494       ch->ptrs_proc();
    00495     }
    00496   }
    00497
    00498   DEBUG(sl, 1, "All pointers nulled");
    00499
    00500   assert(_sl.action == SLA_NULL);
    00501 }
    00502
    00511 void NORETURN SlError(StringID string, const char *extra_msg)
    00512 {
    00513   /* Distinguish between loading into _load_check_data vs. normal save/load. */
    00514   if (_sl.action == SLA_LOAD_CHECK) {
    00515     _load_check_data.error = string;
    00516     free(_load_check_data.error_data);
    00517     _load_check_data.error_data = (extra_msg == NULL) ? NULL : strdup(extra_msg);
    00518   } else {
    00519     _sl.error_str = string;
    00520     free(_sl.extra_msg);
    00521     _sl.extra_msg = (extra_msg == NULL) ? NULL : strdup(extra_msg);
    00522   }
    00523
    00524   /* We have to NULL all pointers here; we might be in a state where
    00525    * the pointers are actually filled with indices, which means that
    00526    * when we access them during cleaning the pool dereferences of
    00527    * those indices will be made with segmentation faults as result. */
    00528   if (_sl.action == SLA_LOAD || _sl.action == SLA_PTRS) SlNullPointers();
    00529   throw std::exception();
    00530 }
    00531
    00539 void NORETURN SlErrorCorrupt(const char *msg)
    00540 {
    00541   SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
    00542 }
    00543
    00544
    00545 typedef void (*AsyncSaveFinishProc)();
    00546 static AsyncSaveFinishProc _async_save_finish = NULL;
    00547 static ThreadObject *_save_thread;
    00548
    00553 static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
    00554 {
    00555   if (_exit_game) return;
    00556   while (_async_save_finish != NULL) CSleep(10);
    00557
    00558   _async_save_finish = proc;
    00559 }
    00560
    00564 void ProcessAsyncSaveFinish()
    00565 {
    00566   if (_async_save_finish == NULL) return;
    00567
    00568   _async_save_finish();
    00569
    00570   _async_save_finish = NULL;
    00571
    00572   if (_save_thread != NULL) {
    00573     _save_thread->Join();
    00574     delete _save_thread;
    00575     _save_thread = NULL;
    00576   }
    00577 }
    00578
    00583 byte SlReadByte()
    00584 {
    00585   return _sl.reader->ReadByte();
    00586 }
    00587
    00592 void SlWriteByte(byte b)
    00593 {
    00594   _sl.dumper->WriteByte(b);
    00595 }
    00596
    00597 static inline int SlReadUint16()
    00598 {
    00599   int x = SlReadByte() << 8;
    00600   return x | SlReadByte();
    00601 }
    00602
    00603 static inline uint32 SlReadUint32()
    00604 {
    00605   uint32 x = SlReadUint16() << 16;
    00606   return x | SlReadUint16();
    00607 }
    00608
    00609 static inline uint64 SlReadUint64()
    00610 {
    00611   uint32 x = SlReadUint32();
    00612   uint32 y = SlReadUint32();
    00613   return (uint64)x << 32 | y;
    00614 }
    00615
    00616 static inline void SlWriteUint16(uint16 v)
    00617 {
    00618   SlWriteByte(GB(v, 8, 8));
    00619   SlWriteByte(GB(v, 0, 8));
    00620 }
    00621
    00622 static inline void SlWriteUint32(uint32 v)
    00623 {
    00624   SlWriteUint16(GB(v, 16, 16));
    00625   SlWriteUint16(GB(v,  0, 16));
    00626 }
    00627
    00628 static inline void SlWriteUint64(uint64 x)
    00629 {
    00630   SlWriteUint32((uint32)(x >> 32));
    00631   SlWriteUint32((uint32)x);
    00632 }
    00633
    00639 static inline void SlSkipBytes(size_t length)
    00640 {
    00641   for (; length != 0; length--) SlReadByte();
    00642 }
    00643
    00653 static uint SlReadSimpleGamma()
    00654 {
    00655   uint i = SlReadByte();
    00656   if (HasBit(i, 7)) {
    00657     i &= ~0x80;
    00658     if (HasBit(i, 6)) {
    00659       i &= ~0x40;
    00660       if (HasBit(i, 5)) {
    00661         i &= ~0x20;
    00662         if (HasBit(i, 4)) {
    00663           SlErrorCorrupt("Unsupported gamma");
    00664         }
    00665         i = (i << 8) | SlReadByte();
    00666       }
    00667       i = (i << 8) | SlReadByte();
    00668     }
    00669     i = (i << 8) | SlReadByte();
    00670   }
    00671   return i;
    00672 }
    00673
    00686 static void SlWriteSimpleGamma(size_t i)
    00687 {
    00688   if (i >= (1 << 7)) {
    00689     if (i >= (1 << 14)) {
    00690       if (i >= (1 << 21)) {
    00691         assert(i < (1 << 28));
    00692         SlWriteByte((byte)(0xE0 | (i >> 24)));
    00693         SlWriteByte((byte)(i >> 16));
    00694       } else {
    00695         SlWriteByte((byte)(0xC0 | (i >> 16)));
    00696       }
    00697       SlWriteByte((byte)(i >> 8));
    00698     } else {
    00699       SlWriteByte((byte)(0x80 | (i >> 8)));
    00700     }
    00701   }
    00702   SlWriteByte((byte)i);
    00703 }
    00704
    00706 static inline uint SlGetGammaLength(size_t i)
    00707 {
    00708   return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21));
    00709 }
    00710
    00711 static inline uint SlReadSparseIndex()
    00712 {
    00713   return SlReadSimpleGamma();
    00714 }
    00715
    00716 static inline void SlWriteSparseIndex(uint index)
    00717 {
    00718   SlWriteSimpleGamma(index);
    00719 }
    00720
    00721 static inline uint SlReadArrayLength()
    00722 {
    00723   return SlReadSimpleGamma();
    00724 }
    00725
    00726 static inline void SlWriteArrayLength(size_t length)
    00727 {
    00728   SlWriteSimpleGamma(length);
    00729 }
    00730
    00731 static inline uint SlGetArrayLength(size_t length)
    00732 {
    00733   return SlGetGammaLength(length);
    00734 }
    00735
    00742 static inline uint SlCalcConvMemLen(VarType conv)
    00743 {
    00744   static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
    00745   byte length = GB(conv, 4, 4);
    00746
    00747   switch (length << 4) {
    00748     case SLE_VAR_STRB:
    00749     case SLE_VAR_STRBQ:
    00750     case SLE_VAR_STR:
    00751     case SLE_VAR_STRQ:
    00752       return SlReadArrayLength();
    00753
    00754     default:
    00755       assert(length < lengthof(conv_mem_size));
    00756       return conv_mem_size[length];
    00757   }
    00758 }
    00759
    00766 static inline byte SlCalcConvFileLen(VarType conv)
    00767 {
    00768   static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
    00769   byte length = GB(conv, 0, 4);
    00770   assert(length < lengthof(conv_file_size));
    00771   return conv_file_size[length];
    00772 }
    00773
    00775 static inline size_t SlCalcRefLen()
    00776 {
    00777   return IsSavegameVersionBefore(69) ? 2 : 4;
    00778 }
    00779
    00780 void SlSetArrayIndex(uint index)
    00781 {
    00782   _sl.need_length = NL_WANTLENGTH;
    00783   _sl.array_index = index;
    00784 }
    00785
    00786 static size_t _next_offs;
    00787
    00792 int SlIterateArray()
    00793 {
    00794   int index;
    00795
    00796   /* After reading in the whole array inside the loop
    00797    * we must have read in all the data, so we must be at end of current block. */
    00798   if (_next_offs != 0 && _sl.reader->GetSize() != _next_offs) SlErrorCorrupt("Invalid chunk size");
    00799
    00800   for (;;) {
    00801     uint length = SlReadArrayLength();
    00802     if (length == 0) {
    00803       _next_offs = 0;
    00804       return -1;
    00805     }
    00806
    00807     _sl.obj_len = --length;
    00808     _next_offs = _sl.reader->GetSize() + length;
    00809
    00810     switch (_sl.block_mode) {
    00811       case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
    00812       case CH_ARRAY:        index = _sl.array_index++; break;
    00813       default:
    00814         DEBUG(sl, 0, "SlIterateArray error");
    00815         return -1; // error
    00816     }
    00817
    00818     if (length != 0) return index;
    00819   }
    00820 }
    00821
    00825 void SlSkipArray()
    00826 {
    00827   while (SlIterateArray() != -1) {
    00828     SlSkipBytes(_next_offs - _sl.reader->GetSize());
    00829   }
    00830 }
    00831
    00837 void SlSetLength(size_t length)
    00838 {
    00839   assert(_sl.action == SLA_SAVE);
    00840
    00841   switch (_sl.need_length) {
    00842     case NL_WANTLENGTH:
    00843       _sl.need_length = NL_NONE;
    00844       switch (_sl.block_mode) {
    00845         case CH_RIFF:
    00846           /* Ugly encoding of >16M RIFF chunks
    00847            * The lower 24 bits are normal
    00848            * The uppermost 4 bits are bits 24:27 */
    00849           assert(length < (1 << 28));
    00850           SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
    00851           break;
    00852         case CH_ARRAY:
    00853           assert(_sl.last_array_index <= _sl.array_index);
    00854           while (++_sl.last_array_index <= _sl.array_index) {
    00855             SlWriteArrayLength(1);
    00856           }
    00857           SlWriteArrayLength(length + 1);
    00858           break;
    00859         case CH_SPARSE_ARRAY:
    00860           SlWriteArrayLength(length + 1 + SlGetArrayLength(_sl.array_index)); // Also include length of sparse index.
    00861           SlWriteSparseIndex(_sl.array_index);
    00862           break;
    00863         default: NOT_REACHED();
    00864       }
    00865       break;
    00866
    00867     case NL_CALCLENGTH:
    00868       _sl.obj_len += (int)length;
    00869       break;
    00870
    00871     default: NOT_REACHED();
    00872   }
    00873 }
    00874
    00881 static void SlCopyBytes(void *ptr, size_t length)
    00882 {
    00883   byte *p = (byte *)ptr;
    00884
    00885   switch (_sl.action) {
    00886     case SLA_LOAD_CHECK:
    00887     case SLA_LOAD:
    00888       for (; length != 0; length--) *p++ = SlReadByte();
    00889       break;
    00890     case SLA_SAVE:
    00891       for (; length != 0; length--) SlWriteByte(*p++);
    00892       break;
    00893     default: NOT_REACHED();
    00894   }
    00895 }
    00896
    00898 size_t SlGetFieldLength()
    00899 {
    00900   return _sl.obj_len;
    00901 }
    00902
    00910 int64 ReadValue(const void *ptr, VarType conv)
    00911 {
    00912   switch (GetVarMemType(conv)) {
    00913     case SLE_VAR_BL:  return (*(const bool *)ptr != 0);
    00914     case SLE_VAR_I8:  return *(const int8  *)ptr;
    00915     case SLE_VAR_U8:  return *(const byte  *)ptr;
    00916     case SLE_VAR_I16: return *(const int16 *)ptr;
    00917     case SLE_VAR_U16: return *(const uint16*)ptr;
    00918     case SLE_VAR_I32: return *(const int32 *)ptr;
    00919     case SLE_VAR_U32: return *(const uint32*)ptr;
    00920     case SLE_VAR_I64: return *(const int64 *)ptr;
    00921     case SLE_VAR_U64: return *(const uint64*)ptr;
    00922     case SLE_VAR_NULL:return 0;
    00923     default: NOT_REACHED();
    00924   }
    00925 }
    00926
    00934 void WriteValue(void *ptr, VarType conv, int64 val)
    00935 {
    00936   switch (GetVarMemType(conv)) {
    00937     case SLE_VAR_BL:  *(bool  *)ptr = (val != 0);  break;
    00938     case SLE_VAR_I8:  *(int8  *)ptr = val; break;
    00939     case SLE_VAR_U8:  *(byte  *)ptr = val; break;
    00940     case SLE_VAR_I16: *(int16 *)ptr = val; break;
    00941     case SLE_VAR_U16: *(uint16*)ptr = val; break;
    00942     case SLE_VAR_I32: *(int32 *)ptr = val; break;
    00943     case SLE_VAR_U32: *(uint32*)ptr = val; break;
    00944     case SLE_VAR_I64: *(int64 *)ptr = val; break;
    00945     case SLE_VAR_U64: *(uint64*)ptr = val; break;
    00946     case SLE_VAR_NAME: *(char**)ptr = CopyFromOldName(val); break;
    00947     case SLE_VAR_NULL: break;
    00948     default: NOT_REACHED();
    00949   }
    00950 }
    00951
    00960 static void SlSaveLoadConv(void *ptr, VarType conv)
    00961 {
    00962   switch (_sl.action) {
    00963     case SLA_SAVE: {
    00964       int64 x = ReadValue(ptr, conv);
    00965
    00966       /* Write the value to the file and check if its value is in the desired range */
    00967       switch (GetVarFileType(conv)) {
    00968         case SLE_FILE_I8: assert(x >= -128 && x <= 127);     SlWriteByte(x);break;
    00969         case SLE_FILE_U8: assert(x >= 0 && x <= 255);        SlWriteByte(x);break;
    00970         case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break;
    00971         case SLE_FILE_STRINGID:
    00972         case SLE_FILE_U16:assert(x >= 0 && x <= 65535);      SlWriteUint16(x);break;
    00973         case SLE_FILE_I32:
    00974         case SLE_FILE_U32:                                   SlWriteUint32((uint32)x);break;
    00975         case SLE_FILE_I64:
    00976         case SLE_FILE_U64:                                   SlWriteUint64(x);break;
    00977         default: NOT_REACHED();
    00978       }
    00979       break;
    00980     }
    00981     case SLA_LOAD_CHECK:
    00982     case SLA_LOAD: {
    00983       int64 x;
    00984       /* Read a value from the file */
    00985       switch (GetVarFileType(conv)) {
    00986         case SLE_FILE_I8:  x = (int8  )SlReadByte();   break;
    00987         case SLE_FILE_U8:  x = (byte  )SlReadByte();   break;
    00988         case SLE_FILE_I16: x = (int16 )SlReadUint16(); break;
    00989         case SLE_FILE_U16: x = (uint16)SlReadUint16(); break;
    00990         case SLE_FILE_I32: x = (int32 )SlReadUint32(); break;
    00991         case SLE_FILE_U32: x = (uint32)SlReadUint32(); break;
    00992         case SLE_FILE_I64: x = (int64 )SlReadUint64(); break;
    00993         case SLE_FILE_U64: x = (uint64)SlReadUint64(); break;
    00994         case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break;
    00995         default: NOT_REACHED();
    00996       }
    00997
    00998       /* Write The value to the struct. These ARE endian safe. */
    00999       WriteValue(ptr, conv, x);
    01000       break;
    01001     }
    01002     case SLA_PTRS: break;
    01003     case SLA_NULL: break;
    01004     default: NOT_REACHED();
    01005   }
    01006 }
    01007
    01017 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
    01018 {
    01019   if (ptr == NULL) return 0;
    01020   return min(strlen(ptr), length - 1);
    01021 }
    01022
    01032 static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
    01033 {
    01034   size_t len;
    01035   const char *str;
    01036
    01037   switch (GetVarMemType(conv)) {
    01038     default: NOT_REACHED();
    01039     case SLE_VAR_STR:
    01040     case SLE_VAR_STRQ:
    01041       str = *(const char * const *)ptr;
    01042       len = SIZE_MAX;
    01043       break;
    01044     case SLE_VAR_STRB:
    01045     case SLE_VAR_STRBQ:
    01046       str = (const char *)ptr;
    01047       len = length;
    01048       break;
    01049   }
    01050
    01051   len = SlCalcNetStringLen(str, len);
    01052   return len + SlGetArrayLength(len); // also include the length of the index
    01053 }
    01054
    01061 static void SlString(void *ptr, size_t length, VarType conv)
    01062 {
    01063   switch (_sl.action) {
    01064     case SLA_SAVE: {
    01065       size_t len;
    01066       switch (GetVarMemType(conv)) {
    01067         default: NOT_REACHED();
    01068         case SLE_VAR_STRB:
    01069         case SLE_VAR_STRBQ:
    01070           len = SlCalcNetStringLen((char *)ptr, length);
    01071           break;
    01072         case SLE_VAR_STR:
    01073         case SLE_VAR_STRQ:
    01074           ptr = *(char **)ptr;
    01075           len = SlCalcNetStringLen((char *)ptr, SIZE_MAX);
    01076           break;
    01077       }
    01078
    01079       SlWriteArrayLength(len);
    01080       SlCopyBytes(ptr, len);
    01081       break;
    01082     }
    01083     case SLA_LOAD_CHECK:
    01084     case SLA_LOAD: {
    01085       size_t len = SlReadArrayLength();
    01086
    01087       switch (GetVarMemType(conv)) {
    01088         default: NOT_REACHED();
    01089         case SLE_VAR_STRB:
    01090         case SLE_VAR_STRBQ:
    01091           if (len >= length) {
    01092             DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
    01093             SlCopyBytes(ptr, length);
    01094             SlSkipBytes(len - length);
    01095             len = length - 1;
    01096           } else {
    01097             SlCopyBytes(ptr, len);
    01098           }
    01099           break;
    01100         case SLE_VAR_STR:
    01101         case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate
    01102           free(*(char **)ptr);
    01103           if (len == 0) {
    01104             *(char **)ptr = NULL;
    01105             return;
    01106           } else {
    01107             *(char **)ptr = MallocT<char>(len + 1); // terminating '\0'
    01108             ptr = *(char **)ptr;
    01109             SlCopyBytes(ptr, len);
    01110           }
    01111           break;
    01112       }
    01113
    01114       ((char *)ptr)[len] = '\0'; // properly terminate the string
    01115       StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK;
    01116       if ((conv & SLF_ALLOW_CONTROL) != 0) {
    01117         settings = settings | SVS_ALLOW_CONTROL_CODE;
    01118         if (IsSavegameVersionBefore(169)) {
    01119           str_fix_scc_encoded((char *)ptr, (char *)ptr + len);
    01120         }
    01121       }
    01122       if ((conv & SLF_ALLOW_NEWLINE) != 0) {
    01123         settings = settings | SVS_ALLOW_NEWLINE;
    01124       }
    01125       str_validate((char *)ptr, (char *)ptr + len, settings);
    01126       break;
    01127     }
    01128     case SLA_PTRS: break;
    01129     case SLA_NULL: break;
    01130     default: NOT_REACHED();
    01131   }
    01132 }
    01133
    01139 static inline size_t SlCalcArrayLen(size_t length, VarType conv)
    01140 {
    01141   return SlCalcConvFileLen(conv) * length;
    01142 }
    01143
    01150 void SlArray(void *array, size_t length, VarType conv)
    01151 {
    01152   if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
    01153
    01154   /* Automatically calculate the length? */
    01155   if (_sl.need_length != NL_NONE) {
    01156     SlSetLength(SlCalcArrayLen(length, conv));
    01157     /* Determine length only? */
    01158     if (_sl.need_length == NL_CALCLENGTH) return;
    01159   }
    01160
    01161   /* NOTICE - handle some buggy stuff, in really old versions everything was saved
    01162    * as a byte-type. So detect this, and adjust array size accordingly */
    01163   if (_sl.action != SLA_SAVE && _sl_version == 0) {
    01164     /* all arrays except difficulty settings */
    01165     if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
    01166         conv == SLE_INT32 || conv == SLE_UINT32) {
    01167       SlCopyBytes(array, length * SlCalcConvFileLen(conv));
    01168       return;
    01169     }
    01170     /* used for conversion of Money 32bit->64bit */
    01171     if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
    01172       for (uint i = 0; i < length; i++) {
    01173         ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
    01174       }
    01175       return;
    01176     }
    01177   }
    01178
    01179   /* If the size of elements is 1 byte both in file and memory, no special
    01180    * conversion is needed, use specialized copy-copy function to speed up things */
    01181   if (conv == SLE_INT8 || conv == SLE_UINT8) {
    01182     SlCopyBytes(array, length);
    01183   } else {
    01184     byte *a = (byte*)array;
    01185     byte mem_size = SlCalcConvMemLen(conv);
    01186
    01187     for (; length != 0; length --) {
    01188       SlSaveLoadConv(a, conv);
    01189       a += mem_size; // get size
    01190     }
    01191   }
    01192 }
    01193
    01194
    01205 static size_t ReferenceToInt(const void *obj, SLRefType rt)
    01206 {
    01207   assert(_sl.action == SLA_SAVE);
    01208
    01209   if (obj == NULL) return 0;
    01210
    01211   switch (rt) {
    01212     case REF_VEHICLE_OLD: // Old vehicles we save as new ones
    01213     case REF_VEHICLE:   return ((const  Vehicle*)obj)->index + 1;
    01214     case REF_STATION:   return ((const  Station*)obj)->index + 1;
    01215     case REF_TOWN:      return ((const     Town*)obj)->index + 1;
    01216     case REF_ORDER:     return ((const    Order*)obj)->index + 1;
    01217     case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
    01218     case REF_ENGINE_RENEWS:  return ((const       EngineRenew*)obj)->index + 1;
    01219     case REF_CARGO_PACKET:   return ((const       CargoPacket*)obj)->index + 1;
    01220     case REF_ORDERLIST:      return ((const         OrderList*)obj)->index + 1;
    01221     case REF_STORAGE:        return ((const PersistentStorage*)obj)->index + 1;
    01222     case REF_LINK_GRAPH:     return ((const         LinkGraph*)obj)->index + 1;
    01223     case REF_LINK_GRAPH_JOB: return ((const      LinkGraphJob*)obj)->index + 1;
    01224     default: NOT_REACHED();
    01225   }
    01226 }
    01227
    01238 static void *IntToReference(size_t index, SLRefType rt)
    01239 {
    01240   assert_compile(sizeof(size_t) <= sizeof(void *));
    01241
    01242   assert(_sl.action == SLA_PTRS);
    01243
    01244   /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE,
    01245    * and should be loaded like that */
    01246   if (rt == REF_VEHICLE_OLD && !IsSavegameVersionBefore(4, 4)) {
    01247     rt = REF_VEHICLE;
    01248   }
    01249
    01250   /* No need to look up NULL pointers, just return immediately */
    01251   if (index == (rt == REF_VEHICLE_OLD ? 0xFFFF : 0)) return NULL;
    01252
    01253   /* Correct index. Old vehicles were saved differently:
    01254    * invalid vehicle was 0xFFFF, now we use 0x0000 for everything invalid. */
    01255   if (rt != REF_VEHICLE_OLD) index--;
    01256
    01257   switch (rt) {
    01258     case REF_ORDERLIST:
    01259       if (OrderList::IsValidID(index)) return OrderList::Get(index);
    01260       SlErrorCorrupt("Referencing invalid OrderList");
    01261
    01262     case REF_ORDER:
    01263       if (Order::IsValidID(index)) return Order::Get(index);
    01264       /* in old versions, invalid order was used to mark end of order list */
    01265       if (IsSavegameVersionBefore(5, 2)) return NULL;
    01266       SlErrorCorrupt("Referencing invalid Order");
    01267
    01268     case REF_VEHICLE_OLD:
    01269     case REF_VEHICLE:
    01270       if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
    01271       SlErrorCorrupt("Referencing invalid Vehicle");
    01272
    01273     case REF_STATION:
    01274       if (Station::IsValidID(index)) return Station::Get(index);
    01275       SlErrorCorrupt("Referencing invalid Station");
    01276
    01277     case REF_TOWN:
    01278       if (Town::IsValidID(index)) return Town::Get(index);
    01279       SlErrorCorrupt("Referencing invalid Town");
    01280
    01281     case REF_ROADSTOPS:
    01282       if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
    01283       SlErrorCorrupt("Referencing invalid RoadStop");
    01284
    01285     case REF_ENGINE_RENEWS:
    01286       if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
    01287       SlErrorCorrupt("Referencing invalid EngineRenew");
    01288
    01289     case REF_CARGO_PACKET:
    01290       if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
    01291       SlErrorCorrupt("Referencing invalid CargoPacket");
    01292
    01293     case REF_STORAGE:
    01294       if (PersistentStorage::IsValidID(index)) return PersistentStorage::Get(index);
    01295       SlErrorCorrupt("Referencing invalid PersistentStorage");
    01296
    01297     case REF_LINK_GRAPH:
    01298       if (LinkGraph::IsValidID(index)) return LinkGraph::Get(index);
    01299       SlErrorCorrupt("Referencing invalid LinkGraph");
    01300
    01301     case REF_LINK_GRAPH_JOB:
    01302       if (LinkGraphJob::IsValidID(index)) return LinkGraphJob::Get(index);
    01303       SlErrorCorrupt("Referencing invalid LinkGraphJob");
    01304
    01305     default: NOT_REACHED();
    01306   }
    01307 }
    01308
    01313 static inline size_t SlCalcListLen(const void *list)
    01314 {
    01315   const std::list<void *> *l = (const std::list<void *> *) list;
    01316
    01317   int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
    01318   /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
    01319    * of the list */
    01320   return l->size() * type_size + type_size;
    01321 }
    01322
    01323
    01329 static void SlList(void *list, SLRefType conv)
    01330 {
    01331   /* Automatically calculate the length? */
    01332   if (_sl.need_length != NL_NONE) {
    01333     SlSetLength(SlCalcListLen(list));
    01334     /* Determine length only? */
    01335     if (_sl.need_length == NL_CALCLENGTH) return;
    01336   }
    01337
    01338   typedef std::list<void *> PtrList;
    01339   PtrList *l = (PtrList *)list;
    01340
    01341   switch (_sl.action) {
    01342     case SLA_SAVE: {
    01343       SlWriteUint32((uint32)l->size());
    01344
    01345       PtrList::iterator iter;
    01346       for (iter = l->begin(); iter != l->end(); ++iter) {
    01347         void *ptr = *iter;
    01348         SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
    01349       }
    01350       break;
    01351     }
    01352     case SLA_LOAD_CHECK:
    01353     case SLA_LOAD: {
    01354       size_t length = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01355
    01356       /* Load each reference and push to the end of the list */
    01357       for (size_t i = 0; i < length; i++) {
    01358         size_t data = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01359         l->push_back((void *)data);
    01360       }
    01361       break;
    01362     }
    01363     case SLA_PTRS: {
    01364       PtrList temp = *l;
    01365
    01366       l->clear();
    01367       PtrList::iterator iter;
    01368       for (iter = temp.begin(); iter != temp.end(); ++iter) {
    01369         void *ptr = IntToReference((size_t)*iter, conv);
    01370         l->push_back(ptr);
    01371       }
    01372       break;
    01373     }
    01374     case SLA_NULL:
    01375       l->clear();
    01376       break;
    01377     default: NOT_REACHED();
    01378   }
    01379 }
    01380
    01381
    01383 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
    01384 {
    01385   if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
    01386   if (sld->conv & SLF_NOT_IN_SAVE) return false;
    01387
    01388   return true;
    01389 }
    01390
    01396 static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
    01397 {
    01398   if ((sld->conv & SLF_NO_NETWORK_SYNC) && _sl.action != SLA_SAVE && _networking && !_network_server) {
    01399     SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
    01400     return true;
    01401   }
    01402
    01403   return false;
    01404 }
    01405
    01412 size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
    01413 {
    01414   size_t length = 0;
    01415
    01416   /* Need to determine the length and write a length tag. */
    01417   for (; sld->cmd != SL_END; sld++) {
    01418     length += SlCalcObjMemberLength(object, sld);
    01419   }
    01420   return length;
    01421 }
    01422
    01423 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
    01424 {
    01425   assert(_sl.action == SLA_SAVE);
    01426
    01427   switch (sld->cmd) {
    01428     case SL_VAR:
    01429     case SL_REF:
    01430     case SL_ARR:
    01431     case SL_STR:
    01432     case SL_LST:
    01433       /* CONDITIONAL saveload types depend on the savegame version */
    01434       if (!SlIsObjectValidInSavegame(sld)) break;
    01435
    01436       switch (sld->cmd) {
    01437         case SL_VAR: return SlCalcConvFileLen(sld->conv);
    01438         case SL_REF: return SlCalcRefLen();
    01439         case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
    01440         case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
    01441         case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
    01442         default: NOT_REACHED();
    01443       }
    01444       break;
    01445     case SL_WRITEBYTE: return 1; // a byte is logically of size 1
    01446     case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
    01447     case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
    01448     default: NOT_REACHED();
    01449   }
    01450   return 0;
    01451 }
    01452
    01453
    01454 bool SlObjectMember(void *ptr, const SaveLoad *sld)
    01455 {
    01456   VarType conv = GB(sld->conv, 0, 8);
    01457   switch (sld->cmd) {
    01458     case SL_VAR:
    01459     case SL_REF:
    01460     case SL_ARR:
    01461     case SL_STR:
    01462     case SL_LST:
    01463       /* CONDITIONAL saveload types depend on the savegame version */
    01464       if (!SlIsObjectValidInSavegame(sld)) return false;
    01465       if (SlSkipVariableOnLoad(sld)) return false;
    01466
    01467       switch (sld->cmd) {
    01468         case SL_VAR: SlSaveLoadConv(ptr, conv); break;
    01469         case SL_REF: // Reference variable, translate
    01470           switch (_sl.action) {
    01471             case SLA_SAVE:
    01472               SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv));
    01473               break;
    01474             case SLA_LOAD_CHECK:
    01475             case SLA_LOAD:
    01476               *(size_t *)ptr = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01477               break;
    01478             case SLA_PTRS:
    01479               *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv);
    01480               break;
    01481             case SLA_NULL:
    01482               *(void **)ptr = NULL;
    01483               break;
    01484             default: NOT_REACHED();
    01485           }
    01486           break;
    01487         case SL_ARR: SlArray(ptr, sld->length, conv); break;
    01488         case SL_STR: SlString(ptr, sld->length, sld->conv); break;
    01489         case SL_LST: SlList(ptr, (SLRefType)conv); break;
    01490         default: NOT_REACHED();
    01491       }
    01492       break;
    01493
    01494     /* SL_WRITEBYTE translates a value of a variable to another one upon
    01495      * saving or loading.
    01496      * XXX - variable renaming abuse
    01497      * game_value: the value of the variable ingame is abused by sld->version_from
    01498      * file_value: the value of the variable in the savegame is abused by sld->version_to */
    01499     case SL_WRITEBYTE:
    01500       switch (_sl.action) {
    01501         case SLA_SAVE: SlWriteByte(sld->version_to); break;
    01502         case SLA_LOAD_CHECK:
    01503         case SLA_LOAD: *(byte *)ptr = sld->version_from; break;
    01504         case SLA_PTRS: break;
    01505         case SLA_NULL: break;
    01506         default: NOT_REACHED();
    01507       }
    01508       break;
    01509
    01510     /* SL_VEH_INCLUDE loads common code for vehicles */
    01511     case SL_VEH_INCLUDE:
    01512       SlObject(ptr, GetVehicleDescription(VEH_END));
    01513       break;
    01514
    01515     case SL_ST_INCLUDE:
    01516       SlObject(ptr, GetBaseStationDescription());
    01517       break;
    01518
    01519     default: NOT_REACHED();
    01520   }
    01521   return true;
    01522 }
    01523
    01529 void SlObject(void *object, const SaveLoad *sld)
    01530 {
    01531   /* Automatically calculate the length? */
    01532   if (_sl.need_length != NL_NONE) {
    01533     SlSetLength(SlCalcObjLength(object, sld));
    01534     if (_sl.need_length == NL_CALCLENGTH) return;
    01535   }
    01536
    01537   for (; sld->cmd != SL_END; sld++) {
    01538     void *ptr = sld->global ? sld->address : GetVariableAddress(object, sld);
    01539     SlObjectMember(ptr, sld);
    01540   }
    01541 }
    01542
    01547 void SlGlobList(const SaveLoadGlobVarList *sldg)
    01548 {
    01549   SlObject(NULL, (const SaveLoad*)sldg);
    01550 }
    01551
    01557 void SlAutolength(AutolengthProc *proc, void *arg)
    01558 {
    01559   size_t offs;
    01560
    01561   assert(_sl.action == SLA_SAVE);
    01562
    01563   /* Tell it to calculate the length */
    01564   _sl.need_length = NL_CALCLENGTH;
    01565   _sl.obj_len = 0;
    01566   proc(arg);
    01567
    01568   /* Setup length */
    01569   _sl.need_length = NL_WANTLENGTH;
    01570   SlSetLength(_sl.obj_len);
    01571
    01572   offs = _sl.dumper->GetSize() + _sl.obj_len;
    01573
    01574   /* And write the stuff */
    01575   proc(arg);
    01576
    01577   if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
    01578 }
    01579
    01584 static void SlLoadChunk(const ChunkHandler *ch)
    01585 {
    01586   byte m = SlReadByte();
    01587   size_t len;
    01588   size_t endoffs;
    01589
    01590   _sl.block_mode = m;
    01591   _sl.obj_len = 0;
    01592
    01593   switch (m) {
    01594     case CH_ARRAY:
    01595       _sl.array_index = 0;
    01596       ch->load_proc();
    01597       break;
    01598     case CH_SPARSE_ARRAY:
    01599       ch->load_proc();
    01600       break;
    01601     default:
    01602       if ((m & 0xF) == CH_RIFF) {
    01603         /* Read length */
    01604         len = (SlReadByte() << 16) | ((m >> 4) << 24);
    01605         len += SlReadUint16();
    01606         _sl.obj_len = len;
    01607         endoffs = _sl.reader->GetSize() + len;
    01608         ch->load_proc();
    01609         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
    01610       } else {
    01611         SlErrorCorrupt("Invalid chunk type");
    01612       }
    01613       break;
    01614   }
    01615 }
    01616
    01622 static void SlLoadCheckChunk(const ChunkHandler *ch)
    01623 {
    01624   byte m = SlReadByte();
    01625   size_t len;
    01626   size_t endoffs;
    01627
    01628   _sl.block_mode = m;
    01629   _sl.obj_len = 0;
    01630
    01631   switch (m) {
    01632     case CH_ARRAY:
    01633       _sl.array_index = 0;
    01634       if (ch->load_check_proc) {
    01635         ch->load_check_proc();
    01636       } else {
    01637         SlSkipArray();
    01638       }
    01639       break;
    01640     case CH_SPARSE_ARRAY:
    01641       if (ch->load_check_proc) {
    01642         ch->load_check_proc();
    01643       } else {
    01644         SlSkipArray();
    01645       }
    01646       break;
    01647     default:
    01648       if ((m & 0xF) == CH_RIFF) {
    01649         /* Read length */
    01650         len = (SlReadByte() << 16) | ((m >> 4) << 24);
    01651         len += SlReadUint16();
    01652         _sl.obj_len = len;
    01653         endoffs = _sl.reader->GetSize() + len;
    01654         if (ch->load_check_proc) {
    01655           ch->load_check_proc();
    01656         } else {
    01657           SlSkipBytes(len);
    01658         }
    01659         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
    01660       } else {
    01661         SlErrorCorrupt("Invalid chunk type");
    01662       }
    01663       break;
    01664   }
    01665 }
    01666
    01671 static ChunkSaveLoadProc *_stub_save_proc;
    01672
    01678 static inline void SlStubSaveProc2(void *arg)
    01679 {
    01680   _stub_save_proc();
    01681 }
    01682
    01688 static void SlStubSaveProc()
    01689 {
    01690   SlAutolength(SlStubSaveProc2, NULL);
    01691 }
    01692
    01698 static void SlSaveChunk(const ChunkHandler *ch)
    01699 {
    01700   ChunkSaveLoadProc *proc = ch->save_proc;
    01701
    01702   /* Don't save any chunk information if there is no save handler. */
    01703   if (proc == NULL) return;
    01704
    01705   SlWriteUint32(ch->id);
    01706   DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    01707
    01708   if (ch->flags & CH_AUTO_LENGTH) {
    01709     /* Need to calculate the length. Solve that by calling SlAutoLength in the save_proc. */
    01710     _stub_save_proc = proc;
    01711     proc = SlStubSaveProc;
    01712   }
    01713
    01714   _sl.block_mode = ch->flags & CH_TYPE_MASK;
    01715   switch (ch->flags & CH_TYPE_MASK) {
    01716     case CH_RIFF:
    01717       _sl.need_length = NL_WANTLENGTH;
    01718       proc();
    01719       break;
    01720     case CH_ARRAY:
    01721       _sl.last_array_index = 0;
    01722       SlWriteByte(CH_ARRAY);
    01723       proc();
    01724       SlWriteArrayLength(0); // Terminate arrays
    01725       break;
    01726     case CH_SPARSE_ARRAY:
    01727       SlWriteByte(CH_SPARSE_ARRAY);
    01728       proc();
    01729       SlWriteArrayLength(0); // Terminate arrays
    01730       break;
    01731     default: NOT_REACHED();
    01732   }
    01733 }
    01734
    01736 static void SlSaveChunks()
    01737 {
    01738   FOR_ALL_CHUNK_HANDLERS(ch) {
    01739     SlSaveChunk(ch);
    01740   }
    01741
    01742   /* Terminator */
    01743   SlWriteUint32(0);
    01744 }
    01745
    01752 static const ChunkHandler *SlFindChunkHandler(uint32 id)
    01753 {
    01754   FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch;
    01755   return NULL;
    01756 }
    01757
    01759 static void SlLoadChunks()
    01760 {
    01761   uint32 id;
    01762   const ChunkHandler *ch;
    01763
    01764   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
    01765     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
    01766
    01767     ch = SlFindChunkHandler(id);
    01768     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
    01769     SlLoadChunk(ch);
    01770   }
    01771 }
    01772
    01774 static void SlLoadCheckChunks()
    01775 {
    01776   uint32 id;
    01777   const ChunkHandler *ch;
    01778
    01779   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
    01780     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
    01781
    01782     ch = SlFindChunkHandler(id);
    01783     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
    01784     SlLoadCheckChunk(ch);
    01785   }
    01786 }
    01787
    01789 static void SlFixPointers()
    01790 {
    01791   _sl.action = SLA_PTRS;
    01792
    01793   DEBUG(sl, 1, "Fixing pointers");
    01794
    01795   FOR_ALL_CHUNK_HANDLERS(ch) {
    01796     if (ch->ptrs_proc != NULL) {
    01797       DEBUG(sl, 2, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    01798       ch->ptrs_proc();
    01799     }
    01800   }
    01801
    01802   DEBUG(sl, 1, "All pointers fixed");
    01803
    01804   assert(_sl.action == SLA_PTRS);
    01805 }
    01806
    01807
    01809 struct FileReader : LoadFilter {
    01810   FILE *file;
    01811   long begin;
    01812
    01817   FileReader(FILE *file) : LoadFilter(NULL), file(file), begin(ftell(file))
    01818   {
    01819   }
    01820
    01822   ~FileReader()
    01823   {
    01824     if (this->file != NULL) fclose(this->file);
    01825     this->file = NULL;
    01826
    01827     /* Make sure we don't double free. */
    01828     _sl.sf = NULL;
    01829   }
    01830
    01831   /* virtual */ size_t Read(byte *buf, size_t size)
    01832   {
    01833     /* We're in the process of shutting down, i.e. in "failure" mode. */
    01834     if (this->file == NULL) return 0;
    01835
    01836     return fread(buf, 1, size, this->file);
    01837   }
    01838
    01839   /* virtual */ void Reset()
    01840   {
    01841     clearerr(this->file);
    01842     fseek(this->file, this->begin, SEEK_SET);
    01843   }
    01844 };
    01845
    01847 struct FileWriter : SaveFilter {
    01848   FILE *file;
    01849
    01854   FileWriter(FILE *file) : SaveFilter(NULL), file(file)
    01855   {
    01856   }
    01857
    01859   ~FileWriter()
    01860   {
    01861     this->Finish();
    01862
    01863     /* Make sure we don't double free. */
    01864     _sl.sf = NULL;
    01865   }
    01866
    01867   /* virtual */ void Write(byte *buf, size_t size)
    01868   {
    01869     /* We're in the process of shutting down, i.e. in "failure" mode. */
    01870     if (this->file == NULL) return;
    01871
    01872     if (fwrite(buf, 1, size, this->file) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
    01873   }
    01874
    01875   /* virtual */ void Finish()
    01876   {
    01877     if (this->file != NULL) fclose(this->file);
    01878     this->file = NULL;
    01879   }
    01880 };
    01881
    01882 /*******************************************
    01883  ********** START OF LZO CODE **************
    01884  *******************************************/
    01885
    01886 #ifdef WITH_LZO
    01887 #include <lzo/lzo1x.h>
    01888
    01890 static const uint LZO_BUFFER_SIZE = 8192;
    01891
    01893 struct LZOLoadFilter : LoadFilter {
    01898   LZOLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    01899   {
    01900     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    01901   }
    01902
    01903   /* virtual */ size_t Read(byte *buf, size_t ssize)
    01904   {
    01905     assert(ssize >= LZO_BUFFER_SIZE);
    01906
    01907     /* Buffer size is from the LZO docs plus the chunk header size. */
    01908     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
    01909     uint32 tmp[2];
    01910     uint32 size;
    01911     lzo_uint len;
    01912
    01913     /* Read header*/
    01914     if (this->chain->Read((byte*)tmp, sizeof(tmp)) != sizeof(tmp)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE, "File read failed");
    01915
    01916     /* Check if size is bad */
    01917     ((uint32*)out)[0] = size = tmp[1];
    01918
    01919     if (_sl_version != 0) {
    01920       tmp[0] = TO_BE32(tmp[0]);
    01921       size = TO_BE32(size);
    01922     }
    01923
    01924     if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size");
    01925
    01926     /* Read block */
    01927     if (this->chain->Read(out + sizeof(uint32), size) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    01928
    01929     /* Verify checksum */
    01930     if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
    01931
    01932     /* Decompress */
    01933     lzo1x_decompress_safe(out + sizeof(uint32) * 1, size, buf, &len, NULL);
    01934     return len;
    01935   }
    01936 };
    01937
    01939 struct LZOSaveFilter : SaveFilter {
    01945   LZOSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    01946   {
    01947     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    01948   }
    01949
    01950   /* virtual */ void Write(byte *buf, size_t size)
    01951   {
    01952     const lzo_bytep in = buf;
    01953     /* Buffer size is from the LZO docs plus the chunk header size. */
    01954     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
    01955     byte wrkmem[LZO1X_1_MEM_COMPRESS];
    01956     lzo_uint outlen;
    01957
    01958     do {
    01959       /* Compress up to LZO_BUFFER_SIZE bytes at once. */
    01960       lzo_uint len = size > LZO_BUFFER_SIZE ? LZO_BUFFER_SIZE : (lzo_uint)size;
    01961       lzo1x_1_compress(in, len, out + sizeof(uint32) * 2, &outlen, wrkmem);
    01962       ((uint32*)out)[1] = TO_BE32((uint32)outlen);
    01963       ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
    01964       this->chain->Write(out, outlen + sizeof(uint32) * 2);
    01965
    01966       /* Move to next data chunk. */
    01967       size -= len;
    01968       in += len;
    01969     } while (size > 0);
    01970   }
    01971 };
    01972
    01973 #endif /* WITH_LZO */
    01974
    01975 /*********************************************
    01976  ******** START OF NOCOMP CODE (uncompressed)*
    01977  *********************************************/
    01978
    01980 struct NoCompLoadFilter : LoadFilter {
    01985   NoCompLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    01986   {
    01987   }
    01988
    01989   /* virtual */ size_t Read(byte *buf, size_t size)
    01990   {
    01991     return this->chain->Read(buf, size);
    01992   }
    01993 };
    01994
    01996 struct NoCompSaveFilter : SaveFilter {
    02002   NoCompSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    02003   {
    02004   }
    02005
    02006   /* virtual */ void Write(byte *buf, size_t size)
    02007   {
    02008     this->chain->Write(buf, size);
    02009   }
    02010 };
    02011
    02012 /********************************************
    02013  ********** START OF ZLIB CODE **************
    02014  ********************************************/
    02015
    02016 #if defined(WITH_ZLIB)
    02017 #include <zlib.h>
    02018
    02020 struct ZlibLoadFilter : LoadFilter {
    02021   z_stream z;
    02022   byte fread_buf[MEMORY_CHUNK_SIZE];
    02023
    02028   ZlibLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    02029   {
    02030     memset(&this->z, 0, sizeof(this->z));
    02031     if (inflateInit(&this->z) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    02032   }
    02033
    02035   ~ZlibLoadFilter()
    02036   {
    02037     inflateEnd(&this->z);
    02038   }
    02039
    02040   /* virtual */ size_t Read(byte *buf, size_t size)
    02041   {
    02042     this->z.next_out  = buf;
    02043     this->z.avail_out = (uint)size;
    02044
    02045     do {
    02046       /* read more bytes from the file? */
    02047       if (this->z.avail_in == 0) {
    02048         this->z.next_in = this->fread_buf;
    02049         this->z.avail_in = (uint)this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
    02050       }
    02051
    02052       /* inflate the data */
    02053       int r = inflate(&this->z, 0);
    02054       if (r == Z_STREAM_END) break;
    02055
    02056       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "inflate() failed");
    02057     } while (this->z.avail_out != 0);
    02058
    02059     return size - this->z.avail_out;
    02060   }
    02061 };
    02062
    02064 struct ZlibSaveFilter : SaveFilter {
    02065   z_stream z;
    02066
    02072   ZlibSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    02073   {
    02074     memset(&this->z, 0, sizeof(this->z));
    02075     if (deflateInit(&this->z, compression_level) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    02076   }
    02077
    02079   ~ZlibSaveFilter()
    02080   {
    02081     deflateEnd(&this->z);
    02082   }
    02083
    02090   void WriteLoop(byte *p, size_t len, int mode)
    02091   {
    02092     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
    02093     uint n;
    02094     this->z.next_in = p;
    02095     this->z.avail_in = (uInt)len;
    02096     do {
    02097       this->z.next_out = buf;
    02098       this->z.avail_out = sizeof(buf);
    02099
    02107       int r = deflate(&this->z, mode);
    02108
    02109       /* bytes were emitted? */
    02110       if ((n = sizeof(buf) - this->z.avail_out) != 0) {
    02111         this->chain->Write(buf, n);
    02112       }
    02113       if (r == Z_STREAM_END) break;
    02114
    02115       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code");
    02116     } while (this->z.avail_in || !this->z.avail_out);
    02117   }
    02118
    02119   /* virtual */ void Write(byte *buf, size_t size)
    02120   {
    02121     this->WriteLoop(buf, size, 0);
    02122   }
    02123
    02124   /* virtual */ void Finish()
    02125   {
    02126     this->WriteLoop(NULL, 0, Z_FINISH);
    02127     this->chain->Finish();
    02128   }
    02129 };
    02130
    02131 #endif /* WITH_ZLIB */
    02132
    02133 /********************************************
    02134  ********** START OF LZMA CODE **************
    02135  ********************************************/
    02136
    02137 #if defined(WITH_LZMA)
    02138 #include <lzma.h>
    02139
    02146 static const lzma_stream _lzma_init = LZMA_STREAM_INIT;
    02147
    02149 struct LZMALoadFilter : LoadFilter {
    02150   lzma_stream lzma;
    02151   byte fread_buf[MEMORY_CHUNK_SIZE];
    02152
    02157   LZMALoadFilter(LoadFilter *chain) : LoadFilter(chain), lzma(_lzma_init)
    02158   {
    02159     /* Allow saves up to 256 MB uncompressed */
    02160     if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    02161   }
    02162
    02164   ~LZMALoadFilter()
    02165   {
    02166     lzma_end(&this->lzma);
    02167   }
    02168
    02169   /* virtual */ size_t Read(byte *buf, size_t size)
    02170   {
    02171     this->lzma.next_out  = buf;
    02172     this->lzma.avail_out = size;
    02173
    02174     do {
    02175       /* read more bytes from the file? */
    02176       if (this->lzma.avail_in == 0) {
    02177         this->lzma.next_in  = this->fread_buf;
    02178         this->lzma.avail_in = this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
    02179       }
    02180
    02181       /* inflate the data */
    02182       lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
    02183       if (r == LZMA_STREAM_END) break;
    02184       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
    02185     } while (this->lzma.avail_out != 0);
    02186
    02187     return size - this->lzma.avail_out;
    02188   }
    02189 };
    02190
    02192 struct LZMASaveFilter : SaveFilter {
    02193   lzma_stream lzma;
    02194
    02200   LZMASaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain), lzma(_lzma_init)
    02201   {
    02202     if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    02203   }
    02204
    02206   ~LZMASaveFilter()
    02207   {
    02208     lzma_end(&this->lzma);
    02209   }
    02210
    02217   void WriteLoop(byte *p, size_t len, lzma_action action)
    02218   {
    02219     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
    02220     size_t n;
    02221     this->lzma.next_in = p;
    02222     this->lzma.avail_in = len;
    02223     do {
    02224       this->lzma.next_out = buf;
    02225       this->lzma.avail_out = sizeof(buf);
    02226
    02227       lzma_ret r = lzma_code(&this->lzma, action);
    02228
    02229       /* bytes were emitted? */
    02230       if ((n = sizeof(buf) - this->lzma.avail_out) != 0) {
    02231         this->chain->Write(buf, n);
    02232       }
    02233       if (r == LZMA_STREAM_END) break;
    02234       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
    02235     } while (this->lzma.avail_in || !this->lzma.avail_out);
    02236   }
    02237
    02238   /* virtual */ void Write(byte *buf, size_t size)
    02239   {
    02240     this->WriteLoop(buf, size, LZMA_RUN);
    02241   }
    02242
    02243   /* virtual */ void Finish()
    02244   {
    02245     this->WriteLoop(NULL, 0, LZMA_FINISH);
    02246     this->chain->Finish();
    02247   }
    02248 };
    02249
    02250 #endif /* WITH_LZMA */
    02251
    02252 /*******************************************
    02253  ************* END OF CODE *****************
    02254  *******************************************/
    02255
    02257 struct SaveLoadFormat {
    02258   const char *name;
    02259   uint32 tag;
    02260
    02261   LoadFilter *(*init_load)(LoadFilter *chain);
    02262   SaveFilter *(*init_write)(SaveFilter *chain, byte compression);
    02263
    02264   byte min_compression;
    02265   byte default_compression;
    02266   byte max_compression;
    02267 };
    02268
    02270 static const SaveLoadFormat _saveload_formats[] = {
    02271 #if defined(WITH_LZO)
    02272   /* Roughly 75% larger than zlib level 6 at only ~7% of the CPU usage. */
    02273   {"lzo",    TO_BE32X('OTTD'), CreateLoadFilter<LZOLoadFilter>,    CreateSaveFilter<LZOSaveFilter>,    0, 0, 0},
    02274 #else
    02275   {"lzo",    TO_BE32X('OTTD'), NULL,                               NULL,                               0, 0, 0},
    02276 #endif
    02277   /* Roughly 5 times larger at only 1% of the CPU usage over zlib level 6. */
    02278   {"none",   TO_BE32X('OTTN'), CreateLoadFilter<NoCompLoadFilter>, CreateSaveFilter<NoCompSaveFilter>, 0, 0, 0},
    02279 #if defined(WITH_ZLIB)
    02280   /* After level 6 the speed reduction is significant (1.5x to 2.5x slower per level), but the reduction in filesize is
    02281    * fairly insignificant (~1% for each step). Lower levels become ~5-10% bigger by each level than level 6 while level
    02282    * 1 is "only" 3 times as fast. Level 0 results in uncompressed savegames at about 8 times the cost of "none". */
    02283   {"zlib",   TO_BE32X('OTTZ'), CreateLoadFilter<ZlibLoadFilter>,   CreateSaveFilter<ZlibSaveFilter>,   0, 6, 9},
    02284 #else
    02285   {"zlib",   TO_BE32X('OTTZ'), NULL,                               NULL,                               0, 0, 0},
    02286 #endif
    02287 #if defined(WITH_LZMA)
    02288   /* Level 2 compression is speed wise as fast as zlib level 6 compression (old default), but results in ~10% smaller saves.
    02289    * Higher compression levels are possible, and might improve savegame size by up to 25%, but are also up to 10 times slower.
    02290    * The next significant reduction in file size is at level 4, but that is already 4 times slower. Level 3 is primarily 50%
    02291    * slower while not improving the filesize, while level 0 and 1 are faster, but don't reduce savegame size much.
    02292    * It's OTTX and not e.g. OTTL because liblzma is part of xz-utils and .tar.xz is preferred over .tar.lzma. */
    02293   {"lzma",   TO_BE32X('OTTX'), CreateLoadFilter<LZMALoadFilter>,   CreateSaveFilter<LZMASaveFilter>,   0, 2, 9},
    02294 #else
    02295   {"lzma",   TO_BE32X('OTTX'), NULL,                               NULL,                               0, 0, 0},
    02296 #endif
    02297 };
    02298
    02306 static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
    02307 {
    02308   const SaveLoadFormat *def = lastof(_saveload_formats);
    02309
    02310   /* find default savegame format, the highest one with which files can be written */
    02311   while (!def->init_write) def--;
    02312
    02313   if (!StrEmpty(s)) {
    02314     /* Get the ":..." of the compression level out of the way */
    02315     char *complevel = strrchr(s, ':');
    02316     if (complevel != NULL) *complevel = '\0';
    02317
    02318     for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
    02319       if (slf->init_write != NULL && strcmp(s, slf->name) == 0) {
    02320         *compression_level = slf->default_compression;
    02321         if (complevel != NULL) {
    02322           /* There is a compression level in the string.
    02323            * First restore the : we removed to do proper name matching,
    02324            * then move the the begin of the actual version. */
    02325           *complevel = ':';
    02326           complevel++;
    02327
    02328           /* Get the version and determine whether all went fine. */
    02329           char *end;
    02330           long level = strtol(complevel, &end, 10);
    02331           if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) {
    02332             SetDParamStr(0, complevel);
    02333             ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL, WL_CRITICAL);
    02334           } else {
    02335             *compression_level = level;
    02336           }
    02337         }
    02338         return slf;
    02339       }
    02340     }
    02341
    02342     SetDParamStr(0, s);
    02343     SetDParamStr(1, def->name);
    02344     ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM, WL_CRITICAL);
    02345
    02346     /* Restore the string by adding the : back */
    02347     if (complevel != NULL) *complevel = ':';
    02348   }
    02349   *compression_level = def->default_compression;
    02350   return def;
    02351 }
    02352
    02353 /* actual loader/saver function */
    02354 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings);
    02355 extern bool AfterLoadGame();
    02356 extern bool LoadOldSaveGame(const char *file);
    02357
    02361 static inline void ClearSaveLoadState()
    02362 {
    02363   delete _sl.dumper;
    02364   _sl.dumper = NULL;
    02365
    02366   delete _sl.sf;
    02367   _sl.sf = NULL;
    02368
    02369   delete _sl.reader;
    02370   _sl.reader = NULL;
    02371
    02372   delete _sl.lf;
    02373   _sl.lf = NULL;
    02374 }
    02375
    02381 static void SaveFileStart()
    02382 {
    02383   _sl.ff_state = _fast_forward;
    02384   _fast_forward = 0;
    02385   if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
    02386
    02387   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START);
    02388   _sl.saveinprogress = true;
    02389 }
    02390
    02392 static void SaveFileDone()
    02393 {
    02394   if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state;
    02395   if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
    02396
    02397   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
    02398   _sl.saveinprogress = false;
    02399 }
    02400
    02402 void SetSaveLoadError(StringID str)
    02403 {
    02404   _sl.error_str = str;
    02405 }
    02406
    02408 const char *GetSaveLoadErrorString()
    02409 {
    02410   SetDParam(0, _sl.error_str);
    02411   SetDParamStr(1, _sl.extra_msg);
    02412
    02413   static char err_str[512];
    02414   GetString(err_str, _sl.action == SLA_SAVE ? STR_ERROR_GAME_SAVE_FAILED : STR_ERROR_GAME_LOAD_FAILED, lastof(err_str));
    02415   return err_str;
    02416 }
    02417
    02419 static void SaveFileError()
    02420 {
    02421   SetDParamStr(0, GetSaveLoadErrorString());
    02422   ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
    02423   SaveFileDone();
    02424 }
    02425
    02430 static SaveOrLoadResult SaveFileToDisk(bool threaded)
    02431 {
    02432   try {
    02433     byte compression;
    02434     const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format, &compression);
    02435
    02436     /* We have written our stuff to memory, now write it to file! */
    02437     uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) };
    02438     _sl.sf->Write((byte*)hdr, sizeof(hdr));
    02439
    02440     _sl.sf = fmt->init_write(_sl.sf, compression);
    02441     _sl.dumper->Flush(_sl.sf);
    02442
    02443     ClearSaveLoadState();
    02444
    02445     if (threaded) SetAsyncSaveFinish(SaveFileDone);
    02446
    02447     return SL_OK;
    02448   } catch (...) {
    02449     ClearSaveLoadState();
    02450
    02451     AsyncSaveFinishProc asfp = SaveFileDone;
    02452
    02453     /* We don't want to shout when saving is just
    02454      * cancelled due to a client disconnecting. */
    02455     if (_sl.error_str != STR_NETWORK_ERROR_LOSTCONNECTION) {
    02456       /* Skip the "colour" character */
    02457       DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
    02458       asfp = SaveFileError;
    02459     }
    02460
    02461     if (threaded) {
    02462       SetAsyncSaveFinish(asfp);
    02463     } else {
    02464       asfp();
    02465     }
    02466     return SL_ERROR;
    02467   }
    02468 }
    02469
    02471 static void SaveFileToDiskThread(void *arg)
    02472 {
    02473   SaveFileToDisk(true);
    02474 }
    02475
    02476 void WaitTillSaved()
    02477 {
    02478   if (_save_thread == NULL) return;
    02479
    02480   _save_thread->Join();
    02481   delete _save_thread;
    02482   _save_thread = NULL;
    02483
    02484   /* Make sure every other state is handled properly as well. */
    02485   ProcessAsyncSaveFinish();
    02486 }
    02487
    02496 static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
    02497 {
    02498   assert(!_sl.saveinprogress);
    02499
    02500   _sl.dumper = new MemoryDumper();
    02501   _sl.sf = writer;
    02502
    02503   _sl_version = SAVEGAME_VERSION;
    02504
    02505   SaveViewportBeforeSaveGame();
    02506   SlSaveChunks();
    02507
    02508   SaveFileStart();
    02509   if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
    02510     if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
    02511
    02512     SaveOrLoadResult result = SaveFileToDisk(false);
    02513     SaveFileDone();
    02514
    02515     return result;
    02516   }
    02517
    02518   return SL_OK;
    02519 }
    02520
    02527 SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
    02528 {
    02529   try {
    02530     _sl.action = SLA_SAVE;
    02531     return DoSave(writer, threaded);
    02532   } catch (...) {
    02533     ClearSaveLoadState();
    02534     return SL_ERROR;
    02535   }
    02536 }
    02537
    02544 static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
    02545 {
    02546   _sl.lf = reader;
    02547
    02548   if (load_check) {
    02549     /* Clear previous check data */
    02550     _load_check_data.Clear();
    02551     /* Mark SL_LOAD_CHECK as supported for this savegame. */
    02552     _load_check_data.checkable = true;
    02553   }
    02554
    02555   uint32 hdr[2];
    02556   if (_sl.lf->Read((byte*)hdr, sizeof(hdr)) != sizeof(hdr)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    02557
    02558   /* see if we have any loader for this type. */
    02559   const SaveLoadFormat *fmt = _saveload_formats;
    02560   for (;;) {
    02561     /* No loader found, treat as version 0 and use LZO format */
    02562     if (fmt == endof(_saveload_formats)) {
    02563       DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format");
    02564       _sl.lf->Reset();
    02565       _sl_version = 0;
    02566       _sl_minor_version = 0;
    02567
    02568       /* Try to find the LZO savegame format; it uses 'OTTD' as tag. */
    02569       fmt = _saveload_formats;
    02570       for (;;) {
    02571         if (fmt == endof(_saveload_formats)) {
    02572           /* Who removed LZO support? Bad bad boy! */
    02573           NOT_REACHED();
    02574         }
    02575         if (fmt->tag == TO_BE32X('OTTD')) break;
    02576         fmt++;
    02577       }
    02578       break;
    02579     }
    02580
    02581     if (fmt->tag == hdr[0]) {
    02582       /* check version number */
    02583       _sl_version = TO_BE32(hdr[1]) >> 16;
    02584       /* Minor is not used anymore from version 18.0, but it is still needed
    02585        * in versions before that (4 cases) which can't be removed easy.
    02586        * Therefore it is loaded, but never saved (or, it saves a 0 in any scenario). */
    02587       _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
    02588
    02589       DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
    02590
    02591       /* Is the version higher than the current? */
    02592       if (_sl_version > SAVEGAME_VERSION) SlError(STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME);
    02593       break;
    02594     }
    02595
    02596     fmt++;
    02597   }
    02598
    02599   /* loader for this savegame type is not implemented? */
    02600   if (fmt->init_load == NULL) {
    02601     char err_str[64];
    02602     snprintf(err_str, lengthof(err_str), "Loader for '%s' is not available.", fmt->name);
    02603     SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
    02604   }
    02605
    02606   _sl.lf = fmt->init_load(_sl.lf);
    02607   _sl.reader = new ReadBuffer(_sl.lf);
    02608   _next_offs = 0;
    02609
    02610   if (!load_check) {
    02611     /* Old maps were hardcoded to 256x256 and thus did not contain
    02612      * any mapsize information. Pre-initialize to 256x256 to not to
    02613      * confuse old games */
    02614     InitializeGame(256, 256, true, true);
    02615
    02616     GamelogReset();
    02617
    02618     if (IsSavegameVersionBefore(4)) {
    02619       /*
    02620        * NewGRFs were introduced between 0.3,4 and 0.3.5, which both
    02621        * shared savegame version 4. Anything before that 'obviously'
    02622        * does not have any NewGRFs. Between the introduction and
    02623        * savegame version 41 (just before 0.5) the NewGRF settings
    02624        * were not stored in the savegame and they were loaded by
    02625        * using the settings from the main menu.
    02626        * So, to recap:
    02627        * - savegame version  <  4:  do not load any NewGRFs.
    02628        * - savegame version >= 41:  load NewGRFs from savegame, which is
    02629        *                            already done at this stage by
    02630        *                            overwriting the main menu settings.
    02631        * - other savegame versions: use main menu settings.
    02632        *
    02633        * This means that users *can* crash savegame version 4..40
    02634        * savegames if they set incompatible NewGRFs in the main menu,
    02635        * but can't crash anymore for savegame version < 4 savegames.
    02636        *
    02637        * Note: this is done here because AfterLoadGame is also called
    02638        * for TTO/TTD/TTDP savegames which have their own NewGRF logic.
    02639        */
    02640       ClearGRFConfigList(&_grfconfig);
    02641     }
    02642   }
    02643
    02644   if (load_check) {
    02645     /* Load chunks into _load_check_data.
    02646      * No pools are loaded. References are not possible, and thus do not need resolving. */
    02647     SlLoadCheckChunks();
    02648   } else {
    02649     /* Load chunks and resolve references */
    02650     SlLoadChunks();
    02651     SlFixPointers();
    02652   }
    02653
    02654   ClearSaveLoadState();
    02655
    02656   _savegame_type = SGT_OTTD;
    02657
    02658   if (load_check) {
    02659     /* The only part from AfterLoadGame() we need */
    02660     _load_check_data.grf_compatibility = IsGoodGRFConfigList(_load_check_data.grfconfig);
    02661   } else {
    02662     GamelogStartAction(GLAT_LOAD);
    02663
    02664     /* After loading fix up savegame for any internal changes that
    02665      * might have occurred since then. If it fails, load back the old game. */
    02666     if (!AfterLoadGame()) {
    02667       GamelogStopAction();
    02668       return SL_REINIT;
    02669     }
    02670
    02671     GamelogStopAction();
    02672   }
    02673
    02674   return SL_OK;
    02675 }
    02676
    02682 SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
    02683 {
    02684   try {
    02685     _sl.action = SLA_LOAD;
    02686     return DoLoad(reader, false);
    02687   } catch (...) {
    02688     ClearSaveLoadState();
    02689     return SL_REINIT;
    02690   }
    02691 }
    02692
    02702 SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
    02703 {
    02704   /* An instance of saving is already active, so don't go saving again */
    02705   if (_sl.saveinprogress && mode == SL_SAVE && threaded) {
    02706     /* if not an autosave, but a user action, show error message */
    02707     if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
    02708     return SL_OK;
    02709   }
    02710   WaitTillSaved();
    02711
    02712   /* Load a TTDLX or TTDPatch game */
    02713   if (mode == SL_OLD_LOAD) {
    02714     InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
    02715
    02716     /* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
    02717      * and if so a new NewGRF list will be made in LoadOldSaveGame.
    02718      * Note: this is done here because AfterLoadGame is also called
    02719      * for OTTD savegames which have their own NewGRF logic. */
    02720     ClearGRFConfigList(&_grfconfig);
    02721     GamelogReset();
    02722     if (!LoadOldSaveGame(filename)) return SL_REINIT;
    02723     _sl_version = 0;
    02724     _sl_minor_version = 0;
    02725     GamelogStartAction(GLAT_LOAD);
    02726     if (!AfterLoadGame()) {
    02727       GamelogStopAction();
    02728       return SL_REINIT;
    02729     }
    02730     GamelogStopAction();
    02731     return SL_OK;
    02732   }
    02733
    02734   switch (mode) {
    02735     case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
    02736     case SL_LOAD: _sl.action = SLA_LOAD; break;
    02737     case SL_SAVE: _sl.action = SLA_SAVE; break;
    02738     default: NOT_REACHED();
    02739   }
    02740
    02741   try {
    02742     FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
    02743
    02744     /* Make it a little easier to load savegames from the console */
    02745     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
    02746     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
    02747     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SCENARIO_DIR);
    02748
    02749     if (fh == NULL) {
    02750       SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    02751     }
    02752
    02753     if (mode == SL_SAVE) { // SAVE game
    02754       DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
    02755       if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
    02756
    02757       return DoSave(new FileWriter(fh), threaded);
    02758     }
    02759
    02760     /* LOAD game */
    02761     assert(mode == SL_LOAD || mode == SL_LOAD_CHECK);
    02762     DEBUG(desync, 1, "load: %s", filename);
    02763     return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK);
    02764   } catch (...) {
    02765     ClearSaveLoadState();
    02766
    02767     /* Skip the "colour" character */
    02768     if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
    02769
    02770     /* A saver/loader exception!! reinitialize all variables to prevent crash! */
    02771     return (mode == SL_LOAD) ? SL_REINIT : SL_ERROR;
    02772   }
    02773 }
    02774
    02776 void DoExitSave()
    02777 {
    02778   SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
    02779 }
    02780
    02786 void GenerateDefaultSaveName(char *buf, const char *last)
    02787 {
    02788   /* Check if we have a name for this map, which is the name of the first
    02789    * available company. When there's no company available we'll use
    02790    * 'Spectator' as "company" name. */
    02791   CompanyID cid = _local_company;
    02792   if (!Company::IsValidID(cid)) {
    02793     const Company *c;
    02794     FOR_ALL_COMPANIES(c) {
    02795       cid = c->index;
    02796       break;
    02797     }
    02798   }
    02799
    02800   SetDParam(0, cid);
    02801
    02802   /* Insert current date */
    02803   switch (_settings_client.gui.date_format_in_default_names) {
    02804     case 0: SetDParam(1, STR_JUST_DATE_LONG); break;
    02805     case 1: SetDParam(1, STR_JUST_DATE_TINY); break;
    02806     case 2: SetDParam(1, STR_JUST_DATE_ISO); break;
    02807     default: NOT_REACHED();
    02808   }
    02809   SetDParam(2, _date);
    02810
    02811   /* Get the correct string (special string for when there's not company) */
    02812   GetString(buf, !Company::IsValidID(cid) ? STR_SAVEGAME_NAME_SPECTATOR : STR_SAVEGAME_NAME_DEFAULT, last);
    02813   SanitizeFilename(buf);
    02814 }
    02815
    02816 #if 0
    02817
    02823 int GetSavegameType(char *file)
    02824 {
    02825   const SaveLoadFormat *fmt;
    02826   uint32 hdr;
    02827   FILE *f;
    02828   int mode = SL_OLD_LOAD;
    02829
    02830   f = fopen(file, "rb");
    02831   if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
    02832     DEBUG(sl, 0, "Savegame is obsolete or invalid format");
    02833     mode = SL_LOAD; // don't try to get filename, just show name as it is written
    02834   } else {
    02835     /* see if we have any loader for this type. */
    02836     for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
    02837       if (fmt->tag == hdr) {
    02838         mode = SL_LOAD; // new type of savegame
    02839         break;
    02840       }
    02841     }
    02842   }
    02843
    02844   fclose(f);
    02845   return mode;
    02846 }
    02847 #endif