diff --git a/date.c b/date.c --- a/date.c +++ b/date.c @@ -70,25 +70,47 @@ static const uint16 _accum_days_for_mont ACCUM_SEP, ACCUM_OCT, ACCUM_NOV, ACCUM_DEC, }; +static inline bool IsLeapYear(Year yr) +{ + return yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0); +} +/** + * Converts a Date to a Year, Month & Day. + * @param date the date to convert from + * @param ymd the year, month and day to write to + */ void ConvertDateToYMD(Date date, YearMonthDay *ymd) { - uint yr = date / (365 + 365 + 365 + 366); - uint rem = date % (365 + 365 + 365 + 366); - uint x; + /* + * Year determination in multiple steps to account for leap + * years. First do the large steps, then the smaller ones. + */ - yr *= 4; + /* There are 97 leap years in 400 years */ + Year yr = 400 * (date / (365 * 400 + 97)); + int rem = date % (365 * 400 + 97); + uint16 x; - if (rem >= 366) { - rem--; - do { - rem -= 365; - yr++; - } while (rem >= 365); - if (rem >= 31 + 28) rem++; + /* There are 24 leap years in 100 years */ + yr += 100 * (rem / (365 * 100 + 24)); + rem = rem % (365 * 100 + 24); + + /* There is 1 leap year every 4 years */ + yr += 4 * (rem / (365 * 4 + 1)); + rem = rem % (365 * 4 + 1); + + /* The last (max 3) years to account for; the first one + * can be, but is not necessarily a leap year */ + while (rem >= (IsLeapYear(yr) ? 366 : 365)) { + rem -= IsLeapYear(yr) ? 366 : 365; + yr++; } - ymd->year = BASE_YEAR + yr; + /* Skip the 29th of February in non-leap years */ + if (!IsLeapYear(yr) && rem >= ACCUM_MAR - 1) rem++; + + ymd->year = yr; x = _month_date_from_year_day[rem]; ymd->month = x >> 5; @@ -97,23 +119,28 @@ void ConvertDateToYMD(Date date, YearMon /** * Converts a tupe of Year, Month and Day to a Date. - * @param year is a number between 0..? + * @param year is a number between 0..MAX_YEAR * @param month is a number between 0..11 * @param day is a number between 1..31 */ Date ConvertYMDToDate(Year year, Month month, Day day) { - uint rem; - uint yr = year - BASE_YEAR; - - /* day in the year */ - rem = _accum_days_for_month[month] + day - 1; + /* + * Each passed leap year adds one day to the 'day count'. + * + * A special case for the year 0 as no year has been passed, + * but '(year - 1) / 4' does not yield '-1' to counteract the + * '+1' at the end of the formula as divisions round to zero. + */ + int nr_of_leap_years = (year == 0) ? 0 : ((year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400 + 1); - /* remove feb 29 from year 1,2,3 */ - if (yr & 3) rem += (yr & 3) * 365 + (rem < 31 + 29); + /* Day-offset in a leap year */ + int days = _accum_days_for_month[month] + day - 1; - /* base date. */ - return (yr >> 2) * (365 + 365 + 365 + 366) + rem; + /* Account for the missing of the 29th of February in non-leap years */ + if (!IsLeapYear(year) && days >= ACCUM_MAR) days--; + + return year * 365 + nr_of_leap_years + days; } /** Functions used by the IncreaseDate function */ @@ -252,12 +279,12 @@ void IncreaseDate(void) /* check if we reached the maximum year, decrement dates by a year */ } else if (_cur_year == MAX_YEAR + 1) { Vehicle *v; + uint days_this_year; _cur_year--; - _date -= 365; - FOR_ALL_VEHICLES(v) { - v->date_of_last_service -= 365; - } + days_this_year = IsLeapYear(_cur_year) ? 366 : 365; + _date -= days_this_year; + FOR_ALL_VEHICLES(v) v->date_of_last_service -= days_this_year; /* Because the _date wraps here, and text-messages expire by game-days, we have to clean out * all of them if the date is set back, else those messages will hang for ever */ diff --git a/date.h b/date.h --- a/date.h +++ b/date.h @@ -24,14 +24,16 @@ * The offset in days from the '_date == 0' till * 'ConvertYMDToDate(ORIGINAL_BASE_YEAR, 0, 1)' */ -#define DAYS_TILL_ORIGINAL_BASE_YEAR 0 +#define DAYS_TILL_ORIGINAL_BASE_YEAR (365 * ORIGINAL_BASE_YEAR + ORIGINAL_BASE_YEAR / 4 - ORIGINAL_BASE_YEAR / 100 + ORIGINAL_BASE_YEAR / 400) /* Temporary value to make transition to full past 2090 easier/more clear */ -#define BASE_YEAR 1920 +#define BASE_YEAR 0 /* The absolute minimum & maximum years in OTTD */ -#define MIN_YEAR 1920 -#define MAX_YEAR 2090 +#define MIN_YEAR 0 +/* MAX_YEAR, nicely rounded value of the number of years that can + * be encoded in a single 32 bits date, about 2^31 / 366 years. */ +#define MAX_YEAR 5000000 /* Year and Date are defined elsewhere */ typedef uint8 Month; diff --git a/engine.c b/engine.c --- a/engine.c +++ b/engine.c @@ -606,8 +606,10 @@ static void Load_ERNW(void) } static const SaveLoad _engine_desc[] = { - SLE_VAR(Engine,intro_date, SLE_UINT16), - SLE_VAR(Engine,age, SLE_UINT16), + SLE_CONDVAR(Engine,intro_date, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), + SLE_CONDVAR(Engine,intro_date, SLE_INT32, 31, SL_MAX_VERSION), + SLE_CONDVAR(Engine,age, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), + SLE_CONDVAR(Engine,age, SLE_INT32, 31, SL_MAX_VERSION), SLE_VAR(Engine,reliability, SLE_UINT16), SLE_VAR(Engine,reliability_spd_dec, SLE_UINT16), SLE_VAR(Engine,reliability_start, SLE_UINT16), diff --git a/engine.h b/engine.h --- a/engine.h +++ b/engine.h @@ -76,8 +76,8 @@ typedef struct RoadVehicleInfo { typedef struct EngineInfo { Date base_intro; byte unk2; ///< Carriages have the highest bit set in this one - byte lifelength; - byte base_life; + Year lifelength; + Year base_life; byte railtype:4; byte climates:4; uint32 refit_mask; diff --git a/genworld_gui.c b/genworld_gui.c --- a/genworld_gui.c +++ b/genworld_gui.c @@ -362,7 +362,7 @@ void GenerateLandscapeWndProc(Window *w, case 19: // Year text WP(w, def_d).data_3 = START_DATE_QUERY; SetDParam(0, _patches_newgame.starting_year); - ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 5, 100, WC_GENERATE_LANDSCAPE, mode, CS_NUMERAL); + ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, WC_GENERATE_LANDSCAPE, mode, CS_NUMERAL); break; case 21: case 23: // Snow line buttons /* Don't allow too fast scrolling */ @@ -629,7 +629,7 @@ void CreateScenarioWndProc(Window *w, Wi case 15: // Year text WP(w, def_d).data_3 = START_DATE_QUERY; SetDParam(0, _patches_newgame.starting_year); - ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 5, 100, WC_GENERATE_LANDSCAPE, GLWP_SCENARIO, CS_NUMERAL); + ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, WC_GENERATE_LANDSCAPE, GLWP_SCENARIO, CS_NUMERAL); break; case 17: case 19: // Height level buttons /* Don't allow too fast scrolling */ diff --git a/industry.h b/industry.h --- a/industry.h +++ b/industry.h @@ -28,7 +28,7 @@ struct Industry { byte type; byte owner; byte color_map; - byte last_prod_year; + Year last_prod_year; byte was_cargo_delivered; uint16 index; diff --git a/industry_cmd.c b/industry_cmd.c --- a/industry_cmd.c +++ b/industry_cmd.c @@ -1929,7 +1929,8 @@ static const SaveLoad _industry_desc[] = SLE_VAR(Industry,type, SLE_UINT8), SLE_VAR(Industry,owner, SLE_UINT8), SLE_VAR(Industry,color_map, SLE_UINT8), - SLE_VAR(Industry,last_prod_year, SLE_UINT8), + SLE_CONDVAR(Industry, last_prod_year, SLE_FILE_U8 | SLE_VAR_I32, 0, 30), + SLE_CONDVAR(Industry, last_prod_year, SLE_INT32, 31, SL_MAX_VERSION), SLE_VAR(Industry,was_cargo_delivered,SLE_UINT8), // reserve extra space in savegame here. (currently 32 bytes) diff --git a/misc.c b/misc.c --- a/misc.c +++ b/misc.c @@ -268,7 +268,8 @@ static void Load_NAME(void) } static const SaveLoadGlobVarList _date_desc[] = { - SLEG_VAR(_date, SLE_UINT16), + SLEG_CONDVAR(_date, SLE_FILE_U16 | SLE_VAR_U32, 0, 30), + SLEG_CONDVAR(_date, SLE_UINT32, 31, SL_MAX_VERSION), SLEG_VAR(_date_fract, SLE_UINT16), SLEG_VAR(_tick_counter, SLE_UINT16), SLEG_VAR(_vehicle_id_ctr_day, SLE_UINT16), diff --git a/misc_gui.c b/misc_gui.c --- a/misc_gui.c +++ b/misc_gui.c @@ -1714,7 +1714,7 @@ static const CheatEntry _cheats_ui[] = { {SLE_BOOL, 0, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, NULL, 0, 0}, {SLE_BOOL, 0, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, NULL, 0, 0}, {SLE_UINT8, 0, STR_CHEAT_SWITCH_CLIMATE, &_opt.landscape, &_cheats.switch_climate.been_used, &ClickChangeClimateCheat,-1, 4}, - {SLE_UINT8, 0, STR_CHEAT_CHANGE_DATE, &_cur_year, &_cheats.change_date.been_used, &ClickChangeDateCheat, -1, 1}, + {SLE_INT32, 0, STR_CHEAT_CHANGE_DATE, &_cur_year, &_cheats.change_date.been_used, &ClickChangeDateCheat, -1, 1}, {SLE_BOOL, 0, STR_CHEAT_ALLOW_CONVRAIL, &_cheats.elrail.value, &_cheats.elrail.been_used, &ClickAllowConvrail, 0, 0}, }; diff --git a/network.h b/network.h --- a/network.h +++ b/network.h @@ -89,7 +89,7 @@ typedef struct NetworkGameInfo { typedef struct NetworkPlayerInfo { char company_name[NETWORK_NAME_LENGTH]; // Company name char password[NETWORK_PASSWORD_LENGTH]; // The password for the player - byte inaugurated_year; // What year the company started in + Year inaugurated_year; // What year the company started in int64 company_value; // The company value int64 money; // The amount of money the company has int64 income; // How much did the company earned last year diff --git a/network_client.c b/network_client.c --- a/network_client.c +++ b/network_client.c @@ -300,7 +300,7 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER return NETWORK_RECV_STATUS_CLOSE_QUERY; NetworkRecv_string(MY_CLIENT, p, _network_player_info[current].company_name, sizeof(_network_player_info[current].company_name)); - _network_player_info[current].inaugurated_year = NetworkRecv_uint8(MY_CLIENT, p); + _network_player_info[current].inaugurated_year = NetworkRecv_uint32(MY_CLIENT, p); _network_player_info[current].company_value = NetworkRecv_uint64(MY_CLIENT, p); _network_player_info[current].money = NetworkRecv_uint64(MY_CLIENT, p); _network_player_info[current].income = NetworkRecv_uint64(MY_CLIENT, p); diff --git a/network_data.h b/network_data.h --- a/network_data.h +++ b/network_data.h @@ -18,9 +18,9 @@ #define NETWORK_EMPTY_INDEX 0 // What version of game-info do we use? -#define NETWORK_GAME_INFO_VERSION 2 +#define NETWORK_GAME_INFO_VERSION 3 // What version of company info is this? -#define NETWORK_COMPANY_INFO_VERSION 3 +#define NETWORK_COMPANY_INFO_VERSION 4 // What version of master-server-protocol do we use? #define NETWORK_MASTER_SERVER_VERSION 1 diff --git a/network_server.c b/network_server.c --- a/network_server.c +++ b/network_server.c @@ -95,7 +95,7 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_CO NetworkSend_uint8 (p, player->index); NetworkSend_string(p, _network_player_info[player->index].company_name); - NetworkSend_uint8 (p, _network_player_info[player->index].inaugurated_year); + NetworkSend_uint32(p, _network_player_info[player->index].inaugurated_year); NetworkSend_uint64(p, _network_player_info[player->index].company_value); NetworkSend_uint64(p, _network_player_info[player->index].money); NetworkSend_uint64(p, _network_player_info[player->index].income); diff --git a/network_udp.c b/network_udp.c --- a/network_udp.c +++ b/network_udp.c @@ -63,6 +63,10 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIEN NetworkSend_uint8 (packet, NETWORK_GAME_INFO_VERSION); + /* NETWORK_GAME_INFO_VERSION = 3 */ + NetworkSend_uint32(packet, _network_game_info.game_date); + NetworkSend_uint32(packet, _network_game_info.start_date); + /* NETWORK_GAME_INFO_VERSION = 2 */ NetworkSend_uint8 (packet, _network_game_info.companies_max); NetworkSend_uint8 (packet, ActivePlayerCount()); @@ -76,8 +80,6 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIEN NetworkSend_uint8 (packet, _network_game_info.clients_max); NetworkSend_uint8 (packet, _network_game_info.clients_on); NetworkSend_uint8 (packet, NetworkSpectatorCount()); - NetworkSend_uint16(packet, _network_game_info.game_date); - NetworkSend_uint16(packet, _network_game_info.start_date); NetworkSend_string(packet, _network_game_info.map_name); NetworkSend_uint16(packet, _network_game_info.map_width); NetworkSend_uint16(packet, _network_game_info.map_height); @@ -114,6 +116,10 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVE /* Please observer the order. In the order in which packets are sent * they are to be received */ switch (game_info_version) { + case 3: + item->info.game_date = NetworkRecv_uint32(&_udp_cs, p); + item->info.start_date = NetworkRecv_uint32(&_udp_cs, p); + /* Fallthrough */ case 2: item->info.companies_max = NetworkRecv_uint8(&_udp_cs, p); item->info.companies_on = NetworkRecv_uint8(&_udp_cs, p); @@ -127,8 +133,10 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVE item->info.clients_max = NetworkRecv_uint8(&_udp_cs, p); item->info.clients_on = NetworkRecv_uint8(&_udp_cs, p); item->info.spectators_on = NetworkRecv_uint8(&_udp_cs, p); - item->info.game_date = NetworkRecv_uint16(&_udp_cs, p); - item->info.start_date = NetworkRecv_uint16(&_udp_cs, p); + if (game_info_version < 3) { // 16 bits dates got scrapped and are read earlier + item->info.game_date = NetworkRecv_uint16(&_udp_cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR; + item->info.start_date = NetworkRecv_uint16(&_udp_cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR; + } NetworkRecv_string(&_udp_cs, p, item->info.map_name, sizeof(item->info.map_name)); item->info.map_width = NetworkRecv_uint16(&_udp_cs, p); item->info.map_height = NetworkRecv_uint16(&_udp_cs, p); @@ -185,7 +193,7 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIEN NetworkSend_uint8(packet, current); NetworkSend_string(packet, _network_player_info[player->index].company_name); - NetworkSend_uint8 (packet, _network_player_info[player->index].inaugurated_year); + NetworkSend_uint32(packet, _network_player_info[player->index].inaugurated_year); NetworkSend_uint64(packet, _network_player_info[player->index].company_value); NetworkSend_uint64(packet, _network_player_info[player->index].money); NetworkSend_uint64(packet, _network_player_info[player->index].income); @@ -212,7 +220,7 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIEN NetworkSend_uint8(packet, 1); NetworkSend_string(packet, ci->client_name); NetworkSend_string(packet, ci->unique_id); - NetworkSend_uint16(packet, ci->join_date); + NetworkSend_uint32(packet, ci->join_date); } } /* Also check for the server itself */ @@ -222,7 +230,7 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIEN NetworkSend_uint8(packet, 1); NetworkSend_string(packet, ci->client_name); NetworkSend_string(packet, ci->unique_id); - NetworkSend_uint16(packet, ci->join_date); + NetworkSend_uint32(packet, ci->join_date); } /* Indicates end of client list */ @@ -237,7 +245,7 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIEN NetworkSend_uint8(packet, 1); NetworkSend_string(packet, ci->client_name); NetworkSend_string(packet, ci->unique_id); - NetworkSend_uint16(packet, ci->join_date); + NetworkSend_uint32(packet, ci->join_date); } } /* Also check for the server itself */ @@ -247,7 +255,7 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIEN NetworkSend_uint8(packet, 1); NetworkSend_string(packet, ci->client_name); NetworkSend_string(packet, ci->unique_id); - NetworkSend_uint16(packet, ci->join_date); + NetworkSend_uint32(packet, ci->join_date); } /* Indicates end of client list */ diff --git a/oldloader.c b/oldloader.c --- a/oldloader.c +++ b/oldloader.c @@ -702,7 +702,7 @@ static const OldChunks industry_chunk[] OCL_SVAR( OC_UINT8, Industry, type ), OCL_SVAR( OC_UINT8, Industry, owner ), OCL_SVAR( OC_UINT8, Industry, color_map ), - OCL_SVAR( OC_UINT8, Industry, last_prod_year ), + 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 ), @@ -995,7 +995,7 @@ static bool LoadOldPlayer(LoadgameState p->money64 = p->player_money = p->current_loan = 100000; _player_colors[num] = p->player_color; - p->inaugurated_year = _old_inaugurated_year - BASE_YEAR; + p->inaugurated_year = _old_inaugurated_year; if (p->location_of_house == 0xFFFF) p->location_of_house = 0; @@ -1122,7 +1122,7 @@ static const OldChunks vehicle_chunk[] = 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_UINT16, Vehicle, date_of_last_service ), + 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 ), @@ -1156,9 +1156,9 @@ static const OldChunks vehicle_chunk[] = OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, cargo_source ), OCL_SVAR( OC_UINT8, Vehicle, cargo_days ), - OCL_SVAR( OC_UINT16, Vehicle, age ), - OCL_SVAR( OC_UINT16, Vehicle, max_age ), - OCL_SVAR( OC_UINT8, Vehicle, build_year ), + 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 ), @@ -1259,8 +1259,8 @@ static bool LoadOldSign(LoadgameState *l static const OldChunks engine_chunk[] = { OCL_SVAR( OC_UINT16, Engine, player_avail ), - OCL_SVAR( OC_UINT16, Engine, intro_date ), - OCL_SVAR( OC_UINT16, Engine, age ), + 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 ), @@ -1375,7 +1375,7 @@ static bool LoadOldMapPart2(LoadgameStat static uint32 _old_cur_town_ctr; static const OldChunks main_chunk[] = { OCL_ASSERT( 0 ), - OCL_VAR ( OC_UINT16, 1, &_date ), + 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] ), diff --git a/openttd.c b/openttd.c --- a/openttd.c +++ b/openttd.c @@ -793,7 +793,7 @@ void SwitchMode(int new_mode) } } _generating_world = false; - _patches_newgame.starting_year = BASE_YEAR + _cur_year; + _patches_newgame.starting_year = ORIGINAL_BASE_YEAR + _cur_year; // delete all stations owned by a player DeleteAllPlayerStations(); } else { @@ -1439,5 +1439,29 @@ bool AfterLoadGame(void) if (!CheckSavegameVersion(27)) AfterLoadStations(); + /* Time starts at 0 instead of 1920. + * Account for this in older games by adding an offset */ + if (CheckSavegameVersion(31)) { + Station *st; + Waypoint *wp; + Engine *e; + Player *player; + Industry *i; + Vehicle *v; + + _date += DAYS_TILL_ORIGINAL_BASE_YEAR; + + FOR_ALL_STATIONS(st) st->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR; + FOR_ALL_WAYPOINTS(wp) wp->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR; + FOR_ALL_ENGINES(e) e->intro_date += DAYS_TILL_ORIGINAL_BASE_YEAR; + FOR_ALL_PLAYERS(player) player->inaugurated_year += ORIGINAL_BASE_YEAR; + FOR_ALL_INDUSTRIES(i) i->last_prod_year += ORIGINAL_BASE_YEAR; + + FOR_ALL_VEHICLES(v) { + v->date_of_last_service += DAYS_TILL_ORIGINAL_BASE_YEAR; + v->build_year += ORIGINAL_BASE_YEAR; + } + } + return true; } diff --git a/openttd.h b/openttd.h --- a/openttd.h +++ b/openttd.h @@ -54,11 +54,11 @@ typedef byte WindowClass; enum { INVALID_YEAR = -1, - INVALID_DATE = (uint16)-1, + INVALID_DATE = -1, }; -typedef int16 Year; -typedef uint16 Date; +typedef int32 Year; +typedef int32 Date; enum GameModes { diff --git a/player.h b/player.h --- a/player.h +++ b/player.h @@ -173,7 +173,7 @@ typedef struct Player { PlayerID share_owners[4]; - byte inaugurated_year; + Year inaugurated_year; byte num_valid_stat_ent; byte quarters_of_bankrupcy; diff --git a/players.c b/players.c --- a/players.c +++ b/players.c @@ -490,7 +490,7 @@ Player *DoStartupNewPlayer(bool is_ai) p->share_owners[0] = p->share_owners[1] = p->share_owners[2] = p->share_owners[3] = OWNER_SPECTATOR; p->avail_railtypes = GetPlayerRailtypes(p->index); - p->inaugurated_year = _cur_year - BASE_YEAR; + p->inaugurated_year = _cur_year; p->face = Random(); /* Engine renewal settings */ @@ -1132,7 +1132,8 @@ static const SaveLoad _player_desc[] = { SLE_CONDVAR(Player, location_of_house, SLE_UINT32, 6, SL_MAX_VERSION), SLE_CONDVAR(Player, last_build_coordinate, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), SLE_CONDVAR(Player, last_build_coordinate, SLE_UINT32, 6, SL_MAX_VERSION), - SLE_VAR(Player,inaugurated_year,SLE_UINT8), + SLE_CONDVAR(Player, inaugurated_year, SLE_FILE_U8 | SLE_VAR_I32, 0, 30), + SLE_CONDVAR(Player, inaugurated_year, SLE_INT32, 31, SL_MAX_VERSION), SLE_ARR(Player,share_owners, SLE_UINT8, 4), diff --git a/saveload.c b/saveload.c --- a/saveload.c +++ b/saveload.c @@ -30,7 +30,7 @@ #include "variables.h" #include -const uint16 SAVEGAME_VERSION = 30; +const uint16 SAVEGAME_VERSION = 31; uint16 _sl_version; /// the major savegame version identifier byte _sl_minor_version; /// the minor savegame version, DO NOT USE! diff --git a/settings.c b/settings.c --- a/settings.c +++ b/settings.c @@ -1207,7 +1207,7 @@ static const SettingDescGlobVarList _net SDTG_BOOL("autoclean_companies", S, 0, _network_autoclean_companies, false, STR_NULL, NULL), SDTG_VAR("autoclean_unprotected",SLE_UINT8, S, 0, _network_autoclean_unprotected,12, 0, 60, STR_NULL, NULL), SDTG_VAR("autoclean_protected", SLE_UINT8, S, 0, _network_autoclean_protected, 36, 0, 180, STR_NULL, NULL), - SDTG_VAR("restart_game_year", SLE_INT16, S,D0, _network_restart_game_year, 0, MIN_YEAR, MAX_YEAR, STR_NULL, NULL), + SDTG_VAR("restart_game_year", SLE_INT32, S,D0, _network_restart_game_year, 0, MIN_YEAR, MAX_YEAR, STR_NULL, NULL), SDTG_END() }; #endif /* ENABLE_NETWORK */ @@ -1321,9 +1321,9 @@ const SettingDesc _patch_settings[] = { SDT_BOOL(Patches, same_industry_close, 0, 0, false, STR_CONFIG_PATCHES_SAMEINDCLOSE, NULL), SDT_BOOL(Patches, bribe, 0, 0, true, STR_CONFIG_PATCHES_BRIBE, NULL), SDT_VAR(Patches, snow_line_height,SLE_UINT8, 0, 0, 7, 2, 13, STR_CONFIG_PATCHES_SNOWLINE_HEIGHT, NULL), - SDT_VAR(Patches, colored_news_year,SLE_FILE_U32 | SLE_VAR_I16, 0,NC, 2000, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_COLORED_NEWS_YEAR,NULL), - SDT_VAR(Patches, starting_year, SLE_FILE_U32 | SLE_VAR_I16, 0,NC, 1950, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_STARTING_YEAR,NULL), - SDT_VAR(Patches, ending_year, SLE_FILE_U32 | SLE_VAR_I16,0,NC|NO,2051, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_ENDING_YEAR, NULL), + SDT_VAR(Patches, colored_news_year,SLE_INT32, 0,NC, 2000, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_COLORED_NEWS_YEAR,NULL), + SDT_VAR(Patches, starting_year, SLE_INT32, 0,NC, 1950, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_STARTING_YEAR,NULL), + SDT_VAR(Patches, ending_year, SLE_INT32,0,NC|NO,2051, MIN_YEAR, MAX_YEAR, STR_CONFIG_PATCHES_ENDING_YEAR, NULL), SDT_BOOL(Patches, smooth_economy, 0, 0, true, STR_CONFIG_PATCHES_SMOOTH_ECONOMY, NULL), SDT_BOOL(Patches, allow_shares, 0, 0, true, STR_CONFIG_PATCHES_ALLOW_SHARES, NULL), @@ -1453,7 +1453,7 @@ const SettingDesc _patch_settings[] = { static const SettingDesc _currency_settings[] = { SDT_VAR(CurrencySpec, rate, SLE_UINT16, S, 0, 1, 0, 100, STR_NULL, NULL), SDT_CHR(CurrencySpec, separator, S, 0, ".", STR_NULL, NULL), - SDT_VAR(CurrencySpec, to_euro, SLE_UINT16, S, 0, 0, 0,1000, STR_NULL, NULL), + SDT_VAR(CurrencySpec, to_euro, SLE_INT32, S, 0, 0, 0,1000, STR_NULL, NULL), SDT_STR(CurrencySpec, prefix, SLE_STRBQ, S, 0, NULL, STR_NULL, NULL), SDT_STR(CurrencySpec, suffix, SLE_STRBQ, S, 0, " credits", STR_NULL, NULL), SDT_END() diff --git a/station_cmd.c b/station_cmd.c --- a/station_cmd.c +++ b/station_cmd.c @@ -3003,7 +3003,8 @@ static const SaveLoad _station_desc[] = // Was custom station class and id SLE_CONDNULL(2, 3, 25), - SLE_CONDVAR(Station,build_date, SLE_UINT16, 3, SL_MAX_VERSION), + SLE_CONDVAR(Station,build_date, SLE_FILE_U16 | SLE_VAR_I32, 3, 30), + SLE_CONDVAR(Station,build_date, SLE_INT32, 31, SL_MAX_VERSION), SLE_CONDREF(Station,bus_stops, REF_ROADSTOPS, 6, SL_MAX_VERSION), SLE_CONDREF(Station,truck_stops, REF_ROADSTOPS, 6, SL_MAX_VERSION), diff --git a/vehicle.c b/vehicle.c --- a/vehicle.c +++ b/vehicle.c @@ -2202,17 +2202,22 @@ const SaveLoad _common_veh_desc[] = { SLE_REF(Vehicle,orders, REF_ORDER), - SLE_VAR(Vehicle,age, SLE_UINT16), - SLE_VAR(Vehicle,max_age, SLE_UINT16), - SLE_VAR(Vehicle,date_of_last_service,SLE_UINT16), - SLE_VAR(Vehicle,service_interval, SLE_UINT16), + SLE_CONDVAR(Vehicle,age, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), + SLE_CONDVAR(Vehicle,age, SLE_INT32, 31, SL_MAX_VERSION), + SLE_CONDVAR(Vehicle,max_age, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), + SLE_CONDVAR(Vehicle,max_age, SLE_INT32, 31, SL_MAX_VERSION), + SLE_CONDVAR(Vehicle,date_of_last_service, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), + SLE_CONDVAR(Vehicle,date_of_last_service, SLE_INT32, 31, SL_MAX_VERSION), + SLE_CONDVAR(Vehicle,service_interval, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), + SLE_CONDVAR(Vehicle,service_interval, SLE_INT32, 31, SL_MAX_VERSION), SLE_VAR(Vehicle,reliability, SLE_UINT16), SLE_VAR(Vehicle,reliability_spd_dec,SLE_UINT16), SLE_VAR(Vehicle,breakdown_ctr, SLE_UINT8), SLE_VAR(Vehicle,breakdown_delay, SLE_UINT8), SLE_VAR(Vehicle,breakdowns_since_last_service, SLE_UINT8), SLE_VAR(Vehicle,breakdown_chance, SLE_UINT8), - SLE_VAR(Vehicle,build_year, SLE_UINT8), + SLE_CONDVAR(Vehicle,build_year, SLE_FILE_U8 | SLE_VAR_I32, 0, 30), + SLE_CONDVAR(Vehicle,build_year, SLE_INT32, 31, SL_MAX_VERSION), SLE_VAR(Vehicle,load_unload_time_rem, SLE_UINT16), @@ -2362,8 +2367,8 @@ static const SaveLoad _disaster_desc[] = SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, station), SLE_UINT16, 5, SL_MAX_VERSION), SLE_VAR(Vehicle,cur_image, SLE_UINT16), - SLE_VAR(Vehicle,age, SLE_UINT16), - + SLE_CONDVAR(Vehicle,age, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), + SLE_CONDVAR(Vehicle,age, SLE_INT32, 31, SL_MAX_VERSION), SLE_VAR(Vehicle,tick_counter, SLE_UINT8), SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleDisaster,image_override), SLE_UINT16), diff --git a/vehicle.h b/vehicle.h --- a/vehicle.h +++ b/vehicle.h @@ -208,8 +208,8 @@ struct Vehicle { VehicleID next_hash; // Related to age and service time - uint16 age; // Age in days - uint16 max_age; // Maximum age + Date age; // Age in days + Date max_age; // Maximum age Date date_of_last_service; Date service_interval; uint16 reliability; @@ -218,7 +218,7 @@ struct Vehicle { byte breakdown_delay; byte breakdowns_since_last_service; byte breakdown_chance; - byte build_year; + Year build_year; bool leave_depot_instantly; // NOSAVE: stores if the vehicle needs to leave the depot it just entered. Used by autoreplace diff --git a/waypoint.c b/waypoint.c --- a/waypoint.c +++ b/waypoint.c @@ -408,7 +408,8 @@ static const SaveLoad _waypoint_desc[] = SLE_VAR(Waypoint, string, SLE_UINT16), SLE_VAR(Waypoint, deleted, SLE_UINT8), - SLE_CONDVAR(Waypoint, build_date, SLE_UINT16, 3, SL_MAX_VERSION), + SLE_CONDVAR(Waypoint, build_date, SLE_FILE_U16 | SLE_VAR_I32, 3, 30), + SLE_CONDVAR(Waypoint, build_date, SLE_INT32, 31, SL_MAX_VERSION), SLE_CONDVAR(Waypoint, localidx, SLE_UINT8, 3, SL_MAX_VERSION), SLE_CONDVAR(Waypoint, grfid, SLE_UINT32, 17, SL_MAX_VERSION),