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  *  173   23967   1.2.0-RC1
00240  *  174   23973   1.2.x
00241  *  175   24136
00242  *  176   24446
00243  *  177   head-to-head
00244  */
00245 extern const uint16 SAVEGAME_VERSION = 177; 
00246 assert_compile(SAVEGAME_VERSION_H2H == SAVEGAME_VERSION);
00247 
00248 SavegameType _savegame_type; 
00249 
00250 uint32 _ttdp_version;     
00251 uint16 _sl_version;       
00252 byte   _sl_minor_version; 
00253 char _savegame_format[8]; 
00254 bool _do_autosave;        
00255 
00257 enum SaveLoadAction {
00258   SLA_LOAD,        
00259   SLA_SAVE,        
00260   SLA_PTRS,        
00261   SLA_NULL,        
00262   SLA_LOAD_CHECK,  
00263 };
00264 
00265 enum NeedLength {
00266   NL_NONE = 0,       
00267   NL_WANTLENGTH = 1, 
00268   NL_CALCLENGTH = 2, 
00269 };
00270 
00272 static const size_t MEMORY_CHUNK_SIZE = 128 * 1024;
00273 
00275 struct ReadBuffer {
00276   byte buf[MEMORY_CHUNK_SIZE]; 
00277   byte *bufp;                  
00278   byte *bufe;                  
00279   LoadFilter *reader;          
00280   size_t read;                 
00281 
00286   ReadBuffer(LoadFilter *reader) : bufp(NULL), bufe(NULL), reader(reader), read(0)
00287   {
00288   }
00289 
00290   inline byte ReadByte()
00291   {
00292     if (this->bufp == this->bufe) {
00293       size_t len = this->reader->Read(this->buf, lengthof(this->buf));
00294       if (len == 0) SlErrorCorrupt("Unexpected end of chunk");
00295 
00296       this->read += len;
00297       this->bufp = this->buf;
00298       this->bufe = this->buf + len;
00299     }
00300 
00301     return *this->bufp++;
00302   }
00303 
00308   size_t GetSize() const
00309   {
00310     return this->read - (this->bufe - this->bufp);
00311   }
00312 };
00313 
00314 
00316 struct MemoryDumper {
00317   AutoFreeSmallVector<byte *, 16> blocks; 
00318   byte *buf;                              
00319   byte *bufe;                             
00320 
00322   MemoryDumper() : buf(NULL), bufe(NULL)
00323   {
00324   }
00325 
00330   inline void WriteByte(byte b)
00331   {
00332     /* Are we at the end of this chunk? */
00333     if (this->buf == this->bufe) {
00334       this->buf = CallocT<byte>(MEMORY_CHUNK_SIZE);
00335       *this->blocks.Append() = this->buf;
00336       this->bufe = this->buf + MEMORY_CHUNK_SIZE;
00337     }
00338 
00339     *this->buf++ = b;
00340   }
00341 
00346   void Flush(SaveFilter *writer)
00347   {
00348     uint i = 0;
00349     size_t t = this->GetSize();
00350 
00351     while (t > 0) {
00352       size_t to_write = min(MEMORY_CHUNK_SIZE, t);
00353 
00354       writer->Write(this->blocks[i++], to_write);
00355       t -= to_write;
00356     }
00357 
00358     writer->Finish();
00359   }
00360 
00365   size_t GetSize() const
00366   {
00367     return this->blocks.Length() * MEMORY_CHUNK_SIZE - (this->bufe - this->buf);
00368   }
00369 };
00370 
00372 struct SaveLoadParams {
00373   SaveLoadAction action;               
00374   NeedLength need_length;              
00375   byte block_mode;                     
00376   bool error;                          
00377 
00378   size_t obj_len;                      
00379   int array_index, last_array_index;   
00380 
00381   MemoryDumper *dumper;                
00382   SaveFilter *sf;                      
00383 
00384   ReadBuffer *reader;                  
00385   LoadFilter *lf;                      
00386 
00387   StringID error_str;                  
00388   char *extra_msg;                     
00389 
00390   byte ff_state;                       
00391   bool saveinprogress;                 
00392 };
00393 
00394 static SaveLoadParams _sl; 
00395 
00396 /* these define the chunks */
00397 extern const ChunkHandler _gamelog_chunk_handlers[];
00398 extern const ChunkHandler _map_chunk_handlers[];
00399 extern const ChunkHandler _misc_chunk_handlers[];
00400 extern const ChunkHandler _name_chunk_handlers[];
00401 extern const ChunkHandler _cheat_chunk_handlers[] ;
00402 extern const ChunkHandler _setting_chunk_handlers[];
00403 extern const ChunkHandler _company_chunk_handlers[];
00404 extern const ChunkHandler _engine_chunk_handlers[];
00405 extern const ChunkHandler _veh_chunk_handlers[];
00406 extern const ChunkHandler _waypoint_chunk_handlers[];
00407 extern const ChunkHandler _depot_chunk_handlers[];
00408 extern const ChunkHandler _order_chunk_handlers[];
00409 extern const ChunkHandler _town_chunk_handlers[];
00410 extern const ChunkHandler _sign_chunk_handlers[];
00411 extern const ChunkHandler _station_chunk_handlers[];
00412 extern const ChunkHandler _industry_chunk_handlers[];
00413 extern const ChunkHandler _economy_chunk_handlers[];
00414 extern const ChunkHandler _subsidy_chunk_handlers[];
00415 extern const ChunkHandler _cargomonitor_chunk_handlers[];
00416 extern const ChunkHandler _goal_chunk_handlers[];
00417 extern const ChunkHandler _ai_chunk_handlers[];
00418 extern const ChunkHandler _game_chunk_handlers[];
00419 extern const ChunkHandler _animated_tile_chunk_handlers[];
00420 extern const ChunkHandler _newgrf_chunk_handlers[];
00421 extern const ChunkHandler _group_chunk_handlers[];
00422 extern const ChunkHandler _cargopacket_chunk_handlers[];
00423 extern const ChunkHandler _autoreplace_chunk_handlers[];
00424 extern const ChunkHandler _labelmaps_chunk_handlers[];
00425 extern const ChunkHandler _airport_chunk_handlers[];
00426 extern const ChunkHandler _object_chunk_handlers[];
00427 extern const ChunkHandler _persistent_storage_chunk_handlers[];
00428 
00430 static const ChunkHandler * const _chunk_handlers[] = {
00431   _gamelog_chunk_handlers,
00432   _map_chunk_handlers,
00433   _misc_chunk_handlers,
00434   _name_chunk_handlers,
00435   _cheat_chunk_handlers,
00436   _setting_chunk_handlers,
00437   _veh_chunk_handlers,
00438   _waypoint_chunk_handlers,
00439   _depot_chunk_handlers,
00440   _order_chunk_handlers,
00441   _industry_chunk_handlers,
00442   _economy_chunk_handlers,
00443   _subsidy_chunk_handlers,
00444   _cargomonitor_chunk_handlers,
00445   _goal_chunk_handlers,
00446   _engine_chunk_handlers,
00447   _town_chunk_handlers,
00448   _sign_chunk_handlers,
00449   _station_chunk_handlers,
00450   _company_chunk_handlers,
00451   _ai_chunk_handlers,
00452   _game_chunk_handlers,
00453   _animated_tile_chunk_handlers,
00454   _newgrf_chunk_handlers,
00455   _group_chunk_handlers,
00456   _cargopacket_chunk_handlers,
00457   _autoreplace_chunk_handlers,
00458   _labelmaps_chunk_handlers,
00459   _airport_chunk_handlers,
00460   _object_chunk_handlers,
00461   _persistent_storage_chunk_handlers,
00462   NULL,
00463 };
00464 
00469 #define FOR_ALL_CHUNK_HANDLERS(ch) \
00470   for (const ChunkHandler * const *chsc = _chunk_handlers; *chsc != NULL; chsc++) \
00471     for (const ChunkHandler *ch = *chsc; ch != NULL; ch = (ch->flags & CH_LAST) ? NULL : ch + 1)
00472 
00474 static void SlNullPointers()
00475 {
00476   _sl.action = SLA_NULL;
00477 
00478   /* We don't want any savegame conversion code to run
00479    * during NULLing; especially those that try to get
00480    * pointers from other pools. */
00481   _sl_version = SAVEGAME_VERSION;
00482 
00483   DEBUG(sl, 1, "Nulling pointers");
00484 
00485   FOR_ALL_CHUNK_HANDLERS(ch) {
00486     if (ch->ptrs_proc != NULL) {
00487       DEBUG(sl, 2, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
00488       ch->ptrs_proc();
00489     }
00490   }
00491 
00492   DEBUG(sl, 1, "All pointers nulled");
00493 
00494   assert(_sl.action == SLA_NULL);
00495 }
00496 
00505 void NORETURN SlError(StringID string, const char *extra_msg)
00506 {
00507   /* Distinguish between loading into _load_check_data vs. normal save/load. */
00508   if (_sl.action == SLA_LOAD_CHECK) {
00509     _load_check_data.error = string;
00510     free(_load_check_data.error_data);
00511     _load_check_data.error_data = (extra_msg == NULL) ? NULL : strdup(extra_msg);
00512   } else {
00513     _sl.error_str = string;
00514     free(_sl.extra_msg);
00515     _sl.extra_msg = (extra_msg == NULL) ? NULL : strdup(extra_msg);
00516   }
00517 
00518   /* We have to NULL all pointers here; we might be in a state where
00519    * the pointers are actually filled with indices, which means that
00520    * when we access them during cleaning the pool dereferences of
00521    * those indices will be made with segmentation faults as result. */
00522   if (_sl.action == SLA_LOAD || _sl.action == SLA_PTRS) SlNullPointers();
00523   throw std::exception();
00524 }
00525 
00533 void NORETURN SlErrorCorrupt(const char *msg)
00534 {
00535   SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
00536 }
00537 
00538 
00539 typedef void (*AsyncSaveFinishProc)();                
00540 static AsyncSaveFinishProc _async_save_finish = NULL; 
00541 static ThreadObject *_save_thread;                    
00542 
00547 static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
00548 {
00549   if (_exit_game) return;
00550   while (_async_save_finish != NULL) CSleep(10);
00551 
00552   _async_save_finish = proc;
00553 }
00554 
00558 void ProcessAsyncSaveFinish()
00559 {
00560   if (_async_save_finish == NULL) return;
00561 
00562   _async_save_finish();
00563 
00564   _async_save_finish = NULL;
00565 
00566   if (_save_thread != NULL) {
00567     _save_thread->Join();
00568     delete _save_thread;
00569     _save_thread = NULL;
00570   }
00571 }
00572 
00577 byte SlReadByte()
00578 {
00579   return _sl.reader->ReadByte();
00580 }
00581 
00586 void SlWriteByte(byte b)
00587 {
00588   _sl.dumper->WriteByte(b);
00589 }
00590 
00591 static inline int SlReadUint16()
00592 {
00593   int x = SlReadByte() << 8;
00594   return x | SlReadByte();
00595 }
00596 
00597 static inline uint32 SlReadUint32()
00598 {
00599   uint32 x = SlReadUint16() << 16;
00600   return x | SlReadUint16();
00601 }
00602 
00603 static inline uint64 SlReadUint64()
00604 {
00605   uint32 x = SlReadUint32();
00606   uint32 y = SlReadUint32();
00607   return (uint64)x << 32 | y;
00608 }
00609 
00610 static inline void SlWriteUint16(uint16 v)
00611 {
00612   SlWriteByte(GB(v, 8, 8));
00613   SlWriteByte(GB(v, 0, 8));
00614 }
00615 
00616 static inline void SlWriteUint32(uint32 v)
00617 {
00618   SlWriteUint16(GB(v, 16, 16));
00619   SlWriteUint16(GB(v,  0, 16));
00620 }
00621 
00622 static inline void SlWriteUint64(uint64 x)
00623 {
00624   SlWriteUint32((uint32)(x >> 32));
00625   SlWriteUint32((uint32)x);
00626 }
00627 
00633 static inline void SlSkipBytes(size_t length)
00634 {
00635   for (; length != 0; length--) SlReadByte();
00636 }
00637 
00647 static uint SlReadSimpleGamma()
00648 {
00649   uint i = SlReadByte();
00650   if (HasBit(i, 7)) {
00651     i &= ~0x80;
00652     if (HasBit(i, 6)) {
00653       i &= ~0x40;
00654       if (HasBit(i, 5)) {
00655         i &= ~0x20;
00656         if (HasBit(i, 4)) {
00657           SlErrorCorrupt("Unsupported gamma");
00658         }
00659         i = (i << 8) | SlReadByte();
00660       }
00661       i = (i << 8) | SlReadByte();
00662     }
00663     i = (i << 8) | SlReadByte();
00664   }
00665   return i;
00666 }
00667 
00680 static void SlWriteSimpleGamma(size_t i)
00681 {
00682   if (i >= (1 << 7)) {
00683     if (i >= (1 << 14)) {
00684       if (i >= (1 << 21)) {
00685         assert(i < (1 << 28));
00686         SlWriteByte((byte)(0xE0 | (i >> 24)));
00687         SlWriteByte((byte)(i >> 16));
00688       } else {
00689         SlWriteByte((byte)(0xC0 | (i >> 16)));
00690       }
00691       SlWriteByte((byte)(i >> 8));
00692     } else {
00693       SlWriteByte((byte)(0x80 | (i >> 8)));
00694     }
00695   }
00696   SlWriteByte((byte)i);
00697 }
00698 
00700 static inline uint SlGetGammaLength(size_t i)
00701 {
00702   return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21));
00703 }
00704 
00705 static inline uint SlReadSparseIndex()
00706 {
00707   return SlReadSimpleGamma();
00708 }
00709 
00710 static inline void SlWriteSparseIndex(uint index)
00711 {
00712   SlWriteSimpleGamma(index);
00713 }
00714 
00715 static inline uint SlReadArrayLength()
00716 {
00717   return SlReadSimpleGamma();
00718 }
00719 
00720 static inline void SlWriteArrayLength(size_t length)
00721 {
00722   SlWriteSimpleGamma(length);
00723 }
00724 
00725 static inline uint SlGetArrayLength(size_t length)
00726 {
00727   return SlGetGammaLength(length);
00728 }
00729 
00736 static inline uint SlCalcConvMemLen(VarType conv)
00737 {
00738   static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
00739   byte length = GB(conv, 4, 4);
00740 
00741   switch (length << 4) {
00742     case SLE_VAR_STRB:
00743     case SLE_VAR_STRBQ:
00744     case SLE_VAR_STR:
00745     case SLE_VAR_STRQ:
00746       return SlReadArrayLength();
00747 
00748     default:
00749       assert(length < lengthof(conv_mem_size));
00750       return conv_mem_size[length];
00751   }
00752 }
00753 
00760 static inline byte SlCalcConvFileLen(VarType conv)
00761 {
00762   static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
00763   byte length = GB(conv, 0, 4);
00764   assert(length < lengthof(conv_file_size));
00765   return conv_file_size[length];
00766 }
00767 
00769 static inline size_t SlCalcRefLen()
00770 {
00771   return IsSavegameVersionBefore(69) ? 2 : 4;
00772 }
00773 
00774 void SlSetArrayIndex(uint index)
00775 {
00776   _sl.need_length = NL_WANTLENGTH;
00777   _sl.array_index = index;
00778 }
00779 
00780 static size_t _next_offs;
00781 
00786 int SlIterateArray()
00787 {
00788   int index;
00789 
00790   /* After reading in the whole array inside the loop
00791    * we must have read in all the data, so we must be at end of current block. */
00792   if (_next_offs != 0 && _sl.reader->GetSize() != _next_offs) SlErrorCorrupt("Invalid chunk size");
00793 
00794   for (;;) {
00795     uint length = SlReadArrayLength();
00796     if (length == 0) {
00797       _next_offs = 0;
00798       return -1;
00799     }
00800 
00801     _sl.obj_len = --length;
00802     _next_offs = _sl.reader->GetSize() + length;
00803 
00804     switch (_sl.block_mode) {
00805       case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
00806       case CH_ARRAY:        index = _sl.array_index++; break;
00807       default:
00808         DEBUG(sl, 0, "SlIterateArray error");
00809         return -1; // error
00810     }
00811 
00812     if (length != 0) return index;
00813   }
00814 }
00815 
00819 void SlSkipArray()
00820 {
00821   while (SlIterateArray() != -1) {
00822     SlSkipBytes(_next_offs - _sl.reader->GetSize());
00823   }
00824 }
00825 
00831 void SlSetLength(size_t length)
00832 {
00833   assert(_sl.action == SLA_SAVE);
00834 
00835   switch (_sl.need_length) {
00836     case NL_WANTLENGTH:
00837       _sl.need_length = NL_NONE;
00838       switch (_sl.block_mode) {
00839         case CH_RIFF:
00840           /* Ugly encoding of >16M RIFF chunks
00841            * The lower 24 bits are normal
00842            * The uppermost 4 bits are bits 24:27 */
00843           assert(length < (1 << 28));
00844           SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
00845           break;
00846         case CH_ARRAY:
00847           assert(_sl.last_array_index <= _sl.array_index);
00848           while (++_sl.last_array_index <= _sl.array_index) {
00849             SlWriteArrayLength(1);
00850           }
00851           SlWriteArrayLength(length + 1);
00852           break;
00853         case CH_SPARSE_ARRAY:
00854           SlWriteArrayLength(length + 1 + SlGetArrayLength(_sl.array_index)); // Also include length of sparse index.
00855           SlWriteSparseIndex(_sl.array_index);
00856           break;
00857         default: NOT_REACHED();
00858       }
00859       break;
00860 
00861     case NL_CALCLENGTH:
00862       _sl.obj_len += (int)length;
00863       break;
00864 
00865     default: NOT_REACHED();
00866   }
00867 }
00868 
00875 static void SlCopyBytes(void *ptr, size_t length)
00876 {
00877   byte *p = (byte *)ptr;
00878 
00879   switch (_sl.action) {
00880     case SLA_LOAD_CHECK:
00881     case SLA_LOAD:
00882       for (; length != 0; length--) *p++ = SlReadByte();
00883       break;
00884     case SLA_SAVE:
00885       for (; length != 0; length--) SlWriteByte(*p++);
00886       break;
00887     default: NOT_REACHED();
00888   }
00889 }
00890 
00892 size_t SlGetFieldLength()
00893 {
00894   return _sl.obj_len;
00895 }
00896 
00904 int64 ReadValue(const void *ptr, VarType conv)
00905 {
00906   switch (GetVarMemType(conv)) {
00907     case SLE_VAR_BL:  return (*(const bool *)ptr != 0);
00908     case SLE_VAR_I8:  return *(const int8  *)ptr;
00909     case SLE_VAR_U8:  return *(const byte  *)ptr;
00910     case SLE_VAR_I16: return *(const int16 *)ptr;
00911     case SLE_VAR_U16: return *(const uint16*)ptr;
00912     case SLE_VAR_I32: return *(const int32 *)ptr;
00913     case SLE_VAR_U32: return *(const uint32*)ptr;
00914     case SLE_VAR_I64: return *(const int64 *)ptr;
00915     case SLE_VAR_U64: return *(const uint64*)ptr;
00916     case SLE_VAR_NULL:return 0;
00917     default: NOT_REACHED();
00918   }
00919 }
00920 
00928 void WriteValue(void *ptr, VarType conv, int64 val)
00929 {
00930   switch (GetVarMemType(conv)) {
00931     case SLE_VAR_BL:  *(bool  *)ptr = (val != 0);  break;
00932     case SLE_VAR_I8:  *(int8  *)ptr = val; break;
00933     case SLE_VAR_U8:  *(byte  *)ptr = val; break;
00934     case SLE_VAR_I16: *(int16 *)ptr = val; break;
00935     case SLE_VAR_U16: *(uint16*)ptr = val; break;
00936     case SLE_VAR_I32: *(int32 *)ptr = val; break;
00937     case SLE_VAR_U32: *(uint32*)ptr = val; break;
00938     case SLE_VAR_I64: *(int64 *)ptr = val; break;
00939     case SLE_VAR_U64: *(uint64*)ptr = val; break;
00940     case SLE_VAR_NAME: *(char**)ptr = CopyFromOldName(val); break;
00941     case SLE_VAR_NULL: break;
00942     default: NOT_REACHED();
00943   }
00944 }
00945 
00954 static void SlSaveLoadConv(void *ptr, VarType conv)
00955 {
00956   switch (_sl.action) {
00957     case SLA_SAVE: {
00958       int64 x = ReadValue(ptr, conv);
00959 
00960       /* Write the value to the file and check if its value is in the desired range */
00961       switch (GetVarFileType(conv)) {
00962         case SLE_FILE_I8: assert(x >= -128 && x <= 127);     SlWriteByte(x);break;
00963         case SLE_FILE_U8: assert(x >= 0 && x <= 255);        SlWriteByte(x);break;
00964         case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break;
00965         case SLE_FILE_STRINGID:
00966         case SLE_FILE_U16:assert(x >= 0 && x <= 65535);      SlWriteUint16(x);break;
00967         case SLE_FILE_I32:
00968         case SLE_FILE_U32:                                   SlWriteUint32((uint32)x);break;
00969         case SLE_FILE_I64:
00970         case SLE_FILE_U64:                                   SlWriteUint64(x);break;
00971         default: NOT_REACHED();
00972       }
00973       break;
00974     }
00975     case SLA_LOAD_CHECK:
00976     case SLA_LOAD: {
00977       int64 x;
00978       /* Read a value from the file */
00979       switch (GetVarFileType(conv)) {
00980         case SLE_FILE_I8:  x = (int8  )SlReadByte();   break;
00981         case SLE_FILE_U8:  x = (byte  )SlReadByte();   break;
00982         case SLE_FILE_I16: x = (int16 )SlReadUint16(); break;
00983         case SLE_FILE_U16: x = (uint16)SlReadUint16(); break;
00984         case SLE_FILE_I32: x = (int32 )SlReadUint32(); break;
00985         case SLE_FILE_U32: x = (uint32)SlReadUint32(); break;
00986         case SLE_FILE_I64: x = (int64 )SlReadUint64(); break;
00987         case SLE_FILE_U64: x = (uint64)SlReadUint64(); break;
00988         case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break;
00989         default: NOT_REACHED();
00990       }
00991 
00992       /* Write The value to the struct. These ARE endian safe. */
00993       WriteValue(ptr, conv, x);
00994       break;
00995     }
00996     case SLA_PTRS: break;
00997     case SLA_NULL: break;
00998     default: NOT_REACHED();
00999   }
01000 }
01001 
01011 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
01012 {
01013   if (ptr == NULL) return 0;
01014   return min(strlen(ptr), length - 1);
01015 }
01016 
01026 static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
01027 {
01028   size_t len;
01029   const char *str;
01030 
01031   switch (GetVarMemType(conv)) {
01032     default: NOT_REACHED();
01033     case SLE_VAR_STR:
01034     case SLE_VAR_STRQ:
01035       str = *(const char * const *)ptr;
01036       len = SIZE_MAX;
01037       break;
01038     case SLE_VAR_STRB:
01039     case SLE_VAR_STRBQ:
01040       str = (const char *)ptr;
01041       len = length;
01042       break;
01043   }
01044 
01045   len = SlCalcNetStringLen(str, len);
01046   return len + SlGetArrayLength(len); // also include the length of the index
01047 }
01048 
01055 static void SlString(void *ptr, size_t length, VarType conv)
01056 {
01057   switch (_sl.action) {
01058     case SLA_SAVE: {
01059       size_t len;
01060       switch (GetVarMemType(conv)) {
01061         default: NOT_REACHED();
01062         case SLE_VAR_STRB:
01063         case SLE_VAR_STRBQ:
01064           len = SlCalcNetStringLen((char *)ptr, length);
01065           break;
01066         case SLE_VAR_STR:
01067         case SLE_VAR_STRQ:
01068           ptr = *(char **)ptr;
01069           len = SlCalcNetStringLen((char *)ptr, SIZE_MAX);
01070           break;
01071       }
01072 
01073       SlWriteArrayLength(len);
01074       SlCopyBytes(ptr, len);
01075       break;
01076     }
01077     case SLA_LOAD_CHECK:
01078     case SLA_LOAD: {
01079       size_t len = SlReadArrayLength();
01080 
01081       switch (GetVarMemType(conv)) {
01082         default: NOT_REACHED();
01083         case SLE_VAR_STRB:
01084         case SLE_VAR_STRBQ:
01085           if (len >= length) {
01086             DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
01087             SlCopyBytes(ptr, length);
01088             SlSkipBytes(len - length);
01089             len = length - 1;
01090           } else {
01091             SlCopyBytes(ptr, len);
01092           }
01093           break;
01094         case SLE_VAR_STR:
01095         case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate
01096           free(*(char **)ptr);
01097           if (len == 0) {
01098             *(char **)ptr = NULL;
01099             return;
01100           } else {
01101             *(char **)ptr = MallocT<char>(len + 1); // terminating '\0'
01102             ptr = *(char **)ptr;
01103             SlCopyBytes(ptr, len);
01104           }
01105           break;
01106       }
01107 
01108       ((char *)ptr)[len] = '\0'; // properly terminate the string
01109       StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK;
01110       if ((conv & SLF_ALLOW_CONTROL) != 0) {
01111         settings = settings | SVS_ALLOW_CONTROL_CODE;
01112         if (IsSavegameVersionBefore(169)) {
01113           str_fix_scc_encoded((char *)ptr, (char *)ptr + len);
01114         }
01115       }
01116       if ((conv & SLF_ALLOW_NEWLINE) != 0) {
01117         settings = settings | SVS_ALLOW_NEWLINE;
01118       }
01119       str_validate((char *)ptr, (char *)ptr + len, settings);
01120       break;
01121     }
01122     case SLA_PTRS: break;
01123     case SLA_NULL: break;
01124     default: NOT_REACHED();
01125   }
01126 }
01127 
01133 static inline size_t SlCalcArrayLen(size_t length, VarType conv)
01134 {
01135   return SlCalcConvFileLen(conv) * length;
01136 }
01137 
01144 void SlArray(void *array, size_t length, VarType conv)
01145 {
01146   if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
01147 
01148   /* Automatically calculate the length? */
01149   if (_sl.need_length != NL_NONE) {
01150     SlSetLength(SlCalcArrayLen(length, conv));
01151     /* Determine length only? */
01152     if (_sl.need_length == NL_CALCLENGTH) return;
01153   }
01154 
01155   /* NOTICE - handle some buggy stuff, in really old versions everything was saved
01156    * as a byte-type. So detect this, and adjust array size accordingly */
01157   if (_sl.action != SLA_SAVE && _sl_version == 0) {
01158     /* all arrays except difficulty settings */
01159     if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
01160         conv == SLE_INT32 || conv == SLE_UINT32) {
01161       SlCopyBytes(array, length * SlCalcConvFileLen(conv));
01162       return;
01163     }
01164     /* used for conversion of Money 32bit->64bit */
01165     if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
01166       for (uint i = 0; i < length; i++) {
01167         ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
01168       }
01169       return;
01170     }
01171   }
01172 
01173   /* If the size of elements is 1 byte both in file and memory, no special
01174    * conversion is needed, use specialized copy-copy function to speed up things */
01175   if (conv == SLE_INT8 || conv == SLE_UINT8) {
01176     SlCopyBytes(array, length);
01177   } else {
01178     byte *a = (byte*)array;
01179     byte mem_size = SlCalcConvMemLen(conv);
01180 
01181     for (; length != 0; length --) {
01182       SlSaveLoadConv(a, conv);
01183       a += mem_size; // get size
01184     }
01185   }
01186 }
01187 
01188 
01199 static size_t ReferenceToInt(const void *obj, SLRefType rt)
01200 {
01201   assert(_sl.action == SLA_SAVE);
01202 
01203   if (obj == NULL) return 0;
01204 
01205   switch (rt) {
01206     case REF_VEHICLE_OLD: // Old vehicles we save as new onces
01207     case REF_VEHICLE:   return ((const  Vehicle*)obj)->index + 1;
01208     case REF_STATION:   return ((const  Station*)obj)->index + 1;
01209     case REF_TOWN:      return ((const     Town*)obj)->index + 1;
01210     case REF_ORDER:     return ((const    Order*)obj)->index + 1;
01211     case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
01212     case REF_ENGINE_RENEWS: return ((const       EngineRenew*)obj)->index + 1;
01213     case REF_CARGO_PACKET:  return ((const       CargoPacket*)obj)->index + 1;
01214     case REF_ORDERLIST:     return ((const         OrderList*)obj)->index + 1;
01215     case REF_STORAGE:       return ((const PersistentStorage*)obj)->index + 1;
01216     default: NOT_REACHED();
01217   }
01218 }
01219 
01230 static void *IntToReference(size_t index, SLRefType rt)
01231 {
01232   assert_compile(sizeof(size_t) <= sizeof(void *));
01233 
01234   assert(_sl.action == SLA_PTRS);
01235 
01236   /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE,
01237    * and should be loaded like that */
01238   if (rt == REF_VEHICLE_OLD && !IsSavegameVersionBefore(4, 4)) {
01239     rt = REF_VEHICLE;
01240   }
01241 
01242   /* No need to look up NULL pointers, just return immediately */
01243   if (index == (rt == REF_VEHICLE_OLD ? 0xFFFF : 0)) return NULL;
01244 
01245   /* Correct index. Old vehicles were saved differently:
01246    * invalid vehicle was 0xFFFF, now we use 0x0000 for everything invalid. */
01247   if (rt != REF_VEHICLE_OLD) index--;
01248 
01249   switch (rt) {
01250     case REF_ORDERLIST:
01251       if (OrderList::IsValidID(index)) return OrderList::Get(index);
01252       SlErrorCorrupt("Referencing invalid OrderList");
01253 
01254     case REF_ORDER:
01255       if (Order::IsValidID(index)) return Order::Get(index);
01256       /* in old versions, invalid order was used to mark end of order list */
01257       if (IsSavegameVersionBefore(5, 2)) return NULL;
01258       SlErrorCorrupt("Referencing invalid Order");
01259 
01260     case REF_VEHICLE_OLD:
01261     case REF_VEHICLE:
01262       if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
01263       SlErrorCorrupt("Referencing invalid Vehicle");
01264 
01265     case REF_STATION:
01266       if (Station::IsValidID(index)) return Station::Get(index);
01267       SlErrorCorrupt("Referencing invalid Station");
01268 
01269     case REF_TOWN:
01270       if (Town::IsValidID(index)) return Town::Get(index);
01271       SlErrorCorrupt("Referencing invalid Town");
01272 
01273     case REF_ROADSTOPS:
01274       if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
01275       SlErrorCorrupt("Referencing invalid RoadStop");
01276 
01277     case REF_ENGINE_RENEWS:
01278       if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
01279       SlErrorCorrupt("Referencing invalid EngineRenew");
01280 
01281     case REF_CARGO_PACKET:
01282       if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
01283       SlErrorCorrupt("Referencing invalid CargoPacket");
01284 
01285     case REF_STORAGE:
01286       if (PersistentStorage::IsValidID(index)) return PersistentStorage::Get(index);
01287       SlErrorCorrupt("Referencing invalid PersistentStorage");
01288 
01289     default: NOT_REACHED();
01290   }
01291 }
01292 
01297 static inline size_t SlCalcListLen(const void *list)
01298 {
01299   const std::list<void *> *l = (const std::list<void *> *) list;
01300 
01301   int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
01302   /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
01303    * of the list */
01304   return l->size() * type_size + type_size;
01305 }
01306 
01307 
01313 static void SlList(void *list, SLRefType conv)
01314 {
01315   /* Automatically calculate the length? */
01316   if (_sl.need_length != NL_NONE) {
01317     SlSetLength(SlCalcListLen(list));
01318     /* Determine length only? */
01319     if (_sl.need_length == NL_CALCLENGTH) return;
01320   }
01321 
01322   typedef std::list<void *> PtrList;
01323   PtrList *l = (PtrList *)list;
01324 
01325   switch (_sl.action) {
01326     case SLA_SAVE: {
01327       SlWriteUint32((uint32)l->size());
01328 
01329       PtrList::iterator iter;
01330       for (iter = l->begin(); iter != l->end(); ++iter) {
01331         void *ptr = *iter;
01332         SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
01333       }
01334       break;
01335     }
01336     case SLA_LOAD_CHECK:
01337     case SLA_LOAD: {
01338       size_t length = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01339 
01340       /* Load each reference and push to the end of the list */
01341       for (size_t i = 0; i < length; i++) {
01342         size_t data = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01343         l->push_back((void *)data);
01344       }
01345       break;
01346     }
01347     case SLA_PTRS: {
01348       PtrList temp = *l;
01349 
01350       l->clear();
01351       PtrList::iterator iter;
01352       for (iter = temp.begin(); iter != temp.end(); ++iter) {
01353         void *ptr = IntToReference((size_t)*iter, conv);
01354         l->push_back(ptr);
01355       }
01356       break;
01357     }
01358     case SLA_NULL:
01359       l->clear();
01360       break;
01361     default: NOT_REACHED();
01362   }
01363 }
01364 
01365 
01367 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
01368 {
01369   if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
01370   if (sld->conv & SLF_NOT_IN_SAVE) return false;
01371 
01372   return true;
01373 }
01374 
01380 static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
01381 {
01382   if ((sld->conv & SLF_NO_NETWORK_SYNC) && _sl.action != SLA_SAVE && _networking && !_network_server) {
01383     SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
01384     return true;
01385   }
01386 
01387   return false;
01388 }
01389 
01396 size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
01397 {
01398   size_t length = 0;
01399 
01400   /* Need to determine the length and write a length tag. */
01401   for (; sld->cmd != SL_END; sld++) {
01402     length += SlCalcObjMemberLength(object, sld);
01403   }
01404   return length;
01405 }
01406 
01407 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
01408 {
01409   assert(_sl.action == SLA_SAVE);
01410 
01411   switch (sld->cmd) {
01412     case SL_VAR:
01413     case SL_REF:
01414     case SL_ARR:
01415     case SL_STR:
01416     case SL_LST:
01417       /* CONDITIONAL saveload types depend on the savegame version */
01418       if (!SlIsObjectValidInSavegame(sld)) break;
01419 
01420       switch (sld->cmd) {
01421         case SL_VAR: return SlCalcConvFileLen(sld->conv);
01422         case SL_REF: return SlCalcRefLen();
01423         case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
01424         case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
01425         case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
01426         default: NOT_REACHED();
01427       }
01428       break;
01429     case SL_WRITEBYTE: return 1; // a byte is logically of size 1
01430     case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
01431     case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
01432     default: NOT_REACHED();
01433   }
01434   return 0;
01435 }
01436 
01437 
01438 bool SlObjectMember(void *ptr, const SaveLoad *sld)
01439 {
01440   VarType conv = GB(sld->conv, 0, 8);
01441   switch (sld->cmd) {
01442     case SL_VAR:
01443     case SL_REF:
01444     case SL_ARR:
01445     case SL_STR:
01446     case SL_LST:
01447       /* CONDITIONAL saveload types depend on the savegame version */
01448       if (!SlIsObjectValidInSavegame(sld)) return false;
01449       if (SlSkipVariableOnLoad(sld)) return false;
01450 
01451       switch (sld->cmd) {
01452         case SL_VAR: SlSaveLoadConv(ptr, conv); break;
01453         case SL_REF: // Reference variable, translate
01454           switch (_sl.action) {
01455             case SLA_SAVE:
01456               SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv));
01457               break;
01458             case SLA_LOAD_CHECK:
01459             case SLA_LOAD:
01460               *(size_t *)ptr = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01461               break;
01462             case SLA_PTRS:
01463               *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv);
01464               break;
01465             case SLA_NULL:
01466               *(void **)ptr = NULL;
01467               break;
01468             default: NOT_REACHED();
01469           }
01470           break;
01471         case SL_ARR: SlArray(ptr, sld->length, conv); break;
01472         case SL_STR: SlString(ptr, sld->length, sld->conv); break;
01473         case SL_LST: SlList(ptr, (SLRefType)conv); break;
01474         default: NOT_REACHED();
01475       }
01476       break;
01477 
01478     /* SL_WRITEBYTE translates a value of a variable to another one upon
01479      * saving or loading.
01480      * XXX - variable renaming abuse
01481      * game_value: the value of the variable ingame is abused by sld->version_from
01482      * file_value: the value of the variable in the savegame is abused by sld->version_to */
01483     case SL_WRITEBYTE:
01484       switch (_sl.action) {
01485         case SLA_SAVE: SlWriteByte(sld->version_to); break;
01486         case SLA_LOAD_CHECK:
01487         case SLA_LOAD: *(byte *)ptr = sld->version_from; break;
01488         case SLA_PTRS: break;
01489         case SLA_NULL: break;
01490         default: NOT_REACHED();
01491       }
01492       break;
01493 
01494     /* SL_VEH_INCLUDE loads common code for vehicles */
01495     case SL_VEH_INCLUDE:
01496       SlObject(ptr, GetVehicleDescription(VEH_END));
01497       break;
01498 
01499     case SL_ST_INCLUDE:
01500       SlObject(ptr, GetBaseStationDescription());
01501       break;
01502 
01503     default: NOT_REACHED();
01504   }
01505   return true;
01506 }
01507 
01513 void SlObject(void *object, const SaveLoad *sld)
01514 {
01515   /* Automatically calculate the length? */
01516   if (_sl.need_length != NL_NONE) {
01517     SlSetLength(SlCalcObjLength(object, sld));
01518     if (_sl.need_length == NL_CALCLENGTH) return;
01519   }
01520 
01521   for (; sld->cmd != SL_END; sld++) {
01522     void *ptr = sld->global ? sld->address : GetVariableAddress(object, sld);
01523     SlObjectMember(ptr, sld);
01524   }
01525 }
01526 
01531 void SlGlobList(const SaveLoadGlobVarList *sldg)
01532 {
01533   SlObject(NULL, (const SaveLoad*)sldg);
01534 }
01535 
01541 void SlAutolength(AutolengthProc *proc, void *arg)
01542 {
01543   size_t offs;
01544 
01545   assert(_sl.action == SLA_SAVE);
01546 
01547   /* Tell it to calculate the length */
01548   _sl.need_length = NL_CALCLENGTH;
01549   _sl.obj_len = 0;
01550   proc(arg);
01551 
01552   /* Setup length */
01553   _sl.need_length = NL_WANTLENGTH;
01554   SlSetLength(_sl.obj_len);
01555 
01556   offs = _sl.dumper->GetSize() + _sl.obj_len;
01557 
01558   /* And write the stuff */
01559   proc(arg);
01560 
01561   if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
01562 }
01563 
01568 static void SlLoadChunk(const ChunkHandler *ch)
01569 {
01570   byte m = SlReadByte();
01571   size_t len;
01572   size_t endoffs;
01573 
01574   _sl.block_mode = m;
01575   _sl.obj_len = 0;
01576 
01577   switch (m) {
01578     case CH_ARRAY:
01579       _sl.array_index = 0;
01580       ch->load_proc();
01581       break;
01582     case CH_SPARSE_ARRAY:
01583       ch->load_proc();
01584       break;
01585     default:
01586       if ((m & 0xF) == CH_RIFF) {
01587         /* Read length */
01588         len = (SlReadByte() << 16) | ((m >> 4) << 24);
01589         len += SlReadUint16();
01590         _sl.obj_len = len;
01591         endoffs = _sl.reader->GetSize() + len;
01592         ch->load_proc();
01593         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
01594       } else {
01595         SlErrorCorrupt("Invalid chunk type");
01596       }
01597       break;
01598   }
01599 }
01600 
01606 static void SlLoadCheckChunk(const ChunkHandler *ch)
01607 {
01608   byte m = SlReadByte();
01609   size_t len;
01610   size_t endoffs;
01611 
01612   _sl.block_mode = m;
01613   _sl.obj_len = 0;
01614 
01615   switch (m) {
01616     case CH_ARRAY:
01617       _sl.array_index = 0;
01618       if (ch->load_check_proc) {
01619         ch->load_check_proc();
01620       } else {
01621         SlSkipArray();
01622       }
01623       break;
01624     case CH_SPARSE_ARRAY:
01625       if (ch->load_check_proc) {
01626         ch->load_check_proc();
01627       } else {
01628         SlSkipArray();
01629       }
01630       break;
01631     default:
01632       if ((m & 0xF) == CH_RIFF) {
01633         /* Read length */
01634         len = (SlReadByte() << 16) | ((m >> 4) << 24);
01635         len += SlReadUint16();
01636         _sl.obj_len = len;
01637         endoffs = _sl.reader->GetSize() + len;
01638         if (ch->load_check_proc) {
01639           ch->load_check_proc();
01640         } else {
01641           SlSkipBytes(len);
01642         }
01643         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
01644       } else {
01645         SlErrorCorrupt("Invalid chunk type");
01646       }
01647       break;
01648   }
01649 }
01650 
01655 static ChunkSaveLoadProc *_stub_save_proc;
01656 
01662 static inline void SlStubSaveProc2(void *arg)
01663 {
01664   _stub_save_proc();
01665 }
01666 
01672 static void SlStubSaveProc()
01673 {
01674   SlAutolength(SlStubSaveProc2, NULL);
01675 }
01676 
01682 static void SlSaveChunk(const ChunkHandler *ch)
01683 {
01684   ChunkSaveLoadProc *proc = ch->save_proc;
01685 
01686   /* Don't save any chunk information if there is no save handler. */
01687   if (proc == NULL) return;
01688 
01689   SlWriteUint32(ch->id);
01690   DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
01691 
01692   if (ch->flags & CH_AUTO_LENGTH) {
01693     /* Need to calculate the length. Solve that by calling SlAutoLength in the save_proc. */
01694     _stub_save_proc = proc;
01695     proc = SlStubSaveProc;
01696   }
01697 
01698   _sl.block_mode = ch->flags & CH_TYPE_MASK;
01699   switch (ch->flags & CH_TYPE_MASK) {
01700     case CH_RIFF:
01701       _sl.need_length = NL_WANTLENGTH;
01702       proc();
01703       break;
01704     case CH_ARRAY:
01705       _sl.last_array_index = 0;
01706       SlWriteByte(CH_ARRAY);
01707       proc();
01708       SlWriteArrayLength(0); // Terminate arrays
01709       break;
01710     case CH_SPARSE_ARRAY:
01711       SlWriteByte(CH_SPARSE_ARRAY);
01712       proc();
01713       SlWriteArrayLength(0); // Terminate arrays
01714       break;
01715     default: NOT_REACHED();
01716   }
01717 }
01718 
01720 static void SlSaveChunks()
01721 {
01722   FOR_ALL_CHUNK_HANDLERS(ch) {
01723     SlSaveChunk(ch);
01724   }
01725 
01726   /* Terminator */
01727   SlWriteUint32(0);
01728 }
01729 
01736 static const ChunkHandler *SlFindChunkHandler(uint32 id)
01737 {
01738   FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch;
01739   return NULL;
01740 }
01741 
01743 static void SlLoadChunks()
01744 {
01745   uint32 id;
01746   const ChunkHandler *ch;
01747 
01748   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
01749     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
01750 
01751     ch = SlFindChunkHandler(id);
01752     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
01753     SlLoadChunk(ch);
01754   }
01755 }
01756 
01758 static void SlLoadCheckChunks()
01759 {
01760   uint32 id;
01761   const ChunkHandler *ch;
01762 
01763   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
01764     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
01765 
01766     ch = SlFindChunkHandler(id);
01767     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
01768     SlLoadCheckChunk(ch);
01769   }
01770 }
01771 
01773 static void SlFixPointers()
01774 {
01775   _sl.action = SLA_PTRS;
01776 
01777   DEBUG(sl, 1, "Fixing pointers");
01778 
01779   FOR_ALL_CHUNK_HANDLERS(ch) {
01780     if (ch->ptrs_proc != NULL) {
01781       DEBUG(sl, 2, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
01782       ch->ptrs_proc();
01783     }
01784   }
01785 
01786   DEBUG(sl, 1, "All pointers fixed");
01787 
01788   assert(_sl.action == SLA_PTRS);
01789 }
01790 
01791 
01793 struct FileReader : LoadFilter {
01794   FILE *file; 
01795   long begin; 
01796 
01801   FileReader(FILE *file) : LoadFilter(NULL), file(file), begin(ftell(file))
01802   {
01803   }
01804 
01806   ~FileReader()
01807   {
01808     if (this->file != NULL) fclose(this->file);
01809     this->file = NULL;
01810 
01811     /* Make sure we don't double free. */
01812     _sl.sf = NULL;
01813   }
01814 
01815   /* virtual */ size_t Read(byte *buf, size_t size)
01816   {
01817     /* We're in the process of shutting down, i.e. in "failure" mode. */
01818     if (this->file == NULL) return 0;
01819 
01820     return fread(buf, 1, size, this->file);
01821   }
01822 
01823   /* virtual */ void Reset()
01824   {
01825     clearerr(this->file);
01826     fseek(this->file, this->begin, SEEK_SET);
01827   }
01828 };
01829 
01831 struct FileWriter : SaveFilter {
01832   FILE *file; 
01833 
01838   FileWriter(FILE *file) : SaveFilter(NULL), file(file)
01839   {
01840   }
01841 
01843   ~FileWriter()
01844   {
01845     this->Finish();
01846 
01847     /* Make sure we don't double free. */
01848     _sl.sf = NULL;
01849   }
01850 
01851   /* virtual */ void Write(byte *buf, size_t size)
01852   {
01853     /* We're in the process of shutting down, i.e. in "failure" mode. */
01854     if (this->file == NULL) return;
01855 
01856     if (fwrite(buf, 1, size, this->file) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
01857   }
01858 
01859   /* virtual */ void Finish()
01860   {
01861     if (this->file != NULL) fclose(this->file);
01862     this->file = NULL;
01863   }
01864 };
01865 
01866 /*******************************************
01867  ********** START OF LZO CODE **************
01868  *******************************************/
01869 
01870 #ifdef WITH_LZO
01871 #include <lzo/lzo1x.h>
01872 
01874 static const uint LZO_BUFFER_SIZE = 8192;
01875 
01877 struct LZOLoadFilter : LoadFilter {
01882   LZOLoadFilter(LoadFilter *chain) : LoadFilter(chain)
01883   {
01884     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
01885   }
01886 
01887   /* virtual */ size_t Read(byte *buf, size_t ssize)
01888   {
01889     assert(ssize >= LZO_BUFFER_SIZE);
01890 
01891     /* Buffer size is from the LZO docs plus the chunk header size. */
01892     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
01893     uint32 tmp[2];
01894     uint32 size;
01895     lzo_uint len;
01896 
01897     /* Read header*/
01898     if (this->chain->Read((byte*)tmp, sizeof(tmp)) != sizeof(tmp)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE, "File read failed");
01899 
01900     /* Check if size is bad */
01901     ((uint32*)out)[0] = size = tmp[1];
01902 
01903     if (_sl_version != 0) {
01904       tmp[0] = TO_BE32(tmp[0]);
01905       size = TO_BE32(size);
01906     }
01907 
01908     if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size");
01909 
01910     /* Read block */
01911     if (this->chain->Read(out + sizeof(uint32), size) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
01912 
01913     /* Verify checksum */
01914     if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
01915 
01916     /* Decompress */
01917     lzo1x_decompress(out + sizeof(uint32) * 1, size, buf, &len, NULL);
01918     return len;
01919   }
01920 };
01921 
01923 struct LZOSaveFilter : SaveFilter {
01929   LZOSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
01930   {
01931     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
01932   }
01933 
01934   /* virtual */ void Write(byte *buf, size_t size)
01935   {
01936     const lzo_bytep in = buf;
01937     /* Buffer size is from the LZO docs plus the chunk header size. */
01938     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
01939     byte wrkmem[LZO1X_1_MEM_COMPRESS];
01940     lzo_uint outlen;
01941 
01942     do {
01943       /* Compress up to LZO_BUFFER_SIZE bytes at once. */
01944       lzo_uint len = size > LZO_BUFFER_SIZE ? LZO_BUFFER_SIZE : (lzo_uint)size;
01945       lzo1x_1_compress(in, len, out + sizeof(uint32) * 2, &outlen, wrkmem);
01946       ((uint32*)out)[1] = TO_BE32((uint32)outlen);
01947       ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
01948       this->chain->Write(out, outlen + sizeof(uint32) * 2);
01949 
01950       /* Move to next data chunk. */
01951       size -= len;
01952       in += len;
01953     } while (size > 0);
01954   }
01955 };
01956 
01957 #endif /* WITH_LZO */
01958 
01959 /*********************************************
01960  ******** START OF NOCOMP CODE (uncompressed)*
01961  *********************************************/
01962 
01964 struct NoCompLoadFilter : LoadFilter {
01969   NoCompLoadFilter(LoadFilter *chain) : LoadFilter(chain)
01970   {
01971   }
01972 
01973   /* virtual */ size_t Read(byte *buf, size_t size)
01974   {
01975     return this->chain->Read(buf, size);
01976   }
01977 };
01978 
01980 struct NoCompSaveFilter : SaveFilter {
01986   NoCompSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
01987   {
01988   }
01989 
01990   /* virtual */ void Write(byte *buf, size_t size)
01991   {
01992     this->chain->Write(buf, size);
01993   }
01994 };
01995 
01996 /********************************************
01997  ********** START OF ZLIB CODE **************
01998  ********************************************/
01999 
02000 #if defined(WITH_ZLIB)
02001 #include <zlib.h>
02002 
02004 struct ZlibLoadFilter : LoadFilter {
02005   z_stream z;                        
02006   byte fread_buf[MEMORY_CHUNK_SIZE]; 
02007 
02012   ZlibLoadFilter(LoadFilter *chain) : LoadFilter(chain)
02013   {
02014     memset(&this->z, 0, sizeof(this->z));
02015     if (inflateInit(&this->z) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
02016   }
02017 
02019   ~ZlibLoadFilter()
02020   {
02021     inflateEnd(&this->z);
02022   }
02023 
02024   /* virtual */ size_t Read(byte *buf, size_t size)
02025   {
02026     this->z.next_out  = buf;
02027     this->z.avail_out = (uint)size;
02028 
02029     do {
02030       /* read more bytes from the file? */
02031       if (this->z.avail_in == 0) {
02032         this->z.next_in = this->fread_buf;
02033         this->z.avail_in = (uint)this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
02034       }
02035 
02036       /* inflate the data */
02037       int r = inflate(&this->z, 0);
02038       if (r == Z_STREAM_END) break;
02039 
02040       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "inflate() failed");
02041     } while (this->z.avail_out != 0);
02042 
02043     return size - this->z.avail_out;
02044   }
02045 };
02046 
02048 struct ZlibSaveFilter : SaveFilter {
02049   z_stream z; 
02050 
02056   ZlibSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
02057   {
02058     memset(&this->z, 0, sizeof(this->z));
02059     if (deflateInit(&this->z, compression_level) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
02060   }
02061 
02063   ~ZlibSaveFilter()
02064   {
02065     deflateEnd(&this->z);
02066   }
02067 
02074   void WriteLoop(byte *p, size_t len, int mode)
02075   {
02076     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
02077     uint n;
02078     this->z.next_in = p;
02079     this->z.avail_in = (uInt)len;
02080     do {
02081       this->z.next_out = buf;
02082       this->z.avail_out = sizeof(buf);
02083 
02091       int r = deflate(&this->z, mode);
02092 
02093       /* bytes were emitted? */
02094       if ((n = sizeof(buf) - this->z.avail_out) != 0) {
02095         this->chain->Write(buf, n);
02096       }
02097       if (r == Z_STREAM_END) break;
02098 
02099       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code");
02100     } while (this->z.avail_in || !this->z.avail_out);
02101   }
02102 
02103   /* virtual */ void Write(byte *buf, size_t size)
02104   {
02105     this->WriteLoop(buf, size, 0);
02106   }
02107 
02108   /* virtual */ void Finish()
02109   {
02110     this->WriteLoop(NULL, 0, Z_FINISH);
02111     this->chain->Finish();
02112   }
02113 };
02114 
02115 #endif /* WITH_ZLIB */
02116 
02117 /********************************************
02118  ********** START OF LZMA CODE **************
02119  ********************************************/
02120 
02121 #if defined(WITH_LZMA)
02122 #include <lzma.h>
02123 
02130 static const lzma_stream _lzma_init = LZMA_STREAM_INIT;
02131 
02133 struct LZMALoadFilter : LoadFilter {
02134   lzma_stream lzma;                  
02135   byte fread_buf[MEMORY_CHUNK_SIZE]; 
02136 
02141   LZMALoadFilter(LoadFilter *chain) : LoadFilter(chain), lzma(_lzma_init)
02142   {
02143     /* Allow saves up to 256 MB uncompressed */
02144     if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
02145   }
02146 
02148   ~LZMALoadFilter()
02149   {
02150     lzma_end(&this->lzma);
02151   }
02152 
02153   /* virtual */ size_t Read(byte *buf, size_t size)
02154   {
02155     this->lzma.next_out  = buf;
02156     this->lzma.avail_out = size;
02157 
02158     do {
02159       /* read more bytes from the file? */
02160       if (this->lzma.avail_in == 0) {
02161         this->lzma.next_in  = this->fread_buf;
02162         this->lzma.avail_in = this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
02163       }
02164 
02165       /* inflate the data */
02166       lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
02167       if (r == LZMA_STREAM_END) break;
02168       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
02169     } while (this->lzma.avail_out != 0);
02170 
02171     return size - this->lzma.avail_out;
02172   }
02173 };
02174 
02176 struct LZMASaveFilter : SaveFilter {
02177   lzma_stream lzma; 
02178 
02184   LZMASaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain), lzma(_lzma_init)
02185   {
02186     if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
02187   }
02188 
02190   ~LZMASaveFilter()
02191   {
02192     lzma_end(&this->lzma);
02193   }
02194 
02201   void WriteLoop(byte *p, size_t len, lzma_action action)
02202   {
02203     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
02204     size_t n;
02205     this->lzma.next_in = p;
02206     this->lzma.avail_in = len;
02207     do {
02208       this->lzma.next_out = buf;
02209       this->lzma.avail_out = sizeof(buf);
02210 
02211       lzma_ret r = lzma_code(&this->lzma, action);
02212 
02213       /* bytes were emitted? */
02214       if ((n = sizeof(buf) - this->lzma.avail_out) != 0) {
02215         this->chain->Write(buf, n);
02216       }
02217       if (r == LZMA_STREAM_END) break;
02218       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
02219     } while (this->lzma.avail_in || !this->lzma.avail_out);
02220   }
02221 
02222   /* virtual */ void Write(byte *buf, size_t size)
02223   {
02224     this->WriteLoop(buf, size, LZMA_RUN);
02225   }
02226 
02227   /* virtual */ void Finish()
02228   {
02229     this->WriteLoop(NULL, 0, LZMA_FINISH);
02230     this->chain->Finish();
02231   }
02232 };
02233 
02234 #endif /* WITH_LZMA */
02235 
02236 /*******************************************
02237  ************* END OF CODE *****************
02238  *******************************************/
02239 
02241 struct SaveLoadFormat {
02242   const char *name;                     
02243   uint32 tag;                           
02244 
02245   LoadFilter *(*init_load)(LoadFilter *chain);                    
02246   SaveFilter *(*init_write)(SaveFilter *chain, byte compression); 
02247 
02248   byte min_compression;                 
02249   byte default_compression;             
02250   byte max_compression;                 
02251 };
02252 
02254 static const SaveLoadFormat _saveload_formats[] = {
02255 #if defined(WITH_LZO)
02256   /* Roughly 75% larger than zlib level 6 at only ~7% of the CPU usage. */
02257   {"lzo",    TO_BE32X('OTTD'), CreateLoadFilter<LZOLoadFilter>,    CreateSaveFilter<LZOSaveFilter>,    0, 0, 0},
02258 #else
02259   {"lzo",    TO_BE32X('OTTD'), NULL,                               NULL,                               0, 0, 0},
02260 #endif
02261   /* Roughly 5 times larger at only 1% of the CPU usage over zlib level 6. */
02262   {"none",   TO_BE32X('OTTN'), CreateLoadFilter<NoCompLoadFilter>, CreateSaveFilter<NoCompSaveFilter>, 0, 0, 0},
02263 #if defined(WITH_ZLIB)
02264   /* After level 6 the speed reduction is significant (1.5x to 2.5x slower per level), but the reduction in filesize is
02265    * fairly insignificant (~1% for each step). Lower levels become ~5-10% bigger by each level than level 6 while level
02266    * 1 is "only" 3 times as fast. Level 0 results in uncompressed savegames at about 8 times the cost of "none". */
02267   {"zlib",   TO_BE32X('OTTZ'), CreateLoadFilter<ZlibLoadFilter>,   CreateSaveFilter<ZlibSaveFilter>,   0, 6, 9},
02268 #else
02269   {"zlib",   TO_BE32X('OTTZ'), NULL,                               NULL,                               0, 0, 0},
02270 #endif
02271 #if defined(WITH_LZMA)
02272   /* Level 2 compression is speed wise as fast as zlib level 6 compression (old default), but results in ~10% smaller saves.
02273    * Higher compression levels are possible, and might improve savegame size by up to 25%, but are also up to 10 times slower.
02274    * The next significant reduction in file size is at level 4, but that is already 4 times slower. Level 3 is primarily 50%
02275    * slower while not improving the filesize, while level 0 and 1 are faster, but don't reduce savegame size much.
02276    * It's OTTX and not e.g. OTTL because liblzma is part of xz-utils and .tar.xz is prefered over .tar.lzma. */
02277   {"lzma",   TO_BE32X('OTTX'), CreateLoadFilter<LZMALoadFilter>,   CreateSaveFilter<LZMASaveFilter>,   0, 2, 9},
02278 #else
02279   {"lzma",   TO_BE32X('OTTX'), NULL,                               NULL,                               0, 0, 0},
02280 #endif
02281 };
02282 
02290 static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
02291 {
02292   const SaveLoadFormat *def = lastof(_saveload_formats);
02293 
02294   /* find default savegame format, the highest one with which files can be written */
02295   while (!def->init_write) def--;
02296 
02297   if (!StrEmpty(s)) {
02298     /* Get the ":..." of the compression level out of the way */
02299     char *complevel = strrchr(s, ':');
02300     if (complevel != NULL) *complevel = '\0';
02301 
02302     for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
02303       if (slf->init_write != NULL && strcmp(s, slf->name) == 0) {
02304         *compression_level = slf->default_compression;
02305         if (complevel != NULL) {
02306           /* There is a compression level in the string.
02307            * First restore the : we removed to do proper name matching,
02308            * then move the the begin of the actual version. */
02309           *complevel = ':';
02310           complevel++;
02311 
02312           /* Get the version and determine whether all went fine. */
02313           char *end;
02314           long level = strtol(complevel, &end, 10);
02315           if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) {
02316             SetDParamStr(0, complevel);
02317             ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL, WL_CRITICAL);
02318           } else {
02319             *compression_level = level;
02320           }
02321         }
02322         return slf;
02323       }
02324     }
02325 
02326     SetDParamStr(0, s);
02327     SetDParamStr(1, def->name);
02328     ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM, WL_CRITICAL);
02329 
02330     /* Restore the string by adding the : back */
02331     if (complevel != NULL) *complevel = ':';
02332   }
02333   *compression_level = def->default_compression;
02334   return def;
02335 }
02336 
02337 /* actual loader/saver function */
02338 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings);
02339 extern bool AfterLoadGame();
02340 extern bool LoadOldSaveGame(const char *file);
02341 
02345 static inline void ClearSaveLoadState()
02346 {
02347   delete _sl.dumper;
02348   _sl.dumper = NULL;
02349 
02350   delete _sl.sf;
02351   _sl.sf = NULL;
02352 
02353   delete _sl.reader;
02354   _sl.reader = NULL;
02355 
02356   delete _sl.lf;
02357   _sl.lf = NULL;
02358 }
02359 
02365 static void SaveFileStart()
02366 {
02367   _sl.ff_state = _fast_forward;
02368   _fast_forward = 0;
02369   if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
02370 
02371   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START);
02372   _sl.saveinprogress = true;
02373 }
02374 
02376 static void SaveFileDone()
02377 {
02378   if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state;
02379   if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
02380 
02381   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
02382   _sl.saveinprogress = false;
02383 }
02384 
02386 void SetSaveLoadError(StringID str)
02387 {
02388   _sl.error_str = str;
02389 }
02390 
02392 const char *GetSaveLoadErrorString()
02393 {
02394   SetDParam(0, _sl.error_str);
02395   SetDParamStr(1, _sl.extra_msg);
02396 
02397   static char err_str[512];
02398   GetString(err_str, _sl.action == SLA_SAVE ? STR_ERROR_GAME_SAVE_FAILED : STR_ERROR_GAME_LOAD_FAILED, lastof(err_str));
02399   return err_str;
02400 }
02401 
02403 static void SaveFileError()
02404 {
02405   SetDParamStr(0, GetSaveLoadErrorString());
02406   ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
02407   SaveFileDone();
02408 }
02409 
02414 static SaveOrLoadResult SaveFileToDisk(bool threaded)
02415 {
02416   try {
02417     byte compression;
02418     const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format, &compression);
02419 
02420     /* We have written our stuff to memory, now write it to file! */
02421     uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) };
02422     _sl.sf->Write((byte*)hdr, sizeof(hdr));
02423 
02424     _sl.sf = fmt->init_write(_sl.sf, compression);
02425     _sl.dumper->Flush(_sl.sf);
02426 
02427     ClearSaveLoadState();
02428 
02429     if (threaded) SetAsyncSaveFinish(SaveFileDone);
02430 
02431     return SL_OK;
02432   } catch (...) {
02433     ClearSaveLoadState();
02434 
02435     AsyncSaveFinishProc asfp = SaveFileDone;
02436 
02437     /* We don't want to shout when saving is just
02438      * cancelled due to a client disconnecting. */
02439     if (_sl.error_str != STR_NETWORK_ERROR_LOSTCONNECTION) {
02440       /* Skip the "colour" character */
02441       DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
02442       asfp = SaveFileError;
02443     }
02444 
02445     if (threaded) {
02446       SetAsyncSaveFinish(asfp);
02447     } else {
02448       asfp();
02449     }
02450     return SL_ERROR;
02451   }
02452 }
02453 
02455 static void SaveFileToDiskThread(void *arg)
02456 {
02457   SaveFileToDisk(true);
02458 }
02459 
02460 void WaitTillSaved()
02461 {
02462   if (_save_thread == NULL) return;
02463 
02464   _save_thread->Join();
02465   delete _save_thread;
02466   _save_thread = NULL;
02467 
02468   /* Make sure every other state is handled properly as well. */
02469   ProcessAsyncSaveFinish();
02470 }
02471 
02480 static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
02481 {
02482   assert(!_sl.saveinprogress);
02483 
02484   _sl.dumper = new MemoryDumper();
02485   _sl.sf = writer;
02486 
02487   _sl_version = SAVEGAME_VERSION;
02488 
02489   SaveViewportBeforeSaveGame();
02490   SlSaveChunks();
02491 
02492   SaveFileStart();
02493   if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
02494     if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
02495 
02496     SaveOrLoadResult result = SaveFileToDisk(false);
02497     SaveFileDone();
02498 
02499     return result;
02500   }
02501 
02502   return SL_OK;
02503 }
02504 
02511 SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
02512 {
02513   try {
02514     _sl.action = SLA_SAVE;
02515     return DoSave(writer, threaded);
02516   } catch (...) {
02517     ClearSaveLoadState();
02518     return SL_ERROR;
02519   }
02520 }
02521 
02528 static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
02529 {
02530   _sl.lf = reader;
02531 
02532   if (load_check) {
02533     /* Clear previous check data */
02534     _load_check_data.Clear();
02535     /* Mark SL_LOAD_CHECK as supported for this savegame. */
02536     _load_check_data.checkable = true;
02537   }
02538 
02539   uint32 hdr[2];
02540   if (_sl.lf->Read((byte*)hdr, sizeof(hdr)) != sizeof(hdr)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
02541 
02542   /* see if we have any loader for this type. */
02543   const SaveLoadFormat *fmt = _saveload_formats;
02544   for (;;) {
02545     /* No loader found, treat as version 0 and use LZO format */
02546     if (fmt == endof(_saveload_formats)) {
02547       DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format");
02548       _sl.lf->Reset();
02549       _sl_version = 0;
02550       _sl_minor_version = 0;
02551 
02552       /* Try to find the LZO savegame format; it uses 'OTTD' as tag. */
02553       fmt = _saveload_formats;
02554       for (;;) {
02555         if (fmt == endof(_saveload_formats)) {
02556           /* Who removed LZO support? Bad bad boy! */
02557           NOT_REACHED();
02558         }
02559         if (fmt->tag == TO_BE32X('OTTD')) break;
02560         fmt++;
02561       }
02562       break;
02563     }
02564 
02565     if (fmt->tag == hdr[0]) {
02566       /* check version number */
02567       _sl_version = TO_BE32(hdr[1]) >> 16;
02568       /* Minor is not used anymore from version 18.0, but it is still needed
02569        * in versions before that (4 cases) which can't be removed easy.
02570        * Therefor it is loaded, but never saved (or, it saves a 0 in any scenario). */
02571       _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
02572 
02573       DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
02574 
02575       /* Is the version higher than the current? */
02576       if (_sl_version > SAVEGAME_VERSION) SlError(STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME);
02577       break;
02578     }
02579 
02580     fmt++;
02581   }
02582 
02583   /* loader for this savegame type is not implemented? */
02584   if (fmt->init_load == NULL) {
02585     char err_str[64];
02586     snprintf(err_str, lengthof(err_str), "Loader for '%s' is not available.", fmt->name);
02587     SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
02588   }
02589 
02590   _sl.lf = fmt->init_load(_sl.lf);
02591   _sl.reader = new ReadBuffer(_sl.lf);
02592   _next_offs = 0;
02593 
02594   if (!load_check) {
02595     /* Old maps were hardcoded to 256x256 and thus did not contain
02596      * any mapsize information. Pre-initialize to 256x256 to not to
02597      * confuse old games */
02598     InitializeGame(256, 256, true, true);
02599     // Hack: do this here, because some saveload functions depend on this
02600     if (_sl_version < SAVEGAME_VERSION_H2H)
02601       _settings_game.game_creation.head_to_head_areas = 1;
02602 
02603     GamelogReset();
02604 
02605     if (IsSavegameVersionBefore(4)) {
02606       /*
02607        * NewGRFs were introduced between 0.3,4 and 0.3.5, which both
02608        * shared savegame version 4. Anything before that 'obviously'
02609        * does not have any NewGRFs. Between the introduction and
02610        * savegame version 41 (just before 0.5) the NewGRF settings
02611        * were not stored in the savegame and they were loaded by
02612        * using the settings from the main menu.
02613        * So, to recap:
02614        * - savegame version  <  4:  do not load any NewGRFs.
02615        * - savegame version >= 41:  load NewGRFs from savegame, which is
02616        *                            already done at this stage by
02617        *                            overwriting the main menu settings.
02618        * - other savegame versions: use main menu settings.
02619        *
02620        * This means that users *can* crash savegame version 4..40
02621        * savegames if they set incompatible NewGRFs in the main menu,
02622        * but can't crash anymore for savegame version < 4 savegames.
02623        *
02624        * Note: this is done here because AfterLoadGame is also called
02625        * for TTO/TTD/TTDP savegames which have their own NewGRF logic.
02626        */
02627       ClearGRFConfigList(&_grfconfig);
02628     }
02629   }
02630 
02631   if (load_check) {
02632     /* Load chunks into _load_check_data.
02633      * No pools are loaded. References are not possible, and thus do not need resolving. */
02634     SlLoadCheckChunks();
02635   } else {
02636     /* Load chunks and resolve references */
02637     SlLoadChunks();
02638     SlFixPointers();
02639   }
02640 
02641   ClearSaveLoadState();
02642 
02643   _savegame_type = SGT_OTTD;
02644 
02645   if (load_check) {
02646     /* The only part from AfterLoadGame() we need */
02647     _load_check_data.grf_compatibility = IsGoodGRFConfigList(_load_check_data.grfconfig);
02648   } else {
02649     GamelogStartAction(GLAT_LOAD);
02650 
02651     /* After loading fix up savegame for any internal changes that
02652      * might have occurred since then. If it fails, load back the old game. */
02653     if (!AfterLoadGame()) {
02654       GamelogStopAction();
02655       return SL_REINIT;
02656     }
02657 
02658     GamelogStopAction();
02659   }
02660 
02661   return SL_OK;
02662 }
02663 
02669 SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
02670 {
02671   try {
02672     _sl.action = SLA_LOAD;
02673     return DoLoad(reader, false);
02674   } catch (...) {
02675     ClearSaveLoadState();
02676     return SL_REINIT;
02677   }
02678 }
02679 
02689 SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
02690 {
02691   /* An instance of saving is already active, so don't go saving again */
02692   if (_sl.saveinprogress && mode == SL_SAVE && threaded) {
02693     /* if not an autosave, but a user action, show error message */
02694     if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
02695     return SL_OK;
02696   }
02697   WaitTillSaved();
02698 
02699   /* Load a TTDLX or TTDPatch game */
02700   if (mode == SL_OLD_LOAD) {
02701     InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
02702 
02703     /* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
02704      * and if so a new NewGRF list will be made in LoadOldSaveGame.
02705      * Note: this is done here because AfterLoadGame is also called
02706      * for OTTD savegames which have their own NewGRF logic. */
02707     ClearGRFConfigList(&_grfconfig);
02708     GamelogReset();
02709     if (!LoadOldSaveGame(filename)) return SL_REINIT;
02710     _sl_version = 0;
02711     _sl_minor_version = 0;
02712     GamelogStartAction(GLAT_LOAD);
02713     if (!AfterLoadGame()) {
02714       GamelogStopAction();
02715       return SL_REINIT;
02716     }
02717     GamelogStopAction();
02718     return SL_OK;
02719   }
02720 
02721   switch (mode) {
02722     case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
02723     case SL_LOAD: _sl.action = SLA_LOAD; break;
02724     case SL_SAVE: _sl.action = SLA_SAVE; break;
02725     default: NOT_REACHED();
02726   }
02727 
02728   try {
02729     FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
02730 
02731     /* Make it a little easier to load savegames from the console */
02732     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
02733     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
02734     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SCENARIO_DIR);
02735 
02736     if (fh == NULL) {
02737       SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
02738     }
02739 
02740     if (mode == SL_SAVE) { // SAVE game
02741       DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
02742       if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
02743 
02744       return DoSave(new FileWriter(fh), threaded);
02745     }
02746 
02747     /* LOAD game */
02748     assert(mode == SL_LOAD || mode == SL_LOAD_CHECK);
02749     DEBUG(desync, 1, "load: %s", filename);
02750     return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK);
02751   } catch (...) {
02752     ClearSaveLoadState();
02753 
02754     /* Skip the "colour" character */
02755     if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
02756 
02757     /* A saver/loader exception!! reinitialize all variables to prevent crash! */
02758     return (mode == SL_LOAD) ? SL_REINIT : SL_ERROR;
02759   }
02760 }
02761 
02763 void DoExitSave()
02764 {
02765   SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
02766 }
02767 
02773 void GenerateDefaultSaveName(char *buf, const char *last)
02774 {
02775   /* Check if we have a name for this map, which is the name of the first
02776    * available company. When there's no company available we'll use
02777    * 'Spectator' as "company" name. */
02778   CompanyID cid = _local_company;
02779   if (!Company::IsValidID(cid)) {
02780     const Company *c;
02781     FOR_ALL_COMPANIES(c) {
02782       cid = c->index;
02783       break;
02784     }
02785   }
02786 
02787   SetDParam(0, cid);
02788 
02789   /* Insert current date */
02790   switch (_settings_client.gui.date_format_in_default_names) {
02791     case 0: SetDParam(1, STR_JUST_DATE_LONG); break;
02792     case 1: SetDParam(1, STR_JUST_DATE_TINY); break;
02793     case 2: SetDParam(1, STR_JUST_DATE_ISO); break;
02794     default: NOT_REACHED();
02795   }
02796   SetDParam(2, _date);
02797 
02798   /* Get the correct string (special string for when there's not company) */
02799   GetString(buf, !Company::IsValidID(cid) ? STR_SAVEGAME_NAME_SPECTATOR : STR_SAVEGAME_NAME_DEFAULT, last);
02800   SanitizeFilename(buf);
02801 }
02802 
02803 #if 0
02804 
02810 int GetSavegameType(char *file)
02811 {
02812   const SaveLoadFormat *fmt;
02813   uint32 hdr;
02814   FILE *f;
02815   int mode = SL_OLD_LOAD;
02816 
02817   f = fopen(file, "rb");
02818   if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
02819     DEBUG(sl, 0, "Savegame is obsolete or invalid format");
02820     mode = SL_LOAD; // don't try to get filename, just show name as it is written
02821   } else {
02822     /* see if we have any loader for this type. */
02823     for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
02824       if (fmt->tag == hdr) {
02825         mode = SL_LOAD; // new type of savegame
02826         break;
02827       }
02828     }
02829   }
02830 
02831   fclose(f);
02832   return mode;
02833 }
02834 #endif