# saveload.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00024 #include "../stdafx.h"
    00025 #include "../debug.h"
    00026 #include "../station_base.h"
    00027 #include "../thread/thread.h"
    00028 #include "../town.h"
    00029 #include "../network/network.h"
    00030 #include "../window_func.h"
    00031 #include "../strings_func.h"
    00032 #include "../core/endian_func.hpp"
    00033 #include "../vehicle_base.h"
    00034 #include "../company_func.h"
    00035 #include "../date_func.h"
    00036 #include "../autoreplace_base.h"
    00037 #include "../roadstop_base.h"
    00038 #include "../statusbar_gui.h"
    00039 #include "../fileio_func.h"
    00040 #include "../gamelog.h"
    00041 #include "../string_func.h"
    00042 #include "../fios.h"
    00043 #include "../error.h"
    00044
    00045 #include "table/strings.h"
    00046
    00047 #include "saveload_internal.h"
    00048 #include "saveload_filter.h"
    00049
    00050 /*
    00051  * Previous savegame versions, the trunk revision where they were
    00052  * introduced and the released version that had that particular
    00053  * savegame version.
    00054  * Up to savegame version 18 there is a minor version as well.
    00055  *
    00056  *    1.0         0.1.x, 0.2.x
    00057  *    2.0         0.3.0
    00058  *    2.1         0.3.1, 0.3.2
    00059  *    3.x         lost
    00060  *    4.0     1
    00061  *    4.1   122   0.3.3, 0.3.4
    00062  *    4.2  1222   0.3.5
    00063  *    4.3  1417
    00064  *    4.4  1426
    00065  *    5.0  1429
    00066  *    5.1  1440
    00067  *    5.2  1525   0.3.6
    00068  *    6.0  1721
    00069  *    6.1  1768
    00070  *    7.0  1770
    00071  *    8.0  1786
    00072  *    9.0  1909
    00073  *   10.0  2030
    00074  *   11.0  2033
    00075  *   11.1  2041
    00076  *   12.1  2046
    00077  *   13.1  2080   0.4.0, 0.4.0.1
    00078  *   14.0  2441
    00079  *   15.0  2499
    00080  *   16.0  2817
    00081  *   16.1  3155
    00082  *   17.0  3212
    00083  *   17.1  3218
    00084  *   18    3227
    00085  *   19    3396
    00086  *   20    3403
    00087  *   21    3472   0.4.x
    00088  *   22    3726
    00089  *   23    3915
    00090  *   24    4150
    00091  *   25    4259
    00092  *   26    4466
    00093  *   27    4757
    00094  *   28    4987
    00095  *   29    5070
    00096  *   30    5946
    00097  *   31    5999
    00098  *   32    6001
    00099  *   33    6440
    00100  *   34    6455
    00101  *   35    6602
    00102  *   36    6624
    00103  *   37    7182
    00104  *   38    7195
    00105  *   39    7269
    00106  *   40    7326
    00107  *   41    7348   0.5.x
    00108  *   42    7573
    00109  *   43    7642
    00110  *   44    8144
    00111  *   45    8501
    00112  *   46    8705
    00113  *   47    8735
    00114  *   48    8935
    00115  *   49    8969
    00116  *   50    8973
    00117  *   51    8978
    00118  *   52    9066
    00119  *   53    9316
    00120  *   54    9613
    00121  *   55    9638
    00122  *   56    9667
    00123  *   57    9691
    00124  *   58    9762
    00125  *   59    9779
    00126  *   60    9874
    00127  *   61    9892
    00128  *   62    9905
    00129  *   63    9956
    00130  *   64   10006
    00131  *   65   10210
    00132  *   66   10211
    00133  *   67   10236
    00134  *   68   10266
    00135  *   69   10319
    00136  *   70   10541
    00137  *   71   10567
    00138  *   72   10601
    00139  *   73   10903
    00140  *   74   11030
    00141  *   75   11107
    00142  *   76   11139
    00143  *   77   11172
    00144  *   78   11176
    00145  *   79   11188
    00146  *   80   11228
    00147  *   81   11244
    00148  *   82   11410
    00149  *   83   11589
    00150  *   84   11822
    00151  *   85   11874
    00152  *   86   12042
    00153  *   87   12129
    00154  *   88   12134
    00155  *   89   12160
    00156  *   90   12293
    00157  *   91   12347
    00158  *   92   12381   0.6.x
    00159  *   93   12648
    00160  *   94   12816
    00161  *   95   12924
    00162  *   96   13226
    00163  *   97   13256
    00164  *   98   13375
    00165  *   99   13838
    00166  *  100   13952
    00167  *  101   14233
    00168  *  102   14332
    00169  *  103   14598
    00170  *  104   14735
    00171  *  105   14803
    00172  *  106   14919
    00173  *  107   15027
    00174  *  108   15045
    00175  *  109   15075
    00176  *  110   15148
    00177  *  111   15190
    00178  *  112   15290
    00179  *  113   15340
    00180  *  114   15601
    00181  *  115   15695
    00182  *  116   15893   0.7.x
    00183  *  117   16037
    00184  *  118   16129
    00185  *  119   16242
    00186  *  120   16439
    00187  *  121   16694
    00188  *  122   16855
    00189  *  123   16909
    00190  *  124   16993
    00191  *  125   17113
    00192  *  126   17433
    00193  *  127   17439
    00194  *  128   18281
    00195  *  129   18292
    00196  *  130   18404
    00197  *  131   18481
    00198  *  132   18522
    00199  *  133   18674
    00200  *  134   18703
    00201  *  135   18719
    00202  *  136   18764
    00203  *  137   18912
    00204  *  138   18942   1.0.x
    00205  *  139   19346
    00206  *  140   19382
    00207  *  141   19799
    00208  *  142   20003
    00209  *  143   20048
    00210  *  144   20334
    00211  *  145   20376
    00212  *  146   20446
    00213  *  147   20621
    00214  *  148   20659
    00215  *  149   20832
    00216  *  150   20857
    00217  *  151   20918
    00218  *  152   21171
    00219  *  153   21263
    00220  *  154   21426
    00221  *  155   21453
    00222  *  156   21728
    00223  *  157   21862
    00224  *  158   21933
    00225  *  159   21962
    00226  *  160   21974   1.1.x
    00227  *  161   22567
    00228  *  162   22713
    00229  *  163   22767
    00230  *  164   23290
    00231  *  165   23304
    00232  *  166   23415
    00233  *  167   23504
    00234  *  168   23637
    00235  *  169   23816
    00236  *  170   23826
    00237  *  171   23835
    00238  *  172   23947
    00239  */
    00240 extern const uint16 SAVEGAME_VERSION = SL_EXT_RATING;
    00241
    00242 SavegameType _savegame_type;
    00243
    00244 uint32 _ttdp_version;
    00245 uint16 _sl_version;
    00246 byte   _sl_minor_version;
    00247 char _savegame_format[8];
    00248 bool _do_autosave;
    00249
    00251 enum SaveLoadAction {
    00252   SLA_LOAD,
    00253   SLA_SAVE,
    00254   SLA_PTRS,
    00255   SLA_NULL,
    00256   SLA_LOAD_CHECK,
    00257 };
    00258
    00259 enum NeedLength {
    00260   NL_NONE = 0,
    00261   NL_WANTLENGTH = 1,
    00262   NL_CALCLENGTH = 2,
    00263 };
    00264
    00266 static const size_t MEMORY_CHUNK_SIZE = 128 * 1024;
    00267
    00269 struct ReadBuffer {
    00270   byte buf[MEMORY_CHUNK_SIZE];
    00271   byte *bufp;
    00272   byte *bufe;
    00273   LoadFilter *reader;
    00274   size_t read;
    00275
    00280   ReadBuffer(LoadFilter *reader) : bufp(NULL), bufe(NULL), reader(reader), read(0)
    00281   {
    00282   }
    00283
    00284   inline byte ReadByte()
    00285   {
    00286     if (this->bufp == this->bufe) {
    00287       size_t len = this->reader->Read(this->buf, lengthof(this->buf));
    00288       if (len == 0) SlErrorCorrupt("Unexpected end of chunk");
    00289
    00290       this->read += len;
    00291       this->bufp = this->buf;
    00292       this->bufe = this->buf + len;
    00293     }
    00294
    00295     return *this->bufp++;
    00296   }
    00297
    00302   size_t GetSize() const
    00303   {
    00304     return this->read - (this->bufe - this->bufp);
    00305   }
    00306 };
    00307
    00308
    00310 struct MemoryDumper {
    00311   AutoFreeSmallVector<byte *, 16> blocks;
    00312   byte *buf;
    00313   byte *bufe;
    00314
    00316   MemoryDumper() : buf(NULL), bufe(NULL)
    00317   {
    00318   }
    00319
    00324   inline void WriteByte(byte b)
    00325   {
    00326     /* Are we at the end of this chunk? */
    00327     if (this->buf == this->bufe) {
    00328       this->buf = CallocT<byte>(MEMORY_CHUNK_SIZE);
    00329       *this->blocks.Append() = this->buf;
    00330       this->bufe = this->buf + MEMORY_CHUNK_SIZE;
    00331     }
    00332
    00333     *this->buf++ = b;
    00334   }
    00335
    00340   void Flush(SaveFilter *writer)
    00341   {
    00342     uint i = 0;
    00343     size_t t = this->GetSize();
    00344
    00345     while (t > 0) {
    00346       size_t to_write = min(MEMORY_CHUNK_SIZE, t);
    00347
    00348       writer->Write(this->blocks[i++], to_write);
    00349       t -= to_write;
    00350     }
    00351
    00352     writer->Finish();
    00353   }
    00354
    00359   size_t GetSize() const
    00360   {
    00361     return this->blocks.Length() * MEMORY_CHUNK_SIZE - (this->bufe - this->buf);
    00362   }
    00363 };
    00364
    00366 struct SaveLoadParams {
    00367   SaveLoadAction action;
    00368   NeedLength need_length;
    00369   byte block_mode;
    00370   bool error;
    00371
    00372   size_t obj_len;
    00373   int array_index, last_array_index;
    00374
    00375   MemoryDumper *dumper;
    00376   SaveFilter *sf;
    00377
    00378   ReadBuffer *reader;
    00379   LoadFilter *lf;
    00380
    00381   StringID error_str;
    00382   char *extra_msg;
    00383
    00384   byte ff_state;
    00385   bool saveinprogress;
    00386 };
    00387
    00388 static SaveLoadParams _sl;
    00389
    00390 /* these define the chunks */
    00391 extern const ChunkHandler _gamelog_chunk_handlers[];
    00392 extern const ChunkHandler _map_chunk_handlers[];
    00393 extern const ChunkHandler _misc_chunk_handlers[];
    00394 extern const ChunkHandler _name_chunk_handlers[];
    00395 extern const ChunkHandler _cheat_chunk_handlers[] ;
    00396 extern const ChunkHandler _setting_chunk_handlers[];
    00397 extern const ChunkHandler _company_chunk_handlers[];
    00398 extern const ChunkHandler _engine_chunk_handlers[];
    00399 extern const ChunkHandler _veh_chunk_handlers[];
    00400 extern const ChunkHandler _waypoint_chunk_handlers[];
    00401 extern const ChunkHandler _depot_chunk_handlers[];
    00402 extern const ChunkHandler _order_chunk_handlers[];
    00403 extern const ChunkHandler _town_chunk_handlers[];
    00404 extern const ChunkHandler _sign_chunk_handlers[];
    00405 extern const ChunkHandler _station_chunk_handlers[];
    00406 extern const ChunkHandler _industry_chunk_handlers[];
    00407 extern const ChunkHandler _economy_chunk_handlers[];
    00408 extern const ChunkHandler _subsidy_chunk_handlers[];
    00409 extern const ChunkHandler _goal_chunk_handlers[];
    00410 extern const ChunkHandler _ai_chunk_handlers[];
    00411 extern const ChunkHandler _game_chunk_handlers[];
    00412 extern const ChunkHandler _animated_tile_chunk_handlers[];
    00413 extern const ChunkHandler _newgrf_chunk_handlers[];
    00414 extern const ChunkHandler _group_chunk_handlers[];
    00415 extern const ChunkHandler _cargopacket_chunk_handlers[];
    00416 extern const ChunkHandler _autoreplace_chunk_handlers[];
    00417 extern const ChunkHandler _labelmaps_chunk_handlers[];
    00418 extern const ChunkHandler _linkgraph_chunk_handlers[];
    00419 extern const ChunkHandler _airport_chunk_handlers[];
    00420 extern const ChunkHandler _object_chunk_handlers[];
    00421 extern const ChunkHandler _persistent_storage_chunk_handlers[];
    00422
    00424 static const ChunkHandler * const _chunk_handlers[] = {
    00425   _gamelog_chunk_handlers,
    00426   _map_chunk_handlers,
    00427   _misc_chunk_handlers,
    00428   _name_chunk_handlers,
    00429   _cheat_chunk_handlers,
    00430   _setting_chunk_handlers,
    00431   _veh_chunk_handlers,
    00432   _waypoint_chunk_handlers,
    00433   _depot_chunk_handlers,
    00434   _order_chunk_handlers,
    00435   _industry_chunk_handlers,
    00436   _economy_chunk_handlers,
    00437   _subsidy_chunk_handlers,
    00438   _goal_chunk_handlers,
    00439   _engine_chunk_handlers,
    00440   _town_chunk_handlers,
    00441   _sign_chunk_handlers,
    00442   _station_chunk_handlers,
    00443   _company_chunk_handlers,
    00444   _ai_chunk_handlers,
    00445   _game_chunk_handlers,
    00446   _animated_tile_chunk_handlers,
    00447   _newgrf_chunk_handlers,
    00448   _group_chunk_handlers,
    00449   _cargopacket_chunk_handlers,
    00450   _autoreplace_chunk_handlers,
    00451   _labelmaps_chunk_handlers,
    00452   _linkgraph_chunk_handlers,
    00453   _airport_chunk_handlers,
    00454   _object_chunk_handlers,
    00455   _persistent_storage_chunk_handlers,
    00456   NULL,
    00457 };
    00458
    00463 #define FOR_ALL_CHUNK_HANDLERS(ch) \
    00464   for (const ChunkHandler * const *chsc = _chunk_handlers; *chsc != NULL; chsc++) \
    00465     for (const ChunkHandler *ch = *chsc; ch != NULL; ch = (ch->flags & CH_LAST) ? NULL : ch + 1)
    00466
    00468 static void SlNullPointers()
    00469 {
    00470   _sl.action = SLA_NULL;
    00471
    00472   /* We don't want any savegame conversion code to run
    00473    * during NULLing; especially those that try to get
    00474    * pointers from other pools. */
    00475   _sl_version = SAVEGAME_VERSION;
    00476
    00477   DEBUG(sl, 1, "Nulling pointers");
    00478
    00479   FOR_ALL_CHUNK_HANDLERS(ch) {
    00480     if (ch->ptrs_proc != NULL) {
    00481       DEBUG(sl, 2, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    00482       ch->ptrs_proc();
    00483     }
    00484   }
    00485
    00486   DEBUG(sl, 1, "All pointers nulled");
    00487
    00488   assert(_sl.action == SLA_NULL);
    00489 }
    00490
    00499 void NORETURN SlError(StringID string, const char *extra_msg)
    00500 {
    00501   /* Distinguish between loading into _load_check_data vs. normal save/load. */
    00502   if (_sl.action == SLA_LOAD_CHECK) {
    00503     _load_check_data.error = string;
    00504     free(_load_check_data.error_data);
    00505     _load_check_data.error_data = (extra_msg == NULL) ? NULL : strdup(extra_msg);
    00506   } else {
    00507     _sl.error_str = string;
    00508     free(_sl.extra_msg);
    00509     _sl.extra_msg = (extra_msg == NULL) ? NULL : strdup(extra_msg);
    00510   }
    00511
    00512   /* We have to NULL all pointers here; we might be in a state where
    00513    * the pointers are actually filled with indices, which means that
    00514    * when we access them during cleaning the pool dereferences of
    00515    * those indices will be made with segmentation faults as result. */
    00516   if (_sl.action == SLA_LOAD || _sl.action == SLA_PTRS) SlNullPointers();
    00517   throw std::exception();
    00518 }
    00519
    00527 void NORETURN SlErrorCorrupt(const char *msg)
    00528 {
    00529   SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
    00530 }
    00531
    00532
    00533 typedef void (*AsyncSaveFinishProc)();
    00534 static AsyncSaveFinishProc _async_save_finish = NULL;
    00535 static ThreadObject *_save_thread;
    00536
    00541 static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
    00542 {
    00543   if (_exit_game) return;
    00544   while (_async_save_finish != NULL) CSleep(10);
    00545
    00546   _async_save_finish = proc;
    00547 }
    00548
    00552 void ProcessAsyncSaveFinish()
    00553 {
    00554   if (_async_save_finish == NULL) return;
    00555
    00556   _async_save_finish();
    00557
    00558   _async_save_finish = NULL;
    00559
    00560   if (_save_thread != NULL) {
    00561     _save_thread->Join();
    00562     delete _save_thread;
    00563     _save_thread = NULL;
    00564   }
    00565 }
    00566
    00571 byte SlReadByte()
    00572 {
    00573   return _sl.reader->ReadByte();
    00574 }
    00575
    00580 void SlWriteByte(byte b)
    00581 {
    00582   _sl.dumper->WriteByte(b);
    00583 }
    00584
    00585 static inline int SlReadUint16()
    00586 {
    00587   int x = SlReadByte() << 8;
    00588   return x | SlReadByte();
    00589 }
    00590
    00591 static inline uint32 SlReadUint32()
    00592 {
    00593   uint32 x = SlReadUint16() << 16;
    00594   return x | SlReadUint16();
    00595 }
    00596
    00597 static inline uint64 SlReadUint64()
    00598 {
    00599   uint32 x = SlReadUint32();
    00600   uint32 y = SlReadUint32();
    00601   return (uint64)x << 32 | y;
    00602 }
    00603
    00604 static inline void SlWriteUint16(uint16 v)
    00605 {
    00606   SlWriteByte(GB(v, 8, 8));
    00607   SlWriteByte(GB(v, 0, 8));
    00608 }
    00609
    00610 static inline void SlWriteUint32(uint32 v)
    00611 {
    00612   SlWriteUint16(GB(v, 16, 16));
    00613   SlWriteUint16(GB(v,  0, 16));
    00614 }
    00615
    00616 static inline void SlWriteUint64(uint64 x)
    00617 {
    00618   SlWriteUint32((uint32)(x >> 32));
    00619   SlWriteUint32((uint32)x);
    00620 }
    00621
    00627 static inline void SlSkipBytes(size_t length)
    00628 {
    00629   for (; length != 0; length--) SlReadByte();
    00630 }
    00631
    00641 static uint SlReadSimpleGamma()
    00642 {
    00643   uint i = SlReadByte();
    00644   if (HasBit(i, 7)) {
    00645     i &= ~0x80;
    00646     if (HasBit(i, 6)) {
    00647       i &= ~0x40;
    00648       if (HasBit(i, 5)) {
    00649         i &= ~0x20;
    00650         if (HasBit(i, 4)) {
    00651           SlErrorCorrupt("Unsupported gamma");
    00652         }
    00653         i = (i << 8) | SlReadByte();
    00654       }
    00655       i = (i << 8) | SlReadByte();
    00656     }
    00657     i = (i << 8) | SlReadByte();
    00658   }
    00659   return i;
    00660 }
    00661
    00674 static void SlWriteSimpleGamma(size_t i)
    00675 {
    00676   if (i >= (1 << 7)) {
    00677     if (i >= (1 << 14)) {
    00678       if (i >= (1 << 21)) {
    00679         assert(i < (1 << 28));
    00680         SlWriteByte((byte)(0xE0 | (i >> 24)));
    00681         SlWriteByte((byte)(i >> 16));
    00682       } else {
    00683         SlWriteByte((byte)(0xC0 | (i >> 16)));
    00684       }
    00685       SlWriteByte((byte)(i >> 8));
    00686     } else {
    00687       SlWriteByte((byte)(0x80 | (i >> 8)));
    00688     }
    00689   }
    00690   SlWriteByte((byte)i);
    00691 }
    00692
    00694 static inline uint SlGetGammaLength(size_t i)
    00695 {
    00696   return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21));
    00697 }
    00698
    00699 static inline uint SlReadSparseIndex()
    00700 {
    00701   return SlReadSimpleGamma();
    00702 }
    00703
    00704 static inline void SlWriteSparseIndex(uint index)
    00705 {
    00706   SlWriteSimpleGamma(index);
    00707 }
    00708
    00709 static inline uint SlReadArrayLength()
    00710 {
    00711   return SlReadSimpleGamma();
    00712 }
    00713
    00714 static inline void SlWriteArrayLength(size_t length)
    00715 {
    00716   SlWriteSimpleGamma(length);
    00717 }
    00718
    00719 static inline uint SlGetArrayLength(size_t length)
    00720 {
    00721   return SlGetGammaLength(length);
    00722 }
    00723
    00730 static inline uint SlCalcConvMemLen(VarType conv)
    00731 {
    00732   static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
    00733   byte length = GB(conv, 4, 4);
    00734
    00735   switch (length << 4) {
    00736     case SLE_VAR_STRB:
    00737     case SLE_VAR_STRBQ:
    00738     case SLE_VAR_STR:
    00739     case SLE_VAR_STRQ:
    00740       return SlReadArrayLength();
    00741
    00742     default:
    00743       assert(length < lengthof(conv_mem_size));
    00744       return conv_mem_size[length];
    00745   }
    00746 }
    00747
    00754 static inline byte SlCalcConvFileLen(VarType conv)
    00755 {
    00756   static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
    00757   byte length = GB(conv, 0, 4);
    00758   assert(length < lengthof(conv_file_size));
    00759   return conv_file_size[length];
    00760 }
    00761
    00763 static inline size_t SlCalcRefLen()
    00764 {
    00765   return IsSavegameVersionBefore(69) ? 2 : 4;
    00766 }
    00767
    00768 void SlSetArrayIndex(uint index)
    00769 {
    00770   _sl.need_length = NL_WANTLENGTH;
    00771   _sl.array_index = index;
    00772 }
    00773
    00774 static size_t _next_offs;
    00775
    00780 int SlIterateArray()
    00781 {
    00782   int index;
    00783
    00784   /* After reading in the whole array inside the loop
    00785    * we must have read in all the data, so we must be at end of current block. */
    00786   if (_next_offs != 0 && _sl.reader->GetSize() != _next_offs) SlErrorCorrupt("Invalid chunk size");
    00787
    00788   for (;;) {
    00789     uint length = SlReadArrayLength();
    00790     if (length == 0) {
    00791       _next_offs = 0;
    00792       return -1;
    00793     }
    00794
    00795     _sl.obj_len = --length;
    00796     _next_offs = _sl.reader->GetSize() + length;
    00797
    00798     switch (_sl.block_mode) {
    00799       case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
    00800       case CH_ARRAY:        index = _sl.array_index++; break;
    00801       default:
    00802         DEBUG(sl, 0, "SlIterateArray error");
    00803         return -1; // error
    00804     }
    00805
    00806     if (length != 0) return index;
    00807   }
    00808 }
    00809
    00813 void SlSkipArray()
    00814 {
    00815   while (SlIterateArray() != -1) {
    00816     SlSkipBytes(_next_offs - _sl.reader->GetSize());
    00817   }
    00818 }
    00819
    00825 void SlSetLength(size_t length)
    00826 {
    00827   assert(_sl.action == SLA_SAVE);
    00828
    00829   switch (_sl.need_length) {
    00830     case NL_WANTLENGTH:
    00831       _sl.need_length = NL_NONE;
    00832       switch (_sl.block_mode) {
    00833         case CH_RIFF:
    00834           /* Ugly encoding of >16M RIFF chunks
    00835            * The lower 24 bits are normal
    00836            * The uppermost 4 bits are bits 24:27 */
    00837           assert(length < (1 << 28));
    00838           SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
    00839           break;
    00840         case CH_ARRAY:
    00841           assert(_sl.last_array_index <= _sl.array_index);
    00842           while (++_sl.last_array_index <= _sl.array_index) {
    00843             SlWriteArrayLength(1);
    00844           }
    00845           SlWriteArrayLength(length + 1);
    00846           break;
    00847         case CH_SPARSE_ARRAY:
    00848           SlWriteArrayLength(length + 1 + SlGetArrayLength(_sl.array_index)); // Also include length of sparse index.
    00849           SlWriteSparseIndex(_sl.array_index);
    00850           break;
    00851         default: NOT_REACHED();
    00852       }
    00853       break;
    00854
    00855     case NL_CALCLENGTH:
    00856       _sl.obj_len += (int)length;
    00857       break;
    00858
    00859     default: NOT_REACHED();
    00860   }
    00861 }
    00862
    00869 static void SlCopyBytes(void *ptr, size_t length)
    00870 {
    00871   byte *p = (byte *)ptr;
    00872
    00873   switch (_sl.action) {
    00874     case SLA_LOAD_CHECK:
    00875     case SLA_LOAD:
    00876       for (; length != 0; length--) *p++ = SlReadByte();
    00877       break;
    00878     case SLA_SAVE:
    00879       for (; length != 0; length--) SlWriteByte(*p++);
    00880       break;
    00881     default: NOT_REACHED();
    00882   }
    00883 }
    00884
    00886 size_t SlGetFieldLength()
    00887 {
    00888   return _sl.obj_len;
    00889 }
    00890
    00898 int64 ReadValue(const void *ptr, VarType conv)
    00899 {
    00900   switch (GetVarMemType(conv)) {
    00901     case SLE_VAR_BL:  return (*(const bool *)ptr != 0);
    00902     case SLE_VAR_I8:  return *(const int8  *)ptr;
    00903     case SLE_VAR_U8:  return *(const byte  *)ptr;
    00904     case SLE_VAR_I16: return *(const int16 *)ptr;
    00905     case SLE_VAR_U16: return *(const uint16*)ptr;
    00906     case SLE_VAR_I32: return *(const int32 *)ptr;
    00907     case SLE_VAR_U32: return *(const uint32*)ptr;
    00908     case SLE_VAR_I64: return *(const int64 *)ptr;
    00909     case SLE_VAR_U64: return *(const uint64*)ptr;
    00910     case SLE_VAR_NULL:return 0;
    00911     default: NOT_REACHED();
    00912   }
    00913 }
    00914
    00922 void WriteValue(void *ptr, VarType conv, int64 val)
    00923 {
    00924   switch (GetVarMemType(conv)) {
    00925     case SLE_VAR_BL:  *(bool  *)ptr = (val != 0);  break;
    00926     case SLE_VAR_I8:  *(int8  *)ptr = val; break;
    00927     case SLE_VAR_U8:  *(byte  *)ptr = val; break;
    00928     case SLE_VAR_I16: *(int16 *)ptr = val; break;
    00929     case SLE_VAR_U16: *(uint16*)ptr = val; break;
    00930     case SLE_VAR_I32: *(int32 *)ptr = val; break;
    00931     case SLE_VAR_U32: *(uint32*)ptr = val; break;
    00932     case SLE_VAR_I64: *(int64 *)ptr = val; break;
    00933     case SLE_VAR_U64: *(uint64*)ptr = val; break;
    00934     case SLE_VAR_NAME: *(char**)ptr = CopyFromOldName(val); break;
    00935     case SLE_VAR_NULL: break;
    00936     default: NOT_REACHED();
    00937   }
    00938 }
    00939
    00948 static void SlSaveLoadConv(void *ptr, VarType conv)
    00949 {
    00950   switch (_sl.action) {
    00951     case SLA_SAVE: {
    00952       int64 x = ReadValue(ptr, conv);
    00953
    00954       /* Write the value to the file and check if its value is in the desired range */
    00955       switch (GetVarFileType(conv)) {
    00956         case SLE_FILE_I8: assert(x >= -128 && x <= 127);     SlWriteByte(x);break;
    00957         case SLE_FILE_U8: assert(x >= 0 && x <= 255);        SlWriteByte(x);break;
    00958         case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break;
    00959         case SLE_FILE_STRINGID:
    00960         case SLE_FILE_U16:assert(x >= 0 && x <= 65535);      SlWriteUint16(x);break;
    00961         case SLE_FILE_I32:
    00962         case SLE_FILE_U32:                                   SlWriteUint32((uint32)x);break;
    00963         case SLE_FILE_I64:
    00964         case SLE_FILE_U64:                                   SlWriteUint64(x);break;
    00965         default: NOT_REACHED();
    00966       }
    00967       break;
    00968     }
    00969     case SLA_LOAD_CHECK:
    00970     case SLA_LOAD: {
    00971       int64 x;
    00972       /* Read a value from the file */
    00973       switch (GetVarFileType(conv)) {
    00974         case SLE_FILE_I8:  x = (int8  )SlReadByte();   break;
    00975         case SLE_FILE_U8:  x = (byte  )SlReadByte();   break;
    00976         case SLE_FILE_I16: x = (int16 )SlReadUint16(); break;
    00977         case SLE_FILE_U16: x = (uint16)SlReadUint16(); break;
    00978         case SLE_FILE_I32: x = (int32 )SlReadUint32(); break;
    00979         case SLE_FILE_U32: x = (uint32)SlReadUint32(); break;
    00980         case SLE_FILE_I64: x = (int64 )SlReadUint64(); break;
    00981         case SLE_FILE_U64: x = (uint64)SlReadUint64(); break;
    00982         case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break;
    00983         default: NOT_REACHED();
    00984       }
    00985
    00986       /* Write The value to the struct. These ARE endian safe. */
    00987       WriteValue(ptr, conv, x);
    00988       break;
    00989     }
    00990     case SLA_PTRS: break;
    00991     case SLA_NULL: break;
    00992     default: NOT_REACHED();
    00993   }
    00994 }
    00995
    01005 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
    01006 {
    01007   if (ptr == NULL) return 0;
    01008   return min(strlen(ptr), length - 1);
    01009 }
    01010
    01020 static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
    01021 {
    01022   size_t len;
    01023   const char *str;
    01024
    01025   switch (GetVarMemType(conv)) {
    01026     default: NOT_REACHED();
    01027     case SLE_VAR_STR:
    01028     case SLE_VAR_STRQ:
    01029       str = *(const char * const *)ptr;
    01030       len = SIZE_MAX;
    01031       break;
    01032     case SLE_VAR_STRB:
    01033     case SLE_VAR_STRBQ:
    01034       str = (const char *)ptr;
    01035       len = length;
    01036       break;
    01037   }
    01038
    01039   len = SlCalcNetStringLen(str, len);
    01040   return len + SlGetArrayLength(len); // also include the length of the index
    01041 }
    01042
    01049 static void SlString(void *ptr, size_t length, VarType conv)
    01050 {
    01051   switch (_sl.action) {
    01052     case SLA_SAVE: {
    01053       size_t len;
    01054       switch (GetVarMemType(conv)) {
    01055         default: NOT_REACHED();
    01056         case SLE_VAR_STRB:
    01057         case SLE_VAR_STRBQ:
    01058           len = SlCalcNetStringLen((char *)ptr, length);
    01059           break;
    01060         case SLE_VAR_STR:
    01061         case SLE_VAR_STRQ:
    01062           ptr = *(char **)ptr;
    01063           len = SlCalcNetStringLen((char *)ptr, SIZE_MAX);
    01064           break;
    01065       }
    01066
    01067       SlWriteArrayLength(len);
    01068       SlCopyBytes(ptr, len);
    01069       break;
    01070     }
    01071     case SLA_LOAD_CHECK:
    01072     case SLA_LOAD: {
    01073       size_t len = SlReadArrayLength();
    01074
    01075       switch (GetVarMemType(conv)) {
    01076         default: NOT_REACHED();
    01077         case SLE_VAR_STRB:
    01078         case SLE_VAR_STRBQ:
    01079           if (len >= length) {
    01080             DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
    01081             SlCopyBytes(ptr, length);
    01082             SlSkipBytes(len - length);
    01083             len = length - 1;
    01084           } else {
    01085             SlCopyBytes(ptr, len);
    01086           }
    01087           break;
    01088         case SLE_VAR_STR:
    01089         case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate
    01090           free(*(char **)ptr);
    01091           if (len == 0) {
    01092             *(char **)ptr = NULL;
    01093             return;
    01094           } else {
    01095             *(char **)ptr = MallocT<char>(len + 1); // terminating '\0'
    01096             ptr = *(char **)ptr;
    01097             SlCopyBytes(ptr, len);
    01098           }
    01099           break;
    01100       }
    01101
    01102       ((char *)ptr)[len] = '\0'; // properly terminate the string
    01103       StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK;
    01104       if ((conv & SLF_ALLOW_CONTROL) != 0) {
    01105         settings = settings | SVS_ALLOW_CONTROL_CODE;
    01106         if (IsSavegameVersionBefore(169)) {
    01107           str_fix_scc_encoded((char *)ptr, (char *)ptr + len);
    01108         }
    01109       }
    01110       if ((conv & SLF_ALLOW_NEWLINE) != 0) {
    01111         settings = settings | SVS_ALLOW_NEWLINE;
    01112       }
    01113       str_validate((char *)ptr, (char *)ptr + len, settings);
    01114       break;
    01115     }
    01116     case SLA_PTRS: break;
    01117     case SLA_NULL: break;
    01118     default: NOT_REACHED();
    01119   }
    01120 }
    01121
    01127 static inline size_t SlCalcArrayLen(size_t length, VarType conv)
    01128 {
    01129   return SlCalcConvFileLen(conv) * length;
    01130 }
    01131
    01138 void SlArray(void *array, size_t length, VarType conv)
    01139 {
    01140   if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
    01141
    01142   /* Automatically calculate the length? */
    01143   if (_sl.need_length != NL_NONE) {
    01144     SlSetLength(SlCalcArrayLen(length, conv));
    01145     /* Determine length only? */
    01146     if (_sl.need_length == NL_CALCLENGTH) return;
    01147   }
    01148
    01149   /* NOTICE - handle some buggy stuff, in really old versions everything was saved
    01150    * as a byte-type. So detect this, and adjust array size accordingly */
    01151   if (_sl.action != SLA_SAVE && _sl_version == 0) {
    01152     /* all arrays except difficulty settings */
    01153     if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
    01154         conv == SLE_INT32 || conv == SLE_UINT32) {
    01155       SlCopyBytes(array, length * SlCalcConvFileLen(conv));
    01156       return;
    01157     }
    01158     /* used for conversion of Money 32bit->64bit */
    01159     if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
    01160       for (uint i = 0; i < length; i++) {
    01161         ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
    01162       }
    01163       return;
    01164     }
    01165   }
    01166
    01167   /* If the size of elements is 1 byte both in file and memory, no special
    01168    * conversion is needed, use specialized copy-copy function to speed up things */
    01169   if (conv == SLE_INT8 || conv == SLE_UINT8) {
    01170     SlCopyBytes(array, length);
    01171   } else {
    01172     byte *a = (byte*)array;
    01173     byte mem_size = SlCalcConvMemLen(conv);
    01174
    01175     for (; length != 0; length --) {
    01176       SlSaveLoadConv(a, conv);
    01177       a += mem_size; // get size
    01178     }
    01179   }
    01180 }
    01181
    01182
    01193 static size_t ReferenceToInt(const void *obj, SLRefType rt)
    01194 {
    01195   assert(_sl.action == SLA_SAVE);
    01196
    01197   if (obj == NULL) return 0;
    01198
    01199   switch (rt) {
    01200     case REF_VEHICLE_OLD: // Old vehicles we save as new onces
    01201     case REF_VEHICLE:   return ((const  Vehicle*)obj)->index + 1;
    01202     case REF_STATION:   return ((const  Station*)obj)->index + 1;
    01203     case REF_TOWN:      return ((const     Town*)obj)->index + 1;
    01204     case REF_ORDER:     return ((const    Order*)obj)->index + 1;
    01205     case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
    01206     case REF_ENGINE_RENEWS: return ((const       EngineRenew*)obj)->index + 1;
    01207     case REF_CARGO_PACKET:  return ((const       CargoPacket*)obj)->index + 1;
    01208     case REF_ORDERLIST:     return ((const         OrderList*)obj)->index + 1;
    01209     case REF_STORAGE:       return ((const PersistentStorage*)obj)->index + 1;
    01210     default: NOT_REACHED();
    01211   }
    01212 }
    01213
    01224 static void *IntToReference(size_t index, SLRefType rt)
    01225 {
    01226   assert_compile(sizeof(size_t) <= sizeof(void *));
    01227
    01228   assert(_sl.action == SLA_PTRS);
    01229
    01230   /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE,
    01231    * and should be loaded like that */
    01232   if (rt == REF_VEHICLE_OLD && !IsSavegameVersionBefore(4, 4)) {
    01233     rt = REF_VEHICLE;
    01234   }
    01235
    01236   /* No need to look up NULL pointers, just return immediately */
    01237   if (index == (rt == REF_VEHICLE_OLD ? 0xFFFF : 0)) return NULL;
    01238
    01239   /* Correct index. Old vehicles were saved differently:
    01240    * invalid vehicle was 0xFFFF, now we use 0x0000 for everything invalid. */
    01241   if (rt != REF_VEHICLE_OLD) index--;
    01242
    01243   switch (rt) {
    01244     case REF_ORDERLIST:
    01245       if (OrderList::IsValidID(index)) return OrderList::Get(index);
    01246       SlErrorCorrupt("Referencing invalid OrderList");
    01247
    01248     case REF_ORDER:
    01249       if (Order::IsValidID(index)) return Order::Get(index);
    01250       /* in old versions, invalid order was used to mark end of order list */
    01251       if (IsSavegameVersionBefore(5, 2)) return NULL;
    01252       SlErrorCorrupt("Referencing invalid Order");
    01253
    01254     case REF_VEHICLE_OLD:
    01255     case REF_VEHICLE:
    01256       if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
    01257       SlErrorCorrupt("Referencing invalid Vehicle");
    01258
    01259     case REF_STATION:
    01260       if (Station::IsValidID(index)) return Station::Get(index);
    01261       SlErrorCorrupt("Referencing invalid Station");
    01262
    01263     case REF_TOWN:
    01264       if (Town::IsValidID(index)) return Town::Get(index);
    01265       SlErrorCorrupt("Referencing invalid Town");
    01266
    01267     case REF_ROADSTOPS:
    01268       if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
    01269       SlErrorCorrupt("Referencing invalid RoadStop");
    01270
    01271     case REF_ENGINE_RENEWS:
    01272       if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
    01273       SlErrorCorrupt("Referencing invalid EngineRenew");
    01274
    01275     case REF_CARGO_PACKET:
    01276       if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
    01277       SlErrorCorrupt("Referencing invalid CargoPacket");
    01278
    01279     case REF_STORAGE:
    01280       if (PersistentStorage::IsValidID(index)) return PersistentStorage::Get(index);
    01281       SlErrorCorrupt("Referencing invalid PersistentStorage");
    01282
    01283     default: NOT_REACHED();
    01284   }
    01285 }
    01286
    01291 static inline size_t SlCalcListLen(const void *list)
    01292 {
    01293   const std::list<void *> *l = (const std::list<void *> *) list;
    01294
    01295   int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
    01296   /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
    01297    * of the list */
    01298   return l->size() * type_size + type_size;
    01299 }
    01300
    01301
    01307 static void SlList(void *list, SLRefType conv)
    01308 {
    01309   /* Automatically calculate the length? */
    01310   if (_sl.need_length != NL_NONE) {
    01311     SlSetLength(SlCalcListLen(list));
    01312     /* Determine length only? */
    01313     if (_sl.need_length == NL_CALCLENGTH) return;
    01314   }
    01315
    01316   typedef std::list<void *> PtrList;
    01317   PtrList *l = (PtrList *)list;
    01318
    01319   switch (_sl.action) {
    01320     case SLA_SAVE: {
    01321       SlWriteUint32((uint32)l->size());
    01322
    01323       PtrList::iterator iter;
    01324       for (iter = l->begin(); iter != l->end(); ++iter) {
    01325         void *ptr = *iter;
    01326         SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
    01327       }
    01328       break;
    01329     }
    01330     case SLA_LOAD_CHECK:
    01331     case SLA_LOAD: {
    01332       size_t length = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01333
    01334       /* Load each reference and push to the end of the list */
    01335       for (size_t i = 0; i < length; i++) {
    01336         size_t data = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01337         l->push_back((void *)data);
    01338       }
    01339       break;
    01340     }
    01341     case SLA_PTRS: {
    01342       PtrList temp = *l;
    01343
    01344       l->clear();
    01345       PtrList::iterator iter;
    01346       for (iter = temp.begin(); iter != temp.end(); ++iter) {
    01347         void *ptr = IntToReference((size_t)*iter, conv);
    01348         l->push_back(ptr);
    01349       }
    01350       break;
    01351     }
    01352     case SLA_NULL:
    01353       l->clear();
    01354       break;
    01355     default: NOT_REACHED();
    01356   }
    01357 }
    01358
    01359
    01361 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
    01362 {
    01363   if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
    01364   if (sld->conv & SLF_NOT_IN_SAVE) return false;
    01365
    01366   return true;
    01367 }
    01368
    01374 static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
    01375 {
    01376   if ((sld->conv & SLF_NO_NETWORK_SYNC) && _sl.action != SLA_SAVE && _networking && !_network_server) {
    01377     SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
    01378     return true;
    01379   }
    01380
    01381   return false;
    01382 }
    01383
    01390 size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
    01391 {
    01392   size_t length = 0;
    01393
    01394   /* Need to determine the length and write a length tag. */
    01395   for (; sld->cmd != SL_END; sld++) {
    01396     length += SlCalcObjMemberLength(object, sld);
    01397   }
    01398   return length;
    01399 }
    01400
    01401 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
    01402 {
    01403   assert(_sl.action == SLA_SAVE);
    01404
    01405   switch (sld->cmd) {
    01406     case SL_VAR:
    01407     case SL_REF:
    01408     case SL_ARR:
    01409     case SL_STR:
    01410     case SL_LST:
    01411       /* CONDITIONAL saveload types depend on the savegame version */
    01412       if (!SlIsObjectValidInSavegame(sld)) break;
    01413
    01414       switch (sld->cmd) {
    01415         case SL_VAR: return SlCalcConvFileLen(sld->conv);
    01416         case SL_REF: return SlCalcRefLen();
    01417         case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
    01418         case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
    01419         case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
    01420         default: NOT_REACHED();
    01421       }
    01422       break;
    01423     case SL_WRITEBYTE: return 1; // a byte is logically of size 1
    01424     case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
    01425     case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
    01426     default: NOT_REACHED();
    01427   }
    01428   return 0;
    01429 }
    01430
    01431
    01432 bool SlObjectMember(void *ptr, const SaveLoad *sld)
    01433 {
    01434   VarType conv = GB(sld->conv, 0, 8);
    01435   switch (sld->cmd) {
    01436     case SL_VAR:
    01437     case SL_REF:
    01438     case SL_ARR:
    01439     case SL_STR:
    01440     case SL_LST:
    01441       /* CONDITIONAL saveload types depend on the savegame version */
    01442       if (!SlIsObjectValidInSavegame(sld)) return false;
    01443       if (SlSkipVariableOnLoad(sld)) return false;
    01444
    01445       switch (sld->cmd) {
    01446         case SL_VAR: SlSaveLoadConv(ptr, conv); break;
    01447         case SL_REF: // Reference variable, translate
    01448           switch (_sl.action) {
    01449             case SLA_SAVE:
    01450               SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv));
    01451               break;
    01452             case SLA_LOAD_CHECK:
    01453             case SLA_LOAD:
    01454               *(size_t *)ptr = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
    01455               break;
    01456             case SLA_PTRS:
    01457               *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv);
    01458               break;
    01459             case SLA_NULL:
    01460               *(void **)ptr = NULL;
    01461               break;
    01462             default: NOT_REACHED();
    01463           }
    01464           break;
    01465         case SL_ARR: SlArray(ptr, sld->length, conv); break;
    01466         case SL_STR: SlString(ptr, sld->length, sld->conv); break;
    01467         case SL_LST: SlList(ptr, (SLRefType)conv); break;
    01468         default: NOT_REACHED();
    01469       }
    01470       break;
    01471
    01472     /* SL_WRITEBYTE translates a value of a variable to another one upon
    01473      * saving or loading.
    01474      * XXX - variable renaming abuse
    01475      * game_value: the value of the variable ingame is abused by sld->version_from
    01476      * file_value: the value of the variable in the savegame is abused by sld->version_to */
    01477     case SL_WRITEBYTE:
    01478       switch (_sl.action) {
    01479         case SLA_SAVE: SlWriteByte(sld->version_to); break;
    01480         case SLA_LOAD_CHECK:
    01481         case SLA_LOAD: *(byte *)ptr = sld->version_from; break;
    01482         case SLA_PTRS: break;
    01483         case SLA_NULL: break;
    01484         default: NOT_REACHED();
    01485       }
    01486       break;
    01487
    01488     /* SL_VEH_INCLUDE loads common code for vehicles */
    01489     case SL_VEH_INCLUDE:
    01490       SlObject(ptr, GetVehicleDescription(VEH_END));
    01491       break;
    01492
    01493     case SL_ST_INCLUDE:
    01494       SlObject(ptr, GetBaseStationDescription());
    01495       break;
    01496
    01497     default: NOT_REACHED();
    01498   }
    01499   return true;
    01500 }
    01501
    01507 void SlObject(void *object, const SaveLoad *sld)
    01508 {
    01509   /* Automatically calculate the length? */
    01510   if (_sl.need_length != NL_NONE) {
    01511     SlSetLength(SlCalcObjLength(object, sld));
    01512     if (_sl.need_length == NL_CALCLENGTH) return;
    01513   }
    01514
    01515   for (; sld->cmd != SL_END; sld++) {
    01516     void *ptr = sld->global ? sld->address : GetVariableAddress(object, sld);
    01517     SlObjectMember(ptr, sld);
    01518   }
    01519 }
    01520
    01525 void SlGlobList(const SaveLoadGlobVarList *sldg)
    01526 {
    01527   SlObject(NULL, (const SaveLoad*)sldg);
    01528 }
    01529
    01535 void SlAutolength(AutolengthProc *proc, void *arg)
    01536 {
    01537   size_t offs;
    01538
    01539   assert(_sl.action == SLA_SAVE);
    01540
    01541   /* Tell it to calculate the length */
    01542   _sl.need_length = NL_CALCLENGTH;
    01543   _sl.obj_len = 0;
    01544   proc(arg);
    01545
    01546   /* Setup length */
    01547   _sl.need_length = NL_WANTLENGTH;
    01548   SlSetLength(_sl.obj_len);
    01549
    01550   offs = _sl.dumper->GetSize() + _sl.obj_len;
    01551
    01552   /* And write the stuff */
    01553   proc(arg);
    01554
    01555   if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
    01556 }
    01557
    01562 static void SlLoadChunk(const ChunkHandler *ch)
    01563 {
    01564   byte m = SlReadByte();
    01565   size_t len;
    01566   size_t endoffs;
    01567
    01568   _sl.block_mode = m;
    01569   _sl.obj_len = 0;
    01570
    01571   switch (m) {
    01572     case CH_ARRAY:
    01573       _sl.array_index = 0;
    01574       ch->load_proc();
    01575       break;
    01576     case CH_SPARSE_ARRAY:
    01577       ch->load_proc();
    01578       break;
    01579     default:
    01580       if ((m & 0xF) == CH_RIFF) {
    01581         /* Read length */
    01582         len = (SlReadByte() << 16) | ((m >> 4) << 24);
    01583         len += SlReadUint16();
    01584         _sl.obj_len = len;
    01585         endoffs = _sl.reader->GetSize() + len;
    01586         ch->load_proc();
    01587         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
    01588       } else {
    01589         SlErrorCorrupt("Invalid chunk type");
    01590       }
    01591       break;
    01592   }
    01593 }
    01594
    01600 static void SlLoadCheckChunk(const ChunkHandler *ch)
    01601 {
    01602   byte m = SlReadByte();
    01603   size_t len;
    01604   size_t endoffs;
    01605
    01606   _sl.block_mode = m;
    01607   _sl.obj_len = 0;
    01608
    01609   switch (m) {
    01610     case CH_ARRAY:
    01611       _sl.array_index = 0;
    01612       if (ch->load_check_proc) {
    01613         ch->load_check_proc();
    01614       } else {
    01615         SlSkipArray();
    01616       }
    01617       break;
    01618     case CH_SPARSE_ARRAY:
    01619       if (ch->load_check_proc) {
    01620         ch->load_check_proc();
    01621       } else {
    01622         SlSkipArray();
    01623       }
    01624       break;
    01625     default:
    01626       if ((m & 0xF) == CH_RIFF) {
    01627         /* Read length */
    01628         len = (SlReadByte() << 16) | ((m >> 4) << 24);
    01629         len += SlReadUint16();
    01630         _sl.obj_len = len;
    01631         endoffs = _sl.reader->GetSize() + len;
    01632         if (ch->load_check_proc) {
    01633           ch->load_check_proc();
    01634         } else {
    01635           SlSkipBytes(len);
    01636         }
    01637         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
    01638       } else {
    01639         SlErrorCorrupt("Invalid chunk type");
    01640       }
    01641       break;
    01642   }
    01643 }
    01644
    01649 static ChunkSaveLoadProc *_stub_save_proc;
    01650
    01656 static inline void SlStubSaveProc2(void *arg)
    01657 {
    01658   _stub_save_proc();
    01659 }
    01660
    01666 static void SlStubSaveProc()
    01667 {
    01668   SlAutolength(SlStubSaveProc2, NULL);
    01669 }
    01670
    01676 static void SlSaveChunk(const ChunkHandler *ch)
    01677 {
    01678   ChunkSaveLoadProc *proc = ch->save_proc;
    01679
    01680   /* Don't save any chunk information if there is no save handler. */
    01681   if (proc == NULL) return;
    01682
    01683   SlWriteUint32(ch->id);
    01684   DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    01685
    01686   if (ch->flags & CH_AUTO_LENGTH) {
    01687     /* Need to calculate the length. Solve that by calling SlAutoLength in the save_proc. */
    01688     _stub_save_proc = proc;
    01689     proc = SlStubSaveProc;
    01690   }
    01691
    01692   _sl.block_mode = ch->flags & CH_TYPE_MASK;
    01693   switch (ch->flags & CH_TYPE_MASK) {
    01694     case CH_RIFF:
    01695       _sl.need_length = NL_WANTLENGTH;
    01696       proc();
    01697       break;
    01698     case CH_ARRAY:
    01699       _sl.last_array_index = 0;
    01700       SlWriteByte(CH_ARRAY);
    01701       proc();
    01702       SlWriteArrayLength(0); // Terminate arrays
    01703       break;
    01704     case CH_SPARSE_ARRAY:
    01705       SlWriteByte(CH_SPARSE_ARRAY);
    01706       proc();
    01707       SlWriteArrayLength(0); // Terminate arrays
    01708       break;
    01709     default: NOT_REACHED();
    01710   }
    01711 }
    01712
    01714 static void SlSaveChunks()
    01715 {
    01716   FOR_ALL_CHUNK_HANDLERS(ch) {
    01717     SlSaveChunk(ch);
    01718   }
    01719
    01720   /* Terminator */
    01721   SlWriteUint32(0);
    01722 }
    01723
    01730 static const ChunkHandler *SlFindChunkHandler(uint32 id)
    01731 {
    01732   FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch;
    01733   return NULL;
    01734 }
    01735
    01737 static void SlLoadChunks()
    01738 {
    01739   uint32 id;
    01740   const ChunkHandler *ch;
    01741
    01742   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
    01743     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
    01744
    01745     ch = SlFindChunkHandler(id);
    01746     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
    01747     SlLoadChunk(ch);
    01748   }
    01749 }
    01750
    01752 static void SlLoadCheckChunks()
    01753 {
    01754   uint32 id;
    01755   const ChunkHandler *ch;
    01756
    01757   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
    01758     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
    01759
    01760     ch = SlFindChunkHandler(id);
    01761     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
    01762     SlLoadCheckChunk(ch);
    01763   }
    01764 }
    01765
    01767 static void SlFixPointers()
    01768 {
    01769   _sl.action = SLA_PTRS;
    01770
    01771   DEBUG(sl, 1, "Fixing pointers");
    01772
    01773   FOR_ALL_CHUNK_HANDLERS(ch) {
    01774     if (ch->ptrs_proc != NULL) {
    01775       DEBUG(sl, 2, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
    01776       ch->ptrs_proc();
    01777     }
    01778   }
    01779
    01780   DEBUG(sl, 1, "All pointers fixed");
    01781
    01782   assert(_sl.action == SLA_PTRS);
    01783 }
    01784
    01785
    01787 struct FileReader : LoadFilter {
    01788   FILE *file;
    01789   long begin;
    01790
    01795   FileReader(FILE *file) : LoadFilter(NULL), file(file), begin(ftell(file))
    01796   {
    01797   }
    01798
    01800   ~FileReader()
    01801   {
    01802     if (this->file != NULL) fclose(this->file);
    01803     this->file = NULL;
    01804
    01805     /* Make sure we don't double free. */
    01806     _sl.sf = NULL;
    01807   }
    01808
    01809   /* virtual */ size_t Read(byte *buf, size_t size)
    01810   {
    01811     /* We're in the process of shutting down, i.e. in "failure" mode. */
    01812     if (this->file == NULL) return 0;
    01813
    01814     return fread(buf, 1, size, this->file);
    01815   }
    01816
    01817   /* virtual */ void Reset()
    01818   {
    01819     clearerr(this->file);
    01820     fseek(this->file, this->begin, SEEK_SET);
    01821   }
    01822 };
    01823
    01825 struct FileWriter : SaveFilter {
    01826   FILE *file;
    01827
    01832   FileWriter(FILE *file) : SaveFilter(NULL), file(file)
    01833   {
    01834   }
    01835
    01837   ~FileWriter()
    01838   {
    01839     this->Finish();
    01840
    01841     /* Make sure we don't double free. */
    01842     _sl.sf = NULL;
    01843   }
    01844
    01845   /* virtual */ void Write(byte *buf, size_t size)
    01846   {
    01847     /* We're in the process of shutting down, i.e. in "failure" mode. */
    01848     if (this->file == NULL) return;
    01849
    01850     if (fwrite(buf, 1, size, this->file) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
    01851   }
    01852
    01853   /* virtual */ void Finish()
    01854   {
    01855     if (this->file != NULL) fclose(this->file);
    01856     this->file = NULL;
    01857   }
    01858 };
    01859
    01860 /*******************************************
    01861  ********** START OF LZO CODE **************
    01862  *******************************************/
    01863
    01864 #ifdef WITH_LZO
    01865 #include <lzo/lzo1x.h>
    01866
    01868 static const uint LZO_BUFFER_SIZE = 8192;
    01869
    01871 struct LZOLoadFilter : LoadFilter {
    01876   LZOLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    01877   {
    01878     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    01879   }
    01880
    01881   /* virtual */ size_t Read(byte *buf, size_t ssize)
    01882   {
    01883     assert(ssize >= LZO_BUFFER_SIZE);
    01884
    01885     /* Buffer size is from the LZO docs plus the chunk header size. */
    01886     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
    01887     uint32 tmp[2];
    01888     uint32 size;
    01889     lzo_uint len;
    01890
    01891     /* Read header*/
    01892     if (this->chain->Read((byte*)tmp, sizeof(tmp)) != sizeof(tmp)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE, "File read failed");
    01893
    01894     /* Check if size is bad */
    01895     ((uint32*)out)[0] = size = tmp[1];
    01896
    01897     if (_sl_version != 0) {
    01898       tmp[0] = TO_BE32(tmp[0]);
    01899       size = TO_BE32(size);
    01900     }
    01901
    01902     if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size");
    01903
    01904     /* Read block */
    01905     if (this->chain->Read(out + sizeof(uint32), size) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    01906
    01907     /* Verify checksum */
    01908     if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
    01909
    01910     /* Decompress */
    01911     lzo1x_decompress(out + sizeof(uint32) * 1, size, buf, &len, NULL);
    01912     return len;
    01913   }
    01914 };
    01915
    01917 struct LZOSaveFilter : SaveFilter {
    01923   LZOSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    01924   {
    01925     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    01926   }
    01927
    01928   /* virtual */ void Write(byte *buf, size_t size)
    01929   {
    01930     const lzo_bytep in = buf;
    01931     /* Buffer size is from the LZO docs plus the chunk header size. */
    01932     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
    01933     byte wrkmem[LZO1X_1_MEM_COMPRESS];
    01934     lzo_uint outlen;
    01935
    01936     do {
    01937       /* Compress up to LZO_BUFFER_SIZE bytes at once. */
    01938       lzo_uint len = size > LZO_BUFFER_SIZE ? LZO_BUFFER_SIZE : (lzo_uint)size;
    01939       lzo1x_1_compress(in, len, out + sizeof(uint32) * 2, &outlen, wrkmem);
    01940       ((uint32*)out)[1] = TO_BE32((uint32)outlen);
    01941       ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
    01942       this->chain->Write(out, outlen + sizeof(uint32) * 2);
    01943
    01944       /* Move to next data chunk. */
    01945       size -= len;
    01946       in += len;
    01947     } while (size > 0);
    01948   }
    01949 };
    01950
    01951 #endif /* WITH_LZO */
    01952
    01953 /*********************************************
    01954  ******** START OF NOCOMP CODE (uncompressed)*
    01955  *********************************************/
    01956
    01958 struct NoCompLoadFilter : LoadFilter {
    01963   NoCompLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    01964   {
    01965   }
    01966
    01967   /* virtual */ size_t Read(byte *buf, size_t size)
    01968   {
    01969     return this->chain->Read(buf, size);
    01970   }
    01971 };
    01972
    01974 struct NoCompSaveFilter : SaveFilter {
    01980   NoCompSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    01981   {
    01982   }
    01983
    01984   /* virtual */ void Write(byte *buf, size_t size)
    01985   {
    01986     this->chain->Write(buf, size);
    01987   }
    01988 };
    01989
    01990 /********************************************
    01991  ********** START OF ZLIB CODE **************
    01992  ********************************************/
    01993
    01994 #if defined(WITH_ZLIB)
    01995 #include <zlib.h>
    01996
    01998 struct ZlibLoadFilter : LoadFilter {
    01999   z_stream z;
    02000   byte fread_buf[MEMORY_CHUNK_SIZE];
    02001
    02006   ZlibLoadFilter(LoadFilter *chain) : LoadFilter(chain)
    02007   {
    02008     memset(&this->z, 0, sizeof(this->z));
    02009     if (inflateInit(&this->z) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    02010   }
    02011
    02013   ~ZlibLoadFilter()
    02014   {
    02015     inflateEnd(&this->z);
    02016   }
    02017
    02018   /* virtual */ size_t Read(byte *buf, size_t size)
    02019   {
    02020     this->z.next_out  = buf;
    02021     this->z.avail_out = (uint)size;
    02022
    02023     do {
    02024       /* read more bytes from the file? */
    02025       if (this->z.avail_in == 0) {
    02026         this->z.next_in = this->fread_buf;
    02027         this->z.avail_in = (uint)this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
    02028       }
    02029
    02030       /* inflate the data */
    02031       int r = inflate(&this->z, 0);
    02032       if (r == Z_STREAM_END) break;
    02033
    02034       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "inflate() failed");
    02035     } while (this->z.avail_out != 0);
    02036
    02037     return size - this->z.avail_out;
    02038   }
    02039 };
    02040
    02042 struct ZlibSaveFilter : SaveFilter {
    02043   z_stream z;
    02044
    02050   ZlibSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
    02051   {
    02052     memset(&this->z, 0, sizeof(this->z));
    02053     if (deflateInit(&this->z, compression_level) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    02054   }
    02055
    02057   ~ZlibSaveFilter()
    02058   {
    02059     deflateEnd(&this->z);
    02060   }
    02061
    02068   void WriteLoop(byte *p, size_t len, int mode)
    02069   {
    02070     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
    02071     uint n;
    02072     this->z.next_in = p;
    02073     this->z.avail_in = (uInt)len;
    02074     do {
    02075       this->z.next_out = buf;
    02076       this->z.avail_out = sizeof(buf);
    02077
    02085       int r = deflate(&this->z, mode);
    02086
    02087       /* bytes were emitted? */
    02088       if ((n = sizeof(buf) - this->z.avail_out) != 0) {
    02089         this->chain->Write(buf, n);
    02090       }
    02091       if (r == Z_STREAM_END) break;
    02092
    02093       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code");
    02094     } while (this->z.avail_in || !this->z.avail_out);
    02095   }
    02096
    02097   /* virtual */ void Write(byte *buf, size_t size)
    02098   {
    02099     this->WriteLoop(buf, size, 0);
    02100   }
    02101
    02102   /* virtual */ void Finish()
    02103   {
    02104     this->WriteLoop(NULL, 0, Z_FINISH);
    02105     this->chain->Finish();
    02106   }
    02107 };
    02108
    02109 #endif /* WITH_ZLIB */
    02110
    02111 /********************************************
    02112  ********** START OF LZMA CODE **************
    02113  ********************************************/
    02114
    02115 #if defined(WITH_LZMA)
    02116 #include <lzma.h>
    02117
    02124 static const lzma_stream _lzma_init = LZMA_STREAM_INIT;
    02125
    02127 struct LZMALoadFilter : LoadFilter {
    02128   lzma_stream lzma;
    02129   byte fread_buf[MEMORY_CHUNK_SIZE];
    02130
    02135   LZMALoadFilter(LoadFilter *chain) : LoadFilter(chain), lzma(_lzma_init)
    02136   {
    02137     /* Allow saves up to 256 MB uncompressed */
    02138     if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
    02139   }
    02140
    02142   ~LZMALoadFilter()
    02143   {
    02144     lzma_end(&this->lzma);
    02145   }
    02146
    02147   /* virtual */ size_t Read(byte *buf, size_t size)
    02148   {
    02149     this->lzma.next_out  = buf;
    02150     this->lzma.avail_out = size;
    02151
    02152     do {
    02153       /* read more bytes from the file? */
    02154       if (this->lzma.avail_in == 0) {
    02155         this->lzma.next_in  = this->fread_buf;
    02156         this->lzma.avail_in = this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
    02157       }
    02158
    02159       /* inflate the data */
    02160       lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
    02161       if (r == LZMA_STREAM_END) break;
    02162       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
    02163     } while (this->lzma.avail_out != 0);
    02164
    02165     return size - this->lzma.avail_out;
    02166   }
    02167 };
    02168
    02170 struct LZMASaveFilter : SaveFilter {
    02171   lzma_stream lzma;
    02172
    02178   LZMASaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain), lzma(_lzma_init)
    02179   {
    02180     if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
    02181   }
    02182
    02184   ~LZMASaveFilter()
    02185   {
    02186     lzma_end(&this->lzma);
    02187   }
    02188
    02195   void WriteLoop(byte *p, size_t len, lzma_action action)
    02196   {
    02197     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
    02198     size_t n;
    02199     this->lzma.next_in = p;
    02200     this->lzma.avail_in = len;
    02201     do {
    02202       this->lzma.next_out = buf;
    02203       this->lzma.avail_out = sizeof(buf);
    02204
    02205       lzma_ret r = lzma_code(&this->lzma, action);
    02206
    02207       /* bytes were emitted? */
    02208       if ((n = sizeof(buf) - this->lzma.avail_out) != 0) {
    02209         this->chain->Write(buf, n);
    02210       }
    02211       if (r == LZMA_STREAM_END) break;
    02212       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
    02213     } while (this->lzma.avail_in || !this->lzma.avail_out);
    02214   }
    02215
    02216   /* virtual */ void Write(byte *buf, size_t size)
    02217   {
    02218     this->WriteLoop(buf, size, LZMA_RUN);
    02219   }
    02220
    02221   /* virtual */ void Finish()
    02222   {
    02223     this->WriteLoop(NULL, 0, LZMA_FINISH);
    02224     this->chain->Finish();
    02225   }
    02226 };
    02227
    02228 #endif /* WITH_LZMA */
    02229
    02230 /*******************************************
    02231  ************* END OF CODE *****************
    02232  *******************************************/
    02233
    02235 struct SaveLoadFormat {
    02236   const char *name;
    02237   uint32 tag;
    02238
    02239   LoadFilter *(*init_load)(LoadFilter *chain);
    02240   SaveFilter *(*init_write)(SaveFilter *chain, byte compression);
    02241
    02242   byte min_compression;
    02243   byte default_compression;
    02244   byte max_compression;
    02245 };
    02246
    02248 static const SaveLoadFormat _saveload_formats[] = {
    02249 #if defined(WITH_LZO)
    02250   /* Roughly 75% larger than zlib level 6 at only ~7% of the CPU usage. */
    02251   {"lzo",    TO_BE32X('OTTD'), CreateLoadFilter<LZOLoadFilter>,    CreateSaveFilter<LZOSaveFilter>,    0, 0, 0},
    02252 #else
    02253   {"lzo",    TO_BE32X('OTTD'), NULL,                               NULL,                               0, 0, 0},
    02254 #endif
    02255   /* Roughly 5 times larger at only 1% of the CPU usage over zlib level 6. */
    02256   {"none",   TO_BE32X('OTTN'), CreateLoadFilter<NoCompLoadFilter>, CreateSaveFilter<NoCompSaveFilter>, 0, 0, 0},
    02257 #if defined(WITH_ZLIB)
    02258   /* After level 6 the speed reduction is significant (1.5x to 2.5x slower per level), but the reduction in filesize is
    02259    * fairly insignificant (~1% for each step). Lower levels become ~5-10% bigger by each level than level 6 while level
    02260    * 1 is "only" 3 times as fast. Level 0 results in uncompressed savegames at about 8 times the cost of "none". */
    02261   {"zlib",   TO_BE32X('OTTZ'), CreateLoadFilter<ZlibLoadFilter>,   CreateSaveFilter<ZlibSaveFilter>,   0, 6, 9},
    02262 #else
    02263   {"zlib",   TO_BE32X('OTTZ'), NULL,                               NULL,                               0, 0, 0},
    02264 #endif
    02265 #if defined(WITH_LZMA)
    02266   /* Level 2 compression is speed wise as fast as zlib level 6 compression (old default), but results in ~10% smaller saves.
    02267    * Higher compression levels are possible, and might improve savegame size by up to 25%, but are also up to 10 times slower.
    02268    * The next significant reduction in file size is at level 4, but that is already 4 times slower. Level 3 is primarily 50%
    02269    * slower while not improving the filesize, while level 0 and 1 are faster, but don't reduce savegame size much.
    02270    * It's OTTX and not e.g. OTTL because liblzma is part of xz-utils and .tar.xz is prefered over .tar.lzma. */
    02271   {"lzma",   TO_BE32X('OTTX'), CreateLoadFilter<LZMALoadFilter>,   CreateSaveFilter<LZMASaveFilter>,   0, 2, 9},
    02272 #else
    02273   {"lzma",   TO_BE32X('OTTX'), NULL,                               NULL,                               0, 0, 0},
    02274 #endif
    02275 };
    02276
    02284 static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
    02285 {
    02286   const SaveLoadFormat *def = lastof(_saveload_formats);
    02287
    02288   /* find default savegame format, the highest one with which files can be written */
    02289   while (!def->init_write) def--;
    02290
    02291   if (!StrEmpty(s)) {
    02292     /* Get the ":..." of the compression level out of the way */
    02293     char *complevel = strrchr(s, ':');
    02294     if (complevel != NULL) *complevel = '\0';
    02295
    02296     for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
    02297       if (slf->init_write != NULL && strcmp(s, slf->name) == 0) {
    02298         *compression_level = slf->default_compression;
    02299         if (complevel != NULL) {
    02300           /* There is a compression level in the string.
    02301            * First restore the : we removed to do proper name matching,
    02302            * then move the the begin of the actual version. */
    02303           *complevel = ':';
    02304           complevel++;
    02305
    02306           /* Get the version and determine whether all went fine. */
    02307           char *end;
    02308           long level = strtol(complevel, &end, 10);
    02309           if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) {
    02310             SetDParamStr(0, complevel);
    02311             ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL, WL_CRITICAL);
    02312           } else {
    02313             *compression_level = level;
    02314           }
    02315         }
    02316         return slf;
    02317       }
    02318     }
    02319
    02320     SetDParamStr(0, s);
    02321     SetDParamStr(1, def->name);
    02322     ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM, WL_CRITICAL);
    02323
    02324     /* Restore the string by adding the : back */
    02325     if (complevel != NULL) *complevel = ':';
    02326   }
    02327   *compression_level = def->default_compression;
    02328   return def;
    02329 }
    02330
    02331 /* actual loader/saver function */
    02332 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings);
    02333 extern bool AfterLoadGame();
    02334 extern bool LoadOldSaveGame(const char *file);
    02335
    02339 static inline void ClearSaveLoadState()
    02340 {
    02341   delete _sl.dumper;
    02342   _sl.dumper = NULL;
    02343
    02344   delete _sl.sf;
    02345   _sl.sf = NULL;
    02346
    02347   delete _sl.reader;
    02348   _sl.reader = NULL;
    02349
    02350   delete _sl.lf;
    02351   _sl.lf = NULL;
    02352 }
    02353
    02359 static void SaveFileStart()
    02360 {
    02361   _sl.ff_state = _fast_forward;
    02362   _fast_forward = 0;
    02363   if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
    02364
    02365   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START);
    02366   _sl.saveinprogress = true;
    02367 }
    02368
    02370 static void SaveFileDone()
    02371 {
    02372   if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state;
    02373   if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
    02374
    02375   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
    02376   _sl.saveinprogress = false;
    02377 }
    02378
    02380 void SetSaveLoadError(StringID str)
    02381 {
    02382   _sl.error_str = str;
    02383 }
    02384
    02386 const char *GetSaveLoadErrorString()
    02387 {
    02388   SetDParam(0, _sl.error_str);
    02389   SetDParamStr(1, _sl.extra_msg);
    02390
    02391   static char err_str[512];
    02392   GetString(err_str, _sl.action == SLA_SAVE ? STR_ERROR_GAME_SAVE_FAILED : STR_ERROR_GAME_LOAD_FAILED, lastof(err_str));
    02393   return err_str;
    02394 }
    02395
    02397 static void SaveFileError()
    02398 {
    02399   SetDParamStr(0, GetSaveLoadErrorString());
    02400   ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
    02401   SaveFileDone();
    02402 }
    02403
    02408 static SaveOrLoadResult SaveFileToDisk(bool threaded)
    02409 {
    02410   try {
    02411     byte compression;
    02412     const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format, &compression);
    02413
    02414     /* We have written our stuff to memory, now write it to file! */
    02415     uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) };
    02416     _sl.sf->Write((byte*)hdr, sizeof(hdr));
    02417
    02418     _sl.sf = fmt->init_write(_sl.sf, compression);
    02419     _sl.dumper->Flush(_sl.sf);
    02420
    02421     ClearSaveLoadState();
    02422
    02423     if (threaded) SetAsyncSaveFinish(SaveFileDone);
    02424
    02425     return SL_OK;
    02426   } catch (...) {
    02427     ClearSaveLoadState();
    02428
    02429     AsyncSaveFinishProc asfp = SaveFileDone;
    02430
    02431     /* We don't want to shout when saving is just
    02432      * cancelled due to a client disconnecting. */
    02433     if (_sl.error_str != STR_NETWORK_ERROR_LOSTCONNECTION) {
    02434       /* Skip the "colour" character */
    02435       DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
    02436       asfp = SaveFileError;
    02437     }
    02438
    02439     if (threaded) {
    02440       SetAsyncSaveFinish(asfp);
    02441     } else {
    02442       asfp();
    02443     }
    02444     return SL_ERROR;
    02445   }
    02446 }
    02447
    02449 static void SaveFileToDiskThread(void *arg)
    02450 {
    02451   SaveFileToDisk(true);
    02452 }
    02453
    02454 void WaitTillSaved()
    02455 {
    02456   if (_save_thread == NULL) return;
    02457
    02458   _save_thread->Join();
    02459   delete _save_thread;
    02460   _save_thread = NULL;
    02461
    02462   /* Make sure every other state is handled properly as well. */
    02463   ProcessAsyncSaveFinish();
    02464 }
    02465
    02474 static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
    02475 {
    02476   assert(!_sl.saveinprogress);
    02477
    02478   _sl.dumper = new MemoryDumper();
    02479   _sl.sf = writer;
    02480
    02481   _sl_version = SAVEGAME_VERSION;
    02482
    02483   SaveViewportBeforeSaveGame();
    02484   SlSaveChunks();
    02485
    02486   SaveFileStart();
    02487   if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
    02488     if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
    02489
    02490     SaveOrLoadResult result = SaveFileToDisk(false);
    02491     SaveFileDone();
    02492
    02493     return result;
    02494   }
    02495
    02496   return SL_OK;
    02497 }
    02498
    02505 SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
    02506 {
    02507   try {
    02508     _sl.action = SLA_SAVE;
    02509     return DoSave(writer, threaded);
    02510   } catch (...) {
    02511     ClearSaveLoadState();
    02512     return SL_ERROR;
    02513   }
    02514 }
    02515
    02522 static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
    02523 {
    02524   _sl.lf = reader;
    02525
    02526   if (load_check) {
    02527     /* Clear previous check data */
    02528     _load_check_data.Clear();
    02529     /* Mark SL_LOAD_CHECK as supported for this savegame. */
    02530     _load_check_data.checkable = true;
    02531   }
    02532
    02533   uint32 hdr[2];
    02534   if (_sl.lf->Read((byte*)hdr, sizeof(hdr)) != sizeof(hdr)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    02535
    02536   /* see if we have any loader for this type. */
    02537   const SaveLoadFormat *fmt = _saveload_formats;
    02538   for (;;) {
    02539     /* No loader found, treat as version 0 and use LZO format */
    02540     if (fmt == endof(_saveload_formats)) {
    02541       DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format");
    02542       _sl.lf->Reset();
    02543       _sl_version = 0;
    02544       _sl_minor_version = 0;
    02545
    02546       /* Try to find the LZO savegame format; it uses 'OTTD' as tag. */
    02547       fmt = _saveload_formats;
    02548       for (;;) {
    02549         if (fmt == endof(_saveload_formats)) {
    02550           /* Who removed LZO support? Bad bad boy! */
    02551           NOT_REACHED();
    02552         }
    02553         if (fmt->tag == TO_BE32X('OTTD')) break;
    02554         fmt++;
    02555       }
    02556       break;
    02557     }
    02558
    02559     if (fmt->tag == hdr[0]) {
    02560       /* check version number */
    02561       _sl_version = TO_BE32(hdr[1]) >> 16;
    02562       /* Minor is not used anymore from version 18.0, but it is still needed
    02563        * in versions before that (4 cases) which can't be removed easy.
    02564        * Therefor it is loaded, but never saved (or, it saves a 0 in any scenario). */
    02565       _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
    02566
    02567       DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
    02568
    02569       /* Is the version higher than the current? */
    02570       if (_sl_version > SAVEGAME_VERSION) SlError(STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME);
    02571       break;
    02572     }
    02573
    02574     fmt++;
    02575   }
    02576
    02577   /* loader for this savegame type is not implemented? */
    02578   if (fmt->init_load == NULL) {
    02579     char err_str[64];
    02580     snprintf(err_str, lengthof(err_str), "Loader for '%s' is not available.", fmt->name);
    02581     SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
    02582   }
    02583
    02584   _sl.lf = fmt->init_load(_sl.lf);
    02585   _sl.reader = new ReadBuffer(_sl.lf);
    02586   _next_offs = 0;
    02587
    02588   if (!load_check) {
    02589     /* Old maps were hardcoded to 256x256 and thus did not contain
    02590      * any mapsize information. Pre-initialize to 256x256 to not to
    02591      * confuse old games */
    02592     InitializeGame(256, 256, true, true);
    02593
    02594     GamelogReset();
    02595
    02596     if (IsSavegameVersionBefore(4)) {
    02597       /*
    02598        * NewGRFs were introduced between 0.3,4 and 0.3.5, which both
    02599        * shared savegame version 4. Anything before that 'obviously'
    02600        * does not have any NewGRFs. Between the introduction and
    02601        * savegame version 41 (just before 0.5) the NewGRF settings
    02602        * were not stored in the savegame and they were loaded by
    02603        * using the settings from the main menu.
    02604        * So, to recap:
    02605        * - savegame version  <  4:  do not load any NewGRFs.
    02606        * - savegame version >= 41:  load NewGRFs from savegame, which is
    02607        *                            already done at this stage by
    02608        *                            overwriting the main menu settings.
    02609        * - other savegame versions: use main menu settings.
    02610        *
    02611        * This means that users *can* crash savegame version 4..40
    02612        * savegames if they set incompatible NewGRFs in the main menu,
    02613        * but can't crash anymore for savegame version < 4 savegames.
    02614        *
    02615        * Note: this is done here because AfterLoadGame is also called
    02616        * for TTO/TTD/TTDP savegames which have their own NewGRF logic.
    02617        */
    02618       ClearGRFConfigList(&_grfconfig);
    02619     }
    02620   }
    02621
    02622   if (load_check) {
    02623     /* Load chunks into _load_check_data.
    02624      * No pools are loaded. References are not possible, and thus do not need resolving. */
    02625     SlLoadCheckChunks();
    02626   } else {
    02627     /* Load chunks and resolve references */
    02628     SlLoadChunks();
    02629     SlFixPointers();
    02630   }
    02631
    02632   ClearSaveLoadState();
    02633
    02634   _savegame_type = SGT_OTTD;
    02635
    02636   if (load_check) {
    02637     /* The only part from AfterLoadGame() we need */
    02638     _load_check_data.grf_compatibility = IsGoodGRFConfigList(_load_check_data.grfconfig);
    02639   } else {
    02640     GamelogStartAction(GLAT_LOAD);
    02641
    02642     /* After loading fix up savegame for any internal changes that
    02643      * might have occurred since then. If it fails, load back the old game. */
    02644     if (!AfterLoadGame()) {
    02645       GamelogStopAction();
    02646       return SL_REINIT;
    02647     }
    02648
    02649     GamelogStopAction();
    02650   }
    02651
    02652   return SL_OK;
    02653 }
    02654
    02660 SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
    02661 {
    02662   try {
    02663     _sl.action = SLA_LOAD;
    02664     return DoLoad(reader, false);
    02665   } catch (...) {
    02666     ClearSaveLoadState();
    02667     return SL_REINIT;
    02668   }
    02669 }
    02670
    02680 SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
    02681 {
    02682   /* An instance of saving is already active, so don't go saving again */
    02683   if (_sl.saveinprogress && mode == SL_SAVE && threaded) {
    02684     /* if not an autosave, but a user action, show error message */
    02685     if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
    02686     return SL_OK;
    02687   }
    02688   WaitTillSaved();
    02689
    02690   /* Load a TTDLX or TTDPatch game */
    02691   if (mode == SL_OLD_LOAD) {
    02692     InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
    02693
    02694     /* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
    02695      * and if so a new NewGRF list will be made in LoadOldSaveGame.
    02696      * Note: this is done here because AfterLoadGame is also called
    02697      * for OTTD savegames which have their own NewGRF logic. */
    02698     ClearGRFConfigList(&_grfconfig);
    02699     GamelogReset();
    02700     if (!LoadOldSaveGame(filename)) return SL_REINIT;
    02701     _sl_version = 0;
    02702     _sl_minor_version = 0;
    02703     GamelogStartAction(GLAT_LOAD);
    02704     if (!AfterLoadGame()) {
    02705       GamelogStopAction();
    02706       return SL_REINIT;
    02707     }
    02708     GamelogStopAction();
    02709     return SL_OK;
    02710   }
    02711
    02712   switch (mode) {
    02713     case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
    02714     case SL_LOAD: _sl.action = SLA_LOAD; break;
    02715     case SL_SAVE: _sl.action = SLA_SAVE; break;
    02716     default: NOT_REACHED();
    02717   }
    02718
    02719   try {
    02720     FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
    02721
    02722     /* Make it a little easier to load savegames from the console */
    02723     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
    02724     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
    02725     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SCENARIO_DIR);
    02726
    02727     if (fh == NULL) {
    02728       SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
    02729     }
    02730
    02731     if (mode == SL_SAVE) { // SAVE game
    02732       DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
    02733       if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
    02734
    02735       return DoSave(new FileWriter(fh), threaded);
    02736     }
    02737
    02738     /* LOAD game */
    02739     assert(mode == SL_LOAD || mode == SL_LOAD_CHECK);
    02740     DEBUG(desync, 1, "load: %s", filename);
    02741     return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK);
    02742   } catch (...) {
    02743     ClearSaveLoadState();
    02744
    02745     /* Skip the "colour" character */
    02746     if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
    02747
    02748     /* A saver/loader exception!! reinitialize all variables to prevent crash! */
    02749     return (mode == SL_LOAD) ? SL_REINIT : SL_ERROR;
    02750   }
    02751 }
    02752
    02754 void DoExitSave()
    02755 {
    02756   SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
    02757 }
    02758
    02764 void GenerateDefaultSaveName(char *buf, const char *last)
    02765 {
    02766   /* Check if we have a name for this map, which is the name of the first
    02767    * available company. When there's no company available we'll use
    02768    * 'Spectator' as "company" name. */
    02769   CompanyID cid = _local_company;
    02770   if (!Company::IsValidID(cid)) {
    02771     const Company *c;
    02772     FOR_ALL_COMPANIES(c) {
    02773       cid = c->index;
    02774       break;
    02775     }
    02776   }
    02777
    02778   SetDParam(0, cid);
    02779
    02780   /* Insert current date */
    02781   switch (_settings_client.gui.date_format_in_default_names) {
    02782     case 0: SetDParam(1, STR_JUST_DATE_LONG); break;
    02783     case 1: SetDParam(1, STR_JUST_DATE_TINY); break;
    02784     case 2: SetDParam(1, STR_JUST_DATE_ISO); break;
    02785     default: NOT_REACHED();
    02786   }
    02787   SetDParam(2, _date);
    02788
    02789   /* Get the correct string (special string for when there's not company) */
    02790   GetString(buf, !Company::IsValidID(cid) ? STR_SAVEGAME_NAME_SPECTATOR : STR_SAVEGAME_NAME_DEFAULT, last);
    02791   SanitizeFilename(buf);
    02792 }
    02793
    02794 #if 0
    02795
    02801 int GetSavegameType(char *file)
    02802 {
    02803   const SaveLoadFormat *fmt;
    02804   uint32 hdr;
    02805   FILE *f;
    02806   int mode = SL_OLD_LOAD;
    02807
    02808   f = fopen(file, "rb");
    02809   if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
    02810     DEBUG(sl, 0, "Savegame is obsolete or invalid format");
    02811     mode = SL_LOAD; // don't try to get filename, just show name as it is written
    02812   } else {
    02813     /* see if we have any loader for this type. */
    02814     for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
    02815       if (fmt->tag == hdr) {
    02816         mode = SL_LOAD; // new type of savegame
    02817         break;
    02818       }
    02819     }
    02820   }
    02821
    02822   fclose(f);
    02823   return mode;
    02824 }
    02825 #endif