OpenTTD Source  20241121-master-g67a0fccfad
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"
13 #include "compat/map_sl_compat.h"
14 
15 #include "../map_func.h"
16 #include "../core/bitmath_func.hpp"
17 #include "../fios.h"
18 
19 #include "../safeguards.h"
20 
21 static uint32_t _map_dim_x;
22 static uint32_t _map_dim_y;
23 
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),
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 
67 static 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 = 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];
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 = 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);
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 = 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];
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 = 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);
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 = 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];
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 = 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);
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 = 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
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 = 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);
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 = 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];
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 = 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);
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 = 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];
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 = 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);
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 = 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];
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 = 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);
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 = 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);
278  }
279  }
280  } else {
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];
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 = 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);
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 = 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];
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 = 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);
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 = 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];
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 = 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);
351  }
352  }
353 };
354 
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[] = {
367  MAPS,
368  MAPT,
369  MAPH,
370  MAPO,
371  MAP2,
372  M3LO,
373  M3HI,
374  MAP5,
375  MAPE,
376  MAP7,
377  MAP8,
378 };
379 
380 extern const ChunkHandlerTable _map_chunk_handlers(map_chunk_handlers);
constexpr static debug_inline 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 uint8_t & m7()
Primarily used for newgrf support.
Definition: map_func.h:185
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 & m5()
General purpose.
Definition: map_func.h:161
debug_inline uint8_t & m1()
Primarily used for ownership information.
Definition: map_func.h:113
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 uint16_t & m2()
Primarily used for indices to towns, industries and stations.
Definition: map_func.h:125
debug_inline uint8_t & m6()
General purpose.
Definition: map_func.h:173
debug_inline uint8_t & m3()
General purpose.
Definition: map_func.h:137
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.
Definition: map_sl_compat.h:16
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition: saveload.cpp:658
void SlCopy(void *object, size_t length, VarType conv)
Copy a list of SL_VARs to/from a savegame.
Definition: saveload.cpp:1029
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
Definition: saveload.cpp:351
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
Definition: saveload.cpp:1893
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
Definition: saveload.cpp:1755
void SlSetLength(size_t length)
Sets the length of either a RIFF object or the number of items in an array.
Definition: saveload.cpp:712
void SlGlobList(const SaveLoadTable &slt)
Save or Load (a list of) global variables.
Definition: saveload.cpp:1947
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:1086
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition: saveload.h:507
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition: saveload.h:510
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition: saveload.h:1239
@ 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:397
@ 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:461
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:713