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