OpenTTD Source 20250205-master-gfd85ab1e2c
map_sl.cpp
Go to the documentation of this file.
1/*
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/>.
6 */
7
10#include "../stdafx.h"
11
12#include "saveload.h"
14
15#include "../map_func.h"
16#include "../core/bitmath_func.hpp"
17#include "../fios.h"
18
19#include "../safeguards.h"
20
21static uint32_t _map_dim_x;
22static uint32_t _map_dim_y;
23
24static 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),
27};
28
30 MAPSChunkHandler() : ChunkHandler('MAPS', CH_TABLE) {}
31
32 void Save() const override
33 {
34 SlTableHeader(_map_desc);
35
36 _map_dim_x = Map::SizeX();
37 _map_dim_y = Map::SizeY();
38
39 SlSetArrayIndex(0);
40 SlGlobList(_map_desc);
41 }
42
43 void Load() const override
44 {
45 const std::vector<SaveLoad> slt = SlCompatTableHeader(_map_desc, _map_sl_compat);
46
48 SlGlobList(slt);
49 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
50
51 Map::Allocate(_map_dim_x, _map_dim_y);
52 }
53
54 void LoadCheck(size_t) const override
55 {
56 const std::vector<SaveLoad> slt = SlCompatTableHeader(_map_desc, _map_sl_compat);
57
59 SlGlobList(slt);
60 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
61
62 _load_check_data.map_size_x = _map_dim_x;
63 _load_check_data.map_size_y = _map_dim_y;
64 }
65};
66
67static const uint MAP_SL_BUF_SIZE = 4096;
68
70 MAPTChunkHandler() : ChunkHandler('MAPT', CH_RIFF) {}
71
72 void Load() const override
73 {
74 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
75 uint size = Map::Size();
76
77 for (TileIndex i{}; 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];
80 }
81 }
82
83 void Save() const override
84 {
85 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
86 uint size = Map::Size();
87
88 SlSetLength(size);
89 for (TileIndex i{}; 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);
92 }
93 }
94};
95
97 MAPHChunkHandler() : ChunkHandler('MAPH', CH_RIFF) {}
98
99 void Load() const override
100 {
101 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
102 uint size = Map::Size();
103
104 for (TileIndex i{}; 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];
107 }
108 }
109
110 void Save() const override
111 {
112 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
113 uint size = Map::Size();
114
115 SlSetLength(size);
116 for (TileIndex i{}; 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);
119 }
120 }
121};
122
124 MAPOChunkHandler() : ChunkHandler('MAPO', CH_RIFF) {}
125
126 void Load() const override
127 {
128 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
129 uint size = Map::Size();
130
131 for (TileIndex i{}; 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];
134 }
135 }
136
137 void Save() const override
138 {
139 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
140 uint size = Map::Size();
141
142 SlSetLength(size);
143 for (TileIndex i{}; 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);
146 }
147 }
148};
149
151 MAP2ChunkHandler() : ChunkHandler('MAP2', CH_RIFF) {}
152
153 void Load() const override
154 {
155 std::array<uint16_t, MAP_SL_BUF_SIZE> buf;
156 uint size = Map::Size();
157
158 for (TileIndex i{}; 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
162 );
163 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) Tile(i++).m2() = buf[j];
164 }
165 }
166
167 void Save() const override
168 {
169 std::array<uint16_t, MAP_SL_BUF_SIZE> buf;
170 uint size = Map::Size();
171
172 SlSetLength(static_cast<uint32_t>(size) * sizeof(uint16_t));
173 for (TileIndex i{}; 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);
176 }
177 }
178};
179
181 M3LOChunkHandler() : ChunkHandler('M3LO', CH_RIFF) {}
182
183 void Load() const override
184 {
185 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
186 uint size = Map::Size();
187
188 for (TileIndex i{}; 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];
191 }
192 }
193
194 void Save() const override
195 {
196 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
197 uint size = Map::Size();
198
199 SlSetLength(size);
200 for (TileIndex i{}; 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);
203 }
204 }
205};
206
208 M3HIChunkHandler() : ChunkHandler('M3HI', CH_RIFF) {}
209
210 void Load() const override
211 {
212 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
213 uint size = Map::Size();
214
215 for (TileIndex i{}; 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];
218 }
219 }
220
221 void Save() const override
222 {
223 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
224 uint size = Map::Size();
225
226 SlSetLength(size);
227 for (TileIndex i{}; 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);
230 }
231 }
232};
233
235 MAP5ChunkHandler() : ChunkHandler('MAP5', CH_RIFF) {}
236
237 void Load() const override
238 {
239 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
240 uint size = Map::Size();
241
242 for (TileIndex i{}; 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];
245 }
246 }
247
248 void Save() const override
249 {
250 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
251 uint size = Map::Size();
252
253 SlSetLength(size);
254 for (TileIndex i{}; 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);
257 }
258 }
259};
260
262 MAPEChunkHandler() : ChunkHandler('MAPE', CH_RIFF) {}
263
264 void Load() const override
265 {
266 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
267 uint size = Map::Size();
268
270 for (TileIndex i{}; 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);
278 }
279 }
280 } else {
281 for (TileIndex i{}; 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];
284 }
285 }
286 }
287
288 void Save() const override
289 {
290 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
291 uint size = Map::Size();
292
293 SlSetLength(size);
294 for (TileIndex i{}; 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);
297 }
298 }
299};
300
302 MAP7ChunkHandler() : ChunkHandler('MAP7', CH_RIFF) {}
303
304 void Load() const override
305 {
306 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
307 uint size = Map::Size();
308
309 for (TileIndex i{}; 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];
312 }
313 }
314
315 void Save() const override
316 {
317 std::array<uint8_t, MAP_SL_BUF_SIZE> buf;
318 uint size = Map::Size();
319
320 SlSetLength(size);
321 for (TileIndex i{}; 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);
324 }
325 }
326};
327
329 MAP8ChunkHandler() : ChunkHandler('MAP8', CH_RIFF) {}
330
331 void Load() const override
332 {
333 std::array<uint16_t, MAP_SL_BUF_SIZE> buf;
334 uint size = Map::Size();
335
336 for (TileIndex i{}; 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];
339 }
340 }
341
342 void Save() const override
343 {
344 std::array<uint16_t, MAP_SL_BUF_SIZE> buf;
345 uint size = Map::Size();
346
347 SlSetLength(static_cast<uint32_t>(size) * sizeof(uint16_t));
348 for (TileIndex i{}; 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);
351 }
352 }
353};
354
355static const MAPSChunkHandler MAPS;
356static const MAPTChunkHandler MAPT;
357static const MAPHChunkHandler MAPH;
358static const MAPOChunkHandler MAPO;
359static const MAP2ChunkHandler MAP2;
360static const M3LOChunkHandler M3LO;
361static const M3HIChunkHandler M3HI;
362static const MAP5ChunkHandler MAP5;
363static const MAPEChunkHandler MAPE;
364static const MAP7ChunkHandler MAP7;
365static const MAP8ChunkHandler MAP8;
366static const ChunkHandlerRef map_chunk_handlers[] = {
367 MAPS,
368 MAPT,
369 MAPH,
370 MAPO,
371 MAP2,
372 M3LO,
373 M3HI,
374 MAP5,
375 MAPE,
376 MAP7,
377 MAP8,
378};
379
380extern const ChunkHandlerTable _map_chunk_handlers(map_chunk_handlers);
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Wrapper class to abstract away the way the tiles are stored.
Definition map_func.h:25
debug_inline uint16_t & m8()
General purpose.
Definition map_func.h:197
debug_inline uint16_t & m2()
Primarily used for indices to towns, industries and stations.
Definition map_func.h:125
debug_inline uint8_t & m7()
Primarily used for newgrf support.
Definition map_func.h:185
debug_inline uint8_t & m4()
General purpose.
Definition map_func.h:149
debug_inline uint8_t & height()
The height of the northern corner.
Definition map_func.h:101
debug_inline uint8_t & m6()
General purpose.
Definition map_func.h:173
debug_inline uint8_t & type()
The type (bits 4..7), bridges (2..3), rainforest/desert (0..1)
Definition map_func.h:89
debug_inline uint8_t & m3()
General purpose.
Definition map_func.h:137
debug_inline uint8_t & m1()
Primarily used for ownership information.
Definition map_func.h:113
debug_inline uint8_t & m5()
General purpose.
Definition map_func.h:161
LoadCheckData _load_check_data
Data loaded from save during SL_LOAD_CHECK.
Definition fios_gui.cpp:41
Loading for map chunks before table headers were added.
const SaveLoadCompat _map_sl_compat[]
Original field order for _map_desc.
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition saveload.cpp:662
void SlCopy(void *object, size_t length, VarType conv)
Copy a list of SL_VARs to/from a savegame.
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
Definition saveload.cpp:354
void SlSetLength(size_t length)
Sets the length of either a RIFF object or the number of items in an array.
Definition saveload.cpp:716
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
void SlGlobList(const SaveLoadTable &slt)
Save or Load (a list of) global variables.
Functions/types related to saving and loading games.
#define SLEG_CONDVAR(name, variable, type, from, to)
Storage of a global variable in some savegame versions.
Definition saveload.h:1110
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition saveload.h:510
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition saveload.h:513
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition saveload.h:1264
@ SLV_42
42 7573
Definition saveload.h:93
@ SLV_6
6.0 1721 6.1 1768
Definition saveload.h:46
@ SLV_RIFF_TO_ARRAY
294 PR#9375 Changed many CH_RIFF chunks to CH_ARRAY chunks.
Definition saveload.h:332
@ SL_MAX_VERSION
Highest possible saveload version.
Definition saveload.h:400
@ SLV_5
5.0 1429 5.1 1440 5.2 1525 0.3.6
Definition saveload.h:43
Handlers and description of chunk.
Definition saveload.h:464
void Load() const override
Load the chunk.
Definition map_sl.cpp:210
void Save() const override
Save the chunk.
Definition map_sl.cpp:221
void Load() const override
Load the chunk.
Definition map_sl.cpp:183
void Save() const override
Save the chunk.
Definition map_sl.cpp:194
void Save() const override
Save the chunk.
Definition map_sl.cpp:167
void Load() const override
Load the chunk.
Definition map_sl.cpp:153
void Save() const override
Save the chunk.
Definition map_sl.cpp:248
void Load() const override
Load the chunk.
Definition map_sl.cpp:237
void Save() const override
Save the chunk.
Definition map_sl.cpp:315
void Load() const override
Load the chunk.
Definition map_sl.cpp:304
void Save() const override
Save the chunk.
Definition map_sl.cpp:342
void Load() const override
Load the chunk.
Definition map_sl.cpp:331
void Load() const override
Load the chunk.
Definition map_sl.cpp:264
void Save() const override
Save the chunk.
Definition map_sl.cpp:288
void Load() const override
Load the chunk.
Definition map_sl.cpp:99
void Save() const override
Save the chunk.
Definition map_sl.cpp:110
void Save() const override
Save the chunk.
Definition map_sl.cpp:137
void Load() const override
Load the chunk.
Definition map_sl.cpp:126
void Save() const override
Save the chunk.
Definition map_sl.cpp:32
void LoadCheck(size_t) const override
Load the chunk for game preview.
Definition map_sl.cpp:54
void Load() const override
Load the chunk.
Definition map_sl.cpp:43
void Load() const override
Load the chunk.
Definition map_sl.cpp:72
void Save() const override
Save the chunk.
Definition map_sl.cpp:83
static uint SizeY()
Get the size of the map along the Y.
Definition map_func.h:279
static debug_inline uint SizeX()
Get the size of the map along the X.
Definition map_func.h:270
static void Allocate(uint size_x, uint size_y)
(Re)allocates a map with the given dimension
Definition map.cpp:36
static debug_inline uint Size()
Get the size of the map.
Definition map_func.h:288
SaveLoad type struct.
Definition saveload.h:718