Keep a tileset of industries
[openttd/fttd.git] / src / saveload / oldloader_sl.cpp
bloba550c980a55246a5f89b37047c8349ef1fe681e2
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 oldloader_sl.cpp Chunks and fix-ups for TTO/TTD/TTDP savegames. TTO loader code is based on SVXConverter by Roman Vetter. */
12 #include "../stdafx.h"
13 #include "../town.h"
14 #include "../industry.h"
15 #include "../company_func.h"
16 #include "../aircraft.h"
17 #include "../roadveh.h"
18 #include "../ship.h"
19 #include "../train.h"
20 #include "../signs_base.h"
21 #include "../station_base.h"
22 #include "../subsidy_base.h"
23 #include "../debug.h"
24 #include "../depot_base.h"
25 #include "../date_func.h"
26 #include "../vehicle_func.h"
27 #include "../effectvehicle_base.h"
28 #include "../engine_func.h"
29 #include "../company_base.h"
30 #include "saveload_internal.h"
31 #include "saveload_error.h"
32 #include "oldloader.h"
34 #include "table/strings.h"
35 #include "../table/engines.h"
36 #include "../table/townname.h"
38 enum OldTileType {
39 OLD_MP_CLEAR, ///< A tile without any structures, i.e. grass, docks, farm fields etc.
40 OLD_MP_RAILWAY, ///< A railway
41 OLD_MP_ROAD, ///< A tile with road (or tram tracks)
42 OLD_MP_HOUSE, ///< A house by a town
43 OLD_MP_TREES, ///< Tile got trees
44 OLD_MP_STATION, ///< A tile of a station
45 OLD_MP_WATER, ///< Water tile
46 OLD_MP_VOID, ///< Invisible tiles at the SW and SE border
47 OLD_MP_INDUSTRY, ///< Part of an industry
48 OLD_MP_TUNNELBRIDGE, ///< Tunnel entry/exit and bridge heads
49 OLD_MP_OBJECT, ///< Contains objects such as transmitters and owned land
50 OLD_MP_MONORAIL,
53 static inline OldTileType GetOldTileType(TileIndex tile)
55 assert(tile < MapSize());
56 return (OldTileType)GB(_mth[tile], 4, 4);
59 static inline bool IsOldTileType(TileIndex tile, OldTileType type)
61 return GetOldTileType(tile) == type;
64 static inline void SetOldTileType(TileIndex tile, OldTileType type)
66 SB(_mth[tile], 4, 4, type);
69 static bool _read_ttdpatch_flags; ///< Have we (tried to) read TTDPatch extra flags?
70 static uint16 _old_extra_chunk_nums; ///< Number of extra TTDPatch chunks
71 static byte _old_vehicle_multiplier; ///< TTDPatch vehicle multiplier
73 static uint8 *_old_map3;
75 static void FixOldMapArray()
77 /* TTO/TTD/TTDP savegames could have buoys at tile 0
78 * (without assigned station struct) */
79 MemSetT(&_mc[0], 0);
80 SetOldTileType(0, OLD_MP_WATER);
81 SB(_mc[0].m1, 0, 5, OWNER_WATER);
84 static void FixTTDMapArray()
86 /* _old_map3 is moved to _m::m3 and _m::m4 */
87 for (TileIndex t = 0; t < OLD_MAP_SIZE; t++) {
88 _mc[t].m3 = _old_map3[t * 2];
89 _mc[t].m4 = _old_map3[t * 2 + 1];
92 for (TileIndex t = 0; t < OLD_MAP_SIZE; t++) {
93 switch (GetOldTileType(t)) {
94 case OLD_MP_STATION:
95 _mc[t].m4 = 0; // We do not understand this TTDP station mapping (yet)
96 switch (_mc[t].m5) {
97 /* We have drive through stops at a totally different place */
98 case 0x53: case 0x54: _mc[t].m5 += 170 - 0x53; break; // Bus drive through
99 case 0x57: case 0x58: _mc[t].m5 += 168 - 0x57; break; // Truck drive through
100 case 0x55: case 0x56: _mc[t].m5 += 170 - 0x55; break; // Bus tram stop
101 case 0x59: case 0x5A: _mc[t].m5 += 168 - 0x59; break; // Truck tram stop
102 default: break;
104 break;
106 case OLD_MP_RAILWAY:
107 /* We save presignals different from TTDPatch, convert them */
108 if (GB(_mc[t].m5, 6, 2) == 1) { // RAIL_TILE_SIGNALS
109 /* This byte is always zero in TTD for this type of tile */
110 if (_mc[t].m4) { // Convert the presignals to our own format
111 _mc[t].m4 = (_mc[t].m4 >> 1) & 7;
114 /* TTDPatch stores PBS things in L6 and all elsewhere; so we'll just
115 * clear it for ourselves and let OTTD's rebuild PBS itself */
116 _mc[t].m4 &= 0xF; // Only keep the lower four bits; upper four is PBS
117 break;
119 case OLD_MP_WATER:
120 /* if water class == 3, make river there */
121 if (GB(_mc[t].m3, 0, 2) == 3) {
122 SetOldTileType(t, OLD_MP_WATER);
123 SB(_mc[t].m1, 0, 5, OWNER_WATER);
124 _mc[t].m2 = 0;
125 _mc[t].m3 = 2; // WATER_CLASS_RIVER
126 _mc[t].m4 = Random();
127 _mc[t].m5 = 0;
129 break;
131 default:
132 break;
136 FixOldMapArray();
139 static void FixTTDDepots()
141 const Depot *d;
142 FOR_ALL_DEPOTS_FROM(d, 252) {
143 /** Workaround for SVXConverter bug, depots 252-255 could be invalid */
144 bool is_depot;
145 switch (GetOldTileType(d->xy)) {
146 case OLD_MP_RAILWAY:
147 is_depot = GB(_mc[d->xy].m5, 6, 2) == 3;
148 break;
149 case OLD_MP_ROAD:
150 is_depot = GB(_mc[d->xy].m5, 6, 2) == 2;
151 break;
152 case OLD_MP_WATER:
153 is_depot = GB(_mc[d->xy].m5, 4, 4) == 8;
154 break;
155 default:
156 is_depot = false;
158 if (!is_depot || _mc[d->xy].m2 != d->index) {
159 delete d;
164 #define FIXNUM(x, y, z) (((((x) << 16) / (y)) + 1) << z)
166 static uint32 RemapOldTownName(uint32 townnameparts, byte old_town_name_type)
168 switch (old_town_name_type) {
169 case 0: case 3: // English, American
170 /* Already OK */
171 return townnameparts;
173 case 1: // French
174 /* For some reason 86 needs to be subtracted from townnameparts
175 * 0000 0000 0000 0000 0000 0000 1111 1111 */
176 return FIXNUM(townnameparts - 86, lengthof(_name_french_real), 0);
178 case 2: // German
179 DEBUG(misc, 0, "German Townnames are buggy (%d)", townnameparts);
180 return townnameparts;
182 case 4: // Latin-American
183 /* 0000 0000 0000 0000 0000 0000 1111 1111 */
184 return FIXNUM(townnameparts, lengthof(_name_spanish_real), 0);
186 case 5: // Silly
187 /* NUM_SILLY_1 - lower 16 bits
188 * NUM_SILLY_2 - upper 16 bits without leading 1 (first 8 bytes)
189 * 1000 0000 2222 2222 0000 0000 1111 1111 */
190 return FIXNUM(townnameparts, lengthof(_name_silly_1), 0) | FIXNUM(GB(townnameparts, 16, 8), lengthof(_name_silly_2), 16);
192 return 0;
195 #undef FIXNUM
197 static void FixOldTowns()
199 Town *town;
201 /* Convert town-names if needed */
202 FOR_ALL_TOWNS(town) {
203 if (IsInsideMM(town->townnametype, 0x20C1, 0x20C3)) {
204 town->townnametype = SPECSTR_TOWNNAME_ENGLISH + _settings_game.game_creation.town_name;
205 town->townnameparts = RemapOldTownName(town->townnameparts, _settings_game.game_creation.town_name);
210 static StringID *_old_vehicle_names;
213 * Convert the old style vehicles into something that resembles
214 * the old new style savegames. Then #AfterLoadGame can handle
215 * the rest of the conversion.
217 void FixOldVehicles(const SavegameTypeVersion *stv)
219 Vehicle *v;
221 FOR_ALL_VEHICLES(v) {
222 if ((size_t)v->next == 0xFFFF) {
223 v->next = NULL;
224 } else {
225 v->next = Vehicle::GetIfValid((size_t)v->next);
228 /* For some reason we need to correct for this */
229 switch (v->spritenum) {
230 case 0xfd: break;
231 case 0xff: v->spritenum = 0xfe; break;
232 default: v->spritenum >>= 1; break;
235 /* Vehicle-subtype is different in TTD(Patch) */
236 if (v->type == VEH_EFFECT) v->subtype = v->subtype >> 1;
238 v->name = CopyFromOldName(stv, _old_vehicle_names[v->index]);
240 /* We haven't used this bit for stations for ages */
241 if (v->type == VEH_ROAD) {
242 RoadVehicle *rv = RoadVehicle::From(v);
243 if (rv->state != RVSB_IN_DEPOT && rv->state != RVSB_WORMHOLE) {
244 ClrBit(rv->state, 2);
245 if (IsOldTileType(rv->tile, OLD_MP_STATION) && _mc[rv->tile].m5 >= 168) {
246 /* Update the vehicle's road state to show we're in a drive through road stop. */
247 SetBit(rv->state, 6);
252 /* The subtype should be 0, but it sometimes isn't :( */
253 if (v->type == VEH_ROAD || v->type == VEH_SHIP) v->subtype = 0;
255 /* Sometimes primary vehicles would have a nothing (invalid) order
256 * or vehicles that could not have an order would still have a
257 * (loading) order which causes assertions and the like later on.
259 if (!IsCompanyBuildableVehicleType(v) ||
260 (v->IsPrimaryVehicle() && v->current_order.IsType(OT_NOTHING))) {
261 v->current_order.MakeDummy();
264 /* Shared orders are fixed in AfterLoadVehicles now */
268 static bool FixTTOMapArray()
270 for (TileIndex t = 0; t < OLD_MAP_SIZE; t++) {
271 switch (GetOldTileType(t)) {
272 case OLD_MP_CLEAR:
273 break;
275 case OLD_MP_MONORAIL:
276 /* TTO has a different way of storing monorail.
277 * Instead of using bits in m3 it uses a different tile type. */
278 _mc[t].m3 = 1; // rail type = monorail (in TTD)
279 SetOldTileType(t, OLD_MP_RAILWAY);
280 _mc[t].m2 = 1; // set monorail ground to RAIL_GROUND_GRASS
281 /* fall through */
282 case OLD_MP_RAILWAY:
283 switch (GB(_mc[t].m5, 6, 2)) {
284 case 0: // RAIL_TILE_NORMAL
285 break;
286 case 1: // RAIL_TILE_SIGNALS
287 _mc[t].m4 = (~_mc[t].m5 & 1) << 2; // signal variant (present only in OTTD)
288 SB(_mc[t].m2, 6, 2, GB(_mc[t].m5, 3, 2)); // signal status
289 _mc[t].m3 |= 0xC0; // both signals are present
290 _mc[t].m5 = HasBit(_mc[t].m5, 5) ? 2 : 1; // track direction (only X or Y)
291 _mc[t].m5 |= 0x40; // RAIL_TILE_SIGNALS
292 break;
293 case 3: // RAIL_TILE_DEPOT
294 _mc[t].m2 = 0;
295 break;
296 default:
297 return false;
299 break;
301 case OLD_MP_ROAD: // road (depot) or level crossing
302 switch (GB(_mc[t].m5, 4, 4)) {
303 case 0: // ROAD_TILE_NORMAL
304 if (_mc[t].m2 == 4) _mc[t].m2 = 5; // 'small trees' -> ROADSIDE_TREES
305 break;
306 case 1: // ROAD_TILE_CROSSING (there aren't monorail crossings in TTO)
307 _mc[t].m3 = _mc[t].m1; // set owner of road = owner of rail
308 break;
309 case 2: // ROAD_TILE_DEPOT
310 break;
311 default:
312 return false;
314 break;
316 case OLD_MP_HOUSE:
317 _mc[t].m3 = _mc[t].m2 & 0xC0; // construction stage
318 _mc[t].m2 &= 0x3F; // building type
319 if (_mc[t].m2 >= 5) _mc[t].m2++; // skip "large office block on snow"
320 break;
322 case OLD_MP_TREES:
323 _mc[t].m3 = GB(_mc[t].m5, 3, 3); // type of trees
324 _mc[t].m5 &= 0xC7; // number of trees and growth status
325 break;
327 case OLD_MP_STATION:
328 _mc[t].m3 = (_mc[t].m5 >= 0x08 && _mc[t].m5 <= 0x0F) ? 1 : 0; // monorail -> 1, others 0 (rail, road, airport, dock)
329 if (_mc[t].m5 >= 8) _mc[t].m5 -= 8; // shift for monorail
330 if (_mc[t].m5 >= 0x42) _mc[t].m5++; // skip heliport
331 break;
333 case OLD_MP_WATER:
334 _mc[t].m3 = _mc[t].m2 = 0;
335 break;
337 case OLD_MP_VOID:
338 _mc[t].m2 = _mc[t].m3 = _mc[t].m5 = 0;
339 break;
341 case OLD_MP_INDUSTRY:
342 _mc[t].m3 = 0;
343 switch (_mc[t].m5) {
344 case 0x24: // farm silo
345 _mc[t].m5 = 0x25;
346 break;
347 case 0x25: case 0x27: // farm
348 case 0x28: case 0x29: case 0x2A: case 0x2B: // factory
349 _mc[t].m5--;
350 break;
351 default:
352 if (_mc[t].m5 >= 0x2C) _mc[t].m5 += 3; // iron ore mine, steel mill or bank
353 break;
355 break;
357 case OLD_MP_TUNNELBRIDGE:
358 if (HasBit(_mc[t].m5, 7)) { // bridge
359 byte m5 = _mc[t].m5;
360 _mc[t].m5 = m5 & 0xE1; // copy bits 7..5, 1
361 if (GB(m5, 1, 2) == 1) _mc[t].m5 |= 0x02; // road bridge
362 if (GB(m5, 1, 2) == 3) _mc[t].m2 |= 0xA0; // monorail bridge -> tubular, steel bridge
363 if (!HasBit(m5, 6)) { // bridge head
364 _mc[t].m3 = (GB(m5, 1, 2) == 3) ? 1 : 0; // track subtype (1 for monorail, 0 for others)
365 } else { // middle bridge part
366 _mc[t].m3 = HasBit(m5, 2) ? 0x10 : 0; // track subtype on bridge
367 if (GB(m5, 3, 2) == 3) _mc[t].m3 |= 1; // track subtype under bridge
368 if (GB(m5, 3, 2) == 1) _mc[t].m5 |= 0x08; // set for road/water under (0 for rail/clear)
370 } else { // tunnel entrance/exit
371 _mc[t].m2 = 0;
372 _mc[t].m3 = HasBit(_mc[t].m5, 3); // monorail
373 _mc[t].m5 &= HasBit(_mc[t].m5, 3) ? 0x03 : 0x07 ; // direction, transport type (== 0 for rail)
375 break;
377 case OLD_MP_OBJECT:
378 _mc[t].m2 = 0;
379 _mc[t].m3 = 0;
380 break;
382 default:
383 return false;
388 FixOldMapArray();
390 return true;
393 static Engine *_old_engines;
395 static bool FixTTOEngines()
397 /** TTD->TTO remapping of engines; 255 means there is no equivalent. SVXConverter uses (almost) the same table. */
398 static const EngineID ttd_to_tto[] = {
399 0, 255, 255, 255, 255, 255, 255, 255, 5, 7, 8, 9, 10, 11, 12, 13,
400 255, 255, 255, 255, 255, 255, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
401 25, 26, 27, 29, 28, 30, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
402 255, 255, 255, 255, 255, 255, 255, 31, 255, 32, 33, 34, 35, 36, 37, 38,
403 39, 40, 41, 42, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
404 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
405 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
406 255, 255, 255, 255, 44, 45, 46, 255, 255, 255, 255, 47, 48, 255, 49, 50,
407 255, 255, 255, 255, 51, 52, 255, 53, 54, 255, 55, 56, 255, 57, 59, 255,
408 58, 60, 255, 61, 62, 255, 63, 64, 255, 65, 66, 255, 255, 255, 255, 255,
409 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
410 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
411 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 67, 68, 69, 70,
412 71, 255, 255, 76, 77, 255, 255, 78, 79, 80, 81, 82, 83, 84, 85, 86,
413 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 255,
414 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 102, 255, 255
417 /** TTO->TTD remapping of engines. SVXConverter uses the same table. */
418 static const EngineID tto_to_ttd[] = {
419 0, 0, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 15, 15, 22,
420 23, 24, 25, 26, 27, 29, 28, 30, 31, 32, 33, 34, 35, 36, 37, 55,
421 57, 59, 58, 60, 61, 62, 63, 64, 65, 66, 67, 116, 116, 117, 118, 123,
422 124, 126, 127, 132, 133, 135, 136, 138, 139, 141, 142, 144, 145, 147, 148, 150,
423 151, 153, 154, 204, 205, 206, 207, 208, 211, 212, 211, 212, 211, 212, 215, 216,
424 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
425 233, 234, 235, 236, 237, 238, 253
428 Vehicle *v;
429 FOR_ALL_VEHICLES(v) {
430 if (v->engine_type >= lengthof(tto_to_ttd)) return false;
431 v->engine_type = tto_to_ttd[v->engine_type];
434 /* Load the default engine set. Many of them will be overridden later */
435 uint j = 0;
436 for (uint i = 0; i < lengthof(_orig_rail_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_TRAIN, i);
437 for (uint i = 0; i < lengthof(_orig_road_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_ROAD, i);
438 for (uint i = 0; i < lengthof(_orig_ship_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_SHIP, i);
439 for (uint i = 0; i < lengthof(_orig_aircraft_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_AIRCRAFT, i);
441 Date aging_date = min(_date + DAYS_TILL_ORIGINAL_BASE_YEAR, ConvertYMDToDate(2050, 0, 1));
443 for (EngineID i = 0; i < 256; i++) {
444 int oi = ttd_to_tto[i];
445 Engine *e = GetTempDataEngine(i);
447 if (oi == 255) {
448 /* Default engine is used */
449 _date += DAYS_TILL_ORIGINAL_BASE_YEAR;
450 StartupOneEngine(e, aging_date);
451 e->intro_date -= DAYS_TILL_ORIGINAL_BASE_YEAR;
452 _date -= DAYS_TILL_ORIGINAL_BASE_YEAR;
454 /* Make sure for example monorail and maglev are available when they should be */
455 if (_date >= e->intro_date && HasBit(e->info.climates, 0)) {
456 e->flags |= ENGINE_AVAILABLE;
457 e->company_avail = (CompanyMask)0xFF;
458 e->age = _date > e->intro_date ? (_date - e->intro_date) / 30 : 0;
460 } else {
461 /* Using data from TTO savegame */
462 Engine *oe = &_old_engines[oi];
464 e->intro_date = oe->intro_date;
465 e->age = oe->age;
466 e->reliability = oe->reliability;
467 e->reliability_spd_dec = oe->reliability_spd_dec;
468 e->reliability_start = oe->reliability_start;
469 e->reliability_max = oe->reliability_max;
470 e->reliability_final = oe->reliability_final;
471 e->duration_phase_1 = oe->duration_phase_1;
472 e->duration_phase_2 = oe->duration_phase_2;
473 e->duration_phase_3 = oe->duration_phase_3;
474 e->flags = oe->flags;
476 e->company_avail = 0;
478 /* One or more engines were remapped to this one. Make this engine available
479 * if at least one of them was available. */
480 for (uint j = 0; j < lengthof(tto_to_ttd); j++) {
481 if (tto_to_ttd[j] == i && _old_engines[j].company_avail != 0) {
482 e->company_avail = (CompanyMask)0xFF;
483 e->flags |= ENGINE_AVAILABLE;
484 break;
488 e->info.climates = 1;
491 e->preview_company = INVALID_COMPANY;
492 e->preview_asked = (CompanyMask)-1;
493 e->preview_wait = 0;
494 e->name = NULL;
497 return true;
500 static void FixTTOCompanies()
502 Company *c;
503 FOR_ALL_COMPANIES(c) {
504 c->cur_economy.company_value = CalculateCompanyValue(c); // company value history is zeroed
508 static inline byte RemapTTOColour(byte tto)
510 /** Lossy remapping of TTO colours to TTD colours. SVXConverter uses the same conversion. */
511 static const byte tto_colour_remap[] = {
512 COLOUR_DARK_BLUE, COLOUR_GREY, COLOUR_YELLOW, COLOUR_RED,
513 COLOUR_PURPLE, COLOUR_DARK_GREEN, COLOUR_ORANGE, COLOUR_PALE_GREEN,
514 COLOUR_BLUE, COLOUR_GREEN, COLOUR_CREAM, COLOUR_BROWN,
515 COLOUR_WHITE, COLOUR_LIGHT_BLUE, COLOUR_MAUVE, COLOUR_PINK
518 if ((size_t)tto >= lengthof(tto_colour_remap)) return COLOUR_GREY; // this shouldn't happen
520 return tto_colour_remap[tto];
523 static inline uint RemapTownIndex(const SavegameTypeVersion *stv, uint x)
525 return stv->type == SGT_TTO ? (x - 0x264) / 78 : (x - 0x264) / 94;
528 static inline uint RemapOrderIndex(const SavegameTypeVersion *stv, uint x)
530 return stv->type == SGT_TTO ? (x - 0x1AC4) / 2 : (x - 0x1C18) / 2;
533 extern TileIndex *_animated_tile_list;
534 extern uint _animated_tile_count;
535 extern char *_old_name_array;
537 static uint32 _old_town_index;
538 static uint16 _old_string_id;
539 static uint16 _old_string_id_2;
541 static void ReadTTDPatchFlags(SavegameTypeVersion *stv)
543 if (_read_ttdpatch_flags) return;
545 _read_ttdpatch_flags = true;
547 /* Set default values */
548 _old_vehicle_multiplier = 1;
549 stv->ttdp.version = 0;
550 _old_extra_chunk_nums = 0;
551 _bump_assert_value = 0;
553 if (stv->type == SGT_TTO) return;
555 /* TTDPatch misuses _old_map3 for flags.. read them! */
556 _old_vehicle_multiplier = _old_map3[0];
557 /* Somehow.... there was an error in some savegames, so 0 becomes 1
558 * and 1 becomes 2. The rest of the values are okay */
559 if (_old_vehicle_multiplier < 2) _old_vehicle_multiplier++;
561 _old_vehicle_names = MallocT<StringID>(_old_vehicle_multiplier * 850);
563 /* TTDPatch increases the Vehicle-part in the middle of the game,
564 * so if the multiplier is anything else but 1, the assert fails..
565 * bump the assert value so it doesn't!
566 * (1 multiplier == 850 vehicles
567 * 1 vehicle == 128 bytes */
568 _bump_assert_value = (_old_vehicle_multiplier - 1) * 850 * 128;
570 for (uint i = 0; i < 17; i++) { // check tile 0, too
571 if (_old_map3[i] != 0) stv->type = SGT_TTDP1;
574 /* Check if we have a modern TTDPatch savegame (has extra data all around) */
575 if (memcmp(&_old_map3[0x1FFFA], "TTDp", 4) == 0) stv->type = SGT_TTDP2;
577 _old_extra_chunk_nums = _old_map3[stv->type == SGT_TTDP2 ? 0x1FFFE : 0x2];
579 /* Clean the misused places */
580 for (uint i = 0; i < 17; i++) _old_map3[i] = 0;
581 for (uint i = 0x1FE00; i < 0x20000; i++) _old_map3[i] = 0;
583 if (stv->type == SGT_TTDP2) DEBUG(oldloader, 2, "Found TTDPatch game");
585 DEBUG(oldloader, 3, "Vehicle-multiplier is set to %d (%d vehicles)", _old_vehicle_multiplier, _old_vehicle_multiplier * 850);
588 static const OldChunks town_chunk[] = {
589 OCL_SVAR( OC_TILE, Town, xy ),
590 OCL_NULL( 2 ), ///< population, no longer in use
591 OCL_SVAR( OC_UINT16, Town, townnametype ),
592 OCL_SVAR( OC_UINT32, Town, townnameparts ),
593 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, grow_counter ),
594 OCL_NULL( 1 ), ///< sort_index, no longer in use
595 OCL_NULL( 4 ), ///< sign-coordinates, no longer in use
596 OCL_NULL( 2 ), ///< namewidth, no longer in use
597 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Town, flags ),
598 OCL_NULL( 10 ), ///< radius, no longer in use
600 OCL_SVAR( OC_INT16, Town, ratings[0] ),
601 OCL_SVAR( OC_INT16, Town, ratings[1] ),
602 OCL_SVAR( OC_INT16, Town, ratings[2] ),
603 OCL_SVAR( OC_INT16, Town, ratings[3] ),
604 OCL_SVAR( OC_INT16, Town, ratings[4] ),
605 OCL_SVAR( OC_INT16, Town, ratings[5] ),
606 OCL_SVAR( OC_INT16, Town, ratings[6] ),
607 OCL_SVAR( OC_INT16, Town, ratings[7] ),
609 OCL_SVAR( OC_FILE_U32 | OC_VAR_U16, Town, have_ratings ),
610 OCL_SVAR( OC_FILE_U32 | OC_VAR_U16, Town, statues ),
611 OCL_NULL( 2 ), ///< num_houses, no longer in use
612 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, time_until_rebuild ),
613 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, growth_rate ),
615 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].new_max ),
616 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].new_max ),
617 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].new_act ),
618 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].new_act ),
619 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].old_max ),
620 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].old_max ),
621 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].old_act ),
622 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].old_act ),
624 OCL_NULL( 2 ), ///< pct_pass_transported / pct_mail_transported, now computed on the fly
626 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TE_FOOD].new_act ),
627 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TE_WATER].new_act ),
628 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TE_FOOD].old_act ),
629 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TE_WATER].old_act ),
631 OCL_SVAR( OC_UINT8, Town, road_build_months ),
632 OCL_SVAR( OC_UINT8, Town, fund_buildings_months ),
634 OCL_CNULL( OC_TTD, 8 ), ///< some junk at the end of the record
636 OCL_END()
639 static bool LoadOldTown(LoadgameState *ls, int num)
641 Town *t = new (num) Town();
642 if (!LoadChunk(ls, t, town_chunk)) return false;
644 if (t->xy != 0) {
645 if (ls->stv->type == SGT_TTO) {
646 /* 0x10B6 is auto-generated name, others are custom names */
647 t->townnametype = t->townnametype == 0x10B6 ? 0x20C1 : t->townnametype + 0x2A00;
649 t->add_to_tileset();
650 } else {
651 delete t;
654 return true;
657 static uint16 _old_order;
658 static const OldChunks order_chunk[] = {
659 OCL_VAR ( OC_UINT16, 1, &_old_order ),
660 OCL_END()
663 static bool LoadOldOrder(LoadgameState *ls, int num)
665 if (!LoadChunk(ls, NULL, order_chunk)) return false;
667 Order *o = new (num) Order();
668 o->AssignOrder(UnpackOldOrder(_old_order));
670 if (o->IsType(OT_NOTHING)) {
671 delete o;
672 } else {
673 /* Relink the orders to each other (in the orders for one vehicle are behind each other,
674 * with an invalid order (OT_NOTHING) as indication that it is the last order */
675 Order *prev = Order::GetIfValid(num - 1);
676 if (prev != NULL) prev->next = o;
679 return true;
682 static bool LoadOldAnimTileList(LoadgameState *ls, int num)
684 /* This is slightly hackish - we must load a chunk into an array whose
685 * address isn't static, but instead pointed to by _animated_tile_list.
686 * To achieve that, create an OldChunks list on the stack on the fly.
687 * The list cannot be static because the value of _animated_tile_list
688 * can change between calls. */
690 const OldChunks anim_chunk[] = {
691 OCL_VAR ( OC_TILE, 256, _animated_tile_list ),
692 OCL_END ()
695 if (!LoadChunk(ls, NULL, anim_chunk)) return false;
697 /* Update the animated tile counter by counting till the first zero in the array */
698 for (_animated_tile_count = 0; _animated_tile_count < 256; _animated_tile_count++) {
699 if (_animated_tile_list[_animated_tile_count] == 0) break;
702 return true;
705 static const OldChunks depot_chunk[] = {
706 OCL_SVAR( OC_TILE, Depot, xy ),
707 OCL_VAR ( OC_UINT32, 1, &_old_town_index ),
708 OCL_END()
711 static bool LoadOldDepot(LoadgameState *ls, int num)
713 Depot *d = new (num) Depot();
714 if (!LoadChunk(ls, d, depot_chunk)) return false;
716 if (d->xy != 0) {
717 /* In some cases, there could be depots referencing invalid town. */
718 Town *t = Town::GetIfValid(RemapTownIndex(ls->stv, _old_town_index));
719 if (t == NULL) t = Town::GetRandom();
720 d->town = t;
721 } else {
722 delete d;
725 return true;
728 static StationID _current_station_id;
729 static uint16 _waiting_acceptance;
730 static uint8 _cargo_source;
731 static uint8 _cargo_days;
733 static const OldChunks goods_chunk[] = {
734 OCL_VAR ( OC_UINT16, 1, &_waiting_acceptance ),
735 OCL_SVAR( OC_UINT8, GoodsEntry, time_since_pickup ),
736 OCL_SVAR( OC_UINT8, GoodsEntry, rating ),
737 OCL_VAR ( OC_UINT8, 1, &_cargo_source ),
738 OCL_VAR ( OC_UINT8, 1, &_cargo_days ),
739 OCL_SVAR( OC_UINT8, GoodsEntry, last_speed ),
740 OCL_SVAR( OC_UINT8, GoodsEntry, last_age ),
742 OCL_END()
745 static bool LoadOldGood(LoadgameState *ls, int num)
747 /* for TTO games, 12th (num == 11) goods entry is created in the Station constructor */
748 if (ls->stv->type == SGT_TTO && num == 11) return true;
750 Station *st = Station::Get(_current_station_id);
751 GoodsEntry *ge = &st->goods[num];
753 if (!LoadChunk(ls, ge, goods_chunk)) return false;
755 SB(ge->acceptance_pickup, GoodsEntry::GES_ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
756 SB(ge->acceptance_pickup, GoodsEntry::GES_PICKUP, 1, _cargo_source != 0xFF);
757 if (GB(_waiting_acceptance, 0, 12) != 0 && CargoPacket::CanAllocateItem()) {
758 ge->cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, (_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source, 0, 0),
759 INVALID_STATION);
762 return true;
765 static const OldChunks station_chunk[] = {
766 OCL_SVAR( OC_TILE, Station, xy ),
767 OCL_VAR ( OC_UINT32, 1, &_old_town_index ),
769 OCL_NULL( 4 ), ///< bus/lorry tile
770 OCL_SVAR( OC_TILE, Station, train_station.tile ),
771 OCL_SVAR( OC_TILE, Station, airport.tile ),
772 OCL_NULL( 2 ), ///< dock tile
773 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Station, train_station.w ),
775 OCL_NULL( 1 ), ///< sort-index, no longer in use
776 OCL_NULL( 2 ), ///< sign-width, no longer in use
778 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
780 OCL_NULL( 4 ), ///< sign left/top, no longer in use
782 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Station, had_vehicle_of_type ),
784 OCL_CHUNK( 12, LoadOldGood ),
786 OCL_SVAR( OC_UINT8, Station, time_since_load ),
787 OCL_SVAR( OC_UINT8, Station, time_since_unload ),
788 OCL_SVAR( OC_UINT8, Station, delete_ctr ),
789 OCL_SVAR( OC_UINT8, Station, owner ),
790 OCL_SVAR( OC_UINT8, Station, facilities ),
791 OCL_SVAR( OC_TTD | OC_UINT8, Station, airport.type ),
792 OCL_SVAR( OC_TTO | OC_FILE_U16 | OC_VAR_U64, Station, airport.flags ),
793 OCL_NULL( 3 ), ///< bus/truck status, blocked months, no longer in use
794 OCL_CNULL( OC_TTD, 1 ), ///< unknown
795 OCL_SVAR( OC_TTD | OC_FILE_U16 | OC_VAR_U64, Station, airport.flags ),
796 OCL_CNULL( OC_TTD, 2 ), ///< last_vehicle. now last_vehicle_type
797 OCL_CNULL( OC_TTD, 4 ), ///< junk at end of chunk
799 OCL_END()
802 static bool LoadOldStation(LoadgameState *ls, int num)
804 Station *st = new (num) Station();
805 _current_station_id = num;
807 if (!LoadChunk(ls, st, station_chunk)) return false;
809 if (st->xy != 0) {
810 st->town = Town::Get(RemapTownIndex(ls->stv, _old_town_index));
812 if (ls->stv->type == SGT_TTO) {
813 if (IsInsideBS(_old_string_id, 0x180F, 32)) {
814 st->string_id = STR_SV_STNAME + (_old_string_id - 0x180F); // automatic name
815 } else {
816 st->string_id = _old_string_id + 0x2800; // custom name
819 if (HasBit(st->airport.flags, 8)) {
820 st->airport.type = 1; // large airport
821 } else if (HasBit(st->airport.flags, 6)) {
822 st->airport.type = 3; // oil rig
823 } else {
824 st->airport.type = 0; // small airport
826 } else {
827 st->string_id = RemapOldStringID(_old_string_id);
829 } else {
830 delete st;
833 return true;
836 static const OldChunks industry_chunk[] = {
837 OCL_SVAR( OC_TILE, Industry, location.tile ),
838 OCL_VAR ( OC_UINT32, 1, &_old_town_index ),
839 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Industry, location.w ),
840 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Industry, location.h ),
841 OCL_NULL( 2 ), ///< used to be industry's produced_cargo
843 OCL_SVAR( OC_TTD | OC_UINT16, Industry, produced_cargo_waiting[0] ),
844 OCL_SVAR( OC_TTD | OC_UINT16, Industry, produced_cargo_waiting[1] ),
845 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Industry, produced_cargo_waiting[0] ),
846 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Industry, produced_cargo_waiting[1] ),
848 OCL_SVAR( OC_UINT8, Industry, production_rate[0] ),
849 OCL_SVAR( OC_UINT8, Industry, production_rate[1] ),
851 OCL_NULL( 3 ), ///< used to be industry's accepts_cargo
853 OCL_SVAR( OC_UINT8, Industry, prod_level ),
855 OCL_SVAR( OC_UINT16, Industry, this_month_production[0] ),
856 OCL_SVAR( OC_UINT16, Industry, this_month_production[1] ),
857 OCL_SVAR( OC_UINT16, Industry, this_month_transported[0] ),
858 OCL_SVAR( OC_UINT16, Industry, this_month_transported[1] ),
860 OCL_SVAR( OC_UINT8, Industry, last_month_pct_transported[0] ),
861 OCL_SVAR( OC_UINT8, Industry, last_month_pct_transported[1] ),
863 OCL_SVAR( OC_UINT16, Industry, last_month_production[0] ),
864 OCL_SVAR( OC_UINT16, Industry, last_month_production[1] ),
865 OCL_SVAR( OC_UINT16, Industry, last_month_transported[0] ),
866 OCL_SVAR( OC_UINT16, Industry, last_month_transported[1] ),
868 OCL_SVAR( OC_UINT8, Industry, type ),
869 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Industry, counter ),
870 OCL_SVAR( OC_UINT8, Industry, owner ),
871 OCL_SVAR( OC_UINT8, Industry, random_colour ),
872 OCL_SVAR( OC_TTD | OC_FILE_U8 | OC_VAR_I32, Industry, last_prod_year ),
873 OCL_SVAR( OC_TTD | OC_UINT16, Industry, counter ),
874 OCL_SVAR( OC_TTD | OC_UINT8, Industry, was_cargo_delivered ),
876 OCL_CNULL( OC_TTD, 9 ), ///< Random junk at the end of this chunk
878 OCL_END()
881 static bool LoadOldIndustry(LoadgameState *ls, int num)
883 Industry *i = new (num) Industry();
884 if (!LoadChunk(ls, i, industry_chunk)) return false;
886 if (i->location.tile != 0) {
887 i->town = Town::Get(RemapTownIndex(ls->stv, _old_town_index));
889 if (ls->stv->type == SGT_TTO) {
890 if (i->type > 0x06) i->type++; // Printing Works were added
891 if (i->type == 0x0A) i->type = 0x12; // Iron Ore Mine has different ID
893 YearMonthDay ymd;
894 ConvertDateToYMD(_date, &ymd);
895 i->last_prod_year = ymd.year;
897 i->random_colour = RemapTTOColour(i->random_colour);
900 i->add_to_tileset();
901 Industry::IncIndustryTypeCount(i->type);
902 } else {
903 delete i;
906 return true;
909 static CompanyID _current_company_id;
910 static int32 _old_yearly;
912 static const OldChunks _company_yearly_chunk[] = {
913 OCL_VAR( OC_INT32, 1, &_old_yearly ),
914 OCL_END()
917 static bool LoadOldCompanyYearly(LoadgameState *ls, int num)
919 Company *c = Company::Get(_current_company_id);
921 for (uint i = 0; i < 13; i++) {
922 if (ls->stv->type == SGT_TTO && i == 6) {
923 _old_yearly = 0; // property maintenance
924 } else {
925 if (!LoadChunk(ls, NULL, _company_yearly_chunk)) return false;
928 c->yearly_expenses[num][i] = _old_yearly;
931 return true;
934 static const OldChunks _company_economy_chunk[] = {
935 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, CompanyEconomyEntry, income ),
936 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, CompanyEconomyEntry, expenses ),
937 OCL_SVAR( OC_INT32, CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1] ),
938 OCL_SVAR( OC_INT32, CompanyEconomyEntry, performance_history ),
939 OCL_SVAR( OC_TTD | OC_FILE_I32 | OC_VAR_I64, CompanyEconomyEntry, company_value ),
941 OCL_END()
944 static bool LoadOldCompanyEconomy(LoadgameState *ls, int num)
946 Company *c = Company::Get(_current_company_id);
948 if (!LoadChunk(ls, &c->cur_economy, _company_economy_chunk)) return false;
950 /* Don't ask, but the number in TTD(Patch) are inversed to OpenTTD */
951 c->cur_economy.income = -c->cur_economy.income;
952 c->cur_economy.expenses = -c->cur_economy.expenses;
954 for (uint i = 0; i < 24; i++) {
955 if (!LoadChunk(ls, &c->old_economy[i], _company_economy_chunk)) return false;
957 c->old_economy[i].income = -c->old_economy[i].income;
958 c->old_economy[i].expenses = -c->old_economy[i].expenses;
961 return true;
964 static const OldChunks _company_chunk[] = {
965 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
966 OCL_SVAR( OC_UINT32, Company, name_2 ),
967 OCL_SVAR( OC_UINT32, Company, face ),
968 OCL_VAR ( OC_UINT16, 1, &_old_string_id_2 ),
969 OCL_SVAR( OC_UINT32, Company, president_name_2 ),
971 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Company, money ),
972 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Company, current_loan ),
974 OCL_SVAR( OC_UINT8, Company, colour ),
975 OCL_SVAR( OC_UINT8, Company, money_fraction ),
976 OCL_SVAR( OC_UINT8, Company, months_of_bankruptcy ),
977 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Company, bankrupt_asked ),
978 OCL_SVAR( OC_FILE_U32 | OC_VAR_I64, Company, bankrupt_value ),
979 OCL_SVAR( OC_UINT16, Company, bankrupt_timeout ),
981 OCL_CNULL( OC_TTD, 4 ), // cargo_types
982 OCL_CNULL( OC_TTO, 2 ), // cargo_types
984 OCL_CHUNK( 3, LoadOldCompanyYearly ),
985 OCL_CHUNK( 1, LoadOldCompanyEconomy ),
987 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Company, inaugurated_year),
988 OCL_SVAR( OC_TILE, Company, last_build_coordinate ),
989 OCL_SVAR( OC_UINT8, Company, num_valid_stat_ent ),
991 OCL_NULL( 230 ), // Old AI
993 OCL_SVAR( OC_UINT8, Company, block_preview ),
994 OCL_CNULL( OC_TTD, 1 ), // Old AI
995 OCL_SVAR( OC_TTD | OC_UINT8, Company, avail_railtypes ),
996 OCL_SVAR( OC_TILE, Company, location_of_HQ ),
997 OCL_SVAR( OC_TTD | OC_UINT8, Company, share_owners[0] ),
998 OCL_SVAR( OC_TTD | OC_UINT8, Company, share_owners[1] ),
999 OCL_SVAR( OC_TTD | OC_UINT8, Company, share_owners[2] ),
1000 OCL_SVAR( OC_TTD | OC_UINT8, Company, share_owners[3] ),
1002 OCL_CNULL( OC_TTD, 8 ), ///< junk at end of chunk
1004 OCL_END()
1007 static bool LoadOldCompany(LoadgameState *ls, int num)
1009 Company *c = new (num) Company();
1011 _current_company_id = (CompanyID)num;
1013 if (!LoadChunk(ls, c, _company_chunk)) return false;
1015 if (_old_string_id == 0) {
1016 delete c;
1017 return true;
1020 if (ls->stv->type == SGT_TTO) {
1021 /* adjust manager's face */
1022 if (HasBit(c->face, 27) && GB(c->face, 26, 1) == GB(c->face, 19, 1)) {
1023 /* if face would be black in TTD, adjust tie colour and thereby face colour */
1024 ClrBit(c->face, 27);
1027 /* Company name */
1028 if (_old_string_id == 0 || _old_string_id == 0x4C00) {
1029 _old_string_id = STR_SV_UNNAMED; // "Unnamed"
1030 } else if (GB(_old_string_id, 8, 8) == 0x52) {
1031 _old_string_id += 0x2A00; // Custom name
1032 } else {
1033 _old_string_id = RemapOldStringID(_old_string_id += 0x240D); // Automatic name
1035 c->name_1 = _old_string_id;
1037 /* Manager name */
1038 switch (_old_string_id_2) {
1039 case 0x4CDA: _old_string_id_2 = SPECSTR_PRESIDENT_NAME; break; // automatic name
1040 case 0x0006: _old_string_id_2 = STR_SV_EMPTY; break; // empty name
1041 default: _old_string_id_2 = _old_string_id_2 + 0x2A00; break; // custom name
1043 c->president_name_1 = _old_string_id_2;
1045 c->colour = RemapTTOColour(c->colour);
1047 if (num != 0) c->is_ai = true;
1048 } else {
1049 c->name_1 = RemapOldStringID(_old_string_id);
1050 c->president_name_1 = RemapOldStringID(_old_string_id_2);
1052 if (num == 0) {
1053 /* If the first company has no name, make sure we call it UNNAMED */
1054 if (c->name_1 == 0) {
1055 c->name_1 = STR_SV_UNNAMED;
1057 } else {
1058 /* Beside some multiplayer maps (1 on 1), which we don't official support,
1059 * all other companies are an AI.. mark them as such */
1060 c->is_ai = true;
1063 /* Sometimes it is better to not ask.. in old scenarios, the money
1064 * was always 893288 pounds. In the newer versions this is correct,
1065 * but correct for those oldies
1066 * Ps: this also means that if you had exact 893288 pounds, you will go back
1067 * to 100000.. this is a very VERY small chance ;) */
1068 if (c->money == 893288) c->money = c->current_loan = 100000;
1071 _company_colours[num] = (Colours)c->colour;
1072 c->inaugurated_year -= ORIGINAL_BASE_YEAR;
1074 return true;
1077 static uint32 _old_order_ptr;
1078 static uint16 _old_next_ptr;
1079 static VehicleID _current_vehicle_id;
1081 static const OldChunks vehicle_train_chunk[] = {
1082 OCL_SVAR( OC_UINT8, Train, trackdir ),
1083 OCL_SVAR( OC_UINT8, Train, force_proceed ),
1084 OCL_SVAR( OC_UINT16, Train, crash_anim_pos ),
1085 OCL_SVAR( OC_UINT8, Train, railtype ),
1087 OCL_NULL( 5 ), ///< Junk
1089 OCL_END()
1092 static const OldChunks vehicle_road_chunk[] = {
1093 OCL_SVAR( OC_UINT8, RoadVehicle, state ),
1094 OCL_SVAR( OC_UINT8, RoadVehicle, frame ),
1095 OCL_SVAR( OC_UINT16, RoadVehicle, blocked_ctr ),
1096 OCL_SVAR( OC_UINT8, RoadVehicle, overtaking ),
1097 OCL_SVAR( OC_UINT8, RoadVehicle, overtaking_ctr ),
1098 OCL_SVAR( OC_UINT16, RoadVehicle, crashed_ctr ),
1099 OCL_SVAR( OC_UINT8, RoadVehicle, reverse_ctr ),
1101 OCL_NULL( 1 ), ///< Junk
1103 OCL_END()
1106 static const OldChunks vehicle_ship_chunk[] = {
1107 OCL_SVAR( OC_UINT8, Ship, trackdir ),
1109 OCL_NULL( 9 ), ///< Junk
1111 OCL_END()
1114 static const OldChunks vehicle_air_chunk[] = {
1115 OCL_SVAR( OC_UINT8, Aircraft, pos ),
1116 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Aircraft, targetairport ),
1117 OCL_SVAR( OC_UINT16, Aircraft, crashed_counter ),
1118 OCL_SVAR( OC_UINT8, Aircraft, state ),
1120 OCL_NULL( 5 ), ///< Junk
1122 OCL_END()
1125 static const OldChunks vehicle_effect_chunk[] = {
1126 OCL_SVAR( OC_UINT16, EffectVehicle, animation_state ),
1127 OCL_SVAR( OC_UINT8, EffectVehicle, animation_substate ),
1129 OCL_NULL( 7 ), // Junk
1131 OCL_END()
1134 static const OldChunks vehicle_disaster_chunk[] = {
1135 OCL_SVAR( OC_UINT16, DisasterVehicle, image_override ),
1136 OCL_SVAR( OC_UINT16, DisasterVehicle, big_ufo_destroyer_target ),
1138 OCL_NULL( 6 ), ///< Junk
1140 OCL_END()
1143 static const OldChunks vehicle_empty_chunk[] = {
1144 OCL_NULL( 10 ), ///< Junk
1146 OCL_END()
1149 static bool LoadOldVehicleUnion(LoadgameState *ls, int num)
1151 Vehicle *v = Vehicle::GetIfValid(_current_vehicle_id);
1152 uint temp = ls->total_read;
1153 bool res;
1155 if (v == NULL) {
1156 res = LoadChunk(ls, NULL, vehicle_empty_chunk);
1157 } else {
1158 switch (v->type) {
1159 default: throw SlCorrupt("Invalid vehicle type");
1160 case VEH_TRAIN : res = LoadChunk(ls, v, vehicle_train_chunk); break;
1161 case VEH_ROAD : res = LoadChunk(ls, v, vehicle_road_chunk); break;
1162 case VEH_SHIP : res = LoadChunk(ls, v, vehicle_ship_chunk); break;
1163 case VEH_AIRCRAFT: res = LoadChunk(ls, v, vehicle_air_chunk); break;
1164 case VEH_EFFECT : res = LoadChunk(ls, v, vehicle_effect_chunk); break;
1165 case VEH_DISASTER: res = LoadChunk(ls, v, vehicle_disaster_chunk); break;
1169 /* This chunk size should always be 10 bytes */
1170 if (ls->total_read - temp != 10) {
1171 DEBUG(oldloader, 0, "Assert failed in VehicleUnion: invalid chunk size");
1172 return false;
1175 return res;
1178 static uint16 _cargo_count;
1180 static const OldChunks vehicle_chunk[] = {
1181 OCL_SVAR( OC_UINT8, Vehicle, subtype ),
1183 OCL_NULL( 2 ), ///< Hash, calculated automatically
1184 OCL_NULL( 2 ), ///< Index, calculated automatically
1186 OCL_VAR ( OC_UINT32, 1, &_old_order_ptr ),
1187 OCL_VAR ( OC_UINT16, 1, &_old_order ),
1189 OCL_NULL ( 1 ), ///< num_orders, now calculated
1190 OCL_SVAR( OC_UINT8, Vehicle, cur_implicit_order_index ),
1191 OCL_SVAR( OC_TILE, Vehicle, dest_tile ),
1192 OCL_SVAR( OC_UINT16, Vehicle, load_unload_ticks ),
1193 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, date_of_last_service ),
1194 OCL_SVAR( OC_UINT16, Vehicle, service_interval ),
1195 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, last_station_visited ),
1196 OCL_SVAR( OC_TTD | OC_UINT8, Vehicle, tick_counter ),
1197 OCL_CNULL( OC_TTD, 2 ), ///< max_speed, now it is calculated.
1198 OCL_CNULL( OC_TTO, 1 ), ///< max_speed, now it is calculated.
1200 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Vehicle, x_pos ),
1201 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Vehicle, y_pos ),
1202 OCL_SVAR( OC_FILE_U8 | OC_VAR_I32, Vehicle, z_pos ),
1203 OCL_SVAR( OC_UINT8, Vehicle, direction ),
1204 OCL_NULL( 2 ), ///< x_offs and y_offs, calculated automatically
1205 OCL_NULL( 2 ), ///< x_extent and y_extent, calculated automatically
1206 OCL_NULL( 1 ), ///< z_extent, calculated automatically
1208 OCL_SVAR( OC_UINT8, Vehicle, owner ),
1209 OCL_SVAR( OC_TILE, Vehicle, tile ),
1210 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, cur_image ),
1212 OCL_NULL( 8 ), ///< Vehicle sprite box, calculated automatically
1214 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Vehicle, vehstatus ),
1215 OCL_SVAR( OC_TTD | OC_UINT16, Vehicle, cur_speed ),
1216 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Vehicle, cur_speed ),
1217 OCL_SVAR( OC_UINT8, Vehicle, subspeed ),
1218 OCL_SVAR( OC_UINT8, Vehicle, acceleration ),
1219 OCL_SVAR( OC_UINT8, Vehicle, progress ),
1221 OCL_SVAR( OC_UINT8, Vehicle, cargo_type ),
1222 OCL_SVAR( OC_TTD | OC_UINT16, Vehicle, cargo_cap ),
1223 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Vehicle, cargo_cap ),
1224 OCL_VAR ( OC_TTD | OC_UINT16, 1, &_cargo_count ),
1225 OCL_VAR ( OC_TTO | OC_FILE_U8 | OC_VAR_U16, 1, &_cargo_count ),
1226 OCL_VAR ( OC_UINT8, 1, &_cargo_source ),
1227 OCL_VAR ( OC_UINT8, 1, &_cargo_days ),
1229 OCL_SVAR( OC_TTO | OC_UINT8, Vehicle, tick_counter ),
1231 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, age ),
1232 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, max_age ),
1233 OCL_SVAR( OC_FILE_U8 | OC_VAR_I32, Vehicle, build_year ),
1234 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, unitnumber ),
1236 OCL_SVAR( OC_TTD | OC_UINT16, Vehicle, engine_type ),
1237 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Vehicle, engine_type ),
1239 OCL_SVAR( OC_UINT8, Vehicle, spritenum ),
1240 OCL_SVAR( OC_UINT8, Vehicle, day_counter ),
1242 OCL_SVAR( OC_UINT8, Vehicle, breakdowns_since_last_service ),
1243 OCL_SVAR( OC_UINT8, Vehicle, breakdown_ctr ),
1244 OCL_SVAR( OC_UINT8, Vehicle, breakdown_delay ),
1245 OCL_SVAR( OC_UINT8, Vehicle, breakdown_chance ),
1247 OCL_CNULL( OC_TTO, 1 ),
1249 OCL_SVAR( OC_UINT16, Vehicle, reliability ),
1250 OCL_SVAR( OC_UINT16, Vehicle, reliability_spd_dec ),
1252 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Vehicle, profit_this_year ),
1253 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Vehicle, profit_last_year ),
1255 OCL_VAR ( OC_UINT16, 1, &_old_next_ptr ),
1257 OCL_SVAR( OC_FILE_U32 | OC_VAR_I64, Vehicle, value ),
1259 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
1261 OCL_CHUNK( 1, LoadOldVehicleUnion ),
1263 OCL_CNULL( OC_TTO, 24 ), ///< junk
1264 OCL_CNULL( OC_TTD, 20 ), ///< junk at end of struct (TTDPatch has some data in it)
1266 OCL_END()
1270 * Load the vehicles of an old style savegame.
1271 * @param ls State (buffer) of the currently loaded game.
1272 * @param num The number of vehicles to load.
1273 * @return True iff loading went without problems.
1275 bool LoadOldVehicle(LoadgameState *ls, int num)
1277 /* Read the TTDPatch flags, because we need some info from it */
1278 ReadTTDPatchFlags(ls->stv);
1280 for (uint i = 0; i < _old_vehicle_multiplier; i++) {
1281 _current_vehicle_id = num * _old_vehicle_multiplier + i;
1283 Vehicle *v;
1285 if (ls->stv->type == SGT_TTO) {
1286 uint type = ReadByte(ls);
1287 switch (type) {
1288 default: return false;
1289 case 0x00 /* VEH_INVALID */: v = NULL; break;
1290 case 0x25 /* MONORAIL */:
1291 case 0x20 /* VEH_TRAIN */: v = new (_current_vehicle_id) Train(); break;
1292 case 0x21 /* VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break;
1293 case 0x22 /* VEH_SHIP */: v = new (_current_vehicle_id) Ship(); break;
1294 case 0x23 /* VEH_AIRCRAFT */: v = new (_current_vehicle_id) Aircraft(); break;
1295 case 0x24 /* VEH_EFFECT */: v = new (_current_vehicle_id) EffectVehicle(); break;
1296 case 0x26 /* VEH_DISASTER */: v = new (_current_vehicle_id) DisasterVehicle(); break;
1299 if (!LoadChunk(ls, v, vehicle_chunk)) return false;
1300 if (v == NULL) continue;
1301 v->refit_cap = v->cargo_cap;
1303 SpriteID sprite = v->cur_image;
1304 /* no need to override other sprites */
1305 if (IsInsideMM(sprite, 1460, 1465)) {
1306 sprite += 580; // aircraft smoke puff
1307 } else if (IsInsideMM(sprite, 2096, 2115)) {
1308 sprite += 977; // special effects part 1
1309 } else if (IsInsideMM(sprite, 2396, 2436)) {
1310 sprite += 1305; // special effects part 2
1311 } else if (IsInsideMM(sprite, 2516, 2539)) {
1312 sprite += 1385; // rotor or disaster-related vehicles
1314 v->cur_image = sprite;
1316 switch (v->type) {
1317 case VEH_TRAIN: {
1318 static const byte spriteset_rail[] = {
1319 0, 2, 4, 4, 8, 10, 12, 14, 16, 18, 20, 22, 40, 42, 44, 46,
1320 48, 52, 54, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 120, 122,
1321 124, 126, 128, 130, 132, 134, 136, 138, 140
1323 if (v->spritenum / 2 >= lengthof(spriteset_rail)) return false;
1324 v->spritenum = spriteset_rail[v->spritenum / 2]; // adjust railway sprite set offset
1325 Train::From(v)->railtype = type == 0x25 ? 1 : 0; // monorail / rail
1326 break;
1329 case VEH_ROAD:
1330 if (v->spritenum >= 22) v->spritenum += 12;
1331 break;
1333 case VEH_SHIP:
1334 v->spritenum += 2;
1336 switch (v->spritenum) {
1337 case 2: // oil tanker && cargo type != oil
1338 if (v->cargo_type != CT_OIL) v->spritenum = 0; // make it a coal/goods ship
1339 break;
1340 case 4: // passenger ship && cargo type == mail
1341 if (v->cargo_type == CT_MAIL) v->spritenum = 0; // make it a mail ship
1342 break;
1343 default:
1344 break;
1346 break;
1348 default:
1349 break;
1352 switch (_old_string_id) {
1353 case 0x0000: break; // empty (invalid vehicles)
1354 case 0x0006: _old_string_id = STR_SV_EMPTY; break; // empty (special vehicles)
1355 case 0x8495: _old_string_id = STR_SV_TRAIN_NAME; break; // "Train X"
1356 case 0x8842: _old_string_id = STR_SV_ROAD_VEHICLE_NAME; break; // "Road Vehicle X"
1357 case 0x8C3B: _old_string_id = STR_SV_SHIP_NAME; break; // "Ship X"
1358 case 0x9047: _old_string_id = STR_SV_AIRCRAFT_NAME; break; // "Aircraft X"
1359 default: _old_string_id += 0x2A00; break; // custom name
1362 _old_vehicle_names[_current_vehicle_id] = _old_string_id;
1363 } else {
1364 /* Read the vehicle type and allocate the right vehicle */
1365 switch (ReadByte(ls)) {
1366 default: throw SlCorrupt("Invalid vehicle type");
1367 case 0x00 /* VEH_INVALID */: v = NULL; break;
1368 case 0x10 /* VEH_TRAIN */: v = new (_current_vehicle_id) Train(); break;
1369 case 0x11 /* VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break;
1370 case 0x12 /* VEH_SHIP */: v = new (_current_vehicle_id) Ship(); break;
1371 case 0x13 /* VEH_AIRCRAFT*/: v = new (_current_vehicle_id) Aircraft(); break;
1372 case 0x14 /* VEH_EFFECT */: v = new (_current_vehicle_id) EffectVehicle(); break;
1373 case 0x15 /* VEH_DISASTER*/: v = new (_current_vehicle_id) DisasterVehicle(); break;
1376 if (!LoadChunk(ls, v, vehicle_chunk)) return false;
1377 if (v == NULL) continue;
1379 _old_vehicle_names[_current_vehicle_id] = RemapOldStringID(_old_string_id);
1381 /* This should be consistent, else we have a big problem... */
1382 if (v->index != _current_vehicle_id) {
1383 DEBUG(oldloader, 0, "Loading failed - vehicle-array is invalid");
1384 return false;
1388 if (_old_order_ptr != 0 && _old_order_ptr != 0xFFFFFFFF) {
1389 uint max = ls->stv->type == SGT_TTO ? 3000 : 5000;
1390 uint old_id = RemapOrderIndex(ls->stv, _old_order_ptr);
1391 if (old_id < max) v->orders.old = Order::Get(old_id); // don't accept orders > max number of orders
1393 v->current_order.AssignOrder(UnpackOldOrder(_old_order));
1395 v->next = (Vehicle *)(size_t)_old_next_ptr;
1397 if (_cargo_count != 0 && CargoPacket::CanAllocateItem()) {
1398 StationID source = (_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
1399 TileIndex source_xy = (source != INVALID_STATION) ? Station::Get(source)->xy : 0;
1400 v->cargo.Append(new CargoPacket(_cargo_count, _cargo_days, source, source_xy, source_xy));
1404 return true;
1407 static const OldChunks sign_chunk[] = {
1408 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
1409 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Sign, x ),
1410 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Sign, y ),
1411 OCL_SVAR( OC_FILE_U16 | OC_VAR_I8, Sign, z ),
1413 OCL_NULL( 6 ), ///< Width of sign, no longer in use
1415 OCL_END()
1418 static bool LoadOldSign(LoadgameState *ls, int num)
1420 Sign *si = new (num) Sign();
1421 if (!LoadChunk(ls, si, sign_chunk)) return false;
1423 if (_old_string_id != 0) {
1424 if (ls->stv->type == SGT_TTO) {
1425 if (_old_string_id != 0x140A) si->name = CopyFromOldName(ls->stv, _old_string_id + 0x2A00);
1426 } else {
1427 si->name = CopyFromOldName(ls->stv, RemapOldStringID(_old_string_id));
1429 si->owner = OWNER_NONE;
1430 } else {
1431 delete si;
1434 return true;
1437 static const OldChunks engine_chunk[] = {
1438 OCL_SVAR( OC_UINT16, Engine, company_avail ),
1439 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Engine, intro_date ),
1440 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Engine, age ),
1441 OCL_SVAR( OC_UINT16, Engine, reliability ),
1442 OCL_SVAR( OC_UINT16, Engine, reliability_spd_dec ),
1443 OCL_SVAR( OC_UINT16, Engine, reliability_start ),
1444 OCL_SVAR( OC_UINT16, Engine, reliability_max ),
1445 OCL_SVAR( OC_UINT16, Engine, reliability_final ),
1446 OCL_SVAR( OC_UINT16, Engine, duration_phase_1 ),
1447 OCL_SVAR( OC_UINT16, Engine, duration_phase_2 ),
1448 OCL_SVAR( OC_UINT16, Engine, duration_phase_3 ),
1450 OCL_NULL( 1 ), // lifelength
1451 OCL_SVAR( OC_UINT8, Engine, flags ),
1452 OCL_NULL( 1 ), // preview_company_rank
1453 OCL_SVAR( OC_UINT8, Engine, preview_wait ),
1455 OCL_CNULL( OC_TTD, 2 ), ///< railtype + junk
1457 OCL_END()
1460 static bool LoadOldEngine(LoadgameState *ls, int num)
1462 Engine *e = ls->stv->type == SGT_TTO ? &_old_engines[num] : GetTempDataEngine(num);
1463 return LoadChunk(ls, e, engine_chunk);
1466 static bool LoadOldEngineName(LoadgameState *ls, int num)
1468 Engine *e = GetTempDataEngine(num);
1469 e->name = CopyFromOldName(ls->stv, RemapOldStringID(ReadUint16(ls)));
1470 return true;
1473 static const OldChunks subsidy_chunk[] = {
1474 OCL_SVAR( OC_UINT8, Subsidy, cargo_type ),
1475 OCL_SVAR( OC_UINT8, Subsidy, remaining ),
1476 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Subsidy, src ),
1477 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Subsidy, dst ),
1479 OCL_END()
1482 static bool LoadOldSubsidy(LoadgameState *ls, int num)
1484 Subsidy *s = new (num) Subsidy();
1485 bool ret = LoadChunk(ls, s, subsidy_chunk);
1486 if (s->cargo_type == CT_INVALID) delete s;
1487 return ret;
1490 static const OldChunks game_difficulty_chunk[] = {
1491 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, max_no_competitors ),
1492 OCL_NULL( 2), // competitor_start_time
1493 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, number_towns ),
1494 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, industry_density ),
1495 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, DifficultySettings, max_loan ),
1496 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, initial_interest ),
1497 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, vehicle_costs ),
1498 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, competitor_speed ),
1499 OCL_NULL( 2), // competitor_intelligence
1500 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, vehicle_breakdowns ),
1501 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, subsidy_multiplier ),
1502 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, construction_cost ),
1503 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, terrain_type ),
1504 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, quantity_sea_lakes ),
1505 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, economy ),
1506 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, line_reverse_mode ),
1507 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, disasters ),
1508 OCL_END()
1511 static bool LoadOldGameDifficulty(LoadgameState *ls, int num)
1513 bool ret = LoadChunk(ls, &_settings_game.difficulty, game_difficulty_chunk);
1514 _settings_game.difficulty.max_loan *= 1000;
1515 return ret;
1519 static bool LoadOldMapPart1(LoadgameState *ls, int num)
1521 if (ls->stv->type == SGT_TTO) {
1522 MemSetT(_mth, 0, OLD_MAP_SIZE);
1523 MemSetT(_mc, 0, OLD_MAP_SIZE);
1526 for (uint i = 0; i < OLD_MAP_SIZE; i++) {
1527 _mc[i].m1 = ReadByte(ls);
1529 for (uint i = 0; i < OLD_MAP_SIZE; i++) {
1530 _mc[i].m2 = ReadByte(ls);
1533 if (ls->stv->type != SGT_TTO) {
1534 for (uint i = 0; i < OLD_MAP_SIZE; i++) {
1535 _old_map3[i * 2] = ReadByte(ls);
1536 _old_map3[i * 2 + 1] = ReadByte(ls);
1538 for (uint i = 0; i < OLD_MAP_SIZE / 4; i++) {
1539 byte b = ReadByte(ls);
1540 _mc[i * 4 + 0].m0 = GB(b, 0, 2);
1541 _mc[i * 4 + 1].m0 = GB(b, 2, 2);
1542 _mc[i * 4 + 2].m0 = GB(b, 4, 2);
1543 _mc[i * 4 + 3].m0 = GB(b, 6, 2);
1547 return true;
1550 static bool LoadOldMapPart2(LoadgameState *ls, int num)
1552 uint i;
1554 for (i = 0; i < OLD_MAP_SIZE; i++) {
1555 _mth[i] = ReadByte(ls);
1557 for (i = 0; i < OLD_MAP_SIZE; i++) {
1558 _mc[i].m5 = ReadByte(ls);
1561 return true;
1564 static bool LoadTTDPatchExtraChunks(LoadgameState *ls, int num)
1566 ReadTTDPatchFlags(ls->stv);
1568 DEBUG(oldloader, 2, "Found %d extra chunk(s)", _old_extra_chunk_nums);
1570 for (int i = 0; i != _old_extra_chunk_nums; i++) {
1571 uint16 id = ReadUint16(ls);
1572 uint32 len = ReadUint32(ls);
1574 switch (id) {
1575 /* List of GRFIDs, used in the savegame. 0x8004 is the new ID
1576 * They are saved in a 'GRFID:4 active:1' format, 5 bytes for each entry */
1577 case 0x2:
1578 case 0x8004: {
1579 /* Skip the first element: TTDP hack for the Action D special variables (FFFF0000 01) */
1580 ReadUint32(ls); ReadByte(ls); len -= 5;
1582 ClearGRFConfigList(&_grfconfig);
1583 while (len != 0) {
1584 uint32 grfid = ReadUint32(ls);
1586 if (ReadByte(ls) == 1) {
1587 GRFConfig *c = new GRFConfig("TTDP game, no information");
1588 c->ident.grfid = grfid;
1590 AppendToGRFConfigList(&_grfconfig, c);
1591 DEBUG(oldloader, 3, "TTDPatch game using GRF file with GRFID %0X", BSWAP32(c->ident.grfid));
1593 len -= 5;
1596 /* Append static NewGRF configuration */
1597 AppendStaticGRFConfigs(&_grfconfig);
1598 break;
1601 /* TTDPatch version and configuration */
1602 case 0x3:
1603 ls->stv->ttdp.version = ReadUint32(ls);
1604 DEBUG(oldloader, 3, "Game saved with TTDPatch version %d.%d.%d r%d",
1605 GB(ls->stv->ttdp.version, 24, 8), GB(ls->stv->ttdp.version, 20, 4), GB(ls->stv->ttdp.version, 16, 4), GB(ls->stv->ttdp.version, 0, 16));
1606 len -= 4;
1607 while (len-- != 0) ReadByte(ls); // skip the configuration
1608 break;
1610 default:
1611 DEBUG(oldloader, 4, "Skipping unknown extra chunk %X", id);
1612 while (len-- != 0) ReadByte(ls);
1613 break;
1617 return true;
1620 extern TileIndex _cur_tileloop_tile;
1621 extern uint16 _disaster_delay;
1622 extern byte _trees_tick_ctr;
1623 extern byte _age_cargo_skip_counter; // From misc_sl.cpp
1624 extern uint8 _old_diff_level;
1625 extern uint8 _old_units;
1626 static const OldChunks main_chunk[] = {
1627 OCL_ASSERT( OC_TTD, 0 ),
1628 OCL_ASSERT( OC_TTO, 0 ),
1629 OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &_date ),
1630 OCL_VAR ( OC_UINT16, 1, &_date_fract ),
1631 OCL_NULL( 600 ), ///< TextEffects
1632 OCL_VAR ( OC_UINT32, 2, &_random.state ),
1634 OCL_ASSERT( OC_TTD, 0x264 ),
1635 OCL_ASSERT( OC_TTO, 0x264 ),
1637 OCL_CCHUNK( OC_TTD, 70, LoadOldTown ),
1638 OCL_CCHUNK( OC_TTO, 80, LoadOldTown ),
1640 OCL_ASSERT( OC_TTD, 0x1C18 ),
1641 OCL_ASSERT( OC_TTO, 0x1AC4 ),
1643 OCL_CCHUNK( OC_TTD, 5000, LoadOldOrder ),
1644 OCL_CCHUNK( OC_TTO, 3000, LoadOldOrder ),
1646 OCL_ASSERT( OC_TTD, 0x4328 ),
1647 OCL_ASSERT( OC_TTO, 0x3234 ),
1649 OCL_CHUNK( 1, LoadOldAnimTileList ),
1650 OCL_NULL( 4 ), ///< old end-of-order-list-pointer, no longer in use
1652 OCL_ASSERT( OC_TTO, 0x3438 ),
1654 OCL_CCHUNK( OC_TTD, 255, LoadOldDepot ),
1655 OCL_CCHUNK( OC_TTO, 252, LoadOldDepot ),
1657 OCL_ASSERT( OC_TTD, 0x4B26 ),
1658 OCL_ASSERT( OC_TTO, 0x3A20 ),
1660 OCL_NULL( 4 ), ///< town counter, no longer in use
1661 OCL_NULL( 2 ), ///< timer_counter, no longer in use
1662 OCL_NULL( 2 ), ///< land_code, no longer in use
1664 OCL_VAR ( OC_FILE_U16 | OC_VAR_U8, 1, &_age_cargo_skip_counter ),
1665 OCL_VAR ( OC_UINT16, 1, &_tick_counter ),
1666 OCL_VAR ( OC_TILE, 1, &_cur_tileloop_tile ),
1668 OCL_ASSERT( OC_TTO, 0x3A2E ),
1670 OCL_CNULL( OC_TTO, 48 * 6 ), ///< prices
1671 OCL_CNULL( OC_TTD, 49 * 6 ), ///< prices
1673 OCL_ASSERT( OC_TTO, 0x3B4E ),
1675 OCL_CNULL( OC_TTO, 11 * 8 ), ///< cargo payment rates
1676 OCL_CNULL( OC_TTD, 12 * 8 ), ///< cargo payment rates
1678 OCL_ASSERT( OC_TTD, 0x4CBA ),
1679 OCL_ASSERT( OC_TTO, 0x3BA6 ),
1681 OCL_CHUNK( 1, LoadOldMapPart1 ),
1683 OCL_ASSERT( OC_TTD, 0x48CBA ),
1684 OCL_ASSERT( OC_TTO, 0x23BA6 ),
1686 OCL_CCHUNK( OC_TTD, 250, LoadOldStation ),
1687 OCL_CCHUNK( OC_TTO, 200, LoadOldStation ),
1689 OCL_ASSERT( OC_TTO, 0x29E16 ),
1691 OCL_CCHUNK( OC_TTD, 90, LoadOldIndustry ),
1692 OCL_CCHUNK( OC_TTO, 100, LoadOldIndustry ),
1694 OCL_ASSERT( OC_TTO, 0x2ADB6 ),
1696 OCL_CHUNK( 8, LoadOldCompany ),
1698 OCL_ASSERT( OC_TTD, 0x547F2 ),
1699 OCL_ASSERT( OC_TTO, 0x2C746 ),
1701 OCL_CCHUNK( OC_TTD, 850, LoadOldVehicle ),
1702 OCL_CCHUNK( OC_TTO, 800, LoadOldVehicle ),
1704 OCL_ASSERT( OC_TTD, 0x6F0F2 ),
1705 OCL_ASSERT( OC_TTO, 0x45746 ),
1707 OCL_VAR ( OC_TTD | OC_UINT8 | OC_DEREFERENCE_POINTER, 32 * 500, &_old_name_array ),
1708 OCL_VAR ( OC_TTO | OC_UINT8 | OC_DEREFERENCE_POINTER, 24 * 200, &_old_name_array ),
1710 OCL_ASSERT( OC_TTO, 0x46A06 ),
1712 OCL_NULL( 0x2000 ), ///< Old hash-table, no longer in use
1714 OCL_CHUNK( 40, LoadOldSign ),
1716 OCL_ASSERT( OC_TTO, 0x48C36 ),
1718 OCL_CCHUNK( OC_TTD, 256, LoadOldEngine ),
1719 OCL_CCHUNK( OC_TTO, 103, LoadOldEngine ),
1721 OCL_ASSERT( OC_TTO, 0x496AC ),
1723 OCL_NULL ( 2 ), // _vehicle_id_ctr_day
1725 OCL_CHUNK( 8, LoadOldSubsidy ),
1727 OCL_ASSERT( OC_TTO, 0x496CE ),
1729 OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &_next_competitor_start ),
1731 OCL_CNULL( OC_TTO, 2 ), ///< available monorail bitmask
1733 OCL_VAR ( OC_FILE_I16 | OC_VAR_I32, 1, &_saved_scrollpos_x ),
1734 OCL_VAR ( OC_FILE_I16 | OC_VAR_I32, 1, &_saved_scrollpos_y ),
1735 OCL_VAR ( OC_FILE_U16 | OC_VAR_U8, 1, &_saved_scrollpos_zoom ),
1737 OCL_NULL( 4 ), ///< max_loan
1738 OCL_VAR ( OC_FILE_U32 | OC_VAR_I64, 1, &_economy.old_max_loan_unround ),
1739 OCL_VAR ( OC_INT16, 1, &_economy.fluct ),
1741 OCL_VAR ( OC_UINT16, 1, &_disaster_delay ),
1743 OCL_ASSERT( OC_TTO, 0x496E4 ),
1745 OCL_CNULL( OC_TTD, 144 ), ///< cargo-stuff
1747 OCL_CCHUNK( OC_TTD, 256, LoadOldEngineName ),
1749 OCL_CNULL( OC_TTD, 144 ), ///< AI cargo-stuff
1750 OCL_NULL( 2 ), ///< Company indexes of companies, no longer in use
1751 OCL_NULL( 1 ), ///< Station tick counter, no longer in use
1753 OCL_VAR ( OC_UINT8, 1, &_settings_game.locale.currency ),
1754 OCL_VAR ( OC_UINT8, 1, &_old_units ),
1755 OCL_VAR ( OC_FILE_U8 | OC_VAR_U32, 1, &_cur_company_tick_index ),
1757 OCL_NULL( 2 ), ///< Date stuff, calculated automatically
1758 OCL_NULL( 8 ), ///< Company colours, calculated automatically
1760 OCL_VAR ( OC_UINT8, 1, &_economy.infl_amount ),
1761 OCL_VAR ( OC_UINT8, 1, &_economy.infl_amount_pr ),
1762 OCL_VAR ( OC_UINT8, 1, &_economy.interest_rate ),
1763 OCL_NULL( 1 ), // available airports
1764 OCL_VAR ( OC_UINT8, 1, &_settings_game.vehicle.road_side ),
1765 OCL_VAR ( OC_UINT8, 1, &_settings_game.game_creation.town_name ),
1767 OCL_CHUNK( 1, LoadOldGameDifficulty ),
1769 OCL_ASSERT( OC_TTD, 0x77130 ),
1771 OCL_VAR ( OC_UINT8, 1, &_old_diff_level ),
1773 OCL_VAR ( OC_TTD | OC_UINT8, 1, &_settings_game.game_creation.landscape ),
1774 OCL_VAR ( OC_TTD | OC_UINT8, 1, &_trees_tick_ctr ),
1776 OCL_CNULL( OC_TTD, 1 ), ///< Custom vehicle types yes/no, no longer used
1777 OCL_VAR ( OC_TTD | OC_UINT8, 1, &_settings_game.game_creation.snow_line_height ),
1779 OCL_CNULL( OC_TTD, 32 ), ///< new_industry_randtable, no longer used (because of new design)
1780 OCL_CNULL( OC_TTD, 36 ), ///< cargo-stuff
1782 OCL_ASSERT( OC_TTD, 0x77179 ),
1783 OCL_ASSERT( OC_TTO, 0x4971D ),
1785 OCL_CHUNK( 1, LoadOldMapPart2 ),
1787 OCL_ASSERT( OC_TTD, 0x97179 ),
1788 OCL_ASSERT( OC_TTO, 0x6971D ),
1790 /* Below any (if available) extra chunks from TTDPatch can follow */
1791 OCL_CHUNK(1, LoadTTDPatchExtraChunks),
1793 OCL_END()
1796 bool LoadTTDMain(LoadgameState *ls)
1798 DEBUG(oldloader, 3, "Reading main chunk...");
1800 _read_ttdpatch_flags = false;
1802 /* Load the biggest chunk */
1803 SmallStackSafeStackAlloc<byte, OLD_MAP_SIZE * 2> map3;
1804 _old_map3 = map3.data;
1805 _old_vehicle_names = NULL;
1806 try {
1807 if (!LoadChunk(ls, NULL, main_chunk)) {
1808 DEBUG(oldloader, 0, "Loading failed");
1809 free(_old_vehicle_names);
1810 return false;
1812 } catch (...) {
1813 free(_old_vehicle_names);
1814 throw;
1817 DEBUG(oldloader, 3, "Done, converting game data...");
1819 FixTTDMapArray();
1820 FixTTDDepots();
1822 /* Fix some general stuff */
1823 _settings_game.game_creation.landscape = _settings_game.game_creation.landscape & 0xF;
1825 /* Fix the game to be compatible with OpenTTD */
1826 FixOldTowns();
1827 FixOldVehicles(ls->stv);
1829 /* We have a new difficulty setting */
1830 _settings_game.difficulty.town_council_tolerance = Clamp(_old_diff_level, 0, 2);
1832 DEBUG(oldloader, 3, "Finished converting game data");
1833 DEBUG(oldloader, 1, "TTD(Patch) savegame successfully converted");
1835 free(_old_vehicle_names);
1837 return true;
1840 bool LoadTTOMain(LoadgameState *ls)
1842 DEBUG(oldloader, 3, "Reading main chunk...");
1844 _read_ttdpatch_flags = false;
1846 SmallStackSafeStackAlloc<byte, 103 * sizeof(Engine)> engines; // we don't want to call Engine constructor here
1847 _old_engines = (Engine *)engines.data;
1848 SmallStackSafeStackAlloc<StringID, 800> vehnames;
1849 _old_vehicle_names = vehnames.data;
1851 /* Load the biggest chunk */
1852 if (!LoadChunk(ls, NULL, main_chunk)) {
1853 DEBUG(oldloader, 0, "Loading failed");
1854 return false;
1856 DEBUG(oldloader, 3, "Done, converting game data...");
1858 if (_settings_game.game_creation.town_name != 0) _settings_game.game_creation.town_name++;
1860 _settings_game.game_creation.landscape = 0;
1861 _trees_tick_ctr = 0xFF;
1863 if (!FixTTOMapArray() || !FixTTOEngines()) {
1864 DEBUG(oldloader, 0, "Conversion failed");
1865 return false;
1868 FixOldTowns();
1869 FixOldVehicles(ls->stv);
1870 FixTTOCompanies();
1872 /* We have a new difficulty setting */
1873 _settings_game.difficulty.town_council_tolerance = Clamp(_old_diff_level, 0, 2);
1875 /* SVXConverter about cargo payment rates correction:
1876 * "increase them to compensate for the faster time advance in TTD compared to TTO
1877 * which otherwise would cause much less income while the annual running costs of
1878 * the vehicles stay the same" */
1879 _economy.inflation_payment = min(_economy.inflation_payment * 124 / 74, MAX_INFLATION);
1881 DEBUG(oldloader, 3, "Finished converting game data");
1882 DEBUG(oldloader, 1, "TTO savegame successfully converted");
1884 return true;