aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-12-01 20:23:43 -0300
committerGitHub <noreply@github.com>2020-12-02 00:23:43 +0100
commitcf6cd714884c41e9550757e364c2f4f5b04fc7f3 (patch)
treebea748b4d1a350e5b8075d63ec9d39d49693829d /Ryujinx.HLE/HOS/Services
parent461c24092ae6e148d896c18aa3e86220c89981f8 (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')
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs37
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs28
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs4
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs42
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs43
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Audio/AudioOutManager/IAudioOut.cs22
-rw-r--r--Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs4
-rw-r--r--Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs6
-rw-r--r--Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs3
-rw-r--r--Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs4
-rw-r--r--Ryujinx.HLE/HOS/Services/Audio/IHardwareOpusDecoderManager.cs3
-rw-r--r--Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs22
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs24
-rw-r--r--Ryujinx.HLE/HOS/Services/IpcService.cs62
-rw-r--r--Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs32
-rw-r--r--Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs21
-rw-r--r--Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs17
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs67
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs7
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs3
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs9
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs5
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs6
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs5
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs24
-rw-r--r--Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs37
-rw-r--r--Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/ServerBase.cs233
-rw-r--r--Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs28
-rw-r--r--Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs5
-rw-r--r--Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs20
-rw-r--r--Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs45
-rw-r--r--Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs5
-rw-r--r--Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs26
-rw-r--r--Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs4
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs3
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs21
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;
}