diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /src/Ryujinx.HLE/HOS/Services/Time/Clock | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Services/Time/Clock')
16 files changed, 769 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockContextWriter.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockContextWriter.cs new file mode 100644 index 00000000..14d3cb24 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockContextWriter.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + class EphemeralNetworkSystemClockContextWriter : SystemClockContextUpdateCallback + { + protected override ResultCode Update() + { + return ResultCode.Success; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs new file mode 100644 index 00000000..003863e4 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/EphemeralNetworkSystemClockCore.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + class EphemeralNetworkSystemClockCore : SystemClockCore + { + public EphemeralNetworkSystemClockCore(SteadyClockCore steadyClockCore) : base(steadyClockCore) { } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/LocalSystemClockContextWriter.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/LocalSystemClockContextWriter.cs new file mode 100644 index 00000000..fb7ebdc5 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/LocalSystemClockContextWriter.cs @@ -0,0 +1,19 @@ +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + class LocalSystemClockContextWriter : SystemClockContextUpdateCallback + { + private TimeSharedMemory _sharedMemory; + + public LocalSystemClockContextWriter(TimeSharedMemory sharedMemory) + { + _sharedMemory = sharedMemory; + } + + protected override ResultCode Update() + { + _sharedMemory.UpdateLocalSystemClockContext(_context); + + return ResultCode.Success; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/NetworkSystemClockContextWriter.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/NetworkSystemClockContextWriter.cs new file mode 100644 index 00000000..36468ec1 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/NetworkSystemClockContextWriter.cs @@ -0,0 +1,19 @@ +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + class NetworkSystemClockContextWriter : SystemClockContextUpdateCallback + { + private TimeSharedMemory _sharedMemory; + + public NetworkSystemClockContextWriter(TimeSharedMemory sharedMemory) + { + _sharedMemory = sharedMemory; + } + + protected override ResultCode Update() + { + _sharedMemory.UpdateNetworkSystemClockContext(_context); + + return ResultCode.Success; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs new file mode 100644 index 00000000..20c334e8 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardLocalSystemClockCore.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + class StandardLocalSystemClockCore : SystemClockCore + { + public StandardLocalSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) {} + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs new file mode 100644 index 00000000..aec03485 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardNetworkSystemClockCore.cs @@ -0,0 +1,36 @@ +using Ryujinx.Cpu; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + class StandardNetworkSystemClockCore : SystemClockCore + { + private TimeSpanType _standardNetworkClockSufficientAccuracy; + + public StandardNetworkSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) + { + _standardNetworkClockSufficientAccuracy = new TimeSpanType(0); + } + + public bool IsStandardNetworkSystemClockAccuracySufficient(ITickSource tickSource) + { + SteadyClockCore steadyClockCore = GetSteadyClockCore(); + SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(tickSource); + + bool isStandardNetworkClockSufficientAccuracy = false; + + ResultCode result = GetClockContext(tickSource, out SystemClockContext context); + + if (result == ResultCode.Success && 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/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs new file mode 100644 index 00000000..8392c4b5 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardSteadyClockCore.cs @@ -0,0 +1,72 @@ +using Ryujinx.Cpu; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + class StandardSteadyClockCore : SteadyClockCore + { + private TimeSpanType _setupValue; + private TimeSpanType _testOffset; + private TimeSpanType _internalOffset; + private TimeSpanType _cachedRawTimePoint; + + public StandardSteadyClockCore() + { + _setupValue = TimeSpanType.Zero; + _testOffset = TimeSpanType.Zero; + _internalOffset = TimeSpanType.Zero; + _cachedRawTimePoint = TimeSpanType.Zero; + } + + public override SteadyClockTimePoint GetTimePoint(ITickSource tickSource) + { + SteadyClockTimePoint result = new SteadyClockTimePoint + { + TimePoint = GetCurrentRawTimePoint(tickSource).ToSeconds(), + ClockSourceId = GetClockSourceId() + }; + + return result; + } + + public override TimeSpanType GetTestOffset() + { + return _testOffset; + } + + public override void SetTestOffset(TimeSpanType testOffset) + { + _testOffset = testOffset; + } + + public override TimeSpanType GetInternalOffset() + { + return _internalOffset; + } + + public override void SetInternalOffset(TimeSpanType internalOffset) + { + _internalOffset = internalOffset; + } + + public override TimeSpanType GetCurrentRawTimePoint(ITickSource tickSource) + { + TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(tickSource.Counter, tickSource.Frequency); + + TimeSpanType rawTimePoint = new TimeSpanType(_setupValue.NanoSeconds + ticksTimeSpan.NanoSeconds); + + if (rawTimePoint.NanoSeconds < _cachedRawTimePoint.NanoSeconds) + { + rawTimePoint.NanoSeconds = _cachedRawTimePoint.NanoSeconds; + } + + _cachedRawTimePoint = rawTimePoint; + + return rawTimePoint; + } + + public void SetSetupValue(TimeSpanType setupValue) + { + _setupValue = setupValue; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs new file mode 100644 index 00000000..fa485437 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs @@ -0,0 +1,108 @@ +using Ryujinx.Cpu; +using Ryujinx.HLE.HOS.Kernel.Threading; +using System; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + class StandardUserSystemClockCore : SystemClockCore + { + private StandardLocalSystemClockCore _localSystemClockCore; + private StandardNetworkSystemClockCore _networkSystemClockCore; + private bool _autoCorrectionEnabled; + private SteadyClockTimePoint _autoCorrectionTime; + private KEvent _autoCorrectionEvent; + + public StandardUserSystemClockCore(StandardLocalSystemClockCore localSystemClockCore, StandardNetworkSystemClockCore networkSystemClockCore) : base(localSystemClockCore.GetSteadyClockCore()) + { + _localSystemClockCore = localSystemClockCore; + _networkSystemClockCore = networkSystemClockCore; + _autoCorrectionEnabled = false; + _autoCorrectionTime = SteadyClockTimePoint.GetRandom(); + _autoCorrectionEvent = null; + } + + protected override ResultCode Flush(SystemClockContext context) + { + // As UserSystemClock isn't a real system clock, this shouldn't happens. + throw new NotImplementedException(); + } + + public override ResultCode GetClockContext(ITickSource tickSource, out SystemClockContext context) + { + ResultCode result = ApplyAutomaticCorrection(tickSource, false); + + context = new SystemClockContext(); + + if (result == ResultCode.Success) + { + return _localSystemClockCore.GetClockContext(tickSource, out context); + } + + return result; + } + + public override ResultCode SetClockContext(SystemClockContext context) + { + return ResultCode.NotImplemented; + } + + private ResultCode ApplyAutomaticCorrection(ITickSource tickSource, bool autoCorrectionEnabled) + { + ResultCode result = ResultCode.Success; + + if (_autoCorrectionEnabled != autoCorrectionEnabled && _networkSystemClockCore.IsClockSetup(tickSource)) + { + result = _networkSystemClockCore.GetClockContext(tickSource, out SystemClockContext context); + + if (result == ResultCode.Success) + { + _localSystemClockCore.SetClockContext(context); + } + } + + return result; + } + + internal void CreateAutomaticCorrectionEvent(Horizon system) + { + _autoCorrectionEvent = new KEvent(system.KernelContext); + } + + public ResultCode SetAutomaticCorrectionEnabled(ITickSource tickSource, bool autoCorrectionEnabled) + { + ResultCode result = ApplyAutomaticCorrection(tickSource, autoCorrectionEnabled); + + if (result == ResultCode.Success) + { + _autoCorrectionEnabled = autoCorrectionEnabled; + } + + return result; + } + + public bool IsAutomaticCorrectionEnabled() + { + return _autoCorrectionEnabled; + } + + public KReadableEvent GetAutomaticCorrectionReadableEvent() + { + return _autoCorrectionEvent.ReadableEvent; + } + + public void SetAutomaticCorrectionUpdatedTime(SteadyClockTimePoint steadyClockTimePoint) + { + _autoCorrectionTime = steadyClockTimePoint; + } + + public SteadyClockTimePoint GetAutomaticCorrectionUpdatedTime() + { + return _autoCorrectionTime; + } + + public void SignalAutomaticCorrectionEvent() + { + _autoCorrectionEvent.WritableEvent.Signal(); + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs new file mode 100644 index 00000000..18da4ed3 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/SteadyClockCore.cs @@ -0,0 +1,98 @@ +using Ryujinx.Common.Utilities; +using Ryujinx.Cpu; +using System; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + abstract class SteadyClockCore + { + private UInt128 _clockSourceId; + private bool _isRtcResetDetected; + private bool _isInitialized; + + public SteadyClockCore() + { + _clockSourceId = UInt128Utils.CreateRandom(); + _isRtcResetDetected = false; + _isInitialized = false; + } + + public UInt128 GetClockSourceId() + { + return _clockSourceId; + } + + public void SetClockSourceId(UInt128 clockSourceId) + { + _clockSourceId = clockSourceId; + } + + public void SetRtcReset() + { + _isRtcResetDetected = true; + } + + public virtual TimeSpanType GetTestOffset() + { + return new TimeSpanType(0); + } + + public virtual void SetTestOffset(TimeSpanType testOffset) {} + + public ResultCode GetRtcValue(out ulong rtcValue) + { + rtcValue = 0; + + return ResultCode.NotImplemented; + } + + public bool IsRtcResetDetected() + { + return _isRtcResetDetected; + } + + public ResultCode GetSetupResultValue() + { + return ResultCode.Success; + } + + public virtual TimeSpanType GetInternalOffset() + { + return new TimeSpanType(0); + } + + public virtual void SetInternalOffset(TimeSpanType internalOffset) {} + + public virtual SteadyClockTimePoint GetTimePoint(ITickSource tickSource) + { + throw new NotImplementedException(); + } + + public virtual TimeSpanType GetCurrentRawTimePoint(ITickSource tickSource) + { + SteadyClockTimePoint timePoint = GetTimePoint(tickSource); + + return TimeSpanType.FromSeconds(timePoint.TimePoint); + } + + public SteadyClockTimePoint GetCurrentTimePoint(ITickSource tickSource) + { + SteadyClockTimePoint result = GetTimePoint(tickSource); + + result.TimePoint += GetTestOffset().ToSeconds(); + result.TimePoint += GetInternalOffset().ToSeconds(); + + return result; + } + + public bool IsInitialized() + { + return _isInitialized; + } + + public void MarkInitialized() + { + _isInitialized = true; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs new file mode 100644 index 00000000..6229f5ed --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs @@ -0,0 +1,71 @@ +using Ryujinx.HLE.HOS.Kernel.Threading; +using System.Collections.Generic; +using System.Threading; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + abstract class SystemClockContextUpdateCallback + { + private List<KWritableEvent> _operationEventList; + protected SystemClockContext _context; + private bool _hasContext; + + public SystemClockContextUpdateCallback() + { + _operationEventList = new List<KWritableEvent>(); + _context = new SystemClockContext(); + _hasContext = false; + } + + private bool NeedUpdate(SystemClockContext context) + { + if (_hasContext) + { + return _context.Offset != context.Offset || _context.SteadyTimePoint.ClockSourceId != context.SteadyTimePoint.ClockSourceId; + } + + return true; + } + + public void RegisterOperationEvent(KWritableEvent writableEvent) + { + Monitor.Enter(_operationEventList); + _operationEventList.Add(writableEvent); + Monitor.Exit(_operationEventList); + } + + private void BroadcastOperationEvent() + { + Monitor.Enter(_operationEventList); + + foreach (KWritableEvent e in _operationEventList) + { + e.Signal(); + } + + Monitor.Exit(_operationEventList); + } + + protected abstract ResultCode Update(); + + public ResultCode Update(SystemClockContext context) + { + ResultCode result = ResultCode.Success; + + if (NeedUpdate(context)) + { + _context = context; + _hasContext = true; + + result = Update(); + + if (result == ResultCode.Success) + { + BroadcastOperationEvent(); + } + } + + return result; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs new file mode 100644 index 00000000..f4bbaa60 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs @@ -0,0 +1,144 @@ +using Ryujinx.Cpu; +using Ryujinx.HLE.HOS.Kernel.Threading; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + abstract class SystemClockCore + { + private SteadyClockCore _steadyClockCore; + private SystemClockContext _context; + private bool _isInitialized; + private SystemClockContextUpdateCallback _systemClockContextUpdateCallback; + + public SystemClockCore(SteadyClockCore steadyClockCore) + { + _steadyClockCore = steadyClockCore; + _context = new SystemClockContext(); + _isInitialized = false; + + _context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId(); + _systemClockContextUpdateCallback = null; + } + + public virtual SteadyClockCore GetSteadyClockCore() + { + return _steadyClockCore; + } + + public ResultCode GetCurrentTime(ITickSource tickSource, out long posixTime) + { + posixTime = 0; + + SteadyClockTimePoint currentTimePoint = _steadyClockCore.GetCurrentTimePoint(tickSource); + + ResultCode result = GetClockContext(tickSource, 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(ITickSource tickSource, long posixTime) + { + SteadyClockTimePoint currentTimePoint = _steadyClockCore.GetCurrentTimePoint(tickSource); + + 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(ITickSource tickSource, out SystemClockContext context) + { + context = _context; + + return ResultCode.Success; + } + + public virtual ResultCode SetClockContext(SystemClockContext context) + { + _context = context; + + return ResultCode.Success; + } + + protected virtual ResultCode Flush(SystemClockContext context) + { + if (_systemClockContextUpdateCallback == null) + { + return ResultCode.Success; + } + + return _systemClockContextUpdateCallback.Update(context); + } + + public void SetUpdateCallbackInstance(SystemClockContextUpdateCallback systemClockContextUpdateCallback) + { + _systemClockContextUpdateCallback = systemClockContextUpdateCallback; + } + + public void RegisterOperationEvent(KWritableEvent writableEvent) + { + if (_systemClockContextUpdateCallback != null) + { + _systemClockContextUpdateCallback.RegisterOperationEvent(writableEvent); + } + } + + public ResultCode SetSystemClockContext(SystemClockContext context) + { + ResultCode result = SetClockContext(context); + + if (result == ResultCode.Success) + { + result = Flush(context); + } + + return result; + } + + public bool IsInitialized() + { + return _isInitialized; + } + + public void MarkInitialized() + { + _isInitialized = true; + } + + public bool IsClockSetup(ITickSource tickSource) + { + ResultCode result = GetClockContext(tickSource, out SystemClockContext context); + + if (result == ResultCode.Success) + { + SteadyClockTimePoint steadyClockTimePoint = _steadyClockCore.GetCurrentTimePoint(tickSource); + + return steadyClockTimePoint.ClockSourceId == context.SteadyTimePoint.ClockSourceId; + } + + return false; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs new file mode 100644 index 00000000..fe74da7e --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/TickBasedSteadyClockCore.cs @@ -0,0 +1,24 @@ +using Ryujinx.Cpu; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + class TickBasedSteadyClockCore : SteadyClockCore + { + public TickBasedSteadyClockCore() {} + + public override SteadyClockTimePoint GetTimePoint(ITickSource tickSource) + { + SteadyClockTimePoint result = new SteadyClockTimePoint + { + TimePoint = 0, + ClockSourceId = GetClockSourceId() + }; + + TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(tickSource.Counter, tickSource.Frequency); + + result.TimePoint = ticksTimeSpan.ToSeconds(); + + return result; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs new file mode 100644 index 00000000..07c1b405 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs @@ -0,0 +1,50 @@ +using Ryujinx.HLE.HOS.Services.Time.TimeZone; +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + [StructLayout(LayoutKind.Sequential, Size = 0xD0)] + struct ClockSnapshot + { + public SystemClockContext UserContext; + public SystemClockContext NetworkContext; + public long UserTime; + public long NetworkTime; + public CalendarTime UserCalendarTime; + public CalendarTime NetworkCalendarTime; + public CalendarAdditionalInfo UserCalendarAdditionalTime; + public CalendarAdditionalInfo NetworkCalendarAdditionalTime; + public SteadyClockTimePoint SteadyClockTimePoint; + + private LocationNameStorageHolder _locationName; + + public Span<byte> LocationName => MemoryMarshal.Cast<LocationNameStorageHolder, byte>(MemoryMarshal.CreateSpan(ref _locationName, LocationNameStorageHolder.Size)); + + [MarshalAs(UnmanagedType.I1)] + public bool IsAutomaticCorrectionEnabled; + public byte Type; + public ushort Unknown; + + + [StructLayout(LayoutKind.Sequential, Pack = 1, Size = Size)] + private struct LocationNameStorageHolder + { + public const int Size = 0x24; + } + + public static ResultCode GetCurrentTime(out long currentTime, SteadyClockTimePoint steadyClockTimePoint, SystemClockContext context) + { + currentTime = 0; + + if (steadyClockTimePoint.ClockSourceId == context.SteadyTimePoint.ClockSourceId) + { + currentTime = steadyClockTimePoint.TimePoint + context.Offset; + + return ResultCode.Success; + } + + return ResultCode.TimeMismatch; + } + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/SteadyClockTimePoint.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/SteadyClockTimePoint.cs new file mode 100644 index 00000000..729e11b6 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/SteadyClockTimePoint.cs @@ -0,0 +1,43 @@ +using Ryujinx.Common.Utilities; +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct SteadyClockTimePoint + { + 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; + } + + public static SteadyClockTimePoint GetRandom() + { + return new SteadyClockTimePoint + { + TimePoint = 0, + ClockSourceId = UInt128Utils.CreateRandom() + }; + } + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/SystemClockContext.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/SystemClockContext.cs new file mode 100644 index 00000000..6b589c28 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/SystemClockContext.cs @@ -0,0 +1,11 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct SystemClockContext + { + public long Offset; + public SteadyClockTimePoint SteadyTimePoint; + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs new file mode 100644 index 00000000..0070193f --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs @@ -0,0 +1,50 @@ +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.HOS.Services.Time.Clock +{ + [StructLayout(LayoutKind.Sequential)] + struct TimeSpanType + { + private const long NanoSecondsPerSecond = 1000000000; + + public static readonly TimeSpanType Zero = new TimeSpanType(0); + + public long NanoSeconds; + + public TimeSpanType(long nanoSeconds) + { + NanoSeconds = nanoSeconds; + } + + public long ToSeconds() + { + return NanoSeconds / NanoSecondsPerSecond; + } + + public TimeSpanType AddSeconds(long seconds) + { + return new TimeSpanType(NanoSeconds + (seconds * NanoSecondsPerSecond)); + } + + public bool IsDaylightSavingTime() + { + return DateTime.UnixEpoch.AddSeconds(ToSeconds()).ToLocalTime().IsDaylightSavingTime(); + } + + public static TimeSpanType FromSeconds(long seconds) + { + return new TimeSpanType(seconds * NanoSecondsPerSecond); + } + + public static TimeSpanType FromTimeSpan(TimeSpan timeSpan) + { + return new TimeSpanType((long)(timeSpan.TotalMilliseconds * 1000000)); + } + + public static TimeSpanType FromTicks(ulong ticks, ulong frequency) + { + return FromSeconds((long)ticks / (long)frequency); + } + } +}
\ No newline at end of file |
