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.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

@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Ipc
Switch device,
KProcess process,
MemoryManager memory,
KSession session,
KClientSession session,
IpcMessage request,
long cmdPtr)
{

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

@ -19,13 +19,13 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
private struct HleIpcMessage
{
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 long MessagePtr { get; private set; }
public HleIpcMessage(
KThread thread,
KSession session,
KClientSession session,
IpcMessage message,
long messagePtr)
{

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,20 +8,20 @@ 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,
KClientSession session,
IpcMessage request,
IpcMessage response,
BinaryReader requestData,

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