aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs')
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs140
1 files changed, 140 insertions, 0 deletions
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs
new file mode 100644
index 00000000..92d86196
--- /dev/null
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs
@@ -0,0 +1,140 @@
+using Ryujinx.Horizon.Common;
+using Ryujinx.Horizon.Sdk.Sf.Hipc;
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Horizon.Sdk.Sf.Cmif
+{
+ class DomainServiceObjectProcessor : ServerMessageProcessor
+ {
+ public const int MaximumObjects = 8;
+
+ private ServerMessageProcessor _implProcessor;
+ private readonly ServerDomainBase _domain;
+ private int _outObjectIdsOffset;
+ private readonly int[] _inObjectIds;
+ private readonly int[] _reservedObjectIds;
+ private ServerMessageRuntimeMetadata _implMetadata;
+
+ private int InObjectsCount => _inObjectIds.Length;
+ private int OutObjectsCount => _implMetadata.OutObjectsCount;
+ private int ImplOutHeadersSize => _implMetadata.OutHeadersSize;
+ private int ImplOutDataTotalSize => _implMetadata.OutDataSize + _implMetadata.OutHeadersSize;
+
+ public DomainServiceObjectProcessor(ServerDomainBase domain, int[] inObjectIds)
+ {
+ _domain = domain;
+ _inObjectIds = inObjectIds;
+ _reservedObjectIds = new int[MaximumObjects];
+ }
+
+ public override void SetImplementationProcessor(ServerMessageProcessor impl)
+ {
+ if (_implProcessor == null)
+ {
+ _implProcessor = impl;
+ }
+ else
+ {
+ _implProcessor.SetImplementationProcessor(impl);
+ }
+
+ _implMetadata = _implProcessor.GetRuntimeMetadata();
+ }
+
+ public override ServerMessageRuntimeMetadata GetRuntimeMetadata()
+ {
+ var runtimeMetadata = _implProcessor.GetRuntimeMetadata();
+
+ return new ServerMessageRuntimeMetadata(
+ (ushort)(runtimeMetadata.InDataSize + runtimeMetadata.InObjectsCount * sizeof(int)),
+ (ushort)(runtimeMetadata.OutDataSize + runtimeMetadata.OutObjectsCount * sizeof(int)),
+ (byte)(runtimeMetadata.InHeadersSize + Unsafe.SizeOf<CmifDomainInHeader>()),
+ (byte)(runtimeMetadata.OutHeadersSize + Unsafe.SizeOf<CmifDomainOutHeader>()),
+ 0,
+ 0);
+ }
+
+ public override Result PrepareForProcess(ref ServiceDispatchContext context, ServerMessageRuntimeMetadata runtimeMetadata)
+ {
+ if (_implMetadata.InObjectsCount != InObjectsCount)
+ {
+ return SfResult.InvalidInObjectsCount;
+ }
+
+ Result result = _domain.ReserveIds(new Span<int>(_reservedObjectIds).Slice(0, OutObjectsCount));
+
+ if (result.IsFailure)
+ {
+ return result;
+ }
+
+ return _implProcessor.PrepareForProcess(ref context, runtimeMetadata);
+ }
+
+ public override Result GetInObjects(Span<ServiceObjectHolder> inObjects)
+ {
+ for (int i = 0; i < InObjectsCount; i++)
+ {
+ inObjects[i] = _domain.GetObject(_inObjectIds[i]);
+ }
+
+ return Result.Success;
+ }
+
+ public override HipcMessageData PrepareForReply(scoped ref ServiceDispatchContext context, out Span<byte> outRawData, ServerMessageRuntimeMetadata runtimeMetadata)
+ {
+ var response = _implProcessor.PrepareForReply(ref context, out outRawData, runtimeMetadata);
+
+ int outHeaderSize = Unsafe.SizeOf<CmifDomainOutHeader>();
+ int implOutDataTotalSize = ImplOutDataTotalSize;
+
+ DebugUtil.Assert(outHeaderSize + implOutDataTotalSize + OutObjectsCount * sizeof(int) <= outRawData.Length);
+
+ outRawData = outRawData.Slice(outHeaderSize);
+ _outObjectIdsOffset = (response.DataWords.Length * sizeof(uint) - outRawData.Length) + implOutDataTotalSize;
+
+ return response;
+ }
+
+ public override void PrepareForErrorReply(scoped ref ServiceDispatchContext context, out Span<byte> outRawData, ServerMessageRuntimeMetadata runtimeMetadata)
+ {
+ _implProcessor.PrepareForErrorReply(ref context, out outRawData, runtimeMetadata);
+
+ int outHeaderSize = Unsafe.SizeOf<CmifDomainOutHeader>();
+ int implOutDataTotalSize = ImplOutDataTotalSize;
+
+ DebugUtil.Assert(outHeaderSize + implOutDataTotalSize <= outRawData.Length);
+
+ outRawData = outRawData.Slice(outHeaderSize);
+
+ _domain.UnreserveIds(new Span<int>(_reservedObjectIds).Slice(0, OutObjectsCount));
+ }
+
+ public override void SetOutObjects(scoped ref ServiceDispatchContext context, HipcMessageData response, Span<ServiceObjectHolder> outObjects)
+ {
+ int outObjectsCount = OutObjectsCount;
+ Span<int> objectIds = _reservedObjectIds;
+
+ for (int i = 0; i < outObjectsCount; i++)
+ {
+ if (outObjects[i] == null)
+ {
+ _domain.UnreserveIds(objectIds.Slice(i, 1));
+ objectIds[i] = 0;
+ continue;
+ }
+
+ _domain.RegisterObject(objectIds[i], outObjects[i]);
+ }
+
+ Span<int> outObjectIds = MemoryMarshal.Cast<byte, int>(MemoryMarshal.Cast<uint, byte>(response.DataWords).Slice(_outObjectIdsOffset));
+
+ for (int i = 0; i < outObjectsCount; i++)
+ {
+ outObjectIds[i] = objectIds[i];
+ }
+ }
+ }
+}