2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
8 /** @file map_sl.cpp Code handling saving and loading of map */
10 #include "../stdafx.h"
13 #include "compat/map_sl_compat.h"
15 #include "../map_func.h"
16 #include "../core/bitmath_func.hpp"
19 #include "../safeguards.h"
21 static uint32_t _map_dim_x
;
22 static uint32_t _map_dim_y
;
24 static const SaveLoad _map_desc
[] = {
25 SLEG_CONDVAR("dim_x", _map_dim_x
, SLE_UINT32
, SLV_6
, SL_MAX_VERSION
),
26 SLEG_CONDVAR("dim_y", _map_dim_y
, SLE_UINT32
, SLV_6
, SL_MAX_VERSION
),
29 struct MAPSChunkHandler
: ChunkHandler
{
30 MAPSChunkHandler() : ChunkHandler('MAPS', CH_TABLE
) {}
32 void Save() const override
34 SlTableHeader(_map_desc
);
36 _map_dim_x
= Map::SizeX();
37 _map_dim_y
= Map::SizeY();
40 SlGlobList(_map_desc
);
43 void Load() const override
45 const std::vector
<SaveLoad
> slt
= SlCompatTableHeader(_map_desc
, _map_sl_compat
);
47 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY
) && SlIterateArray() == -1) return;
49 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY
) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
51 Map::Allocate(_map_dim_x
, _map_dim_y
);
54 void LoadCheck(size_t) const override
56 const std::vector
<SaveLoad
> slt
= SlCompatTableHeader(_map_desc
, _map_sl_compat
);
58 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY
) && SlIterateArray() == -1) return;
60 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY
) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
62 _load_check_data
.map_size_x
= _map_dim_x
;
63 _load_check_data
.map_size_y
= _map_dim_y
;
67 static const uint MAP_SL_BUF_SIZE
= 4096;
69 struct MAPTChunkHandler
: ChunkHandler
{
70 MAPTChunkHandler() : ChunkHandler('MAPT', CH_RIFF
) {}
72 void Load() const override
74 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
75 uint size
= Map::Size();
77 for (TileIndex i
= 0; i
!= size
;) {
78 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
79 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) Tile(i
++).type() = buf
[j
];
83 void Save() const override
85 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
86 uint size
= Map::Size();
89 for (TileIndex i
= 0; i
!= size
;) {
90 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) buf
[j
] = Tile(i
++).type();
91 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
96 struct MAPHChunkHandler
: ChunkHandler
{
97 MAPHChunkHandler() : ChunkHandler('MAPH', CH_RIFF
) {}
99 void Load() const override
101 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
102 uint size
= Map::Size();
104 for (TileIndex i
= 0; i
!= size
;) {
105 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
106 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) Tile(i
++).height() = buf
[j
];
110 void Save() const override
112 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
113 uint size
= Map::Size();
116 for (TileIndex i
= 0; i
!= size
;) {
117 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) buf
[j
] = Tile(i
++).height();
118 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
123 struct MAPOChunkHandler
: ChunkHandler
{
124 MAPOChunkHandler() : ChunkHandler('MAPO', CH_RIFF
) {}
126 void Load() const override
128 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
129 uint size
= Map::Size();
131 for (TileIndex i
= 0; i
!= size
;) {
132 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
133 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) Tile(i
++).m1() = buf
[j
];
137 void Save() const override
139 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
140 uint size
= Map::Size();
143 for (TileIndex i
= 0; i
!= size
;) {
144 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) buf
[j
] = Tile(i
++).m1();
145 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
150 struct MAP2ChunkHandler
: ChunkHandler
{
151 MAP2ChunkHandler() : ChunkHandler('MAP2', CH_RIFF
) {}
153 void Load() const override
155 std::array
<uint16_t, MAP_SL_BUF_SIZE
> buf
;
156 uint size
= Map::Size();
158 for (TileIndex i
= 0; i
!= size
;) {
159 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
,
160 /* In those versions the m2 was 8 bits */
161 IsSavegameVersionBefore(SLV_5
) ? SLE_FILE_U8
| SLE_VAR_U16
: SLE_UINT16
163 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) Tile(i
++).m2() = buf
[j
];
167 void Save() const override
169 std::array
<uint16_t, MAP_SL_BUF_SIZE
> buf
;
170 uint size
= Map::Size();
172 SlSetLength(static_cast<uint32_t>(size
) * sizeof(uint16_t));
173 for (TileIndex i
= 0; i
!= size
;) {
174 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) buf
[j
] = Tile(i
++).m2();
175 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT16
);
180 struct M3LOChunkHandler
: ChunkHandler
{
181 M3LOChunkHandler() : ChunkHandler('M3LO', CH_RIFF
) {}
183 void Load() const override
185 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
186 uint size
= Map::Size();
188 for (TileIndex i
= 0; i
!= size
;) {
189 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
190 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) Tile(i
++).m3() = buf
[j
];
194 void Save() const override
196 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
197 uint size
= Map::Size();
200 for (TileIndex i
= 0; i
!= size
;) {
201 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) buf
[j
] = Tile(i
++).m3();
202 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
207 struct M3HIChunkHandler
: ChunkHandler
{
208 M3HIChunkHandler() : ChunkHandler('M3HI', CH_RIFF
) {}
210 void Load() const override
212 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
213 uint size
= Map::Size();
215 for (TileIndex i
= 0; i
!= size
;) {
216 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
217 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) Tile(i
++).m4() = buf
[j
];
221 void Save() const override
223 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
224 uint size
= Map::Size();
227 for (TileIndex i
= 0; i
!= size
;) {
228 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) buf
[j
] = Tile(i
++).m4();
229 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
234 struct MAP5ChunkHandler
: ChunkHandler
{
235 MAP5ChunkHandler() : ChunkHandler('MAP5', CH_RIFF
) {}
237 void Load() const override
239 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
240 uint size
= Map::Size();
242 for (TileIndex i
= 0; i
!= size
;) {
243 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
244 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) Tile(i
++).m5() = buf
[j
];
248 void Save() const override
250 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
251 uint size
= Map::Size();
254 for (TileIndex i
= 0; i
!= size
;) {
255 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) buf
[j
] = Tile(i
++).m5();
256 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
261 struct MAPEChunkHandler
: ChunkHandler
{
262 MAPEChunkHandler() : ChunkHandler('MAPE', CH_RIFF
) {}
264 void Load() const override
266 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
267 uint size
= Map::Size();
269 if (IsSavegameVersionBefore(SLV_42
)) {
270 for (TileIndex i
= 0; i
!= size
;) {
271 /* 1024, otherwise we overflow on 64x64 maps! */
272 SlCopy(buf
.data(), 1024, SLE_UINT8
);
273 for (uint j
= 0; j
!= 1024; j
++) {
274 Tile(i
++).m6() = GB(buf
[j
], 0, 2);
275 Tile(i
++).m6() = GB(buf
[j
], 2, 2);
276 Tile(i
++).m6() = GB(buf
[j
], 4, 2);
277 Tile(i
++).m6() = GB(buf
[j
], 6, 2);
281 for (TileIndex i
= 0; i
!= size
;) {
282 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
283 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) Tile(i
++).m6() = buf
[j
];
288 void Save() const override
290 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
291 uint size
= Map::Size();
294 for (TileIndex i
= 0; i
!= size
;) {
295 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) buf
[j
] = Tile(i
++).m6();
296 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
301 struct MAP7ChunkHandler
: ChunkHandler
{
302 MAP7ChunkHandler() : ChunkHandler('MAP7', CH_RIFF
) {}
304 void Load() const override
306 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
307 uint size
= Map::Size();
309 for (TileIndex i
= 0; i
!= size
;) {
310 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
311 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) Tile(i
++).m7() = buf
[j
];
315 void Save() const override
317 std::array
<uint8_t, MAP_SL_BUF_SIZE
> buf
;
318 uint size
= Map::Size();
321 for (TileIndex i
= 0; i
!= size
;) {
322 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) buf
[j
] = Tile(i
++).m7();
323 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT8
);
328 struct MAP8ChunkHandler
: ChunkHandler
{
329 MAP8ChunkHandler() : ChunkHandler('MAP8', CH_RIFF
) {}
331 void Load() const override
333 std::array
<uint16_t, MAP_SL_BUF_SIZE
> buf
;
334 uint size
= Map::Size();
336 for (TileIndex i
= 0; i
!= size
;) {
337 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT16
);
338 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) Tile(i
++).m8() = buf
[j
];
342 void Save() const override
344 std::array
<uint16_t, MAP_SL_BUF_SIZE
> buf
;
345 uint size
= Map::Size();
347 SlSetLength(static_cast<uint32_t>(size
) * sizeof(uint16_t));
348 for (TileIndex i
= 0; i
!= size
;) {
349 for (uint j
= 0; j
!= MAP_SL_BUF_SIZE
; j
++) buf
[j
] = Tile(i
++).m8();
350 SlCopy(buf
.data(), MAP_SL_BUF_SIZE
, SLE_UINT16
);
355 static const MAPSChunkHandler MAPS
;
356 static const MAPTChunkHandler MAPT
;
357 static const MAPHChunkHandler MAPH
;
358 static const MAPOChunkHandler MAPO
;
359 static const MAP2ChunkHandler MAP2
;
360 static const M3LOChunkHandler M3LO
;
361 static const M3HIChunkHandler M3HI
;
362 static const MAP5ChunkHandler MAP5
;
363 static const MAPEChunkHandler MAPE
;
364 static const MAP7ChunkHandler MAP7
;
365 static const MAP8ChunkHandler MAP8
;
366 static const ChunkHandlerRef map_chunk_handlers
[] = {
380 extern const ChunkHandlerTable
_map_chunk_handlers(map_chunk_handlers
);