saveload.cpp

Go to the documentation of this file.
00001 /* $Id: saveload.cpp 26670 2014-07-01 20:13:23Z 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           i &= ~0x10;
00674           if (HasBit(i, 3)) {
00675             SlErrorCorrupt("Unsupported gamma");
00676           }
00677           i = SlReadByte(); // 32 bits only.
00678         }
00679         i = (i << 8) | SlReadByte();
00680       }
00681       i = (i << 8) | SlReadByte();
00682     }
00683     i = (i << 8) | SlReadByte();
00684   }
00685   return i;
00686 }
00687 
00705 static void SlWriteSimpleGamma(size_t i)
00706 {
00707   if (i >= (1 << 7)) {
00708     if (i >= (1 << 14)) {
00709       if (i >= (1 << 21)) {
00710         if (i >= (1 << 28)) {
00711           assert(i <= UINT32_MAX); // We can only support 32 bits for now.
00712           SlWriteByte((byte)(0xF0));
00713           SlWriteByte((byte)(i >> 24));
00714         } else {
00715           SlWriteByte((byte)(0xE0 | (i >> 24)));
00716         }
00717         SlWriteByte((byte)(i >> 16));
00718       } else {
00719         SlWriteByte((byte)(0xC0 | (i >> 16)));
00720       }
00721       SlWriteByte((byte)(i >> 8));
00722     } else {
00723       SlWriteByte((byte)(0x80 | (i >> 8)));
00724     }
00725   }
00726   SlWriteByte((byte)i);
00727 }
00728 
00730 static inline uint SlGetGammaLength(size_t i)
00731 {
00732   return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21)) + (i >= (1 << 28));
00733 }
00734 
00735 static inline uint SlReadSparseIndex()
00736 {
00737   return SlReadSimpleGamma();
00738 }
00739 
00740 static inline void SlWriteSparseIndex(uint index)
00741 {
00742   SlWriteSimpleGamma(index);
00743 }
00744 
00745 static inline uint SlReadArrayLength()
00746 {
00747   return SlReadSimpleGamma();
00748 }
00749 
00750 static inline void SlWriteArrayLength(size_t length)
00751 {
00752   SlWriteSimpleGamma(length);
00753 }
00754 
00755 static inline uint SlGetArrayLength(size_t length)
00756 {
00757   return SlGetGammaLength(length);
00758 }
00759 
00766 static inline uint SlCalcConvMemLen(VarType conv)
00767 {
00768   static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
00769   byte length = GB(conv, 4, 4);
00770 
00771   switch (length << 4) {
00772     case SLE_VAR_STRB:
00773     case SLE_VAR_STRBQ:
00774     case SLE_VAR_STR:
00775     case SLE_VAR_STRQ:
00776       return SlReadArrayLength();
00777 
00778     default:
00779       assert(length < lengthof(conv_mem_size));
00780       return conv_mem_size[length];
00781   }
00782 }
00783 
00790 static inline byte SlCalcConvFileLen(VarType conv)
00791 {
00792   static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
00793   byte length = GB(conv, 0, 4);
00794   assert(length < lengthof(conv_file_size));
00795   return conv_file_size[length];
00796 }
00797 
00799 static inline size_t SlCalcRefLen()
00800 {
00801   return IsSavegameVersionBefore(69) ? 2 : 4;
00802 }
00803 
00804 void SlSetArrayIndex(uint index)
00805 {
00806   _sl.need_length = NL_WANTLENGTH;
00807   _sl.array_index = index;
00808 }
00809 
00810 static size_t _next_offs;
00811 
00816 int SlIterateArray()
00817 {
00818   int index;
00819 
00820   /* After reading in the whole array inside the loop
00821    * we must have read in all the data, so we must be at end of current block. */
00822   if (_next_offs != 0 && _sl.reader->GetSize() != _next_offs) SlErrorCorrupt("Invalid chunk size");
00823 
00824   for (;;) {
00825     uint length = SlReadArrayLength();
00826     if (length == 0) {
00827       _next_offs = 0;
00828       return -1;
00829     }
00830 
00831     _sl.obj_len = --length;
00832     _next_offs = _sl.reader->GetSize() + length;
00833 
00834     switch (_sl.block_mode) {
00835       case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
00836       case CH_ARRAY:        index = _sl.array_index++; break;
00837       default:
00838         DEBUG(sl, 0, "SlIterateArray error");
00839         return -1; // error
00840     }
00841 
00842     if (length != 0) return index;
00843   }
00844 }
00845 
00849 void SlSkipArray()
00850 {
00851   while (SlIterateArray() != -1) {
00852     SlSkipBytes(_next_offs - _sl.reader->GetSize());
00853   }
00854 }
00855 
00861 void SlSetLength(size_t length)
00862 {
00863   assert(_sl.action == SLA_SAVE);
00864 
00865   switch (_sl.need_length) {
00866     case NL_WANTLENGTH:
00867       _sl.need_length = NL_NONE;
00868       switch (_sl.block_mode) {
00869         case CH_RIFF:
00870           /* Ugly encoding of >16M RIFF chunks
00871            * The lower 24 bits are normal
00872            * The uppermost 4 bits are bits 24:27 */
00873           assert(length < (1 << 28));
00874           SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
00875           break;
00876         case CH_ARRAY:
00877           assert(_sl.last_array_index <= _sl.array_index);
00878           while (++_sl.last_array_index <= _sl.array_index) {
00879             SlWriteArrayLength(1);
00880           }
00881           SlWriteArrayLength(length + 1);
00882           break;
00883         case CH_SPARSE_ARRAY:
00884           SlWriteArrayLength(length + 1 + SlGetArrayLength(_sl.array_index)); // Also include length of sparse index.
00885           SlWriteSparseIndex(_sl.array_index);
00886           break;
00887         default: NOT_REACHED();
00888       }
00889       break;
00890 
00891     case NL_CALCLENGTH:
00892       _sl.obj_len += (int)length;
00893       break;
00894 
00895     default: NOT_REACHED();
00896   }
00897 }
00898 
00905 static void SlCopyBytes(void *ptr, size_t length)
00906 {
00907   byte *p = (byte *)ptr;
00908 
00909   switch (_sl.action) {
00910     case SLA_LOAD_CHECK:
00911     case SLA_LOAD:
00912       for (; length != 0; length--) *p++ = SlReadByte();
00913       break;
00914     case SLA_SAVE:
00915       for (; length != 0; length--) SlWriteByte(*p++);
00916       break;
00917     default: NOT_REACHED();
00918   }
00919 }
00920 
00922 size_t SlGetFieldLength()
00923 {
00924   return _sl.obj_len;
00925 }
00926 
00934 int64 ReadValue(const void *ptr, VarType conv)
00935 {
00936   switch (GetVarMemType(conv)) {
00937     case SLE_VAR_BL:  return (*(const bool *)ptr != 0);
00938     case SLE_VAR_I8:  return *(const int8  *)ptr;
00939     case SLE_VAR_U8:  return *(const byte  *)ptr;
00940     case SLE_VAR_I16: return *(const int16 *)ptr;
00941     case SLE_VAR_U16: return *(const uint16*)ptr;
00942     case SLE_VAR_I32: return *(const int32 *)ptr;
00943     case SLE_VAR_U32: return *(const uint32*)ptr;
00944     case SLE_VAR_I64: return *(const int64 *)ptr;
00945     case SLE_VAR_U64: return *(const uint64*)ptr;
00946     case SLE_VAR_NULL:return 0;
00947     default: NOT_REACHED();
00948   }
00949 }
00950 
00958 void WriteValue(void *ptr, VarType conv, int64 val)
00959 {
00960   switch (GetVarMemType(conv)) {
00961     case SLE_VAR_BL:  *(bool  *)ptr = (val != 0);  break;
00962     case SLE_VAR_I8:  *(int8  *)ptr = val; break;
00963     case SLE_VAR_U8:  *(byte  *)ptr = val; break;
00964     case SLE_VAR_I16: *(int16 *)ptr = val; break;
00965     case SLE_VAR_U16: *(uint16*)ptr = val; break;
00966     case SLE_VAR_I32: *(int32 *)ptr = val; break;
00967     case SLE_VAR_U32: *(uint32*)ptr = val; break;
00968     case SLE_VAR_I64: *(int64 *)ptr = val; break;
00969     case SLE_VAR_U64: *(uint64*)ptr = val; break;
00970     case SLE_VAR_NAME: *(char**)ptr = CopyFromOldName(val); break;
00971     case SLE_VAR_NULL: break;
00972     default: NOT_REACHED();
00973   }
00974 }
00975 
00984 static void SlSaveLoadConv(void *ptr, VarType conv)
00985 {
00986   switch (_sl.action) {
00987     case SLA_SAVE: {
00988       int64 x = ReadValue(ptr, conv);
00989 
00990       /* Write the value to the file and check if its value is in the desired range */
00991       switch (GetVarFileType(conv)) {
00992         case SLE_FILE_I8: assert(x >= -128 && x <= 127);     SlWriteByte(x);break;
00993         case SLE_FILE_U8: assert(x >= 0 && x <= 255);        SlWriteByte(x);break;
00994         case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break;
00995         case SLE_FILE_STRINGID:
00996         case SLE_FILE_U16:assert(x >= 0 && x <= 65535);      SlWriteUint16(x);break;
00997         case SLE_FILE_I32:
00998         case SLE_FILE_U32:                                   SlWriteUint32((uint32)x);break;
00999         case SLE_FILE_I64:
01000         case SLE_FILE_U64:                                   SlWriteUint64(x);break;
01001         default: NOT_REACHED();
01002       }
01003       break;
01004     }
01005     case SLA_LOAD_CHECK:
01006     case SLA_LOAD: {
01007       int64 x;
01008       /* Read a value from the file */
01009       switch (GetVarFileType(conv)) {
01010         case SLE_FILE_I8:  x = (int8  )SlReadByte();   break;
01011         case SLE_FILE_U8:  x = (byte  )SlReadByte();   break;
01012         case SLE_FILE_I16: x = (int16 )SlReadUint16(); break;
01013         case SLE_FILE_U16: x = (uint16)SlReadUint16(); break;
01014         case SLE_FILE_I32: x = (int32 )SlReadUint32(); break;
01015         case SLE_FILE_U32: x = (uint32)SlReadUint32(); break;
01016         case SLE_FILE_I64: x = (int64 )SlReadUint64(); break;
01017         case SLE_FILE_U64: x = (uint64)SlReadUint64(); break;
01018         case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break;
01019         default: NOT_REACHED();
01020       }
01021 
01022       /* Write The value to the struct. These ARE endian safe. */
01023       WriteValue(ptr, conv, x);
01024       break;
01025     }
01026     case SLA_PTRS: break;
01027     case SLA_NULL: break;
01028     default: NOT_REACHED();
01029   }
01030 }
01031 
01041 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
01042 {
01043   if (ptr == NULL) return 0;
01044   return min(strlen(ptr), length - 1);
01045 }
01046 
01056 static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
01057 {
01058   size_t len;
01059   const char *str;
01060 
01061   switch (GetVarMemType(conv)) {
01062     default: NOT_REACHED();
01063     case SLE_VAR_STR:
01064     case SLE_VAR_STRQ:
01065       str = *(const char * const *)ptr;
01066       len = SIZE_MAX;
01067       break;
01068     case SLE_VAR_STRB:
01069     case SLE_VAR_STRBQ:
01070       str = (const char *)ptr;
01071       len = length;
01072       break;
01073   }
01074 
01075   len = SlCalcNetStringLen(str, len);
01076   return len + SlGetArrayLength(len); // also include the length of the index
01077 }
01078 
01085 static void SlString(void *ptr, size_t length, VarType conv)
01086 {
01087   switch (_sl.action) {
01088     case SLA_SAVE: {
01089       size_t len;
01090       switch (GetVarMemType(conv)) {
01091         default: NOT_REACHED();
01092         case SLE_VAR_STRB:
01093         case SLE_VAR_STRBQ:
01094           len = SlCalcNetStringLen((char *)ptr, length);
01095           break;
01096         case SLE_VAR_STR:
01097         case SLE_VAR_STRQ:
01098           ptr = *(char **)ptr;
01099           len = SlCalcNetStringLen((char *)ptr, SIZE_MAX);
01100           break;
01101       }
01102 
01103       SlWriteArrayLength(len);
01104       SlCopyBytes(ptr, len);
01105       break;
01106     }
01107     case SLA_LOAD_CHECK:
01108     case SLA_LOAD: {
01109       size_t len = SlReadArrayLength();
01110 
01111       switch (GetVarMemType(conv)) {
01112         default: NOT_REACHED();
01113         case SLE_VAR_STRB:
01114         case SLE_VAR_STRBQ:
01115           if (len >= length) {
01116             DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
01117             SlCopyBytes(ptr, length);
01118             SlSkipBytes(len - length);
01119             len = length - 1;
01120           } else {
01121             SlCopyBytes(ptr, len);
01122           }
01123           break;
01124         case SLE_VAR_STR:
01125         case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate
01126           free(*(char **)ptr);
01127           if (len == 0) {
01128             *(char **)ptr = NULL;
01129             return;
01130           } else {
01131             *(char **)ptr = MallocT<char>(len + 1); // terminating '\0'
01132             ptr = *(char **)ptr;
01133             SlCopyBytes(ptr, len);
01134           }
01135           break;
01136       }
01137 
01138       ((char *)ptr)[len] = '\0'; // properly terminate the string
01139       StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK;
01140       if ((conv & SLF_ALLOW_CONTROL) != 0) {
01141         settings = settings | SVS_ALLOW_CONTROL_CODE;
01142         if (IsSavegameVersionBefore(169)) {
01143           str_fix_scc_encoded((char *)ptr, (char *)ptr + len);
01144         }
01145       }
01146       if ((conv & SLF_ALLOW_NEWLINE) != 0) {
01147         settings = settings | SVS_ALLOW_NEWLINE;
01148       }
01149       str_validate((char *)ptr, (char *)ptr + len, settings);
01150       break;
01151     }
01152     case SLA_PTRS: break;
01153     case SLA_NULL: break;
01154     default: NOT_REACHED();
01155   }
01156 }
01157 
01163 static inline size_t SlCalcArrayLen(size_t length, VarType conv)
01164 {
01165   return SlCalcConvFileLen(conv) * length;
01166 }
01167 
01174 void SlArray(void *array, size_t length, VarType conv)
01175 {
01176   if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
01177 
01178   /* Automatically calculate the length? */
01179   if (_sl.need_length != NL_NONE) {
01180     SlSetLength(SlCalcArrayLen(length, conv));
01181     /* Determine length only? */
01182     if (_sl.need_length == NL_CALCLENGTH) return;
01183   }
01184 
01185   /* NOTICE - handle some buggy stuff, in really old versions everything was saved
01186    * as a byte-type. So detect this, and adjust array size accordingly */
01187   if (_sl.action != SLA_SAVE && _sl_version == 0) {
01188     /* all arrays except difficulty settings */
01189     if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
01190         conv == SLE_INT32 || conv == SLE_UINT32) {
01191       SlCopyBytes(array, length * SlCalcConvFileLen(conv));
01192       return;
01193     }
01194     /* used for conversion of Money 32bit->64bit */
01195     if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
01196       for (uint i = 0; i < length; i++) {
01197         ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
01198       }
01199       return;
01200     }
01201   }
01202 
01203   /* If the size of elements is 1 byte both in file and memory, no special
01204    * conversion is needed, use specialized copy-copy function to speed up things */
01205   if (conv == SLE_INT8 || conv == SLE_UINT8) {
01206     SlCopyBytes(array, length);
01207   } else {
01208     byte *a = (byte*)array;
01209     byte mem_size = SlCalcConvMemLen(conv);
01210 
01211     for (; length != 0; length --) {
01212       SlSaveLoadConv(a, conv);
01213       a += mem_size; // get size
01214     }
01215   }
01216 }
01217 
01218 
01229 static size_t ReferenceToInt(const void *obj, SLRefType rt)
01230 {
01231   assert(_sl.action == SLA_SAVE);
01232 
01233   if (obj == NULL) return 0;
01234 
01235   switch (rt) {
01236     case REF_VEHICLE_OLD: // Old vehicles we save as new ones
01237     case REF_VEHICLE:   return ((const  Vehicle*)obj)->index + 1;
01238     case REF_STATION:   return ((const  Station*)obj)->index + 1;
01239     case REF_TOWN:      return ((const     Town*)obj)->index + 1;
01240     case REF_ORDER:     return ((const    Order*)obj)->index + 1;
01241     case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
01242     case REF_ENGINE_RENEWS:  return ((const       EngineRenew*)obj)->index + 1;
01243     case REF_CARGO_PACKET:   return ((const       CargoPacket*)obj)->index + 1;
01244     case REF_ORDERLIST:      return ((const         OrderList*)obj)->index + 1;
01245     case REF_STORAGE:        return ((const PersistentStorage*)obj)->index + 1;
01246     case REF_LINK_GRAPH:     return ((const         LinkGraph*)obj)->index + 1;
01247     case REF_LINK_GRAPH_JOB: return ((const      LinkGraphJob*)obj)->index + 1;
01248     default: NOT_REACHED();
01249   }
01250 }
01251 
01262 static void *IntToReference(size_t index, SLRefType rt)
01263 {
01264   assert_compile(sizeof(size_t) <= sizeof(void *));
01265 
01266   assert(_sl.action == SLA_PTRS);
01267 
01268   /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE,
01269    * and should be loaded like that */
01270   if (rt == REF_VEHICLE_OLD && !IsSavegameVersionBefore(4, 4)) {
01271     rt = REF_VEHICLE;
01272   }
01273 
01274   /* No need to look up NULL pointers, just return immediately */
01275   if (index == (rt == REF_VEHICLE_OLD ? 0xFFFF : 0)) return NULL;
01276 
01277   /* Correct index. Old vehicles were saved differently:
01278    * invalid vehicle was 0xFFFF, now we use 0x0000 for everything invalid. */
01279   if (rt != REF_VEHICLE_OLD) index--;
01280 
01281   switch (rt) {
01282     case REF_ORDERLIST:
01283       if (OrderList::IsValidID(index)) return OrderList::Get(index);
01284       SlErrorCorrupt("Referencing invalid OrderList");
01285 
01286     case REF_ORDER:
01287       if (Order::IsValidID(index)) return Order::Get(index);
01288       /* in old versions, invalid order was used to mark end of order list */
01289       if (IsSavegameVersionBefore(5, 2)) return NULL;
01290       SlErrorCorrupt("Referencing invalid Order");
01291 
01292     case REF_VEHICLE_OLD:
01293     case REF_VEHICLE:
01294       if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
01295       SlErrorCorrupt("Referencing invalid Vehicle");
01296 
01297     case REF_STATION:
01298       if (Station::IsValidID(index)) return Station::Get(index);
01299       SlErrorCorrupt("Referencing invalid Station");
01300 
01301     case REF_TOWN:
01302       if (Town::IsValidID(index)) return Town::Get(index);
01303       SlErrorCorrupt("Referencing invalid Town");
01304 
01305     case REF_ROADSTOPS:
01306       if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
01307       SlErrorCorrupt("Referencing invalid RoadStop");
01308 
01309     case REF_ENGINE_RENEWS:
01310       if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
01311       SlErrorCorrupt("Referencing invalid EngineRenew");
01312 
01313     case REF_CARGO_PACKET:
01314       if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
01315       SlErrorCorrupt("Referencing invalid CargoPacket");
01316 
01317     case REF_STORAGE:
01318       if (PersistentStorage::IsValidID(index)) return PersistentStorage::Get(index);
01319       SlErrorCorrupt("Referencing invalid PersistentStorage");
01320 
01321     case REF_LINK_GRAPH:
01322       if (LinkGraph::IsValidID(index)) return LinkGraph::Get(index);
01323       SlErrorCorrupt("Referencing invalid LinkGraph");
01324 
01325     case REF_LINK_GRAPH_JOB:
01326       if (LinkGraphJob::IsValidID(index)) return LinkGraphJob::Get(index);
01327       SlErrorCorrupt("Referencing invalid LinkGraphJob");
01328 
01329     default: NOT_REACHED();
01330   }
01331 }
01332 
01337 static inline size_t SlCalcListLen(const void *list)
01338 {
01339   const std::list<void *> *l = (const std::list<void *> *) list;
01340 
01341   int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
01342   /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
01343    * of the list */
01344   return l->size() * type_size + type_size;
01345 }
01346 
01347 
01353 static void SlList(void *list, SLRefType conv)
01354 {
01355   /* Automatically calculate the length? */
01356   if (_sl.need_length != NL_NONE) {
01357     SlSetLength(SlCalcListLen(list));
01358     /* Determine length only? */
01359     if (_sl.need_length == NL_CALCLENGTH) return;
01360   }
01361 
01362   typedef std::list<void *> PtrList;
01363   PtrList *l = (PtrList *)list;
01364 
01365   switch (_sl.action) {
01366     case SLA_SAVE: {
01367       SlWriteUint32((uint32)l->size());
01368 
01369       PtrList::iterator iter;
01370       for (iter = l->begin(); iter != l->end(); ++iter) {
01371         void *ptr = *iter;
01372         SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
01373       }
01374       break;
01375     }
01376     case SLA_LOAD_CHECK:
01377     case SLA_LOAD: {
01378       size_t length = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01379 
01380       /* Load each reference and push to the end of the list */
01381       for (size_t i = 0; i < length; i++) {
01382         size_t data = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01383         l->push_back((void *)data);
01384       }
01385       break;
01386     }
01387     case SLA_PTRS: {
01388       PtrList temp = *l;
01389 
01390       l->clear();
01391       PtrList::iterator iter;
01392       for (iter = temp.begin(); iter != temp.end(); ++iter) {
01393         void *ptr = IntToReference((size_t)*iter, conv);
01394         l->push_back(ptr);
01395       }
01396       break;
01397     }
01398     case SLA_NULL:
01399       l->clear();
01400       break;
01401     default: NOT_REACHED();
01402   }
01403 }
01404 
01405 
01407 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
01408 {
01409   if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
01410   if (sld->conv & SLF_NOT_IN_SAVE) return false;
01411 
01412   return true;
01413 }
01414 
01420 static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
01421 {
01422   if ((sld->conv & SLF_NO_NETWORK_SYNC) && _sl.action != SLA_SAVE && _networking && !_network_server) {
01423     SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
01424     return true;
01425   }
01426 
01427   return false;
01428 }
01429 
01436 size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
01437 {
01438   size_t length = 0;
01439 
01440   /* Need to determine the length and write a length tag. */
01441   for (; sld->cmd != SL_END; sld++) {
01442     length += SlCalcObjMemberLength(object, sld);
01443   }
01444   return length;
01445 }
01446 
01447 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
01448 {
01449   assert(_sl.action == SLA_SAVE);
01450 
01451   switch (sld->cmd) {
01452     case SL_VAR:
01453     case SL_REF:
01454     case SL_ARR:
01455     case SL_STR:
01456     case SL_LST:
01457       /* CONDITIONAL saveload types depend on the savegame version */
01458       if (!SlIsObjectValidInSavegame(sld)) break;
01459 
01460       switch (sld->cmd) {
01461         case SL_VAR: return SlCalcConvFileLen(sld->conv);
01462         case SL_REF: return SlCalcRefLen();
01463         case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
01464         case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
01465         case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
01466         default: NOT_REACHED();
01467       }
01468       break;
01469     case SL_WRITEBYTE: return 1; // a byte is logically of size 1
01470     case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
01471     case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
01472     default: NOT_REACHED();
01473   }
01474   return 0;
01475 }
01476 
01477 
01478 bool SlObjectMember(void *ptr, const SaveLoad *sld)
01479 {
01480   VarType conv = GB(sld->conv, 0, 8);
01481   switch (sld->cmd) {
01482     case SL_VAR:
01483     case SL_REF:
01484     case SL_ARR:
01485     case SL_STR:
01486     case SL_LST:
01487       /* CONDITIONAL saveload types depend on the savegame version */
01488       if (!SlIsObjectValidInSavegame(sld)) return false;
01489       if (SlSkipVariableOnLoad(sld)) return false;
01490 
01491       switch (sld->cmd) {
01492         case SL_VAR: SlSaveLoadConv(ptr, conv); break;
01493         case SL_REF: // Reference variable, translate
01494           switch (_sl.action) {
01495             case SLA_SAVE:
01496               SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv));
01497               break;
01498             case SLA_LOAD_CHECK:
01499             case SLA_LOAD:
01500               *(size_t *)ptr = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01501               break;
01502             case SLA_PTRS:
01503               *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv);
01504               break;
01505             case SLA_NULL:
01506               *(void **)ptr = NULL;
01507               break;
01508             default: NOT_REACHED();
01509           }
01510           break;
01511         case SL_ARR: SlArray(ptr, sld->length, conv); break;
01512         case SL_STR: SlString(ptr, sld->length, sld->conv); break;
01513         case SL_LST: SlList(ptr, (SLRefType)conv); break;
01514         default: NOT_REACHED();
01515       }
01516       break;
01517 
01518     /* SL_WRITEBYTE translates a value of a variable to another one upon
01519      * saving or loading.
01520      * XXX - variable renaming abuse
01521      * game_value: the value of the variable ingame is abused by sld->version_from
01522      * file_value: the value of the variable in the savegame is abused by sld->version_to */
01523     case SL_WRITEBYTE:
01524       switch (_sl.action) {
01525         case SLA_SAVE: SlWriteByte(sld->version_to); break;
01526         case SLA_LOAD_CHECK:
01527         case SLA_LOAD: *(byte *)ptr = sld->version_from; break;
01528         case SLA_PTRS: break;
01529         case SLA_NULL: break;
01530         default: NOT_REACHED();
01531       }
01532       break;
01533 
01534     /* SL_VEH_INCLUDE loads common code for vehicles */
01535     case SL_VEH_INCLUDE:
01536       SlObject(ptr, GetVehicleDescription(VEH_END));
01537       break;
01538 
01539     case SL_ST_INCLUDE:
01540       SlObject(ptr, GetBaseStationDescription());
01541       break;
01542 
01543     default: NOT_REACHED();
01544   }
01545   return true;
01546 }
01547 
01553 void SlObject(void *object, const SaveLoad *sld)
01554 {
01555   /* Automatically calculate the length? */
01556   if (_sl.need_length != NL_NONE) {
01557     SlSetLength(SlCalcObjLength(object, sld));
01558     if (_sl.need_length == NL_CALCLENGTH) return;
01559   }
01560 
01561   for (; sld->cmd != SL_END; sld++) {
01562     void *ptr = sld->global ? sld->address : GetVariableAddress(object, sld);
01563     SlObjectMember(ptr, sld);
01564   }
01565 }
01566 
01571 void SlGlobList(const SaveLoadGlobVarList *sldg)
01572 {
01573   SlObject(NULL, (const SaveLoad*)sldg);
01574 }
01575 
01581 void SlAutolength(AutolengthProc *proc, void *arg)
01582 {
01583   size_t offs;
01584 
01585   assert(_sl.action == SLA_SAVE);
01586 
01587   /* Tell it to calculate the length */
01588   _sl.need_length = NL_CALCLENGTH;
01589   _sl.obj_len = 0;
01590   proc(arg);
01591 
01592   /* Setup length */
01593   _sl.need_length = NL_WANTLENGTH;
01594   SlSetLength(_sl.obj_len);
01595 
01596   offs = _sl.dumper->GetSize() + _sl.obj_len;
01597 
01598   /* And write the stuff */
01599   proc(arg);
01600 
01601   if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
01602 }
01603 
01608 static void SlLoadChunk(const ChunkHandler *ch)
01609 {
01610   byte m = SlReadByte();
01611   size_t len;
01612   size_t endoffs;
01613 
01614   _sl.block_mode = m;
01615   _sl.obj_len = 0;
01616 
01617   switch (m) {
01618     case CH_ARRAY:
01619       _sl.array_index = 0;
01620       ch->load_proc();
01621       break;
01622     case CH_SPARSE_ARRAY:
01623       ch->load_proc();
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         ch->load_proc();
01633         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
01634       } else {
01635         SlErrorCorrupt("Invalid chunk type");
01636       }
01637       break;
01638   }
01639 }
01640 
01646 static void SlLoadCheckChunk(const ChunkHandler *ch)
01647 {
01648   byte m = SlReadByte();
01649   size_t len;
01650   size_t endoffs;
01651 
01652   _sl.block_mode = m;
01653   _sl.obj_len = 0;
01654 
01655   switch (m) {
01656     case CH_ARRAY:
01657       _sl.array_index = 0;
01658       if (ch->load_check_proc) {
01659         ch->load_check_proc();
01660       } else {
01661         SlSkipArray();
01662       }
01663       break;
01664     case CH_SPARSE_ARRAY:
01665       if (ch->load_check_proc) {
01666         ch->load_check_proc();
01667       } else {
01668         SlSkipArray();
01669       }
01670       break;
01671     default:
01672       if ((m & 0xF) == CH_RIFF) {
01673         /* Read length */
01674         len = (SlReadByte() << 16) | ((m >> 4) << 24);
01675         len += SlReadUint16();
01676         _sl.obj_len = len;
01677         endoffs = _sl.reader->GetSize() + len;
01678         if (ch->load_check_proc) {
01679           ch->load_check_proc();
01680         } else {
01681           SlSkipBytes(len);
01682         }
01683         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
01684       } else {
01685         SlErrorCorrupt("Invalid chunk type");
01686       }
01687       break;
01688   }
01689 }
01690 
01695 static ChunkSaveLoadProc *_stub_save_proc;
01696 
01702 static inline void SlStubSaveProc2(void *arg)
01703 {
01704   _stub_save_proc();
01705 }
01706 
01712 static void SlStubSaveProc()
01713 {
01714   SlAutolength(SlStubSaveProc2, NULL);
01715 }
01716 
01722 static void SlSaveChunk(const ChunkHandler *ch)
01723 {
01724   ChunkSaveLoadProc *proc = ch->save_proc;
01725 
01726   /* Don't save any chunk information if there is no save handler. */
01727   if (proc == NULL) return;
01728 
01729   SlWriteUint32(ch->id);
01730   DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
01731 
01732   if (ch->flags & CH_AUTO_LENGTH) {
01733     /* Need to calculate the length. Solve that by calling SlAutoLength in the save_proc. */
01734     _stub_save_proc = proc;
01735     proc = SlStubSaveProc;
01736   }
01737 
01738   _sl.block_mode = ch->flags & CH_TYPE_MASK;
01739   switch (ch->flags & CH_TYPE_MASK) {
01740     case CH_RIFF:
01741       _sl.need_length = NL_WANTLENGTH;
01742       proc();
01743       break;
01744     case CH_ARRAY:
01745       _sl.last_array_index = 0;
01746       SlWriteByte(CH_ARRAY);
01747       proc();
01748       SlWriteArrayLength(0); // Terminate arrays
01749       break;
01750     case CH_SPARSE_ARRAY:
01751       SlWriteByte(CH_SPARSE_ARRAY);
01752       proc();
01753       SlWriteArrayLength(0); // Terminate arrays
01754       break;
01755     default: NOT_REACHED();
01756   }
01757 }
01758 
01760 static void SlSaveChunks()
01761 {
01762   FOR_ALL_CHUNK_HANDLERS(ch) {
01763     SlSaveChunk(ch);
01764   }
01765 
01766   /* Terminator */
01767   SlWriteUint32(0);
01768 }
01769 
01776 static const ChunkHandler *SlFindChunkHandler(uint32 id)
01777 {
01778   FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch;
01779   return NULL;
01780 }
01781 
01783 static void SlLoadChunks()
01784 {
01785   uint32 id;
01786   const ChunkHandler *ch;
01787 
01788   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
01789     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
01790 
01791     ch = SlFindChunkHandler(id);
01792     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
01793     SlLoadChunk(ch);
01794   }
01795 }
01796 
01798 static void SlLoadCheckChunks()
01799 {
01800   uint32 id;
01801   const ChunkHandler *ch;
01802 
01803   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
01804     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
01805 
01806     ch = SlFindChunkHandler(id);
01807     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
01808     SlLoadCheckChunk(ch);
01809   }
01810 }
01811 
01813 static void SlFixPointers()
01814 {
01815   _sl.action = SLA_PTRS;
01816 
01817   DEBUG(sl, 1, "Fixing pointers");
01818 
01819   FOR_ALL_CHUNK_HANDLERS(ch) {
01820     if (ch->ptrs_proc != NULL) {
01821       DEBUG(sl, 2, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
01822       ch->ptrs_proc();
01823     }
01824   }
01825 
01826   DEBUG(sl, 1, "All pointers fixed");
01827 
01828   assert(_sl.action == SLA_PTRS);
01829 }
01830 
01831 
01833 struct FileReader : LoadFilter {
01834   FILE *file; 
01835   long begin; 
01836 
01841   FileReader(FILE *file) : LoadFilter(NULL), file(file), begin(ftell(file))
01842   {
01843   }
01844 
01846   ~FileReader()
01847   {
01848     if (this->file != NULL) fclose(this->file);
01849     this->file = NULL;
01850 
01851     /* Make sure we don't double free. */
01852     _sl.sf = NULL;
01853   }
01854 
01855   /* virtual */ size_t Read(byte *buf, size_t size)
01856   {
01857     /* We're in the process of shutting down, i.e. in "failure" mode. */
01858     if (this->file == NULL) return 0;
01859 
01860     return fread(buf, 1, size, this->file);
01861   }
01862 
01863   /* virtual */ void Reset()
01864   {
01865     clearerr(this->file);
01866     if (fseek(this->file, this->begin, SEEK_SET)) {
01867       DEBUG(sl, 1, "Could not reset the file reading");
01868     }
01869   }
01870 };
01871 
01873 struct FileWriter : SaveFilter {
01874   FILE *file; 
01875 
01880   FileWriter(FILE *file) : SaveFilter(NULL), file(file)
01881   {
01882   }
01883 
01885   ~FileWriter()
01886   {
01887     this->Finish();
01888 
01889     /* Make sure we don't double free. */
01890     _sl.sf = NULL;
01891   }
01892 
01893   /* virtual */ void Write(byte *buf, size_t size)
01894   {
01895     /* We're in the process of shutting down, i.e. in "failure" mode. */
01896     if (this->file == NULL) return;
01897 
01898     if (fwrite(buf, 1, size, this->file) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
01899   }
01900 
01901   /* virtual */ void Finish()
01902   {
01903     if (this->file != NULL) fclose(this->file);
01904     this->file = NULL;
01905   }
01906 };
01907 
01908 /*******************************************
01909  ********** START OF LZO CODE **************
01910  *******************************************/
01911 
01912 #ifdef WITH_LZO
01913 #include <lzo/lzo1x.h>
01914 
01916 static const uint LZO_BUFFER_SIZE = 8192;
01917 
01919 struct LZOLoadFilter : LoadFilter {
01924   LZOLoadFilter(LoadFilter *chain) : LoadFilter(chain)
01925   {
01926     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
01927   }
01928 
01929   /* virtual */ size_t Read(byte *buf, size_t ssize)
01930   {
01931     assert(ssize >= LZO_BUFFER_SIZE);
01932 
01933     /* Buffer size is from the LZO docs plus the chunk header size. */
01934     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
01935     uint32 tmp[2];
01936     uint32 size;
01937     lzo_uint len;
01938 
01939     /* Read header*/
01940     if (this->chain->Read((byte*)tmp, sizeof(tmp)) != sizeof(tmp)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE, "File read failed");
01941 
01942     /* Check if size is bad */
01943     ((uint32*)out)[0] = size = tmp[1];
01944 
01945     if (_sl_version != 0) {
01946       tmp[0] = TO_BE32(tmp[0]);
01947       size = TO_BE32(size);
01948     }
01949 
01950     if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size");
01951 
01952     /* Read block */
01953     if (this->chain->Read(out + sizeof(uint32), size) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
01954 
01955     /* Verify checksum */
01956     if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
01957 
01958     /* Decompress */
01959     lzo1x_decompress_safe(out + sizeof(uint32) * 1, size, buf, &len, NULL);
01960     return len;
01961   }
01962 };
01963 
01965 struct LZOSaveFilter : SaveFilter {
01971   LZOSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
01972   {
01973     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
01974   }
01975 
01976   /* virtual */ void Write(byte *buf, size_t size)
01977   {
01978     const lzo_bytep in = buf;
01979     /* Buffer size is from the LZO docs plus the chunk header size. */
01980     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
01981     byte wrkmem[LZO1X_1_MEM_COMPRESS];
01982     lzo_uint outlen;
01983 
01984     do {
01985       /* Compress up to LZO_BUFFER_SIZE bytes at once. */
01986       lzo_uint len = size > LZO_BUFFER_SIZE ? LZO_BUFFER_SIZE : (lzo_uint)size;
01987       lzo1x_1_compress(in, len, out + sizeof(uint32) * 2, &outlen, wrkmem);
01988       ((uint32*)out)[1] = TO_BE32((uint32)outlen);
01989       ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
01990       this->chain->Write(out, outlen + sizeof(uint32) * 2);
01991 
01992       /* Move to next data chunk. */
01993       size -= len;
01994       in += len;
01995     } while (size > 0);
01996   }
01997 };
01998 
01999 #endif /* WITH_LZO */
02000 
02001 /*********************************************
02002  ******** START OF NOCOMP CODE (uncompressed)*
02003  *********************************************/
02004 
02006 struct NoCompLoadFilter : LoadFilter {
02011   NoCompLoadFilter(LoadFilter *chain) : LoadFilter(chain)
02012   {
02013   }
02014 
02015   /* virtual */ size_t Read(byte *buf, size_t size)
02016   {
02017     return this->chain->Read(buf, size);
02018   }
02019 };
02020 
02022 struct NoCompSaveFilter : SaveFilter {
02028   NoCompSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
02029   {
02030   }
02031 
02032   /* virtual */ void Write(byte *buf, size_t size)
02033   {
02034     this->chain->Write(buf, size);
02035   }
02036 };
02037 
02038 /********************************************
02039  ********** START OF ZLIB CODE **************
02040  ********************************************/
02041 
02042 #if defined(WITH_ZLIB)
02043 #include <zlib.h>
02044 
02046 struct ZlibLoadFilter : LoadFilter {
02047   z_stream z;                        
02048   byte fread_buf[MEMORY_CHUNK_SIZE]; 
02049 
02054   ZlibLoadFilter(LoadFilter *chain) : LoadFilter(chain)
02055   {
02056     memset(&this->z, 0, sizeof(this->z));
02057     if (inflateInit(&this->z) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
02058   }
02059 
02061   ~ZlibLoadFilter()
02062   {
02063     inflateEnd(&this->z);
02064   }
02065 
02066   /* virtual */ size_t Read(byte *buf, size_t size)
02067   {
02068     this->z.next_out  = buf;
02069     this->z.avail_out = (uint)size;
02070 
02071     do {
02072       /* read more bytes from the file? */
02073       if (this->z.avail_in == 0) {
02074         this->z.next_in = this->fread_buf;
02075         this->z.avail_in = (uint)this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
02076       }
02077 
02078       /* inflate the data */
02079       int r = inflate(&this->z, 0);
02080       if (r == Z_STREAM_END) break;
02081 
02082       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "inflate() failed");
02083     } while (this->z.avail_out != 0);
02084 
02085     return size - this->z.avail_out;
02086   }
02087 };
02088 
02090 struct ZlibSaveFilter : SaveFilter {
02091   z_stream z; 
02092 
02098   ZlibSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
02099   {
02100     memset(&this->z, 0, sizeof(this->z));
02101     if (deflateInit(&this->z, compression_level) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
02102   }
02103 
02105   ~ZlibSaveFilter()
02106   {
02107     deflateEnd(&this->z);
02108   }
02109 
02116   void WriteLoop(byte *p, size_t len, int mode)
02117   {
02118     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
02119     uint n;
02120     this->z.next_in = p;
02121     this->z.avail_in = (uInt)len;
02122     do {
02123       this->z.next_out = buf;
02124       this->z.avail_out = sizeof(buf);
02125 
02133       int r = deflate(&this->z, mode);
02134 
02135       /* bytes were emitted? */
02136       if ((n = sizeof(buf) - this->z.avail_out) != 0) {
02137         this->chain->Write(buf, n);
02138       }
02139       if (r == Z_STREAM_END) break;
02140 
02141       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code");
02142     } while (this->z.avail_in || !this->z.avail_out);
02143   }
02144 
02145   /* virtual */ void Write(byte *buf, size_t size)
02146   {
02147     this->WriteLoop(buf, size, 0);
02148   }
02149 
02150   /* virtual */ void Finish()
02151   {
02152     this->WriteLoop(NULL, 0, Z_FINISH);
02153     this->chain->Finish();
02154   }
02155 };
02156 
02157 #endif /* WITH_ZLIB */
02158 
02159 /********************************************
02160  ********** START OF LZMA CODE **************
02161  ********************************************/
02162 
02163 #if defined(WITH_LZMA)
02164 #include <lzma.h>
02165 
02172 static const lzma_stream _lzma_init = LZMA_STREAM_INIT;
02173 
02175 struct LZMALoadFilter : LoadFilter {
02176   lzma_stream lzma;                  
02177   byte fread_buf[MEMORY_CHUNK_SIZE]; 
02178 
02183   LZMALoadFilter(LoadFilter *chain) : LoadFilter(chain), lzma(_lzma_init)
02184   {
02185     /* Allow saves up to 256 MB uncompressed */
02186     if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
02187   }
02188 
02190   ~LZMALoadFilter()
02191   {
02192     lzma_end(&this->lzma);
02193   }
02194 
02195   /* virtual */ size_t Read(byte *buf, size_t size)
02196   {
02197     this->lzma.next_out  = buf;
02198     this->lzma.avail_out = size;
02199 
02200     do {
02201       /* read more bytes from the file? */
02202       if (this->lzma.avail_in == 0) {
02203         this->lzma.next_in  = this->fread_buf;
02204         this->lzma.avail_in = this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
02205       }
02206 
02207       /* inflate the data */
02208       lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
02209       if (r == LZMA_STREAM_END) break;
02210       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
02211     } while (this->lzma.avail_out != 0);
02212 
02213     return size - this->lzma.avail_out;
02214   }
02215 };
02216 
02218 struct LZMASaveFilter : SaveFilter {
02219   lzma_stream lzma; 
02220 
02226   LZMASaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain), lzma(_lzma_init)
02227   {
02228     if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
02229   }
02230 
02232   ~LZMASaveFilter()
02233   {
02234     lzma_end(&this->lzma);
02235   }
02236 
02243   void WriteLoop(byte *p, size_t len, lzma_action action)
02244   {
02245     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
02246     size_t n;
02247     this->lzma.next_in = p;
02248     this->lzma.avail_in = len;
02249     do {
02250       this->lzma.next_out = buf;
02251       this->lzma.avail_out = sizeof(buf);
02252 
02253       lzma_ret r = lzma_code(&this->lzma, action);
02254 
02255       /* bytes were emitted? */
02256       if ((n = sizeof(buf) - this->lzma.avail_out) != 0) {
02257         this->chain->Write(buf, n);
02258       }
02259       if (r == LZMA_STREAM_END) break;
02260       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
02261     } while (this->lzma.avail_in || !this->lzma.avail_out);
02262   }
02263 
02264   /* virtual */ void Write(byte *buf, size_t size)
02265   {
02266     this->WriteLoop(buf, size, LZMA_RUN);
02267   }
02268 
02269   /* virtual */ void Finish()
02270   {
02271     this->WriteLoop(NULL, 0, LZMA_FINISH);
02272     this->chain->Finish();
02273   }
02274 };
02275 
02276 #endif /* WITH_LZMA */
02277 
02278 /*******************************************
02279  ************* END OF CODE *****************
02280  *******************************************/
02281 
02283 struct SaveLoadFormat {
02284   const char *name;                     
02285   uint32 tag;                           
02286 
02287   LoadFilter *(*init_load)(LoadFilter *chain);                    
02288   SaveFilter *(*init_write)(SaveFilter *chain, byte compression); 
02289 
02290   byte min_compression;                 
02291   byte default_compression;             
02292   byte max_compression;                 
02293 };
02294 
02296 static const SaveLoadFormat _saveload_formats[] = {
02297 #if defined(WITH_LZO)
02298   /* Roughly 75% larger than zlib level 6 at only ~7% of the CPU usage. */
02299   {"lzo",    TO_BE32X('OTTD'), CreateLoadFilter<LZOLoadFilter>,    CreateSaveFilter<LZOSaveFilter>,    0, 0, 0},
02300 #else
02301   {"lzo",    TO_BE32X('OTTD'), NULL,                               NULL,                               0, 0, 0},
02302 #endif
02303   /* Roughly 5 times larger at only 1% of the CPU usage over zlib level 6. */
02304   {"none",   TO_BE32X('OTTN'), CreateLoadFilter<NoCompLoadFilter>, CreateSaveFilter<NoCompSaveFilter>, 0, 0, 0},
02305 #if defined(WITH_ZLIB)
02306   /* After level 6 the speed reduction is significant (1.5x to 2.5x slower per level), but the reduction in filesize is
02307    * fairly insignificant (~1% for each step). Lower levels become ~5-10% bigger by each level than level 6 while level
02308    * 1 is "only" 3 times as fast. Level 0 results in uncompressed savegames at about 8 times the cost of "none". */
02309   {"zlib",   TO_BE32X('OTTZ'), CreateLoadFilter<ZlibLoadFilter>,   CreateSaveFilter<ZlibSaveFilter>,   0, 6, 9},
02310 #else
02311   {"zlib",   TO_BE32X('OTTZ'), NULL,                               NULL,                               0, 0, 0},
02312 #endif
02313 #if defined(WITH_LZMA)
02314   /* Level 2 compression is speed wise as fast as zlib level 6 compression (old default), but results in ~10% smaller saves.
02315    * Higher compression levels are possible, and might improve savegame size by up to 25%, but are also up to 10 times slower.
02316    * The next significant reduction in file size is at level 4, but that is already 4 times slower. Level 3 is primarily 50%
02317    * slower while not improving the filesize, while level 0 and 1 are faster, but don't reduce savegame size much.
02318    * It's OTTX and not e.g. OTTL because liblzma is part of xz-utils and .tar.xz is preferred over .tar.lzma. */
02319   {"lzma",   TO_BE32X('OTTX'), CreateLoadFilter<LZMALoadFilter>,   CreateSaveFilter<LZMASaveFilter>,   0, 2, 9},
02320 #else
02321   {"lzma",   TO_BE32X('OTTX'), NULL,                               NULL,                               0, 0, 0},
02322 #endif
02323 };
02324 
02332 static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
02333 {
02334   const SaveLoadFormat *def = lastof(_saveload_formats);
02335 
02336   /* find default savegame format, the highest one with which files can be written */
02337   while (!def->init_write) def--;
02338 
02339   if (!StrEmpty(s)) {
02340     /* Get the ":..." of the compression level out of the way */
02341     char *complevel = strrchr(s, ':');
02342     if (complevel != NULL) *complevel = '\0';
02343 
02344     for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
02345       if (slf->init_write != NULL && strcmp(s, slf->name) == 0) {
02346         *compression_level = slf->default_compression;
02347         if (complevel != NULL) {
02348           /* There is a compression level in the string.
02349            * First restore the : we removed to do proper name matching,
02350            * then move the the begin of the actual version. */
02351           *complevel = ':';
02352           complevel++;
02353 
02354           /* Get the version and determine whether all went fine. */
02355           char *end;
02356           long level = strtol(complevel, &end, 10);
02357           if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) {
02358             SetDParamStr(0, complevel);
02359             ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL, WL_CRITICAL);
02360           } else {
02361             *compression_level = level;
02362           }
02363         }
02364         return slf;
02365       }
02366     }
02367 
02368     SetDParamStr(0, s);
02369     SetDParamStr(1, def->name);
02370     ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM, WL_CRITICAL);
02371 
02372     /* Restore the string by adding the : back */
02373     if (complevel != NULL) *complevel = ':';
02374   }
02375   *compression_level = def->default_compression;
02376   return def;
02377 }
02378 
02379 /* actual loader/saver function */
02380 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings);
02381 extern bool AfterLoadGame();
02382 extern bool LoadOldSaveGame(const char *file);
02383 
02387 static inline void ClearSaveLoadState()
02388 {
02389   delete _sl.dumper;
02390   _sl.dumper = NULL;
02391 
02392   delete _sl.sf;
02393   _sl.sf = NULL;
02394 
02395   delete _sl.reader;
02396   _sl.reader = NULL;
02397 
02398   delete _sl.lf;
02399   _sl.lf = NULL;
02400 }
02401 
02407 static void SaveFileStart()
02408 {
02409   _sl.ff_state = _fast_forward;
02410   _fast_forward = 0;
02411   if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
02412 
02413   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START);
02414   _sl.saveinprogress = true;
02415 }
02416 
02418 static void SaveFileDone()
02419 {
02420   if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state;
02421   if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
02422 
02423   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
02424   _sl.saveinprogress = false;
02425 }
02426 
02428 void SetSaveLoadError(StringID str)
02429 {
02430   _sl.error_str = str;
02431 }
02432 
02434 const char *GetSaveLoadErrorString()
02435 {
02436   SetDParam(0, _sl.error_str);
02437   SetDParamStr(1, _sl.extra_msg);
02438 
02439   static char err_str[512];
02440   GetString(err_str, _sl.action == SLA_SAVE ? STR_ERROR_GAME_SAVE_FAILED : STR_ERROR_GAME_LOAD_FAILED, lastof(err_str));
02441   return err_str;
02442 }
02443 
02445 static void SaveFileError()
02446 {
02447   SetDParamStr(0, GetSaveLoadErrorString());
02448   ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
02449   SaveFileDone();
02450 }
02451 
02456 static SaveOrLoadResult SaveFileToDisk(bool threaded)
02457 {
02458   try {
02459     byte compression;
02460     const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format, &compression);
02461 
02462     /* We have written our stuff to memory, now write it to file! */
02463     uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) };
02464     _sl.sf->Write((byte*)hdr, sizeof(hdr));
02465 
02466     _sl.sf = fmt->init_write(_sl.sf, compression);
02467     _sl.dumper->Flush(_sl.sf);
02468 
02469     ClearSaveLoadState();
02470 
02471     if (threaded) SetAsyncSaveFinish(SaveFileDone);
02472 
02473     return SL_OK;
02474   } catch (...) {
02475     ClearSaveLoadState();
02476 
02477     AsyncSaveFinishProc asfp = SaveFileDone;
02478 
02479     /* We don't want to shout when saving is just
02480      * cancelled due to a client disconnecting. */
02481     if (_sl.error_str != STR_NETWORK_ERROR_LOSTCONNECTION) {
02482       /* Skip the "colour" character */
02483       DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
02484       asfp = SaveFileError;
02485     }
02486 
02487     if (threaded) {
02488       SetAsyncSaveFinish(asfp);
02489     } else {
02490       asfp();
02491     }
02492     return SL_ERROR;
02493   }
02494 }
02495 
02497 static void SaveFileToDiskThread(void *arg)
02498 {
02499   SaveFileToDisk(true);
02500 }
02501 
02502 void WaitTillSaved()
02503 {
02504   if (_save_thread == NULL) return;
02505 
02506   _save_thread->Join();
02507   delete _save_thread;
02508   _save_thread = NULL;
02509 
02510   /* Make sure every other state is handled properly as well. */
02511   ProcessAsyncSaveFinish();
02512 }
02513 
02522 static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
02523 {
02524   assert(!_sl.saveinprogress);
02525 
02526   _sl.dumper = new MemoryDumper();
02527   _sl.sf = writer;
02528 
02529   _sl_version = SAVEGAME_VERSION;
02530 
02531   SaveViewportBeforeSaveGame();
02532   SlSaveChunks();
02533 
02534   SaveFileStart();
02535   if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
02536     if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
02537 
02538     SaveOrLoadResult result = SaveFileToDisk(false);
02539     SaveFileDone();
02540 
02541     return result;
02542   }
02543 
02544   return SL_OK;
02545 }
02546 
02553 SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
02554 {
02555   try {
02556     _sl.action = SLA_SAVE;
02557     return DoSave(writer, threaded);
02558   } catch (...) {
02559     ClearSaveLoadState();
02560     return SL_ERROR;
02561   }
02562 }
02563 
02570 static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
02571 {
02572   _sl.lf = reader;
02573 
02574   if (load_check) {
02575     /* Clear previous check data */
02576     _load_check_data.Clear();
02577     /* Mark SL_LOAD_CHECK as supported for this savegame. */
02578     _load_check_data.checkable = true;
02579   }
02580 
02581   uint32 hdr[2];
02582   if (_sl.lf->Read((byte*)hdr, sizeof(hdr)) != sizeof(hdr)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
02583 
02584   /* see if we have any loader for this type. */
02585   const SaveLoadFormat *fmt = _saveload_formats;
02586   for (;;) {
02587     /* No loader found, treat as version 0 and use LZO format */
02588     if (fmt == endof(_saveload_formats)) {
02589       DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format");
02590       _sl.lf->Reset();
02591       _sl_version = 0;
02592       _sl_minor_version = 0;
02593 
02594       /* Try to find the LZO savegame format; it uses 'OTTD' as tag. */
02595       fmt = _saveload_formats;
02596       for (;;) {
02597         if (fmt == endof(_saveload_formats)) {
02598           /* Who removed LZO support? Bad bad boy! */
02599           NOT_REACHED();
02600         }
02601         if (fmt->tag == TO_BE32X('OTTD')) break;
02602         fmt++;
02603       }
02604       break;
02605     }
02606 
02607     if (fmt->tag == hdr[0]) {
02608       /* check version number */
02609       _sl_version = TO_BE32(hdr[1]) >> 16;
02610       /* Minor is not used anymore from version 18.0, but it is still needed
02611        * in versions before that (4 cases) which can't be removed easy.
02612        * Therefore it is loaded, but never saved (or, it saves a 0 in any scenario). */
02613       _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
02614 
02615       DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
02616 
02617       /* Is the version higher than the current? */
02618       if (_sl_version > SAVEGAME_VERSION) SlError(STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME);
02619       break;
02620     }
02621 
02622     fmt++;
02623   }
02624 
02625   /* loader for this savegame type is not implemented? */
02626   if (fmt->init_load == NULL) {
02627     char err_str[64];
02628     snprintf(err_str, lengthof(err_str), "Loader for '%s' is not available.", fmt->name);
02629     SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
02630   }
02631 
02632   _sl.lf = fmt->init_load(_sl.lf);
02633   _sl.reader = new ReadBuffer(_sl.lf);
02634   _next_offs = 0;
02635 
02636   if (!load_check) {
02637     /* Old maps were hardcoded to 256x256 and thus did not contain
02638      * any mapsize information. Pre-initialize to 256x256 to not to
02639      * confuse old games */
02640     InitializeGame(256, 256, true, true);
02641 
02642     GamelogReset();
02643 
02644     if (IsSavegameVersionBefore(4)) {
02645       /*
02646        * NewGRFs were introduced between 0.3,4 and 0.3.5, which both
02647        * shared savegame version 4. Anything before that 'obviously'
02648        * does not have any NewGRFs. Between the introduction and
02649        * savegame version 41 (just before 0.5) the NewGRF settings
02650        * were not stored in the savegame and they were loaded by
02651        * using the settings from the main menu.
02652        * So, to recap:
02653        * - savegame version  <  4:  do not load any NewGRFs.
02654        * - savegame version >= 41:  load NewGRFs from savegame, which is
02655        *                            already done at this stage by
02656        *                            overwriting the main menu settings.
02657        * - other savegame versions: use main menu settings.
02658        *
02659        * This means that users *can* crash savegame version 4..40
02660        * savegames if they set incompatible NewGRFs in the main menu,
02661        * but can't crash anymore for savegame version < 4 savegames.
02662        *
02663        * Note: this is done here because AfterLoadGame is also called
02664        * for TTO/TTD/TTDP savegames which have their own NewGRF logic.
02665        */
02666       ClearGRFConfigList(&_grfconfig);
02667     }
02668   }
02669 
02670   if (load_check) {
02671     /* Load chunks into _load_check_data.
02672      * No pools are loaded. References are not possible, and thus do not need resolving. */
02673     SlLoadCheckChunks();
02674   } else {
02675     /* Load chunks and resolve references */
02676     SlLoadChunks();
02677     SlFixPointers();
02678   }
02679 
02680   ClearSaveLoadState();
02681 
02682   _savegame_type = SGT_OTTD;
02683 
02684   if (load_check) {
02685     /* The only part from AfterLoadGame() we need */
02686     _load_check_data.grf_compatibility = IsGoodGRFConfigList(_load_check_data.grfconfig);
02687   } else {
02688     GamelogStartAction(GLAT_LOAD);
02689 
02690     /* After loading fix up savegame for any internal changes that
02691      * might have occurred since then. If it fails, load back the old game. */
02692     if (!AfterLoadGame()) {
02693       GamelogStopAction();
02694       return SL_REINIT;
02695     }
02696 
02697     GamelogStopAction();
02698   }
02699 
02700   return SL_OK;
02701 }
02702 
02708 SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
02709 {
02710   try {
02711     _sl.action = SLA_LOAD;
02712     return DoLoad(reader, false);
02713   } catch (...) {
02714     ClearSaveLoadState();
02715     return SL_REINIT;
02716   }
02717 }
02718 
02728 SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
02729 {
02730   /* An instance of saving is already active, so don't go saving again */
02731   if (_sl.saveinprogress && mode == SL_SAVE && threaded) {
02732     /* if not an autosave, but a user action, show error message */
02733     if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
02734     return SL_OK;
02735   }
02736   WaitTillSaved();
02737 
02738   try {
02739     /* Load a TTDLX or TTDPatch game */
02740     if (mode == SL_OLD_LOAD) {
02741       InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
02742 
02743       /* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
02744       * and if so a new NewGRF list will be made in LoadOldSaveGame.
02745       * Note: this is done here because AfterLoadGame is also called
02746       * for OTTD savegames which have their own NewGRF logic. */
02747       ClearGRFConfigList(&_grfconfig);
02748       GamelogReset();
02749       if (!LoadOldSaveGame(filename)) return SL_REINIT;
02750       _sl_version = 0;
02751       _sl_minor_version = 0;
02752       GamelogStartAction(GLAT_LOAD);
02753       if (!AfterLoadGame()) {
02754         GamelogStopAction();
02755         return SL_REINIT;
02756       }
02757       GamelogStopAction();
02758       return SL_OK;
02759     }
02760 
02761     switch (mode) {
02762       case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
02763       case SL_LOAD: _sl.action = SLA_LOAD; break;
02764       case SL_SAVE: _sl.action = SLA_SAVE; break;
02765       default: NOT_REACHED();
02766     }
02767 
02768     FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
02769 
02770     /* Make it a little easier to load savegames from the console */
02771     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
02772     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
02773     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SCENARIO_DIR);
02774 
02775     if (fh == NULL) {
02776       SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
02777     }
02778 
02779     if (mode == SL_SAVE) { // SAVE game
02780       DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
02781       if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
02782 
02783       return DoSave(new FileWriter(fh), threaded);
02784     }
02785 
02786     /* LOAD game */
02787     assert(mode == SL_LOAD || mode == SL_LOAD_CHECK);
02788     DEBUG(desync, 1, "load: %s", filename);
02789     return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK);
02790   } catch (...) {
02791     ClearSaveLoadState();
02792 
02793     /* Skip the "colour" character */
02794     if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
02795 
02796     /* A saver/loader exception!! reinitialize all variables to prevent crash! */
02797     return (mode == SL_LOAD || mode == SL_OLD_LOAD) ? SL_REINIT : SL_ERROR;
02798   }
02799 }
02800 
02802 void DoExitSave()
02803 {
02804   SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
02805 }
02806 
02812 void GenerateDefaultSaveName(char *buf, const char *last)
02813 {
02814   /* Check if we have a name for this map, which is the name of the first
02815    * available company. When there's no company available we'll use
02816    * 'Spectator' as "company" name. */
02817   CompanyID cid = _local_company;
02818   if (!Company::IsValidID(cid)) {
02819     const Company *c;
02820     FOR_ALL_COMPANIES(c) {
02821       cid = c->index;
02822       break;
02823     }
02824   }
02825 
02826   SetDParam(0, cid);
02827 
02828   /* Insert current date */
02829   switch (_settings_client.gui.date_format_in_default_names) {
02830     case 0: SetDParam(1, STR_JUST_DATE_LONG); break;
02831     case 1: SetDParam(1, STR_JUST_DATE_TINY); break;
02832     case 2: SetDParam(1, STR_JUST_DATE_ISO); break;
02833     default: NOT_REACHED();
02834   }
02835   SetDParam(2, _date);
02836 
02837   /* Get the correct string (special string for when there's not company) */
02838   GetString(buf, !Company::IsValidID(cid) ? STR_SAVEGAME_NAME_SPECTATOR : STR_SAVEGAME_NAME_DEFAULT, last);
02839   SanitizeFilename(buf);
02840 }
02841 
02842 #if 0
02843 
02849 int GetSavegameType(char *file)
02850 {
02851   const SaveLoadFormat *fmt;
02852   uint32 hdr;
02853   FILE *f;
02854   int mode = SL_OLD_LOAD;
02855 
02856   f = fopen(file, "rb");
02857   if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
02858     DEBUG(sl, 0, "Savegame is obsolete or invalid format");
02859     mode = SL_LOAD; // don't try to get filename, just show name as it is written
02860   } else {
02861     /* see if we have any loader for this type. */
02862     for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
02863       if (fmt->tag == hdr) {
02864         mode = SL_LOAD; // new type of savegame
02865         break;
02866       }
02867     }
02868   }
02869 
02870   fclose(f);
02871   return mode;
02872 }
02873 #endif