Implement smarter switching between old and new IPC system to support the old HLE services implementation without the manual switch
This commit is contained in:
parent
c629f3c8a2
commit
2f6c8b2edc
10 changed files with 76 additions and 75 deletions
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<KSession>(handle);
|
||||
KClientSession clientSession = _process.HandleTable.GetObject<KClientSession>(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));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<KSession>(handle);
|
||||
KClientSession session = context.Process.HandleTable.GetObject<KClientSession>(handle);
|
||||
|
||||
return session?.Service is T ? (T)session.Service : null;
|
||||
}
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue