diff options
author | gdkchan <gab.dark.100@gmail.com> | 2020-12-01 20:23:43 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-02 00:23:43 +0100 |
commit | cf6cd714884c41e9550757e364c2f4f5b04fc7f3 (patch) | |
tree | bea748b4d1a350e5b8075d63ec9d39d49693829d /Ryujinx.HLE/HOS/Services | |
parent | 461c24092ae6e148d896c18aa3e86220c89981f8 (diff) |
IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel (#1458)
* IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel
* Fix for applet transfer memory + some nits
* Keep handles if possible to avoid server handle table exhaustion
* Fix IPC ZeroFill bug
* am: Correctly implement CreateManagedDisplayLayer and implement CreateManagedDisplaySeparableLayer
CreateManagedDisplaySeparableLayer is requires since 10.x+ when appletResourceUserId != 0
* Make it exit properly
* Make ServiceNotImplementedException show the full message again
* Allow yielding execution to avoid starving other threads
* Only wait if active
* Merge IVirtualMemoryManager and IAddressSpaceManager
* Fix Ro loading data from the wrong process
Co-authored-by: Thog <me@thog.eu>
Diffstat (limited to 'Ryujinx.HLE/HOS/Services')
54 files changed, 682 insertions, 390 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs index f131aff8..55539637 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs @@ -4,7 +4,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService { class ISystemAppletProxy : IpcService { - public ISystemAppletProxy() { } + private readonly long _pid; + + public ISystemAppletProxy(long pid) + { + _pid = pid; + } [Command(0)] // GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter> @@ -19,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService // GetSelfController() -> object<nn::am::service::ISelfController> public ResultCode GetSelfController(ServiceCtx context) { - MakeObject(context, new ISelfController(context.Device.System)); + MakeObject(context, new ISelfController(context.Device.System, _pid)); return ResultCode.Success; } @@ -28,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService // GetWindowController() -> object<nn::am::service::IWindowController> public ResultCode GetWindowController(ServiceCtx context) { - MakeObject(context, new IWindowController()); + MakeObject(context, new IWindowController(_pid)); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs index 16ffe9ee..7d9d06e5 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs @@ -18,6 +18,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib private KEvent _normalOutDataEvent; private KEvent _interactiveOutDataEvent; + private int _stateChangedEventHandle; + private int _normalOutDataEventHandle; + private int _interactiveOutDataEventHandle; + public ILibraryAppletAccessor(AppletId appletId, Horizon system) { _stateChangedEvent = new KEvent(system.KernelContext); @@ -32,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib _applet.AppletStateChanged += OnAppletStateChanged; _normalSession.DataAvailable += OnNormalOutData; _interactiveSession.DataAvailable += OnInteractiveOutData; - + Logger.Info?.Print(LogClass.ServiceAm, $"Applet '{appletId}' created."); } @@ -55,12 +59,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib // GetAppletStateChangedEvent() -> handle<copy> public ResultCode GetAppletStateChangedEvent(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_stateChangedEvent.ReadableEvent, out int handle) != KernelResult.Success) + if (_stateChangedEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_stateChangedEvent.ReadableEvent, out _stateChangedEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_stateChangedEventHandle); return ResultCode.Success; } @@ -69,8 +76,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib // Start() public ResultCode Start(ServiceCtx context) { - return (ResultCode)_applet.Start(_normalSession.GetConsumer(), - _interactiveSession.GetConsumer()); + return (ResultCode)_applet.Start(_normalSession.GetConsumer(), _interactiveSession.GetConsumer()); } [Command(30)] @@ -138,12 +144,16 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib // GetPopOutDataEvent() -> handle<copy> public ResultCode GetPopOutDataEvent(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_normalOutDataEvent.ReadableEvent, out int handle) != KernelResult.Success) + if (_normalOutDataEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_normalOutDataEvent.ReadableEvent, out _normalOutDataEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_normalOutDataEventHandle); return ResultCode.Success; } @@ -152,12 +162,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib // GetPopInteractiveOutDataEvent() -> handle<copy> public ResultCode GetPopInteractiveOutDataEvent(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_interactiveOutDataEvent.ReadableEvent, out int handle) != KernelResult.Success) + if (_interactiveOutDataEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_interactiveOutDataEvent.ReadableEvent, out _interactiveOutDataEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_interactiveOutDataEventHandle); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs index 62319d47..e3b73c29 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs @@ -12,7 +12,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys private Apm.SystemManagerServer _apmSystemManagerServer; private Lbl.LblControllerServer _lblControllerServer; - private bool _vrModeEnabled = false; + private bool _vrModeEnabled; + private int _messageEventHandle; + private int _displayResolutionChangedEventHandle; public ICommonStateGetter(ServiceCtx context) { @@ -25,14 +27,17 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys // GetEventHandle() -> handle<copy> public ResultCode GetEventHandle(ServiceCtx context) { - KEvent Event = context.Device.System.AppletState.MessageEvent; + KEvent messageEvent = context.Device.System.AppletState.MessageEvent; - if (context.Process.HandleTable.GenerateHandle(Event.ReadableEvent, out int handle) != KernelResult.Success) + if (_messageEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(messageEvent.ReadableEvent, out _messageEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_messageEventHandle); return ResultCode.Success; } @@ -147,7 +152,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys _lblControllerServer.DisableVrMode(); } - // TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used. + // TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used. } [Command(60)] // 3.0.0+ @@ -164,12 +169,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys // GetDefaultDisplayResolutionChangeEvent() -> handle<copy> public ResultCode GetDefaultDisplayResolutionChangeEvent(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(context.Device.System.DisplayResolutionChangeEvent.ReadableEvent, out int handle) != KernelResult.Success) + if (_displayResolutionChangedEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(context.Device.System.DisplayResolutionChangeEvent.ReadableEvent, out _displayResolutionChangedEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_displayResolutionChangedEventHandle); Logger.Stub?.PrintStub(LogClass.ServiceAm); @@ -189,7 +197,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys _apmSystemManagerServer.SetCpuBoostMode((Apm.CpuBoostMode)cpuBoostMode); - // TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used. + // TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used. return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs index 5fafa154..580574a8 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs @@ -9,6 +9,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys class IHomeMenuFunctions : IpcService { private KEvent _channelEvent; + private int _channelEventHandle; public IHomeMenuFunctions(Horizon system) { @@ -29,12 +30,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys // GetPopFromGeneralChannelEvent() -> handle<copy> public ResultCode GetPopFromGeneralChannelEvent(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_channelEvent.ReadableEvent, out int handle) != KernelResult.Success) + if (_channelEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_channelEvent.ReadableEvent, out _channelEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_channelEventHandle); Logger.Stub?.PrintStub(LogClass.ServiceAm); diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs index decf5470..5b91e235 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs @@ -49,7 +49,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys } var data = new byte[transferMem.Size]; - context.Memory.Read(transferMem.Address, data); + transferMem.Creator.CpuMemory.Read(transferMem.Address, data); + + context.Device.System.KernelContext.Syscall.CloseHandle(handle); MakeObject(context, new IStorage(data)); diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs index 8b1275ac..b2cc7160 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs @@ -8,10 +8,13 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys { class ISelfController : IpcService { + private readonly long _pid; + private KEvent _libraryAppletLaunchableEvent; + private int _libraryAppletLaunchableEventHandle; private KEvent _accumulatedSuspendedTickChangedEvent; - private int _accumulatedSuspendedTickChangedEventHandle = 0; + private int _accumulatedSuspendedTickChangedEventHandle; private object _fatalSectionLock = new object(); private int _fatalSectionCount; @@ -32,9 +35,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys private uint _screenShotImageOrientation = 0; private uint _idleTimeDetectionExtension = 0; - public ISelfController(Horizon system) + public ISelfController(Horizon system, long pid) { _libraryAppletLaunchableEvent = new KEvent(system.KernelContext); + _pid = pid; } [Command(0)] @@ -103,12 +107,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys { _libraryAppletLaunchableEvent.ReadableEvent.Signal(); - if (context.Process.HandleTable.GenerateHandle(_libraryAppletLaunchableEvent.ReadableEvent, out int handle) != KernelResult.Success) + if (_libraryAppletLaunchableEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_libraryAppletLaunchableEvent.ReadableEvent, out _libraryAppletLaunchableEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_libraryAppletLaunchableEventHandle); Logger.Stub?.PrintStub(LogClass.ServiceAm); @@ -206,6 +213,31 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys return ResultCode.Success; } + [Command(40)] + // CreateManagedDisplayLayer() -> u64 + public ResultCode CreateManagedDisplayLayer(ServiceCtx context) + { + context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long layerId); + + context.ResponseData.Write(layerId); + + return ResultCode.Success; + } + + [Command(44)] // 10.0.0+ + // CreateManagedDisplaySeparableLayer() -> (u64, u64) + public ResultCode CreateManagedDisplaySeparableLayer(ServiceCtx context) + { + // NOTE: first create the recoding layer and then the display one because right now Surface Flinger only use the last id. + context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long recordingLayerId); + context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long displayLayerId); + + context.ResponseData.Write(displayLayerId); + context.ResponseData.Write(recordingLayerId); + + return ResultCode.Success; + } + [Command(50)] // SetHandlesRequestToDisplay(b8) public ResultCode SetHandlesRequestToDisplay(ServiceCtx context) diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs index 5c5c9b88..8c127b98 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs @@ -4,7 +4,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys { class IWindowController : IpcService { - public IWindowController() { } + private readonly long _pid; + + public IWindowController(long pid) + { + _pid = pid; + } [Command(1)] // GetAppletResourceUserId() -> nn::applet::AppletResourceUserId @@ -12,7 +17,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys { Logger.Stub?.PrintStub(LogClass.ServiceAm); - context.ResponseData.Write(0L); + long appletResourceUserId = context.Device.System.AppletState.AppletResourceUserIds.Add(_pid); + + context.ResponseData.Write(appletResourceUserId); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs index d29a8da4..d518dde4 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs @@ -11,7 +11,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE // OpenSystemAppletProxy(u64, pid, handle<copy>) -> object<nn::am::service::ISystemAppletProxy> public ResultCode OpenSystemAppletProxy(ServiceCtx context) { - MakeObject(context, new ISystemAppletProxy()); + MakeObject(context, new ISystemAppletProxy(context.Request.HandleDesc.PId)); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs index b9dfee30..6a5ad4c1 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs @@ -28,6 +28,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati private KEvent _friendInvitationStorageChannelEvent; private KEvent _notificationStorageChannelEvent; + private int _gpuErrorDetectedSystemEventHandle; + private int _friendInvitationStorageChannelEventHandle; + private int _notificationStorageChannelEventHandle; + public IApplicationFunctions(Horizon system) { _gpuErrorDetectedSystemEvent = new KEvent(system.KernelContext); @@ -122,7 +126,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati return ResultCode.Success; } - // If desired language is not supported by application, use first supported language from TitleLanguage. + // If desired language is not supported by application, use first supported language from TitleLanguage. // TODO: In the future, a GUI could enable user-specified search priority if (((1 << (int)context.Device.System.State.DesiredTitleLanguage) & supportedLanguages) == 0) { @@ -293,12 +297,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati resultCode = InitializeApplicationCopyrightFrameBufferImpl(transferMemoryAddress, transferMemorySize, width, height); } - /* - if (transferMemoryHandle) + if (transferMemoryHandle != 0) { - svcCloseHandle(transferMemoryHandle); + context.Device.System.KernelContext.Syscall.CloseHandle(transferMemoryHandle); } - */ return resultCode; } @@ -455,15 +457,18 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati // GetGpuErrorDetectedSystemEvent() -> handle<copy> public ResultCode GetGpuErrorDetectedSystemEvent(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_gpuErrorDetectedSystemEvent.ReadableEvent, out int gpuErrorDetectedSystemEventHandle) != KernelResult.Success) + if (_gpuErrorDetectedSystemEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_gpuErrorDetectedSystemEvent.ReadableEvent, out _gpuErrorDetectedSystemEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(gpuErrorDetectedSystemEventHandle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_gpuErrorDetectedSystemEventHandle); - // NOTE: This is used by "sdk" NSO during applet-application initialization. - // A seperate thread is setup where event-waiting is handled. + // NOTE: This is used by "sdk" NSO during applet-application initialization. + // A seperate thread is setup where event-waiting is handled. // When the Event is signaled, official sw will assert. return ResultCode.Success; @@ -473,12 +478,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati // GetFriendInvitationStorageChannelEvent() -> handle<copy> public ResultCode GetFriendInvitationStorageChannelEvent(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_friendInvitationStorageChannelEvent.ReadableEvent, out int friendInvitationStorageChannelEventHandle) != KernelResult.Success) + if (_friendInvitationStorageChannelEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_friendInvitationStorageChannelEvent.ReadableEvent, out _friendInvitationStorageChannelEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(friendInvitationStorageChannelEventHandle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_friendInvitationStorageChannelEventHandle); return ResultCode.Success; } @@ -501,12 +509,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati // GetNotificationStorageChannelEvent() -> handle<copy> public ResultCode GetNotificationStorageChannelEvent(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_notificationStorageChannelEvent.ReadableEvent, out int notificationStorageChannelEventHandle) != KernelResult.Success) + if (_notificationStorageChannelEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_notificationStorageChannelEvent.ReadableEvent, out _notificationStorageChannelEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(notificationStorageChannelEventHandle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_notificationStorageChannelEventHandle); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs index 700886fd..28a52573 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs @@ -5,7 +5,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService { class IApplicationProxy : IpcService { - public IApplicationProxy() { } + private readonly long _pid; + + public IApplicationProxy(long pid) + { + _pid = pid; + } [Command(0)] // GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter> @@ -20,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService // GetSelfController() -> object<nn::am::service::ISelfController> public ResultCode GetSelfController(ServiceCtx context) { - MakeObject(context, new ISelfController(context.Device.System)); + MakeObject(context, new ISelfController(context.Device.System, _pid)); return ResultCode.Success; } @@ -29,7 +34,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService // GetWindowController() -> object<nn::am::service::IWindowController> public ResultCode GetWindowController(ServiceCtx context) { - MakeObject(context, new IWindowController()); + MakeObject(context, new IWindowController(_pid)); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs b/Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs index 0aee24fe..8487d319 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs @@ -11,7 +11,7 @@ namespace Ryujinx.HLE.HOS.Services.Am // OpenApplicationProxy(u64, pid, handle<copy>) -> object<nn::am::service::IApplicationProxy> public ResultCode OpenApplicationProxy(ServiceCtx context) { - MakeObject(context, new IApplicationProxy()); + MakeObject(context, new IApplicationProxy(context.Request.HandleDesc.PId)); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioOutManager/IAudioOut.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioOutManager/IAudioOut.cs index af9cccb2..86e5566a 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioOutManager/IAudioOut.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioOutManager/IAudioOut.cs @@ -10,15 +10,18 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioOutManager { class IAudioOut : IpcService, IDisposable { - private IAalOutput _audioOut; - private KEvent _releaseEvent; - private int _track; + private readonly IAalOutput _audioOut; + private readonly KEvent _releaseEvent; + private int _releaseEventHandle; + private readonly int _track; + private readonly int _clientHandle; - public IAudioOut(IAalOutput audioOut, KEvent releaseEvent, int track) + public IAudioOut(IAalOutput audioOut, KEvent releaseEvent, int track, int clientHandle) { _audioOut = audioOut; _releaseEvent = releaseEvent; _track = track; + _clientHandle = clientHandle; } [Command(0)] @@ -59,12 +62,15 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioOutManager // RegisterBufferEvent() -> handle<copy> public ResultCode RegisterBufferEvent(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_releaseEvent.ReadableEvent, out int handle) != KernelResult.Success) + if (_releaseEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_releaseEvent.ReadableEvent, out _releaseEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_releaseEventHandle); return ResultCode.Success; } @@ -108,7 +114,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioOutManager // NOTE: Assume PCM16 all the time, change if new format are found. short[] buffer = new short[data.SampleBufferSize / sizeof(short)]; - context.Memory.Read((ulong)data.SampleBufferPtr, MemoryMarshal.Cast<short, byte>(buffer)); + context.Process.HandleTable.GetKProcess(_clientHandle).CpuMemory.Read((ulong)data.SampleBufferPtr, MemoryMarshal.Cast<short, byte>(buffer)); _audioOut.AppendBuffer(_track, tag, buffer); diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs index e12a9919..5aff3475 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs @@ -33,7 +33,9 @@ namespace Ryujinx.HLE.HOS.Services.Audio public ResultCode OpenAudioRenderer(ServiceCtx context, out IAudioRenderer obj, ref AudioRendererConfiguration parameter, ulong workBufferSize, ulong appletResourceUserId, KTransferMemory workBufferTransferMemory, uint processHandle) { - ResultCode result = (ResultCode)_impl.OpenAudioRenderer(out AudioRenderSystem renderer, context.Memory, ref parameter, appletResourceUserId, workBufferTransferMemory.Address, workBufferTransferMemory.Size, processHandle); + var memoryManager = context.Process.HandleTable.GetKProcess((int)processHandle).CpuMemory; + + ResultCode result = (ResultCode)_impl.OpenAudioRenderer(out AudioRenderSystem renderer, memoryManager, ref parameter, appletResourceUserId, workBufferTransferMemory.Address, workBufferTransferMemory.Size, processHandle); if (result == ResultCode.Success) { diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs index effd8f15..a789dfed 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs @@ -14,9 +14,9 @@ namespace Ryujinx.HLE.HOS.Services.Audio private IAudioRendererManager _impl; - public AudioRendererManagerServer(ServiceCtx context) : this(new AudioRendererManager(context.Device.System.AudioRendererManager, context.Device.System.AudioDeviceSessionRegistry)) { } + public AudioRendererManagerServer(ServiceCtx context) : this(context, new AudioRendererManager(context.Device.System.AudioRendererManager, context.Device.System.AudioDeviceSessionRegistry)) { } - public AudioRendererManagerServer(IAudioRendererManager impl) : base(new ServerBase("AudioRendererServer")) + public AudioRendererManagerServer(ServiceCtx context, IAudioRendererManager impl) : base(new ServerBase(context.Device.System.KernelContext, "AudioRendererServer")) { _impl = impl; } @@ -40,6 +40,8 @@ namespace Ryujinx.HLE.HOS.Services.Audio MakeObject(context, new AudioRendererServer(renderer)); } + context.Device.System.KernelContext.Syscall.CloseHandle((int)processHandle); + return result; } diff --git a/Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs b/Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs index 3081cd49..b3f7f5e0 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs @@ -1,4 +1,5 @@ using Ryujinx.Cpu; +using Ryujinx.Memory; using System; using System.Text; @@ -57,7 +58,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio return ResultCode.Success; } - private uint ListAudioInsImpl(MemoryManager memory, long bufferPosition, long bufferSize, bool filtered = false) + private uint ListAudioInsImpl(IVirtualMemoryManager memory, long bufferPosition, long bufferSize, bool filtered = false) { uint count = 0; diff --git a/Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs b/Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs index 646acef4..91ec287c 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs @@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio private const int DefaultSampleRate = 48000; private const int DefaultChannelsCount = 2; - public IAudioOutManager(ServiceCtx context) : base(new ServerBase("AudioOutServer")) { } + public IAudioOutManager(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "AudioOutServer")) { } [Command(0)] // ListAudioOuts() -> (u32 count, buffer<bytes, 6>) @@ -134,7 +134,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio int track = audioOut.OpenTrack(sampleRate, channels, callback); - MakeObject(context, new IAudioOut(audioOut, releaseEvent, track)); + MakeObject(context, new IAudioOut(audioOut, releaseEvent, track, context.Request.HandleDesc.ToCopy[0])); context.ResponseData.Write(sampleRate); context.ResponseData.Write(channels); diff --git a/Ryujinx.HLE/HOS/Services/Audio/IHardwareOpusDecoderManager.cs b/Ryujinx.HLE/HOS/Services/Audio/IHardwareOpusDecoderManager.cs index ed40cdad..c8cc281e 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/IHardwareOpusDecoderManager.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/IHardwareOpusDecoderManager.cs @@ -16,6 +16,9 @@ namespace Ryujinx.HLE.HOS.Services.Audio MakeObject(context, new IHardwareOpusDecoder(sampleRate, channelsCount)); + // Close transfer memory immediately as we don't use it. + context.Device.System.KernelContext.Syscall.CloseHandle(context.Request.HandleDesc.ToCopy[0]); + return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs b/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs index d56a6a43..54b1a58a 100644 --- a/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs +++ b/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs @@ -12,6 +12,7 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator class IDeliveryCacheProgressService : IpcService { private KEvent _event; + private int _eventHandle; public IDeliveryCacheProgressService(ServiceCtx context) { @@ -22,12 +23,15 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator // GetEvent() -> handle<copy> public ResultCode GetEvent(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out int handle) != KernelResult.Success) + if (_eventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out _eventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_eventHandle); Logger.Stub?.PrintStub(LogClass.ServiceBcat); diff --git a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index 44f406a0..e29a040f 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs } [Command(8)] - // OpenFileSystemWithId(nn::fssrv::sf::FileSystemType filesystem_type, nn::ApplicationId tid, buffer<bytes<0x301>, 0x19, 0x301> path) + // OpenFileSystemWithId(nn::fssrv::sf::FileSystemType filesystem_type, nn::ApplicationId tid, buffer<bytes<0x301>, 0x19, 0x301> path) // -> object<nn::fssrv::sf::IFileSystem> contentFs public ResultCode OpenFileSystemWithId(ServiceCtx context) { @@ -138,12 +138,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs // Workaround that by setting the application ID and owner ID if they're not already set if (attribute.ProgramId == ProgramId.InvalidId) { - attribute.ProgramId = new ProgramId(context.Process.TitleId); - } - - if (creationInfo.OwnerId == 0) - { - creationInfo.OwnerId = 0; + attribute.ProgramId = new ProgramId(context.Device.Application.TitleId); } Logger.Info?.Print(LogClass.ServiceFs, $"Creating save with title ID {attribute.ProgramId.Value:x16}"); @@ -215,12 +210,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs // Workaround that by setting the application ID and owner ID if they're not already set if (attribute.ProgramId == ProgramId.InvalidId) { - attribute.ProgramId = new ProgramId(context.Process.TitleId); - } - - if (creationInfo.OwnerId == 0) - { - creationInfo.OwnerId = 0; + attribute.ProgramId = new ProgramId(context.Device.Application.TitleId); } Result result = _baseFileSystemProxy.CreateSaveDataFileSystemWithHashSalt(ref attribute, ref creationInfo, ref metaCreateInfo, ref hashSalt); @@ -239,7 +229,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs // Workaround that by setting the application ID if it's not already set if (attribute.ProgramId == ProgramId.InvalidId) { - attribute.ProgramId = new ProgramId(context.Process.TitleId); + attribute.ProgramId = new ProgramId(context.Device.Application.TitleId); } Result result = _baseFileSystemProxy.OpenSaveDataFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem, spaceId, ref attribute); @@ -280,7 +270,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs // Workaround that by setting the application ID if it's not already set if (attribute.ProgramId == ProgramId.InvalidId) { - attribute.ProgramId = new ProgramId(context.Process.TitleId); + attribute.ProgramId = new ProgramId(context.Device.Application.TitleId); } Result result = _baseFileSystemProxy.OpenReadOnlySaveDataFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem, spaceId, ref attribute); @@ -328,7 +318,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs filter.SetSaveDataType(SaveDataType.Cache); filter.SetProgramId(new ProgramId(context.Process.TitleId)); - // FS would query the User and SdCache space IDs to find where the existing cache is (if any). + // FS would query the User and SdCache space IDs to find where the existing cache is (if any). // We always have the SD card inserted, so we can always use SdCache for now. Result result = _baseFileSystemProxy.OpenSaveDataInfoReaderBySaveDataSpaceId( out ReferenceCountedDisposable<LibHac.FsSrv.ISaveDataInfoReader> infoReader, SaveDataSpaceId.SdCache); diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs b/Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs index 2c3a6500..dfce2d73 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs @@ -8,6 +8,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer class IAppletResource : IpcService { private KSharedMemory _hidSharedMem; + private int _hidSharedMemHandle; public IAppletResource(KSharedMemory hidSharedMem) { @@ -18,12 +19,15 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer // GetSharedMemoryHandle() -> handle<copy> public ResultCode GetSharedMemoryHandle(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_hidSharedMem, out int handle) != KernelResult.Success) + if (_hidSharedMemHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_hidSharedMem, out _hidSharedMemHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_hidSharedMemHandle); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs index d3bf9319..dfcf2b25 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs @@ -35,7 +35,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid private HidAccelerometerParameters _accelerometerParams; private HidVibrationValue _vibrationValue; - public IHidServer(ServiceCtx context) : base(new ServerBase("HidServer")) + public IHidServer(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "HidServer")) { _xpadIdEvent = new KEvent(context.Device.System.KernelContext); _palmaOperationCompleteEvent = new KEvent(context.Device.System.KernelContext); @@ -559,9 +559,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid ControllerType type = (ControllerType)context.RequestData.ReadInt32(); long appletResourceUserId = context.RequestData.ReadInt64(); - Logger.Stub?.PrintStub(LogClass.ServiceHid, new { - appletResourceUserId, - type + Logger.Stub?.PrintStub(LogClass.ServiceHid, new { + appletResourceUserId, + type }); context.Device.Hid.Npads.SupportedStyleSets = type; @@ -577,9 +577,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid context.ResponseData.Write((int)context.Device.Hid.Npads.SupportedStyleSets); - Logger.Stub?.PrintStub(LogClass.ServiceHid, new { + Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, - context.Device.Hid.Npads.SupportedStyleSets + context.Device.Hid.Npads.SupportedStyleSets }); return ResultCode.Success; @@ -704,9 +704,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid long appletResourceUserId = context.RequestData.ReadInt64(); context.Device.Hid.Npads.JoyHold = (NpadJoyHoldType)context.RequestData.ReadInt64(); - Logger.Stub?.PrintStub(LogClass.ServiceHid, new { - appletResourceUserId, - context.Device.Hid.Npads.JoyHold + Logger.Stub?.PrintStub(LogClass.ServiceHid, new { + appletResourceUserId, + context.Device.Hid.Npads.JoyHold }); return ResultCode.Success; @@ -720,9 +720,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid context.ResponseData.Write((long)context.Device.Hid.Npads.JoyHold); - Logger.Stub?.PrintStub(LogClass.ServiceHid, new { - appletResourceUserId, - context.Device.Hid.Npads.JoyHold + Logger.Stub?.PrintStub(LogClass.ServiceHid, new { + appletResourceUserId, + context.Device.Hid.Npads.JoyHold }); return ResultCode.Success; diff --git a/Ryujinx.HLE/HOS/Services/IpcService.cs b/Ryujinx.HLE/HOS/Services/IpcService.cs index 9d40d80f..f9858107 100644 --- a/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -1,8 +1,6 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel.Common; -using Ryujinx.HLE.HOS.Kernel.Ipc; using System; using System.Collections.Generic; using System.IO; @@ -17,6 +15,7 @@ namespace Ryujinx.HLE.HOS.Services public ServerBase Server { get; private set; } + private IpcService _parent; private IdDictionary _domainObjects; private int _selfId; private bool _isDomain; @@ -32,6 +31,7 @@ namespace Ryujinx.HLE.HOS.Services Server = server; + _parent = this; _domainObjects = new IdDictionary(); _selfId = -1; } @@ -62,8 +62,8 @@ namespace Ryujinx.HLE.HOS.Services int domainWord0 = context.RequestData.ReadInt32(); int domainObjId = context.RequestData.ReadInt32(); - int domainCmd = (domainWord0 >> 0) & 0xff; - int inputObjCount = (domainWord0 >> 8) & 0xff; + int domainCmd = (domainWord0 >> 0) & 0xff; + int inputObjCount = (domainWord0 >> 8) & 0xff; int dataPayloadSize = (domainWord0 >> 16) & 0xffff; context.RequestData.BaseStream.Seek(0x10 + dataPayloadSize, SeekOrigin.Begin); @@ -96,8 +96,8 @@ namespace Ryujinx.HLE.HOS.Services } } - long sfciMagic = context.RequestData.ReadInt64(); - int commandId = (int)context.RequestData.ReadInt64(); + long sfciMagic = context.RequestData.ReadInt64(); + int commandId = (int)context.RequestData.ReadInt64(); bool serviceExists = service.Commands.TryGetValue(commandId, out MethodInfo processRequest); @@ -145,56 +145,37 @@ namespace Ryujinx.HLE.HOS.Services { string dbgMessage = $"{service.GetType().FullName}: {commandId}"; - throw new ServiceNotImplementedException(context, dbgMessage); + throw new ServiceNotImplementedException(service, context, dbgMessage); } } - protected static void MakeObject(ServiceCtx context, IpcService obj) + protected void MakeObject(ServiceCtx context, IpcService obj) { - IpcService service = context.Session.Service; + obj.TrySetServer(_parent.Server); - obj.TrySetServer(service.Server); - - if (service._isDomain) + if (_parent._isDomain) { - context.Response.ObjectIds.Add(service.Add(obj)); + obj._parent = _parent; + + context.Response.ObjectIds.Add(_parent.Add(obj)); } else { - KSession session = new KSession(context.Device.System.KernelContext); - - session.ClientSession.Service = obj; - - if (context.Process.HandleTable.GenerateHandle(session.ClientSession, out int handle) != KernelResult.Success) - { - throw new InvalidOperationException("Out of handles!"); - } + context.Device.System.KernelContext.Syscall.CreateSession(false, 0, out int serverSessionHandle, out int clientSessionHandle); - session.ServerSession.DecrementReferenceCount(); - session.ClientSession.DecrementReferenceCount(); + obj.Server.AddSessionObj(serverSessionHandle, obj); - context.Response.HandleDesc = IpcHandleDesc.MakeMove(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeMove(clientSessionHandle); } } - protected static T GetObject<T>(ServiceCtx context, int index) where T : IpcService + protected T GetObject<T>(ServiceCtx context, int index) where T : IpcService { - IpcService service = context.Session.Service; - - if (!service._isDomain) - { - int handle = context.Request.HandleDesc.ToMove[index]; - - KClientSession session = context.Process.HandleTable.GetObject<KClientSession>(handle); - - return session?.Service is T ? (T)session.Service : null; - } - int objId = context.Request.ObjectIds[index]; - IIpcService obj = service.GetObject(objId); + IIpcService obj = _parent.GetObject(objId); - return obj is T ? (T)obj : null; + return obj is T t ? t : null; } public bool TrySetServer(ServerBase newServer) @@ -230,5 +211,10 @@ namespace Ryujinx.HLE.HOS.Services { return _domainObjects.GetData<IIpcService>(id); } + + public void SetParent(IpcService parent) + { + _parent = parent._parent; + } } } diff --git a/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs b/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs index bc55d1a1..2cd35b9e 100644 --- a/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs +++ b/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs @@ -103,98 +103,98 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp // StartDetection(bytes<8, 4>) public ResultCode StartDetection(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(4)] // StopDetection(bytes<8, 4>) public ResultCode StopDetection(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(5)] // Mount(bytes<8, 4>, u32, u32) public ResultCode Mount(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(6)] // Unmount(bytes<8, 4>) public ResultCode Unmount(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(7)] // OpenApplicationArea(bytes<8, 4>, u32) public ResultCode OpenApplicationArea(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(8)] // GetApplicationArea(bytes<8, 4>) -> (u32, buffer<unknown, 6>) public ResultCode GetApplicationArea(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(9)] // SetApplicationArea(bytes<8, 4>, buffer<unknown, 5>) public ResultCode SetApplicationArea(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(10)] // Flush(bytes<8, 4>) public ResultCode Flush(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(11)] // Restore(bytes<8, 4>) public ResultCode Restore(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(12)] // CreateApplicationArea(bytes<8, 4>, u32, buffer<unknown, 5>) public ResultCode CreateApplicationArea(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(13)] // GetTagInfo(bytes<8, 4>) -> buffer<unknown<0x58>, 0x1a> public ResultCode GetTagInfo(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(14)] // GetRegisterInfo(bytes<8, 4>) -> buffer<unknown<0x100>, 0x1a> public ResultCode GetRegisterInfo(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(15)] // GetCommonInfo(bytes<8, 4>) -> buffer<unknown<0x40>, 0x1a> public ResultCode GetCommonInfo(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(16)] // GetModelInfo(bytes<8, 4>) -> buffer<unknown<0x40>, 0x1a> public ResultCode GetModelInfo(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(17)] @@ -308,7 +308,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp // GetApplicationAreaSize(bytes<8, 4>) -> u32 public ResultCode GetApplicationAreaSize(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(23)] // 3.0.0+ @@ -334,7 +334,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp // RecreateApplicationArea(bytes<8, 4>, u32, buffer<unknown, 5>) public ResultCode RecreateApplicationArea(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs b/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs index 2f6be8bf..51f9487f 100644 --- a/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs +++ b/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs @@ -11,6 +11,9 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService private KEvent _event0; private KEvent _event1; + private int _event0Handle; + private int _event1Handle; + private uint _version; public IRequest(Horizon system, uint version) @@ -50,17 +53,23 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService // GetSystemEventReadableHandles() -> (handle<copy>, handle<copy>) public ResultCode GetSystemEventReadableHandles(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_event0.ReadableEvent, out int handle0) != KernelResult.Success) + if (_event0Handle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_event0.ReadableEvent, out _event0Handle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - if (context.Process.HandleTable.GenerateHandle(_event1.ReadableEvent, out int handle1) != KernelResult.Success) + if (_event1Handle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_event1.ReadableEvent, out _event1Handle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle0, handle1); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_event0Handle, _event1Handle); return ResultCode.Success; } @@ -107,7 +116,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService return ResultCode.Unknown180; } - // Returns appletId, libraryAppletMode, outSize and a buffer. + // Returns appletId, libraryAppletMode, outSize and a buffer. // Returned applet ids- (0x19, 0xf, 0xe) // libraryAppletMode seems to be 0 for all applets supported. diff --git a/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs b/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs index 8cfafb1a..e6fca499 100644 --- a/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs +++ b/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs @@ -11,6 +11,8 @@ namespace Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServ { private readonly KEvent _event; + private int _eventHandle; + public IShopServiceAccessor(Horizon system) { _event = new KEvent(system.KernelContext); @@ -22,12 +24,15 @@ namespace Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServ { MakeObject(context, new IShopServiceAsync()); - if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out int handle) != KernelResult.Success) + if (_eventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out _eventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_eventHandle); Logger.Stub?.PrintStub(LogClass.ServiceNim); diff --git a/Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs b/Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs index e9f27cb5..debcd57e 100644 --- a/Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs +++ b/Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs @@ -9,7 +9,9 @@ namespace Ryujinx.HLE.HOS.Services.Ns [Service("aoc:u")] class IAddOnContentManager : IpcService { - KEvent _addOnContentListChangedEvent; + private readonly KEvent _addOnContentListChangedEvent; + + private int _addOnContentListChangedEventHandle; public IAddOnContentManager(ServiceCtx context) { @@ -22,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns { long pid = context.Process.Pid; - // Official code checks ApplicationControlProperty.RuntimeAddOnContentInstall + // Official code checks ApplicationControlProperty.RuntimeAddOnContentInstall // if true calls ns:am ListAvailableAddOnContent again to get updated count byte runtimeAddOnContentInstall = context.Device.Application.ControlData.Value.RuntimeAddOnContentInstall; @@ -135,12 +137,15 @@ namespace Ryujinx.HLE.HOS.Services.Ns { // Official code seems to make an internal call to ns:am Cmd 84 GetDynamicCommitEvent() - if (context.Process.HandleTable.GenerateHandle(_addOnContentListChangedEvent.ReadableEvent, out int handle) != KernelResult.Success) + if (_addOnContentListChangedEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(_addOnContentListChangedEvent.ReadableEvent, out _addOnContentListChangedEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_addOnContentListChangedEventHandle); Logger.Stub?.PrintStub(LogClass.ServiceNs); @@ -148,7 +153,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns } - [Command(9)] // [10.0.0+] + [Command(9)] // [10.0.0+] // GetAddOnContentLostErrorCode() -> u64 public ResultCode GetAddOnContentLostErrorCode(ServiceCtx context) { diff --git a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs index 0812683b..9f1ace36 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs @@ -4,7 +4,6 @@ using Ryujinx.Cpu; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Kernel.Memory; -using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel; @@ -12,6 +11,7 @@ using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; using Ryujinx.HLE.HOS.Services.Nv.Types; +using Ryujinx.Memory; using System; using System.Collections.Generic; using System.Reflection; @@ -27,47 +27,45 @@ namespace Ryujinx.HLE.HOS.Services.Nv private static Dictionary<string, Type> _deviceFileRegistry = new Dictionary<string, Type>() { - { "/dev/nvmap", typeof(NvMapDeviceFile) }, - { "/dev/nvhost-ctrl", typeof(NvHostCtrlDeviceFile) }, - { "/dev/nvhost-ctrl-gpu", typeof(NvHostCtrlGpuDeviceFile) }, - { "/dev/nvhost-as-gpu", typeof(NvHostAsGpuDeviceFile) }, - { "/dev/nvhost-gpu", typeof(NvHostGpuDeviceFile) }, - //{ "/dev/nvhost-msenc", typeof(NvHostChannelDeviceFile) }, - { "/dev/nvhost-nvdec", typeof(NvHostChannelDeviceFile) }, - //{ "/dev/nvhost-nvjpg", typeof(NvHostChannelDeviceFile) }, - { "/dev/nvhost-vic", typeof(NvHostChannelDeviceFile) }, - //{ "/dev/nvhost-display", typeof(NvHostChannelDeviceFile) }, + { "/dev/nvmap", typeof(NvMapDeviceFile) }, + { "/dev/nvhost-ctrl", typeof(NvHostCtrlDeviceFile) }, + { "/dev/nvhost-ctrl-gpu", typeof(NvHostCtrlGpuDeviceFile) }, + { "/dev/nvhost-as-gpu", typeof(NvHostAsGpuDeviceFile) }, + { "/dev/nvhost-gpu", typeof(NvHostGpuDeviceFile) }, + //{ "/dev/nvhost-msenc", typeof(NvHostChannelDeviceFile) }, + { "/dev/nvhost-nvdec", typeof(NvHostChannelDeviceFile) }, + //{ "/dev/nvhost-nvjpg", typeof(NvHostChannelDeviceFile) }, + { "/dev/nvhost-vic", typeof(NvHostChannelDeviceFile) }, + //{ "/dev/nvhost-display", typeof(NvHostChannelDeviceFile) }, }; private static IdDictionary _deviceFileIdRegistry = new IdDictionary(); - private KProcess _owner; + private IVirtualMemoryManager _clientMemory; + private long _owner; private bool _transferMemInitialized = false; - public INvDrvServices(ServiceCtx context) : base(new ServerBase("NvservicesServer")) + public INvDrvServices(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "NvservicesServer")) { - _owner = null; + _owner = 0; } private int Open(ServiceCtx context, string path) { - if (context.Process == _owner) + if (_deviceFileRegistry.TryGetValue(path, out Type deviceFileClass)) { - if (_deviceFileRegistry.TryGetValue(path, out Type deviceFileClass)) - { - ConstructorInfo constructor = deviceFileClass.GetConstructor(new Type[] { typeof(ServiceCtx) }); + ConstructorInfo constructor = deviceFileClass.GetConstructor(new Type[] { typeof(ServiceCtx), typeof(IVirtualMemoryManager), typeof(long) }); - NvDeviceFile deviceFile = (NvDeviceFile)constructor.Invoke(new object[] { context }); + NvDeviceFile deviceFile = (NvDeviceFile)constructor.Invoke(new object[] { context, _clientMemory, _owner }); - deviceFile.Path = path; + deviceFile.Path = path; - return _deviceFileIdRegistry.Add(deviceFile); - } - else - { - Logger.Warning?.Print(LogClass.ServiceNv, $"Cannot find file device \"{path}\"!"); - } + return _deviceFileIdRegistry.Add(deviceFile); + } + else + { + Logger.Warning?.Print(LogClass.ServiceNv, $"Cannot find file device \"{path}\"!"); } return -1; @@ -150,7 +148,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv return NvResult.NotImplemented; } - if (deviceFile.Owner.Pid != _owner.Pid) + if (deviceFile.Owner != _owner) { return NvResult.AccessDenied; } @@ -160,7 +158,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv private NvResult EnsureInitialized() { - if (_owner == null) + if (_owner == 0) { Logger.Warning?.Print(LogClass.ServiceNv, "INvDrvServices is not initialized!"); @@ -229,8 +227,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv if (errorCode == NvResult.Success) { long pathPtr = context.Request.SendBuff[0].Position; + long pathSize = context.Request.SendBuff[0].Size; - string path = MemoryHelper.ReadAsciiString(context.Memory, pathPtr); + string path = MemoryHelper.ReadAsciiString(context.Memory, pathPtr, pathSize); fd = Open(context, path); @@ -322,7 +321,11 @@ namespace Ryujinx.HLE.HOS.Services.Nv // TODO: When transfer memory will be implemented, this could be removed. _transferMemInitialized = true; - _owner = context.Process; + int clientHandle = context.Request.HandleDesc.ToCopy[0]; + + _clientMemory = context.Process.HandleTable.GetKProcess(clientHandle).CpuMemory; + + context.Device.System.KernelContext.Syscall.GetProcessId(clientHandle, out _owner); context.ResponseData.Write((uint)NvResult.Success); @@ -425,7 +428,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv // ForceSetClientPid(u64) -> u32 error_code public ResultCode ForceSetClientPid(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(8)] @@ -452,7 +455,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv // InitializeDevtools(u32, handle<copy>) -> u32 error_code; public ResultCode InitializeDevtools(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(11)] // 3.0.0+ diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs index af4734ea..34ff4ccb 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs @@ -1,6 +1,5 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Kernel.Memory; -using Ryujinx.HLE.HOS.Kernel.Process; using System; using System.Diagnostics; using System.Reflection; @@ -12,14 +11,14 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices abstract class NvDeviceFile { public readonly ServiceCtx Context; - public readonly KProcess Owner; + public readonly long Owner; public string Path; - public NvDeviceFile(ServiceCtx context) + public NvDeviceFile(ServiceCtx context, long owner) { Context = context; - Owner = context.Process; + Owner = owner; } public virtual NvInternalResult QueryEvent(out int eventHandle, uint eventId) diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs index 0000f495..6c49fd5c 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs @@ -3,6 +3,7 @@ using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; +using Ryujinx.Memory; using System; using System.Collections.Concurrent; @@ -12,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu { private static ConcurrentDictionary<KProcess, AddressSpaceContext> _addressSpaceContextRegistry = new ConcurrentDictionary<KProcess, AddressSpaceContext>(); - public NvHostAsGpuDeviceFile(ServiceCtx context) : base(context) { } + public NvHostAsGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) { } public override NvInternalResult Ioctl(NvIoctl command, Span<byte> arguments) { diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs index 863b01d1..d675ffc7 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs @@ -5,6 +5,7 @@ using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; using Ryujinx.HLE.HOS.Services.Nv.Types; +using Ryujinx.Memory; using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -19,9 +20,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel private uint _submitTimeout; private uint _timeslice; - private Switch _device; + private readonly Switch _device; - private Cpu.MemoryManager _memory; + private readonly IVirtualMemoryManager _memory; public enum ResourcePolicy { @@ -37,10 +38,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel private NvFence _channelSyncpoint; - public NvHostChannelDeviceFile(ServiceCtx context) : base(context) + public NvHostChannelDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) { _device = context.Device; - _memory = context.Memory; + _memory = memory; _timeout = 3000; _submitTimeout = 0; _timeslice = 0; diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs index 52389140..f27c065e 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs @@ -1,6 +1,7 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types; +using Ryujinx.Memory; using System; namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel @@ -11,7 +12,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel private KEvent _smExceptionBptPauseReportEvent; private KEvent _errorNotifierEvent; - public NvHostGpuDeviceFile(ServiceCtx context) : base(context) + public NvHostGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, memory, owner) { _smExceptionBptIntReportEvent = new KEvent(context.Device.System.KernelContext); _smExceptionBptPauseReportEvent = new KEvent(context.Device.System.KernelContext); @@ -55,7 +56,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel if (targetEvent != null) { - if (Owner.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success) + if (Context.Process.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success) { throw new InvalidOperationException("Out of handles!"); } diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs index a5384596..f0e5634e 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs @@ -5,7 +5,7 @@ using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl.Types; using Ryujinx.HLE.HOS.Services.Nv.Types; using Ryujinx.HLE.HOS.Services.Settings; - +using Ryujinx.Memory; using System; using System.Text; using System.Threading; @@ -20,7 +20,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl private Switch _device; private NvHostEvent[] _events; - public NvHostCtrlDeviceFile(ServiceCtx context) : base(context) + public NvHostCtrlDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) { if (NxSettings.Settings.TryGetValue("nv!rmos_set_production_mode", out object productionModeSetting)) { @@ -126,7 +126,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl if (targetEvent != null) { - if (Owner.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success) + if (Context.Process.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success) { throw new InvalidOperationException("Out of handles!"); } diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs index e0acf0df..840d95b9 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs @@ -2,6 +2,7 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu.Types; +using Ryujinx.Memory; using System; using System.Diagnostics; @@ -15,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu private KEvent _errorEvent; private KEvent _unknownEvent; - public NvHostCtrlGpuDeviceFile(ServiceCtx context) : base(context) + public NvHostCtrlGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) { _errorEvent = new KEvent(context.Device.System.KernelContext); _unknownEvent = new KEvent(context.Device.System.KernelContext); @@ -98,7 +99,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu if (targetEvent != null) { - if (Owner.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success) + if (Context.Process.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success) { throw new InvalidOperationException("Out of handles!"); } diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs index 3cc47c42..a549c81c 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs @@ -1,7 +1,7 @@ using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gpu.Memory; -using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.Memory; using System; using System.Collections.Concurrent; @@ -11,9 +11,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap { private const int FlagNotFreedYet = 1; - private static ConcurrentDictionary<KProcess, IdDictionary> _maps = new ConcurrentDictionary<KProcess, IdDictionary>(); + private static ConcurrentDictionary<long, IdDictionary> _maps = new ConcurrentDictionary<long, IdDictionary>(); - public NvMapDeviceFile(ServiceCtx context) : base(context) + public NvMapDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) { IdDictionary dict = _maps.GetOrAdd(Owner, (key) => new IdDictionary()); @@ -244,9 +244,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap return dict.Add(map); } - private static bool DeleteMapWithHandle(KProcess process, int handle) + private static bool DeleteMapWithHandle(long pid, int handle) { - if (_maps.TryGetValue(process, out IdDictionary dict)) + if (_maps.TryGetValue(pid, out IdDictionary dict)) { return dict.Delete(handle) != null; } @@ -254,14 +254,14 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap return false; } - public static void IncrementMapRefCount(KProcess process, int handle, bool allowHandleZero = false) + public static void IncrementMapRefCount(long pid, int handle, bool allowHandleZero = false) { - GetMapFromHandle(process, handle, allowHandleZero)?.IncrementRefCount(); + GetMapFromHandle(pid, handle, allowHandleZero)?.IncrementRefCount(); } - public static bool DecrementMapRefCount(KProcess process, int handle) + public static bool DecrementMapRefCount(long pid, int handle) { - NvMapHandle map = GetMapFromHandle(process, handle, false); + NvMapHandle map = GetMapFromHandle(pid, handle, false); if (map == null) { @@ -270,7 +270,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap if (map.DecrementRefCount() <= 0) { - DeleteMapWithHandle(process, handle); + DeleteMapWithHandle(pid, handle); Logger.Info?.Print(LogClass.ServiceNv, $"Deleted map {handle}!"); @@ -282,9 +282,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap } } - public static NvMapHandle GetMapFromHandle(KProcess process, int handle, bool allowHandleZero = false) + public static NvMapHandle GetMapFromHandle(long pid, int handle, bool allowHandleZero = false) { - if ((allowHandleZero || handle != 0) && _maps.TryGetValue(process, out IdDictionary dict)) + if ((allowHandleZero || handle != 0) && _maps.TryGetValue(pid, out IdDictionary dict)) { return dict.GetData<NvMapHandle>(handle); } diff --git a/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs b/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs index 46374acc..c78634fa 100644 --- a/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs @@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro return ResultCode.InvalidAddress; } - StructReader reader = new StructReader(context.Memory, nrrAddress); + StructReader reader = new StructReader(_owner.CpuMemory, nrrAddress); NrrHeader header = reader.Read<NrrHeader>(); if (header.Magic != NrrMagic) @@ -71,7 +71,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro { byte[] temp = new byte[0x20]; - context.Memory.Read((ulong)(nrrAddress + header.HashOffset + (i * 0x20)), temp); + _owner.CpuMemory.Read((ulong)(nrrAddress + header.HashOffset + (i * 0x20)), temp); hashes.Add(temp); } @@ -131,8 +131,8 @@ namespace Ryujinx.HLE.HOS.Services.Ro return ResultCode.InvalidAddress; } - uint magic = context.Memory.Read<uint>(nroAddress + 0x10); - uint nroFileSize = context.Memory.Read<uint>(nroAddress + 0x18); + uint magic = _owner.CpuMemory.Read<uint>(nroAddress + 0x10); + uint nroFileSize = _owner.CpuMemory.Read<uint>(nroAddress + 0x18); if (magic != NroMagic || nroSize != nroFileSize) { @@ -141,7 +141,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro byte[] nroData = new byte[nroSize]; - context.Memory.Read(nroAddress, nroData); + _owner.CpuMemory.Read(nroAddress, nroData); byte[] nroHash = null; @@ -176,7 +176,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro // Check if everything is contiguous. if (nro.RoOffset != nro.TextOffset + nro.Text.Length || nro.DataOffset != nro.RoOffset + nro.Ro.Length || - nroFileSize != nro.DataOffset + nro.Data.Length) + nroFileSize != nro.DataOffset + nro.Data.Length) { return ResultCode.InvalidNro; } @@ -337,21 +337,21 @@ namespace Ryujinx.HLE.HOS.Services.Ro KernelResult result; - result = process.MemoryManager.SetProcessMemoryPermission(textStart, roStart - textStart, MemoryPermission.ReadAndExecute); + result = process.MemoryManager.SetProcessMemoryPermission(textStart, roStart - textStart, KMemoryPermission.ReadAndExecute); if (result != KernelResult.Success) { return result; } - result = process.MemoryManager.SetProcessMemoryPermission(roStart, dataStart - roStart, MemoryPermission.Read); + result = process.MemoryManager.SetProcessMemoryPermission(roStart, dataStart - roStart, KMemoryPermission.Read); if (result != KernelResult.Success) { return result; } - return process.MemoryManager.SetProcessMemoryPermission(dataStart, bssEnd - dataStart, MemoryPermission.ReadAndWrite); + return process.MemoryManager.SetProcessMemoryPermission(dataStart, bssEnd - dataStart, KMemoryPermission.ReadAndWrite); } private ResultCode RemoveNrrInfo(long nrrAddress) @@ -420,9 +420,9 @@ namespace Ryujinx.HLE.HOS.Services.Ro return (ResultCode)result; } - private ResultCode IsInitialized(KProcess process) + private ResultCode IsInitialized(long pid) { - if (_owner != null && _owner.Pid == process.Pid) + if (_owner != null && _owner.Pid == pid) { return ResultCode.Success; } @@ -434,7 +434,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro // LoadNro(u64, u64, u64, u64, u64, pid) -> u64 public ResultCode LoadNro(ServiceCtx context) { - ResultCode result = IsInitialized(context.Process); + ResultCode result = IsInitialized(_owner.Pid); // Zero context.RequestData.ReadUInt64(); @@ -454,11 +454,11 @@ namespace Ryujinx.HLE.HOS.Services.Ro if (result == ResultCode.Success) { - result = MapNro(context.Process, info, out nroMappedAddress); + result = MapNro(_owner, info, out nroMappedAddress); if (result == ResultCode.Success) { - result = (ResultCode)SetNroMemoryPermissions(context.Process, info.Executable, nroMappedAddress); + result = (ResultCode)SetNroMemoryPermissions(_owner, info.Executable, nroMappedAddress); if (result == ResultCode.Success) { @@ -479,7 +479,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro // UnloadNro(u64, u64, pid) public ResultCode UnloadNro(ServiceCtx context) { - ResultCode result = IsInitialized(context.Process); + ResultCode result = IsInitialized(_owner.Pid); // Zero context.RequestData.ReadUInt64(); @@ -503,7 +503,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro // LoadNrr(u64, u64, u64, pid) public ResultCode LoadNrr(ServiceCtx context) { - ResultCode result = IsInitialized(context.Process); + ResultCode result = IsInitialized(_owner.Pid); // pid placeholder, zero context.RequestData.ReadUInt64(); @@ -536,7 +536,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro // UnloadNrr(u64, u64, pid) public ResultCode UnloadNrr(ServiceCtx context) { - ResultCode result = IsInitialized(context.Process); + ResultCode result = IsInitialized(_owner.Pid); // pid placeholder, zero context.RequestData.ReadUInt64(); @@ -565,7 +565,8 @@ namespace Ryujinx.HLE.HOS.Services.Ro return ResultCode.InvalidSession; } - _owner = context.Process; + _owner = context.Process.HandleTable.GetKProcess(context.Request.HandleDesc.ToCopy[0]); + context.Device.System.KernelContext.Syscall.CloseHandle(context.Request.HandleDesc.ToCopy[0]); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs b/Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs index 001c38e2..5be54f00 100644 --- a/Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs +++ b/Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs @@ -9,6 +9,8 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pl [Service("pl:s")] // 9.0.0+ class ISharedFontManager : IpcService { + private int _fontSharedMemHandle; + public ISharedFontManager(ServiceCtx context) { } [Command(0)] @@ -63,12 +65,15 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pl { context.Device.System.Font.EnsureInitialized(context.Device.System.ContentManager); - if (context.Process.HandleTable.GenerateHandle(context.Device.System.FontSharedMem, out int handle) != KernelResult.Success) + if (_fontSharedMemHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(context.Device.System.FontSharedMem, out _fontSharedMemHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_fontSharedMemHandle); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/ServerBase.cs b/Ryujinx.HLE/HOS/Services/ServerBase.cs index 211e0e6b..f70d930f 100644 --- a/Ryujinx.HLE/HOS/Services/ServerBase.cs +++ b/Ryujinx.HLE/HOS/Services/ServerBase.cs @@ -1,62 +1,193 @@ -using Ryujinx.Common; using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Ipc; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Threading; using System; +using System.Buffers.Binary; +using System.Collections.Generic; using System.IO; +using System.Threading; namespace Ryujinx.HLE.HOS.Services { class ServerBase { - private struct IpcRequest + // Must be the maximum value used by services (highest one know is the one used by nvservices = 0x8000). + // Having a size that is too low will cause failures as data copy will fail if the receiving buffer is + // not large enough. + private const int PointerBufferSize = 0x8000; + + private readonly static int[] DefaultCapabilities = new int[] { - public Switch Device { get; } - public KProcess Process => Thread?.Owner; - public KThread Thread { get; } - public KClientSession Session { get; } - public ulong MessagePtr { get; } - public ulong MessageSize { get; } - - public IpcRequest(Switch device, KThread thread, KClientSession session, ulong messagePtr, ulong messageSize) - { - Device = device; - Thread = thread; - Session = session; - MessagePtr = messagePtr; - MessageSize = messageSize; - } + 0x030363F7, + 0x1FFFFFCF, + 0x207FFFEF, + 0x47E0060F, + 0x0048BFFF, + 0x01007FFF + }; + + private readonly KernelContext _context; + private readonly KProcess _selfProcess; + + private readonly List<int> _sessionHandles = new List<int>(); + private readonly List<int> _portHandles = new List<int>(); + private readonly Dictionary<int, IpcService> _sessions = new Dictionary<int, IpcService>(); + private readonly Dictionary<int, IpcService> _ports = new Dictionary<int, IpcService>(); + + public ManualResetEvent InitDone { get; } + public IpcService SmObject { get; set; } + public string Name { get; } + + public ServerBase(KernelContext context, string name) + { + InitDone = new ManualResetEvent(false); + Name = name; + _context = context; - public void SignalDone(KernelResult result) - { - Thread.ObjSyncResult = result; - Thread.Reschedule(ThreadSchedState.Running); - } + const ProcessCreationFlags flags = + ProcessCreationFlags.EnableAslr | + ProcessCreationFlags.AddressSpace64Bit | + ProcessCreationFlags.Is64Bit | + ProcessCreationFlags.PoolPartitionSystem; + + ProcessCreationInfo creationInfo = new ProcessCreationInfo("Service", 1, 0, 0x8000000, 1, flags, 0, 0); + + context.Syscall.CreateProcess(creationInfo, DefaultCapabilities, out int handle, null, ServerLoop); + + _selfProcess = context.Scheduler.GetCurrentProcess().HandleTable.GetKProcess(handle); + + context.Syscall.StartProcess(handle, 44, 3, 0x1000); } - private readonly AsyncWorkQueue<IpcRequest> _ipcProcessor; + private void AddPort(int serverPortHandle, IpcService obj) + { + _portHandles.Add(serverPortHandle); + _ports.Add(serverPortHandle, obj); + } - public ServerBase(string name) + public void AddSessionObj(KServerSession serverSession, IpcService obj) { - _ipcProcessor = new AsyncWorkQueue<IpcRequest>(Process, name); + _selfProcess.HandleTable.GenerateHandle(serverSession, out int serverSessionHandle); + AddSessionObj(serverSessionHandle, obj); } - public void PushMessage(Switch device, KThread thread, KClientSession session, ulong messagePtr, ulong messageSize) + public void AddSessionObj(int serverSessionHandle, IpcService obj) { - _ipcProcessor.Add(new IpcRequest(device, thread, session, messagePtr, messageSize)); + _sessionHandles.Add(serverSessionHandle); + _sessions.Add(serverSessionHandle, obj); } - private void Process(IpcRequest message) + private void ServerLoop() { - byte[] reqData = new byte[message.MessageSize]; + if (SmObject != null) + { + _context.Syscall.ManageNamedPort("sm:", 50, out int serverPortHandle); + + AddPort(serverPortHandle, SmObject); + + InitDone.Set(); + } + else + { + InitDone.Dispose(); + } + + KThread thread = _context.Scheduler.GetCurrentThread(); + ulong messagePtr = thread.TlsAddress; + _context.Syscall.SetHeapSize(0x200000, out ulong heapAddr); + + _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0); + _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10); + _selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48)); + + int replyTargetHandle = 0; + + while (true) + { + int[] handles = _portHandles.ToArray(); + + for (int i = 0; i < handles.Length; i++) + { + if (_context.Syscall.AcceptSession(handles[i], out int serverSessionHandle) == KernelResult.Success) + { + AddSessionObj(serverSessionHandle, _ports[handles[i]]); + } + } + + handles = _sessionHandles.ToArray(); + + var rc = _context.Syscall.ReplyAndReceive(handles, replyTargetHandle, 1000000L, out int signaledIndex); + + thread.HandlePostSyscall(); + + if (!thread.Context.Running) + { + break; + } - message.Process.CpuMemory.Read(message.MessagePtr, reqData); + replyTargetHandle = 0; - IpcMessage request = new IpcMessage(reqData, (long)message.MessagePtr); + if (rc == KernelResult.Success && signaledIndex != -1) + { + int signaledHandle = handles[signaledIndex]; + + if (Process(signaledHandle, heapAddr)) + { + replyTargetHandle = signaledHandle; + } + } + else + { + _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0); + _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10); + _selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48)); + } + } + } + + private bool Process(int serverSessionHandle, ulong recvListAddr) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + KThread thread = _context.Scheduler.GetCurrentThread(); + ulong messagePtr = thread.TlsAddress; + ulong messageSize = 0x100; + + byte[] reqData = new byte[messageSize]; + + process.CpuMemory.Read(messagePtr, reqData); + + IpcMessage request = new IpcMessage(reqData, (long)messagePtr); IpcMessage response = new IpcMessage(); + ulong tempAddr = recvListAddr; + int sizesOffset = request.RawData.Length - ((request.RecvListBuff.Count * 2 + 3) & ~3); + + bool noReceive = true; + + for (int i = 0; i < request.ReceiveBuff.Count; i++) + { + noReceive &= (request.ReceiveBuff[i].Position == 0); + } + + if (noReceive) + { + for (int i = 0; i < request.RecvListBuff.Count; i++) + { + int size = BinaryPrimitives.ReadInt16LittleEndian(request.RawData.AsSpan().Slice(sizesOffset + i * 2, 2)); + + response.PtrBuff.Add(new IpcPtrBuffDesc((long)tempAddr, i, size)); + + request.RecvListBuff[i] = new IpcRecvListBuffDesc((long)tempAddr, size); + + tempAddr += (ulong)size; + } + } + + bool shouldReply = true; + using (MemoryStream raw = new MemoryStream(request.RawData)) { BinaryReader reqReader = new BinaryReader(raw); @@ -71,17 +202,16 @@ namespace Ryujinx.HLE.HOS.Services BinaryWriter resWriter = new BinaryWriter(resMs); ServiceCtx context = new ServiceCtx( - message.Device, - message.Process, - message.Process.CpuMemory, - message.Thread, - message.Session, + _context.Device, + process, + process.CpuMemory, + thread, request, response, reqReader, resWriter); - message.Session.Service.CallMethod(context); + _sessions[serverSessionHandle].CallMethod(context); response.RawData = resMs.ToArray(); } @@ -95,11 +225,11 @@ namespace Ryujinx.HLE.HOS.Services switch (cmdId) { case 0: - request = FillResponse(response, 0, message.Session.Service.ConvertToDomain()); + request = FillResponse(response, 0, _sessions[serverSessionHandle].ConvertToDomain()); break; case 3: - request = FillResponse(response, 0, 0x1000); + request = FillResponse(response, 0, PointerBufferSize); break; // TODO: Whats the difference between IpcDuplicateSession/Ex? @@ -107,12 +237,11 @@ namespace Ryujinx.HLE.HOS.Services case 4: int unknown = reqReader.ReadInt32(); - if (message.Process.HandleTable.GenerateHandle(message.Session, out int handle) != KernelResult.Success) - { - throw new InvalidOperationException("Out of handles!"); - } + _context.Syscall.CreateSession(false, 0, out int dupServerSessionHandle, out int dupClientSessionHandle); - response.HandleDesc = IpcHandleDesc.MakeMove(handle); + AddSessionObj(dupServerSessionHandle, _sessions[serverSessionHandle]); + + response.HandleDesc = IpcHandleDesc.MakeMove(dupClientSessionHandle); request = FillResponse(response, 0); @@ -123,18 +252,24 @@ namespace Ryujinx.HLE.HOS.Services } else if (request.Type == IpcMessageType.CloseSession) { - message.SignalDone(KernelResult.PortRemoteClosed); - return; + _context.Syscall.CloseHandle(serverSessionHandle); + _sessionHandles.Remove(serverSessionHandle); + IpcService service = _sessions[serverSessionHandle]; + if (service is IDisposable disposableObj) + { + disposableObj.Dispose(); + } + _sessions.Remove(serverSessionHandle); + shouldReply = false; } else { throw new NotImplementedException(request.Type.ToString()); } - message.Process.CpuMemory.Write(message.MessagePtr, response.GetBytes((long)message.MessagePtr)); + process.CpuMemory.Write(messagePtr, response.GetBytes((long)messagePtr, recvListAddr | ((ulong)PointerBufferSize << 48))); + return shouldReply; } - - message.SignalDone(KernelResult.Success); } private static IpcMessage FillResponse(IpcMessage response, long result, params int[] values) diff --git a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs index d8f31faf..69bb3708 100644 --- a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Ipc; using System; @@ -11,18 +12,17 @@ using System.Reflection; namespace Ryujinx.HLE.HOS.Services.Sm { - [Service("sm:")] class IUserInterface : IpcService { private Dictionary<string, Type> _services; - private ConcurrentDictionary<string, KPort> _registeredServices; + private readonly ConcurrentDictionary<string, KPort> _registeredServices; private readonly ServerBase _commonServer; private bool _isInitialized; - public IUserInterface(ServiceCtx context = null) : base(new ServerBase("SmServer")) + public IUserInterface(KernelContext context) { _registeredServices = new ConcurrentDictionary<string, KPort>(); @@ -31,18 +31,9 @@ namespace Ryujinx.HLE.HOS.Services.Sm .Select(service => (((ServiceAttribute)service).Name, type))) .ToDictionary(service => service.Name, service => service.type); - _commonServer = new ServerBase("CommonServer"); - } - - public static void InitializePort(Horizon system) - { - KPort port = new KPort(system.KernelContext, 256, false, 0); - - port.ClientPort.SetName("sm:"); - - IUserInterface smService = new IUserInterface(); + TrySetServer(new ServerBase(context, "SmServer") { SmObject = this }); - port.ClientPort.Service = smService; + _commonServer = new ServerBase(context, "CommonServer"); } [Command(0)] @@ -92,16 +83,13 @@ namespace Ryujinx.HLE.HOS.Services.Sm : (IpcService)Activator.CreateInstance(type, context); service.TrySetServer(_commonServer); - - session.ClientSession.Service = service; + service.Server.AddSessionObj(session.ServerSession, service); } else { if (ServiceConfiguration.IgnoreMissingServices) { Logger.Warning?.Print(LogClass.Service, $"Missing service {name} ignored"); - - session.ClientSession.Service = new DummyService(name); } else { @@ -142,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm int maxSessions = context.RequestData.ReadInt32(); - if (name == string.Empty) + if (string.IsNullOrEmpty(name)) { return ResultCode.InvalidName; } @@ -185,7 +173,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm int maxSessions = context.RequestData.ReadInt32(); - if (name == string.Empty) + if (string.IsNullOrEmpty(name)) { return ResultCode.InvalidName; } diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs index 4ed62128..f7dd7e17 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs @@ -102,7 +102,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd private List<BsdSocket> _sockets = new List<BsdSocket>(); - public IClient(ServiceCtx context, bool isPrivileged) : base(new ServerBase("BsdServer")) + public IClient(ServiceCtx context, bool isPrivileged) : base(new ServerBase(context.Device.System.KernelContext, "BsdServer")) { _isPrivileged = isPrivileged; } @@ -247,6 +247,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd Logger.Stub?.PrintStub(LogClass.ServiceBsd); + // Close transfer memory immediately as we don't use it. + context.Device.System.KernelContext.Syscall.CloseHandle(context.Request.HandleDesc.ToCopy[0]); + return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs index 02a508b0..90f22dfb 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs @@ -118,14 +118,14 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd // ImportSettings(u32, buffer<unknown, 5>) -> buffer<unknown, 6> public ResultCode ImportSettings(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(15)] // Unknown(bytes<1>) public ResultCode Unknown(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(20)] @@ -164,49 +164,49 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd // GetNasServiceSetting(buffer<unknown<0x10>, 0x15>) -> buffer<unknown<0x108>, 0x16> public ResultCode GetNasServiceSetting(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(31)] // GetNasServiceSettingEx(buffer<unknown<0x10>, 0x15>) -> (u32, buffer<unknown<0x108>, 0x16>) public ResultCode GetNasServiceSettingEx(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(40)] // GetNasRequestFqdn() -> buffer<unknown<0x100>, 0x16> public ResultCode GetNasRequestFqdn(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(41)] // GetNasRequestFqdnEx() -> (u32, buffer<unknown<0x100>, 0x16>) public ResultCode GetNasRequestFqdnEx(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(42)] // GetNasApiFqdn() -> buffer<unknown<0x100>, 0x16> public ResultCode GetNasApiFqdn(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(43)] // GetNasApiFqdnEx() -> (u32, buffer<unknown<0x100>, 0x16>) public ResultCode GetNasApiFqdnEx(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(50)] // GetCurrentSetting() -> buffer<unknown<0x12bf0>, 0x16> public ResultCode GetCurrentSetting(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(60)] @@ -262,7 +262,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd // IsChangeEnvironmentIdentifierDisabled() -> bytes<1> public ResultCode IsChangeEnvironmentIdentifierDisabled(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs index 3dd21fde..2a9a6064 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs @@ -1,15 +1,15 @@ -using Ryujinx.HLE.HOS.Kernel.Process; - -namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger +namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { - class BufferQueue + static class BufferQueue { - public static void CreateBufferQueue(Switch device, KProcess process, out BufferQueueProducer producer, out BufferQueueConsumer consumer) + public static BufferQueueCore CreateBufferQueue(Switch device, long pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer) { - BufferQueueCore core = new BufferQueueCore(device, process); + BufferQueueCore core = new BufferQueueCore(device, pid); producer = new BufferQueueProducer(core); consumer = new BufferQueueConsumer(core); + + return core; } } } diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs index 7f6f6c31..389a980b 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs @@ -1,5 +1,5 @@ using Ryujinx.Common.Logging; -using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.SurfaceFlinger.Types; using System; @@ -40,11 +40,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger private KEvent _waitBufferFreeEvent; private KEvent _frameAvailableEvent; - public KProcess Owner { get; } + public long Owner { get; } + + public bool Active { get; private set; } public const int BufferHistoryArraySize = 8; - public BufferQueueCore(Switch device, KProcess process) + public BufferQueueCore(Switch device, long pid) { Slots = new BufferSlotArray(); IsAbandoned = false; @@ -70,7 +72,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger _waitBufferFreeEvent = new KEvent(device.System.KernelContext); _frameAvailableEvent = new KEvent(device.System.KernelContext); - Owner = process; + Owner = pid; + + Active = true; BufferHistory = new BufferInfo[BufferHistoryArraySize]; EnableExternalEvent = true; @@ -162,6 +166,16 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger } } + public void PrepareForExit() + { + lock (Lock) + { + Active = false; + + Monitor.PulseAll(Lock); + } + } + // TODO: Find an accurate way to handle a regular condvar here as this will wake up unwanted threads in some edge cases. public void SignalDequeueEvent() { @@ -170,7 +184,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger public void WaitDequeueEvent() { - Monitor.Wait(Lock); + Monitor.Exit(Lock); + + KernelStatic.YieldUntilCompletion(WaitForLock); + + Monitor.Enter(Lock); } public void SignalIsAllocatingEvent() @@ -180,7 +198,22 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger public void WaitIsAllocatingEvent() { - Monitor.Wait(Lock); + Monitor.Exit(Lock); + + KernelStatic.YieldUntilCompletion(WaitForLock); + + Monitor.Enter(Lock); + } + + private void WaitForLock() + { + lock (Lock) + { + if (Active) + { + Monitor.Wait(Lock); + } + } } public void FreeBufferLocked(int slot) diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs index 6ef49538..03df04ad 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs @@ -816,6 +816,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger } Core.WaitDequeueEvent(); + + if (!Core.Active) + { + break; + } } } diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs index 8ee943df..b3c81381 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs @@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { abstract class IHOSBinderDriver : IpcService { - public IHOSBinderDriver() {} + public IHOSBinderDriver() { } [Command(0)] // TransactParcel(s32, u32, u32, buffer<unknown, 5, 0>) -> buffer<unknown, 6, 0> diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs index 4713e50b..4927b40e 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs @@ -1,10 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu; -using Ryujinx.HLE.HOS.Kernel.Process; -using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; -using Ryujinx.HLE.HOS.Services.Nv.Types; using System; using System.Collections.Generic; using System.Diagnostics; @@ -40,7 +37,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger public int ProducerBinderId; public IGraphicBufferProducer Producer; public BufferItemConsumer Consumer; - public KProcess Owner; + public BufferQueueCore Core; + public long Owner; } private class TextureCallbackInformation @@ -84,7 +82,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger } } - public IGraphicBufferProducer OpenLayer(KProcess process, long layerId) + public IGraphicBufferProducer OpenLayer(long pid, long layerId) { bool needCreate; @@ -95,13 +93,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger if (needCreate) { - CreateLayerFromId(process, layerId); + CreateLayerFromId(pid, layerId); } return GetProducerByLayerId(layerId); } - public IGraphicBufferProducer CreateLayer(KProcess process, out long layerId) + public IGraphicBufferProducer CreateLayer(long pid, out long layerId) { layerId = 1; @@ -116,25 +114,26 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger } } - CreateLayerFromId(process, layerId); + CreateLayerFromId(pid, layerId); return GetProducerByLayerId(layerId); } - private void CreateLayerFromId(KProcess process, long layerId) + private void CreateLayerFromId(long pid, long layerId) { lock (Lock) { Logger.Info?.Print(LogClass.SurfaceFlinger, $"Creating layer {layerId}"); - BufferQueue.CreateBufferQueue(_device, process, out BufferQueueProducer producer, out BufferQueueConsumer consumer); + BufferQueueCore core = BufferQueue.CreateBufferQueue(_device, pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer); _layers.Add(layerId, new Layer { ProducerBinderId = HOSBinderDriverServer.RegisterBinderObject(producer), Producer = producer, Consumer = new BufferItemConsumer(_device, consumer, 0, -1, false, this), - Owner = process + Core = core, + Owner = pid }); LastId = layerId; @@ -345,6 +344,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger public void Dispose() { _isRunning = false; + + foreach (Layer layer in _layers.Values) + { + layer.Core.PrepareForExit(); + } } public void OnFrameAvailable(ref BufferItem item) diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs index 8d63d9cc..d86ff21e 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs @@ -42,23 +42,23 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger Buffer = parcel.ReadUnmanagedType<NvGraphicBuffer>(); } - public void IncrementNvMapHandleRefCount(KProcess process) + public void IncrementNvMapHandleRefCount(long pid) { - NvMapDeviceFile.IncrementMapRefCount(process, Buffer.NvMapId); + NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.NvMapId); for (int i = 0; i < Buffer.Surfaces.Length; i++) { - NvMapDeviceFile.IncrementMapRefCount(process, Buffer.Surfaces[i].NvMapHandle); + NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.Surfaces[i].NvMapHandle); } } - public void DecrementNvMapHandleRefCount(KProcess process) + public void DecrementNvMapHandleRefCount(long pid) { - NvMapDeviceFile.DecrementMapRefCount(process, Buffer.NvMapId); + NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.NvMapId); for (int i = 0; i < Buffer.Surfaces.Length; i++) { - NvMapDeviceFile.DecrementMapRefCount(process, Buffer.Surfaces[i].NvMapHandle); + NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.Surfaces[i].NvMapHandle); } } diff --git a/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs b/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs index 743b9e13..ecee7206 100644 --- a/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs +++ b/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs @@ -15,10 +15,12 @@ namespace Ryujinx.HLE.HOS.Services.Time private IStaticServiceForPsc _inner; private TimePermissions _permissions; - public IStaticServiceForGlue(ServiceCtx context, TimePermissions permissions) : base(new ServerBase("TimeServer")) + public IStaticServiceForGlue(ServiceCtx context, TimePermissions permissions) : base(new ServerBase(context.Device.System.KernelContext, "TimeServer")) { _permissions = permissions; _inner = new IStaticServiceForPsc(context, permissions); + _inner.TrySetServer(Server); + _inner.SetParent(this); } [Command(0)] diff --git a/Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs b/Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs index 64b21381..aeb0e8a8 100644 --- a/Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs +++ b/Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs @@ -149,7 +149,7 @@ namespace Ryujinx.HLE.HOS.Services.Time public ResultCode Unknown50(ServiceCtx context) { // TODO: figure out the usage of this event - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(51)] @@ -157,7 +157,7 @@ namespace Ryujinx.HLE.HOS.Services.Time public ResultCode Unknown51(ServiceCtx context) { // TODO: figure out the usage of this event - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(52)] @@ -165,7 +165,7 @@ namespace Ryujinx.HLE.HOS.Services.Time public ResultCode Unknown52(ServiceCtx context) { // TODO: figure out the usage of this event - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(60)] @@ -201,7 +201,7 @@ namespace Ryujinx.HLE.HOS.Services.Time public ResultCode GetAlarmRegistrationEvent(ServiceCtx context) { // TODO - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(201)] @@ -209,7 +209,7 @@ namespace Ryujinx.HLE.HOS.Services.Time public ResultCode UpdateSteadyAlarms(ServiceCtx context) { // TODO - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(202)] @@ -217,7 +217,7 @@ namespace Ryujinx.HLE.HOS.Services.Time public ResultCode TryGetNextSteadyClockAlarmSnapshot(ServiceCtx context) { // TODO - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } } } diff --git a/Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs b/Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs index 22ffe656..ee99da77 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs @@ -5,8 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi [Service("vi:u")] class IApplicationRootService : IpcService { - // vi:u/m/s aren't on 3 separate threads but we can't put them together with the current ServerBase - public IApplicationRootService(ServiceCtx context) : base(new ServerBase("ViServerU")) { } + public IApplicationRootService(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "ViServerU")) { } [Command(0)] // GetDisplayService(u32) -> object<nn::visrv::sf::IApplicationDisplayService> diff --git a/Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs b/Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs index a90690ea..6157a16f 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs @@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi class IManagerRootService : IpcService { // vi:u/m/s aren't on 3 separate threads but we can't put them together with the current ServerBase - public IManagerRootService(ServiceCtx context) : base(new ServerBase("ViServerM")) { } + public IManagerRootService(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "ViServerM")) { } [Command(2)] // GetDisplayService(u32) -> object<nn::visrv::sf::IApplicationDisplayService> diff --git a/Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs b/Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs index 65b21613..9847a2da 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs @@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi class ISystemRootService : IpcService { // vi:u/m/s aren't on 3 separate threads but we can't put them together with the current ServerBase - public ISystemRootService(ServiceCtx context) : base(new ServerBase("ViServerS")) { } + public ISystemRootService(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "ViServerS")) { } [Command(1)] // GetDisplayService(u32) -> object<nn::visrv::sf::IApplicationDisplayService> diff --git a/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs b/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs index 012a81ff..6b874722 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs @@ -1,11 +1,10 @@ using Ryujinx.Common.Logging; -using Ryujinx.HLE.HOS.Services.SurfaceFlinger; namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService { class IManagerDisplayService : IpcService { - private static IApplicationDisplayService _applicationDisplayService; + private IApplicationDisplayService _applicationDisplayService; public IManagerDisplayService(IApplicationDisplayService applicationDisplayService) { @@ -16,10 +15,13 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService // CreateManagedLayer(u32, u64, nn::applet::AppletResourceUserId) -> u64 public ResultCode CreateManagedLayer(ServiceCtx context) { - long layerFlags = context.RequestData.ReadInt64(); - long displayId = context.RequestData.ReadInt64(); + long layerFlags = context.RequestData.ReadInt64(); + long displayId = context.RequestData.ReadInt64(); + long appletResourceUserId = context.RequestData.ReadInt64(); - context.Device.System.SurfaceFlinger.CreateLayer(context.Process, out long layerId); + long pid = context.Device.System.AppletState.AppletResourceUserIds.GetData<long>((int)appletResourceUserId); + + context.Device.System.SurfaceFlinger.CreateLayer(pid, out long layerId); context.ResponseData.Write(layerId); diff --git a/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs b/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs index 194bda2d..36f220c6 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs @@ -4,7 +4,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService { class ISystemDisplayService : IpcService { - private static IApplicationDisplayService _applicationDisplayService; + private IApplicationDisplayService _applicationDisplayService; public ISystemDisplayService(IApplicationDisplayService applicationDisplayService) { diff --git a/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs b/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs index bd00fc02..a4b9f358 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs @@ -11,7 +11,9 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService { class IApplicationDisplayService : IpcService { - private IdDictionary _displays; + private readonly IdDictionary _displays; + + private int _vsyncEventHandle; public IApplicationDisplayService() { @@ -121,7 +123,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService long userId = context.RequestData.ReadInt64(); long parcelPtr = context.Request.ReceiveBuff[0].Position; - IBinder producer = context.Device.System.SurfaceFlinger.OpenLayer(context.Process, layerId); + IBinder producer = context.Device.System.SurfaceFlinger.OpenLayer(context.Request.HandleDesc.PId, layerId); Parcel parcel = new Parcel(0x28, 0x4); @@ -159,7 +161,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService // TODO: support multi display. Display disp = _displays.GetData<Display>((int)displayId); - IBinder producer = context.Device.System.SurfaceFlinger.CreateLayer(context.Process, out long layerId); + IBinder producer = context.Device.System.SurfaceFlinger.CreateLayer(0, out long layerId); Parcel parcel = new Parcel(0x28, 0x4); @@ -268,8 +270,8 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService const ulong defaultAlignment = 0x1000; const ulong defaultSize = 0x20000; - // NOTE: The official service setup a A8B8G8R8 texture with a linear layout and then query its size. - // As we don't need this texture on the emulator, we can just simplify this logic and directly + // NOTE: The official service setup a A8B8G8R8 texture with a linear layout and then query its size. + // As we don't need this texture on the emulator, we can just simplify this logic and directly // do a linear layout size calculation. (stride * height * bytePerPixel) int pitch = BitUtils.AlignUp(BitUtils.DivRoundUp(width * 32, 8), 64); int memorySize = pitch * BitUtils.AlignUp(height, 64); @@ -289,12 +291,15 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService { string name = GetDisplayName(context); - if (context.Process.HandleTable.GenerateHandle(context.Device.System.VsyncEvent.ReadableEvent, out int handle) != KernelResult.Success) + if (_vsyncEventHandle == 0) { - throw new InvalidOperationException("Out of handles!"); + if (context.Process.HandleTable.GenerateHandle(context.Device.System.VsyncEvent.ReadableEvent, out _vsyncEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_vsyncEventHandle); return ResultCode.Success; } |