diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs index 554dc911c3..629d8ee114 100644 --- a/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockContextUpdateCallback.cs @@ -1,4 +1,5 @@ using Ryujinx.HLE.HOS.Kernel.Threading; +using System; using System.Collections.Generic; using System.Threading; @@ -6,13 +7,13 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock { abstract class SystemClockContextUpdateCallback { - private List _operationEventList; - protected SystemClockContext _context; - private bool _hasContext; + private List _operationEventList; + protected SystemClockContext _context; + private bool _hasContext; public SystemClockContextUpdateCallback() { - _operationEventList = new List(); + _operationEventList = new List(); _context = new SystemClockContext(); _hasContext = false; } @@ -27,13 +28,20 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock return true; } + public void RegisterOperationEvent(KWritableEvent writableEvent) + { + Monitor.Enter(_operationEventList); + _operationEventList.Add(writableEvent); + Monitor.Exit(_operationEventList); + } + private void BroadcastOperationEvent() { Monitor.Enter(_operationEventList); - foreach (KEvent e in _operationEventList) + foreach (KWritableEvent e in _operationEventList) { - e.WritableEvent.Signal(); + e.Signal(); } Monitor.Exit(_operationEventList); diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs index 76ab575928..75c71663d6 100644 --- a/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/SystemClockCore.cs @@ -1,4 +1,5 @@ -using Ryujinx.HLE.HOS.Kernel.Threading; +using System; +using Ryujinx.HLE.HOS.Kernel.Threading; namespace Ryujinx.HLE.HOS.Services.Time.Clock { @@ -96,6 +97,14 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock _systemClockContextUpdateCallback = systemClockContextUpdateCallback; } + public void RegisterOperationEvent(KWritableEvent writableEvent) + { + if (_systemClockContextUpdateCallback != null) + { + _systemClockContextUpdateCallback.RegisterOperationEvent(writableEvent); + } + } + public ResultCode SetSystemClockContext(SystemClockContext context) { ResultCode result = SetClockContext(context); diff --git a/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs b/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs index 5ab2717852..e754bc29cd 100644 --- a/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs +++ b/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs @@ -1,5 +1,9 @@ using Ryujinx.Common; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Time.Clock; +using System; namespace Ryujinx.HLE.HOS.Services.Time.StaticService { @@ -8,12 +12,14 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService private SystemClockCore _clockCore; private bool _writePermission; private bool _bypassUninitializedClock; + private int _operationEventReadableHandle; public ISystemClock(SystemClockCore clockCore, bool writePermission, bool bypassUninitializedCloc) { - _clockCore = clockCore; - _writePermission = writePermission; - _bypassUninitializedClock = bypassUninitializedCloc; + _clockCore = clockCore; + _writePermission = writePermission; + _bypassUninitializedClock = bypassUninitializedCloc; + _operationEventReadableHandle = 0; } [Command(0)] @@ -93,5 +99,26 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService return result; } + + [Command(4)] // 9.0.0+ + // GetOperationEventReadableHandle() -> handle + public ResultCode GetOperationEventReadableHandle(ServiceCtx context) + { + if (_operationEventReadableHandle == 0) + { + KEvent kEvent = new KEvent(context.Device.System); + + _clockCore.RegisterOperationEvent(kEvent.WritableEvent); + + if (context.Process.HandleTable.GenerateHandle(kEvent.ReadableEvent, out _operationEventReadableHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_operationEventReadableHandle); + + return ResultCode.Success; + } } } \ No newline at end of file