Abstract SteadyClockCore to follow Nintendo changes in 4.x

This is the ground work for 4.0.0 support
This commit is contained in:
Thog 2019-07-22 20:53:25 +02:00
parent d254548548
commit 1d7d289c55
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
9 changed files with 161 additions and 127 deletions

View file

@ -199,7 +199,7 @@ namespace Ryujinx.HLE.HOS
// TODO: use set:sys (and set external clock source id from settings)
// TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate.
SteadyClockCore.Instance.ConfigureSetupValue();
StandardSteadyClockCore.Instance.ConfigureSetupValue();
if (Services.Set.NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes))
{

View file

@ -4,7 +4,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
class StandardLocalSystemClockCore : SystemClockCore
{
private SteadyClockCore _steadyClockCore;
private StandardSteadyClockCore _steadyClockCore;
private SystemClockContext _context;
private static StandardLocalSystemClockCore instance;
@ -15,14 +15,14 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
if (instance == null)
{
instance = new StandardLocalSystemClockCore(SteadyClockCore.Instance);
instance = new StandardLocalSystemClockCore(StandardSteadyClockCore.Instance);
}
return instance;
}
}
public StandardLocalSystemClockCore(SteadyClockCore steadyClockCore)
public StandardLocalSystemClockCore(StandardSteadyClockCore steadyClockCore)
{
_steadyClockCore = steadyClockCore;
_context = new SystemClockContext();
@ -37,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
return ResultCode.Success;
}
public override SteadyClockCore GetSteadyClockCore()
public override StandardSteadyClockCore GetSteadyClockCore()
{
return _steadyClockCore;
}

View file

@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
class StandardNetworkSystemClockCore : SystemClockCore
{
private SteadyClockCore _steadyClockCore;
private StandardSteadyClockCore _steadyClockCore;
private SystemClockContext _context;
private TimeSpanType _standardNetworkClockSufficientAccuracy;
@ -17,14 +17,14 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
if (instance == null)
{
instance = new StandardNetworkSystemClockCore(SteadyClockCore.Instance);
instance = new StandardNetworkSystemClockCore(StandardSteadyClockCore.Instance);
}
return instance;
}
}
public StandardNetworkSystemClockCore(SteadyClockCore steadyClockCore)
public StandardNetworkSystemClockCore(StandardSteadyClockCore steadyClockCore)
{
_steadyClockCore = steadyClockCore;
_context = new SystemClockContext();
@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
return ResultCode.Success;
}
public override SteadyClockCore GetSteadyClockCore()
public override StandardSteadyClockCore GetSteadyClockCore()
{
return _steadyClockCore;
}
@ -61,7 +61,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
public bool IsStandardNetworkSystemClockAccuracySufficient(KThread thread)
{
SteadyClockCore steadyClockCore = GetSteadyClockCore();
StandardSteadyClockCore steadyClockCore = GetSteadyClockCore();
SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(thread);
bool isStandardNetworkClockSufficientAccuracy = false;

View file

@ -0,0 +1,116 @@
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 StandardSteadyClockCore : SteadyClockCore
{
private long _setupValue;
private ResultCode _setupResultCode;
private bool _isRtcResetDetected;
private TimeSpanType _testOffset;
private TimeSpanType _internalOffset;
private UInt128 _clockSourceId;
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);
_clockSourceId = new UInt128(Guid.NewGuid().ToByteArray());
}
public override SteadyClockTimePoint GetTimePoint(KThread thread)
{
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;
}
public UInt128 GetClockSourceId()
{
return _clockSourceId;
}
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;
}
}
}

View file

@ -35,7 +35,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
return ResultCode.NotImplemented;
}
public override SteadyClockCore GetSteadyClockCore()
public override StandardSteadyClockCore GetSteadyClockCore()
{
return _localSystemClockCore.GetSteadyClockCore();
}

View file

@ -1,131 +1,49 @@
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 static SteadyClockCore instance;
public static SteadyClockCore Instance
public virtual TimeSpanType GetTestOffset()
{
get
{
if (instance == null)
{
instance = new SteadyClockCore();
}
return instance;
}
return new TimeSpanType(0);
}
private SteadyClockCore()
public virtual void SetTestOffset(TimeSpanType testOffset) {}
public virtual ResultCode GetRtcValue(out ulong rtcValue)
{
_testOffset = new TimeSpanType(0);
_internalOffset = new TimeSpanType(0);
_clockSourceId = new UInt128(Guid.NewGuid().ToByteArray());
rtcValue = 0;
return ResultCode.NotImplemented;
}
private SteadyClockTimePoint GetTimePoint(KThread thread)
public virtual ResultCode GetSetupResultValue()
{
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;
return ResultCode.NotImplemented;
}
public UInt128 GetClockSourceId()
public virtual TimeSpanType GetInternalOffset()
{
return _clockSourceId;
return new TimeSpanType(0);
}
public virtual void SetInternalOffset(TimeSpanType internalOffset) {}
public virtual SteadyClockTimePoint GetTimePoint(KThread thread)
{
throw new NotImplementedException();
}
public SteadyClockTimePoint GetCurrentTimePoint(KThread thread)
{
SteadyClockTimePoint result = GetTimePoint(thread);
result.TimePoint += _testOffset.ToSeconds();
result.TimePoint += _internalOffset.ToSeconds();
result.TimePoint += GetTestOffset().ToSeconds();
result.TimePoint += GetInternalOffset().ToSeconds();
return result;
}
public TimeSpanType GetTestOffset()
{
return _testOffset;
}
public void SetTestOffset(TimeSpanType testOffset)
{
_testOffset = testOffset;
}
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;
}
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;
}
}
}

