aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.HLE/HOS/Horizon.cs3
-rw-r--r--Ryujinx.HLE/HOS/ProgramLoader.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Lm/ILogService.cs19
-rw-r--r--Ryujinx.HLE/HOS/Services/Lm/LogService/ILogger.cs109
-rw-r--r--Ryujinx.HLE/HOS/Services/Lm/LogService/Types/LmLogField.cs18
-rw-r--r--Ryujinx.HLE/HOS/Services/Lm/LogService/Types/LmLogLevel.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs182
-rw-r--r--Ryujinx.HLE/HOS/Services/Prepo/ResultCode.cs15
-rw-r--r--Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs2
-rw-r--r--Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs57
-rw-r--r--Ryujinx.Horizon/HeapAllocator.cs12
-rw-r--r--Ryujinx.Horizon/HorizonOptions.cs6
-rw-r--r--Ryujinx.Horizon/HorizonStatic.cs26
-rw-r--r--Ryujinx.Horizon/IService.cs2
-rw-r--r--Ryujinx.Horizon/LogManager/Ipc/LmLogger.cs (renamed from Ryujinx.Horizon/LogManager/LmLogger.cs)37
-rw-r--r--Ryujinx.Horizon/LogManager/Ipc/LogService.cs (renamed from Ryujinx.Horizon/LogManager/LmLog.cs)11
-rw-r--r--Ryujinx.Horizon/LogManager/LmIpcServer.cs31
-rw-r--r--Ryujinx.Horizon/LogManager/LmMain.cs9
-rw-r--r--Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs218
-rw-r--r--Ryujinx.Horizon/Prepo/PrepoIpcServer.cs49
-rw-r--r--Ryujinx.Horizon/Prepo/PrepoMain.cs17
-rw-r--r--Ryujinx.Horizon/Prepo/PrepoResult.cs15
-rw-r--r--Ryujinx.Horizon/Prepo/PrepoServerManager.cs30
-rw-r--r--Ryujinx.Horizon/Prepo/Types/PrepoPortIndex.cs12
-rw-r--r--Ryujinx.Horizon/Prepo/Types/PrepoServicePermissionLevel.cs (renamed from Ryujinx.HLE/HOS/Services/Prepo/Types/PrepoServicePermissionLevel.cs)5
-rw-r--r--Ryujinx.Horizon/Ryujinx.Horizon.csproj4
-rw-r--r--Ryujinx.Horizon/Sdk/Account/Uid.cs62
-rw-r--r--Ryujinx.Horizon/Sdk/Lm/ILmLogger.cs12
-rw-r--r--Ryujinx.Horizon/Sdk/Lm/ILogService.cs11
-rw-r--r--Ryujinx.Horizon/Sdk/Prepo/IPrepoService.cs20
-rw-r--r--Ryujinx.Horizon/Sdk/ServiceUtil.cs9
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/CmifDomainInHeader.cs10
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/CmifDomainRequestType.cs4
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/CmifMessage.cs81
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/CmifOutHeader.cs6
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/CmifRequest.cs8
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/CmifRequestFormat.cs26
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/CmifResponse.cs4
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/CommandType.cs12
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectDispatchTable.cs4
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs10
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/PointerAndSize.cs4
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/ServerMessageRuntimeMetadata.cs33
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchContext.cs18
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTable.cs4
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs16
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/CommandArg.cs36
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/CommandArgAttributes.cs8
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/CommandHandler.cs22
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/CommandSerialization.cs3
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/HipcBufferFlags.cs12
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/HipcBufferMode.cs4
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/HipcManager.cs4
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMessage.cs122
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMessageData.cs8
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMetadata.cs18
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/HipcReceiveListEntry.cs2
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/HipcResult.cs21
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/HipcStaticDescriptor.cs8
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/ManagerOptions.cs16
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/Server.cs20
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/ServerDomainSessionManager.cs2
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/ServerManager.cs4
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/ServerManagerBase.cs33
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSession.cs16
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs41
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs38
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/RawDataOffsetCalculator.cs18
-rw-r--r--Ryujinx.Horizon/Sdk/Sf/SfResult.cs36
-rw-r--r--Ryujinx.Horizon/Sdk/Sm/IManagerService.cs8
-rw-r--r--Ryujinx.Horizon/Sdk/Sm/IUserService.cs13
-rw-r--r--Ryujinx.Horizon/Sdk/Sm/SmApi.cs22
-rw-r--r--Ryujinx.Horizon/ServiceEntry.cs16
-rw-r--r--Ryujinx.Horizon/ServiceTable.cs46
-rw-r--r--Ryujinx.Horizon/Sm/Impl/ServiceInfo.cs10
-rw-r--r--Ryujinx.Horizon/Sm/Impl/ServiceManager.cs9
-rw-r--r--Ryujinx.Horizon/Sm/Ipc/ManagerService.cs8
-rw-r--r--Ryujinx.Horizon/Sm/Ipc/UserService.cs (renamed from Ryujinx.Horizon/Sm/UserService.cs)10
-rw-r--r--Ryujinx.Horizon/Sm/ManagerService.cs8
-rw-r--r--Ryujinx.Horizon/Sm/SmMain.cs30
-rw-r--r--Ryujinx.Horizon/Sm/SmResult.cs20
-rw-r--r--Ryujinx.Horizon/Sm/SmServerManager.cs30
-rw-r--r--Ryujinx.Horizon/Sm/Types/SmPortIndex.cs8
83 files changed, 1106 insertions, 880 deletions
diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs
index a8b5be33..ca3f8103 100644
--- a/Ryujinx.HLE/HOS/Horizon.cs
+++ b/Ryujinx.HLE/HOS/Horizon.cs
@@ -123,6 +123,8 @@ namespace Ryujinx.HLE.HOS
internal LibHacHorizonManager LibHacHorizonManager { get; private set; }
+ internal ServiceTable ServiceTable { get; private set; }
+
public bool IsPaused { get; private set; }
public Horizon(Switch device)
@@ -326,6 +328,7 @@ namespace Ryujinx.HLE.HOS
private void StartNewServices()
{
+ ServiceTable = new ServiceTable();
var services = ServiceTable.GetServices(new HorizonOptions(Device.Configuration.IgnoreMissingServices));
foreach (var service in services)
diff --git a/Ryujinx.HLE/HOS/ProgramLoader.cs b/Ryujinx.HLE/HOS/ProgramLoader.cs
index 09e1ac31..b6a39a20 100644
--- a/Ryujinx.HLE/HOS/ProgramLoader.cs
+++ b/Ryujinx.HLE/HOS/ProgramLoader.cs
@@ -182,6 +182,8 @@ namespace Ryujinx.HLE.HOS
byte[] arguments = null,
params IExecutable[] executables)
{
+ context.Device.System.ServiceTable.WaitServicesReady();
+
LibHac.Result rc = metaData.GetNpdm(out var npdm);
if (rc.IsFailure())
diff --git a/Ryujinx.HLE/HOS/Services/Lm/ILogService.cs b/Ryujinx.HLE/HOS/Services/Lm/ILogService.cs
deleted file mode 100644
index 0976431b..00000000
--- a/Ryujinx.HLE/HOS/Services/Lm/ILogService.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using Ryujinx.HLE.HOS.Services.Lm.LogService;
-
-namespace Ryujinx.HLE.HOS.Services.Lm
-{
- [Service("lm")]
- class ILogService : IpcService
- {
- public ILogService(ServiceCtx context) { }
-
- [CommandHipc(0)]
- // Initialize(u64, pid) -> object<nn::lm::ILogger>
- public ResultCode Initialize(ServiceCtx context)
- {
- MakeObject(context, new ILogger());
-
- return ResultCode.Success;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Lm/LogService/ILogger.cs b/Ryujinx.HLE/HOS/Services/Lm/LogService/ILogger.cs
deleted file mode 100644
index 3181668f..00000000
--- a/Ryujinx.HLE/HOS/Services/Lm/LogService/ILogger.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using Ryujinx.Common.Logging;
-using System.IO;
-using System.Text;
-
-namespace Ryujinx.HLE.HOS.Services.Lm.LogService
-{
- class ILogger : IpcService
- {
- public ILogger() { }
-
- [CommandHipc(0)]
- // Log(buffer<unknown, 0x21>)
- public ResultCode Log(ServiceCtx context)
- {
- Logger.Guest?.Print(LogClass.ServiceLm, LogImpl(context));
-
- return ResultCode.Success;
- }
-
- private string LogImpl(ServiceCtx context)
- {
- (ulong bufPos, ulong bufSize) = context.Request.GetBufferType0x21();
-
- byte[] logBuffer = new byte[bufSize];
-
- context.Memory.Read(bufPos, logBuffer);
-
- using MemoryStream ms = new MemoryStream(logBuffer);
-
- BinaryReader reader = new BinaryReader(ms);
-
- long pid = reader.ReadInt64();
- long threadContext = reader.ReadInt64();
- short flags = reader.ReadInt16();
- byte level = reader.ReadByte();
- byte verbosity = reader.ReadByte();
- int payloadLength = reader.ReadInt32();
-
- StringBuilder sb = new StringBuilder();
-
- sb.AppendLine($"Guest Log:\n Log level: {(LmLogLevel)level}");
-
- while (ms.Position < ms.Length)
- {
- int type = ReadEncodedInt(reader);
- int size = ReadEncodedInt(reader);
-
- LmLogField field = (LmLogField)type;
-
- string fieldStr = string.Empty;
-
- if (field == LmLogField.Start)
- {
- reader.ReadBytes(size);
-
- continue;
- }
- else if (field == LmLogField.Stop)
- {
- break;
- }
- else if (field == LmLogField.Line)
- {
- fieldStr = $"{field}: {reader.ReadInt32()}";
- }
- else if (field == LmLogField.DropCount)
- {
- fieldStr = $"{field}: {reader.ReadInt64()}";
- }
- else if (field == LmLogField.Time)
- {
- fieldStr = $"{field}: {reader.ReadInt64()}s";
- }
- else if (field < LmLogField.Count)
- {
- fieldStr = $"{field}: '{Encoding.UTF8.GetString(reader.ReadBytes(size)).TrimEnd()}'";
- }
- else
- {
- fieldStr = $"Field{field}: '{Encoding.UTF8.GetString(reader.ReadBytes(size)).TrimEnd()}'";
- }
-
- sb.AppendLine($" {fieldStr}");
- }
-
- return sb.ToString();
- }
-
- private static int ReadEncodedInt(BinaryReader reader)
- {
- int result = 0;
- int position = 0;
-
- byte encoded;
-
- do
- {
- encoded = reader.ReadByte();
-
- result += (encoded & 0x7F) << (7 * position);
-
- position++;
-
- } while ((encoded & 0x80) != 0);
-
- return result;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Lm/LogService/Types/LmLogField.cs b/Ryujinx.HLE/HOS/Services/Lm/LogService/Types/LmLogField.cs
deleted file mode 100644
index 3f93e167..00000000
--- a/Ryujinx.HLE/HOS/Services/Lm/LogService/Types/LmLogField.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Lm.LogService
-{
- enum LmLogField
- {
- Start = 0,
- Stop = 1,
- Message = 2,
- Line = 3,
- Filename = 4,
- Function = 5,
- Module = 6,
- Thread = 7,
- DropCount = 8,
- Time = 9,
- ProgramName = 10,
- Count
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Lm/LogService/Types/LmLogLevel.cs b/Ryujinx.HLE/HOS/Services/Lm/LogService/Types/LmLogLevel.cs
deleted file mode 100644
index ee1a8396..00000000
--- a/Ryujinx.HLE/HOS/Services/Lm/LogService/Types/LmLogLevel.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Lm.LogService
-{
- enum LmLogLevel
- {
- Trace,
- Info,
- Warning,
- Error,
- Critical
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs b/Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs
deleted file mode 100644
index 019626f1..00000000
--- a/Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs
+++ /dev/null
@@ -1,182 +0,0 @@
-using MsgPack;
-using MsgPack.Serialization;
-using Ryujinx.Common;
-using Ryujinx.Common.Logging;
-using Ryujinx.Common.Utilities;
-using Ryujinx.HLE.HOS.Services.Account.Acc;
-using Ryujinx.HLE.Utilities;
-using System;
-using System.Text;
-
-namespace Ryujinx.HLE.HOS.Services.Prepo
-{
- [Service("prepo:a", PrepoServicePermissionLevel.Admin)] // 1.0.0-5.1.0
- [Service("prepo:a2", PrepoServicePermissionLevel.Admin)] // 6.0.0+
- [Service("prepo:m", PrepoServicePermissionLevel.Manager)]
- [Service("prepo:u", PrepoServicePermissionLevel.User)]
- [Service("prepo:s", PrepoServicePermissionLevel.System)]
- class IPrepoService : IpcService
- {
- private PrepoServicePermissionLevel _permission;
- private ulong _systemSessionId;
-
- public IPrepoService(ServiceCtx context, PrepoServicePermissionLevel permission)
- {
- _permission = permission;
- }
-
- [CommandHipc(10100)] // 1.0.0-5.1.0
- [CommandHipc(10102)] // 6.0.0-9.2.0
- [CommandHipc(10104)] // 10.0.0+
- // SaveReport(u64, pid, buffer<u8, 9>, buffer<bytes, 5>)
- public ResultCode SaveReport(ServiceCtx context)
- {
- if ((_permission & PrepoServicePermissionLevel.User) == 0)
- {
- return ResultCode.PermissionDenied;
- }
-
- // We don't care about the differences since we don't use the play report.
- return ProcessReport(context, withUserID: false);
- }
-
- [CommandHipc(10101)] // 1.0.0-5.1.0
- [CommandHipc(10103)] // 6.0.0-9.2.0
- [CommandHipc(10105)] // 10.0.0+
- // SaveReportWithUser(nn::account::Uid, u64, pid, buffer<u8, 9>, buffer<bytes, 5>)
- public ResultCode SaveReportWithUser(ServiceCtx context)
- {
- if ((_permission & PrepoServicePermissionLevel.User) == 0)
- {
- return ResultCode.PermissionDenied;
- }
-
- // We don't care about the differences since we don't use the play report.
- return ProcessReport(context, withUserID: true);
- }
-
- [CommandHipc(10200)]
- // RequestImmediateTransmission()
- public ResultCode RequestImmediateTransmission(ServiceCtx context)
- {
- // It signals an event of nn::prepo::detail::service::core::TransmissionStatusManager that requests the transmission of the report.
- // Since we don't use reports it's fine to do nothing.
-
- return ResultCode.Success;
- }
-
- [CommandHipc(10300)]
- // GetTransmissionStatus() -> u32
- public ResultCode GetTransmissionStatus(ServiceCtx context)
- {
- // It returns the transmission result of nn::prepo::detail::service::core::TransmissionStatusManager.
- // Since we don't use reports it's fine to return ResultCode.Success.
- context.ResponseData.Write((int)ResultCode.Success);
-
- return ResultCode.Success;
- }
-
- [CommandHipc(10400)] // 9.0.0+
- // GetSystemSessionId() -> u64
- public ResultCode GetSystemSessionId(ServiceCtx context)
- {
- if ((_permission & PrepoServicePermissionLevel.User) == 0)
- {
- return ResultCode.PermissionDenied;
- }
-
- if (_systemSessionId == 0)
- {
- byte[] randomBuffer = new byte[8];
-
- Random.Shared.NextBytes(randomBuffer);
-
- _systemSessionId = BitConverter.ToUInt64(randomBuffer, 0);
- }
-
- context.ResponseData.Write(_systemSessionId);
-
- return ResultCode.Success;
- }
-
- [CommandHipc(20100)]
- // SaveSystemReport(u64, pid, buffer<u8, 9>, buffer<bytes, 5>)
- public ResultCode SaveSystemReport(ServiceCtx context)
- {
- if ((_permission & PrepoServicePermissionLevel.System) != 0)
- {
- return ResultCode.PermissionDenied;
- }
-
- // We don't care about the differences since we don't use the play report.
- return ProcessReport(context, withUserID: false);
- }
-
- [CommandHipc(20101)]
- // SaveSystemReportWithUser(nn::account::Uid, u64, pid, buffer<u8, 9>, buffer<bytes, 5>)
- public ResultCode SaveSystemReportWithUser(ServiceCtx context)
- {
- if ((_permission & PrepoServicePermissionLevel.System) != 0)
- {
- return ResultCode.PermissionDenied;
- }
-
- // We don't care about the differences since we don't use the play report.
- return ProcessReport(context, withUserID: true);
- }
-
- private ResultCode ProcessReport(ServiceCtx context, bool withUserID)
- {
- UserId userId = withUserID ? context.RequestData.ReadStruct<UserId>() : new UserId();
- string gameRoom = StringUtils.ReadUtf8String(context);
-
- if (withUserID)
- {
- if (userId.IsNull)
- {
- return ResultCode.InvalidArgument;
- }
- }
-
- if (gameRoom == string.Empty)
- {
- return ResultCode.InvalidState;
- }
-
- ulong inputPosition = context.Request.SendBuff[0].Position;
- ulong inputSize = context.Request.SendBuff[0].Size;
-
- if (inputSize == 0)
- {
- return ResultCode.InvalidBufferSize;
- }
-
- byte[] inputBuffer = new byte[inputSize];
-
- context.Memory.Read(inputPosition, inputBuffer);
-
- Logger.Info?.Print(LogClass.ServicePrepo, ReadReportBuffer(inputBuffer, gameRoom, userId));
-
- return ResultCode.Success;
- }
-
- private string ReadReportBuffer(byte[] buffer, string room, UserId userId)
- {
- StringBuilder builder = new StringBuilder();
- MessagePackObject deserializedReport = MessagePackSerializer.UnpackMessagePackObject(buffer);
-
- builder.AppendLine();
- builder.AppendLine("PlayReport log:");
-
- if (!userId.IsNull)
- {
- builder.AppendLine($" UserId: {userId}");
- }
-
- builder.AppendLine($" Room: {room}");
- builder.AppendLine($" Report: {MessagePackObjectFormatter.Format(deserializedReport)}");
-
- return builder.ToString();
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Prepo/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Prepo/ResultCode.cs
deleted file mode 100644
index 3199e270..00000000
--- a/Ryujinx.HLE/HOS/Services/Prepo/ResultCode.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Prepo
-{
- enum ResultCode
- {
- ModuleId = 129,
- ErrorCodeShift = 9,
-
- Success = 0,
-
- InvalidArgument = (1 << ErrorCodeShift) | ModuleId,
- InvalidState = (5 << ErrorCodeShift) | ModuleId,
- InvalidBufferSize = (9 << ErrorCodeShift) | ModuleId,
- PermissionDenied = (90 << ErrorCodeShift) | ModuleId
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
index 86031a70..73652da4 100644
--- a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
+++ b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
@@ -180,7 +180,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
return ResultCode.InvalidName;
}
- Logger.Info?.Print(LogClass.ServiceSm, $"Register \"{name}\".");
+ Logger.Debug?.Print(LogClass.ServiceSm, $"Register \"{name}\".");
KPort port = new KPort(context.Device.System.KernelContext, maxSessions, isLight, null);
diff --git a/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs b/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs
index a66d57a3..332e04d1 100644
--- a/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs
+++ b/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs
@@ -123,44 +123,51 @@ namespace Ryujinx.Horizon.Generators.Hipc
{
string[] args = new string[method.ParameterList.Parameters.Count];
- int index = 0;
-
- foreach (var parameter in method.ParameterList.Parameters)
+ if (args.Length == 0)
{
- string canonicalTypeName = GetCanonicalTypeNameWithGenericArguments(compilation, parameter.Type);
- CommandArgType argType = GetCommandArgType(compilation, parameter);
-
- string arg;
+ generator.AppendLine($"{{ {commandId}, new CommandHandler({method.Identifier.Text}, Array.Empty<CommandArg>()) }},");
+ }
+ else
+ {
+ int index = 0;
- if (argType == CommandArgType.Buffer)
+ foreach (var parameter in method.ParameterList.Parameters)
{
- string bufferFlags = GetFirstAttributeAgument(compilation, parameter, TypeBufferAttribute, 0);
- string bufferFixedSize = GetFirstAttributeAgument(compilation, parameter, TypeBufferAttribute, 1);
+ string canonicalTypeName = GetCanonicalTypeNameWithGenericArguments(compilation, parameter.Type);
+ CommandArgType argType = GetCommandArgType(compilation, parameter);
+
+ string arg;
- if (bufferFixedSize != null)
+ if (argType == CommandArgType.Buffer)
+ {
+ string bufferFlags = GetFirstAttributeAgument(compilation, parameter, TypeBufferAttribute, 0);
+ string bufferFixedSize = GetFirstAttributeAgument(compilation, parameter, TypeBufferAttribute, 1);
+
+ if (bufferFixedSize != null)
+ {
+ arg = $"new CommandArg({bufferFlags}, {bufferFixedSize})";
+ }
+ else
+ {
+ arg = $"new CommandArg({bufferFlags})";
+ }
+ }
+ else if (argType == CommandArgType.InArgument || argType == CommandArgType.OutArgument)
{
- arg = $"new CommandArg({bufferFlags}, {bufferFixedSize})";
+ string alignment = GetTypeAlignmentExpression(compilation, parameter.Type);
+
+ arg = $"new CommandArg(CommandArgType.{argType}, Unsafe.SizeOf<{canonicalTypeName}>(), {alignment})";
}
else
{
- arg = $"new CommandArg({bufferFlags})";
+ arg = $"new CommandArg(CommandArgType.{argType})";
}
- }
- else if (argType == CommandArgType.InArgument || argType == CommandArgType.OutArgument)
- {
- string alignment = GetTypeAlignmentExpression(compilation, parameter.Type);
- arg = $"new CommandArg(CommandArgType.{argType}, Unsafe.SizeOf<{canonicalTypeName}>(), {alignment})";
- }
- else
- {
- arg = $"new CommandArg(CommandArgType.{argType})";
+ args[index++] = arg;
}
- args[index++] = arg;
+ generator.AppendLine($"{{ {commandId}, new CommandHandler({method.Identifier.Text}, {string.Join(", ", args)}) }},");
}
-
- generator.AppendLine($"{{ {commandId}, new CommandHandler({method.Identifier.Text}, {string.Join(", ", args)}) }},");
}
}
diff --git a/Ryujinx.Horizon/HeapAllocator.cs b/Ryujinx.Horizon/HeapAllocator.cs
index 867c9677..40ff14d0 100644
--- a/Ryujinx.Horizon/HeapAllocator.cs
+++ b/Ryujinx.Horizon/HeapAllocator.cs
@@ -12,12 +12,12 @@ namespace Ryujinx.Horizon
private struct Range : IComparable<Range>
{
public ulong Offset { get; }
- public ulong Size { get; }
+ public ulong Size { get; }
public Range(ulong offset, ulong size)
{
Offset = offset;
- Size = size;
+ Size = size;
}
public int CompareTo(Range other)
@@ -31,7 +31,7 @@ namespace Ryujinx.Horizon
public HeapAllocator()
{
- _freeRanges = new List<Range>();
+ _freeRanges = new List<Range>();
_currentHeapSize = 0;
}
@@ -70,8 +70,8 @@ namespace Ryujinx.Horizon
var range = _freeRanges[i];
ulong alignedOffset = BitUtils.AlignUp(range.Offset, alignment);
- ulong sizeDelta = alignedOffset - range.Offset;
- ulong usableSize = range.Size - sizeDelta;
+ ulong sizeDelta = alignedOffset - range.Offset;
+ ulong usableSize = range.Size - sizeDelta;
if (sizeDelta < range.Size && usableSize >= size)
{
@@ -82,7 +82,7 @@ namespace Ryujinx.Horizon
InsertFreeRange(range.Offset, sizeDelta);
}
- ulong endOffset = range.Offset + range.Size;
+ ulong endOffset = range.Offset + range.Size;
ulong remainingSize = endOffset - (alignedOffset + size);
if (remainingSize != 0)
{
diff --git a/Ryujinx.Horizon/HorizonOptions.cs b/Ryujinx.Horizon/HorizonOptions.cs
index b1567c6a..6d580e8b 100644
--- a/Ryujinx.Horizon/HorizonOptions.cs
+++ b/Ryujinx.Horizon/HorizonOptions.cs
@@ -2,11 +2,13 @@ namespace Ryujinx.Horizon
{
public struct HorizonOptions
{
- public bool IgnoreMissingServices { get; }
+ public bool IgnoreMissingServices { get; }
+ public bool ThrowOnInvalidCommandIds { get; }
public HorizonOptions(bool ignoreMissingServices)
{
- IgnoreMissingServices = ignoreMissingServices;
+ IgnoreMissingServices = ignoreMissingServices;
+ ThrowOnInvalidCommandIds = true;
}
}
}
diff --git a/Ryujinx.Horizon/HorizonStatic.cs b/Ryujinx.Horizon/HorizonStatic.cs
index 1e483cd4..e372df69 100644
--- a/Ryujinx.Horizon/HorizonStatic.cs
+++ b/Ryujinx.Horizon/HorizonStatic.cs
@@ -21,24 +21,24 @@ namespace Ryujinx.Horizon
[ThreadStatic]
private static int _threadHandle;
- public static HorizonOptions Options => _options;
- public static ISyscallApi Syscall => _syscall;
- public static IVirtualMemoryManager AddressSpace => _addressSpace;
- public static IThreadContext ThreadContext => _threadContext;
- public static int CurrentThreadHandle => _threadHandle;
+ public static HorizonOptions Options => _options;
+ public static ISyscallApi Syscall => _syscall;
+ public static IVirtualMemoryManager AddressSpace => _addressSpace;
+ public static IThreadContext ThreadContext => _threadContext;
+ public static int CurrentThreadHandle => _threadHandle;
public static void Register(
- HorizonOptions options,
- ISyscallApi syscallApi,
+ HorizonOptions options,
+ ISyscallApi syscallApi,
IVirtualMemoryManager addressSpace,
- IThreadContext threadContext,
- int threadHandle)
+ IThreadContext threadContext,
+ int threadHandle)
{
- _options = options;
- _syscall = syscallApi;
- _addressSpace = addressSpace;
+ _options = options;
+ _syscall = syscallApi;
+ _addressSpace = addressSpace;
_threadContext = threadContext;
- _threadHandle = threadHandle;
+ _threadHandle = threadHandle;
}
}
}
diff --git a/Ryujinx.Horizon/IService.cs b/Ryujinx.Horizon/IService.cs
index 67c12cef..c0bc0bcb 100644
--- a/Ryujinx.Horizon/IService.cs
+++ b/Ryujinx.Horizon/IService.cs
@@ -2,6 +2,6 @@
{
interface IService
{
- abstract static void Main();
+ abstract static void Main(ServiceTable serviceTable);
}
}
diff --git a/Ryujinx.Horizon/LogManager/LmLogger.cs b/Ryujinx.Horizon/LogManager/Ipc/LmLogger.cs
index 461776cd..002a5982 100644
--- a/Ryujinx.Horizon/LogManager/LmLogger.cs
+++ b/Ryujinx.Horizon/LogManager/Ipc/LmLogger.cs
@@ -9,23 +9,23 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
-namespace Ryujinx.Horizon.LogManager
+namespace Ryujinx.Horizon.LogManager.Ipc
{
- partial class LmLogger : IServiceObject
+ partial class LmLogger : ILmLogger
{
- private readonly LmLog _log;
- private readonly ulong _clientProcessId;
+ private readonly LogService _log;
+ private readonly ulong _pid;
- public LmLogger(LmLog log, ulong clientProcessId)
+ public LmLogger(LogService log, ulong pid)
{
_log = log;
- _clientProcessId = clientProcessId;
+ _pid = pid;
}
[CmifCommand(0)]
public Result Log([Buffer(HipcBufferFlags.In | HipcBufferFlags.AutoSelect)] Span<byte> message)
{
- if (!SetProcessId(message, _clientProcessId))
+ if (!SetProcessId(message, _pid))
{
return Result.Success;
}
@@ -35,7 +35,7 @@ namespace Ryujinx.Horizon.LogManager
return Result.Success;
}
- [CmifCommand(1)]
+ [CmifCommand(1)] // 3.0.0+
public Result SetDestination(LogDestination destination)
{
_log.LogDestination = destination;
@@ -48,7 +48,6 @@ namespace Ryujinx.Horizon.LogManager
ref LogPacketHeader header = ref MemoryMarshal.Cast<byte, LogPacketHeader>(message)[0];
uint expectedMessageSize = (uint)Unsafe.SizeOf<LogPacketHeader>() + header.PayloadSize;
-
if (expectedMessageSize != (uint)message.Length)
{
Logger.Warning?.Print(LogClass.ServiceLm, $"Invalid message size (expected 0x{expectedMessageSize:X} but got 0x{message.Length:X}).");
@@ -63,13 +62,11 @@ namespace Ryujinx.Horizon.LogManager
private static string LogImpl(ReadOnlySpan<byte> message)
{
- SpanReader reader = new SpanReader(message);
-
- LogPacketHeader header = reader.Read<LogPacketHeader>();
-
- StringBuilder sb = new StringBuilder();
+ SpanReader reader = new(message);
+ LogPacketHeader header = reader.Read<LogPacketHeader>();
+ StringBuilder builder = new();
- sb.AppendLine($"Guest Log:\n Log level: {header.Severity}");
+ builder.AppendLine($"Guest Log:\n Log level: {header.Severity}");
while (reader.Length > 0)
{
@@ -78,7 +75,7 @@ namespace Ryujinx.Horizon.LogManager
LogDataChunkKey field = (LogDataChunkKey)type;
- string fieldStr = string.Empty;
+ string fieldStr;
if (field == LogDataChunkKey.Start)
{
@@ -111,16 +108,16 @@ namespace Ryujinx.Horizon.LogManager
fieldStr = $"Field{field}: '{Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd()}'";
}
- sb.AppendLine($" {fieldStr}");
+ builder.AppendLine($" {fieldStr}");
}
- return sb.ToString();
+ return builder.ToString();
}
private static int ReadUleb128(ref SpanReader reader)
{
int result = 0;
- int count = 0;
+ int count = 0;
byte encoded;
@@ -136,4 +133,4 @@ namespace Ryujinx.Horizon.LogManager
return result;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/LogManager/LmLog.cs b/Ryujinx.Horizon/LogManager/Ipc/LogService.cs
index 772465c4..6899739e 100644
--- a/Ryujinx.Horizon/LogManager/LmLog.cs
+++ b/Ryujinx.Horizon/LogManager/Ipc/LogService.cs
@@ -2,18 +2,19 @@
using Ryujinx.Horizon.Sdk.Lm;
using Ryujinx.Horizon.Sdk.Sf;
-namespace Ryujinx.Horizon.LogManager
+namespace Ryujinx.Horizon.LogManager.Ipc
{
- partial class LmLog : IServiceObject
+ partial class LogService : ILogService
{
public LogDestination LogDestination { get; set; } = LogDestination.TargetManager;
[CmifCommand(0)]
- public Result OpenLogger(out LmLogger logger, [ClientProcessId] ulong clientProcessId)
+ public Result OpenLogger(out LmLogger logger, [ClientProcessId] ulong pid)
{
- logger = new LmLogger(this, clientProcessId);
+ // NOTE: Internal name is Logger, but we rename it LmLogger to avoid name clash with Ryujinx.Common.Logging logger.
+ logger = new LmLogger(this, pid);
return Result.Success;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/LogManager/LmIpcServer.cs b/Ryujinx.Horizon/LogManager/LmIpcServer.cs
index 7b757fe9..71b844a2 100644
--- a/Ryujinx.Horizon/LogManager/LmIpcServer.cs
+++ b/Ryujinx.Horizon/LogManager/LmIpcServer.cs
@@ -1,6 +1,6 @@
-using Ryujinx.Horizon.Sdk.Sf.Hipc;
+using Ryujinx.Horizon.LogManager.Ipc;
+using Ryujinx.Horizon.Sdk.Sf.Hipc;
using Ryujinx.Horizon.Sdk.Sm;
-using Ryujinx.Horizon.Sm;
namespace Ryujinx.Horizon.LogManager
{
@@ -9,36 +9,25 @@ namespace Ryujinx.Horizon.LogManager
private const int LogMaxSessionsCount = 42;
private const int PointerBufferSize = 0x400;
- private const int MaxDomains = 31;
- private const int MaxDomainObjects = 61;
+ private const int MaxDomains = 31;
+ private const int MaxDomainObjects = 61;
+ private const int MaxPortsCount = 1;
- private const int MaxPortsCount = 1;
+ private static readonly ManagerOptions _logManagerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
- private static readonly ManagerOptions _logManagerOptions = new ManagerOptions(
- PointerBufferSize,
- MaxDomains,
- MaxDomainObjects,
- false);
-
- private static readonly ServiceName _logServiceName = ServiceName.Encode("lm");
-
- private SmApi _sm;
+ private SmApi _sm;
private ServerManager _serverManager;
- private LmLog _logServiceObject;
-
public void Initialize()
{
- HeapAllocator allocator = new HeapAllocator();
+ HeapAllocator allocator = new();
_sm = new SmApi();
_sm.Initialize().AbortOnFailure();
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _logManagerOptions, LogMaxSessionsCount);
- _logServiceObject = new LmLog();
-
- _serverManager.RegisterObjectForServer(_logServiceObject, _logServiceName, LogMaxSessionsCount);
+ _serverManager.RegisterObjectForServer(new LogService(), ServiceName.Encode("lm"), LogMaxSessionsCount);
}
public void ServiceRequests()
@@ -51,4 +40,4 @@ namespace Ryujinx.Horizon.LogManager
_serverManager.Dispose();
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/LogManager/LmMain.cs b/Ryujinx.Horizon/LogManager/LmMain.cs
index 8c0262ac..bbe96d4c 100644
--- a/Ryujinx.Horizon/LogManager/LmMain.cs
+++ b/Ryujinx.Horizon/LogManager/LmMain.cs
@@ -2,13 +2,16 @@
{
class LmMain : IService
{
- public static void Main()
+ public static void Main(ServiceTable serviceTable)
{
- LmIpcServer ipcServer = new LmIpcServer();
+ LmIpcServer ipcServer = new();
ipcServer.Initialize();
+
+ serviceTable.SignalServiceReady();
+
ipcServer.ServiceRequests();
ipcServer.Shutdown();
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs b/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs
new file mode 100644
index 00000000..672bba4e
--- /dev/null
+++ b/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs
@@ -0,0 +1,218 @@
+using MsgPack;
+using MsgPack.Serialization;
+using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
+using Ryujinx.Horizon.Common;
+using Ryujinx.Horizon.Prepo.Types;
+using Ryujinx.Horizon.Sdk.Account;
+using Ryujinx.Horizon.Sdk.Prepo;
+using Ryujinx.Horizon.Sdk.Sf;
+using Ryujinx.Horizon.Sdk.Sf.Hipc;
+using System;
+using System.Text;
+
+namespace Ryujinx.Horizon.Prepo.Ipc
+{
+ partial class PrepoService : IPrepoService
+ {
+ enum PlayReportKind
+ {
+ Normal,
+ System
+ }
+
+ private readonly PrepoServicePermissionLevel _permissionLevel;
+ private ulong _systemSessionId;
+
+ private bool _immediateTransmissionEnabled = false;
+ private bool _userAgreementCheckEnabled = true;
+
+ public PrepoService(PrepoServicePermissionLevel permissionLevel)
+ {
+ _permissionLevel = permissionLevel;
+ }
+
+ [CmifCommand(10100)] // 1.0.0-5.1.0
+ [CmifCommand(10102)] // 6.0.0-9.2.0
+ [CmifCommand(10104)] // 10.0.0+
+ public Result SaveReport([Buffer(HipcBufferFlags.In | HipcBufferFlags.Pointer)] ReadOnlySpan<byte> gameRoomBuffer, [Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<byte> reportBuffer, [ClientProcessId] ulong pid)
+ {
+ if ((_permissionLevel & PrepoServicePermissionLevel.User) == 0)
+ {
+ return PrepoResult.PermissionDenied;
+ }
+
+ ProcessPlayReport(PlayReportKind.Normal, pid, gameRoomBuffer, reportBuffer, Uid.Null);
+
+ return Result.Success;
+ }
+
+ [CmifCommand(10101)] // 1.0.0-5.1.0
+ [CmifCommand(10103)] // 6.0.0-9.2.0
+ [CmifCommand(10105)] // 10.0.0+
+ public Result SaveReportWithUser(Uid userId, [Buffer(HipcBufferFlags.In | HipcBufferFlags.Pointer)] ReadOnlySpan<byte> gameRoomBuffer, [Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<byte> reportBuffer, [ClientProcessId] ulong pid)
+ {
+ if ((_permissionLevel & PrepoServicePermissionLevel.User) == 0)
+ {
+ return PrepoResult.PermissionDenied;
+ }
+
+ ProcessPlayReport(PlayReportKind.Normal, pid, gameRoomBuffer, reportBuffer, userId, true);
+
+ return Result.Success;
+ }
+
+ [CmifCommand(10200)]
+ public Result RequestImmediateTransmission()
+ {
+ _immediateTransmissionEnabled = true;
+
+ // It signals an event of nn::prepo::detail::service::core::TransmissionStatusManager that requests the transmission of the report.
+ // Since we don't use reports, it's fine to do nothing.
+
+ return Result.Success;
+ }
+
+ [CmifCommand(10300)]
+ public Result GetTransmissionStatus(out int status)
+ {
+ status = 0;
+
+ if (_immediateTransmissionEnabled && _userAgreementCheckEnabled)
+ {
+ status = 1;
+ }
+
+ return Result.Success;
+ }
+
+ [CmifCommand(10400)] // 9.0.0+
+ public Result GetSystemSessionId(out ulong systemSessionId)
+ {
+ systemSessionId = default;
+
+ if ((_permissionLevel & PrepoServicePermissionLevel.User) == 0)
+ {
+ return PrepoResult.PermissionDenied;
+ }
+
+ if (_systemSessionId == 0)
+ {
+ _systemSessionId = (ulong)Random.Shared.NextInt64();
+ }
+
+ systemSessionId = _systemSessionId;
+
+ return Result.Success;
+ }
+
+ [CmifCommand(20100)]
+ public Result SaveSystemReport([Buffer(HipcBufferFlags.In | HipcBufferFlags.Pointer)] ReadOnlySpan<byte> gameRoomBuffer, [Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<byte> reportBuffer, [ClientProcessId] ulong pid)
+ {
+ if ((_permissionLevel & PrepoServicePermissionLevel.System) != 0)
+ {
+ return PrepoResult.PermissionDenied;
+ }
+
+ return ProcessPlayReport(PlayReportKind.System, pid, gameRoomBuffer, reportBuffer, Uid.Null);
+ }
+
+ [CmifCommand(20101)]
+ public Result SaveSystemReportWithUser(Uid userId, [Buffer(HipcBufferFlags.In | HipcBufferFlags.Pointer)] ReadOnlySpan<byte> gameRoomBuffer, [Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<byte> reportBuffer, [ClientProcessId] ulong pid)
+ {
+ if ((_permissionLevel & PrepoServicePermissionLevel.System) != 0)
+ {
+ return PrepoResult.PermissionDenied;
+ }
+
+ return ProcessPlayReport(PlayReportKind.System, pid, gameRoomBuffer, reportBuffer, userId, true);
+ }
+
+ [CmifCommand(40100)] // 2.0.0+
+ public Result IsUserAgreementCheckEnabled(out bool enabled)
+ {
+ enabled = false;
+
+ if (_permissionLevel == PrepoServicePermissionLevel.User || _permissionLevel == PrepoServicePermissionLevel.System)
+ {
+ enabled = _userAgreementCheckEnabled;
+
+ // If "enabled" is false, it sets some internal fields to 0.
+ // Then, it mounts "prepo-sys:/is_user_agreement_check_enabled.bin" and returns the contained bool.
+ // We can return the private bool instead, we don't care about the agreement since we don't send reports.
+
+ return Result.Success;
+ }
+
+ return PrepoResult.PermissionDenied;
+ }
+
+ [CmifCommand(40101)] // 2.0.0+
+ public Result SetUserAgreementCheckEnabled(bool enabled)
+ {
+ if (_permissionLevel == PrepoServicePermissionLevel.User || _permissionLevel == PrepoServicePermissionLevel.System)
+ {
+ _userAgreementCheckEnabled = enabled;
+
+ // If "enabled" is false, it sets some internal fields to 0.
+ // Then, it mounts "prepo-sys:/is_user_agreement_check_enabled.bin" and stores the "enabled" value.
+ // We can store in the private bool instead, we don't care about the agreement since we don't send reports.
+
+ return Result.Success;
+ }
+
+ return PrepoResult.PermissionDenied;
+ }
+
+ private static Result ProcessPlayReport(PlayReportKind playReportKind, ulong pid, ReadOnlySpan<byte> gameRoomBuffer, ReadOnlySpan<byte> reportBuffer, Uid userId, bool withUserId = false)
+ {
+ if (withUserId)
+ {
+ if (userId.IsNull)
+ {
+ return PrepoResult.InvalidArgument;
+ }
+ }
+
+ if (gameRoomBuffer.Length > 31)
+ {
+ return PrepoResult.InvalidArgument;
+ }
+
+ string gameRoom = Encoding.UTF8.GetString(gameRoomBuffer).TrimEnd();
+
+ if (gameRoom == string.Empty)
+ {
+ return PrepoResult.InvalidState;
+ }
+
+ if (reportBuffer.Length == 0)
+ {
+ return PrepoResult.InvalidBufferSize;
+ }
+
+ // NOTE: The service calls arp:r using the pid to get the application id, if it fails PrepoResult.InvalidPid is returned.
+ // Reports are stored internally and an event is signaled to transmit them.
+
+ StringBuilder builder = new();
+ MessagePackObject deserializedReport = MessagePackSerializer.UnpackMessagePackObject(reportBuffer.ToArray());
+
+ builder.AppendLine();
+ builder.AppendLine("PlayReport log:");
+ builder.AppendLine($" Kind: {playReportKind}");
+ builder.AppendLine($" Pid: {pid}");
+
+ if (!userId.IsNull)
+ {
+ builder.AppendLine($" UserId: {userId}");
+ }
+
+ builder.AppendLine($" Room: {gameRoom}");
+ builder.AppendLine($" Report: {MessagePackObjectFormatter.Format(deserializedReport)}");
+
+ Logger.Info?.Print(LogClass.ServicePrepo, builder.ToString());
+
+ return Result.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Prepo/PrepoIpcServer.cs b/Ryujinx.Horizon/Prepo/PrepoIpcServer.cs
new file mode 100644
index 00000000..ba19ff6f
--- /dev/null
+++ b/Ryujinx.Horizon/Prepo/PrepoIpcServer.cs
@@ -0,0 +1,49 @@
+using Ryujinx.Horizon.Prepo.Types;
+using Ryujinx.Horizon.Sdk.Sf.Hipc;
+using Ryujinx.Horizon.Sdk.Sm;
+
+namespace Ryujinx.Horizon.Prepo
+{
+ class PrepoIpcServer
+ {
+ private const int PrepoMaxSessionsCount = 12;
+ private const int PrepoTotalMaxSessionsCount = PrepoMaxSessionsCount * 6;
+
+ private const int PointerBufferSize = 0x3800;
+ private const int MaxDomains = 64;
+ private const int MaxDomainObjects = 16;
+ private const int MaxPortsCount = 6;
+
+ private static readonly ManagerOptions _logManagerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
+
+ private SmApi _sm;
+ private PrepoServerManager _serverManager;
+
+ public void Initialize()
+ {
+ HeapAllocator allocator = new();
+
+ _sm = new SmApi();
+ _sm.Initialize().AbortOnFailure();
+
+ _serverManager = new PrepoServerManager(allocator, _sm, MaxPortsCount, _logManagerOptions, PrepoTotalMaxSessionsCount);
+
+ _serverManager.RegisterServer((int)PrepoPortIndex.Admin, ServiceName.Encode("prepo:a"), PrepoMaxSessionsCount); // 1.0.0-5.1.0
+ _serverManager.RegisterServer((int)PrepoPortIndex.Admin2, ServiceName.Encode("prepo:a2"), PrepoMaxSessionsCount); // 6.0.0+
+ _serverManager.RegisterServer((int)PrepoPortIndex.Manager, ServiceName.Encode("prepo:m"), PrepoMaxSessionsCount);
+ _serverManager.RegisterServer((int)PrepoPortIndex.User, ServiceName.Encode("prepo:u"), PrepoMaxSessionsCount);
+ _serverManager.RegisterServer((int)PrepoPortIndex.System, ServiceName.Encode("prepo:s"), PrepoMaxSessionsCount);
+ _serverManager.RegisterServer((int)PrepoPortIndex.Debug, ServiceName.Encode("prepo:d"), PrepoMaxSessionsCount); // 1.0.0
+ }
+
+ public void ServiceRequests()
+ {
+ _serverManager.ServiceRequests();
+ }
+
+ public void Shutdown()
+ {
+ _serverManager.Dispose();
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Prepo/PrepoMain.cs b/Ryujinx.Horizon/Prepo/PrepoMain.cs
new file mode 100644
index 00000000..5ff0f53d
--- /dev/null
+++ b/Ryujinx.Horizon/Prepo/PrepoMain.cs
@@ -0,0 +1,17 @@
+namespace Ryujinx.Horizon.Prepo
+{
+ class PrepoMain : IService
+ {
+ public static void Main(ServiceTable serviceTable)
+ {
+ PrepoIpcServer ipcServer = new();
+
+ ipcServer.Initialize();
+
+ serviceTable.SignalServiceReady();
+
+ ipcServer.ServiceRequests();
+ ipcServer.Shutdown();
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Prepo/PrepoResult.cs b/Ryujinx.Horizon/Prepo/PrepoResult.cs
new file mode 100644
index 00000000..12255e3d
--- /dev/null
+++ b/Ryujinx.Horizon/Prepo/PrepoResult.cs
@@ -0,0 +1,15 @@
+using Ryujinx.Horizon.Common;
+
+namespace Ryujinx.Horizon.Prepo
+{
+ static class PrepoResult
+ {
+ private const int ModuleId = 129;
+
+ public static Result InvalidArgument => new(ModuleId, 1);
+ public static Result InvalidState => new(ModuleId, 5);
+ public static Result InvalidBufferSize => new(ModuleId, 9);
+ public static Result PermissionDenied => new(ModuleId, 90);
+ public static Result InvalidPid => new(ModuleId, 101);
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Prepo/PrepoServerManager.cs b/Ryujinx.Horizon/Prepo/PrepoServerManager.cs
new file mode 100644
index 00000000..55e4ff7d
--- /dev/null
+++ b/Ryujinx.Horizon/Prepo/PrepoServerManager.cs
@@ -0,0 +1,30 @@
+using Ryujinx.Horizon.Common;
+using Ryujinx.Horizon.Prepo.Ipc;
+using Ryujinx.Horizon.Prepo.Types;
+using Ryujinx.Horizon.Sdk.Sf.Hipc;
+using Ryujinx.Horizon.Sdk.Sm;
+using System;
+
+namespace Ryujinx.Horizon.Prepo
+{
+ class PrepoServerManager : ServerManager
+ {
+ public PrepoServerManager(HeapAllocator allocator, SmApi sm, int maxPorts, ManagerOptions options, int maxSessions) : base(allocator, sm, maxPorts, options, maxSessions)
+ {
+ }
+
+ protected override Result OnNeedsToAccept(int portIndex, Server server)
+ {
+ return (PrepoPortIndex)portIndex switch
+ {
+ PrepoPortIndex.Admin => AcceptImpl(server, new PrepoService(PrepoServicePermissionLevel.Admin)),
+ PrepoPortIndex.Admin2 => AcceptImpl(server, new PrepoService(PrepoServicePermissionLevel.Admin)),
+ PrepoPortIndex.Manager => AcceptImpl(server, new PrepoService(PrepoServicePermissionLevel.Manager)),
+ PrepoPortIndex.User => AcceptImpl(server, new PrepoService(PrepoServicePermissionLevel.User)),
+ PrepoPortIndex.System => AcceptImpl(server, new PrepoService(PrepoServicePermissionLevel.System)),
+ PrepoPortIndex.Debug => AcceptImpl(server, new PrepoService(PrepoServicePermissionLevel.Debug)),
+ _ => throw new ArgumentOutOfRangeException(nameof(portIndex)),
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Prepo/Types/PrepoPortIndex.cs b/Ryujinx.Horizon/Prepo/Types/PrepoPortIndex.cs
new file mode 100644
index 00000000..f4d6b877
--- /dev/null
+++ b/Ryujinx.Horizon/Prepo/Types/PrepoPortIndex.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Horizon.Prepo.Types
+{
+ enum PrepoPortIndex
+ {
+ Admin,
+ Admin2,
+ Manager,
+ User,
+ System,
+ Debug
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Prepo/Types/PrepoServicePermissionLevel.cs b/Ryujinx.Horizon/Prepo/Types/PrepoServicePermissionLevel.cs
index 35774707..8214f4b9 100644
--- a/Ryujinx.HLE/HOS/Services/Prepo/Types/PrepoServicePermissionLevel.cs
+++ b/Ryujinx.Horizon/Prepo/Types/PrepoServicePermissionLevel.cs
@@ -1,10 +1,11 @@
-namespace Ryujinx.HLE.HOS.Services.Prepo
+namespace Ryujinx.Horizon.Prepo.Types
{
enum PrepoServicePermissionLevel
{
Admin = -1,
User = 1,
System = 2,
- Manager = 6
+ Manager = 6,
+ Debug = unchecked((int)0x80000006)
}
} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Ryujinx.Horizon.csproj b/Ryujinx.Horizon/Ryujinx.Horizon.csproj
index e4591c6f..0139c367 100644
--- a/Ryujinx.Horizon/Ryujinx.Horizon.csproj
+++ b/Ryujinx.Horizon/Ryujinx.Horizon.csproj
@@ -11,4 +11,8 @@
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
</ItemGroup>
+ <ItemGroup>
+ <PackageReference Include="LibHac" />
+ </ItemGroup>
+
</Project>
diff --git a/Ryujinx.Horizon/Sdk/Account/Uid.cs b/Ryujinx.Horizon/Sdk/Account/Uid.cs
new file mode 100644
index 00000000..a0a39978
--- /dev/null
+++ b/Ryujinx.Horizon/Sdk/Account/Uid.cs
@@ -0,0 +1,62 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Horizon.Sdk.Account
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public readonly record struct Uid
+ {
+ public readonly long High;
+ public readonly long Low;
+
+ public bool IsNull => (Low | High) == 0;
+
+ public static Uid Null => new(0, 0);
+
+ public Uid(long low, long high)
+ {
+ Low = low;
+ High = high;
+ }
+
+ public Uid(byte[] bytes)
+ {
+ High = BitConverter.ToInt64(bytes, 0);
+ Low = BitConverter.ToInt64(bytes, 8);
+ }
+
+ public Uid(string hex)
+ {
+ if (hex == null || hex.Length != 32 || !hex.All("0123456789abcdefABCDEF".Contains))
+ {
+ throw new ArgumentException("Invalid Hex value!", nameof(hex));
+ }
+
+ Low = Convert.ToInt64(hex[16..], 16);
+ High = Convert.ToInt64(hex[..16], 16);
+ }
+
+ public void Write(BinaryWriter binaryWriter)
+ {
+ binaryWriter.Write(High);
+ binaryWriter.Write(Low);
+ }
+
+ public override string ToString()
+ {
+ return High.ToString("x16") + Low.ToString("x16");
+ }
+
+ public LibHac.Account.Uid ToLibHacUid()
+ {
+ return new LibHac.Account.Uid((ulong)High, (ulong)Low);
+ }
+
+ public UInt128 ToUInt128()
+ {
+ return new UInt128((ulong)High, (ulong)Low);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Lm/ILmLogger.cs b/Ryujinx.Horizon/Sdk/Lm/ILmLogger.cs
new file mode 100644
index 00000000..bb5770cb
--- /dev/null
+++ b/Ryujinx.Horizon/Sdk/Lm/ILmLogger.cs
@@ -0,0 +1,12 @@
+using Ryujinx.Horizon.Common;
+using Ryujinx.Horizon.Sdk.Sf;
+using System;
+
+namespace Ryujinx.Horizon.Sdk.Lm
+{
+ interface ILmLogger : IServiceObject
+ {
+ Result Log(Span<byte> message);
+ Result SetDestination(LogDestination destination);
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Lm/ILogService.cs b/Ryujinx.Horizon/Sdk/Lm/ILogService.cs
new file mode 100644
index 00000000..ad6c8455
--- /dev/null
+++ b/Ryujinx.Horizon/Sdk/Lm/ILogService.cs
@@ -0,0 +1,11 @@
+using Ryujinx.Horizon.Common;
+using Ryujinx.Horizon.LogManager.Ipc;
+using Ryujinx.Horizon.Sdk.Sf;
+
+namespace Ryujinx.Horizon.Sdk.Lm
+{
+ interface ILogService : IServiceObject
+ {
+ Result OpenLogger(out LmLogger logger, ulong pid);
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Prepo/IPrepoService.cs b/Ryujinx.Horizon/Sdk/Prepo/IPrepoService.cs
new file mode 100644
index 00000000..f61ee61b
--- /dev/null
+++ b/Ryujinx.Horizon/Sdk/Prepo/IPrepoService.cs
@@ -0,0 +1,20 @@
+using Ryujinx.Horizon.Common;
+using Ryujinx.Horizon.Sdk.Account;
+using Ryujinx.Horizon.Sdk.Sf;
+using System;
+
+namespace Ryujinx.Horizon.Sdk.Prepo
+{
+ interface IPrepoService : IServiceObject
+ {
+ Result SaveReport(ReadOnlySpan<byte> gameRoomBuffer, ReadOnlySpan<byte> reportBuffer, ulong pid);
+ Result SaveReportWithUser(Uid userId, ReadOnlySpan<byte> gameRoomBuffer, ReadOnlySpan<byte> reportBuffer, ulong pid);
+ Result RequestImmediateTransmission();
+ Result GetTransmissionStatus(out int status);
+ Result GetSystemSessionId(out ulong systemSessionId);
+ Result SaveSystemReport(ReadOnlySpan<byte> gameRoomBuffer, ReadOnlySpan<byte> reportBuffer, ulong pid);
+ Result SaveSystemReportWithUser(Uid userId, ReadOnlySpan<byte> gameRoomBuffer, ReadOnlySpan<byte> reportBuffer, ulong pid);
+ Result IsUserAgreementCheckEnabled(out bool enabled);
+ Result SetUserAgreementCheckEnabled(bool enabled);
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/ServiceUtil.cs b/Ryujinx.Horizon/Sdk/ServiceUtil.cs
index 413ac1f6..fe6fcce1 100644
--- a/Ryujinx.Horizon/Sdk/ServiceUtil.cs
+++ b/Ryujinx.Horizon/Sdk/ServiceUtil.cs
@@ -10,15 +10,15 @@ namespace Ryujinx.Horizon.Sdk
public static Result SendRequest(out CmifResponse response, int sessionHandle, uint requestId, bool sendPid, scoped ReadOnlySpan<byte> data)
{
ulong tlsAddress = HorizonStatic.ThreadContext.TlsAddress;
- int tlsSize = Api.TlsMessageBufferSize;
+ int tlsSize = Api.TlsMessageBufferSize;
using (var tlsRegion = HorizonStatic.AddressSpace.GetWritableRegion(tlsAddress, tlsSize))
{
CmifRequest request = CmifMessage.CreateRequest(tlsRegion.Memory.Span, new CmifRequestFormat()
{
- DataSize = data.Length,
+ DataSize = data.Length,
RequestId = requestId,
- SendPid = sendPid
+ SendPid = sendPid
});
data.CopyTo(request.Data);
@@ -29,10 +29,11 @@ namespace Ryujinx.Horizon.Sdk
if (result.IsFailure)
{
response = default;
+
return result;
}
return CmifMessage.ParseResponse(out response, HorizonStatic.AddressSpace.GetWritableRegion(tlsAddress, tlsSize).Memory.Span, false, 0);
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifDomainInHeader.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifDomainInHeader.cs
index 88211501..beaff613 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifDomainInHeader.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifDomainInHeader.cs
@@ -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;
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifDomainRequestType.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifDomainRequestType.cs
index b913db94..1a02e082 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifDomainRequestType.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifDomainRequestType.cs
@@ -2,8 +2,8 @@
{
enum CmifDomainRequestType : byte
{
- Invalid = 0,
+ Invalid = 0,
SendMessage = 1,
- Close = 2
+ Close = 2
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifMessage.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifMessage.cs
index 781452e3..0d23d33b 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifMessage.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifMessage.cs
@@ -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();
+ int rawDataSizeInWords = (totalSize + sizeof(uint) - 1) / sizeof(uint);
- 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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifOutHeader.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifOutHeader.cs
index 2828cde5..00b9d2bd 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifOutHeader.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifOutHeader.cs
@@ -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
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifRequest.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifRequest.cs
index 80772ad3..e44a84ec 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifRequest.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifRequest.cs
@@ -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;
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifRequestFormat.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifRequestFormat.cs
index d1154578..592f11f4 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifRequestFormat.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifRequestFormat.cs
@@ -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
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifResponse.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifResponse.cs
index d1d8dc9c..2ff31eb6 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifResponse.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/CmifResponse.cs
@@ -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;
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/CommandType.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/CommandType.cs
index b3b05864..82c0648b 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/CommandType.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/CommandType.cs
@@ -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
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectDispatchTable.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectDispatchTable.cs
index bcf311b2..b0b4498d 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectDispatchTable.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectDispatchTable.cs
@@ -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)
{
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs
index 92d86196..796b8a78 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/DomainServiceObjectProcessor.cs
@@ -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++)
{
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/PointerAndSize.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/PointerAndSize.cs
index 5af00077..ad0e1824 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/PointerAndSize.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/PointerAndSize.cs
@@ -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;
}
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/ServerMessageRuntimeMetadata.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/ServerMessageRuntimeMetadata.cs
index 18a40430..6a92e8d5 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/ServerMessageRuntimeMetadata.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/ServerMessageRuntimeMetadata.cs
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchContext.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchContext.cs
index 3339a1a6..31be810d 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchContext.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchContext.cs
@@ -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;
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTable.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTable.cs
index 145c1783..21b342df 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTable.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTable.cs
@@ -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());
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs b/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs
index a0e28ca8..81600067 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/CommandArg.cs b/Ryujinx.Horizon/Sdk/Sf/CommandArg.cs
index 8f367b4e..47aedde9 100644
--- a/Ryujinx.Horizon/Sdk/Sf/CommandArg.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/CommandArg.cs
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/CommandArgAttributes.cs b/Ryujinx.Horizon/Sdk/Sf/CommandArgAttributes.cs
index 5b7c302f..294c7d58 100644
--- a/Ryujinx.Horizon/Sdk/Sf/CommandArgAttributes.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/CommandArgAttributes.cs
@@ -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
{
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/CommandHandler.cs b/Ryujinx.Horizon/Sdk/Sf/CommandHandler.cs
index ae42a8ef..fe079d47 100644
--- a/Ryujinx.Horizon/Sdk/Sf/CommandHandler.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/CommandHandler.cs
@@ -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>()..];
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/CommandSerialization.cs b/Ryujinx.Horizon/Sdk/Sf/CommandSerialization.cs
index 9a3a511a..feb2d666 100644
--- a/Ryujinx.Horizon/Sdk/Sf/CommandSerialization.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/CommandSerialization.cs
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcBufferFlags.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcBufferFlags.cs
index 594af2c8..269ab4fe 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcBufferFlags.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcBufferFlags.cs
@@ -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
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcBufferMode.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcBufferMode.cs
index 4ef6374b..b1e67253 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcBufferMode.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcBufferMode.cs
@@ -2,9 +2,9 @@
{
enum HipcBufferMode
{
- Normal = 0,
+ Normal = 0,
NonSecure = 1,
- Invalid = 2,
+ Invalid = 2,
NonDevice = 3
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcManager.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcManager.cs
index ea2ec650..7541e294 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcManager.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcManager.cs
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMessage.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMessage.cs
index 3017f404..6500d6cf 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMessage.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMessage.cs
@@ -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).Slice(padding, meta.DataWordsCount - padding);
+ dataWords = MemoryMarshal.Cast<byte, uint>(data)[padding..meta.DataWordsCount];
- 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
};
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMessageData.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMessageData.cs
index c83c422c..154b8f07 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMessageData.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMessageData.cs
@@ -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;
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMetadata.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMetadata.cs
index fe13137a..10abc400 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMetadata.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcMetadata.cs
@@ -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;
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcReceiveListEntry.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcReceiveListEntry.cs
index 94bf0968..56cf16fb 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcReceiveListEntry.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcReceiveListEntry.cs
@@ -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);
}
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcResult.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcResult.cs
index ef989a98..3b483be8 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcResult.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcResult.cs
@@ -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);
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcStaticDescriptor.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcStaticDescriptor.cs
index 5cebf47c..103820a6 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcStaticDescriptor.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcStaticDescriptor.cs
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/ManagerOptions.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/ManagerOptions.cs
index e087cb22..b99d63c5 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/ManagerOptions.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/ManagerOptions.cs
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/Server.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/Server.cs
index 923f2d52..bbbab898 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/Server.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/Server.cs
@@ -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)
{
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerDomainSessionManager.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerDomainSessionManager.cs
index d920a659..dda77539 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerDomainSessionManager.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerDomainSessionManager.cs
@@ -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);
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerManager.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerManager.cs
index 5bb2de25..2ca9ceea 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerManager.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerManager.cs
@@ -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);
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerManagerBase.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerManagerBase.cs
index 68cae6bc..9d21290d 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerManagerBase.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerManagerBase.cs
@@ -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
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSession.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSession.cs
index eb98fefd..a1730082 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSession.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSession.cs
@@ -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;
}
}
}
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs
index e85892f2..6d395081 100644
--- a/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs b/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs
index 53202ede..6bba49ae 100644
--- a/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/RawDataOffsetCalculator.cs b/Ryujinx.Horizon/Sdk/Sf/RawDataOffsetCalculator.cs
index 982f454f..10e4f909 100644
--- a/Ryujinx.Horizon/Sdk/Sf/RawDataOffsetCalculator.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/RawDataOffsetCalculator.cs
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sf/SfResult.cs b/Ryujinx.Horizon/Sdk/Sf/SfResult.cs
index 6aa11ba5..72502d17 100644
--- a/Ryujinx.Horizon/Sdk/Sf/SfResult.cs
+++ b/Ryujinx.Horizon/Sdk/Sf/SfResult.cs
@@ -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);
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sm/IManagerService.cs b/Ryujinx.Horizon/Sdk/Sm/IManagerService.cs
new file mode 100644
index 00000000..64428583
--- /dev/null
+++ b/Ryujinx.Horizon/Sdk/Sm/IManagerService.cs
@@ -0,0 +1,8 @@
+using Ryujinx.Horizon.Sdk.Sf;
+
+namespace Ryujinx.Horizon.Sdk.Sm
+{
+ interface IManagerService : IServiceObject
+ {
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sm/IUserService.cs b/Ryujinx.Horizon/Sdk/Sm/IUserService.cs
new file mode 100644
index 00000000..ad9bc9d7
--- /dev/null
+++ b/Ryujinx.Horizon/Sdk/Sm/IUserService.cs
@@ -0,0 +1,13 @@
+using Ryujinx.Horizon.Common;
+using Ryujinx.Horizon.Sdk.Sf;
+
+namespace Ryujinx.Horizon.Sdk.Sm
+{
+ interface IUserService : IServiceObject
+ {
+ Result Initialize(ulong clientProcessId);
+ Result GetService(out int handle, ServiceName name);
+ Result RegisterService(out int handle, ServiceName name, int maxSessions, bool isLight);
+ Result UnregisterService(ServiceName name);
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sdk/Sm/SmApi.cs b/Ryujinx.Horizon/Sdk/Sm/SmApi.cs
index e4b0eea1..533e68d9 100644
--- a/Ryujinx.Horizon/Sdk/Sm/SmApi.cs
+++ b/Ryujinx.Horizon/Sdk/Sm/SmApi.cs
@@ -7,16 +7,18 @@ namespace Ryujinx.Horizon.Sdk.Sm
{
class SmApi
{
+ private const string SmName = "sm:";
+
private int _portHandle;
public Result Initialize()
{
- Result result = HorizonStatic.Syscall.ConnectToNamedPort(out int portHandle, "sm:");
+ Result result = HorizonStatic.Syscall.ConnectToNamedPort(out int portHandle, SmName);
while (result == KernelResult.NotFound)
{
HorizonStatic.Syscall.SleepThread(50000000L);
- result = HorizonStatic.Syscall.ConnectToNamedPort(out portHandle, "sm:");
+ result = HorizonStatic.Syscall.ConnectToNamedPort(out portHandle, SmName);
}
if (result.IsFailure)
@@ -33,7 +35,7 @@ namespace Ryujinx.Horizon.Sdk.Sm
{
Span<byte> data = stackalloc byte[8];
- SpanWriter writer = new SpanWriter(data);
+ SpanWriter writer = new(data);
writer.Write(0UL);
@@ -44,7 +46,7 @@ namespace Ryujinx.Horizon.Sdk.Sm
{
Span<byte> data = stackalloc byte[8];
- SpanWriter writer = new SpanWriter(data);
+ SpanWriter writer = new(data);
writer.Write(name);
@@ -53,10 +55,12 @@ namespace Ryujinx.Horizon.Sdk.Sm
if (result.IsFailure)
{
handle = 0;
+
return result;
}
handle = response.MoveHandles[0];
+
return Result.Success;
}
@@ -64,7 +68,7 @@ namespace Ryujinx.Horizon.Sdk.Sm
{
Span<byte> data = stackalloc byte[16];
- SpanWriter writer = new SpanWriter(data);
+ SpanWriter writer = new(data);
writer.Write(name);
writer.Write(isLight ? 1 : 0);
@@ -75,10 +79,12 @@ namespace Ryujinx.Horizon.Sdk.Sm
if (result.IsFailure)
{
handle = 0;
+
return result;
}
handle = response.MoveHandles[0];
+
return Result.Success;
}
@@ -86,7 +92,7 @@ namespace Ryujinx.Horizon.Sdk.Sm
{
Span<byte> data = stackalloc byte[8];
- SpanWriter writer = new SpanWriter(data);
+ SpanWriter writer = new(data);
writer.Write(name);
@@ -97,11 +103,11 @@ namespace Ryujinx.Horizon.Sdk.Sm
{
Span<byte> data = stackalloc byte[8];
- SpanWriter writer = new SpanWriter(data);
+ SpanWriter writer = new(data);
writer.Write(0UL);
return ServiceUtil.SendRequest(out _, _portHandle, 4, sendPid: true, data);
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/ServiceEntry.cs b/Ryujinx.Horizon/ServiceEntry.cs
index 3fea46c1..06152d9f 100644
--- a/Ryujinx.Horizon/ServiceEntry.cs
+++ b/Ryujinx.Horizon/ServiceEntry.cs
@@ -6,20 +6,22 @@ namespace Ryujinx.Horizon
{
public struct ServiceEntry
{
- private readonly Action _entrypoint;
- private readonly HorizonOptions _options;
+ private readonly Action<ServiceTable> _entrypoint;
+ private readonly ServiceTable _serviceTable;
+ private readonly HorizonOptions _options;
- internal ServiceEntry(Action entrypoint, HorizonOptions options)
+ internal ServiceEntry(Action<ServiceTable> entrypoint, ServiceTable serviceTable, HorizonOptions options)
{
- _entrypoint = entrypoint;
- _options = options;
+ _entrypoint = entrypoint;
+ _serviceTable = serviceTable;
+ _options = options;
}
public void Start(ISyscallApi syscallApi, IVirtualMemoryManager addressSpace, IThreadContext threadContext)
{
HorizonStatic.Register(_options, syscallApi, addressSpace, threadContext, (int)threadContext.GetX(1));
- _entrypoint();
+ _entrypoint(_serviceTable);
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/ServiceTable.cs b/Ryujinx.Horizon/ServiceTable.cs
index 933b6a59..2edc6ea1 100644
--- a/Ryujinx.Horizon/ServiceTable.cs
+++ b/Ryujinx.Horizon/ServiceTable.cs
@@ -1,22 +1,58 @@
using Ryujinx.Horizon.LogManager;
+using Ryujinx.Horizon.Prepo;
using System.Collections.Generic;
+using System.Threading;
namespace Ryujinx.Horizon
{
- public static class ServiceTable
+ public class ServiceTable
{
- public static IEnumerable<ServiceEntry> GetServices(HorizonOptions options)
+ private int _readyServices;
+ private int _totalServices;
+
+ private readonly ManualResetEvent _servicesReadyEvent = new(false);
+
+ public IEnumerable<ServiceEntry> GetServices(HorizonOptions options)
{
- List<ServiceEntry> entries = new List<ServiceEntry>();
+ List<ServiceEntry> entries = new();
void RegisterService<T>() where T : IService
{
- entries.Add(new ServiceEntry(T.Main, options));
+ entries.Add(new ServiceEntry(T.Main, this, options));
}
RegisterService<LmMain>();
+ RegisterService<PrepoMain>();
+
+ _totalServices = entries.Count;
return entries;
}
+
+ internal void SignalServiceReady()
+ {
+ if (Interlocked.Increment(ref _readyServices) == _totalServices)
+ {
+ _servicesReadyEvent.Set();
+ }
+ }
+
+ public void WaitServicesReady()
+ {
+ _servicesReadyEvent.WaitOne();
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _servicesReadyEvent.Dispose();
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sm/Impl/ServiceInfo.cs b/Ryujinx.Horizon/Sm/Impl/ServiceInfo.cs
index fed420aa..50c18a2c 100644
--- a/Ryujinx.Horizon/Sm/Impl/ServiceInfo.cs
+++ b/Ryujinx.Horizon/Sm/Impl/ServiceInfo.cs
@@ -5,16 +5,16 @@ namespace Ryujinx.Horizon.Sm.Impl
struct ServiceInfo
{
public ServiceName Name;
- public ulong OwnerProcessId;
- public int PortHandle;
+ public ulong OwnerProcessId;
+ public int PortHandle;
public void Free()
{
HorizonStatic.Syscall.CloseHandle(PortHandle);
- Name = ServiceName.Invalid;
+ Name = ServiceName.Invalid;
OwnerProcessId = 0L;
- PortHandle = 0;
+ PortHandle = 0;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sm/Impl/ServiceManager.cs b/Ryujinx.Horizon/Sm/Impl/ServiceManager.cs
index cdf2d17f..44a1ec46 100644
--- a/Ryujinx.Horizon/Sm/Impl/ServiceManager.cs
+++ b/Ryujinx.Horizon/Sm/Impl/ServiceManager.cs
@@ -107,8 +107,8 @@ namespace Ryujinx.Horizon.Sm.Impl
return result;
}
- freeService.PortHandle = clientPort;
- freeService.Name = name;
+ freeService.PortHandle = clientPort;
+ freeService.Name = name;
freeService.OwnerProcessId = processId;
return Result.Success;
@@ -126,20 +126,19 @@ namespace Ryujinx.Horizon.Sm.Impl
// TODO: Validation with GetProcessInfo etc.
int serviceIndex = GetServiceInfo(name);
-
if (serviceIndex < 0)
{
return SmResult.NotRegistered;
}
ref var serviceInfo = ref _services[serviceIndex];
-
if (serviceInfo.OwnerProcessId != processId)
{
return SmResult.NotAllowed;
}
serviceInfo.Free();
+
return Result.Success;
}
@@ -194,4 +193,4 @@ namespace Ryujinx.Horizon.Sm.Impl
return -1;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sm/Ipc/ManagerService.cs b/Ryujinx.Horizon/Sm/Ipc/ManagerService.cs
new file mode 100644
index 00000000..c7dcddc9
--- /dev/null
+++ b/Ryujinx.Horizon/Sm/Ipc/ManagerService.cs
@@ -0,0 +1,8 @@
+using Ryujinx.Horizon.Sdk.Sm;
+
+namespace Ryujinx.Horizon.Sm.Ipc
+{
+ partial class ManagerService : IManagerService
+ {
+ }
+}
diff --git a/Ryujinx.Horizon/Sm/UserService.cs b/Ryujinx.Horizon/Sm/Ipc/UserService.cs
index d3b4537b..d093913a 100644
--- a/Ryujinx.Horizon/Sm/UserService.cs
+++ b/Ryujinx.Horizon/Sm/Ipc/UserService.cs
@@ -3,14 +3,14 @@ using Ryujinx.Horizon.Sdk.Sf;
using Ryujinx.Horizon.Sdk.Sm;
using Ryujinx.Horizon.Sm.Impl;
-namespace Ryujinx.Horizon.Sm
+namespace Ryujinx.Horizon.Sm.Ipc
{
- partial class UserService : IServiceObject
+ partial class UserService : IUserService
{
private readonly ServiceManager _serviceManager;
private ulong _clientProcessId;
- private bool _initialized;
+ private bool _initialized;
public UserService(ServiceManager serviceManager)
{
@@ -21,7 +21,7 @@ namespace Ryujinx.Horizon.Sm
public Result Initialize([ClientProcessId] ulong clientProcessId)
{
_clientProcessId = clientProcessId;
- _initialized = true;
+ _initialized = true;
return Result.Success;
}
@@ -63,4 +63,4 @@ namespace Ryujinx.Horizon.Sm
return _serviceManager.UnregisterService(_clientProcessId, name);
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sm/ManagerService.cs b/Ryujinx.Horizon/Sm/ManagerService.cs
deleted file mode 100644
index 1719dcfd..00000000
--- a/Ryujinx.Horizon/Sm/ManagerService.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using Ryujinx.Horizon.Sdk.Sf;
-
-namespace Ryujinx.Horizon.Sm
-{
- partial class ManagerService : IServiceObject
- {
- }
-}
diff --git a/Ryujinx.Horizon/Sm/SmMain.cs b/Ryujinx.Horizon/Sm/SmMain.cs
index 8c37bece..5656d464 100644
--- a/Ryujinx.Horizon/Sm/SmMain.cs
+++ b/Ryujinx.Horizon/Sm/SmMain.cs
@@ -1,30 +1,34 @@
-using Ryujinx.Horizon.Sdk.Sf.Hipc;
+using Ryujinx.Horizon.Prepo.Types;
+using Ryujinx.Horizon.Prepo;
+using Ryujinx.Horizon.Sdk.Sf.Hipc;
using Ryujinx.Horizon.Sdk.Sm;
using Ryujinx.Horizon.Sm.Impl;
+using Ryujinx.Horizon.Sm.Types;
namespace Ryujinx.Horizon.Sm
{
public class SmMain
{
- private enum PortIndex
- {
- User,
- Manager
- }
+ private const int SmMaxSessionsCount = 64;
+ private const int SmmMaxSessionsCount = 1;
+ private const int SmTotalMaxSessionsCount = SmMaxSessionsCount + SmmMaxSessionsCount;
private const int MaxPortsCount = 2;
- private readonly ServerManager _serverManager = new ServerManager(null, null, MaxPortsCount, ManagerOptions.Default, 0);
- private readonly ServiceManager _serviceManager = new ServiceManager();
+ private SmServerManager _serverManager;
+
+ private readonly ServiceManager _serviceManager = new();
public void Main()
{
- HorizonStatic.Syscall.ManageNamedPort(out int smHandle, "sm:", 64).AbortOnFailure();
+ HorizonStatic.Syscall.ManageNamedPort(out int smHandle, "sm:", SmMaxSessionsCount).AbortOnFailure();
+
+ _serverManager = new SmServerManager(_serviceManager, null, null, MaxPortsCount, ManagerOptions.Default, SmTotalMaxSessionsCount);
- _serverManager.RegisterServer((int)PortIndex.User, smHandle);
- _serviceManager.RegisterServiceForSelf(out int smmHandle, ServiceName.Encode("sm:m"), 1).AbortOnFailure();
- _serverManager.RegisterServer((int)PortIndex.Manager, smmHandle);
+ _serverManager.RegisterServer((int)SmPortIndex.User, smHandle);
+ _serviceManager.RegisterServiceForSelf(out int smmHandle, ServiceName.Encode("sm:m"), SmmMaxSessionsCount).AbortOnFailure();
+ _serverManager.RegisterServer((int)SmPortIndex.Manager, smmHandle);
_serverManager.ServiceRequests();
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sm/SmResult.cs b/Ryujinx.Horizon/Sm/SmResult.cs
index 3063445d..2d503a4f 100644
--- a/Ryujinx.Horizon/Sm/SmResult.cs
+++ b/Ryujinx.Horizon/Sm/SmResult.cs
@@ -6,14 +6,14 @@ namespace Ryujinx.Horizon.Sm
{
private const int ModuleId = 21;
- public static Result OutOfProcess => new Result(ModuleId, 1);
- public static Result InvalidClient => new Result(ModuleId, 2);
- public static Result OutOfSessions => new Result(ModuleId, 3);
- public static Result AlreadyRegistered => new Result(ModuleId, 4);
- public static Result OutOfServices => new Result(ModuleId, 5);
- public static Result InvalidServiceName => new Result(ModuleId, 6);
- public static Result NotRegistered => new Result(ModuleId, 7);
- public static Result NotAllowed => new Result(ModuleId, 8);
- public static Result TooLargeAccessControl => new Result(ModuleId, 9);
+ public static Result OutOfProcess => new(ModuleId, 1);
+ public static Result InvalidClient => new(ModuleId, 2);
+ public static Result OutOfSessions => new(ModuleId, 3);
+ public static Result AlreadyRegistered => new(ModuleId, 4);
+ public static Result OutOfServices => new(ModuleId, 5);
+ public static Result InvalidServiceName => new(ModuleId, 6);
+ public static Result NotRegistered => new(ModuleId, 7);
+ public static Result NotAllowed => new(ModuleId, 8);
+ public static Result TooLargeAccessControl => new(ModuleId, 9);
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sm/SmServerManager.cs b/Ryujinx.Horizon/Sm/SmServerManager.cs
new file mode 100644
index 00000000..dc8dc5b6
--- /dev/null
+++ b/Ryujinx.Horizon/Sm/SmServerManager.cs
@@ -0,0 +1,30 @@
+using Ryujinx.Horizon.Common;
+using Ryujinx.Horizon.Sdk.Sf.Hipc;
+using Ryujinx.Horizon.Sdk.Sm;
+using Ryujinx.Horizon.Sm.Impl;
+using Ryujinx.Horizon.Sm.Ipc;
+using Ryujinx.Horizon.Sm.Types;
+using System;
+
+namespace Ryujinx.Horizon.Sm
+{
+ class SmServerManager : ServerManager
+ {
+ private readonly ServiceManager _serviceManager;
+
+ public SmServerManager(ServiceManager serviceManager, HeapAllocator allocator, SmApi sm, int maxPorts, ManagerOptions options, int maxSessions) : base(allocator, sm, maxPorts, options, maxSessions)
+ {
+ _serviceManager = serviceManager;
+ }
+
+ protected override Result OnNeedsToAccept(int portIndex, Server server)
+ {
+ return (SmPortIndex)portIndex switch
+ {
+ SmPortIndex.User => AcceptImpl(server, new UserService(_serviceManager)),
+ SmPortIndex.Manager => AcceptImpl(server, new ManagerService()),
+ _ => throw new ArgumentOutOfRangeException(nameof(portIndex)),
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Horizon/Sm/Types/SmPortIndex.cs b/Ryujinx.Horizon/Sm/Types/SmPortIndex.cs
new file mode 100644
index 00000000..5325558b
--- /dev/null
+++ b/Ryujinx.Horizon/Sm/Types/SmPortIndex.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Horizon.Sm.Types
+{
+ enum SmPortIndex
+ {
+ User,
+ Manager
+ }
+} \ No newline at end of file