diff --git a/Ryujinx.HLE/OsHle/Services/Time/IStaticService.cs b/Ryujinx.HLE/OsHle/Services/Time/IStaticService.cs index 1f012144..55601a89 100644 --- a/Ryujinx.HLE/OsHle/Services/Time/IStaticService.cs +++ b/Ryujinx.HLE/OsHle/Services/Time/IStaticService.cs @@ -1,4 +1,5 @@ using Ryujinx.HLE.OsHle.Ipc; +using System; using System.Collections.Generic; namespace Ryujinx.HLE.OsHle.Services.Time @@ -9,15 +10,18 @@ namespace Ryujinx.HLE.OsHle.Services.Time public override IReadOnlyDictionary Commands => m_Commands; + private static readonly DateTime StartupDate = DateTime.UtcNow; + public IStaticService() { m_Commands = new Dictionary() { - { 0, GetStandardUserSystemClock }, - { 1, GetStandardNetworkSystemClock }, - { 2, GetStandardSteadyClock }, - { 3, GetTimeZoneService }, - { 4, GetStandardLocalSystemClock } + { 0, GetStandardUserSystemClock }, + { 1, GetStandardNetworkSystemClock }, + { 2, GetStandardSteadyClock }, + { 3, GetTimeZoneService }, + { 4, GetStandardLocalSystemClock }, + { 300, CalculateMonotonicSystemClockBaseTimePoint } }; } @@ -56,5 +60,15 @@ namespace Ryujinx.HLE.OsHle.Services.Time return 0; } + public long CalculateMonotonicSystemClockBaseTimePoint(ServiceCtx Context) + { + long TimeOffset = (long)(DateTime.UtcNow - StartupDate).TotalSeconds; + long SystemClockContextEpoch = Context.RequestData.ReadInt64(); + + Context.ResponseData.Write(TimeOffset + SystemClockContextEpoch); + + return 0; + } + } } \ No newline at end of file diff --git a/Ryujinx.HLE/OsHle/Services/Time/ISteadyClock.cs b/Ryujinx.HLE/OsHle/Services/Time/ISteadyClock.cs index 6be097b7..e2cb34e3 100644 --- a/Ryujinx.HLE/OsHle/Services/Time/ISteadyClock.cs +++ b/Ryujinx.HLE/OsHle/Services/Time/ISteadyClock.cs @@ -1,4 +1,5 @@ using Ryujinx.HLE.OsHle.Ipc; +using System; using System.Collections.Generic; namespace Ryujinx.HLE.OsHle.Services.Time @@ -9,12 +10,44 @@ namespace Ryujinx.HLE.OsHle.Services.Time public override IReadOnlyDictionary Commands => m_Commands; + private ulong TestOffset; + public ISteadyClock() { m_Commands = new Dictionary() { - //... + { 0, GetCurrentTimePoint }, + { 1, GetTestOffset }, + { 2, SetTestOffset } }; + + TestOffset = 0; + } + + public long GetCurrentTimePoint(ServiceCtx Context) + { + Context.ResponseData.Write((long)(System.Diagnostics.Process.GetCurrentProcess().StartTime - DateTime.Now).TotalSeconds); + + for (int i = 0; i < 0x10; i++) + { + Context.ResponseData.Write((byte)0); + } + + return 0; + } + + public long GetTestOffset(ServiceCtx Context) + { + Context.ResponseData.Write(TestOffset); + + return 0; + } + + public long SetTestOffset(ServiceCtx Context) + { + TestOffset = Context.RequestData.ReadUInt64(); + + return 0; } } } \ No newline at end of file diff --git a/Ryujinx.HLE/OsHle/Services/Time/ISystemClock.cs b/Ryujinx.HLE/OsHle/Services/Time/ISystemClock.cs index 787f86c2..27b65c3c 100644 --- a/Ryujinx.HLE/OsHle/Services/Time/ISystemClock.cs +++ b/Ryujinx.HLE/OsHle/Services/Time/ISystemClock.cs @@ -14,14 +14,36 @@ namespace Ryujinx.HLE.OsHle.Services.Time private SystemClockType ClockType; + private DateTime SystemClockContextEpoch; + + private long SystemClockTimePoint; + + private byte[] SystemClockContextEnding; + + private long TimeOffset; + public ISystemClock(SystemClockType ClockType) { m_Commands = new Dictionary() { - { 0, GetCurrentTime } + { 0, GetCurrentTime }, + { 1, SetCurrentTime }, + { 2, GetSystemClockContext }, + { 3, SetSystemClockContext } }; - this.ClockType = ClockType; + this.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; } public long GetCurrentTime(ServiceCtx Context) @@ -34,7 +56,50 @@ namespace Ryujinx.HLE.OsHle.Services.Time CurrentTime = CurrentTime.ToUniversalTime(); } - Context.ResponseData.Write((long)(DateTime.Now - Epoch).TotalSeconds); + Context.ResponseData.Write((long)((CurrentTime - Epoch).TotalSeconds) + TimeOffset); + + return 0; + } + + public long SetCurrentTime(ServiceCtx Context) + { + DateTime CurrentTime = DateTime.Now; + + if (ClockType == SystemClockType.User || + ClockType == SystemClockType.Network) + { + CurrentTime = CurrentTime.ToUniversalTime(); + } + + TimeOffset = (Context.RequestData.ReadInt64() - (long)(CurrentTime - Epoch).TotalSeconds); + + return 0; + } + + public long 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); + + // This seems to be some kind of identifier? + for (int i = 0; i < 0x10; i++) + { + Context.ResponseData.Write(SystemClockContextEnding[i]); + } + + return 0; + } + + public long SetSystemClockContext(ServiceCtx Context) + { + long NewSystemClockEpoch = Context.RequestData.ReadInt64(); + long NewSystemClockTimePoint = Context.RequestData.ReadInt64(); + + SystemClockContextEpoch = Epoch.Add(TimeSpan.FromSeconds(NewSystemClockEpoch)); + SystemClockTimePoint = NewSystemClockTimePoint; + SystemClockContextEnding = Context.RequestData.ReadBytes(0x10); return 0; } diff --git a/Ryujinx.HLE/OsHle/Services/Time/SystemClockType.cs b/Ryujinx.HLE/OsHle/Services/Time/SystemClockType.cs index 518e1eb0..d581d9ca 100644 --- a/Ryujinx.HLE/OsHle/Services/Time/SystemClockType.cs +++ b/Ryujinx.HLE/OsHle/Services/Time/SystemClockType.cs @@ -4,6 +4,7 @@ namespace Ryujinx.HLE.OsHle.Services.Time { User, Network, - Local + Local, + EphemeralNetwork } } \ No newline at end of file