| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- using System.Collections.Generic;
- using System.IO;
- namespace Ryujinx.HLE.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 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(byte[] Data, long CmdPtr) : this()
- {
- using (MemoryStream MS = new MemoryStream(Data))
- {
- BinaryReader Reader = new BinaryReader(MS);
- Initialize(Reader, CmdPtr);
- }
- }
- private void Initialize(BinaryReader Reader, long CmdPtr)
- {
- 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;
- }
- 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)
- {
- 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) / 4;
- Word1 = DataLength & 0x3ff;
- if (HandleDesc != null)
- {
- Word1 |= 1 << 31;
- }
- Writer.Write(Word0);
- Writer.Write(Word1);
- Writer.Write(HandleData);
- MS.Seek(Pad0, SeekOrigin.Current);
- if (RawData != null)
- {
- Writer.Write(RawData);
- }
- 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 Position, long Size) GetBufferType0x21()
- {
- if (PtrBuff.Count != 0 &&
- PtrBuff[0].Position != 0 &&
- PtrBuff[0].Size != 0)
- {
- return (PtrBuff[0].Position, PtrBuff[0].Size);
- }
- if (SendBuff.Count != 0 &&
- SendBuff[0].Position != 0 &&
- SendBuff[0].Size != 0)
- {
- return (SendBuff[0].Position, SendBuff[0].Size);
- }
- return (0, 0);
- }
- public (long Position, long Size) GetBufferType0x22()
- {
- if (RecvListBuff.Count != 0 &&
- RecvListBuff[0].Position != 0 &&
- RecvListBuff[0].Size != 0)
- {
- return (RecvListBuff[0].Position, RecvListBuff[0].Size);
- }
- if (ReceiveBuff.Count != 0 &&
- ReceiveBuff[0].Position != 0 &&
- ReceiveBuff[0].Size != 0)
- {
- return (ReceiveBuff[0].Position, ReceiveBuff[0].Size);
- }
- return (0, 0);
- }
- }
- }
|