diff options
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Time/Clock')
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) |
