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
parent c629f3c8a2
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.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();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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