Update ClockCore logics to 9.0.0
Also apply 9.0.0 permissions and comment time:u, and time:a (as those are going to be moved)
This commit is contained in:
parent
ecafff7ff9
commit
26b4aad831
12 changed files with 280 additions and 110 deletions
|
@ -19,7 +19,7 @@
|
|||
|
||||
public EphemeralNetworkSystemClockCore(SteadyClockCore steadyClockCore) : base(steadyClockCore) { }
|
||||
|
||||
public override ResultCode Flush(SystemClockContext context)
|
||||
protected override ResultCode Flush(SystemClockContext context)
|
||||
{
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
public StandardLocalSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) {}
|
||||
|
||||
public override ResultCode Flush(SystemClockContext context)
|
||||
protected override ResultCode Flush(SystemClockContext context)
|
||||
{
|
||||
// TODO: set:sys SetUserSystemClockContext
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
_standardNetworkClockSufficientAccuracy = new TimeSpanType(0);
|
||||
}
|
||||
|
||||
public override ResultCode Flush(SystemClockContext context)
|
||||
protected override ResultCode Flush(SystemClockContext context)
|
||||
{
|
||||
// TODO: set:sys SetNetworkSystemClockContext
|
||||
|
||||
|
@ -40,7 +40,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)
|
||||
{
|
||||
|
|
|
@ -5,11 +5,12 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
{
|
||||
class StandardSteadyClockCore : SteadyClockCore
|
||||
{
|
||||
private long _setupValue;
|
||||
private ResultCode _setupResultCode;
|
||||
private bool _isRtcResetDetected;
|
||||
private TimeSpanType _setupValue;
|
||||
// TODO: move this to glue when we will have psc fully done
|
||||
//private ResultCode _setupResultCode;
|
||||
private TimeSpanType _testOffset;
|
||||
private TimeSpanType _internalOffset;
|
||||
private TimeSpanType _cachedRawTimePoint;
|
||||
|
||||
private static StandardSteadyClockCore _instance;
|
||||
|
||||
|
@ -28,22 +29,20 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
|
||||
private StandardSteadyClockCore()
|
||||
{
|
||||
_testOffset = new TimeSpanType(0);
|
||||
_internalOffset = new TimeSpanType(0);
|
||||
_setupValue = new TimeSpanType(0);
|
||||
_testOffset = new TimeSpanType(0);
|
||||
_internalOffset = new TimeSpanType(0);
|
||||
_cachedRawTimePoint = new TimeSpanType(0);
|
||||
}
|
||||
|
||||
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 +56,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,12 +66,24 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
_internalOffset = internalOffset;
|
||||
}
|
||||
|
||||
public override ResultCode GetSetupResultValue()
|
||||
public override TimeSpanType GetCurrentRawTimePoint(KThread thread)
|
||||
{
|
||||
return _setupResultCode;
|
||||
TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.CntpctEl0, thread.Context.CntfrqEl0);
|
||||
|
||||
TimeSpanType rawTimePoint = new TimeSpanType(_setupValue.NanoSeconds + ticksTimeSpan.NanoSeconds);
|
||||
|
||||
if (rawTimePoint.NanoSeconds < _cachedRawTimePoint.NanoSeconds)
|
||||
{
|
||||
rawTimePoint.NanoSeconds = _cachedRawTimePoint.NanoSeconds;
|
||||
}
|
||||
|
||||
_cachedRawTimePoint = rawTimePoint;
|
||||
|
||||
return rawTimePoint;
|
||||
}
|
||||
|
||||
public void ConfigureSetupValue()
|
||||
// TODO: move this to glue when we will have psc fully done
|
||||
/*public void ConfigureSetupValue()
|
||||
{
|
||||
int retry = 0;
|
||||
|
||||
|
@ -94,7 +95,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
|
||||
if (result == ResultCode.Success)
|
||||
{
|
||||
_setupValue = (long)rtcValue;
|
||||
_setupValue = TimeSpanType.FromSeconds((long)rtcValue);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -102,6 +103,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
}
|
||||
|
||||
_setupResultCode = result;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,12 +30,12 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
_autoCorrectionEnabled = false;
|
||||
}
|
||||
|
||||
public override ResultCode Flush(SystemClockContext context)
|
||||
protected override ResultCode Flush(SystemClockContext context)
|
||||
{
|
||||
return ResultCode.NotImplemented;
|
||||
}
|
||||
|
||||
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 +43,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,11 +60,11 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
@ -32,9 +36,14 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
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 +58,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 +74,15 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool IsInitialized()
|
||||
{
|
||||
return _isInitialized;
|
||||
}
|
||||
|
||||
public void MarkInitialized()
|
||||
{
|
||||
_isInitialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
{
|
||||
private SteadyClockCore _steadyClockCore;
|
||||
private SystemClockContext _context;
|
||||
private bool _isInitialized;
|
||||
|
||||
public SystemClockCore(SteadyClockCore steadyClockCore)
|
||||
{
|
||||
_steadyClockCore = steadyClockCore;
|
||||
_context = new SystemClockContext();
|
||||
_isInitialized = false;
|
||||
|
||||
_context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId();
|
||||
}
|
||||
|
@ -20,31 +22,94 @@ 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 abstract ResultCode Flush(SystemClockContext context);
|
||||
|
||||
public bool IsClockSetup(KThread thread)
|
||||
public ResultCode SetSystemClockContext(SystemClockContext context)
|
||||
{
|
||||
ResultCode result = GetSystemClockContext(thread, out 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;
|
||||
}
|
||||
|
|
|
@ -12,10 +12,10 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace Ryujinx.HLE.HOS.Services.Time
|
||||
{
|
||||
[Service("time:a", TimePermissions.Applet)]
|
||||
//[Service("time:a", TimePermissions.Admin)]
|
||||
[Service("time:s", TimePermissions.System)]
|
||||
[Service("time:u", TimePermissions.User)]
|
||||
[Service("time:su", TimePermissions.System)] // 9.0.0+ - TODO: Fix the permission.
|
||||
//[Service("time:u", TimePermissions.User)]
|
||||
[Service("time:su", TimePermissions.System)]
|
||||
class IStaticService : IpcService
|
||||
{
|
||||
private TimePermissions _permissions;
|
||||
|
@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
// GetStandardUserSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
||||
public ResultCode GetStandardUserSystemClock(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ISystemClock(StandardUserSystemClockCore.Instance, (_permissions & TimePermissions.UserSystemClockWritableMask) != 0));
|
||||
MakeObject(context, new ISystemClock(StandardUserSystemClockCore.Instance, (_permissions & TimePermissions.UserSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
// GetStandardNetworkSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
||||
public ResultCode GetStandardNetworkSystemClock(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ISystemClock(StandardNetworkSystemClockCore.Instance, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0));
|
||||
MakeObject(context, new ISystemClock(StandardNetworkSystemClockCore.Instance, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
// GetStandardSteadyClock() -> object<nn::timesrv::detail::service::ISteadyClock>
|
||||
public ResultCode GetStandardSteadyClock(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ISteadyClock());
|
||||
MakeObject(context, new ISteadyClock(StandardSteadyClockCore.Instance, (_permissions & TimePermissions.SteadyClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
// GetStandardLocalSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
||||
public ResultCode GetStandardLocalSystemClock(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ISystemClock(StandardLocalSystemClockCore.Instance, (_permissions & TimePermissions.LocalSystemClockWritableMask) != 0));
|
||||
MakeObject(context, new ISystemClock(StandardLocalSystemClockCore.Instance, (_permissions & TimePermissions.LocalSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
// GetEphemeralNetworkSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
||||
public ResultCode GetEphemeralNetworkSystemClock(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ISystemClock(StandardNetworkSystemClockCore.Instance, false));
|
||||
MakeObject(context, new ISystemClock(StandardNetworkSystemClockCore.Instance, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -104,7 +104,14 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
// IsStandardUserSystemClockAutomaticCorrectionEnabled() -> bool
|
||||
public ResultCode IsStandardUserSystemClockAutomaticCorrectionEnabled(ServiceCtx context)
|
||||
{
|
||||
context.ResponseData.Write(StandardUserSystemClockCore.Instance.IsAutomaticCorrectionEnabled());
|
||||
StandardUserSystemClockCore userClock = StandardUserSystemClockCore.Instance;
|
||||
|
||||
if (!userClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
context.ResponseData.Write(userClock.IsAutomaticCorrectionEnabled());
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -113,6 +120,14 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
// SetStandardUserSystemClockAutomaticCorrectionEnabled(b8)
|
||||
public ResultCode SetStandardUserSystemClockAutomaticCorrectionEnabled(ServiceCtx context)
|
||||
{
|
||||
SteadyClockCore steadyClock = StandardSteadyClockCore.Instance;
|
||||
StandardUserSystemClockCore userClock = StandardUserSystemClockCore.Instance;
|
||||
|
||||
if (!userClock.IsInitialized() || !steadyClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
if ((_permissions & TimePermissions.UserSystemClockWritableMask) == 0)
|
||||
{
|
||||
return ResultCode.PermissionDenied;
|
||||
|
@ -136,8 +151,15 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
// CalculateMonotonicSystemClockBaseTimePoint(nn::time::SystemClockContext) -> s64
|
||||
public ResultCode CalculateMonotonicSystemClockBaseTimePoint(ServiceCtx context)
|
||||
{
|
||||
SteadyClockCore steadyClock = StandardSteadyClockCore.Instance;
|
||||
|
||||
if (!steadyClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
SystemClockContext otherContext = context.RequestData.ReadStruct<SystemClockContext>();
|
||||
SteadyClockTimePoint currentTimePoint = StandardSteadyClockCore.Instance.GetCurrentTimePoint(context.Thread);
|
||||
SteadyClockTimePoint currentTimePoint = steadyClock.GetCurrentTimePoint(context.Thread);
|
||||
|
||||
ResultCode result = ResultCode.TimeMismatch;
|
||||
|
||||
|
@ -160,11 +182,11 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
{
|
||||
byte type = context.RequestData.ReadByte();
|
||||
|
||||
ResultCode result = StandardUserSystemClockCore.Instance.GetSystemClockContext(context.Thread, out SystemClockContext userContext);
|
||||
ResultCode result = StandardUserSystemClockCore.Instance.GetClockContext(context.Thread, out SystemClockContext userContext);
|
||||
|
||||
if (result == ResultCode.Success)
|
||||
{
|
||||
result = StandardNetworkSystemClockCore.Instance.GetSystemClockContext(context.Thread, out SystemClockContext networkContext);
|
||||
result = StandardNetworkSystemClockCore.Instance.GetClockContext(context.Thread, out SystemClockContext networkContext);
|
||||
|
||||
if (result == ResultCode.Success)
|
||||
{
|
||||
|
@ -205,7 +227,6 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
// CalculateStandardUserSystemClockDifferenceByUser(buffer<nn::time::sf::ClockSnapshot, 0x19>, buffer<nn::time::sf::ClockSnapshot, 0x19>) -> nn::TimeSpanType
|
||||
public ResultCode CalculateStandardUserSystemClockDifferenceByUser(ServiceCtx context)
|
||||
{
|
||||
|
||||
ClockSnapshot clockSnapshotA = ReadClockSnapshotFromBuffer(context, context.Request.ExchangeBuff[0]);
|
||||
ClockSnapshot clockSnapshotB = ReadClockSnapshotFromBuffer(context, context.Request.ExchangeBuff[1]);
|
||||
TimeSpanType difference = TimeSpanType.FromSeconds(clockSnapshotB.UserContext.Offset - clockSnapshotA.UserContext.Offset);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
PermissionDenied = (1 << ErrorCodeShift) | ModuleId,
|
||||
TimeMismatch = (102 << ErrorCodeShift) | ModuleId,
|
||||
UninitializedClock = (103 << ErrorCodeShift) | ModuleId,
|
||||
TimeNotFound = (200 << ErrorCodeShift) | ModuleId,
|
||||
Overflow = (201 << ErrorCodeShift) | ModuleId,
|
||||
LocationNameTooLong = (801 << ErrorCodeShift) | ModuleId,
|
||||
|
|
|
@ -5,11 +5,27 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
{
|
||||
class ISteadyClock : IpcService
|
||||
{
|
||||
private SteadyClockCore _steadyClock;
|
||||
private bool _writePermission;
|
||||
private bool _bypassUninitializedClock;
|
||||
|
||||
public ISteadyClock(SteadyClockCore steadyClock, bool writePermission, bool bypassUninitializedClock)
|
||||
{
|
||||
_steadyClock = steadyClock;
|
||||
_writePermission = writePermission;
|
||||
_bypassUninitializedClock = bypassUninitializedClock;
|
||||
}
|
||||
|
||||
[Command(0)]
|
||||
// GetCurrentTimePoint() -> nn::time::SteadyClockTimePoint
|
||||
public ResultCode GetCurrentTimePoint(ServiceCtx context)
|
||||
{
|
||||
SteadyClockTimePoint currentTimePoint = StandardSteadyClockCore.Instance.GetCurrentTimePoint(context.Thread);
|
||||
if (!_bypassUninitializedClock && !_steadyClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
SteadyClockTimePoint currentTimePoint = _steadyClock.GetCurrentTimePoint(context.Thread);
|
||||
|
||||
context.ResponseData.WriteStruct(currentTimePoint);
|
||||
|
||||
|
@ -20,7 +36,12 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
// GetTestOffset() -> nn::TimeSpanType
|
||||
public ResultCode GetTestOffset(ServiceCtx context)
|
||||
{
|
||||
context.ResponseData.WriteStruct(StandardSteadyClockCore.Instance.GetTestOffset());
|
||||
if (!_bypassUninitializedClock && !_steadyClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
context.ResponseData.WriteStruct(_steadyClock.GetTestOffset());
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -29,18 +50,33 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
// SetTestOffset(nn::TimeSpanType)
|
||||
public ResultCode SetTestOffset(ServiceCtx context)
|
||||
{
|
||||
if (!_writePermission)
|
||||
{
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
if (!_bypassUninitializedClock && !_steadyClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
TimeSpanType testOffset = context.RequestData.ReadStruct<TimeSpanType>();
|
||||
|
||||
StandardSteadyClockCore.Instance.SetTestOffset(testOffset);
|
||||
_steadyClock.SetTestOffset(testOffset);
|
||||
|
||||
return 0;
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[Command(100)] // 2.0.0+
|
||||
// GetRtcValue() -> u64
|
||||
public ResultCode GetRtcValue(ServiceCtx context)
|
||||
{
|
||||
ResultCode result = StandardSteadyClockCore.Instance.GetRtcValue(out ulong rtcValue);
|
||||
if (!_bypassUninitializedClock && !_steadyClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
ResultCode result = _steadyClock.GetRtcValue(out ulong rtcValue);
|
||||
|
||||
if (result == ResultCode.Success)
|
||||
{
|
||||
|
@ -54,7 +90,12 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
// IsRtcResetDetected() -> bool
|
||||
public ResultCode IsRtcResetDetected(ServiceCtx context)
|
||||
{
|
||||
context.ResponseData.Write(StandardSteadyClockCore.Instance.IsRtcResetDetected());
|
||||
if (!_bypassUninitializedClock && !_steadyClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
context.ResponseData.Write(_steadyClock.IsRtcResetDetected());
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -63,7 +104,12 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
// GetSetupResultValue() -> u32
|
||||
public ResultCode GetSetupResultValue(ServiceCtx context)
|
||||
{
|
||||
context.ResponseData.Write((uint)StandardSteadyClockCore.Instance.GetSetupResultValue());
|
||||
if (!_bypassUninitializedClock && !_steadyClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
context.ResponseData.Write((uint)_steadyClock.GetSetupResultValue());
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -72,7 +118,12 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
// GetInternalOffset() -> nn::TimeSpanType
|
||||
public ResultCode GetInternalOffset(ServiceCtx context)
|
||||
{
|
||||
context.ResponseData.WriteStruct(StandardSteadyClockCore.Instance.GetInternalOffset());
|
||||
if (!_bypassUninitializedClock && !_steadyClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
context.ResponseData.WriteStruct(_steadyClock.GetInternalOffset());
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -81,9 +132,19 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
// SetInternalOffset(nn::TimeSpanType)
|
||||
public ResultCode SetInternalOffset(ServiceCtx context)
|
||||
{
|
||||
if (!_writePermission)
|
||||
{
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
if (!_bypassUninitializedClock && !_steadyClock.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
TimeSpanType internalOffset = context.RequestData.ReadStruct<TimeSpanType>();
|
||||
|
||||
StandardSteadyClockCore.Instance.SetInternalOffset(internalOffset);
|
||||
_steadyClock.SetInternalOffset(internalOffset);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
|
|
@ -7,34 +7,29 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
{
|
||||
private SystemClockCore _clockCore;
|
||||
private bool _writePermission;
|
||||
private bool _bypassUninitializedClock;
|
||||
|
||||
public ISystemClock(SystemClockCore clockCore, bool writePermission)
|
||||
public ISystemClock(SystemClockCore clockCore, bool writePermission, bool bypassUninitializedCloc)
|
||||
{
|
||||
_clockCore = clockCore;
|
||||
_writePermission = writePermission;
|
||||
_clockCore = clockCore;
|
||||
_writePermission = writePermission;
|
||||
_bypassUninitializedClock = bypassUninitializedCloc;
|
||||
}
|
||||
|
||||
[Command(0)]
|
||||
// GetCurrentTime() -> nn::time::PosixTime
|
||||
public ResultCode GetCurrentTime(ServiceCtx context)
|
||||
{
|
||||
SteadyClockCore steadyClockCore = _clockCore.GetSteadyClockCore();
|
||||
SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(context.Thread);
|
||||
if (!_bypassUninitializedClock && !_clockCore.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
ResultCode result = _clockCore.GetSystemClockContext(context.Thread, out SystemClockContext clockContext);
|
||||
ResultCode result = _clockCore.GetCurrentTime(context.Thread, out long posixTime);
|
||||
|
||||
if (result == ResultCode.Success)
|
||||
{
|
||||
result = ResultCode.TimeMismatch;
|
||||
|
||||
if (currentTimePoint.ClockSourceId == clockContext.SteadyTimePoint.ClockSourceId)
|
||||
{
|
||||
long posixTime = clockContext.Offset + currentTimePoint.TimePoint;
|
||||
|
||||
context.ResponseData.Write(posixTime);
|
||||
|
||||
result = 0;
|
||||
}
|
||||
context.ResponseData.Write(posixTime);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -49,31 +44,26 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
long posixTime = context.RequestData.ReadInt64();
|
||||
SteadyClockCore steadyClockCore = _clockCore.GetSteadyClockCore();
|
||||
SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(context.Thread);
|
||||
|
||||
SystemClockContext clockContext = new SystemClockContext()
|
||||
if (!_bypassUninitializedClock && !_clockCore.IsInitialized())
|
||||
{
|
||||
Offset = posixTime - currentTimePoint.TimePoint,
|
||||
SteadyTimePoint = currentTimePoint
|
||||
};
|
||||
|
||||
ResultCode result = _clockCore.SetSystemClockContext(clockContext);
|
||||
|
||||
if (result == ResultCode.Success)
|
||||
{
|
||||
result = _clockCore.Flush(clockContext);
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
return result;
|
||||
long posixTime = context.RequestData.ReadInt64();
|
||||
|
||||
return _clockCore.SetCurrentTime(context.Thread, posixTime);
|
||||
}
|
||||
|
||||
[Command(2)]
|
||||
// GetSystemClockContext() -> nn::time::SystemClockContext
|
||||
// GetClockContext() -> nn::time::SystemClockContext
|
||||
public ResultCode GetSystemClockContext(ServiceCtx context)
|
||||
{
|
||||
ResultCode result = _clockCore.GetSystemClockContext(context.Thread, out SystemClockContext clockContext);
|
||||
if (!_bypassUninitializedClock && !_clockCore.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
ResultCode result = _clockCore.GetClockContext(context.Thread, out SystemClockContext clockContext);
|
||||
|
||||
if (result == ResultCode.Success)
|
||||
{
|
||||
|
@ -84,7 +74,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
}
|
||||
|
||||
[Command(3)]
|
||||
// SetSystemClockContext(nn::time::SystemClockContext)
|
||||
// SetClockContext(nn::time::SystemClockContext)
|
||||
public ResultCode SetSystemClockContext(ServiceCtx context)
|
||||
{
|
||||
if (!_writePermission)
|
||||
|
@ -92,15 +82,15 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
|||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
if (!_bypassUninitializedClock && !_clockCore.IsInitialized())
|
||||
{
|
||||
return ResultCode.UninitializedClock;
|
||||
}
|
||||
|
||||
SystemClockContext clockContext = context.RequestData.ReadStruct<SystemClockContext>();
|
||||
|
||||
ResultCode result = _clockCore.SetSystemClockContext(clockContext);
|
||||
|
||||
if (result == ResultCode.Success)
|
||||
{
|
||||
result = _clockCore.Flush(clockContext);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,15 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
LocalSystemClockWritableMask = 0x1,
|
||||
UserSystemClockWritableMask = 0x2,
|
||||
NetworkSystemClockWritableMask = 0x4,
|
||||
UnknownPermissionMask = 0x8,
|
||||
TimeZoneWritableMask = 0x8,
|
||||
SteadyClockWritableMask = 0x10,
|
||||
BypassUninitialized = 0x20,
|
||||
|
||||
User = 0,
|
||||
Applet = LocalSystemClockWritableMask | UserSystemClockWritableMask | UnknownPermissionMask,
|
||||
System = NetworkSystemClockWritableMask
|
||||
User = 0,
|
||||
Admin = LocalSystemClockWritableMask | UserSystemClockWritableMask | TimeZoneWritableMask,
|
||||
System = NetworkSystemClockWritableMask,
|
||||
SystemUpdate = BypassUninitialized,
|
||||
Repair = SteadyClockWritableMask,
|
||||
Manufacture = LocalSystemClockWritableMask | UserSystemClockWritableMask | NetworkSystemClockWritableMask | TimeZoneWritableMask | SteadyClockWritableMask
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue