aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services/Time/Clock
diff options
context:
space:
mode:
authorThomas Guillemard <me@thog.eu>2019-07-15 19:52:35 +0200
committerAc_K <Acoustik666@gmail.com>2019-07-15 19:52:35 +0200
commit1f3a34dd7a5977fc340de310b2109493e5e6973f (patch)
tree95b6e42b3e99fec08b1c361fe8fb82510471514d /Ryujinx.HLE/HOS/Services/Time/Clock
parentd8424a63c637f0636e301252b2b8a1fb90f2457d (diff)
Implement time:* 2.0.0 & 3.0.0 commands (#735)
* Finish ISteadyClock implementation * Implement IsStandardNetworkSystemClockAccuracySufficient Also use signed values for offsets and TimeSpanType * Address comments * Fix one missing nit and improve one comment
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Time/Clock')
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/ClockTypes.cs34
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs27
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs51
3 files changed, 101 insertions, 11 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/ClockTypes.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/ClockTypes.cs
index 1e527c00..860f5ad2 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/ClockTypes.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/ClockTypes.cs
@@ -1,4 +1,5 @@
using Ryujinx.HLE.Utilities;
+using System;
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Time.Clock
@@ -6,35 +7,56 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
[StructLayout(LayoutKind.Sequential)]
struct TimeSpanType
{
- public ulong NanoSeconds;
+ public long NanoSeconds;
- public TimeSpanType(ulong nanoSeconds)
+ public TimeSpanType(long nanoSeconds)
{
NanoSeconds = nanoSeconds;
}
- public ulong ToSeconds()
+ public long ToSeconds()
{
return NanoSeconds / 1000000000;
}
public static TimeSpanType FromTicks(ulong ticks, ulong frequency)
{
- return new TimeSpanType(ticks * 1000000000 / frequency);
+ return new TimeSpanType((long)ticks * 1000000000 / (long)frequency);
}
}
[StructLayout(LayoutKind.Sequential)]
struct SteadyClockTimePoint
{
- public ulong TimePoint;
+ public long TimePoint;
public UInt128 ClockSourceId;
+
+ public ResultCode GetSpanBetween(SteadyClockTimePoint other, out long outSpan)
+ {
+ outSpan = 0;
+
+ if (ClockSourceId == other.ClockSourceId)
+ {
+ try
+ {
+ outSpan = checked(other.TimePoint - TimePoint);
+
+ return ResultCode.Success;
+ }
+ catch (OverflowException)
+ {
+ return ResultCode.Overflow;
+ }
+ }
+
+ return ResultCode.Overflow;
+ }
}
[StructLayout(LayoutKind.Sequential)]
struct SystemClockContext
{
- public ulong Offset;
+ public long Offset;
public SteadyClockTimePoint SteadyTimePoint;
}
}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs
index 59bc822c..c00f460e 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs
@@ -1,4 +1,5 @@
-using Ryujinx.HLE.HOS.Kernel.Threading;
+using System;
+using Ryujinx.HLE.HOS.Kernel.Threading;
namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
@@ -6,6 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
private SteadyClockCore _steadyClockCore;
private SystemClockContext _context;
+ private TimeSpanType _standardNetworkClockSufficientAccuracy;
private static StandardNetworkSystemClockCore instance;
@@ -27,7 +29,8 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
_steadyClockCore = steadyClockCore;
_context = new SystemClockContext();
- _context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId();
+ _context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId();
+ _standardNetworkClockSufficientAccuracy = new TimeSpanType(0);
}
public override ResultCode Flush(SystemClockContext context)
@@ -55,5 +58,25 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
return ResultCode.Success;
}
+
+ public bool IsStandardNetworkSystemClockAccuracySufficient(KThread thread)
+ {
+ SteadyClockCore steadyClockCore = GetSteadyClockCore();
+ SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(thread);
+
+ bool isStandardNetworkClockSufficientAccuracy = false;
+
+ if (_context.SteadyTimePoint.GetSpanBetween(currentTimePoint, out long outSpan) == ResultCode.Success)
+ {
+ isStandardNetworkClockSufficientAccuracy = outSpan * 1000000000 < _standardNetworkClockSufficientAccuracy.NanoSeconds;
+ }
+
+ return isStandardNetworkClockSufficientAccuracy;
+ }
+
+ public void SetStandardNetworkClockSufficientAccuracy(TimeSpanType standardNetworkClockSufficientAccuracy)
+ {
+ _standardNetworkClockSufficientAccuracy = standardNetworkClockSufficientAccuracy;
+ }
}
}
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs
index b69b7d3c..e661ab53 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs
@@ -1,4 +1,5 @@
using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.HLE.HOS.Services.Bpc;
using Ryujinx.HLE.Utilities;
using System;
@@ -6,6 +7,9 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
class SteadyClockCore
{
+ private long _setupValue;
+ private ResultCode _setupResultCode;
+ private bool _isRtcResetDetected;
private TimeSpanType _testOffset;
private TimeSpanType _internalOffset;
private UInt128 _clockSourceId;
@@ -42,7 +46,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.ThreadState.CntpctEl0, thread.Context.ThreadState.CntfrqEl0);
- result.TimePoint = _internalOffset.ToSeconds() + ticksTimeSpan.ToSeconds();
+ result.TimePoint = _setupValue + ticksTimeSpan.ToSeconds();
return result;
}
@@ -57,6 +61,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
SteadyClockTimePoint result = GetTimePoint(thread);
result.TimePoint += _testOffset.ToSeconds();
+ result.TimePoint += _internalOffset.ToSeconds();
return result;
}
@@ -71,16 +76,56 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
_testOffset = testOffset;
}
- // TODO: check if this is accurate
+ public ResultCode GetRtcValue(out ulong rtcValue)
+ {
+ return (ResultCode)IRtcManager.GetExternalRtcValue(out rtcValue);
+ }
+
+ public bool IsRtcResetDetected()
+ {
+ return _isRtcResetDetected;
+ }
+
+ public ResultCode GetSetupResultCode()
+ {
+ return _setupResultCode;
+ }
+
public TimeSpanType GetInternalOffset()
{
return _internalOffset;
}
- // TODO: check if this is accurate
public void SetInternalOffset(TimeSpanType internalOffset)
{
_internalOffset = internalOffset;
}
+
+ public 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;
+ }
}
}