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