map_sl.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 
00012 #include "../stdafx.h"
00013 #include "../map_func.h"
00014 #include "../core/bitmath_func.hpp"
00015 #include "../fios.h"
00016 #include "../tile_map.h"
00017 
00018 #include "saveload.h"
00019 
00020 static uint32 _map_dim_x;
00021 static uint32 _map_dim_y;
00022 
00023 static const SaveLoadGlobVarList _map_dimensions[] = {
00024   SLEG_CONDVAR(_map_dim_x, SLE_UINT32, 6, SL_MAX_VERSION),
00025   SLEG_CONDVAR(_map_dim_y, SLE_UINT32, 6, SL_MAX_VERSION),
00026       SLEG_END()
00027 };
00028 
00029 static void Save_MAPS()
00030 {
00031   _map_dim_x = MapSizeX();
00032   _map_dim_y = MapSizeY();
00033   SlGlobList(_map_dimensions);
00034 }
00035 
00036 static void Load_MAPS()
00037 {
00038   SlGlobList(_map_dimensions);
00039   /* Don't construct _map_heightdata here, because we don't know wether
00040    * we need it before Load_MAPH. */
00041   AllocateMap(_map_dim_x, _map_dim_y, false);
00042 }
00043 
00044 static void Check_MAPS()
00045 {
00046   SlGlobList(_map_dimensions);
00047   _load_check_data.map_size_x = _map_dim_x;
00048   _load_check_data.map_size_y = _map_dim_y;
00049 }
00050 
00051 static const uint MAP_SL_BUF_SIZE = 4096;
00052 
00053 static void Load_MAPT()
00054 {
00055   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00056   TileIndex size = MapSize();
00057 
00058   for (TileIndex i = 0; i != size;) {
00059     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00060     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type_height = buf[j];
00061   }
00062 }
00063 
00064 static void Save_MAPT()
00065 {
00066   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00067   TileIndex size = MapSize();
00068 
00069   SlSetLength(size);
00070   for (TileIndex i = 0; i != size;) {
00071     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type_height;
00072     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00073   }
00074 }
00075 
00076 static void Load_MAP1()
00077 {
00078   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00079   TileIndex size = MapSize();
00080 
00081   for (TileIndex i = 0; i != size;) {
00082     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00083     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m1 = buf[j];
00084   }
00085 }
00086 
00087 static void Save_MAP1()
00088 {
00089   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00090   TileIndex size = MapSize();
00091 
00092   SlSetLength(size);
00093   for (TileIndex i = 0; i != size;) {
00094     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m1;
00095     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00096   }
00097 }
00098 
00099 static void Load_MAP2()
00100 {
00101   SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
00102   TileIndex size = MapSize();
00103 
00104   for (TileIndex i = 0; i != size;) {
00105     SlArray(buf, MAP_SL_BUF_SIZE,
00106       /* In those versions the m2 was 8 bits */
00107       IsSavegameVersionBefore(5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16
00108     );
00109     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m2 = buf[j];
00110   }
00111 }
00112 
00113 static void Save_MAP2()
00114 {
00115   SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
00116   TileIndex size = MapSize();
00117 
00118   SlSetLength(size * sizeof(uint16));
00119   for (TileIndex i = 0; i != size;) {
00120     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m2;
00121     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16);
00122   }
00123 }
00124 
00125 static void Load_MAP3()
00126 {
00127   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00128   TileIndex size = MapSize();
00129 
00130   for (TileIndex i = 0; i != size;) {
00131     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00132     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m3 = buf[j];
00133   }
00134 }
00135 
00136 static void Save_MAP3()
00137 {
00138   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00139   TileIndex size = MapSize();
00140 
00141   SlSetLength(size);
00142   for (TileIndex i = 0; i != size;) {
00143     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m3;
00144     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00145   }
00146 }
00147 
00148 static void Load_MAP4()
00149 {
00150   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00151   TileIndex size = MapSize();
00152 
00153   for (TileIndex i = 0; i != size;) {
00154     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00155     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m4 = buf[j];
00156   }
00157 }
00158 
00159 static void Save_MAP4()
00160 {
00161   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00162   TileIndex size = MapSize();
00163 
00164   SlSetLength(size);
00165   for (TileIndex i = 0; i != size;) {
00166     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m4;
00167     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00168   }
00169 }
00170 
00171 static void Load_MAP5()
00172 {
00173   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00174   TileIndex size = MapSize();
00175 
00176   for (TileIndex i = 0; i != size;) {
00177     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00178     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m5 = buf[j];
00179   }
00180 }
00181 
00182 static void Save_MAP5()
00183 {
00184   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00185   TileIndex size = MapSize();
00186 
00187   SlSetLength(size);
00188   for (TileIndex i = 0; i != size;) {
00189     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m5;
00190     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00191   }
00192 }
00193 
00194 static void Load_MAP6()
00195 {
00196   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00197   TileIndex size = MapSize();
00198 
00199   if (IsSavegameVersionBefore(42)) {
00200     for (TileIndex i = 0; i != size;) {
00201       /* 1024, otherwise we overflow on 64x64 maps! */
00202       SlArray(buf, 1024, SLE_UINT8);
00203       for (uint j = 0; j != 1024; j++) {
00204         _m[i++].m6 = GB(buf[j], 0, 2);
00205         _m[i++].m6 = GB(buf[j], 2, 2);
00206         _m[i++].m6 = GB(buf[j], 4, 2);
00207         _m[i++].m6 = GB(buf[j], 6, 2);
00208       }
00209     }
00210   } else {
00211     for (TileIndex i = 0; i != size;) {
00212       SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00213       for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m6 = buf[j];
00214     }
00215   }
00216 }
00217 
00218 static void Save_MAP6()
00219 {
00220   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00221   TileIndex size = MapSize();
00222 
00223   SlSetLength(size);
00224   for (TileIndex i = 0; i != size;) {
00225     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m6;
00226     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00227   }
00228 }
00229 
00230 static void Load_MAP7()
00231 {
00232   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00233   TileIndex size = MapSize();
00234 
00235   for (TileIndex i = 0; i != size;) {
00236     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00237     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m7 = buf[j];
00238   }
00239 }
00240 
00241 static void Save_MAP7()
00242 {
00243   SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
00244   TileIndex size = MapSize();
00245 
00246   SlSetLength(size);
00247   for (TileIndex i = 0; i != size;) {
00248     for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m7;
00249     SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
00250   }
00251 }
00281 static void Load_MAPH()
00282 {
00283   /* Maybe it was still filled from the previous game. */
00284   free(_map_heightdata);
00285   /* Does free set it to NULL?  I don't know, so I better do it explicitely. */
00286   _map_heightdata = NULL;
00287   if (SlGetFieldLength() != 0) {
00288     /* We didn't construct it before because we didn't know wether we need it
00289      * before - see comment of AllocateMap for a detailed explanation. */
00290     _map_heightdata = CallocT<TileHeightData>(MapSize());
00291 
00292     SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
00293     TileIndex size = MapSize();
00294 
00295     for (TileIndex i = 0; i != size;) {
00296       SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16);
00297       for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) {
00298       _map_heightdata[i++].heightlevel = buf[j];
00299       }
00300     }
00301   }
00302 }
00303 
00304 static void Save_MAPH()
00305 {
00306   /* Assure that configuration setting is consistent to the data. */
00307   assert(AllowMoreHeightlevels() == (_map_heightdata != NULL));
00308 
00309   if (!AllowMoreHeightlevels()) {
00310     SlSetLength(0);
00311   } else {
00312     SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
00313     TileIndex size = MapSize();
00314 
00315     SlSetLength(size * sizeof(uint16));
00316     for (TileIndex i = 0; i != size;) {
00317       for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _map_heightdata[i++].heightlevel;
00318       SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16);
00319     }
00320   }
00321 }
00322 
00323 extern const ChunkHandler _map_chunk_handlers[] = {
00324   { 'MAPS', Save_MAPS, Load_MAPS, NULL, Check_MAPS, CH_RIFF },
00325   { 'MAPT', Save_MAPT, Load_MAPT, NULL, NULL,       CH_RIFF },
00326   { 'MAPO', Save_MAP1, Load_MAP1, NULL, NULL,       CH_RIFF },
00327   { 'MAP2', Save_MAP2, Load_MAP2, NULL, NULL,       CH_RIFF },
00328   { 'M3LO', Save_MAP3, Load_MAP3, NULL, NULL,       CH_RIFF },
00329   { 'M3HI', Save_MAP4, Load_MAP4, NULL, NULL,       CH_RIFF },
00330   { 'MAP5', Save_MAP5, Load_MAP5, NULL, NULL,       CH_RIFF },
00331   { 'MAPE', Save_MAP6, Load_MAP6, NULL, NULL,       CH_RIFF },
00332   { 'MAP7', Save_MAP7, Load_MAP7, NULL, NULL,       CH_RIFF },
00333   { 'MAPH', Save_MAPH, Load_MAPH, NULL, NULL,       CH_RIFF | CH_LAST },
00334 };