HipcMessage.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. using Ryujinx.Common;
  2. using Ryujinx.Horizon.Sdk.Sf.Cmif;
  3. using System;
  4. using System.Runtime.CompilerServices;
  5. using System.Runtime.InteropServices;
  6. namespace Ryujinx.Horizon.Sdk.Sf.Hipc
  7. {
  8. ref struct HipcMessage
  9. {
  10. public const int AutoReceiveStatic = byte.MaxValue;
  11. public HipcMetadata Meta;
  12. public HipcMessageData Data;
  13. public ulong Pid;
  14. public HipcMessage(Span<byte> data)
  15. {
  16. int initialLength = data.Length;
  17. Header header = MemoryMarshal.Cast<byte, Header>(data)[0];
  18. data = data[Unsafe.SizeOf<Header>()..];
  19. int receiveStaticsCount = 0;
  20. ulong pid = 0;
  21. if (header.ReceiveStaticMode != 0)
  22. {
  23. if (header.ReceiveStaticMode == 2)
  24. {
  25. receiveStaticsCount = AutoReceiveStatic;
  26. }
  27. else if (header.ReceiveStaticMode > 2)
  28. {
  29. receiveStaticsCount = header.ReceiveStaticMode - 2;
  30. }
  31. }
  32. SpecialHeader specialHeader = default;
  33. if (header.HasSpecialHeader)
  34. {
  35. specialHeader = MemoryMarshal.Cast<byte, SpecialHeader>(data)[0];
  36. data = data[Unsafe.SizeOf<SpecialHeader>()..];
  37. if (specialHeader.SendPid)
  38. {
  39. pid = MemoryMarshal.Cast<byte, ulong>(data)[0];
  40. data = data[sizeof(ulong)..];
  41. }
  42. }
  43. Meta = new HipcMetadata()
  44. {
  45. Type = (int)header.Type,
  46. SendStaticsCount = header.SendStaticsCount,
  47. SendBuffersCount = header.SendBuffersCount,
  48. ReceiveBuffersCount = header.ReceiveBuffersCount,
  49. ExchangeBuffersCount = header.ExchangeBuffersCount,
  50. DataWordsCount = header.DataWordsCount,
  51. ReceiveStaticsCount = receiveStaticsCount,
  52. SendPid = specialHeader.SendPid,
  53. CopyHandlesCount = specialHeader.CopyHandlesCount,
  54. MoveHandlesCount = specialHeader.MoveHandlesCount
  55. };
  56. Data = CreateMessageData(Meta, data, initialLength);
  57. Pid = pid;
  58. }
  59. public static HipcMessageData WriteResponse(
  60. Span<byte> destination,
  61. int sendStaticCount,
  62. int dataWordsCount,
  63. int copyHandlesCount,
  64. int moveHandlesCount)
  65. {
  66. return WriteMessage(destination, new HipcMetadata()
  67. {
  68. SendStaticsCount = sendStaticCount,
  69. DataWordsCount = dataWordsCount,
  70. CopyHandlesCount = copyHandlesCount,
  71. MoveHandlesCount = moveHandlesCount
  72. });
  73. }
  74. public static HipcMessageData WriteMessage(Span<byte> destination, HipcMetadata meta)
  75. {
  76. int initialLength = destination.Length;
  77. bool hasSpecialHeader = meta.SendPid || meta.CopyHandlesCount != 0 || meta.MoveHandlesCount != 0;
  78. MemoryMarshal.Cast<byte, Header>(destination)[0] = new Header()
  79. {
  80. Type = (CommandType)meta.Type,
  81. SendStaticsCount = meta.SendStaticsCount,
  82. SendBuffersCount = meta.SendBuffersCount,
  83. ReceiveBuffersCount = meta.ReceiveBuffersCount,
  84. ExchangeBuffersCount = meta.ExchangeBuffersCount,
  85. DataWordsCount = meta.DataWordsCount,
  86. ReceiveStaticMode = meta.ReceiveStaticsCount != 0 ? (meta.ReceiveStaticsCount != AutoReceiveStatic ? meta.ReceiveStaticsCount + 2 : 2) : 0,
  87. HasSpecialHeader = hasSpecialHeader
  88. };
  89. destination = destination[Unsafe.SizeOf<Header>()..];
  90. if (hasSpecialHeader)
  91. {
  92. MemoryMarshal.Cast<byte, SpecialHeader>(destination)[0] = new SpecialHeader()
  93. {
  94. SendPid = meta.SendPid,
  95. CopyHandlesCount = meta.CopyHandlesCount,
  96. MoveHandlesCount = meta.MoveHandlesCount
  97. };
  98. destination = destination[Unsafe.SizeOf<SpecialHeader>()..];
  99. if (meta.SendPid)
  100. {
  101. destination = destination[sizeof(ulong)..];
  102. }
  103. }
  104. return CreateMessageData(meta, destination, initialLength);
  105. }
  106. private static HipcMessageData CreateMessageData(HipcMetadata meta, Span<byte> data, int initialLength)
  107. {
  108. Span<int> copyHandles = Span<int>.Empty;
  109. if (meta.CopyHandlesCount != 0)
  110. {
  111. copyHandles = MemoryMarshal.Cast<byte, int>(data)[..meta.CopyHandlesCount];
  112. data = data[(meta.CopyHandlesCount * sizeof(int))..];
  113. }
  114. Span<int> moveHandles = Span<int>.Empty;
  115. if (meta.MoveHandlesCount != 0)
  116. {
  117. moveHandles = MemoryMarshal.Cast<byte, int>(data)[..meta.MoveHandlesCount];
  118. data = data[(meta.MoveHandlesCount * sizeof(int))..];
  119. }
  120. Span<HipcStaticDescriptor> sendStatics = Span<HipcStaticDescriptor>.Empty;
  121. if (meta.SendStaticsCount != 0)
  122. {
  123. sendStatics = MemoryMarshal.Cast<byte, HipcStaticDescriptor>(data)[..meta.SendStaticsCount];
  124. data = data[(meta.SendStaticsCount * Unsafe.SizeOf<HipcStaticDescriptor>())..];
  125. }
  126. Span<HipcBufferDescriptor> sendBuffers = Span<HipcBufferDescriptor>.Empty;
  127. if (meta.SendBuffersCount != 0)
  128. {
  129. sendBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data)[..meta.SendBuffersCount];
  130. data = data[(meta.SendBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>())..];
  131. }
  132. Span<HipcBufferDescriptor> receiveBuffers = Span<HipcBufferDescriptor>.Empty;
  133. if (meta.ReceiveBuffersCount != 0)
  134. {
  135. receiveBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data)[..meta.ReceiveBuffersCount];
  136. data = data[(meta.ReceiveBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>())..];
  137. }
  138. Span<HipcBufferDescriptor> exchangeBuffers = Span<HipcBufferDescriptor>.Empty;
  139. if (meta.ExchangeBuffersCount != 0)
  140. {
  141. exchangeBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data)[..meta.ExchangeBuffersCount];
  142. data = data[(meta.ExchangeBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>())..];
  143. }
  144. Span<uint> dataWords = Span<uint>.Empty;
  145. if (meta.DataWordsCount != 0)
  146. {
  147. int dataOffset = initialLength - data.Length;
  148. int dataOffsetAligned = BitUtils.AlignUp(dataOffset, 0x10);
  149. int padding = (dataOffsetAligned - dataOffset) / sizeof(uint);
  150. dataWords = MemoryMarshal.Cast<byte, uint>(data)[padding..meta.DataWordsCount];
  151. data = data[(meta.DataWordsCount * sizeof(uint))..];
  152. }
  153. Span<HipcReceiveListEntry> receiveList = Span<HipcReceiveListEntry>.Empty;
  154. if (meta.ReceiveStaticsCount != 0)
  155. {
  156. int receiveListSize = meta.ReceiveStaticsCount == AutoReceiveStatic ? 1 : meta.ReceiveStaticsCount;
  157. receiveList = MemoryMarshal.Cast<byte, HipcReceiveListEntry>(data)[..receiveListSize];
  158. }
  159. return new HipcMessageData()
  160. {
  161. SendStatics = sendStatics,
  162. SendBuffers = sendBuffers,
  163. ReceiveBuffers = receiveBuffers,
  164. ExchangeBuffers = exchangeBuffers,
  165. DataWords = dataWords,
  166. ReceiveList = receiveList,
  167. CopyHandles = copyHandles,
  168. MoveHandles = moveHandles
  169. };
  170. }
  171. }
  172. }