diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index 51db8884c0..95cd30f0f7 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -32,6 +32,7 @@ namespace Ryujinx.HLE.HOS internal const int HidSize = 0x40000; internal const int FontSize = 0x1100000; internal const int IirsSize = 0x8000; + internal const int TimeSize = 0x1000; private const int MemoryBlockAllocatorSize = 0x2710; @@ -84,6 +85,7 @@ namespace Ryujinx.HLE.HOS internal KSharedMemory HidSharedMem { get; private set; } internal KSharedMemory FontSharedMem { get; private set; } internal KSharedMemory IirsSharedMem { get; private set; } + internal KSharedMemory TimeSharedMem { get; private set; } internal SharedFontManager Font { get; private set; } @@ -161,20 +163,24 @@ namespace Ryujinx.HLE.HOS ulong hidPa = region.Address; ulong fontPa = region.Address + HidSize; ulong iirsPa = region.Address + HidSize + FontSize; + ulong timePa = region.Address + HidSize + FontSize + IirsSize; HidBaseAddress = (long)(hidPa - DramMemoryMap.DramBase); KPageList hidPageList = new KPageList(); KPageList fontPageList = new KPageList(); KPageList iirsPageList = new KPageList(); + KPageList timePageList = new KPageList(); hidPageList .AddRange(hidPa, HidSize / KMemoryManager.PageSize); fontPageList.AddRange(fontPa, FontSize / KMemoryManager.PageSize); iirsPageList.AddRange(iirsPa, IirsSize / KMemoryManager.PageSize); + timePageList.AddRange(timePa, TimeSize / KMemoryManager.PageSize); HidSharedMem = new KSharedMemory(this, hidPageList, 0, 0, MemoryPermission.Read); FontSharedMem = new KSharedMemory(this, fontPageList, 0, 0, MemoryPermission.Read); IirsSharedMem = new KSharedMemory(this, iirsPageList, 0, 0, MemoryPermission.Read); + TimeSharedMem = new KSharedMemory(this, timePageList, 0, 0, MemoryPermission.Read); AppletState = new AppletStateMgr(this); @@ -676,4 +682,4 @@ namespace Ryujinx.HLE.HOS } } } -} +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Time/IStaticService.cs b/Ryujinx.HLE/HOS/Services/Time/IStaticService.cs index fcbaa49216..107d0578d6 100644 --- a/Ryujinx.HLE/HOS/Services/Time/IStaticService.cs +++ b/Ryujinx.HLE/HOS/Services/Time/IStaticService.cs @@ -1,4 +1,5 @@ using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Common; using System; using System.Collections.Generic; @@ -6,6 +7,8 @@ namespace Ryujinx.HLE.HOS.Services.Time { class IStaticService : IpcService { + private int _timeSharedMemoryNativeHandle = 0; + private Dictionary _commands; public override IReadOnlyDictionary Commands => _commands; @@ -16,15 +19,30 @@ namespace Ryujinx.HLE.HOS.Services.Time { _commands = new Dictionary { - { 0, GetStandardUserSystemClock }, - { 1, GetStandardNetworkSystemClock }, - { 2, GetStandardSteadyClock }, - { 3, GetTimeZoneService }, - { 4, GetStandardLocalSystemClock }, - { 300, CalculateMonotonicSystemClockBaseTimePoint } + { 0, GetStandardUserSystemClock }, + { 1, GetStandardNetworkSystemClock }, + { 2, GetStandardSteadyClock }, + { 3, GetTimeZoneService }, + { 4, GetStandardLocalSystemClock }, + //{ 5, GetEphemeralNetworkSystemClock }, // 4.0.0+ + { 20, GetSharedMemoryNativeHandle }, // 6.0.0+ + //{ 30, GetStandardNetworkClockOperationEventReadableHandle }, // 6.0.0+ + //{ 31, GetEphemeralNetworkClockOperationEventReadableHandle }, // 6.0.0+ + //{ 50, SetStandardSteadyClockInternalOffset }, // 4.0.0+ + //{ 100, IsStandardUserSystemClockAutomaticCorrectionEnabled }, + //{ 101, SetStandardUserSystemClockAutomaticCorrectionEnabled }, + //{ 102, GetStandardUserSystemClockInitialYear }, // 5.0.0+ + //{ 200, IsStandardNetworkSystemClockAccuracySufficient }, // 3.0.0+ + //{ 201, GetStandardUserSystemClockAutomaticCorrectionUpdatedTime }, // 6.0.0+ + { 300, CalculateMonotonicSystemClockBaseTimePoint }, // 4.0.0+ + //{ 400, GetClockSnapshot }, // 4.0.0+ + //{ 401, GetClockSnapshotFromSystemClockContext }, // 4.0.0+ + //{ 500, CalculateStandardUserSystemClockDifferenceByUser }, // 4.0.0+ + //{ 501, CalculateSpanBetween }, // 4.0.0+ }; } + // GetStandardUserSystemClock() -> object public long GetStandardUserSystemClock(ServiceCtx context) { MakeObject(context, new ISystemClock(SystemClockType.User)); @@ -32,6 +50,7 @@ namespace Ryujinx.HLE.HOS.Services.Time return 0; } + // GetStandardNetworkSystemClock() -> object public long GetStandardNetworkSystemClock(ServiceCtx context) { MakeObject(context, new ISystemClock(SystemClockType.Network)); @@ -39,6 +58,7 @@ namespace Ryujinx.HLE.HOS.Services.Time return 0; } + // GetStandardSteadyClock() -> object public long GetStandardSteadyClock(ServiceCtx context) { MakeObject(context, new ISteadyClock()); @@ -46,6 +66,7 @@ namespace Ryujinx.HLE.HOS.Services.Time return 0; } + // GetTimeZoneService() -> object public long GetTimeZoneService(ServiceCtx context) { MakeObject(context, new ITimeZoneService()); @@ -53,6 +74,7 @@ namespace Ryujinx.HLE.HOS.Services.Time return 0; } + // GetStandardLocalSystemClock() -> object public long GetStandardLocalSystemClock(ServiceCtx context) { MakeObject(context, new ISystemClock(SystemClockType.Local)); @@ -60,6 +82,23 @@ namespace Ryujinx.HLE.HOS.Services.Time return 0; } + // GetSharedMemoryNativeHandle() -> handle + public long GetSharedMemoryNativeHandle(ServiceCtx context) + { + if (_timeSharedMemoryNativeHandle == 0) + { + if (context.Process.HandleTable.GenerateHandle(context.Device.System.TimeSharedMem, out _timeSharedMemoryNativeHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_timeSharedMemoryNativeHandle); + + return 0; + } + + // CalculateMonotonicSystemClockBaseTimePoint(nn::time::SystemClockContext) -> u64 public long CalculateMonotonicSystemClockBaseTimePoint(ServiceCtx context) { long timeOffset = (long)(DateTime.UtcNow - StartupDate).TotalSeconds;