saveload.cpp

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

Generated on Fri Feb 18 21:53:45 2011 for OpenTTD by  doxygen 1.6.1