aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary <mary@mary.zone>2023-05-08 00:15:58 +0200
committerGitHub <noreply@github.com>2023-05-08 00:15:58 +0200
commit470a8031a44145f906b50919ce1a4e01d51c15ff (patch)
treefbb7634d81f9f071e28e027c52120d4e91f5f2ec
parent5440d4ad5c5421a474a61e582e524ced5bd65547 (diff)
time: Update for 15.0.0 changes and fixes long standing issues (#4822)1.1.766
* time: Update for 15.0.0 changes Last time we did an upgrade on the time service was during 9.x era, it was about time to take back that reverse again! 15.0.0 added a new structure on the shared memory to get steady clock raw timepoints with a granularity in nanoseconds. This commit implements this new part. I plan to write a follow up with a bit of refactoring of this ancient part of the emulator. As always, reverse and work done by your truly. PS: As a reminder, if this change is reused anywhere else, work should be credited as Ryujinx and not my person. * time: Do not set setup value to posix time This should fix local and network clock returning 0 under usage with shared memory. This probably fix #2430. * Address gdkchan's comment * Fix internal offset not working since changes and ensure that user clock have a valid clock id * time: Report auto correcting clock and hardcode steady clock unique id Fix Pokemon Sword Pokejobs for real. * Address gdkchan's comment
-rw-r--r--src/Ryujinx.HLE/HOS/Horizon.cs11
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ContinuousAdjustmentTimePoint.cs13
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Time/TimeSharedMemory.cs53
3 files changed, 56 insertions, 21 deletions
diff --git a/src/Ryujinx.HLE/HOS/Horizon.cs b/src/Ryujinx.HLE/HOS/Horizon.cs
index 1639532e..f73dea1d 100644
--- a/src/Ryujinx.HLE/HOS/Horizon.cs
+++ b/src/Ryujinx.HLE/HOS/Horizon.cs
@@ -200,9 +200,10 @@ namespace Ryujinx.HLE.HOS
LibHacHorizonManager = device.Configuration.LibHacHorizonManager;
+ // We hardcode a clock source id to avoid it changing between each start.
// TODO: use set:sys (and get external clock source id from settings)
// TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate.
- UInt128 clockSourceId = UInt128Utils.CreateRandom();
+ UInt128 clockSourceId = new UInt128(0x36a0328702ce8bc1, 0x1608eaba02333284);
IRtcManager.GetExternalRtcValue(out ulong rtcValue);
// We assume the rtc is system time.
@@ -222,22 +223,22 @@ namespace Ryujinx.HLE.HOS
internalOffset = internalOffset.AddSeconds(-3600L);
}
- internalOffset = new TimeSpanType(-internalOffset.NanoSeconds);
+ systemTime = new TimeSpanType(systemTime.NanoSeconds + internalOffset.NanoSeconds);
// First init the standard steady clock
- TimeServiceManager.Instance.SetupStandardSteadyClock(TickSource, clockSourceId, systemTime, internalOffset, TimeSpanType.Zero, false);
+ TimeServiceManager.Instance.SetupStandardSteadyClock(TickSource, clockSourceId, TimeSpanType.Zero, TimeSpanType.Zero, TimeSpanType.Zero, false);
TimeServiceManager.Instance.SetupStandardLocalSystemClock(TickSource, new SystemClockContext(), systemTime.ToSeconds());
+ TimeServiceManager.Instance.StandardLocalSystemClock.GetClockContext(TickSource, out SystemClockContext localSytemClockContext);
if (NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes))
{
TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000);
// The network system clock needs a valid system clock, as such we setup this system clock using the local system clock.
- TimeServiceManager.Instance.StandardLocalSystemClock.GetClockContext(TickSource, out SystemClockContext localSytemClockContext);
TimeServiceManager.Instance.SetupStandardNetworkSystemClock(localSytemClockContext, standardNetworkClockSufficientAccuracy);
}
- TimeServiceManager.Instance.SetupStandardUserSystemClock(TickSource, false, SteadyClockTimePoint.GetRandom());
+ TimeServiceManager.Instance.SetupStandardUserSystemClock(TickSource, true, localSytemClockContext.SteadyTimePoint);
// FIXME: TimeZone should be init here but it's actually done in ContentManager
diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ContinuousAdjustmentTimePoint.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ContinuousAdjustmentTimePoint.cs
new file mode 100644
index 00000000..b57dfaa0
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ContinuousAdjustmentTimePoint.cs
@@ -0,0 +1,13 @@
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.HLE.HOS.Services.Time.Clock.Types
+{
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ struct ContinuousAdjustmentTimePoint
+ {
+ public ulong ClockOffset;
+ public long Multiplier;
+ public long DivisorLog2;
+ public SystemClockContext Context;
+ }
+}
diff --git a/src/Ryujinx.HLE/HOS/Services/Time/TimeSharedMemory.cs b/src/Ryujinx.HLE/HOS/Services/Time/TimeSharedMemory.cs
index 7063290b..6b1e1687 100644
--- a/src/Ryujinx.HLE/HOS/Services/Time/TimeSharedMemory.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Time/TimeSharedMemory.cs
@@ -1,8 +1,8 @@
using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Services.Time.Clock;
+using Ryujinx.HLE.HOS.Services.Time.Clock.Types;
using Ryujinx.HLE.HOS.Services.Time.Types;
-using Ryujinx.HLE.Utilities;
using System;
using System.Runtime.CompilerServices;
using System.Threading;
@@ -16,10 +16,11 @@ namespace Ryujinx.HLE.HOS.Services.Time
private SharedMemoryStorage _timeSharedMemoryStorage;
private int _timeSharedMemorySize;
- private const uint SteadyClockContextOffset = 0x00;
- private const uint LocalSystemClockContextOffset = 0x38;
- private const uint NetworkSystemClockContextOffset = 0x80;
+ private const uint SteadyClockContextOffset = 0x00;
+ private const uint LocalSystemClockContextOffset = 0x38;
+ private const uint NetworkSystemClockContextOffset = 0x80;
private const uint AutomaticCorrectionEnabledOffset = 0xC8;
+ private const uint ContinuousAdjustmentTimePointOffset = 0xD0;
public void Initialize(Switch device, KSharedMemory sharedMemory, SharedMemoryStorage timeSharedMemoryStorage, int timeSharedMemorySize)
{
@@ -39,15 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
public void SetupStandardSteadyClock(ITickSource tickSource, UInt128 clockSourceId, TimeSpanType currentTimePoint)
{
- TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(tickSource.Counter, tickSource.Frequency);
-
- SteadyClockContext context = new SteadyClockContext
- {
- InternalOffset = (ulong)(currentTimePoint.NanoSeconds - ticksTimeSpan.NanoSeconds),
- ClockSourceId = clockSourceId
- };
-
- WriteObjectToSharedMemory(SteadyClockContextOffset, 4, context);
+ UpdateSteadyClock(tickSource, clockSourceId, currentTimePoint);
}
public void SetAutomaticCorrectionEnabled(bool isAutomaticCorrectionEnabled)
@@ -58,10 +51,38 @@ namespace Ryujinx.HLE.HOS.Services.Time
public void SetSteadyClockRawTimePoint(ITickSource tickSource, TimeSpanType currentTimePoint)
{
- SteadyClockContext context = ReadObjectFromSharedMemory<SteadyClockContext>(SteadyClockContextOffset, 4);
- TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(tickSource.Counter, tickSource.Frequency);
+ SteadyClockContext context = ReadObjectFromSharedMemory<SteadyClockContext>(SteadyClockContextOffset, 4);
- context.InternalOffset = (ulong)(currentTimePoint.NanoSeconds - ticksTimeSpan.NanoSeconds);
+ UpdateSteadyClock(tickSource, context.ClockSourceId, currentTimePoint);
+ }
+
+ private void UpdateSteadyClock(ITickSource tickSource, UInt128 clockSourceId, TimeSpanType currentTimePoint)
+ {
+ TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(tickSource.Counter, tickSource.Frequency);
+
+ ContinuousAdjustmentTimePoint adjustmentTimePoint = new ContinuousAdjustmentTimePoint
+ {
+ ClockOffset = (ulong)ticksTimeSpan.NanoSeconds,
+ Multiplier = 1,
+ DivisorLog2 = 0,
+ Context = new SystemClockContext
+ {
+ Offset = 0,
+ SteadyTimePoint = new SteadyClockTimePoint
+ {
+ ClockSourceId = clockSourceId,
+ TimePoint = 0
+ }
+ }
+ };
+
+ WriteObjectToSharedMemory(ContinuousAdjustmentTimePointOffset, 4, adjustmentTimePoint);
+
+ SteadyClockContext context = new SteadyClockContext
+ {
+ InternalOffset = (ulong)(currentTimePoint.NanoSeconds - ticksTimeSpan.NanoSeconds),
+ ClockSourceId = clockSourceId
+ };
WriteObjectToSharedMemory(SteadyClockContextOffset, 4, context);
}