diff options
| author | Thomas Guillemard <me@thog.eu> | 2019-07-25 16:44:51 +0200 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2019-07-25 11:44:51 -0300 |
| commit | 54b79dffa8eafe9da9765329930e8832ae90ae83 (patch) | |
| tree | 1ba6b60288997c8ce21a72bbd28e3efb7b8db2d7 /Ryujinx.HLE/HOS/Services/Time/Clock | |
| parent | d254548548398977a45dbfc03f2cc091c5a74f03 (diff) | |
Implement time:* 4.0.0 commands (#736)
* Abstract SteadyClockCore to follow Nintendo changes in 4.x
This is the ground work for 4.0.0 support
* Implement TickBasedSteadyClockCore
Preparation for the ephemeral clock.
* Refactor SystemClockCore to follow 4.0.0 changes
* Implement EphemeralNetworkSystemClock
* Implement GetSnapshotClock & GetSnapshotClockFromSystemClockContext
* Implement CalculateStandardUserSystemClockDifferenceByUser & CalculateSpanBetween
* Remove an outdated comment & unused import
* Fix a nit and GetClockSnapshot
* Address comment
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Time/Clock')
9 files changed, 288 insertions, 175 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/ClockTypes.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/ClockTypes.cs index 860f5ad2..c70819c0 100644 --- a/Ryujinx.HLE/HOS/Services/Time/Clock/ClockTypes.cs +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/ClockTypes.cs @@ -7,6 +7,8 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock [StructLayout(LayoutKind.Sequential)] struct TimeSpanType { + private const long NanoSecondsPerSecond = 1000000000; + public long NanoSeconds; public TimeSpanType(long nanoSeconds) @@ -16,12 +18,17 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock public long ToSeconds() { - return NanoSeconds / 1000000000; + return NanoSeconds / NanoSecondsPerSecond; + } + + public static TimeSpanType FromSeconds(long seconds) + { + return new TimeSpanType(seconds * NanoSecondsPerSecond); } public static TimeSpanType FromTicks(ulong ticks, ulong frequency) { - return new TimeSpanType((long)ticks * 1000000000 / (long)frequency); + return FromSeconds((long)ticks / (long)frequency); } } @@ -59,4 +66,40 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock public long Offset; public SteadyClockTimePoint SteadyTimePoint; } + + [StructLayout(LayoutKind.Sequential, Size = 0xD0)] + struct ClockSnapshot + { + public SystemClockContext UserContext; + public SystemClockContext NetworkContext; + public long UserTime; + public long NetworkTime; + public CalendarTime UserCalendarTime; + public CalendarTime NetworkCalendarTime; + public CalendarAdditionalInfo UserCalendarAdditionalTime; + public CalendarAdditionalInfo NetworkCalendarAdditionalTime; + public SteadyClockTimePoint SteadyClockTimePoint; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x24)] + public char[] LocationName; + + [MarshalAs(UnmanagedType.I1)] + public bool IsAutomaticCorrectionEnabled; + public byte Type; + public ushort Unknown; + + public static ResultCode GetCurrentTime(out long currentTime, SteadyClockTimePoint steadyClockTimePoint, SystemClockContext context) + { + currentTime = 0; + + if (steadyClockTimePoint.ClockSourceId == context.SteadyTimePoint.ClockSourceId) + { + currentTime = steadyClockTimePoint.TimePoint + context.Offset; + + return ResultCode.Success; + } + + return ResultCode.TimeMismatch; + } + } } diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs new file mode 100644 index 00000000..8e9073a4 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs @@ -0,0 +1,27 @@ +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + 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/StandardLocalSystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs index 16550199..a1727976 100644 --- a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs @@ -1,34 +1,23 @@ -using Ryujinx.HLE.HOS.Kernel.Threading; - -namespace Ryujinx.HLE.HOS.Services.Time.Clock +namespace Ryujinx.HLE.HOS.Services.Time.Clock { class StandardLocalSystemClockCore : SystemClockCore { - private SteadyClockCore _steadyClockCore; - private SystemClockContext _context; - - private static StandardLocalSystemClockCore instance; + private static StandardLocalSystemClockCore _instance; public static StandardLocalSystemClockCore Instance { get { - if (instance == null) + if (_instance == null) { - instance = new StandardLocalSystemClockCore(SteadyClockCore.Instance); + _instance = new StandardLocalSystemClockCore(StandardSteadyClockCore.Instance); } - return instance; + return _instance; } } - public StandardLocalSystemClockCore(SteadyClockCore steadyClockCore) - { - _steadyClockCore = steadyClockCore; - _context = new SystemClockContext(); - - _context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId(); - } + public StandardLocalSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) {} public override ResultCode Flush(SystemClockContext context) { @@ -36,24 +25,5 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock return ResultCode.Success; } - - public override SteadyClockCore GetSteadyClockCore() - { - return _steadyClockCore; - } - - public override ResultCode GetSystemClockContext(KThread thread, out SystemClockContext context) - { - context = _context; - - return ResultCode.Success; - } - - public override ResultCode SetSystemClockContext(SystemClockContext context) - { - _context = context; - - return ResultCode.Success; - } } } diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs index c00f460e..5037fb60 100644 --- a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs @@ -1,35 +1,28 @@ -using System; -using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.HLE.HOS.Kernel.Threading; namespace Ryujinx.HLE.HOS.Services.Time.Clock { class StandardNetworkSystemClockCore : SystemClockCore { - private SteadyClockCore _steadyClockCore; - private SystemClockContext _context; private TimeSpanType _standardNetworkClockSufficientAccuracy; - private static StandardNetworkSystemClockCore instance; + private static StandardNetworkSystemClockCore _instance; public static StandardNetworkSystemClockCore Instance { get { - if (instance == null) + if (_instance == null) { - instance = new StandardNetworkSystemClockCore(SteadyClockCore.Instance); + _instance = new StandardNetworkSystemClockCore(StandardSteadyClockCore.Instance); } - return instance; + return _instance; } } - public StandardNetworkSystemClockCore(SteadyClockCore steadyClockCore) + public StandardNetworkSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) { - _steadyClockCore = steadyClockCore; - _context = new SystemClockContext(); - - _context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId(); _standardNetworkClockSufficientAccuracy = new TimeSpanType(0); } @@ -40,25 +33,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock return ResultCode.Success; } - public override SteadyClockCore GetSteadyClockCore() - { - return _steadyClockCore; - } - - public override ResultCode GetSystemClockContext(KThread thread, out SystemClockContext context) - { - context = _context; - - return ResultCode.Success; - } - - public override ResultCode SetSystemClockContext(SystemClockContext context) - { - _context = context; - - return ResultCode.Success; - } - public bool IsStandardNetworkSystemClockAccuracySufficient(KThread thread) { SteadyClockCore steadyClockCore = GetSteadyClockCore(); @@ -66,7 +40,9 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock bool isStandardNetworkClockSufficientAccuracy = false; - if (_context.SteadyTimePoint.GetSpanBetween(currentTimePoint, out long outSpan) == ResultCode.Success) + ResultCode result = GetSystemClockContext(thread, out SystemClockContext context); + + if (result == ResultCode.Success && context.SteadyTimePoint.GetSpanBetween(currentTimePoint, out long outSpan) == ResultCode.Success) { isStandardNetworkClockSufficientAccuracy = outSpan * 1000000000 < _standardNetworkClockSufficientAccuracy.NanoSeconds; } diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs new file mode 100644 index 00000000..fea5bf2f --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs @@ -0,0 +1,107 @@ +using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.HLE.HOS.Services.Bpc; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + class StandardSteadyClockCore : SteadyClockCore + { + private long _setupValue; + private ResultCode _setupResultCode; + private bool _isRtcResetDetected; + private TimeSpanType _testOffset; + private TimeSpanType _internalOffset; + + private static StandardSteadyClockCore _instance; + + public static StandardSteadyClockCore Instance + { + get + { + if (_instance == null) + { + _instance = new StandardSteadyClockCore(); + } + + return _instance; + } + } + + private StandardSteadyClockCore() + { + _testOffset = new TimeSpanType(0); + _internalOffset = new TimeSpanType(0); + } + + public override SteadyClockTimePoint GetTimePoint(KThread thread) + { + SteadyClockTimePoint result = new SteadyClockTimePoint + { + TimePoint = 0, + ClockSourceId = GetClockSourceId() + }; + + TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.ThreadState.CntpctEl0, thread.Context.ThreadState.CntfrqEl0); + + result.TimePoint = _setupValue + ticksTimeSpan.ToSeconds(); + + return result; + } + + public override TimeSpanType GetTestOffset() + { + return _testOffset; + } + + public override void SetTestOffset(TimeSpanType testOffset) + { + _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; + } + + public override void SetInternalOffset(TimeSpanType internalOffset) + { + _internalOffset = internalOffset; + } + + public override ResultCode GetSetupResultValue() + { + return _setupResultCode; + } + + public void ConfigureSetupValue() + { + int retry = 0; + + ResultCode result = ResultCode.Success; + + while (retry < 20) + { + result = (ResultCode)IRtcManager.GetExternalRtcValue(out ulong rtcValue); + + if (result == ResultCode.Success) + { + _setupValue = (long)rtcValue; + break; + } + + retry++; + } + + _setupResultCode = result; + } + } +} diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs index 00f296ad..c98b0064 100644 --- a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs @@ -8,22 +8,22 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock private StandardNetworkSystemClockCore _networkSystemClockCore; private bool _autoCorrectionEnabled; - private static StandardUserSystemClockCore instance; + private static StandardUserSystemClockCore _instance; public static StandardUserSystemClockCore Instance { get { - if (instance == null) + if (_instance == null) { - instance = new StandardUserSystemClockCore(StandardLocalSystemClockCore.Instance, StandardNetworkSystemClockCore.Instance); + _instance = new StandardUserSystemClockCore(StandardLocalSystemClockCore.Instance, StandardNetworkSystemClockCore.Instance); } - return instance; + return _instance; } } - public StandardUserSystemClockCore(StandardLocalSystemClockCore localSystemClockCore, StandardNetworkSystemClockCore networkSystemClockCore) + public StandardUserSystemClockCore(StandardLocalSystemClockCore localSystemClockCore, StandardNetworkSystemClockCore networkSystemClockCore) : base(localSystemClockCore.GetSteadyClockCore()) { _localSystemClockCore = localSystemClockCore; _networkSystemClockCore = networkSystemClockCore; @@ -35,11 +35,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock return ResultCode.NotImplemented; } - public override SteadyClockCore GetSteadyClockCore() - { - return _localSystemClockCore.GetSteadyClockCore(); - } - public override ResultCode GetSystemClockContext(KThread thread, out SystemClockContext context) { ResultCode result = ApplyAutomaticCorrection(thread, false); diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs index e661ab53..54d9accf 100644 --- a/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs @@ -1,54 +1,16 @@ using Ryujinx.HLE.HOS.Kernel.Threading; -using Ryujinx.HLE.HOS.Services.Bpc; using Ryujinx.HLE.Utilities; using System; namespace Ryujinx.HLE.HOS.Services.Time.Clock { - class SteadyClockCore + abstract class SteadyClockCore { - private long _setupValue; - private ResultCode _setupResultCode; - private bool _isRtcResetDetected; - private TimeSpanType _testOffset; - private TimeSpanType _internalOffset; - private UInt128 _clockSourceId; + private UInt128 _clockSourceId; - private static SteadyClockCore instance; - - public static SteadyClockCore Instance - { - get - { - if (instance == null) - { - instance = new SteadyClockCore(); - } - - return instance; - } - } - - private SteadyClockCore() - { - _testOffset = new TimeSpanType(0); - _internalOffset = new TimeSpanType(0); - _clockSourceId = new UInt128(Guid.NewGuid().ToByteArray()); - } - - private SteadyClockTimePoint GetTimePoint(KThread thread) + public SteadyClockCore() { - SteadyClockTimePoint result = new SteadyClockTimePoint - { - TimePoint = 0, - ClockSourceId = _clockSourceId - }; - - TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.ThreadState.CntpctEl0, thread.Context.ThreadState.CntfrqEl0); - - result.TimePoint = _setupValue + ticksTimeSpan.ToSeconds(); - - return result; + _clockSourceId = new UInt128(Guid.NewGuid().ToByteArray()); } public UInt128 GetClockSourceId() @@ -56,76 +18,45 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock return _clockSourceId; } - public SteadyClockTimePoint GetCurrentTimePoint(KThread thread) - { - SteadyClockTimePoint result = GetTimePoint(thread); - - result.TimePoint += _testOffset.ToSeconds(); - result.TimePoint += _internalOffset.ToSeconds(); - - return result; - } - - public TimeSpanType GetTestOffset() + public virtual TimeSpanType GetTestOffset() { - return _testOffset; + return new TimeSpanType(0); } - public void SetTestOffset(TimeSpanType testOffset) - { - _testOffset = testOffset; - } + public virtual void SetTestOffset(TimeSpanType testOffset) {} - public ResultCode GetRtcValue(out ulong rtcValue) + public virtual ResultCode GetRtcValue(out ulong rtcValue) { - return (ResultCode)IRtcManager.GetExternalRtcValue(out rtcValue); - } + rtcValue = 0; - public bool IsRtcResetDetected() - { - return _isRtcResetDetected; + return ResultCode.NotImplemented; } - public ResultCode GetSetupResultCode() + public virtual ResultCode GetSetupResultValue() { - return _setupResultCode; + return ResultCode.NotImplemented; } - public TimeSpanType GetInternalOffset() + public virtual TimeSpanType GetInternalOffset() { - return _internalOffset; + return new TimeSpanType(0); } - public void SetInternalOffset(TimeSpanType internalOffset) - { - _internalOffset = internalOffset; - } + public virtual void SetInternalOffset(TimeSpanType internalOffset) {} - public ResultCode GetSetupResultValue() + public virtual SteadyClockTimePoint GetTimePoint(KThread thread) { - return _setupResultCode; + throw new NotImplementedException(); } - public void ConfigureSetupValue() + public SteadyClockTimePoint GetCurrentTimePoint(KThread thread) { - int retry = 0; - - ResultCode result = ResultCode.Success; - - while (retry < 20) - { - result = (ResultCode)IRtcManager.GetExternalRtcValue(out ulong rtcValue); - - if (result == ResultCode.Success) - { - _setupValue = (long)rtcValue; - break; - } + SteadyClockTimePoint result = GetTimePoint(thread); - retry++; - } + result.TimePoint += GetTestOffset().ToSeconds(); + result.TimePoint += GetInternalOffset().ToSeconds(); - _setupResultCode = result; + return result; } } } diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs index d3a056e4..52f3c908 100644 --- a/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs @@ -4,11 +4,35 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock { abstract class SystemClockCore { - public abstract SteadyClockCore GetSteadyClockCore(); + private SteadyClockCore _steadyClockCore; + private SystemClockContext _context; - public abstract ResultCode GetSystemClockContext(KThread thread, out SystemClockContext context); + public SystemClockCore(SteadyClockCore steadyClockCore) + { + _steadyClockCore = steadyClockCore; + _context = new SystemClockContext(); + + _context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId(); + } - public abstract ResultCode SetSystemClockContext(SystemClockContext context); + public virtual SteadyClockCore GetSteadyClockCore() + { + return _steadyClockCore; + } + + public virtual ResultCode GetSystemClockContext(KThread thread, out SystemClockContext context) + { + context = _context; + + return ResultCode.Success; + } + + public virtual ResultCode SetSystemClockContext(SystemClockContext context) + { + _context = context; + + return ResultCode.Success; + } public abstract ResultCode Flush(SystemClockContext context); diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs new file mode 100644 index 00000000..7a69b014 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs @@ -0,0 +1,40 @@ +using Ryujinx.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; + +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 override SteadyClockTimePoint GetTimePoint(KThread thread) + { + SteadyClockTimePoint result = new SteadyClockTimePoint + { + TimePoint = 0, + ClockSourceId = GetClockSourceId() + }; + + TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.ThreadState.CntpctEl0, thread.Context.ThreadState.CntfrqEl0); + + result.TimePoint = ticksTimeSpan.ToSeconds(); + + return result; + } + } +} |
