saveload.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00024 #include "../stdafx.h"
00025 #include "../debug.h"
00026 #include "../station_base.h"
00027 #include "../thread/thread.h"
00028 #include "../town.h"
00029 #include "../network/network.h"
00030 #include "../window_func.h"
00031 #include "../strings_func.h"
00032 #include "../core/endian_func.hpp"
00033 #include "../vehicle_base.h"
00034 #include "../company_func.h"
00035 #include "../date_func.h"
00036 #include "../autoreplace_base.h"
00037 #include "../roadstop_base.h"
00038 #include "../statusbar_gui.h"
00039 #include "../fileio_func.h"
00040 #include "../gamelog.h"
00041 #include "../string_func.h"
00042 #include "../engine_base.h"
00043 #include "../fios.h"
00044 #include "../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  */
00226 extern const uint16 SAVEGAME_VERSION = 157; 
00227 
00228 SavegameType _savegame_type; 
00229 
00230 uint32 _ttdp_version;     
00231 uint16 _sl_version;       
00232 byte   _sl_minor_version; 
00233 char _savegame_format[8]; 
00234 bool _do_autosave;        
00235 
00237 enum SaveLoadAction {
00238   SLA_LOAD,        
00239   SLA_SAVE,        
00240   SLA_PTRS,        
00241   SLA_NULL,        
00242   SLA_LOAD_CHECK,  
00243 };
00244 
00245 enum NeedLength {
00246   NL_NONE = 0,       
00247   NL_WANTLENGTH = 1, 
00248   NL_CALCLENGTH = 2, 
00249 };
00250 
00252 static const size_t MEMORY_CHUNK_SIZE = 128 * 1024;
00253 
00255 struct ReadBuffer {
00256   byte buf[MEMORY_CHUNK_SIZE]; 
00257   byte *bufp;                  
00258   byte *bufe;                  
00259   LoadFilter *reader;          
00260   size_t read;                 
00261 
00266   ReadBuffer(LoadFilter *reader) : bufp(NULL), bufe(NULL), reader(reader), read(0)
00267   {
00268   }
00269 
00270   FORCEINLINE byte ReadByte()
00271   {
00272     if (this->bufp == this->bufe) {
00273       size_t len = this->reader->Read(this->buf, lengthof(this->buf));
00274       if (len == 0) SlErrorCorrupt("Unexpected end of chunk");
00275 
00276       this->read += len;
00277       this->bufp = this->buf;
00278       this->bufe = this->buf + len;
00279     }
00280 
00281     return *this->bufp++;
00282   }
00283 
00288   size_t GetSize() const
00289   {
00290     return this->read - (this->bufe - this->bufp);
00291   }
00292 };
00293 
00294 
00296 struct MemoryDumper {
00297   AutoFreeSmallVector<byte *, 16> blocks; 
00298   byte *buf;                              
00299   byte *bufe;                             
00300 
00302   MemoryDumper() : buf(NULL), bufe(NULL)
00303   {
00304   }
00305 
00310   FORCEINLINE void WriteByte(byte b)
00311   {
00312     /* Are we at the end of this chunk? */
00313     if (this->buf == this->bufe) {
00314       this->buf = CallocT<byte>(MEMORY_CHUNK_SIZE);
00315       *this->blocks.Append() = this->buf;
00316       this->bufe = this->buf + MEMORY_CHUNK_SIZE;
00317     }
00318 
00319     *this->buf++ = b;
00320   }
00321 
00326   void Flush(SaveFilter *writer)
00327   {
00328     uint i = 0;
00329     size_t t = this->GetSize();
00330 
00331     while (t > 0) {
00332       size_t to_write = min(MEMORY_CHUNK_SIZE, t);
00333 
00334       writer->Write(this->blocks[i++], to_write);
00335       t -= to_write;
00336     }
00337 
00338     writer->Finish();
00339   }
00340 
00345   size_t GetSize() const
00346   {
00347     return this->blocks.Length() * MEMORY_CHUNK_SIZE - (this->bufe - this->buf);
00348   }
00349 };
00350 
00352 struct SaveLoadParams {
00353   SaveLoadAction action;               
00354   NeedLength need_length;              
00355   byte block_mode;                     
00356   bool error;                          
00357 
00358   size_t obj_len;                      
00359   int array_index, last_array_index;   
00360 
00361   MemoryDumper *dumper;                
00362   SaveFilter *sf;                      
00363 
00364   ReadBuffer *reader;                  
00365   LoadFilter *lf;                      
00366 
00367   StringID error_str;                  
00368   char *extra_msg;                     
00369 
00370   byte ff_state;                       
00371   bool saveinprogress;                 
00372 };
00373 
00374 static SaveLoadParams _sl; 
00375 
00376 /* these define the chunks */
00377 extern const ChunkHandler _gamelog_chunk_handlers[];
00378 extern const ChunkHandler _map_chunk_handlers[];
00379 extern const ChunkHandler _misc_chunk_handlers[];
00380 extern const ChunkHandler _name_chunk_handlers[];
00381 extern const ChunkHandler _cheat_chunk_handlers[] ;
00382 extern const ChunkHandler _setting_chunk_handlers[];
00383 extern const ChunkHandler _company_chunk_handlers[];
00384 extern const ChunkHandler _engine_chunk_handlers[];
00385 extern const ChunkHandler _veh_chunk_handlers[];
00386 extern const ChunkHandler _waypoint_chunk_handlers[];
00387 extern const ChunkHandler _depot_chunk_handlers[];
00388 extern const ChunkHandler _order_chunk_handlers[];
00389 extern const ChunkHandler _town_chunk_handlers[];
00390 extern const ChunkHandler _sign_chunk_handlers[];
00391 extern const ChunkHandler _station_chunk_handlers[];
00392 extern const ChunkHandler _industry_chunk_handlers[];
00393 extern const ChunkHandler _economy_chunk_handlers[];
00394 extern const ChunkHandler _subsidy_chunk_handlers[];
00395 extern const ChunkHandler _ai_chunk_handlers[];
00396 extern const ChunkHandler _animated_tile_chunk_handlers[];
00397 extern const ChunkHandler _newgrf_chunk_handlers[];
00398 extern const ChunkHandler _group_chunk_handlers[];
00399 extern const ChunkHandler _cargopacket_chunk_handlers[];
00400 extern const ChunkHandler _autoreplace_chunk_handlers[];
00401 extern const ChunkHandler _labelmaps_chunk_handlers[];
00402 extern const ChunkHandler _airport_chunk_handlers[];
00403 extern const ChunkHandler _object_chunk_handlers[];
00404 
00406 static const ChunkHandler * const _chunk_handlers[] = {
00407   _gamelog_chunk_handlers,
00408   _map_chunk_handlers,
00409   _misc_chunk_handlers,
00410   _name_chunk_handlers,
00411   _cheat_chunk_handlers,
00412   _setting_chunk_handlers,
00413   _veh_chunk_handlers,
00414   _waypoint_chunk_handlers,
00415   _depot_chunk_handlers,
00416   _order_chunk_handlers,
00417   _industry_chunk_handlers,
00418   _economy_chunk_handlers,
00419   _subsidy_chunk_handlers,
00420   _engine_chunk_handlers,
00421   _town_chunk_handlers,
00422   _sign_chunk_handlers,
00423   _station_chunk_handlers,
00424   _company_chunk_handlers,
00425   _ai_chunk_handlers,
00426   _animated_tile_chunk_handlers,
00427   _newgrf_chunk_handlers,
00428   _group_chunk_handlers,
00429   _cargopacket_chunk_handlers,
00430   _autoreplace_chunk_handlers,
00431   _labelmaps_chunk_handlers,
00432   _airport_chunk_handlers,
00433   _object_chunk_handlers,
00434   NULL,
00435 };
00436 
00441 #define FOR_ALL_CHUNK_HANDLERS(ch) \
00442   for (const ChunkHandler * const *chsc = _chunk_handlers; *chsc != NULL; chsc++) \
00443     for (const ChunkHandler *ch = *chsc; ch != NULL; ch = (ch->flags & CH_LAST) ? NULL : ch + 1)
00444 
00446 static void SlNullPointers()
00447 {
00448   _sl.action = SLA_NULL;
00449 
00450   DEBUG(sl, 1, "Nulling pointers");
00451 
00452   FOR_ALL_CHUNK_HANDLERS(ch) {
00453     if (ch->ptrs_proc != NULL) {
00454       DEBUG(sl, 2, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
00455       ch->ptrs_proc();
00456     }
00457   }
00458 
00459   DEBUG(sl, 1, "All pointers nulled");
00460 
00461   assert(_sl.action == SLA_NULL);
00462 }
00463 
00472 static void NORETURN SlError(StringID string, const char *extra_msg = NULL)
00473 {
00474   /* Distinguish between loading into _load_check_data vs. normal save/load. */
00475   if (_sl.action == SLA_LOAD_CHECK) {
00476     _load_check_data.error = string;
00477     free(_load_check_data.error_data);
00478     _load_check_data.error_data = (extra_msg == NULL) ? NULL : strdup(extra_msg);
00479   } else {
00480     _sl.error_str = string;
00481     free(_sl.extra_msg);
00482     _sl.extra_msg = (extra_msg == NULL) ? NULL : strdup(extra_msg);
00483     /* We have to NULL all pointers here; we might be in a state where
00484      * the pointers are actually filled with indices, which means that
00485      * when we access them during cleaning the pool dereferences of
00486      * those indices will be made with segmentation faults as result. */
00487   }
00488   if (_sl.action == SLA_LOAD || _sl.action == SLA_PTRS) SlNullPointers();
00489   throw std::exception();
00490 }
00491 
00499 void NORETURN SlErrorCorrupt(const char *msg)
00500 {
00501   SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg);
00502 }
00503 
00504 
00505 typedef void (*AsyncSaveFinishProc)();                
00506 static AsyncSaveFinishProc _async_save_finish = NULL; 
00507 static ThreadObject *_save_thread;                    
00508 
00513 static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
00514 {
00515   if (_exit_game) return;
00516   while (_async_save_finish != NULL) CSleep(10);
00517 
00518   _async_save_finish = proc;
00519 }
00520 
00524 void ProcessAsyncSaveFinish()
00525 {
00526   if (_async_save_finish == NULL) return;
00527 
00528   _async_save_finish();
00529 
00530   _async_save_finish = NULL;
00531 
00532   if (_save_thread != NULL) {
00533     _save_thread->Join();
00534     delete _save_thread;
00535     _save_thread = NULL;
00536   }
00537 }
00538 
00543 byte SlReadByte()
00544 {
00545   return _sl.reader->ReadByte();
00546 }
00547 
00552 void SlWriteByte(byte b)
00553 {
00554   _sl.dumper->WriteByte(b);
00555 }
00556 
00557 static inline int SlReadUint16()
00558 {
00559   int x = SlReadByte() << 8;
00560   return x | SlReadByte();
00561 }
00562 
00563 static inline uint32 SlReadUint32()
00564 {
00565   uint32 x = SlReadUint16() << 16;
00566   return x | SlReadUint16();
00567 }
00568 
00569 static inline uint64 SlReadUint64()
00570 {
00571   uint32 x = SlReadUint32();
00572   uint32 y = SlReadUint32();
00573   return (uint64)x << 32 | y;
00574 }
00575 
00576 static inline void SlWriteUint16(uint16 v)
00577 {
00578   SlWriteByte(GB(v, 8, 8));
00579   SlWriteByte(GB(v, 0, 8));
00580 }
00581 
00582 static inline void SlWriteUint32(uint32 v)
00583 {
00584   SlWriteUint16(GB(v, 16, 16));
00585   SlWriteUint16(GB(v,  0, 16));
00586 }
00587 
00588 static inline void SlWriteUint64(uint64 x)
00589 {
00590   SlWriteUint32((uint32)(x >> 32));
00591   SlWriteUint32((uint32)x);
00592 }
00593 
00599 static inline void SlSkipBytes(size_t length)
00600 {
00601   for (; length != 0; length--) SlReadByte();
00602 }
00603 
00613 static uint SlReadSimpleGamma()
00614 {
00615   uint i = SlReadByte();
00616   if (HasBit(i, 7)) {
00617     i &= ~0x80;
00618     if (HasBit(i, 6)) {
00619       i &= ~0x40;
00620       if (HasBit(i, 5)) {
00621         i &= ~0x20;
00622         if (HasBit(i, 4)) {
00623           SlErrorCorrupt("Unsupported gamma");
00624         }
00625         i = (i << 8) | SlReadByte();
00626       }
00627       i = (i << 8) | SlReadByte();
00628     }
00629     i = (i << 8) | SlReadByte();
00630   }
00631   return i;
00632 }
00633 
00646 static void SlWriteSimpleGamma(size_t i)
00647 {
00648   if (i >= (1 << 7)) {
00649     if (i >= (1 << 14)) {
00650       if (i >= (1 << 21)) {
00651         assert(i < (1 << 28));
00652         SlWriteByte((byte)(0xE0 | (i >> 24)));
00653         SlWriteByte((byte)(i >> 16));
00654       } else {
00655         SlWriteByte((byte)(0xC0 | (i >> 16)));
00656       }
00657       SlWriteByte((byte)(i >> 8));
00658     } else {
00659       SlWriteByte((byte)(0x80 | (i >> 8)));
00660     }
00661   }
00662   SlWriteByte((byte)i);
00663 }
00664 
00666 static inline uint SlGetGammaLength(size_t i)
00667 {
00668   return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21));
00669 }
00670 
00671 static inline uint SlReadSparseIndex()
00672 {
00673   return SlReadSimpleGamma();
00674 }
00675 
00676 static inline void SlWriteSparseIndex(uint index)
00677 {
00678   SlWriteSimpleGamma(index);
00679 }
00680 
00681 static inline uint SlReadArrayLength()
00682 {
00683   return SlReadSimpleGamma();
00684 }
00685 
00686 static inline void SlWriteArrayLength(size_t length)
00687 {
00688   SlWriteSimpleGamma(length);
00689 }
00690 
00691 static inline uint SlGetArrayLength(size_t length)
00692 {
00693   return SlGetGammaLength(length);
00694 }
00695 
00702 static inline uint SlCalcConvMemLen(VarType conv)
00703 {
00704   static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
00705   byte length = GB(conv, 4, 4);
00706 
00707   switch (length << 4) {
00708     case SLE_VAR_STRB:
00709     case SLE_VAR_STRBQ:
00710     case SLE_VAR_STR:
00711     case SLE_VAR_STRQ:
00712       return SlReadArrayLength();
00713 
00714     default:
00715       assert(length < lengthof(conv_mem_size));
00716       return conv_mem_size[length];
00717   }
00718 }
00719 
00726 static inline byte SlCalcConvFileLen(VarType conv)
00727 {
00728   static const byte conv_file_size[] = {1, 1, 2, 2, 4, 4, 8, 8, 2};
00729   byte length = GB(conv, 0, 4);
00730   assert(length < lengthof(conv_file_size));
00731   return conv_file_size[length];
00732 }
00733 
00735 static inline size_t SlCalcRefLen()
00736 {
00737   return IsSavegameVersionBefore(69) ? 2 : 4;
00738 }
00739 
00740 void SlSetArrayIndex(uint index)
00741 {
00742   _sl.need_length = NL_WANTLENGTH;
00743   _sl.array_index = index;
00744 }
00745 
00746 static size_t _next_offs;
00747 
00752 int SlIterateArray()
00753 {
00754   int index;
00755 
00756   /* After reading in the whole array inside the loop
00757    * we must have read in all the data, so we must be at end of current block. */
00758   if (_next_offs != 0 && _sl.reader->GetSize() != _next_offs) SlErrorCorrupt("Invalid chunk size");
00759 
00760   while (true) {
00761     uint length = SlReadArrayLength();
00762     if (length == 0) {
00763       _next_offs = 0;
00764       return -1;
00765     }
00766 
00767     _sl.obj_len = --length;
00768     _next_offs = _sl.reader->GetSize() + length;
00769 
00770     switch (_sl.block_mode) {
00771       case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
00772       case CH_ARRAY:        index = _sl.array_index++; break;
00773       default:
00774         DEBUG(sl, 0, "SlIterateArray error");
00775         return -1; // error
00776     }
00777 
00778     if (length != 0) return index;
00779   }
00780 }
00781 
00785 void SlSkipArray()
00786 {
00787   while (SlIterateArray() != -1) {
00788     SlSkipBytes(_next_offs - _sl.reader->GetSize());
00789   }
00790 }
00791 
00797 void SlSetLength(size_t length)
00798 {
00799   assert(_sl.action == SLA_SAVE);
00800 
00801   switch (_sl.need_length) {
00802     case NL_WANTLENGTH:
00803       _sl.need_length = NL_NONE;
00804       switch (_sl.block_mode) {
00805         case CH_RIFF:
00806           /* Ugly encoding of >16M RIFF chunks
00807            * The lower 24 bits are normal
00808            * The uppermost 4 bits are bits 24:27 */
00809           assert(length < (1 << 28));
00810           SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
00811           break;
00812         case CH_ARRAY:
00813           assert(_sl.last_array_index <= _sl.array_index);
00814           while (++_sl.last_array_index <= _sl.array_index) {
00815             SlWriteArrayLength(1);
00816           }
00817           SlWriteArrayLength(length + 1);
00818           break;
00819         case CH_SPARSE_ARRAY:
00820           SlWriteArrayLength(length + 1 + SlGetArrayLength(_sl.array_index)); // Also include length of sparse index.
00821           SlWriteSparseIndex(_sl.array_index);
00822           break;
00823         default: NOT_REACHED();
00824       }
00825       break;
00826 
00827     case NL_CALCLENGTH:
00828       _sl.obj_len += (int)length;
00829       break;
00830 
00831     default: NOT_REACHED();
00832   }
00833 }
00834 
00841 static void SlCopyBytes(void *ptr, size_t length)
00842 {
00843   byte *p = (byte *)ptr;
00844 
00845   switch (_sl.action) {
00846     case SLA_LOAD_CHECK:
00847     case SLA_LOAD:
00848       for (; length != 0; length--) *p++ = SlReadByte();
00849       break;
00850     case SLA_SAVE:
00851       for (; length != 0; length--) SlWriteByte(*p++);
00852       break;
00853     default: NOT_REACHED();
00854   }
00855 }
00856 
00858 size_t SlGetFieldLength()
00859 {
00860   return _sl.obj_len;
00861 }
00862 
00870 int64 ReadValue(const void *ptr, VarType conv)
00871 {
00872   switch (GetVarMemType(conv)) {
00873     case SLE_VAR_BL:  return (*(bool *)ptr != 0);
00874     case SLE_VAR_I8:  return *(int8  *)ptr;
00875     case SLE_VAR_U8:  return *(byte  *)ptr;
00876     case SLE_VAR_I16: return *(int16 *)ptr;
00877     case SLE_VAR_U16: return *(uint16*)ptr;
00878     case SLE_VAR_I32: return *(int32 *)ptr;
00879     case SLE_VAR_U32: return *(uint32*)ptr;
00880     case SLE_VAR_I64: return *(int64 *)ptr;
00881     case SLE_VAR_U64: return *(uint64*)ptr;
00882     case SLE_VAR_NULL:return 0;
00883     default: NOT_REACHED();
00884   }
00885 }
00886 
00894 void WriteValue(void *ptr, VarType conv, int64 val)
00895 {
00896   switch (GetVarMemType(conv)) {
00897     case SLE_VAR_BL:  *(bool  *)ptr = (val != 0);  break;
00898     case SLE_VAR_I8:  *(int8  *)ptr = val; break;
00899     case SLE_VAR_U8:  *(byte  *)ptr = val; break;
00900     case SLE_VAR_I16: *(int16 *)ptr = val; break;
00901     case SLE_VAR_U16: *(uint16*)ptr = val; break;
00902     case SLE_VAR_I32: *(int32 *)ptr = val; break;
00903     case SLE_VAR_U32: *(uint32*)ptr = val; break;
00904     case SLE_VAR_I64: *(int64 *)ptr = val; break;
00905     case SLE_VAR_U64: *(uint64*)ptr = val; break;
00906     case SLE_VAR_NAME: *(char**)ptr = CopyFromOldName(val); break;
00907     case SLE_VAR_NULL: break;
00908     default: NOT_REACHED();
00909   }
00910 }
00911 
00920 static void SlSaveLoadConv(void *ptr, VarType conv)
00921 {
00922   switch (_sl.action) {
00923     case SLA_SAVE: {
00924       int64 x = ReadValue(ptr, conv);
00925 
00926       /* Write the value to the file and check if its value is in the desired range */
00927       switch (GetVarFileType(conv)) {
00928         case SLE_FILE_I8: assert(x >= -128 && x <= 127);     SlWriteByte(x);break;
00929         case SLE_FILE_U8: assert(x >= 0 && x <= 255);        SlWriteByte(x);break;
00930         case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break;
00931         case SLE_FILE_STRINGID:
00932         case SLE_FILE_U16:assert(x >= 0 && x <= 65535);      SlWriteUint16(x);break;
00933         case SLE_FILE_I32:
00934         case SLE_FILE_U32:                                   SlWriteUint32((uint32)x);break;
00935         case SLE_FILE_I64:
00936         case SLE_FILE_U64:                                   SlWriteUint64(x);break;
00937         default: NOT_REACHED();
00938       }
00939       break;
00940     }
00941     case SLA_LOAD_CHECK:
00942     case SLA_LOAD: {
00943       int64 x;
00944       /* Read a value from the file */
00945       switch (GetVarFileType(conv)) {
00946         case SLE_FILE_I8:  x = (int8  )SlReadByte();   break;
00947         case SLE_FILE_U8:  x = (byte  )SlReadByte();   break;
00948         case SLE_FILE_I16: x = (int16 )SlReadUint16(); break;
00949         case SLE_FILE_U16: x = (uint16)SlReadUint16(); break;
00950         case SLE_FILE_I32: x = (int32 )SlReadUint32(); break;
00951         case SLE_FILE_U32: x = (uint32)SlReadUint32(); break;
00952         case SLE_FILE_I64: x = (int64 )SlReadUint64(); break;
00953         case SLE_FILE_U64: x = (uint64)SlReadUint64(); break;
00954         case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break;
00955         default: NOT_REACHED();
00956       }
00957 
00958       /* Write The value to the struct. These ARE endian safe. */
00959       WriteValue(ptr, conv, x);
00960       break;
00961     }
00962     case SLA_PTRS: break;
00963     case SLA_NULL: break;
00964     default: NOT_REACHED();
00965   }
00966 }
00967 
00977 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
00978 {
00979   if (ptr == NULL) return 0;
00980   return min(strlen(ptr), length - 1);
00981 }
00982 
00992 static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
00993 {
00994   size_t len;
00995   const char *str;
00996 
00997   switch (GetVarMemType(conv)) {
00998     default: NOT_REACHED();
00999     case SLE_VAR_STR:
01000     case SLE_VAR_STRQ:
01001       str = *(const char**)ptr;
01002       len = SIZE_MAX;
01003       break;
01004     case SLE_VAR_STRB:
01005     case SLE_VAR_STRBQ:
01006       str = (const char*)ptr;
01007       len = length;
01008       break;
01009   }
01010 
01011   len = SlCalcNetStringLen(str, len);
01012   return len + SlGetArrayLength(len); // also include the length of the index
01013 }
01014 
01021 static void SlString(void *ptr, size_t length, VarType conv)
01022 {
01023   switch (_sl.action) {
01024     case SLA_SAVE: {
01025       size_t len;
01026       switch (GetVarMemType(conv)) {
01027         default: NOT_REACHED();
01028         case SLE_VAR_STRB:
01029         case SLE_VAR_STRBQ:
01030           len = SlCalcNetStringLen((char *)ptr, length);
01031           break;
01032         case SLE_VAR_STR:
01033         case SLE_VAR_STRQ:
01034           ptr = *(char **)ptr;
01035           len = SlCalcNetStringLen((char *)ptr, SIZE_MAX);
01036           break;
01037       }
01038 
01039       SlWriteArrayLength(len);
01040       SlCopyBytes(ptr, len);
01041       break;
01042     }
01043     case SLA_LOAD_CHECK:
01044     case SLA_LOAD: {
01045       size_t len = SlReadArrayLength();
01046 
01047       switch (GetVarMemType(conv)) {
01048         default: NOT_REACHED();
01049         case SLE_VAR_STRB:
01050         case SLE_VAR_STRBQ:
01051           if (len >= length) {
01052             DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
01053             SlCopyBytes(ptr, length);
01054             SlSkipBytes(len - length);
01055             len = length - 1;
01056           } else {
01057             SlCopyBytes(ptr, len);
01058           }
01059           break;
01060         case SLE_VAR_STR:
01061         case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate
01062           free(*(char **)ptr);
01063           if (len == 0) {
01064             *(char **)ptr = NULL;
01065           } else {
01066             *(char **)ptr = MallocT<char>(len + 1); // terminating '\0'
01067             ptr = *(char **)ptr;
01068             SlCopyBytes(ptr, len);
01069           }
01070           break;
01071       }
01072 
01073       ((char *)ptr)[len] = '\0'; // properly terminate the string
01074       str_validate((char *)ptr, (char *)ptr + len);
01075       break;
01076     }
01077     case SLA_PTRS: break;
01078     case SLA_NULL: break;
01079     default: NOT_REACHED();
01080   }
01081 }
01082 
01088 static inline size_t SlCalcArrayLen(size_t length, VarType conv)
01089 {
01090   return SlCalcConvFileLen(conv) * length;
01091 }
01092 
01099 void SlArray(void *array, size_t length, VarType conv)
01100 {
01101   if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
01102 
01103   /* Automatically calculate the length? */
01104   if (_sl.need_length != NL_NONE) {
01105     SlSetLength(SlCalcArrayLen(length, conv));
01106     /* Determine length only? */
01107     if (_sl.need_length == NL_CALCLENGTH) return;
01108   }
01109 
01110   /* NOTICE - handle some buggy stuff, in really old versions everything was saved
01111    * as a byte-type. So detect this, and adjust array size accordingly */
01112   if (_sl.action != SLA_SAVE && _sl_version == 0) {
01113     /* all arrays except difficulty settings */
01114     if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
01115         conv == SLE_INT32 || conv == SLE_UINT32) {
01116       SlCopyBytes(array, length * SlCalcConvFileLen(conv));
01117       return;
01118     }
01119     /* used for conversion of Money 32bit->64bit */
01120     if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
01121       for (uint i = 0; i < length; i++) {
01122         ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
01123       }
01124       return;
01125     }
01126   }
01127 
01128   /* If the size of elements is 1 byte both in file and memory, no special
01129    * conversion is needed, use specialized copy-copy function to speed up things */
01130   if (conv == SLE_INT8 || conv == SLE_UINT8) {
01131     SlCopyBytes(array, length);
01132   } else {
01133     byte *a = (byte*)array;
01134     byte mem_size = SlCalcConvMemLen(conv);
01135 
01136     for (; length != 0; length --) {
01137       SlSaveLoadConv(a, conv);
01138       a += mem_size; // get size
01139     }
01140   }
01141 }
01142 
01143 
01154 static size_t ReferenceToInt(const void *obj, SLRefType rt)
01155 {
01156   assert(_sl.action == SLA_SAVE);
01157 
01158   if (obj == NULL) return 0;
01159 
01160   switch (rt) {
01161     case REF_VEHICLE_OLD: // Old vehicles we save as new onces
01162     case REF_VEHICLE:   return ((const  Vehicle*)obj)->index + 1;
01163     case REF_STATION:   return ((const  Station*)obj)->index + 1;
01164     case REF_TOWN:      return ((const     Town*)obj)->index + 1;
01165     case REF_ORDER:     return ((const    Order*)obj)->index + 1;
01166     case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
01167     case REF_ENGINE_RENEWS: return ((const EngineRenew*)obj)->index + 1;
01168     case REF_CARGO_PACKET:  return ((const CargoPacket*)obj)->index + 1;
01169     case REF_ORDERLIST:     return ((const   OrderList*)obj)->index + 1;
01170     default: NOT_REACHED();
01171   }
01172 }
01173 
01184 static void *IntToReference(size_t index, SLRefType rt)
01185 {
01186   assert_compile(sizeof(size_t) <= sizeof(void *));
01187 
01188   assert(_sl.action == SLA_PTRS);
01189 
01190   /* After version 4.3 REF_VEHICLE_OLD is saved as REF_VEHICLE,
01191    * and should be loaded like that */
01192   if (rt == REF_VEHICLE_OLD && !IsSavegameVersionBefore(4, 4)) {
01193     rt = REF_VEHICLE;
01194   }
01195 
01196   /* No need to look up NULL pointers, just return immediately */
01197   if (index == (rt == REF_VEHICLE_OLD ? 0xFFFF : 0)) return NULL;
01198 
01199   /* Correct index. Old vehicles were saved differently:
01200    * invalid vehicle was 0xFFFF, now we use 0x0000 for everything invalid. */
01201   if (rt != REF_VEHICLE_OLD) index--;
01202 
01203   switch (rt) {
01204     case REF_ORDERLIST:
01205       if (OrderList::IsValidID(index)) return OrderList::Get(index);
01206       SlErrorCorrupt("Referencing invalid OrderList");
01207 
01208     case REF_ORDER:
01209       if (Order::IsValidID(index)) return Order::Get(index);
01210       /* in old versions, invalid order was used to mark end of order list */
01211       if (IsSavegameVersionBefore(5, 2)) return NULL;
01212       SlErrorCorrupt("Referencing invalid Order");
01213 
01214     case REF_VEHICLE_OLD:
01215     case REF_VEHICLE:
01216       if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
01217       SlErrorCorrupt("Referencing invalid Vehicle");
01218 
01219     case REF_STATION:
01220       if (Station::IsValidID(index)) return Station::Get(index);
01221       SlErrorCorrupt("Referencing invalid Station");
01222 
01223     case REF_TOWN:
01224       if (Town::IsValidID(index)) return Town::Get(index);
01225       SlErrorCorrupt("Referencing invalid Town");
01226 
01227     case REF_ROADSTOPS:
01228       if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
01229       SlErrorCorrupt("Referencing invalid RoadStop");
01230 
01231     case REF_ENGINE_RENEWS:
01232       if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
01233       SlErrorCorrupt("Referencing invalid EngineRenew");
01234 
01235     case REF_CARGO_PACKET:
01236       if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
01237       SlErrorCorrupt("Referencing invalid CargoPacket");
01238 
01239     default: NOT_REACHED();
01240   }
01241 }
01242 
01247 static inline size_t SlCalcListLen(const void *list)
01248 {
01249   std::list<void *> *l = (std::list<void *> *) list;
01250 
01251   int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
01252   /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
01253    * of the list */
01254   return l->size() * type_size + type_size;
01255 }
01256 
01257 
01263 static void SlList(void *list, SLRefType conv)
01264 {
01265   /* Automatically calculate the length? */
01266   if (_sl.need_length != NL_NONE) {
01267     SlSetLength(SlCalcListLen(list));
01268     /* Determine length only? */
01269     if (_sl.need_length == NL_CALCLENGTH) return;
01270   }
01271 
01272   typedef std::list<void *> PtrList;
01273   PtrList *l = (PtrList *)list;
01274 
01275   switch (_sl.action) {
01276     case SLA_SAVE: {
01277       SlWriteUint32((uint32)l->size());
01278 
01279       PtrList::iterator iter;
01280       for (iter = l->begin(); iter != l->end(); ++iter) {
01281         void *ptr = *iter;
01282         SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
01283       }
01284       break;
01285     }
01286     case SLA_LOAD_CHECK:
01287     case SLA_LOAD: {
01288       size_t length = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01289 
01290       /* Load each reference and push to the end of the list */
01291       for (size_t i = 0; i < length; i++) {
01292         size_t data = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01293         l->push_back((void *)data);
01294       }
01295       break;
01296     }
01297     case SLA_PTRS: {
01298       PtrList temp = *l;
01299 
01300       l->clear();
01301       PtrList::iterator iter;
01302       for (iter = temp.begin(); iter != temp.end(); ++iter) {
01303         void *ptr = IntToReference((size_t)*iter, conv);
01304         l->push_back(ptr);
01305       }
01306       break;
01307     }
01308     case SLA_NULL:
01309       l->clear();
01310       break;
01311     default: NOT_REACHED();
01312   }
01313 }
01314 
01315 
01317 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
01318 {
01319   if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
01320   if (sld->conv & SLF_SAVE_NO) return false;
01321 
01322   return true;
01323 }
01324 
01330 static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
01331 {
01332   if ((sld->conv & SLF_NETWORK_NO) && _sl.action != SLA_SAVE && _networking && !_network_server) {
01333     SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
01334     return true;
01335   }
01336 
01337   return false;
01338 }
01339 
01346 size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
01347 {
01348   size_t length = 0;
01349 
01350   /* Need to determine the length and write a length tag. */
01351   for (; sld->cmd != SL_END; sld++) {
01352     length += SlCalcObjMemberLength(object, sld);
01353   }
01354   return length;
01355 }
01356 
01357 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
01358 {
01359   assert(_sl.action == SLA_SAVE);
01360 
01361   switch (sld->cmd) {
01362     case SL_VAR:
01363     case SL_REF:
01364     case SL_ARR:
01365     case SL_STR:
01366     case SL_LST:
01367       /* CONDITIONAL saveload types depend on the savegame version */
01368       if (!SlIsObjectValidInSavegame(sld)) break;
01369 
01370       switch (sld->cmd) {
01371         case SL_VAR: return SlCalcConvFileLen(sld->conv);
01372         case SL_REF: return SlCalcRefLen();
01373         case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
01374         case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
01375         case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
01376         default: NOT_REACHED();
01377       }
01378       break;
01379     case SL_WRITEBYTE: return 1; // a byte is logically of size 1
01380     case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
01381     case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
01382     default: NOT_REACHED();
01383   }
01384   return 0;
01385 }
01386 
01387 
01388 bool SlObjectMember(void *ptr, const SaveLoad *sld)
01389 {
01390   VarType conv = GB(sld->conv, 0, 8);
01391   switch (sld->cmd) {
01392     case SL_VAR:
01393     case SL_REF:
01394     case SL_ARR:
01395     case SL_STR:
01396     case SL_LST:
01397       /* CONDITIONAL saveload types depend on the savegame version */
01398       if (!SlIsObjectValidInSavegame(sld)) return false;
01399       if (SlSkipVariableOnLoad(sld)) return false;
01400 
01401       switch (sld->cmd) {
01402         case SL_VAR: SlSaveLoadConv(ptr, conv); break;
01403         case SL_REF: // Reference variable, translate
01404           switch (_sl.action) {
01405             case SLA_SAVE:
01406               SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv));
01407               break;
01408             case SLA_LOAD_CHECK:
01409             case SLA_LOAD:
01410               *(size_t *)ptr = IsSavegameVersionBefore(69) ? SlReadUint16() : SlReadUint32();
01411               break;
01412             case SLA_PTRS:
01413               *(void **)ptr = IntToReference(*(size_t *)ptr, (SLRefType)conv);
01414               break;
01415             case SLA_NULL:
01416               *(void **)ptr = NULL;
01417               break;
01418             default: NOT_REACHED();
01419           }
01420           break;
01421         case SL_ARR: SlArray(ptr, sld->length, conv); break;
01422         case SL_STR: SlString(ptr, sld->length, conv); break;
01423         case SL_LST: SlList(ptr, (SLRefType)conv); break;
01424         default: NOT_REACHED();
01425       }
01426       break;
01427 
01428     /* SL_WRITEBYTE translates a value of a variable to another one upon
01429      * saving or loading.
01430      * XXX - variable renaming abuse
01431      * game_value: the value of the variable ingame is abused by sld->version_from
01432      * file_value: the value of the variable in the savegame is abused by sld->version_to */
01433     case SL_WRITEBYTE:
01434       switch (_sl.action) {
01435         case SLA_SAVE: SlWriteByte(sld->version_to); break;
01436         case SLA_LOAD_CHECK:
01437         case SLA_LOAD: *(byte *)ptr = sld->version_from; break;
01438         case SLA_PTRS: break;
01439         case SLA_NULL: break;
01440         default: NOT_REACHED();
01441       }
01442       break;
01443 
01444     /* SL_VEH_INCLUDE loads common code for vehicles */
01445     case SL_VEH_INCLUDE:
01446       SlObject(ptr, GetVehicleDescription(VEH_END));
01447       break;
01448 
01449     case SL_ST_INCLUDE:
01450       SlObject(ptr, GetBaseStationDescription());
01451       break;
01452 
01453     default: NOT_REACHED();
01454   }
01455   return true;
01456 }
01457 
01463 void SlObject(void *object, const SaveLoad *sld)
01464 {
01465   /* Automatically calculate the length? */
01466   if (_sl.need_length != NL_NONE) {
01467     SlSetLength(SlCalcObjLength(object, sld));
01468     if (_sl.need_length == NL_CALCLENGTH) return;
01469   }
01470 
01471   for (; sld->cmd != SL_END; sld++) {
01472     void *ptr = sld->global ? sld->address : GetVariableAddress(object, sld);
01473     SlObjectMember(ptr, sld);
01474   }
01475 }
01476 
01481 void SlGlobList(const SaveLoadGlobVarList *sldg)
01482 {
01483   SlObject(NULL, (const SaveLoad*)sldg);
01484 }
01485 
01491 void SlAutolength(AutolengthProc *proc, void *arg)
01492 {
01493   size_t offs;
01494 
01495   assert(_sl.action == SLA_SAVE);
01496 
01497   /* Tell it to calculate the length */
01498   _sl.need_length = NL_CALCLENGTH;
01499   _sl.obj_len = 0;
01500   proc(arg);
01501 
01502   /* Setup length */
01503   _sl.need_length = NL_WANTLENGTH;
01504   SlSetLength(_sl.obj_len);
01505 
01506   offs = _sl.dumper->GetSize() + _sl.obj_len;
01507 
01508   /* And write the stuff */
01509   proc(arg);
01510 
01511   if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
01512 }
01513 
01518 static void SlLoadChunk(const ChunkHandler *ch)
01519 {
01520   byte m = SlReadByte();
01521   size_t len;
01522   size_t endoffs;
01523 
01524   _sl.block_mode = m;
01525   _sl.obj_len = 0;
01526 
01527   switch (m) {
01528     case CH_ARRAY:
01529       _sl.array_index = 0;
01530       ch->load_proc();
01531       break;
01532     case CH_SPARSE_ARRAY:
01533       ch->load_proc();
01534       break;
01535     default:
01536       if ((m & 0xF) == CH_RIFF) {
01537         /* Read length */
01538         len = (SlReadByte() << 16) | ((m >> 4) << 24);
01539         len += SlReadUint16();
01540         _sl.obj_len = len;
01541         endoffs = _sl.reader->GetSize() + len;
01542         ch->load_proc();
01543         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
01544       } else {
01545         SlErrorCorrupt("Invalid chunk type");
01546       }
01547       break;
01548   }
01549 }
01550 
01556 static void SlLoadCheckChunk(const ChunkHandler *ch)
01557 {
01558   byte m = SlReadByte();
01559   size_t len;
01560   size_t endoffs;
01561 
01562   _sl.block_mode = m;
01563   _sl.obj_len = 0;
01564 
01565   switch (m) {
01566     case CH_ARRAY:
01567       _sl.array_index = 0;
01568       if (ch->load_check_proc) {
01569         ch->load_check_proc();
01570       } else {
01571         SlSkipArray();
01572       }
01573       break;
01574     case CH_SPARSE_ARRAY:
01575       if (ch->load_check_proc) {
01576         ch->load_check_proc();
01577       } else {
01578         SlSkipArray();
01579       }
01580       break;
01581     default:
01582       if ((m & 0xF) == CH_RIFF) {
01583         /* Read length */
01584         len = (SlReadByte() << 16) | ((m >> 4) << 24);
01585         len += SlReadUint16();
01586         _sl.obj_len = len;
01587         endoffs = _sl.reader->GetSize() + len;
01588         if (ch->load_check_proc) {
01589           ch->load_check_proc();
01590         } else {
01591           SlSkipBytes(len);
01592         }
01593         if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
01594       } else {
01595         SlErrorCorrupt("Invalid chunk type");
01596       }
01597       break;
01598   }
01599 }
01600 
01605 static ChunkSaveLoadProc *_stub_save_proc;
01606 
01612 static inline void SlStubSaveProc2(void *arg)
01613 {
01614   _stub_save_proc();
01615 }
01616 
01622 static void SlStubSaveProc()
01623 {
01624   SlAutolength(SlStubSaveProc2, NULL);
01625 }
01626 
01632 static void SlSaveChunk(const ChunkHandler *ch)
01633 {
01634   ChunkSaveLoadProc *proc = ch->save_proc;
01635 
01636   /* Don't save any chunk information if there is no save handler. */
01637   if (proc == NULL) return;
01638 
01639   SlWriteUint32(ch->id);
01640   DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
01641 
01642   if (ch->flags & CH_AUTO_LENGTH) {
01643     /* Need to calculate the length. Solve that by calling SlAutoLength in the save_proc. */
01644     _stub_save_proc = proc;
01645     proc = SlStubSaveProc;
01646   }
01647 
01648   _sl.block_mode = ch->flags & CH_TYPE_MASK;
01649   switch (ch->flags & CH_TYPE_MASK) {
01650     case CH_RIFF:
01651       _sl.need_length = NL_WANTLENGTH;
01652       proc();
01653       break;
01654     case CH_ARRAY:
01655       _sl.last_array_index = 0;
01656       SlWriteByte(CH_ARRAY);
01657       proc();
01658       SlWriteArrayLength(0); // Terminate arrays
01659       break;
01660     case CH_SPARSE_ARRAY:
01661       SlWriteByte(CH_SPARSE_ARRAY);
01662       proc();
01663       SlWriteArrayLength(0); // Terminate arrays
01664       break;
01665     default: NOT_REACHED();
01666   }
01667 }
01668 
01670 static void SlSaveChunks()
01671 {
01672   FOR_ALL_CHUNK_HANDLERS(ch) {
01673     SlSaveChunk(ch);
01674   }
01675 
01676   /* Terminator */
01677   SlWriteUint32(0);
01678 }
01679 
01686 static const ChunkHandler *SlFindChunkHandler(uint32 id)
01687 {
01688   FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch;
01689   return NULL;
01690 }
01691 
01693 static void SlLoadChunks()
01694 {
01695   uint32 id;
01696   const ChunkHandler *ch;
01697 
01698   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
01699     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
01700 
01701     ch = SlFindChunkHandler(id);
01702     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
01703     SlLoadChunk(ch);
01704   }
01705 }
01706 
01708 static void SlLoadCheckChunks()
01709 {
01710   uint32 id;
01711   const ChunkHandler *ch;
01712 
01713   for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
01714     DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id);
01715 
01716     ch = SlFindChunkHandler(id);
01717     if (ch == NULL) SlErrorCorrupt("Unknown chunk type");
01718     SlLoadCheckChunk(ch);
01719   }
01720 }
01721 
01723 static void SlFixPointers()
01724 {
01725   _sl.action = SLA_PTRS;
01726 
01727   DEBUG(sl, 1, "Fixing pointers");
01728 
01729   FOR_ALL_CHUNK_HANDLERS(ch) {
01730     if (ch->ptrs_proc != NULL) {
01731       DEBUG(sl, 2, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id);
01732       ch->ptrs_proc();
01733     }
01734   }
01735 
01736   DEBUG(sl, 1, "All pointers fixed");
01737 
01738   assert(_sl.action == SLA_PTRS);
01739 }
01740 
01741 
01743 struct FileReader : LoadFilter {
01744   FILE *file; 
01745   long begin; 
01746 
01751   FileReader(FILE *file) : LoadFilter(NULL), file(file), begin(ftell(file))
01752   {
01753   }
01754 
01756   ~FileReader()
01757   {
01758     if (this->file != NULL) fclose(this->file);
01759     this->file = NULL;
01760 
01761     /* Make sure we don't double free. */
01762     _sl.sf = NULL;
01763   }
01764 
01765   /* virtual */ size_t Read(byte *buf, size_t size)
01766   {
01767     /* We're in the process of shutting down, i.e. in "failure" mode. */
01768     if (this->file == NULL) return 0;
01769 
01770     return fread(buf, 1, size, this->file);
01771   }
01772 
01773   /* virtual */ void Reset()
01774   {
01775     clearerr(this->file);
01776     fseek(this->file, this->begin, SEEK_SET);
01777   }
01778 };
01779 
01781 struct FileWriter : SaveFilter {
01782   FILE *file; 
01783 
01788   FileWriter(FILE *file) : SaveFilter(NULL), file(file)
01789   {
01790   }
01791 
01793   ~FileWriter()
01794   {
01795     this->Finish();
01796 
01797     /* Make sure we don't double free. */
01798     _sl.sf = NULL;
01799   }
01800 
01801   /* virtual */ void Write(byte *buf, size_t size)
01802   {
01803     /* We're in the process of shutting down, i.e. in "failure" mode. */
01804     if (this->file == NULL) return;
01805 
01806     if (fwrite(buf, 1, size, this->file) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
01807   }
01808 
01809   /* virtual */ void Finish()
01810   {
01811     if (this->file != NULL) fclose(this->file);
01812     this->file = NULL;
01813   }
01814 };
01815 
01816 /*******************************************
01817  ********** START OF LZO CODE **************
01818  *******************************************/
01819 
01820 #ifdef WITH_LZO
01821 #include <lzo/lzo1x.h>
01822 
01824 static const uint LZO_BUFFER_SIZE = 8192;
01825 
01827 struct LZOLoadFilter : LoadFilter {
01832   LZOLoadFilter(LoadFilter *chain) : LoadFilter(chain)
01833   {
01834     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
01835   }
01836 
01837   /* virtual */ size_t Read(byte *buf, size_t ssize)
01838   {
01839     assert(ssize >= LZO_BUFFER_SIZE);
01840 
01841     /* Buffer size is from the LZO docs plus the chunk header size. */
01842     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
01843     uint32 tmp[2];
01844     uint32 size;
01845     lzo_uint len;
01846 
01847     /* Read header*/
01848     if (this->chain->Read((byte*)tmp, sizeof(tmp)) != sizeof(tmp)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE, "File read failed");
01849 
01850     /* Check if size is bad */
01851     ((uint32*)out)[0] = size = tmp[1];
01852 
01853     if (_sl_version != 0) {
01854       tmp[0] = TO_BE32(tmp[0]);
01855       size = TO_BE32(size);
01856     }
01857 
01858     if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size");
01859 
01860     /* Read block */
01861     if (this->chain->Read(out + sizeof(uint32), size) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
01862 
01863     /* Verify checksum */
01864     if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
01865 
01866     /* Decompress */
01867     lzo1x_decompress(out + sizeof(uint32) * 1, size, buf, &len, NULL);
01868     return len;
01869   }
01870 };
01871 
01873 struct LZOSaveFilter : SaveFilter {
01879   LZOSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
01880   {
01881     if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
01882   }
01883 
01884   /* virtual */ void Write(byte *buf, size_t size)
01885   {
01886     const lzo_bytep in = buf;
01887     /* Buffer size is from the LZO docs plus the chunk header size. */
01888     byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
01889     byte wrkmem[LZO1X_1_MEM_COMPRESS];
01890     lzo_uint outlen;
01891 
01892     do {
01893       /* Compress up to LZO_BUFFER_SIZE bytes at once. */
01894       lzo_uint len = size > LZO_BUFFER_SIZE ? LZO_BUFFER_SIZE : (lzo_uint)size;
01895       lzo1x_1_compress(in, len, out + sizeof(uint32) * 2, &outlen, wrkmem);
01896       ((uint32*)out)[1] = TO_BE32((uint32)outlen);
01897       ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
01898       this->chain->Write(out, outlen + sizeof(uint32) * 2);
01899 
01900       /* Move to next data chunk. */
01901       size -= len;
01902       in += len;
01903     } while (size > 0);
01904   }
01905 };
01906 
01907 #endif /* WITH_LZO */
01908 
01909 /*********************************************
01910  ******** START OF NOCOMP CODE (uncompressed)*
01911  *********************************************/
01912 
01914 struct NoCompLoadFilter : LoadFilter {
01919   NoCompLoadFilter(LoadFilter *chain) : LoadFilter(chain)
01920   {
01921   }
01922 
01923   /* virtual */ size_t Read(byte *buf, size_t size)
01924   {
01925     return this->chain->Read(buf, size);
01926   }
01927 };
01928 
01930 struct NoCompSaveFilter : SaveFilter {
01936   NoCompSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
01937   {
01938   }
01939 
01940   /* virtual */ void Write(byte *buf, size_t size)
01941   {
01942     this->chain->Write(buf, size);
01943   }
01944 };
01945 
01946 /********************************************
01947  ********** START OF ZLIB CODE **************
01948  ********************************************/
01949 
01950 #if defined(WITH_ZLIB)
01951 #include <zlib.h>
01952 
01954 struct ZlibLoadFilter : LoadFilter {
01955   z_stream z;                        
01956   byte fread_buf[MEMORY_CHUNK_SIZE]; 
01957 
01962   ZlibLoadFilter(LoadFilter *chain) : LoadFilter(chain)
01963   {
01964     memset(&this->z, 0, sizeof(this->z));
01965     if (inflateInit(&this->z) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
01966   }
01967 
01969   ~ZlibLoadFilter()
01970   {
01971     inflateEnd(&this->z);
01972   }
01973 
01974   /* virtual */ size_t Read(byte *buf, size_t size)
01975   {
01976     this->z.next_out  = buf;
01977     this->z.avail_out = (uint)size;
01978 
01979     do {
01980       /* read more bytes from the file? */
01981       if (this->z.avail_in == 0) {
01982         this->z.next_in = this->fread_buf;
01983         this->z.avail_in = (uint)this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
01984       }
01985 
01986       /* inflate the data */
01987       int r = inflate(&this->z, 0);
01988       if (r == Z_STREAM_END) break;
01989 
01990       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "inflate() failed");
01991     } while (this->z.avail_out != 0);
01992 
01993     return size - this->z.avail_out;
01994   }
01995 };
01996 
01998 struct ZlibSaveFilter : SaveFilter {
01999   z_stream z; 
02000 
02006   ZlibSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
02007   {
02008     memset(&this->z, 0, sizeof(this->z));
02009     if (deflateInit(&this->z, compression_level) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
02010   }
02011 
02018   void WriteLoop(byte *p, size_t len, int mode)
02019   {
02020     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
02021     uint n;
02022     this->z.next_in = p;
02023     this->z.avail_in = (uInt)len;
02024     do {
02025       this->z.next_out = buf;
02026       this->z.avail_out = sizeof(buf);
02027 
02035       int r = deflate(&this->z, mode);
02036 
02037       /* bytes were emitted? */
02038       if ((n = sizeof(buf) - this->z.avail_out) != 0) {
02039         this->chain->Write(buf, n);
02040       }
02041       if (r == Z_STREAM_END) break;
02042 
02043       if (r != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "zlib returned error code");
02044     } while (this->z.avail_in || !this->z.avail_out);
02045   }
02046 
02047   /* virtual */ void Write(byte *buf, size_t size)
02048   {
02049     this->WriteLoop(buf, size, 0);
02050   }
02051 
02052   /* virtual */ void Finish()
02053   {
02054     this->WriteLoop(NULL, 0, Z_FINISH);
02055     this->chain->Finish();
02056     deflateEnd(&this->z);
02057   }
02058 };
02059 
02060 #endif /* WITH_ZLIB */
02061 
02062 /********************************************
02063  ********** START OF LZMA CODE **************
02064  ********************************************/
02065 
02066 #if defined(WITH_LZMA)
02067 #include <lzma.h>
02068 
02075 static const lzma_stream _lzma_init = LZMA_STREAM_INIT;
02076 
02078 struct LZMALoadFilter : LoadFilter {
02079   lzma_stream lzma;                  
02080   byte fread_buf[MEMORY_CHUNK_SIZE]; 
02081 
02086   LZMALoadFilter(LoadFilter *chain) : LoadFilter(chain), lzma(_lzma_init)
02087   {
02088     /* Allow saves up to 256 MB uncompressed */
02089     if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
02090   }
02091 
02093   ~LZMALoadFilter()
02094   {
02095     lzma_end(&this->lzma);
02096   }
02097 
02098   /* virtual */ size_t Read(byte *buf, size_t size)
02099   {
02100     this->lzma.next_out  = buf;
02101     this->lzma.avail_out = size;
02102 
02103     do {
02104       /* read more bytes from the file? */
02105       if (this->lzma.avail_in == 0) {
02106         this->lzma.next_in  = this->fread_buf;
02107         this->lzma.avail_in = this->chain->Read(this->fread_buf, sizeof(this->fread_buf));
02108       }
02109 
02110       /* inflate the data */
02111       lzma_ret r = lzma_code(&this->lzma, LZMA_RUN);
02112       if (r == LZMA_STREAM_END) break;
02113       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
02114     } while (this->lzma.avail_out != 0);
02115 
02116     return size - this->lzma.avail_out;
02117   }
02118 };
02119 
02121 struct LZMASaveFilter : SaveFilter {
02122   lzma_stream lzma; 
02123 
02129   LZMASaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain), lzma(_lzma_init)
02130   {
02131     if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
02132   }
02133 
02140   void WriteLoop(byte *p, size_t len, lzma_action action)
02141   {
02142     byte buf[MEMORY_CHUNK_SIZE]; // output buffer
02143     size_t n;
02144     this->lzma.next_in = p;
02145     this->lzma.avail_in = len;
02146     do {
02147       this->lzma.next_out = buf;
02148       this->lzma.avail_out = sizeof(buf);
02149 
02150       lzma_ret r = lzma_code(&this->lzma, action);
02151 
02152       /* bytes were emitted? */
02153       if ((n = sizeof(buf) - this->lzma.avail_out) != 0) {
02154         this->chain->Write(buf, n);
02155       }
02156       if (r == LZMA_STREAM_END) break;
02157       if (r != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "liblzma returned error code");
02158     } while (this->lzma.avail_in || !this->lzma.avail_out);
02159   }
02160 
02161   /* virtual */ void Write(byte *buf, size_t size)
02162   {
02163     this->WriteLoop(buf, size, LZMA_RUN);
02164   }
02165 
02166   /* virtual */ void Finish()
02167   {
02168     this->WriteLoop(NULL, 0, LZMA_FINISH);
02169     this->chain->Finish();
02170     lzma_end(&this->lzma);
02171   }
02172 };
02173 
02174 #endif /* WITH_LZMA */
02175 
02176 /*******************************************
02177  ************* END OF CODE *****************
02178  *******************************************/
02179 
02181 struct SaveLoadFormat {
02182   const char *name;                     
02183   uint32 tag;                           
02184 
02185   LoadFilter *(*init_load)(LoadFilter *chain);                    
02186   SaveFilter *(*init_write)(SaveFilter *chain, byte compression); 
02187 
02188   byte min_compression;                 
02189   byte default_compression;             
02190   byte max_compression;                 
02191 };
02192 
02194 static const SaveLoadFormat _saveload_formats[] = {
02195 #if defined(WITH_LZO)
02196   /* Roughly 75% larger than zlib level 6 at only ~7% of the CPU usage. */
02197   {"lzo",    TO_BE32X('OTTD'), CreateLoadFilter<LZOLoadFilter>,    CreateSaveFilter<LZOSaveFilter>,    0, 0, 0},
02198 #else
02199   {"lzo",    TO_BE32X('OTTD'), NULL,                               NULL,                               0, 0, 0},
02200 #endif
02201   /* Roughly 5 times larger at only 1% of the CPU usage over zlib level 6. */
02202   {"none",   TO_BE32X('OTTN'), CreateLoadFilter<NoCompLoadFilter>, CreateSaveFilter<NoCompSaveFilter>, 0, 0, 0},
02203 #if defined(WITH_ZLIB)
02204   /* After level 6 the speed reduction is significant (1.5x to 2.5x slower per level), but the reduction in filesize is
02205    * fairly insignificant (~1% for each step). Lower levels become ~5-10% bigger by each level than level 6 while level
02206    * 1 is "only" 3 times as fast. Level 0 results in uncompressed savegames at about 8 times the cost of "none". */
02207   {"zlib",   TO_BE32X('OTTZ'), CreateLoadFilter<ZlibLoadFilter>,   CreateSaveFilter<ZlibSaveFilter>,   0, 6, 9},
02208 #else
02209   {"zlib",   TO_BE32X('OTTZ'), NULL,                               NULL,                               0, 0, 0},
02210 #endif
02211 #if defined(WITH_LZMA)
02212   /* Level 2 compression is speed wise as fast as zlib level 6 compression (old default), but results in ~10% smaller saves.
02213    * Higher compression levels are possible, and might improve savegame size by up to 25%, but are also up to 10 times slower.
02214    * The next significant reduction in file size is at level 4, but that is already 4 times slower. Level 3 is primarily 50%
02215    * slower while not improving the filesize, while level 0 and 1 are faster, but don't reduce savegame size much.
02216    * It's OTTX and not e.g. OTTL because liblzma is part of xz-utils and .tar.xz is prefered over .tar.lzma. */
02217   {"lzma",   TO_BE32X('OTTX'), CreateLoadFilter<LZMALoadFilter>,   CreateSaveFilter<LZMASaveFilter>,   0, 2, 9},
02218 #else
02219   {"lzma",   TO_BE32X('OTTX'), NULL,                               NULL,                               0, 0, 0},
02220 #endif
02221 };
02222 
02230 static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
02231 {
02232   const SaveLoadFormat *def = lastof(_saveload_formats);
02233 
02234   /* find default savegame format, the highest one with which files can be written */
02235   while (!def->init_write) def--;
02236 
02237   if (!StrEmpty(s)) {
02238     /* Get the ":..." of the compression level out of the way */
02239     char *complevel = strrchr(s, ':');
02240     if (complevel != NULL) *complevel = '\0';
02241 
02242     for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
02243       if (slf->init_write != NULL && strcmp(s, slf->name) == 0) {
02244         *compression_level = slf->default_compression;
02245         if (complevel != NULL) {
02246           /* There is a compression level in the string.
02247            * First restore the : we removed to do proper name matching,
02248            * then move the the begin of the actual version. */
02249           *complevel = ':';
02250           complevel++;
02251 
02252           /* Get the version and determine whether all went fine. */
02253           char *end;
02254           long level = strtol(complevel, &end, 10);
02255           if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) {
02256             ShowInfoF("Compression level '%s' is not valid.", complevel);
02257           } else {
02258             *compression_level = level;
02259           }
02260         }
02261         return slf;
02262       }
02263     }
02264 
02265     ShowInfoF("Savegame format '%s' is not available. Reverting to '%s'.", s, def->name);
02266 
02267     /* Restore the string by adding the : back */
02268     if (complevel != NULL) *complevel = ':';
02269   }
02270   *compression_level = def->default_compression;
02271   return def;
02272 }
02273 
02274 /* actual loader/saver function */
02275 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings);
02276 extern bool AfterLoadGame();
02277 extern bool LoadOldSaveGame(const char *file);
02278 
02282 static inline void ClearSaveLoadState()
02283 {
02284   delete _sl.dumper;
02285   _sl.dumper = NULL;
02286 
02287   delete _sl.sf;
02288   _sl.sf = NULL;
02289 
02290   delete _sl.reader;
02291   _sl.reader = NULL;
02292 
02293   delete _sl.lf;
02294   _sl.lf = NULL;
02295 }
02296 
02302 static void SaveFileStart()
02303 {
02304   _sl.ff_state = _fast_forward;
02305   _fast_forward = 0;
02306   if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
02307 
02308   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START);
02309   _sl.saveinprogress = true;
02310 }
02311 
02313 static void SaveFileDone()
02314 {
02315   if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state;
02316   if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
02317 
02318   InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
02319   _sl.saveinprogress = false;
02320 }
02321 
02323 void SetSaveLoadError(StringID str)
02324 {
02325   _sl.error_str = str;
02326 }
02327 
02329 const char *GetSaveLoadErrorString()
02330 {
02331   SetDParam(0, _sl.error_str);
02332   SetDParamStr(1, _sl.extra_msg);
02333 
02334   static char err_str[512];
02335   GetString(err_str, _sl.action == SLA_SAVE ? STR_ERROR_GAME_SAVE_FAILED : STR_ERROR_GAME_LOAD_FAILED, lastof(err_str));
02336   return err_str;
02337 }
02338 
02340 static void SaveFileError()
02341 {
02342   SetDParamStr(0, GetSaveLoadErrorString());
02343   ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
02344   SaveFileDone();
02345 }
02346 
02351 static SaveOrLoadResult SaveFileToDisk(bool threaded)
02352 {
02353   try {
02354     byte compression;
02355     const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format, &compression);
02356 
02357     /* We have written our stuff to memory, now write it to file! */
02358     uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) };
02359     _sl.sf->Write((byte*)hdr, sizeof(hdr));
02360 
02361     _sl.sf = fmt->init_write(_sl.sf, compression);
02362     _sl.dumper->Flush(_sl.sf);
02363 
02364     ClearSaveLoadState();
02365 
02366     if (threaded) SetAsyncSaveFinish(SaveFileDone);
02367 
02368     return SL_OK;
02369   } catch (...) {
02370     ClearSaveLoadState();
02371 
02372     /* Skip the "colour" character */
02373     DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
02374 
02375     if (threaded) {
02376       SetAsyncSaveFinish(SaveFileError);
02377     } else {
02378       SaveFileError();
02379     }
02380     return SL_ERROR;
02381   }
02382 }
02383 
02385 static void SaveFileToDiskThread(void *arg)
02386 {
02387   SaveFileToDisk(true);
02388 }
02389 
02390 void WaitTillSaved()
02391 {
02392   if (_save_thread == NULL) return;
02393 
02394   _save_thread->Join();
02395   delete _save_thread;
02396   _save_thread = NULL;
02397 }
02398 
02407 static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
02408 {
02409   assert(!_sl.saveinprogress);
02410 
02411   _sl.dumper = new MemoryDumper();
02412   _sl.sf = writer;
02413 
02414   _sl_version = SAVEGAME_VERSION;
02415 
02416   SaveViewportBeforeSaveGame();
02417   SlSaveChunks();
02418 
02419   SaveFileStart();
02420   if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
02421     if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
02422 
02423     SaveOrLoadResult result = SaveFileToDisk(false);
02424     SaveFileDone();
02425 
02426     return result;
02427   }
02428 
02429   return SL_OK;
02430 }
02431 
02438 SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
02439 {
02440   try {
02441     _sl.action = SLA_SAVE;
02442     return DoSave(writer, threaded);
02443   } catch (...) {
02444     ClearSaveLoadState();
02445     return SL_ERROR;
02446   }
02447 }
02448 
02455 static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
02456 {
02457   _sl.lf = reader;
02458 
02459   if (load_check) {
02460     /* Clear previous check data */
02461     _load_check_data.Clear();
02462     /* Mark SL_LOAD_CHECK as supported for this savegame. */
02463     _load_check_data.checkable = true;
02464   }
02465 
02466   uint32 hdr[2];
02467   if (_sl.lf->Read((byte*)hdr, sizeof(hdr)) != sizeof(hdr)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
02468 
02469   /* see if we have any loader for this type. */
02470   const SaveLoadFormat *fmt = _saveload_formats;
02471   for (;;) {
02472     /* No loader found, treat as version 0 and use LZO format */
02473     if (fmt == endof(_saveload_formats)) {
02474       DEBUG(sl, 0, "Unknown savegame type, trying to load it as the buggy format");
02475       _sl.lf->Reset();
02476       _sl_version = 0;
02477       _sl_minor_version = 0;
02478 
02479       /* Try to find the LZO savegame format; it uses 'OTTD' as tag. */
02480       fmt = _saveload_formats;
02481       for (;;) {
02482         if (fmt == endof(_saveload_formats)) {
02483           /* Who removed LZO support? Bad bad boy! */
02484           NOT_REACHED();
02485         }
02486         if (fmt->tag == TO_BE32X('OTTD')) break;
02487         fmt++;
02488       }
02489       break;
02490     }
02491 
02492     if (fmt->tag == hdr[0]) {
02493       /* check version number */
02494       _sl_version = TO_BE32(hdr[1]) >> 16;
02495       /* Minor is not used anymore from version 18.0, but it is still needed
02496        * in versions before that (4 cases) which can't be removed easy.
02497        * Therefor it is loaded, but never saved (or, it saves a 0 in any scenario).
02498        * So never EVER use this minor version again. -- TrueLight -- 22-11-2005 */
02499       _sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
02500 
02501       DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
02502 
02503       /* Is the version higher than the current? */
02504       if (_sl_version > SAVEGAME_VERSION) SlError(STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME);
02505       break;
02506     }
02507 
02508     fmt++;
02509   }
02510 
02511   /* loader for this savegame type is not implemented? */
02512   if (fmt->init_load == NULL) {
02513     char err_str[64];
02514     snprintf(err_str, lengthof(err_str), "Loader for '%s' is not available.", fmt->name);
02515     SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
02516   }
02517 
02518   _sl.lf = fmt->init_load(_sl.lf);
02519   _sl.reader = new ReadBuffer(_sl.lf);
02520   _next_offs = 0;
02521 
02522   if (!load_check) {
02523     _engine_mngr.ResetToDefaultMapping();
02524 
02525     /* Old maps were hardcoded to 256x256 and thus did not contain
02526      * any mapsize information. Pre-initialize to 256x256 to not to
02527      * confuse old games */
02528     InitializeGame(256, 256, true, true);
02529 
02530     GamelogReset();
02531 
02532     if (IsSavegameVersionBefore(4)) {
02533       /*
02534        * NewGRFs were introduced between 0.3,4 and 0.3.5, which both
02535        * shared savegame version 4. Anything before that 'obviously'
02536        * does not have any NewGRFs. Between the introduction and
02537        * savegame version 41 (just before 0.5) the NewGRF settings
02538        * were not stored in the savegame and they were loaded by
02539        * using the settings from the main menu.
02540        * So, to recap:
02541        * - savegame version  <  4:  do not load any NewGRFs.
02542        * - savegame version >= 41:  load NewGRFs from savegame, which is
02543        *                            already done at this stage by
02544        *                            overwriting the main menu settings.
02545        * - other savegame versions: use main menu settings.
02546        *
02547        * This means that users *can* crash savegame version 4..40
02548        * savegames if they set incompatible NewGRFs in the main menu,
02549        * but can't crash anymore for savegame version < 4 savegames.
02550        *
02551        * Note: this is done here because AfterLoadGame is also called
02552        * for TTO/TTD/TTDP savegames which have their own NewGRF logic.
02553        */
02554       ClearGRFConfigList(&_grfconfig);
02555     }
02556   }
02557 
02558   if (load_check) {
02559     /* Load chunks into _load_check_data.
02560      * No pools are loaded. References are not possible, and thus do not need resolving. */
02561     SlLoadCheckChunks();
02562   } else {
02563     /* Load chunks and resolve references */
02564     SlLoadChunks();
02565     SlFixPointers();
02566   }
02567 
02568   ClearSaveLoadState();
02569 
02570   _savegame_type = SGT_OTTD;
02571 
02572   if (load_check) {
02573     /* The only part from AfterLoadGame() we need */
02574     _load_check_data.grf_compatibility = IsGoodGRFConfigList(_load_check_data.grfconfig);
02575   } else {
02576     GamelogStartAction(GLAT_LOAD);
02577 
02578     /* After loading fix up savegame for any internal changes that
02579      * might have occurred since then. If it fails, load back the old game. */
02580     if (!AfterLoadGame()) {
02581       GamelogStopAction();
02582       return SL_REINIT;
02583     }
02584 
02585     GamelogStopAction();
02586   }
02587 
02588   return SL_OK;
02589 }
02590 
02596 SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
02597 {
02598   try {
02599     _sl.action = SLA_LOAD;
02600     return DoLoad(reader, false);
02601   } catch (...) {
02602     ClearSaveLoadState();
02603     return SL_REINIT;
02604   }
02605 }
02606 
02616 SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
02617 {
02618   /* An instance of saving is already active, so don't go saving again */
02619   if (_sl.saveinprogress && mode == SL_SAVE && threaded) {
02620     /* if not an autosave, but a user action, show error message */
02621     if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
02622     return SL_OK;
02623   }
02624   WaitTillSaved();
02625 
02626   /* Load a TTDLX or TTDPatch game */
02627   if (mode == SL_OLD_LOAD) {
02628     _engine_mngr.ResetToDefaultMapping();
02629     InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
02630 
02631     /* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
02632      * and if so a new NewGRF list will be made in LoadOldSaveGame.
02633      * Note: this is done here because AfterLoadGame is also called
02634      * for OTTD savegames which have their own NewGRF logic. */
02635     ClearGRFConfigList(&_grfconfig);
02636     GamelogReset();
02637     if (!LoadOldSaveGame(filename)) return SL_REINIT;
02638     _sl_version = 0;
02639     _sl_minor_version = 0;
02640     GamelogStartAction(GLAT_LOAD);
02641     if (!AfterLoadGame()) {
02642       GamelogStopAction();
02643       return SL_REINIT;
02644     }
02645     GamelogStopAction();
02646     return SL_OK;
02647   }
02648 
02649   switch (mode) {
02650     case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
02651     case SL_LOAD: _sl.action = SLA_LOAD; break;
02652     case SL_SAVE: _sl.action = SLA_SAVE; break;
02653     default: NOT_REACHED();
02654   }
02655 
02656   try {
02657     FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
02658 
02659     /* Make it a little easier to load savegames from the console */
02660     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
02661     if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
02662 
02663     if (fh == NULL) {
02664       SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
02665     }
02666 
02667     if (mode == SL_SAVE) { // SAVE game
02668       DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
02669       if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
02670 
02671       return DoSave(new FileWriter(fh), threaded);
02672     }
02673 
02674     /* LOAD game */
02675     assert(mode == SL_LOAD || mode == SL_LOAD_CHECK);
02676     DEBUG(desync, 1, "load: %s", filename);
02677     return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK);
02678   } catch (...) {
02679     ClearSaveLoadState();
02680 
02681     /* Skip the "colour" character */
02682     if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
02683 
02684     /* A saver/loader exception!! reinitialize all variables to prevent crash! */
02685     return (mode == SL_LOAD) ? SL_REINIT : SL_ERROR;
02686   }
02687 }
02688 
02690 void DoExitSave()
02691 {
02692   SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
02693 }
02694 
02700 void GenerateDefaultSaveName(char *buf, const char *last)
02701 {
02702   /* Check if we have a name for this map, which is the name of the first
02703    * available company. When there's no company available we'll use
02704    * 'Spectator' as "company" name. */
02705   CompanyID cid = _local_company;
02706   if (!Company::IsValidID(cid)) {
02707     const Company *c;
02708     FOR_ALL_COMPANIES(c) {
02709       cid = c->index;
02710       break;
02711     }
02712   }
02713 
02714   SetDParam(0, cid);
02715 
02716   /* Insert current date */
02717   switch (_settings_client.gui.date_format_in_default_names) {
02718     case 0: SetDParam(1, STR_JUST_DATE_LONG); break;
02719     case 1: SetDParam(1, STR_JUST_DATE_TINY); break;
02720     case 2: SetDParam(1, STR_JUST_DATE_ISO); break;
02721     default: NOT_REACHED();
02722   }
02723   SetDParam(2, _date);
02724 
02725   /* Get the correct string (special string for when there's not company) */
02726   GetString(buf, !Company::IsValidID(cid) ? STR_SAVEGAME_NAME_SPECTATOR : STR_SAVEGAME_NAME_DEFAULT, last);
02727   SanitizeFilename(buf);
02728 }
02729 
02730 #if 0
02731 
02737 int GetSavegameType(char *file)
02738 {
02739   const SaveLoadFormat *fmt;
02740   uint32 hdr;
02741   FILE *f;
02742   int mode = SL_OLD_LOAD;
02743 
02744   f = fopen(file, "rb");
02745   if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
02746     DEBUG(sl, 0, "Savegame is obsolete or invalid format");
02747     mode = SL_LOAD; // don't try to get filename, just show name as it is written
02748   } else {
02749     /* see if we have any loader for this type. */
02750     for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
02751       if (fmt->tag == hdr) {
02752         mode = SL_LOAD; // new type of savegame
02753         break;
02754       }
02755     }
02756   }
02757 
02758   fclose(f);
02759   return mode;
02760 }
02761 #endif

Generated on Sun Jan 23 01:49:08 2011 for OpenTTD by  doxygen 1.6.1