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:
gdkchan 2018-12-27 22:00:25 -03:00
commit 2f6c8b2edc
10 changed files with 76 additions and 75 deletions

View file

@ -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();

View file

@ -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();

View file

@ -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)

View file

@ -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;

View file

@ -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();
} }

View file

@ -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;

View file

@ -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));

View file

@ -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;

View file

@ -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;
} }

View file

@ -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!");
} }