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 inRawData, ref Span 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 outHeader, ref ServiceDispatchContext context, ReadOnlySpan 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); return result.IsFailure ? result : _invoke(ref context, _processor, runtimeMetadata, inRawData, ref outHeader); } public static void GetCmifOutHeaderPointer(ref Span outHeader, ref Span outRawData) { outHeader = MemoryMarshal.Cast(outRawData)[..1]; outRawData = outRawData[Unsafe.SizeOf()..]; } } }