diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index 5274605a19..5e2e28f4c7 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -6,6 +6,7 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.HLE.HOS.Services.Sm; using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Npdm; @@ -165,6 +166,8 @@ namespace Ryujinx.HLE.HOS Font = new SharedFontManager(device, (long)(fontPa - DramMemoryMap.DramBase)); + IUserInterface.InitializePort(this); + VsyncEvent = new KEvent(this); LoadKeySet(); diff --git a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs index ecfa25ed02..1eba4b4124 100644 --- a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs +++ b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs @@ -10,12 +10,12 @@ namespace Ryujinx.HLE.HOS.Ipc static class IpcHandler { public static KernelResult IpcCall( - Switch device, - KProcess process, - MemoryManager memory, - KSession session, - IpcMessage request, - long cmdPtr) + Switch device, + KProcess process, + MemoryManager memory, + KClientSession session, + IpcMessage request, + long cmdPtr) { IpcMessage response = new IpcMessage(); diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs index 2863054447..375f050b64 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs @@ -1,5 +1,6 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Services; namespace Ryujinx.HLE.HOS.Kernel.Ipc { @@ -13,6 +14,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc private object _countIncLock; + //TODO: Remove that, we need it for now to allow HLE + //SM implementation to work with the new IPC system. + public IpcService Service { get; set; } + public KClientPort(Horizon system) : base(system) { _countIncLock = new object(); @@ -57,6 +62,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc KSession session = new KSession(System); + if (Service != null) + { + session.ClientSession.Service = Service; + } + KernelResult result = _parent.EnqueueIncomingSession(session.ServerSession); if (result != KernelResult.Success) diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs index 8e8f874ceb..abb99440a1 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs @@ -1,6 +1,7 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.HLE.HOS.Services; namespace Ryujinx.HLE.HOS.Kernel.Ipc { @@ -12,6 +13,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc public int ResourceStatus { get; private set; } + public IpcService Service { get; set; } + public KClientSession(Horizon system, KSession parent) : base(system) { _parent = parent; diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs index 1b9bb337d5..304fab1a3e 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs @@ -1,6 +1,5 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Process; -using Ryujinx.HLE.HOS.Services; using System; namespace Ryujinx.HLE.HOS.Kernel.Ipc @@ -12,22 +11,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc private bool _hasBeenInitialized; - public IpcService Service { get; private set; } - - public string ServiceName { get; private set; } - public KSession(Horizon system) : base(system) { ServerSession = new KServerSession(system, this); ClientSession = new KClientSession(system, this); } - public KSession(Horizon system, IpcService service, string serviceName) : base(system) - { - Service = service; - ServiceName = serviceName; - } - public void Dispose() { Dispose(true); @@ -35,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc protected virtual void Dispose(bool disposing) { - if (disposing && Service is IDisposable disposableService) + if (disposing && ClientSession.Service is IDisposable disposableService) { disposableService.Dispose(); } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs index 08340b06bb..7171eaef75 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs @@ -18,16 +18,16 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall private struct HleIpcMessage { - public KThread Thread { get; private set; } - public KSession Session { get; private set; } - public IpcMessage Message { get; private set; } - public long MessagePtr { get; private set; } + public KThread Thread { get; private set; } + public KClientSession Session { get; private set; } + public IpcMessage Message { get; private set; } + public long MessagePtr { get; private set; } public HleIpcMessage( - KThread thread, - KSession session, - IpcMessage message, - long messagePtr) + KThread thread, + KClientSession session, + IpcMessage message, + long messagePtr) { Thread = thread; Session = session; diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs index 431376a06b..d2e4754f21 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs @@ -8,15 +8,12 @@ using Ryujinx.HLE.HOS.Kernel.Ipc; using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Threading; -using Ryujinx.HLE.HOS.Services; using System.Threading; namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { partial class SvcHandler { - private const bool UseLegacyIpc = true; - public void ExitProcess64() { ExitProcess(); @@ -148,26 +145,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult ConnectToNamedPort64(ulong namePtr, out int handle) { - if (!UseLegacyIpc) - { - return ConnectToNamedPort_(namePtr, out handle); - } - return ConnectToNamedPort(namePtr, out handle); } private KernelResult ConnectToNamedPort(ulong namePtr, out int handle) - { - string name = MemoryHelper.ReadAsciiString(_memory, (long)namePtr, 8); - - //TODO: Validate that app has perms to access the service, and that the service - //actually exists, return error codes otherwise. - KSession session = new KSession(_system, ServiceFactory.MakeService(_system, name), name); - - return _process.HandleTable.GenerateHandle(session, out handle); - } - - private KernelResult ConnectToNamedPort_(ulong namePtr, out int handle) { handle = 0; @@ -213,11 +194,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult SendSyncRequest64(int handle) { - if (!UseLegacyIpc) - { - return SendSyncRequest_(handle); - } - return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.ThreadState.Tpidr, 0x100, handle); } @@ -230,9 +206,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { byte[] messageData = _memory.ReadBytes((long)messagePtr, (long)size); - KSession session = _process.HandleTable.GetObject(handle); + KClientSession clientSession = _process.HandleTable.GetObject(handle); - if (session != null) + if (clientSession == null || clientSession.Service == null) + { + return SendSyncRequest_(handle); + } + + if (clientSession != null) { _system.CriticalSection.Enter(); @@ -247,7 +228,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage( currentThread, - session, + clientSession, message, (long)messagePtr)); diff --git a/Ryujinx.HLE/HOS/ServiceCtx.cs b/Ryujinx.HLE/HOS/ServiceCtx.cs index 005d16f34f..af42d41762 100644 --- a/Ryujinx.HLE/HOS/ServiceCtx.cs +++ b/Ryujinx.HLE/HOS/ServiceCtx.cs @@ -8,24 +8,24 @@ namespace Ryujinx.HLE.HOS { class ServiceCtx { - public Switch Device { get; private set; } - public KProcess Process { get; private set; } - public MemoryManager Memory { get; private set; } - public KSession Session { get; private set; } - public IpcMessage Request { get; private set; } - public IpcMessage Response { get; private set; } - public BinaryReader RequestData { get; private set; } - public BinaryWriter ResponseData { get; private set; } + public Switch Device { get; } + public KProcess Process { get; } + public MemoryManager Memory { get; } + public KClientSession Session { get; } + public IpcMessage Request { get; } + public IpcMessage Response { get; } + public BinaryReader RequestData { get; } + public BinaryWriter ResponseData { get; } public ServiceCtx( - Switch device, - KProcess process, - MemoryManager memory, - KSession session, - IpcMessage request, - IpcMessage response, - BinaryReader requestData, - BinaryWriter responseData) + Switch device, + KProcess process, + MemoryManager memory, + KClientSession session, + IpcMessage request, + IpcMessage response, + BinaryReader requestData, + BinaryWriter responseData) { Device = device; Process = process; diff --git a/Ryujinx.HLE/HOS/Services/IpcService.cs b/Ryujinx.HLE/HOS/Services/IpcService.cs index ac503e4f89..9d221e5526 100644 --- a/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -115,7 +115,7 @@ namespace Ryujinx.HLE.HOS.Services } else { - string dbgMessage = $"{context.Session.ServiceName} {service.GetType().Name}: {commandId}"; + string dbgMessage = $"{service.GetType().FullName}: {commandId}"; throw new NotImplementedException(dbgMessage); } @@ -131,9 +131,11 @@ namespace Ryujinx.HLE.HOS.Services } else { - KSession session = new KSession(context.Device.System, obj, context.Session.ServiceName); + KSession session = new KSession(context.Device.System); - if (context.Process.HandleTable.GenerateHandle(session, out int handle) != KernelResult.Success) + session.ClientSession.Service = obj; + + if (context.Process.HandleTable.GenerateHandle(session.ClientSession, out int handle) != KernelResult.Success) { throw new InvalidOperationException("Out of handles!"); } @@ -150,7 +152,7 @@ namespace Ryujinx.HLE.HOS.Services { int handle = context.Request.HandleDesc.ToMove[index]; - KSession session = context.Process.HandleTable.GetObject(handle); + KClientSession session = context.Process.HandleTable.GetObject(handle); return session?.Service is T ? (T)session.Service : null; } diff --git a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs index 3bcd608876..86204b54ce 100644 --- a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs @@ -23,6 +23,17 @@ namespace Ryujinx.HLE.HOS.Services.Sm }; } + public static void InitializePort(Horizon system) + { + KPort port = new KPort(system); + + port.Initialize(256, false, 0); + + port.ClientPort.SetName("sm:"); + + port.ClientPort.Service = new IUserInterface(); + } + private const int SmNotInitialized = 0x415; public long Initialize(ServiceCtx context) @@ -59,9 +70,11 @@ namespace Ryujinx.HLE.HOS.Services.Sm return 0; } - KSession session = new KSession(context.Device.System, ServiceFactory.MakeService(context.Device.System, name), name); + KSession session = new KSession(context.Device.System); - if (context.Process.HandleTable.GenerateHandle(session, out int handle) != KernelResult.Success) + session.ClientSession.Service = ServiceFactory.MakeService(context.Device.System, name); + + if (context.Process.HandleTable.GenerateHandle(session.ClientSession, out int handle) != KernelResult.Success) { throw new InvalidOperationException("Out of handles!"); }