saveload.cpp

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

Generated on Fri Feb 4 20:53:46 2011 for OpenTTD by  doxygen 1.6.1