diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-30 01:55:20 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-30 02:31:58 -0400 |
| commit | 0218eacfd560d0ce48b3ffe64d279ee85bbf1347 (patch) | |
| tree | cbe764aa642b55cae06e94f15bd0e16f234e6052 /src/core/hle/service | |
| parent | 08be623a271d13b66497a98265f6832e9aa2c0d0 (diff) | |
nx2: run the guest counter at 31.25 MHz for Switch 2 titles
The Switch 2 counter runs at 31.25 MHz and its SDK converts ticks with
that constant: Mario Kart World's sdk builds 31,250,000 in
nn::os::GetSystemTickFrequency, TickManager::ConvertToTimeSpan and
TickManager::ConvertToTick (19.2 MHz appears nowhere). Eglantine counted
at the Switch 1 rate for every title, so every tick-based time in a
Switch 2 game was off by 1.63x: elapsed times read short, and a deadline
of one 60 Hz frame converted to ticks waited ~27 ms.
The wall clock now has a guest counter frequency, set at boot: 31.25 MHz
for Switch 2 programs, 19.2 MHz otherwise, EDEN_NX2_CNTFRQ=<Hz> to force
one. CNTPCT reads, CNTFRQ_EL0, svcGetSystemTick, thread tick counts and
the time services' tick conversions follow it, and the CNTPCT spin
detection keeps its ~1.7 us threshold.
Mario Kart World, title screen and attract demo, 180 s, same build:
frame times unchanged (17-19 ms once warm), process CPU time 848 s
instead of 930 s.
Diffstat (limited to 'src/core/hle/service')
| -rw-r--r-- | src/core/hle/service/psc/time/common.h | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/src/core/hle/service/psc/time/common.h b/src/core/hle/service/psc/time/common.h index 2183fa72b8..6f7d2cb88b 100644 --- a/src/core/hle/service/psc/time/common.h +++ b/src/core/hle/service/psc/time/common.h @@ -134,12 +134,13 @@ struct OperationEvent : public Common::IntrusiveListBaseNode<OperationEvent> { Kernel::KEvent* m_event{}; }; -constexpr inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) { +inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) { constexpr auto one_second_ns{ std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()}; - constexpr s64 max{Common::WallClock::CNTFRQ * - ((std::numeric_limits<s64>::max)() / one_second_ns)}; + // The guest counter's frequency: 31.25 MHz for Switch 2 titles. + const s64 frequency{static_cast<s64>(Common::g_wall_clock.GetGuestCNTFRQ())}; + const s64 max{frequency * ((std::numeric_limits<s64>::max)() / one_second_ns)}; if (ticks > max) { return std::chrono::nanoseconds((std::numeric_limits<s64>::max)()); @@ -147,8 +148,8 @@ constexpr inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) { return std::chrono::nanoseconds((std::numeric_limits<s64>::min)()); } - auto a{ticks / Common::WallClock::CNTFRQ * one_second_ns}; - auto b{((ticks % Common::WallClock::CNTFRQ) * one_second_ns) / Common::WallClock::CNTFRQ}; + auto a{ticks / frequency * one_second_ns}; + auto b{((ticks % frequency) * one_second_ns) / frequency}; return std::chrono::nanoseconds(a + b); } |
