2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file oldloader_sl.cpp Chunks and fix-ups for TTO/TTD/TTDP savegames. TTO loader code is based on SVXConverter by Roman Vetter. */
10 #include "../stdafx.h"
12 #include "../industry.h"
13 #include "../company_func.h"
14 #include "../aircraft.h"
15 #include "../roadveh.h"
18 #include "../signs_base.h"
19 #include "../station_base.h"
20 #include "../subsidy_base.h"
22 #include "../depot_base.h"
23 #include "../timer/timer_game_calendar.h"
24 #include "../timer/timer_game_calendar.h"
25 #include "../vehicle_func.h"
26 #include "../effectvehicle_base.h"
27 #include "../engine_func.h"
28 #include "../company_base.h"
29 #include "../disaster_vehicle.h"
30 #include "../timer/timer.h"
31 #include "../timer/timer_game_tick.h"
32 #include "../timer/timer_game_calendar.h"
33 #include "saveload_internal.h"
34 #include "oldloader.h"
36 #include "table/strings.h"
37 #include "../table/engines.h"
38 #include "../table/townname.h"
40 #include "../safeguards.h"
42 static bool _read_ttdpatch_flags
; ///< Have we (tried to) read TTDPatch extra flags?
43 static uint16_t _old_extra_chunk_nums
; ///< Number of extra TTDPatch chunks
44 static uint8_t _old_vehicle_multiplier
; ///< TTDPatch vehicle multiplier
48 /* TTO/TTD/TTDP savegames could have buoys at tile 0
49 * (without assigned station struct) */
53 static void FixTTDMapArray()
55 for (auto tile
: Map::Iterate()) {
56 switch (GetTileType(tile
)) {
58 tile
.m4() = 0; // We do not understand this TTDP station mapping (yet)
60 /* We have drive through stops at a totally different place */
61 case 0x53: case 0x54: tile
.m5() += 170 - 0x53; break; // Bus drive through
62 case 0x57: case 0x58: tile
.m5() += 168 - 0x57; break; // Truck drive through
63 case 0x55: case 0x56: tile
.m5() += 170 - 0x55; break; // Bus tram stop
64 case 0x59: case 0x5A: tile
.m5() += 168 - 0x59; break; // Truck tram stop
70 /* We save presignals different from TTDPatch, convert them */
71 if (GB(tile
.m5(), 6, 2) == 1) { // RAIL_TILE_SIGNALS
72 /* This byte is always zero in TTD for this type of tile */
73 if (tile
.m4()) { // Convert the presignals to our own format
74 tile
.m4() = (tile
.m4() >> 1) & 7;
77 /* TTDPatch stores PBS things in L6 and all elsewhere; so we'll just
78 * clear it for ourselves and let OTTD's rebuild PBS itself */
79 tile
.m4() &= 0xF; // Only keep the lower four bits; upper four is PBS
83 /* if water class == 3, make river there */
84 if (GB(tile
.m3(), 0, 2) == 3) {
85 SetTileType(tile
, MP_WATER
);
86 SetTileOwner(tile
, OWNER_WATER
);
88 tile
.m3() = 2; // WATER_CLASS_RIVER
102 static void FixTTDDepots()
104 for (const Depot
*d
: Depot::Iterate(252)) {
105 if (!IsDepotTile(d
->xy
) || GetDepotIndex(d
->xy
) != d
->index
) {
106 /** Workaround for SVXConverter bug, depots 252-255 could be invalid */
112 #define FIXNUM(x, y, z) (((((x) << 16) / (y)) + 1) << z)
114 static uint32_t RemapOldTownName(uint32_t townnameparts
, uint8_t old_town_name_type
)
116 switch (old_town_name_type
) {
117 case 0: case 3: // English, American
119 return townnameparts
;
122 /* For some reason 86 needs to be subtracted from townnameparts
123 * 0000 0000 0000 0000 0000 0000 1111 1111 */
124 return FIXNUM(townnameparts
- 86, lengthof(_name_french_real
), 0);
127 Debug(misc
, 0, "German Townnames are buggy ({})", townnameparts
);
128 return townnameparts
;
130 case 4: // Latin-American
131 /* 0000 0000 0000 0000 0000 0000 1111 1111 */
132 return FIXNUM(townnameparts
, lengthof(_name_spanish_real
), 0);
135 /* NUM_SILLY_1 - lower 16 bits
136 * NUM_SILLY_2 - upper 16 bits without leading 1 (first 8 bytes)
137 * 1000 0000 2222 2222 0000 0000 1111 1111 */
138 return FIXNUM(townnameparts
, lengthof(_name_silly_1
), 0) | FIXNUM(GB(townnameparts
, 16, 8), lengthof(_name_silly_2
), 16);
145 static void FixOldTowns()
147 /* Convert town-names if needed */
148 for (Town
*town
: Town::Iterate()) {
149 if (IsInsideMM(town
->townnametype
, 0x20C1, 0x20C3)) {
150 town
->townnametype
= SPECSTR_TOWNNAME_ENGLISH
+ _settings_game
.game_creation
.town_name
;
151 town
->townnameparts
= RemapOldTownName(town
->townnameparts
, _settings_game
.game_creation
.town_name
);
156 static StringID
*_old_vehicle_names
;
159 * Convert the old style vehicles into something that resembles
160 * the old new style savegames. Then #AfterLoadGame can handle
161 * the rest of the conversion.
163 void FixOldVehicles()
165 for (Vehicle
*v
: Vehicle::Iterate()) {
166 if ((size_t)v
->next
== 0xFFFF) {
169 v
->next
= Vehicle::GetIfValid((size_t)v
->next
);
172 /* For some reason we need to correct for this */
173 switch (v
->spritenum
) {
175 case 0xff: v
->spritenum
= 0xfe; break;
176 default: v
->spritenum
>>= 1; break;
179 /* Vehicle-subtype is different in TTD(Patch) */
180 if (v
->type
== VEH_EFFECT
) v
->subtype
= v
->subtype
>> 1;
182 v
->name
= CopyFromOldName(_old_vehicle_names
[v
->index
]);
184 /* We haven't used this bit for stations for ages */
185 if (v
->type
== VEH_ROAD
) {
186 RoadVehicle
*rv
= RoadVehicle::From(v
);
187 if (rv
->state
!= RVSB_IN_DEPOT
&& rv
->state
!= RVSB_WORMHOLE
) {
188 ClrBit(rv
->state
, 2);
190 if (IsTileType(tile
, MP_STATION
) && tile
.m5() >= 168) {
191 /* Update the vehicle's road state to show we're in a drive through road stop. */
192 SetBit(rv
->state
, RVS_IN_DT_ROAD_STOP
);
197 /* The subtype should be 0, but it sometimes isn't :( */
198 if (v
->type
== VEH_ROAD
|| v
->type
== VEH_SHIP
) v
->subtype
= 0;
200 /* Sometimes primary vehicles would have a nothing (invalid) order
201 * or vehicles that could not have an order would still have a
202 * (loading) order which causes assertions and the like later on.
204 if (!IsCompanyBuildableVehicleType(v
) ||
205 (v
->IsPrimaryVehicle() && v
->current_order
.IsType(OT_NOTHING
))) {
206 v
->current_order
.MakeDummy();
209 /* Shared orders are fixed in AfterLoadVehicles now */
213 static bool FixTTOMapArray()
215 for (auto tile
: Map::Iterate()) {
216 TileType tt
= GetTileType(tile
);
218 /* TTO has a different way of storing monorail.
219 * Instead of using bits in m3 it uses a different tile type. */
220 tile
.m3() = 1; // rail type = monorail (in TTD)
221 SetTileType(tile
, MP_RAILWAY
);
222 tile
.m2() = 1; // set monorail ground to RAIL_GROUND_GRASS
231 switch (GB(tile
.m5(), 6, 2)) {
232 case 0: // RAIL_TILE_NORMAL
234 case 1: // RAIL_TILE_SIGNALS
235 tile
.m4() = (~tile
.m5() & 1) << 2; // signal variant (present only in OTTD)
236 SB(tile
.m2(), 6, 2, GB(tile
.m5(), 3, 2)); // signal status
237 tile
.m3() |= 0xC0; // both signals are present
238 tile
.m5() = HasBit(tile
.m5(), 5) ? 2 : 1; // track direction (only X or Y)
239 tile
.m5() |= 0x40; // RAIL_TILE_SIGNALS
241 case 3: // RAIL_TILE_DEPOT
249 case MP_ROAD
: // road (depot) or level crossing
250 switch (GB(tile
.m5(), 4, 4)) {
251 case 0: // ROAD_TILE_NORMAL
252 if (tile
.m2() == 4) tile
.m2() = 5; // 'small trees' -> ROADSIDE_TREES
254 case 1: // ROAD_TILE_CROSSING (there aren't monorail crossings in TTO)
255 tile
.m3() = tile
.m1(); // set owner of road = owner of rail
257 case 2: // ROAD_TILE_DEPOT
265 tile
.m3() = tile
.m2() & 0xC0; // construction stage
266 tile
.m2() &= 0x3F; // building type
267 if (tile
.m2() >= 5) tile
.m2()++; // skip "large office block on snow"
271 tile
.m3() = GB(tile
.m5(), 3, 3); // type of trees
272 tile
.m5() &= 0xC7; // number of trees and growth status
276 tile
.m3() = (tile
.m5() >= 0x08 && tile
.m5() <= 0x0F) ? 1 : 0; // monorail -> 1, others 0 (rail, road, airport, dock)
277 if (tile
.m5() >= 8) tile
.m5() -= 8; // shift for monorail
278 if (tile
.m5() >= 0x42) tile
.m5()++; // skip heliport
282 tile
.m3() = tile
.m2() = 0;
286 tile
.m2() = tile
.m3() = tile
.m5() = 0;
292 case 0x24: // farm silo
295 case 0x25: case 0x27: // farm
296 case 0x28: case 0x29: case 0x2A: case 0x2B: // factory
300 if (tile
.m5() >= 0x2C) tile
.m5() += 3; // iron ore mine, steel mill or bank
305 case MP_TUNNELBRIDGE
:
306 if (HasBit(tile
.m5(), 7)) { // bridge
307 uint8_t m5
= tile
.m5();
308 tile
.m5() = m5
& 0xE1; // copy bits 7..5, 1
309 if (GB(m5
, 1, 2) == 1) tile
.m5() |= 0x02; // road bridge
310 if (GB(m5
, 1, 2) == 3) tile
.m2() |= 0xA0; // monorail bridge -> tubular, steel bridge
311 if (!HasBit(m5
, 6)) { // bridge head
312 tile
.m3() = (GB(m5
, 1, 2) == 3) ? 1 : 0; // track subtype (1 for monorail, 0 for others)
313 } else { // middle bridge part
314 tile
.m3() = HasBit(m5
, 2) ? 0x10 : 0; // track subtype on bridge
315 if (GB(m5
, 3, 2) == 3) tile
.m3() |= 1; // track subtype under bridge
316 if (GB(m5
, 3, 2) == 1) tile
.m5() |= 0x08; // set for road/water under (0 for rail/clear)
318 } else { // tunnel entrance/exit
320 tile
.m3() = HasBit(tile
.m5(), 3); // monorail
321 tile
.m5() &= HasBit(tile
.m5(), 3) ? 0x03 : 0x07 ; // direction, transport type (== 0 for rail)
341 static Engine
*_old_engines
;
343 static bool FixTTOEngines()
345 /** TTD->TTO remapping of engines; 255 means there is no equivalent. SVXConverter uses (almost) the same table. */
346 static const EngineID ttd_to_tto
[] = {
347 0, 255, 255, 255, 255, 255, 255, 255, 5, 7, 8, 9, 10, 11, 12, 13,
348 255, 255, 255, 255, 255, 255, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
349 25, 26, 27, 29, 28, 30, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
350 255, 255, 255, 255, 255, 255, 255, 31, 255, 32, 33, 34, 35, 36, 37, 38,
351 39, 40, 41, 42, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
352 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
353 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
354 255, 255, 255, 255, 44, 45, 46, 255, 255, 255, 255, 47, 48, 255, 49, 50,
355 255, 255, 255, 255, 51, 52, 255, 53, 54, 255, 55, 56, 255, 57, 59, 255,
356 58, 60, 255, 61, 62, 255, 63, 64, 255, 65, 66, 255, 255, 255, 255, 255,
357 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
358 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
359 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 67, 68, 69, 70,
360 71, 255, 255, 76, 77, 255, 255, 78, 79, 80, 81, 82, 83, 84, 85, 86,
361 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 255,
362 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 102, 255, 255
365 /** TTO->TTD remapping of engines. SVXConverter uses the same table. */
366 static const EngineID tto_to_ttd
[] = {
367 0, 0, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 15, 15, 22,
368 23, 24, 25, 26, 27, 29, 28, 30, 31, 32, 33, 34, 35, 36, 37, 55,
369 57, 59, 58, 60, 61, 62, 63, 64, 65, 66, 67, 116, 116, 117, 118, 123,
370 124, 126, 127, 132, 133, 135, 136, 138, 139, 141, 142, 144, 145, 147, 148, 150,
371 151, 153, 154, 204, 205, 206, 207, 208, 211, 212, 211, 212, 211, 212, 215, 216,
372 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
373 233, 234, 235, 236, 237, 238, 253
376 for (Vehicle
*v
: Vehicle::Iterate()) {
377 if (v
->engine_type
>= lengthof(tto_to_ttd
)) return false;
378 v
->engine_type
= tto_to_ttd
[v
->engine_type
];
381 /* Load the default engine set. Many of them will be overridden later */
384 for (uint i
= 0; i
< lengthof(_orig_rail_vehicle_info
); i
++, j
++) new (GetTempDataEngine(j
)) Engine(VEH_TRAIN
, i
);
385 for (uint i
= 0; i
< lengthof(_orig_road_vehicle_info
); i
++, j
++) new (GetTempDataEngine(j
)) Engine(VEH_ROAD
, i
);
386 for (uint i
= 0; i
< lengthof(_orig_ship_vehicle_info
); i
++, j
++) new (GetTempDataEngine(j
)) Engine(VEH_SHIP
, i
);
387 for (uint i
= 0; i
< lengthof(_orig_aircraft_vehicle_info
); i
++, j
++) new (GetTempDataEngine(j
)) Engine(VEH_AIRCRAFT
, i
);
390 TimerGameCalendar::Date aging_date
= std::min(TimerGameCalendar::date
+ CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR
, TimerGameCalendar::ConvertYMDToDate(2050, 0, 1));
391 TimerGameCalendar::YearMonthDay aging_ymd
= TimerGameCalendar::ConvertDateToYMD(aging_date
);
393 for (EngineID i
= 0; i
< 256; i
++) {
394 int oi
= ttd_to_tto
[i
];
395 Engine
*e
= GetTempDataEngine(i
);
398 /* Default engine is used */
399 TimerGameCalendar::date
+= CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR
;
400 StartupOneEngine(e
, aging_ymd
, 0);
401 CalcEngineReliability(e
, false);
402 e
->intro_date
-= CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR
;
403 TimerGameCalendar::date
-= CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR
;
405 /* Make sure for example monorail and maglev are available when they should be */
406 if (TimerGameCalendar::date
>= e
->intro_date
&& HasBit(e
->info
.climates
, 0)) {
407 e
->flags
|= ENGINE_AVAILABLE
;
408 e
->company_avail
= MAX_UVALUE(CompanyMask
);
409 e
->age
= TimerGameCalendar::date
> e
->intro_date
? (TimerGameCalendar::date
- e
->intro_date
).base() / 30 : 0;
412 /* Using data from TTO savegame */
413 Engine
*oe
= &_old_engines
[oi
];
415 e
->intro_date
= oe
->intro_date
;
417 e
->reliability
= oe
->reliability
;
418 e
->reliability_spd_dec
= oe
->reliability_spd_dec
;
419 e
->reliability_start
= oe
->reliability_start
;
420 e
->reliability_max
= oe
->reliability_max
;
421 e
->reliability_final
= oe
->reliability_final
;
422 e
->duration_phase_1
= oe
->duration_phase_1
;
423 e
->duration_phase_2
= oe
->duration_phase_2
;
424 e
->duration_phase_3
= oe
->duration_phase_3
;
425 e
->flags
= oe
->flags
;
427 e
->company_avail
= 0;
429 /* One or more engines were remapped to this one. Make this engine available
430 * if at least one of them was available. */
431 for (uint j
= 0; j
< lengthof(tto_to_ttd
); j
++) {
432 if (tto_to_ttd
[j
] == i
&& _old_engines
[j
].company_avail
!= 0) {
433 e
->company_avail
= MAX_UVALUE(CompanyMask
);
434 e
->flags
|= ENGINE_AVAILABLE
;
439 e
->info
.climates
= 1;
442 e
->preview_company
= INVALID_COMPANY
;
443 e
->preview_asked
= MAX_UVALUE(CompanyMask
);
445 e
->name
= std::string
{};
451 static void FixTTOCompanies()
453 for (Company
*c
: Company::Iterate()) {
454 c
->cur_economy
.company_value
= CalculateCompanyValue(c
); // company value history is zeroed
458 static inline Colours
RemapTTOColour(Colours tto
)
460 /** Lossy remapping of TTO colours to TTD colours. SVXConverter uses the same conversion. */
461 static const Colours tto_colour_remap
[] = {
462 COLOUR_DARK_BLUE
, COLOUR_GREY
, COLOUR_YELLOW
, COLOUR_RED
,
463 COLOUR_PURPLE
, COLOUR_DARK_GREEN
, COLOUR_ORANGE
, COLOUR_PALE_GREEN
,
464 COLOUR_BLUE
, COLOUR_GREEN
, COLOUR_CREAM
, COLOUR_BROWN
,
465 COLOUR_WHITE
, COLOUR_LIGHT_BLUE
, COLOUR_MAUVE
, COLOUR_PINK
468 if (static_cast<size_t>(tto
) >= std::size(tto_colour_remap
)) return COLOUR_GREY
; // this shouldn't happen
470 return tto_colour_remap
[tto
];
473 static inline uint
RemapTownIndex(uint x
)
475 return _savegame_type
== SGT_TTO
? (x
- 0x264) / 78 : (x
- 0x264) / 94;
478 static inline uint
RemapOrderIndex(uint x
)
480 return _savegame_type
== SGT_TTO
? (x
- 0x1AC4) / 2 : (x
- 0x1C18) / 2;
483 extern std::vector
<TileIndex
> _animated_tiles
;
484 extern TimeoutTimer
<TimerGameTick
> _new_competitor_timeout
;
485 extern char *_old_name_array
;
487 static uint32_t _old_town_index
;
488 static uint16_t _old_string_id
;
489 static uint16_t _old_string_id_2
;
491 static void ClearOldMap3(TileIndex t
)
498 static Town
*RemapTown(TileIndex fallback
)
500 /* In some cases depots, industries and stations could refer to a missing town. */
501 Town
*t
= Town::GetIfValid(RemapTownIndex(_old_town_index
));
503 /* In case the town that was refered to does not exist, find the closest.
504 * However, this needs the kd-tree to be present. */
506 t
= CalcClosestTownFromTile(fallback
);
511 static void ReadTTDPatchFlags()
513 if (_read_ttdpatch_flags
) return;
515 _read_ttdpatch_flags
= true;
517 /* Set default values */
518 _old_vehicle_multiplier
= 1;
520 _old_extra_chunk_nums
= 0;
521 _bump_assert_value
= 0;
523 if (_savegame_type
== SGT_TTO
) return;
525 /* TTDPatch misuses old map3 (now m3/m4) for flags.. read them! */
526 _old_vehicle_multiplier
= Tile(0).m3();
527 /* Somehow.... there was an error in some savegames, so 0 becomes 1
528 * and 1 becomes 2. The rest of the values are okay */
529 if (_old_vehicle_multiplier
< 2) _old_vehicle_multiplier
++;
531 _old_vehicle_names
= MallocT
<StringID
>(_old_vehicle_multiplier
* 850);
533 /* TTDPatch increases the Vehicle-part in the middle of the game,
534 * so if the multiplier is anything else but 1, the assert fails..
535 * bump the assert value so it doesn't!
536 * (1 multiplier == 850 vehicles
537 * 1 vehicle == 128 bytes */
538 _bump_assert_value
= (_old_vehicle_multiplier
- 1) * 850 * 128;
540 /* The first 17 bytes are used by TTDP1, which translates to the first 9 m3s and first 8 m4s. */
541 for (TileIndex i
= 0; i
<= 8; i
++) { // check tile 0, too
543 if (tile
.m3() != 0 || (i
!= 8 && tile
.m4() != 0)) _savegame_type
= SGT_TTDP1
;
546 /* Check if we have a modern TTDPatch savegame (has extra data all around) */
547 Tile
ttdp2_header_first(Map::Size() - 3);
548 Tile
ttdp2_header_second(Map::Size() - 2);
549 if (ttdp2_header_first
.m3() == 'T' && ttdp2_header_first
.m4() == 'T' &&
550 ttdp2_header_second
.m3() == 'D' && ttdp2_header_second
.m4() == 'p') {
551 _savegame_type
= SGT_TTDP2
;
554 Tile extra_chunk_tile
= Tile(_savegame_type
== SGT_TTDP2
? Map::Size() - 1 : 1);
555 _old_extra_chunk_nums
= extra_chunk_tile
.m3() | extra_chunk_tile
.m4() << 8;
557 /* Clean the misused places */
558 for (TileIndex i
= 0; i
< 9; i
++) ClearOldMap3(i
);
559 for (TileIndex i
= TileXY(0, Map::MaxY()); i
< Map::Size(); i
++) ClearOldMap3(i
);
561 if (_savegame_type
== SGT_TTDP2
) Debug(oldloader
, 2, "Found TTDPatch game");
563 Debug(oldloader
, 3, "Vehicle-multiplier is set to {} ({} vehicles)", _old_vehicle_multiplier
, _old_vehicle_multiplier
* 850);
566 static const OldChunks town_chunk
[] = {
567 OCL_SVAR( OC_TILE
, Town
, xy
),
568 OCL_NULL( 2 ), ///< population, no longer in use
569 OCL_SVAR( OC_UINT16
, Town
, townnametype
),
570 OCL_SVAR( OC_UINT32
, Town
, townnameparts
),
571 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Town
, grow_counter
),
572 OCL_NULL( 1 ), ///< sort_index, no longer in use
573 OCL_NULL( 4 ), ///< sign-coordinates, no longer in use
574 OCL_NULL( 2 ), ///< namewidth, no longer in use
575 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, Town
, flags
),
576 OCL_NULL( 10 ), ///< radius, no longer in use
578 OCL_SVAR( OC_INT16
, Town
, ratings
[0] ),
579 OCL_SVAR( OC_INT16
, Town
, ratings
[1] ),
580 OCL_SVAR( OC_INT16
, Town
, ratings
[2] ),
581 OCL_SVAR( OC_INT16
, Town
, ratings
[3] ),
582 OCL_SVAR( OC_INT16
, Town
, ratings
[4] ),
583 OCL_SVAR( OC_INT16
, Town
, ratings
[5] ),
584 OCL_SVAR( OC_INT16
, Town
, ratings
[6] ),
585 OCL_SVAR( OC_INT16
, Town
, ratings
[7] ),
587 OCL_SVAR( OC_FILE_U32
| OC_VAR_U16
, Town
, have_ratings
),
588 OCL_SVAR( OC_FILE_U32
| OC_VAR_U16
, Town
, statues
),
589 OCL_NULL( 2 ), ///< num_houses, no longer in use
590 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Town
, time_until_rebuild
),
591 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Town
, growth_rate
),
593 /* Slots 0 and 2 are passengers and mail respectively for old saves. */
594 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Town
, supplied
[0].new_max
),
595 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Town
, supplied
[2].new_max
),
596 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Town
, supplied
[0].new_act
),
597 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Town
, supplied
[2].new_act
),
598 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Town
, supplied
[0].old_max
),
599 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Town
, supplied
[2].old_max
),
600 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Town
, supplied
[0].old_act
),
601 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Town
, supplied
[2].old_act
),
603 OCL_NULL( 2 ), ///< pct_pass_transported / pct_mail_transported, now computed on the fly
605 OCL_SVAR( OC_TTD
| OC_UINT16
, Town
, received
[TAE_FOOD
].new_act
),
606 OCL_SVAR( OC_TTD
| OC_UINT16
, Town
, received
[TAE_WATER
].new_act
),
607 OCL_SVAR( OC_TTD
| OC_UINT16
, Town
, received
[TAE_FOOD
].old_act
),
608 OCL_SVAR( OC_TTD
| OC_UINT16
, Town
, received
[TAE_WATER
].old_act
),
610 OCL_SVAR( OC_UINT8
, Town
, road_build_months
),
611 OCL_SVAR( OC_UINT8
, Town
, fund_buildings_months
),
613 OCL_CNULL( OC_TTD
, 8 ), ///< some junk at the end of the record
618 static bool LoadOldTown(LoadgameState
*ls
, int num
)
620 Town
*t
= new (num
) Town();
621 if (!LoadChunk(ls
, t
, town_chunk
)) return false;
624 if (_savegame_type
== SGT_TTO
) {
625 /* 0x10B6 is auto-generated name, others are custom names */
626 t
->townnametype
= t
->townnametype
== 0x10B6 ? 0x20C1 : t
->townnametype
+ 0x2A00;
635 static uint16_t _old_order
;
636 static const OldChunks order_chunk
[] = {
637 OCL_VAR ( OC_UINT16
, 1, &_old_order
),
641 static bool LoadOldOrder(LoadgameState
*ls
, int num
)
643 if (!LoadChunk(ls
, nullptr, order_chunk
)) return false;
645 Order
*o
= new (num
) Order();
646 o
->AssignOrder(UnpackOldOrder(_old_order
));
648 if (o
->IsType(OT_NOTHING
)) {
651 /* Relink the orders to each other (in the orders for one vehicle are behind each other,
652 * with an invalid order (OT_NOTHING) as indication that it is the last order */
653 Order
*prev
= Order::GetIfValid(num
- 1);
654 if (prev
!= nullptr) prev
->next
= o
;
660 static bool LoadOldAnimTileList(LoadgameState
*ls
, int)
662 TileIndex anim_list
[256];
663 const OldChunks anim_chunk
[] = {
664 OCL_VAR ( OC_TILE
, 256, anim_list
),
668 if (!LoadChunk(ls
, nullptr, anim_chunk
)) return false;
670 /* The first zero in the loaded array indicates the end of the list. */
671 for (int i
= 0; i
< 256; i
++) {
672 if (anim_list
[i
] == 0) break;
673 _animated_tiles
.push_back(anim_list
[i
]);
679 static const OldChunks depot_chunk
[] = {
680 OCL_SVAR( OC_TILE
, Depot
, xy
),
681 OCL_VAR ( OC_UINT32
, 1, &_old_town_index
),
685 static bool LoadOldDepot(LoadgameState
*ls
, int num
)
687 Depot
*d
= new (num
) Depot();
688 if (!LoadChunk(ls
, d
, depot_chunk
)) return false;
691 d
->town
= RemapTown(d
->xy
);
699 static StationID _current_station_id
;
700 static uint16_t _waiting_acceptance
;
701 static uint8_t _cargo_source
;
702 static uint8_t _cargo_periods
;
704 static const OldChunks goods_chunk
[] = {
705 OCL_VAR ( OC_UINT16
, 1, &_waiting_acceptance
),
706 OCL_SVAR( OC_UINT8
, GoodsEntry
, time_since_pickup
),
707 OCL_SVAR( OC_UINT8
, GoodsEntry
, rating
),
708 OCL_VAR ( OC_UINT8
, 1, &_cargo_source
),
709 OCL_VAR ( OC_UINT8
, 1, &_cargo_periods
),
710 OCL_SVAR( OC_UINT8
, GoodsEntry
, last_speed
),
711 OCL_SVAR( OC_UINT8
, GoodsEntry
, last_age
),
716 static bool LoadOldGood(LoadgameState
*ls
, int num
)
718 /* for TTO games, 12th (num == 11) goods entry is created in the Station constructor */
719 if (_savegame_type
== SGT_TTO
&& num
== 11) return true;
721 Station
*st
= Station::Get(_current_station_id
);
722 GoodsEntry
*ge
= &st
->goods
[num
];
724 if (!LoadChunk(ls
, ge
, goods_chunk
)) return false;
726 AssignBit(ge
->status
, GoodsEntry::GES_ACCEPTANCE
, HasBit(_waiting_acceptance
, 15));
727 AssignBit(ge
->status
, GoodsEntry::GES_RATING
, _cargo_source
!= 0xFF);
728 if (GB(_waiting_acceptance
, 0, 12) != 0 && CargoPacket::CanAllocateItem()) {
729 ge
->cargo
.Append(new CargoPacket(GB(_waiting_acceptance
, 0, 12), _cargo_periods
, (_cargo_source
== 0xFF) ? INVALID_STATION
: _cargo_source
, INVALID_TILE
, 0),
736 static const OldChunks station_chunk
[] = {
737 OCL_SVAR( OC_TILE
, Station
, xy
),
738 OCL_VAR ( OC_UINT32
, 1, &_old_town_index
),
740 OCL_NULL( 4 ), ///< bus/lorry tile
741 OCL_SVAR( OC_TILE
, Station
, train_station
.tile
),
742 OCL_SVAR( OC_TILE
, Station
, airport
.tile
),
743 OCL_NULL( 2 ), ///< dock tile
744 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Station
, train_station
.w
),
746 OCL_NULL( 1 ), ///< sort-index, no longer in use
747 OCL_NULL( 2 ), ///< sign-width, no longer in use
749 OCL_VAR ( OC_UINT16
, 1, &_old_string_id
),
751 OCL_NULL( 4 ), ///< sign left/top, no longer in use
753 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, Station
, had_vehicle_of_type
),
755 OCL_CHUNK( 12, LoadOldGood
),
757 OCL_SVAR( OC_UINT8
, Station
, time_since_load
),
758 OCL_SVAR( OC_UINT8
, Station
, time_since_unload
),
759 OCL_SVAR( OC_UINT8
, Station
, delete_ctr
),
760 OCL_SVAR( OC_UINT8
, Station
, owner
),
761 OCL_SVAR( OC_UINT8
, Station
, facilities
),
762 OCL_SVAR( OC_TTD
| OC_UINT8
, Station
, airport
.type
),
763 OCL_SVAR( OC_TTO
| OC_FILE_U16
| OC_VAR_U64
, Station
, airport
.flags
),
764 OCL_NULL( 3 ), ///< bus/truck status, blocked months, no longer in use
765 OCL_CNULL( OC_TTD
, 1 ), ///< unknown
766 OCL_SVAR( OC_TTD
| OC_FILE_U16
| OC_VAR_U64
, Station
, airport
.flags
),
767 OCL_CNULL( OC_TTD
, 2 ), ///< last_vehicle. now last_vehicle_type
768 OCL_CNULL( OC_TTD
, 4 ), ///< junk at end of chunk
773 static bool LoadOldStation(LoadgameState
*ls
, int num
)
775 Station
*st
= new (num
) Station();
776 _current_station_id
= num
;
778 if (!LoadChunk(ls
, st
, station_chunk
)) return false;
781 st
->town
= RemapTown(st
->xy
);
783 if (_savegame_type
== SGT_TTO
) {
784 if (IsInsideBS(_old_string_id
, 0x180F, 32)) {
785 st
->string_id
= STR_SV_STNAME
+ (_old_string_id
- 0x180F); // automatic name
787 st
->string_id
= _old_string_id
+ 0x2800; // custom name
790 if (HasBit(st
->airport
.flags
, 8)) {
791 st
->airport
.type
= 1; // large airport
792 } else if (HasBit(st
->airport
.flags
, 6)) {
793 st
->airport
.type
= 3; // oil rig
795 st
->airport
.type
= 0; // small airport
798 st
->string_id
= RemapOldStringID(_old_string_id
);
807 /* Old save games always have 3 input and 2 output slots per industry. */
808 static std::array
<Industry::AcceptedCargo
, INDUSTRY_ORIGINAL_NUM_INPUTS
> _old_accepted
{};
809 static std::array
<Industry::ProducedCargo
, INDUSTRY_ORIGINAL_NUM_OUTPUTS
> _old_produced
{};
811 static const OldChunks industry_chunk
[] = {
812 OCL_SVAR( OC_TILE
, Industry
, location
.tile
),
813 OCL_VAR ( OC_UINT32
, 1, &_old_town_index
),
814 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Industry
, location
.w
),
815 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Industry
, location
.h
),
816 OCL_NULL( 2 ), ///< used to be industry's produced_cargo
818 OCL_VAR( OC_TTD
| OC_UINT16
, 1, &_old_produced
[0].waiting
),
819 OCL_VAR( OC_TTD
| OC_UINT16
, 1, &_old_produced
[1].waiting
),
820 OCL_VAR( OC_TTO
| OC_FILE_U8
| OC_VAR_U16
, 1, &_old_produced
[0].waiting
),
821 OCL_VAR( OC_TTO
| OC_FILE_U8
| OC_VAR_U16
, 1, &_old_produced
[1].waiting
),
823 OCL_VAR( OC_UINT8
, 1, &_old_produced
[0].rate
),
824 OCL_VAR( OC_UINT8
, 1, &_old_produced
[1].rate
),
826 OCL_NULL( 3 ), ///< used to be industry's accepts_cargo
828 OCL_SVAR( OC_UINT8
, Industry
, prod_level
),
830 OCL_VAR( OC_UINT16
, 1, &_old_produced
[0].history
[THIS_MONTH
].production
),
831 OCL_VAR( OC_UINT16
, 1, &_old_produced
[1].history
[THIS_MONTH
].production
),
832 OCL_VAR( OC_UINT16
, 1, &_old_produced
[0].history
[THIS_MONTH
].transported
),
833 OCL_VAR( OC_UINT16
, 1, &_old_produced
[1].history
[THIS_MONTH
].transported
),
835 OCL_NULL( 2 ), ///< last_month_pct_transported, now computed on the fly
837 OCL_VAR( OC_UINT16
, 1, &_old_produced
[0].history
[LAST_MONTH
].production
),
838 OCL_VAR( OC_UINT16
, 1, &_old_produced
[1].history
[LAST_MONTH
].production
),
839 OCL_VAR( OC_UINT16
, 1, &_old_produced
[0].history
[LAST_MONTH
].transported
),
840 OCL_VAR( OC_UINT16
, 1, &_old_produced
[1].history
[LAST_MONTH
].transported
),
842 OCL_SVAR( OC_UINT8
, Industry
, type
),
843 OCL_SVAR( OC_TTO
| OC_FILE_U8
| OC_VAR_U16
, Industry
, counter
),
844 OCL_SVAR( OC_UINT8
, Industry
, owner
),
845 OCL_SVAR( OC_UINT8
, Industry
, random_colour
),
846 OCL_SVAR( OC_TTD
| OC_FILE_U8
| OC_VAR_I32
, Industry
, last_prod_year
),
847 OCL_SVAR( OC_TTD
| OC_UINT16
, Industry
, counter
),
848 OCL_SVAR( OC_TTD
| OC_UINT8
, Industry
, was_cargo_delivered
),
850 OCL_CNULL( OC_TTD
, 9 ), ///< Random junk at the end of this chunk
855 static bool LoadOldIndustry(LoadgameState
*ls
, int num
)
857 Industry
*i
= new (num
) Industry();
858 if (!LoadChunk(ls
, i
, industry_chunk
)) return false;
860 if (i
->location
.tile
!= 0) {
861 /* Copy data from old fixed arrays to industry. */
862 std::copy(std::begin(_old_accepted
), std::end(_old_accepted
), std::back_inserter(i
->accepted
));
863 std::copy(std::begin(_old_produced
), std::end(_old_produced
), std::back_inserter(i
->produced
));
865 i
->town
= RemapTown(i
->location
.tile
);
867 if (_savegame_type
== SGT_TTO
) {
868 if (i
->type
> 0x06) i
->type
++; // Printing Works were added
869 if (i
->type
== 0x0A) i
->type
= 0x12; // Iron Ore Mine has different ID
871 TimerGameEconomy::YearMonthDay ymd
= TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date
);
872 i
->last_prod_year
= ymd
.year
;
874 i
->random_colour
= RemapTTOColour(i
->random_colour
);
877 Industry::IncIndustryTypeCount(i
->type
);
885 static CompanyID _current_company_id
;
886 static int32_t _old_yearly
;
888 static const OldChunks _company_yearly_chunk
[] = {
889 OCL_VAR( OC_INT32
, 1, &_old_yearly
),
893 static bool LoadOldCompanyYearly(LoadgameState
*ls
, int num
)
895 Company
*c
= Company::Get(_current_company_id
);
897 for (uint i
= 0; i
< 13; i
++) {
898 if (_savegame_type
== SGT_TTO
&& i
== 6) {
899 _old_yearly
= 0; // property maintenance
901 if (!LoadChunk(ls
, nullptr, _company_yearly_chunk
)) return false;
904 c
->yearly_expenses
[num
][i
] = _old_yearly
;
910 static const OldChunks _company_economy_chunk
[] = {
911 OCL_SVAR( OC_FILE_I32
| OC_VAR_I64
, CompanyEconomyEntry
, income
),
912 OCL_SVAR( OC_FILE_I32
| OC_VAR_I64
, CompanyEconomyEntry
, expenses
),
913 OCL_SVAR( OC_INT32
, CompanyEconomyEntry
, delivered_cargo
[NUM_CARGO
- 1] ),
914 OCL_SVAR( OC_INT32
, CompanyEconomyEntry
, performance_history
),
915 OCL_SVAR( OC_TTD
| OC_FILE_I32
| OC_VAR_I64
, CompanyEconomyEntry
, company_value
),
920 static bool LoadOldCompanyEconomy(LoadgameState
*ls
, int)
922 Company
*c
= Company::Get(_current_company_id
);
924 if (!LoadChunk(ls
, &c
->cur_economy
, _company_economy_chunk
)) return false;
926 /* Don't ask, but the number in TTD(Patch) are inversed to OpenTTD */
927 c
->cur_economy
.income
= -c
->cur_economy
.income
;
928 c
->cur_economy
.expenses
= -c
->cur_economy
.expenses
;
930 for (uint i
= 0; i
< 24; i
++) {
931 if (!LoadChunk(ls
, &c
->old_economy
[i
], _company_economy_chunk
)) return false;
933 c
->old_economy
[i
].income
= -c
->old_economy
[i
].income
;
934 c
->old_economy
[i
].expenses
= -c
->old_economy
[i
].expenses
;
940 static const OldChunks _company_chunk
[] = {
941 OCL_VAR ( OC_UINT16
, 1, &_old_string_id
),
942 OCL_SVAR( OC_UINT32
, Company
, name_2
),
943 OCL_SVAR( OC_UINT32
, Company
, face
),
944 OCL_VAR ( OC_UINT16
, 1, &_old_string_id_2
),
945 OCL_SVAR( OC_UINT32
, Company
, president_name_2
),
947 OCL_SVAR( OC_FILE_I32
| OC_VAR_I64
, Company
, money
),
948 OCL_SVAR( OC_FILE_I32
| OC_VAR_I64
, Company
, current_loan
),
950 OCL_SVAR( OC_UINT8
, Company
, colour
),
951 OCL_SVAR( OC_UINT8
, Company
, money_fraction
),
952 OCL_SVAR( OC_UINT8
, Company
, months_of_bankruptcy
),
953 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Company
, bankrupt_asked
),
954 OCL_SVAR( OC_FILE_U32
| OC_VAR_I64
, Company
, bankrupt_value
),
955 OCL_SVAR( OC_UINT16
, Company
, bankrupt_timeout
),
957 OCL_CNULL( OC_TTD
, 4 ), // cargo_types
958 OCL_CNULL( OC_TTO
, 2 ), // cargo_types
960 OCL_CHUNK( 3, LoadOldCompanyYearly
),
961 OCL_CHUNK( 1, LoadOldCompanyEconomy
),
963 OCL_SVAR( OC_FILE_U16
| OC_VAR_I32
, Company
, inaugurated_year
),
964 OCL_SVAR( OC_TILE
, Company
, last_build_coordinate
),
965 OCL_SVAR( OC_UINT8
, Company
, num_valid_stat_ent
),
967 OCL_NULL( 230 ), // Old AI
969 OCL_SVAR( OC_UINT8
, Company
, block_preview
),
970 OCL_CNULL( OC_TTD
, 1 ), // Old AI
971 OCL_CNULL( OC_TTD
, 1 ), // avail_railtypes
972 OCL_SVAR( OC_TILE
, Company
, location_of_HQ
),
974 OCL_CNULL( OC_TTD
, 4 ), // Shares
976 OCL_CNULL( OC_TTD
, 8 ), // junk at end of chunk
981 static bool LoadOldCompany(LoadgameState
*ls
, int num
)
983 Company
*c
= new (num
) Company();
985 _current_company_id
= (CompanyID
)num
;
987 if (!LoadChunk(ls
, c
, _company_chunk
)) return false;
989 if (_old_string_id
== 0) {
994 if (_savegame_type
== SGT_TTO
) {
995 /* adjust manager's face */
996 if (HasBit(c
->face
, 27) && GB(c
->face
, 26, 1) == GB(c
->face
, 19, 1)) {
997 /* if face would be black in TTD, adjust tie colour and thereby face colour */
1002 if (_old_string_id
== 0 || _old_string_id
== 0x4C00) {
1003 _old_string_id
= STR_SV_UNNAMED
; // "Unnamed"
1004 } else if (GB(_old_string_id
, 8, 8) == 0x52) {
1005 _old_string_id
+= 0x2A00; // Custom name
1007 _old_string_id
= RemapOldStringID(_old_string_id
+= 0x240D); // Automatic name
1009 c
->name_1
= _old_string_id
;
1012 switch (_old_string_id_2
) {
1013 case 0x4CDA: _old_string_id_2
= SPECSTR_PRESIDENT_NAME
; break; // automatic name
1014 case 0x0006: _old_string_id_2
= STR_SV_EMPTY
; break; // empty name
1015 default: _old_string_id_2
= _old_string_id_2
+ 0x2A00; break; // custom name
1017 c
->president_name_1
= _old_string_id_2
;
1019 c
->colour
= RemapTTOColour(c
->colour
);
1021 if (num
!= 0) c
->is_ai
= true;
1023 c
->name_1
= RemapOldStringID(_old_string_id
);
1024 c
->president_name_1
= RemapOldStringID(_old_string_id_2
);
1027 /* If the first company has no name, make sure we call it UNNAMED */
1028 if (c
->name_1
== 0) {
1029 c
->name_1
= STR_SV_UNNAMED
;
1032 /* Beside some multiplayer maps (1 on 1), which we don't official support,
1033 * all other companies are an AI.. mark them as such */
1037 /* Sometimes it is better to not ask.. in old scenarios, the money
1038 * was always 893288 pounds. In the newer versions this is correct,
1039 * but correct for those oldies
1040 * Ps: this also means that if you had exact 893288 pounds, you will go back
1041 * to 100000.. this is a very VERY small chance ;) */
1042 if (c
->money
== 893288) c
->money
= c
->current_loan
= 100000;
1045 _company_colours
[num
] = c
->colour
;
1046 c
->inaugurated_year
-= EconomyTime::ORIGINAL_BASE_YEAR
;
1051 static uint32_t _old_order_ptr
;
1052 static uint16_t _old_next_ptr
;
1053 static VehicleID _current_vehicle_id
;
1055 static const OldChunks vehicle_train_chunk
[] = {
1056 OCL_SVAR( OC_UINT8
, Train
, track
),
1057 OCL_SVAR( OC_UINT8
, Train
, force_proceed
),
1058 OCL_SVAR( OC_UINT16
, Train
, crash_anim_pos
),
1059 OCL_SVAR( OC_UINT8
, Train
, railtype
),
1061 OCL_NULL( 5 ), ///< Junk
1066 static const OldChunks vehicle_road_chunk
[] = {
1067 OCL_SVAR( OC_UINT8
, RoadVehicle
, state
),
1068 OCL_SVAR( OC_UINT8
, RoadVehicle
, frame
),
1069 OCL_SVAR( OC_UINT16
, RoadVehicle
, blocked_ctr
),
1070 OCL_SVAR( OC_UINT8
, RoadVehicle
, overtaking
),
1071 OCL_SVAR( OC_UINT8
, RoadVehicle
, overtaking_ctr
),
1072 OCL_SVAR( OC_UINT16
, RoadVehicle
, crashed_ctr
),
1073 OCL_SVAR( OC_UINT8
, RoadVehicle
, reverse_ctr
),
1075 OCL_NULL( 1 ), ///< Junk
1080 static const OldChunks vehicle_ship_chunk
[] = {
1081 OCL_SVAR( OC_UINT8
, Ship
, state
),
1083 OCL_NULL( 9 ), ///< Junk
1088 static const OldChunks vehicle_air_chunk
[] = {
1089 OCL_SVAR( OC_UINT8
, Aircraft
, pos
),
1090 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Aircraft
, targetairport
),
1091 OCL_SVAR( OC_UINT16
, Aircraft
, crashed_counter
),
1092 OCL_SVAR( OC_UINT8
, Aircraft
, state
),
1094 OCL_NULL( 5 ), ///< Junk
1099 static const OldChunks vehicle_effect_chunk
[] = {
1100 OCL_SVAR( OC_UINT16
, EffectVehicle
, animation_state
),
1101 OCL_SVAR( OC_UINT8
, EffectVehicle
, animation_substate
),
1103 OCL_NULL( 7 ), // Junk
1108 static const OldChunks vehicle_disaster_chunk
[] = {
1109 OCL_SVAR( OC_UINT16
, DisasterVehicle
, image_override
),
1110 OCL_SVAR( OC_UINT16
, DisasterVehicle
, big_ufo_destroyer_target
),
1112 OCL_NULL( 6 ), ///< Junk
1117 static const OldChunks vehicle_empty_chunk
[] = {
1118 OCL_NULL( 10 ), ///< Junk
1123 static bool LoadOldVehicleUnion(LoadgameState
*ls
, int)
1125 Vehicle
*v
= Vehicle::GetIfValid(_current_vehicle_id
);
1126 uint temp
= ls
->total_read
;
1130 res
= LoadChunk(ls
, nullptr, vehicle_empty_chunk
);
1133 default: SlErrorCorrupt("Invalid vehicle type");
1134 case VEH_TRAIN
: res
= LoadChunk(ls
, v
, vehicle_train_chunk
); break;
1135 case VEH_ROAD
: res
= LoadChunk(ls
, v
, vehicle_road_chunk
); break;
1136 case VEH_SHIP
: res
= LoadChunk(ls
, v
, vehicle_ship_chunk
); break;
1137 case VEH_AIRCRAFT
: res
= LoadChunk(ls
, v
, vehicle_air_chunk
); break;
1138 case VEH_EFFECT
: res
= LoadChunk(ls
, v
, vehicle_effect_chunk
); break;
1139 case VEH_DISASTER
: res
= LoadChunk(ls
, v
, vehicle_disaster_chunk
); break;
1143 /* This chunk size should always be 10 bytes */
1144 if (ls
->total_read
- temp
!= 10) {
1145 Debug(oldloader
, 0, "Assert failed in VehicleUnion: invalid chunk size");
1152 static uint16_t _cargo_count
;
1154 static const OldChunks vehicle_chunk
[] = {
1155 OCL_SVAR( OC_UINT8
, Vehicle
, subtype
),
1157 OCL_NULL( 2 ), ///< Hash, calculated automatically
1158 OCL_NULL( 2 ), ///< Index, calculated automatically
1160 OCL_VAR ( OC_UINT32
, 1, &_old_order_ptr
),
1161 OCL_VAR ( OC_UINT16
, 1, &_old_order
),
1163 OCL_NULL ( 1 ), ///< num_orders, now calculated
1164 OCL_SVAR( OC_UINT8
, Vehicle
, cur_implicit_order_index
),
1165 OCL_SVAR( OC_TILE
, Vehicle
, dest_tile
),
1166 OCL_SVAR( OC_UINT16
, Vehicle
, load_unload_ticks
),
1167 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Vehicle
, date_of_last_service
),
1168 OCL_SVAR( OC_UINT16
, Vehicle
, service_interval
),
1169 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Vehicle
, last_station_visited
),
1170 OCL_SVAR( OC_TTD
| OC_UINT8
, Vehicle
, tick_counter
),
1171 OCL_CNULL( OC_TTD
, 2 ), ///< max_speed, now it is calculated.
1172 OCL_CNULL( OC_TTO
, 1 ), ///< max_speed, now it is calculated.
1174 OCL_SVAR( OC_FILE_U16
| OC_VAR_I32
, Vehicle
, x_pos
),
1175 OCL_SVAR( OC_FILE_U16
| OC_VAR_I32
, Vehicle
, y_pos
),
1176 OCL_SVAR( OC_FILE_U8
| OC_VAR_I32
, Vehicle
, z_pos
),
1177 OCL_SVAR( OC_UINT8
, Vehicle
, direction
),
1178 OCL_NULL( 2 ), ///< x_offs and y_offs, calculated automatically
1179 OCL_NULL( 2 ), ///< x_extent and y_extent, calculated automatically
1180 OCL_NULL( 1 ), ///< z_extent, calculated automatically
1182 OCL_SVAR( OC_UINT8
, Vehicle
, owner
),
1183 OCL_SVAR( OC_TILE
, Vehicle
, tile
),
1184 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Vehicle
, sprite_cache
.sprite_seq
.seq
[0].sprite
),
1186 OCL_NULL( 8 ), ///< Vehicle sprite box, calculated automatically
1188 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, Vehicle
, vehstatus
),
1189 OCL_SVAR( OC_TTD
| OC_UINT16
, Vehicle
, cur_speed
),
1190 OCL_SVAR( OC_TTO
| OC_FILE_U8
| OC_VAR_U16
, Vehicle
, cur_speed
),
1191 OCL_SVAR( OC_UINT8
, Vehicle
, subspeed
),
1192 OCL_SVAR( OC_UINT8
, Vehicle
, acceleration
),
1193 OCL_SVAR( OC_UINT8
, Vehicle
, progress
),
1195 OCL_SVAR( OC_UINT8
, Vehicle
, cargo_type
),
1196 OCL_SVAR( OC_TTD
| OC_UINT16
, Vehicle
, cargo_cap
),
1197 OCL_SVAR( OC_TTO
| OC_FILE_U8
| OC_VAR_U16
, Vehicle
, cargo_cap
),
1198 OCL_VAR ( OC_TTD
| OC_UINT16
, 1, &_cargo_count
),
1199 OCL_VAR ( OC_TTO
| OC_FILE_U8
| OC_VAR_U16
, 1, &_cargo_count
),
1200 OCL_VAR ( OC_UINT8
, 1, &_cargo_source
),
1201 OCL_VAR ( OC_UINT8
, 1, &_cargo_periods
),
1203 OCL_SVAR( OC_TTO
| OC_UINT8
, Vehicle
, tick_counter
),
1205 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Vehicle
, age
),
1206 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Vehicle
, max_age
),
1207 OCL_SVAR( OC_FILE_U8
| OC_VAR_I32
, Vehicle
, build_year
),
1208 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Vehicle
, unitnumber
),
1210 OCL_SVAR( OC_TTD
| OC_UINT16
, Vehicle
, engine_type
),
1211 OCL_SVAR( OC_TTO
| OC_FILE_U8
| OC_VAR_U16
, Vehicle
, engine_type
),
1213 OCL_SVAR( OC_UINT8
, Vehicle
, spritenum
),
1214 OCL_SVAR( OC_UINT8
, Vehicle
, day_counter
),
1216 OCL_SVAR( OC_UINT8
, Vehicle
, breakdowns_since_last_service
),
1217 OCL_SVAR( OC_UINT8
, Vehicle
, breakdown_ctr
),
1218 OCL_SVAR( OC_UINT8
, Vehicle
, breakdown_delay
),
1219 OCL_SVAR( OC_UINT8
, Vehicle
, breakdown_chance
),
1221 OCL_CNULL( OC_TTO
, 1 ),
1223 OCL_SVAR( OC_UINT16
, Vehicle
, reliability
),
1224 OCL_SVAR( OC_UINT16
, Vehicle
, reliability_spd_dec
),
1226 OCL_SVAR( OC_FILE_I32
| OC_VAR_I64
, Vehicle
, profit_this_year
),
1227 OCL_SVAR( OC_FILE_I32
| OC_VAR_I64
, Vehicle
, profit_last_year
),
1229 OCL_VAR ( OC_UINT16
, 1, &_old_next_ptr
),
1231 OCL_SVAR( OC_FILE_U32
| OC_VAR_I64
, Vehicle
, value
),
1233 OCL_VAR ( OC_UINT16
, 1, &_old_string_id
),
1235 OCL_CHUNK( 1, LoadOldVehicleUnion
),
1237 OCL_CNULL( OC_TTO
, 24 ), ///< junk
1238 OCL_CNULL( OC_TTD
, 20 ), ///< junk at end of struct (TTDPatch has some data in it)
1244 * Load the vehicles of an old style savegame.
1245 * @param ls State (buffer) of the currently loaded game.
1246 * @param num The number of vehicles to load.
1247 * @return True iff loading went without problems.
1249 bool LoadOldVehicle(LoadgameState
*ls
, int num
)
1251 /* Read the TTDPatch flags, because we need some info from it */
1252 ReadTTDPatchFlags();
1254 for (uint i
= 0; i
< _old_vehicle_multiplier
; i
++) {
1255 _current_vehicle_id
= num
* _old_vehicle_multiplier
+ i
;
1259 if (_savegame_type
== SGT_TTO
) {
1260 uint type
= ReadByte(ls
);
1262 default: return false;
1263 case 0x00 /* VEH_INVALID */: v
= nullptr; break;
1264 case 0x25 /* MONORAIL */:
1265 case 0x20 /* VEH_TRAIN */: v
= new (_current_vehicle_id
) Train(); break;
1266 case 0x21 /* VEH_ROAD */: v
= new (_current_vehicle_id
) RoadVehicle(); break;
1267 case 0x22 /* VEH_SHIP */: v
= new (_current_vehicle_id
) Ship(); break;
1268 case 0x23 /* VEH_AIRCRAFT */: v
= new (_current_vehicle_id
) Aircraft(); break;
1269 case 0x24 /* VEH_EFFECT */: v
= new (_current_vehicle_id
) EffectVehicle(); break;
1270 case 0x26 /* VEH_DISASTER */: v
= new (_current_vehicle_id
) DisasterVehicle(); break;
1273 if (!LoadChunk(ls
, v
, vehicle_chunk
)) return false;
1274 if (v
== nullptr) continue;
1275 v
->refit_cap
= v
->cargo_cap
;
1277 SpriteID sprite
= v
->sprite_cache
.sprite_seq
.seq
[0].sprite
;
1278 /* no need to override other sprites */
1279 if (IsInsideMM(sprite
, 1460, 1465)) {
1280 sprite
+= 580; // aircraft smoke puff
1281 } else if (IsInsideMM(sprite
, 2096, 2115)) {
1282 sprite
+= 977; // special effects part 1
1283 } else if (IsInsideMM(sprite
, 2396, 2436)) {
1284 sprite
+= 1305; // special effects part 2
1285 } else if (IsInsideMM(sprite
, 2516, 2539)) {
1286 sprite
+= 1385; // rotor or disaster-related vehicles
1288 v
->sprite_cache
.sprite_seq
.seq
[0].sprite
= sprite
;
1292 static const uint8_t spriteset_rail
[] = {
1293 0, 2, 4, 4, 8, 10, 12, 14, 16, 18, 20, 22, 40, 42, 44, 46,
1294 48, 52, 54, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 120, 122,
1295 124, 126, 128, 130, 132, 134, 136, 138, 140
1297 if (v
->spritenum
/ 2 >= lengthof(spriteset_rail
)) return false;
1298 v
->spritenum
= spriteset_rail
[v
->spritenum
/ 2]; // adjust railway sprite set offset
1299 /* Should be the original values for monorail / rail, can't use RailType constants */
1300 Train::From(v
)->railtype
= static_cast<RailType
>(type
== 0x25 ? 1 : 0);
1305 if (v
->spritenum
>= 22) v
->spritenum
+= 12;
1311 switch (v
->spritenum
) {
1312 case 2: // oil tanker && cargo type != oil
1313 if (v
->cargo_type
!= 3) v
->spritenum
= 0; // make it a coal/goods ship
1315 case 4: // passenger ship && cargo type == mail
1316 if (v
->cargo_type
== 2) v
->spritenum
= 0; // make it a mail ship
1327 switch (_old_string_id
) {
1328 case 0x0000: break; // empty (invalid vehicles)
1329 case 0x0006: _old_string_id
= STR_SV_EMPTY
; break; // empty (special vehicles)
1330 case 0x8495: _old_string_id
= STR_SV_TRAIN_NAME
; break; // "Train X"
1331 case 0x8842: _old_string_id
= STR_SV_ROAD_VEHICLE_NAME
; break; // "Road Vehicle X"
1332 case 0x8C3B: _old_string_id
= STR_SV_SHIP_NAME
; break; // "Ship X"
1333 case 0x9047: _old_string_id
= STR_SV_AIRCRAFT_NAME
; break; // "Aircraft X"
1334 default: _old_string_id
+= 0x2A00; break; // custom name
1337 _old_vehicle_names
[_current_vehicle_id
] = _old_string_id
;
1339 /* Read the vehicle type and allocate the right vehicle */
1340 switch (ReadByte(ls
)) {
1341 default: SlErrorCorrupt("Invalid vehicle type");
1342 case 0x00 /* VEH_INVALID */: v
= nullptr; break;
1343 case 0x10 /* VEH_TRAIN */: v
= new (_current_vehicle_id
) Train(); break;
1344 case 0x11 /* VEH_ROAD */: v
= new (_current_vehicle_id
) RoadVehicle(); break;
1345 case 0x12 /* VEH_SHIP */: v
= new (_current_vehicle_id
) Ship(); break;
1346 case 0x13 /* VEH_AIRCRAFT*/: v
= new (_current_vehicle_id
) Aircraft(); break;
1347 case 0x14 /* VEH_EFFECT */: v
= new (_current_vehicle_id
) EffectVehicle(); break;
1348 case 0x15 /* VEH_DISASTER*/: v
= new (_current_vehicle_id
) DisasterVehicle(); break;
1351 if (!LoadChunk(ls
, v
, vehicle_chunk
)) return false;
1352 if (v
== nullptr) continue;
1354 _old_vehicle_names
[_current_vehicle_id
] = RemapOldStringID(_old_string_id
);
1356 /* This should be consistent, else we have a big problem... */
1357 if (v
->index
!= _current_vehicle_id
) {
1358 Debug(oldloader
, 0, "Loading failed - vehicle-array is invalid");
1363 if (_old_order_ptr
!= 0 && _old_order_ptr
!= 0xFFFFFFFF) {
1364 uint max
= _savegame_type
== SGT_TTO
? 3000 : 5000;
1365 uint old_id
= RemapOrderIndex(_old_order_ptr
);
1366 if (old_id
< max
) v
->old_orders
= Order::Get(old_id
); // don't accept orders > max number of orders
1368 v
->current_order
.AssignOrder(UnpackOldOrder(_old_order
));
1370 if (v
->type
== VEH_DISASTER
) {
1371 DisasterVehicle::From(v
)->state
= UnpackOldOrder(_old_order
).GetDestination();
1374 v
->next
= (Vehicle
*)(size_t)_old_next_ptr
;
1376 if (_cargo_count
!= 0 && CargoPacket::CanAllocateItem()) {
1377 StationID source
= (_cargo_source
== 0xFF) ? INVALID_STATION
: _cargo_source
;
1378 TileIndex source_xy
= (source
!= INVALID_STATION
) ? Station::Get(source
)->xy
: (TileIndex
)0;
1379 v
->cargo
.Append(new CargoPacket(_cargo_count
, _cargo_periods
, source
, source_xy
, 0));
1386 static const OldChunks sign_chunk
[] = {
1387 OCL_VAR ( OC_UINT16
, 1, &_old_string_id
),
1388 OCL_SVAR( OC_FILE_U16
| OC_VAR_I32
, Sign
, x
),
1389 OCL_SVAR( OC_FILE_U16
| OC_VAR_I32
, Sign
, y
),
1390 OCL_SVAR( OC_FILE_U16
| OC_VAR_I8
, Sign
, z
),
1392 OCL_NULL( 6 ), ///< Width of sign, no longer in use
1397 static bool LoadOldSign(LoadgameState
*ls
, int num
)
1399 Sign
*si
= new (num
) Sign();
1400 if (!LoadChunk(ls
, si
, sign_chunk
)) return false;
1402 if (_old_string_id
!= 0) {
1403 if (_savegame_type
== SGT_TTO
) {
1404 if (_old_string_id
!= 0x140A) si
->name
= CopyFromOldName(_old_string_id
+ 0x2A00);
1406 si
->name
= CopyFromOldName(RemapOldStringID(_old_string_id
));
1408 si
->owner
= OWNER_NONE
;
1416 static const OldChunks engine_chunk
[] = {
1417 OCL_SVAR( OC_UINT16
, Engine
, company_avail
),
1418 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Engine
, intro_date
),
1419 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, Engine
, age
),
1420 OCL_SVAR( OC_UINT16
, Engine
, reliability
),
1421 OCL_SVAR( OC_UINT16
, Engine
, reliability_spd_dec
),
1422 OCL_SVAR( OC_UINT16
, Engine
, reliability_start
),
1423 OCL_SVAR( OC_UINT16
, Engine
, reliability_max
),
1424 OCL_SVAR( OC_UINT16
, Engine
, reliability_final
),
1425 OCL_SVAR( OC_UINT16
, Engine
, duration_phase_1
),
1426 OCL_SVAR( OC_UINT16
, Engine
, duration_phase_2
),
1427 OCL_SVAR( OC_UINT16
, Engine
, duration_phase_3
),
1429 OCL_NULL( 1 ), // lifelength
1430 OCL_SVAR( OC_UINT8
, Engine
, flags
),
1431 OCL_NULL( 1 ), // preview_company_rank
1432 OCL_SVAR( OC_UINT8
, Engine
, preview_wait
),
1434 OCL_CNULL( OC_TTD
, 2 ), ///< railtype + junk
1439 static bool LoadOldEngine(LoadgameState
*ls
, int num
)
1441 Engine
*e
= _savegame_type
== SGT_TTO
? &_old_engines
[num
] : GetTempDataEngine(num
);
1442 return LoadChunk(ls
, e
, engine_chunk
);
1445 static bool LoadOldEngineName(LoadgameState
*ls
, int num
)
1447 Engine
*e
= GetTempDataEngine(num
);
1448 e
->name
= CopyFromOldName(RemapOldStringID(ReadUint16(ls
)));
1452 static const OldChunks subsidy_chunk
[] = {
1453 OCL_SVAR( OC_UINT8
, Subsidy
, cargo_type
),
1454 OCL_SVAR( OC_UINT8
, Subsidy
, remaining
),
1455 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Subsidy
, src
),
1456 OCL_SVAR( OC_FILE_U8
| OC_VAR_U16
, Subsidy
, dst
),
1461 static bool LoadOldSubsidy(LoadgameState
*ls
, int num
)
1463 Subsidy
*s
= new (num
) Subsidy();
1464 bool ret
= LoadChunk(ls
, s
, subsidy_chunk
);
1465 if (!IsValidCargoID(s
->cargo_type
)) delete s
;
1469 static const OldChunks game_difficulty_chunk
[] = {
1470 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, max_no_competitors
),
1471 OCL_NULL( 2), // competitor_start_time
1472 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, number_towns
),
1473 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, industry_density
),
1474 OCL_SVAR( OC_FILE_U16
| OC_VAR_U32
, DifficultySettings
, max_loan
),
1475 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, initial_interest
),
1476 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, vehicle_costs
),
1477 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, competitor_speed
),
1478 OCL_NULL( 2), // competitor_intelligence
1479 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, vehicle_breakdowns
),
1480 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, subsidy_multiplier
),
1481 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, construction_cost
),
1482 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, terrain_type
),
1483 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, quantity_sea_lakes
),
1484 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, economy
),
1485 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, line_reverse_mode
),
1486 OCL_SVAR( OC_FILE_U16
| OC_VAR_U8
, DifficultySettings
, disasters
),
1490 static bool LoadOldGameDifficulty(LoadgameState
*ls
, int)
1492 bool ret
= LoadChunk(ls
, &_settings_game
.difficulty
, game_difficulty_chunk
);
1493 _settings_game
.difficulty
.max_loan
*= 1000;
1498 static bool LoadOldMapPart1(LoadgameState
*ls
, int)
1500 if (_savegame_type
== SGT_TTO
) {
1501 Map::Allocate(OLD_MAP_SIZE
, OLD_MAP_SIZE
);
1504 for (auto t
: Map::Iterate()) {
1505 t
.m1() = ReadByte(ls
);
1507 for (auto t
: Map::Iterate()) {
1508 t
.m2() = ReadByte(ls
);
1511 if (_savegame_type
!= SGT_TTO
) {
1512 /* old map3 is split into to m3 and m4 */
1513 for (auto t
: Map::Iterate()) {
1514 t
.m3() = ReadByte(ls
);
1515 t
.m4() = ReadByte(ls
);
1517 auto range
= Map::Iterate();
1518 for (auto it
= range
.begin(); it
!= range
.end(); /* nothing. */) {
1519 uint8_t b
= ReadByte(ls
);
1520 for (int i
= 0; i
< 8; i
+= 2, ++it
) (*it
).m6() = GB(b
, i
, 2);
1527 static bool LoadOldMapPart2(LoadgameState
*ls
, int)
1529 for (auto t
: Map::Iterate()) {
1530 t
.type() = ReadByte(ls
);
1532 for (auto t
: Map::Iterate()) {
1533 t
.m5() = ReadByte(ls
);
1539 static bool LoadTTDPatchExtraChunks(LoadgameState
*ls
, int)
1541 ReadTTDPatchFlags();
1543 Debug(oldloader
, 2, "Found {} extra chunk(s)", _old_extra_chunk_nums
);
1545 for (int i
= 0; i
!= _old_extra_chunk_nums
; i
++) {
1546 uint16_t id
= ReadUint16(ls
);
1547 uint32_t len
= ReadUint32(ls
);
1550 /* List of GRFIDs, used in the savegame. 0x8004 is the new ID
1551 * They are saved in a 'GRFID:4 active:1' format, 5 bytes for each entry */
1554 /* Skip the first element: TTDP hack for the Action D special variables (FFFF0000 01) */
1555 ReadUint32(ls
); ReadByte(ls
); len
-= 5;
1557 ClearGRFConfigList(&_grfconfig
);
1559 uint32_t grfid
= ReadUint32(ls
);
1561 if (ReadByte(ls
) == 1) {
1562 GRFConfig
*c
= new GRFConfig("TTDP game, no information");
1563 c
->ident
.grfid
= grfid
;
1565 AppendToGRFConfigList(&_grfconfig
, c
);
1566 Debug(oldloader
, 3, "TTDPatch game using GRF file with GRFID {:08X}", BSWAP32(c
->ident
.grfid
));
1571 /* Append static NewGRF configuration */
1572 AppendStaticGRFConfigs(&_grfconfig
);
1576 /* TTDPatch version and configuration */
1578 _ttdp_version
= ReadUint32(ls
);
1579 Debug(oldloader
, 3, "Game saved with TTDPatch version {}.{}.{} r{}",
1580 GB(_ttdp_version
, 24, 8), GB(_ttdp_version
, 20, 4), GB(_ttdp_version
, 16, 4), GB(_ttdp_version
, 0, 16));
1582 while (len
-- != 0) ReadByte(ls
); // skip the configuration
1586 Debug(oldloader
, 4, "Skipping unknown extra chunk {}", id
);
1587 while (len
-- != 0) ReadByte(ls
);
1595 extern TileIndex _cur_tileloop_tile
;
1596 extern uint16_t _disaster_delay
;
1597 extern uint8_t _trees_tick_ctr
;
1598 extern uint8_t _age_cargo_skip_counter
; // From misc_sl.cpp
1599 extern uint8_t _old_diff_level
;
1600 extern uint8_t _old_units
;
1601 static const OldChunks main_chunk
[] = {
1602 OCL_ASSERT( OC_TTD
, 0 ),
1603 OCL_ASSERT( OC_TTO
, 0 ),
1604 OCL_VAR ( OC_FILE_U16
| OC_VAR_U32
, 1, &TimerGameCalendar::date
),
1605 OCL_VAR ( OC_UINT16
, 1, &TimerGameCalendar::date_fract
),
1606 OCL_NULL( 600 ), ///< TextEffects
1607 OCL_VAR ( OC_UINT32
, 2, &_random
.state
),
1609 OCL_ASSERT( OC_TTD
, 0x264 ),
1610 OCL_ASSERT( OC_TTO
, 0x264 ),
1612 OCL_CCHUNK( OC_TTD
, 70, LoadOldTown
),
1613 OCL_CCHUNK( OC_TTO
, 80, LoadOldTown
),
1615 OCL_ASSERT( OC_TTD
, 0x1C18 ),
1616 OCL_ASSERT( OC_TTO
, 0x1AC4 ),
1618 OCL_CCHUNK( OC_TTD
, 5000, LoadOldOrder
),
1619 OCL_CCHUNK( OC_TTO
, 3000, LoadOldOrder
),
1621 OCL_ASSERT( OC_TTD
, 0x4328 ),
1622 OCL_ASSERT( OC_TTO
, 0x3234 ),
1624 OCL_CHUNK( 1, LoadOldAnimTileList
),
1625 OCL_NULL( 4 ), ///< old end-of-order-list-pointer, no longer in use
1627 OCL_ASSERT( OC_TTO
, 0x3438 ),
1629 OCL_CCHUNK( OC_TTD
, 255, LoadOldDepot
),
1630 OCL_CCHUNK( OC_TTO
, 252, LoadOldDepot
),
1632 OCL_ASSERT( OC_TTD
, 0x4B26 ),
1633 OCL_ASSERT( OC_TTO
, 0x3A20 ),
1635 OCL_NULL( 4 ), ///< town counter, no longer in use
1636 OCL_NULL( 2 ), ///< timer_counter, no longer in use
1637 OCL_NULL( 2 ), ///< land_code, no longer in use
1639 OCL_VAR ( OC_FILE_U16
| OC_VAR_U8
, 1, &_age_cargo_skip_counter
),
1640 OCL_VAR ( OC_FILE_U16
| OC_VAR_U64
, 1, &TimerGameTick::counter
),
1641 OCL_VAR ( OC_TILE
, 1, &_cur_tileloop_tile
),
1643 OCL_ASSERT( OC_TTO
, 0x3A2E ),
1645 OCL_CNULL( OC_TTO
, 48 * 6 ), ///< prices
1646 OCL_CNULL( OC_TTD
, 49 * 6 ), ///< prices
1648 OCL_ASSERT( OC_TTO
, 0x3B4E ),
1650 OCL_CNULL( OC_TTO
, 11 * 8 ), ///< cargo payment rates
1651 OCL_CNULL( OC_TTD
, 12 * 8 ), ///< cargo payment rates
1653 OCL_ASSERT( OC_TTD
, 0x4CBA ),
1654 OCL_ASSERT( OC_TTO
, 0x3BA6 ),
1656 OCL_CHUNK( 1, LoadOldMapPart1
),
1658 OCL_ASSERT( OC_TTD
, 0x48CBA ),
1659 OCL_ASSERT( OC_TTO
, 0x23BA6 ),
1661 OCL_CCHUNK( OC_TTD
, 250, LoadOldStation
),
1662 OCL_CCHUNK( OC_TTO
, 200, LoadOldStation
),
1664 OCL_ASSERT( OC_TTO
, 0x29E16 ),
1666 OCL_CCHUNK( OC_TTD
, 90, LoadOldIndustry
),
1667 OCL_CCHUNK( OC_TTO
, 100, LoadOldIndustry
),
1669 OCL_ASSERT( OC_TTO
, 0x2ADB6 ),
1671 OCL_CHUNK( 8, LoadOldCompany
),
1673 OCL_ASSERT( OC_TTD
, 0x547F2 ),
1674 OCL_ASSERT( OC_TTO
, 0x2C746 ),
1676 OCL_CCHUNK( OC_TTD
, 850, LoadOldVehicle
),
1677 OCL_CCHUNK( OC_TTO
, 800, LoadOldVehicle
),
1679 OCL_ASSERT( OC_TTD
, 0x6F0F2 ),
1680 OCL_ASSERT( OC_TTO
, 0x45746 ),
1682 OCL_VAR ( OC_TTD
| OC_UINT8
| OC_DEREFERENCE_POINTER
, 32 * 500, &_old_name_array
),
1683 OCL_VAR ( OC_TTO
| OC_UINT8
| OC_DEREFERENCE_POINTER
, 24 * 200, &_old_name_array
),
1685 OCL_ASSERT( OC_TTO
, 0x46A06 ),
1687 OCL_NULL( 0x2000 ), ///< Old hash-table, no longer in use
1689 OCL_CHUNK( 40, LoadOldSign
),
1691 OCL_ASSERT( OC_TTO
, 0x48C36 ),
1693 OCL_CCHUNK( OC_TTD
, 256, LoadOldEngine
),
1694 OCL_CCHUNK( OC_TTO
, 103, LoadOldEngine
),
1696 OCL_ASSERT( OC_TTO
, 0x496AC ),
1698 OCL_NULL ( 2 ), // _vehicle_id_ctr_day
1700 OCL_CHUNK( 8, LoadOldSubsidy
),
1702 OCL_ASSERT( OC_TTO
, 0x496CE ),
1704 OCL_VAR ( OC_FILE_U16
| OC_VAR_U32
, 1, &_new_competitor_timeout
.period
.value
),
1706 OCL_CNULL( OC_TTO
, 2 ), ///< available monorail bitmask
1708 OCL_VAR ( OC_FILE_I16
| OC_VAR_I32
, 1, &_saved_scrollpos_x
),
1709 OCL_VAR ( OC_FILE_I16
| OC_VAR_I32
, 1, &_saved_scrollpos_y
),
1710 OCL_VAR ( OC_FILE_U16
| OC_VAR_U8
, 1, &_saved_scrollpos_zoom
),
1712 OCL_NULL( 4 ), ///< max_loan
1713 OCL_VAR ( OC_FILE_U32
| OC_VAR_I64
, 1, &_economy
.old_max_loan_unround
),
1714 OCL_VAR ( OC_INT16
, 1, &_economy
.fluct
),
1716 OCL_VAR ( OC_UINT16
, 1, &_disaster_delay
),
1718 OCL_ASSERT( OC_TTO
, 0x496E4 ),
1720 OCL_CNULL( OC_TTD
, 144 ), ///< cargo-stuff
1722 OCL_CCHUNK( OC_TTD
, 256, LoadOldEngineName
),
1724 OCL_CNULL( OC_TTD
, 144 ), ///< AI cargo-stuff
1725 OCL_NULL( 2 ), ///< Company indexes of companies, no longer in use
1726 OCL_NULL( 1 ), ///< Station tick counter, no longer in use
1728 OCL_VAR ( OC_UINT8
, 1, &_settings_game
.locale
.currency
),
1729 OCL_VAR ( OC_UINT8
, 1, &_old_units
),
1730 OCL_VAR ( OC_FILE_U8
| OC_VAR_U32
, 1, &_cur_company_tick_index
),
1732 OCL_NULL( 2 ), ///< Date stuff, calculated automatically
1733 OCL_NULL( 8 ), ///< Company colours, calculated automatically
1735 OCL_VAR ( OC_UINT8
, 1, &_economy
.infl_amount
),
1736 OCL_VAR ( OC_UINT8
, 1, &_economy
.infl_amount_pr
),
1737 OCL_VAR ( OC_UINT8
, 1, &_economy
.interest_rate
),
1738 OCL_NULL( 1 ), // available airports
1739 OCL_VAR ( OC_UINT8
, 1, &_settings_game
.vehicle
.road_side
),
1740 OCL_VAR ( OC_UINT8
, 1, &_settings_game
.game_creation
.town_name
),
1742 OCL_CHUNK( 1, LoadOldGameDifficulty
),
1744 OCL_ASSERT( OC_TTD
, 0x77130 ),
1746 OCL_VAR ( OC_UINT8
, 1, &_old_diff_level
),
1748 OCL_VAR ( OC_TTD
| OC_UINT8
, 1, &_settings_game
.game_creation
.landscape
),
1749 OCL_VAR ( OC_TTD
| OC_UINT8
, 1, &_trees_tick_ctr
),
1751 OCL_CNULL( OC_TTD
, 1 ), ///< Custom vehicle types yes/no, no longer used
1752 OCL_VAR ( OC_TTD
| OC_UINT8
, 1, &_settings_game
.game_creation
.snow_line_height
),
1754 OCL_CNULL( OC_TTD
, 32 ), ///< new_industry_randtable, no longer used (because of new design)
1755 OCL_CNULL( OC_TTD
, 36 ), ///< cargo-stuff
1757 OCL_ASSERT( OC_TTD
, 0x77179 ),
1758 OCL_ASSERT( OC_TTO
, 0x4971D ),
1760 OCL_CHUNK( 1, LoadOldMapPart2
),
1762 OCL_ASSERT( OC_TTD
, 0x97179 ),
1763 OCL_ASSERT( OC_TTO
, 0x6971D ),
1765 /* Below any (if available) extra chunks from TTDPatch can follow */
1766 OCL_CHUNK(1, LoadTTDPatchExtraChunks
),
1771 bool LoadTTDMain(LoadgameState
*ls
)
1773 Debug(oldloader
, 3, "Reading main chunk...");
1775 _read_ttdpatch_flags
= false;
1777 /* Load the biggest chunk */
1778 _old_vehicle_names
= nullptr;
1780 if (!LoadChunk(ls
, nullptr, main_chunk
)) {
1781 Debug(oldloader
, 0, "Loading failed");
1782 free(_old_vehicle_names
);
1786 free(_old_vehicle_names
);
1790 Debug(oldloader
, 3, "Done, converting game data...");
1795 /* Fix some general stuff */
1796 _settings_game
.game_creation
.landscape
= _settings_game
.game_creation
.landscape
& 0xF;
1798 /* Fix the game to be compatible with OpenTTD */
1802 /* We have a new difficulty setting */
1803 _settings_game
.difficulty
.town_council_tolerance
= Clamp(_old_diff_level
, 0, 2);
1805 Debug(oldloader
, 3, "Finished converting game data");
1806 Debug(oldloader
, 1, "TTD(Patch) savegame successfully converted");
1808 free(_old_vehicle_names
);
1813 bool LoadTTOMain(LoadgameState
*ls
)
1815 Debug(oldloader
, 3, "Reading main chunk...");
1817 _read_ttdpatch_flags
= false;
1819 std::array
<uint8_t, 103 * sizeof(Engine
)> engines
; // we don't want to call Engine constructor here
1820 _old_engines
= (Engine
*)engines
.data();
1821 std::array
<StringID
, 800> vehnames
;
1822 _old_vehicle_names
= vehnames
.data();
1824 /* Load the biggest chunk */
1825 if (!LoadChunk(ls
, nullptr, main_chunk
)) {
1826 Debug(oldloader
, 0, "Loading failed");
1829 Debug(oldloader
, 3, "Done, converting game data...");
1831 if (_settings_game
.game_creation
.town_name
!= 0) _settings_game
.game_creation
.town_name
++;
1833 _settings_game
.game_creation
.landscape
= 0;
1834 _trees_tick_ctr
= 0xFF;
1836 if (!FixTTOMapArray() || !FixTTOEngines()) {
1837 Debug(oldloader
, 0, "Conversion failed");
1845 /* We have a new difficulty setting */
1846 _settings_game
.difficulty
.town_council_tolerance
= Clamp(_old_diff_level
, 0, 2);
1848 /* SVXConverter about cargo payment rates correction:
1849 * "increase them to compensate for the faster time advance in TTD compared to TTO
1850 * which otherwise would cause much less income while the annual running costs of
1851 * the vehicles stay the same" */
1852 _economy
.inflation_payment
= std::min(_economy
.inflation_payment
* 124 / 74, MAX_INFLATION
);
1854 Debug(oldloader
, 3, "Finished converting game data");
1855 Debug(oldloader
, 1, "TTO savegame successfully converted");