aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services/Time/Clock
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Time/Clock')
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockContextWriter.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs20
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/LocalSystemClockContextWriter.cs19
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/NetworkSystemClockContextWriter.cs19
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs22
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs24
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs83
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs60
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs44
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs72
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs109
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs29
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/Types/SteadyClockTimePoint.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs2
14 files changed, 351 insertions, 173 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockContextWriter.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockContextWriter.cs
new file mode 100644
index 00000000..14d3cb24
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockContextWriter.cs
@@ -0,0 +1,10 @@
+namespace Ryujinx.HLE.HOS.Services.Time.Clock
+{
+ class EphemeralNetworkSystemClockContextWriter : SystemClockContextUpdateCallback
+ {
+ protected override ResultCode Update()
+ {
+ return ResultCode.Success;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs
index 8e9073a4..003863e4 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs
@@ -2,26 +2,6 @@
{
class EphemeralNetworkSystemClockCore : SystemClockCore
{
- private static EphemeralNetworkSystemClockCore _instance;
-
- public static EphemeralNetworkSystemClockCore Instance
- {
- get
- {
- if (_instance == null)
- {
- _instance = new EphemeralNetworkSystemClockCore(TickBasedSteadyClockCore.Instance);
- }
-
- return _instance;
- }
- }
-
public EphemeralNetworkSystemClockCore(SteadyClockCore steadyClockCore) : base(steadyClockCore) { }
-
- public override ResultCode Flush(SystemClockContext context)
- {
- return ResultCode.Success;
- }
}
}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/LocalSystemClockContextWriter.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/LocalSystemClockContextWriter.cs
new file mode 100644
index 00000000..fb7ebdc5
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/LocalSystemClockContextWriter.cs
@@ -0,0 +1,19 @@
+namespace Ryujinx.HLE.HOS.Services.Time.Clock
+{
+ class LocalSystemClockContextWriter : SystemClockContextUpdateCallback
+ {
+ private TimeSharedMemory _sharedMemory;
+
+ public LocalSystemClockContextWriter(TimeSharedMemory sharedMemory)
+ {
+ _sharedMemory = sharedMemory;
+ }
+
+ protected override ResultCode Update()
+ {
+ _sharedMemory.UpdateLocalSystemClockContext(_context);
+
+ return ResultCode.Success;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/NetworkSystemClockContextWriter.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/NetworkSystemClockContextWriter.cs
new file mode 100644
index 00000000..36468ec1
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/NetworkSystemClockContextWriter.cs
@@ -0,0 +1,19 @@
+namespace Ryujinx.HLE.HOS.Services.Time.Clock
+{
+ class NetworkSystemClockContextWriter : SystemClockContextUpdateCallback
+ {
+ private TimeSharedMemory _sharedMemory;
+
+ public NetworkSystemClockContextWriter(TimeSharedMemory sharedMemory)
+ {
+ _sharedMemory = sharedMemory;
+ }
+
+ protected override ResultCode Update()
+ {
+ _sharedMemory.UpdateNetworkSystemClockContext(_context);
+
+ return ResultCode.Success;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs
index a1727976..20c334e8 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs
@@ -2,28 +2,6 @@
{
class StandardLocalSystemClockCore : SystemClockCore
{
- private static StandardLocalSystemClockCore _instance;
-
- public static StandardLocalSystemClockCore Instance
- {
- get
- {
- if (_instance == null)
- {
- _instance = new StandardLocalSystemClockCore(StandardSteadyClockCore.Instance);
- }
-
- return _instance;
- }
- }
-
public StandardLocalSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) {}
-
- public override ResultCode Flush(SystemClockContext context)
- {
- // TODO: set:sys SetUserSystemClockContext
-
- return ResultCode.Success;
- }
}
}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs
index cc21dd9a..b86f703d 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs
@@ -6,33 +6,11 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
private TimeSpanType _standardNetworkClockSufficientAccuracy;
- private static StandardNetworkSystemClockCore _instance;
-
- public static StandardNetworkSystemClockCore Instance
- {
- get
- {
- if (_instance == null)
- {
- _instance = new StandardNetworkSystemClockCore(StandardSteadyClockCore.Instance);
- }
-
- return _instance;
- }
- }
-
public StandardNetworkSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore)
{
_standardNetworkClockSufficientAccuracy = new TimeSpanType(0);
}
- public override ResultCode Flush(SystemClockContext context)
- {
- // TODO: set:sys SetNetworkSystemClockContext
-
- return ResultCode.Success;
- }
-
public bool IsStandardNetworkSystemClockAccuracySufficient(KThread thread)
{
SteadyClockCore steadyClockCore = GetSteadyClockCore();
@@ -40,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
bool isStandardNetworkClockSufficientAccuracy = false;
- ResultCode result = GetSystemClockContext(thread, out SystemClockContext context);
+ ResultCode result = GetClockContext(thread, out SystemClockContext context);
if (result == ResultCode.Success && context.SteadyTimePoint.GetSpanBetween(currentTimePoint, out long outSpan) == ResultCode.Success)
{
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs
index 1bc5bee7..370e7d73 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs
@@ -1,49 +1,30 @@
using Ryujinx.HLE.HOS.Kernel.Threading;
-using Ryujinx.HLE.HOS.Services.Pcv.Bpc;
namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
class StandardSteadyClockCore : SteadyClockCore
{
- private long _setupValue;
- private ResultCode _setupResultCode;
- private bool _isRtcResetDetected;
+ private TimeSpanType _setupValue;
private TimeSpanType _testOffset;
private TimeSpanType _internalOffset;
+ private TimeSpanType _cachedRawTimePoint;
- private static StandardSteadyClockCore _instance;
-
- public static StandardSteadyClockCore Instance
- {
- get
- {
- if (_instance == null)
- {
- _instance = new StandardSteadyClockCore();
- }
-
- return _instance;
- }
- }
-
- private StandardSteadyClockCore()
+ public StandardSteadyClockCore()
{
- _testOffset = new TimeSpanType(0);
- _internalOffset = new TimeSpanType(0);
+ _setupValue = TimeSpanType.Zero;
+ _testOffset = TimeSpanType.Zero;
+ _internalOffset = TimeSpanType.Zero;
+ _cachedRawTimePoint = TimeSpanType.Zero;
}
public override SteadyClockTimePoint GetTimePoint(KThread thread)
{
SteadyClockTimePoint result = new SteadyClockTimePoint
{
- TimePoint = 0,
+ TimePoint = GetCurrentRawTimePoint(thread).ToSeconds(),
ClockSourceId = GetClockSourceId()
};
- TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.CntpctEl0, thread.Context.CntfrqEl0);
-
- result.TimePoint = _setupValue + ticksTimeSpan.ToSeconds();
-
return result;
}
@@ -57,16 +38,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
_testOffset = testOffset;
}
- public override ResultCode GetRtcValue(out ulong rtcValue)
- {
- return (ResultCode)IRtcManager.GetExternalRtcValue(out rtcValue);
- }
-
- public bool IsRtcResetDetected()
- {
- return _isRtcResetDetected;
- }
-
public override TimeSpanType GetInternalOffset()
{
return _internalOffset;
@@ -77,31 +48,35 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
_internalOffset = internalOffset;
}
- public override ResultCode GetSetupResultValue()
+ public override TimeSpanType GetCurrentRawTimePoint(KThread thread)
{
- return _setupResultCode;
- }
+ TimeSpanType ticksTimeSpan;
- public void ConfigureSetupValue()
- {
- int retry = 0;
+ // As this may be called before the guest code, we support passing a null thread to make this api usable.
+ if (thread == null)
+ {
+ ticksTimeSpan = TimeSpanType.FromSeconds(0);
+ }
+ else
+ {
+ ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.CntpctEl0, thread.Context.CntfrqEl0);
+ }
- ResultCode result = ResultCode.Success;
+ TimeSpanType rawTimePoint = new TimeSpanType(_setupValue.NanoSeconds + ticksTimeSpan.NanoSeconds);
- while (retry < 20)
+ if (rawTimePoint.NanoSeconds < _cachedRawTimePoint.NanoSeconds)
{
- result = (ResultCode)IRtcManager.GetExternalRtcValue(out ulong rtcValue);
+ rawTimePoint.NanoSeconds = _cachedRawTimePoint.NanoSeconds;
+ }
- if (result == ResultCode.Success)
- {
- _setupValue = (long)rtcValue;
- break;
- }
+ _cachedRawTimePoint = rawTimePoint;
- retry++;
- }
+ return rawTimePoint;
+ }
- _setupResultCode = result;
+ public void SetSetupValue(TimeSpanType setupValue)
+ {
+ _setupValue = setupValue;
}
}
}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs
index c98b0064..42bc05fa 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs
@@ -1,4 +1,5 @@
using Ryujinx.HLE.HOS.Kernel.Threading;
+using System;
namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
@@ -7,35 +8,25 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
private StandardLocalSystemClockCore _localSystemClockCore;
private StandardNetworkSystemClockCore _networkSystemClockCore;
private bool _autoCorrectionEnabled;
-
- private static StandardUserSystemClockCore _instance;
-
- public static StandardUserSystemClockCore Instance
- {
- get
- {
- if (_instance == null)
- {
- _instance = new StandardUserSystemClockCore(StandardLocalSystemClockCore.Instance, StandardNetworkSystemClockCore.Instance);
- }
-
- return _instance;
- }
- }
+ private SteadyClockTimePoint _autoCorrectionTime;
+ private KEvent _autoCorrectionEvent;
public StandardUserSystemClockCore(StandardLocalSystemClockCore localSystemClockCore, StandardNetworkSystemClockCore networkSystemClockCore) : base(localSystemClockCore.GetSteadyClockCore())
{
_localSystemClockCore = localSystemClockCore;
_networkSystemClockCore = networkSystemClockCore;
_autoCorrectionEnabled = false;
+ _autoCorrectionTime = SteadyClockTimePoint.GetRandom();
+ _autoCorrectionEvent = null;
}
- public override ResultCode Flush(SystemClockContext context)
+ protected override ResultCode Flush(SystemClockContext context)
{
- return ResultCode.NotImplemented;
+ // As UserSystemClock isn't a real system clock, this shouldn't happens.
+ throw new NotImplementedException();
}
- public override ResultCode GetSystemClockContext(KThread thread, out SystemClockContext context)
+ public override ResultCode GetClockContext(KThread thread, out SystemClockContext context)
{
ResultCode result = ApplyAutomaticCorrection(thread, false);
@@ -43,13 +34,13 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
if (result == ResultCode.Success)
{
- return _localSystemClockCore.GetSystemClockContext(thread, out context);
+ return _localSystemClockCore.GetClockContext(thread, out context);
}
return result;
}
- public override ResultCode SetSystemClockContext(SystemClockContext context)
+ public override ResultCode SetClockContext(SystemClockContext context)
{
return ResultCode.NotImplemented;
}
@@ -60,17 +51,22 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
if (_autoCorrectionEnabled != autoCorrectionEnabled && _networkSystemClockCore.IsClockSetup(thread))
{
- result = _networkSystemClockCore.GetSystemClockContext(thread, out SystemClockContext context);
+ result = _networkSystemClockCore.GetClockContext(thread, out SystemClockContext context);
if (result == ResultCode.Success)
{
- _localSystemClockCore.SetSystemClockContext(context);
+ _localSystemClockCore.SetClockContext(context);
}
}
return result;
}
+ internal void CreateAutomaticCorrectionEvent(Horizon system)
+ {
+ _autoCorrectionEvent = new KEvent(system);
+ }
+
public ResultCode SetAutomaticCorrectionEnabled(KThread thread, bool autoCorrectionEnabled)
{
ResultCode result = ApplyAutomaticCorrection(thread, autoCorrectionEnabled);
@@ -87,5 +83,25 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
return _autoCorrectionEnabled;
}
+
+ public KReadableEvent GetAutomaticCorrectionReadableEvent()
+ {
+ return _autoCorrectionEvent.ReadableEvent;
+ }
+
+ public void SetAutomaticCorrectionUpdatedTime(SteadyClockTimePoint steadyClockTimePoint)
+ {
+ _autoCorrectionTime = steadyClockTimePoint;
+ }
+
+ public SteadyClockTimePoint GetAutomaticCorrectionUpdatedTime()
+ {
+ return _autoCorrectionTime;
+ }
+
+ public void SignalAutomaticCorrectionEvent()
+ {
+ _autoCorrectionEvent.WritableEvent.Signal();
+ }
}
}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs
index 54d9accf..83ace981 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs
@@ -7,10 +7,14 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
abstract class SteadyClockCore
{
private UInt128 _clockSourceId;
+ private bool _isRtcResetDetected;
+ private bool _isInitialized;
public SteadyClockCore()
{
- _clockSourceId = new UInt128(Guid.NewGuid().ToByteArray());
+ _clockSourceId = new UInt128(Guid.NewGuid().ToByteArray());
+ _isRtcResetDetected = false;
+ _isInitialized = false;
}
public UInt128 GetClockSourceId()
@@ -18,6 +22,16 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
return _clockSourceId;
}
+ public void SetClockSourceId(UInt128 clockSourceId)
+ {
+ _clockSourceId = clockSourceId;
+ }
+
+ public void SetRtcReset()
+ {
+ _isRtcResetDetected = true;
+ }
+
public virtual TimeSpanType GetTestOffset()
{
return new TimeSpanType(0);
@@ -25,16 +39,21 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
public virtual void SetTestOffset(TimeSpanType testOffset) {}
- public virtual ResultCode GetRtcValue(out ulong rtcValue)
+ public ResultCode GetRtcValue(out ulong rtcValue)
{
rtcValue = 0;
return ResultCode.NotImplemented;
}
- public virtual ResultCode GetSetupResultValue()
+ public bool IsRtcResetDetected()
{
- return ResultCode.NotImplemented;
+ return _isRtcResetDetected;
+ }
+
+ public ResultCode GetSetupResultValue()
+ {
+ return ResultCode.Success;
}
public virtual TimeSpanType GetInternalOffset()
@@ -49,6 +68,13 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
throw new NotImplementedException();
}
+ public virtual TimeSpanType GetCurrentRawTimePoint(KThread thread)
+ {
+ SteadyClockTimePoint timePoint = GetTimePoint(thread);
+
+ return TimeSpanType.FromSeconds(timePoint.TimePoint);
+ }
+
public SteadyClockTimePoint GetCurrentTimePoint(KThread thread)
{
SteadyClockTimePoint result = GetTimePoint(thread);
@@ -58,5 +84,15 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
return result;
}
+
+ public bool IsInitialized()
+ {
+ return _isInitialized;
+ }
+
+ public void MarkInitialized()
+ {
+ _isInitialized = true;
+ }
}
}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs
new file mode 100644
index 00000000..629d8ee1
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs
@@ -0,0 +1,72 @@
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Ryujinx.HLE.HOS.Services.Time.Clock
+{
+ abstract class SystemClockContextUpdateCallback
+ {
+ private List<KWritableEvent> _operationEventList;
+ protected SystemClockContext _context;
+ private bool _hasContext;
+
+ public SystemClockContextUpdateCallback()
+ {
+ _operationEventList = new List<KWritableEvent>();
+ _context = new SystemClockContext();
+ _hasContext = false;
+ }
+
+ private bool NeedUpdate(SystemClockContext context)
+ {
+ if (_hasContext)
+ {
+ return _context.Offset != context.Offset || _context.SteadyTimePoint.ClockSourceId != context.SteadyTimePoint.ClockSourceId;
+ }
+
+ return true;
+ }
+
+ public void RegisterOperationEvent(KWritableEvent writableEvent)
+ {
+ Monitor.Enter(_operationEventList);
+ _operationEventList.Add(writableEvent);
+ Monitor.Exit(_operationEventList);
+ }
+
+ private void BroadcastOperationEvent()
+ {
+ Monitor.Enter(_operationEventList);
+
+ foreach (KWritableEvent e in _operationEventList)
+ {
+ e.Signal();
+ }
+
+ Monitor.Exit(_operationEventList);
+ }
+
+ protected abstract ResultCode Update();
+
+ public ResultCode Update(SystemClockContext context)
+ {
+ ResultCode result = ResultCode.Success;
+
+ if (NeedUpdate(context))
+ {
+ _context = context;
+ _hasContext = true;
+
+ result = Update();
+
+ if (result == ResultCode.Success)
+ {
+ BroadcastOperationEvent();
+ }
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs
index 52f3c908..865b1c09 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs
@@ -1,18 +1,23 @@
-using Ryujinx.HLE.HOS.Kernel.Threading;
+using System;
+using Ryujinx.HLE.HOS.Kernel.Threading;
namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
abstract class SystemClockCore
{
- private SteadyClockCore _steadyClockCore;
- private SystemClockContext _context;
+ private SteadyClockCore _steadyClockCore;
+ private SystemClockContext _context;
+ private bool _isInitialized;
+ private SystemClockContextUpdateCallback _systemClockContextUpdateCallback;
public SystemClockCore(SteadyClockCore steadyClockCore)
{
_steadyClockCore = steadyClockCore;
_context = new SystemClockContext();
+ _isInitialized = false;
_context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId();
+ _systemClockContextUpdateCallback = null;
}
public virtual SteadyClockCore GetSteadyClockCore()
@@ -20,31 +25,115 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
return _steadyClockCore;
}
- public virtual ResultCode GetSystemClockContext(KThread thread, out SystemClockContext context)
+ public ResultCode GetCurrentTime(KThread thread, out long posixTime)
+ {
+ posixTime = 0;
+
+ SteadyClockTimePoint currentTimePoint = _steadyClockCore.GetCurrentTimePoint(thread);
+
+ ResultCode result = GetClockContext(thread, out SystemClockContext clockContext);
+
+ if (result == ResultCode.Success)
+ {
+ result = ResultCode.TimeMismatch;
+
+ if (currentTimePoint.ClockSourceId == clockContext.SteadyTimePoint.ClockSourceId)
+ {
+ posixTime = clockContext.Offset + currentTimePoint.TimePoint;
+
+ result = 0;
+ }
+ }
+
+ return result;
+ }
+
+ public ResultCode SetCurrentTime(KThread thread, long posixTime)
+ {
+ SteadyClockTimePoint currentTimePoint = _steadyClockCore.GetCurrentTimePoint(thread);
+
+ SystemClockContext clockContext = new SystemClockContext()
+ {
+ Offset = posixTime - currentTimePoint.TimePoint,
+ SteadyTimePoint = currentTimePoint
+ };
+
+ ResultCode result = SetClockContext(clockContext);
+
+ if (result == ResultCode.Success)
+ {
+ result = Flush(clockContext);
+ }
+
+ return result;
+ }
+
+ public virtual ResultCode GetClockContext(KThread thread, out SystemClockContext context)
{
context = _context;
return ResultCode.Success;
}
- public virtual ResultCode SetSystemClockContext(SystemClockContext context)
+ public virtual ResultCode SetClockContext(SystemClockContext context)
{
_context = context;
return ResultCode.Success;
}
- public abstract ResultCode Flush(SystemClockContext context);
+ protected virtual ResultCode Flush(SystemClockContext context)
+ {
+ if (_systemClockContextUpdateCallback == null)
+ {
+ return ResultCode.Success;
+ }
- public bool IsClockSetup(KThread thread)
+ return _systemClockContextUpdateCallback.Update(context);
+ }
+
+ public void SetUpdateCallbackInstance(SystemClockContextUpdateCallback systemClockContextUpdateCallback)
{
- ResultCode result = GetSystemClockContext(thread, out SystemClockContext context);
+ _systemClockContextUpdateCallback = systemClockContextUpdateCallback;
+ }
+
+ public void RegisterOperationEvent(KWritableEvent writableEvent)
+ {
+ if (_systemClockContextUpdateCallback != null)
+ {
+ _systemClockContextUpdateCallback.RegisterOperationEvent(writableEvent);
+ }
+ }
+
+ public ResultCode SetSystemClockContext(SystemClockContext context)
+ {
+ ResultCode result = SetClockContext(context);
if (result == ResultCode.Success)
{
- SteadyClockCore steadyClockCore = GetSteadyClockCore();
+ result = Flush(context);
+ }
- SteadyClockTimePoint steadyClockTimePoint = steadyClockCore.GetCurrentTimePoint(thread);
+ return result;
+ }
+
+ public bool IsInitialized()
+ {
+ return _isInitialized;
+ }
+
+ public void MarkInitialized()
+ {
+ _isInitialized = true;
+ }
+
+ public bool IsClockSetup(KThread thread)
+ {
+ ResultCode result = GetClockContext(thread, out SystemClockContext context);
+
+ if (result == ResultCode.Success)
+ {
+ SteadyClockTimePoint steadyClockTimePoint = _steadyClockCore.GetCurrentTimePoint(thread);
return steadyClockTimePoint.ClockSourceId == context.SteadyTimePoint.ClockSourceId;
}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs
index e5baba25..06502082 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs
@@ -4,22 +4,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
class TickBasedSteadyClockCore : SteadyClockCore
{
- private static TickBasedSteadyClockCore _instance;
-
- public static TickBasedSteadyClockCore Instance
- {
- get
- {
- if (_instance == null)
- {
- _instance = new TickBasedSteadyClockCore();
- }
-
- return _instance;
- }
- }
-
- private TickBasedSteadyClockCore() {}
+ public TickBasedSteadyClockCore() {}
public override SteadyClockTimePoint GetTimePoint(KThread thread)
{
@@ -29,7 +14,17 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
ClockSourceId = GetClockSourceId()
};
- TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.CntpctEl0, thread.Context.CntfrqEl0);
+ TimeSpanType ticksTimeSpan;
+
+ // As this may be called before the guest code, we support passing a null thread to make this api usable.
+ if (thread == null)
+ {
+ ticksTimeSpan = TimeSpanType.FromSeconds(0);
+ }
+ else
+ {
+ ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.CntpctEl0, thread.Context.CntfrqEl0);
+ }
result.TimePoint = ticksTimeSpan.ToSeconds();
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/Types/SteadyClockTimePoint.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/Types/SteadyClockTimePoint.cs
index 0055b5ea..71fb4521 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/Types/SteadyClockTimePoint.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/Types/SteadyClockTimePoint.cs
@@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
[StructLayout(LayoutKind.Sequential)]
struct SteadyClockTimePoint
{
- public long TimePoint;
+ public long TimePoint;
public UInt128 ClockSourceId;
public ResultCode GetSpanBetween(SteadyClockTimePoint other, out long outSpan)
@@ -30,5 +30,14 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
return ResultCode.Overflow;
}
+
+ public static SteadyClockTimePoint GetRandom()
+ {
+ return new SteadyClockTimePoint
+ {
+ TimePoint = 0,
+ ClockSourceId = new UInt128(Guid.NewGuid().ToByteArray())
+ };
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs
index 93579709..c336ad41 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs
@@ -7,6 +7,8 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
private const long NanoSecondsPerSecond = 1000000000;
+ public static readonly TimeSpanType Zero = new TimeSpanType(0);
+
public long NanoSeconds;
public TimeSpanType(long nanoSeconds)