2023-01-04 23:15:45 +01:00
|
|
|
|
using Ryujinx.Common;
|
|
|
|
|
using Ryujinx.Horizon.Sdk.Sf.Cmif;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
|
|
|
|
namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|
|
|
|
{
|
|
|
|
|
ref struct HipcMessage
|
|
|
|
|
{
|
|
|
|
|
public const int AutoReceiveStatic = byte.MaxValue;
|
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
public HipcMetadata Meta;
|
2023-01-04 23:15:45 +01:00
|
|
|
|
public HipcMessageData Data;
|
2023-01-08 13:13:39 +01:00
|
|
|
|
public ulong Pid;
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
|
|
|
|
public HipcMessage(Span<byte> data)
|
|
|
|
|
{
|
|
|
|
|
int initialLength = data.Length;
|
|
|
|
|
|
|
|
|
|
Header header = MemoryMarshal.Cast<byte, Header>(data)[0];
|
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
data = data[Unsafe.SizeOf<Header>()..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
int receiveStaticsCount = 0;
|
|
|
|
|
ulong pid = 0;
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
|
|
|
|
if (header.ReceiveStaticMode != 0)
|
|
|
|
|
{
|
|
|
|
|
if (header.ReceiveStaticMode == 2)
|
|
|
|
|
{
|
|
|
|
|
receiveStaticsCount = AutoReceiveStatic;
|
|
|
|
|
}
|
|
|
|
|
else if (header.ReceiveStaticMode > 2)
|
|
|
|
|
{
|
|
|
|
|
receiveStaticsCount = header.ReceiveStaticMode - 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SpecialHeader specialHeader = default;
|
|
|
|
|
|
|
|
|
|
if (header.HasSpecialHeader)
|
|
|
|
|
{
|
|
|
|
|
specialHeader = MemoryMarshal.Cast<byte, SpecialHeader>(data)[0];
|
2023-01-08 13:13:39 +01:00
|
|
|
|
data = data[Unsafe.SizeOf<SpecialHeader>()..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
|
|
|
|
if (specialHeader.SendPid)
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
pid = MemoryMarshal.Cast<byte, ulong>(data)[0];
|
|
|
|
|
data = data[sizeof(ulong)..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Meta = new HipcMetadata()
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
Type = (int)header.Type,
|
|
|
|
|
SendStaticsCount = header.SendStaticsCount,
|
|
|
|
|
SendBuffersCount = header.SendBuffersCount,
|
|
|
|
|
ReceiveBuffersCount = header.ReceiveBuffersCount,
|
2023-01-04 23:15:45 +01:00
|
|
|
|
ExchangeBuffersCount = header.ExchangeBuffersCount,
|
2023-01-08 13:13:39 +01:00
|
|
|
|
DataWordsCount = header.DataWordsCount,
|
|
|
|
|
ReceiveStaticsCount = receiveStaticsCount,
|
|
|
|
|
SendPid = specialHeader.SendPid,
|
|
|
|
|
CopyHandlesCount = specialHeader.CopyHandlesCount,
|
|
|
|
|
MoveHandlesCount = specialHeader.MoveHandlesCount
|
2023-01-04 23:15:45 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Data = CreateMessageData(Meta, data, initialLength);
|
2023-01-08 13:13:39 +01:00
|
|
|
|
Pid = pid;
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static HipcMessageData WriteResponse(
|
|
|
|
|
Span<byte> destination,
|
2023-01-08 13:13:39 +01:00
|
|
|
|
int sendStaticCount,
|
|
|
|
|
int dataWordsCount,
|
|
|
|
|
int copyHandlesCount,
|
|
|
|
|
int moveHandlesCount)
|
2023-01-04 23:15:45 +01:00
|
|
|
|
{
|
|
|
|
|
return WriteMessage(destination, new HipcMetadata()
|
|
|
|
|
{
|
|
|
|
|
SendStaticsCount = sendStaticCount,
|
2023-01-08 13:13:39 +01:00
|
|
|
|
DataWordsCount = dataWordsCount,
|
2023-01-04 23:15:45 +01:00
|
|
|
|
CopyHandlesCount = copyHandlesCount,
|
|
|
|
|
MoveHandlesCount = moveHandlesCount
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static HipcMessageData WriteMessage(Span<byte> destination, HipcMetadata meta)
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
int initialLength = destination.Length;
|
2023-01-04 23:15:45 +01:00
|
|
|
|
bool hasSpecialHeader = meta.SendPid || meta.CopyHandlesCount != 0 || meta.MoveHandlesCount != 0;
|
|
|
|
|
|
|
|
|
|
MemoryMarshal.Cast<byte, Header>(destination)[0] = new Header()
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
Type = (CommandType)meta.Type,
|
|
|
|
|
SendStaticsCount = meta.SendStaticsCount,
|
|
|
|
|
SendBuffersCount = meta.SendBuffersCount,
|
|
|
|
|
ReceiveBuffersCount = meta.ReceiveBuffersCount,
|
2023-01-04 23:15:45 +01:00
|
|
|
|
ExchangeBuffersCount = meta.ExchangeBuffersCount,
|
2023-01-08 13:13:39 +01:00
|
|
|
|
DataWordsCount = meta.DataWordsCount,
|
|
|
|
|
ReceiveStaticMode = meta.ReceiveStaticsCount != 0 ? (meta.ReceiveStaticsCount != AutoReceiveStatic ? meta.ReceiveStaticsCount + 2 : 2) : 0,
|
|
|
|
|
HasSpecialHeader = hasSpecialHeader
|
2023-01-04 23:15:45 +01:00
|
|
|
|
};
|
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
destination = destination[Unsafe.SizeOf<Header>()..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
|
|
|
|
if (hasSpecialHeader)
|
|
|
|
|
{
|
|
|
|
|
MemoryMarshal.Cast<byte, SpecialHeader>(destination)[0] = new SpecialHeader()
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
SendPid = meta.SendPid,
|
2023-01-04 23:15:45 +01:00
|
|
|
|
CopyHandlesCount = meta.CopyHandlesCount,
|
|
|
|
|
MoveHandlesCount = meta.MoveHandlesCount
|
|
|
|
|
};
|
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
destination = destination[Unsafe.SizeOf<SpecialHeader>()..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
|
|
|
|
if (meta.SendPid)
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
destination = destination[sizeof(ulong)..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CreateMessageData(meta, destination, initialLength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static HipcMessageData CreateMessageData(HipcMetadata meta, Span<byte> data, int initialLength)
|
|
|
|
|
{
|
|
|
|
|
Span<int> copyHandles = Span<int>.Empty;
|
|
|
|
|
|
|
|
|
|
if (meta.CopyHandlesCount != 0)
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
copyHandles = MemoryMarshal.Cast<byte, int>(data)[..meta.CopyHandlesCount];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
data = data[(meta.CopyHandlesCount * sizeof(int))..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Span<int> moveHandles = Span<int>.Empty;
|
|
|
|
|
|
|
|
|
|
if (meta.MoveHandlesCount != 0)
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
moveHandles = MemoryMarshal.Cast<byte, int>(data)[..meta.MoveHandlesCount];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
data = data[(meta.MoveHandlesCount * sizeof(int))..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Span<HipcStaticDescriptor> sendStatics = Span<HipcStaticDescriptor>.Empty;
|
|
|
|
|
|
|
|
|
|
if (meta.SendStaticsCount != 0)
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
sendStatics = MemoryMarshal.Cast<byte, HipcStaticDescriptor>(data)[..meta.SendStaticsCount];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
data = data[(meta.SendStaticsCount * Unsafe.SizeOf<HipcStaticDescriptor>())..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Span<HipcBufferDescriptor> sendBuffers = Span<HipcBufferDescriptor>.Empty;
|
|
|
|
|
|
|
|
|
|
if (meta.SendBuffersCount != 0)
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
sendBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data)[..meta.SendBuffersCount];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
data = data[(meta.SendBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>())..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Span<HipcBufferDescriptor> receiveBuffers = Span<HipcBufferDescriptor>.Empty;
|
|
|
|
|
|
|
|
|
|
if (meta.ReceiveBuffersCount != 0)
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
receiveBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data)[..meta.ReceiveBuffersCount];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
data = data[(meta.ReceiveBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>())..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Span<HipcBufferDescriptor> exchangeBuffers = Span<HipcBufferDescriptor>.Empty;
|
|
|
|
|
|
|
|
|
|
if (meta.ExchangeBuffersCount != 0)
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
exchangeBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data)[..meta.ExchangeBuffersCount];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
data = data[(meta.ExchangeBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>())..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Span<uint> dataWords = Span<uint>.Empty;
|
|
|
|
|
|
|
|
|
|
if (meta.DataWordsCount != 0)
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
int dataOffset = initialLength - data.Length;
|
2023-01-04 23:15:45 +01:00
|
|
|
|
int dataOffsetAligned = BitUtils.AlignUp(dataOffset, 0x10);
|
2023-01-08 13:13:39 +01:00
|
|
|
|
int padding = (dataOffsetAligned - dataOffset) / sizeof(uint);
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
dataWords = MemoryMarshal.Cast<byte, uint>(data)[padding..meta.DataWordsCount];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
data = data[(meta.DataWordsCount * sizeof(uint))..];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Span<HipcReceiveListEntry> receiveList = Span<HipcReceiveListEntry>.Empty;
|
|
|
|
|
|
|
|
|
|
if (meta.ReceiveStaticsCount != 0)
|
|
|
|
|
{
|
|
|
|
|
int receiveListSize = meta.ReceiveStaticsCount == AutoReceiveStatic ? 1 : meta.ReceiveStaticsCount;
|
|
|
|
|
|
2023-01-08 13:13:39 +01:00
|
|
|
|
receiveList = MemoryMarshal.Cast<byte, HipcReceiveListEntry>(data)[..receiveListSize];
|
2023-01-04 23:15:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new HipcMessageData()
|
|
|
|
|
{
|
2023-01-08 13:13:39 +01:00
|
|
|
|
SendStatics = sendStatics,
|
|
|
|
|
SendBuffers = sendBuffers,
|
|
|
|
|
ReceiveBuffers = receiveBuffers,
|
2023-01-04 23:15:45 +01:00
|
|
|
|
ExchangeBuffers = exchangeBuffers,
|
2023-01-08 13:13:39 +01:00
|
|
|
|
DataWords = dataWords,
|
|
|
|
|
ReceiveList = receiveList,
|
|
|
|
|
CopyHandles = copyHandles,
|
|
|
|
|
MoveHandles = moveHandles
|
2023-01-04 23:15:45 +01:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|