Slightly improve code when converting old signals
[openttd/fttd.git] / src / saveload / map_sl.cpp
blobb0d25b9c63a5b15302e2002dc82d1cb107741181
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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 */
10 /** @file map_sl.cpp Code handling saving and loading of map */
12 #include "../stdafx.h"
13 #include "../core/bitmath_func.hpp"
14 #include "../core/random_func.hpp"
15 #include "../fios.h"
16 #include "../town.h"
17 #include "../landscape_type.h"
18 #include "../signal_type.h"
19 #include "../map/ground.h"
20 #include "../map/water.h"
21 #include "../map/station.h"
23 #include "saveload_buffer.h"
26 enum OldTileType {
27 OLD_MP_CLEAR, ///< A tile without any structures, i.e. grass, docks, farm fields etc.
28 OLD_MP_RAILWAY, ///< A railway
29 OLD_MP_ROAD, ///< A tile with road (or tram tracks)
30 OLD_MP_HOUSE, ///< A house by a town
31 OLD_MP_TREES, ///< Tile got trees
32 OLD_MP_STATION, ///< A tile of a station
33 OLD_MP_WATER, ///< Water tile
34 OLD_MP_VOID, ///< Invisible tiles at the SW and SE border
35 OLD_MP_INDUSTRY, ///< Part of an industry
36 OLD_MP_TUNNELBRIDGE, ///< Tunnel entry/exit and bridge heads
37 OLD_MP_OBJECT, ///< Contains objects such as transmitters and owned land
40 static inline OldTileType GetOldTileType(TileIndex tile)
42 assert(tile < MapSize());
43 return (OldTileType)GB(_mth[tile], 4, 4);
46 static inline bool IsOldTileType(TileIndex tile, OldTileType type)
48 return GetOldTileType(tile) == type;
51 static inline void SetOldTileType(TileIndex tile, OldTileType type)
53 SB(_mth[tile], 4, 4, type);
56 static inline uint OldTileHeight(TileIndex tile)
58 assert(tile < MapSize());
59 return GB(_mth[tile], 0, 4);
62 static bool IsOldTileFlat(TileIndex tile)
64 assert(tile < MapSize());
66 if (TileX(tile) == MapMaxX() || TileY(tile) == MapMaxY() ||
67 TileX(tile) == 0 || TileY(tile) == 0) {
68 return true;
71 uint h = OldTileHeight(tile);
72 if (OldTileHeight(tile + TileDiffXY(1, 0)) != h) return false;
73 if (OldTileHeight(tile + TileDiffXY(0, 1)) != h) return false;
74 if (OldTileHeight(tile + TileDiffXY(1, 1)) != h) return false;
76 return true;
80 /**
81 * Fix map array after loading an old savegame
83 void AfterLoadMap(const SavegameTypeVersion *stv)
85 TileIndex map_size = MapSize();
87 /* in legacy version 2.1 of the savegame, town owner was unified. */
88 if (IsOTTDSavegameVersionBefore(stv, 2, 1)) {
89 for (TileIndex tile = 0; tile < map_size; tile++) {
90 switch (GetOldTileType(tile)) {
91 case OLD_MP_ROAD:
92 if (GB(_mc[tile].m5, 4, 2) == 1 && HasBit(_mc[tile].m3, 7)) {
93 _mc[tile].m3 = OWNER_TOWN;
95 /* FALL THROUGH */
97 case OLD_MP_TUNNELBRIDGE:
98 if (_mc[tile].m1 & 0x80) SB(_mc[tile].m1, 0, 5, OWNER_TOWN);
99 break;
101 default: break;
106 /* In legacy version 6.1 we put the town index in the map-array. To do this, we need
107 * to use m2 (16bit big), so we need to clean m2, and that is where this is
108 * all about ;) */
109 if (IsOTTDSavegameVersionBefore(stv, 6, 1)) {
110 for (TileIndex t = 0; t < map_size; t++) {
111 switch (GetOldTileType(t)) {
112 case OLD_MP_HOUSE:
113 _mc[t].m4 = _mc[t].m2;
114 _mc[t].m2 = 0;
115 break;
117 case OLD_MP_ROAD:
118 _mc[t].m4 |= (_mc[t].m2 << 4);
119 _mc[t].m2 = 0;
120 break;
122 default: break;
127 /* From legacy version 15, we moved a semaphore bit from bit 2 to bit 3 in m4, making
128 * room for PBS. Now in version 21 move it back :P. */
129 if (IsOTTDSavegameVersionBefore(stv, 21) && !IsOTTDSavegameVersionBefore(stv, 15)) {
130 for (TileIndex t = 0; t < map_size; t++) {
131 switch (GetOldTileType(t)) {
132 case OLD_MP_RAILWAY:
133 if (GB(_mc[t].m5, 6, 2) == 1) {
134 /* convert PBS signals to combo-signals */
135 if (HasBit(_mc[t].m2, 2)) SB(_mc[t].m2, 0, 3, 3);
137 /* move the signal variant back */
138 SB(_mc[t].m2, 3, 1, HasBit(_mc[t].m2, 3) ? SIG_SEMAPHORE : SIG_ELECTRIC);
139 ClrBit(_mc[t].m2, 3);
142 /* Clear PBS reservation on track */
143 if (GB(_mc[t].m5, 6, 2) != 3) {
144 SB(_mc[t].m4, 4, 4, 0);
145 } else {
146 ClrBit(_mc[t].m3, 6);
148 break;
150 case OLD_MP_STATION: // Clear PBS reservation on station
151 ClrBit(_mc[t].m3, 6);
152 break;
154 default: break;
159 if (IsOTTDSavegameVersionBefore(stv, 48)) {
160 for (TileIndex t = 0; t < map_size; t++) {
161 switch (GetOldTileType(t)) {
162 case OLD_MP_RAILWAY:
163 if (!HasBit(_mc[t].m5, 7)) {
164 /* Swap ground type and signal type for plain rail tiles, so the
165 * ground type uses the same bits as for depots and waypoints. */
166 uint tmp = GB(_mc[t].m4, 0, 4);
167 SB(_mc[t].m4, 0, 4, GB(_mc[t].m2, 0, 4));
168 SB(_mc[t].m2, 0, 4, tmp);
169 } else if (HasBit(_mc[t].m5, 2)) {
170 /* Split waypoint and depot rail type and remove the subtype. */
171 ClrBit(_mc[t].m5, 2);
172 ClrBit(_mc[t].m5, 6);
174 break;
176 case OLD_MP_ROAD:
177 /* Swap m3 and m4, so the track type for rail crossings is the
178 * same as for normal rail. */
179 Swap(_mc[t].m3, _mc[t].m4);
180 break;
182 default: break;
187 /* From legacy version 53, the map array was changed for house tiles to allow
188 * space for newhouses grf features. A new byte, m7, was also added. */
189 if (IsOTTDSavegameVersionBefore(stv, 53)) {
190 for (TileIndex t = 0; t < map_size; t++) {
191 if (IsOldTileType(t, OLD_MP_HOUSE)) {
192 if (GB(_mc[t].m3, 6, 2) != TOWN_HOUSE_COMPLETED) {
193 /* Move the construction stage from m3[7..6] to m5[5..4].
194 * The construction counter does not have to move. */
195 SB(_mc[t].m5, 3, 2, GB(_mc[t].m3, 6, 2));
196 SB(_mc[t].m3, 6, 2, 0);
197 } else {
198 /* The "lift has destination" bit has been moved from
199 * m5[7] to m7[0]. */
200 SB(_mc[t].m7, 0, 1, HasBit(_mc[t].m5, 7));
201 ClrBit(_mc[t].m5, 7);
203 /* The "lift is moving" bit has been removed, as it does
204 * the same job as the "lift has destination" bit. */
205 ClrBit(_mc[t].m1, 7);
207 /* The position of the lift goes from m1[7..0] to m0[7..2],
208 * making m1 totally free, now. The lift position does not
209 * have to be a full byte since the maximum value is 36. */
210 SB(_mc[t].m0, 2, 6, GB(_mc[t].m1, 0, 6 ));
212 _mc[t].m1 = 0;
213 _mc[t].m3 = 0x80;
219 if (IsOTTDSavegameVersionBefore(stv, 64)) {
220 /* Since now we allow different signal types and variants on a single tile.
221 * Move signal states to m4 to make room and clone the signal type/variant. */
222 for (TileIndex t = 0; t < map_size; t++) {
223 if (IsOldTileType(t, OLD_MP_RAILWAY) && GB(_mc[t].m5, 6, 2) == 1) {
224 /* move signal states */
225 SB(_mc[t].m4, 4, 4, GB(_mc[t].m2, 4, 4));
226 /* clone signal type and variant */
227 SB(_mc[t].m2, 4, 3, GB(_mc[t].m2, 0, 3));
228 ClrBit(_mc[t].m2, 7);
233 if (IsOTTDSavegameVersionBefore(stv, 72)) {
234 /* Locks in very old savegames had OWNER_WATER as owner */
235 for (TileIndex t = 0; t < map_size; t++) {
236 switch (GetOldTileType(t)) {
237 default: break;
239 case OLD_MP_WATER:
240 if (GB(_mc[t].m5, 4, 4) == 1 && GB(_mc[t].m1, 0, 5) == OWNER_WATER) SB(_mc[t].m1, 0, 5, OWNER_NONE);
241 break;
243 case OLD_MP_STATION: {
244 if (HasBit(_mc[t].m0, 3)) SetBit(_mc[t].m0, 2);
245 byte gfx = _mc[t].m5;
246 int st;
247 if ( IsInsideMM(gfx, 0, 8)) { // Rail station
248 st = 0;
249 _mc[t].m5 = gfx - 0;
250 } else if (IsInsideMM(gfx, 8, 67)) { // Airport
251 st = 1;
252 _mc[t].m5 = gfx - 8;
253 } else if (IsInsideMM(gfx, 67, 71)) { // Truck
254 st = 2;
255 _mc[t].m5 = gfx - 67;
256 } else if (IsInsideMM(gfx, 71, 75)) { // Bus
257 st = 3;
258 _mc[t].m5 = gfx - 71;
259 } else if (gfx == 75) { // Oil rig
260 st = 4;
261 _mc[t].m5 = gfx - 75;
262 } else if (IsInsideMM(gfx, 76, 82)) { // Dock
263 st = 5;
264 _mc[t].m5 = gfx - 76;
265 } else if (gfx == 82) { // Buoy
266 st = 6;
267 _mc[t].m5 = gfx - 82;
268 } else if (IsInsideMM(gfx, 83, 168)) { // Extended airport
269 st = 1;
270 _mc[t].m5 = gfx - 83 + 67 - 8;
271 } else if (IsInsideMM(gfx, 168, 170)) { // Drive through truck
272 st = 2;
273 _mc[t].m5 = gfx - 168 + GFX_ROAD_DT_OFFSET;
274 } else if (IsInsideMM(gfx, 170, 172)) { // Drive through bus
275 st = 3;
276 _mc[t].m5 = gfx - 170 + GFX_ROAD_DT_OFFSET;
277 } else {
278 throw SlCorrupt("Invalid station tile");
280 SB(_mc[t].m0, 3, 3, st);
281 break;
287 /* Before legacy version 81, the density of grass was always stored as zero, and
288 * grassy trees were always drawn fully grassy. Furthermore, trees on rough
289 * land used to have zero density, now they have full density. Therefore,
290 * make all grassy/rough land trees have a density of 3. */
291 if (IsOTTDSavegameVersionBefore(stv, 81)) {
292 for (TileIndex t = 0; t < map_size; t++) {
293 if (GetOldTileType(t) == OLD_MP_TREES) {
294 uint groundType = GB(_mc[t].m2, 4, 2);
295 if (groundType != 2) SB(_mc[t].m2, 6, 2, 3);
300 /* The void tiles on the southern border used to belong to a wrong class (pre 4.3).
301 * This problem appears in savegame version 21 too, see r3455. But after loading the
302 * savegame and saving again, the buggy map array could be converted to new savegame
303 * version. It didn't show up before r12070. */
304 if (IsOTTDSavegameVersionBefore(stv, 87)) {
305 TileIndex t;
307 for (t = MapMaxX(); t < map_size - 1; t += MapSizeX()) {
308 _mth[t] = OLD_MP_VOID << 4;
309 memset(&_mc[t], 0, sizeof(_mc[t]));
312 for (t = MapSizeX() * MapMaxY(); t < map_size; t++) {
313 _mth[t] = OLD_MP_VOID << 4;
314 memset(&_mc[t], 0, sizeof(_mc[t]));
318 if (IsOTTDSavegameVersionBefore(stv, 114)) {
319 bool old_bridge = IsOTTDSavegameVersionBefore(stv, 42);
320 bool add_roadtypes = IsOTTDSavegameVersionBefore(stv, 61);
322 for (TileIndex t = 0; t < map_size; t++) {
323 switch (GetOldTileType(t)) {
324 case OLD_MP_CLEAR:
325 case OLD_MP_RAILWAY:
326 case OLD_MP_WATER:
327 case OLD_MP_OBJECT:
328 if (old_bridge) SB(_mc[t].m0, 6, 2, 0);
329 break;
331 case OLD_MP_ROAD:
332 if (add_roadtypes) {
333 SB(_mc[t].m5, 6, 2, GB(_mc[t].m5, 4, 2));
334 SB(_mc[t].m7, 6, 2, 1);
335 } else {
336 SB(_mc[t].m7, 6, 2, GB(_mc[t].m7, 5, 3));
338 SB(_mc[t].m7, 5, 1, GB(_mc[t].m3, 7, 1)); // snow/desert
339 switch (GB(_mc[t].m5, 6, 2)) {
340 default: throw SlCorrupt("Invalid road tile type");
341 case 0:
342 if (add_roadtypes) {
343 SB(_mc[t].m0, 2, 4, 0);
344 } else {
345 SB(_mc[t].m5, 0, 4, GB(_mc[t].m4, 0, 4)); // road bits
347 SB(_mc[t].m7, 0, 4, GB(_mc[t].m3, 0, 4)); // road works
348 SB(_mc[t].m0, 3, 3, GB(_mc[t].m3, 4, 3)); // ground
349 SB(_mc[t].m3, 0, 4, add_roadtypes ? 0 : GB(_mc[t].m4, 4, 4)); // tram bits
350 SB(_mc[t].m3, 4, 4, GB(_mc[t].m5, 0, 4)); // tram owner
351 break;
353 case 1:
354 SB(_mc[t].m7, 0, 5, GB(_mc[t].m4, 0, 5)); // road owner
355 SB(_mc[t].m0, 3, 3, GB(_mc[t].m3, 4, 3)); // ground
356 SB(_mc[t].m3, 4, 4, GB(_mc[t].m5, 0, 4)); // tram owner
357 SB(_mc[t].m5, 0, 1, add_roadtypes ? GB(_mc[t].m5, 3, 1) : GB(_mc[t].m4, 6, 1)); // road axis
358 SB(_mc[t].m5, 5, 1, add_roadtypes ? GB(_mc[t].m5, 2, 1) : GB(_mc[t].m4, 5, 1)); // crossing state
359 break;
361 case 2:
362 break;
364 _mc[t].m4 = 0;
365 if (old_bridge) SB(_mc[t].m0, 6, 2, 0);
366 break;
368 case OLD_MP_STATION:
369 if (GB(_mc[t].m0, 4, 2) != 1) break;
371 SB(_mc[t].m7, 6, 2, add_roadtypes ? 1 : GB(_mc[t].m3, 0, 3));
372 SB(_mc[t].m7, 0, 5, HasBit(_mc[t].m0, 2) ? OWNER_TOWN : (Owner)GB(_mc[t].m1, 0, 5));
373 SB(_mc[t].m3, 4, 4, _mc[t].m1);
374 _mc[t].m4 = 0;
375 break;
377 case OLD_MP_TUNNELBRIDGE: {
378 if (!old_bridge || !HasBit(_mc[t].m5, 7) || !HasBit(_mc[t].m5, 6)) {
379 if (((old_bridge && HasBit(_mc[t].m5, 7)) ? GB(_mc[t].m5, 1, 2) : GB(_mc[t].m5, 2, 2)) == 1) {
380 /* Middle part of "old" bridges */
381 SB(_mc[t].m7, 6, 2, add_roadtypes ? 1 : GB(_mc[t].m3, 0, 3));
383 Owner o = (Owner)GB(_mc[t].m1, 0, 5);
384 SB(_mc[t].m7, 0, 5, o); // road owner
385 SB(_mc[t].m3, 4, 4, o == OWNER_NONE ? OWNER_TOWN : o); // tram owner
387 SB(_mc[t].m0, 2, 4, GB(_mc[t].m2, 4, 4)); // bridge type
388 SB(_mc[t].m7, 5, 1, GB(_mc[t].m4, 7, 1)); // snow/desert
390 _mc[t].m2 = 0;
391 _mc[t].m4 = 0;
392 if (old_bridge) SB(_mc[t].m0, 6, 2, 0);
395 if (!old_bridge || !HasBit(_mc[t].m5, 7)) break;
397 Axis axis = (Axis)GB(_mc[t].m5, 0, 1);
399 if (HasBit(_mc[t].m5, 6)) { // middle part
400 if (HasBit(_mc[t].m5, 5)) { // transport route under bridge?
401 if (GB(_mc[t].m5, 3, 2) == 0) {
402 SetOldTileType(t, OLD_MP_RAILWAY);
403 _mc[t].m2 = 0;
404 SB(_mc[t].m3, 4, 4, 0);
405 _mc[t].m5 = axis == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X;
406 _mc[t].m4 = _mc[t].m7 = 0;
407 } else {
408 SetOldTileType(t, OLD_MP_ROAD);
409 _mc[t].m2 = INVALID_TOWN;
410 _mc[t].m3 = _mc[t].m4 = 0;
411 SB(_mc[t].m3, 4, 4, OWNER_TOWN);
412 _mc[t].m5 = axis == AXIS_X ? ROAD_Y : ROAD_X;
413 _mc[t].m7 = 1 << 6;
415 } else if (GB(_mc[t].m5, 3, 2) == 0) {
416 SetOldTileType(t, OLD_MP_CLEAR);
417 _mc[t].m1 = OWNER_NONE;
418 _mc[t].m2 = 0;
419 _mc[t].m3 = _mc[t].m4 = _mc[t].m7 = 0;
420 _mc[t].m5 = 3;
421 } else if (!IsOldTileFlat(t)) {
422 SetOldTileType(t, OLD_MP_WATER);
423 SB(_mc[t].m1, 0, 5, OWNER_WATER);
424 SB(_mc[t].m1, 5, 2, WATER_CLASS_SEA);
425 _mc[t].m2 = 0;
426 _mc[t].m3 = _mc[t].m4 = _mc[t].m7 = 0;
427 _mc[t].m5 = 1;
428 } else if (GB(_mc[t].m1, 0, 5) == OWNER_WATER) {
429 SetOldTileType(t, OLD_MP_WATER);
430 SB(_mc[t].m1, 0, 5, OWNER_WATER);
431 SB(_mc[t].m1, 5, 2, WATER_CLASS_SEA);
432 _mc[t].m2 = 0;
433 _mc[t].m3 = _mc[t].m4 = _mc[t].m5 = _mc[t].m7 = 0;
434 } else {
435 SetOldTileType(t, OLD_MP_WATER);
436 SB(_mc[t].m1, 5, 2, WATER_CLASS_CANAL);
437 _mc[t].m2 = 0;
438 _mc[t].m3 = _mc[t].m5 = _mc[t].m7 = 0;
439 _mc[t].m4 = Random();
441 SB(_mc[t].m0, 2, 6, (1 << 4) << axis);
442 } else { // ramp
443 DiagDirection dir = AxisToDiagDir(axis);
444 if (HasBit(_mc[t].m5, 5)) dir = ReverseDiagDir(dir);
445 TransportType type = (TransportType)GB(_mc[t].m5, 1, 2);
447 _mc[t].m5 = 1 << 7 | type << 2 | dir;
450 break;
453 default: break;
458 /* From legacy version 82, old style canals (above sealevel (0), WATER owner) are no longer supported.
459 Replace the owner for those by OWNER_NONE. */
460 if (IsOTTDSavegameVersionBefore(stv, 82)) {
461 for (TileIndex t = 0; t < map_size; t++) {
462 if (IsOldTileType(t, OLD_MP_WATER) &&
463 _mc[t].m5 == 0 &&
464 GB(_mc[t].m1, 0, 5) == OWNER_WATER &&
465 OldTileHeight(t) != 0) {
466 SB(_mc[t].m1, 0, 5, OWNER_NONE);
472 * Add the 'previous' owner to the ship depots so we can reset it with
473 * the correct values when it gets destroyed. This prevents that
474 * someone can remove canals owned by somebody else and it prevents
475 * making floods using the removal of ship depots.
477 if (IsOTTDSavegameVersionBefore(stv, 83)) {
478 for (TileIndex t = 0; t < map_size; t++) {
479 if (IsOldTileType(t, OLD_MP_WATER) && GB(_mc[t].m5, 4, 4) == 8) {
480 _mc[t].m4 = (OldTileHeight(t) == 0) ? OWNER_WATER : OWNER_NONE;
485 /* The water class was moved/unified. */
486 if (IsOTTDSavegameVersionBefore(stv, 146)) {
487 for (TileIndex t = 0; t < map_size; t++) {
488 switch (GetOldTileType(t)) {
489 case OLD_MP_STATION:
490 switch (GB(_mc[t].m0, 3, 3)) {
491 case 4:
492 case 5:
493 case 6:
494 SB(_mc[t].m1, 5, 2, GB(_mc[t].m3, 0, 2));
495 SB(_mc[t].m3, 0, 2, 0);
496 break;
498 default:
499 SB(_mc[t].m1, 5, 2, WATER_CLASS_INVALID);
500 break;
502 break;
504 case OLD_MP_WATER:
505 SB(_mc[t].m1, 5, 2, GB(_mc[t].m3, 0, 2));
506 SB(_mc[t].m3, 0, 2, 0);
507 break;
509 case OLD_MP_OBJECT:
510 SB(_mc[t].m1, 5, 2, WATER_CLASS_INVALID);
511 break;
513 default:
514 /* No water class. */
515 break;
520 if (IsOTTDSavegameVersionBefore(stv, 86)) {
521 for (TileIndex t = 0; t < map_size; t++) {
522 /* Move river flag and update canals to use water class */
523 if (IsOldTileType(t, OLD_MP_WATER) && GB(_mc[t].m1, 5, 2) != WATER_CLASS_RIVER) {
524 if (_mc[t].m5 == 0) {
525 if (GB(_mc[t].m1, 0, 5) == OWNER_WATER) {
526 SB(_mc[t].m1, 5, 2, WATER_CLASS_SEA);
527 _mc[t].m4 = 0;
528 } else {
529 SB(_mc[t].m1, 5, 2, WATER_CLASS_CANAL);
530 _mc[t].m4 = Random();
532 _mc[t].m2 = 0;
533 _mc[t].m3 = _mc[t].m5 = _mc[t].m7 = 0;
534 SB(_mc[t].m0, 2, 4, 0);
535 } else if (GB(_mc[t].m5, 4, 4) == 8) {
536 Owner o = (Owner)_mc[t].m4; // Original water owner
537 SB(_mc[t].m1, 5, 2, o == OWNER_WATER ? WATER_CLASS_SEA : WATER_CLASS_CANAL);
543 /* Move the signal variant back up one bit for PBS. We don't convert the old PBS
544 * format here, as an old layout wouldn't work properly anyway. To be safe, we
545 * clear any possible PBS reservations as well. */
546 if (IsOTTDSavegameVersionBefore(stv, 100)) {
547 for (TileIndex t = 0; t < map_size; t++) {
548 switch (GetOldTileType(t)) {
549 case OLD_MP_RAILWAY:
550 if (GB(_mc[t].m5, 6, 2) == 1) {
551 /* move the signal variant */
552 SB(_mc[t].m2, 3, 1, HasBit(_mc[t].m2, 2) ? SIG_SEMAPHORE : SIG_ELECTRIC);
553 SB(_mc[t].m2, 7, 1, HasBit(_mc[t].m2, 6) ? SIG_SEMAPHORE : SIG_ELECTRIC);
554 ClrBit(_mc[t].m2, 2);
555 ClrBit(_mc[t].m2, 6);
558 /* Clear PBS reservation on track */
559 if (GB(_mc[t].m5, 6, 2) == 3) {
560 ClrBit(_mc[t].m5, 4);
561 } else {
562 SB(_mc[t].m2, 8, 4, 0);
564 break;
566 case OLD_MP_ROAD: // Clear PBS reservation on crossing
567 if (GB(_mc[t].m5, 6, 2) == 1) ClrBit(_mc[t].m5, 4);
568 break;
570 case OLD_MP_STATION: // Clear PBS reservation on station
571 if (GB(_mc[t].m0, 3, 3) == 0 || GB(_mc[t].m0, 3, 3) == 7) ClrBit(_mc[t].m0, 2);
572 break;
574 case OLD_MP_TUNNELBRIDGE: // Clear PBS reservation on tunnels/bridges
575 if (GB(_mc[t].m5, 2, 2) == 0) ClrBit(_mc[t].m5, 4);
576 break;
578 default: break;
583 if (IsOTTDSavegameVersionBefore(stv, 112)) {
584 for (TileIndex t = 0; t < map_size; t++) {
585 /* Check for HQ bit being set, instead of using map accessor,
586 * since we've already changed it code-wise */
587 if (IsOldTileType(t, OLD_MP_OBJECT) && HasBit(_mc[t].m5, 7)) {
588 /* Move size and part identification of HQ out of the m5 attribute,
589 * on new locations */
590 _mc[t].m3 = GB(_mc[t].m5, 0, 5);
591 _mc[t].m5 = 4;
596 /* The bits for the tree ground and tree density have
597 * been swapped (m2 bits 7..6 and 5..4. */
598 if (IsOTTDSavegameVersionBefore(stv, 135)) {
599 for (TileIndex t = 0; t < map_size; t++) {
600 if (IsOldTileType(t, OLD_MP_CLEAR)) {
601 if (GB(_mc[t].m5, 2, 3) == 4) {
602 SB(_mc[t].m5, 2, 6, 0);
603 SetBit(_mc[t].m3, 4);
604 } else {
605 ClrBit(_mc[t].m3, 4);
607 } else if (IsOldTileType(t, OLD_MP_TREES)) {
608 uint density = GB(_mc[t].m2, 6, 2);
609 uint ground = GB(_mc[t].m2, 4, 2);
610 uint counter = GB(_mc[t].m2, 0, 4);
611 _mc[t].m2 = ground << 6 | density << 4 | counter;
616 /* Reset tropic zone for VOID tiles, they shall not have any. */
617 if (IsOTTDSavegameVersionBefore(stv, 141)) {
618 for (TileIndex t = 0; t < map_size; t++) {
619 if (IsOldTileType(t, OLD_MP_VOID)) SB(_mc[t].m0, 0, 2, 0);
623 if (IsOTTDSavegameVersionBefore(stv, 144)) {
624 for (TileIndex t = 0; t < map_size; t++) {
625 if (!IsOldTileType(t, OLD_MP_OBJECT)) continue;
627 /* Reordering/generalisation of the object bits. */
628 bool is_hq = _mc[t].m5 == 4;
629 SB(_mc[t].m0, 2, 4, is_hq ? GB(_mc[t].m3, 2, 3) : 0);
630 _mc[t].m3 = is_hq ? GB(_mc[t].m3, 1, 1) | GB(_mc[t].m3, 0, 1) << 4 : 0;
632 /* Make sure those bits are clear as well! */
633 _mc[t].m4 = 0;
634 _mc[t].m7 = 0;
638 if (IsOTTDSavegameVersionBefore(stv, 147)) {
639 /* Move the animation frame to the same location (m7) for all objects. */
640 for (TileIndex t = 0; t < map_size; t++) {
641 switch (GetOldTileType(t)) {
642 case OLD_MP_HOUSE:
643 /* This needs GRF knowledge, so it is done in AfterLoadGame */
644 break;
646 case OLD_MP_INDUSTRY:
647 Swap(_mc[t].m3, _mc[t].m7);
648 break;
650 case OLD_MP_OBJECT:
651 /* hack: temporarily store offset in m4;
652 * it will be used (and removed) in AfterLoadGame */
653 _mc[t].m4 = _mc[t].m3;
655 /* move the animation state. */
656 _mc[t].m7 = GB(_mc[t].m0, 2, 4);
657 SB(_mc[t].m0, 2, 4, 0);
658 _mc[t].m3 = 0;
659 break;
661 default:
662 /* For stations/airports it's already at m7 */
663 break;
668 if (IsOTTDSavegameVersionBefore(stv, 164)) {
669 /* We store 4 fences in the field tiles instead of only SE and SW. */
670 for (TileIndex t = 0; t < map_size; t++) {
671 if (!IsOldTileType(t, OLD_MP_CLEAR) && !IsOldTileType(t, OLD_MP_TREES)) continue;
672 if (IsOldTileType(t, OLD_MP_CLEAR) && !HasBit(_mc[t].m3, 4) && GB(_mc[t].m5, 2, 3) == 3) continue;
674 uint fence = GB(_mc[t].m4, 5, 3);
675 if (fence != 0) {
676 TileIndex neighbour = TILE_ADDXY(t, 1, 0);
677 if (IsOldTileType(neighbour, OLD_MP_CLEAR) && !HasBit(_mc[neighbour].m3, 4) && GB(_mc[neighbour].m5, 2, 3) == 3) {
678 SB(_mc[neighbour].m3, 5, 3, fence);
682 fence = GB(_mc[t].m4, 2, 3);
683 if (fence != 0) {
684 TileIndex neighbour = TILE_ADDXY(t, 0, 1);
685 if (IsOldTileType(neighbour, OLD_MP_CLEAR) && !HasBit(_mc[neighbour].m3, 4) && GB(_mc[neighbour].m5, 2, 3) == 3) {
686 SB(_mc[neighbour].m0, 2, 3, fence);
690 SB(_mc[t].m4, 2, 3, 0);
691 SB(_mc[t].m4, 5, 3, 0);
695 /* Switch to the new map array */
696 if (IsFullSavegameVersionBefore(stv, 1)) {
697 for (TileIndex t = 0; t < map_size; t++) {
698 uint zone = GB(_mc[t].m0, 0, 2);
700 switch (GetOldTileType(t)) {
701 case OLD_MP_CLEAR: {
702 uint fence_nw = GB(_mc[t].m0, 2, 3);
703 _mc[t].m0 = GB(_mc[t].m0, 6, 2) | (TT_GROUND << 4);
704 uint ground = GB(_mc[t].m5, 2, 3);
705 if (ground == 3) {
706 SB(_mc[t].m1, 6, 2, TT_GROUND_FIELDS);
707 uint counter = GB(_mc[t].m5, 5, 3);
708 SB(_mc[t].m5, 2, 3, fence_nw);
709 SB(_mc[t].m5, 5, 3, GB(_mc[t].m3, 5, 3));
710 SB(_mc[t].m3, 4, 4, GB(_mc[t].m3, 0, 4));
711 SB(_mc[t].m3, 0, 4, counter);
712 } else {
713 SB(_mc[t].m1, 6, 2, TT_GROUND_CLEAR);
714 _mc[t].m4 = GB(_mc[t].m5, 0, 2);
715 if (HasBit(_mc[t].m3, 4)) {
716 switch (ground) {
717 case 1: ground = GROUND_SNOW_ROUGH; break;
718 case 2: ground = GROUND_SNOW_ROCKS; break;
719 default: ground = GROUND_SNOW; break;
721 } else {
722 switch (ground) {
723 default: ground = GROUND_GRASS; break;
724 case 1: ground = GROUND_ROUGH; break;
725 case 2: ground = GROUND_ROCKS; break;
726 case 4: ground = GROUND_SNOW; break;
727 case 5: ground = GROUND_DESERT; break;
730 SB(_mc[t].m3, 4, 4, ground);
731 SB(_mc[t].m3, 0, 4, GB(_mc[t].m5, 5, 3));
732 _mc[t].m5 = 0;
734 _mc[t].m7 = 0;
735 break;
738 case OLD_MP_RAILWAY: {
739 uint ground = GB(_mc[t].m4, 0, 4);
740 if (!HasBit(_mc[t].m5, 7)) { // track
741 _mc[t].m0 = GB(_mc[t].m0, 6, 2) | (TT_RAILWAY << 4);
742 SB(_mc[t].m1, 6, 2, TT_TRACK);
743 if (HasBit(_mc[t].m5, 6)) { // with signals
744 _mc[t].m7 = GB(_mc[t].m4, 4, 2) | (GB(_mc[t].m3, 4, 2) << 2) | (GB(_mc[t].m2, 4, 3) << 4) | (GB(_mc[t].m2, 7, 1) << 7);
745 _mc[t].m4 = GB(_mc[t].m4, 6, 2) | (GB(_mc[t].m3, 6, 2) << 2) | (GB(_mc[t].m2, 0, 3) << 4) | (GB(_mc[t].m2, 3, 1) << 7);
746 } else {
747 _mc[t].m4 = _mc[t].m7 = 0;
749 SB(_mc[t].m3, 4, 4, ground);
750 SB(_mc[t].m2, 0, 8, GB(_mc[t].m5, 0, 6));
751 } else if (HasBit(_mc[t].m5, 6)) { // depot
752 _mc[t].m0 = GB(_mc[t].m0, 6, 2) | (TT_MISC << 4);
753 SB(_mc[t].m1, 6, 2, TT_MISC_DEPOT);
754 ClrBit(_mc[t].m1, 5);
755 SB(_mc[t].m3, 4, 4, ground == 12 ? 1 : 0);
756 _mc[t].m5 &= 0x13;
757 _mc[t].m4 = _mc[t].m7 = 0;
758 } else { // old waypoint
759 if (!IsOTTDSavegameVersionBefore(stv, 123)) {
760 throw SlCorrupt("Invalid rail tile type");
762 /* temporary hack; AfterLoadGame will fix this */
763 _mc[t].m0 = GB(_mc[t].m5, 4, 1) | (STATION_WAYPOINT << 1) | (TT_STATION << 4);
765 break;
768 case OLD_MP_ROAD: {
769 uint roadside = GB(_mc[t].m0, 3, 3);
770 _mc[t].m0 = GB(_mc[t].m0, 6, 2);
771 switch (GB(_mc[t].m5, 6, 2)) {
772 case 0: { // normal road
773 _mc[t].m0 |= (TT_ROAD << 4);
774 SB(_mc[t].m1, 6, 2, TT_TRACK);
775 _mc[t].m4 = GB(_mc[t].m5, 0, 4) | (GB(_mc[t].m3, 0, 4) << 4);
776 SB(_mc[t].m5, 0, 4, GB(_mc[t].m3, 4, 4));
777 _mc[t].m3 = (GB(_mc[t].m5, 4, 2) << 6) | (GB(_mc[t].m7, 5, 1) << 4);
778 SB(_mc[t].m5, 4, 4, roadside);
779 break;
782 case 1: // level crossing
783 _mc[t].m0 |= (TT_MISC << 4);
784 SB(_mc[t].m1, 6, 2, TT_MISC_CROSSING);
785 SB(_mc[t].m3, 4, 4, GB(_mc[t].m7, 5, 1));
786 SB(_mc[t].m4, 5, 1, GB(_mc[t].m5, 0, 1));
787 SB(_mc[t].m4, 6, 1, GB(_mc[t].m5, 5, 1));
788 SB(_mc[t].m4, 7, 1, GB(_mc[t].m5, 4, 1));
789 _mc[t].m5 = GB(_mc[t].m3, 4, 4) | (roadside << 4);
790 break;
792 case 2: // road depot
793 _mc[t].m0 |= (TT_MISC << 4);
794 SB(_mc[t].m1, 6, 2, TT_MISC_DEPOT);
795 SetBit(_mc[t].m1, 5);
796 _mc[t].m3 = GB(_mc[t].m7, 5, 1) << 4;
797 _mc[t].m4 = 0;
798 _mc[t].m5 &= 0x03;
799 _mc[t].m7 &= 0xE0;
800 break;
802 break;
805 case OLD_MP_HOUSE: {
806 uint random = _mc[t].m1;
807 _mc[t].m1 = GB(_mc[t].m0, 2, 6) | (_mc[t].m3 & 0xC0);
808 _mc[t].m0 = GB(_mc[t].m3, 0, 6) | 0xC0;
809 _mc[t].m3 = random;
810 break;
813 case OLD_MP_TREES:
814 _mc[t].m0 = TT_GROUND << 4;
815 SB(_mc[t].m1, 6, 2, TT_GROUND_TREES);
816 _mc[t].m7 = _mc[t].m3;
817 switch (GB(_mc[t].m2, 6, 3)) {
818 case 0: _mc[t].m3 = GROUND_GRASS << 4; break;
819 case 1: _mc[t].m3 = GROUND_ROUGH << 4; break;
820 case 2: _mc[t].m3 = _settings_game.game_creation.landscape == LT_TROPIC ? GROUND_DESERT << 4 : GROUND_SNOW << 4; break;
821 case 3: _mc[t].m3 = GROUND_SHORE << 4; break;
822 case 4: _mc[t].m3 = GROUND_SNOW_ROUGH << 4; break;
824 SB(_mc[t].m3, 0, 4, GB(_mc[t].m2, 0, 4));
825 _mc[t].m4 = GB(_mc[t].m2, 4, 2);
826 _mc[t].m2 = 0;
827 break;
829 case OLD_MP_STATION: {
830 uint type = GB(_mc[t].m0, 2, 4);
831 if ((type == STATION_WAYPOINT) && IsOTTDSavegameVersionBefore(stv, 123)) {
832 throw SlCorrupt("Invalid station type");
834 _mc[t].m0 = type | (TT_STATION << 4);
835 break;
838 case OLD_MP_WATER:
839 _mc[t].m0 = GB(_mc[t].m0, 6, 2) | (TT_WATER << 4);
840 _mc[t].m3 = _mc[t].m4;
841 _mc[t].m4 = 0;
842 break;
844 case OLD_MP_VOID:
845 _mc[t].m0 = TT_GROUND << 4;
846 _mc[t].m1 = TT_GROUND_VOID << 6;
847 _mc[t].m2 = 0;
848 _mc[t].m3 = _mc[t].m4 = _mc[t].m5 = _mc[t].m7 = 0;
849 break;
851 case OLD_MP_INDUSTRY:
852 _mc[t].m0 = GB(_mc[t].m0, 3, 3) | (GB(_mc[t].m0, 2, 1) << 3) | 0x80;
853 break;
855 case OLD_MP_TUNNELBRIDGE:
856 if (HasBit(_mc[t].m5, 7)) { // bridge
857 uint type = GB(_mc[t].m0, 2, 4);
858 switch (GB(_mc[t].m5, 2, 2)) {
859 case 0: // rail
860 _mc[t].m0 = GB(_mc[t].m0, 6, 2) | (TT_RAILWAY << 4);
861 SB(_mc[t].m1, 6, 2, TT_BRIDGE);
862 SB(_mc[t].m2, 12, 4, type);
863 SB(_mc[t].m3, 4, 2, GB(_mc[t].m7, 5, 1));
864 SB(_mc[t].m3, 6, 2, GB(_mc[t].m5, 0, 2));
865 break;
866 case 1: { // road
867 _mc[t].m0 = GB(_mc[t].m0, 6, 2) | (TT_ROAD << 4);
868 SB(_mc[t].m1, 6, 2, TT_BRIDGE);
869 if (HasBit(_mc[t].m7, 6)) SB(_mc[t].m1, 0, 5, GB(_mc[t].m7, 0, 5));
870 uint tram = GB(_mc[t].m3, 4, 4);
871 _mc[t].m3 = (GB(_mc[t].m5, 0, 2) << 6) | (GB(_mc[t].m7, 5, 1) << 4);
872 _mc[t].m5 = tram;
873 SB(_mc[t].m7, 0, 4, type);
874 } break;
875 case 2: // aqueduct
876 _mc[t].m0 = GB(_mc[t].m0, 6, 2) | (TT_MISC << 4);
877 SB(_mc[t].m1, 6, 2, TT_MISC_AQUEDUCT);
878 _mc[t].m3 = (GB(_mc[t].m5, 0, 2) << 6) | (GB(_mc[t].m7, 5, 1) << 4);
879 _mc[t].m5 = 0;
880 break;
881 default:
882 throw SlCorrupt("Invalid bridge transport type");
884 } else { // tunnel
885 _mc[t].m0 = GB(_mc[t].m0, 6, 2) | (TT_MISC << 4);
886 SB(_mc[t].m1, 6, 2, TT_MISC_TUNNEL);
887 uint tram = GB(_mc[t].m3, 4, 4);
888 SB(_mc[t].m3, 4, 2, GB(_mc[t].m7, 5, 1));
889 SB(_mc[t].m3, 6, 2, GB(_mc[t].m5, 0, 2));
890 SB(_mc[t].m5, 6, 2, GB(_mc[t].m5, 2, 2));
891 SB(_mc[t].m5, 0, 4, tram);
893 break;
895 case OLD_MP_OBJECT:
896 _mc[t].m0 = GB(_mc[t].m0, 6, 2) | (TT_OBJECT << 4);
897 break;
899 default:
900 throw SlCorrupt("Invalid tile type");
903 SB(_mth[t], 4, 4, zone << 2);
907 /* Add second railtype to rail tiles */
908 if (IsFullSavegameVersionBefore(stv, 3)) {
909 for (TileIndex t = 0; t < map_size; t++) {
910 if (IsTileTypeSubtype(t, TT_RAILWAY, TT_TRACK)) {
911 SB(_mc[t].m5, 0, 4, GB(_mc[t].m3, 0, 4));
916 /* Add road layout to road bridgeheads */
917 if (IsFullSavegameVersionBefore(stv, 7)) {
918 for (TileIndex t = 0; t < map_size; t++) {
919 if (IsTileTypeSubtype(t, TT_ROAD, TT_BRIDGE)) {
920 RoadBits bits = AxisToRoadBits(DiagDirToAxis((DiagDirection)GB(_mc[t].m3, 6, 2)));
921 SB(_mc[t].m4, 0, 4, HasBit(_mc[t].m7, 6) ? bits : 0);
922 SB(_mc[t].m4, 4, 4, HasBit(_mc[t].m7, 7) ? bits : 0);
927 /* Add track layout to rail bridgeheads */
928 if (IsFullSavegameVersionBefore(stv, 8)) {
929 for (TileIndex t = 0; t < map_size; t++) {
930 if (IsTileTypeSubtype(t, TT_RAILWAY, TT_BRIDGE)) {
931 Track track = DiagDirToDiagTrack((DiagDirection)GB(_mc[t].m3, 6, 2));
932 bool reserved = HasBit(_mc[t].m5, 4);
933 SB(_mc[t].m2, 0, 6, TrackToTrackBits(track));
934 SB(_mc[t].m2, 6, 1, reserved ? 1 : 0);
935 SB(_mc[t].m2, 8, 4, reserved ? (track + 1) : 0);
936 SB(_mc[t].m5, 4, 4, 0);
937 _mc[t].m4 = _mc[t].m7 = 0;
942 /* Split tunnelhead/tunnel PBS reservation */
943 if (IsFullSavegameVersionBefore(stv, 9)) {
944 for (TileIndex t = 0; t < map_size; t++) {
945 if (IsTileTypeSubtype(t, TT_MISC, TT_MISC_TUNNEL) && GB(_mc[t].m5, 6, 2) == 0) {
946 if (HasBit(_mc[t].m5, 4)) {
947 SetBit(_mc[t].m5, 5);
948 } else {
949 ClrBit(_mc[t].m5, 5);
955 /* Roadworks now count down, not up */
956 if (IsFullSavegameVersionBefore(stv, 12)) {
957 for (TileIndex t = 0; t < map_size; t++) {
958 if (IsTileTypeSubtype(t, TT_ROAD, TT_TRACK)) {
959 uint roadside = GB(_mc[t].m5, 4, 3);
960 if (roadside > 5) {
961 SB(_mc[t].m5, 4, 3, roadside - 5);
962 SB(_mc[t].m7, 0, 4, 0xF - GB(_mc[t].m7, 0, 4));
968 /* Store direction for ship depots */
969 if (IsFullSavegameVersionBefore(stv, 14)) {
970 for (TileIndex t = 0; t < map_size; t++) {
971 if (IsTileType(t, TT_WATER) && GB(_mc[t].m5, 4, 4) == 8) {
972 DiagDirection dir = AxisToDiagDir((Axis)GB(_mc[t].m5, 1, 1));
973 SB(_mc[t].m5, 0, 2, HasBit(_mc[t].m5, 0) ? dir : ReverseDiagDir(dir));
980 struct MapDim {
981 uint32 x, y;
984 static const SaveLoad _map_dimensions[] = {
985 SLE_VAR(MapDim, x, SLE_UINT32, 0, , 6, ),
986 SLE_VAR(MapDim, y, SLE_UINT32, 0, , 6, ),
987 SLE_END()
990 static void Save_MAPS(SaveDumper *dumper)
992 MapDim map_dim;
993 map_dim.x = MapSizeX();
994 map_dim.y = MapSizeY();
995 dumper->WriteRIFFObject(&map_dim, _map_dimensions);
998 static void Load_MAPS(LoadBuffer *reader)
1000 MapDim map_dim;
1001 reader->ReadObject(&map_dim, _map_dimensions);
1002 AllocateMap(map_dim.x, map_dim.y);
1005 static void Check_MAPS(LoadBuffer *reader)
1007 MapDim map_dim;
1008 reader->ReadObject(&map_dim, _map_dimensions);
1009 _load_check_data.map_size_x = map_dim.x;
1010 _load_check_data.map_size_y = map_dim.y;
1013 static const uint MAP_SL_BUF_SIZE = 4096;
1015 static void Load_MAPT(LoadBuffer *reader)
1017 reader->CopyBytes(_mth, MapSize());
1020 static void Save_MAPT(SaveDumper *dumper)
1022 TileIndex size = MapSize();
1024 dumper->WriteRIFFSize(size);
1025 dumper->CopyBytes(_mth, size);
1028 static void Load_MAP1(LoadBuffer *reader)
1030 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1031 TileIndex size = MapSize();
1033 for (TileIndex i = 0; i != size;) {
1034 reader->ReadArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1035 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _mc[i++].m1 = buf[j];
1039 static void Save_MAP1(SaveDumper *dumper)
1041 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1042 TileIndex size = MapSize();
1044 dumper->WriteRIFFSize(size);
1045 for (TileIndex i = 0; i != size;) {
1046 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _mc[i++].m1;
1047 dumper->WriteArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1051 static void Load_MAP2(LoadBuffer *reader)
1053 SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
1054 TileIndex size = MapSize();
1056 for (TileIndex i = 0; i != size;) {
1057 reader->ReadArray(buf, MAP_SL_BUF_SIZE,
1058 /* In those versions the m2 was 8 bits */
1059 reader->IsOTTDVersionBefore(5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16
1061 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _mc[i++].m2 = buf[j];
1065 static void Save_MAP2(SaveDumper *dumper)
1067 SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
1068 TileIndex size = MapSize();
1070 dumper->WriteRIFFSize(size * sizeof(uint16));
1071 for (TileIndex i = 0; i != size;) {
1072 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _mc[i++].m2;
1073 dumper->WriteArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16);
1077 static void Load_MAP3(LoadBuffer *reader)
1079 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1080 TileIndex size = MapSize();
1082 for (TileIndex i = 0; i != size;) {
1083 reader->ReadArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1084 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _mc[i++].m3 = buf[j];
1088 static void Save_MAP3(SaveDumper *dumper)
1090 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1091 TileIndex size = MapSize();
1093 dumper->WriteRIFFSize(size);
1094 for (TileIndex i = 0; i != size;) {
1095 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _mc[i++].m3;
1096 dumper->WriteArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1100 static void Load_MAP4(LoadBuffer *reader)
1102 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1103 TileIndex size = MapSize();
1105 for (TileIndex i = 0; i != size;) {
1106 reader->ReadArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1107 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _mc[i++].m4 = buf[j];
1111 static void Save_MAP4(SaveDumper *dumper)
1113 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1114 TileIndex size = MapSize();
1116 dumper->WriteRIFFSize(size);
1117 for (TileIndex i = 0; i != size;) {
1118 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _mc[i++].m4;
1119 dumper->WriteArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1123 static void Load_MAP5(LoadBuffer *reader)
1125 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1126 TileIndex size = MapSize();
1128 for (TileIndex i = 0; i != size;) {
1129 reader->ReadArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1130 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _mc[i++].m5 = buf[j];
1134 static void Save_MAP5(SaveDumper *dumper)
1136 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1137 TileIndex size = MapSize();
1139 dumper->WriteRIFFSize(size);
1140 for (TileIndex i = 0; i != size;) {
1141 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _mc[i++].m5;
1142 dumper->WriteArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1146 static void Load_MAP0(LoadBuffer *reader)
1148 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1149 TileIndex size = MapSize();
1151 if (reader->IsOTTDVersionBefore(42)) {
1152 for (TileIndex i = 0; i != size;) {
1153 /* 1024, otherwise we overflow on 64x64 maps! */
1154 reader->ReadArray(buf, 1024, SLE_UINT8);
1155 for (uint j = 0; j != 1024; j++) {
1156 _mc[i++].m0 = GB(buf[j], 0, 2);
1157 _mc[i++].m0 = GB(buf[j], 2, 2);
1158 _mc[i++].m0 = GB(buf[j], 4, 2);
1159 _mc[i++].m0 = GB(buf[j], 6, 2);
1162 } else {
1163 for (TileIndex i = 0; i != size;) {
1164 reader->ReadArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1165 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _mc[i++].m0 = buf[j];
1170 static void Save_MAP0(SaveDumper *dumper)
1172 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1173 TileIndex size = MapSize();
1175 dumper->WriteRIFFSize(size);
1176 for (TileIndex i = 0; i != size;) {
1177 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _mc[i++].m0;
1178 dumper->WriteArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1182 static void Load_MAP7(LoadBuffer *reader)
1184 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1185 TileIndex size = MapSize();
1187 for (TileIndex i = 0; i != size;) {
1188 reader->ReadArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1189 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _mc[i++].m7 = buf[j];
1193 static void Save_MAP7(SaveDumper *dumper)
1195 SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
1196 TileIndex size = MapSize();
1198 dumper->WriteRIFFSize(size);
1199 for (TileIndex i = 0; i != size;) {
1200 for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _mc[i++].m7;
1201 dumper->WriteArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
1205 extern const ChunkHandler _map_chunk_handlers[] = {
1206 { 'MAPS', Save_MAPS, Load_MAPS, NULL, Check_MAPS, CH_RIFF },
1207 { 'MAPT', Save_MAPT, Load_MAPT, NULL, NULL, CH_RIFF },
1208 { 'MAPO', Save_MAP1, Load_MAP1, NULL, NULL, CH_RIFF },
1209 { 'MAP2', Save_MAP2, Load_MAP2, NULL, NULL, CH_RIFF },
1210 { 'M3LO', Save_MAP3, Load_MAP3, NULL, NULL, CH_RIFF },
1211 { 'M3HI', Save_MAP4, Load_MAP4, NULL, NULL, CH_RIFF },
1212 { 'MAP5', Save_MAP5, Load_MAP5, NULL, NULL, CH_RIFF },
1213 { 'MAPE', Save_MAP0, Load_MAP0, NULL, NULL, CH_RIFF },
1214 { 'MAP7', Save_MAP7, Load_MAP7, NULL, NULL, CH_RIFF | CH_LAST },