Horizon: Impl Prepo, Fixes bugs, Clean things (#4220)
* Horizon: Impl Prepo, Fixes bugs, Clean things * remove ToArray() * resultCode > status * Remove old services * Addresses gdkchan's comments and more cleanup * Addresses Gdkchan's feedback 2 * Reorganize services, make sure service are loaded before guest Co-Authored-By: gdkchan <5624669+gdkchan@users.noreply.github.com> * Create interfaces for lm and sm Co-authored-by: gdkchan <5624669+gdkchan@users.noreply.github.com>
This commit is contained in:
parent
3ffceab1fb
commit
550747eac6
83 changed files with 1106 additions and 880 deletions
|
@ -3,10 +3,10 @@
|
|||
struct CmifDomainInHeader
|
||||
{
|
||||
public CmifDomainRequestType Type;
|
||||
public byte ObjectsCount;
|
||||
public ushort DataSize;
|
||||
public int ObjectId;
|
||||
public uint Padding;
|
||||
public uint Token;
|
||||
public byte ObjectsCount;
|
||||
public ushort DataSize;
|
||||
public int ObjectId;
|
||||
public uint Padding;
|
||||
public uint Token;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
{
|
||||
enum CmifDomainRequestType : byte
|
||||
{
|
||||
Invalid = 0,
|
||||
Invalid = 0,
|
||||
SendMessage = 1,
|
||||
Close = 2
|
||||
Close = 2
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
{
|
||||
static class CmifMessage
|
||||
{
|
||||
public const uint CmifInHeaderMagic = 0x49434653; // SFCI
|
||||
public const uint CmifInHeaderMagic = 0x49434653; // SFCI
|
||||
public const uint CmifOutHeaderMagic = 0x4f434653; // SFCO
|
||||
|
||||
public static CmifRequest CreateRequest(Span<byte> output, CmifRequestFormat format)
|
||||
|
@ -21,27 +21,31 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
}
|
||||
|
||||
totalSize += Unsafe.SizeOf<CmifInHeader>() + format.DataSize;
|
||||
totalSize = (totalSize + 1) & ~1;
|
||||
totalSize = (totalSize + 1) & ~1;
|
||||
|
||||
int outPointerSizeTableOffset = totalSize;
|
||||
int outPointerSizeTableSize = format.OutAutoBuffersCount + format.OutPointersCount;
|
||||
int outPointerSizeTableSize = format.OutAutoBuffersCount + format.OutPointersCount;
|
||||
|
||||
totalSize += sizeof(ushort) * outPointerSizeTableSize;
|
||||
|
||||
int rawDataSizeInWords = (totalSize + sizeof(uint) - 1) / sizeof(uint);
|
||||
|
||||
CmifRequest request = new CmifRequest();
|
||||
|
||||
request.Hipc = HipcMessage.WriteMessage(output, new HipcMetadata()
|
||||
CmifRequest request = new()
|
||||
{
|
||||
Type = format.Context != 0 ? (int)CommandType.RequestWithContext : (int)CommandType.Request,
|
||||
SendStaticsCount = format.InAutoBuffersCount + format.InPointersCount,
|
||||
SendBuffersCount = format.InAutoBuffersCount + format.InBuffersCount,
|
||||
ReceiveBuffersCount = format.OutAutoBuffersCount + format.OutBuffersCount,
|
||||
ExchangeBuffersCount = format.InOutBuffersCount,
|
||||
DataWordsCount = rawDataSizeInWords,
|
||||
ReceiveStaticsCount = outPointerSizeTableSize + format.OutFixedPointersCount,
|
||||
SendPid = format.SendPid,
|
||||
CopyHandlesCount = format.HandlesCount,
|
||||
MoveHandlesCount = 0
|
||||
});
|
||||
Hipc = HipcMessage.WriteMessage(output, new HipcMetadata()
|
||||
{
|
||||
Type = format.Context != 0 ? (int)CommandType.RequestWithContext : (int)CommandType.Request,
|
||||
SendStaticsCount = format.InAutoBuffersCount + format.InPointersCount,
|
||||
SendBuffersCount = format.InAutoBuffersCount + format.InBuffersCount,
|
||||
ReceiveBuffersCount = format.OutAutoBuffersCount + format.OutBuffersCount,
|
||||
ExchangeBuffersCount = format.InOutBuffersCount,
|
||||
DataWordsCount = rawDataSizeInWords,
|
||||
ReceiveStaticsCount = outPointerSizeTableSize + format.OutFixedPointersCount,
|
||||
SendPid = format.SendPid,
|
||||
CopyHandlesCount = format.HandlesCount,
|
||||
MoveHandlesCount = 0
|
||||
})
|
||||
};
|
||||
|
||||
Span<uint> data = request.Hipc.DataWords;
|
||||
|
||||
|
@ -53,35 +57,36 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
|
||||
domainHeader = new CmifDomainInHeader()
|
||||
{
|
||||
Type = CmifDomainRequestType.SendMessage,
|
||||
Type = CmifDomainRequestType.SendMessage,
|
||||
ObjectsCount = (byte)format.ObjectsCount,
|
||||
DataSize = (ushort)payloadSize,
|
||||
ObjectId = format.ObjectId,
|
||||
Padding = 0,
|
||||
Token = format.Context
|
||||
DataSize = (ushort)payloadSize,
|
||||
ObjectId = format.ObjectId,
|
||||
Padding = 0,
|
||||
Token = format.Context
|
||||
};
|
||||
|
||||
data = data.Slice(Unsafe.SizeOf<CmifDomainInHeader>() / sizeof(uint));
|
||||
data = data[(Unsafe.SizeOf<CmifDomainInHeader>() / sizeof(uint))..];
|
||||
|
||||
request.Objects = data.Slice((payloadSize + sizeof(uint) - 1) / sizeof(uint));
|
||||
request.Objects = data[((payloadSize + sizeof(uint) - 1) / sizeof(uint))..];
|
||||
}
|
||||
|
||||
ref CmifInHeader header = ref MemoryMarshal.Cast<uint, CmifInHeader>(data)[0];
|
||||
|
||||
header = new CmifInHeader()
|
||||
{
|
||||
Magic = CmifInHeaderMagic,
|
||||
Version = format.Context != 0 ? 1u : 0u,
|
||||
Magic = CmifInHeaderMagic,
|
||||
Version = format.Context != 0 ? 1u : 0u,
|
||||
CommandId = format.RequestId,
|
||||
Token = format.ObjectId != 0 ? 0u : format.Context
|
||||
Token = format.ObjectId != 0 ? 0u : format.Context
|
||||
};
|
||||
|
||||
request.Data = MemoryMarshal.Cast<uint, byte>(data).Slice(Unsafe.SizeOf<CmifInHeader>());
|
||||
request.Data = MemoryMarshal.Cast<uint, byte>(data)[Unsafe.SizeOf<CmifInHeader>()..];
|
||||
|
||||
int paddingSizeBefore = (rawDataSizeInWords - request.Hipc.DataWords.Length) * sizeof(uint);
|
||||
|
||||
Span<byte> outPointerTable = MemoryMarshal.Cast<uint, byte>(request.Hipc.DataWords).Slice(outPointerSizeTableOffset - paddingSizeBefore);
|
||||
request.OutPointerSizes = MemoryMarshal.Cast<byte, ushort>(outPointerTable);
|
||||
Span<byte> outPointerTable = MemoryMarshal.Cast<uint, byte>(request.Hipc.DataWords)[(outPointerSizeTableOffset - paddingSizeBefore)..];
|
||||
|
||||
request.OutPointerSizes = MemoryMarshal.Cast<byte, ushort>(outPointerTable);
|
||||
request.ServerPointerSize = format.ServerPointerSize;
|
||||
|
||||
return request;
|
||||
|
@ -89,15 +94,15 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
|
||||
public static Result ParseResponse(out CmifResponse response, Span<byte> input, bool isDomain, int size)
|
||||
{
|
||||
HipcMessage responseMessage = new HipcMessage(input);
|
||||
HipcMessage responseMessage = new(input);
|
||||
|
||||
Span<byte> data = MemoryMarshal.Cast<uint, byte>(responseMessage.Data.DataWords);
|
||||
Span<byte> data = MemoryMarshal.Cast<uint, byte>(responseMessage.Data.DataWords);
|
||||
Span<uint> objects = Span<uint>.Empty;
|
||||
|
||||
if (isDomain)
|
||||
{
|
||||
data = data.Slice(Unsafe.SizeOf<CmifDomainOutHeader>());
|
||||
objects = MemoryMarshal.Cast<byte, uint>(data.Slice(Unsafe.SizeOf<CmifOutHeader>() + size));
|
||||
data = data[Unsafe.SizeOf<CmifDomainOutHeader>()..];
|
||||
objects = MemoryMarshal.Cast<byte, uint>(data[(Unsafe.SizeOf<CmifOutHeader>() + size)..]);
|
||||
}
|
||||
|
||||
CmifOutHeader header = MemoryMarshal.Cast<byte, CmifOutHeader>(data)[0];
|
||||
|
@ -105,19 +110,21 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
if (header.Magic != CmifOutHeaderMagic)
|
||||
{
|
||||
response = default;
|
||||
|
||||
return SfResult.InvalidOutHeader;
|
||||
}
|
||||
|
||||
if (header.Result.IsFailure)
|
||||
{
|
||||
response = default;
|
||||
|
||||
return header.Result;
|
||||
}
|
||||
|
||||
response = new CmifResponse()
|
||||
{
|
||||
Data = data.Slice(Unsafe.SizeOf<CmifOutHeader>()),
|
||||
Objects = objects,
|
||||
Data = data[Unsafe.SizeOf<CmifOutHeader>()..],
|
||||
Objects = objects,
|
||||
CopyHandles = responseMessage.Data.CopyHandles,
|
||||
MoveHandles = responseMessage.Data.MoveHandles
|
||||
};
|
||||
|
@ -125,4 +132,4 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,10 +5,10 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
struct CmifOutHeader
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public uint Magic;
|
||||
public uint Version;
|
||||
public uint Magic;
|
||||
public uint Version;
|
||||
public Result Result;
|
||||
public uint Token;
|
||||
public uint Token;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
ref struct CmifRequest
|
||||
{
|
||||
public HipcMessageData Hipc;
|
||||
public Span<byte> Data;
|
||||
public Span<ushort> OutPointerSizes;
|
||||
public Span<uint> Objects;
|
||||
public int ServerPointerSize;
|
||||
public Span<byte> Data;
|
||||
public Span<ushort> OutPointerSizes;
|
||||
public Span<uint> Objects;
|
||||
public int ServerPointerSize;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,21 +3,21 @@
|
|||
struct CmifRequestFormat
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public int ObjectId;
|
||||
public int ObjectId;
|
||||
public uint RequestId;
|
||||
public uint Context;
|
||||
public int DataSize;
|
||||
public int ServerPointerSize;
|
||||
public int InAutoBuffersCount;
|
||||
public int OutAutoBuffersCount;
|
||||
public int InBuffersCount;
|
||||
public int OutBuffersCount;
|
||||
public int InOutBuffersCount;
|
||||
public int InPointersCount;
|
||||
public int OutPointersCount;
|
||||
public int OutFixedPointersCount;
|
||||
public int ObjectsCount;
|
||||
public int HandlesCount;
|
||||
public int DataSize;
|
||||
public int ServerPointerSize;
|
||||
public int InAutoBuffersCount;
|
||||
public int OutAutoBuffersCount;
|
||||
public int InBuffersCount;
|
||||
public int OutBuffersCount;
|
||||
public int InOutBuffersCount;
|
||||
public int InPointersCount;
|
||||
public int OutPointersCount;
|
||||
public int OutFixedPointersCount;
|
||||
public int ObjectsCount;
|
||||
public int HandlesCount;
|
||||
public bool SendPid;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
{
|
||||
public ReadOnlySpan<byte> Data;
|
||||
public ReadOnlySpan<uint> Objects;
|
||||
public ReadOnlySpan<int> CopyHandles;
|
||||
public ReadOnlySpan<int> MoveHandles;
|
||||
public ReadOnlySpan<int> CopyHandles;
|
||||
public ReadOnlySpan<int> MoveHandles;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
{
|
||||
enum CommandType
|
||||
{
|
||||
Invalid = 0,
|
||||
LegacyRequest = 1,
|
||||
Close = 2,
|
||||
LegacyControl = 3,
|
||||
Request = 4,
|
||||
Control = 5,
|
||||
Invalid = 0,
|
||||
LegacyRequest = 1,
|
||||
Close = 2,
|
||||
LegacyControl = 3,
|
||||
Request = 4,
|
||||
Control = 5,
|
||||
RequestWithContext = 6,
|
||||
ControlWithContext = 7
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
|
||||
var inHeader = MemoryMarshal.Cast<byte, CmifDomainInHeader>(inRawData)[0];
|
||||
|
||||
ReadOnlySpan<byte> inDomainRawData = inRawData.Slice(Unsafe.SizeOf<CmifDomainInHeader>());
|
||||
ReadOnlySpan<byte> inDomainRawData = inRawData[Unsafe.SizeOf<CmifDomainInHeader>()..];
|
||||
|
||||
int targetObjectId = inHeader.ObjectId;
|
||||
|
||||
|
@ -39,7 +39,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
return SfResult.InvalidHeaderSize;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> inMessageRawData = inDomainRawData.Slice(0, inHeader.DataSize);
|
||||
ReadOnlySpan<byte> inMessageRawData = inDomainRawData[..inHeader.DataSize];
|
||||
|
||||
if (inHeader.ObjectsCount > DomainServiceObjectProcessor.MaximumObjects)
|
||||
{
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
return SfResult.InvalidInObjectsCount;
|
||||
}
|
||||
|
||||
Result result = _domain.ReserveIds(new Span<int>(_reservedObjectIds).Slice(0, OutObjectsCount));
|
||||
Result result = _domain.ReserveIds(new Span<int>(_reservedObjectIds)[..OutObjectsCount]);
|
||||
|
||||
if (result.IsFailure)
|
||||
{
|
||||
|
@ -92,7 +92,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
|
||||
DebugUtil.Assert(outHeaderSize + implOutDataTotalSize + OutObjectsCount * sizeof(int) <= outRawData.Length);
|
||||
|
||||
outRawData = outRawData.Slice(outHeaderSize);
|
||||
outRawData = outRawData[outHeaderSize..];
|
||||
_outObjectIdsOffset = (response.DataWords.Length * sizeof(uint) - outRawData.Length) + implOutDataTotalSize;
|
||||
|
||||
return response;
|
||||
|
@ -107,9 +107,9 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
|
||||
DebugUtil.Assert(outHeaderSize + implOutDataTotalSize <= outRawData.Length);
|
||||
|
||||
outRawData = outRawData.Slice(outHeaderSize);
|
||||
outRawData = outRawData[outHeaderSize..];
|
||||
|
||||
_domain.UnreserveIds(new Span<int>(_reservedObjectIds).Slice(0, OutObjectsCount));
|
||||
_domain.UnreserveIds(new Span<int>(_reservedObjectIds)[..OutObjectsCount]);
|
||||
}
|
||||
|
||||
public override void SetOutObjects(scoped ref ServiceDispatchContext context, HipcMessageData response, Span<ServiceObjectHolder> outObjects)
|
||||
|
@ -129,7 +129,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
_domain.RegisterObject(objectIds[i], outObjects[i]);
|
||||
}
|
||||
|
||||
Span<int> outObjectIds = MemoryMarshal.Cast<byte, int>(MemoryMarshal.Cast<uint, byte>(response.DataWords).Slice(_outObjectIdsOffset));
|
||||
Span<int> outObjectIds = MemoryMarshal.Cast<byte, int>(MemoryMarshal.Cast<uint, byte>(response.DataWords)[_outObjectIdsOffset..]);
|
||||
|
||||
for (int i = 0; i < outObjectsCount; i++)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
{
|
||||
struct PointerAndSize
|
||||
{
|
||||
public static PointerAndSize Empty => new PointerAndSize(0UL, 0UL);
|
||||
public static PointerAndSize Empty => new(0UL, 0UL);
|
||||
|
||||
public ulong Address { get; }
|
||||
public ulong Size { get; }
|
||||
|
@ -11,7 +11,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
public PointerAndSize(ulong address, ulong size)
|
||||
{
|
||||
Address = address;
|
||||
Size = size;
|
||||
Size = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,28 +2,29 @@
|
|||
{
|
||||
struct ServerMessageRuntimeMetadata
|
||||
{
|
||||
public ushort InDataSize { get; }
|
||||
public ushort OutDataSize { get; }
|
||||
public byte InHeadersSize { get; }
|
||||
public byte OutHeadersSize { get; }
|
||||
public byte InObjectsCount { get; }
|
||||
public byte OutObjectsCount { get; }
|
||||
public ushort InDataSize { get; }
|
||||
public ushort OutDataSize { get; }
|
||||
public byte InHeadersSize { get; }
|
||||
public byte OutHeadersSize { get; }
|
||||
public byte InObjectsCount { get; }
|
||||
public byte OutObjectsCount { get; }
|
||||
|
||||
public int UnfixedOutPointerSizeOffset => InDataSize + InHeadersSize + 0x10;
|
||||
|
||||
public ServerMessageRuntimeMetadata(
|
||||
ushort inDataSize,
|
||||
ushort outDataSize,
|
||||
byte inHeadersSize,
|
||||
byte outHeadersSize,
|
||||
byte inObjectsCount,
|
||||
byte outObjectsCount)
|
||||
byte inHeadersSize,
|
||||
byte outHeadersSize,
|
||||
byte inObjectsCount,
|
||||
byte outObjectsCount)
|
||||
{
|
||||
InDataSize = inDataSize;
|
||||
OutDataSize = outDataSize;
|
||||
InHeadersSize = inHeadersSize;
|
||||
OutHeadersSize = outHeadersSize;
|
||||
InObjectsCount = inObjectsCount;
|
||||
InDataSize = inDataSize;
|
||||
OutDataSize = outDataSize;
|
||||
InHeadersSize = inHeadersSize;
|
||||
OutHeadersSize = outHeadersSize;
|
||||
InObjectsCount = inObjectsCount;
|
||||
OutObjectsCount = outObjectsCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,14 +5,14 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
{
|
||||
ref struct ServiceDispatchContext
|
||||
{
|
||||
public IServiceObject ServiceObject;
|
||||
public ServerSessionManager Manager;
|
||||
public ServerSession Session;
|
||||
public IServiceObject ServiceObject;
|
||||
public ServerSessionManager Manager;
|
||||
public ServerSession Session;
|
||||
public ServerMessageProcessor Processor;
|
||||
public HandlesToClose HandlesToClose;
|
||||
public PointerAndSize PointerBuffer;
|
||||
public ReadOnlySpan<byte> InMessageBuffer;
|
||||
public Span<byte> OutMessageBuffer;
|
||||
public HipcMessage Request;
|
||||
public HandlesToClose HandlesToClose;
|
||||
public PointerAndSize PointerBuffer;
|
||||
public ReadOnlySpan<byte> InMessageBuffer;
|
||||
public Span<byte> OutMessageBuffer;
|
||||
public HipcMessage Request;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
public ServiceDispatchTable(string objectName, IReadOnlyDictionary<int, CommandHandler> entries)
|
||||
{
|
||||
_objectName = objectName;
|
||||
_entries = entries;
|
||||
_entries = entries;
|
||||
}
|
||||
|
||||
public override Result ProcessMessage(ref ServiceDispatchContext context, ReadOnlySpan<byte> inRawData)
|
||||
|
@ -30,4 +30,4 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
return new ServiceDispatchTable(instance.GetType().Name, instance.GetCommandHandlers());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,17 +39,21 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
|
||||
if (!entries.TryGetValue((int)commandId, out var commandHandler))
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.KernelIpc, $"{objectName} command ID 0x{commandId:X} is not implemented");
|
||||
|
||||
if (HorizonStatic.Options.IgnoreMissingServices)
|
||||
{
|
||||
// If ignore missing services is enabled, just pretend that everything is fine.
|
||||
var response = PrepareForStubReply(ref context, out Span<byte> outRawData);
|
||||
PrepareForStubReply(ref context, out Span<byte> outRawData);
|
||||
CommandHandler.GetCmifOutHeaderPointer(ref outHeader, ref outRawData);
|
||||
outHeader[0] = new CmifOutHeader() { Magic = CmifMessage.CmifOutHeaderMagic, Result = Result.Success };
|
||||
|
||||
Logger.Warning?.Print(LogClass.Service, $"Missing service {objectName} (command ID: {commandId}) ignored");
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
else if (HorizonStatic.Options.ThrowOnInvalidCommandIds)
|
||||
{
|
||||
throw new NotImplementedException($"{objectName} command ID: {commandId} is not implemented");
|
||||
}
|
||||
|
||||
return SfResult.UnknownCommandId;
|
||||
}
|
||||
|
@ -72,6 +76,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
if (outHeader.IsEmpty)
|
||||
{
|
||||
commandResult.AbortOnSuccess();
|
||||
|
||||
return commandResult;
|
||||
}
|
||||
|
||||
|
@ -80,11 +85,10 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
private static HipcMessageData PrepareForStubReply(scoped ref ServiceDispatchContext context, out Span<byte> outRawData)
|
||||
private static void PrepareForStubReply(scoped ref ServiceDispatchContext context, out Span<byte> outRawData)
|
||||
{
|
||||
var response = HipcMessage.WriteResponse(context.OutMessageBuffer, 0, 0x20 / sizeof(uint), 0, 0);
|
||||
outRawData = MemoryMarshal.Cast<uint, byte>(response.DataWords);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,37 +20,37 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
|
||||
struct CommandArg
|
||||
{
|
||||
public CommandArgType Type { get; }
|
||||
public HipcBufferFlags BufferFlags { get; }
|
||||
public ushort BufferFixedSize { get; }
|
||||
public int ArgSize { get; }
|
||||
public int ArgAlignment { get; }
|
||||
public CommandArgType Type { get; }
|
||||
public HipcBufferFlags BufferFlags { get; }
|
||||
public ushort BufferFixedSize { get; }
|
||||
public int ArgSize { get; }
|
||||
public int ArgAlignment { get; }
|
||||
|
||||
public CommandArg(CommandArgType type)
|
||||
{
|
||||
Type = type;
|
||||
BufferFlags = default;
|
||||
Type = type;
|
||||
BufferFlags = default;
|
||||
BufferFixedSize = 0;
|
||||
ArgSize = 0;
|
||||
ArgAlignment = 0;
|
||||
ArgSize = 0;
|
||||
ArgAlignment = 0;
|
||||
}
|
||||
|
||||
public CommandArg(CommandArgType type, int argSize, int argAlignment)
|
||||
{
|
||||
Type = type;
|
||||
BufferFlags = default;
|
||||
Type = type;
|
||||
BufferFlags = default;
|
||||
BufferFixedSize = 0;
|
||||
ArgSize = argSize;
|
||||
ArgAlignment = argAlignment;
|
||||
ArgSize = argSize;
|
||||
ArgAlignment = argAlignment;
|
||||
}
|
||||
|
||||
public CommandArg(HipcBufferFlags flags, ushort fixedSize = 0)
|
||||
{
|
||||
Type = CommandArgType.Buffer;
|
||||
BufferFlags = flags;
|
||||
Type = CommandArgType.Buffer;
|
||||
BufferFlags = flags;
|
||||
BufferFixedSize = fixedSize;
|
||||
ArgSize = 0;
|
||||
ArgAlignment = 0;
|
||||
ArgSize = 0;
|
||||
ArgAlignment = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,8 +6,8 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
class BufferAttribute : Attribute
|
||||
{
|
||||
public HipcBufferFlags Flags { get; }
|
||||
public ushort FixedSize { get; }
|
||||
public HipcBufferFlags Flags { get; }
|
||||
public ushort FixedSize { get; }
|
||||
|
||||
public BufferAttribute(HipcBufferFlags flags)
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
|
||||
public BufferAttribute(HipcBufferFlags flags, ushort fixedSize)
|
||||
{
|
||||
Flags = flags | HipcBufferFlags.FixedSize;
|
||||
Flags = flags | HipcBufferFlags.FixedSize;
|
||||
FixedSize = fixedSize;
|
||||
}
|
||||
}
|
||||
|
@ -35,4 +35,4 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
class MoveHandleAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,20 +9,20 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
class CommandHandler
|
||||
{
|
||||
public delegate Result MethodInvoke(
|
||||
ref ServiceDispatchContext context,
|
||||
HipcCommandProcessor processor,
|
||||
ref ServiceDispatchContext context,
|
||||
HipcCommandProcessor processor,
|
||||
ServerMessageRuntimeMetadata runtimeMetadata,
|
||||
ReadOnlySpan<byte> inRawData,
|
||||
ref Span<CmifOutHeader> outHeader);
|
||||
ReadOnlySpan<byte> inRawData,
|
||||
ref Span<CmifOutHeader> outHeader);
|
||||
|
||||
private readonly MethodInvoke _invoke;
|
||||
private readonly MethodInvoke _invoke;
|
||||
private readonly HipcCommandProcessor _processor;
|
||||
|
||||
public string MethodName => _invoke.Method.Name;
|
||||
|
||||
public CommandHandler(MethodInvoke invoke, params CommandArg[] args)
|
||||
{
|
||||
_invoke = invoke;
|
||||
_invoke = invoke;
|
||||
_processor = new HipcCommandProcessor(args);
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,8 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
context.Processor.SetImplementationProcessor(_processor);
|
||||
}
|
||||
|
||||
var runtimeMetadata = context.Processor.GetRuntimeMetadata();
|
||||
Result result = context.Processor.PrepareForProcess(ref context, runtimeMetadata);
|
||||
var runtimeMetadata = context.Processor.GetRuntimeMetadata();
|
||||
Result result = context.Processor.PrepareForProcess(ref context, runtimeMetadata);
|
||||
|
||||
if (result.IsFailure)
|
||||
{
|
||||
|
@ -50,8 +50,8 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
|
||||
public static void GetCmifOutHeaderPointer(ref Span<CmifOutHeader> outHeader, ref Span<byte> outRawData)
|
||||
{
|
||||
outHeader = MemoryMarshal.Cast<byte, CmifOutHeader>(outRawData).Slice(0, 1);
|
||||
outRawData = outRawData.Slice(Unsafe.SizeOf<CmifOutHeader>());
|
||||
outHeader = MemoryMarshal.Cast<byte, CmifOutHeader>(outRawData)[..1];
|
||||
outRawData = outRawData[Unsafe.SizeOf<CmifOutHeader>()..];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
public static ref T GetRef<T>(PointerAndSize bufferRange) where T : unmanaged
|
||||
{
|
||||
var writableRegion = GetWritableRegion(bufferRange);
|
||||
|
||||
return ref MemoryMarshal.Cast<byte, T>(writableRegion.Memory.Span)[0];
|
||||
}
|
||||
|
||||
|
@ -65,4 +66,4 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
response.MoveHandles[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,12 +5,12 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
[Flags]
|
||||
enum HipcBufferFlags : byte
|
||||
{
|
||||
In = 1 << 0,
|
||||
Out = 1 << 1,
|
||||
MapAlias = 1 << 2,
|
||||
Pointer = 1 << 3,
|
||||
FixedSize = 1 << 4,
|
||||
AutoSelect = 1 << 5,
|
||||
In = 1 << 0,
|
||||
Out = 1 << 1,
|
||||
MapAlias = 1 << 2,
|
||||
Pointer = 1 << 3,
|
||||
FixedSize = 1 << 4,
|
||||
AutoSelect = 1 << 5,
|
||||
MapTransferAllowsNonSecure = 1 << 6,
|
||||
MapTransferAllowsNonDevice = 1 << 7
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
{
|
||||
enum HipcBufferMode
|
||||
{
|
||||
Normal = 0,
|
||||
Normal = 0,
|
||||
NonSecure = 1,
|
||||
Invalid = 2,
|
||||
Invalid = 2,
|
||||
NonDevice = 3
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
{
|
||||
clientHandle = 0;
|
||||
|
||||
if (!(_session.ServiceObjectHolder.ServiceObject is DomainServiceObject domain))
|
||||
if (_session.ServiceObjectHolder.ServiceObject is not DomainServiceObject domain)
|
||||
{
|
||||
return HipcResult.TargetNotDomain;
|
||||
}
|
||||
|
@ -112,4 +112,4 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,9 +10,9 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
{
|
||||
public const int AutoReceiveStatic = byte.MaxValue;
|
||||
|
||||
public HipcMetadata Meta;
|
||||
public HipcMetadata Meta;
|
||||
public HipcMessageData Data;
|
||||
public ulong Pid;
|
||||
public ulong Pid;
|
||||
|
||||
public HipcMessage(Span<byte> data)
|
||||
{
|
||||
|
@ -20,10 +20,10 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
|
||||
Header header = MemoryMarshal.Cast<byte, Header>(data)[0];
|
||||
|
||||
data = data.Slice(Unsafe.SizeOf<Header>());
|
||||
data = data[Unsafe.SizeOf<Header>()..];
|
||||
|
||||
int receiveStaticsCount = 0;
|
||||
ulong pid = 0;
|
||||
int receiveStaticsCount = 0;
|
||||
ulong pid = 0;
|
||||
|
||||
if (header.ReceiveStaticMode != 0)
|
||||
{
|
||||
|
@ -42,46 +42,44 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
if (header.HasSpecialHeader)
|
||||
{
|
||||
specialHeader = MemoryMarshal.Cast<byte, SpecialHeader>(data)[0];
|
||||
|
||||
data = data.Slice(Unsafe.SizeOf<SpecialHeader>());
|
||||
data = data[Unsafe.SizeOf<SpecialHeader>()..];
|
||||
|
||||
if (specialHeader.SendPid)
|
||||
{
|
||||
pid = MemoryMarshal.Cast<byte, ulong>(data)[0];
|
||||
|
||||
data = data.Slice(sizeof(ulong));
|
||||
pid = MemoryMarshal.Cast<byte, ulong>(data)[0];
|
||||
data = data[sizeof(ulong)..];
|
||||
}
|
||||
}
|
||||
|
||||
Meta = new HipcMetadata()
|
||||
{
|
||||
Type = (int)header.Type,
|
||||
SendStaticsCount = header.SendStaticsCount,
|
||||
SendBuffersCount = header.SendBuffersCount,
|
||||
ReceiveBuffersCount = header.ReceiveBuffersCount,
|
||||
Type = (int)header.Type,
|
||||
SendStaticsCount = header.SendStaticsCount,
|
||||
SendBuffersCount = header.SendBuffersCount,
|
||||
ReceiveBuffersCount = header.ReceiveBuffersCount,
|
||||
ExchangeBuffersCount = header.ExchangeBuffersCount,
|
||||
DataWordsCount = header.DataWordsCount,
|
||||
ReceiveStaticsCount = receiveStaticsCount,
|
||||
SendPid = specialHeader.SendPid,
|
||||
CopyHandlesCount = specialHeader.CopyHandlesCount,
|
||||
MoveHandlesCount = specialHeader.MoveHandlesCount
|
||||
DataWordsCount = header.DataWordsCount,
|
||||
ReceiveStaticsCount = receiveStaticsCount,
|
||||
SendPid = specialHeader.SendPid,
|
||||
CopyHandlesCount = specialHeader.CopyHandlesCount,
|
||||
MoveHandlesCount = specialHeader.MoveHandlesCount
|
||||
};
|
||||
|
||||
Data = CreateMessageData(Meta, data, initialLength);
|
||||
Pid = pid;
|
||||
Pid = pid;
|
||||
}
|
||||
|
||||
public static HipcMessageData WriteResponse(
|
||||
Span<byte> destination,
|
||||
int sendStaticCount,
|
||||
int dataWordsCount,
|
||||
int copyHandlesCount,
|
||||
int moveHandlesCount)
|
||||
int sendStaticCount,
|
||||
int dataWordsCount,
|
||||
int copyHandlesCount,
|
||||
int moveHandlesCount)
|
||||
{
|
||||
return WriteMessage(destination, new HipcMetadata()
|
||||
{
|
||||
SendStaticsCount = sendStaticCount,
|
||||
DataWordsCount = dataWordsCount,
|
||||
DataWordsCount = dataWordsCount,
|
||||
CopyHandlesCount = copyHandlesCount,
|
||||
MoveHandlesCount = moveHandlesCount
|
||||
});
|
||||
|
@ -89,38 +87,37 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
|
||||
public static HipcMessageData WriteMessage(Span<byte> destination, HipcMetadata meta)
|
||||
{
|
||||
int initialLength = destination.Length;
|
||||
|
||||
int initialLength = destination.Length;
|
||||
bool hasSpecialHeader = meta.SendPid || meta.CopyHandlesCount != 0 || meta.MoveHandlesCount != 0;
|
||||
|
||||
MemoryMarshal.Cast<byte, Header>(destination)[0] = new Header()
|
||||
{
|
||||
Type = (CommandType)meta.Type,
|
||||
SendStaticsCount = meta.SendStaticsCount,
|
||||
SendBuffersCount = meta.SendBuffersCount,
|
||||
ReceiveBuffersCount = meta.ReceiveBuffersCount,
|
||||
Type = (CommandType)meta.Type,
|
||||
SendStaticsCount = meta.SendStaticsCount,
|
||||
SendBuffersCount = meta.SendBuffersCount,
|
||||
ReceiveBuffersCount = meta.ReceiveBuffersCount,
|
||||
ExchangeBuffersCount = meta.ExchangeBuffersCount,
|
||||
DataWordsCount = meta.DataWordsCount,
|
||||
ReceiveStaticMode = meta.ReceiveStaticsCount != 0 ? (meta.ReceiveStaticsCount != AutoReceiveStatic ? meta.ReceiveStaticsCount + 2 : 2) : 0,
|
||||
HasSpecialHeader = hasSpecialHeader
|
||||
DataWordsCount = meta.DataWordsCount,
|
||||
ReceiveStaticMode = meta.ReceiveStaticsCount != 0 ? (meta.ReceiveStaticsCount != AutoReceiveStatic ? meta.ReceiveStaticsCount + 2 : 2) : 0,
|
||||
HasSpecialHeader = hasSpecialHeader
|
||||
};
|
||||
|
||||
destination = destination.Slice(Unsafe.SizeOf<Header>());
|
||||
destination = destination[Unsafe.SizeOf<Header>()..];
|
||||
|
||||
if (hasSpecialHeader)
|
||||
{
|
||||
MemoryMarshal.Cast<byte, SpecialHeader>(destination)[0] = new SpecialHeader()
|
||||
{
|
||||
SendPid = meta.SendPid,
|
||||
SendPid = meta.SendPid,
|
||||
CopyHandlesCount = meta.CopyHandlesCount,
|
||||
MoveHandlesCount = meta.MoveHandlesCount
|
||||
};
|
||||
|
||||
destination = destination.Slice(Unsafe.SizeOf<SpecialHeader>());
|
||||
destination = destination[Unsafe.SizeOf<SpecialHeader>()..];
|
||||
|
||||
if (meta.SendPid)
|
||||
{
|
||||
destination = destination.Slice(sizeof(ulong));
|
||||
destination = destination[sizeof(ulong)..];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,68 +130,67 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
|
||||
if (meta.CopyHandlesCount != 0)
|
||||
{
|
||||
copyHandles = MemoryMarshal.Cast<byte, int>(data).Slice(0, meta.CopyHandlesCount);
|
||||
copyHandles = MemoryMarshal.Cast<byte, int>(data)[..meta.CopyHandlesCount];
|
||||
|
||||
data = data.Slice(meta.CopyHandlesCount * sizeof(int));
|
||||
data = data[(meta.CopyHandlesCount * sizeof(int))..];
|
||||
}
|
||||
|
||||
Span<int> moveHandles = Span<int>.Empty;
|
||||
|
||||
if (meta.MoveHandlesCount != 0)
|
||||
{
|
||||
moveHandles = MemoryMarshal.Cast<byte, int>(data).Slice(0, meta.MoveHandlesCount);
|
||||
moveHandles = MemoryMarshal.Cast<byte, int>(data)[..meta.MoveHandlesCount];
|
||||
|
||||
data = data.Slice(meta.MoveHandlesCount * sizeof(int));
|
||||
data = data[(meta.MoveHandlesCount * sizeof(int))..];
|
||||
}
|
||||
|
||||
Span<HipcStaticDescriptor> sendStatics = Span<HipcStaticDescriptor>.Empty;
|
||||
|
||||
if (meta.SendStaticsCount != 0)
|
||||
{
|
||||
sendStatics = MemoryMarshal.Cast<byte, HipcStaticDescriptor>(data).Slice(0, meta.SendStaticsCount);
|
||||
sendStatics = MemoryMarshal.Cast<byte, HipcStaticDescriptor>(data)[..meta.SendStaticsCount];
|
||||
|
||||
data = data.Slice(meta.SendStaticsCount * Unsafe.SizeOf<HipcStaticDescriptor>());
|
||||
data = data[(meta.SendStaticsCount * Unsafe.SizeOf<HipcStaticDescriptor>())..];
|
||||
}
|
||||
|
||||
Span<HipcBufferDescriptor> sendBuffers = Span<HipcBufferDescriptor>.Empty;
|
||||
|
||||
if (meta.SendBuffersCount != 0)
|
||||
{
|
||||
sendBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data).Slice(0, meta.SendBuffersCount);
|
||||
sendBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data)[..meta.SendBuffersCount];
|
||||
|
||||
data = data.Slice(meta.SendBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>());
|
||||
data = data[(meta.SendBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>())..];
|
||||
}
|
||||
|
||||
Span<HipcBufferDescriptor> receiveBuffers = Span<HipcBufferDescriptor>.Empty;
|
||||
|
||||
if (meta.ReceiveBuffersCount != 0)
|
||||
{
|
||||
receiveBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data).Slice(0, meta.ReceiveBuffersCount);
|
||||
receiveBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data)[..meta.ReceiveBuffersCount];
|
||||
|
||||
data = data.Slice(meta.ReceiveBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>());
|
||||
data = data[(meta.ReceiveBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>())..];
|
||||
}
|
||||
|
||||
Span<HipcBufferDescriptor> exchangeBuffers = Span<HipcBufferDescriptor>.Empty;
|
||||
|
||||
if (meta.ExchangeBuffersCount != 0)
|
||||
{
|
||||
exchangeBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data).Slice(0, meta.ExchangeBuffersCount);
|
||||
exchangeBuffers = MemoryMarshal.Cast<byte, HipcBufferDescriptor>(data)[..meta.ExchangeBuffersCount];
|
||||
|
||||
data = data.Slice(meta.ExchangeBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>());
|
||||
data = data[(meta.ExchangeBuffersCount * Unsafe.SizeOf<HipcBufferDescriptor>())..];
|
||||
}
|
||||
|
||||
Span<uint> dataWords = Span<uint>.Empty;
|
||||
|
||||
if (meta.DataWordsCount != 0)
|
||||
{
|
||||
int dataOffset = initialLength - data.Length;
|
||||
int dataOffset = initialLength - data.Length;
|
||||
int dataOffsetAligned = BitUtils.AlignUp(dataOffset, 0x10);
|
||||
int padding = (dataOffsetAligned - dataOffset) / sizeof(uint);
|
||||
|
||||
int padding = (dataOffsetAligned - dataOffset) / sizeof(uint);
|
||||
dataWords = MemoryMarshal.Cast<byte, uint>(data)[padding..meta.DataWordsCount];
|
||||
|
||||
dataWords = MemoryMarshal.Cast<byte, uint>(data).Slice(padding, meta.DataWordsCount - padding);
|
||||
|
||||
data = data.Slice(meta.DataWordsCount * sizeof(uint));
|
||||
data = data[(meta.DataWordsCount * sizeof(uint))..];
|
||||
}
|
||||
|
||||
Span<HipcReceiveListEntry> receiveList = Span<HipcReceiveListEntry>.Empty;
|
||||
|
@ -203,19 +199,19 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
{
|
||||
int receiveListSize = meta.ReceiveStaticsCount == AutoReceiveStatic ? 1 : meta.ReceiveStaticsCount;
|
||||
|
||||
receiveList = MemoryMarshal.Cast<byte, HipcReceiveListEntry>(data).Slice(0, receiveListSize);
|
||||
receiveList = MemoryMarshal.Cast<byte, HipcReceiveListEntry>(data)[..receiveListSize];
|
||||
}
|
||||
|
||||
return new HipcMessageData()
|
||||
{
|
||||
SendStatics = sendStatics,
|
||||
SendBuffers = sendBuffers,
|
||||
ReceiveBuffers = receiveBuffers,
|
||||
SendStatics = sendStatics,
|
||||
SendBuffers = sendBuffers,
|
||||
ReceiveBuffers = receiveBuffers,
|
||||
ExchangeBuffers = exchangeBuffers,
|
||||
DataWords = dataWords,
|
||||
ReceiveList = receiveList,
|
||||
CopyHandles = copyHandles,
|
||||
MoveHandles = moveHandles
|
||||
DataWords = dataWords,
|
||||
ReceiveList = receiveList,
|
||||
CopyHandles = copyHandles,
|
||||
MoveHandles = moveHandles
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
public Span<HipcBufferDescriptor> SendBuffers;
|
||||
public Span<HipcBufferDescriptor> ReceiveBuffers;
|
||||
public Span<HipcBufferDescriptor> ExchangeBuffers;
|
||||
public Span<uint> DataWords;
|
||||
public Span<uint> DataWords;
|
||||
public Span<HipcReceiveListEntry> ReceiveList;
|
||||
public Span<int> CopyHandles;
|
||||
public Span<int> MoveHandles;
|
||||
public Span<int> CopyHandles;
|
||||
public Span<int> MoveHandles;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,15 +2,15 @@
|
|||
{
|
||||
struct HipcMetadata
|
||||
{
|
||||
public int Type;
|
||||
public int SendStaticsCount;
|
||||
public int SendBuffersCount;
|
||||
public int ReceiveBuffersCount;
|
||||
public int ExchangeBuffersCount;
|
||||
public int DataWordsCount;
|
||||
public int ReceiveStaticsCount;
|
||||
public int Type;
|
||||
public int SendStaticsCount;
|
||||
public int SendBuffersCount;
|
||||
public int ReceiveBuffersCount;
|
||||
public int ExchangeBuffersCount;
|
||||
public int DataWordsCount;
|
||||
public int ReceiveStaticsCount;
|
||||
public bool SendPid;
|
||||
public int CopyHandlesCount;
|
||||
public int MoveHandlesCount;
|
||||
public int CopyHandlesCount;
|
||||
public int MoveHandlesCount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
public HipcReceiveListEntry(ulong address, ulong size)
|
||||
{
|
||||
_addressLow = (uint)address;
|
||||
_word1 = (ushort)(address >> 32) | (uint)(size << 16);
|
||||
_word1 = (ushort)(address >> 32) | (uint)(size << 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,17 +6,14 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
{
|
||||
public const int ModuleId = 11;
|
||||
|
||||
public static Result OutOfSessionMemory => new Result(ModuleId, 102);
|
||||
public static Result OutOfSessions => new Result(ModuleId, 131);
|
||||
public static Result PointerBufferTooSmall => new Result(ModuleId, 141);
|
||||
public static Result OutOfDomains => new Result(ModuleId, 200);
|
||||
|
||||
public static Result InvalidRequestSize => new Result(ModuleId, 402);
|
||||
public static Result UnknownCommandType => new Result(ModuleId, 403);
|
||||
|
||||
public static Result InvalidCmifRequest => new Result(ModuleId, 420);
|
||||
|
||||
public static Result TargetNotDomain => new Result(ModuleId, 491);
|
||||
public static Result DomainObjectNotFound => new Result(ModuleId, 492);
|
||||
public static Result OutOfSessionMemory => new(ModuleId, 102);
|
||||
public static Result OutOfSessions => new(ModuleId, 131);
|
||||
public static Result PointerBufferTooSmall => new(ModuleId, 141);
|
||||
public static Result OutOfDomains => new(ModuleId, 200);
|
||||
public static Result InvalidRequestSize => new(ModuleId, 402);
|
||||
public static Result UnknownCommandType => new(ModuleId, 403);
|
||||
public static Result InvalidCmifRequest => new(ModuleId, 420);
|
||||
public static Result TargetNotDomain => new(ModuleId, 491);
|
||||
public static Result DomainObjectNotFound => new(ModuleId, 492);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
{
|
||||
private readonly ulong _data;
|
||||
|
||||
public ulong Address => ((((_data >> 2) & 0x70) | ((_data >> 12) & 0xf)) << 32) | (_data >> 32);
|
||||
public ushort Size => (ushort)(_data >> 16);
|
||||
public int ReceiveIndex => (int)(_data & 0xf);
|
||||
public ulong Address => ((((_data >> 2) & 0x70) | ((_data >> 12) & 0xf)) << 32) | (_data >> 32);
|
||||
public ushort Size => (ushort)(_data >> 16);
|
||||
public int ReceiveIndex => (int)(_data & 0xf);
|
||||
|
||||
public HipcStaticDescriptor(ulong address, ushort size, int receiveIndex)
|
||||
{
|
||||
|
@ -19,4 +19,4 @@
|
|||
_data = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,19 +2,19 @@
|
|||
{
|
||||
struct ManagerOptions
|
||||
{
|
||||
public static ManagerOptions Default => new ManagerOptions(0, 0, 0, false);
|
||||
public static ManagerOptions Default => new(0, 0, 0, false);
|
||||
|
||||
public int PointerBufferSize { get; }
|
||||
public int MaxDomains { get; }
|
||||
public int MaxDomainObjects { get; }
|
||||
public int PointerBufferSize { get; }
|
||||
public int MaxDomains { get; }
|
||||
public int MaxDomainObjects { get; }
|
||||
public bool CanDeferInvokeRequest { get; }
|
||||
|
||||
public ManagerOptions(int pointerBufferSize, int maxDomains, int maxDomainObjects, bool canDeferInvokeRequest)
|
||||
{
|
||||
PointerBufferSize = pointerBufferSize;
|
||||
MaxDomains = maxDomains;
|
||||
MaxDomainObjects = maxDomainObjects;
|
||||
PointerBufferSize = pointerBufferSize;
|
||||
MaxDomains = maxDomains;
|
||||
MaxDomainObjects = maxDomainObjects;
|
||||
CanDeferInvokeRequest = canDeferInvokeRequest;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,22 +6,22 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
{
|
||||
class Server : MultiWaitHolderOfHandle
|
||||
{
|
||||
public int PortIndex { get; }
|
||||
public int PortHandle { get; }
|
||||
public ServiceName Name { get; }
|
||||
public bool Managed { get; }
|
||||
public int PortIndex { get; }
|
||||
public int PortHandle { get; }
|
||||
public ServiceName Name { get; }
|
||||
public bool Managed { get; }
|
||||
public ServiceObjectHolder StaticObject { get; }
|
||||
|
||||
public Server(
|
||||
int portIndex,
|
||||
int portHandle,
|
||||
ServiceName name,
|
||||
bool managed,
|
||||
int portIndex,
|
||||
int portHandle,
|
||||
ServiceName name,
|
||||
bool managed,
|
||||
ServiceObjectHolder staticHoder) : base(portHandle)
|
||||
{
|
||||
PortHandle = portHandle;
|
||||
Name = name;
|
||||
Managed = managed;
|
||||
Name = name;
|
||||
Managed = managed;
|
||||
|
||||
if (staticHoder != null)
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
|
||||
protected override Result DispatchManagerRequest(ServerSession session, Span<byte> inMessage, Span<byte> outMessage)
|
||||
{
|
||||
HipcManager hipcManager = new HipcManager(this, session);
|
||||
HipcManager hipcManager = new(this, session);
|
||||
|
||||
return DispatchRequest(new ServiceObjectHolder(hipcManager), session, inMessage, outMessage);
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
return null;
|
||||
}
|
||||
|
||||
ServerSession session = new ServerSession(sessionIndex, sessionHandle, obj);
|
||||
ServerSession session = new(sessionIndex, sessionHandle, obj);
|
||||
|
||||
_sessions.Add(session);
|
||||
|
||||
|
@ -111,7 +111,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
{
|
||||
lock (_resourceLock)
|
||||
{
|
||||
Server server = new Server(portIndex, portHandle, name, managed, staticHoder);
|
||||
Server server = new(portIndex, portHandle, name, managed, staticHoder);
|
||||
|
||||
_servers.Add(server);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
|
||||
private enum UserDataTag
|
||||
{
|
||||
Server = 1,
|
||||
Server = 1,
|
||||
Session = 2
|
||||
}
|
||||
|
||||
|
@ -36,16 +36,17 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
_canDeferInvokeRequest = options.CanDeferInvokeRequest;
|
||||
|
||||
_multiWait = new MultiWait();
|
||||
_waitList = new MultiWait();
|
||||
_waitList = new MultiWait();
|
||||
|
||||
_multiWaitSelectionLock = new object();
|
||||
_waitListLock = new object();
|
||||
_waitListLock = new object();
|
||||
|
||||
_requestStopEvent = new Event(EventClearMode.ManualClear);
|
||||
_notifyEvent = new Event(EventClearMode.ManualClear);
|
||||
_notifyEvent = new Event(EventClearMode.ManualClear);
|
||||
|
||||
_requestStopEventHolder = new MultiWaitHolderOfEvent(_requestStopEvent);
|
||||
_multiWait.LinkMultiWaitHolder(_requestStopEventHolder);
|
||||
|
||||
_notifyEventHolder = new MultiWaitHolderOfEvent(_notifyEvent);
|
||||
_multiWait.LinkMultiWaitHolder(_notifyEventHolder);
|
||||
}
|
||||
|
@ -73,6 +74,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
private void RegisterServerImpl(int portIndex, ServiceObjectHolder staticHolder, int portHandle)
|
||||
{
|
||||
Server server = AllocateServer(portIndex, portHandle, ServiceName.Invalid, managed: false, staticHolder);
|
||||
|
||||
RegisterServerImpl(server);
|
||||
}
|
||||
|
||||
|
@ -86,6 +88,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
}
|
||||
|
||||
Server server = AllocateServer(portIndex, portHandle, name, managed: true, staticHolder);
|
||||
|
||||
RegisterServerImpl(server);
|
||||
|
||||
return Result.Success;
|
||||
|
@ -103,6 +106,11 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
protected Result AcceptImpl(Server server, IServiceObject obj)
|
||||
{
|
||||
return AcceptSession(server.PortHandle, new ServiceObjectHolder(obj));
|
||||
}
|
||||
|
||||
public void ServiceRequests()
|
||||
{
|
||||
while (WaitAndProcessRequestsImpl());
|
||||
|
@ -175,7 +183,8 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
protected override void RegisterSessionToWaitList(ServerSession session)
|
||||
{
|
||||
session.HasReceived = false;
|
||||
session.UserData = UserDataTag.Session;
|
||||
session.UserData = UserDataTag.Session;
|
||||
|
||||
RegisterToWaitList(session);
|
||||
}
|
||||
|
||||
|
@ -198,15 +207,12 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
|
||||
private Result Process(MultiWaitHolder holder)
|
||||
{
|
||||
switch ((UserDataTag)holder.UserData)
|
||||
return (UserDataTag)holder.UserData switch
|
||||
{
|
||||
case UserDataTag.Server:
|
||||
return ProcessForServer(holder);
|
||||
case UserDataTag.Session:
|
||||
return ProcessForSession(holder);
|
||||
default:
|
||||
throw new NotImplementedException(((UserDataTag)holder.UserData).ToString());
|
||||
}
|
||||
UserDataTag.Server => ProcessForServer(holder),
|
||||
UserDataTag.Session => ProcessForSession(holder),
|
||||
_ => throw new NotImplementedException(((UserDataTag)holder.UserData).ToString())
|
||||
};
|
||||
}
|
||||
|
||||
private Result ProcessForServer(MultiWaitHolder holder)
|
||||
|
@ -259,6 +265,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
}
|
||||
|
||||
session.HasReceived = true;
|
||||
|
||||
tlsMessage.Memory.Span.CopyTo(savedMessage.Memory.Span);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -6,18 +6,18 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
class ServerSession : MultiWaitHolderOfHandle
|
||||
{
|
||||
public ServiceObjectHolder ServiceObjectHolder { get; set; }
|
||||
public PointerAndSize PointerBuffer { get; set; }
|
||||
public PointerAndSize SavedMessage { get; set; }
|
||||
public int SessionIndex { get; }
|
||||
public int SessionHandle { get; }
|
||||
public bool IsClosed { get; set; }
|
||||
public bool HasReceived { get; set; }
|
||||
public PointerAndSize PointerBuffer { get; set; }
|
||||
public PointerAndSize SavedMessage { get; set; }
|
||||
public int SessionIndex { get; }
|
||||
public int SessionHandle { get; }
|
||||
public bool IsClosed { get; set; }
|
||||
public bool HasReceived { get; set; }
|
||||
|
||||
public ServerSession(int index, int handle, ServiceObjectHolder obj) : base(handle)
|
||||
{
|
||||
ServiceObjectHolder = obj;
|
||||
SessionIndex = index;
|
||||
SessionHandle = handle;
|
||||
SessionIndex = index;
|
||||
SessionHandle = handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,9 +75,10 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
}
|
||||
|
||||
session.PointerBuffer = GetSessionPointerBuffer(session);
|
||||
session.SavedMessage = GetSessionSavedMessageBuffer(session);
|
||||
session.SavedMessage = GetSessionSavedMessageBuffer(session);
|
||||
|
||||
RegisterSessionToWaitList(session);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
|
@ -109,10 +110,10 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
}
|
||||
|
||||
protected virtual Server AllocateServer(
|
||||
int portIndex,
|
||||
int portHandle,
|
||||
ServiceName name,
|
||||
bool managed,
|
||||
int portIndex,
|
||||
int portHandle,
|
||||
ServiceName name,
|
||||
bool managed,
|
||||
ServiceObjectHolder staticHoder)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
|
@ -141,6 +142,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
protected void CloseSessionImpl(ServerSession session)
|
||||
{
|
||||
int sessionHandle = session.Handle;
|
||||
|
||||
Os.FinalizeMultiWaitHolder(session);
|
||||
DestroySession(session);
|
||||
HorizonStatic.Syscall.CloseHandle(sessionHandle).AbortOnFailure();
|
||||
|
@ -156,6 +158,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
if (session.IsClosed || GetCmifCommandType(message) == CommandType.Close)
|
||||
{
|
||||
CloseSessionImpl(session);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
else
|
||||
|
@ -165,6 +168,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
if (result.IsSuccess)
|
||||
{
|
||||
RegisterSessionToWaitList(session);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
else if (SfResult.RequestContextChanged(result))
|
||||
|
@ -176,6 +180,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
Logger.Warning?.Print(LogClass.KernelIpc, $"Request processing returned error {result}");
|
||||
|
||||
CloseSessionImpl(session);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
@ -197,8 +202,8 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
return DispatchManagerRequest(session, inMessage, outMessage);
|
||||
default:
|
||||
return HipcResult.UnknownCommandType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetInlineContext(CommandType commandType, ReadOnlySpan<byte> inMessage)
|
||||
{
|
||||
|
@ -231,7 +236,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
{
|
||||
HipcMessageData messageData = HipcMessage.WriteMessage(message, new HipcMetadata()
|
||||
{
|
||||
Type = (int)CommandType.Invalid,
|
||||
Type = (int)CommandType.Invalid,
|
||||
ReceiveStaticsCount = HipcMessage.AutoReceiveStatic
|
||||
});
|
||||
|
||||
|
@ -271,9 +276,9 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
|
||||
protected virtual Result DispatchRequest(
|
||||
ServiceObjectHolder objectHolder,
|
||||
ServerSession session,
|
||||
Span<byte> inMessage,
|
||||
Span<byte> outMessage)
|
||||
ServerSession session,
|
||||
Span<byte> inMessage,
|
||||
Span<byte> outMessage)
|
||||
{
|
||||
HipcMessage request;
|
||||
|
||||
|
@ -288,14 +293,14 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
|
||||
var dispatchCtx = new ServiceDispatchContext()
|
||||
{
|
||||
ServiceObject = objectHolder.ServiceObject,
|
||||
Manager = this,
|
||||
Session = session,
|
||||
HandlesToClose = new HandlesToClose(),
|
||||
PointerBuffer = session.PointerBuffer,
|
||||
InMessageBuffer = inMessage,
|
||||
ServiceObject = objectHolder.ServiceObject,
|
||||
Manager = this,
|
||||
Session = session,
|
||||
HandlesToClose = new HandlesToClose(),
|
||||
PointerBuffer = session.PointerBuffer,
|
||||
InMessageBuffer = inMessage,
|
||||
OutMessageBuffer = outMessage,
|
||||
Request = request
|
||||
Request = request
|
||||
};
|
||||
|
||||
ReadOnlySpan<byte> inRawData = MemoryMarshal.Cast<uint, byte>(dispatchCtx.Request.Data.DataWords);
|
||||
|
@ -332,4 +337,4 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
|||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -136,9 +136,9 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
ulong pointerBufferTail = context.PointerBuffer.Address;
|
||||
ulong pointerBufferHead = pointerBufferTail + context.PointerBuffer.Size;
|
||||
|
||||
int sendMapAliasIndex = 0;
|
||||
int recvMapAliasIndex = 0;
|
||||
int sendPointerIndex = 0;
|
||||
int sendMapAliasIndex = 0;
|
||||
int recvMapAliasIndex = 0;
|
||||
int sendPointerIndex = 0;
|
||||
int unfixedRecvPointerIndex = 0;
|
||||
|
||||
for (int i = 0; i < _args.Length; i++)
|
||||
|
@ -188,8 +188,9 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
if (flags.HasFlag(HipcBufferFlags.In))
|
||||
{
|
||||
var descriptor = context.Request.Data.SendStatics[sendPointerIndex++];
|
||||
ulong address = descriptor.Address;
|
||||
ulong size = descriptor.Size;
|
||||
ulong address = descriptor.Address;
|
||||
ulong size = descriptor.Size;
|
||||
|
||||
_bufferRanges[i] = new PointerAndSize(address, size);
|
||||
|
||||
if (size != 0)
|
||||
|
@ -207,13 +208,14 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
}
|
||||
else
|
||||
{
|
||||
var data = MemoryMarshal.Cast<uint, byte>(context.Request.Data.DataWords);
|
||||
var recvPointerSizes = MemoryMarshal.Cast<byte, ushort>(data.Slice(runtimeMetadata.UnfixedOutPointerSizeOffset));
|
||||
var data = MemoryMarshal.Cast<uint, byte>(context.Request.Data.DataWords);
|
||||
var recvPointerSizes = MemoryMarshal.Cast<byte, ushort>(data[runtimeMetadata.UnfixedOutPointerSizeOffset..]);
|
||||
|
||||
size = recvPointerSizes[unfixedRecvPointerIndex++];
|
||||
}
|
||||
|
||||
pointerBufferHead = BitUtils.AlignDown(pointerBufferHead - size, 0x10UL);
|
||||
_bufferRanges[i] = new PointerAndSize(pointerBufferHead, size);
|
||||
_bufferRanges[i] = new PointerAndSize(pointerBufferHead, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,16 +306,17 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
{
|
||||
ref var meta = ref context.Request.Meta;
|
||||
bool requestValid = true;
|
||||
requestValid &= meta.SendPid == _hasInProcessIdHolder;
|
||||
requestValid &= meta.SendStaticsCount == _inPointerBuffersCount;
|
||||
requestValid &= meta.SendBuffersCount == _inMapAliasBuffersCount;
|
||||
requestValid &= meta.ReceiveBuffersCount == _outMapAliasBuffersCount;
|
||||
requestValid &= meta.SendPid == _hasInProcessIdHolder;
|
||||
requestValid &= meta.SendStaticsCount == _inPointerBuffersCount;
|
||||
requestValid &= meta.SendBuffersCount == _inMapAliasBuffersCount;
|
||||
requestValid &= meta.ReceiveBuffersCount == _outMapAliasBuffersCount;
|
||||
requestValid &= meta.ExchangeBuffersCount == 0;
|
||||
requestValid &= meta.CopyHandlesCount == _inCopyHandlesCount;
|
||||
requestValid &= meta.MoveHandlesCount == _inMoveHandlesCount;
|
||||
requestValid &= meta.CopyHandlesCount == _inCopyHandlesCount;
|
||||
requestValid &= meta.MoveHandlesCount == _inMoveHandlesCount;
|
||||
|
||||
int rawSizeInBytes = meta.DataWordsCount * sizeof(uint);
|
||||
int commandRawSize = BitUtils.AlignUp(runtimeMetadata.UnfixedOutPointerSizeOffset + (OutUnfixedSizePointerBuffersCount * sizeof(ushort)), sizeof(uint));
|
||||
|
||||
requestValid &= rawSizeInBytes >= commandRawSize;
|
||||
|
||||
return requestValid ? Result.Success : HipcResult.InvalidCmifRequest;
|
||||
|
@ -340,7 +343,7 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
{
|
||||
if (_args[i].Type == CommandArgType.InObject)
|
||||
{
|
||||
int index = inObjectIndex++;
|
||||
int index = inObjectIndex++;
|
||||
var inObject = inObjects[index];
|
||||
|
||||
objects[index] = inObject?.ServiceObject;
|
||||
|
@ -365,6 +368,7 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
_outCopyHandlesCount,
|
||||
_outMoveHandlesCount + runtimeMetadata.OutObjectsCount);
|
||||
outRawData = MemoryMarshal.Cast<uint, byte>(response.DataWords);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -377,6 +381,7 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
(BitUtils.AlignUp(rawDataSize, 4) + 0x10) / sizeof(uint),
|
||||
0,
|
||||
0);
|
||||
|
||||
outRawData = MemoryMarshal.Cast<uint, byte>(response.DataWords);
|
||||
}
|
||||
|
||||
|
@ -410,6 +415,7 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
if (obj == null)
|
||||
{
|
||||
response.MoveHandles[index] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -418,4 +424,4 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
response.MoveHandles[index] = clientHandle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,24 +12,22 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
{
|
||||
int argsCount = args.Length;
|
||||
|
||||
int[] sizes = new int[argsCount];
|
||||
int[] sizes = new int[argsCount];
|
||||
int[] aligns = new int[argsCount];
|
||||
int[] map = new int[argsCount];
|
||||
int[] map = new int[argsCount];
|
||||
|
||||
for (int i = 0; i < argsCount; i++)
|
||||
{
|
||||
sizes[i] = args[i].ArgSize;
|
||||
sizes[i] = args[i].ArgSize;
|
||||
aligns[i] = args[i].ArgAlignment;
|
||||
map[i] = i;
|
||||
map[i] = i;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argsCount; i++)
|
||||
{
|
||||
for (int j = i; j > 0 && aligns[map[j - 1]] > aligns[map[j]]; j--)
|
||||
{
|
||||
var temp = map[j - 1];
|
||||
map[j - 1] = map[j];
|
||||
map[j] = temp;
|
||||
(map[j], map[j - 1]) = (map[j - 1], map[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,9 +35,9 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
|
||||
foreach (int i in map)
|
||||
{
|
||||
offset = BitUtils.AlignUp(offset, aligns[i]);
|
||||
offset = BitUtils.AlignUp(offset, aligns[i]);
|
||||
offsets[i] = offset;
|
||||
offset += sizes[i];
|
||||
offset += sizes[i];
|
||||
}
|
||||
|
||||
offsets[argsCount] = offset;
|
||||
|
@ -48,4 +46,4 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
return offsets;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,26 +6,22 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
|||
{
|
||||
public const int ModuleId = 10;
|
||||
|
||||
public static Result NotSupported => new Result(ModuleId, 1);
|
||||
public static Result InvalidHeaderSize => new Result(ModuleId, 202);
|
||||
public static Result InvalidInHeader => new Result(ModuleId, 211);
|
||||
public static Result InvalidOutHeader => new Result(ModuleId, 212);
|
||||
public static Result UnknownCommandId => new Result(ModuleId, 221);
|
||||
public static Result InvalidOutRawSize => new Result(ModuleId, 232);
|
||||
public static Result InvalidInObjectsCount => new Result(ModuleId, 235);
|
||||
public static Result InvalidOutObjectsCount => new Result(ModuleId, 236);
|
||||
public static Result InvalidInObject => new Result(ModuleId, 239);
|
||||
|
||||
public static Result TargetNotFound => new Result(ModuleId, 261);
|
||||
|
||||
public static Result OutOfDomainEntries => new Result(ModuleId, 301);
|
||||
|
||||
public static Result InvalidatedByUser => new Result(ModuleId, 802);
|
||||
public static Result RequestDeferredByUser => new Result(ModuleId, 812);
|
||||
public static Result NotSupported => new(ModuleId, 1);
|
||||
public static Result InvalidHeaderSize => new(ModuleId, 202);
|
||||
public static Result InvalidInHeader => new(ModuleId, 211);
|
||||
public static Result InvalidOutHeader => new(ModuleId, 212);
|
||||
public static Result UnknownCommandId => new(ModuleId, 221);
|
||||
public static Result InvalidOutRawSize => new(ModuleId, 232);
|
||||
public static Result InvalidInObjectsCount => new(ModuleId, 235);
|
||||
public static Result InvalidOutObjectsCount => new(ModuleId, 236);
|
||||
public static Result InvalidInObject => new(ModuleId, 239);
|
||||
public static Result TargetNotFound => new(ModuleId, 261);
|
||||
public static Result OutOfDomainEntries => new(ModuleId, 301);
|
||||
public static Result InvalidatedByUser => new(ModuleId, 802);
|
||||
public static Result RequestDeferredByUser => new(ModuleId, 812);
|
||||
|
||||
public static bool RequestContextChanged(Result result) => result.InRange(800, 899);
|
||||
public static bool Invalidated(Result result) => result.InRange(801, 809);
|
||||
|
||||
public static bool RequestDeferred(Result result) => result.InRange(811, 819);
|
||||
public static bool Invalidated(Result result) => result.InRange(801, 809);
|
||||
public static bool RequestDeferred(Result result) => result.InRange(811, 819);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue