diff --git a/src/date.cpp b/src/date.cpp index a330f1ce94..eb5d2ba327 100644 --- a/src/date.cpp +++ b/src/date.cpp @@ -29,7 +29,7 @@ YearMonthDay _cur_date_ymd; ///< Current date as YearMonthDay struct Date _date; ///< Current date in days (day counter) DateFract _date_fract; ///< Fractional part of the day. -uint16 _tick_counter; ///< Ever incrementing (and sometimes wrapping) tick counter for setting off various events +uint64 _tick_counter; ///< Ever incrementing tick counter for setting off various events uint8 _tick_skip_counter; ///< Counter for ticks, when only vehicles are moving and nothing else happens uint32 _scaled_tick_counter; ///< Tick counter in daylength-scaled ticks DateTicksScaled _scaled_date_ticks; ///< Date as ticks in daylength-scaled ticks @@ -63,7 +63,7 @@ void SetDate(Date date, DateFract fract) void SetScaledTickVariables() { _scaled_date_ticks = ((((DateTicksScaled)_date * DAY_TICKS) + _date_fract) * _settings_game.economy.day_length_factor) + _tick_skip_counter; - _scaled_tick_counter = (((uint32)_tick_counter) * _settings_game.economy.day_length_factor) + _tick_skip_counter; + _scaled_tick_counter = (uint32)((_tick_counter * _settings_game.economy.day_length_factor) + _tick_skip_counter); } #define M(a, b) ((a << 5) | b) diff --git a/src/date_func.h b/src/date_func.h index 0258250a15..3d03ac0e74 100644 --- a/src/date_func.h +++ b/src/date_func.h @@ -15,7 +15,7 @@ extern YearMonthDay _cur_date_ymd; extern Date _date; extern DateFract _date_fract; -extern uint16 _tick_counter; +extern uint64 _tick_counter; extern uint8 _tick_skip_counter; extern uint32 _scaled_tick_counter; extern DateTicksScaled _scaled_date_ticks; diff --git a/src/gamelog_internal.h b/src/gamelog_internal.h index 71c81cc799..a6f8780f0e 100644 --- a/src/gamelog_internal.h +++ b/src/gamelog_internal.h @@ -81,7 +81,7 @@ struct LoggedAction { LoggedChange *change; ///< First logged change in this action uint32 changes; ///< Number of changes in this action GamelogActionType at; ///< Type of action - uint16 tick; ///< Tick when it happened + uint64 tick; ///< Tick when it happened }; extern LoggedAction *_gamelog_action; diff --git a/src/newgrf.cpp b/src/newgrf.cpp index e3727e7ab0..49e371c80e 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -7191,7 +7191,7 @@ bool GetGlobalVariable(byte param, uint32 *value, const GRFFile *grffile) return true; case 0x0A: // animation counter - *value = _tick_counter; + *value = GB(_tick_counter, 0, 16); return true; case 0x0B: { // TTDPatch version @@ -11358,7 +11358,7 @@ void LoadNewGRF(uint load_index, uint num_baseset) YearMonthDay date_ymd = _cur_date_ymd; Date date = _date; DateFract date_fract = _date_fract; - uint16 tick_counter = _tick_counter; + uint64 tick_counter = _tick_counter; uint8 tick_skip_counter = _tick_skip_counter; byte display_opt = _display_opt; diff --git a/src/newgrf_profiling.cpp b/src/newgrf_profiling.cpp index 27a1bc80ef..5326740207 100644 --- a/src/newgrf_profiling.cpp +++ b/src/newgrf_profiling.cpp @@ -109,7 +109,7 @@ uint32 NewGRFProfiler::Finish() fputs("Tick,Sprite,Feature,Item,CallbackID,Microseconds,Depth,Result\n", f); for (const Call &c : this->calls) { - fprintf(f, "%u,%u,0x%X,%u,0x%X,%u,%u,%u\n", c.tick, c.root_sprite, c.feat, c.item, (uint)c.cb, c.time, c.subs, c.result); + fprintf(f, OTTD_PRINTF64U ",%u,0x%X,%u,0x%X,%u,%u,%u\n", c.tick, c.root_sprite, c.feat, c.item, (uint)c.cb, c.time, c.subs, c.result); total_microseconds += c.time; } @@ -141,7 +141,7 @@ std::string NewGRFProfiler::GetOutputFilename() const uint32 NewGRFProfiler::FinishAll() { - int max_ticks = 0; + uint64 max_ticks = 0; uint32 total_microseconds = 0; for (NewGRFProfiler &pr : _newgrf_profilers) { if (pr.active) { @@ -151,7 +151,7 @@ uint32 NewGRFProfiler::FinishAll() } if (total_microseconds > 0 && max_ticks > 0) { - IConsolePrintF(CC_DEBUG, "Total NewGRF callback processing: %u microseconds over %d ticks", total_microseconds, max_ticks); + IConsolePrintF(CC_DEBUG, "Total NewGRF callback processing: %u microseconds over " OTTD_PRINTF64U " ticks", total_microseconds, max_ticks); } _newgrf_profile_end_date = MAX_DAY; diff --git a/src/newgrf_profiling.h b/src/newgrf_profiling.h index e5b2813f59..15adb87830 100644 --- a/src/newgrf_profiling.h +++ b/src/newgrf_profiling.h @@ -45,14 +45,14 @@ struct NewGRFProfiler { uint32 result; ///< Result of callback uint32 subs; ///< Sub-calls to other sprite groups uint32 time; ///< Time taken for resolution (microseconds) - uint16 tick; ///< Game tick + uint64 tick; ///< Game tick CallbackID cb; ///< Callback ID GrfSpecFeature feat; ///< GRF feature being resolved for }; const GRFFile *grffile; ///< Which GRF is being profiled bool active; ///< Is this profiler collecting data - uint16 start_tick; ///< Tick number this profiler was started on + uint64 start_tick; ///< Tick number this profiler was started on Call cur_call; ///< Data for current call in progress std::vector calls; ///< All calls collected so far }; diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 3b2c0ad12d..2590a3b65b 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -174,8 +174,9 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_GRF_ROADSTOPS, XSCF_NULL, 1, 1, "grf_road_stops", nullptr, nullptr, nullptr }, { XSLFI_INDUSTRY_ANIM_MASK, XSCF_IGNORABLE_ALL, 1, 1, "industry_anim_mask", nullptr, nullptr, nullptr }, { XSLFI_NEW_SIGNAL_STYLES, XSCF_NULL, 2, 2, "new_signal_styles", nullptr, nullptr, "XBST,NSID" }, - { XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr }, { XSLFI_NO_TREE_COUNTER, XSCF_IGNORABLE_ALL, 1, 1, "no_tree_counter", nullptr, nullptr, nullptr }, + { XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr }, + { XSLFI_U64_TICK_COUNTER, XSCF_NULL, 1, 1, "u64_tick_counter", nullptr, nullptr, nullptr }, { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker }; diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index ed9fd2f979..0617e8b60e 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -130,6 +130,7 @@ enum SlXvFeatureIndex { XSLFI_NO_TREE_COUNTER, ///< No tree counter XSLFI_SCRIPT_INT64, ///< See: SLV_SCRIPT_INT64 + XSLFI_U64_TICK_COUNTER, ///< See: SLV_U64_TICK_COUNTER XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk diff --git a/src/saveload/gamelog_sl.cpp b/src/saveload/gamelog_sl.cpp index ef1c076e9f..8270190c53 100644 --- a/src/saveload/gamelog_sl.cpp +++ b/src/saveload/gamelog_sl.cpp @@ -17,7 +17,8 @@ #include "../safeguards.h" static const SaveLoad _glog_action_desc[] = { - SLE_VAR(LoggedAction, tick, SLE_UINT16), + SLE_CONDVAR_X(LoggedAction, tick, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER, 0, 0)), + SLE_CONDVAR_X(LoggedAction, tick, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER)), }; static const SaveLoad _glog_mode_desc[] = { @@ -144,7 +145,7 @@ static void Save_GLOG() assert((uint)lc->ct < lengthof(_glog_desc)); length += SlCalcObjLength(lc, _glog_desc[lc->ct]) + 1; } - length += 4; + length += 10; } length++; diff --git a/src/saveload/misc_sl.cpp b/src/saveload/misc_sl.cpp index 71a60f6ac5..0f106729df 100644 --- a/src/saveload/misc_sl.cpp +++ b/src/saveload/misc_sl.cpp @@ -76,7 +76,8 @@ static const SaveLoad _date_desc[] = { SLEG_CONDVAR(_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), SLEG_CONDVAR(_date, SLE_INT32, SLV_31, SL_MAX_VERSION), SLEG_VAR(_date_fract, SLE_UINT16), - SLEG_VAR(_tick_counter, SLE_UINT16), + SLEG_CONDVAR_X(_tick_counter, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER, 0, 0)), + SLEG_CONDVAR_X(_tick_counter, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER)), SLEG_CONDVAR_X(_tick_skip_counter, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH)), SLE_CONDNULL(2, SL_MIN_VERSION, SLV_157), // _vehicle_id_ctr_day SLEG_CONDVAR(_age_cargo_skip_counter, SLE_UINT8, SL_MIN_VERSION, SLV_162), @@ -106,7 +107,8 @@ static const SaveLoad _date_check_desc[] = { SLEG_CONDVAR(_load_check_data.current_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), SLEG_CONDVAR(_load_check_data.current_date, SLE_INT32, SLV_31, SL_MAX_VERSION), SLE_NULL(2), // _date_fract - SLE_NULL(2), // _tick_counter + SLE_CONDNULL_X(2, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER, 0, 0)), // _tick_counter + SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER)), // _tick_counter SLE_CONDNULL_X(1, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH)), // _tick_skip_counter SLE_CONDNULL(2, SL_MIN_VERSION, SLV_157), // _vehicle_id_ctr_day SLE_CONDNULL(1, SL_MIN_VERSION, SLV_162), // _age_cargo_skip_counter diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 8a46806060..dfc375c216 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -1610,7 +1610,7 @@ static const OldChunks main_chunk[] = { OCL_NULL( 2 ), ///< land_code, no longer in use OCL_VAR ( OC_FILE_U16 | OC_VAR_U8, 1, &_age_cargo_skip_counter ), - OCL_VAR ( OC_UINT16, 1, &_tick_counter ), + OCL_VAR ( OC_FILE_U16 | OC_VAR_U64, 1, &_tick_counter ), OCL_VAR ( OC_TILE, 1, &_cur_tileloop_tile ), OCL_ASSERT( OC_TTO, 0x3A2E ), diff --git a/src/saveload/saveload_common.h b/src/saveload/saveload_common.h index dd31c2f9af..9972c816f3 100644 --- a/src/saveload/saveload_common.h +++ b/src/saveload/saveload_common.h @@ -349,6 +349,7 @@ enum SaveLoadVersion : uint16 { SLV_LINKGRAPH_TRAVEL_TIME, ///< 297 PR#9457 v12.0-RC1 Store travel time in the linkgraph. SLV_DOCK_DOCKINGTILES, ///< 298 PR#9578 All tiles around docks may be docking tiles. SLV_REPAIR_OBJECT_DOCKING_TILES, ///< 299 PR#9594 v12.0 Fixing issue with docking tiles overlapping objects. + SLV_U64_TICK_COUNTER, ///< 300 PR#10035 Make _tick_counter 64bit to avoid wrapping. SL_MAX_VERSION, ///< Highest possible saveload version diff --git a/src/saveload/upstream/gamelog_sl.cpp b/src/saveload/upstream/gamelog_sl.cpp index 0432b6d6c7..cb2176d80b 100644 --- a/src/saveload/upstream/gamelog_sl.cpp +++ b/src/saveload/upstream/gamelog_sl.cpp @@ -349,7 +349,8 @@ public: static const SaveLoad _gamelog_desc[] = { SLE_CONDVAR(LoggedAction, at, SLE_UINT8, SLV_RIFF_TO_ARRAY, SL_MAX_VERSION), - SLE_VAR(LoggedAction, tick, SLE_UINT16), + SLE_CONDVAR(LoggedAction, tick, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SLV_U64_TICK_COUNTER), + SLE_CONDVAR(LoggedAction, tick, SLE_UINT64, SLV_U64_TICK_COUNTER, SL_MAX_VERSION), SLEG_STRUCTLIST("action", SlGamelogAction), }; diff --git a/src/saveload/upstream/misc_sl.cpp b/src/saveload/upstream/misc_sl.cpp index 4afa2ed0ba..b43ebdcb68 100644 --- a/src/saveload/upstream/misc_sl.cpp +++ b/src/saveload/upstream/misc_sl.cpp @@ -40,7 +40,8 @@ static const SaveLoad _date_desc[] = { SLEG_CONDVAR("date", _date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), SLEG_CONDVAR("date", _date, SLE_INT32, SLV_31, SL_MAX_VERSION), SLEG_VAR("date_fract", _date_fract, SLE_UINT16), - SLEG_VAR("tick_counter", _tick_counter, SLE_UINT16), + SLEG_CONDVAR("tick_counter", _tick_counter, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SLV_U64_TICK_COUNTER), + SLEG_CONDVAR("tick_counter", _tick_counter, SLE_UINT64, SLV_U64_TICK_COUNTER, SL_MAX_VERSION), SLEG_CONDVAR("age_cargo_skip_counter", _age_cargo_skip_counter, SLE_UINT8, SL_MIN_VERSION, SLV_162), SLEG_CONDVAR("cur_tileloop_tile", _cur_tileloop_tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6), SLEG_CONDVAR("cur_tileloop_tile", _cur_tileloop_tile, SLE_UINT32, SLV_6, SL_MAX_VERSION), diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index cd1a5b1567..eb271c86b0 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -914,7 +914,7 @@ static void TileLoop_Trees(TileIndex tile) /* _tick_counter is incremented by 256 between each call, so ignore lower 8 bits. * Also, we add tile % 31 to spread the updates evenly over the map, * where 31 is just some prime number that looks ok. */ - uint32 cycle = (uint32)tile % 31 + (_tick_counter >> 8); + uint32 cycle = (uint32)((tile % 31) + (_tick_counter >> 8)); /* Handle growth of grass (under trees/on MP_TREES tiles) at every 8th processings, like it's done for grass on MP_CLEAR tiles. */ if ((cycle & 7) == 7 && GetTreeGround(tile) == TREE_GROUND_GRASS) {