#include "stdafx.h" #include "ttd.h" #include "town.h" #include "industry.h" #include "station.h" #include "economy.h" #include "player.h" #include "engine.h" #include "vehicle.h" extern byte _name_array[512][32]; extern TileIndex _animated_tile_list[256]; #if defined(_MSC_VER) #pragma pack(push, 1) #endif typedef struct { uint16 string_id; uint16 x; uint16 right; uint16 y; uint16 bottom; uint16 duration; uint32 params[2]; } GCC_PACK OldTextEffect; assert_compile(sizeof(OldTextEffect) == 0x14); typedef struct { uint16 xy; uint16 population; uint16 townnametype; uint32 townnameparts; byte grow_counter; byte sort_index; int16 sign_left, sign_top; byte namewidth_1, namewidth_2; uint16 flags12; uint16 radius[5]; uint16 ratings[8]; uint32 have_ratings; uint32 statues; uint16 num_houses; byte time_until_rebuild; byte growth_rate; uint16 new_max_pass, new_max_mail; uint16 new_act_pass, new_act_mail; uint16 max_pass, max_mail; uint16 act_pass, act_mail; byte pct_pass_transported, pct_mail_transported; uint16 new_act_food, new_act_water; uint16 act_food, act_water; byte road_build_months; byte fund_buildings_months; // unused bytes at the end of the Town Struct uint32 unk56; uint32 unk5A; } GCC_PACK OldTown; assert_compile(sizeof(OldTown) == 0x5E); typedef struct { uint16 xy; uint32 town; } GCC_PACK OldDepot; assert_compile(sizeof(OldDepot) == 0x6); typedef struct { uint32 price; uint16 frac; } GCC_PACK OldPrice; assert_compile(sizeof(OldPrice) == 0x6); typedef struct { uint32 price; uint16 frac; uint16 unused; } GCC_PACK OldPaymentRate; assert_compile(sizeof(OldPaymentRate) == 8); typedef struct { uint16 waiting_acceptance; byte days_since_pickup; byte rating; byte enroute_from; byte enroute_time; byte last_speed; byte last_age; } GCC_PACK OldGoodsEntry; assert_compile(sizeof(OldGoodsEntry) == 8); typedef struct { uint16 xy; uint32 town; uint16 bus_tile, lorry_tile, train_tile, airport_tile, dock_tile; byte platforms; byte alpha_order_obsolete; // alpha_order is obsolete since savegame format 4 byte namewidth_1, namewidth_2; uint16 string_id; int16 sign_left, sign_top; uint16 had_vehicle_of_type; OldGoodsEntry goods[12]; byte time_since_load, time_since_unload; byte delete_ctr; byte owner; byte facilities; byte airport_type; byte truck_stop_status, bus_stop_status; byte blocked_months_obsolete; byte unk85; uint16 airport_flags; uint16 last_vehicle; uint32 unk8A; } GCC_PACK OldStation; assert_compile(sizeof(OldStation) == 0x8E); typedef struct { uint16 xy; uint32 town; byte width; byte height; byte produced_cargo[2]; uint16 cargo_waiting[2]; byte production_rate[2]; byte accepts_cargo[3]; byte prod_level; uint16 last_mo_production[2]; uint16 last_mo_transported[2]; byte pct_transported[2]; uint16 total_production[2]; uint16 total_transported[2]; byte type; byte owner; byte color_map; byte last_prod_year; uint16 counter; byte was_cargo_delivered; byte nothing; uint32 unk2E; uint32 unk32; } GCC_PACK OldIndustry; assert_compile(sizeof(OldIndustry) == 0x36); typedef struct { int32 cost[13]; } GCC_PACK OldPlayerExpenses; assert_compile(sizeof(OldPlayerExpenses) == 0x34); typedef struct { int32 income; int32 expenses; uint32 delivered_cargo; uint32 performance_history; uint32 company_value; } GCC_PACK OldPlayerEconomy; assert_compile(sizeof(OldPlayerEconomy) == 0x14); typedef struct { uint16 spec_tile; uint16 use_tile; byte rand_rng; byte cur_rule; byte unk6; byte unk7; byte buildcmd_a; byte buildcmd_b; byte direction; byte cargo; byte unused[8]; } GCC_PACK OldAiBuildRec; assert_compile(sizeof(OldAiBuildRec) == 0x14); typedef struct { uint16 tile; byte data; } GCC_PACK OldAiBannedTile; assert_compile(sizeof(OldAiBannedTile) == 3); typedef struct { uint16 name_1; uint32 name_2; uint32 face; uint16 pres_name_1; uint32 pres_name_2; uint32 money; uint32 loan; byte color; byte money_fract; byte quarters_of_bankrupcy; byte bankrupt_asked; uint32 bankrupt_value; uint16 bankrupt_timeout; uint32 cargo_types; OldPlayerExpenses expenses[3]; OldPlayerEconomy economy[24 + 1]; uint16 inaugurated_date; uint16 last_build_coordinate; byte num_valid_stat_ent; byte ai_state; byte unused; byte ai_state_mode; uint16 ai_state_counter; uint16 ai_timeout_counter; OldAiBuildRec ai_src, ai_dst, ai_mid1, ai_mid2; byte unused_2[20]; byte ai_cargo_type; byte ai_num_wagons; byte ai_build_kind; byte ai_num_build_rec; byte ai_num_loco_to_build; byte ai_num_want_fullload; byte unused_3[14]; uint16 ai_loco_id; // NOT USED uint16 ai_wagonlist[9]; byte ai_order_list_blocks[20]; uint16 ai_start_tile_a; uint16 ai_start_tile_b; uint16 ai_cur_tile_a; uint16 ai_cur_tile_b; byte ai_start_dir_a; byte ai_start_dir_b; byte ai_cur_dir_a; byte ai_cur_dir_b; byte ai_banned_tile_count; OldAiBannedTile banned_tiles[16]; byte ai_railtype_to_use; byte ai_route_type_mask; byte block_preview; byte ai_tick; byte max_railtype; uint16 location_of_house; byte share_owners[4]; uint32 unk3AA; uint32 unk3AE; } GCC_PACK OldPlayer; assert_compile(sizeof(OldPlayer) == 0x3B2); typedef struct { byte track; byte force_proceed; uint16 crash_anim_pos; byte railtype; } GCC_PACK OldVehicleRailUnion; assert_compile(sizeof(OldVehicleRailUnion) == 5); typedef struct { byte unk0; byte targetairport; uint16 crashed_counter; byte state; } GCC_PACK OldVehicleAirUnion; assert_compile(sizeof(OldVehicleAirUnion) == 5); typedef struct { byte state; byte frame; uint16 unk2; byte overtaking; byte overtaking_ctr; uint16 crashed_ctr; byte reverse_ctr; } GCC_PACK OldVehicleRoadUnion; assert_compile(sizeof(OldVehicleRoadUnion) == 9); typedef struct { uint16 unk0; byte unk2; } GCC_PACK OldVehicleSpecialUnion; assert_compile(sizeof(OldVehicleSpecialUnion) == 3); typedef struct { uint16 image_override; uint16 unk2; } GCC_PACK OldVehicleDisasterUnion; assert_compile(sizeof(OldVehicleDisasterUnion) == 4); typedef struct { byte state; } OldVehicleShipUnion; assert_compile(sizeof(OldVehicleShipUnion) == 1); typedef union { OldVehicleRailUnion rail; OldVehicleAirUnion air; OldVehicleRoadUnion road; OldVehicleSpecialUnion special; OldVehicleDisasterUnion disaster; OldVehicleShipUnion ship; byte pad[10]; } GCC_PACK OldVehicleUnion; assert_compile(sizeof(OldVehicleUnion) == 10); typedef struct { byte type; byte subtype; uint16 next_hash; // NOLOAD, calculated automatically. uint16 index; // NOLOAD, calculated automatically. uint32 schedule_ptr; byte next_order, next_order_param; byte num_orders; byte cur_order_index; uint16 dest_tile; uint16 load_unload_time_rem; uint16 date_of_last_service; uint16 service_interval; byte last_station_visited; byte tick_counter; uint16 max_speed; uint16 x_pos, y_pos; byte z_pos; byte direction; byte x_offs, y_offs; byte sprite_width, sprite_height, z_height; byte owner; uint16 tile; uint16 cur_image; int16 left_coord, right_coord, top_coord, bottom_coord; // NOLOAD, calculated automatically. uint16 vehstatus; uint16 cur_speed; byte subspeed; byte acceleration; byte progress; byte cargo_type; uint16 capacity; uint16 number_of_pieces; byte source_of_pieces; byte days_in_transit; uint16 age_in_days, max_age_in_days; byte build_year; byte unitnumber; uint16 engine_type; byte spritenum; byte day_counter; byte breakdowns_since_last_service; byte breakdown_ctr, breakdown_delay, breakdown_chance; uint16 reliability, reliability_spd_dec; uint32 profit_this_year, profit_last_year; uint16 next_in_chain; uint32 value; uint16 string_id; OldVehicleUnion u; byte unused[20]; } GCC_PACK OldVehicle; assert_compile(sizeof(OldVehicle) == 0x80); typedef struct { byte name[32]; } GCC_PACK OldName; typedef struct { uint16 text; int16 x,y,z; byte namewidth_1, namewidth_2; int16 sign_left, sign_top; } GCC_PACK OldSign; assert_compile(sizeof(OldSign) == 0xE); typedef struct { uint16 player_avail; uint16 intro_date; uint16 age; uint16 reliability, reliability_spd_dec, reliability_start, reliability_max, reliability_final; uint16 duration_phase_1, duration_phase_2, duration_phase_3; byte lifelength; byte flags; byte preview_player; byte preview_wait; byte railtype; byte unk1B; } GCC_PACK OldEngine; assert_compile(sizeof(OldEngine) == 0x1C); typedef struct { byte cargo_type; byte age; byte from; byte to; } GCC_PACK OldSubsidy; assert_compile(sizeof(OldSubsidy) == 4); typedef struct { uint16 max_no_competitors; uint16 competitor_start_time; uint16 number_towns; uint16 number_industries; uint16 max_loan; uint16 initial_interest; uint16 vehicle_costs; uint16 competitor_speed; uint16 competitor_intelligence; uint16 vehicle_breakdowns; uint16 subsidy_multiplier; uint16 construction_cost; uint16 terrain_type; uint16 quantity_sea_lakes; uint16 economy; uint16 line_reverse_mode; uint16 disasters; } GCC_PACK OldGameSettings; assert_compile(sizeof(OldGameSettings) == 0x22); typedef struct { uint16 date; uint16 date_fract; OldTextEffect te_list[30]; // NOLOAD: not so important. uint32 seed_1, seed_2; OldTown town_list[70]; uint16 order_list[5000]; uint16 animated_tile_list[256]; uint32 ptr_to_next_order; OldDepot depots[255]; uint32 cur_town_ptr; uint16 timer_counter; uint16 land_code; // NOLOAD: never needed in game uint16 age_cargo_skip_counter; uint16 tick_counter; uint16 cur_tileloop_tile; OldPrice prices[49]; OldPaymentRate cargo_payment_rates[12]; byte map_owner[256*256]; byte map2[256*256]; uint16 map3[256*256]; byte map_extra[256*256/4]; OldStation stations[250]; OldIndustry industries[90]; OldPlayer players[8]; OldVehicle vehicles[850]; OldName names[500]; uint16 vehicle_position_hash[0x1000]; // NOLOAD, calculated automatically. OldSign signs[40]; OldEngine engines[256]; uint16 vehicle_id_ctr_day; OldSubsidy subsidies[8]; uint16 next_competitor_start; uint16 saved_main_scrollpos_x, saved_main_scrollpos_y, saved_main_scrollpos_zoom; uint32 maximum_loan, maximum_loan_unround; uint16 economy_fluct; uint16 disaster_delay; //NOLOAD. These are calculated from InitializeLandscapeVariables uint16 cargo_names_s[12], cargo_names_p[12], cargo_names_long_s[12], cargo_names_long_p[12], cargo_names_short[12]; uint16 cargo_sprites[12]; uint16 engine_name_strings[256]; //NOLOAD. These are calculated from InitializeLandscapeVariables uint16 railveh_by_cargo_1[12], railveh_by_cargo_2[12], railveh_by_cargo_3[12]; uint16 roadveh_by_cargo_start[12]; byte roadveh_by_cargo_count[12]; uint16 ship_of_type_start[12]; byte ship_of_type_count[12]; byte human_player_1, human_player_2; //NOLOAD. Calculated automatically. byte station_tick_ctr; byte currency; byte use_kilometers; byte cur_player_tick_index; byte cur_year, cur_month; //NOLOAD. Calculated automatically. byte player_colors[8]; //NOLOAD. Calculated automatically byte inflation_amount; byte inflation_amount_payment_rates; byte interest_rate; byte avail_aircraft; byte road_side; byte town_name_type; OldGameSettings game_diff; byte difficulty_level; byte landscape_type; byte trees_tick_ctr; byte vehicle_design_names; byte snow_line_height; byte new_industry_randtable[32]; // NOLOAD. Not needed due to different code design. //NOLOAD. Initialized by InitializeLandscapeVariables byte cargo_weights[12]; byte transit_days_table_1[12]; byte transit_days_table_2[12]; byte map_type_and_height[256*256]; byte map5[256*256]; } GCC_PACK OldMain; assert_compile(sizeof(OldMain) == 487801 + 256*256*2); #if defined(_MSC_VER) #pragma pack(pop) #endif #define REMAP_TOWN_IDX(x) (x - (0x0459154 - 0x0458EF0)) / sizeof(OldTown) #define REMAP_TOWN_PTR(x) DEREF_TOWN( REMAP_TOWN_IDX(x) ) #define REMAP_ORDER_IDX(x) (x - (0x045AB08 - 0x0458EF0)) / sizeof(uint16) typedef struct LoadSavegameState { int8 mode; byte rep_char; size_t count; size_t buffer_count; FILE *fin; byte *buffer_cur; byte buffer[4096]; } LoadSavegameState; static LoadSavegameState *_cur_state; static byte GetSavegameByteFromBuffer() { LoadSavegameState *lss = _cur_state; if (lss->buffer_count == 0) { int count = fread(lss->buffer, 1, 4096, lss->fin) ; /* if (count == 0) { memset(lss->buffer, 0, sizeof(lss->buffer)); count = 4096; }*/ assert(count != 0); lss->buffer_count = count; lss->buffer_cur = lss->buffer; } lss->buffer_count--; return *lss->buffer_cur++; } static byte DecodeSavegameByte() { LoadSavegameState *lss = _cur_state; int8 x; if (lss->mode < 0) { if (lss->count != 0) { lss->count--; return lss->rep_char; } } else if (lss->mode > 0) { if (lss->count != 0) { lss->count--; return GetSavegameByteFromBuffer(); } } x = GetSavegameByteFromBuffer(); if (x >= 0) { lss->count = x; lss->mode = 1; return GetSavegameByteFromBuffer(); } else { lss->mode = -1; lss->count = -x; lss->rep_char = GetSavegameByteFromBuffer(); return lss->rep_char; } } static void LoadSavegameBytes(void *p, size_t count) { byte *ptr = (byte*)p; assert(count > 0); do { *ptr++ = DecodeSavegameByte(); } while (--count); } extern uint32 GetOldTownName(uint32 townnameparts, byte old_town_name_type); static void FixTown(Town *t, OldTown *o, int num, byte town_name_type) { do { t->xy = o->xy; t->population = o->population; t->townnametype = o->townnametype; t->townnameparts = o->townnameparts; // Random TownNames if (IS_INT_INSIDE(o->townnametype, 0x20C1, 0x20C2 + 1)) { t->townnametype = SPECSTR_TOWNNAME_ENGLISH + town_name_type; if (o->xy) t->townnameparts = GetOldTownName(o->townnameparts, town_name_type); } t->grow_counter = o->grow_counter; t->flags12 = o->flags12; memcpy(t->ratings,o->ratings,sizeof(t->ratings)); t->have_ratings = o->have_ratings; t->statues = o->statues; t->num_houses = o->num_houses; t->time_until_rebuild = o->time_until_rebuild; t->growth_rate = o->growth_rate; t->new_max_pass = o->new_max_pass; t->new_max_mail = o->new_max_mail; t->new_act_pass = o->new_act_pass; t->new_act_mail = o->new_act_mail; t->max_pass = o->max_pass; t->max_mail = o->max_mail; t->act_pass = o->act_pass; t->act_mail = o->act_mail; t->pct_pass_transported = o->pct_pass_transported; t->pct_mail_transported = o->pct_mail_transported; t->new_act_food = o->new_act_food; t->new_act_water = o->new_act_water; t->act_food = o->act_food; t->act_water = o->act_water; t->road_build_months = o->road_build_months; t->fund_buildings_months = o->fund_buildings_months; } while (t++,o++,--num); } static void FixIndustry(Industry *i, OldIndustry *o, int num) { do { i->xy = o->xy; i->town = REMAP_TOWN_PTR(o->town); i->width = o->width; i->height = o->height; i->produced_cargo[0] = o->produced_cargo[0]; i->produced_cargo[1] = o->produced_cargo[1]; i->cargo_waiting[0] = o->cargo_waiting[0]; i->cargo_waiting[1] = o->cargo_waiting[1]; i->production_rate[0] = o->production_rate[0]; i->production_rate[1] = o->production_rate[1]; i->accepts_cargo[0] = o->accepts_cargo[0]; i->accepts_cargo[1] = o->accepts_cargo[1]; i->accepts_cargo[2] = o->accepts_cargo[2]; i->prod_level = o->prod_level; i->last_mo_production[0] = o->last_mo_production[0]; i->last_mo_production[1] = o->last_mo_production[1]; i->last_mo_transported[0] = o->last_mo_transported[0]; i->last_mo_transported[1] = o->last_mo_transported[1]; i->last_mo_transported[2] = o->last_mo_transported[2]; i->pct_transported[0] = o->pct_transported[0]; i->pct_transported[1] = o->pct_transported[1]; i->total_production[0] = o->total_production[0]; i->total_production[1] = o->total_production[1]; i->total_transported[0] = i->total_transported[0]; i->total_transported[1] = i->total_transported[1]; i->type = o->type; i->owner = o->owner; i->color_map = o->color_map; i->last_prod_year = o->last_prod_year; i->counter = o->counter; i->was_cargo_delivered = o->was_cargo_delivered; } while (i++,o++,--num); } static void FixGoodsEntry(GoodsEntry *g, OldGoodsEntry *o, int num) { do { g->waiting_acceptance = o->waiting_acceptance; g->days_since_pickup = o->days_since_pickup; g->rating = o->rating; g->enroute_from = o->enroute_from; g->enroute_time = o->enroute_time; g->last_speed = o->last_speed; g->last_age = o->last_age; } while (g++,o++,--num); } static void FixStation(Station *s, OldStation *o, int num) { do { s->xy = o->xy; s->town = REMAP_TOWN_PTR(o->town); s->bus_tile = o->bus_tile; s->lorry_tile = o->lorry_tile; s->train_tile = o->train_tile; s->airport_tile = o->airport_tile; s->dock_tile = o->dock_tile; if (o->train_tile) { int w = (o->platforms >> 3) & 0x7; int h = (o->platforms & 0x7); if (_map5[o->train_tile]&1) intswap(w,h); s->trainst_w = w; s->trainst_h = h; } s->string_id = RemapOldStringID(o->string_id); s->had_vehicle_of_type = o->had_vehicle_of_type; FixGoodsEntry(s->goods, o->goods, lengthof(o->goods)); s->time_since_load = o->time_since_load; s->time_since_unload = o->time_since_unload; s->delete_ctr = o->delete_ctr; s->owner = o->owner; s->facilities = o->facilities; s->airport_type = o->airport_type; s->truck_stop_status = o->truck_stop_status; s->bus_stop_status = o->bus_stop_status; s->blocked_months_obsolete = o->blocked_months_obsolete; s->airport_flags = o->airport_flags; s->last_vehicle = o->last_vehicle; } while (s++,o++,--num); } static void FixDepot(Depot *n, OldDepot *o, int num) { do { n->town_index = REMAP_TOWN_IDX(o->town); n->xy = o->xy; } while (n++,o++,--num); } static void FixVehicle(Vehicle *n, OldVehicle *o, int num) { do { n->type = o->type; n->subtype = o->subtype; if (o->schedule_ptr == 0xFFFFFFFF || o->schedule_ptr == 0) { n->schedule_ptr = NULL; } else { n->schedule_ptr = _order_array + REMAP_ORDER_IDX(o->schedule_ptr); assert(n->schedule_ptr >= _order_array && n->schedule_ptr < _ptr_to_next_order); } n->next_order = o->next_order; n->next_order_param = o->next_order_param; n->num_orders = o->num_orders; n->cur_order_index = o->cur_order_index; n->dest_tile = o->dest_tile; n->load_unload_time_rem = o->load_unload_time_rem; n->date_of_last_service = o->date_of_last_service; n->service_interval = o->service_interval; n->last_station_visited = o->last_station_visited; n->tick_counter = o->tick_counter; n->max_speed = o->max_speed; n->x_pos = o->x_pos; n->y_pos = o->y_pos; n->z_pos = o->z_pos; n->direction = o->direction; n->x_offs = o->x_offs; n->y_offs = o->y_offs; n->sprite_width = o->sprite_width; n->sprite_height = o->sprite_height; n->z_height = o->z_height; n->owner = o->owner; n->tile = o->tile; n->cur_image = o->cur_image; n->vehstatus = o->vehstatus; n->cur_speed = o->cur_speed; n->subspeed = o->subspeed; n->acceleration = o->acceleration; n->progress = o->progress; n->cargo_type = o->cargo_type; n->cargo_cap = o->capacity; n->cargo_count = o->number_of_pieces; n->cargo_source = o->source_of_pieces; n->cargo_days = o->days_in_transit; n->age = o->age_in_days; n->max_age = o->max_age_in_days; n->build_year = o->build_year; n->unitnumber = o->unitnumber; n->engine_type = o->engine_type; n->spritenum = o->spritenum>>1; n->day_counter = o->day_counter; n->breakdowns_since_last_service = o->breakdowns_since_last_service; n->breakdown_ctr = o->breakdown_ctr; n->breakdown_delay = o->breakdown_delay; n->breakdown_chance = o->breakdown_chance; n->reliability = o->reliability; n->reliability_spd_dec = o->reliability_spd_dec; n->profit_this_year = o->profit_this_year; n->profit_last_year = o->profit_last_year; n->next = o->next_in_chain == 0xffff ? NULL : &_vehicles[o->next_in_chain]; n->value = o->value; n->string_id = RemapOldStringID(o->string_id); switch(o->type) { case VEH_Train: n->u.rail.track = o->u.rail.track; n->u.rail.force_proceed = o->u.rail.force_proceed; n->u.rail.crash_anim_pos = o->u.rail.crash_anim_pos; n->u.rail.railtype = o->u.rail.railtype; break; case VEH_Road: n->u.road.state = o->u.road.state; n->u.road.frame = o->u.road.frame; n->u.road.unk2 = o->u.road.unk2; n->u.road.overtaking = o->u.road.overtaking; n->u.road.overtaking_ctr = o->u.road.overtaking_ctr; n->u.road.crashed_ctr = o->u.road.crashed_ctr; n->u.road.reverse_ctr = o->u.road.reverse_ctr; break; case VEH_Ship: n->u.ship.state = o->u.ship.state; break; case VEH_Aircraft: n->u.air.crashed_counter = o->u.air.crashed_counter; n->u.air.pos = o->u.air.unk0; n->u.air.targetairport = o->u.air.targetairport; n->u.air.state = o->u.air.state; break; case VEH_Special: n->u.special.unk0 = o->u.special.unk0; n->u.special.unk2 = o->u.special.unk2; n->subtype = o->subtype >> 1; break; case VEH_Disaster: n->u.disaster.image_override = o->u.disaster.image_override; n->u.disaster.unk2 = o->u.disaster.unk2; break; } } while (n++,o++,--num); } static void FixSubsidy(Subsidy *n, OldSubsidy *o, int num) { do { n->age = o->age; n->cargo_type = o->cargo_type; n->from = o->from; n->to = o->to; } while (n++,o++,--num); } static void FixEconomy(PlayerEconomyEntry *n, OldPlayerEconomy *o) { n->company_value = o->company_value; n->delivered_cargo = o->delivered_cargo; n->income = -o->income; n->expenses = -o->expenses; n->performance_history = o->performance_history; } static void FixAiBuildRec(AiBuildRec *n, OldAiBuildRec *o) { n->spec_tile = o->spec_tile; n->use_tile = o->use_tile; n->rand_rng = o->rand_rng; n->cur_building_rule = o->cur_rule; n->unk6 = o->unk6; n->unk7 = o->unk7; n->buildcmd_a = o->buildcmd_a; n->buildcmd_b = o->buildcmd_b; n->direction = o->direction; n->cargo = o->cargo; } static void FixPlayer(Player *n, OldPlayer *o, int num, byte town_name_type) { int i, j; int x = 0; do { n->name_1 = RemapOldStringID(o->name_1); n->name_2 = o->name_2; /* In every Old TTD(Patch) game Player1 (0) is human, and all others are AI * (Except in .SV2 savegames, which were 2 player games, but we are not fixing * that */ if (x == 0) { if (o->name_1 == 0) // if first player doesn't have a name, he is 'unnamed' n->name_1 = STR_SV_UNNAMED; } else { n->is_ai = 1; } if (o->name_1 != 0) n->is_active = true; n->face = o->face; n->president_name_1 = o->pres_name_1; n->president_name_2 = o->pres_name_2; n->money64 = n->player_money = o->money; n->current_loan = o->loan; // Correct money for scenario loading. // It's always 893288 pounds (and no loan), if not corrected if(o->money==0xda168) n->money64 = n->player_money = n->current_loan =100000; n->player_color = o->color; _player_colors[x] = o->color; x++; n->player_money_fraction = o->money_fract; n->quarters_of_bankrupcy = o->quarters_of_bankrupcy; n->bankrupt_asked = o->bankrupt_asked; n->bankrupt_value = o->bankrupt_value; n->bankrupt_timeout = o->bankrupt_timeout; n->cargo_types = o->cargo_types; for(i=0; i!=3; i++) for(j=0; j!=13; j++) n->yearly_expenses[i][j] = o->expenses[i].cost[j]; FixEconomy(&n->cur_economy, &o->economy[0]); for(i=0; i!=24; i++) FixEconomy(&n->old_economy[i], &o->economy[i+1]); n->inaugurated_year = o->inaugurated_date - 1920; n->last_build_coordinate = o->last_build_coordinate; n->num_valid_stat_ent = o->num_valid_stat_ent; /* Not good, since AI doesn't have a vehicle assigned as * in p->ai.cur_veh and thus will crash on certain actions. * Best is to set state to AiStateVehLoop (2) * n->ai.state = o->ai_state; */ n->ai.state = 2; n->ai.state_mode = o->ai_state_mode; n->ai.state_counter = o->ai_state_counter; n->ai.timeout_counter = o->ai_timeout_counter; n->ai.banned_tile_count = o->ai_banned_tile_count; n->ai.railtype_to_use = o->ai_railtype_to_use; FixAiBuildRec(&n->ai.src, &o->ai_src); FixAiBuildRec(&n->ai.dst, &o->ai_dst); FixAiBuildRec(&n->ai.mid1, &o->ai_mid1); FixAiBuildRec(&n->ai.mid2, &o->ai_mid2); n->ai.cargo_type = o->ai_cargo_type; n->ai.num_wagons = o->ai_num_wagons; n->ai.num_build_rec = o->ai_num_build_rec; n->ai.num_loco_to_build = o->ai_num_loco_to_build; n->ai.num_want_fullload = o->ai_num_want_fullload; for(i=0; i!=9; i++) n->ai.wagon_list[i] = o->ai_wagonlist[i]; memcpy(n->ai.order_list_blocks, o->ai_order_list_blocks, 20); n->ai.start_tile_a = o->ai_start_tile_a; n->ai.start_tile_b = o->ai_start_tile_b; n->ai.cur_tile_a = o->ai_cur_tile_a; n->ai.cur_tile_b = o->ai_cur_tile_b; n->ai.start_dir_a = o->ai_start_dir_a; n->ai.start_dir_b = o->ai_start_dir_b; n->ai.cur_dir_a = o->ai_cur_dir_a; n->ai.cur_dir_b = o->ai_cur_dir_b; for(i=0; i!=16; i++) { n->ai.banned_tiles[i] = o->banned_tiles[i].tile; n->ai.banned_val[i] = o->banned_tiles[i].data; } n->ai.build_kind = o->ai_build_kind; n->ai.route_type_mask = o->ai_route_type_mask; n->ai.tick = o->ai_tick; n->block_preview = o->block_preview; n->max_railtype = (o->max_railtype == 0) ? 1 : o->max_railtype; n->location_of_house = o->location_of_house; if (o->location_of_house == 0xFFFF) n->location_of_house = 0; n->share_owners[0] = o->share_owners[0]; n->share_owners[1] = o->share_owners[1]; n->share_owners[2] = o->share_owners[2]; n->share_owners[3] = o->share_owners[3]; if (o->ai_state == 2) { n->ai.cur_veh = NULL; } } while (n++,o++,--num); } static void FixName(OldName *o, int num) { int i; for(i=0; i!=num; i++) { memcpy(_name_array[i], o[i].name, sizeof(o[i].name)); } } static void FixSign(SignStruct *n, OldSign *o, int num) { do { n->str = o->text; n->x = o->x; n->y = o->y; n->z = o->z; } while (n++,o++,--num); } static void FixEngine(Engine *n, OldEngine *o, int num) { int i = 0; do { n->player_avail = o->player_avail; n->intro_date = o->intro_date; n->age = o->age; if ((i >= 27 && i < 54) || (i >= 57 && i < 84) || (i >= 89 && i < 116)) n->age = 0xffff; n->reliability = o->reliability; n->reliability_spd_dec = o->reliability_spd_dec; n->reliability_start = o->reliability_start; n->reliability_max = o->reliability_max; n->reliability_final = o->reliability_final; n->duration_phase_1 = o->duration_phase_1; n->duration_phase_2 = o->duration_phase_2; n->duration_phase_3 = o->duration_phase_3; n->lifelength = o->lifelength; n->flags = o->flags; n->preview_player = o->preview_player; n->preview_wait = o->preview_wait; n->railtype = o->railtype; } while (n++,o++,i++,--num); } void FixGameDifficulty(GameDifficulty *n, OldGameSettings *o) { n->max_no_competitors = o->max_no_competitors; n->competitor_start_time = o->competitor_start_time; n->number_towns = o->number_towns; n->number_industries = o->number_industries; n->max_loan = o->max_loan; n->initial_interest = o->initial_interest; n->vehicle_costs = o->vehicle_costs; n->competitor_speed = o->competitor_speed; n->competitor_intelligence = o->competitor_intelligence; n->vehicle_breakdowns = o->vehicle_breakdowns; n->subsidy_multiplier = o->subsidy_multiplier; n->construction_cost = o->construction_cost; n->terrain_type = o->terrain_type; n->quantity_sea_lakes = o->quantity_sea_lakes; n->economy = o->economy; n->line_reverse_mode = o->line_reverse_mode; n->disasters = o->disasters; } // loader for old style savegames bool LoadOldSaveGame(const char *file) { LoadSavegameState lss; OldMain *m; int i; _cur_state = &lss; memset(&lss, 0, sizeof(lss)); lss.fin = fopen(file, "rb"); if (lss.fin == NULL) return false; /* B - byte 8bit (1) * W - word 16bit (2 bytes) * L - 'long' word 32bit (4 bytes) */ fseek(lss.fin, 49, SEEK_SET); // 47B TITLE, W Checksum - Total 49 /* Load the file into memory * Game Data 0x77179 + L4 (256x256) + L5 (256x256) */ m = (OldMain *)malloc(sizeof(OldMain)); LoadSavegameBytes(m, sizeof(OldMain)); // copy sections of it to our datastructures. memcpy(_map_owner, m->map_owner, sizeof(_map_owner)); memcpy(_map2, m->map2, sizeof(_map2)); memcpy(_map_type_and_height, m->map_type_and_height, sizeof(_map_type_and_height)); memcpy(_map5, m->map5, sizeof(_map5)); for(i=0; i!=256*256; i++) { _map3_lo[i] = m->map3[i] & 0xFF; _map3_hi[i] = m->map3[i] >> 8; } memcpy(_map_extra_bits, m->map_extra, sizeof(_map_extra_bits)); // go through the tables and see if we can find any ttdpatch presignals. Then convert those to our format. for(i=0; i!=256*256; i++) { if (IS_TILETYPE(i, MP_RAILWAY) && (_map5[i] & 0xC0) == 0x40) { // this byte is always zero in real ttd. if (_map3_hi[i]) { // convert ttdpatch presignal format to openttd presignal format. _map3_hi[i] = (_map3_hi[i] >> 1) & 7; } } } memcpy(_order_array, m->order_list, sizeof(m->order_list)); _ptr_to_next_order = _order_array + REMAP_ORDER_IDX(m->ptr_to_next_order); FixTown(_towns, m->town_list, lengthof(m->town_list), m->town_name_type); FixIndustry(_industries, m->industries, lengthof(m->industries)); FixStation(_stations, m->stations, lengthof(m->stations)); FixDepot(_depots, m->depots, lengthof(m->depots)); FixVehicle(_vehicles, m->vehicles, lengthof(m->vehicles)); FixSubsidy(_subsidies, m->subsidies, lengthof(m->subsidies)); FixPlayer(_players, m->players, lengthof(m->players), m->town_name_type); FixName(m->names, lengthof(m->names)); FixSign(_sign_list, m->signs, lengthof(m->signs)); FixEngine(_engines, m->engines, lengthof(m->engines)); _opt.diff_level = m->difficulty_level; _opt.currency = m->currency; _opt.kilometers = m->use_kilometers; _opt.town_name = m->town_name_type; _opt.landscape = m->landscape_type; _opt.snow_line = m->snow_line_height; _opt.autosave = 0; _opt.road_side = m->road_side; FixGameDifficulty(&_opt.diff, &m->game_diff); // Load globals _date = m->date; _date_fract = m->date_fract; _tick_counter = m->tick_counter; _vehicle_id_ctr_day = m->vehicle_id_ctr_day; _age_cargo_skip_counter = m->age_cargo_skip_counter; _avail_aircraft = m->avail_aircraft; _cur_tileloop_tile = m->cur_tileloop_tile; _disaster_delay = m->disaster_delay; _station_tick_ctr = m->station_tick_ctr; _random_seeds[0][0] = m->seed_1; _random_seeds[0][1] = m->seed_2; _cur_town_ctr = REMAP_TOWN_IDX(m->cur_town_ptr); _cur_player_tick_index = m->cur_player_tick_index; _next_competitor_start = m->next_competitor_start; _trees_tick_ctr = m->trees_tick_ctr; _saved_scrollpos_x = m->saved_main_scrollpos_x; _saved_scrollpos_y = m->saved_main_scrollpos_y; _saved_scrollpos_zoom = m->saved_main_scrollpos_zoom; // Load economy stuff _economy.max_loan = m->maximum_loan; _economy.max_loan_unround = m->maximum_loan_unround; _economy.fluct = m->economy_fluct; _economy.interest_rate = m->interest_rate; _economy.infl_amount = m->inflation_amount; _economy.infl_amount_pr = m->inflation_amount_payment_rates; memcpy(_animated_tile_list, m->animated_tile_list, sizeof(m->animated_tile_list)); memcpy(_engine_name_strings, m->engine_name_strings, sizeof(m->engine_name_strings)); for(i=0; i!=lengthof(m->prices); i++) { ((uint32*)&_price)[i] = m->prices[i].price; _price_frac[i] = m->prices[i].frac; } for(i=0; i!=lengthof(m->cargo_payment_rates); i++) { _cargo_payment_rates[i] = -(int32)m->cargo_payment_rates[i].price; _cargo_payment_rates_frac[i] = m->cargo_payment_rates[i].frac; } free(m); fclose(lss.fin); return true; } void GetOldSaveGameName(char *title, const char *file) { FILE *f; f = fopen(file, "rb"); title[0] = 0; title[48] = 0; if (!f) return; if (fread(title, 1, 48, f) != 48) title[0] = 0; fclose(f); } void GetOldScenarioGameName(char *title, const char *file) { GetOldSaveGameName(title, file); }