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