saveload.cpp

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