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.Memory;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Sm;
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
using Ryujinx.HLE.Loaders.Executables;
|
using Ryujinx.HLE.Loaders.Executables;
|
||||||
using Ryujinx.HLE.Loaders.Npdm;
|
using Ryujinx.HLE.Loaders.Npdm;
|
||||||
|
@ -165,6 +166,8 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
Font = new SharedFontManager(device, (long)(fontPa - DramMemoryMap.DramBase));
|
Font = new SharedFontManager(device, (long)(fontPa - DramMemoryMap.DramBase));
|
||||||
|
|
||||||
|
IUserInterface.InitializePort(this);
|
||||||
|
|
||||||
VsyncEvent = new KEvent(this);
|
VsyncEvent = new KEvent(this);
|
||||||
|
|
||||||
LoadKeySet();
|
LoadKeySet();
|
||||||
|
|
|
@ -10,12 +10,12 @@ namespace Ryujinx.HLE.HOS.Ipc
|
||||||
static class IpcHandler
|
static class IpcHandler
|
||||||
{
|
{
|
||||||
public static KernelResult IpcCall(
|
public static KernelResult IpcCall(
|
||||||
Switch device,
|
Switch device,
|
||||||
KProcess process,
|
KProcess process,
|
||||||
MemoryManager memory,
|
MemoryManager memory,
|
||||||
KSession session,
|
KClientSession session,
|
||||||
IpcMessage request,
|
IpcMessage request,
|
||||||
long cmdPtr)
|
long cmdPtr)
|
||||||
{
|
{
|
||||||
IpcMessage response = new IpcMessage();
|
IpcMessage response = new IpcMessage();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
using Ryujinx.HLE.HOS.Services;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
{
|
{
|
||||||
|
@ -13,6 +14,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
private object _countIncLock;
|
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)
|
public KClientPort(Horizon system) : base(system)
|
||||||
{
|
{
|
||||||
_countIncLock = new object();
|
_countIncLock = new object();
|
||||||
|
@ -57,6 +62,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
KSession session = new KSession(System);
|
KSession session = new KSession(System);
|
||||||
|
|
||||||
|
if (Service != null)
|
||||||
|
{
|
||||||
|
session.ClientSession.Service = Service;
|
||||||
|
}
|
||||||
|
|
||||||
KernelResult result = _parent.EnqueueIncomingSession(session.ServerSession);
|
KernelResult result = _parent.EnqueueIncomingSession(session.ServerSession);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != KernelResult.Success)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.HLE.HOS.Services;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
{
|
{
|
||||||
|
@ -12,6 +13,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
public int ResourceStatus { get; private set; }
|
public int ResourceStatus { get; private set; }
|
||||||
|
|
||||||
|
public IpcService Service { get; set; }
|
||||||
|
|
||||||
public KClientSession(Horizon system, KSession parent) : base(system)
|
public KClientSession(Horizon system, KSession parent) : base(system)
|
||||||
{
|
{
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.HOS.Services;
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
@ -12,22 +11,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
private bool _hasBeenInitialized;
|
private bool _hasBeenInitialized;
|
||||||
|
|
||||||
public IpcService Service { get; private set; }
|
|
||||||
|
|
||||||
public string ServiceName { get; private set; }
|
|
||||||
|
|
||||||
public KSession(Horizon system) : base(system)
|
public KSession(Horizon system) : base(system)
|
||||||
{
|
{
|
||||||
ServerSession = new KServerSession(system, this);
|
ServerSession = new KServerSession(system, this);
|
||||||
ClientSession = new KClientSession(system, this);
|
ClientSession = new KClientSession(system, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KSession(Horizon system, IpcService service, string serviceName) : base(system)
|
|
||||||
{
|
|
||||||
Service = service;
|
|
||||||
ServiceName = serviceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
|
@ -35,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing && Service is IDisposable disposableService)
|
if (disposing && ClientSession.Service is IDisposable disposableService)
|
||||||
{
|
{
|
||||||
disposableService.Dispose();
|
disposableService.Dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,16 +18,16 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
|
|
||||||
private struct HleIpcMessage
|
private struct HleIpcMessage
|
||||||
{
|
{
|
||||||
public KThread Thread { get; private set; }
|
public KThread Thread { get; private set; }
|
||||||
public KSession Session { get; private set; }
|
public KClientSession Session { get; private set; }
|
||||||
public IpcMessage Message { get; private set; }
|
public IpcMessage Message { get; private set; }
|
||||||
public long MessagePtr { get; private set; }
|
public long MessagePtr { get; private set; }
|
||||||
|
|
||||||
public HleIpcMessage(
|
public HleIpcMessage(
|
||||||
KThread thread,
|
KThread thread,
|
||||||
KSession session,
|
KClientSession session,
|
||||||
IpcMessage message,
|
IpcMessage message,
|
||||||
long messagePtr)
|
long messagePtr)
|
||||||
{
|
{
|
||||||
Thread = thread;
|
Thread = thread;
|
||||||
Session = session;
|
Session = session;
|
||||||
|
|
|
@ -8,15 +8,12 @@ using Ryujinx.HLE.HOS.Kernel.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
{
|
{
|
||||||
partial class SvcHandler
|
partial class SvcHandler
|
||||||
{
|
{
|
||||||
private const bool UseLegacyIpc = true;
|
|
||||||
|
|
||||||
public void ExitProcess64()
|
public void ExitProcess64()
|
||||||
{
|
{
|
||||||
ExitProcess();
|
ExitProcess();
|
||||||
|
@ -148,26 +145,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
|
|
||||||
public KernelResult ConnectToNamedPort64(ulong namePtr, out int handle)
|
public KernelResult ConnectToNamedPort64(ulong namePtr, out int handle)
|
||||||
{
|
{
|
||||||
if (!UseLegacyIpc)
|
|
||||||
{
|
|
||||||
return ConnectToNamedPort_(namePtr, out handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConnectToNamedPort(namePtr, out handle);
|
return ConnectToNamedPort(namePtr, out handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult ConnectToNamedPort(ulong namePtr, out int 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;
|
handle = 0;
|
||||||
|
|
||||||
|
@ -213,11 +194,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
|
|
||||||
public KernelResult SendSyncRequest64(int handle)
|
public KernelResult SendSyncRequest64(int handle)
|
||||||
{
|
{
|
||||||
if (!UseLegacyIpc)
|
|
||||||
{
|
|
||||||
return SendSyncRequest_(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.ThreadState.Tpidr, 0x100, 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);
|
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();
|
_system.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -247,7 +228,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
|
|
||||||
ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage(
|
ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage(
|
||||||
currentThread,
|
currentThread,
|
||||||
session,
|
clientSession,
|
||||||
message,
|
message,
|
||||||
(long)messagePtr));
|
(long)messagePtr));
|
||||||
|
|
||||||
|
|
|
@ -8,24 +8,24 @@ namespace Ryujinx.HLE.HOS
|
||||||
{
|
{
|
||||||
class ServiceCtx
|
class ServiceCtx
|
||||||
{
|
{
|
||||||
public Switch Device { get; private set; }
|
public Switch Device { get; }
|
||||||
public KProcess Process { get; private set; }
|
public KProcess Process { get; }
|
||||||
public MemoryManager Memory { get; private set; }
|
public MemoryManager Memory { get; }
|
||||||
public KSession Session { get; private set; }
|
public KClientSession Session { get; }
|
||||||
public IpcMessage Request { get; private set; }
|
public IpcMessage Request { get; }
|
||||||
public IpcMessage Response { get; private set; }
|
public IpcMessage Response { get; }
|
||||||
public BinaryReader RequestData { get; private set; }
|
public BinaryReader RequestData { get; }
|
||||||
public BinaryWriter ResponseData { get; private set; }
|
public BinaryWriter ResponseData { get; }
|
||||||
|
|
||||||
public ServiceCtx(
|
public ServiceCtx(
|
||||||
Switch device,
|
Switch device,
|
||||||
KProcess process,
|
KProcess process,
|
||||||
MemoryManager memory,
|
MemoryManager memory,
|
||||||
KSession session,
|
KClientSession session,
|
||||||
IpcMessage request,
|
IpcMessage request,
|
||||||
IpcMessage response,
|
IpcMessage response,
|
||||||
BinaryReader requestData,
|
BinaryReader requestData,
|
||||||
BinaryWriter responseData)
|
BinaryWriter responseData)
|
||||||
{
|
{
|
||||||
Device = device;
|
Device = device;
|
||||||
Process = process;
|
Process = process;
|
||||||
|
|
|
@ -115,7 +115,7 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string dbgMessage = $"{context.Session.ServiceName} {service.GetType().Name}: {commandId}";
|
string dbgMessage = $"{service.GetType().FullName}: {commandId}";
|
||||||
|
|
||||||
throw new NotImplementedException(dbgMessage);
|
throw new NotImplementedException(dbgMessage);
|
||||||
}
|
}
|
||||||
|
@ -131,9 +131,11 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
}
|
}
|
||||||
else
|
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!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -150,7 +152,7 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
{
|
{
|
||||||
int handle = context.Request.HandleDesc.ToMove[index];
|
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;
|
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;
|
private const int SmNotInitialized = 0x415;
|
||||||
|
|
||||||
public long Initialize(ServiceCtx context)
|
public long Initialize(ServiceCtx context)
|
||||||
|
@ -59,9 +70,11 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
return 0;
|
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!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue