[WIP] Add support for events (#60)
* Add support for events, move concept of domains to IpcService * Support waiting for KThread, remove some test code, other tweaks * Use move handle on NIFM since I can't test that now, it's better to leave it how it was
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
namespace Ryujinx.Core.OsHle.Ipc
|
||||
{
|
||||
enum IpcDomCmd
|
||||
{
|
||||
SendMsg = 1,
|
||||
DeleteObj = 2
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using ChocolArm64.Memory;
|
||||
using Ryujinx.Core.OsHle.Handles;
|
||||
using Ryujinx.Core.OsHle.IpcServices;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
@@ -8,20 +7,15 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||
{
|
||||
static class IpcHandler
|
||||
{
|
||||
private const long SfciMagic = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'I' << 24;
|
||||
private const long SfcoMagic = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'O' << 24;
|
||||
|
||||
public static void IpcCall(
|
||||
Switch Ns,
|
||||
Process Process,
|
||||
AMemory Memory,
|
||||
HSession Session,
|
||||
KSession Session,
|
||||
IpcMessage Request,
|
||||
int ThreadId,
|
||||
long CmdPtr,
|
||||
int HndId)
|
||||
long CmdPtr)
|
||||
{
|
||||
IpcMessage Response = new IpcMessage(Request.IsDomain && Request.Type == IpcMessageType.Request);
|
||||
IpcMessage Response = new IpcMessage();
|
||||
|
||||
using (MemoryStream Raw = new MemoryStream(Request.RawData))
|
||||
{
|
||||
@@ -29,94 +23,25 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||
|
||||
if (Request.Type == IpcMessageType.Request)
|
||||
{
|
||||
string ServiceName = Session.Service.GetType().Name;
|
||||
Response.Type = IpcMessageType.Response;
|
||||
|
||||
ServiceProcessRequest ProcReq = null;
|
||||
|
||||
bool IgnoreNullPR = false;
|
||||
|
||||
string DbgServiceName = string.Empty;
|
||||
|
||||
if (Session is HDomain Dom)
|
||||
using (MemoryStream ResMS = new MemoryStream())
|
||||
{
|
||||
if (Request.DomCmd == IpcDomCmd.SendMsg)
|
||||
{
|
||||
long Magic = ReqReader.ReadInt64();
|
||||
int CmdId = (int)ReqReader.ReadInt64();
|
||||
BinaryWriter ResWriter = new BinaryWriter(ResMS);
|
||||
|
||||
object Obj = Dom.GetObject(Request.DomObjId);
|
||||
ServiceCtx Context = new ServiceCtx(
|
||||
Ns,
|
||||
Process,
|
||||
Memory,
|
||||
Session,
|
||||
Request,
|
||||
Response,
|
||||
ReqReader,
|
||||
ResWriter);
|
||||
|
||||
if (Obj is HDomain)
|
||||
{
|
||||
Session.Service.Commands.TryGetValue(CmdId, out ProcReq);
|
||||
Session.Service.CallMethod(Context);
|
||||
|
||||
DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}";
|
||||
}
|
||||
else if (Obj != null)
|
||||
{
|
||||
((IIpcService)Obj).Commands.TryGetValue(CmdId, out ProcReq);
|
||||
|
||||
DbgServiceName = $"{Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}";
|
||||
}
|
||||
}
|
||||
else if (Request.DomCmd == IpcDomCmd.DeleteObj)
|
||||
{
|
||||
Dom.Delete(Request.DomObjId);
|
||||
|
||||
Response = FillResponse(Response, 0);
|
||||
|
||||
IgnoreNullPR = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long Magic = ReqReader.ReadInt64();
|
||||
int CmdId = (int)ReqReader.ReadInt64();
|
||||
|
||||
if (Session is HSessionObj)
|
||||
{
|
||||
object Obj = ((HSessionObj)Session).Obj;
|
||||
|
||||
((IIpcService)Obj).Commands.TryGetValue(CmdId, out ProcReq);
|
||||
|
||||
DbgServiceName = $"{Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}";
|
||||
}
|
||||
else
|
||||
{
|
||||
Session.Service.Commands.TryGetValue(CmdId, out ProcReq);
|
||||
|
||||
DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}";
|
||||
}
|
||||
}
|
||||
|
||||
DbgServiceName = $"Tid {ThreadId} {ServiceName} {DbgServiceName}";
|
||||
|
||||
Logging.Debug($"IpcMessage: {DbgServiceName}");
|
||||
|
||||
if (ProcReq != null)
|
||||
{
|
||||
using (MemoryStream ResMS = new MemoryStream())
|
||||
{
|
||||
BinaryWriter ResWriter = new BinaryWriter(ResMS);
|
||||
|
||||
ServiceCtx Context = new ServiceCtx(
|
||||
Ns,
|
||||
Process,
|
||||
Memory,
|
||||
Session,
|
||||
Request,
|
||||
Response,
|
||||
ReqReader,
|
||||
ResWriter);
|
||||
|
||||
long Result = ProcReq(Context);
|
||||
|
||||
Response = FillResponse(Response, Result, ResMS.ToArray());
|
||||
}
|
||||
}
|
||||
else if (!IgnoreNullPR)
|
||||
{
|
||||
throw new NotImplementedException(DbgServiceName);
|
||||
Response.RawData = ResMS.ToArray();
|
||||
}
|
||||
}
|
||||
else if (Request.Type == IpcMessageType.Control)
|
||||
@@ -128,11 +53,7 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
HDomain Dom = new HDomain(Session);
|
||||
|
||||
Process.HandleTable.ReplaceData(HndId, Dom);
|
||||
|
||||
Request = FillResponse(Response, 0, Dom.Add(Dom));
|
||||
Request = FillResponse(Response, 0, Session.Service.ConvertToDomain());
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -198,7 +119,7 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||
{
|
||||
BinaryWriter Writer = new BinaryWriter(MS);
|
||||
|
||||
Writer.Write(SfcoMagic);
|
||||
Writer.Write(IpcMagic.Sfco);
|
||||
Writer.Write(Result);
|
||||
|
||||
if (Data != null)
|
||||
|
||||
@@ -125,8 +125,7 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||
|
||||
Reader.ReadInt64(); //Padding
|
||||
|
||||
IpcMessage += Environment.NewLine + $" Domain:" + Environment.NewLine +
|
||||
$" DomCmd: {Enum.GetName(typeof(IpcDomCmd), DomCmd)}" + Environment.NewLine +
|
||||
IpcMessage += Environment.NewLine + $" Domain:" + Environment.NewLine + Environment.NewLine +
|
||||
$" DomObjId: {DomObjId.ToString()}" + Environment.NewLine;
|
||||
}
|
||||
|
||||
|
||||
8
Ryujinx.Core/OsHle/Ipc/IpcMagic.cs
Normal file
8
Ryujinx.Core/OsHle/Ipc/IpcMagic.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Ryujinx.Core.OsHle.Ipc
|
||||
{
|
||||
abstract class IpcMagic
|
||||
{
|
||||
public const long Sfci = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'I' << 24;
|
||||
public const long Sfco = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'O' << 24;
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,6 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||
|
||||
public List<int> ResponseObjIds { get; private set; }
|
||||
|
||||
public bool IsDomain { get; private set; }
|
||||
public IpcDomCmd DomCmd { get; private set; }
|
||||
public int DomObjId { get; private set; }
|
||||
|
||||
public byte[] RawData { get; set; }
|
||||
|
||||
public IpcMessage()
|
||||
@@ -34,27 +30,18 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||
ResponseObjIds = new List<int>();
|
||||
}
|
||||
|
||||
public IpcMessage(bool Domain) : this()
|
||||
public IpcMessage(byte[] Data, long CmdPtr) : this()
|
||||
{
|
||||
IsDomain = Domain;
|
||||
}
|
||||
|
||||
public IpcMessage(byte[] Data, long CmdPtr, bool Domain) : this()
|
||||
{
|
||||
Logging.Ipc(Data, CmdPtr, Domain);
|
||||
|
||||
using (MemoryStream MS = new MemoryStream(Data))
|
||||
{
|
||||
BinaryReader Reader = new BinaryReader(MS);
|
||||
|
||||
Initialize(Reader, CmdPtr, Domain);
|
||||
Initialize(Reader, CmdPtr);
|
||||
}
|
||||
}
|
||||
|
||||
private void Initialize(BinaryReader Reader, long CmdPtr, bool Domain)
|
||||
private void Initialize(BinaryReader Reader, long CmdPtr)
|
||||
{
|
||||
IsDomain = Domain;
|
||||
|
||||
int Word0 = Reader.ReadInt32();
|
||||
int Word1 = Reader.ReadInt32();
|
||||
|
||||
@@ -110,19 +97,6 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||
RecvListCount = 0;
|
||||
}
|
||||
|
||||
if (Domain && Type == IpcMessageType.Request)
|
||||
{
|
||||
int DomWord0 = Reader.ReadInt32();
|
||||
|
||||
DomCmd = (IpcDomCmd)(DomWord0 & 0xff);
|
||||
|
||||
RawDataSize = (DomWord0 >> 16) & 0xffff;
|
||||
|
||||
DomObjId = Reader.ReadInt32();
|
||||
|
||||
Reader.ReadInt64(); //Padding
|
||||
}
|
||||
|
||||
RawData = Reader.ReadBytes(RawDataSize);
|
||||
|
||||
Reader.BaseStream.Seek(RecvListPos, SeekOrigin.Begin);
|
||||
@@ -165,9 +139,7 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||
//This is the weirdest padding I've seen so far...
|
||||
int Pad1 = 0x10 - Pad0;
|
||||
|
||||
DataLength = (DataLength + Pad0 + Pad1 + (IsDomain ? 0x10 : 0)) / 4;
|
||||
|
||||
DataLength += ResponseObjIds.Count;
|
||||
DataLength = (DataLength + Pad0 + Pad1) / 4;
|
||||
|
||||
Word1 = DataLength & 0x3ff;
|
||||
|
||||
@@ -182,23 +154,11 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||
|
||||
MS.Seek(Pad0, SeekOrigin.Current);
|
||||
|
||||
if (IsDomain)
|
||||
{
|
||||
Writer.Write(ResponseObjIds.Count);
|
||||
Writer.Write(0);
|
||||
Writer.Write(0L);
|
||||
}
|
||||
|
||||
if (RawData != null)
|
||||
{
|
||||
Writer.Write(RawData);
|
||||
}
|
||||
|
||||
foreach (int Id in ResponseObjIds)
|
||||
{
|
||||
Writer.Write(Id);
|
||||
}
|
||||
|
||||
Writer.Write(new byte[Pad1]);
|
||||
|
||||
return MS.ToArray();
|
||||
|
||||
Reference in New Issue
Block a user