diff options
Diffstat (limited to 'Ryujinx.Horizon/Sdk/Sf/CommandHandler.cs')
-rw-r--r-- | Ryujinx.Horizon/Sdk/Sf/CommandHandler.cs | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/Ryujinx.Horizon/Sdk/Sf/CommandHandler.cs b/Ryujinx.Horizon/Sdk/Sf/CommandHandler.cs new file mode 100644 index 00000000..ae42a8ef --- /dev/null +++ b/Ryujinx.Horizon/Sdk/Sf/CommandHandler.cs @@ -0,0 +1,57 @@ +using Ryujinx.Horizon.Common; +using Ryujinx.Horizon.Sdk.Sf.Cmif; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Ryujinx.Horizon.Sdk.Sf +{ + class CommandHandler + { + public delegate Result MethodInvoke( + ref ServiceDispatchContext context, + HipcCommandProcessor processor, + ServerMessageRuntimeMetadata runtimeMetadata, + ReadOnlySpan<byte> inRawData, + ref Span<CmifOutHeader> outHeader); + + private readonly MethodInvoke _invoke; + private readonly HipcCommandProcessor _processor; + + public string MethodName => _invoke.Method.Name; + + public CommandHandler(MethodInvoke invoke, params CommandArg[] args) + { + _invoke = invoke; + _processor = new HipcCommandProcessor(args); + } + + public Result Invoke(ref Span<CmifOutHeader> outHeader, ref ServiceDispatchContext context, ReadOnlySpan<byte> inRawData) + { + if (context.Processor == null) + { + context.Processor = _processor; + } + else + { + context.Processor.SetImplementationProcessor(_processor); + } + + var runtimeMetadata = context.Processor.GetRuntimeMetadata(); + Result result = context.Processor.PrepareForProcess(ref context, runtimeMetadata); + + if (result.IsFailure) + { + return result; + } + + return _invoke(ref context, _processor, runtimeMetadata, inRawData, ref outHeader); + } + + 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>()); + } + } +} |