|
@@ -1,97 +1,107 @@
|
|
|
-using System;
|
|
|
|
|
|
|
+using Ryujinx.Common;
|
|
|
|
|
+using Ryujinx.HLE.HOS.Services.Time.Clock;
|
|
|
|
|
|
|
|
namespace Ryujinx.HLE.HOS.Services.Time
|
|
namespace Ryujinx.HLE.HOS.Services.Time
|
|
|
{
|
|
{
|
|
|
class ISystemClock : IpcService
|
|
class ISystemClock : IpcService
|
|
|
{
|
|
{
|
|
|
- private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
|
|
|
|
|
|
+ private SystemClockCore _clockCore;
|
|
|
|
|
+ private bool _writePermission;
|
|
|
|
|
|
|
|
- private SystemClockType _clockType;
|
|
|
|
|
- private DateTime _systemClockContextEpoch;
|
|
|
|
|
- private long _systemClockTimePoint;
|
|
|
|
|
- private byte[] _systemClockContextEnding;
|
|
|
|
|
- private long _timeOffset;
|
|
|
|
|
-
|
|
|
|
|
- public ISystemClock(SystemClockType clockType)
|
|
|
|
|
|
|
+ public ISystemClock(SystemClockCore clockCore, bool writePermission)
|
|
|
{
|
|
{
|
|
|
- _clockType = clockType;
|
|
|
|
|
- _systemClockContextEpoch = System.Diagnostics.Process.GetCurrentProcess().StartTime;
|
|
|
|
|
- _systemClockContextEnding = new byte[0x10];
|
|
|
|
|
- _timeOffset = 0;
|
|
|
|
|
-
|
|
|
|
|
- if (clockType == SystemClockType.User ||
|
|
|
|
|
- clockType == SystemClockType.Network)
|
|
|
|
|
- {
|
|
|
|
|
- _systemClockContextEpoch = _systemClockContextEpoch.ToUniversalTime();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- _systemClockTimePoint = (long)(_systemClockContextEpoch - Epoch).TotalSeconds;
|
|
|
|
|
|
|
+ _clockCore = clockCore;
|
|
|
|
|
+ _writePermission = writePermission;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
[Command(0)]
|
|
[Command(0)]
|
|
|
// GetCurrentTime() -> nn::time::PosixTime
|
|
// GetCurrentTime() -> nn::time::PosixTime
|
|
|
public ResultCode GetCurrentTime(ServiceCtx context)
|
|
public ResultCode GetCurrentTime(ServiceCtx context)
|
|
|
{
|
|
{
|
|
|
- DateTime currentTime = DateTime.Now;
|
|
|
|
|
|
|
+ SteadyClockCore steadyClockCore = _clockCore.GetSteadyClockCore();
|
|
|
|
|
+ SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(context.Thread);
|
|
|
|
|
+
|
|
|
|
|
+ ResultCode result = _clockCore.GetSystemClockContext(context.Thread, out SystemClockContext clockContext);
|
|
|
|
|
|
|
|
- if (_clockType == SystemClockType.User ||
|
|
|
|
|
- _clockType == SystemClockType.Network)
|
|
|
|
|
|
|
+ if (result == ResultCode.Success)
|
|
|
{
|
|
{
|
|
|
- currentTime = currentTime.ToUniversalTime();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ result = ResultCode.TimeMismatch;
|
|
|
|
|
+
|
|
|
|
|
+ if (currentTimePoint.ClockSourceId == clockContext.SteadyTimePoint.ClockSourceId)
|
|
|
|
|
+ {
|
|
|
|
|
+ ulong posixTime = clockContext.Offset + currentTimePoint.TimePoint;
|
|
|
|
|
+
|
|
|
|
|
+ context.ResponseData.Write(posixTime);
|
|
|
|
|
|
|
|
- context.ResponseData.Write((long)((currentTime - Epoch).TotalSeconds) + _timeOffset);
|
|
|
|
|
|
|
+ result = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return ResultCode.Success;
|
|
|
|
|
|
|
+ return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
[Command(1)]
|
|
[Command(1)]
|
|
|
// SetCurrentTime(nn::time::PosixTime)
|
|
// SetCurrentTime(nn::time::PosixTime)
|
|
|
public ResultCode SetCurrentTime(ServiceCtx context)
|
|
public ResultCode SetCurrentTime(ServiceCtx context)
|
|
|
{
|
|
{
|
|
|
- DateTime currentTime = DateTime.Now;
|
|
|
|
|
-
|
|
|
|
|
- if (_clockType == SystemClockType.User ||
|
|
|
|
|
- _clockType == SystemClockType.Network)
|
|
|
|
|
|
|
+ if (!_writePermission)
|
|
|
{
|
|
{
|
|
|
- currentTime = currentTime.ToUniversalTime();
|
|
|
|
|
|
|
+ return ResultCode.PermissionDenied;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- _timeOffset = (context.RequestData.ReadInt64() - (long)(currentTime - Epoch).TotalSeconds);
|
|
|
|
|
|
|
+ ulong posixTime = context.RequestData.ReadUInt64();
|
|
|
|
|
+ SteadyClockCore steadyClockCore = _clockCore.GetSteadyClockCore();
|
|
|
|
|
+ SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(context.Thread);
|
|
|
|
|
+
|
|
|
|
|
+ SystemClockContext clockContext = new SystemClockContext()
|
|
|
|
|
+ {
|
|
|
|
|
+ Offset = posixTime - currentTimePoint.TimePoint,
|
|
|
|
|
+ SteadyTimePoint = currentTimePoint
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ ResultCode result = _clockCore.SetSystemClockContext(clockContext);
|
|
|
|
|
+
|
|
|
|
|
+ if (result == ResultCode.Success)
|
|
|
|
|
+ {
|
|
|
|
|
+ result = _clockCore.Flush(clockContext);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return ResultCode.Success;
|
|
|
|
|
|
|
+ return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
[Command(2)]
|
|
[Command(2)]
|
|
|
// GetSystemClockContext() -> nn::time::SystemClockContext
|
|
// GetSystemClockContext() -> nn::time::SystemClockContext
|
|
|
public ResultCode GetSystemClockContext(ServiceCtx context)
|
|
public ResultCode GetSystemClockContext(ServiceCtx context)
|
|
|
{
|
|
{
|
|
|
- context.ResponseData.Write((long)(_systemClockContextEpoch - Epoch).TotalSeconds);
|
|
|
|
|
-
|
|
|
|
|
- // The point in time, TODO: is there a link between epoch and this?
|
|
|
|
|
- context.ResponseData.Write(_systemClockTimePoint);
|
|
|
|
|
|
|
+ ResultCode result = _clockCore.GetSystemClockContext(context.Thread, out SystemClockContext clockContext);
|
|
|
|
|
|
|
|
- // This seems to be some kind of identifier?
|
|
|
|
|
- for (int i = 0; i < 0x10; i++)
|
|
|
|
|
|
|
+ if (result == ResultCode.Success)
|
|
|
{
|
|
{
|
|
|
- context.ResponseData.Write(_systemClockContextEnding[i]);
|
|
|
|
|
|
|
+ context.ResponseData.WriteStruct(clockContext);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return ResultCode.Success;
|
|
|
|
|
|
|
+ return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
[Command(3)]
|
|
[Command(3)]
|
|
|
// SetSystemClockContext(nn::time::SystemClockContext)
|
|
// SetSystemClockContext(nn::time::SystemClockContext)
|
|
|
public ResultCode SetSystemClockContext(ServiceCtx context)
|
|
public ResultCode SetSystemClockContext(ServiceCtx context)
|
|
|
{
|
|
{
|
|
|
- long newSystemClockEpoch = context.RequestData.ReadInt64();
|
|
|
|
|
- long newSystemClockTimePoint = context.RequestData.ReadInt64();
|
|
|
|
|
|
|
+ if (!_writePermission)
|
|
|
|
|
+ {
|
|
|
|
|
+ return ResultCode.PermissionDenied;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ SystemClockContext clockContext = context.RequestData.ReadStruct<SystemClockContext>();
|
|
|
|
|
|
|
|
- _systemClockContextEpoch = Epoch.Add(TimeSpan.FromSeconds(newSystemClockEpoch));
|
|
|
|
|
- _systemClockTimePoint = newSystemClockTimePoint;
|
|
|
|
|
- _systemClockContextEnding = context.RequestData.ReadBytes(0x10);
|
|
|
|
|
|
|
+ ResultCode result = _clockCore.SetSystemClockContext(clockContext);
|
|
|
|
|
+
|
|
|
|
|
+ if (result == ResultCode.Success)
|
|
|
|
|
+ {
|
|
|
|
|
+ result = _clockCore.Flush(clockContext);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return ResultCode.Success;
|
|
|
|
|
|
|
+ return result;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|