From e4915fb7d2077584a11a15141bc81d28ed2b0125 Mon Sep 17 00:00:00 2001 From: Kelebek1 Date: Sun, 29 Oct 2023 13:50:55 +0000 Subject: Rework time service to fix time passing offline. --- src/common/arm64/native_clock.cpp | 24 ++++++++++-------------- src/common/arm64/native_clock.h | 10 ++++------ src/common/memory_detect.h | 2 +- src/common/settings.h | 13 ++++++++++--- src/common/time_zone.cpp | 12 +++++++++++- src/common/uuid.h | 12 ++---------- src/common/wall_clock.cpp | 32 +++++++++++++++----------------- src/common/wall_clock.h | 9 +++------ src/common/x64/native_clock.cpp | 26 +++++++++++--------------- src/common/x64/native_clock.h | 9 +++------ 10 files changed, 70 insertions(+), 79 deletions(-) (limited to 'src/common') diff --git a/src/common/arm64/native_clock.cpp b/src/common/arm64/native_clock.cpp index f437d7187..76ffb74ba 100644 --- a/src/common/arm64/native_clock.cpp +++ b/src/common/arm64/native_clock.cpp @@ -30,27 +30,27 @@ NativeClock::NativeClock() { } std::chrono::nanoseconds NativeClock::GetTimeNS() const { - return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_cntfrq_factor)}; + return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_cntfrq_factor)}; } std::chrono::microseconds NativeClock::GetTimeUS() const { - return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_cntfrq_factor)}; + return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)}; } std::chrono::milliseconds NativeClock::GetTimeMS() const { - return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_cntfrq_factor)}; + return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)}; } -u64 NativeClock::GetCNTPCT() const { - return MultiplyHigh(GetHostTicksElapsed(), guest_cntfrq_factor); +s64 NativeClock::GetCNTPCT() const { + return MultiplyHigh(GetUptime(), guest_cntfrq_factor); } -u64 NativeClock::GetGPUTick() const { - return MultiplyHigh(GetHostTicksElapsed(), gputick_cntfrq_factor); +s64 NativeClock::GetGPUTick() const { + return MultiplyHigh(GetUptime(), gputick_cntfrq_factor); } -u64 NativeClock::GetHostTicksNow() const { - u64 cntvct_el0 = 0; +s64 NativeClock::GetUptime() const { + s64 cntvct_el0 = 0; asm volatile("dsb ish\n\t" "mrs %[cntvct_el0], cntvct_el0\n\t" "dsb ish\n\t" @@ -58,15 +58,11 @@ u64 NativeClock::GetHostTicksNow() const { return cntvct_el0; } -u64 NativeClock::GetHostTicksElapsed() const { - return GetHostTicksNow(); -} - bool NativeClock::IsNative() const { return true; } -u64 NativeClock::GetHostCNTFRQ() { +s64 NativeClock::GetHostCNTFRQ() { u64 cntfrq_el0 = 0; std::string_view board{""}; #ifdef ANDROID diff --git a/src/common/arm64/native_clock.h b/src/common/arm64/native_clock.h index a28b419f2..94bc1882e 100644 --- a/src/common/arm64/native_clock.h +++ b/src/common/arm64/native_clock.h @@ -17,17 +17,15 @@ public: std::chrono::milliseconds GetTimeMS() const override; - u64 GetCNTPCT() const override; + s64 GetCNTPCT() const override; - u64 GetGPUTick() const override; + s64 GetGPUTick() const override; - u64 GetHostTicksNow() const override; - - u64 GetHostTicksElapsed() const override; + s64 GetUptime() const override; bool IsNative() const override; - static u64 GetHostCNTFRQ(); + static s64 GetHostCNTFRQ(); public: using FactorType = unsigned __int128; diff --git a/src/common/memory_detect.h b/src/common/memory_detect.h index a345e6d28..c8f239aed 100644 --- a/src/common/memory_detect.h +++ b/src/common/memory_detect.h @@ -18,4 +18,4 @@ struct MemoryInfo { */ [[nodiscard]] const MemoryInfo& GetMemInfo(); -} // namespace Common \ No newline at end of file +} // namespace Common diff --git a/src/common/settings.h b/src/common/settings.h index 07dba53ab..16749ab68 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -419,9 +419,16 @@ struct Values { linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true}; SwitchableSetting custom_rtc{ linkage, 0, "custom_rtc", Category::System, Specialization::Time, - true, true, &custom_rtc_enabled}; - // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` - s64 custom_rtc_differential; + false, true, &custom_rtc_enabled}; + SwitchableSetting custom_rtc_offset{linkage, + 0, + std::numeric_limits::min(), + std::numeric_limits::max(), + "custom_rtc_offset", + Category::System, + Specialization::Countable, + true, + true}; SwitchableSetting rng_seed_enabled{ linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true}; SwitchableSetting rng_seed{ diff --git a/src/common/time_zone.cpp b/src/common/time_zone.cpp index 69e728a9d..f77df604f 100644 --- a/src/common/time_zone.cpp +++ b/src/common/time_zone.cpp @@ -88,7 +88,17 @@ std::string FindSystemTimeZone() { LOG_ERROR(Common, "Time zone {} not handled, defaulting to hour offset.", tz_index); } } - return fmt::format("Etc/GMT{:s}{:d}", hours > 0 ? "-" : "+", std::abs(hours)); + + // For some reason the Etc/GMT times are reversed. GMT+6 contains -21600 as its offset, + // -6 hours instead of +6 hours, so these signs are purposefully reversed to fix it. + std::string postfix{""}; + if (hours > 0) { + postfix = fmt::format("-{:d}", std::abs(hours)); + } else if (hours < 0) { + postfix = fmt::format("+{:d}", std::abs(hours)); + } + + return fmt::format("Etc/GMT{:s}", postfix); } } // namespace Common::TimeZone diff --git a/src/common/uuid.h b/src/common/uuid.h index 7172ca165..81bfefbbb 100644 --- a/src/common/uuid.h +++ b/src/common/uuid.h @@ -12,9 +12,8 @@ namespace Common { struct UUID { - std::array uuid{}; + std::array uuid; - /// Constructs an invalid UUID. constexpr UUID() = default; /// Constructs a UUID from a reference to a 128 bit array. @@ -34,14 +33,6 @@ struct UUID { */ explicit UUID(std::string_view uuid_string); - ~UUID() = default; - - constexpr UUID(const UUID&) noexcept = default; - constexpr UUID(UUID&&) noexcept = default; - - constexpr UUID& operator=(const UUID&) noexcept = default; - constexpr UUID& operator=(UUID&&) noexcept = default; - /** * Returns whether the stored UUID is valid or not. * @@ -121,6 +112,7 @@ struct UUID { friend constexpr bool operator==(const UUID& lhs, const UUID& rhs) = default; }; static_assert(sizeof(UUID) == 0x10, "UUID has incorrect size."); +static_assert(std::is_trivial_v); /// An invalid UUID. This UUID has all its bytes set to 0. constexpr UUID InvalidUUID = {}; diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp index 012fdc1e0..e14bf3e65 100644 --- a/src/common/wall_clock.cpp +++ b/src/common/wall_clock.cpp @@ -18,42 +18,40 @@ namespace Common { class StandardWallClock final : public WallClock { public: - explicit StandardWallClock() : start_time{SteadyClock::Now()} {} + explicit StandardWallClock() {} std::chrono::nanoseconds GetTimeNS() const override { - return SteadyClock::Now() - start_time; + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); } std::chrono::microseconds GetTimeUS() const override { - return static_cast(GetHostTicksElapsed() / NsToUsRatio::den); + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); } std::chrono::milliseconds GetTimeMS() const override { - return static_cast(GetHostTicksElapsed() / NsToMsRatio::den); + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); } - u64 GetCNTPCT() const override { - return GetHostTicksElapsed() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den; + s64 GetCNTPCT() const override { + return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den; } - u64 GetGPUTick() const override { - return GetHostTicksElapsed() * NsToGPUTickRatio::num / NsToGPUTickRatio::den; + s64 GetGPUTick() const override { + return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den; } - u64 GetHostTicksNow() const override { - return static_cast(SteadyClock::Now().time_since_epoch().count()); - } - - u64 GetHostTicksElapsed() const override { - return static_cast(GetTimeNS().count()); + s64 GetUptime() const override { + return std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()) + .count(); } bool IsNative() const override { return false; } - -private: - SteadyClock::time_point start_time; }; std::unique_ptr CreateOptimalClock() { diff --git a/src/common/wall_clock.h b/src/common/wall_clock.h index f45d3d8c5..3a0c43909 100644 --- a/src/common/wall_clock.h +++ b/src/common/wall_clock.h @@ -29,16 +29,13 @@ public: virtual std::chrono::milliseconds GetTimeMS() const = 0; /// @returns The guest CNTPCT ticks since the construction of this clock. - virtual u64 GetCNTPCT() const = 0; + virtual s64 GetCNTPCT() const = 0; /// @returns The guest GPU ticks since the construction of this clock. - virtual u64 GetGPUTick() const = 0; + virtual s64 GetGPUTick() const = 0; /// @returns The raw host timer ticks since an indeterminate epoch. - virtual u64 GetHostTicksNow() const = 0; - - /// @returns The raw host timer ticks since the construction of this clock. - virtual u64 GetHostTicksElapsed() const = 0; + virtual s64 GetUptime() const = 0; /// @returns Whether the clock directly uses the host's hardware clock. virtual bool IsNative() const = 0; diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index 7d2a26bd9..d2d27fafe 100644 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp @@ -8,39 +8,35 @@ namespace Common::X64 { NativeClock::NativeClock(u64 rdtsc_frequency_) - : start_ticks{FencedRDTSC()}, rdtsc_frequency{rdtsc_frequency_}, - ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency)}, + : rdtsc_frequency{rdtsc_frequency_}, ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den, + rdtsc_frequency)}, us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)}, ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)}, cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)}, gputick_rdtsc_factor{GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency)} {} std::chrono::nanoseconds NativeClock::GetTimeNS() const { - return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_rdtsc_factor)}; + return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_rdtsc_factor)}; } std::chrono::microseconds NativeClock::GetTimeUS() const { - return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_rdtsc_factor)}; + return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_rdtsc_factor)}; } std::chrono::milliseconds NativeClock::GetTimeMS() const { - return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_rdtsc_factor)}; + return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_rdtsc_factor)}; } -u64 NativeClock::GetCNTPCT() const { - return MultiplyHigh(GetHostTicksElapsed(), cntpct_rdtsc_factor); +s64 NativeClock::GetCNTPCT() const { + return MultiplyHigh(GetUptime(), cntpct_rdtsc_factor); } -u64 NativeClock::GetGPUTick() const { - return MultiplyHigh(GetHostTicksElapsed(), gputick_rdtsc_factor); +s64 NativeClock::GetGPUTick() const { + return MultiplyHigh(GetUptime(), gputick_rdtsc_factor); } -u64 NativeClock::GetHostTicksNow() const { - return FencedRDTSC(); -} - -u64 NativeClock::GetHostTicksElapsed() const { - return FencedRDTSC() - start_ticks; +s64 NativeClock::GetUptime() const { + return static_cast(FencedRDTSC()); } bool NativeClock::IsNative() const { diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h index 334415eff..b2629b031 100644 --- a/src/common/x64/native_clock.h +++ b/src/common/x64/native_clock.h @@ -17,18 +17,15 @@ public: std::chrono::milliseconds GetTimeMS() const override; - u64 GetCNTPCT() const override; + s64 GetCNTPCT() const override; - u64 GetGPUTick() const override; + s64 GetGPUTick() const override; - u64 GetHostTicksNow() const override; - - u64 GetHostTicksElapsed() const override; + s64 GetUptime() const override; bool IsNative() const override; private: - u64 start_ticks; u64 rdtsc_frequency; u64 ns_rdtsc_factor; -- cgit v1.2.3