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:
Thog 2019-09-28 21:43:52 +02:00
parent ecafff7ff9
commit 26b4aad831
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
12 changed files with 280 additions and 110 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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)
{

View file

@ -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;
}
}*/
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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,

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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
}
}