OpenTTD Source  12.0-beta2
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 #include <array>
19 
20 #include "../safeguards.h"
21 
22 static uint32 _map_dim_x;
23 static uint32 _map_dim_y;
24 
25 static const SaveLoad _map_desc[] = {
26  SLEG_CONDVAR("dim_x", _map_dim_x, SLE_UINT32, SLV_6, SL_MAX_VERSION),
27  SLEG_CONDVAR("dim_y", _map_dim_y, SLE_UINT32, SLV_6, SL_MAX_VERSION),
28 };
29 
31  MAPSChunkHandler() : ChunkHandler('MAPS', CH_TABLE) {}
32 
33  void Save() const override
34  {
35  SlTableHeader(_map_desc);
36 
37  _map_dim_x = MapSizeX();
38  _map_dim_y = MapSizeY();
39 
40  SlSetArrayIndex(0);
41  SlGlobList(_map_desc);
42  }
43 
44  void Load() const override
45  {
46  const std::vector<SaveLoad> slt = SlCompatTableHeader(_map_desc, _map_sl_compat);
47 
49  SlGlobList(slt);
50  if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
51 
52  AllocateMap(_map_dim_x, _map_dim_y);
53  }
54 
55  void LoadCheck(size_t) const override
56  {
57  const std::vector<SaveLoad> slt = SlCompatTableHeader(_map_desc, _map_sl_compat);
58 
60  SlGlobList(slt);
61  if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
62 
63  _load_check_data.map_size_x = _map_dim_x;
64  _load_check_data.map_size_y = _map_dim_y;
65  }
66 };
67 
68 static const uint MAP_SL_BUF_SIZE = 4096;
69 
71  MAPTChunkHandler() : ChunkHandler('MAPT', CH_RIFF) {}
72 
73  void Load() const override
74  {
75  std::array<byte, MAP_SL_BUF_SIZE> buf;
76  TileIndex size = MapSize();
77 
78  for (TileIndex i = 0; i != size;) {
79  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
80  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type = buf[j];
81  }
82  }
83 
84  void Save() const override
85  {
86  std::array<byte, MAP_SL_BUF_SIZE> buf;
87  TileIndex size = MapSize();
88 
89  SlSetLength(size);
90  for (TileIndex i = 0; i != size;) {
91  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type;
92  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
93  }
94  }
95 };
96 
98  MAPHChunkHandler() : ChunkHandler('MAPH', CH_RIFF) {}
99 
100  void Load() const override
101  {
102  std::array<byte, MAP_SL_BUF_SIZE> buf;
103  TileIndex size = MapSize();
104 
105  for (TileIndex i = 0; i != size;) {
106  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
107  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j];
108  }
109  }
110 
111  void Save() const override
112  {
113  std::array<byte, MAP_SL_BUF_SIZE> buf;
114  TileIndex size = MapSize();
115 
116  SlSetLength(size);
117  for (TileIndex i = 0; i != size;) {
118  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].height;
119  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
120  }
121  }
122 };
123 
125  MAPOChunkHandler() : ChunkHandler('MAPO', CH_RIFF) {}
126 
127  void Load() const override
128  {
129  std::array<byte, MAP_SL_BUF_SIZE> buf;
130  TileIndex size = MapSize();
131 
132  for (TileIndex i = 0; i != size;) {
133  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
134  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m1 = buf[j];
135  }
136  }
137 
138  void Save() const override
139  {
140  std::array<byte, MAP_SL_BUF_SIZE> buf;
141  TileIndex size = MapSize();
142 
143  SlSetLength(size);
144  for (TileIndex i = 0; i != size;) {
145  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m1;
146  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
147  }
148  }
149 };
150 
152  MAP2ChunkHandler() : ChunkHandler('MAP2', CH_RIFF) {}
153 
154  void Load() const override
155  {
156  std::array<uint16, MAP_SL_BUF_SIZE> buf;
157  TileIndex size = MapSize();
158 
159  for (TileIndex i = 0; i != size;) {
160  SlCopy(buf.data(), MAP_SL_BUF_SIZE,
161  /* In those versions the m2 was 8 bits */
162  IsSavegameVersionBefore(SLV_5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16
163  );
164  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m2 = buf[j];
165  }
166  }
167 
168  void Save() const override
169  {
170  std::array<uint16, MAP_SL_BUF_SIZE> buf;
171  TileIndex size = MapSize();
172 
173  SlSetLength(size * sizeof(uint16));
174  for (TileIndex i = 0; i != size;) {
175  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m2;
176  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
177  }
178  }
179 };
180 
182  M3LOChunkHandler() : ChunkHandler('M3LO', CH_RIFF) {}
183 
184  void Load() const override
185  {
186  std::array<byte, MAP_SL_BUF_SIZE> buf;
187  TileIndex size = MapSize();
188 
189  for (TileIndex i = 0; i != size;) {
190  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
191  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m3 = buf[j];
192  }
193  }
194 
195  void Save() const override
196  {
197  std::array<byte, MAP_SL_BUF_SIZE> buf;
198  TileIndex size = MapSize();
199 
200  SlSetLength(size);
201  for (TileIndex i = 0; i != size;) {
202  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m3;
203  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
204  }
205  }
206 };
207 
209  M3HIChunkHandler() : ChunkHandler('M3HI', CH_RIFF) {}
210 
211  void Load() const override
212  {
213  std::array<byte, MAP_SL_BUF_SIZE> buf;
214  TileIndex size = MapSize();
215 
216  for (TileIndex i = 0; i != size;) {
217  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
218  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m4 = buf[j];
219  }
220  }
221 
222  void Save() const override
223  {
224  std::array<byte, MAP_SL_BUF_SIZE> buf;
225  TileIndex size = MapSize();
226 
227  SlSetLength(size);
228  for (TileIndex i = 0; i != size;) {
229  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m4;
230  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
231  }
232  }
233 };
234 
236  MAP5ChunkHandler() : ChunkHandler('MAP5', CH_RIFF) {}
237 
238  void Load() const override
239  {
240  std::array<byte, MAP_SL_BUF_SIZE> buf;
241  TileIndex size = MapSize();
242 
243  for (TileIndex i = 0; i != size;) {
244  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
245  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m5 = buf[j];
246  }
247  }
248 
249  void Save() const override
250  {
251  std::array<byte, MAP_SL_BUF_SIZE> buf;
252  TileIndex size = MapSize();
253 
254  SlSetLength(size);
255  for (TileIndex i = 0; i != size;) {
256  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m5;
257  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
258  }
259  }
260 };
261 
263  MAPEChunkHandler() : ChunkHandler('MAPE', CH_RIFF) {}
264 
265  void Load() const override
266  {
267  std::array<byte, MAP_SL_BUF_SIZE> buf;
268  TileIndex size = MapSize();
269 
271  for (TileIndex i = 0; i != size;) {
272  /* 1024, otherwise we overflow on 64x64 maps! */
273  SlCopy(buf.data(), 1024, SLE_UINT8);
274  for (uint j = 0; j != 1024; j++) {
275  _me[i++].m6 = GB(buf[j], 0, 2);
276  _me[i++].m6 = GB(buf[j], 2, 2);
277  _me[i++].m6 = GB(buf[j], 4, 2);
278  _me[i++].m6 = GB(buf[j], 6, 2);
279  }
280  }
281  } else {
282  for (TileIndex i = 0; i != size;) {
283  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
284  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m6 = buf[j];
285  }
286  }
287  }
288 
289  void Save() const override
290  {
291  std::array<byte, MAP_SL_BUF_SIZE> buf;
292  TileIndex size = MapSize();
293 
294  SlSetLength(size);
295  for (TileIndex i = 0; i != size;) {
296  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m6;
297  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
298  }
299  }
300 };
301 
303  MAP7ChunkHandler() : ChunkHandler('MAP7', CH_RIFF) {}
304 
305  void Load() const override
306  {
307  std::array<byte, MAP_SL_BUF_SIZE> buf;
308  TileIndex size = MapSize();
309 
310  for (TileIndex i = 0; i != size;) {
311  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
312  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m7 = buf[j];
313  }
314  }
315 
316  void Save() const override
317  {
318  std::array<byte, MAP_SL_BUF_SIZE> buf;
319  TileIndex size = MapSize();
320 
321  SlSetLength(size);
322  for (TileIndex i = 0; i != size;) {
323  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m7;
324  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
325  }
326  }
327 };
328 
330  MAP8ChunkHandler() : ChunkHandler('MAP8', CH_RIFF) {}
331 
332  void Load() const override
333  {
334  std::array<uint16, MAP_SL_BUF_SIZE> buf;
335  TileIndex size = MapSize();
336 
337  for (TileIndex i = 0; i != size;) {
338  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
339  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m8 = buf[j];
340  }
341  }
342 
343  void Save() const override
344  {
345  std::array<uint16, MAP_SL_BUF_SIZE> buf;
346  TileIndex size = MapSize();
347 
348  SlSetLength(size * sizeof(uint16));
349  for (TileIndex i = 0; i != size;) {
350  for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m8;
351  SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
352  }
353  }
354 };
355 
356 static const MAPSChunkHandler MAPS;
357 static const MAPTChunkHandler MAPT;
358 static const MAPHChunkHandler MAPH;
359 static const MAPOChunkHandler MAPO;
360 static const MAP2ChunkHandler MAP2;
361 static const M3LOChunkHandler M3LO;
362 static const M3HIChunkHandler M3HI;
363 static const MAP5ChunkHandler MAP5;
364 static const MAPEChunkHandler MAPE;
365 static const MAP7ChunkHandler MAP7;
366 static const MAP8ChunkHandler MAP8;
367 static const ChunkHandlerRef map_chunk_handlers[] = {
368  MAPS,
369  MAPT,
370  MAPH,
371  MAPO,
372  MAP2,
373  M3LO,
374  M3HI,
375  MAP5,
376  MAPE,
377  MAP7,
378  MAP8,
379 };
380 
381 extern const ChunkHandlerTable _map_chunk_handlers(map_chunk_handlers);
TileIndex
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:83
MAPHChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:100
SLV_RIFF_TO_ARRAY
@ SLV_RIFF_TO_ARRAY
294 PR#9375 Changed many CH_RIFF chunks to CH_ARRAY chunks.
Definition: saveload.h:336
GB
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:32
MAPOChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:138
ChunkHandlerRef
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition: saveload.h:443
SlCopy
void SlCopy(void *object, size_t length, VarType conv)
Copy a list of SL_VARs to/from a savegame.
Definition: saveload.cpp:1151
MAP5ChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:238
MAPSChunkHandler::LoadCheck
void LoadCheck(size_t) const override
Load the chunk for game preview.
Definition: map_sl.cpp:55
_load_check_data
LoadCheckData _load_check_data
Data loaded from save during SL_LOAD_CHECK.
Definition: fios_gui.cpp:38
MAPSChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:33
_me
TileExtended * _me
Extended Tiles of the map.
Definition: map.cpp:31
MAPSChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:44
MAP5ChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:249
saveload.h
ChunkHandler::type
ChunkType type
Type of the chunk.
Definition: saveload.h:408
MAPOChunkHandler
Definition: map_sl.cpp:124
MAP8ChunkHandler
Definition: map_sl.cpp:329
MAP2ChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:154
ChunkHandler
Handlers and description of chunk.
Definition: saveload.h:406
SlSetLength
void SlSetLength(size_t length)
Sets the length of either a RIFF object or the number of items in an array.
Definition: saveload.cpp:723
MAP8ChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:343
M3HIChunkHandler
Definition: map_sl.cpp:208
MAP7ChunkHandler
Definition: map_sl.cpp:302
SlGlobList
void SlGlobList(const SaveLoadTable &slt)
Save or Load (a list of) global variables.
Definition: saveload.cpp:2083
MapSizeX
static uint MapSizeX()
Get the size of the map along the X.
Definition: map_func.h:72
MAPHChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:111
SLV_5
@ SLV_5
5.0 1429 5.1 1440 5.2 1525 0.3.6
Definition: saveload.h:47
TileExtended::m6
byte m6
General purpose.
Definition: map_type.h:34
M3HIChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:211
MapSize
static uint MapSize()
Get the size of the map.
Definition: map_func.h:92
MAPTChunkHandler
Definition: map_sl.cpp:70
MAP2ChunkHandler
Definition: map_sl.cpp:151
span
A trimmed down version of what std::span will be in C++20.
Definition: span_type.hpp:60
MAP2ChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:168
M3LOChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:195
MAP7ChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:316
_map_sl_compat
const SaveLoadCompat _map_sl_compat[]
Original field order for _map_desc.
Definition: map_sl_compat.h:16
MAPSChunkHandler
Definition: map_sl.cpp:30
M3HIChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:222
MAP7ChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:305
IsSavegameVersionBefore
static bool IsSavegameVersionBefore(SaveLoadVersion major, byte minor=0)
Checks whether the savegame is below major.
Definition: saveload.h:1024
MapSizeY
static uint MapSizeY()
Get the size of the map along the Y.
Definition: map_func.h:82
MAP8ChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:332
SLV_42
@ SLV_42
42 7573
Definition: saveload.h:97
SL_MAX_VERSION
@ SL_MAX_VERSION
Highest possible saveload version.
Definition: saveload.h:342
MAPEChunkHandler
Definition: map_sl.cpp:262
SLEG_CONDVAR
#define SLEG_CONDVAR(name, variable, type, from, to)
Storage of a global variable in some savegame versions.
Definition: saveload.h:849
SLV_6
@ SLV_6
6.0 1721 6.1 1768
Definition: saveload.h:50
SlErrorCorrupt
void NORETURN SlErrorCorrupt(const char *msg)
Error handler for corrupt savegames.
Definition: saveload.cpp:364
MAPTChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:84
MAPEChunkHandler::Save
void Save() const override
Save the chunk.
Definition: map_sl.cpp:289
MAPEChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:265
M3LOChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:184
SlCompatTableHeader
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
Definition: saveload.cpp:2029
MAPOChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:127
MAP5ChunkHandler
Definition: map_sl.cpp:235
SlTableHeader
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
Definition: saveload.cpp:1891
SaveLoad
SaveLoad type struct.
Definition: saveload.h:653
AllocateMap
void AllocateMap(uint size_x, uint size_y)
(Re)allocates a map with the given dimension
Definition: map.cpp:39
_m
Tile * _m
Tiles of the map.
Definition: map.cpp:30
SlIterateArray
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition: saveload.cpp:670
M3LOChunkHandler
Definition: map_sl.cpp:181
map_sl_compat.h
MAPHChunkHandler
Definition: map_sl.cpp:97
MAPTChunkHandler::Load
void Load() const override
Load the chunk.
Definition: map_sl.cpp:73