saveload.cpp

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