View file

@ -4,7 +4,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
abstract class SystemClockCore
{
public abstract SteadyClockCore GetSteadyClockCore();
public abstract StandardSteadyClockCore GetSteadyClockCore();
public abstract ResultCode GetSystemClockContext(KThread thread, out SystemClockContext context);
@ -18,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
if (result == ResultCode.Success)
{
SteadyClockCore steadyClockCore = GetSteadyClockCore();
StandardSteadyClockCore steadyClockCore = GetSteadyClockCore();
SteadyClockTimePoint steadyClockTimePoint = steadyClockCore.GetCurrentTimePoint(thread);

View file

@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetCurrentTimePoint() -> nn::time::SteadyClockTimePoint
public ResultCode GetCurrentTimePoint(ServiceCtx context)
{
SteadyClockTimePoint currentTimePoint = SteadyClockCore.Instance.GetCurrentTimePoint(context.Thread);
SteadyClockTimePoint currentTimePoint = StandardSteadyClockCore.Instance.GetCurrentTimePoint(context.Thread);
context.ResponseData.WriteStruct(currentTimePoint);
@ -20,7 +20,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetTestOffset() -> nn::TimeSpanType
public ResultCode GetTestOffset(ServiceCtx context)
{
context.ResponseData.WriteStruct(SteadyClockCore.Instance.GetTestOffset());
context.ResponseData.WriteStruct(StandardSteadyClockCore.Instance.GetTestOffset());
return ResultCode.Success;
}
@ -31,7 +31,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
{
TimeSpanType testOffset = context.RequestData.ReadStruct<TimeSpanType>();
SteadyClockCore.Instance.SetTestOffset(testOffset);
StandardSteadyClockCore.Instance.SetTestOffset(testOffset);
return 0;
}
@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetRtcValue() -> u64
public ResultCode GetRtcValue(ServiceCtx context)
{
ResultCode result = SteadyClockCore.Instance.GetRtcValue(out ulong rtcValue);
ResultCode result = StandardSteadyClockCore.Instance.GetRtcValue(out ulong rtcValue);
if (result == ResultCode.Success)
{
@ -54,7 +54,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// IsRtcResetDetected() -> bool
public ResultCode IsRtcResetDetected(ServiceCtx context)
{
context.ResponseData.Write(SteadyClockCore.Instance.IsRtcResetDetected());
context.ResponseData.Write(StandardSteadyClockCore.Instance.IsRtcResetDetected());
return ResultCode.Success;
}
@ -63,7 +63,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetSetupResultValue() -> u32
public ResultCode GetSetupResultValue(ServiceCtx context)
{
context.ResponseData.Write((uint)SteadyClockCore.Instance.GetSetupResultCode());
context.ResponseData.Write((uint)StandardSteadyClockCore.Instance.GetSetupResultValue());
return ResultCode.Success;
}
@ -72,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetInternalOffset() -> nn::TimeSpanType
public ResultCode GetInternalOffset(ServiceCtx context)
{
context.ResponseData.WriteStruct(SteadyClockCore.Instance.GetInternalOffset());
context.ResponseData.WriteStruct(StandardSteadyClockCore.Instance.GetInternalOffset());
return ResultCode.Success;
}
@ -83,7 +83,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
{
TimeSpanType internalOffset = context.RequestData.ReadStruct<TimeSpanType>();
SteadyClockCore.Instance.SetInternalOffset(internalOffset);
StandardSteadyClockCore.Instance.SetInternalOffset(internalOffset);
return ResultCode.Success;
}

View file

@ -18,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetCurrentTime() -> nn::time::PosixTime
public ResultCode GetCurrentTime(ServiceCtx context)
{
SteadyClockCore steadyClockCore = _clockCore.GetSteadyClockCore();
StandardSteadyClockCore steadyClockCore = _clockCore.GetSteadyClockCore();
SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(context.Thread);
ResultCode result = _clockCore.GetSystemClockContext(context.Thread, out SystemClockContext clockContext);
@ -50,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
}
long posixTime = context.RequestData.ReadInt64();
SteadyClockCore steadyClockCore = _clockCore.GetSteadyClockCore();
StandardSteadyClockCore steadyClockCore = _clockCore.GetSteadyClockCore();
SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(context.Thread);
SystemClockContext clockContext = new SystemClockContext()