| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- namespace Ryujinx.HLE.HOS.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> ObjectIds { 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>();
- ObjectIds = 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;
- // only HIPC have the padding requirements.
- if (Type < IpcMessageType.TipcCloseSession)
- {
- long pad0 = GetPadSize16(reader.BaseStream.Position + cmdPtr);
- if (rawDataSize != 0)
- {
- rawDataSize -= (int)pad0;
- }
- 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, ulong recvListAddr)
- {
- 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;
- dataLength = (dataLength + 3) & ~3;
- int rawLength = dataLength;
- int pad0 = (int)GetPadSize16(cmdPtr + 8 + handleData.Length + PtrBuff.Count * 8);
- // 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) | (2 << 10);
- if (HandleDesc != null)
- {
- word1 |= 1 << 31;
- }
- writer.Write(word0);
- writer.Write(word1);
- writer.Write(handleData);
- for (int index = 0; index < PtrBuff.Count; index++)
- {
- writer.Write(PtrBuff[index].GetWord0());
- writer.Write(PtrBuff[index].GetWord1());
- }
- ms.Seek(pad0, SeekOrigin.Current);
- if (RawData != null)
- {
- writer.Write(RawData);
- ms.Seek(rawLength - RawData.Length, SeekOrigin.Current);
- }
- writer.Write(new byte[pad1]);
- writer.Write(recvListAddr);
- return ms.ToArray();
- }
- }
- public byte[] GetBytesTipc()
- {
- Debug.Assert(PtrBuff.Count == 0);
- using (MemoryStream ms = new MemoryStream())
- {
- BinaryWriter writer = new BinaryWriter(ms);
- int word0;
- int word1;
- word0 = (int)Type;
- 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;
- dataLength = ((dataLength + 3) & ~3) / 4;
- word1 = (dataLength & 0x3ff);
- if (HandleDesc != null)
- {
- word1 |= 1 << 31;
- }
- writer.Write(word0);
- writer.Write(word1);
- writer.Write(handleData);
- if (RawData != null)
- {
- writer.Write(RawData);
- }
- return ms.ToArray();
- }
- }
- private long GetPadSize16(long position)
- {
- if ((position & 0xf) != 0)
- {
- return 0x10 - (position & 0xf);
- }
- return 0;
- }
- // ReSharper disable once InconsistentNaming
- public (ulong Position, ulong Size) GetBufferType0x21(int index = 0)
- {
- if (PtrBuff.Count > index && PtrBuff[index].Position != 0)
- {
- return (PtrBuff[index].Position, PtrBuff[index].Size);
- }
- if (SendBuff.Count > index)
- {
- return (SendBuff[index].Position, SendBuff[index].Size);
- }
- return (0, 0);
- }
- // ReSharper disable once InconsistentNaming
- public (ulong Position, ulong Size) GetBufferType0x22(int index = 0)
- {
- if (RecvListBuff.Count > index && RecvListBuff[index].Position != 0)
- {
- return (RecvListBuff[index].Position, RecvListBuff[index].Size);
- }
- if (ReceiveBuff.Count > index)
- {
- return (ReceiveBuff[index].Position, ReceiveBuff[index].Size);
- }
- return (0, 0);
- }
- }
- }
|