Update: Translations from eints
[openttd-github.git] / src / saveload / oldloader_sl.cpp
blobc78c21648338100b3d51f6d46ed920b79613597b
1 /*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
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"
11 #include "../town.h"
12 #include "../industry.h"
13 #include "../company_func.h"
14 #include "../aircraft.h"
15 #include "../roadveh.h"
16 #include "../ship.h"
17 #include "../train.h"
18 #include "../signs_base.h"
19 #include "../station_base.h"
20 #include "../subsidy_base.h"
21 #include "../debug.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
46 void FixOldMapArray()
48 /* TTO/TTD/TTDP savegames could have buoys at tile 0
49 * (without assigned station struct) */
50 MakeSea(0);
53 static void FixTTDMapArray()
55 for (auto tile : Map::Iterate()) {
56 switch (GetTileType(tile)) {
57 case MP_STATION:
58 tile.m4() = 0; // We do not understand this TTDP station mapping (yet)
59 switch (tile.m5()) {
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
65 default: break;
67 break;
69 case MP_RAILWAY:
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
80 break;
82 case MP_WATER:
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);
87 tile.m2() = 0;
88 tile.m3() = 2; // WATER_CLASS_RIVER
89 tile.m4() = Random();
90 tile.m5() = 0;
92 break;
94 default:
95 break;
99 FixOldMapArray();
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 */
107 delete d;
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
118 /* Already OK */
119 return townnameparts;
121 case 1: // French
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);
126 case 2: // German
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);
134 case 5: // Silly
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);
140 return 0;
143 #undef FIXNUM
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_START + _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) {
167 v->next = nullptr;
168 } else {
169 v->next = Vehicle::GetIfValid((size_t)v->next);
172 /* For some reason we need to correct for this */
173 switch (v->spritenum) {
174 case 0xfd: break;
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);
189 Tile tile(rv->tile);
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);
217 if (tt == 11) {
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
223 tt = MP_RAILWAY;
226 switch (tt) {
227 case MP_CLEAR:
228 break;
230 case MP_RAILWAY:
231 switch (GB(tile.m5(), 6, 2)) {
232 case 0: // RAIL_TILE_NORMAL
233 break;
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
240 break;
241 case 3: // RAIL_TILE_DEPOT
242 tile.m2() = 0;
243 break;
244 default:
245 return false;
247 break;
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
253 break;
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
256 break;
257 case 2: // ROAD_TILE_DEPOT
258 break;
259 default:
260 return false;
262 break;
264 case MP_HOUSE:
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"
268 break;
270 case MP_TREES:
271 tile.m3() = GB(tile.m5(), 3, 3); // type of trees
272 tile.m5() &= 0xC7; // number of trees and growth status
273 break;
275 case MP_STATION:
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
279 break;
281 case MP_WATER:
282 tile.m3() = tile.m2() = 0;
283 break;
285 case MP_VOID:
286 tile.m2() = tile.m3() = tile.m5() = 0;
287 break;
289 case MP_INDUSTRY:
290 tile.m3() = 0;
291 switch (tile.m5()) {
292 case 0x24: // farm silo
293 tile.m5() = 0x25;
294 break;
295 case 0x25: case 0x27: // farm
296 case 0x28: case 0x29: case 0x2A: case 0x2B: // factory
297 tile.m5()--;
298 break;
299 default:
300 if (tile.m5() >= 0x2C) tile.m5() += 3; // iron ore mine, steel mill or bank
301 break;
303 break;
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
319 tile.m2() = 0;
320 tile.m3() = HasBit(tile.m5(), 3); // monorail
321 tile.m5() &= HasBit(tile.m5(), 3) ? 0x03 : 0x07 ; // direction, transport type (== 0 for rail)
323 break;
325 case MP_OBJECT:
326 tile.m2() = 0;
327 tile.m3() = 0;
328 break;
330 default:
331 return false;
336 FixOldMapArray();
338 return true;
341 static Engine *_old_engines;
343 static bool FixTTOEngines()
345 using OldEngineID = uint8_t;
346 /** TTD->TTO remapping of engines; 255 means there is no equivalent. SVXConverter uses (almost) the same table. */
347 static const OldEngineID ttd_to_tto[] = {
348 0, 255, 255, 255, 255, 255, 255, 255, 5, 7, 8, 9, 10, 11, 12, 13,
349 255, 255, 255, 255, 255, 255, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
350 25, 26, 27, 29, 28, 30, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
351 255, 255, 255, 255, 255, 255, 255, 31, 255, 32, 33, 34, 35, 36, 37, 38,
352 39, 40, 41, 42, 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, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
355 255, 255, 255, 255, 44, 45, 46, 255, 255, 255, 255, 47, 48, 255, 49, 50,
356 255, 255, 255, 255, 51, 52, 255, 53, 54, 255, 55, 56, 255, 57, 59, 255,
357 58, 60, 255, 61, 62, 255, 63, 64, 255, 65, 66, 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, 255, 255, 255, 255,
360 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 67, 68, 69, 70,
361 71, 255, 255, 76, 77, 255, 255, 78, 79, 80, 81, 82, 83, 84, 85, 86,
362 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 255,
363 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 102, 255, 255
366 /** TTO->TTD remapping of engines. SVXConverter uses the same table. */
367 static const OldEngineID tto_to_ttd[] = {
368 0, 0, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 15, 15, 22,
369 23, 24, 25, 26, 27, 29, 28, 30, 31, 32, 33, 34, 35, 36, 37, 55,
370 57, 59, 58, 60, 61, 62, 63, 64, 65, 66, 67, 116, 116, 117, 118, 123,
371 124, 126, 127, 132, 133, 135, 136, 138, 139, 141, 142, 144, 145, 147, 148, 150,
372 151, 153, 154, 204, 205, 206, 207, 208, 211, 212, 211, 212, 211, 212, 215, 216,
373 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
374 233, 234, 235, 236, 237, 238, 253
377 for (Vehicle *v : Vehicle::Iterate()) {
378 if (v->engine_type >= lengthof(tto_to_ttd)) return false;
379 v->engine_type = static_cast<EngineID>(tto_to_ttd[v->engine_type]);
382 /* Load the default engine set. Many of them will be overridden later */
384 uint j = 0;
385 for (uint16_t i = 0; i < lengthof(_orig_rail_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_TRAIN, i);
386 for (uint16_t i = 0; i < lengthof(_orig_road_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_ROAD, i);
387 for (uint16_t i = 0; i < lengthof(_orig_ship_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_SHIP, i);
388 for (uint16_t i = 0; i < lengthof(_orig_aircraft_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_AIRCRAFT, i);
391 TimerGameCalendar::Date aging_date = std::min(TimerGameCalendar::date + CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR, TimerGameCalendar::ConvertYMDToDate(TimerGameCalendar::Year{2050}, 0, 1));
392 TimerGameCalendar::YearMonthDay aging_ymd = TimerGameCalendar::ConvertDateToYMD(aging_date);
394 for (EngineID i = 0; i < 256; i++) {
395 OldEngineID oi = ttd_to_tto[i];
396 Engine *e = GetTempDataEngine(i);
398 if (oi == 255) {
399 /* Default engine is used */
400 TimerGameCalendar::date += CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR;
401 StartupOneEngine(e, aging_ymd, 0);
402 CalcEngineReliability(e, false);
403 e->intro_date -= CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR;
404 TimerGameCalendar::date -= CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR;
406 /* Make sure for example monorail and maglev are available when they should be */
407 if (TimerGameCalendar::date >= e->intro_date && e->info.climates.Test(LandscapeType::Temperate)) {
408 e->flags.Set(EngineFlag::Available);
409 e->company_avail = std::numeric_limits<CompanyMask>::max();
410 e->age = TimerGameCalendar::date > e->intro_date ? (TimerGameCalendar::date - e->intro_date).base() / 30 : 0;
412 } else {
413 /* Using data from TTO savegame */
414 Engine *oe = &_old_engines[oi];
416 e->intro_date = oe->intro_date;
417 e->age = oe->age;
418 e->reliability = oe->reliability;
419 e->reliability_spd_dec = oe->reliability_spd_dec;
420 e->reliability_start = oe->reliability_start;
421 e->reliability_max = oe->reliability_max;
422 e->reliability_final = oe->reliability_final;
423 e->duration_phase_1 = oe->duration_phase_1;
424 e->duration_phase_2 = oe->duration_phase_2;
425 e->duration_phase_3 = oe->duration_phase_3;
426 e->flags = oe->flags;
428 e->company_avail = 0;
430 /* One or more engines were remapped to this one. Make this engine available
431 * if at least one of them was available. */
432 for (uint j = 0; j < lengthof(tto_to_ttd); j++) {
433 if (tto_to_ttd[j] == i && _old_engines[j].company_avail != 0) {
434 e->company_avail = std::numeric_limits<CompanyMask>::max();
435 e->flags.Set(EngineFlag::Available);
436 break;
440 e->info.climates = LandscapeType::Temperate;
443 e->preview_company = INVALID_COMPANY;
444 e->preview_asked = std::numeric_limits<CompanyMask>::max();
445 e->preview_wait = 0;
446 e->name = std::string{};
449 return true;
452 static void FixTTOCompanies()
454 for (Company *c : Company::Iterate()) {
455 c->cur_economy.company_value = CalculateCompanyValue(c); // company value history is zeroed
459 static inline Colours RemapTTOColour(Colours tto)
461 /** Lossy remapping of TTO colours to TTD colours. SVXConverter uses the same conversion. */
462 static const Colours tto_colour_remap[] = {
463 COLOUR_DARK_BLUE, COLOUR_GREY, COLOUR_YELLOW, COLOUR_RED,
464 COLOUR_PURPLE, COLOUR_DARK_GREEN, COLOUR_ORANGE, COLOUR_PALE_GREEN,
465 COLOUR_BLUE, COLOUR_GREEN, COLOUR_CREAM, COLOUR_BROWN,
466 COLOUR_WHITE, COLOUR_LIGHT_BLUE, COLOUR_MAUVE, COLOUR_PINK
469 if (static_cast<size_t>(tto) >= std::size(tto_colour_remap)) return COLOUR_GREY; // this shouldn't happen
471 return tto_colour_remap[tto];
474 static inline uint RemapTownIndex(uint x)
476 return _savegame_type == SGT_TTO ? (x - 0x264) / 78 : (x - 0x264) / 94;
479 static inline uint RemapOrderIndex(uint x)
481 return _savegame_type == SGT_TTO ? (x - 0x1AC4) / 2 : (x - 0x1C18) / 2;
484 extern std::vector<TileIndex> _animated_tiles;
485 extern TimeoutTimer<TimerGameTick> _new_competitor_timeout;
486 extern char *_old_name_array;
488 static uint32_t _old_town_index;
489 static uint16_t _old_string_id;
490 static uint16_t _old_string_id_2;
492 static void ClearOldMap3(TileIndex t)
494 Tile tile(t);
495 tile.m3() = 0;
496 tile.m4() = 0;
499 static Town *RemapTown(TileIndex fallback)
501 /* In some cases depots, industries and stations could refer to a missing town. */
502 Town *t = Town::GetIfValid(RemapTownIndex(_old_town_index));
503 if (t == nullptr) {
504 /* In case the town that was refered to does not exist, find the closest.
505 * However, this needs the kd-tree to be present. */
506 RebuildTownKdtree();
507 t = CalcClosestTownFromTile(fallback);
509 return t;
512 static void ReadTTDPatchFlags()
514 if (_read_ttdpatch_flags) return;
516 _read_ttdpatch_flags = true;
518 /* Set default values */
519 _old_vehicle_multiplier = 1;
520 _ttdp_version = 0;
521 _old_extra_chunk_nums = 0;
522 _bump_assert_value = 0;
524 if (_savegame_type == SGT_TTO) return;
526 /* TTDPatch misuses old map3 (now m3/m4) for flags.. read them! */
527 _old_vehicle_multiplier = Tile(0).m3();
528 /* Somehow.... there was an error in some savegames, so 0 becomes 1
529 * and 1 becomes 2. The rest of the values are okay */
530 if (_old_vehicle_multiplier < 2) _old_vehicle_multiplier++;
532 _old_vehicle_names = MallocT<StringID>(_old_vehicle_multiplier * 850);
534 /* TTDPatch increases the Vehicle-part in the middle of the game,
535 * so if the multiplier is anything else but 1, the assert fails..
536 * bump the assert value so it doesn't!
537 * (1 multiplier == 850 vehicles
538 * 1 vehicle == 128 bytes */
539 _bump_assert_value = (_old_vehicle_multiplier - 1) * 850 * 128;
541 /* The first 17 bytes are used by TTDP1, which translates to the first 9 m3s and first 8 m4s. */
542 for (TileIndex i{}; i <= 8; i++) { // check tile 0, too
543 Tile tile(i);
544 if (tile.m3() != 0 || (i != 8 && tile.m4() != 0)) _savegame_type = SGT_TTDP1;
547 /* Check if we have a modern TTDPatch savegame (has extra data all around) */
548 Tile ttdp2_header_first(Map::Size() - 3);
549 Tile ttdp2_header_second(Map::Size() - 2);
550 if (ttdp2_header_first.m3() == 'T' && ttdp2_header_first.m4() == 'T' &&
551 ttdp2_header_second.m3() == 'D' && ttdp2_header_second.m4() == 'p') {
552 _savegame_type = SGT_TTDP2;
555 Tile extra_chunk_tile = Tile(_savegame_type == SGT_TTDP2 ? Map::Size() - 1 : 1);
556 _old_extra_chunk_nums = extra_chunk_tile.m3() | extra_chunk_tile.m4() << 8;
558 /* Clean the misused places */
559 for (TileIndex i{}; i < 9; i++) ClearOldMap3(i);
560 for (TileIndex i = TileXY(0, Map::MaxY()); i < Map::Size(); i++) ClearOldMap3(i);
562 if (_savegame_type == SGT_TTDP2) Debug(oldloader, 2, "Found TTDPatch game");
564 Debug(oldloader, 3, "Vehicle-multiplier is set to {} ({} vehicles)", _old_vehicle_multiplier, _old_vehicle_multiplier * 850);
567 static const OldChunks town_chunk[] = {
568 OCL_SVAR( OC_TILE, Town, xy ),
569 OCL_NULL( 2 ), ///< population, no longer in use
570 OCL_SVAR( OC_UINT16, Town, townnametype ),
571 OCL_SVAR( OC_UINT32, Town, townnameparts ),
572 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, grow_counter ),
573 OCL_NULL( 1 ), ///< sort_index, no longer in use
574 OCL_NULL( 4 ), ///< sign-coordinates, no longer in use
575 OCL_NULL( 2 ), ///< namewidth, no longer in use
576 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Town, flags ),
577 OCL_NULL( 10 ), ///< radius, no longer in use
579 OCL_SVAR( OC_INT16, Town, ratings[0] ),
580 OCL_SVAR( OC_INT16, Town, ratings[1] ),
581 OCL_SVAR( OC_INT16, Town, ratings[2] ),
582 OCL_SVAR( OC_INT16, Town, ratings[3] ),
583 OCL_SVAR( OC_INT16, Town, ratings[4] ),
584 OCL_SVAR( OC_INT16, Town, ratings[5] ),
585 OCL_SVAR( OC_INT16, Town, ratings[6] ),
586 OCL_SVAR( OC_INT16, Town, ratings[7] ),
588 OCL_SVAR( OC_FILE_U32 | OC_VAR_U16, Town, have_ratings ),
589 OCL_SVAR( OC_FILE_U32 | OC_VAR_U16, Town, statues ),
590 OCL_NULL( 2 ), ///< num_houses, no longer in use
591 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, time_until_rebuild ),
592 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, growth_rate ),
594 /* Slots 0 and 2 are passengers and mail respectively for old saves. */
595 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].new_max ),
596 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].new_max ),
597 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].new_act ),
598 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].new_act ),
599 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].old_max ),
600 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].old_max ),
601 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].old_act ),
602 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].old_act ),
604 OCL_NULL( 2 ), ///< pct_pass_transported / pct_mail_transported, now computed on the fly
606 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TAE_FOOD].new_act ),
607 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TAE_WATER].new_act ),
608 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TAE_FOOD].old_act ),
609 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TAE_WATER].old_act ),
611 OCL_SVAR( OC_UINT8, Town, road_build_months ),
612 OCL_SVAR( OC_UINT8, Town, fund_buildings_months ),
614 OCL_CNULL( OC_TTD, 8 ), ///< some junk at the end of the record
616 OCL_END()
619 static bool LoadOldTown(LoadgameState *ls, int num)
621 Town *t = new (num) Town();
622 if (!LoadChunk(ls, t, town_chunk)) return false;
624 if (t->xy != 0) {
625 if (_savegame_type == SGT_TTO) {
626 /* 0x10B6 is auto-generated name, others are custom names */
627 t->townnametype = t->townnametype == 0x10B6 ? 0x20C1 : t->townnametype + 0x2A00;
629 } else {
630 delete t;
633 return true;
636 static uint16_t _old_order;
637 static const OldChunks order_chunk[] = {
638 OCL_VAR ( OC_UINT16, 1, &_old_order ),
639 OCL_END()
642 static bool LoadOldOrder(LoadgameState *ls, int num)
644 if (!LoadChunk(ls, nullptr, order_chunk)) return false;
646 Order *o = new (num) Order();
647 o->AssignOrder(UnpackOldOrder(_old_order));
649 if (o->IsType(OT_NOTHING)) {
650 delete o;
651 } else {
652 /* Relink the orders to each other (in the orders for one vehicle are behind each other,
653 * with an invalid order (OT_NOTHING) as indication that it is the last order */
654 Order *prev = Order::GetIfValid(num - 1);
655 if (prev != nullptr) prev->next = o;
658 return true;
661 static bool LoadOldAnimTileList(LoadgameState *ls, int)
663 TileIndex anim_list[256];
664 const OldChunks anim_chunk[] = {
665 OCL_VAR ( OC_TILE, 256, anim_list ),
666 OCL_END ()
669 if (!LoadChunk(ls, nullptr, anim_chunk)) return false;
671 /* The first zero in the loaded array indicates the end of the list. */
672 for (int i = 0; i < 256; i++) {
673 if (anim_list[i] == 0) break;
674 _animated_tiles.push_back(anim_list[i]);
677 return true;
680 static const OldChunks depot_chunk[] = {
681 OCL_SVAR( OC_TILE, Depot, xy ),
682 OCL_VAR ( OC_UINT32, 1, &_old_town_index ),
683 OCL_END()
686 static bool LoadOldDepot(LoadgameState *ls, int num)
688 Depot *d = new (num) Depot();
689 if (!LoadChunk(ls, d, depot_chunk)) return false;
691 if (d->xy != 0) {
692 d->town = RemapTown(d->xy);
693 } else {
694 delete d;
697 return true;
700 static StationID _current_station_id;
701 static uint16_t _waiting_acceptance;
702 static uint8_t _cargo_source;
703 static uint8_t _cargo_periods;
705 static const OldChunks goods_chunk[] = {
706 OCL_VAR ( OC_UINT16, 1, &_waiting_acceptance ),
707 OCL_SVAR( OC_UINT8, GoodsEntry, time_since_pickup ),
708 OCL_SVAR( OC_UINT8, GoodsEntry, rating ),
709 OCL_VAR ( OC_UINT8, 1, &_cargo_source ),
710 OCL_VAR ( OC_UINT8, 1, &_cargo_periods ),
711 OCL_SVAR( OC_UINT8, GoodsEntry, last_speed ),
712 OCL_SVAR( OC_UINT8, GoodsEntry, last_age ),
714 OCL_END()
717 static bool LoadOldGood(LoadgameState *ls, int num)
719 /* for TTO games, 12th (num == 11) goods entry is created in the Station constructor */
720 if (_savegame_type == SGT_TTO && num == 11) return true;
722 Station *st = Station::Get(_current_station_id);
723 GoodsEntry *ge = &st->goods[num];
725 if (!LoadChunk(ls, ge, goods_chunk)) return false;
727 AssignBit(ge->status, GoodsEntry::GES_ACCEPTANCE, HasBit(_waiting_acceptance, 15));
728 AssignBit(ge->status, GoodsEntry::GES_RATING, _cargo_source != 0xFF);
729 if (GB(_waiting_acceptance, 0, 12) != 0 && CargoPacket::CanAllocateItem()) {
730 ge->GetOrCreateData().cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_periods, (_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source, INVALID_TILE, 0),
731 INVALID_STATION);
734 return true;
737 static const OldChunks station_chunk[] = {
738 OCL_SVAR( OC_TILE, Station, xy ),
739 OCL_VAR ( OC_UINT32, 1, &_old_town_index ),
741 OCL_NULL( 4 ), ///< bus/lorry tile
742 OCL_SVAR( OC_TILE, Station, train_station.tile ),
743 OCL_SVAR( OC_TILE, Station, airport.tile ),
744 OCL_NULL( 2 ), ///< dock tile
745 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Station, train_station.w ),
747 OCL_NULL( 1 ), ///< sort-index, no longer in use
748 OCL_NULL( 2 ), ///< sign-width, no longer in use
750 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
752 OCL_NULL( 4 ), ///< sign left/top, no longer in use
754 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Station, had_vehicle_of_type ),
756 OCL_CHUNK( 12, LoadOldGood ),
758 OCL_SVAR( OC_UINT8, Station, time_since_load ),
759 OCL_SVAR( OC_UINT8, Station, time_since_unload ),
760 OCL_SVAR( OC_UINT8, Station, delete_ctr ),
761 OCL_SVAR( OC_UINT8, Station, owner ),
762 OCL_SVAR( OC_UINT8, Station, facilities ),
763 OCL_SVAR( OC_TTD | OC_UINT8, Station, airport.type ),
764 OCL_SVAR( OC_TTO | OC_FILE_U16 | OC_VAR_U64, Station, airport.flags ),
765 OCL_NULL( 3 ), ///< bus/truck status, blocked months, no longer in use
766 OCL_CNULL( OC_TTD, 1 ), ///< unknown
767 OCL_SVAR( OC_TTD | OC_FILE_U16 | OC_VAR_U64, Station, airport.flags ),
768 OCL_CNULL( OC_TTD, 2 ), ///< last_vehicle. now last_vehicle_type
769 OCL_CNULL( OC_TTD, 4 ), ///< junk at end of chunk
771 OCL_END()
774 static bool LoadOldStation(LoadgameState *ls, int num)
776 Station *st = new (num) Station();
777 _current_station_id = num;
779 if (!LoadChunk(ls, st, station_chunk)) return false;
781 if (st->xy != 0) {
782 st->town = RemapTown(st->xy);
784 if (_savegame_type == SGT_TTO) {
785 if (IsInsideBS(_old_string_id, 0x180F, 32)) {
786 st->string_id = STR_SV_STNAME + (_old_string_id - 0x180F); // automatic name
787 } else {
788 st->string_id = _old_string_id + 0x2800; // custom name
791 if (HasBit(st->airport.flags, 8)) {
792 st->airport.type = 1; // large airport
793 } else if (HasBit(st->airport.flags, 6)) {
794 st->airport.type = 3; // oil rig
795 } else {
796 st->airport.type = 0; // small airport
798 } else {
799 st->string_id = RemapOldStringID(_old_string_id);
801 } else {
802 delete st;
805 return true;
808 /* Old save games always have 3 input and 2 output slots per industry. */
809 static std::array<Industry::AcceptedCargo, INDUSTRY_ORIGINAL_NUM_INPUTS> _old_accepted{};
810 static std::array<Industry::ProducedCargo, INDUSTRY_ORIGINAL_NUM_OUTPUTS> _old_produced{};
812 static const OldChunks industry_chunk[] = {
813 OCL_SVAR( OC_TILE, Industry, location.tile ),
814 OCL_VAR ( OC_UINT32, 1, &_old_town_index ),
815 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Industry, location.w ),
816 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Industry, location.h ),
817 OCL_NULL( 2 ), ///< used to be industry's produced_cargo
819 OCL_VAR( OC_TTD | OC_UINT16, 1, &_old_produced[0].waiting ),
820 OCL_VAR( OC_TTD | OC_UINT16, 1, &_old_produced[1].waiting ),
821 OCL_VAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, 1, &_old_produced[0].waiting ),
822 OCL_VAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, 1, &_old_produced[1].waiting ),
824 OCL_VAR( OC_UINT8, 1, &_old_produced[0].rate ),
825 OCL_VAR( OC_UINT8, 1, &_old_produced[1].rate ),
827 OCL_NULL( 3 ), ///< used to be industry's accepts_cargo
829 OCL_SVAR( OC_UINT8, Industry, prod_level ),
831 OCL_VAR( OC_UINT16, 1, &_old_produced[0].history[THIS_MONTH].production ),
832 OCL_VAR( OC_UINT16, 1, &_old_produced[1].history[THIS_MONTH].production ),
833 OCL_VAR( OC_UINT16, 1, &_old_produced[0].history[THIS_MONTH].transported ),
834 OCL_VAR( OC_UINT16, 1, &_old_produced[1].history[THIS_MONTH].transported ),
836 OCL_NULL( 2 ), ///< last_month_pct_transported, now computed on the fly
838 OCL_VAR( OC_UINT16, 1, &_old_produced[0].history[LAST_MONTH].production ),
839 OCL_VAR( OC_UINT16, 1, &_old_produced[1].history[LAST_MONTH].production ),
840 OCL_VAR( OC_UINT16, 1, &_old_produced[0].history[LAST_MONTH].transported ),
841 OCL_VAR( OC_UINT16, 1, &_old_produced[1].history[LAST_MONTH].transported ),
843 OCL_SVAR( OC_UINT8, Industry, type ),
844 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Industry, counter ),
845 OCL_SVAR( OC_UINT8, Industry, owner ),
846 OCL_SVAR( OC_UINT8, Industry, random_colour ),
847 OCL_SVAR( OC_TTD | OC_FILE_U8 | OC_VAR_I32, Industry, last_prod_year ),
848 OCL_SVAR( OC_TTD | OC_UINT16, Industry, counter ),
849 OCL_SVAR( OC_TTD | OC_UINT8, Industry, was_cargo_delivered ),
851 OCL_CNULL( OC_TTD, 9 ), ///< Random junk at the end of this chunk
853 OCL_END()
856 static bool LoadOldIndustry(LoadgameState *ls, int num)
858 Industry *i = new (num) Industry();
859 if (!LoadChunk(ls, i, industry_chunk)) return false;
861 if (i->location.tile != 0) {
862 /* Copy data from old fixed arrays to industry. */
863 std::copy(std::begin(_old_accepted), std::end(_old_accepted), std::back_inserter(i->accepted));
864 std::copy(std::begin(_old_produced), std::end(_old_produced), std::back_inserter(i->produced));
866 i->town = RemapTown(i->location.tile);
868 if (_savegame_type == SGT_TTO) {
869 if (i->type > 0x06) i->type++; // Printing Works were added
870 if (i->type == 0x0A) i->type = 0x12; // Iron Ore Mine has different ID
872 TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
873 i->last_prod_year = ymd.year;
875 i->random_colour = RemapTTOColour(i->random_colour);
878 Industry::industries[i->type].push_back(i->index); // Assume savegame indices are sorted.
879 } else {
880 delete i;
883 return true;
886 static CompanyID _current_company_id;
887 static int32_t _old_yearly;
889 static const OldChunks _company_yearly_chunk[] = {
890 OCL_VAR( OC_INT32, 1, &_old_yearly ),
891 OCL_END()
894 static bool LoadOldCompanyYearly(LoadgameState *ls, int num)
896 Company *c = Company::Get(_current_company_id);
898 for (uint i = 0; i < 13; i++) {
899 if (_savegame_type == SGT_TTO && i == 6) {
900 _old_yearly = 0; // property maintenance
901 } else {
902 if (!LoadChunk(ls, nullptr, _company_yearly_chunk)) return false;
905 c->yearly_expenses[num][i] = _old_yearly;
908 return true;
911 static const OldChunks _company_economy_chunk[] = {
912 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, CompanyEconomyEntry, income ),
913 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, CompanyEconomyEntry, expenses ),
914 OCL_SVAR( OC_INT32, CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1] ),
915 OCL_SVAR( OC_INT32, CompanyEconomyEntry, performance_history ),
916 OCL_SVAR( OC_TTD | OC_FILE_I32 | OC_VAR_I64, CompanyEconomyEntry, company_value ),
918 OCL_END()
921 static bool LoadOldCompanyEconomy(LoadgameState *ls, int)
923 Company *c = Company::Get(_current_company_id);
925 if (!LoadChunk(ls, &c->cur_economy, _company_economy_chunk)) return false;
927 /* Don't ask, but the number in TTD(Patch) are inversed to OpenTTD */
928 c->cur_economy.income = -c->cur_economy.income;
929 c->cur_economy.expenses = -c->cur_economy.expenses;
931 for (uint i = 0; i < 24; i++) {
932 if (!LoadChunk(ls, &c->old_economy[i], _company_economy_chunk)) return false;
934 c->old_economy[i].income = -c->old_economy[i].income;
935 c->old_economy[i].expenses = -c->old_economy[i].expenses;
938 return true;
941 static const OldChunks _company_chunk[] = {
942 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
943 OCL_SVAR( OC_UINT32, Company, name_2 ),
944 OCL_SVAR( OC_UINT32, Company, face ),
945 OCL_VAR ( OC_UINT16, 1, &_old_string_id_2 ),
946 OCL_SVAR( OC_UINT32, Company, president_name_2 ),
948 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Company, money ),
949 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Company, current_loan ),
951 OCL_SVAR( OC_UINT8, Company, colour ),
952 OCL_SVAR( OC_UINT8, Company, money_fraction ),
953 OCL_SVAR( OC_UINT8, Company, months_of_bankruptcy ),
954 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Company, bankrupt_asked ),
955 OCL_SVAR( OC_FILE_U32 | OC_VAR_I64, Company, bankrupt_value ),
956 OCL_SVAR( OC_UINT16, Company, bankrupt_timeout ),
958 OCL_CNULL( OC_TTD, 4 ), // cargo_types
959 OCL_CNULL( OC_TTO, 2 ), // cargo_types
961 OCL_CHUNK( 3, LoadOldCompanyYearly ),
962 OCL_CHUNK( 1, LoadOldCompanyEconomy ),
964 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Company, inaugurated_year),
965 OCL_SVAR( OC_TILE, Company, last_build_coordinate ),
966 OCL_SVAR( OC_UINT8, Company, num_valid_stat_ent ),
968 OCL_NULL( 230 ), // Old AI
970 OCL_SVAR( OC_UINT8, Company, block_preview ),
971 OCL_CNULL( OC_TTD, 1 ), // Old AI
972 OCL_CNULL( OC_TTD, 1 ), // avail_railtypes
973 OCL_SVAR( OC_TILE, Company, location_of_HQ ),
975 OCL_CNULL( OC_TTD, 4 ), // Shares
977 OCL_CNULL( OC_TTD, 8 ), // junk at end of chunk
979 OCL_END()
982 static bool LoadOldCompany(LoadgameState *ls, int num)
984 Company *c = new (num) Company();
986 _current_company_id = (CompanyID)num;
988 if (!LoadChunk(ls, c, _company_chunk)) return false;
990 if (_old_string_id == 0) {
991 delete c;
992 return true;
995 if (_savegame_type == SGT_TTO) {
996 /* adjust manager's face */
997 if (HasBit(c->face, 27) && GB(c->face, 26, 1) == GB(c->face, 19, 1)) {
998 /* if face would be black in TTD, adjust tie colour and thereby face colour */
999 ClrBit(c->face, 27);
1002 /* Company name */
1003 if (_old_string_id == 0 || _old_string_id == 0x4C00) {
1004 _old_string_id = STR_SV_UNNAMED; // "Unnamed"
1005 } else if (GB(_old_string_id, 8, 8) == 0x52) {
1006 _old_string_id += 0x2A00; // Custom name
1007 } else {
1008 _old_string_id = RemapOldStringID(_old_string_id += 0x240D); // Automatic name
1010 c->name_1 = _old_string_id;
1012 /* Manager name */
1013 switch (_old_string_id_2) {
1014 case 0x4CDA: _old_string_id_2 = SPECSTR_PRESIDENT_NAME; break; // automatic name
1015 case 0x0006: _old_string_id_2 = STR_SV_EMPTY; break; // empty name
1016 default: _old_string_id_2 = _old_string_id_2 + 0x2A00; break; // custom name
1018 c->president_name_1 = _old_string_id_2;
1020 c->colour = RemapTTOColour(c->colour);
1022 if (num != 0) c->is_ai = true;
1023 } else {
1024 c->name_1 = RemapOldStringID(_old_string_id);
1025 c->president_name_1 = RemapOldStringID(_old_string_id_2);
1027 if (num == 0) {
1028 /* If the first company has no name, make sure we call it UNNAMED */
1029 if (c->name_1 == STR_NULL) {
1030 c->name_1 = STR_SV_UNNAMED;
1032 } else {
1033 /* Beside some multiplayer maps (1 on 1), which we don't official support,
1034 * all other companies are an AI.. mark them as such */
1035 c->is_ai = true;
1038 /* Sometimes it is better to not ask.. in old scenarios, the money
1039 * was always 893288 pounds. In the newer versions this is correct,
1040 * but correct for those oldies
1041 * Ps: this also means that if you had exact 893288 pounds, you will go back
1042 * to 100000.. this is a very VERY small chance ;) */
1043 if (c->money == 893288) c->money = c->current_loan = 100000;
1046 _company_colours[num] = c->colour;
1047 c->inaugurated_year -= EconomyTime::ORIGINAL_BASE_YEAR;
1049 return true;
1052 static uint32_t _old_order_ptr;
1053 static uint16_t _old_next_ptr;
1054 static VehicleID _current_vehicle_id;
1056 static const OldChunks vehicle_train_chunk[] = {
1057 OCL_SVAR( OC_UINT8, Train, track ),
1058 OCL_SVAR( OC_UINT8, Train, force_proceed ),
1059 OCL_SVAR( OC_UINT16, Train, crash_anim_pos ),
1060 OCL_SVAR( OC_UINT8, Train, railtype ),
1062 OCL_NULL( 5 ), ///< Junk
1064 OCL_END()
1067 static const OldChunks vehicle_road_chunk[] = {
1068 OCL_SVAR( OC_UINT8, RoadVehicle, state ),
1069 OCL_SVAR( OC_UINT8, RoadVehicle, frame ),
1070 OCL_SVAR( OC_UINT16, RoadVehicle, blocked_ctr ),
1071 OCL_SVAR( OC_UINT8, RoadVehicle, overtaking ),
1072 OCL_SVAR( OC_UINT8, RoadVehicle, overtaking_ctr ),
1073 OCL_SVAR( OC_UINT16, RoadVehicle, crashed_ctr ),
1074 OCL_SVAR( OC_UINT8, RoadVehicle, reverse_ctr ),
1076 OCL_NULL( 1 ), ///< Junk
1078 OCL_END()
1081 static const OldChunks vehicle_ship_chunk[] = {
1082 OCL_SVAR( OC_UINT8, Ship, state ),
1084 OCL_NULL( 9 ), ///< Junk
1086 OCL_END()
1089 static const OldChunks vehicle_air_chunk[] = {
1090 OCL_SVAR( OC_UINT8, Aircraft, pos ),
1091 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Aircraft, targetairport ),
1092 OCL_SVAR( OC_UINT16, Aircraft, crashed_counter ),
1093 OCL_SVAR( OC_UINT8, Aircraft, state ),
1095 OCL_NULL( 5 ), ///< Junk
1097 OCL_END()
1100 static const OldChunks vehicle_effect_chunk[] = {
1101 OCL_SVAR( OC_UINT16, EffectVehicle, animation_state ),
1102 OCL_SVAR( OC_UINT8, EffectVehicle, animation_substate ),
1104 OCL_NULL( 7 ), // Junk
1106 OCL_END()
1109 static const OldChunks vehicle_disaster_chunk[] = {
1110 OCL_SVAR( OC_UINT16, DisasterVehicle, image_override ),
1111 OCL_SVAR( OC_UINT16, DisasterVehicle, big_ufo_destroyer_target ),
1113 OCL_NULL( 6 ), ///< Junk
1115 OCL_END()
1118 static const OldChunks vehicle_empty_chunk[] = {
1119 OCL_NULL( 10 ), ///< Junk
1121 OCL_END()
1124 static bool LoadOldVehicleUnion(LoadgameState *ls, int)
1126 Vehicle *v = Vehicle::GetIfValid(_current_vehicle_id);
1127 uint temp = ls->total_read;
1128 bool res;
1130 if (v == nullptr) {
1131 res = LoadChunk(ls, nullptr, vehicle_empty_chunk);
1132 } else {
1133 switch (v->type) {
1134 default: SlErrorCorrupt("Invalid vehicle type");
1135 case VEH_TRAIN : res = LoadChunk(ls, v, vehicle_train_chunk); break;
1136 case VEH_ROAD : res = LoadChunk(ls, v, vehicle_road_chunk); break;
1137 case VEH_SHIP : res = LoadChunk(ls, v, vehicle_ship_chunk); break;
1138 case VEH_AIRCRAFT: res = LoadChunk(ls, v, vehicle_air_chunk); break;
1139 case VEH_EFFECT : res = LoadChunk(ls, v, vehicle_effect_chunk); break;
1140 case VEH_DISASTER: res = LoadChunk(ls, v, vehicle_disaster_chunk); break;
1144 /* This chunk size should always be 10 bytes */
1145 if (ls->total_read - temp != 10) {
1146 Debug(oldloader, 0, "Assert failed in VehicleUnion: invalid chunk size");
1147 return false;
1150 return res;
1153 static uint16_t _cargo_count;
1155 static const OldChunks vehicle_chunk[] = {
1156 OCL_SVAR( OC_UINT8, Vehicle, subtype ),
1158 OCL_NULL( 2 ), ///< Hash, calculated automatically
1159 OCL_NULL( 2 ), ///< Index, calculated automatically
1161 OCL_VAR ( OC_UINT32, 1, &_old_order_ptr ),
1162 OCL_VAR ( OC_UINT16, 1, &_old_order ),
1164 OCL_NULL ( 1 ), ///< num_orders, now calculated
1165 OCL_SVAR( OC_UINT8, Vehicle, cur_implicit_order_index ),
1166 OCL_SVAR( OC_TILE, Vehicle, dest_tile ),
1167 OCL_SVAR( OC_UINT16, Vehicle, load_unload_ticks ),
1168 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, date_of_last_service ),
1169 OCL_SVAR( OC_UINT16, Vehicle, service_interval ),
1170 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, last_station_visited ),
1171 OCL_SVAR( OC_TTD | OC_UINT8, Vehicle, tick_counter ),
1172 OCL_CNULL( OC_TTD, 2 ), ///< max_speed, now it is calculated.
1173 OCL_CNULL( OC_TTO, 1 ), ///< max_speed, now it is calculated.
1175 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Vehicle, x_pos ),
1176 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Vehicle, y_pos ),
1177 OCL_SVAR( OC_FILE_U8 | OC_VAR_I32, Vehicle, z_pos ),
1178 OCL_SVAR( OC_UINT8, Vehicle, direction ),
1179 OCL_NULL( 2 ), ///< x_offs and y_offs, calculated automatically
1180 OCL_NULL( 2 ), ///< x_extent and y_extent, calculated automatically
1181 OCL_NULL( 1 ), ///< z_extent, calculated automatically
1183 OCL_SVAR( OC_UINT8, Vehicle, owner ),
1184 OCL_SVAR( OC_TILE, Vehicle, tile ),
1185 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, sprite_cache.sprite_seq.seq[0].sprite ),
1187 OCL_NULL( 8 ), ///< Vehicle sprite box, calculated automatically
1189 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Vehicle, vehstatus ),
1190 OCL_SVAR( OC_TTD | OC_UINT16, Vehicle, cur_speed ),
1191 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Vehicle, cur_speed ),
1192 OCL_SVAR( OC_UINT8, Vehicle, subspeed ),
1193 OCL_SVAR( OC_UINT8, Vehicle, acceleration ),
1194 OCL_SVAR( OC_UINT8, Vehicle, progress ),
1196 OCL_SVAR( OC_UINT8, Vehicle, cargo_type ),
1197 OCL_SVAR( OC_TTD | OC_UINT16, Vehicle, cargo_cap ),
1198 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Vehicle, cargo_cap ),
1199 OCL_VAR ( OC_TTD | OC_UINT16, 1, &_cargo_count ),
1200 OCL_VAR ( OC_TTO | OC_FILE_U8 | OC_VAR_U16, 1, &_cargo_count ),
1201 OCL_VAR ( OC_UINT8, 1, &_cargo_source ),
1202 OCL_VAR ( OC_UINT8, 1, &_cargo_periods ),
1204 OCL_SVAR( OC_TTO | OC_UINT8, Vehicle, tick_counter ),
1206 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, age ),
1207 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, max_age ),
1208 OCL_SVAR( OC_FILE_U8 | OC_VAR_I32, Vehicle, build_year ),
1209 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, unitnumber ),
1211 OCL_SVAR( OC_TTD | OC_UINT16, Vehicle, engine_type ),
1212 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Vehicle, engine_type ),
1214 OCL_SVAR( OC_UINT8, Vehicle, spritenum ),
1215 OCL_SVAR( OC_UINT8, Vehicle, day_counter ),
1217 OCL_SVAR( OC_UINT8, Vehicle, breakdowns_since_last_service ),
1218 OCL_SVAR( OC_UINT8, Vehicle, breakdown_ctr ),
1219 OCL_SVAR( OC_UINT8, Vehicle, breakdown_delay ),
1220 OCL_SVAR( OC_UINT8, Vehicle, breakdown_chance ),
1222 OCL_CNULL( OC_TTO, 1 ),
1224 OCL_SVAR( OC_UINT16, Vehicle, reliability ),
1225 OCL_SVAR( OC_UINT16, Vehicle, reliability_spd_dec ),
1227 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Vehicle, profit_this_year ),
1228 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Vehicle, profit_last_year ),
1230 OCL_VAR ( OC_UINT16, 1, &_old_next_ptr ),
1232 OCL_SVAR( OC_FILE_U32 | OC_VAR_I64, Vehicle, value ),
1234 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
1236 OCL_CHUNK( 1, LoadOldVehicleUnion ),
1238 OCL_CNULL( OC_TTO, 24 ), ///< junk
1239 OCL_CNULL( OC_TTD, 20 ), ///< junk at end of struct (TTDPatch has some data in it)
1241 OCL_END()
1245 * Load the vehicles of an old style savegame.
1246 * @param ls State (buffer) of the currently loaded game.
1247 * @param num The number of vehicles to load.
1248 * @return True iff loading went without problems.
1250 bool LoadOldVehicle(LoadgameState *ls, int num)
1252 /* Read the TTDPatch flags, because we need some info from it */
1253 ReadTTDPatchFlags();
1255 for (uint i = 0; i < _old_vehicle_multiplier; i++) {
1256 _current_vehicle_id = num * _old_vehicle_multiplier + i;
1258 Vehicle *v;
1260 if (_savegame_type == SGT_TTO) {
1261 uint type = ReadByte(ls);
1262 switch (type) {
1263 default: return false;
1264 case 0x00 /* VEH_INVALID */: v = nullptr; break;
1265 case 0x25 /* MONORAIL */:
1266 case 0x20 /* VEH_TRAIN */: v = new (_current_vehicle_id) Train(); break;
1267 case 0x21 /* VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break;
1268 case 0x22 /* VEH_SHIP */: v = new (_current_vehicle_id) Ship(); break;
1269 case 0x23 /* VEH_AIRCRAFT */: v = new (_current_vehicle_id) Aircraft(); break;
1270 case 0x24 /* VEH_EFFECT */: v = new (_current_vehicle_id) EffectVehicle(); break;
1271 case 0x26 /* VEH_DISASTER */: v = new (_current_vehicle_id) DisasterVehicle(); break;
1274 if (!LoadChunk(ls, v, vehicle_chunk)) return false;
1275 if (v == nullptr) continue;
1276 v->refit_cap = v->cargo_cap;
1278 SpriteID sprite = v->sprite_cache.sprite_seq.seq[0].sprite;
1279 /* no need to override other sprites */
1280 if (IsInsideMM(sprite, 1460, 1465)) {
1281 sprite += 580; // aircraft smoke puff
1282 } else if (IsInsideMM(sprite, 2096, 2115)) {
1283 sprite += 977; // special effects part 1
1284 } else if (IsInsideMM(sprite, 2396, 2436)) {
1285 sprite += 1305; // special effects part 2
1286 } else if (IsInsideMM(sprite, 2516, 2539)) {
1287 sprite += 1385; // rotor or disaster-related vehicles
1289 v->sprite_cache.sprite_seq.seq[0].sprite = sprite;
1291 switch (v->type) {
1292 case VEH_TRAIN: {
1293 static const uint8_t spriteset_rail[] = {
1294 0, 2, 4, 4, 8, 10, 12, 14, 16, 18, 20, 22, 40, 42, 44, 46,
1295 48, 52, 54, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 120, 122,
1296 124, 126, 128, 130, 132, 134, 136, 138, 140
1298 if (v->spritenum / 2 >= lengthof(spriteset_rail)) return false;
1299 v->spritenum = spriteset_rail[v->spritenum / 2]; // adjust railway sprite set offset
1300 /* Should be the original values for monorail / rail, can't use RailType constants */
1301 Train::From(v)->railtype = static_cast<RailType>(type == 0x25 ? 1 : 0);
1302 break;
1305 case VEH_ROAD:
1306 if (v->spritenum >= 22) v->spritenum += 12;
1307 break;
1309 case VEH_SHIP:
1310 v->spritenum += 2;
1312 switch (v->spritenum) {
1313 case 2: // oil tanker && cargo type != oil
1314 if (v->cargo_type != 3) v->spritenum = 0; // make it a coal/goods ship
1315 break;
1316 case 4: // passenger ship && cargo type == mail
1317 if (v->cargo_type == 2) v->spritenum = 0; // make it a mail ship
1318 break;
1319 default:
1320 break;
1322 break;
1324 default:
1325 break;
1328 switch (_old_string_id) {
1329 case 0x0000: break; // empty (invalid vehicles)
1330 case 0x0006: _old_string_id = STR_SV_EMPTY; break; // empty (special vehicles)
1331 case 0x8495: _old_string_id = STR_SV_TRAIN_NAME; break; // "Train X"
1332 case 0x8842: _old_string_id = STR_SV_ROAD_VEHICLE_NAME; break; // "Road Vehicle X"
1333 case 0x8C3B: _old_string_id = STR_SV_SHIP_NAME; break; // "Ship X"
1334 case 0x9047: _old_string_id = STR_SV_AIRCRAFT_NAME; break; // "Aircraft X"
1335 default: _old_string_id += 0x2A00; break; // custom name
1338 _old_vehicle_names[_current_vehicle_id] = _old_string_id;
1339 } else {
1340 /* Read the vehicle type and allocate the right vehicle */
1341 switch (ReadByte(ls)) {
1342 default: SlErrorCorrupt("Invalid vehicle type");
1343 case 0x00 /* VEH_INVALID */: v = nullptr; break;
1344 case 0x10 /* VEH_TRAIN */: v = new (_current_vehicle_id) Train(); break;
1345 case 0x11 /* VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break;
1346 case 0x12 /* VEH_SHIP */: v = new (_current_vehicle_id) Ship(); break;
1347 case 0x13 /* VEH_AIRCRAFT*/: v = new (_current_vehicle_id) Aircraft(); break;
1348 case 0x14 /* VEH_EFFECT */: v = new (_current_vehicle_id) EffectVehicle(); break;
1349 case 0x15 /* VEH_DISASTER*/: v = new (_current_vehicle_id) DisasterVehicle(); break;
1352 if (!LoadChunk(ls, v, vehicle_chunk)) return false;
1353 if (v == nullptr) continue;
1355 _old_vehicle_names[_current_vehicle_id] = RemapOldStringID(_old_string_id);
1357 /* This should be consistent, else we have a big problem... */
1358 if (v->index != _current_vehicle_id) {
1359 Debug(oldloader, 0, "Loading failed - vehicle-array is invalid");
1360 return false;
1364 if (_old_order_ptr != 0 && _old_order_ptr != 0xFFFFFFFF) {
1365 uint max = _savegame_type == SGT_TTO ? 3000 : 5000;
1366 uint old_id = RemapOrderIndex(_old_order_ptr);
1367 if (old_id < max) v->old_orders = Order::Get(old_id); // don't accept orders > max number of orders
1369 v->current_order.AssignOrder(UnpackOldOrder(_old_order));
1371 if (v->type == VEH_DISASTER) {
1372 DisasterVehicle::From(v)->state = UnpackOldOrder(_old_order).GetDestination();
1375 v->next = (Vehicle *)(size_t)_old_next_ptr;
1377 if (_cargo_count != 0 && CargoPacket::CanAllocateItem()) {
1378 StationID source = (_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
1379 TileIndex source_xy = (source != INVALID_STATION) ? Station::Get(source)->xy : (TileIndex)0;
1380 v->cargo.Append(new CargoPacket(_cargo_count, _cargo_periods, source, source_xy, 0));
1384 return true;
1387 static const OldChunks sign_chunk[] = {
1388 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
1389 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Sign, x ),
1390 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Sign, y ),
1391 OCL_SVAR( OC_FILE_U16 | OC_VAR_I8, Sign, z ),
1393 OCL_NULL( 6 ), ///< Width of sign, no longer in use
1395 OCL_END()
1398 static bool LoadOldSign(LoadgameState *ls, int num)
1400 Sign *si = new (num) Sign();
1401 if (!LoadChunk(ls, si, sign_chunk)) return false;
1403 if (_old_string_id != 0) {
1404 if (_savegame_type == SGT_TTO) {
1405 if (_old_string_id != 0x140A) si->name = CopyFromOldName(_old_string_id + 0x2A00);
1406 } else {
1407 si->name = CopyFromOldName(RemapOldStringID(_old_string_id));
1409 si->owner = OWNER_NONE;
1410 } else {
1411 delete si;
1414 return true;
1417 static const OldChunks engine_chunk[] = {
1418 OCL_SVAR( OC_UINT16, Engine, company_avail ),
1419 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Engine, intro_date ),
1420 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Engine, age ),
1421 OCL_SVAR( OC_UINT16, Engine, reliability ),
1422 OCL_SVAR( OC_UINT16, Engine, reliability_spd_dec ),
1423 OCL_SVAR( OC_UINT16, Engine, reliability_start ),
1424 OCL_SVAR( OC_UINT16, Engine, reliability_max ),
1425 OCL_SVAR( OC_UINT16, Engine, reliability_final ),
1426 OCL_SVAR( OC_UINT16, Engine, duration_phase_1 ),
1427 OCL_SVAR( OC_UINT16, Engine, duration_phase_2 ),
1428 OCL_SVAR( OC_UINT16, Engine, duration_phase_3 ),
1430 OCL_NULL( 1 ), // lifelength
1431 OCL_SVAR( OC_UINT8, Engine, flags ),
1432 OCL_NULL( 1 ), // preview_company_rank
1433 OCL_SVAR( OC_UINT8, Engine, preview_wait ),
1435 OCL_CNULL( OC_TTD, 2 ), ///< railtype + junk
1437 OCL_END()
1440 static bool LoadOldEngine(LoadgameState *ls, int num)
1442 Engine *e = _savegame_type == SGT_TTO ? &_old_engines[num] : GetTempDataEngine(num);
1443 return LoadChunk(ls, e, engine_chunk);
1446 static bool LoadOldEngineName(LoadgameState *ls, int num)
1448 Engine *e = GetTempDataEngine(num);
1449 e->name = CopyFromOldName(RemapOldStringID(ReadUint16(ls)));
1450 return true;
1453 static const OldChunks subsidy_chunk[] = {
1454 OCL_SVAR( OC_UINT8, Subsidy, cargo_type ),
1455 OCL_SVAR( OC_UINT8, Subsidy, remaining ),
1456 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Subsidy, src ),
1457 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Subsidy, dst ),
1459 OCL_END()
1462 static bool LoadOldSubsidy(LoadgameState *ls, int num)
1464 Subsidy *s = new (num) Subsidy();
1465 bool ret = LoadChunk(ls, s, subsidy_chunk);
1466 if (!IsValidCargoType(s->cargo_type)) delete s;
1467 return ret;
1470 static const OldChunks game_difficulty_chunk[] = {
1471 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, max_no_competitors ),
1472 OCL_NULL( 2), // competitor_start_time
1473 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, number_towns ),
1474 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, industry_density ),
1475 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, DifficultySettings, max_loan ),
1476 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, initial_interest ),
1477 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, vehicle_costs ),
1478 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, competitor_speed ),
1479 OCL_NULL( 2), // competitor_intelligence
1480 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, vehicle_breakdowns ),
1481 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, subsidy_multiplier ),
1482 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, construction_cost ),
1483 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, terrain_type ),
1484 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, quantity_sea_lakes ),
1485 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, economy ),
1486 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, line_reverse_mode ),
1487 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, disasters ),
1488 OCL_END()
1491 static bool LoadOldGameDifficulty(LoadgameState *ls, int)
1493 bool ret = LoadChunk(ls, &_settings_game.difficulty, game_difficulty_chunk);
1494 _settings_game.difficulty.max_loan *= 1000;
1495 return ret;
1499 static bool LoadOldMapPart1(LoadgameState *ls, int)
1501 if (_savegame_type == SGT_TTO) {
1502 Map::Allocate(OLD_MAP_SIZE, OLD_MAP_SIZE);
1505 for (auto t : Map::Iterate()) {
1506 t.m1() = ReadByte(ls);
1508 for (auto t : Map::Iterate()) {
1509 t.m2() = ReadByte(ls);
1512 if (_savegame_type != SGT_TTO) {
1513 /* old map3 is split into to m3 and m4 */
1514 for (auto t : Map::Iterate()) {
1515 t.m3() = ReadByte(ls);
1516 t.m4() = ReadByte(ls);
1518 auto range = Map::Iterate();
1519 for (auto it = range.begin(); it != range.end(); /* nothing. */) {
1520 uint8_t b = ReadByte(ls);
1521 for (int i = 0; i < 8; i += 2, ++it) (*it).m6() = GB(b, i, 2);
1525 return true;
1528 static bool LoadOldMapPart2(LoadgameState *ls, int)
1530 for (auto t : Map::Iterate()) {
1531 t.type() = ReadByte(ls);
1533 for (auto t : Map::Iterate()) {
1534 t.m5() = ReadByte(ls);
1537 return true;
1540 static bool LoadTTDPatchExtraChunks(LoadgameState *ls, int)
1542 ReadTTDPatchFlags();
1544 Debug(oldloader, 2, "Found {} extra chunk(s)", _old_extra_chunk_nums);
1546 for (int i = 0; i != _old_extra_chunk_nums; i++) {
1547 uint16_t id = ReadUint16(ls);
1548 uint32_t len = ReadUint32(ls);
1550 switch (id) {
1551 /* List of GRFIDs, used in the savegame. 0x8004 is the new ID
1552 * They are saved in a 'GRFID:4 active:1' format, 5 bytes for each entry */
1553 case 0x2:
1554 case 0x8004: {
1555 /* Skip the first element: TTDP hack for the Action D special variables (FFFF0000 01) */
1556 ReadUint32(ls); ReadByte(ls); len -= 5;
1558 ClearGRFConfigList(_grfconfig);
1559 while (len != 0) {
1560 uint32_t grfid = ReadUint32(ls);
1562 if (ReadByte(ls) == 1) {
1563 auto c = std::make_unique<GRFConfig>("TTDP game, no information");
1564 c->ident.grfid = grfid;
1566 Debug(oldloader, 3, "TTDPatch game using GRF file with GRFID {:08X}", std::byteswap(c->ident.grfid));
1567 AppendToGRFConfigList(_grfconfig, std::move(c));
1569 len -= 5;
1572 /* Append static NewGRF configuration */
1573 AppendStaticGRFConfigs(_grfconfig);
1574 break;
1577 /* TTDPatch version and configuration */
1578 case 0x3:
1579 _ttdp_version = ReadUint32(ls);
1580 Debug(oldloader, 3, "Game saved with TTDPatch version {}.{}.{} r{}",
1581 GB(_ttdp_version, 24, 8), GB(_ttdp_version, 20, 4), GB(_ttdp_version, 16, 4), GB(_ttdp_version, 0, 16));
1582 len -= 4;
1583 while (len-- != 0) ReadByte(ls); // skip the configuration
1584 break;
1586 default:
1587 Debug(oldloader, 4, "Skipping unknown extra chunk {}", id);
1588 while (len-- != 0) ReadByte(ls);
1589 break;
1593 return true;
1596 extern TileIndex _cur_tileloop_tile;
1597 extern uint16_t _disaster_delay;
1598 extern uint8_t _trees_tick_ctr;
1599 extern uint8_t _age_cargo_skip_counter; // From misc_sl.cpp
1600 extern uint8_t _old_diff_level;
1601 extern uint8_t _old_units;
1602 static const OldChunks main_chunk[] = {
1603 OCL_ASSERT( OC_TTD, 0 ),
1604 OCL_ASSERT( OC_TTO, 0 ),
1605 OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &TimerGameCalendar::date ),
1606 OCL_VAR ( OC_UINT16, 1, &TimerGameCalendar::date_fract ),
1607 OCL_NULL( 600 ), ///< TextEffects
1608 OCL_VAR ( OC_UINT32, 2, &_random.state ),
1610 OCL_ASSERT( OC_TTD, 0x264 ),
1611 OCL_ASSERT( OC_TTO, 0x264 ),
1613 OCL_CCHUNK( OC_TTD, 70, LoadOldTown ),
1614 OCL_CCHUNK( OC_TTO, 80, LoadOldTown ),
1616 OCL_ASSERT( OC_TTD, 0x1C18 ),
1617 OCL_ASSERT( OC_TTO, 0x1AC4 ),
1619 OCL_CCHUNK( OC_TTD, 5000, LoadOldOrder ),
1620 OCL_CCHUNK( OC_TTO, 3000, LoadOldOrder ),
1622 OCL_ASSERT( OC_TTD, 0x4328 ),
1623 OCL_ASSERT( OC_TTO, 0x3234 ),
1625 OCL_CHUNK( 1, LoadOldAnimTileList ),
1626 OCL_NULL( 4 ), ///< old end-of-order-list-pointer, no longer in use
1628 OCL_ASSERT( OC_TTO, 0x3438 ),
1630 OCL_CCHUNK( OC_TTD, 255, LoadOldDepot ),
1631 OCL_CCHUNK( OC_TTO, 252, LoadOldDepot ),
1633 OCL_ASSERT( OC_TTD, 0x4B26 ),
1634 OCL_ASSERT( OC_TTO, 0x3A20 ),
1636 OCL_NULL( 4 ), ///< town counter, no longer in use
1637 OCL_NULL( 2 ), ///< timer_counter, no longer in use
1638 OCL_NULL( 2 ), ///< land_code, no longer in use
1640 OCL_VAR ( OC_FILE_U16 | OC_VAR_U8, 1, &_age_cargo_skip_counter ),
1641 OCL_VAR ( OC_FILE_U16 | OC_VAR_U64, 1, &TimerGameTick::counter ),
1642 OCL_VAR ( OC_TILE, 1, &_cur_tileloop_tile ),
1644 OCL_ASSERT( OC_TTO, 0x3A2E ),
1646 OCL_CNULL( OC_TTO, 48 * 6 ), ///< prices
1647 OCL_CNULL( OC_TTD, 49 * 6 ), ///< prices
1649 OCL_ASSERT( OC_TTO, 0x3B4E ),
1651 OCL_CNULL( OC_TTO, 11 * 8 ), ///< cargo payment rates
1652 OCL_CNULL( OC_TTD, 12 * 8 ), ///< cargo payment rates
1654 OCL_ASSERT( OC_TTD, 0x4CBA ),
1655 OCL_ASSERT( OC_TTO, 0x3BA6 ),
1657 OCL_CHUNK( 1, LoadOldMapPart1 ),
1659 OCL_ASSERT( OC_TTD, 0x48CBA ),
1660 OCL_ASSERT( OC_TTO, 0x23BA6 ),
1662 OCL_CCHUNK( OC_TTD, 250, LoadOldStation ),
1663 OCL_CCHUNK( OC_TTO, 200, LoadOldStation ),
1665 OCL_ASSERT( OC_TTO, 0x29E16 ),
1667 OCL_CCHUNK( OC_TTD, 90, LoadOldIndustry ),
1668 OCL_CCHUNK( OC_TTO, 100, LoadOldIndustry ),
1670 OCL_ASSERT( OC_TTO, 0x2ADB6 ),
1672 OCL_CHUNK( 8, LoadOldCompany ),
1674 OCL_ASSERT( OC_TTD, 0x547F2 ),
1675 OCL_ASSERT( OC_TTO, 0x2C746 ),
1677 OCL_CCHUNK( OC_TTD, 850, LoadOldVehicle ),
1678 OCL_CCHUNK( OC_TTO, 800, LoadOldVehicle ),
1680 OCL_ASSERT( OC_TTD, 0x6F0F2 ),
1681 OCL_ASSERT( OC_TTO, 0x45746 ),
1683 OCL_VAR ( OC_TTD | OC_UINT8 | OC_DEREFERENCE_POINTER, 32 * 500, &_old_name_array ),
1684 OCL_VAR ( OC_TTO | OC_UINT8 | OC_DEREFERENCE_POINTER, 24 * 200, &_old_name_array ),
1686 OCL_ASSERT( OC_TTO, 0x46A06 ),
1688 OCL_NULL( 0x2000 ), ///< Old hash-table, no longer in use
1690 OCL_CHUNK( 40, LoadOldSign ),
1692 OCL_ASSERT( OC_TTO, 0x48C36 ),
1694 OCL_CCHUNK( OC_TTD, 256, LoadOldEngine ),
1695 OCL_CCHUNK( OC_TTO, 103, LoadOldEngine ),
1697 OCL_ASSERT( OC_TTO, 0x496AC ),
1699 OCL_NULL ( 2 ), // _vehicle_id_ctr_day
1701 OCL_CHUNK( 8, LoadOldSubsidy ),
1703 OCL_ASSERT( OC_TTO, 0x496CE ),
1705 OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &_new_competitor_timeout.period.value ),
1707 OCL_CNULL( OC_TTO, 2 ), ///< available monorail bitmask
1709 OCL_VAR ( OC_FILE_I16 | OC_VAR_I32, 1, &_saved_scrollpos_x ),
1710 OCL_VAR ( OC_FILE_I16 | OC_VAR_I32, 1, &_saved_scrollpos_y ),
1711 OCL_VAR ( OC_FILE_U16 | OC_VAR_U8, 1, &_saved_scrollpos_zoom ),
1713 OCL_NULL( 4 ), ///< max_loan
1714 OCL_VAR ( OC_FILE_U32 | OC_VAR_I64, 1, &_economy.old_max_loan_unround ),
1715 OCL_VAR ( OC_INT16, 1, &_economy.fluct ),
1717 OCL_VAR ( OC_UINT16, 1, &_disaster_delay ),
1719 OCL_ASSERT( OC_TTO, 0x496E4 ),
1721 OCL_CNULL( OC_TTD, 144 ), ///< cargo-stuff
1723 OCL_CCHUNK( OC_TTD, 256, LoadOldEngineName ),
1725 OCL_CNULL( OC_TTD, 144 ), ///< AI cargo-stuff
1726 OCL_NULL( 2 ), ///< Company indexes of companies, no longer in use
1727 OCL_NULL( 1 ), ///< Station tick counter, no longer in use
1729 OCL_VAR ( OC_UINT8, 1, &_settings_game.locale.currency ),
1730 OCL_VAR ( OC_UINT8, 1, &_old_units ),
1731 OCL_VAR ( OC_FILE_U8 | OC_VAR_U32, 1, &_cur_company_tick_index ),
1733 OCL_NULL( 2 ), ///< Date stuff, calculated automatically
1734 OCL_NULL( 8 ), ///< Company colours, calculated automatically
1736 OCL_VAR ( OC_UINT8, 1, &_economy.infl_amount ),
1737 OCL_VAR ( OC_UINT8, 1, &_economy.infl_amount_pr ),
1738 OCL_VAR ( OC_UINT8, 1, &_economy.interest_rate ),
1739 OCL_NULL( 1 ), // available airports
1740 OCL_VAR ( OC_UINT8, 1, &_settings_game.vehicle.road_side ),
1741 OCL_VAR ( OC_UINT8, 1, &_settings_game.game_creation.town_name ),
1743 OCL_CHUNK( 1, LoadOldGameDifficulty ),
1745 OCL_ASSERT( OC_TTD, 0x77130 ),
1747 OCL_VAR ( OC_UINT8, 1, &_old_diff_level ),
1749 OCL_VAR ( OC_TTD | OC_UINT8, 1, &_settings_game.game_creation.landscape ),
1750 OCL_VAR ( OC_TTD | OC_UINT8, 1, &_trees_tick_ctr ),
1752 OCL_CNULL( OC_TTD, 1 ), ///< Custom vehicle types yes/no, no longer used
1753 OCL_VAR ( OC_TTD | OC_UINT8, 1, &_settings_game.game_creation.snow_line_height ),
1755 OCL_CNULL( OC_TTD, 32 ), ///< new_industry_randtable, no longer used (because of new design)
1756 OCL_CNULL( OC_TTD, 36 ), ///< cargo-stuff
1758 OCL_ASSERT( OC_TTD, 0x77179 ),
1759 OCL_ASSERT( OC_TTO, 0x4971D ),
1761 OCL_CHUNK( 1, LoadOldMapPart2 ),
1763 OCL_ASSERT( OC_TTD, 0x97179 ),
1764 OCL_ASSERT( OC_TTO, 0x6971D ),
1766 /* Below any (if available) extra chunks from TTDPatch can follow */
1767 OCL_CHUNK(1, LoadTTDPatchExtraChunks),
1769 OCL_END()
1772 bool LoadTTDMain(LoadgameState *ls)
1774 Debug(oldloader, 3, "Reading main chunk...");
1776 _read_ttdpatch_flags = false;
1778 /* Load the biggest chunk */
1779 _old_vehicle_names = nullptr;
1780 try {
1781 if (!LoadChunk(ls, nullptr, main_chunk)) {
1782 Debug(oldloader, 0, "Loading failed");
1783 free(_old_vehicle_names);
1784 return false;
1786 } catch (...) {
1787 free(_old_vehicle_names);
1788 throw;
1791 Debug(oldloader, 3, "Done, converting game data...");
1793 FixTTDMapArray();
1794 FixTTDDepots();
1796 /* Fix some general stuff */
1797 if (to_underlying(_settings_game.game_creation.landscape) >= NUM_LANDSCAPE) _settings_game.game_creation.landscape = LandscapeType::Temperate;
1799 /* Fix the game to be compatible with OpenTTD */
1800 FixOldTowns();
1801 FixOldVehicles();
1803 /* We have a new difficulty setting */
1804 _settings_game.difficulty.town_council_tolerance = Clamp(_old_diff_level, 0, 2);
1806 Debug(oldloader, 3, "Finished converting game data");
1807 Debug(oldloader, 1, "TTD(Patch) savegame successfully converted");
1809 free(_old_vehicle_names);
1811 return true;
1814 bool LoadTTOMain(LoadgameState *ls)
1816 Debug(oldloader, 3, "Reading main chunk...");
1818 _read_ttdpatch_flags = false;
1820 std::array<uint8_t, 103 * sizeof(Engine)> engines; // we don't want to call Engine constructor here
1821 _old_engines = (Engine *)engines.data();
1822 std::array<StringID, 800> vehnames;
1823 _old_vehicle_names = vehnames.data();
1825 /* Load the biggest chunk */
1826 if (!LoadChunk(ls, nullptr, main_chunk)) {
1827 Debug(oldloader, 0, "Loading failed");
1828 return false;
1830 Debug(oldloader, 3, "Done, converting game data...");
1832 if (_settings_game.game_creation.town_name != 0) _settings_game.game_creation.town_name++;
1834 _settings_game.game_creation.landscape = LandscapeType::Temperate;
1835 _trees_tick_ctr = 0xFF;
1837 if (!FixTTOMapArray() || !FixTTOEngines()) {
1838 Debug(oldloader, 0, "Conversion failed");
1839 return false;
1842 FixOldTowns();
1843 FixOldVehicles();
1844 FixTTOCompanies();
1846 /* We have a new difficulty setting */
1847 _settings_game.difficulty.town_council_tolerance = Clamp(_old_diff_level, 0, 2);
1849 /* SVXConverter about cargo payment rates correction:
1850 * "increase them to compensate for the faster time advance in TTD compared to TTO
1851 * which otherwise would cause much less income while the annual running costs of
1852 * the vehicles stay the same" */
1853 _economy.inflation_payment = std::min(_economy.inflation_payment * 124 / 74, MAX_INFLATION);
1855 Debug(oldloader, 3, "Finished converting game data");
1856 Debug(oldloader, 1, "TTO savegame successfully converted");
1858 return true;