# saveload.cpp

Go to the documentation of this file.

    00001 /* $Id: saveload.cpp 26169 2013-12-22 11:55:07Z frosch $ */
    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/linkgraph.h"
    00039 #include "../linkgraph/linkgraphjob.h"
    00040 #include "../statusbar_gui.h"
    00041 #include "../fileio_func.h"
    00042 #include "../gamelog.h"
    00043 #include "../string_func.h"
    00044 #include "../fios.h"
    00045 #include "../error.h"
    00046
    00047 #include "table/strings.h"
    00048
    00049 #include "saveload_internal.h"
    00050 #include "saveload_filter.h"
    00051
    00052 /*
    00053  * Previous savegame versions, the trunk revision where they were
    00054  * introduced and the released version that had that particular
    00055  * savegame version.
    00056  * Up to savegame version 18 there is a minor version as well.
    00057  *
    00058  *    1.0         0.1.x, 0.2.x
    00059  *    2.0         0.3.0
    00060  *    2.1         0.3.1, 0.3.2
    00061  *    3.x         lost
    00062  *    4.0     1
    00063  *    4.1   122   0.3.3, 0.3.4
    00064  *    4.2  1222   0.3.5
    00065  *    4.3  1417
    00066  *    4.4  1426
    00067  *    5.0  1429
    00068  *    5.1  1440
    00069  *    5.2  1525   0.3.6
    00070  *    6.0  1721
    00071  *    6.1  1768
    00072  *    7.0  1770
    00073  *    8.0  1786
    00074  *    9.0  1909
    00075  *   10.0  2030
    00076  *   11.0  2033
    00077  *   11.1  2041
    00078  *   12.1  2046
    00079  *   13.1  2080   0.4.0, 0.4.0.1
    00080  *   14.0  2441
    00081  *   15.0  2499
    00082  *   16.0  2817
    00083  *   16.1  3155
    00084  *   17.0  3212
    00085  *   17.1  3218
    00086  *   18    3227
    00087  *   19    3396
    00088  *   20    3403
    00089  *   21    3472   0.4.x
    00090  *   22    3726
    00091  *   23    3915
    00092  *   24    4150
    00093  *   25    4259
    00094  *   26    4466
    00095  *   27    4757
    00096  *   28    4987
    00097  *   29    5070
    00098  *   30    5946
    00099  *   31    5999
    00100  *   32    6001
    00101  *   33    6440
    00102  *   34    6455
    00103  *   35    6602
    00104  *   36    6624
    00105  *   37    7182
    00106  *   38    7195
    00107  *   39    7269
    00108  *   40    7326
    00109  *   41    7348   0.5.x
    00110  *   42    7573
    00111  *   43    7642
    00112  *   44    8144
    00113  *   45    8501
    00114  *   46    8705
    00115  *   47    8735
    00116  *   48    8935
    00117  *   49    8969
    00118  *   50    8973
    00119  *   51    8978
    00120  *   52    9066
    00121  *   53    9316
    00122  *   54    9613
    00123  *   55    9638
    00124  *   56    9667
    00125  *   57    9691
    00126  *   58    9762
    00127  *   59    9779
    00128  *   60    9874
    00129  *   61    9892
    00130  *   62    9905
    00131  *   63    9956
    00132  *   64   10006
    00133  *   65   10210
    00134  *   66   10211
    00135  *   67   10236
    00136  *   68   10266
    00137  *   69   10319
    00138  *   70   10541
    00139  *   71   10567
    00140  *   72   10601
    00141  *   73   10903
    00142  *   74   11030
    00143  *   75   11107
    00144  *   76   11139
    00145  *   77   11172
    00146  *   78   11176
    00147  *   79   11188
    00148  *   80   11228
    00149  *   81   11244
    00150  *   82   11410
    00151  *   83   11589
    00152  *   84   11822
    00153  *   85   11874
    00154  *   86   12042
    00155  *   87   12129
    00156  *   88   12134
    00157  *   89   12160
    00158  *   90   12293
    00159  *   91   12347
    00160  *   92   12381   0.6.x
    00161  *   93   12648
    00162  *   94   12816
    00163  *   95   12924
    00164  *   96   13226
    00165  *   97   13256
    00166  *   98   13375
    00167  *   99   13838
    00168  *  100   13952
    00169  *  101   14233
    00170  *  102   14332
    00171  *  103   14598
    00172  *  104   14735
    00173  *  105   14803
    00174  *  106   14919
    00175  *  107   15027
    00176  *  108   15045
    00177  *  109   15075
    00178  *  110   15148
    00179  *  111   15190
    00180  *  112   15290
    00181  *  113   15340
    00182  *  114   15601
    00183  *  115   15695
    00184  *  116   15893   0.7.x
    00185  *  117   16037
    00186  *  118   16129
    00187  *  119   16242
    00188  *  120   16439
    00189  *  121   16694
    00190  *  122   16855
    00191  *  123   16909
    00192  *  124   16993
    00193  *  125   17113
    00194  *  126   17433
    00195  *  127   17439
    00196  *  128   18281
    00197  *  129   18292
    00198  *  130   18404
    00199  *  131   18481
    00200  *  132   18522
    00201  *  133   18674
    00202  *  134   18703
    00203  *  135   18719
    00204  *  136   18764
    00205  *  137   18912
    00206  *  138   18942   1.0.x
    00207  *  139   19346
    00208  *  140   19382
    00209  *  141   19799
    00210  *  142   20003
    00211  *  143   20048
    00212  *  144   20334
    00213  *  145   20376
    00214  *  146   20446
    00215  *  147   20621
    00216  *  148   20659
    00217  *  149   20832
    00218  *  150   20857
    00219  *  151   20918
    00220  *  152   21171
    00221  *  153   21263
    00222  *  154   21426
    00223  *  155   21453
    00224  *  156   21728
    00225  *  157   21862
    00226  *  158   21933
    00227  *  159   21962
    00228  *  160   21974   1.1.x
    00229  *  161   22567
    00230  *  162   22713
    00231  *  163   22767
    00232  *  164   23290
    00233  *  165   23304
    00234  *  166   23415
    00235  *  167   23504
    00236  *  168   23637
    00237  *  169   23816
    00238  *  170   23826
    00239  *  171   23835
    00240  *  172   23947
    00241  *  173   23967   1.2.0-RC1
    00242  *  174   23973   1.2.x
    00243  *  175   24136
    00244  *  176   24446
    00245  *  177   24619
    00246  *  178   24789
    00247  *  179   24810
    00248  *  180   24998   1.3.x
    00249  *  181   25012
    00250  *  182   25296
    00251  *  183   25363
    00252  *  184   25508
    00253  *  185   25620
    00254  *  186   25833
    00255  *  187   25899
    00256  *  188   26169
    00257  */
    00258 extern const uint16 SAVEGAME_VERSION = 188;
    00259
    00260 SavegameType _savegame_type;
    00261
    00262 uint32 _ttdp_version;
    00263 uint16 _sl_version;
    00264 byte   _sl_minor_version;
    00265 char _savegame_format[8];
    00266 bool _do_autosave;
    00267
    00269 enum SaveLoadAction {
    00270   SLA_LOAD,
    00271   SLA_SAVE,
    00272   SLA_PTRS,
    00273   SLA_NULL,
    00274   SLA_LOAD_CHECK,
    00275 };
    00276
    00277 enum NeedLength {
    00278   NL_NONE = 0,
    00279   NL_WANTLENGTH = 1,
    00280   NL_CALCLENGTH = 2,
    00281 };
    00282
    00284 static const size_t MEMORY_CHUNK_SIZE = 128 * 1024;
    00285
    00287 struct ReadBuffer {
    00288   byte buf[MEMORY_CHUNK_SIZE];
    00289   byte *bufp;
    00290   byte *bufe;
    00291   LoadFilter *reader;
    00292   size_t read;
    00293
    00298   ReadBuffer(LoadFilter *reader) : bufp(NULL), bufe(NULL), reader(reader), read(0)
    00299   {
    00300   }
    00301
    00302   inline byte ReadByte()
    00303   {
    00304     if (this->bufp == this->bufe) {
    00305       size_t len = this->reader->Read(this->buf, lengthof(this->buf));
    00306       if (len == 0) SlErrorCorrupt("Unexpected end of chunk");
    00307
    00308       this->read += len;
    00309       this->bufp = this->buf;
    00310       this->bufe = this->buf + len;
    00311     }
    00312
    00313     return *this->bufp++;
    00314   }
    00315
    00320   size_t GetSize() const
    00321   {
    00322     return this->read - (this->bufe - this->bufp);
    00323   }
    00324 };
    00325
    00326
    00328 struct MemoryDumper {
    00329   AutoFreeSmallVector<byte *, 16> blocks;
    00330   byte *buf;
    00331   byte *bufe;
    00332
    00334   MemoryDumper() : buf(NULL), bufe(NULL)
    00335   {
    00336   }
    00337
    00342   inline void WriteByte(byte b)
    00343   {
    00344     /* Are we at the end of this chunk? */
    00345     if (this->buf == this->bufe) {
    00346       this->buf = CallocT<byte>(MEMORY_CHUNK_SIZE);
    00347       *this->blocks.Append() = this->buf;
    00348       this->bufe = this->buf + MEMORY_CHUNK_SIZE;
    00349     }
    00350
    00351     *this->buf++ = b;
    00352   }
    00353
    00358   void Flush(SaveFilter *writer)
    00359   {
    00360     uint i = 0;
    00361     size_t t = this->GetSize();
    00362
    00363     while (t > 0) {
    00364       size_t to_write = min(MEMORY_CHUNK_SIZE, t);
    00365
    00366       writer->Write(this->blocks[i++], to_write);
    00367       t -= to_write;
    00368     }
    00369
    00370     writer->Finish();
    00371   }
    00372
    00377   size_t GetSize() const
    00378   {
    00379     return this->blocks.Length() * MEMORY_CHUNK_SIZE - (this->bufe - this->buf);
    00380   }
    00381 };
    00382
    00384 struct SaveLoadParams {
    00385   SaveLoadAction action;
    00386   NeedLength need_length;
    00387   byte block_mode;
    00388   bool error;
    00389
    00390   size_t obj_len;
    00391   int array_index, last_array_index;
    00392
    00393   MemoryDumper *dumper;
    00394   SaveFilter *sf;
    00395
    00396   ReadBuffer *reader;
    00397   LoadFilter *lf;
    00398
    00399   StringID error_str;
    00400   char *extra_msg;
    00401
    00402   byte ff_state;
    00403   bool saveinprogress;
    00404 };
    00405
    00406 static SaveLoadParams _sl;
    00407
    00408 /* these define the chunks */
    00409 extern const ChunkHandler _gamelog_chunk_handlers[];
    00410 extern const ChunkHandler _map_chunk_handlers[];
    00411 extern const ChunkHandler _misc_chunk_handlers[];
    00412 extern const ChunkHandler _name_chunk_handlers[];
    00413 extern const ChunkHandler _cheat_chunk_handlers[] ;
    00414 extern const ChunkHandler _setting_chunk_handlers[];
    00415 extern const ChunkHandler _company_chunk_handlers[];
    00416 extern const ChunkHandler _engine_chunk_handlers[];
    00417 extern const ChunkHandler _veh_chunk_handlers[];
    00418 extern const ChunkHandler _waypoint_chunk_handlers[];
    00419 extern const ChunkHandler _depot_chunk_handlers[];
    00420 extern const ChunkHandler _order_chunk_handlers[];
    00421 extern const ChunkHandler _town_chunk_handlers[];
    00422 extern const ChunkHandler _sign_chunk_handlers[];
    00423 extern const ChunkHandler _station_chunk_handlers[];
    00424 extern const ChunkHandler _industry_chunk_handlers[];
    00425 extern const ChunkHandler _economy_chunk_handlers[];
    00426 extern const ChunkHandler _subsidy_chunk_handlers[];
    00427 extern const ChunkHandler _cargomonitor_chunk_handlers[];
    00428 extern const ChunkHandler _goal_chunk_handlers[];
    00429 extern const ChunkHandler _story_page_chunk_handlers[];
    00430 extern const ChunkHandler _ai_chunk_handlers[];
    00431 extern const ChunkHandler _game_chunk_handlers[];
    00432 extern const ChunkHandler _animated_tile_chunk_handlers[];
    00433 extern const ChunkHandler _newgrf_chunk_handlers[];
    00434 extern const ChunkHandler _group_chunk_handlers[];
    00435 extern const ChunkHandler _cargopacket_chunk_handlers[];
    00436 extern const ChunkHandler _autoreplace_chunk_handlers[];
    00437 extern const ChunkHandler _labelmaps_chunk_handlers[];
    00438 extern const ChunkHandler _linkgraph_chunk_handlers[];
    00439 extern const ChunkHandler _airport_chunk_handlers[];
    00440 extern const ChunkHandler _object_chunk_handlers[];
    00441 extern const ChunkHandler _persistent_storage_chunk_handlers[];
    00442
    00444 static const ChunkHandler * const _chunk_handlers[] = {
    00445   _gamelog_chunk_handlers,
    00446   _map_chunk_handlers,
    00447   _misc_chunk_handlers,
    00448   _name_chunk_handlers,
    00449   _cheat_chunk_handlers,
    00450   _setting_chunk_handlers,
    00451   _veh_chunk_handlers,
    00452   _waypoint_chunk_handlers,
    00453   _depot_chunk_handlers,
    00454   _order_chunk_handlers,
    00455   _industry_chunk_handlers,
    00456   _economy_chunk_handlers,
    00457   _subsidy_chunk_handlers,
    00458   _cargomonitor_chunk_handlers,
    00459   _goal_chunk_handlers,
    00460   _story_page_chunk_handlers,
    00461   _engine_chunk_handlers,
    00462   _town_chunk_handlers,
    00463   _sign_chunk_handlers,
    00464   _station_chunk_handlers,
    00465   _company_chunk_handlers,
    00466   _ai_chunk_handlers,
    00467   _game_chunk_handlers,
    00468   _animated_tile_chunk_handlers,
    00469   _newgrf_chunk_handlers,
    00470   _group_chunk_handlers,
    00471   _cargopacket_chunk_handlers,
    00472   _autoreplace_chunk_handlers,
    00473   _labelmaps_chunk_handlers,
    00474   _linkgraph_chunk_handlers,
    00475   _airport_chunk_handlers,
    00476   _object_chunk_handlers,
    00477   _persistent_storage_chunk_handlers,
    00478   NULL,
    00479 };
    00480
    00485 #define FOR_ALL_CHUNK_HANDLERS(ch) \
    00486   for (const ChunkHandler * const *chsc = _chunk_handlers; *chsc != NULL; chsc++) \
    00487     for (const ChunkHandler *ch = *chsc; ch != NULL; ch = (ch->flags & CH_LAST) ? NULL : ch + 1)
    00488
    00490 static void SlNullPointers()
    00491 {
    00492   _sl.action = SLA_NULL;
    00493
    00494   /* We don't want any savegame conversion code to run
    00495    * during NULLing; especially those that try to get
    00496    * pointers from other pools. */
    00497   _sl_version = SAVEGAME_VERSION;
    00498
    00499   DEBUG(sl, 1, "Nulling pointers");
    00500
    00501   FOR_ALL_CHUNK_HANDLERS(ch) {
    00502     if (ch->ptrs_proc != NULL) {
    00503       DEBUG(sl, 2, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    00504       ch->ptrs_proc();
    00505     }
    00506   }
    00507
    00508   DEBUG(sl, 1, "All pointers nulled");
    00509
    00510   assert(_sl.action == SLA_NULL);
    00511 }
    00512
    00521 void NORETURN SlError(StringID string, const char *extra_msg)
    00522 {
    00523   /* Distinguish between loading into _load_check_data vs. normal save/load. */
    00524   if (_sl.action == SLA_LOAD_CHECK) {
    00525     _load_check_data.error = string;
    00526     free(_load_check_data.error_data);
    00527     _load_check_data.error_data = (extra_msg == NULL) ? NULL : strdup(extra_msg);
    00528   } else {
    00529     _sl.error_str = string;
    00530     free(_sl.extra_msg);
    00531     _sl.extra_msg = (extra_msg == NULL) ? NULL : strdup(extra_msg);
    00532   }
    00533
    00534   /* We have to NULL all pointers here; we might be in a state where
    00535    * the pointers are actually filled with indices, which means that
    00536    * when we access them during cleaning the pool dereferences of
    00537    * those indices will be made with segmentation faults as result. */
    00538   if (_sl.action == SLA_LOAD || _sl.action == SLA_PTRS) SlNullPointers();
    00539   throw std::exception();
    00540 }
    00541
    00549 void NORETURN SlErrorCorrupt(const char *msg)
    00550 {
    00551   SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
    00552 }
    00553
    00554
    00555 typedef void (*AsyncSaveFinishProc)();
    00556 static AsyncSaveFinishProc _async_save_finish = NULL;
    00557 static ThreadObject *_save_thread;
    00558
    00563 static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
    00564 {
    00565   if (_exit_game) return;
    00566   while (_async_save_finish != NULL) CSleep(10);
    00567
    00568   _async_save_finish = proc;
    00569 }
    00570
    00574 void ProcessAsyncSaveFinish()
    00575 {
    00576   if (_async_save_finish == NULL) return;
    00577
    00578   _async_save_finish();
    00579
    00580   _async_save_finish = NULL;
    00581
    00582   if (_save_thread != NULL) {
    00583     _save_thread->Join();
    00584     delete _save_thread;
    00585     _save_thread = NULL;
    00586   }
    00587 }
    00588
    00593 byte SlReadByte()
    00594 {
    00595   return _sl.reader->ReadByte();
    00596 }
    00597
    00602 void SlWriteByte(byte b)
    00603 {
    00604   _sl.dumper->WriteByte(b);
    00605 }
    00606
    00607 static inline int SlReadUint16()
    00608 {
    00609   int x = SlReadByte() << 8;
    00610   return x | SlReadByte();
    00611 }
    00612
    00613 static inline uint32 SlReadUint32()
    00614 {
    00615   uint32 x = SlReadUint16() << 16;
    00616   return x | SlReadUint16();
    00617 }
    00618
    00619 static inline uint64 SlReadUint64()
    00620 {
    00621   uint32 x = SlReadUint32();
    00622   uint32 y = SlReadUint32();
    00623   return (uint64)x << 32 | y;
    00624 }
    00625
    00626 static inline void SlWriteUint16(uint16 v)
    00627 {
    00628   SlWriteByte(GB(v, 8, 8));
    00629   SlWriteByte(GB(v, 0, 8));
    00630 }
    00631
    00632 static inline void SlWriteUint32(uint32 v)
    00633 {
    00634   SlWriteUint16(GB(v, 16, 16));
    00635   SlWriteUint16(GB(v,  0, 16));
    00636 }
    00637
    00638 static inline void SlWriteUint64(uint64 x)
    00639 {
    00640   SlWriteUint32((uint32)(x >> 32));
    00641   SlWriteUint32((uint32)x);
    00642 }
    00643
    00649 static inline void SlSkipBytes(size_t length)
    00650 {
    00651   for (; length != 0; length--) SlReadByte();
    00652 }
    00653
    00663 static uint SlReadSimpleGamma()
    00664 {
    00665   uint i = SlReadByte();
    00666   if (HasBit(i, 7)) {
    00667     i &= ~0x80;
    00668     if (HasBit(i, 6)) {
    00669       i &= ~0x40;
    00670       if (HasBit(i, 5)) {
    00671         i &= ~0x20;
    00672         if (HasBit(i, 4)) {
    00673           SlErrorCorrupt("Unsupported gamma");
    00674         }
    00675         i = (i << 8) | SlReadByte();
    00676       }
    00677       i = (i << 8) | SlReadByte();
    00678     }
    00679     i = (i << 8) | SlReadByte();
    00680   }
    00681   return i;
    00682 }
    00683
    00696 static void SlWriteSimpleGamma(size_t i)
    00697 {
    00698   if (i >= (1 << 7)) {
    00699     if (i >= (1 << 14)) {
    00700       if (i >= (1 << 21)) {
    00701         assert(i < (1 << 28));
    00702         SlWriteByte((byte)(0xE0 | (i >> 24)));
    00703         SlWriteByte((byte)(i >> 16));
    00704       } else {
    00705         SlWriteByte((byte)(0xC0 | (i >> 16)));
    00706       }
    00707       SlWriteByte((byte)(i >> 8));
    00708     } else {
    00709       SlWriteByte((byte)(0x80 | (i >> 8)));
    00710     }
    00711   }
    00712   SlWriteByte((byte)i);
    00713 }
    00714
    00716 static inline uint SlGetGammaLength(size_t i)
    00717 {
    00718   return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21));
    00719 }
    00720
    00721 static inline uint SlReadSparseIndex()
    00722 {
    00723   return SlReadSimpleGamma();
    00724 }
    00725
    00726 static inline void SlWriteSparseIndex(uint index)
    00727 {
    00728   SlWriteSimpleGamma(index);
    00729 }
    00730
    00731 static inline uint SlReadArrayLength()
    00732 {
    00733   return SlReadSimpleGamma();
    00734 }
    00735
    00736 static inline void SlWriteArrayLength(size_t length)
    00737 {
    00738   SlWriteSimpleGamma(length);
    00739 }
    00740
    00741 static inline uint SlGetArrayLength(size_t length)
    00742 {
    00743   return SlGetGammaLength(length);
    00744 }
    00745
    00752 static inline uint SlCalcConvMemLen(VarType conv)
    00753 {
    00754   static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
    00755   byte length = GB(conv, 4, 4);
    00756
    00757   switch (length << 4) {
    00758     case SLE_VAR_STRB:
    00759     case SLE_VAR_STRBQ:
    00760     case SLE_VAR_STR:
    00761     case SLE_VAR_STRQ:
    00762       return SlReadArrayLength();
    00763
    00764     default:
    00765       assert(length < lengthof(conv_mem_size));
    00766       return conv_mem_size[length];
    00767   }
    00768 }
    00769
    00776 static inline byte SlCalcConvFileLen(VarType conv)
    00777 {
    00778   static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
    00779   byte length = GB(conv, 0, 4);
    00780   assert(length < lengthof(conv_file_size));
    00781   return conv_file_size[length];
    00782 }
    00783
    00785 static inline size_t SlCalcRefLen()
    00786 {
    00787   return IsSavegameVersionBefore(69) ? 2 : 4;
    00788 }
    00789
    00790 void SlSetArrayIndex(uint index)
    00791 {
    00792   _sl.need_length = NL_WANTLENGTH;
    00793   _sl.array_index = index;
    00794 }
    00795
    00796 static size_t _next_offs;
    00797
    00802 int SlIterateArray()
    00803 {
    00804   int index;
    00805
    00806   /* After reading in the whole array inside the loop
    00807    * we must have read in all the data, so we must be at end of current block. */
    00808   if (_next_offs != 0 && _sl.reader->GetSize() != _next_offs) SlErrorCorrupt("Invalid chunk size");
    00809
    00810   for (;;) {
    00811     uint length = SlReadArrayLength();
    00812     if (length == 0) {
    00813       _next_offs = 0;
    00814       return -1;
    00815     }
    00816
    00817     _sl.obj_len = --length;
    00818     _next_offs = _sl.reader->GetSize() + length;
    00819
    00820     switch (_sl.block_mode) {
    00821       case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
    00822       case CH_ARRAY:        index = _sl.array_index++; break;
    00823       default:
    00824         DEBUG(sl, 0, "SlIterateArray error");
    00825         return -1; // error
    00826     }
    00827
    00828     if (length != 0) return index;
    00829   }
    00830 }
    00831
    00835 void SlSkipArray()
    00836 {
    00837   while (SlIterateArray() != -1) {
    00838     SlSkipBytes(_next_offs - _sl.reader->GetSize());
    00839   }
    00840 }
    00841
    00847 void SlSetLength(size_t length)
    00848 {
    00849   assert(_sl.action == SLA_SAVE);
    00850
    00851   switch (_sl.need_length) {
    00852     case NL_WANTLENGTH:
    00853       _sl.need_length = NL_NONE;
    00854       switch (_sl.block_mode) {
    00855         case CH_RIFF:
    00856           /* Ugly encoding of >16M RIFF chunks
    00857            * The lower 24 bits are normal
    00858            * The uppermost 4 bits are bits 24:27 */
    00859           assert(length < (1 << 28));
    00860           SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
    00861           break;
    00862         case CH_ARRAY:
    00863           assert(_sl.last_array_index <= _sl.array_index);
    00864           while (++_sl.last_array_index <= _sl.array_index) {
    00865             SlWriteArrayLength(1);
    00866           }
    00867           SlWriteArrayLength(length + 1);
    00868           break;
    00869         case CH_SPARSE_ARRAY:
    00870           SlWriteArrayLength(length + 1 + SlGetArrayLength(_sl.array_index)); // Also include length of sparse index.
    00871           SlWriteSparseIndex(_sl.array_index);
    00872           break;
    00873         default: NOT_REACHED();
    00874       }
    00875       break;
    00876
    00877     case NL_CALCLENGTH:
    00878       _sl.obj_len += (int)length;
    00879       break;
    00880
    00881     default: NOT_REACHED();
    00882   }
    00883 }
    00884
    00891 static void SlCopyBytes(void *ptr, size_t length)
    00892 {
    00893   byte *p = (byte *)ptr;
    00894
    00895   switch (_sl.action) {
    00896     case SLA_LOAD_CHECK:
    00897     case SLA_LOAD:
    00898       for (; length != 0; length--) *p++ = SlReadByte();
    00899       break;
    00900     case SLA_SAVE:
    00901       for (; length != 0; length--) SlWriteByte(*p++);
    00902       break;
    00903     default: NOT_REACHED();
    00904   }
    00905 }
    00906
    00908 size_t SlGetFieldLength()
    00909 {
    00910   return _sl.obj_len;
    00911 }
    00912
    00920 int64 ReadValue(const void *ptr, VarType conv)
    00921 {
    00922   switch (GetVarMemType(conv)) {
    00923     case SLE_VAR_BL:  return (*(const bool *)ptr != 0);
    00924     case SLE_VAR_I8:  return *(const int8  *)ptr;
    00925     case SLE_VAR_U8:  return *(const byte  *)ptr;
    00926     case SLE_VAR_I16: return *(const int16 *)ptr;
    00927     case SLE_VAR_U16: return *(const uint16*)ptr;
    00928     case SLE_VAR_I32: return *(const int32 *)ptr;
    00929     case SLE_VAR_U32: return *(const uint32*)ptr;
    00930     case SLE_VAR_I64: return *(const int64 *)ptr;
    00931     case SLE_VAR_U64: return *(const uint64*)ptr;
    00932     case SLE_VAR_NULL:return 0;
    00933     default: NOT_REACHED();
    00934   }
    00935 }
    00936
    00944 void WriteValue(void *ptr, VarType conv, int64 val)
    00945 {
    00946   switch (GetVarMemType(conv)) {
    00947     case SLE_VAR_BL:  *(bool  *)ptr = (val != 0);  break;
    00948     case SLE_VAR_I8:  *(int8  *)ptr = val; break;
    00949     case SLE_VAR_U8:  *(byte  *)ptr = val; break;
    00950     case SLE_VAR_I16: *(int16 *)ptr = val; break;
    00951     case SLE_VAR_U16: *(uint16*)ptr = val; break;
    00952     case SLE_VAR_I32: *(int32 *)ptr = val; break;
    00953     case SLE_VAR_U32: *(uint32*)ptr = val; break;
    00954     case SLE_VAR_I64: *(int64 *)ptr = val; break;
    00955     case SLE_VAR_U64: *(uint64*)ptr = val; break;
    00956     case SLE_VAR_NAME: *(char**)ptr = CopyFromOldName(val); break;
    00957     case SLE_VAR_NULL: break;
    00958     default: NOT_REACHED();
    00959   }
    00960 }
    00961
    00970 static void SlSaveLoadConv(void *ptr, VarType conv)
    00971 {
    00972   switch (_sl.action) {
    00973     case SLA_SAVE: {
    00974       int64 x = ReadValue(ptr, conv);
    00975
    00976       /* Write the value to the file and check if its value is in the desired range */
    00977       switch (GetVarFileType(conv)) {
    00978         case SLE_FILE_I8: assert(x >= -128 && x <= 127);     SlWriteByte(x);break;
    00979         case SLE_FILE_U8: assert(x >= 0 && x <= 255);        SlWriteByte(x);break;
    00980         case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break;
    00981         case SLE_FILE_STRINGID:
    00982         case SLE_FILE_U16:assert(x >= 0 && x <= 65535);      SlWriteUint16(x);break;
    00983         case SLE_FILE_I32:
    00984         case SLE_FILE_U32:                                   SlWriteUint32((uint32)x);break;
    00985         case SLE_FILE_I64:
    00986         case SLE_FILE_U64:                                   SlWriteUint64(x);break;
    00987         default: NOT_REACHED();
    00988       }
    00989       break;
    00990     }
    00991     case SLA_LOAD_CHECK:
    00992     case SLA_LOAD: {
    00993       int64 x;
    00994       /* Read a value from the file */
    00995       switch (GetVarFileType(conv)) {
    00996         case SLE_FILE_I8:  x = (int8  )SlReadByte();   break;
    00997         case SLE_FILE_U8:  x = (byte  )SlReadByte();   break;
    00998         case SLE_FILE_I16: x = (int16 )SlReadUint16(); break;
    00999         case SLE_FILE_U16: x = (uint16)SlReadUint16(); break;
    01000         case SLE_FILE_I32: x = (int32 )SlReadUint32(); break;
    01001         case SLE_FILE_U32: x = (uint32)SlReadUint32(); break;
    01002         case SLE_FILE_I64: x = (int64 )SlReadUint64(); break;
    01003         case SLE_FILE_U64: x = (uint64)SlReadUint64(); break;
    01004         case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break;
    01005         default: NOT_REACHED();
    01006       }
    01007
    01008       /* Write The value to the struct. These ARE endian safe. */
    01009       WriteValue(ptr, conv, x);
    01010       break;
    01011     }
    01012     case SLA_PTRS: break;
    01013     case SLA_NULL: break;
    01014     default: NOT_REACHED();
    01015   }
    01016 }
    01017
    01027 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
    01028 {
    01029   if (ptr == NULL) return 0;
    01030   return min(strlen(ptr), length - 1);
    01031 }
    01032
    01042 static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
    01043 {
    01044   size_t len;
    01045   const char *str;
    01046
    01047   switch (GetVarMemType(conv)) {
    01048     default: NOT_REACHED();
    01049     case SLE_VAR_STR:
    01050     case SLE_VAR_STRQ:
    01051       str = *(const char * const *)ptr;
    01052       len = SIZE_MAX;
    01053       break;
    01054     case SLE_VAR_STRB:
    01055     case SLE_VAR_STRBQ:
    01056       str = (const char *)ptr;
    01057       len = length;
    01058       break;
    01059   }
    01060
    01061   len = SlCalcNetStringLen(str, len);
    01062   return len + SlGetArrayLength(len); // also include the length of the index
    01063 }
    01064
    01071 static void SlString(void *ptr, size_t length, VarType conv)
    01072 {
    01073   switch (_sl.action) {
    01074     case SLA_SAVE: {
    01075       size_t len;
    01076       switch (GetVarMemType(conv)) {
    01077         default: NOT_REACHED();
    01078         case SLE_VAR_STRB:
    01079         case SLE_VAR_STRBQ:
    01080           len = SlCalcNetStringLen((char *)ptr, length);
    01081           break;
    01082         case SLE_VAR_STR:
    01083         case SLE_VAR_STRQ:
    01084           ptr = *(char **)ptr;
    01085           len = SlCalcNetStringLen((char *)ptr, SIZE_MAX);
    01086           break;
    01087       }
    01088
    01089       SlWriteArrayLength(len);
    01090       SlCopyBytes(ptr, len);
    01091       break;
    01092     }
    01093     case SLA_LOAD_CHECK:
    01094     case SLA_LOAD: {
    01095       size_t len = SlReadArrayLength();
    01096
    01097       switch (GetVarMemType(conv)) {
    01098         default: NOT_REACHED();
    01099         case SLE_VAR_STRB:
    01100         case SLE_VAR_STRBQ:
    01101           if (len >= length) {
    01102             DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
    01103             SlCopyBytes(ptr, length);
    01104             SlSkipBytes(len - length);
    01105             len = length - 1;
    01106           } else {
    01107             SlCopyBytes(ptr, len);
    01108           }
    01109           break;
    01110         case SLE_VAR_STR:
    01111         case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate
    01112           free(*(char **)ptr);
    01113           if (len == 0) {
    01114             *(char **)ptr = NULL;
    01115             return;
    01116           } else {
    01117             *(char **)ptr = MallocT<char>(len + 1); // terminating '\0'
    01118             ptr = *(char **)ptr;
    01119             SlCopyBytes(ptr, len);
    01120           }
    01121           break;
    01122       }
    01123
    01124       ((char *)ptr)[len] = '\0'; // properly terminate the string
    01125       StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK;
    01126       if ((conv & SLF_ALLOW_CONTROL) != 0) {
    01127         settings = settings | SVS_ALLOW_CONTROL_CODE;
    01128         if (IsSavegameVersionBefore(169)) {
    01129           str_fix_scc_encoded((char *)ptr, (char *)ptr + len);
    01130         }
    01131       }
    01132       if ((conv & SLF_ALLOW_NEWLINE) != 0) {
    01133         settings = settings | SVS_ALLOW_NEWLINE;
    01134       }
    01135       str_validate((char *)ptr, (char *)ptr + len, settings);
    01136       break;
    01137     }
    01138     case SLA_PTRS: break;
    01139     case SLA_NULL: break;
    01140     default: NOT_REACHED();
    01141   }
    01142 }
    01143
    01149 static inline size_t SlCalcArrayLen(size_t length, VarType conv)
    01150 {
    01151   return SlCalcConvFileLen(conv) * length;
    01152 }
    01153
    01160 void SlArray(void *array, size_t length, VarType conv)
    01161 {
    01162   if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
    01163
    01164   /* Automatically calculate the length? */
    01165   if (_sl.need_length != NL_NONE) {
    01166     SlSetLength(SlCalcArrayLen(length, conv));
    01167     /* Determine length only? */
    01168     if (_sl.need_length == NL_CALCLENGTH) return;
    01169   }
    01170
    01171   /* NOTICE - handle some buggy stuff, in really old versions everything was saved
    01172    * as a byte-type. So detect this, and adjust array size accordingly */
    01173   if (_sl.action != SLA_SAVE && _sl_version == 0) {
    01174     /* all arrays except difficulty settings */
    01175     if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
    01176         conv == SLE_INT32 || conv == SLE_UINT32) {
    01177       SlCopyBytes(array, length * SlCalcConvFileLen(conv));
    01178       return;
    01179     }
    01180     /* used for conversion of Money 32bit->64bit */
    01181     if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
    01182       for (uint i = 0; i < length; i++) {
    01183         ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
    01184       }
    01185       return;
    01186     }
    01187   }
    01188
    01189   /* If the size of elements is 1 byte both in file and memory, no special
    01190    * conversion is needed, use specialized copy-copy function to speed up things */
    01191   if (conv == SLE_INT8 || conv == SLE_UINT8) {
    01192     SlCopyBytes(array, length);
    01193   } else {
    01194     byte *a = (byte*)array;
    01195     byte mem_size = SlCalcConvMemLen(conv);
    01196
    01197     for (; length != 0; length --) {
    01198       SlSaveLoadConv(a, conv);
    01199       a += mem_size; // get size
    01200     }
    01201   }
    01202 }
    01203
    01204
    01215 static size_t ReferenceToInt(const void *obj, SLRefType rt)
    01216 {
    01217   assert(_sl.action == SLA_SAVE);
    01218
    01219   if (obj == NULL) return 0;
    01220
    01221   switch (rt) {
    01222     case REF_VEHICLE_OLD: // Old vehicles we save as new ones
    01223     case REF_VEHICLE:   return ((const  Vehicle*)obj)->index + 1;
    01224     case REF_STATION:   return ((const  Station*)obj)->index + 1;
    01225     case REF_TOWN:      return ((const     Town*)obj)->index + 1;
    01226     case REF_ORDER:     return ((const    Order*)obj)->index + 1;
    01227     case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
    01228     case REF_ENGINE_RENEWS:  return ((const       EngineRenew*)obj)->index + 1;
    01229     case REF_CARGO_PACKET:   return ((const       CargoPacket*)obj)->index + 1;
    01230     case REF_ORDERLIST:      return ((const         OrderList*)obj)->index + 1;
    01231     case REF_STORAGE:        return ((const PersistentStorage*)obj)->index + 1;
    01232     case REF_LINK_GRAPH:     return ((const         LinkGraph*)obj)->index + 1;
    01233     case REF_LINK_GRAPH_JOB: return ((const      LinkGraphJob*)obj)->index + 1;
    01234     default: NOT_REACHED();
    01235   }
    01236 }
    01237
    01248 static void *IntToReference(size_t index, SLRefType rt)
    01249 {
    01250   assert_compile(sizeof(size_t) <= sizeof(void *));
    01251
    01252   assert(_sl.action == SLA_PTRS);
    01253
    01254   /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE,
    01255    * and should be loaded like that */
    01256   if (rt == REF_VEHICLE_OLD && !IsSavegameVersionBefore(4, 4)) {
    01257     rt = REF_VEHICLE;
    01258   }
    01259
    01260   /* No need to look up NULL pointers, just return immediately */
    01261   if (index == (rt == REF_VEHICLE_OLD ? 0xFFFF : 0)) return NULL;
    01262
    01263   /* Correct index. Old vehicles were saved differently:
    01264    * invalid vehicle was 0xFFFF, now we use 0x0000 for everything invalid. */
    01265   if (rt != REF_VEHICLE_OLD) index--;
    01266
    01267   switch (rt) {
    01268     case REF_ORDERLIST:
    01269       if (OrderList::IsValidID(index)) return OrderList::Get(index);
    01270       SlErrorCorrupt("Referencing invalid OrderList");
    01271
    01272     case REF_ORDER:
    01273       if (Order::IsValidID(index)) return Order::Get(index);
    01274       /* in old versions, invalid order was used to mark end of order list */
    01275       if (IsSavegameVersionBefore(5, 2)) return NULL;
    01276       SlErrorCorrupt("Referencing invalid Order");
    01277
    01278     case REF_VEHICLE_OLD:
    01279     case REF_VEHICLE:
    01280       if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
    01281       SlErrorCorrupt("Referencing invalid Vehicle");
    01282
    01283     case REF_STATION:
    01284       if (Station::IsValidID(index)) return Station::Get(index);
    01285       SlErrorCorrupt("Referencing invalid Station");
    01286
    01287     case REF_TOWN:
    01288       if (Town::IsValidID(index)) return Town::Get(index);
    01289       SlErrorCorrupt("Referencing invalid Town");
    01290
    01291     case REF_ROADSTOPS:
    01292       if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
    01293       SlErrorCorrupt("Referencing invalid RoadStop");
    01294
    01295     case REF_ENGINE_RENEWS:
    01296       if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
    01297       SlErrorCorrupt("Referencing invalid EngineRenew");
    01298
    01299     case REF_CARGO_PACKET:
    01300       if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
    01301       SlErrorCorrupt("Referencing invalid CargoPacket");
    01302
    01303     case REF_STORAGE:
    01304       if (PersistentStorage::IsValidID(index)) return PersistentStorage::Get(index);
    01305       SlErrorCorrupt("Referencing invalid PersistentStorage");
    01306
    01307     case REF_LINK_GRAPH:
    01308       if (LinkGraph::IsValidID(index)) return LinkGraph::Get(index);
    01309       SlErrorCorrupt("Referencing invalid LinkGraph");
    01310
    01311     case REF_LINK_GRAPH_JOB:
    01312       if (LinkGraphJob::IsValidID(index)) return LinkGraphJob::Get(index);
    01313       SlErrorCorrupt("Referencing invalid LinkGraphJob");
    01314
    01315     default: NOT_REACHED();
    01316   }
    01317 }
    01318
    01323 static inline size_t SlCalcListLen(const void *list)
    01324 {
    01325   const std::list<void *> *l = (const std::list<void *> *) list;
    01326
    01327   int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
    01328   /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
    01329    * of the list */
    01330   return l->size() * type_size + type_size;
    01331 }
    01332
    01333
    01339 static void SlList(void *list, SLRefType conv)
    01340 {
    01341   /* Automatically calculate the length? */
    01342   if (_sl.need_length != NL_NONE) {
    01343     SlSetLength(SlCalcListLen(list));
    01344     /* Determine length only? */
    01345     if (_sl.need_length == NL_CALCLENGTH) return;
    01346   }
    01347
    01348   typedef std::list<void *> PtrList;
    01349   PtrList *l = (PtrList *)list;
    01350
    01351   switch (_sl.action) {
    01352     case SLA_SAVE: {
    01353       SlWriteUint32((uint32)l->size());
    01354
    01355       PtrList::iterator iter;
    01356       for (iter = l->begin(); iter != l->end(); ++iter) {
    01357         void *ptr = *iter;
    01358         SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
    01359       }
    01360       break;
    01361     }
    01362     case SLA_LOAD_CHECK:
    01363     case SLA_LOAD: {
    01364       size_t length = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01365
    01366       /* Load each reference and push to the end of the list */
    01367       for (size_t i = 0; i < length; i++) {
    01368         size_t data = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01369         l->push_back((void *)data);
    01370       }
    01371       break;
    01372     }
    01373     case SLA_PTRS: {
    01374       PtrList temp = *l;
    01375
    01376       l->clear();
    01377       PtrList::iterator iter;
    01378       for (iter = temp.begin(); iter != temp.end(); ++iter) {
    01379         void *ptr = IntToReference((size_t)*iter, conv);
    01380         l->push_back(ptr);
    01381       }
    01382       break;
    01383     }
    01384     case SLA_NULL:
    01385       l->clear();
    01386       break;
    01387     default: NOT_REACHED();
    01388   }
    01389 }
    01390
    01391
    01393 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
    01394 {
    01395   if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
    01396   if (sld->conv & SLF_NOT_IN_SAVE) return false;
    01397
    01398   return true;
    01399 }
    01400
    01406 static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
    01407 {
    01408   if ((sld->conv & SLF_NO_NETWORK_SYNC) && _sl.action != SLA_SAVE && _networking && !_network_server) {
    01409     SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
    01410     return true;
    01411   }
    01412
    01413   return false;
    01414 }
    01415
    01422 size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
    01423 {
    01424   size_t length = 0;
    01425
    01426   /* Need to determine the length and write a length tag. */
    01427   for (; sld->cmd != SL_END; sld++) {
    01428     length += SlCalcObjMemberLength(object, sld);
    01429   }
    01430   return length;
    01431 }
    01432
    01433 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
    01434 {
    01435   assert(_sl.action == SLA_SAVE);
    01436
    01437   switch (sld->cmd) {
    01438     case SL_VAR:
    01439     case SL_REF:
    01440     case SL_ARR:
    01441     case SL_STR:
    01442     case SL_LST:
    01443       /* CONDITIONAL saveload types depend on the savegame version */
    01444       if (!SlIsObjectValidInSavegame(sld)) break;
    01445
    01446       switch (sld->cmd) {
    01447         case SL_VAR: return SlCalcConvFileLen(sld->conv);
    01448         case SL_REF: return SlCalcRefLen();
    01449         case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
    01450         case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
    01451         case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
    01452         default: NOT_REACHED();
    01453       }
    01454       break;
    01455     case SL_WRITEBYTE: return 1; // a byte is logically of size 1
    01456     case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
    01457     case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
    01458     default: NOT_REACHED();
    01459   }
    01460   return 0;
    01461 }
    01462
    01463
    01464 bool SlObjectMember(void *ptr, const SaveLoad *sld)
    01465 {
    01466   VarType conv = GB(sld->conv, 0, 8);
    01467   switch (sld->cmd) {
    01468     case SL_VAR:
    01469     case SL_REF:
    01470     case SL_ARR:
    01471     case SL_STR:
    01472     case SL_LST:
    01473       /* CONDITIONAL saveload types depend on the savegame version */
    01474       if (!SlIsObjectValidInSavegame(sld)) return false;
    01475       if (SlSkipVariableOnLoad(sld)) return false;
    01476
    01477       switch (sld->cmd) {
    01478         case SL_VAR: SlSaveLoadConv(ptr, conv); break;
    01479         case SL_REF: // Reference variable, translate
    01480           switch (_sl.action) {
    01481             case SLA_SAVE:
    01482               SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv));
    01483               break;
    01484             case SLA_LOAD_CHECK:
    01485             case SLA_LOAD:
    01486               *(size_t *)ptr = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01487               break;
    01488             case SLA_PTRS:
    01489               *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv);
    01490               break;
    01491             case SLA_NULL:
    01492               *(void **)ptr = NULL;
    01493               break;
    01494             default: NOT_REACHED();
    01495           }
    01496           break;
    01497         case SL_ARR: SlArray(ptr, sld->length, conv); break;
    01498         case SL_STR: SlString(ptr, sld->length, sld->conv); break;
    01499         case SL_LST: SlList(ptr, (SLRefType)conv); break;
    01500         default: NOT_REACHED();
    01501       }
    01502       break;
    01503
    01504     /* SL_WRITEBYTE translates a value of a variable to another one upon
    01505      * saving or loading.
    01506      * XXX - variable renaming abuse
    01507      * game_value: the value of the variable ingame is abused by sld->version_from
    01508      * file_value: the value of the variable in the savegame is abused by sld->version_to */
    01509     case SL_WRITEBYTE:
    01510       switch (_sl.action) {
    01511         case SLA_SAVE: SlWriteByte(sld->version_to); break;
    01512         case SLA_LOAD_CHECK:
    01513         case SLA_LOAD: *(byte *)ptr = sld->version_from; break;
    01514         case SLA_PTRS: break;
    01515         case SLA_NULL: break;
    01516         default: NOT_REACHED();
    01517       }
    01518       break;
    01519
    01520     /* SL_VEH_INCLUDE loads common code for vehicles */
    01521     case SL_VEH_INCLUDE:
    01522       SlObject(ptr, GetVehicleDescription(VEH_END));
    01523       break;
    01524
    01525     case SL_ST_INCLUDE:
    01526       SlObject(ptr, GetBaseStationDescription());
    01527       break;
    01528
    01529     default: NOT_REACHED();
    01530   }
    01531   return true;
    01532 }
    01533
    01539 void SlObject(void *object, const SaveLoad *sld)
    01540 {
    01541   /* Automatically calculate the length? */
    01542   if (_sl.need_length != NL_NONE) {
    01543     SlSetLength(SlCalcObjLength(object, sld));
    01544     if (_sl.need_length == NL_CALCLENGTH) return;
    01545   }
    01546
    01547   for (; sld->cmd != SL_END; sld++) {
    01548     void *ptr = sld->global ? sld->address : GetVariableAddress(object, sld);
    01549     SlObjectMember(ptr, sld);
    01550   }
    01551 }
    01552
    01557 void SlGlobList(const SaveLoadGlobVarList *sldg)
    01558 {
    01559   SlObject(NULL, (const SaveLoad*)sldg);
    01560 }
    01561
    01567 void SlAutolength(AutolengthProc *proc, void *arg)
    01568 {
    01569   size_t offs;
    01570
    01571   assert(_sl.action == SLA_SAVE);
    01572
    01573   /* Tell it to calculate the length */
    01574   _sl.need_length = NL_CALCLENGTH;
    01575   _sl.obj_len = 0;
    01576   proc(arg);
    01577
    01578   /* Setup length */
    01579   _sl.need_length = NL_WANTLENGTH;
    01580   SlSetLength(_sl.obj_len);
    01581
    01582   offs = _sl.dumper->GetSize() + _sl.obj_len;
    01583
    01584   /* And write the stuff */
    01585   proc(arg);
    01586
    01587   if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
    01588 }
    01589
    01594 static void SlLoadChunk(const ChunkHandler *ch)
    01595 {
    01596   byte m = SlReadByte();
    01597   size_t len;
    01598   size_t endoffs;
    01599
    01600   _sl.block_mode = m;
    01601   _sl.obj_len = 0;
    01602
    01603   switch (m) {
    01604     case CH_ARRAY:
    01605       _sl.array_index = 0;
    01606       ch->load_proc();
    01607       break;
    01608     case CH_SPARSE_ARRAY:
    01609       ch->load_proc();
    01610       break;
    01611     default:
    01612       if ((m & 0xF) == CH_RIFF) {
    01613         /* Read length */
    01614         len = (SlReadByte() << 16) | ((m >> 4) << 24);
    01615         len += SlReadUint16();
    01616         _sl.obj_len = len;
    01617         endoffs = _sl.reader->GetSize() + len;
    01618         ch->load_proc();
    01619         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
    01620       } else {
    01621         SlErrorCorrupt("Invalid chunk type");
    01622       }
    01623       break;
    01624   }
    01625 }
    01626
    01632 static void SlLoadCheckChunk(const ChunkHandler *ch)
    01633 {
    01634   byte m = SlReadByte();
    01635   size_t len;
    01636   size_t endoffs;
    01637
    01638   _sl.block_mode = m;
    01639   _sl.obj_len = 0;
    01640
    01641   switch (m) {
    01642     case CH_ARRAY:
    01643       _sl.array_index = 0;
    01644       if (ch->load_check_proc) {
    01645         ch->load_check_proc();
    01646       } else {
    01647         SlSkipArray();
    01648       }
    01649       break;
    01650     case CH_SPARSE_ARRAY:
    01651       if (ch->load_check_proc) {
    01652         ch->load_check_proc();
    01653       } else {
    01654         SlSkipArray();
    01655       }
    01656       break;
    01657     default:
    01658       if ((m & 0xF) == CH_RIFF) {
    01659         /* Read length */
    01660         len = (SlReadByte() << 16) | ((m >> 4) << 24);
    01661         len += SlReadUint16();
    01662         _sl.obj_len = len;
    01663         endoffs = _sl.reader->GetSize() + len;
    01664         if (ch->load_check_proc) {
    01665           ch->load_check_proc();
    01666         } else {
    01667           SlSkipBytes(len);
    01668         }
    01669         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
    01670       } else {
    01671         SlErrorCorrupt("Invalid chunk type");
    01672       }
    01673       break;
    01674   }
    01675 }
    01676
    01681 static ChunkSaveLoadProc *_stub_save_proc;
    01682
    01688 static inline void SlStubSaveProc2(void *arg)
    01689 {
    01690   _stub_save_proc();
    01691 }
    01692
    01698 static void SlStubSaveProc()
    01699 {
    01700   SlAutolength(SlStubSaveProc2, NULL);
    01701 }
    01702
    01708 static void SlSaveChunk(const ChunkHandler *ch)
    01709 {
    01710   ChunkSaveLoadProc *proc = ch->save_proc;
    01711
    01712   /* Don't save any chunk information if there is no save handler. */
    01713   if (proc == NULL) return;
    01714
    01715   SlWriteUint32(ch->id);
    01716   DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    01717
    01718   if (ch->flags & CH_AUTO_LENGTH) {
    01719     /* Need to calculate the length. Solve that by calling SlAutoLength in the save_proc. */
    01720     _stub_save_proc = proc;
    01721     proc = SlStubSaveProc;
    01722   }
    01723
    01724   _sl.block_mode = ch->flags & CH_TYPE_MASK;
    01725   switch (ch->flags & CH_TYPE_MASK) {
    01726     case CH_RIFF:
    01727       _sl.need_length = NL_WANTLENGTH;
    01728       proc();
    01729       break;
    01730     case CH_ARRAY:
    01731       _sl.last_array_index = 0;
    01732       SlWriteByte(CH_ARRAY);
    01733       proc();
    01734       SlWriteArrayLength(0); // Terminate arrays
    01735       break;
    01736     case CH_SPARSE_ARRAY:
    01737       SlWriteByte(CH_SPARSE_ARRAY);
    01738       proc();
    01739       SlWriteArrayLength(0); // Terminate arrays
    01740       break;
    01741     default: NOT_REACHED();
    01742   }
    01743 }
    01744
    01746 static void SlSaveChunks()
    01747 {
    01748   FOR_ALL_CHUNK_HANDLERS(ch) {
    01749     SlSaveChunk(ch);
    01750   }
    01751
    01752   /* Terminator */
    01753   SlWriteUint32(0);
    01754 }
    01755
    01762 static const ChunkHandler *SlFindChunkHandler(uint32 id)
    01763 {
    01764   FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch;
    01765   return NULL;
    01766 }
    01767
    01769 static void SlLoadChunks()
    01770 {
    01771   uint32 id;
    01772   const ChunkHandler *ch;
    01773
    01774   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
    01775     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
    01776
    01777     ch = SlFindChunkHandler(id);
    01778     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
    01779     SlLoadChunk(ch);
    01780   }
    01781 }
    01782
    01784 static void SlLoadCheckChunks()
    01785 {
    01786   uint32 id;
    01787   const ChunkHandler *ch;
    01788
    01789   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
    01790     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
    01791
    01792     ch = SlFindChunkHandler(id);
    01793     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
    01794     SlLoadCheckChunk(ch);
    01795   }
    01796 }
    01797
    01799 static void SlFixPointers()
    01800 {
    01801   _sl.action = SLA_PTRS;
    01802
    01803   DEBUG(sl, 1, "Fixing pointers");
    01804
    01805   FOR_ALL_CHUNK_HANDLERS(ch) {
    01806     if (ch->ptrs_proc != NULL) {
    01807       DEBUG(sl, 2, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    01808       ch->ptrs_proc();
    01809     }
    01810   }
    01811
    01812   DEBUG(sl, 1, "All pointers fixed");
    01813
    01814   assert(_sl.action == SLA_PTRS);
    01815 }
    01816
    01817
    01819 struct FileReader : LoadFilter {
    01820   FILE *file;
    01821   long begin;
    01822
    01827   FileReader(FILE *file) : LoadFilter(NULL), file(file), begin(ftell(file))
    01828   {
    01829   }
    01830
    01832   ~FileReader()
    01833   {
    01834     if (this->file != NULL) fclose(this->file);
    01835     this->file = NULL;
    01836
    01837     /* Make sure we don't double free. */
    01838     _sl.sf = NULL;
    01839   }
    01840
    01841   /* virtual */ size_t Read(byte *buf, size_t size)
    01842   {
    01843     /* We're in the process of shutting down, i.e. in "failure" mode. */
    01844     if (this->file == NULL) return 0;
    01845
    01846     return fread(buf, 1, size, this->file);
    01847   }
    01848
    01849   /* virtual */ void Reset()
    01850   {
    01851     clearerr(this->file);
    01852     if (fseek(this->file, this->begin, SEEK_SET)) {
    01853       DEBUG(sl, 1, "Could not reset the file reading");
    01854     }
    01855   }
    01856 };
    01857
    01859 struct FileWriter : SaveFilter {
    01860   FILE *file;
    01861
    01866   FileWriter(FILE *file) : SaveFilter(NULL), file(file)
    01867   {
    01868   }
    01869
    01871   ~FileWriter()
    01872   {
    01873     this->Finish();
    01874
    01875     /* Make sure we don't double free. */
    01876     _sl.sf = NULL;
    01877   }
    01878
    01879   /* virtual */ void Write(byte *buf, size_t size)
    01880   {
    01881     /* We're in the process of shutting down, i.e. in "failure" mode. */
    01882     if (this->file == NULL) return;
    01883
    01884     if (fwrite(buf, 1, size, this->file) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
    01885   }
    01886
    01887   /* virtual */ void Finish()
    01888   {
    01889     if (this->file != NULL) fclose(this->file);
    01890     this->file = NULL;
    01891   }
    01892 };
    01893
    01894 /*******************************************
    01895  ********** START OF LZO CODE **************
    01896  *******************************************/
    01897
    01898 #ifdef WITH_LZO
    01899 #include <lzo/lzo1x.h>
    01900
    01902 static const uint LZO_BUFFER_SIZE = 8192;
    01903
    01905 struct LZOLoadFilter : LoadFilter {
    01910   LZOLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    01911   {
    01912     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    01913   }
    01914
    01915   /* virtual */ size_t Read(byte *buf, size_t ssize)
    01916   {
    01917     assert(ssize >= LZO_BUFFER_SIZE);
    01918
    01919     /* Buffer size is from the LZO docs plus the chunk header size. */
    01920     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
    01921     uint32 tmp[2];
    01922     uint32 size;
    01923     lzo_uint len;
    01924
    01925     /* Read header*/
    01926     if (this->chain->Read((byte*)tmp, sizeof(tmp)) != sizeof(tmp)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE, "File read failed");
    01927
    01928     /* Check if size is bad */
    01929     ((uint32*)out)[0] = size = tmp[1];
    01930
    01931     if (_sl_version != 0) {
    01932       tmp[0] = TO_BE32(tmp[0]);
    01933       size = TO_BE32(size);
    01934     }
    01935
    01936     if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size");
    01937
    01938     /* Read block */
    01939     if (this->chain->Read(out + sizeof(uint32), size) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    01940
    01941     /* Verify checksum */
    01942     if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
    01943
    01944     /* Decompress */
    01945     lzo1x_decompress_safe(out + sizeof(uint32) * 1, size, buf, &len, NULL);
    01946     return len;
    01947   }
    01948 };
    01949
    01951 struct LZOSaveFilter : SaveFilter {
    01957   LZOSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    01958   {
    01959     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    01960   }
    01961
    01962   /* virtual */ void Write(byte *buf, size_t size)
    01963   {
    01964     const lzo_bytep in = buf;
    01965     /* Buffer size is from the LZO docs plus the chunk header size. */
    01966     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
    01967     byte wrkmem[LZO1X_1_MEM_COMPRESS];
    01968     lzo_uint outlen;
    01969
    01970     do {
    01971       /* Compress up to LZO_BUFFER_SIZE bytes at once. */
    01972       lzo_uint len = size > LZO_BUFFER_SIZE ? LZO_BUFFER_SIZE : (lzo_uint)size;
    01973       lzo1x_1_compress(in, len, out + sizeof(uint32) * 2, &outlen, wrkmem);
    01974       ((uint32*)out)[1] = TO_BE32((uint32)outlen);
    01975       ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
    01976       this->chain->Write(out, outlen + sizeof(uint32) * 2);
    01977
    01978       /* Move to next data chunk. */
    01979       size -= len;
    01980       in += len;
    01981     } while (size > 0);
    01982   }
    01983 };
    01984
    01985 #endif /* WITH_LZO */
    01986
    01987 /*********************************************
    01988  ******** START OF NOCOMP CODE (uncompressed)*
    01989  *********************************************/
    01990
    01992 struct NoCompLoadFilter : LoadFilter {
    01997   NoCompLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    01998   {
    01999   }
    02000
    02001   /* virtual */ size_t Read(byte *buf, size_t size)
    02002   {
    02003     return this->chain->Read(buf, size);
    02004   }
    02005 };
    02006
    02008 struct NoCompSaveFilter : SaveFilter {
    02014   NoCompSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    02015   {
    02016   }
    02017
    02018   /* virtual */ void Write(byte *buf, size_t size)
    02019   {
    02020     this->chain->Write(buf, size);
    02021   }
    02022 };
    02023
    02024 /********************************************
    02025  ********** START OF ZLIB CODE **************
    02026  ********************************************/
    02027
    02028 #if defined(WITH_ZLIB)
    02029 #include <zlib.h>
    02030
    02032 struct ZlibLoadFilter : LoadFilter {
    02033   z_stream z;
    02034   byte fread_buf[MEMORY_CHUNK_SIZE];
    02035
    02040   ZlibLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    02041   {
    02042     memset(&this->z, 0, sizeof(this->z));
    02043     if (inflateInit(&this->z) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    02044   }
    02045
    02047   ~ZlibLoadFilter()
    02048   {
    02049     inflateEnd(&this->z);
    02050   }
    02051
    02052   /* virtual */ size_t Read(byte *buf, size_t size)
    02053   {
    02054     this->z.next_out  = buf;
    02055     this->z.avail_out = (uint)size;
    02056
    02057     do {
    02058       /* read more bytes from the file? */
    02059       if (this->z.avail_in == 0) {
    02060         this->z.next_in = this->fread_buf;
    02061         this->z.avail_in = (uint)this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
    02062       }
    02063
    02064       /* inflate the data */
    02065       int r = inflate(&this->z, 0);
    02066       if (r == Z_STREAM_END) break;
    02067
    02068       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "inflate() failed");
    02069     } while (this->z.avail_out != 0);
    02070
    02071     return size - this->z.avail_out;
    02072   }
    02073 };
    02074
    02076 struct ZlibSaveFilter : SaveFilter {
    02077   z_stream z;
    02078
    02084   ZlibSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    02085   {
    02086     memset(&this->z, 0, sizeof(this->z));
    02087     if (deflateInit(&this->z, compression_level) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    02088   }
    02089
    02091   ~ZlibSaveFilter()
    02092   {
    02093     deflateEnd(&this->z);
    02094   }
    02095
    02102   void WriteLoop(byte *p, size_t len, int mode)
    02103   {
    02104     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
    02105     uint n;
    02106     this->z.next_in = p;
    02107     this->z.avail_in = (uInt)len;
    02108     do {
    02109       this->z.next_out = buf;
    02110       this->z.avail_out = sizeof(buf);
    02111
    02119       int r = deflate(&this->z, mode);
    02120
    02121       /* bytes were emitted? */
    02122       if ((n = sizeof(buf) - this->z.avail_out) != 0) {
    02123         this->chain->Write(buf, n);
    02124       }
    02125       if (r == Z_STREAM_END) break;
    02126
    02127       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code");
    02128     } while (this->z.avail_in || !this->z.avail_out);
    02129   }
    02130
    02131   /* virtual */ void Write(byte *buf, size_t size)
    02132   {
    02133     this->WriteLoop(buf, size, 0);
    02134   }
    02135
    02136   /* virtual */ void Finish()
    02137   {
    02138     this->WriteLoop(NULL, 0, Z_FINISH);
    02139     this->chain->Finish();
    02140   }
    02141 };
    02142
    02143 #endif /* WITH_ZLIB */
    02144
    02145 /********************************************
    02146  ********** START OF LZMA CODE **************
    02147  ********************************************/
    02148
    02149 #if defined(WITH_LZMA)
    02150 #include <lzma.h>
    02151
    02158 static const lzma_stream _lzma_init = LZMA_STREAM_INIT;
    02159
    02161 struct LZMALoadFilter : LoadFilter {
    02162   lzma_stream lzma;
    02163   byte fread_buf[MEMORY_CHUNK_SIZE];
    02164
    02169   LZMALoadFilter(LoadFilter *chain) : LoadFilter(chain), lzma(_lzma_init)
    02170   {
    02171     /* Allow saves up to 256 MB uncompressed */
    02172     if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    02173   }
    02174
    02176   ~LZMALoadFilter()
    02177   {
    02178     lzma_end(&this->lzma);
    02179   }
    02180
    02181   /* virtual */ size_t Read(byte *buf, size_t size)
    02182   {
    02183     this->lzma.next_out  = buf;
    02184     this->lzma.avail_out = size;
    02185
    02186     do {
    02187       /* read more bytes from the file? */
    02188       if (this->lzma.avail_in == 0) {
    02189         this->lzma.next_in  = this->fread_buf;
    02190         this->lzma.avail_in = this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
    02191       }
    02192
    02193       /* inflate the data */
    02194       lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
    02195       if (r == LZMA_STREAM_END) break;
    02196       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
    02197     } while (this->lzma.avail_out != 0);
    02198
    02199     return size - this->lzma.avail_out;
    02200   }
    02201 };
    02202
    02204 struct LZMASaveFilter : SaveFilter {
    02205   lzma_stream lzma;
    02206
    02212   LZMASaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain), lzma(_lzma_init)
    02213   {
    02214     if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    02215   }
    02216
    02218   ~LZMASaveFilter()
    02219   {
    02220     lzma_end(&this->lzma);
    02221   }
    02222
    02229   void WriteLoop(byte *p, size_t len, lzma_action action)
    02230   {
    02231     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
    02232     size_t n;
    02233     this->lzma.next_in = p;
    02234     this->lzma.avail_in = len;
    02235     do {
    02236       this->lzma.next_out = buf;
    02237       this->lzma.avail_out = sizeof(buf);
    02238
    02239       lzma_ret r = lzma_code(&this->lzma, action);
    02240
    02241       /* bytes were emitted? */
    02242       if ((n = sizeof(buf) - this->lzma.avail_out) != 0) {
    02243         this->chain->Write(buf, n);
    02244       }
    02245       if (r == LZMA_STREAM_END) break;
    02246       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
    02247     } while (this->lzma.avail_in || !this->lzma.avail_out);
    02248   }
    02249
    02250   /* virtual */ void Write(byte *buf, size_t size)
    02251   {
    02252     this->WriteLoop(buf, size, LZMA_RUN);
    02253   }
    02254
    02255   /* virtual */ void Finish()
    02256   {
    02257     this->WriteLoop(NULL, 0, LZMA_FINISH);
    02258     this->chain->Finish();
    02259   }
    02260 };
    02261
    02262 #endif /* WITH_LZMA */
    02263
    02264 /*******************************************
    02265  ************* END OF CODE *****************
    02266  *******************************************/
    02267
    02269 struct SaveLoadFormat {
    02270   const char *name;
    02271   uint32 tag;
    02272
    02273   LoadFilter *(*init_load)(LoadFilter *chain);
    02274   SaveFilter *(*init_write)(SaveFilter *chain, byte compression);
    02275
    02276   byte min_compression;
    02277   byte default_compression;
    02278   byte max_compression;
    02279 };
    02280
    02282 static const SaveLoadFormat _saveload_formats[] = {
    02283 #if defined(WITH_LZO)
    02284   /* Roughly 75% larger than zlib level 6 at only ~7% of the CPU usage. */
    02285   {"lzo",    TO_BE32X('OTTD'), CreateLoadFilter<LZOLoadFilter>,    CreateSaveFilter<LZOSaveFilter>,    0, 0, 0},
    02286 #else
    02287   {"lzo",    TO_BE32X('OTTD'), NULL,                               NULL,                               0, 0, 0},
    02288 #endif
    02289   /* Roughly 5 times larger at only 1% of the CPU usage over zlib level 6. */
    02290   {"none",   TO_BE32X('OTTN'), CreateLoadFilter<NoCompLoadFilter>, CreateSaveFilter<NoCompSaveFilter>, 0, 0, 0},
    02291 #if defined(WITH_ZLIB)
    02292   /* After level 6 the speed reduction is significant (1.5x to 2.5x slower per level), but the reduction in filesize is
    02293    * fairly insignificant (~1% for each step). Lower levels become ~5-10% bigger by each level than level 6 while level
    02294    * 1 is "only" 3 times as fast. Level 0 results in uncompressed savegames at about 8 times the cost of "none". */
    02295   {"zlib",   TO_BE32X('OTTZ'), CreateLoadFilter<ZlibLoadFilter>,   CreateSaveFilter<ZlibSaveFilter>,   0, 6, 9},
    02296 #else
    02297   {"zlib",   TO_BE32X('OTTZ'), NULL,                               NULL,                               0, 0, 0},
    02298 #endif
    02299 #if defined(WITH_LZMA)
    02300   /* Level 2 compression is speed wise as fast as zlib level 6 compression (old default), but results in ~10% smaller saves.
    02301    * Higher compression levels are possible, and might improve savegame size by up to 25%, but are also up to 10 times slower.
    02302    * The next significant reduction in file size is at level 4, but that is already 4 times slower. Level 3 is primarily 50%
    02303    * slower while not improving the filesize, while level 0 and 1 are faster, but don't reduce savegame size much.
    02304    * It's OTTX and not e.g. OTTL because liblzma is part of xz-utils and .tar.xz is preferred over .tar.lzma. */
    02305   {"lzma",   TO_BE32X('OTTX'), CreateLoadFilter<LZMALoadFilter>,   CreateSaveFilter<LZMASaveFilter>,   0, 2, 9},
    02306 #else
    02307   {"lzma",   TO_BE32X('OTTX'), NULL,                               NULL,                               0, 0, 0},
    02308 #endif
    02309 };
    02310
    02318 static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
    02319 {
    02320   const SaveLoadFormat *def = lastof(_saveload_formats);
    02321
    02322   /* find default savegame format, the highest one with which files can be written */
    02323   while (!def->init_write) def--;
    02324
    02325   if (!StrEmpty(s)) {
    02326     /* Get the ":..." of the compression level out of the way */
    02327     char *complevel = strrchr(s, ':');
    02328     if (complevel != NULL) *complevel = '\0';
    02329
    02330     for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
    02331       if (slf->init_write != NULL && strcmp(s, slf->name) == 0) {
    02332         *compression_level = slf->default_compression;
    02333         if (complevel != NULL) {
    02334           /* There is a compression level in the string.
    02335            * First restore the : we removed to do proper name matching,
    02336            * then move the the begin of the actual version. */
    02337           *complevel = ':';
    02338           complevel++;
    02339
    02340           /* Get the version and determine whether all went fine. */
    02341           char *end;
    02342           long level = strtol(complevel, &end, 10);
    02343           if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) {
    02344             SetDParamStr(0, complevel);
    02345             ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL, WL_CRITICAL);
    02346           } else {
    02347             *compression_level = level;
    02348           }
    02349         }
    02350         return slf;
    02351       }
    02352     }
    02353
    02354     SetDParamStr(0, s);
    02355     SetDParamStr(1, def->name);
    02356     ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM, WL_CRITICAL);
    02357
    02358     /* Restore the string by adding the : back */
    02359     if (complevel != NULL) *complevel = ':';
    02360   }
    02361   *compression_level = def->default_compression;
    02362   return def;
    02363 }
    02364
    02365 /* actual loader/saver function */
    02366 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings);
    02367 extern bool AfterLoadGame();
    02368 extern bool LoadOldSaveGame(const char *file);
    02369
    02373 static inline void ClearSaveLoadState()
    02374 {
    02375   delete _sl.dumper;
    02376   _sl.dumper = NULL;
    02377
    02378   delete _sl.sf;
    02379   _sl.sf = NULL;
    02380
    02381   delete _sl.reader;
    02382   _sl.reader = NULL;
    02383
    02384   delete _sl.lf;
    02385   _sl.lf = NULL;
    02386 }
    02387
    02393 static void SaveFileStart()
    02394 {
    02395   _sl.ff_state = _fast_forward;
    02396   _fast_forward = 0;
    02397   if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
    02398
    02399   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START);
    02400   _sl.saveinprogress = true;
    02401 }
    02402
    02404 static void SaveFileDone()
    02405 {
    02406   if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state;
    02407   if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
    02408
    02409   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
    02410   _sl.saveinprogress = false;
    02411 }
    02412
    02414 void SetSaveLoadError(StringID str)
    02415 {
    02416   _sl.error_str = str;
    02417 }
    02418
    02420 const char *GetSaveLoadErrorString()
    02421 {
    02422   SetDParam(0, _sl.error_str);
    02423   SetDParamStr(1, _sl.extra_msg);
    02424
    02425   static char err_str[512];
    02426   GetString(err_str, _sl.action == SLA_SAVE ? STR_ERROR_GAME_SAVE_FAILED : STR_ERROR_GAME_LOAD_FAILED, lastof(err_str));
    02427   return err_str;
    02428 }
    02429
    02431 static void SaveFileError()
    02432 {
    02433   SetDParamStr(0, GetSaveLoadErrorString());
    02434   ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
    02435   SaveFileDone();
    02436 }
    02437
    02442 static SaveOrLoadResult SaveFileToDisk(bool threaded)
    02443 {
    02444   try {
    02445     byte compression;
    02446     const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format, &compression);
    02447
    02448     /* We have written our stuff to memory, now write it to file! */
    02449     uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) };
    02450     _sl.sf->Write((byte*)hdr, sizeof(hdr));
    02451
    02452     _sl.sf = fmt->init_write(_sl.sf, compression);
    02453     _sl.dumper->Flush(_sl.sf);
    02454
    02455     ClearSaveLoadState();
    02456
    02457     if (threaded) SetAsyncSaveFinish(SaveFileDone);
    02458
    02459     return SL_OK;
    02460   } catch (...) {
    02461     ClearSaveLoadState();
    02462
    02463     AsyncSaveFinishProc asfp = SaveFileDone;
    02464
    02465     /* We don't want to shout when saving is just
    02466      * cancelled due to a client disconnecting. */
    02467     if (_sl.error_str != STR_NETWORK_ERROR_LOSTCONNECTION) {
    02468       /* Skip the "colour" character */
    02469       DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
    02470       asfp = SaveFileError;
    02471     }
    02472
    02473     if (threaded) {
    02474       SetAsyncSaveFinish(asfp);
    02475     } else {
    02476       asfp();
    02477     }
    02478     return SL_ERROR;
    02479   }
    02480 }
    02481
    02483 static void SaveFileToDiskThread(void *arg)
    02484 {
    02485   SaveFileToDisk(true);
    02486 }
    02487
    02488 void WaitTillSaved()
    02489 {
    02490   if (_save_thread == NULL) return;
    02491
    02492   _save_thread->Join();
    02493   delete _save_thread;
    02494   _save_thread = NULL;
    02495
    02496   /* Make sure every other state is handled properly as well. */
    02497   ProcessAsyncSaveFinish();
    02498 }
    02499
    02508 static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
    02509 {
    02510   assert(!_sl.saveinprogress);
    02511
    02512   _sl.dumper = new MemoryDumper();
    02513   _sl.sf = writer;
    02514
    02515   _sl_version = SAVEGAME_VERSION;
    02516
    02517   SaveViewportBeforeSaveGame();
    02518   SlSaveChunks();
    02519
    02520   SaveFileStart();
    02521   if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
    02522     if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
    02523
    02524     SaveOrLoadResult result = SaveFileToDisk(false);
    02525     SaveFileDone();
    02526
    02527     return result;
    02528   }
    02529
    02530   return SL_OK;
    02531 }
    02532
    02539 SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
    02540 {
    02541   try {
    02542     _sl.action = SLA_SAVE;
    02543     return DoSave(writer, threaded);
    02544   } catch (...) {
    02545     ClearSaveLoadState();
    02546     return SL_ERROR;
    02547   }
    02548 }
    02549
    02556 static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
    02557 {
    02558   _sl.lf = reader;
    02559
    02560   if (load_check) {
    02561     /* Clear previous check data */
    02562     _load_check_data.Clear();
    02563     /* Mark SL_LOAD_CHECK as supported for this savegame. */
    02564     _load_check_data.checkable = true;
    02565   }
    02566
    02567   uint32 hdr[2];
    02568   if (_sl.lf->Read((byte*)hdr, sizeof(hdr)) != sizeof(hdr)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    02569
    02570   /* see if we have any loader for this type. */
    02571   const SaveLoadFormat *fmt = _saveload_formats;
    02572   for (;;) {
    02573     /* No loader found, treat as version 0 and use LZO format */
    02574     if (fmt == endof(_saveload_formats)) {
    02575       DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format");
    02576       _sl.lf->Reset();
    02577       _sl_version = 0;
    02578       _sl_minor_version = 0;
    02579
    02580       /* Try to find the LZO savegame format; it uses 'OTTD' as tag. */
    02581       fmt = _saveload_formats;
    02582       for (;;) {
    02583         if (fmt == endof(_saveload_formats)) {
    02584           /* Who removed LZO support? Bad bad boy! */
    02585           NOT_REACHED();
    02586         }
    02587         if (fmt->tag == TO_BE32X('OTTD')) break;
    02588         fmt++;
    02589       }
    02590       break;
    02591     }
    02592
    02593     if (fmt->tag == hdr[0]) {
    02594       /* check version number */
    02595       _sl_version = TO_BE32(hdr[1]) >> 16;
    02596       /* Minor is not used anymore from version 18.0, but it is still needed
    02597        * in versions before that (4 cases) which can't be removed easy.
    02598        * Therefore it is loaded, but never saved (or, it saves a 0 in any scenario). */
    02599       _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
    02600
    02601       DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
    02602
    02603       /* Is the version higher than the current? */
    02604       if (_sl_version > SAVEGAME_VERSION) SlError(STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME);
    02605       break;
    02606     }
    02607
    02608     fmt++;
    02609   }
    02610
    02611   /* loader for this savegame type is not implemented? */
    02612   if (fmt->init_load == NULL) {
    02613     char err_str[64];
    02614     snprintf(err_str, lengthof(err_str), "Loader for '%s' is not available.", fmt->name);
    02615     SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
    02616   }
    02617
    02618   _sl.lf = fmt->init_load(_sl.lf);
    02619   _sl.reader = new ReadBuffer(_sl.lf);
    02620   _next_offs = 0;
    02621
    02622   if (!load_check) {
    02623     /* Old maps were hardcoded to 256x256 and thus did not contain
    02624      * any mapsize information. Pre-initialize to 256x256 to not to
    02625      * confuse old games */
    02626     InitializeGame(256, 256, true, true);
    02627
    02628     GamelogReset();
    02629
    02630     if (IsSavegameVersionBefore(4)) {
    02631       /*
    02632        * NewGRFs were introduced between 0.3,4 and 0.3.5, which both
    02633        * shared savegame version 4. Anything before that 'obviously'
    02634        * does not have any NewGRFs. Between the introduction and
    02635        * savegame version 41 (just before 0.5) the NewGRF settings
    02636        * were not stored in the savegame and they were loaded by
    02637        * using the settings from the main menu.
    02638        * So, to recap:
    02639        * - savegame version  <  4:  do not load any NewGRFs.
    02640        * - savegame version >= 41:  load NewGRFs from savegame, which is
    02641        *                            already done at this stage by
    02642        *                            overwriting the main menu settings.
    02643        * - other savegame versions: use main menu settings.
    02644        *
    02645        * This means that users *can* crash savegame version 4..40
    02646        * savegames if they set incompatible NewGRFs in the main menu,
    02647        * but can't crash anymore for savegame version < 4 savegames.
    02648        *
    02649        * Note: this is done here because AfterLoadGame is also called
    02650        * for TTO/TTD/TTDP savegames which have their own NewGRF logic.
    02651        */
    02652       ClearGRFConfigList(&_grfconfig);
    02653     }
    02654   }
    02655
    02656   if (load_check) {
    02657     /* Load chunks into _load_check_data.
    02658      * No pools are loaded. References are not possible, and thus do not need resolving. */
    02659     SlLoadCheckChunks();
    02660   } else {
    02661     /* Load chunks and resolve references */
    02662     SlLoadChunks();
    02663     SlFixPointers();
    02664   }
    02665
    02666   ClearSaveLoadState();
    02667
    02668   _savegame_type = SGT_OTTD;
    02669
    02670   if (load_check) {
    02671     /* The only part from AfterLoadGame() we need */
    02672     _load_check_data.grf_compatibility = IsGoodGRFConfigList(_load_check_data.grfconfig);
    02673   } else {
    02674     GamelogStartAction(GLAT_LOAD);
    02675
    02676     /* After loading fix up savegame for any internal changes that
    02677      * might have occurred since then. If it fails, load back the old game. */
    02678     if (!AfterLoadGame()) {
    02679       GamelogStopAction();
    02680       return SL_REINIT;
    02681     }
    02682
    02683     GamelogStopAction();
    02684   }
    02685
    02686   return SL_OK;
    02687 }
    02688
    02694 SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
    02695 {
    02696   try {
    02697     _sl.action = SLA_LOAD;
    02698     return DoLoad(reader, false);
    02699   } catch (...) {
    02700     ClearSaveLoadState();
    02701     return SL_REINIT;
    02702   }
    02703 }
    02704
    02714 SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
    02715 {
    02716   /* An instance of saving is already active, so don't go saving again */
    02717   if (_sl.saveinprogress && mode == SL_SAVE && threaded) {
    02718     /* if not an autosave, but a user action, show error message */
    02719     if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
    02720     return SL_OK;
    02721   }
    02722   WaitTillSaved();
    02723
    02724   try {
    02725     /* Load a TTDLX or TTDPatch game */
    02726     if (mode == SL_OLD_LOAD) {
    02727       InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
    02728
    02729       /* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
    02730       * and if so a new NewGRF list will be made in LoadOldSaveGame.
    02731       * Note: this is done here because AfterLoadGame is also called
    02732       * for OTTD savegames which have their own NewGRF logic. */
    02733       ClearGRFConfigList(&_grfconfig);
    02734       GamelogReset();
    02735       if (!LoadOldSaveGame(filename)) return SL_REINIT;
    02736       _sl_version = 0;
    02737       _sl_minor_version = 0;
    02738       GamelogStartAction(GLAT_LOAD);
    02739       if (!AfterLoadGame()) {
    02740         GamelogStopAction();
    02741         return SL_REINIT;
    02742       }
    02743       GamelogStopAction();
    02744       return SL_OK;
    02745     }
    02746
    02747     switch (mode) {
    02748       case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
    02749       case SL_LOAD: _sl.action = SLA_LOAD; break;
    02750       case SL_SAVE: _sl.action = SLA_SAVE; break;
    02751       default: NOT_REACHED();
    02752     }
    02753
    02754     FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
    02755
    02756     /* Make it a little easier to load savegames from the console */
    02757     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
    02758     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
    02759     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SCENARIO_DIR);
    02760
    02761     if (fh == NULL) {
    02762       SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    02763     }
    02764
    02765     if (mode == SL_SAVE) { // SAVE game
    02766       DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
    02767       if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
    02768
    02769       return DoSave(new FileWriter(fh), threaded);
    02770     }
    02771
    02772     /* LOAD game */
    02773     assert(mode == SL_LOAD || mode == SL_LOAD_CHECK);
    02774     DEBUG(desync, 1, "load: %s", filename);
    02775     return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK);
    02776   } catch (...) {
    02777     ClearSaveLoadState();
    02778
    02779     /* Skip the "colour" character */
    02780     if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
    02781
    02782     /* A saver/loader exception!! reinitialize all variables to prevent crash! */
    02783     return (mode == SL_LOAD || mode == SL_OLD_LOAD) ? SL_REINIT : SL_ERROR;
    02784   }
    02785 }
    02786
    02788 void DoExitSave()
    02789 {
    02790   SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
    02791 }
    02792
    02798 void GenerateDefaultSaveName(char *buf, const char *last)
    02799 {
    02800   /* Check if we have a name for this map, which is the name of the first
    02801    * available company. When there's no company available we'll use
    02802    * 'Spectator' as "company" name. */
    02803   CompanyID cid = _local_company;
    02804   if (!Company::IsValidID(cid)) {
    02805     const Company *c;
    02806     FOR_ALL_COMPANIES(c) {
    02807       cid = c->index;
    02808       break;
    02809     }
    02810   }
    02811
    02812   SetDParam(0, cid);
    02813
    02814   /* Insert current date */
    02815   switch (_settings_client.gui.date_format_in_default_names) {
    02816     case 0: SetDParam(1, STR_JUST_DATE_LONG); break;
    02817     case 1: SetDParam(1, STR_JUST_DATE_TINY); break;
    02818     case 2: SetDParam(1, STR_JUST_DATE_ISO); break;
    02819     default: NOT_REACHED();
    02820   }
    02821   SetDParam(2, _date);
    02822
    02823   /* Get the correct string (special string for when there's not company) */
    02824   GetString(buf, !Company::IsValidID(cid) ? STR_SAVEGAME_NAME_SPECTATOR : STR_SAVEGAME_NAME_DEFAULT, last);
    02825   SanitizeFilename(buf);
    02826 }
    02827
    02828 #if 0
    02829
    02835 int GetSavegameType(char *file)
    02836 {
    02837   const SaveLoadFormat *fmt;
    02838   uint32 hdr;
    02839   FILE *f;
    02840   int mode = SL_OLD_LOAD;
    02841
    02842   f = fopen(file, "rb");
    02843   if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
    02844     DEBUG(sl, 0, "Savegame is obsolete or invalid format");
    02845     mode = SL_LOAD; // don't try to get filename, just show name as it is written
    02846   } else {
    02847     /* see if we have any loader for this type. */
    02848     for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
    02849       if (fmt->tag == hdr) {
    02850         mode = SL_LOAD; // new type of savegame
    02851         break;
    02852       }
    02853     }
    02854   }
    02855
    02856   fclose(f);
    02857   return mode;
    02858 }
    02859 #endif