mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2025-11-07 09:48:58 -06:00
aloha
This commit is contained in:
27
Ryujinx/OsHle/Ipc/IpcBuffDesc.cs
Normal file
27
Ryujinx/OsHle/Ipc/IpcBuffDesc.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.OsHle.Ipc
|
||||
{
|
||||
struct IpcBuffDesc
|
||||
{
|
||||
public long Position { get; private set; }
|
||||
public long Size { get; private set; }
|
||||
public int Flags { get; private set; }
|
||||
|
||||
public IpcBuffDesc(BinaryReader Reader)
|
||||
{
|
||||
long Word0 = Reader.ReadUInt32();
|
||||
long Word1 = Reader.ReadUInt32();
|
||||
long Word2 = Reader.ReadUInt32();
|
||||
|
||||
Position = Word1;
|
||||
Position |= (Word2 << 4) & 0x0f00000000;
|
||||
Position |= (Word2 << 34) & 0x7000000000;
|
||||
|
||||
Size = Word0;
|
||||
Size |= (Word2 << 8) & 0xf00000000;
|
||||
|
||||
Flags = (int)Word2 & 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Ryujinx/OsHle/Ipc/IpcDomCmd.cs
Normal file
8
Ryujinx/OsHle/Ipc/IpcDomCmd.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Ryujinx.OsHle.Ipc
|
||||
{
|
||||
enum IpcDomCmd
|
||||
{
|
||||
SendMsg = 1,
|
||||
DeleteObj = 2
|
||||
}
|
||||
}
|
||||
90
Ryujinx/OsHle/Ipc/IpcHandleDesc.cs
Normal file
90
Ryujinx/OsHle/Ipc/IpcHandleDesc.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.OsHle.Ipc
|
||||
{
|
||||
class IpcHandleDesc
|
||||
{
|
||||
public bool HasPId { get; private set; }
|
||||
|
||||
public long PId { get; private set; }
|
||||
|
||||
public int[] ToCopy { get; private set; }
|
||||
public int[] ToMove { get; private set; }
|
||||
|
||||
public IpcHandleDesc(BinaryReader Reader)
|
||||
{
|
||||
int Word = Reader.ReadInt32();
|
||||
|
||||
HasPId = (Word & 1) != 0;
|
||||
|
||||
ToCopy = new int[(Word >> 1) & 0xf];
|
||||
ToMove = new int[(Word >> 5) & 0xf];
|
||||
|
||||
PId = HasPId ? Reader.ReadInt64() : 0;
|
||||
|
||||
for (int Index = 0; Index < ToCopy.Length; Index++)
|
||||
{
|
||||
ToCopy[Index] = Reader.ReadInt32();
|
||||
}
|
||||
|
||||
for (int Index = 0; Index < ToMove.Length; Index++)
|
||||
{
|
||||
ToMove[Index] = Reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public IpcHandleDesc(int[] Copy, int[] Move)
|
||||
{
|
||||
ToCopy = Copy ?? throw new ArgumentNullException(nameof(Copy));
|
||||
ToMove = Move ?? throw new ArgumentNullException(nameof(Move));
|
||||
}
|
||||
|
||||
public IpcHandleDesc(int[] Copy, int[] Move, long PId) : this(Copy, Move)
|
||||
{
|
||||
this.PId = PId;
|
||||
|
||||
HasPId = true;
|
||||
}
|
||||
|
||||
public static IpcHandleDesc MakeCopy(int Handle) => new IpcHandleDesc(
|
||||
new int[] { Handle },
|
||||
new int[0]);
|
||||
|
||||
public static IpcHandleDesc MakeMove(int Handle) => new IpcHandleDesc(
|
||||
new int[0],
|
||||
new int[] { Handle });
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
using (MemoryStream MS = new MemoryStream())
|
||||
{
|
||||
BinaryWriter Writer = new BinaryWriter(MS);
|
||||
|
||||
int Word = HasPId ? 1 : 0;
|
||||
|
||||
Word |= (ToCopy.Length & 0xf) << 1;
|
||||
Word |= (ToMove.Length & 0xf) << 5;
|
||||
|
||||
Writer.Write(Word);
|
||||
|
||||
if (HasPId)
|
||||
{
|
||||
Writer.Write((long)PId);
|
||||
}
|
||||
|
||||
foreach (int Handle in ToCopy)
|
||||
{
|
||||
Writer.Write(Handle);
|
||||
}
|
||||
|
||||
foreach (int Handle in ToMove)
|
||||
{
|
||||
Writer.Write(Handle);
|
||||
}
|
||||
|
||||
return MS.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
358
Ryujinx/OsHle/Ipc/IpcHandler.cs
Normal file
358
Ryujinx/OsHle/Ipc/IpcHandler.cs
Normal file
@@ -0,0 +1,358 @@
|
||||
using ChocolArm64.Memory;
|
||||
using Ryujinx.OsHle.Handles;
|
||||
using Ryujinx.OsHle.Objects;
|
||||
using Ryujinx.OsHle.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.OsHle.Ipc
|
||||
{
|
||||
static class IpcHandler
|
||||
{
|
||||
private delegate long ServiceProcessRequest(ServiceCtx Context);
|
||||
|
||||
private static Dictionary<(string, int), ServiceProcessRequest> ServiceCmds =
|
||||
new Dictionary<(string, int), ServiceProcessRequest>()
|
||||
{
|
||||
{ ( "acc:u0", 3), Service.AccU0ListOpenUsers },
|
||||
{ ( "acc:u0", 5), Service.AccU0GetProfile },
|
||||
{ ( "acc:u0", 100), Service.AccU0InitializeApplicationInfo },
|
||||
{ ( "acc:u0", 101), Service.AccU0GetBaasAccountManagerForApplication },
|
||||
{ ( "apm", 0), Service.ApmOpenSession },
|
||||
{ ( "appletOE", 0), Service.AppletOpenApplicationProxy },
|
||||
{ ( "audout:u", 0), Service.AudOutListAudioOuts },
|
||||
{ ( "audout:u", 1), Service.AudOutOpenAudioOut },
|
||||
{ ( "audren:u", 0), Service.AudRenOpenAudioRenderer },
|
||||
{ ( "audren:u", 1), Service.AudRenGetAudioRendererWorkBufferSize },
|
||||
{ ( "friend:a", 0), Service.FriendCreateFriendService },
|
||||
{ ( "fsp-srv", 1), Service.FspSrvInitialize },
|
||||
{ ( "fsp-srv", 51), Service.FspSrvMountSaveData },
|
||||
{ ( "fsp-srv", 200), Service.FspSrvOpenDataStorageByCurrentProcess },
|
||||
{ ( "fsp-srv", 203), Service.FspSrvOpenRomStorage },
|
||||
{ ( "fsp-srv", 1005), Service.FspSrvGetGlobalAccessLogMode },
|
||||
{ ( "hid", 0), Service.HidCreateAppletResource },
|
||||
{ ( "hid", 11), Service.HidActivateTouchScreen },
|
||||
{ ( "hid", 100), Service.HidSetSupportedNpadStyleSet },
|
||||
{ ( "hid", 102), Service.HidSetSupportedNpadIdType },
|
||||
{ ( "hid", 103), Service.HidActivateNpad },
|
||||
{ ( "hid", 120), Service.HidSetNpadJoyHoldType },
|
||||
{ ( "lm", 0), Service.LmInitialize },
|
||||
{ ( "nvdrv", 0), Service.NvDrvOpen },
|
||||
{ ( "nvdrv", 1), Service.NvDrvIoctl },
|
||||
{ ( "nvdrv", 2), Service.NvDrvClose },
|
||||
{ ( "nvdrv", 3), Service.NvDrvInitialize },
|
||||
{ ( "nvdrv", 4), Service.NvDrvQueryEvent },
|
||||
{ ( "nvdrv:a", 0), Service.NvDrvOpen },
|
||||
{ ( "nvdrv:a", 1), Service.NvDrvIoctl },
|
||||
{ ( "nvdrv:a", 2), Service.NvDrvClose },
|
||||
{ ( "nvdrv:a", 3), Service.NvDrvInitialize },
|
||||
{ ( "nvdrv:a", 4), Service.NvDrvQueryEvent },
|
||||
{ ( "pctl:a", 0), Service.PctlCreateService },
|
||||
{ ( "pl:u", 1), Service.PlGetLoadState },
|
||||
{ ( "pl:u", 2), Service.PlGetFontSize },
|
||||
{ ( "pl:u", 3), Service.PlGetSharedMemoryAddressOffset },
|
||||
{ ( "pl:u", 4), Service.PlGetSharedMemoryNativeHandle },
|
||||
{ ( "set", 1), Service.SetGetAvailableLanguageCodes },
|
||||
{ ( "sm:", 0), Service.SmInitialize },
|
||||
{ ( "sm:", 1), Service.SmGetService },
|
||||
{ ( "time:u", 0), Service.TimeGetStandardUserSystemClock },
|
||||
{ ( "time:u", 1), Service.TimeGetStandardNetworkSystemClock },
|
||||
{ ( "time:u", 2), Service.TimeGetStandardSteadyClock },
|
||||
{ ( "time:u", 3), Service.TimeGetTimeZoneService },
|
||||
{ ( "time:s", 0), Service.TimeGetStandardUserSystemClock },
|
||||
{ ( "time:s", 1), Service.TimeGetStandardNetworkSystemClock },
|
||||
{ ( "time:s", 2), Service.TimeGetStandardSteadyClock },
|
||||
{ ( "time:s", 3), Service.TimeGetTimeZoneService },
|
||||
{ ( "vi:m", 2), Service.ViGetDisplayService },
|
||||
};
|
||||
|
||||
private static Dictionary<(Type, int), ServiceProcessRequest> ObjectCmds =
|
||||
new Dictionary<(Type, int), ServiceProcessRequest>()
|
||||
{
|
||||
//IManagerForApplication
|
||||
{ (typeof(AccIManagerForApplication), 0), AccIManagerForApplication.CheckAvailability },
|
||||
{ (typeof(AccIManagerForApplication), 1), AccIManagerForApplication.GetAccountId },
|
||||
|
||||
//IProfile
|
||||
{ (typeof(AccIProfile), 1), AccIProfile.GetBase },
|
||||
|
||||
//IApplicationFunctions
|
||||
{ (typeof(AmIApplicationFunctions), 1), AmIApplicationFunctions.PopLaunchParameter },
|
||||
{ (typeof(AmIApplicationFunctions), 20), AmIApplicationFunctions.EnsureSaveData },
|
||||
{ (typeof(AmIApplicationFunctions), 21), AmIApplicationFunctions.GetDesiredLanguage },
|
||||
|
||||
//IApplicationProxy
|
||||
{ (typeof(AmIApplicationProxy), 0), AmIApplicationProxy.GetCommonStateGetter },
|
||||
{ (typeof(AmIApplicationProxy), 1), AmIApplicationProxy.GetSelfController },
|
||||
{ (typeof(AmIApplicationProxy), 2), AmIApplicationProxy.GetWindowController },
|
||||
{ (typeof(AmIApplicationProxy), 3), AmIApplicationProxy.GetAudioController },
|
||||
{ (typeof(AmIApplicationProxy), 4), AmIApplicationProxy.GetDisplayController },
|
||||
{ (typeof(AmIApplicationProxy), 11), AmIApplicationProxy.GetLibraryAppletCreator },
|
||||
{ (typeof(AmIApplicationProxy), 20), AmIApplicationProxy.GetApplicationFunctions },
|
||||
{ (typeof(AmIApplicationProxy), 1000), AmIApplicationProxy.GetDebugFunctions },
|
||||
|
||||
//ICommonStateGetter
|
||||
{ (typeof(AmICommonStateGetter), 0), AmICommonStateGetter.GetEventHandle },
|
||||
{ (typeof(AmICommonStateGetter), 1), AmICommonStateGetter.ReceiveMessage },
|
||||
{ (typeof(AmICommonStateGetter), 5), AmICommonStateGetter.GetOperationMode },
|
||||
{ (typeof(AmICommonStateGetter), 6), AmICommonStateGetter.GetPerformanceMode },
|
||||
{ (typeof(AmICommonStateGetter), 9), AmICommonStateGetter.GetCurrentFocusState },
|
||||
|
||||
//ISelfController
|
||||
{ (typeof(AmISelfController), 11), AmISelfController.SetOperationModeChangedNotification },
|
||||
{ (typeof(AmISelfController), 12), AmISelfController.SetPerformanceModeChangedNotification },
|
||||
{ (typeof(AmISelfController), 13), AmISelfController.SetFocusHandlingMode },
|
||||
|
||||
//IStorage
|
||||
{ (typeof(AmIStorage), 0), AmIStorage.Open },
|
||||
|
||||
//IStorageAccessor
|
||||
{ (typeof(AmIStorageAccessor), 0), AmIStorageAccessor.GetSize },
|
||||
{ (typeof(AmIStorageAccessor), 11), AmIStorageAccessor.Read },
|
||||
|
||||
//IWindowController
|
||||
{ (typeof(AmIWindowController), 1), AmIWindowController.GetAppletResourceUserId },
|
||||
{ (typeof(AmIWindowController), 10), AmIWindowController.AcquireForegroundRights },
|
||||
|
||||
//ISession
|
||||
{ (typeof(ApmISession), 0), ApmISession.SetPerformanceConfiguration },
|
||||
|
||||
//IAudioRenderer
|
||||
{ (typeof(AudIAudioRenderer), 4), AudIAudioRenderer.RequestUpdateAudioRenderer },
|
||||
{ (typeof(AudIAudioRenderer), 5), AudIAudioRenderer.StartAudioRenderer },
|
||||
{ (typeof(AudIAudioRenderer), 7), AudIAudioRenderer.QuerySystemEvent },
|
||||
|
||||
//IFile
|
||||
{ (typeof(FspSrvIFile), 0), FspSrvIFile.Read },
|
||||
{ (typeof(FspSrvIFile), 1), FspSrvIFile.Write },
|
||||
|
||||
//IFileSystem
|
||||
{ (typeof(FspSrvIFileSystem), 7), FspSrvIFileSystem.GetEntryType },
|
||||
{ (typeof(FspSrvIFileSystem), 8), FspSrvIFileSystem.OpenFile },
|
||||
{ (typeof(FspSrvIFileSystem), 10), FspSrvIFileSystem.Commit },
|
||||
|
||||
//IStorage
|
||||
{ (typeof(FspSrvIStorage), 0), FspSrvIStorage.Read },
|
||||
|
||||
//IAppletResource
|
||||
{ (typeof(HidIAppletResource), 0), HidIAppletResource.GetSharedMemoryHandle },
|
||||
|
||||
//ISystemClock
|
||||
{ (typeof(TimeISystemClock), 0), TimeISystemClock.GetCurrentTime },
|
||||
|
||||
//IApplicationDisplayService
|
||||
{ (typeof(ViIApplicationDisplayService), 100), ViIApplicationDisplayService.GetRelayService },
|
||||
{ (typeof(ViIApplicationDisplayService), 101), ViIApplicationDisplayService.GetSystemDisplayService },
|
||||
{ (typeof(ViIApplicationDisplayService), 102), ViIApplicationDisplayService.GetManagerDisplayService },
|
||||
{ (typeof(ViIApplicationDisplayService), 1010), ViIApplicationDisplayService.OpenDisplay },
|
||||
{ (typeof(ViIApplicationDisplayService), 2020), ViIApplicationDisplayService.OpenLayer },
|
||||
{ (typeof(ViIApplicationDisplayService), 2030), ViIApplicationDisplayService.CreateStrayLayer },
|
||||
{ (typeof(ViIApplicationDisplayService), 2101), ViIApplicationDisplayService.SetLayerScalingMode },
|
||||
{ (typeof(ViIApplicationDisplayService), 5202), ViIApplicationDisplayService.GetDisplayVSyncEvent },
|
||||
|
||||
//IHOSBinderDriver
|
||||
{ (typeof(ViIHOSBinderDriver), 0), ViIHOSBinderDriver.TransactParcel },
|
||||
{ (typeof(ViIHOSBinderDriver), 1), ViIHOSBinderDriver.AdjustRefcount },
|
||||
{ (typeof(ViIHOSBinderDriver), 2), ViIHOSBinderDriver.GetNativeHandle },
|
||||
|
||||
//IManagerDisplayService
|
||||
{ (typeof(ViIManagerDisplayService), 2010), ViIManagerDisplayService.CreateManagedLayer },
|
||||
{ (typeof(ViIManagerDisplayService), 6000), ViIManagerDisplayService.AddToLayerStack },
|
||||
|
||||
//ISystemDisplayService
|
||||
{ (typeof(ViISystemDisplayService), 2205), ViISystemDisplayService.SetLayerZ },
|
||||
};
|
||||
|
||||
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 ProcessRequest(
|
||||
Switch Ns,
|
||||
AMemory Memory,
|
||||
HSession Session,
|
||||
IpcMessage Request,
|
||||
long CmdPtr,
|
||||
int HndId)
|
||||
{
|
||||
IpcMessage Response = new IpcMessage(Request.IsDomain);
|
||||
|
||||
using (MemoryStream Raw = new MemoryStream(Request.RawData))
|
||||
{
|
||||
BinaryReader ReqReader = new BinaryReader(Raw);
|
||||
|
||||
if (Request.Type == IpcMessageType.Request)
|
||||
{
|
||||
string ServiceName = Session.ServiceName;
|
||||
|
||||
ServiceProcessRequest ProcReq = null;
|
||||
|
||||
bool IgnoreNullPR = false;
|
||||
|
||||
if (Session is HDomain Dom)
|
||||
{
|
||||
if (Request.DomCmd == IpcDomCmd.SendMsg)
|
||||
{
|
||||
long Magic = ReqReader.ReadInt64();
|
||||
int CmdId = (int)ReqReader.ReadInt64();
|
||||
|
||||
object Obj = Dom.GetObject(Request.DomObjId);
|
||||
|
||||
if (Obj is HDomain)
|
||||
{
|
||||
ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq);
|
||||
}
|
||||
else if (Obj != null)
|
||||
{
|
||||
ObjectCmds.TryGetValue((Obj.GetType(), CmdId), out ProcReq);
|
||||
}
|
||||
}
|
||||
else if (Request.DomCmd == IpcDomCmd.DeleteObj)
|
||||
{
|
||||
Dom.DeleteObject(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;
|
||||
|
||||
ObjectCmds.TryGetValue((Obj.GetType(), CmdId), out ProcReq);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq);
|
||||
}
|
||||
}
|
||||
|
||||
if (ProcReq != null)
|
||||
{
|
||||
using (MemoryStream ResMS = new MemoryStream())
|
||||
{
|
||||
BinaryWriter ResWriter = new BinaryWriter(ResMS);
|
||||
|
||||
ServiceCtx Context = new ServiceCtx(
|
||||
Ns,
|
||||
Memory,
|
||||
Session,
|
||||
Request,
|
||||
Response,
|
||||
ReqReader,
|
||||
ResWriter);
|
||||
|
||||
long Result = ProcReq(Context);
|
||||
|
||||
Response = FillResponse(Response, Result, ResMS.ToArray());
|
||||
}
|
||||
}
|
||||
else if (!IgnoreNullPR)
|
||||
{
|
||||
throw new NotImplementedException(ServiceName);
|
||||
}
|
||||
}
|
||||
else if (Request.Type == IpcMessageType.Control)
|
||||
{
|
||||
long Magic = ReqReader.ReadInt64();
|
||||
long CmdId = ReqReader.ReadInt64();
|
||||
|
||||
switch (CmdId)
|
||||
{
|
||||
case 0: Request = IpcConvertSessionToDomain(Ns, Session, Response, HndId); break;
|
||||
case 3: Request = IpcQueryBufferPointerSize(Response); break;
|
||||
case 4: Request = IpcDuplicateSessionEx(Ns, Session, Response, ReqReader); break;
|
||||
|
||||
default: throw new NotImplementedException(CmdId.ToString());
|
||||
}
|
||||
}
|
||||
else if (Request.Type == IpcMessageType.Unknown2)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException(Request.Type.ToString());
|
||||
}
|
||||
|
||||
AMemoryHelper.WriteBytes(Memory, CmdPtr, Response.GetBytes(CmdPtr));
|
||||
}
|
||||
}
|
||||
|
||||
private static IpcMessage IpcConvertSessionToDomain(
|
||||
Switch Ns,
|
||||
HSession Session,
|
||||
IpcMessage Response,
|
||||
int HndId)
|
||||
{
|
||||
HDomain Dom = new HDomain(Session);
|
||||
|
||||
Ns.Os.Handles.ReplaceData(HndId, Dom);
|
||||
|
||||
return FillResponse(Response, 0, Dom.GenertateObjectId(Dom));
|
||||
}
|
||||
|
||||
private static IpcMessage IpcDuplicateSessionEx(
|
||||
Switch Ns,
|
||||
HSession Session,
|
||||
IpcMessage Response,
|
||||
BinaryReader ReqReader)
|
||||
{
|
||||
int Unknown = ReqReader.ReadInt32();
|
||||
|
||||
int Handle = Ns.Os.Handles.GenerateId(Session);
|
||||
|
||||
Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
||||
|
||||
return FillResponse(Response, 0);
|
||||
}
|
||||
|
||||
private static IpcMessage IpcQueryBufferPointerSize(IpcMessage Response)
|
||||
{
|
||||
return FillResponse(Response, 0, 0x500);
|
||||
}
|
||||
|
||||
private static IpcMessage FillResponse(IpcMessage Response, long Result, params int[] Values)
|
||||
{
|
||||
using (MemoryStream MS = new MemoryStream())
|
||||
{
|
||||
BinaryWriter Writer = new BinaryWriter(MS);
|
||||
|
||||
foreach (int Value in Values)
|
||||
{
|
||||
Writer.Write(Value);
|
||||
}
|
||||
|
||||
return FillResponse(Response, Result, MS.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private static IpcMessage FillResponse(IpcMessage Response, long Result, byte[] Data = null)
|
||||
{
|
||||
Response.Type = IpcMessageType.Response;
|
||||
|
||||
using (MemoryStream MS = new MemoryStream())
|
||||
{
|
||||
BinaryWriter Writer = new BinaryWriter(MS);
|
||||
|
||||
Writer.Write(SfcoMagic);
|
||||
Writer.Write(Result);
|
||||
|
||||
if (Data != null)
|
||||
{
|
||||
Writer.Write(Data);
|
||||
}
|
||||
|
||||
Response.RawData = MS.ToArray();
|
||||
}
|
||||
|
||||
return Response;
|
||||
}
|
||||
}
|
||||
}
|
||||
231
Ryujinx/OsHle/Ipc/IpcMessage.cs
Normal file
231
Ryujinx/OsHle/Ipc/IpcMessage.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.OsHle.Ipc
|
||||
{
|
||||
class IpcMessage
|
||||
{
|
||||
public IpcMessageType Type { get; set; }
|
||||
|
||||
public IpcHandleDesc HandleDesc { get; set; }
|
||||
|
||||
public List<IpcPtrBuffDesc> PtrBuff { get; private set; }
|
||||
public List<IpcBuffDesc> SendBuff { get; private set; }
|
||||
public List<IpcBuffDesc> ReceiveBuff { get; private set; }
|
||||
public List<IpcBuffDesc> ExchangeBuff { get; private set; }
|
||||
public List<IpcRecvListBuffDesc> RecvListBuff { get; private set; }
|
||||
|
||||
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()
|
||||
{
|
||||
PtrBuff = new List<IpcPtrBuffDesc>();
|
||||
SendBuff = new List<IpcBuffDesc>();
|
||||
ReceiveBuff = new List<IpcBuffDesc>();
|
||||
ExchangeBuff = new List<IpcBuffDesc>();
|
||||
RecvListBuff = new List<IpcRecvListBuffDesc>();
|
||||
|
||||
ResponseObjIds = new List<int>();
|
||||
}
|
||||
|
||||
public IpcMessage(bool Domain) : this()
|
||||
{
|
||||
IsDomain = Domain;
|
||||
}
|
||||
|
||||
public IpcMessage(byte[] Data, long CmdPtr, bool Domain) : this()
|
||||
{
|
||||
using (MemoryStream MS = new MemoryStream(Data))
|
||||
{
|
||||
BinaryReader Reader = new BinaryReader(MS);
|
||||
|
||||
Initialize(Reader, CmdPtr, Domain);
|
||||
}
|
||||
}
|
||||
|
||||
private void Initialize(BinaryReader Reader, long CmdPtr, bool Domain)
|
||||
{
|
||||
IsDomain = Domain;
|
||||
|
||||
int Word0 = Reader.ReadInt32();
|
||||
int Word1 = Reader.ReadInt32();
|
||||
|
||||
Type = (IpcMessageType)(Word0 & 0xffff);
|
||||
|
||||
int PtrBuffCount = (Word0 >> 16) & 0xf;
|
||||
int SendBuffCount = (Word0 >> 20) & 0xf;
|
||||
int RecvBuffCount = (Word0 >> 24) & 0xf;
|
||||
int XchgBuffCount = (Word0 >> 28) & 0xf;
|
||||
|
||||
int RawDataSize = (Word1 >> 0) & 0x3ff;
|
||||
int RecvListFlags = (Word1 >> 10) & 0xf;
|
||||
bool HndDescEnable = ((Word1 >> 31) & 0x1) != 0;
|
||||
|
||||
if (HndDescEnable)
|
||||
{
|
||||
HandleDesc = new IpcHandleDesc(Reader);
|
||||
}
|
||||
|
||||
for (int Index = 0; Index < PtrBuffCount; Index++)
|
||||
{
|
||||
PtrBuff.Add(new IpcPtrBuffDesc(Reader));
|
||||
}
|
||||
|
||||
void ReadBuff(List<IpcBuffDesc> Buff, int Count)
|
||||
{
|
||||
for (int Index = 0; Index < Count; Index++)
|
||||
{
|
||||
Buff.Add(new IpcBuffDesc(Reader));
|
||||
}
|
||||
}
|
||||
|
||||
ReadBuff(SendBuff, SendBuffCount);
|
||||
ReadBuff(ReceiveBuff, RecvBuffCount);
|
||||
ReadBuff(ExchangeBuff, XchgBuffCount);
|
||||
|
||||
RawDataSize *= 4;
|
||||
|
||||
long RecvListPos = Reader.BaseStream.Position + RawDataSize;
|
||||
|
||||
long Pad0 = GetPadSize16(Reader.BaseStream.Position + CmdPtr);
|
||||
|
||||
Reader.BaseStream.Seek(Pad0, SeekOrigin.Current);
|
||||
|
||||
int RecvListCount = RecvListFlags - 2;
|
||||
|
||||
if (RecvListCount == 0)
|
||||
{
|
||||
RecvListCount = 1;
|
||||
}
|
||||
else if (RecvListCount < 0)
|
||||
{
|
||||
RecvListCount = 0;
|
||||
}
|
||||
|
||||
if (Domain)
|
||||
{
|
||||
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);
|
||||
|
||||
for (int Index = 0; Index < RecvListCount; Index++)
|
||||
{
|
||||
RecvListBuff.Add(new IpcRecvListBuffDesc(Reader));
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetBytes(long CmdPtr)
|
||||
{
|
||||
//todo
|
||||
using (MemoryStream MS = new MemoryStream())
|
||||
{
|
||||
BinaryWriter Writer = new BinaryWriter(MS);
|
||||
|
||||
int Word0;
|
||||
int Word1;
|
||||
|
||||
Word0 = (int)Type;
|
||||
Word0 |= (PtrBuff.Count & 0xf) << 16;
|
||||
Word0 |= (SendBuff.Count & 0xf) << 20;
|
||||
Word0 |= (ReceiveBuff.Count & 0xf) << 24;
|
||||
Word0 |= (ExchangeBuff.Count & 0xf) << 28;
|
||||
|
||||
byte[] HandleData = new byte[0];
|
||||
|
||||
if (HandleDesc != null)
|
||||
{
|
||||
HandleData = HandleDesc.GetBytes();
|
||||
}
|
||||
|
||||
int DataLength = RawData?.Length ?? 0;
|
||||
|
||||
int Pad0 = (int)GetPadSize16(CmdPtr + 8 + HandleData.Length);
|
||||
|
||||
//Apparently, padding after Raw Data is 16 bytes, however when there is
|
||||
//padding before Raw Data too, we need to subtract the size of this padding.
|
||||
//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;
|
||||
|
||||
Word1 = DataLength & 0x3ff;
|
||||
|
||||
if (HandleDesc != null)
|
||||
{
|
||||
Word1 |= 1 << 31;
|
||||
}
|
||||
|
||||
Writer.Write(Word0);
|
||||
Writer.Write(Word1);
|
||||
Writer.Write(HandleData);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
private long GetPadSize16(long Position)
|
||||
{
|
||||
if ((Position & 0xf) != 0)
|
||||
{
|
||||
return 0x10 - (Position & 0xf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long GetSendBuffPtr()
|
||||
{
|
||||
if (SendBuff.Count > 0 && SendBuff[0].Position != 0)
|
||||
{
|
||||
return SendBuff[0].Position;
|
||||
}
|
||||
|
||||
if (PtrBuff.Count > 0 && PtrBuff[0].Position != 0)
|
||||
{
|
||||
return PtrBuff[0].Position;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Ryujinx/OsHle/Ipc/IpcMessageType.cs
Normal file
10
Ryujinx/OsHle/Ipc/IpcMessageType.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Ryujinx.OsHle.Ipc
|
||||
{
|
||||
enum IpcMessageType
|
||||
{
|
||||
Response = 0,
|
||||
Unknown2 = 2,
|
||||
Request = 4,
|
||||
Control = 5
|
||||
}
|
||||
}
|
||||
26
Ryujinx/OsHle/Ipc/IpcPtrBuffDesc.cs
Normal file
26
Ryujinx/OsHle/Ipc/IpcPtrBuffDesc.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.OsHle.Ipc
|
||||
{
|
||||
struct IpcPtrBuffDesc
|
||||
{
|
||||
public long Position { get; private set; }
|
||||
public int Index { get; private set; }
|
||||
public short Size { get; private set; }
|
||||
|
||||
public IpcPtrBuffDesc(BinaryReader Reader)
|
||||
{
|
||||
long Word0 = Reader.ReadUInt32();
|
||||
long Word1 = Reader.ReadUInt32();
|
||||
|
||||
Position = Word1;
|
||||
Position |= (Word0 << 20) & 0x0f00000000;
|
||||
Position |= (Word0 << 30) & 0x7000000000;
|
||||
|
||||
Index = ((int)Word0 >> 0) & 0x03f;
|
||||
Index |= ((int)Word0 >> 3) & 0x1c0;
|
||||
|
||||
Size = (short)(Word0 >> 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
Ryujinx/OsHle/Ipc/IpcRecvListBuffDesc.cs
Normal file
19
Ryujinx/OsHle/Ipc/IpcRecvListBuffDesc.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.OsHle.Ipc
|
||||
{
|
||||
struct IpcRecvListBuffDesc
|
||||
{
|
||||
public long Position { get; private set; }
|
||||
public short Size { get; private set; }
|
||||
|
||||
public IpcRecvListBuffDesc(BinaryReader Reader)
|
||||
{
|
||||
long Value = Reader.ReadInt64();
|
||||
|
||||
Position = Value & 0xffffffffffff;
|
||||
|
||||
Size = (short)(Value >> 48);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user