diff options
author | KUDr <kudr@openttd.org> | 2007-01-10 18:12:09 +0000 |
---|---|---|
committer | KUDr <kudr@openttd.org> | 2007-01-10 18:12:09 +0000 |
commit | e373ea7096c741a8189f7a480863fd21dd6f6be1 (patch) | |
tree | d9abc3d9810159441bed9f82a52bd1ee52d770dd /src/oldloader.c | |
parent | 001d858b528d78743deaf7dcea46ea8f0736bad9 (diff) | |
download | openttd-e373ea7096c741a8189f7a480863fd21dd6f6be1.tar.xz |
(svn r8033) [cpp] - Prepare for merge from branches/cpp (all .c files renamed to .cpp)
Diffstat (limited to 'src/oldloader.c')
-rw-r--r-- | src/oldloader.c | 1583 |
1 files changed, 0 insertions, 1583 deletions
diff --git a/src/oldloader.c b/src/oldloader.c deleted file mode 100644 index f6a56fdd6..000000000 --- a/src/oldloader.c +++ /dev/null @@ -1,1583 +0,0 @@ -/* $Id$ */ - -#include "stdafx.h" -#include "openttd.h" -#include "station_map.h" -#include "table/strings.h" -#include "functions.h" -#include "map.h" -#include "town.h" -#include "industry.h" -#include "station.h" -#include "economy.h" -#include "player.h" -#include "engine.h" -#include "vehicle.h" -#include "signs.h" -#include "debug.h" -#include "depot.h" -#include "network/network.h" -#include "ai/ai.h" -#include "date.h" - -enum { - HEADER_SIZE = 49, - BUFFER_SIZE = 4096, - - OLD_MAP_SIZE = 256 * 256 -}; - -typedef struct LoadgameState { - FILE *file; - - uint chunk_size; - - bool decoding; - byte decode_char; - - uint buffer_count; - uint buffer_cur; - byte buffer[BUFFER_SIZE]; - - uint total_read; - bool failed; -} LoadgameState; - -/* OldChunk-Type */ -typedef enum OldChunkTypes { - OC_SIMPLE = 0, - OC_NULL = 1, - OC_CHUNK = 2, - OC_ASSERT = 3, - /* 8 bytes allocated (256 max) */ - - OC_VAR_I8 = 1 << 8, - OC_VAR_U8 = 2 << 8, - OC_VAR_I16 = 3 << 8, - OC_VAR_U16 = 4 << 8, - OC_VAR_I32 = 5 << 8, - OC_VAR_U32 = 6 << 8, - OC_VAR_I64 = 7 << 8, - /* 8 bytes allocated (256 max) */ - - OC_FILE_I8 = 1 << 16, - OC_FILE_U8 = 2 << 16, - OC_FILE_I16 = 3 << 16, - OC_FILE_U16 = 4 << 16, - OC_FILE_I32 = 5 << 16, - OC_FILE_U32 = 6 << 16, - /* 8 bytes allocated (256 max) */ - - OC_INT8 = OC_VAR_I8 | OC_FILE_I8, - OC_UINT8 = OC_VAR_U8 | OC_FILE_U8, - OC_INT16 = OC_VAR_I16 | OC_FILE_I16, - OC_UINT16 = OC_VAR_U16 | OC_FILE_U16, - OC_INT32 = OC_VAR_I32 | OC_FILE_I32, - OC_UINT32 = OC_VAR_U32 | OC_FILE_U32, - - OC_TILE = OC_VAR_U32 | OC_FILE_U16, - - OC_END = 0 ///< End of the whole chunk, all 32bits set to zero -} OldChunkType; - -typedef bool OldChunkProc(LoadgameState *ls, int num); - -typedef struct OldChunks { - OldChunkType type; ///< Type of field - uint32 amount; ///< Amount of fields - - void *ptr; ///< Pointer where to save the data (may only be set if offset is 0) - uint offset; ///< Offset from basepointer (may only be set if ptr is NULL) - OldChunkProc *proc; ///< Pointer to function that is called with OC_CHUNK -} OldChunks; - -/* If it fails, check lines above.. */ -assert_compile(sizeof(TileIndex) == 4); - -static uint32 _bump_assert_value; -static bool _read_ttdpatch_flags; - -static OldChunkType GetOldChunkType(OldChunkType type) {return GB(type, 0, 8);} -static OldChunkType GetOldChunkVarType(OldChunkType type) {return GB(type, 8, 8) << 8;} -static OldChunkType GetOldChunkFileType(OldChunkType type) {return GB(type, 16, 8) << 16;} - -static inline byte CalcOldVarLen(OldChunkType type) -{ - static const byte type_mem_size[] = {0, 1, 1, 2, 2, 4, 4, 8}; - byte length = GB(type, 8, 8); - assert(length != 0 && length < lengthof(type_mem_size)); - return type_mem_size[length]; -} - -/** - * - * Reads a byte from a file (do not call yourself, use ReadByte()) - * - */ -static byte ReadByteFromFile(LoadgameState *ls) -{ - /* To avoid slow reads, we read BUFFER_SIZE of bytes per time - and just return a byte per time */ - if (ls->buffer_cur >= ls->buffer_count) { - /* Read some new bytes from the file */ - int count = (int)fread(ls->buffer, 1, BUFFER_SIZE, ls->file); - - /* We tried to read, but there is nothing in the file anymore.. */ - if (count == 0) { - DEBUG(oldloader, 0, "Read past end of file, loading failed"); - ls->failed = true; - } - - ls->buffer_count = count; - ls->buffer_cur = 0; - } - - return ls->buffer[ls->buffer_cur++]; -} - -/** - * - * Reads a byte from the buffer and decompress if needed - * - */ -static byte ReadByte(LoadgameState *ls) -{ - /* Old savegames have a nice compression algorithm (RLE) - which means that we have a chunk, which starts with a length - byte. If that byte is negative, we have to repeat the next byte - that many times (+1). Else, we need to read that amount of bytes. - Works pretty good if you have many zero's behind eachother */ - - if (ls->chunk_size == 0) { - /* Read new chunk */ - int8 new_byte = ReadByteFromFile(ls); - - if (new_byte < 0) { - /* Repeat next char for new_byte times */ - ls->decoding = true; - ls->decode_char = ReadByteFromFile(ls); - ls->chunk_size = -new_byte + 1; - } else { - ls->decoding = false; - ls->chunk_size = new_byte + 1; - } - } - - ls->total_read++; - ls->chunk_size--; - - return ls->decoding ? ls->decode_char : ReadByteFromFile(ls); -} - -static inline uint16 ReadUint16(LoadgameState *ls) -{ - byte x = ReadByte(ls); - return x | ReadByte(ls) << 8; -} - -static inline uint32 ReadUint32(LoadgameState *ls) -{ - uint16 x = ReadUint16(ls); - return x | ReadUint16(ls) << 16; -} - -/** - * - * Loads a chunk from the old savegame - * - */ -static bool LoadChunk(LoadgameState *ls, void *base, const OldChunks *chunks) -{ - const OldChunks *chunk = chunks; - byte *base_ptr = base; - - while (chunk->type != OC_END) { - byte* ptr = chunk->ptr; - uint i; - - for (i = 0; i < chunk->amount; i++) { - if (ls->failed) return false; - - /* Handle simple types */ - if (GetOldChunkType(chunk->type) != 0) { - switch (GetOldChunkType(chunk->type)) { - /* Just read the byte and forget about it */ - case OC_NULL: ReadByte(ls); break; - - case OC_CHUNK: - /* Call function, with 'i' as parameter to tell which item we - * are going to read */ - if (!chunk->proc(ls, i)) return false; - break; - - case OC_ASSERT: - DEBUG(oldloader, 4, "Assert point: 0x%X / 0x%X", ls->total_read, chunk->offset + _bump_assert_value); - if (ls->total_read != chunk->offset + _bump_assert_value) ls->failed = true; - default: break; - } - } else { - uint32 res = 0; - - /* Reading from the file: bits 16 to 23 have the FILE type */ - switch (GetOldChunkFileType(chunk->type)) { - case OC_FILE_I8: res = (int8)ReadByte(ls); break; - case OC_FILE_U8: res = ReadByte(ls); break; - case OC_FILE_I16: res = (int16)ReadUint16(ls); break; - case OC_FILE_U16: res = ReadUint16(ls); break; - case OC_FILE_I32: res = (int32)ReadUint32(ls); break; - case OC_FILE_U32: res = ReadUint32(ls); break; - default: NOT_REACHED(); - } - - /* Sanity check */ - assert(base_ptr != NULL || chunk->ptr != NULL); - - /* Writing to the var: bits 8 to 15 have the VAR type */ - if (chunk->ptr == NULL) ptr = base_ptr + chunk->offset; - - /* Write the data */ - switch (GetOldChunkVarType(chunk->type)) { - case OC_VAR_I8: *(int8 *)ptr = GB(res, 0, 8); break; - case OC_VAR_U8: *(uint8 *)ptr = GB(res, 0, 8); break; - case OC_VAR_I16:*(int16 *)ptr = GB(res, 0, 16); break; - case OC_VAR_U16:*(uint16*)ptr = GB(res, 0, 16); break; - case OC_VAR_I32:*(int32 *)ptr = res; break; - case OC_VAR_U32:*(uint32*)ptr = res; break; - case OC_VAR_I64:*(int64 *)ptr = res; break; - default: NOT_REACHED(); - } - - /* Increase pointer base for arrays when looping */ - if (chunk->amount > 1 && chunk->ptr != NULL) ptr += CalcOldVarLen(chunk->type); - } - } - - chunk++; - } - - return true; -} - -/** - * - * Initialize some data before reading - * - */ -static void InitLoading(LoadgameState *ls) -{ - ls->chunk_size = 0; - ls->total_read = 0; - ls->failed = false; - - ls->decoding = false; - ls->decode_char = 0; - - ls->buffer_cur = 0; - ls->buffer_count = 0; - memset(ls->buffer, 0, BUFFER_SIZE); - - _bump_assert_value = 0; - - _read_ttdpatch_flags = false; -} - - -/* - * Begin -- Stuff to fix the savegames to be OpenTTD compatible - */ - -extern uint32 GetOldTownName(uint32 townnameparts, byte old_town_name_type); - -static void FixOldTowns(void) -{ - Town *town; - - /* Convert town-names if needed */ - FOR_ALL_TOWNS(town) { - if (IS_INT_INSIDE(town->townnametype, 0x20C1, 0x20C3)) { - town->townnametype = SPECSTR_TOWNNAME_ENGLISH + _opt.town_name; - town->townnameparts = GetOldTownName(town->townnameparts, _opt.town_name); - } - } -} - -static void FixOldStations(void) -{ - Station *st; - - FOR_ALL_STATIONS(st) { - /* Check if we need to swap width and height for the station */ - if (st->train_tile != 0 && GetRailStationAxis(st->train_tile) != AXIS_X) { - swap_byte(&st->trainst_w, &st->trainst_h); - } - - /* Check if there is a bus or truck station, and convert to new format */ - if (st->bus_tile_obsolete != 0) { - st->bus_stops = AllocateRoadStop(); - st->bus_stops->xy = st->bus_tile_obsolete; - st->bus_stops->used = true; - st->bus_stops->status = 3; - st->bus_stops->station = st->index; - st->bus_stops->next = NULL; - st->bus_stops->prev = NULL; - st->bus_stops->num_vehicles = 0; - } - - if (st->lorry_tile_obsolete != 0) { - st->truck_stops = AllocateRoadStop(); - st->truck_stops->xy = st->lorry_tile_obsolete; - st->truck_stops->used = true; - st->truck_stops->status = 3; - st->truck_stops->station = st->index; - st->truck_stops->next = NULL; - st->truck_stops->prev = NULL; - st->truck_stops->num_vehicles = 0; - } - } -} - -static void FixOldVehicles(void) -{ - /* Check for shared orders, and link them correctly */ - Vehicle* v; - - FOR_ALL_VEHICLES(v) { - Vehicle *u; - - FOR_ALL_VEHICLES_FROM(u, v->index + 1) { - /* If a vehicle has the same orders, add the link to eachother - * in both vehicles */ - if (v->orders == u->orders) { - v->next_shared = u; - u->prev_shared = v; - break; - } - } - } -} - -/* - * End -- Stuff to fix the savegames to be OpenTTD compatible - */ - - -/* Help: - * - OCL_SVAR: load 'type' to offset 'offset' in a struct of type 'base', which must also - * be given via base in LoadChunk() as real pointer - * - OCL_VAR: load 'type' to a global var - * - OCL_END: every struct must end with this - * - OCL_NULL: read 'amount' of bytes and send them to /dev/null or something - * - OCL_CHUNK: load an other proc to load a part of the savegame, 'amount' times - * - OCL_ASSERT: to check if we are really at the place we expect to be.. because old savegames are too binary to be sure ;) - */ -#define OCL_SVAR(type, base, offset) { type, 1, NULL, (uint)offsetof(base, offset), NULL } -#define OCL_VAR(type, amount, pointer) { type, amount, pointer, 0, NULL } -#define OCL_END() { OC_END, 0, NULL, 0, NULL } -#define OCL_NULL(amount) { OC_NULL, amount, NULL, 0, NULL } -#define OCL_CHUNK(amount, proc) { OC_CHUNK, amount, NULL, 0, proc } -#define OCL_ASSERT(size) { OC_ASSERT, 1, NULL, size, NULL } - -/* The savegames has some hard-coded pointers, because it always enters the same - piece of memory.. we don't.. so we need to remap ;) - Old Towns are 94 bytes big - Old Orders are 2 bytes big */ -#define REMAP_TOWN_IDX(x) ((x) - (0x0459154 - 0x0458EF0)) / 94 -#define REMAP_ORDER_IDX(x) ((x) - (0x045AB08 - 0x0458EF0)) / 2 - -extern TileIndex _animated_tile_list[256]; -extern char _name_array[512][32]; - -static byte _old_vehicle_multiplier; -static uint8 _old_map3[OLD_MAP_SIZE * 2]; -static bool _new_ttdpatch_format; -static uint32 _old_town_index; -static uint16 _old_string_id; -static uint16 _old_string_id_2; - -static void ReadTTDPatchFlags(void) -{ - int i; - - if (_read_ttdpatch_flags) return; - - _read_ttdpatch_flags = true; - - /* TTDPatch misuses _old_map3 for flags.. read them! */ - _old_vehicle_multiplier = _old_map3[0]; - /* Somehow.... there was an error in some savegames, so 0 becomes 1 - and 1 becomes 2. The rest of the values are okay */ - if (_old_vehicle_multiplier < 2) _old_vehicle_multiplier++; - - /* TTDPatch incraeses the Vehicle-part in the middle of the game, - so if the multipler is anything else but 1, the assert fails.. - bump the assert value so it doesn't! - (1 multipler == 850 vehicles - 1 vehicle == 128 bytes */ - _bump_assert_value = (_old_vehicle_multiplier - 1) * 850 * 128; - - /* Check if we have a modern TTDPatch savegame (has extra data all around) */ - _new_ttdpatch_format = (memcmp(&_old_map3[0x1FFFA], "TTDp", 4) == 0); - - /* Clean the misused places */ - for (i = 0; i < 17; i++) _old_map3[i] = 0; - for (i = 0x1FE00; i < 0x20000; i++) _old_map3[i] = 0; - - if (_new_ttdpatch_format) DEBUG(oldloader, 1, "Found TTDPatch game"); - - DEBUG(oldloader, 1, "Vehicle-multiplier is set to %d (%d vehicles)", _old_vehicle_multiplier, _old_vehicle_multiplier * 850); -} - -static const OldChunks town_chunk[] = { - OCL_SVAR( OC_TILE, Town, xy ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, population ), - OCL_SVAR( OC_UINT16, Town, townnametype ), - OCL_SVAR( OC_UINT32, Town, townnameparts ), - OCL_SVAR( OC_UINT8, Town, grow_counter ), - OCL_NULL( 1 ), // sort_index, no longer in use - OCL_NULL( 4 ), // sign-coordinates, no longer in use - OCL_NULL( 2 ), // namewidth, no longer in use - OCL_SVAR( OC_UINT16, Town, flags12 ), - OCL_NULL( 10 ), // radius, no longer in use - - OCL_SVAR( OC_UINT16, Town, ratings[0] ), - OCL_SVAR( OC_UINT16, Town, ratings[1] ), - OCL_SVAR( OC_UINT16, Town, ratings[2] ), - OCL_SVAR( OC_UINT16, Town, ratings[3] ), - OCL_SVAR( OC_UINT16, Town, ratings[4] ), - OCL_SVAR( OC_UINT16, Town, ratings[5] ), - OCL_SVAR( OC_UINT16, Town, ratings[6] ), - OCL_SVAR( OC_UINT16, Town, ratings[7] ), - - /* XXX - This is pretty odd.. we read 32bit, but only write 8bit.. sure there is - nothing changed?? */ - OCL_SVAR( OC_FILE_U32 | OC_VAR_U8, Town, have_ratings ), - OCL_SVAR( OC_FILE_U32 | OC_VAR_U8, Town, statues ), - OCL_SVAR( OC_UINT16, Town, num_houses ), - OCL_SVAR( OC_UINT8, Town, time_until_rebuild ), - OCL_SVAR( OC_UINT8, Town, growth_rate ), - - OCL_SVAR( OC_UINT16, Town, new_max_pass ), - OCL_SVAR( OC_UINT16, Town, new_max_mail ), - OCL_SVAR( OC_UINT16, Town, new_act_pass ), - OCL_SVAR( OC_UINT16, Town, new_act_mail ), - OCL_SVAR( OC_UINT16, Town, max_pass ), - OCL_SVAR( OC_UINT16, Town, max_mail ), - OCL_SVAR( OC_UINT16, Town, act_pass ), - OCL_SVAR( OC_UINT16, Town, act_mail ), - - OCL_SVAR( OC_UINT8, Town, pct_pass_transported ), - OCL_SVAR( OC_UINT8, Town, pct_mail_transported ), - - OCL_SVAR( OC_UINT16, Town, new_act_food ), - OCL_SVAR( OC_UINT16, Town, new_act_water ), - OCL_SVAR( OC_UINT16, Town, act_food ), - OCL_SVAR( OC_UINT16, Town, act_water ), - - OCL_SVAR( OC_UINT8, Town, road_build_months ), - OCL_SVAR( OC_UINT8, Town, fund_buildings_months ), - - OCL_NULL( 8 ), // some junk at the end of the record - - OCL_END() -}; -static bool LoadOldTown(LoadgameState *ls, int num) -{ - if (!AddBlockIfNeeded(&_Town_pool, num)) - error("Towns: failed loading savegame: too many towns"); - - return LoadChunk(ls, GetTown(num), town_chunk); -} - -static uint16 _old_order; -static const OldChunks order_chunk[] = { - OCL_VAR ( OC_UINT16, 1, &_old_order ), - OCL_END() -}; - -static bool LoadOldOrder(LoadgameState *ls, int num) -{ - if (!AddBlockIfNeeded(&_Order_pool, num)) - error("Orders: failed loading savegame: too many orders"); - - if (!LoadChunk(ls, NULL, order_chunk)) return false; - - AssignOrder(GetOrder(num), UnpackOldOrder(_old_order)); - - /* Relink the orders to eachother (in TTD(Patch) the orders for one - vehicle are behind eachother, with OT_NOTHING as indication that - it is the last order */ - if (num > 0 && GetOrder(num)->type != OT_NOTHING) - GetOrder(num - 1)->next = GetOrder(num); - - return true; -} - -static const OldChunks depot_chunk[] = { - OCL_SVAR( OC_TILE, Depot, xy ), - OCL_VAR ( OC_UINT32, 1, &_old_town_index ), - OCL_END() -}; - -static bool LoadOldDepot(LoadgameState *ls, int num) -{ - if (!AddBlockIfNeeded(&_Depot_pool, num)) - error("Depots: failed loading savegame: too many depots"); - - if (!LoadChunk(ls, GetDepot(num), depot_chunk)) return false; - - if (IsValidDepot(GetDepot(num))) { - GetDepot(num)->town_index = REMAP_TOWN_IDX(_old_town_index); - } - - return true; -} - -static int32 _old_price; -static uint16 _old_price_frac; -static const OldChunks price_chunk[] = { - OCL_VAR ( OC_INT32, 1, &_old_price ), - OCL_VAR ( OC_UINT16, 1, &_old_price_frac ), - OCL_END() -}; - -static bool LoadOldPrice(LoadgameState *ls, int num) -{ - if (!LoadChunk(ls, NULL, price_chunk)) return false; - - /* We use a struct to store the prices, but they are ints in a row.. - so just access the struct as an array of int32's */ - ((int32*)&_price)[num] = _old_price; - _price_frac[num] = _old_price_frac; - - return true; -} - -static const OldChunks cargo_payment_rate_chunk[] = { - OCL_VAR ( OC_INT32, 1, &_old_price ), - OCL_VAR ( OC_UINT16, 1, &_old_price_frac ), - - OCL_NULL( 2 ), // Junk - OCL_END() -}; - -static bool LoadOldCargoPaymentRate(LoadgameState *ls, int num) -{ - if (!LoadChunk(ls, NULL, cargo_payment_rate_chunk)) return false; - - _cargo_payment_rates[num] = -_old_price; - _cargo_payment_rates_frac[num] = _old_price_frac; - - return true; -} - -static uint8 _old_platforms; -static uint _current_station_id; - -static const OldChunks goods_chunk[] = { - OCL_SVAR( OC_UINT16, GoodsEntry, waiting_acceptance ), - OCL_SVAR( OC_UINT8, GoodsEntry, days_since_pickup ), - OCL_SVAR( OC_UINT8, GoodsEntry, rating ), - OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, GoodsEntry, enroute_from ), - OCL_SVAR( OC_UINT8, GoodsEntry, enroute_time ), - OCL_SVAR( OC_UINT8, GoodsEntry, last_speed ), - OCL_SVAR( OC_UINT8, GoodsEntry, last_age ), - - OCL_END() -}; - -static bool LoadOldGood(LoadgameState *ls, int num) -{ - Station *st = GetStation(_current_station_id); - return LoadChunk(ls, &st->goods[num], goods_chunk); -} - -static const OldChunks station_chunk[] = { - OCL_SVAR( OC_TILE, Station, xy ), - OCL_VAR ( OC_UINT32, 1, &_old_town_index ), - - OCL_SVAR( OC_TILE, Station, bus_tile_obsolete ), - OCL_SVAR( OC_TILE, Station, lorry_tile_obsolete ), - OCL_SVAR( OC_TILE, Station, train_tile ), - OCL_SVAR( OC_TILE, Station, airport_tile ), - OCL_SVAR( OC_TILE, Station, dock_tile ), - - OCL_VAR ( OC_UINT8, 1, &_old_platforms ), - - OCL_NULL( 1 ), // sort-index, no longer in use - OCL_NULL( 2 ), // sign-width, no longer in use - - OCL_VAR ( OC_UINT16, 1, &_old_string_id ), - - OCL_NULL( 4 ), // sign left/top, no longer in use - - OCL_SVAR( OC_UINT16, Station, had_vehicle_of_type ), - - OCL_CHUNK( 12, LoadOldGood ), - - OCL_SVAR( OC_UINT8, Station, time_since_load ), - OCL_SVAR( OC_UINT8, Station, time_since_unload ), - OCL_SVAR( OC_UINT8, Station, delete_ctr ), - OCL_SVAR( OC_UINT8, Station, owner ), - OCL_SVAR( OC_UINT8, Station, facilities ), - OCL_SVAR( OC_UINT8, Station, airport_type ), - OCL_NULL( 2 ), // Bus/truck status, no longer in use - OCL_SVAR( OC_UINT8, Station, blocked_months_obsolete ), - OCL_NULL( 1 ), // Unknown - OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Station, airport_flags ), - OCL_NULL( 2 ), // last_vehicle. now last_vehicle_type - - OCL_NULL( 4 ), // Junk at end of chunk - - OCL_END() -}; -static bool LoadOldStation(LoadgameState *ls, int num) -{ - Station *st; - - if (!AddBlockIfNeeded(&_Station_pool, num)) - error("Stations: failed loading savegame: too many stations"); - - st = GetStation(num); - _current_station_id = num; - - if (!LoadChunk(ls, st, station_chunk)) - return false; - - if (IsValidStation(st)) { - if (st->train_tile) { - /* Calculate the trainst_w and trainst_h */ - uint w = GB(_old_platforms, 3, 3); - uint h = GB(_old_platforms, 0, 3); - st->trainst_w = w; - st->trainst_h = h; - } - - st->town = GetTown(REMAP_TOWN_IDX(_old_town_index)); - st->string_id = RemapOldStringID(_old_string_id); - } - - return true; -} - -static const OldChunks industry_chunk[] = { - OCL_SVAR( OC_TILE, Industry, xy ), - OCL_VAR ( OC_UINT32, 1, &_old_town_index ), - OCL_SVAR( OC_UINT8, Industry, width ), - OCL_SVAR( OC_UINT8, Industry, height ), - OCL_SVAR( OC_UINT8, Industry, produced_cargo[0] ), - OCL_SVAR( OC_UINT8, Industry, produced_cargo[1] ), - - OCL_SVAR( OC_UINT16, Industry, cargo_waiting[0] ), - OCL_SVAR( OC_UINT16, Industry, cargo_waiting[1] ), - - OCL_SVAR( OC_UINT8, Industry, production_rate[0] ), - OCL_SVAR( OC_UINT8, Industry, production_rate[1] ), - - OCL_SVAR( OC_UINT8, Industry, accepts_cargo[0] ), - OCL_SVAR( OC_UINT8, Industry, accepts_cargo[1] ), - OCL_SVAR( OC_UINT8, Industry, accepts_cargo[2] ), - - OCL_SVAR( OC_UINT8, Industry, prod_level ), - - OCL_SVAR( OC_UINT16, Industry, last_mo_production[0] ), - OCL_SVAR( OC_UINT16, Industry, last_mo_production[1] ), - OCL_SVAR( OC_UINT16, Industry, last_mo_transported[0] ), - OCL_SVAR( OC_UINT16, Industry, last_mo_transported[1] ), - - OCL_SVAR( OC_UINT8, Industry, pct_transported[0] ), - OCL_SVAR( OC_UINT8, Industry, pct_transported[1] ), - - OCL_SVAR( OC_UINT16, Industry, total_production[0] ), - OCL_SVAR( OC_UINT16, Industry, total_production[1] ), - OCL_SVAR( OC_UINT16, Industry, total_transported[0] ), - OCL_SVAR( OC_UINT16, Industry, total_transported[1] ), - - OCL_SVAR( OC_UINT8, Industry, type ), - OCL_SVAR( OC_UINT8, Industry, owner ), - OCL_SVAR( OC_UINT8, Industry, random_color ), - OCL_SVAR( OC_FILE_U8 | OC_VAR_I32, Industry, last_prod_year ), - OCL_SVAR( OC_UINT16, Industry, counter ), - OCL_SVAR( OC_UINT8, Industry, was_cargo_delivered ), - - OCL_NULL( 9 ), // Random junk at the end of this chunk - - OCL_END() -}; - -static bool LoadOldIndustry(LoadgameState *ls, int num) -{ - Industry *i; - - if (!AddBlockIfNeeded(&_Industry_pool, num)) - error("Industries: failed loading savegame: too many industries"); - - i = GetIndustry(num); - if (!LoadChunk(ls, i, industry_chunk)) return false; - - if (IsValidIndustry(i)) { - i->town = GetTown(REMAP_TOWN_IDX(_old_town_index)); - } - - return true; -} - -static PlayerID _current_player_id; -static uint16 _old_inaugurated_year; -static int32 _old_yearly; - -static const OldChunks player_yearly_chunk[] = { - OCL_VAR( OC_INT32, 1, &_old_yearly ), - OCL_END() -}; - -static bool OldPlayerYearly(LoadgameState *ls, int num) -{ - int i; - Player *p = GetPlayer(_current_player_id); - - for (i = 0; i < 13; i++) { - if (!LoadChunk(ls, NULL, player_yearly_chunk)) return false; - - p->yearly_expenses[num][i] = _old_yearly; - } - - return true; -} - -static const OldChunks player_economy_chunk[] = { - OCL_SVAR( OC_INT32, PlayerEconomyEntry, income ), - OCL_SVAR( OC_INT32, PlayerEconomyEntry, expenses ), - OCL_SVAR( OC_INT32, PlayerEconomyEntry, delivered_cargo ), - OCL_SVAR( OC_INT32, PlayerEconomyEntry, performance_history ), - OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, PlayerEconomyEntry, company_value ), - - OCL_END() -}; - -static bool OldPlayerEconomy(LoadgameState *ls, int num) -{ - int i; - Player *p = GetPlayer(_current_player_id); - - if (!LoadChunk(ls, &p->cur_economy, player_economy_chunk)) return false; - - /* Don't ask, but the number in TTD(Patch) are inversed to OpenTTD */ - p->cur_economy.income = -p->cur_economy.income; - p->cur_economy.expenses = -p->cur_economy.expenses; - - for (i = 0; i < 24; i++) { - if (!LoadChunk(ls, &p->old_economy[i], player_economy_chunk)) return false; - - p->old_economy[i].income = -p->old_economy[i].income; - p->old_economy[i].expenses = -p->old_economy[i].expenses; - } - - return true; -} - -static const OldChunks player_ai_build_rec_chunk[] = { - OCL_SVAR( OC_TILE, AiBuildRec, spec_tile ), - OCL_SVAR( OC_TILE, AiBuildRec, use_tile ), - OCL_SVAR( OC_UINT8, AiBuildRec, rand_rng ), - OCL_SVAR( OC_UINT8, AiBuildRec, cur_building_rule ), - OCL_SVAR( OC_UINT8, AiBuildRec, unk6 ), - OCL_SVAR( OC_UINT8, AiBuildRec, unk7 ), - OCL_SVAR( OC_UINT8, AiBuildRec, buildcmd_a ), - OCL_SVAR( OC_UINT8, AiBuildRec, buildcmd_b ), - OCL_SVAR( OC_UINT8, AiBuildRec, direction ), - OCL_SVAR( OC_UINT8, AiBuildRec, cargo ), - - OCL_NULL( 8 ), // Junk... - - OCL_END() -}; - -static bool OldLoadAIBuildRec(LoadgameState *ls, int num) -{ - Player *p = GetPlayer(_current_player_id); - - switch (num) { - case 0: return LoadChunk(ls, &p->ai.src, player_ai_build_rec_chunk); - case 1: return LoadChunk(ls, &p->ai.dst, player_ai_build_rec_chunk); - case 2: return LoadChunk(ls, &p->ai.mid1, player_ai_build_rec_chunk); - case 3: return LoadChunk(ls, &p->ai.mid2, player_ai_build_rec_chunk); - } - - return false; -} -static const OldChunks player_ai_chunk[] = { - OCL_SVAR( OC_UINT8, PlayerAI, state ), - OCL_NULL( 1 ), // Junk - OCL_SVAR( OC_UINT8, PlayerAI, state_mode ), - OCL_SVAR( OC_UINT16, PlayerAI, state_counter ), - OCL_SVAR( OC_UINT16, PlayerAI, timeout_counter ), - - OCL_CHUNK( 4, OldLoadAIBuildRec ), - - OCL_NULL( 20 ), // More junk - - OCL_SVAR( OC_UINT8, PlayerAI, cargo_type ), - OCL_SVAR( OC_UINT8, PlayerAI, num_wagons ), - OCL_SVAR( OC_UINT8, PlayerAI, build_kind ), - OCL_SVAR( OC_UINT8, PlayerAI, num_build_rec ), - OCL_SVAR( OC_UINT8, PlayerAI, num_loco_to_build ), - OCL_SVAR( OC_UINT8, PlayerAI, num_want_fullload ), - - OCL_NULL( 14 ), // Oh no more junk :| - - OCL_NULL( 2 ), // Loco-id, not used - - OCL_SVAR( OC_UINT16, PlayerAI, wagon_list[0] ), - OCL_SVAR( OC_UINT16, PlayerAI, wagon_list[1] ), - OCL_SVAR( OC_UINT16, PlayerAI, wagon_list[2] ), - OCL_SVAR( OC_UINT16, PlayerAI, wagon_list[3] ), - OCL_SVAR( OC_UINT16, PlayerAI, wagon_list[4] ), - OCL_SVAR( OC_UINT16, PlayerAI, wagon_list[5] ), - OCL_SVAR( OC_UINT16, PlayerAI, wagon_list[6] ), - OCL_SVAR( OC_UINT16, PlayerAI, wagon_list[7] ), - OCL_SVAR( OC_UINT16, PlayerAI, wagon_list[8] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[0] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[1] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[2] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[3] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[4] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[5] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[6] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[7] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[8] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[9] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[10] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[11] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[12] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[13] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[14] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[15] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[16] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[17] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[18] ), - OCL_SVAR( OC_UINT8, PlayerAI, order_list_blocks[19] ), - - OCL_SVAR( OC_UINT16, PlayerAI, start_tile_a ), - OCL_SVAR( OC_UINT16, PlayerAI, start_tile_b ), - OCL_SVAR( OC_UINT16, PlayerAI, cur_tile_a ), - OCL_SVAR( OC_UINT16, PlayerAI, cur_tile_b ), - - OCL_SVAR( OC_UINT8, PlayerAI, start_dir_a ), - OCL_SVAR( OC_UINT8, PlayerAI, start_dir_b ), - OCL_SVAR( OC_UINT8, PlayerAI, cur_dir_a ), - OCL_SVAR( OC_UINT8, PlayerAI, cur_dir_b ), - - OCL_SVAR( OC_UINT8, PlayerAI, banned_tile_count ), - - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[0] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[0] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[1] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[1] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[2] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[2] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[3] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[3] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[4] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[4] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[5] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[5] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[6] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[6] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[7] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[7] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[8] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[8] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[9] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[9] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[10] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[10] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[11] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[11] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[12] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[12] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[13] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[13] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[14] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[14] ), - OCL_SVAR( OC_TILE, PlayerAI, banned_tiles[15] ), - OCL_SVAR( OC_UINT8, PlayerAI, banned_val[15] ), - - OCL_SVAR( OC_UINT8, PlayerAI, railtype_to_use ), - OCL_SVAR( OC_UINT8, PlayerAI, route_type_mask ), - - OCL_END() -}; - -static bool OldPlayerAI(LoadgameState *ls, int num) -{ - Player *p = GetPlayer(_current_player_id); - - return LoadChunk(ls, &p->ai, player_ai_chunk); -} - -static const OldChunks player_chunk[] = { - OCL_VAR ( OC_UINT16, 1, &_old_string_id ), - OCL_SVAR( OC_UINT32, Player, name_2 ), - OCL_SVAR( OC_UINT32, Player, face ), - OCL_VAR ( OC_UINT16, 1, &_old_string_id_2 ), - OCL_SVAR( OC_UINT32, Player, president_name_2 ), - - OCL_SVAR( OC_INT32, Player, player_money ), - OCL_SVAR( OC_INT32, Player, current_loan ), - - OCL_SVAR( OC_UINT8, Player, player_color ), - OCL_SVAR( OC_UINT8, Player, player_money_fraction ), - OCL_SVAR( OC_UINT8, Player, quarters_of_bankrupcy ), - OCL_SVAR( OC_UINT8, Player, bankrupt_asked ), - OCL_SVAR( OC_UINT32, Player, bankrupt_value ), - OCL_SVAR( OC_UINT16, Player, bankrupt_timeout ), - - OCL_SVAR( OC_FILE_U32 | OC_VAR_U16, Player, cargo_types ), - - OCL_CHUNK( 3, OldPlayerYearly ), - OCL_CHUNK( 1, OldPlayerEconomy ), - - OCL_VAR ( OC_UINT16, 1, &_old_inaugurated_year ), - OCL_SVAR( OC_TILE, Player, last_build_coordinate ), - OCL_SVAR( OC_UINT8, Player, num_valid_stat_ent ), - - OCL_CHUNK( 1, OldPlayerAI ), - - OCL_SVAR( OC_UINT8, Player, block_preview ), - OCL_SVAR( OC_UINT8, Player, ai.tick ), - OCL_SVAR( OC_UINT8, Player, avail_railtypes ), - OCL_SVAR( OC_TILE, Player, location_of_house ), - OCL_SVAR( OC_UINT8, Player, share_owners[0] ), - OCL_SVAR( OC_UINT8, Player, share_owners[1] ), - OCL_SVAR( OC_UINT8, Player, share_owners[2] ), - OCL_SVAR( OC_UINT8, Player, share_owners[3] ), - - OCL_NULL( 8 ), // junk at end of chunk - - OCL_END() -}; - -static bool LoadOldPlayer(LoadgameState *ls, int num) -{ - Player *p = GetPlayer(num); - - _current_player_id = num; - - if (!LoadChunk(ls, p, player_chunk)) return false; - - p->name_1 = RemapOldStringID(_old_string_id); - p->president_name_1 = RemapOldStringID(_old_string_id_2); - p->money64 = p->player_money; - - if (num == 0) { - /* If the first player has no name, make sure we call it UNNAMED */ - if (p->name_1 == 0) - p->name_1 = STR_SV_UNNAMED; - } else { - /* Beside some multiplayer maps (1 on 1), which we don't official support, - all other players are an AI.. mark them as such */ - p->is_ai = true; - } - - /* Sometimes it is better to not ask.. in old scenarios, the money - was always 893288 pounds. In the newer versions this is correct, - but correct for those oldies - Ps: this also means that if you had exact 893288 pounds, you will go back - to 10000.. this is a very VERY small chance ;) */ - if (p->player_money == 893288) - p->money64 = p->player_money = p->current_loan = 100000; - - _player_colors[num] = p->player_color; - p->inaugurated_year = _old_inaugurated_year; - if (p->location_of_house == 0xFFFF) - p->location_of_house = 0; - - /* State 20 for AI players is sell vehicle. Since the AI struct is not - * really figured out as of now, p->ai.cur_veh; needed for 'sell vehicle' - * is NULL and the function will crash. To fix this, just change the state - * to some harmless state, like 'loop vehicle'; 1 */ - if (!IsHumanPlayer(num) && p->ai.state == 20) p->ai.state = 1; - - if (p->is_ai && (!_networking || _network_server) && _ai.enabled) - AI_StartNewAI(p->index); - - return true; -} - -static uint32 _old_order_ptr; -static uint16 _old_next_ptr; -static uint32 _current_vehicle_id; - -static const OldChunks vehicle_train_chunk[] = { - OCL_SVAR( OC_UINT8, VehicleRail, track ), - OCL_SVAR( OC_UINT8, VehicleRail, force_proceed ), - OCL_SVAR( OC_UINT16, VehicleRail, crash_anim_pos ), - OCL_SVAR( OC_UINT8, VehicleRail, railtype ), - - OCL_NULL( 5 ), // Junk - - OCL_END() -}; - -static const OldChunks vehicle_road_chunk[] = { - OCL_SVAR( OC_UINT8, VehicleRoad, state ), - OCL_SVAR( OC_UINT8, VehicleRoad, frame ), - OCL_SVAR( OC_UINT16, VehicleRoad, blocked_ctr ), - OCL_SVAR( OC_UINT8, VehicleRoad, overtaking ), - OCL_SVAR( OC_UINT8, VehicleRoad, overtaking_ctr ), - OCL_SVAR( OC_UINT16, VehicleRoad, crashed_ctr ), - OCL_SVAR( OC_UINT8, VehicleRoad, reverse_ctr ), - - OCL_NULL( 1 ), // Junk - - OCL_END() -}; - -static const OldChunks vehicle_ship_chunk[] = { - OCL_SVAR( OC_UINT8, VehicleShip, state ), - - OCL_NULL( 9 ), // Junk - - OCL_END() -}; - -static const OldChunks vehicle_air_chunk[] = { - OCL_SVAR( OC_UINT8, VehicleAir, pos ), - OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, VehicleAir, targetairport ), - OCL_SVAR( OC_UINT16, VehicleAir, crashed_counter ), - OCL_SVAR( OC_UINT8, VehicleAir, state ), - - OCL_NULL( 5 ), // Junk - - OCL_END() -}; - -static const OldChunks vehicle_special_chunk[] = { - OCL_SVAR( OC_UINT16, VehicleSpecial, unk0 ), - OCL_SVAR( OC_UINT8, VehicleSpecial, unk2 ), - - OCL_NULL( 7 ), // Junk - - OCL_END() -}; - -static const OldChunks vehicle_disaster_chunk[] = { - OCL_SVAR( OC_UINT16, VehicleDisaster, image_override ), - OCL_SVAR( OC_UINT16, VehicleDisaster, unk2 ), - - OCL_NULL( 6 ), // Junk - - OCL_END() -}; - -static const OldChunks vehicle_empty_chunk[] = { - OCL_NULL( 10 ), // Junk - - OCL_END() -}; - -static bool LoadOldVehicleUnion(LoadgameState *ls, int num) -{ - Vehicle *v = GetVehicle(_current_vehicle_id); - uint temp = ls->total_read; - bool res; - - switch (v->type) { - case VEH_Train: res = LoadChunk(ls, &v->u.rail, vehicle_train_chunk); break; - case VEH_Road: res = LoadChunk(ls, &v->u.road, vehicle_road_chunk); break; - case VEH_Ship: res = LoadChunk(ls, &v->u.ship, vehicle_ship_chunk); break; - case VEH_Aircraft: res = LoadChunk(ls, &v->u.air, vehicle_air_chunk); break; - case VEH_Special: res = LoadChunk(ls, &v->u.special, vehicle_special_chunk); break; - case VEH_Disaster: res = LoadChunk(ls, &v->u.disaster, vehicle_disaster_chunk); break; - default: res = LoadChunk(ls, NULL, vehicle_empty_chunk); break; - } - - /* This chunk size should always be 10 bytes */ - if (ls->total_read - temp != 10) { - DEBUG(oldloader, 4, "Assert failed in Vehicle"); - return false; - } - - return res; -} - -static const OldChunks vehicle_chunk[] = { - OCL_SVAR( OC_UINT8, Vehicle, type ), - OCL_SVAR( OC_UINT8, Vehicle, subtype ), - - OCL_NULL( 2 ), // Hash, calculated automatically - OCL_NULL( 2 ), // Index, calculated automatically - - OCL_VAR ( OC_UINT32, 1, &_old_order_ptr ), - OCL_VAR ( OC_UINT16, 1, &_old_order ), - - OCL_SVAR( OC_UINT8, Vehicle, num_orders ), - OCL_SVAR( OC_UINT8, Vehicle, cur_order_index ), - OCL_SVAR( OC_TILE, Vehicle, dest_tile ), - OCL_SVAR( OC_UINT16, Vehicle, load_unload_time_rem ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, date_of_last_service ), - OCL_SVAR( OC_UINT16, Vehicle, service_interval ), - OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, last_station_visited ), - OCL_SVAR( OC_UINT8, Vehicle, tick_counter ), - OCL_SVAR( OC_UINT16, Vehicle, max_speed ), - - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Vehicle, x_pos ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Vehicle, y_pos ), - OCL_SVAR( OC_UINT8, Vehicle, z_pos ), - OCL_SVAR( OC_UINT8, Vehicle, direction ), - OCL_SVAR( OC_INT8, Vehicle, x_offs ), - OCL_SVAR( OC_INT8, Vehicle, y_offs ), - OCL_SVAR( OC_UINT8, Vehicle, sprite_width ), - OCL_SVAR( OC_UINT8, Vehicle, sprite_height ), - OCL_SVAR( OC_UINT8, Vehicle, z_height ), - - OCL_SVAR( OC_UINT8, Vehicle, owner ), - OCL_SVAR( OC_TILE, Vehicle, tile ), - OCL_SVAR( OC_UINT16, Vehicle, cur_image ), - - OCL_NULL( 8 ), // Vehicle sprite box, calculated automatically - - OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Vehicle, vehstatus ), - OCL_SVAR( OC_UINT16, Vehicle, cur_speed ), - OCL_SVAR( OC_UINT8, Vehicle, subspeed ), - OCL_SVAR( OC_UINT8, Vehicle, acceleration ), - OCL_SVAR( OC_UINT8, Vehicle, progress ), - - OCL_SVAR( OC_UINT8, Vehicle, cargo_type ), - OCL_SVAR( OC_UINT16, Vehicle, cargo_cap ), - OCL_SVAR( OC_UINT16, Vehicle, cargo_count ), - OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, cargo_source ), - OCL_SVAR( OC_UINT8, Vehicle, cargo_days ), - - OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, age ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, max_age ), - OCL_SVAR( OC_FILE_U8 | OC_VAR_I32, Vehicle, build_year ), - OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, unitnumber ), - - OCL_SVAR( OC_UINT16, Vehicle, engine_type ), - - OCL_SVAR( OC_UINT8, Vehicle, spritenum ), - OCL_SVAR( OC_UINT8, Vehicle, day_counter ), - - OCL_SVAR( OC_UINT8, Vehicle, breakdowns_since_last_service ), - OCL_SVAR( OC_UINT8, Vehicle, breakdown_ctr ), - OCL_SVAR( OC_UINT8, Vehicle, breakdown_delay ), - OCL_SVAR( OC_UINT8, Vehicle, breakdown_chance ), - - OCL_SVAR( OC_UINT16, Vehicle, reliability ), - OCL_SVAR( OC_UINT16, Vehicle, reliability_spd_dec ), - - OCL_SVAR( OC_INT32, Vehicle, profit_this_year ), - OCL_SVAR( OC_INT32, Vehicle, profit_last_year ), - - OCL_VAR ( OC_UINT16, 1, &_old_next_ptr ), - - OCL_SVAR( OC_UINT32, Vehicle, value ), - - OCL_VAR ( OC_UINT16, 1, &_old_string_id ), - - OCL_CHUNK( 1, LoadOldVehicleUnion ), - - OCL_NULL( 20 ), // Junk at end of struct (TTDPatch has some data in it) - - OCL_END() -}; - -static bool LoadOldVehicle(LoadgameState *ls, int num) -{ - uint i; - - /* Read the TTDPatch flags, because we need some info from it */ - ReadTTDPatchFlags(); - - for (i = 0; i < _old_vehicle_multiplier; i++) { - Vehicle *v; - - _current_vehicle_id = num * _old_vehicle_multiplier + i; - - if (!AddBlockIfNeeded(&_Vehicle_pool, _current_vehicle_id)) - error("Vehicles: failed loading savegame: too many vehicles"); - - v = GetVehicle(_current_vehicle_id); - if (!LoadChunk(ls, v, vehicle_chunk)) return false; - - /* This should be consistent, else we have a big problem... */ - if (v->index != _current_vehicle_id) { - DEBUG(oldloader, 0, "Loading failed - vehicle-array is invalid"); - return false; - } - - if (_old_order_ptr != 0 && _old_order_ptr != 0xFFFFFFFF) { - v->orders = GetOrder(REMAP_ORDER_IDX(_old_order_ptr)); - } - AssignOrder(&v->current_order, UnpackOldOrder(_old_order)); - - /* For some reason we need to correct for this */ - switch (v->spritenum) { - case 0xfd: break; - case 0xff: v->spritenum = 0xfe; break; - default: v->spritenum >>= 1; break; - } - - if (_old_next_ptr != 0xFFFF) - v->next = GetVehicle(_old_next_ptr); - - v->string_id = RemapOldStringID(_old_string_id); - - /* Vehicle-subtype is different in TTD(Patch) */ - if (v->type == VEH_Special) v->subtype = v->subtype >> 1; - } - - return true; -} - -static const OldChunks sign_chunk[] = { - OCL_SVAR( OC_UINT16, Sign, str ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32,Sign, x ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32,Sign, y ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I8, Sign, z ), - - OCL_NULL( 6 ), // Width of sign, no longer in use - - OCL_END() -}; - -static bool LoadOldSign(LoadgameState *ls, int num) -{ - if (!AddBlockIfNeeded(&_Sign_pool, num)) - error("Signs: failed loading savegame: too many signs"); - - return LoadChunk(ls, GetSign(num), sign_chunk); -} - -static const OldChunks engine_chunk[] = { - OCL_SVAR( OC_UINT16, Engine, player_avail ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Engine, intro_date ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Engine, age ), - OCL_SVAR( OC_UINT16, Engine, reliability ), - OCL_SVAR( OC_UINT16, Engine, reliability_spd_dec ), - OCL_SVAR( OC_UINT16, Engine, reliability_start ), - OCL_SVAR( OC_UINT16, Engine, reliability_max ), - OCL_SVAR( OC_UINT16, Engine, reliability_final ), - OCL_SVAR( OC_UINT16, Engine, duration_phase_1 ), - OCL_SVAR( OC_UINT16, Engine, duration_phase_2 ), - OCL_SVAR( OC_UINT16, Engine, duration_phase_3 ), - - OCL_SVAR( OC_UINT8, Engine, lifelength ), - OCL_SVAR( OC_UINT8, Engine, flags ), - OCL_SVAR( OC_UINT8, Engine, preview_player ), - OCL_SVAR( OC_UINT8, Engine, preview_wait ), - OCL_SVAR( OC_UINT8, Engine, railtype ), - - OCL_NULL( 1 ), // Junk - - OCL_END() -}; - -static bool LoadOldEngine(LoadgameState *ls, int num) -{ - if (!LoadChunk(ls, GetEngine(num), engine_chunk)) return false; - - /* Make sure wagons are marked as do-not-age */ - if ((num >= 27 && num < 54) || (num >= 57 && num < 84) || (num >= 89 && num < 116)) - GetEngine(num)->age = 0xFFFF; - - return true; -} - -static const OldChunks subsidy_chunk[] = { - OCL_SVAR( OC_UINT8, Subsidy, cargo_type ), - OCL_SVAR( OC_UINT8, Subsidy, age ), - OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Subsidy, from ), - OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Subsidy, to ), - - OCL_END() -}; - -static inline bool LoadOldSubsidy(LoadgameState *ls, int num) -{ - return LoadChunk(ls, &_subsidies[num], subsidy_chunk); -} - -static const OldChunks game_difficulty_chunk[] = { - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, max_no_competitors ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, competitor_start_time ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, number_towns ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, number_industries ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, max_loan ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, initial_interest ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, vehicle_costs ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, competitor_speed ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, competitor_intelligence ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, vehicle_breakdowns ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, subsidy_multiplier ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, construction_cost ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, terrain_type ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, quantity_sea_lakes ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, economy ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, line_reverse_mode ), - OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, GameDifficulty, disasters ), - OCL_END() -}; - -static inline bool LoadOldGameDifficulty(LoadgameState *ls, int num) -{ - return LoadChunk(ls, &_opt.diff, game_difficulty_chunk); -} - - -static bool LoadOldMapPart1(LoadgameState *ls, int num) -{ - uint i; - - for (i = 0; i < OLD_MAP_SIZE; i++) { - _m[i].m1 = ReadByte(ls); - } - for (i = 0; i < OLD_MAP_SIZE; i++) { - _m[i].m2 = ReadByte(ls); - } - for (i = 0; i < OLD_MAP_SIZE; i++) { - _old_map3[i * 2] = ReadByte(ls); - _old_map3[i * 2 + 1] = ReadByte(ls); - } - for (i = 0; i < OLD_MAP_SIZE / 4; i++) { - byte b = ReadByte(ls); - _m[i * 4 + 0].extra = GB(b, 0, 2); - _m[i * 4 + 1].extra = GB(b, 2, 2); - _m[i * 4 + 2].extra = GB(b, 4, 2); - _m[i * 4 + 3].extra = GB(b, 6, 2); - } - - return !ls->failed; -} - -static bool LoadOldMapPart2(LoadgameState *ls, int num) -{ - uint i; - - for (i = 0; i < OLD_MAP_SIZE; i++) { - _m[i].type_height = ReadByte(ls); - } - for (i = 0; i < OLD_MAP_SIZE; i++) { - _m[i].m5 = ReadByte(ls); - } - - return !ls->failed; -} - -static uint32 _old_cur_town_ctr; -static const OldChunks main_chunk[] = { - OCL_ASSERT( 0 ), - OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &_date ), - OCL_VAR ( OC_UINT16, 1, &_date_fract ), - OCL_NULL( 600 ), // TextEffects - OCL_VAR ( OC_UINT32, 2, &_random_seeds[0] ), - - OCL_ASSERT( 0x264 ), - OCL_CHUNK( 70, LoadOldTown ), - OCL_ASSERT( 0x1C18 ), - OCL_CHUNK(5000, LoadOldOrder ), - OCL_ASSERT( 0x4328 ), - - OCL_VAR ( OC_TILE, 256, &_animated_tile_list[0] ), - OCL_NULL( 4 ), // old end-of-order-list-pointer, no longer in use - - OCL_CHUNK( 255, LoadOldDepot ), - OCL_ASSERT( 0x4B26 ), - - OCL_VAR ( OC_UINT32, 1, &_old_cur_town_ctr ), - OCL_NULL( 2 ), // timer_counter, no longer in use - OCL_NULL( 2 ), // land_code, no longer in use - - OCL_VAR ( OC_FILE_U16 | OC_VAR_U8, 1, &_age_cargo_skip_counter ), - OCL_VAR ( OC_UINT16, 1, &_tick_counter ), - OCL_VAR ( OC_TILE, 1, &_cur_tileloop_tile ), - - OCL_CHUNK( 49, LoadOldPrice ), - OCL_CHUNK( 12, LoadOldCargoPaymentRate ), - - OCL_ASSERT( 0x4CBA ), - - OCL_CHUNK( 1, LoadOldMapPart1 ), - - OCL_ASSERT( 0x48CBA ), - - OCL_CHUNK(250, LoadOldStation ), - OCL_CHUNK( 90, LoadOldIndustry ), - OCL_CHUNK( 8, LoadOldPlayer ), - - OCL_ASSERT( 0x547F2 ), - - OCL_CHUNK( 850, LoadOldVehicle ), - - OCL_ASSERT( 0x6F0F2 ), - - OCL_VAR ( OC_UINT8, 32 * 500, &_name_array[0] ), - - OCL_NULL( 0x2000 ), // Old hash-table, no longer in use - - OCL_CHUNK( 40, LoadOldSign ), - OCL_CHUNK(256, LoadOldEngine ), - - OCL_VAR ( OC_UINT16, 1, &_vehicle_id_ctr_day ), - - OCL_CHUNK( 8, LoadOldSubsidy ), - - OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &_next_competitor_start ), - OCL_VAR ( OC_FILE_I16 | OC_VAR_I32, 1, &_saved_scrollpos_x ), - OCL_VAR ( OC_FILE_I16 | OC_VAR_I32, 1, &_saved_scrollpos_y ), - OCL_VAR ( OC_FILE_U16 | OC_VAR_U8, 1, &_saved_scrollpos_zoom ), - - OCL_VAR ( OC_UINT32, 1, &_economy.max_loan ), - OCL_VAR ( OC_UINT32, 1, &_economy.max_loan_unround ), - OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &_economy.fluct ), - - OCL_VAR ( OC_UINT16, 1, &_disaster_delay ), - - OCL_NULL( 144 ), // cargo-stuff, calculated in InitializeLandscapeVariables - - OCL_VAR ( OC_UINT16, 256, &_engine_name_strings[0] ), - - OCL_NULL( 144 ), // AI cargo-stuff, calculated in InitializeLandscapeVariables - OCL_NULL( 2 ), // Company indexes of players, no longer in use - - OCL_VAR ( OC_FILE_U8 | OC_VAR_U16, 1, &_station_tick_ctr ), - - OCL_VAR ( OC_UINT8, 1, &_opt.currency ), - OCL_VAR ( OC_UINT8, 1, &_opt.units ), - OCL_VAR ( OC_FILE_U8 | OC_VAR_U32, 1, &_cur_player_tick_index ), - - OCL_NULL( 2 ), // Date stuff, calculated automatically - OCL_NULL( 8 ), // Player colors, calculated automatically - - OCL_VAR ( OC_UINT8, 1, &_economy.infl_amount ), - OCL_VAR ( OC_UINT8, 1, &_economy.infl_amount_pr ), - OCL_VAR ( OC_UINT8, 1, &_economy.interest_rate ), - OCL_VAR ( OC_UINT8, 1, &_avail_aircraft ), - OCL_VAR ( OC_UINT8, 1, &_opt.road_side ), - OCL_VAR ( OC_UINT8, 1, &_opt.town_name ), - - OCL_CHUNK( 1, LoadOldGameDifficulty ), - - OCL_ASSERT( 0x77130 ), - - OCL_VAR ( OC_UINT8, 1, &_opt.diff_level ), - OCL_VAR ( OC_UINT8, 1, &_opt.landscape ), - OCL_VAR ( OC_UINT8, 1, &_trees_tick_ctr ), - - OCL_NULL( 1 ), // Custom vehicle types yes/no, no longer used - OCL_VAR ( OC_UINT8, 1, &_opt.snow_line ), - - OCL_NULL( 32 ), // new_industry_randtable, no longer used (because of new design) - OCL_NULL( 36 ), // cargo-stuff, calculated in InitializeLandscapeVariables - - OCL_ASSERT( 0x77179 ), - - OCL_CHUNK( 1, LoadOldMapPart2 ), - - OCL_ASSERT( 0x97179 ), - - /* Below any (if available) extra chunks from TTDPatch can follow */ - - OCL_END() -}; - -static bool LoadOldMain(LoadgameState *ls) -{ - int i; - - /* The first 49 is the name of the game + checksum, skip it */ - fseek(ls->file, HEADER_SIZE, SEEK_SET); - - DEBUG(oldloader, 4, "Reading main chunk..."); - /* Load the biggest chunk */ - if (!LoadChunk(ls, NULL, main_chunk)) { - DEBUG(oldloader, 0, "Loading failed"); - return false; - } - DEBUG(oldloader, 4, "Done, converting game data..."); - - /* Fix some general stuff */ - _opt.landscape = _opt.landscape & 0xF; - - /* Remap some pointers */ - _cur_town_ctr = REMAP_TOWN_IDX(_old_cur_town_ctr); - - /* _old_map3 is changed in _map3_lo and _map3_hi */ - for (i = 0; i < OLD_MAP_SIZE; i++) { - _m[i].m3 = _old_map3[i * 2]; - _m[i].m4 = _old_map3[i * 2 + 1]; - } - - for (i = 0; i < OLD_MAP_SIZE; i ++) { - if (IsTileType(i, MP_RAILWAY)) { - /* We save presignals different from TTDPatch, convert them */ - if (GetRailTileType(i) == RAIL_TILE_SIGNALS) { - /* This byte is always zero in TTD for this type of tile */ - if (_m[i].m4) /* Convert the presignals to our own format */ - _m[i].m4 = (_m[i].m4 >> 1) & 7; - } - /* TTDPatch stores PBS things in L6 and all elsewhere; so we'll just - * clear it for ourselves and let OTTD's rebuild PBS itself */ - _m[i].m4 &= 0xF; /* Only keep the lower four bits; upper four is PBS */ - } - } - - /* Fix the game to be compatible with OpenTTD */ - FixOldTowns(); - FixOldStations(); - FixOldVehicles(); - - AddTypeToEngines(); - - /* We have a new difficulty setting */ - _opt.diff.town_council_tolerance = clamp(_opt.diff_level, 0, 2); - - DEBUG(oldloader, 4, "Finished converting game data"); - DEBUG(oldloader, 1, "TTD(Patch) savegame successfully converted"); - - return true; -} - -bool LoadOldSaveGame(const char *file) -{ - LoadgameState ls; - - DEBUG(oldloader, 4, "Trying to load a TTD(Patch) savegame"); - - InitLoading(&ls); - - /* Open file */ - ls.file = fopen(file, "rb"); - - if (ls.file == NULL) { - DEBUG(oldloader, 0, "Cannot open file '%s'", file); - return false; - } - - /* Load the main chunk */ - if (!LoadOldMain(&ls)) return false; - - fclose(ls.file); - - _pause = 2; - - return true; -} - -void GetOldSaveGameName(char *title, const char *path, const char *file) -{ - char filename[MAX_PATH]; - FILE *f; - - snprintf(filename, lengthof(filename), "%s" PATHSEP "%s", path, file); - f = fopen(filename, "rb"); - title[0] = '\0'; - title[48] = '\0'; - - if (f == NULL) return; - - if (fread(title, 1, 48, f) != 48) snprintf(title, 48, "Corrupt file"); - - fclose(f); -} |