Index: station_cmd.c =================================================================== --- station_cmd.c (revision 4608) +++ station_cmd.c (working copy) @@ -2846,7 +2846,8 @@ // 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, 26), + SLE_CONDVAR(Station,build_date, SLE_INT32, 27, 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), Index: graph_gui.c =================================================================== --- graph_gui.c (revision 4608) +++ graph_gui.c (working copy) @@ -28,8 +28,8 @@ uint sel; // bitmask of the players *excluded* (e.g. 11111111 means that no players are shown) byte num_dataset; byte num_on_x_axis; - byte month; - byte year; + Month month; + Year year; bool include_neg; byte num_vert_lines; uint16 unk61A; @@ -292,7 +292,8 @@ const Player* p; uint excludebits = _legend_excludebits; int nums; - int mo,yr; + Month mo; + Year yr; // Exclude the players which aren't valid FOR_ALL_PLAYERS(p) { Index: engine.c =================================================================== --- engine.c (revision 4608) +++ engine.c (working copy) @@ -149,11 +149,10 @@ static void AdjustAvailAircraft(void) { - uint16 date = _date; byte avail = 0; - if (date >= 12784) avail |= 2; // big airport - if (date < 14610 || _patches.always_small_airport) avail |= 1; // small airport - if (date >= 15706) avail |= 4; // enable heliport + if (_cur_year >= 1955) avail |= 2; // big airport + if (_cur_year < 1960 || _patches.always_small_airport) avail |= 1; // small airport + if (_cur_year >= 1963) avail |= 4; // enable heliport if (avail != _avail_aircraft) { _avail_aircraft = avail; @@ -208,11 +207,10 @@ e->flags = 0; e->player_avail = 0; - // The magic value of 729 days below comes from the NewGRF spec. If the - // base intro date is before 1922 then the random number of days is not - // added. + // If the base intro date is before 1922 then the random number of days + // is not added. r = Random(); - e->intro_date = ei->base_intro <= 729 ? ei->base_intro : GB(r, 0, 9) + ei->base_intro; + e->intro_date = ei->base_intro < ConvertYearToDay(1922) ? ei->base_intro : (int32)GB(r, 0, 9) + ei->base_intro; if (e->intro_date <= _date) { e->age = (_date - e->intro_date) >> 5; e->player_avail = (byte)-1; @@ -299,7 +297,7 @@ { EngineID i; - if (_cur_year >= 130) return; + if (_cur_year >= 2050) return; for (i = 0; i != lengthof(_engines); i++) { Engine* e = &_engines[i]; @@ -420,7 +418,7 @@ { Engine *e; - if (_cur_year < 130) { + if (_cur_year < 2050) { for (e = _engines; e != endof(_engines); e++) { // Age the vehicle if (e->flags & ENGINE_AVAILABLE && e->age != 0xFFFF) { @@ -662,8 +660,10 @@ } 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, 26), + SLE_CONDVAR(Engine,intro_date, SLE_INT32, 27, SL_MAX_VERSION), + SLE_CONDVAR(Engine,age, SLE_FILE_U16 | SLE_VAR_I32, 0, 26), + SLE_CONDVAR(Engine,age, SLE_INT32, 27, SL_MAX_VERSION), SLE_VAR(Engine,reliability, SLE_UINT16), SLE_VAR(Engine,reliability_spd_dec, SLE_UINT16), SLE_VAR(Engine,reliability_start, SLE_UINT16), Index: oldloader.c =================================================================== --- oldloader.c (revision 4608) +++ oldloader.c (working copy) @@ -703,7 +703,7 @@ 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 ), @@ -1123,7 +1123,7 @@ 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_I32, 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 ), @@ -1157,9 +1157,9 @@ 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_I32, Vehicle, age ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, 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 ), @@ -1263,8 +1263,8 @@ 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_I32, Engine, intro_date ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Engine, age ), OCL_SVAR( OC_UINT16, Engine, reliability ), OCL_SVAR( OC_UINT16, Engine, reliability_spd_dec ), OCL_SVAR( OC_UINT16, Engine, reliability_start ), @@ -1379,7 +1379,7 @@ 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_I32, 1, &_date ), OCL_VAR ( OC_UINT16, 1, &_date_fract ), OCL_NULL( 600 ), // TextEffects OCL_VAR ( OC_UINT32, 2, &_random_seeds[0] ), Index: engine.h =================================================================== --- engine.h (revision 4608) +++ engine.h (working copy) @@ -72,7 +72,7 @@ * @see table/engines.h */ typedef struct EngineInfo { - uint16 base_intro; + Date base_intro; byte unk2; ///< Carriages have the highest bit set in this one byte lifelength; byte base_life; @@ -83,8 +83,8 @@ } EngineInfo; typedef struct Engine { - uint16 intro_date; - uint16 age; + Date intro_date; + Date age; uint16 reliability; uint16 reliability_spd_dec; uint16 reliability_start, reliability_max, reliability_final; Index: functions.h =================================================================== --- functions.h (revision 4608) +++ functions.h (working copy) @@ -115,7 +115,7 @@ uint32 InteractiveRandom(void); /* Used for random sequences that are not the same on the other end of the multiplayer link */ uint InteractiveRandomRange(uint max); -void SetDate(uint date); +void SetDate(Date date); /* facedraw.c */ void DrawPlayerFace(uint32 face, int color, int x, int y); @@ -170,9 +170,9 @@ #define AllocateNameUnique(name, skip) RealAllocateName(name, skip, true) #define AllocateName(name, skip) RealAllocateName(name, skip, false) StringID RealAllocateName(const char *name, byte skip, bool check_double); -void ConvertDayToYMD(YearMonthDay *ymd, uint16 date); -uint ConvertYMDToDay(uint year, uint month, uint day); -uint ConvertIntDate(uint date); +void ConvertDayToYMD(YearMonthDay *ymd, Date date); +Date ConvertYearToDay(Year year); +Date ConvertYMDToDay(Year year, Month month, Day day); /* misc functions */ void MarkTileDirty(int x, int y); Index: industry.h =================================================================== --- industry.h (revision 4608) +++ industry.h (working copy) @@ -25,7 +25,7 @@ byte type; byte owner; byte color_map; - byte last_prod_year; + Year last_prod_year; byte was_cargo_delivered; uint16 index; Index: network.c =================================================================== --- network.c (revision 4608) +++ network.c (working copy) @@ -967,7 +967,7 @@ _network_game_info.spectators_on = 0; _network_game_info.game_date = _date; - _network_game_info.start_date = ConvertIntDate(_patches.starting_date); + _network_game_info.start_date = ConvertYearToDay(_patches.starting_date); _network_game_info.map_width = MapSizeX(); _network_game_info.map_height = MapSizeY(); _network_game_info.map_set = _opt.landscape; Index: network.h =================================================================== --- network.h (revision 4608) +++ network.h (working copy) @@ -76,8 +76,8 @@ byte companies_on; // How many started companies do we have (XXX - disabled for server atm, use ActivePlayerCount()) byte spectators_max; // Max spectators allowed on server byte spectators_on; // How many spectators do we have? (XXX - disabled for server atm, use NetworkSpectatorCount()) - uint16 game_date; // Current date - uint16 start_date; // When the game started + Date game_date; // Current date + Date start_date; // When the game started char map_name[NETWORK_NAME_LENGTH]; // Map which is played ["random" for a randomized map] uint16 map_width; // Map width uint16 map_height; // Map height @@ -89,7 +89,7 @@ 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 @@ -107,7 +107,7 @@ byte client_lang; /// The language of the client byte client_playas; /// As which player is this client playing (PlayerID) uint32 client_ip; /// IP-address of the client (so he can be banned) - uint16 join_date; /// Gamedate the player has joined + Date join_date; /// Gamedate the player has joined char unique_id[NETWORK_NAME_LENGTH]; /// Every play sends an unique id so we can indentify him } NetworkClientInfo; @@ -206,7 +206,7 @@ VARDEF uint8 _network_autoclean_unprotected; // Remove a company after X months VARDEF uint8 _network_autoclean_protected; // Unprotect a company after X months -VARDEF uint16 _network_restart_game_date; // If this year is reached, the server automaticly restarts +VARDEF Year _network_restart_game_date; // If this year is reached, the server automaticly restarts NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool game_info); Index: misc_gui.c =================================================================== --- misc_gui.c (revision 4608) +++ misc_gui.c (working copy) @@ -1674,8 +1674,6 @@ YearMonthDay ymd; ConvertDayToYMD(&ymd, _date); - if ((ymd.year == 0 && p2 == -1) || (ymd.year == 170 && p2 == 1)) return _cur_year; - SetDate(ConvertYMDToDay(_cur_year + p2, ymd.month, ymd.day)); EnginesMonthlyLoop(); SetWindowDirty(FindWindowById(WC_STATUS_BAR, 0)); @@ -1707,7 +1705,7 @@ {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}, }; Index: network_udp.c =================================================================== --- network_udp.c (revision 4608) +++ network_udp.c (working copy) @@ -11,6 +11,7 @@ #include "network_gamelist.h" #include "network_udp.h" #include "variables.h" +#include "functions.h" extern void UpdateNetworkGameWindow(bool unselect); extern void NetworkPopulateCompanyInfo(void); @@ -75,8 +76,8 @@ 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_uint32(packet, _network_game_info.game_date); //Version 3 + NetworkSend_uint32(packet, _network_game_info.start_date); //Version 3 NetworkSend_string(packet, _network_game_info.map_name); NetworkSend_uint16(packet, _network_game_info.map_width); NetworkSend_uint16(packet, _network_game_info.map_height); @@ -113,6 +114,7 @@ /* Please observer the order. In the order in which packets are sent * they are to be received */ switch (game_info_version) { + case 3: // Change of size of dates case 2: item->info.companies_max = NetworkRecv_uint8(&_udp_cs, p); item->info.companies_on = NetworkRecv_uint8(&_udp_cs, p); @@ -126,8 +128,13 @@ 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) { + item->info.game_date = NetworkRecv_uint16(&_udp_cs, p) + ConvertYearToDay(1920); + item->info.start_date = NetworkRecv_uint16(&_udp_cs, p) + ConvertYearToDay(1920); + } else { + item->info.game_date = NetworkRecv_uint32(&_udp_cs, p); + item->info.start_date = NetworkRecv_uint32(&_udp_cs, p); + } 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); @@ -187,7 +194,7 @@ 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); Index: variables.h =================================================================== --- variables.h (revision 4608) +++ variables.h (working copy) @@ -38,7 +38,7 @@ VARDEF GameOptions *_opt_ptr; // Current date -VARDEF uint16 _date; +VARDEF Date _date; VARDEF uint16 _date_fract; // Amount of game ticks @@ -136,7 +136,7 @@ uint16 servint_ships; // service interval for ships bool autorenew; - int16 autorenew_months; + Month autorenew_months; int32 autorenew_money; byte pf_maxdepth; // maximum recursion depth when searching for a train route for new pathfinder @@ -149,9 +149,9 @@ bool ai_disable_veh_roadveh; // disable types for AI bool ai_disable_veh_aircraft; // disable types for AI bool ai_disable_veh_ship; // disable types for AI - uint32 starting_date; // starting date - uint32 ending_date; // end of the game (just show highscore) - uint32 colored_news_date; // when does newspaper become colored? + Year starting_date; // starting date + Year ending_date; // end of the game (just show highscore) + Year colored_news_date; // when does newspaper become colored? bool keep_all_autosave; // name the autosave in a different way. bool autosave_on_exit; // save an autosave when you quit the game, but do not ask "Do you really want to quit?" @@ -251,8 +251,8 @@ // NOSAVE: can be determined from _date -VARDEF byte _cur_year; -VARDEF byte _cur_month; +VARDEF Year _cur_year; +VARDEF Month _cur_month; VARDEF uint32 _frame_counter; Index: players.c =================================================================== --- players.c (revision 4608) +++ players.c (working copy) @@ -1131,7 +1131,8 @@ 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, 25), + SLE_CONDVAR(Player, inaugurated_year, SLE_INT32, 26, SL_MAX_VERSION), SLE_ARR(Player,share_owners, SLE_UINT8, 4), Index: tunnelbridge_cmd.c =================================================================== --- tunnelbridge_cmd.c (revision 4608) +++ tunnelbridge_cmd.c (working copy) @@ -43,19 +43,19 @@ | | | | maximum speed | | | | | sprite to use in GUI string with description | | | | | | | */ - { 0, 0, 16, 80, 32, 0xA24 , STR_5012_WOODEN , NULL, 0 }, - { 0, 0, 2, 112, 48, 0xA26 | PALETTE_TO_STRUCT_RED , STR_5013_CONCRETE , NULL, 0 }, - { 10, 0, 5, 144, 64, 0xA25 , STR_500F_GIRDER_STEEL , NULL, 0 }, - { 0, 2, 10, 168, 80, 0xA22 | PALETTE_TO_STRUCT_CONCRETE, STR_5011_SUSPENSION_CONCRETE, NULL, 0 }, - { 10, 3, 16, 185, 96, 0xA22 , STR_500E_SUSPENSION_STEEL , NULL, 0 }, - { 10, 3, 16, 192, 112, 0xA22 | PALETTE_TO_STRUCT_YELLOW , STR_500E_SUSPENSION_STEEL , NULL, 0 }, - { 10, 3, 7, 224, 160, 0xA23 , STR_5010_CANTILEVER_STEEL , NULL, 0 }, - { 10, 3, 8, 232, 208, 0xA23 | PALETTE_TO_STRUCT_BROWN , STR_5010_CANTILEVER_STEEL , NULL, 0 }, - { 10, 3, 9, 248, 240, 0xA23 | PALETTE_TO_STRUCT_RED , STR_5010_CANTILEVER_STEEL , NULL, 0 }, - { 10, 0, 2, 240, 256, 0xA27 , STR_500F_GIRDER_STEEL , NULL, 0 }, - { 75, 2, 16, 255, 320, 0xA28 , STR_5014_TUBULAR_STEEL , NULL, 0 }, - { 85, 2, 32, 380, 512, 0xA28 | PALETTE_TO_STRUCT_YELLOW , STR_5014_TUBULAR_STEEL , NULL, 0 }, - { 90, 2, 32, 510, 608, 0xA28 | PALETTE_TO_STRUCT_GREY , STR_BRIDGE_TUBULAR_SILICON , NULL, 0 } + { 0, 0, 16, 80, 32, 0xA24 , STR_5012_WOODEN , NULL, 0 }, + { 0, 0, 2, 112, 48, 0xA26 | PALETTE_TO_STRUCT_RED , STR_5013_CONCRETE , NULL, 0 }, + { 1930, 0, 5, 144, 64, 0xA25 , STR_500F_GIRDER_STEEL , NULL, 0 }, + { 0, 2, 10, 168, 80, 0xA22 | PALETTE_TO_STRUCT_CONCRETE, STR_5011_SUSPENSION_CONCRETE, NULL, 0 }, + { 1930, 3, 16, 185, 96, 0xA22 , STR_500E_SUSPENSION_STEEL , NULL, 0 }, + { 1930, 3, 16, 192, 112, 0xA22 | PALETTE_TO_STRUCT_YELLOW , STR_500E_SUSPENSION_STEEL , NULL, 0 }, + { 1930, 3, 7, 224, 160, 0xA23 , STR_5010_CANTILEVER_STEEL , NULL, 0 }, + { 1930, 3, 8, 232, 208, 0xA23 | PALETTE_TO_STRUCT_BROWN , STR_5010_CANTILEVER_STEEL , NULL, 0 }, + { 1930, 3, 9, 248, 240, 0xA23 | PALETTE_TO_STRUCT_RED , STR_5010_CANTILEVER_STEEL , NULL, 0 }, + { 1930, 0, 2, 240, 256, 0xA27 , STR_500F_GIRDER_STEEL , NULL, 0 }, + { 1995, 2, 16, 255, 320, 0xA28 , STR_5014_TUBULAR_STEEL , NULL, 0 }, + { 2005, 2, 32, 380, 512, 0xA28 | PALETTE_TO_STRUCT_YELLOW , STR_5014_TUBULAR_STEEL , NULL, 0 }, + { 2010, 2, 32, 510, 608, 0xA28 | PALETTE_TO_STRUCT_GREY , STR_BRIDGE_TUBULAR_SILICON , NULL, 0 } }; Bridge _bridge[MAX_BRIDGES]; Index: openttd.c =================================================================== --- openttd.c (revision 4608) +++ openttd.c (working copy) @@ -315,7 +315,7 @@ const char *optformat; char musicdriver[16], sounddriver[16], videodriver[16]; int resolution[2] = {0,0}; - uint startdate = -1; + Year startdate = INVALID_YEAR; bool dedicated = false; bool network = false; @@ -406,7 +406,7 @@ if (sounddriver[0]) ttd_strlcpy(_ini_sounddriver, sounddriver, sizeof(_ini_sounddriver)); if (videodriver[0]) ttd_strlcpy(_ini_videodriver, videodriver, sizeof(_ini_videodriver)); if (resolution[0]) { _cur_resolution[0] = resolution[0]; _cur_resolution[1] = resolution[1]; } - if (startdate != (uint)-1) _patches.starting_date = startdate; + if (startdate != INVALID_YEAR) _patches.starting_date = startdate; if (_dedicated_forks && !dedicated) _dedicated_forks = false; @@ -1424,6 +1424,28 @@ } } + // From version 27, time starts at 0 instead of 1920. Account for this in older games by adding the offset on. + if (CheckSavegameVersion(27)) { + int j; + Station *st; + Player *player; + Industry *i; + + _date += ConvertYearToDay(1920); + + FOR_ALL_STATIONS(st) + st->build_date += ConvertYearToDay(1920); + + FOR_ALL_PLAYERS(player) + player->inaugurated_year += 1920; + + FOR_ALL_INDUSTRIES(i) + i->last_prod_year += 1920; + + for(j = 0; j < TOTAL_NUM_ENGINES; j++) + _engines[j].intro_date += ConvertYearToDay(1920); + } + FOR_ALL_PLAYERS(p) p->avail_railtypes = GetPlayerRailtypes(p->index); return true; Index: openttd.h =================================================================== --- openttd.h (revision 4608) +++ openttd.h (working copy) @@ -30,8 +30,20 @@ byte owner; } SortStruct; +enum { + INVALID_DATE = -1, + INVALID_YEAR = -1, +}; + +typedef int32 Date; +typedef int32 Year; +typedef int16 Month; +typedef int8 Day; + typedef struct YearMonthDay { - int year, month, day; + Year year; + Month month; + Day day; } YearMonthDay; /* --- 1 Day is 74 ticks --- @@ -43,9 +55,13 @@ * * 1 day is thus about 2 seconds (74*27 = 1998) on a machine that can run OpenTTD normally */ #define DAY_TICKS 74 -#define MAX_YEAR_BEGIN_REAL 1920 -#define MAX_YEAR_END_REAL 2090 -#define MAX_YEAR_END 170 +#define DAYS_TILL_1920 (365 * 1920 + 1920 / 4 - 1920 / 100 + 1920 / 400) +#define MAX_YEAR_BEGIN_REAL 0 +#define MAX_YEAR_END_REAL 5000 +/** int32 is max (1 << 31 - 1), but this is in years, so divide by 1 << 9 (512) + * so a date is always within the int32 range, + * Max is therefore about the year 4 million */ +#define MAX_YEAR_END ((1 << 22)) #include "map.h" #include "slope.h" @@ -285,7 +301,7 @@ typedef struct TileDesc { StringID str; byte owner; - uint16 build_date; + Date build_date; uint32 dparam[2]; } TileDesc; Index: network_data.h =================================================================== --- network_data.h (revision 4608) +++ network_data.h (working copy) @@ -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 Index: strings.c =================================================================== --- strings.c (revision 4608) +++ strings.c (working copy) @@ -316,7 +316,7 @@ } -static char *FormatYmdString(char *buff, uint16 number) +static char *FormatYmdString(char *buff, int32 number) { const char *src; YearMonthDay ymd; @@ -332,7 +332,7 @@ return FormatNoCommaNumber(buff + 4, ymd.year + MAX_YEAR_BEGIN_REAL); } -static char *FormatMonthAndYear(char *buff, uint16 number) +static char *FormatMonthAndYear(char *buff, int32 number) { const char *src; YearMonthDay ymd; @@ -345,7 +345,7 @@ return FormatNoCommaNumber(buff, ymd.year + MAX_YEAR_BEGIN_REAL); } -static char *FormatTinyDate(char *buff, uint16 number) +static char *FormatTinyDate(char *buff, int32 number) { YearMonthDay ymd; Index: saveload.c =================================================================== --- saveload.c (revision 4608) +++ saveload.c (working copy) @@ -30,7 +30,7 @@ #include "variables.h" #include -const uint16 SAVEGAME_VERSION = 26; +const uint16 SAVEGAME_VERSION = 27; uint16 _sl_version; /// the major savegame version identifier byte _sl_minor_version; /// the minor savegame version, DO NOT USE! Index: aircraft_gui.c =================================================================== --- aircraft_gui.c (revision 4608) +++ aircraft_gui.c (working copy) @@ -52,7 +52,7 @@ y += 10; /* Design date - Life length */ - SetDParam(0, ymd.year + 1920); + SetDParam(0, ymd.year); SetDParam(1, e->lifelength); DrawString(x, y, STR_PURCHASE_INFO_DESIGNED_LIFE, 0); y += 10; @@ -367,7 +367,7 @@ do { if (v->subtype <= 2) { SetDParam(0, GetCustomEngineName(v->engine_type)); - SetDParam(1, 1920 + v->build_year); + SetDParam(1, v->build_year); SetDParam(2, v->value); DrawString(60, y, STR_A011_BUILT_VALUE, 0); y += 10; Index: player.h =================================================================== --- player.h (revision 4608) +++ player.h (working copy) @@ -118,7 +118,7 @@ byte action; int last_id; // here is stored the last id of the searched city/industry - uint last_vehiclecheck_date; // Used in CheckVehicle + Date last_vehiclecheck_date; // Used in CheckVehicle Ai_SpecialVehicle special_vehicles[AI_MAX_SPECIAL_VEHICLES]; // Some vehicles have some special flags TileIndex from_tile; @@ -173,7 +173,7 @@ PlayerID share_owners[4]; - byte inaugurated_year; + Year inaugurated_year; byte num_valid_stat_ent; byte quarters_of_bankrupcy; @@ -192,7 +192,7 @@ EngineRenewList engine_renew_list; // Defined later bool engine_renew; bool renew_keep_length; - int16 engine_renew_months; + Month engine_renew_months; uint32 engine_renew_money; } Player; Index: industry_cmd.c =================================================================== --- industry_cmd.c (revision 4608) +++ industry_cmd.c (working copy) @@ -1526,7 +1526,7 @@ return; case INDUSTRYLIFE_CLOSABLE: - if ((byte)(_cur_year - i->last_prod_year) < 5 || !CHANCE16(1, 180)) + if ((_cur_year - i->last_prod_year) < 5 || !CHANCE16(1, 180)) closeit = false; break; @@ -1642,8 +1642,8 @@ type = _new_industry_rand[_opt.landscape][GB(r, 16, 5)]; - if (type == IT_OIL_WELL && _date > 10958) return; - if (type == IT_OIL_RIG && _date < 14610) return; + if (type == IT_OIL_WELL && _cur_year > 1950) return; + if (type == IT_OIL_RIG && _cur_year < 1960) return; j = 2000; for (;;) { @@ -1716,7 +1716,7 @@ case INDUSTRYLIFE_CLOSABLE: /* maybe close */ - if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1,2)) { + if ( (_cur_year - i->last_prod_year) >= 5 && CHANCE16(1,2)) { i->prod_level = 0; str = indspec->closure_text; } @@ -1802,7 +1802,8 @@ 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, 26), + SLE_CONDVAR(Industry, last_prod_year, SLE_INT32, 27, SL_MAX_VERSION), SLE_VAR(Industry,was_cargo_delivered,SLE_UINT8), // reserve extra space in savegame here. (currently 32 bytes) Index: texteff.c =================================================================== --- texteff.c (revision 4608) +++ texteff.c (working copy) @@ -30,7 +30,7 @@ typedef struct TextMessage { char message[MAX_TEXTMESSAGE_LENGTH]; uint16 color; - uint16 end_date; + Date end_date; } TextMessage; #define MAX_CHAT_MESSAGES 10 Index: table/town_land.h =================================================================== --- table/town_land.h (revision 4608) +++ table/town_land.h (working copy) @@ -2019,120 +2019,122 @@ typedef struct { - byte min,max; + Year min, max; } HousetypeYear; +#define START_OFFSET 1920 + static const HousetypeYear _housetype_years[] = { - {43, 255}, - {37, 255}, - {48, 255}, - {0, 255}, - {55, 255}, - {55, 255}, - {0, 255}, - {39, 255}, - {39, 255}, - {25, 255}, - {25, 255}, - {0, 255}, - {15, 255}, - {31, 255}, - {10, 40}, - {10, 40}, - {10, 40}, - {57, 255}, - {63, 255}, - {65, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 31}, - {0, 32}, - {11, 255}, - {15, 255}, - {43, 255}, - {0, 35}, - {53, 255}, - {0, 255}, - {38, 255}, - {38, 255}, - {38, 255}, - {38, 255}, - {80, 255}, - {0, 40}, - {0, 40}, - {25, 255}, - {63, 255}, - {63, 255}, - {63, 255}, - {63, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 43}, - {0, 43}, - {46, 255}, - {46, 255}, - {50, 255}, - {50, 255}, - {54, 255}, - {54, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 40}, - {0, 40}, - {52, 255}, - {52, 255}, - {52, 255}, - {52, 255}, - {43, 255}, - {43, 255}, - {58, 255}, - {58, 255}, - {47, 255}, - {47, 255}, - {47, 255}, - {47, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {53, 255}, - {42, 255}, - {64, 255}, - {64, 255}, - {0, 255}, - {73, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, - {0, 255}, + {START_OFFSET + 43, MAX_YEAR_END}, + {START_OFFSET + 37, MAX_YEAR_END}, + {START_OFFSET + 48, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {START_OFFSET + 55, MAX_YEAR_END}, + {START_OFFSET + 55, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {START_OFFSET + 39, MAX_YEAR_END}, + {START_OFFSET + 39, MAX_YEAR_END}, + {START_OFFSET + 25, MAX_YEAR_END}, + {START_OFFSET + 25, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {START_OFFSET + 15, MAX_YEAR_END}, + {START_OFFSET + 31, MAX_YEAR_END}, + {START_OFFSET + 10, START_OFFSET + 40}, + {START_OFFSET + 10, START_OFFSET + 40}, + {START_OFFSET + 10, START_OFFSET + 40}, + {START_OFFSET + 57, MAX_YEAR_END}, + {START_OFFSET + 63, MAX_YEAR_END}, + {START_OFFSET + 65, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, START_OFFSET + 31}, + {0, START_OFFSET + 32}, + {START_OFFSET + 11, MAX_YEAR_END}, + {START_OFFSET + 15, MAX_YEAR_END}, + {START_OFFSET + 43, MAX_YEAR_END}, + {0, START_OFFSET + 35}, + {START_OFFSET + 53, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {START_OFFSET + 38, MAX_YEAR_END}, + {START_OFFSET + 38, MAX_YEAR_END}, + {START_OFFSET + 38, MAX_YEAR_END}, + {START_OFFSET + 38, MAX_YEAR_END}, + {START_OFFSET + 80, MAX_YEAR_END}, + {0, START_OFFSET + 40}, + {0, START_OFFSET + 40}, + {START_OFFSET + 25, MAX_YEAR_END}, + {START_OFFSET + 63, MAX_YEAR_END}, + {START_OFFSET + 63, MAX_YEAR_END}, + {START_OFFSET + 63, MAX_YEAR_END}, + {START_OFFSET + 63, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, START_OFFSET + 43}, + {0, START_OFFSET + 43}, + {START_OFFSET + 46, MAX_YEAR_END}, + {START_OFFSET + 46, MAX_YEAR_END}, + {START_OFFSET + 50, MAX_YEAR_END}, + {START_OFFSET + 50, MAX_YEAR_END}, + {START_OFFSET + 54, MAX_YEAR_END}, + {START_OFFSET + 54, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, START_OFFSET + 40}, + {0, START_OFFSET + 40}, + {START_OFFSET + 52, MAX_YEAR_END}, + {START_OFFSET + 52, MAX_YEAR_END}, + {START_OFFSET + 52, MAX_YEAR_END}, + {START_OFFSET + 52, MAX_YEAR_END}, + {START_OFFSET + 43, MAX_YEAR_END}, + {START_OFFSET + 43, MAX_YEAR_END}, + {START_OFFSET + 58, MAX_YEAR_END}, + {START_OFFSET + 58, MAX_YEAR_END}, + {START_OFFSET + 47, MAX_YEAR_END}, + {START_OFFSET + 47, MAX_YEAR_END}, + {START_OFFSET + 47, MAX_YEAR_END}, + {START_OFFSET + 47, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {START_OFFSET + 53, MAX_YEAR_END}, + {START_OFFSET + 42, MAX_YEAR_END}, + {START_OFFSET + 64, MAX_YEAR_END}, + {START_OFFSET + 64, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {START_OFFSET + 73, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, + {0, MAX_YEAR_END}, }; assert_compile(lengthof(_housetype_years) == HOUSE_MAX); Index: table/engines.h =================================================================== --- table/engines.h (revision 4608) +++ table/engines.h (working copy) @@ -15,7 +15,7 @@ * @param e Rail Type of the vehicle * @param f Bitmask of the climates */ -#define MK(a, b, c, d, e, f) { a, b, c, d, e, f, 0, 0 } +#define MK(a, b, c, d, e, f) { DAYS_TILL_1920 + a, b, c, d, e, f, 0, 0 } /** Writes the properties of a train carriage into the EngineInfo struct. * @see EngineInfo * @param a Introduction date @@ -23,7 +23,7 @@ * @param f Bitmask of the climates * @note the 0x80 in parameter b sets the "is carriage bit" */ -#define MW(a, b, c, d, e, f) { a, b | 0x80, c, d, e, f, 0, 0 } +#define MW(a, b, c, d, e, f) { DAYS_TILL_1920 + a, b | 0x80, c, d, e, f, 0, 0 } // Rail types // R = Conventional railway Index: vehicle.c =================================================================== --- vehicle.c (revision 4608) +++ vehicle.c (working copy) @@ -2143,9 +2143,12 @@ 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_CONDVAR(Vehicle,age, SLE_FILE_U16 | SLE_VAR_I32, 0, 26), + SLE_CONDVAR(Vehicle,age, SLE_INT32, 27, SL_MAX_VERSION), + SLE_CONDVAR(Vehicle,max_age, SLE_FILE_U16 | SLE_VAR_I32, 0, 26), + SLE_CONDVAR(Vehicle,max_age, SLE_INT32, 27, SL_MAX_VERSION), + SLE_CONDVAR(Vehicle,date_of_last_service, SLE_FILE_U16 | SLE_VAR_I32, 0, 26), + SLE_CONDVAR(Vehicle,date_of_last_service, SLE_INT32, 27, SL_MAX_VERSION), SLE_VAR(Vehicle,service_interval, SLE_UINT16), SLE_VAR(Vehicle,reliability, SLE_UINT16), SLE_VAR(Vehicle,reliability_spd_dec,SLE_UINT16), @@ -2153,7 +2156,8 @@ 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, 26), + SLE_CONDVAR(Vehicle,build_year, SLE_INT32, 27, SL_MAX_VERSION), SLE_VAR(Vehicle,load_unload_time_rem, SLE_UINT16), @@ -2303,7 +2307,8 @@ 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, 26), + SLE_CONDVAR(Vehicle,age, SLE_INT32, 27, SL_MAX_VERSION), SLE_VAR(Vehicle,tick_counter, SLE_UINT8), Index: vehicle.h =================================================================== --- vehicle.h (revision 4608) +++ vehicle.h (working copy) @@ -207,9 +207,9 @@ VehicleID next_hash; // Related to age and service time - uint16 age; // Age in days - uint16 max_age; // Maximum age - uint16 date_of_last_service; + Date age; // Age in days + Date max_age; // Maximum age + Date date_of_last_service; uint16 service_interval; uint16 reliability; uint16 reliability_spd_dec; @@ -217,7 +217,7 @@ 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 Index: misc.c =================================================================== --- misc.c (revision 4608) +++ misc.c (working copy) @@ -76,7 +76,7 @@ return GB(InteractiveRandom(), 0, 16) * max >> 16; } -void SetDate(uint date) +void SetDate(Date date) { YearMonthDay ymd; @@ -143,8 +143,8 @@ _cur_tileloop_tile = 0; if ((mode & IG_DATE_RESET) == IG_DATE_RESET) { - uint starting = ConvertIntDate(_patches.starting_date); - if (starting == (uint)-1) starting = 10958; + Date starting = ConvertYearToDay(_patches.starting_date); + if (starting == INVALID_DATE) starting = ConvertYearToDay(1950); SetDate(starting); } @@ -323,23 +323,32 @@ }; -void ConvertDayToYMD(YearMonthDay *ymd, uint16 date) +static inline bool IsLeapYear(Year yr) { - uint yr = date / (365+365+365+366); - uint rem = date % (365+365+365+366); + return yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0); +} + +void ConvertDayToYMD(YearMonthDay *ymd, Date date) +{ + /* Year determination in multiple steps for leap years */ + // There are 97 leap years in 400 years + Year yr = 400 * (date / (365 * 400 + 97)); + uint rem = date % (365 * 400 + 97); uint x; - yr *= 4; + // There are 24 leap years in 100 years + yr += 100 * (rem / (365 * 100 + 24)); + rem = rem % (365 * 100 + 24); - if (rem >= 366) { - rem--; - do { - rem -= 365; - yr++; - } while (rem >= 365); - if (rem >= 31+28) rem++; - } + // There is 1 leap years every 4 years + yr += 4 * (rem / (365 * 4 + 1)); + rem = rem % (365 * 4 + 1); + yr += rem / 365; + rem = rem % 365; + + if (!IsLeapYear(yr) && rem >= ACCUM_MAR - 1) rem++; + ymd->year = yr; x = _month_date_from_year_day[rem]; @@ -347,52 +356,29 @@ ymd->day = x & 0x1F; } -// year is a number between 0..? -// month is a number between 0..11 -// day is a number between 1..31 -uint ConvertYMDToDay(uint year, uint month, uint day) +Date ConvertYearToDay(Year year) { - uint rem; + // Each passed leap year adds one day to the 'day count' + uint nr_of_leap_years = year / 4 - year / 100 + year / 400; - // day in the year - rem = _accum_days_for_month[month] + day - 1; + if (year < MAX_YEAR_BEGIN_REAL || year > MAX_YEAR_END) + return INVALID_DATE; - // remove feb 29 from year 1,2,3 - if (year & 3) rem += (year & 3) * 365 + (rem < 31+29); - - // base date. - return (year >> 2) * (365+365+365+366) + rem; + return year * 365 + nr_of_leap_years; } -// convert a date on the form -// 1920 - 2090 (MAX_YEAR_END_REAL) -// 192001 - 209012 -// 19200101 - 20901231 -// or if > 2090 and below 65536, treat it as a daycount -// returns -1 if no conversion was possible -uint ConvertIntDate(uint date) +// year is a number between 0..? +// month is a number between 0..11 +// day is a number between 1..31 +Date ConvertYMDToDay(Year year, Month month, Day day) { - uint year, month = 0, day = 1; + // day-offset in a leap year + uint rem = _accum_days_for_month[month] + day - 1; - if (IS_INT_INSIDE(date, 1920, MAX_YEAR_END_REAL + 1)) { - year = date - 1920; - } else if (IS_INT_INSIDE(date, 192001, 209012+1)) { - month = date % 100 - 1; - year = date / 100 - 1920; - } else if (IS_INT_INSIDE(date, 19200101, 20901231+1)) { - day = date % 100; date /= 100; - month = date % 100 - 1; - year = date / 100 - 1920; - } else if (IS_INT_INSIDE(date, 2091, 65536)) { - return date; - } else { - return (uint)-1; - } + // remove 29th of Februari in non leap years + if (!IsLeapYear(year) && rem >= ACCUM_MAR) rem--; - // invalid ranges? - if (month >= 12 || !IS_INT_INSIDE(day, 1, 31+1)) return (uint)-1; - - return ConvertYMDToDay(year, month, day); + return ConvertYearToDay(year) + rem; } @@ -541,7 +527,7 @@ } /* check if we entered a new year? */ - if ((byte)ymd.year == _cur_year) + if (ymd.year == _cur_year) return; _cur_year = ymd.year; @@ -557,26 +543,10 @@ #endif /* ENABLE_NETWORK */ /* check if we reached end of the game (31 dec 2050) */ - if (_cur_year == _patches.ending_date - MAX_YEAR_BEGIN_REAL) { - ShowEndGameChart(); - /* check if we reached 2090 (MAX_YEAR_END_REAL), that's the maximum year. */ - } else if (_cur_year == (MAX_YEAR_END + 1)) { - Vehicle* v; + if (_cur_year == _patches.ending_date) + ShowEndGameChart(); - _cur_year = MAX_YEAR_END; - _date = 62093; - FOR_ALL_VEHICLES(v) { - v->date_of_last_service -= 365; // 1 year is 365 days long - } - - /* 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 */ - InitTextMessage(); - } - if (_patches.auto_euro) CheckSwitchToEuro(); - - /* XXX: check if year 2050 was reached */ } int FindFirstBit(uint32 value) @@ -617,7 +587,8 @@ } static const SaveLoadGlobVarList _date_desc[] = { - SLEG_VAR(_date, SLE_UINT16), + SLEG_CONDVAR(_date, SLE_FILE_U16 | SLE_VAR_I32, 0, 26), + SLEG_CONDVAR(_date, SLE_INT32, 27, SL_MAX_VERSION), SLEG_VAR(_date_fract, SLE_UINT16), SLEG_VAR(_tick_counter, SLE_UINT16), SLEG_VAR(_vehicle_id_ctr_day, SLE_UINT16), Index: player_gui.c =================================================================== --- player_gui.c (revision 4608) +++ player_gui.c (working copy) @@ -27,7 +27,8 @@ static void DrawPlayerEconomyStats(const Player *p, byte mode) { - int x,y,i,j,year; + int x,y,i,j; + Year year; const int64 (*tbl)[13]; int64 sum, cost; StringID str; @@ -46,7 +47,7 @@ tbl = p->yearly_expenses + 2; do { if (year >= p->inaugurated_year) { - SetDParam(0, year + 1920); + SetDParam(0, year); DrawStringCenterUnderline(x-17, 15, STR_7010, 0); sum = 0; for (i = 0; i != 13; i++) { @@ -535,7 +536,7 @@ w->disabled_state = dis; DrawWindowWidgets(w); - SetDParam(0, p->inaugurated_year + 1920); + SetDParam(0, p->inaugurated_year); DrawString(110, 25, STR_7038_INAUGURATED, 0); DrawPlayerVehiclesAmount(w->window_number); Index: bridge.h =================================================================== --- bridge.h (revision 4608) +++ bridge.h (working copy) @@ -12,7 +12,7 @@ /** Struct containing information about a single bridge type */ typedef struct Bridge { - byte avail_year; ///< the year in which the bridge becomes available + Year avail_year; ///< the year in which the bridge becomes available byte min_length; ///< the minimum length of the bridge (not counting start and end tile) byte max_length; ///< the maximum length of the bridge (not counting start and end tile) uint16 price; ///< the relative price of the bridge Index: main_gui.c =================================================================== --- main_gui.c (revision 4608) +++ main_gui.c (working copy) @@ -33,9 +33,9 @@ #include "network_client.h" #include "network_server.h" -/* Min/Max date for scenario editor */ -static const uint MinDate = 0; // 1920-01-01 (MAX_YEAR_BEGIN_REAL) -static const uint MaxDate = 29220; // 2000-01-01 +/* Min/Max year for scenario editor */ +static const Year MinYear = 0; +static const Year MaxYear = 3000; static int _rename_id; static int _rename_what; @@ -1004,7 +1004,7 @@ HandleButtonClick(w, 6); InvalidateWidget(w, 5); - if (_date > MinDate) SetDate(ConvertYMDToDay(_cur_year - 1, 0, 1)); + if (_cur_year > MinYear) SetDate(ConvertYMDToDay(_cur_year - 1, 0, 1)); } _left_button_clicked = false; } @@ -1016,7 +1016,7 @@ HandleButtonClick(w, 7); InvalidateWidget(w, 5); - if (_date < MaxDate) SetDate(ConvertYMDToDay(_cur_year + 1, 0, 1)); + if (_cur_year < MaxYear) SetDate(ConvertYMDToDay(_cur_year + 1, 0, 1)); } _left_button_clicked = false; } @@ -2063,12 +2063,12 @@ switch (e->event) { case WE_PAINT: /* XXX look for better place for these */ - if (_date <= MinDate) { + if (_cur_year <= MinYear) { SETBIT(w->disabled_state, 6); } else { CLRBIT(w->disabled_state, 6); } - if (_date >= MaxDate) { + if (_cur_year >= MaxYear) { SETBIT(w->disabled_state, 7); } else { CLRBIT(w->disabled_state, 7); Index: roadveh_gui.c =================================================================== --- roadveh_gui.c (revision 4608) +++ roadveh_gui.c (working copy) @@ -51,7 +51,7 @@ y += 10; /* Design date - Life length */ - SetDParam(0, ymd.year + 1920); + SetDParam(0, ymd.year); SetDParam(1, e->lifelength); DrawString(x, y, STR_PURCHASE_INFO_DESIGNED_LIFE, 0); y += 10; @@ -129,7 +129,7 @@ DrawRoadVehImage(v, 3, 57, INVALID_VEHICLE); SetDParam(0, GetCustomEngineName(v->engine_type)); - SetDParam(1, 1920 + v->build_year); + SetDParam(1, v->build_year); SetDParam(2, v->value); DrawString(34, 57, STR_9011_BUILT_VALUE, 0); Index: settings.c =================================================================== --- settings.c (revision 4608) +++ settings.c (working copy) @@ -1382,7 +1382,7 @@ 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_STRQ, S, 0, NULL, STR_NULL, NULL), SDT_STR(CurrencySpec, suffix, SLE_STRQ, S, 0, " credits", STR_NULL, NULL), SDT_END() Index: disaster_cmd.c =================================================================== --- disaster_cmd.c (revision 4608) +++ disaster_cmd.c (working copy) @@ -950,27 +950,25 @@ Disaster7_Init, }; -#define MK(a, b) { (a) - MAX_YEAR_BEGIN_REAL, (b) - MAX_YEAR_BEGIN_REAL } static const struct { - byte min; - byte max; + Year min; + Year max; } _dis_years[] = { - MK(1930, 1955), - MK(1940, 1970), - MK(1960, 1990), - MK(1970, 2000), - MK(2000, 2100), - MK(1940, 1965), - MK(1975, 2010), - MK(1950, 1985) + { 1930, 1955 }, + { 1940, 1970 }, + { 1960, 1990 }, + { 1970, 2000 }, + { 2000, 2100 }, + { 1940, 1965 }, + { 1975, 2010 }, + { 1950, 1985 } }; -#undef MK static void DoDisaster(void) { byte buf[lengthof(_dis_years)]; - byte year = _cur_year; + Year year = _cur_year; uint i; uint j; Index: waypoint.c =================================================================== --- waypoint.c (revision 4608) +++ waypoint.c (working copy) @@ -456,7 +456,8 @@ 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, 26), + SLE_CONDVAR(Waypoint, build_date, SLE_INT32, 27, SL_MAX_VERSION), SLE_CONDVAR(Waypoint, localidx, SLE_UINT8, 3, SL_MAX_VERSION), SLE_CONDVAR(Waypoint, grfid, SLE_UINT32, 17, SL_MAX_VERSION), Index: waypoint.h =================================================================== --- waypoint.h (revision 4608) +++ waypoint.h (working copy) @@ -15,7 +15,7 @@ StringID string; ///< If this is zero (i.e. no custom name), town + town_cn is used for naming ViewportSign sign; ///< Dimensions of sign (not saved) - uint16 build_date; ///< Date of construction + Date build_date; ///< Date of construction byte stat_id; ///< ID of waypoint within the waypoint class (not saved) uint32 grfid; ///< ID of GRF file Index: news.h =================================================================== --- news.h (revision 4608) +++ news.h (working copy) @@ -6,7 +6,7 @@ struct NewsItem { StringID string_id; uint16 duration; - uint16 date; + Date date; byte flags; byte display_mode; byte type; Index: train_gui.c =================================================================== --- train_gui.c (revision 4608) +++ train_gui.c (working copy) @@ -73,7 +73,7 @@ y += 10; /* Design date - Life length */ - SetDParam(0, ymd.year + 1920); + SetDParam(0, ymd.year); SetDParam(1, e->lifelength); DrawString(x,y, STR_PURCHASE_INFO_DESIGNED_LIFE, 0); y += 10; @@ -1093,7 +1093,7 @@ if (!(rvi->flags & RVI_WAGON)) { SetDParam(0, GetCustomEngineName(v->engine_type)); - SetDParam(1, v->build_year + 1920); + SetDParam(1, v->build_year); SetDParam(2, v->value); DrawString(x, y, STR_882C_BUILT_VALUE, 0x10); } else { Index: station.h =================================================================== --- station.h (revision 4608) +++ station.h (working copy) @@ -75,7 +75,7 @@ uint num_specs; StationSpecList *speclist; - uint16 build_date; + Date build_date; //uint16 airport_flags; uint32 airport_flags; Index: network_client.c =================================================================== --- network_client.c (revision 4608) +++ network_client.c (working copy) @@ -299,7 +299,7 @@ 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); Index: network_server.c =================================================================== --- network_server.c (revision 4608) +++ network_server.c (working copy) @@ -94,7 +94,7 @@ 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); Index: news_gui.c =================================================================== --- news_gui.c (revision 4608) +++ news_gui.c (working copy) @@ -260,7 +260,7 @@ ni->flags = (byte)(flags >> 8) | NF_NOEXPIRE; // show this news message in color? - if (_date >= ConvertIntDate(_patches.colored_news_date)) + if (_cur_year >= _patches.colored_news_date) ni->flags |= NF_INCOLOR; ni->type = (byte)(flags >> 16); Index: currency.c =================================================================== --- currency.c (revision 4608) +++ currency.c (working copy) @@ -78,10 +78,10 @@ uint i; for (i = 0; i != lengthof(_currency_specs); i++) { - uint16 to_euro = _currency_specs[i].to_euro; + Year to_euro = _currency_specs[i].to_euro; - if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && _cur_year >= to_euro - MAX_YEAR_BEGIN_REAL) continue; - if (to_euro == CF_ISEURO && _cur_year < 2000 - MAX_YEAR_BEGIN_REAL) continue; + if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && _cur_year >= to_euro) continue; + if (to_euro == CF_ISEURO && _cur_year < 2000) continue; mask |= (1 << i); } mask |= (1 << CUSTOM_CURRENCY_ID); // always allow custom currency Index: currency.h =================================================================== --- currency.h (revision 4608) +++ currency.h (working copy) @@ -11,7 +11,7 @@ typedef struct { uint16 rate; char separator; - uint16 to_euro; + Year to_euro; char prefix[16]; char suffix[16]; } CurrencySpec; Index: ship_gui.c =================================================================== --- ship_gui.c (revision 4608) +++ ship_gui.c (working copy) @@ -52,7 +52,7 @@ /* Design date - Life length */ e = GetEngine(engine_number); ConvertDayToYMD(&ymd, e->intro_date); - SetDParam(0, ymd.year + 1920); + SetDParam(0, ymd.year); SetDParam(1, e->lifelength); DrawString(x,y, STR_PURCHASE_INFO_DESIGNED_LIFE, 0); y += 10; @@ -206,7 +206,7 @@ DrawShipImage(v, 3, 57, INVALID_VEHICLE); - SetDParam(1, 1920 + v->build_year); + SetDParam(1, v->build_year); SetDParam(0, GetCustomEngineName(v->engine_type)); SetDParam(2, v->value); DrawString(74, 57, STR_9816_BUILT_VALUE, 0); Index: newgrf_engine.c =================================================================== --- newgrf_engine.c (revision 4608) +++ newgrf_engine.c (working copy) @@ -313,7 +313,7 @@ veh_prop(0x41, veh->age & 0xFF); veh_prop(0x42, veh->max_age); veh_prop(0x43, veh->max_age & 0xFF); - veh_prop(0x44, veh->build_year); + veh_prop(0x44, clamp(veh->build_year, 1920, 2175) - 1920); veh_prop(0x45, veh->unitnumber); veh_prop(0x46, veh->engine_type); veh_prop(0x47, veh->engine_type & 0xFF); Index: airport.c =================================================================== --- airport.c (revision 4608) +++ airport.c (working copy) @@ -375,9 +375,7 @@ { uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft() - // 1980-1-1 is --> 21915 - // 1990-1-1 is --> 25568 - if (_date >= 21915) SETBIT(bytemask, 3); // metropilitan airport 1980 - if (_date >= 25568) SETBIT(bytemask, 4); // international airport 1990 + if (_cur_year >= 1980) SETBIT(bytemask, 3); // metropolitan airport 1980 + if (_cur_year >= 1990) SETBIT(bytemask, 4); // international airport 1990 return bytemask; } Index: newgrf.c =================================================================== --- newgrf.c (revision 4608) +++ newgrf.c (working copy) @@ -1011,7 +1011,14 @@ switch (prop) { case 0x08: /* Year of availability */ - FOR_EACH_OBJECT _bridge[brid + i].avail_year = grf_load_byte(&buf); + FOR_EACH_OBJECT { + byte avail_year = grf_load_byte(&buf); + if (avail_year == 0) { + _bridge[brid + i].avail_year = 0; + } else { + _bridge[brid + i].avail_year = avail_year + 1920; + } + } break; case 0x09: /* Minimum length */ @@ -1064,6 +1071,10 @@ FOR_EACH_OBJECT _bridge[brid + i].flags = grf_load_byte(&buf); break; + case 0x0F: /* Long year -- must be set after property 8 */ + FOR_EACH_OBJECT _bridge[brid + i].avail_year = grf_load_word(&buf); + break; + default: ret = true; } @@ -1177,10 +1188,14 @@ case GSF_AIRCRAFT: /* Common properties for vehicles */ switch (prop) { - case 0x00: /* Introduction date */ - FOR_EACH_OBJECT ei[i].base_intro = grf_load_word(&buf); + case 0x00: /* Short introduction date */ + FOR_EACH_OBJECT ei[i].base_intro = grf_load_word(&buf) + ConvertYearToDay(1920); break; + case 0x01: /* Long introduction date */ + FOR_EACH_OBJECT ei[i].base_intro = grf_load_dword(&buf); + break; + case 0x02: /* Decay speed */ FOR_EACH_OBJECT SB(ei[i].unk2, 0, 7, grf_load_byte(&buf) & 0x7F); break;