saveload.cpp

Go to the documentation of this file.
00001 /* $Id: saveload.cpp 23967 2012-02-19 19:05:57Z rubidium $ */
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.x
00240  */
00241 extern const uint16 SAVEGAME_VERSION = 173; 
00242 
00243 SavegameType _savegame_type; 
00244 
00245 uint32 _ttdp_version;     
00246 uint16 _sl_version;       
00247 byte   _sl_minor_version; 
00248 char _savegame_format[8]; 
00249 bool _do_autosave;        
00250 
00252 enum SaveLoadAction {
00253   SLA_LOAD,        
00254   SLA_SAVE,        
00255   SLA_PTRS,        
00256   SLA_NULL,        
00257   SLA_LOAD_CHECK,  
00258 };
00259 
00260 enum NeedLength {
00261   NL_NONE = 0,       
00262   NL_WANTLENGTH = 1, 
00263   NL_CALCLENGTH = 2, 
00264 };
00265 
00267 static const size_t MEMORY_CHUNK_SIZE = 128 * 1024;
00268 
00270 struct ReadBuffer {
00271   byte buf[MEMORY_CHUNK_SIZE]; 
00272   byte *bufp;                  
00273   byte *bufe;                  
00274   LoadFilter *reader;          
00275   size_t read;                 
00276 
00281   ReadBuffer(LoadFilter *reader) : bufp(NULL), bufe(NULL), reader(reader), read(0)
00282   {
00283   }
00284 
00285   inline byte ReadByte()
00286   {
00287     if (this->bufp == this->bufe) {
00288       size_t len = this->reader->Read(this->buf, lengthof(this->buf));
00289       if (len == 0) SlErrorCorrupt("Unexpected end of chunk");
00290 
00291       this->read += len;
00292       this->bufp = this->buf;
00293       this->bufe = this->buf + len;
00294     }
00295 
00296     return *this->bufp++;
00297   }
00298 
00303   size_t GetSize() const
00304   {
00305     return this->read - (this->bufe - this->bufp);
00306   }
00307 };
00308 
00309 
00311 struct MemoryDumper {
00312   AutoFreeSmallVector<byte *, 16> blocks; 
00313   byte *buf;                              
00314   byte *bufe;                             
00315 
00317   MemoryDumper() : buf(NULL), bufe(NULL)
00318   {
00319   }
00320 
00325   inline void WriteByte(byte b)
00326   {
00327     /* Are we at the end of this chunk? */
00328     if (this->buf == this->bufe) {
00329       this->buf = CallocT<byte>(MEMORY_CHUNK_SIZE);
00330       *this->blocks.Append() = this->buf;
00331       this->bufe = this->buf + MEMORY_CHUNK_SIZE;
00332     }
00333 
00334     *this->buf++ = b;
00335   }
00336 
00341   void Flush(SaveFilter *writer)
00342   {
00343     uint i = 0;
00344     size_t t = this->GetSize();
00345 
00346     while (t > 0) {
00347       size_t to_write = min(MEMORY_CHUNK_SIZE, t);
00348 
00349       writer->Write(this->blocks[i++], to_write);
00350       t -= to_write;
00351     }
00352 
00353     writer->Finish();
00354   }
00355 
00360   size_t GetSize() const
00361   {
00362     return this->blocks.Length() * MEMORY_CHUNK_SIZE - (this->bufe - this->buf);
00363   }
00364 };
00365 
00367 struct SaveLoadParams {
00368   SaveLoadAction action;               
00369   NeedLength need_length;              
00370   byte block_mode;                     
00371   bool error;                          
00372 
00373   size_t obj_len;                      
00374   int array_index, last_array_index;   
00375 
00376   MemoryDumper *dumper;                
00377   SaveFilter *sf;                      
00378 
00379   ReadBuffer *reader;                  
00380   LoadFilter *lf;                      
00381 
00382   StringID error_str;                  
00383   char *extra_msg;                     
00384 
00385   byte ff_state;                       
00386   bool saveinprogress;                 
00387 };
00388 
00389 static SaveLoadParams _sl; 
00390 
00391 /* these define the chunks */
00392 extern const ChunkHandler _gamelog_chunk_handlers[];
00393 extern const ChunkHandler _map_chunk_handlers[];
00394 extern const ChunkHandler _misc_chunk_handlers[];
00395 extern const ChunkHandler _name_chunk_handlers[];
00396 extern const ChunkHandler _cheat_chunk_handlers[] ;
00397 extern const ChunkHandler _setting_chunk_handlers[];
00398 extern const ChunkHandler _company_chunk_handlers[];
00399 extern const ChunkHandler _engine_chunk_handlers[];
00400 extern const ChunkHandler _veh_chunk_handlers[];
00401 extern const ChunkHandler _waypoint_chunk_handlers[];
00402 extern const ChunkHandler _depot_chunk_handlers[];
00403 extern const ChunkHandler _order_chunk_handlers[];
00404 extern const ChunkHandler _town_chunk_handlers[];
00405 extern const ChunkHandler _sign_chunk_handlers[];
00406 extern const ChunkHandler _station_chunk_handlers[];
00407 extern const ChunkHandler _industry_chunk_handlers[];
00408 extern const ChunkHandler _economy_chunk_handlers[];
00409 extern const ChunkHandler _subsidy_chunk_handlers[];
00410 extern const ChunkHandler _goal_chunk_handlers[];
00411 extern const ChunkHandler _ai_chunk_handlers[];
00412 extern const ChunkHandler _game_chunk_handlers[];
00413 extern const ChunkHandler _animated_tile_chunk_handlers[];
00414 extern const ChunkHandler _newgrf_chunk_handlers[];
00415 extern const ChunkHandler _group_chunk_handlers[];
00416 extern const ChunkHandler _cargopacket_chunk_handlers[];
00417 extern const ChunkHandler _autoreplace_chunk_handlers[];
00418 extern const ChunkHandler _labelmaps_chunk_handlers[];
00419 extern const ChunkHandler _airport_chunk_handlers[];
00420 extern const ChunkHandler _object_chunk_handlers[];
00421 extern const ChunkHandler _persistent_storage_chunk_handlers[];
00422 
00424 static const ChunkHandler * const _chunk_handlers[] = {
00425   _gamelog_chunk_handlers,
00426   _map_chunk_handlers,
00427   _misc_chunk_handlers,
00428   _name_chunk_handlers,
00429   _cheat_chunk_handlers,
00430   _setting_chunk_handlers,
00431   _veh_chunk_handlers,
00432   _waypoint_chunk_handlers,
00433   _depot_chunk_handlers,
00434   _order_chunk_handlers,
00435   _industry_chunk_handlers,
00436   _economy_chunk_handlers,
00437   _subsidy_chunk_handlers,
00438   _goal_chunk_handlers,
00439   _engine_chunk_handlers,
00440   _town_chunk_handlers,
00441   _sign_chunk_handlers,
00442   _station_chunk_handlers,
00443   _company_chunk_handlers,
00444   _ai_chunk_handlers,
00445   _game_chunk_handlers,
00446   _animated_tile_chunk_handlers,
00447   _newgrf_chunk_handlers,
00448   _group_chunk_handlers,
00449   _cargopacket_chunk_handlers,
00450   _autoreplace_chunk_handlers,
00451   _labelmaps_chunk_handlers,
00452   _airport_chunk_handlers,
00453   _object_chunk_handlers,
00454   _persistent_storage_chunk_handlers,
00455   NULL,
00456 };
00457 
00462 #define FOR_ALL_CHUNK_HANDLERS(ch) \
00463   for (const ChunkHandler * const *chsc = _chunk_handlers; *chsc != NULL; chsc++) \
00464     for (const ChunkHandler *ch = *chsc; ch != NULL; ch = (ch->flags & CH_LAST) ? NULL : ch + 1)
00465 
00467 static void SlNullPointers()
00468 {
00469   _sl.action = SLA_NULL;
00470 
00471   /* We don't want any savegame conversion code to run
00472    * during NULLing; especially those that try to get
00473    * pointers from other pools. */
00474   _sl_version = SAVEGAME_VERSION;
00475 
00476   DEBUG(sl, 1, "Nulling pointers");
00477 
00478   FOR_ALL_CHUNK_HANDLERS(ch) {
00479     if (ch->ptrs_proc != NULL) {
00480       DEBUG(sl, 2, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
00481       ch->ptrs_proc();
00482     }
00483   }
00484 
00485   DEBUG(sl, 1, "All pointers nulled");
00486 
00487   assert(_sl.action == SLA_NULL);
00488 }
00489 
00498 void NORETURN SlError(StringID string, const char *extra_msg)
00499 {
00500   /* Distinguish between loading into _load_check_data vs. normal save/load. */
00501   if (_sl.action == SLA_LOAD_CHECK) {
00502     _load_check_data.error = string;
00503     free(_load_check_data.error_data);
00504     _load_check_data.error_data = (extra_msg == NULL) ? NULL : strdup(extra_msg);
00505   } else {
00506     _sl.error_str = string;
00507     free(_sl.extra_msg);
00508     _sl.extra_msg = (extra_msg == NULL) ? NULL : strdup(extra_msg);
00509   }
00510 
00511   /* We have to NULL all pointers here; we might be in a state where
00512    * the pointers are actually filled with indices, which means that
00513    * when we access them during cleaning the pool dereferences of
00514    * those indices will be made with segmentation faults as result. */
00515   if (_sl.action == SLA_LOAD || _sl.action == SLA_PTRS) SlNullPointers();
00516   throw std::exception();
00517 }
00518 
00526 void NORETURN SlErrorCorrupt(const char *msg)
00527 {
00528   SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
00529 }
00530 
00531 
00532 typedef void (*AsyncSaveFinishProc)();                
00533 static AsyncSaveFinishProc _async_save_finish = NULL; 
00534 static ThreadObject *_save_thread;                    
00535 
00540 static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
00541 {
00542   if (_exit_game) return;
00543   while (_async_save_finish != NULL) CSleep(10);
00544 
00545   _async_save_finish = proc;
00546 }
00547 
00551 void ProcessAsyncSaveFinish()
00552 {
00553   if (_async_save_finish == NULL) return;
00554 
00555   _async_save_finish();
00556 
00557   _async_save_finish = NULL;
00558 
00559   if (_save_thread != NULL) {
00560     _save_thread->Join();
00561     delete _save_thread;
00562     _save_thread = NULL;
00563   }
00564 }
00565 
00570 byte SlReadByte()
00571 {
00572   return _sl.reader->ReadByte();
00573 }
00574 
00579 void SlWriteByte(byte b)
00580 {
00581   _sl.dumper->WriteByte(b);
00582 }
00583 
00584 static inline int SlReadUint16()
00585 {
00586   int x = SlReadByte() << 8;
00587   return x | SlReadByte();
00588 }
00589 
00590 static inline uint32 SlReadUint32()
00591 {
00592   uint32 x = SlReadUint16() << 16;
00593   return x | SlReadUint16();
00594 }
00595 
00596 static inline uint64 SlReadUint64()
00597 {
00598   uint32 x = SlReadUint32();
00599   uint32 y = SlReadUint32();
00600   return (uint64)x << 32 | y;
00601 }
00602 
00603 static inline void SlWriteUint16(uint16 v)
00604 {
00605   SlWriteByte(GB(v, 8, 8));
00606   SlWriteByte(GB(v, 0, 8));
00607 }
00608 
00609 static inline void SlWriteUint32(uint32 v)
00610 {
00611   SlWriteUint16(GB(v, 16, 16));
00612   SlWriteUint16(GB(v,  0, 16));
00613 }
00614 
00615 static inline void SlWriteUint64(uint64 x)
00616 {
00617   SlWriteUint32((uint32)(x >> 32));
00618   SlWriteUint32((uint32)x);
00619 }
00620 
00626 static inline void SlSkipBytes(size_t length)
00627 {
00628   for (; length != 0; length--) SlReadByte();
00629 }
00630 
00640 static uint SlReadSimpleGamma()
00641 {
00642   uint i = SlReadByte();
00643   if (HasBit(i, 7)) {
00644     i &= ~0x80;
00645     if (HasBit(i, 6)) {
00646       i &= ~0x40;
00647       if (HasBit(i, 5)) {
00648         i &= ~0x20;
00649         if (HasBit(i, 4)) {
00650           SlErrorCorrupt("Unsupported gamma");
00651         }
00652         i = (i << 8) | SlReadByte();
00653       }
00654       i = (i << 8) | SlReadByte();
00655     }
00656     i = (i << 8) | SlReadByte();
00657   }
00658   return i;
00659 }
00660 
00673 static void SlWriteSimpleGamma(size_t i)
00674 {
00675   if (i >= (1 << 7)) {
00676     if (i >= (1 << 14)) {
00677       if (i >= (1 << 21)) {
00678         assert(i < (1 << 28));
00679         SlWriteByte((byte)(0xE0 | (i >> 24)));
00680         SlWriteByte((byte)(i >> 16));
00681       } else {
00682         SlWriteByte((byte)(0xC0 | (i >> 16)));
00683       }
00684       SlWriteByte((byte)(i >> 8));
00685     } else {
00686       SlWriteByte((byte)(0x80 | (i >> 8)));
00687     }
00688   }
00689   SlWriteByte((byte)i);
00690 }
00691 
00693 static inline uint SlGetGammaLength(size_t i)
00694 {
00695   return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21));
00696 }
00697 
00698 static inline uint SlReadSparseIndex()
00699 {
00700   return SlReadSimpleGamma();
00701 }
00702 
00703 static inline void SlWriteSparseIndex(uint index)
00704 {
00705   SlWriteSimpleGamma(index);
00706 }
00707 
00708 static inline uint SlReadArrayLength()
00709 {
00710   return SlReadSimpleGamma();
00711 }
00712 
00713 static inline void SlWriteArrayLength(size_t length)
00714 {
00715   SlWriteSimpleGamma(length);
00716 }
00717 
00718 static inline uint SlGetArrayLength(size_t length)
00719 {
00720   return SlGetGammaLength(length);
00721 }
00722 
00729 static inline uint SlCalcConvMemLen(VarType conv)
00730 {
00731   static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
00732   byte length = GB(conv, 4, 4);
00733 
00734   switch (length << 4) {
00735     case SLE_VAR_STRB:
00736     case SLE_VAR_STRBQ:
00737     case SLE_VAR_STR:
00738     case SLE_VAR_STRQ:
00739       return SlReadArrayLength();
00740 
00741     default:
00742       assert(length < lengthof(conv_mem_size));
00743       return conv_mem_size[length];
00744   }
00745 }
00746 
00753 static inline byte SlCalcConvFileLen(VarType conv)
00754 {
00755   static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
00756   byte length = GB(conv, 0, 4);
00757   assert(length < lengthof(conv_file_size));
00758   return conv_file_size[length];
00759 }
00760 
00762 static inline size_t SlCalcRefLen()
00763 {
00764   return IsSavegameVersionBefore(69) ? 2 : 4;
00765 }
00766 
00767 void SlSetArrayIndex(uint index)
00768 {
00769   _sl.need_length = NL_WANTLENGTH;
00770   _sl.array_index = index;
00771 }
00772 
00773 static size_t _next_offs;
00774 
00779 int SlIterateArray()
00780 {
00781   int index;
00782 
00783   /* After reading in the whole array inside the loop
00784    * we must have read in all the data, so we must be at end of current block. */
00785   if (_next_offs != 0 && _sl.reader->GetSize() != _next_offs) SlErrorCorrupt("Invalid chunk size");
00786 
00787   for (;;) {
00788     uint length = SlReadArrayLength();
00789     if (length == 0) {
00790       _next_offs = 0;
00791       return -1;
00792     }
00793 
00794     _sl.obj_len = --length;
00795     _next_offs = _sl.reader->GetSize() + length;
00796 
00797     switch (_sl.block_mode) {
00798       case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
00799       case CH_ARRAY:        index = _sl.array_index++; break;
00800       default:
00801         DEBUG(sl, 0, "SlIterateArray error");
00802         return -1; // error
00803     }
00804 
00805     if (length != 0) return index;
00806   }
00807 }
00808 
00812 void SlSkipArray()
00813 {
00814   while (SlIterateArray() != -1) {
00815     SlSkipBytes(_next_offs - _sl.reader->GetSize());
00816   }
00817 }
00818 
00824 void SlSetLength(size_t length)
00825 {
00826   assert(_sl.action == SLA_SAVE);
00827 
00828   switch (_sl.need_length) {
00829     case NL_WANTLENGTH:
00830       _sl.need_length = NL_NONE;
00831       switch (_sl.block_mode) {
00832         case CH_RIFF:
00833           /* Ugly encoding of >16M RIFF chunks
00834            * The lower 24 bits are normal
00835            * The uppermost 4 bits are bits 24:27 */
00836           assert(length < (1 << 28));
00837           SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
00838           break;
00839         case CH_ARRAY:
00840           assert(_sl.last_array_index <= _sl.array_index);
00841           while (++_sl.last_array_index <= _sl.array_index) {
00842             SlWriteArrayLength(1);
00843           }
00844           SlWriteArrayLength(length + 1);
00845           break;
00846         case CH_SPARSE_ARRAY:
00847           SlWriteArrayLength(length + 1 + SlGetArrayLength(_sl.array_index)); // Also include length of sparse index.
00848           SlWriteSparseIndex(_sl.array_index);
00849           break;
00850         default: NOT_REACHED();
00851       }
00852       break;
00853 
00854     case NL_CALCLENGTH:
00855       _sl.obj_len += (int)length;
00856       break;
00857 
00858     default: NOT_REACHED();
00859   }
00860 }
00861 
00868 static void SlCopyBytes(void *ptr, size_t length)
00869 {
00870   byte *p = (byte *)ptr;
00871 
00872   switch (_sl.action) {
00873     case SLA_LOAD_CHECK:
00874     case SLA_LOAD:
00875       for (; length != 0; length--) *p++ = SlReadByte();
00876       break;
00877     case SLA_SAVE:
00878       for (; length != 0; length--) SlWriteByte(*p++);
00879       break;
00880     default: NOT_REACHED();
00881   }
00882 }
00883 
00885 size_t SlGetFieldLength()
00886 {
00887   return _sl.obj_len;
00888 }
00889 
00897 int64 ReadValue(const void *ptr, VarType conv)
00898 {
00899   switch (GetVarMemType(conv)) {
00900     case SLE_VAR_BL:  return (*(const bool *)ptr != 0);
00901     case SLE_VAR_I8:  return *(const int8  *)ptr;
00902     case SLE_VAR_U8:  return *(const byte  *)ptr;
00903     case SLE_VAR_I16: return *(const int16 *)ptr;
00904     case SLE_VAR_U16: return *(const uint16*)ptr;
00905     case SLE_VAR_I32: return *(const int32 *)ptr;
00906     case SLE_VAR_U32: return *(const uint32*)ptr;
00907     case SLE_VAR_I64: return *(const int64 *)ptr;
00908     case SLE_VAR_U64: return *(const uint64*)ptr;
00909     case SLE_VAR_NULL:return 0;
00910     default: NOT_REACHED();
00911   }
00912 }
00913 
00921 void WriteValue(void *ptr, VarType conv, int64 val)
00922 {
00923   switch (GetVarMemType(conv)) {
00924     case SLE_VAR_BL:  *(bool  *)ptr = (val != 0);  break;
00925     case SLE_VAR_I8:  *(int8  *)ptr = val; break;
00926     case SLE_VAR_U8:  *(byte  *)ptr = val; break;
00927     case SLE_VAR_I16: *(int16 *)ptr = val; break;
00928     case SLE_VAR_U16: *(uint16*)ptr = val; break;
00929     case SLE_VAR_I32: *(int32 *)ptr = val; break;
00930     case SLE_VAR_U32: *(uint32*)ptr = val; break;
00931     case SLE_VAR_I64: *(int64 *)ptr = val; break;
00932     case SLE_VAR_U64: *(uint64*)ptr = val; break;
00933     case SLE_VAR_NAME: *(char**)ptr = CopyFromOldName(val); break;
00934     case SLE_VAR_NULL: break;
00935     default: NOT_REACHED();
00936   }
00937 }
00938 
00947 static void SlSaveLoadConv(void *ptr, VarType conv)
00948 {
00949   switch (_sl.action) {
00950     case SLA_SAVE: {
00951       int64 x = ReadValue(ptr, conv);
00952 
00953       /* Write the value to the file and check if its value is in the desired range */
00954       switch (GetVarFileType(conv)) {
00955         case SLE_FILE_I8: assert(x >= -128 && x <= 127);     SlWriteByte(x);break;
00956         case SLE_FILE_U8: assert(x >= 0 && x <= 255);        SlWriteByte(x);break;
00957         case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break;
00958         case SLE_FILE_STRINGID:
00959         case SLE_FILE_U16:assert(x >= 0 && x <= 65535);      SlWriteUint16(x);break;
00960         case SLE_FILE_I32:
00961         case SLE_FILE_U32:                                   SlWriteUint32((uint32)x);break;
00962         case SLE_FILE_I64:
00963         case SLE_FILE_U64:                                   SlWriteUint64(x);break;
00964         default: NOT_REACHED();
00965       }
00966       break;
00967     }
00968     case SLA_LOAD_CHECK:
00969     case SLA_LOAD: {
00970       int64 x;
00971       /* Read a value from the file */
00972       switch (GetVarFileType(conv)) {
00973         case SLE_FILE_I8:  x = (int8  )SlReadByte();   break;
00974         case SLE_FILE_U8:  x = (byte  )SlReadByte();   break;
00975         case SLE_FILE_I16: x = (int16 )SlReadUint16(); break;
00976         case SLE_FILE_U16: x = (uint16)SlReadUint16(); break;
00977         case SLE_FILE_I32: x = (int32 )SlReadUint32(); break;
00978         case SLE_FILE_U32: x = (uint32)SlReadUint32(); break;
00979         case SLE_FILE_I64: x = (int64 )SlReadUint64(); break;
00980         case SLE_FILE_U64: x = (uint64)SlReadUint64(); break;
00981         case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break;
00982         default: NOT_REACHED();
00983       }
00984 
00985       /* Write The value to the struct. These ARE endian safe. */
00986       WriteValue(ptr, conv, x);
00987       break;
00988     }
00989     case SLA_PTRS: break;
00990     case SLA_NULL: break;
00991     default: NOT_REACHED();
00992   }
00993 }
00994 
01004 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
01005 {
01006   if (ptr == NULL) return 0;
01007   return min(strlen(ptr), length - 1);
01008 }
01009 
01019 static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
01020 {
01021   size_t len;
01022   const char *str;
01023 
01024   switch (GetVarMemType(conv)) {
01025     default: NOT_REACHED();
01026     case SLE_VAR_STR:
01027     case SLE_VAR_STRQ:
01028       str = *(const char * const *)ptr;
01029       len = SIZE_MAX;
01030       break;
01031     case SLE_VAR_STRB:
01032     case SLE_VAR_STRBQ:
01033       str = (const char *)ptr;
01034       len = length;
01035       break;
01036   }
01037 
01038   len = SlCalcNetStringLen(str, len);
01039   return len + SlGetArrayLength(len); // also include the length of the index
01040 }
01041 
01048 static void SlString(void *ptr, size_t length, VarType conv)
01049 {
01050   switch (_sl.action) {
01051     case SLA_SAVE: {
01052       size_t len;
01053       switch (GetVarMemType(conv)) {
01054         default: NOT_REACHED();
01055         case SLE_VAR_STRB:
01056         case SLE_VAR_STRBQ:
01057           len = SlCalcNetStringLen((char *)ptr, length);
01058           break;
01059         case SLE_VAR_STR:
01060         case SLE_VAR_STRQ:
01061           ptr = *(char **)ptr;
01062           len = SlCalcNetStringLen((char *)ptr, SIZE_MAX);
01063           break;
01064       }
01065 
01066       SlWriteArrayLength(len);
01067       SlCopyBytes(ptr, len);
01068       break;
01069     }
01070     case SLA_LOAD_CHECK:
01071     case SLA_LOAD: {
01072       size_t len = SlReadArrayLength();
01073 
01074       switch (GetVarMemType(conv)) {
01075         default: NOT_REACHED();
01076         case SLE_VAR_STRB:
01077         case SLE_VAR_STRBQ:
01078           if (len >= length) {
01079             DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
01080             SlCopyBytes(ptr, length);
01081             SlSkipBytes(len - length);
01082             len = length - 1;
01083           } else {
01084             SlCopyBytes(ptr, len);
01085           }
01086           break;
01087         case SLE_VAR_STR:
01088         case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate
01089           free(*(char **)ptr);
01090           if (len == 0) {
01091             *(char **)ptr = NULL;
01092             return;
01093           } else {
01094             *(char **)ptr = MallocT<char>(len + 1); // terminating '\0'
01095             ptr = *(char **)ptr;
01096             SlCopyBytes(ptr, len);
01097           }
01098           break;
01099       }
01100 
01101       ((char *)ptr)[len] = '\0'; // properly terminate the string
01102       StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK;
01103       if ((conv & SLF_ALLOW_CONTROL) != 0) {
01104         settings = settings | SVS_ALLOW_CONTROL_CODE;
01105         if (IsSavegameVersionBefore(169)) {
01106           str_fix_scc_encoded((char *)ptr, (char *)ptr + len);
01107         }
01108       }
01109       if ((conv & SLF_ALLOW_NEWLINE) != 0) {
01110         settings = settings | SVS_ALLOW_NEWLINE;
01111       }
01112       str_validate((char *)ptr, (char *)ptr + len, settings);
01113       break;
01114     }
01115     case SLA_PTRS: break;
01116     case SLA_NULL: break;
01117     default: NOT_REACHED();
01118   }
01119 }
01120 
01126 static inline size_t SlCalcArrayLen(size_t length, VarType conv)
01127 {
01128   return SlCalcConvFileLen(conv) * length;
01129 }
01130 
01137 void SlArray(void *array, size_t length, VarType conv)
01138 {
01139   if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
01140 
01141   /* Automatically calculate the length? */
01142   if (_sl.need_length != NL_NONE) {
01143     SlSetLength(SlCalcArrayLen(length, conv));
01144     /* Determine length only? */
01145     if (_sl.need_length == NL_CALCLENGTH) return;
01146   }
01147 
01148   /* NOTICE - handle some buggy stuff, in really old versions everything was saved
01149    * as a byte-type. So detect this, and adjust array size accordingly */
01150   if (_sl.action != SLA_SAVE && _sl_version == 0) {
01151     /* all arrays except difficulty settings */
01152     if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
01153         conv == SLE_INT32 || conv == SLE_UINT32) {
01154       SlCopyBytes(array, length * SlCalcConvFileLen(conv));
01155       return;
01156     }
01157     /* used for conversion of Money 32bit->64bit */
01158     if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
01159       for (uint i = 0; i < length; i++) {
01160         ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
01161       }
01162       return;
01163     }
01164   }
01165 
01166   /* If the size of elements is 1 byte both in file and memory, no special
01167    * conversion is needed, use specialized copy-copy function to speed up things */
01168   if (conv == SLE_INT8 || conv == SLE_UINT8) {
01169     SlCopyBytes(array, length);
01170   } else {
01171     byte *a = (byte*)array;
01172     byte mem_size = SlCalcConvMemLen(conv);
01173 
01174     for (; length != 0; length --) {
01175       SlSaveLoadConv(a, conv);
01176       a += mem_size; // get size
01177     }
01178   }
01179 }
01180 
01181 
01192 static size_t ReferenceToInt(const void *obj, SLRefType rt)
01193 {
01194   assert(_sl.action == SLA_SAVE);
01195 
01196   if (obj == NULL) return 0;
01197 
01198   switch (rt) {
01199     case REF_VEHICLE_OLD: // Old vehicles we save as new onces
01200     case REF_VEHICLE:   return ((const  Vehicle*)obj)->index + 1;
01201     case REF_STATION:   return ((const  Station*)obj)->index + 1;
01202     case REF_TOWN:      return ((const     Town*)obj)->index + 1;
01203     case REF_ORDER:     return ((const    Order*)obj)->index + 1;
01204     case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
01205     case REF_ENGINE_RENEWS: return ((const       EngineRenew*)obj)->index + 1;
01206     case REF_CARGO_PACKET:  return ((const       CargoPacket*)obj)->index + 1;
01207     case REF_ORDERLIST:     return ((const         OrderList*)obj)->index + 1;
01208     case REF_STORAGE:       return ((const PersistentStorage*)obj)->index + 1;
01209     default: NOT_REACHED();
01210   }
01211 }
01212 
01223 static void *IntToReference(size_t index, SLRefType rt)
01224 {
01225   assert_compile(sizeof(size_t) <= sizeof(void *));
01226 
01227   assert(_sl.action == SLA_PTRS);
01228 
01229   /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE,
01230    * and should be loaded like that */
01231   if (rt == REF_VEHICLE_OLD && !IsSavegameVersionBefore(4, 4)) {
01232     rt = REF_VEHICLE;
01233   }
01234 
01235   /* No need to look up NULL pointers, just return immediately */
01236   if (index == (rt == REF_VEHICLE_OLD ? 0xFFFF : 0)) return NULL;
01237 
01238   /* Correct index. Old vehicles were saved differently:
01239    * invalid vehicle was 0xFFFF, now we use 0x0000 for everything invalid. */
01240   if (rt != REF_VEHICLE_OLD) index--;
01241 
01242   switch (rt) {
01243     case REF_ORDERLIST:
01244       if (OrderList::IsValidID(index)) return OrderList::Get(index);
01245       SlErrorCorrupt("Referencing invalid OrderList");
01246 
01247     case REF_ORDER:
01248       if (Order::IsValidID(index)) return Order::Get(index);
01249       /* in old versions, invalid order was used to mark end of order list */
01250       if (IsSavegameVersionBefore(5, 2)) return NULL;
01251       SlErrorCorrupt("Referencing invalid Order");
01252 
01253     case REF_VEHICLE_OLD:
01254     case REF_VEHICLE:
01255       if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
01256       SlErrorCorrupt("Referencing invalid Vehicle");
01257 
01258     case REF_STATION:
01259       if (Station::IsValidID(index)) return Station::Get(index);
01260       SlErrorCorrupt("Referencing invalid Station");
01261 
01262     case REF_TOWN:
01263       if (Town::IsValidID(index)) return Town::Get(index);
01264       SlErrorCorrupt("Referencing invalid Town");
01265 
01266     case REF_ROADSTOPS:
01267       if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
01268       SlErrorCorrupt("Referencing invalid RoadStop");
01269 
01270     case REF_ENGINE_RENEWS:
01271       if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
01272       SlErrorCorrupt("Referencing invalid EngineRenew");
01273 
01274     case REF_CARGO_PACKET:
01275       if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
01276       SlErrorCorrupt("Referencing invalid CargoPacket");
01277 
01278     case REF_STORAGE:
01279       if (PersistentStorage::IsValidID(index)) return PersistentStorage::Get(index);
01280       SlErrorCorrupt("Referencing invalid PersistentStorage");
01281 
01282     default: NOT_REACHED();
01283   }
01284 }
01285 
01290 static inline size_t SlCalcListLen(const void *list)
01291 {
01292   const std::list<void *> *l = (const std::list<void *> *) list;
01293 
01294   int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
01295   /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
01296    * of the list */
01297   return l->size() * type_size + type_size;
01298 }
01299 
01300 
01306 static void SlList(void *list, SLRefType conv)
01307 {
01308   /* Automatically calculate the length? */
01309   if (_sl.need_length != NL_NONE) {
01310     SlSetLength(SlCalcListLen(list));
01311     /* Determine length only? */
01312     if (_sl.need_length == NL_CALCLENGTH) return;
01313   }
01314 
01315   typedef std::list<void *> PtrList;
01316   PtrList *l = (PtrList *)list;
01317 
01318   switch (_sl.action) {
01319     case SLA_SAVE: {
01320       SlWriteUint32((uint32)l->size());
01321 
01322       PtrList::iterator iter;
01323       for (iter = l->begin(); iter != l->end(); ++iter) {
01324         void *ptr = *iter;
01325         SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
01326       }
01327       break;
01328     }
01329     case SLA_LOAD_CHECK:
01330     case SLA_LOAD: {
01331       size_t length = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01332 
01333       /* Load each reference and push to the end of the list */
01334       for (size_t i = 0; i < length; i++) {
01335         size_t data = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01336         l->push_back((void *)data);
01337       }
01338       break;
01339     }
01340     case SLA_PTRS: {
01341       PtrList temp = *l;
01342 
01343       l->clear();
01344       PtrList::iterator iter;
01345       for (iter = temp.begin(); iter != temp.end(); ++iter) {
01346         void *ptr = IntToReference((size_t)*iter, conv);
01347         l->push_back(ptr);
01348       }
01349       break;
01350     }
01351     case SLA_NULL:
01352       l->clear();
01353       break;
01354     default: NOT_REACHED();
01355   }
01356 }
01357 
01358 
01360 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
01361 {
01362   if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
01363   if (sld->conv & SLF_NOT_IN_SAVE) return false;
01364 
01365   return true;
01366 }
01367 
01373 static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
01374 {
01375   if ((sld->conv & SLF_NO_NETWORK_SYNC) && _sl.action != SLA_SAVE && _networking && !_network_server) {
01376     SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
01377     return true;
01378   }
01379 
01380   return false;
01381 }
01382 
01389 size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
01390 {
01391   size_t length = 0;
01392 
01393   /* Need to determine the length and write a length tag. */
01394   for (; sld->cmd != SL_END; sld++) {
01395     length += SlCalcObjMemberLength(object, sld);
01396   }
01397   return length;
01398 }
01399 
01400 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
01401 {
01402   assert(_sl.action == SLA_SAVE);
01403 
01404   switch (sld->cmd) {
01405     case SL_VAR:
01406     case SL_REF:
01407     case SL_ARR:
01408     case SL_STR:
01409     case SL_LST:
01410       /* CONDITIONAL saveload types depend on the savegame version */
01411       if (!SlIsObjectValidInSavegame(sld)) break;
01412 
01413       switch (sld->cmd) {
01414         case SL_VAR: return SlCalcConvFileLen(sld->conv);
01415         case SL_REF: return SlCalcRefLen();
01416         case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
01417         case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
01418         case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
01419         default: NOT_REACHED();
01420       }
01421       break;
01422     case SL_WRITEBYTE: return 1; // a byte is logically of size 1
01423     case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
01424     case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
01425     default: NOT_REACHED();
01426   }
01427   return 0;
01428 }
01429 
01430 
01431 bool SlObjectMember(void *ptr, const SaveLoad *sld)
01432 {
01433   VarType conv = GB(sld->conv, 0, 8);
01434   switch (sld->cmd) {
01435     case SL_VAR:
01436     case SL_REF:
01437     case SL_ARR:
01438     case SL_STR:
01439     case SL_LST:
01440       /* CONDITIONAL saveload types depend on the savegame version */
01441       if (!SlIsObjectValidInSavegame(sld)) return false;
01442       if (SlSkipVariableOnLoad(sld)) return false;
01443 
01444       switch (sld->cmd) {
01445         case SL_VAR: SlSaveLoadConv(ptr, conv); break;
01446         case SL_REF: // Reference variable, translate
01447           switch (_sl.action) {
01448             case SLA_SAVE:
01449               SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv));
01450               break;
01451             case SLA_LOAD_CHECK:
01452             case SLA_LOAD:
01453               *(size_t *)ptr = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01454               break;
01455             case SLA_PTRS:
01456               *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv);
01457               break;
01458             case SLA_NULL:
01459               *(void **)ptr = NULL;
01460               break;
01461             default: NOT_REACHED();
01462           }
01463           break;
01464         case SL_ARR: SlArray(ptr, sld->length, conv); break;
01465         case SL_STR: SlString(ptr, sld->length, sld->conv); break;
01466         case SL_LST: SlList(ptr, (SLRefType)conv); break;
01467         default: NOT_REACHED();
01468       }
01469       break;
01470 
01471     /* SL_WRITEBYTE translates a value of a variable to another one upon
01472      * saving or loading.
01473      * XXX - variable renaming abuse
01474      * game_value: the value of the variable ingame is abused by sld->version_from
01475      * file_value: the value of the variable in the savegame is abused by sld->version_to */
01476     case SL_WRITEBYTE:
01477       switch (_sl.action) {
01478         case SLA_SAVE: SlWriteByte(sld->version_to); break;
01479         case SLA_LOAD_CHECK:
01480         case SLA_LOAD: *(byte *)ptr = sld->version_from; break;
01481         case SLA_PTRS: break;
01482         case SLA_NULL: break;
01483         default: NOT_REACHED();
01484       }
01485       break;
01486 
01487     /* SL_VEH_INCLUDE loads common code for vehicles */
01488     case SL_VEH_INCLUDE:
01489       SlObject(ptr, GetVehicleDescription(VEH_END));
01490       break;
01491 
01492     case SL_ST_INCLUDE:
01493       SlObject(ptr, GetBaseStationDescription());
01494       break;
01495 
01496     default: NOT_REACHED();
01497   }
01498   return true;
01499 }
01500 
01506 void SlObject(void *object, const SaveLoad *sld)
01507 {
01508   /* Automatically calculate the length? */
01509   if (_sl.need_length != NL_NONE) {
01510     SlSetLength(SlCalcObjLength(object, sld));
01511     if (_sl.need_length == NL_CALCLENGTH) return;
01512   }
01513 
01514   for (; sld->cmd != SL_END; sld++) {
01515     void *ptr = sld->global ? sld->address : GetVariableAddress(object, sld);
01516     SlObjectMember(ptr, sld);
01517   }
01518 }
01519 
01524 void SlGlobList(const SaveLoadGlobVarList *sldg)
01525 {
01526   SlObject(NULL, (const SaveLoad*)sldg);
01527 }
01528 
01534 void SlAutolength(AutolengthProc *proc, void *arg)
01535 {
01536   size_t offs;
01537 
01538   assert(_sl.action == SLA_SAVE);
01539 
01540   /* Tell it to calculate the length */
01541   _sl.need_length = NL_CALCLENGTH;
01542   _sl.obj_len = 0;
01543   proc(arg);
01544 
01545   /* Setup length */
01546   _sl.need_length = NL_WANTLENGTH;
01547   SlSetLength(_sl.obj_len);
01548 
01549   offs = _sl.dumper->GetSize() + _sl.obj_len;
01550 
01551   /* And write the stuff */
01552   proc(arg);
01553 
01554   if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
01555 }
01556 
01561 static void SlLoadChunk(const ChunkHandler *ch)
01562 {
01563   byte m = SlReadByte();
01564   size_t len;
01565   size_t endoffs;
01566 
01567   _sl.block_mode = m;
01568   _sl.obj_len = 0;
01569 
01570   switch (m) {
01571     case CH_ARRAY:
01572       _sl.array_index = 0;
01573       ch->load_proc();
01574       break;
01575     case CH_SPARSE_ARRAY:
01576       ch->load_proc();
01577       break;
01578     default:
01579       if ((m & 0xF) == CH_RIFF) {
01580         /* Read length */
01581         len = (SlReadByte() << 16) | ((m >> 4) << 24);
01582         len += SlReadUint16();
01583         _sl.obj_len = len;
01584         endoffs = _sl.reader->GetSize() + len;
01585         ch->load_proc();
01586         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
01587       } else {
01588         SlErrorCorrupt("Invalid chunk type");
01589       }
01590       break;
01591   }
01592 }
01593 
01599 static void SlLoadCheckChunk(const ChunkHandler *ch)
01600 {
01601   byte m = SlReadByte();
01602   size_t len;
01603   size_t endoffs;
01604 
01605   _sl.block_mode = m;
01606   _sl.obj_len = 0;
01607 
01608   switch (m) {
01609     case CH_ARRAY:
01610       _sl.array_index = 0;
01611       if (ch->load_check_proc) {
01612         ch->load_check_proc();
01613       } else {
01614         SlSkipArray();
01615       }
01616       break;
01617     case CH_SPARSE_ARRAY:
01618       if (ch->load_check_proc) {
01619         ch->load_check_proc();
01620       } else {
01621         SlSkipArray();
01622       }
01623       break;
01624     default:
01625       if ((m & 0xF) == CH_RIFF) {
01626         /* Read length */
01627         len = (SlReadByte() << 16) | ((m >> 4) << 24);
01628         len += SlReadUint16();
01629         _sl.obj_len = len;
01630         endoffs = _sl.reader->GetSize() + len;
01631         if (ch->load_check_proc) {
01632           ch->load_check_proc();
01633         } else {
01634           SlSkipBytes(len);
01635         }
01636         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
01637       } else {
01638         SlErrorCorrupt("Invalid chunk type");
01639       }
01640       break;
01641   }
01642 }
01643 
01648 static ChunkSaveLoadProc *_stub_save_proc;
01649 
01655 static inline void SlStubSaveProc2(void *arg)
01656 {
01657   _stub_save_proc();
01658 }
01659 
01665 static void SlStubSaveProc()
01666 {
01667   SlAutolength(SlStubSaveProc2, NULL);
01668 }
01669 
01675 static void SlSaveChunk(const ChunkHandler *ch)
01676 {
01677   ChunkSaveLoadProc *proc = ch->save_proc;
01678 
01679   /* Don't save any chunk information if there is no save handler. */
01680   if (proc == NULL) return;
01681 
01682   SlWriteUint32(ch->id);
01683   DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
01684 
01685   if (ch->flags & CH_AUTO_LENGTH) {
01686     /* Need to calculate the length. Solve that by calling SlAutoLength in the save_proc. */
01687     _stub_save_proc = proc;
01688     proc = SlStubSaveProc;
01689   }
01690 
01691   _sl.block_mode = ch->flags & CH_TYPE_MASK;
01692   switch (ch->flags & CH_TYPE_MASK) {
01693     case CH_RIFF:
01694       _sl.need_length = NL_WANTLENGTH;
01695       proc();
01696       break;
01697     case CH_ARRAY:
01698       _sl.last_array_index = 0;
01699       SlWriteByte(CH_ARRAY);
01700       proc();
01701       SlWriteArrayLength(0); // Terminate arrays
01702       break;
01703     case CH_SPARSE_ARRAY:
01704       SlWriteByte(CH_SPARSE_ARRAY);
01705       proc();
01706       SlWriteArrayLength(0); // Terminate arrays
01707       break;
01708     default: NOT_REACHED();
01709   }
01710 }
01711 
01713 static void SlSaveChunks()
01714 {
01715   FOR_ALL_CHUNK_HANDLERS(ch) {
01716     SlSaveChunk(ch);
01717   }
01718 
01719   /* Terminator */
01720   SlWriteUint32(0);
01721 }
01722 
01729 static const ChunkHandler *SlFindChunkHandler(uint32 id)
01730 {
01731   FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch;
01732   return NULL;
01733 }
01734 
01736 static void SlLoadChunks()
01737 {
01738   uint32 id;
01739   const ChunkHandler *ch;
01740 
01741   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
01742     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
01743 
01744     ch = SlFindChunkHandler(id);
01745     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
01746     SlLoadChunk(ch);
01747   }
01748 }
01749 
01751 static void SlLoadCheckChunks()
01752 {
01753   uint32 id;
01754   const ChunkHandler *ch;
01755 
01756   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
01757     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
01758 
01759     ch = SlFindChunkHandler(id);
01760     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
01761     SlLoadCheckChunk(ch);
01762   }
01763 }
01764 
01766 static void SlFixPointers()
01767 {
01768   _sl.action = SLA_PTRS;
01769 
01770   DEBUG(sl, 1, "Fixing pointers");
01771 
01772   FOR_ALL_CHUNK_HANDLERS(ch) {
01773     if (ch->ptrs_proc != NULL) {
01774       DEBUG(sl, 2, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
01775       ch->ptrs_proc();
01776     }
01777   }
01778 
01779   DEBUG(sl, 1, "All pointers fixed");
01780 
01781   assert(_sl.action == SLA_PTRS);
01782 }
01783 
01784 
01786 struct FileReader : LoadFilter {
01787   FILE *file; 
01788   long begin; 
01789 
01794   FileReader(FILE *file) : LoadFilter(NULL), file(file), begin(ftell(file))
01795   {
01796   }
01797 
01799   ~FileReader()
01800   {
01801     if (this->file != NULL) fclose(this->file);
01802     this->file = NULL;
01803 
01804     /* Make sure we don't double free. */
01805     _sl.sf = NULL;
01806   }
01807 
01808   /* virtual */ size_t Read(byte *buf, size_t size)
01809   {
01810     /* We're in the process of shutting down, i.e. in "failure" mode. */
01811     if (this->file == NULL) return 0;
01812 
01813     return fread(buf, 1, size, this->file);
01814   }
01815 
01816   /* virtual */ void Reset()
01817   {
01818     clearerr(this->file);
01819     fseek(this->file, this->begin, SEEK_SET);
01820   }
01821 };
01822 
01824 struct FileWriter : SaveFilter {
01825   FILE *file; 
01826 
01831   FileWriter(FILE *file) : SaveFilter(NULL), file(file)
01832   {
01833   }
01834 
01836   ~FileWriter()
01837   {
01838     this->Finish();
01839 
01840     /* Make sure we don't double free. */
01841     _sl.sf = NULL;
01842   }
01843 
01844   /* virtual */ void Write(byte *buf, size_t size)
01845   {
01846     /* We're in the process of shutting down, i.e. in "failure" mode. */
01847     if (this->file == NULL) return;
01848 
01849     if (fwrite(buf, 1, size, this->file) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
01850   }
01851 
01852   /* virtual */ void Finish()
01853   {
01854     if (this->file != NULL) fclose(this->file);
01855     this->file = NULL;
01856   }
01857 };
01858 
01859 /*******************************************
01860  ********** START OF LZO CODE **************
01861  *******************************************/
01862 
01863 #ifdef WITH_LZO
01864 #include <lzo/lzo1x.h>
01865 
01867 static const uint LZO_BUFFER_SIZE = 8192;
01868 
01870 struct LZOLoadFilter : LoadFilter {
01875   LZOLoadFilter(LoadFilter *chain) : LoadFilter(chain)
01876   {
01877     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
01878   }
01879 
01880   /* virtual */ size_t Read(byte *buf, size_t ssize)
01881   {
01882     assert(ssize >= LZO_BUFFER_SIZE);
01883 
01884     /* Buffer size is from the LZO docs plus the chunk header size. */
01885     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
01886     uint32 tmp[2];
01887     uint32 size;
01888     lzo_uint len;
01889 
01890     /* Read header*/
01891     if (this->chain->Read((byte*)tmp, sizeof(tmp)) != sizeof(tmp)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE, "File read failed");
01892 
01893     /* Check if size is bad */
01894     ((uint32*)out)[0] = size = tmp[1];
01895 
01896     if (_sl_version != 0) {
01897       tmp[0] = TO_BE32(tmp[0]);
01898       size = TO_BE32(size);
01899     }
01900 
01901     if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size");
01902 
01903     /* Read block */
01904     if (this->chain->Read(out + sizeof(uint32), size) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
01905 
01906     /* Verify checksum */
01907     if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
01908 
01909     /* Decompress */
01910     lzo1x_decompress(out + sizeof(uint32) * 1, size, buf, &len, NULL);
01911     return len;
01912   }
01913 };
01914 
01916 struct LZOSaveFilter : SaveFilter {
01922   LZOSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
01923   {
01924     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
01925   }
01926 
01927   /* virtual */ void Write(byte *buf, size_t size)
01928   {
01929     const lzo_bytep in = buf;
01930     /* Buffer size is from the LZO docs plus the chunk header size. */
01931     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
01932     byte wrkmem[LZO1X_1_MEM_COMPRESS];
01933     lzo_uint outlen;
01934 
01935     do {
01936       /* Compress up to LZO_BUFFER_SIZE bytes at once. */
01937       lzo_uint len = size > LZO_BUFFER_SIZE ? LZO_BUFFER_SIZE : (lzo_uint)size;
01938       lzo1x_1_compress(in, len, out + sizeof(uint32) * 2, &outlen, wrkmem);
01939       ((uint32*)out)[1] = TO_BE32((uint32)outlen);
01940       ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
01941       this->chain->Write(out, outlen + sizeof(uint32) * 2);
01942 
01943       /* Move to next data chunk. */
01944       size -= len;
01945       in += len;
01946     } while (size > 0);
01947   }
01948 };
01949 
01950 #endif /* WITH_LZO */
01951 
01952 /*********************************************
01953  ******** START OF NOCOMP CODE (uncompressed)*
01954  *********************************************/
01955 
01957 struct NoCompLoadFilter : LoadFilter {
01962   NoCompLoadFilter(LoadFilter *chain) : LoadFilter(chain)
01963   {
01964   }
01965 
01966   /* virtual */ size_t Read(byte *buf, size_t size)
01967   {
01968     return this->chain->Read(buf, size);
01969   }
01970 };
01971 
01973 struct NoCompSaveFilter : SaveFilter {
01979   NoCompSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
01980   {
01981   }
01982 
01983   /* virtual */ void Write(byte *buf, size_t size)
01984   {
01985     this->chain->Write(buf, size);
01986   }
01987 };
01988 
01989 /********************************************
01990  ********** START OF ZLIB CODE **************
01991  ********************************************/
01992 
01993 #if defined(WITH_ZLIB)
01994 #include <zlib.h>
01995 
01997 struct ZlibLoadFilter : LoadFilter {
01998   z_stream z;                        
01999   byte fread_buf[MEMORY_CHUNK_SIZE]; 
02000 
02005   ZlibLoadFilter(LoadFilter *chain) : LoadFilter(chain)
02006   {
02007     memset(&this->z, 0, sizeof(this->z));
02008     if (inflateInit(&this->z) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
02009   }
02010 
02012   ~ZlibLoadFilter()
02013   {
02014     inflateEnd(&this->z);
02015   }
02016 
02017   /* virtual */ size_t Read(byte *buf, size_t size)
02018   {
02019     this->z.next_out  = buf;
02020     this->z.avail_out = (uint)size;
02021 
02022     do {
02023       /* read more bytes from the file? */
02024       if (this->z.avail_in == 0) {
02025         this->z.next_in = this->fread_buf;
02026         this->z.avail_in = (uint)this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
02027       }
02028 
02029       /* inflate the data */
02030       int r = inflate(&this->z, 0);
02031       if (r == Z_STREAM_END) break;
02032 
02033       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "inflate() failed");
02034     } while (this->z.avail_out != 0);
02035 
02036     return size - this->z.avail_out;
02037   }
02038 };
02039 
02041 struct ZlibSaveFilter : SaveFilter {
02042   z_stream z; 
02043 
02049   ZlibSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
02050   {
02051     memset(&this->z, 0, sizeof(this->z));
02052     if (deflateInit(&this->z, compression_level) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
02053   }
02054 
02056   ~ZlibSaveFilter()
02057   {
02058     deflateEnd(&this->z);
02059   }
02060 
02067   void WriteLoop(byte *p, size_t len, int mode)
02068   {
02069     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
02070     uint n;
02071     this->z.next_in = p;
02072     this->z.avail_in = (uInt)len;
02073     do {
02074       this->z.next_out = buf;
02075       this->z.avail_out = sizeof(buf);
02076 
02084       int r = deflate(&this->z, mode);
02085 
02086       /* bytes were emitted? */
02087       if ((n = sizeof(buf) - this->z.avail_out) != 0) {
02088         this->chain->Write(buf, n);
02089       }
02090       if (r == Z_STREAM_END) break;
02091 
02092       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code");
02093     } while (this->z.avail_in || !this->z.avail_out);
02094   }
02095 
02096   /* virtual */ void Write(byte *buf, size_t size)
02097   {
02098     this->WriteLoop(buf, size, 0);
02099   }
02100 
02101   /* virtual */ void Finish()
02102   {
02103     this->WriteLoop(NULL, 0, Z_FINISH);
02104     this->chain->Finish();
02105   }
02106 };
02107 
02108 #endif /* WITH_ZLIB */
02109 
02110 /********************************************
02111  ********** START OF LZMA CODE **************
02112  ********************************************/
02113 
02114 #if defined(WITH_LZMA)
02115 #include <lzma.h>
02116 
02123 static const lzma_stream _lzma_init = LZMA_STREAM_INIT;
02124 
02126 struct LZMALoadFilter : LoadFilter {
02127   lzma_stream lzma;                  
02128   byte fread_buf[MEMORY_CHUNK_SIZE]; 
02129 
02134   LZMALoadFilter(LoadFilter *chain) : LoadFilter(chain), lzma(_lzma_init)
02135   {
02136     /* Allow saves up to 256 MB uncompressed */
02137     if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
02138   }
02139 
02141   ~LZMALoadFilter()
02142   {
02143     lzma_end(&this->lzma);
02144   }
02145 
02146   /* virtual */ size_t Read(byte *buf, size_t size)
02147   {
02148     this->lzma.next_out  = buf;
02149     this->lzma.avail_out = size;
02150 
02151     do {
02152       /* read more bytes from the file? */
02153       if (this->lzma.avail_in == 0) {
02154         this->lzma.next_in  = this->fread_buf;
02155         this->lzma.avail_in = this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
02156       }
02157 
02158       /* inflate the data */
02159       lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
02160       if (r == LZMA_STREAM_END) break;
02161       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
02162     } while (this->lzma.avail_out != 0);
02163 
02164     return size - this->lzma.avail_out;
02165   }
02166 };
02167 
02169 struct LZMASaveFilter : SaveFilter {
02170   lzma_stream lzma; 
02171 
02177   LZMASaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain), lzma(_lzma_init)
02178   {
02179     if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
02180   }
02181 
02183   ~LZMASaveFilter()
02184   {
02185     lzma_end(&this->lzma);
02186   }
02187 
02194   void WriteLoop(byte *p, size_t len, lzma_action action)
02195   {
02196     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
02197     size_t n;
02198     this->lzma.next_in = p;
02199     this->lzma.avail_in = len;
02200     do {
02201       this->lzma.next_out = buf;
02202       this->lzma.avail_out = sizeof(buf);
02203 
02204       lzma_ret r = lzma_code(&this->lzma, action);
02205 
02206       /* bytes were emitted? */
02207       if ((n = sizeof(buf) - this->lzma.avail_out) != 0) {
02208         this->chain->Write(buf, n);
02209       }
02210       if (r == LZMA_STREAM_END) break;
02211       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
02212     } while (this->lzma.avail_in || !this->lzma.avail_out);
02213   }
02214 
02215   /* virtual */ void Write(byte *buf, size_t size)
02216   {
02217     this->WriteLoop(buf, size, LZMA_RUN);
02218   }
02219 
02220   /* virtual */ void Finish()
02221   {
02222     this->WriteLoop(NULL, 0, LZMA_FINISH);
02223     this->chain->Finish();
02224   }
02225 };
02226 
02227 #endif /* WITH_LZMA */
02228 
02229 /*******************************************
02230  ************* END OF CODE *****************
02231  *******************************************/
02232 
02234 struct SaveLoadFormat {
02235   const char *name;                     
02236   uint32 tag;                           
02237 
02238   LoadFilter *(*init_load)(LoadFilter *chain);                    
02239   SaveFilter *(*init_write)(SaveFilter *chain, byte compression); 
02240 
02241   byte min_compression;                 
02242   byte default_compression;             
02243   byte max_compression;                 
02244 };
02245 
02247 static const SaveLoadFormat _saveload_formats[] = {
02248 #if defined(WITH_LZO)
02249   /* Roughly 75% larger than zlib level 6 at only ~7% of the CPU usage. */
02250   {"lzo",    TO_BE32X('OTTD'), CreateLoadFilter<LZOLoadFilter>,    CreateSaveFilter<LZOSaveFilter>,    0, 0, 0},
02251 #else
02252   {"lzo",    TO_BE32X('OTTD'), NULL,                               NULL,                               0, 0, 0},
02253 #endif
02254   /* Roughly 5 times larger at only 1% of the CPU usage over zlib level 6. */
02255   {"none",   TO_BE32X('OTTN'), CreateLoadFilter<NoCompLoadFilter>, CreateSaveFilter<NoCompSaveFilter>, 0, 0, 0},
02256 #if defined(WITH_ZLIB)
02257   /* After level 6 the speed reduction is significant (1.5x to 2.5x slower per level), but the reduction in filesize is
02258    * fairly insignificant (~1% for each step). Lower levels become ~5-10% bigger by each level than level 6 while level
02259    * 1 is "only" 3 times as fast. Level 0 results in uncompressed savegames at about 8 times the cost of "none". */
02260   {"zlib",   TO_BE32X('OTTZ'), CreateLoadFilter<ZlibLoadFilter>,   CreateSaveFilter<ZlibSaveFilter>,   0, 6, 9},
02261 #else
02262   {"zlib",   TO_BE32X('OTTZ'), NULL,                               NULL,                               0, 0, 0},
02263 #endif
02264 #if defined(WITH_LZMA)
02265   /* Level 2 compression is speed wise as fast as zlib level 6 compression (old default), but results in ~10% smaller saves.
02266    * Higher compression levels are possible, and might improve savegame size by up to 25%, but are also up to 10 times slower.
02267    * The next significant reduction in file size is at level 4, but that is already 4 times slower. Level 3 is primarily 50%
02268    * slower while not improving the filesize, while level 0 and 1 are faster, but don't reduce savegame size much.
02269    * It's OTTX and not e.g. OTTL because liblzma is part of xz-utils and .tar.xz is prefered over .tar.lzma. */
02270   {"lzma",   TO_BE32X('OTTX'), CreateLoadFilter<LZMALoadFilter>,   CreateSaveFilter<LZMASaveFilter>,   0, 2, 9},
02271 #else
02272   {"lzma",   TO_BE32X('OTTX'), NULL,                               NULL,                               0, 0, 0},
02273 #endif
02274 };
02275 
02283 static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
02284 {
02285   const SaveLoadFormat *def = lastof(_saveload_formats);
02286 
02287   /* find default savegame format, the highest one with which files can be written */
02288   while (!def->init_write) def--;
02289 
02290   if (!StrEmpty(s)) {
02291     /* Get the ":..." of the compression level out of the way */
02292     char *complevel = strrchr(s, ':');
02293     if (complevel != NULL) *complevel = '\0';
02294 
02295     for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
02296       if (slf->init_write != NULL && strcmp(s, slf->name) == 0) {
02297         *compression_level = slf->default_compression;
02298         if (complevel != NULL) {
02299           /* There is a compression level in the string.
02300            * First restore the : we removed to do proper name matching,
02301            * then move the the begin of the actual version. */
02302           *complevel = ':';
02303           complevel++;
02304 
02305           /* Get the version and determine whether all went fine. */
02306           char *end;
02307           long level = strtol(complevel, &end, 10);
02308           if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) {
02309             SetDParamStr(0, complevel);
02310             ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL, WL_CRITICAL);
02311           } else {
02312             *compression_level = level;
02313           }
02314         }
02315         return slf;
02316       }
02317     }
02318 
02319     SetDParamStr(0, s);
02320     SetDParamStr(1, def->name);
02321     ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM, WL_CRITICAL);
02322 
02323     /* Restore the string by adding the : back */
02324     if (complevel != NULL) *complevel = ':';
02325   }
02326   *compression_level = def->default_compression;
02327   return def;
02328 }
02329 
02330 /* actual loader/saver function */
02331 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings);
02332 extern bool AfterLoadGame();
02333 extern bool LoadOldSaveGame(const char *file);
02334 
02338 static inline void ClearSaveLoadState()
02339 {
02340   delete _sl.dumper;
02341   _sl.dumper = NULL;
02342 
02343   delete _sl.sf;
02344   _sl.sf = NULL;
02345 
02346   delete _sl.reader;
02347   _sl.reader = NULL;
02348 
02349   delete _sl.lf;
02350   _sl.lf = NULL;
02351 }
02352 
02358 static void SaveFileStart()
02359 {
02360   _sl.ff_state = _fast_forward;
02361   _fast_forward = 0;
02362   if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
02363 
02364   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START);
02365   _sl.saveinprogress = true;
02366 }
02367 
02369 static void SaveFileDone()
02370 {
02371   if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state;
02372   if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
02373 
02374   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
02375   _sl.saveinprogress = false;
02376 }
02377 
02379 void SetSaveLoadError(StringID str)
02380 {
02381   _sl.error_str = str;
02382 }
02383 
02385 const char *GetSaveLoadErrorString()
02386 {
02387   SetDParam(0, _sl.error_str);
02388   SetDParamStr(1, _sl.extra_msg);
02389 
02390   static char err_str[512];
02391   GetString(err_str, _sl.action == SLA_SAVE ? STR_ERROR_GAME_SAVE_FAILED : STR_ERROR_GAME_LOAD_FAILED, lastof(err_str));
02392   return err_str;
02393 }
02394 
02396 static void SaveFileError()
02397 {
02398   SetDParamStr(0, GetSaveLoadErrorString());
02399   ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
02400   SaveFileDone();
02401 }
02402 
02407 static SaveOrLoadResult SaveFileToDisk(bool threaded)
02408 {
02409   try {
02410     byte compression;
02411     const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format, &compression);
02412 
02413     /* We have written our stuff to memory, now write it to file! */
02414     uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) };
02415     _sl.sf->Write((byte*)hdr, sizeof(hdr));
02416 
02417     _sl.sf = fmt->init_write(_sl.sf, compression);
02418     _sl.dumper->Flush(_sl.sf);
02419 
02420     ClearSaveLoadState();
02421 
02422     if (threaded) SetAsyncSaveFinish(SaveFileDone);
02423 
02424     return SL_OK;
02425   } catch (...) {
02426     ClearSaveLoadState();
02427 
02428     AsyncSaveFinishProc asfp = SaveFileDone;
02429 
02430     /* We don't want to shout when saving is just
02431      * cancelled due to a client disconnecting. */
02432     if (_sl.error_str != STR_NETWORK_ERROR_LOSTCONNECTION) {
02433       /* Skip the "colour" character */
02434       DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
02435       asfp = SaveFileError;
02436     }
02437 
02438     if (threaded) {
02439       SetAsyncSaveFinish(asfp);
02440     } else {
02441       asfp();
02442     }
02443     return SL_ERROR;
02444   }
02445 }
02446 
02448 static void SaveFileToDiskThread(void *arg)
02449 {
02450   SaveFileToDisk(true);
02451 }
02452 
02453 void WaitTillSaved()
02454 {
02455   if (_save_thread == NULL) return;
02456 
02457   _save_thread->Join();
02458   delete _save_thread;
02459   _save_thread = NULL;
02460 
02461   /* Make sure every other state is handled properly as well. */
02462   ProcessAsyncSaveFinish();
02463 }
02464 
02473 static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
02474 {
02475   assert(!_sl.saveinprogress);
02476 
02477   _sl.dumper = new MemoryDumper();
02478   _sl.sf = writer;
02479 
02480   _sl_version = SAVEGAME_VERSION;
02481 
02482   SaveViewportBeforeSaveGame();
02483   SlSaveChunks();
02484 
02485   SaveFileStart();
02486   if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
02487     if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
02488 
02489     SaveOrLoadResult result = SaveFileToDisk(false);
02490     SaveFileDone();
02491 
02492     return result;
02493   }
02494 
02495   return SL_OK;
02496 }
02497 
02504 SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
02505 {
02506   try {
02507     _sl.action = SLA_SAVE;
02508     return DoSave(writer, threaded);
02509   } catch (...) {
02510     ClearSaveLoadState();
02511     return SL_ERROR;
02512   }
02513 }
02514 
02521 static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
02522 {
02523   _sl.lf = reader;
02524 
02525   if (load_check) {
02526     /* Clear previous check data */
02527     _load_check_data.Clear();
02528     /* Mark SL_LOAD_CHECK as supported for this savegame. */
02529     _load_check_data.checkable = true;
02530   }
02531 
02532   uint32 hdr[2];
02533   if (_sl.lf->Read((byte*)hdr, sizeof(hdr)) != sizeof(hdr)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
02534 
02535   /* see if we have any loader for this type. */
02536   const SaveLoadFormat *fmt = _saveload_formats;
02537   for (;;) {
02538     /* No loader found, treat as version 0 and use LZO format */
02539     if (fmt == endof(_saveload_formats)) {
02540       DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format");
02541       _sl.lf->Reset();
02542       _sl_version = 0;
02543       _sl_minor_version = 0;
02544 
02545       /* Try to find the LZO savegame format; it uses 'OTTD' as tag. */
02546       fmt = _saveload_formats;
02547       for (;;) {
02548         if (fmt == endof(_saveload_formats)) {
02549           /* Who removed LZO support? Bad bad boy! */
02550           NOT_REACHED();
02551         }
02552         if (fmt->tag == TO_BE32X('OTTD')) break;
02553         fmt++;
02554       }
02555       break;
02556     }
02557 
02558     if (fmt->tag == hdr[0]) {
02559       /* check version number */
02560       _sl_version = TO_BE32(hdr[1]) >> 16;
02561       /* Minor is not used anymore from version 18.0, but it is still needed
02562        * in versions before that (4 cases) which can't be removed easy.
02563        * Therefor it is loaded, but never saved (or, it saves a 0 in any scenario). */
02564       _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
02565 
02566       DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
02567 
02568       /* Is the version higher than the current? */
02569       if (_sl_version > SAVEGAME_VERSION) SlError(STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME);
02570       break;
02571     }
02572 
02573     fmt++;
02574   }
02575 
02576   /* loader for this savegame type is not implemented? */
02577   if (fmt->init_load == NULL) {
02578     char err_str[64];
02579     snprintf(err_str, lengthof(err_str), "Loader for '%s' is not available.", fmt->name);
02580     SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
02581   }
02582 
02583   _sl.lf = fmt->init_load(_sl.lf);
02584   _sl.reader = new ReadBuffer(_sl.lf);
02585   _next_offs = 0;
02586 
02587   if (!load_check) {
02588     /* Old maps were hardcoded to 256x256 and thus did not contain
02589      * any mapsize information. Pre-initialize to 256x256 to not to
02590      * confuse old games */
02591     InitializeGame(256, 256, true, true);
02592 
02593     GamelogReset();
02594 
02595     if (IsSavegameVersionBefore(4)) {
02596       /*
02597        * NewGRFs were introduced between 0.3,4 and 0.3.5, which both
02598        * shared savegame version 4. Anything before that 'obviously'
02599        * does not have any NewGRFs. Between the introduction and
02600        * savegame version 41 (just before 0.5) the NewGRF settings
02601        * were not stored in the savegame and they were loaded by
02602        * using the settings from the main menu.
02603        * So, to recap:
02604        * - savegame version  <  4:  do not load any NewGRFs.
02605        * - savegame version >= 41:  load NewGRFs from savegame, which is
02606        *                            already done at this stage by
02607        *                            overwriting the main menu settings.
02608        * - other savegame versions: use main menu settings.
02609        *
02610        * This means that users *can* crash savegame version 4..40
02611        * savegames if they set incompatible NewGRFs in the main menu,
02612        * but can't crash anymore for savegame version < 4 savegames.
02613        *
02614        * Note: this is done here because AfterLoadGame is also called
02615        * for TTO/TTD/TTDP savegames which have their own NewGRF logic.
02616        */
02617       ClearGRFConfigList(&_grfconfig);
02618     }
02619   }
02620 
02621   if (load_check) {
02622     /* Load chunks into _load_check_data.
02623      * No pools are loaded. References are not possible, and thus do not need resolving. */
02624     SlLoadCheckChunks();
02625   } else {
02626     /* Load chunks and resolve references */
02627     SlLoadChunks();
02628     SlFixPointers();
02629   }
02630 
02631   ClearSaveLoadState();
02632 
02633   _savegame_type = SGT_OTTD;
02634 
02635   if (load_check) {
02636     /* The only part from AfterLoadGame() we need */
02637     _load_check_data.grf_compatibility = IsGoodGRFConfigList(_load_check_data.grfconfig);
02638   } else {
02639     GamelogStartAction(GLAT_LOAD);
02640 
02641     /* After loading fix up savegame for any internal changes that
02642      * might have occurred since then. If it fails, load back the old game. */
02643     if (!AfterLoadGame()) {
02644       GamelogStopAction();
02645       return SL_REINIT;
02646     }
02647 
02648     GamelogStopAction();
02649   }
02650 
02651   return SL_OK;
02652 }
02653 
02659 SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
02660 {
02661   try {
02662     _sl.action = SLA_LOAD;
02663     return DoLoad(reader, false);
02664   } catch (...) {
02665     ClearSaveLoadState();
02666     return SL_REINIT;
02667   }
02668 }
02669 
02679 SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
02680 {
02681   /* An instance of saving is already active, so don't go saving again */
02682   if (_sl.saveinprogress && mode == SL_SAVE && threaded) {
02683     /* if not an autosave, but a user action, show error message */
02684     if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
02685     return SL_OK;
02686   }
02687   WaitTillSaved();
02688 
02689   /* Load a TTDLX or TTDPatch game */
02690   if (mode == SL_OLD_LOAD) {
02691     InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
02692 
02693     /* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
02694      * and if so a new NewGRF list will be made in LoadOldSaveGame.
02695      * Note: this is done here because AfterLoadGame is also called
02696      * for OTTD savegames which have their own NewGRF logic. */
02697     ClearGRFConfigList(&_grfconfig);
02698     GamelogReset();
02699     if (!LoadOldSaveGame(filename)) return SL_REINIT;
02700     _sl_version = 0;
02701     _sl_minor_version = 0;
02702     GamelogStartAction(GLAT_LOAD);
02703     if (!AfterLoadGame()) {
02704       GamelogStopAction();
02705       return SL_REINIT;
02706     }
02707     GamelogStopAction();
02708     return SL_OK;
02709   }
02710 
02711   switch (mode) {
02712     case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
02713     case SL_LOAD: _sl.action = SLA_LOAD; break;
02714     case SL_SAVE: _sl.action = SLA_SAVE; break;
02715     default: NOT_REACHED();
02716   }
02717 
02718   try {
02719     FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
02720 
02721     /* Make it a little easier to load savegames from the console */
02722     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
02723     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
02724     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SCENARIO_DIR);
02725 
02726     if (fh == NULL) {
02727       SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
02728     }
02729 
02730     if (mode == SL_SAVE) { // SAVE game
02731       DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
02732       if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
02733 
02734       return DoSave(new FileWriter(fh), threaded);
02735     }
02736 
02737     /* LOAD game */
02738     assert(mode == SL_LOAD || mode == SL_LOAD_CHECK);
02739     DEBUG(desync, 1, "load: %s", filename);
02740     return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK);
02741   } catch (...) {
02742     ClearSaveLoadState();
02743 
02744     /* Skip the "colour" character */
02745     if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
02746 
02747     /* A saver/loader exception!! reinitialize all variables to prevent crash! */
02748     return (mode == SL_LOAD) ? SL_REINIT : SL_ERROR;
02749   }
02750 }
02751 
02753 void DoExitSave()
02754 {
02755   SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
02756 }
02757 
02763 void GenerateDefaultSaveName(char *buf, const char *last)
02764 {
02765   /* Check if we have a name for this map, which is the name of the first
02766    * available company. When there's no company available we'll use
02767    * 'Spectator' as "company" name. */
02768   CompanyID cid = _local_company;
02769   if (!Company::IsValidID(cid)) {
02770     const Company *c;
02771     FOR_ALL_COMPANIES(c) {
02772       cid = c->index;
02773       break;
02774     }
02775   }
02776 
02777   SetDParam(0, cid);
02778 
02779   /* Insert current date */
02780   switch (_settings_client.gui.date_format_in_default_names) {
02781     case 0: SetDParam(1, STR_JUST_DATE_LONG); break;
02782     case 1: SetDParam(1, STR_JUST_DATE_TINY); break;
02783     case 2: SetDParam(1, STR_JUST_DATE_ISO); break;
02784     default: NOT_REACHED();
02785   }
02786   SetDParam(2, _date);
02787 
02788   /* Get the correct string (special string for when there's not company) */
02789   GetString(buf, !Company::IsValidID(cid) ? STR_SAVEGAME_NAME_SPECTATOR : STR_SAVEGAME_NAME_DEFAULT, last);
02790   SanitizeFilename(buf);
02791 }
02792 
02793 #if 0
02794 
02800 int GetSavegameType(char *file)
02801 {
02802   const SaveLoadFormat *fmt;
02803   uint32 hdr;
02804   FILE *f;
02805   int mode = SL_OLD_LOAD;
02806 
02807   f = fopen(file, "rb");
02808   if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
02809     DEBUG(sl, 0, "Savegame is obsolete or invalid format");
02810     mode = SL_LOAD; // don't try to get filename, just show name as it is written
02811   } else {
02812     /* see if we have any loader for this type. */
02813     for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
02814       if (fmt->tag == hdr) {
02815         mode = SL_LOAD; // new type of savegame
02816         break;
02817       }
02818     }
02819   }
02820 
02821   fclose(f);
02822   return mode;
02823 }
02824 #endif