using System; using System.IO; namespace Ryujinx.Core.OsHle.Ipc { public static class IpcLog { public static string Message(byte[] Data, long CmdPtr, bool Domain) { string IpcMessage = ""; using (MemoryStream MS = new MemoryStream(Data)) { BinaryReader Reader = new BinaryReader(MS); int Word0 = Reader.ReadInt32(); int Word1 = Reader.ReadInt32(); int Type = (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; IpcMessage += Environment.NewLine + $" {Logging.GetExecutionTime()} | IpcMessage >" + Environment.NewLine + $" Type: {Enum.GetName(typeof(IpcMessageType), Type)}" + Environment.NewLine + $" PtrBuffCount: {PtrBuffCount.ToString()}" + Environment.NewLine + $" SendBuffCount: {SendBuffCount.ToString()}" + Environment.NewLine + $" RecvBuffCount: {RecvBuffCount.ToString()}" + Environment.NewLine + $" XchgBuffCount: {XchgBuffCount.ToString()}" + Environment.NewLine + $" RawDataSize: {RawDataSize.ToString()}" + Environment.NewLine + $" RecvListFlags: {RecvListFlags.ToString()}" + Environment.NewLine + $" HndDescEnable: {HndDescEnable.ToString()}" + Environment.NewLine; if (HndDescEnable) { int Word = Reader.ReadInt32(); bool HasPId = (Word & 1) != 0; int[] ToCopy = new int[(Word >> 1) & 0xf]; int[] ToMove = new int[(Word >> 5) & 0xf]; long 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(); } IpcMessage += Environment.NewLine + " HndDesc:" + Environment.NewLine + $" PId: {PId.ToString()}" + Environment.NewLine + $" ToCopy.Length: {ToCopy.Length.ToString()}" + Environment.NewLine + $" ToMove.Length: {ToMove.Length.ToString()}" + Environment.NewLine; } for (int Index = 0; Index < PtrBuffCount; Index++) { long IpcPtrBuffDescWord0 = Reader.ReadUInt32(); long IpcPtrBuffDescWord1 = Reader.ReadUInt32(); long Position = IpcPtrBuffDescWord1; Position |= (IpcPtrBuffDescWord0 << 20) & 0x0f00000000; Position |= (IpcPtrBuffDescWord0 << 30) & 0x7000000000; int IpcPtrBuffDescIndex = ((int)IpcPtrBuffDescWord0 >> 0) & 0x03f; IpcPtrBuffDescIndex |= ((int)IpcPtrBuffDescWord0 >> 3) & 0x1c0; short Size = (short)(IpcPtrBuffDescWord0 >> 16); IpcMessage += Environment.NewLine + $" PtrBuff[{Index}]:" + Environment.NewLine + $" Position: {Position.ToString()}" + Environment.NewLine + $" IpcPtrBuffDescIndex: {IpcPtrBuffDescIndex.ToString()}" + Environment.NewLine + $" Size: {Size.ToString()}" + Environment.NewLine; } ReadIpcBuffValues(Reader, SendBuffCount, IpcMessage, "SendBuff"); ReadIpcBuffValues(Reader, RecvBuffCount, IpcMessage, "RecvBuff"); ReadIpcBuffValues(Reader, XchgBuffCount, IpcMessage, "XchgBuff"); RawDataSize *= 4; long RecvListPos = Reader.BaseStream.Position + RawDataSize; long Pad0 = 0; if ((Reader.BaseStream.Position + CmdPtr & 0xf) != 0) { Pad0 = 0x10 - (Reader.BaseStream.Position + CmdPtr & 0xf); } Reader.BaseStream.Seek(Pad0, SeekOrigin.Current); int RecvListCount = RecvListFlags - 2; if (RecvListCount == 0) { RecvListCount = 1; } else if (RecvListCount < 0) { RecvListCount = 0; } if (Domain && (IpcMessageType)Type == IpcMessageType.Request) { int DomWord0 = Reader.ReadInt32(); int DomCmd = (DomWord0 & 0xff); RawDataSize = (DomWord0 >> 16) & 0xffff; int DomObjId = Reader.ReadInt32(); Reader.ReadInt64(); //Padding IpcMessage += Environment.NewLine + $" Domain:" + Environment.NewLine + Environment.NewLine + $" DomObjId: {DomObjId.ToString()}" + Environment.NewLine; } byte[] RawData = Reader.ReadBytes(RawDataSize); IpcMessage += Environment.NewLine + $" RawData:" + Environment.NewLine + Logging.HexDump(RawData); Reader.BaseStream.Seek(RecvListPos, SeekOrigin.Begin); for (int Index = 0; Index < RecvListCount; Index++) { long RecvListBuffValue = Reader.ReadInt64(); long RecvListBuffPosition = RecvListBuffValue & 0xffffffffffff; long RecvListBuffSize = (short)(RecvListBuffValue >> 48); IpcMessage += Environment.NewLine + $" RecvList[{Index}]:" + Environment.NewLine + $" Value: {RecvListBuffValue.ToString()}" + Environment.NewLine + $" Position: {RecvListBuffPosition.ToString()}" + Environment.NewLine + $" Size: {RecvListBuffSize.ToString()}" + Environment.NewLine; } } return IpcMessage; } private static void ReadIpcBuffValues(BinaryReader Reader, int Count, string IpcMessage, string BufferName) { for (int Index = 0; Index < Count; Index++) { long Word0 = Reader.ReadUInt32(); long Word1 = Reader.ReadUInt32(); long Word2 = Reader.ReadUInt32(); long Position = Word1; Position |= (Word2 << 4) & 0x0f00000000; Position |= (Word2 << 34) & 0x7000000000; long Size = Word0; Size |= (Word2 << 8) & 0xf00000000; int Flags = (int)Word2 & 3; IpcMessage += Environment.NewLine + $" {BufferName}[{Index}]:" + Environment.NewLine + $" Position: {Position.ToString()}" + Environment.NewLine + $" Flags: {Flags.ToString()}" + Environment.NewLine + $" Size: {Size.ToString()}" + Environment.NewLine; } } } }