From 550747eac6c0f6da14070c8b6d208bde6f1d1eb9 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Sun, 8 Jan 2023 13:13:39 +0100 Subject: Horizon: Impl Prepo, Fixes bugs, Clean things (#4220) * Horizon: Impl Prepo, Fixes bugs, Clean things * remove ToArray() * resultCode > status * Remove old services * Addresses gdkchan's comments and more cleanup * Addresses Gdkchan's feedback 2 * Reorganize services, make sure service are loaded before guest Co-Authored-By: gdkchan <5624669+gdkchan@users.noreply.github.com> * Create interfaces for lm and sm Co-authored-by: gdkchan <5624669+gdkchan@users.noreply.github.com> --- Ryujinx.Horizon/LogManager/Ipc/LmLogger.cs | 136 ++++++++++++++++++++++++++ Ryujinx.Horizon/LogManager/Ipc/LogService.cs | 20 ++++ Ryujinx.Horizon/LogManager/LmIpcServer.cs | 31 ++---- Ryujinx.Horizon/LogManager/LmLog.cs | 19 ---- Ryujinx.Horizon/LogManager/LmLogger.cs | 139 --------------------------- Ryujinx.Horizon/LogManager/LmMain.cs | 9 +- 6 files changed, 172 insertions(+), 182 deletions(-) create mode 100644 Ryujinx.Horizon/LogManager/Ipc/LmLogger.cs create mode 100644 Ryujinx.Horizon/LogManager/Ipc/LogService.cs delete mode 100644 Ryujinx.Horizon/LogManager/LmLog.cs delete mode 100644 Ryujinx.Horizon/LogManager/LmLogger.cs (limited to 'Ryujinx.Horizon/LogManager') diff --git a/Ryujinx.Horizon/LogManager/Ipc/LmLogger.cs b/Ryujinx.Horizon/LogManager/Ipc/LmLogger.cs new file mode 100644 index 00000000..002a5982 --- /dev/null +++ b/Ryujinx.Horizon/LogManager/Ipc/LmLogger.cs @@ -0,0 +1,136 @@ +using Ryujinx.Common.Logging; +using Ryujinx.Common.Memory; +using Ryujinx.Horizon.Common; +using Ryujinx.Horizon.Sdk.Lm; +using Ryujinx.Horizon.Sdk.Sf; +using Ryujinx.Horizon.Sdk.Sf.Hipc; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; + +namespace Ryujinx.Horizon.LogManager.Ipc +{ + partial class LmLogger : ILmLogger + { + private readonly LogService _log; + private readonly ulong _pid; + + public LmLogger(LogService log, ulong pid) + { + _log = log; + _pid = pid; + } + + [CmifCommand(0)] + public Result Log([Buffer(HipcBufferFlags.In | HipcBufferFlags.AutoSelect)] Span message) + { + if (!SetProcessId(message, _pid)) + { + return Result.Success; + } + + Logger.Guest?.Print(LogClass.ServiceLm, LogImpl(message)); + + return Result.Success; + } + + [CmifCommand(1)] // 3.0.0+ + public Result SetDestination(LogDestination destination) + { + _log.LogDestination = destination; + + return Result.Success; + } + + private static bool SetProcessId(Span message, ulong processId) + { + ref LogPacketHeader header = ref MemoryMarshal.Cast(message)[0]; + + uint expectedMessageSize = (uint)Unsafe.SizeOf() + 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})."); + + return false; + } + + header.ProcessId = processId; + + return true; + } + + private static string LogImpl(ReadOnlySpan message) + { + SpanReader reader = new(message); + LogPacketHeader header = reader.Read(); + StringBuilder builder = new(); + + builder.AppendLine($"Guest Log:\n Log level: {header.Severity}"); + + while (reader.Length > 0) + { + int type = ReadUleb128(ref reader); + int size = ReadUleb128(ref reader); + + LogDataChunkKey field = (LogDataChunkKey)type; + + string fieldStr; + + if (field == LogDataChunkKey.Start) + { + reader.Skip(size); + + continue; + } + else if (field == LogDataChunkKey.Stop) + { + break; + } + else if (field == LogDataChunkKey.Line) + { + fieldStr = $"{field}: {reader.Read()}"; + } + else if (field == LogDataChunkKey.DropCount) + { + fieldStr = $"{field}: {reader.Read()}"; + } + else if (field == LogDataChunkKey.Time) + { + fieldStr = $"{field}: {reader.Read()}s"; + } + else if (field < LogDataChunkKey.Count) + { + fieldStr = $"{field}: '{Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd()}'"; + } + else + { + fieldStr = $"Field{field}: '{Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd()}'"; + } + + builder.AppendLine($" {fieldStr}"); + } + + return builder.ToString(); + } + + private static int ReadUleb128(ref SpanReader reader) + { + int result = 0; + int count = 0; + + byte encoded; + + do + { + encoded = reader.Read(); + + result += (encoded & 0x7F) << (7 * count); + + count++; + } while ((encoded & 0x80) != 0); + + return result; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Horizon/LogManager/Ipc/LogService.cs b/Ryujinx.Horizon/LogManager/Ipc/LogService.cs new file mode 100644 index 00000000..6899739e --- /dev/null +++ b/Ryujinx.Horizon/LogManager/Ipc/LogService.cs @@ -0,0 +1,20 @@ +using Ryujinx.Horizon.Common; +using Ryujinx.Horizon.Sdk.Lm; +using Ryujinx.Horizon.Sdk.Sf; + +namespace Ryujinx.Horizon.LogManager.Ipc +{ + partial class LogService : ILogService + { + public LogDestination LogDestination { get; set; } = LogDestination.TargetManager; + + [CmifCommand(0)] + public Result OpenLogger(out LmLogger logger, [ClientProcessId] ulong pid) + { + // 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/LmLog.cs b/Ryujinx.Horizon/LogManager/LmLog.cs deleted file mode 100644 index 772465c4..00000000 --- a/Ryujinx.Horizon/LogManager/LmLog.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Ryujinx.Horizon.Common; -using Ryujinx.Horizon.Sdk.Lm; -using Ryujinx.Horizon.Sdk.Sf; - -namespace Ryujinx.Horizon.LogManager -{ - partial class LmLog : IServiceObject - { - public LogDestination LogDestination { get; set; } = LogDestination.TargetManager; - - [CmifCommand(0)] - public Result OpenLogger(out LmLogger logger, [ClientProcessId] ulong clientProcessId) - { - logger = new LmLogger(this, clientProcessId); - - return Result.Success; - } - } -} diff --git a/Ryujinx.Horizon/LogManager/LmLogger.cs b/Ryujinx.Horizon/LogManager/LmLogger.cs deleted file mode 100644 index 461776cd..00000000 --- a/Ryujinx.Horizon/LogManager/LmLogger.cs +++ /dev/null @@ -1,139 +0,0 @@ -using Ryujinx.Common.Logging; -using Ryujinx.Common.Memory; -using Ryujinx.Horizon.Common; -using Ryujinx.Horizon.Sdk.Lm; -using Ryujinx.Horizon.Sdk.Sf; -using Ryujinx.Horizon.Sdk.Sf.Hipc; -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text; - -namespace Ryujinx.Horizon.LogManager -{ - partial class LmLogger : IServiceObject - { - private readonly LmLog _log; - private readonly ulong _clientProcessId; - - public LmLogger(LmLog log, ulong clientProcessId) - { - _log = log; - _clientProcessId = clientProcessId; - } - - [CmifCommand(0)] - public Result Log([Buffer(HipcBufferFlags.In | HipcBufferFlags.AutoSelect)] Span message) - { - if (!SetProcessId(message, _clientProcessId)) - { - return Result.Success; - } - - Logger.Guest?.Print(LogClass.ServiceLm, LogImpl(message)); - - return Result.Success; - } - - [CmifCommand(1)] - public Result SetDestination(LogDestination destination) - { - _log.LogDestination = destination; - - return Result.Success; - } - - private static bool SetProcessId(Span message, ulong processId) - { - ref LogPacketHeader header = ref MemoryMarshal.Cast(message)[0]; - - uint expectedMessageSize = (uint)Unsafe.SizeOf() + 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})."); - - return false; - } - - header.ProcessId = processId; - - return true; - } - - private static string LogImpl(ReadOnlySpan message) - { - SpanReader reader = new SpanReader(message); - - LogPacketHeader header = reader.Read(); - - StringBuilder sb = new StringBuilder(); - - sb.AppendLine($"Guest Log:\n Log level: {header.Severity}"); - - while (reader.Length > 0) - { - int type = ReadUleb128(ref reader); - int size = ReadUleb128(ref reader); - - LogDataChunkKey field = (LogDataChunkKey)type; - - string fieldStr = string.Empty; - - if (field == LogDataChunkKey.Start) - { - reader.Skip(size); - - continue; - } - else if (field == LogDataChunkKey.Stop) - { - break; - } - else if (field == LogDataChunkKey.Line) - { - fieldStr = $"{field}: {reader.Read()}"; - } - else if (field == LogDataChunkKey.DropCount) - { - fieldStr = $"{field}: {reader.Read()}"; - } - else if (field == LogDataChunkKey.Time) - { - fieldStr = $"{field}: {reader.Read()}s"; - } - else if (field < LogDataChunkKey.Count) - { - fieldStr = $"{field}: '{Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd()}'"; - } - else - { - fieldStr = $"Field{field}: '{Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd()}'"; - } - - sb.AppendLine($" {fieldStr}"); - } - - return sb.ToString(); - } - - private static int ReadUleb128(ref SpanReader reader) - { - int result = 0; - int count = 0; - - byte encoded; - - do - { - encoded = reader.Read(); - - result += (encoded & 0x7F) << (7 * count); - - count++; - } while ((encoded & 0x80) != 0); - - return result; - } - } -} 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 -- cgit v1.2.3