From 232a882d47749b278fc4e06607beefe87c44e56b Mon Sep 17 00:00:00 2001 From: LotP1 <68976644+LotP1@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:41:18 +0200 Subject: [PATCH 1/8] test 1: add an event handle --- .../ApplicationProxy/IApplicationFunctions.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs index 8648b0642..caf1c3a4c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs @@ -31,11 +31,13 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati private readonly KEvent _friendInvitationStorageChannelEvent; private readonly KEvent _notificationStorageChannelEvent; private readonly KEvent _healthWarningDisappearedSystemEvent; + private readonly KEvent _unknownEvent; private int _gpuErrorDetectedSystemEventHandle; private int _friendInvitationStorageChannelEventHandle; private int _notificationStorageChannelEventHandle; private int _healthWarningDisappearedSystemEventHandle; + private int _unknownEventHandle; private bool _gamePlayRecordingState; @@ -50,6 +52,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati _friendInvitationStorageChannelEvent = new KEvent(system.KernelContext); _notificationStorageChannelEvent = new KEvent(system.KernelContext); _healthWarningDisappearedSystemEvent = new KEvent(system.KernelContext); + _unknownEvent = new KEvent(system.KernelContext); _horizon = system.LibHacHorizonManager.AmClient; } @@ -647,6 +650,25 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati return ResultCode.Success; } + + [CommandCmif(210)] + // GetUnknownEvent() -> handle + public ResultCode GetUnknownEvent(ServiceCtx context) + { + if (_unknownEventHandle == 0) + { + if (context.Process.HandleTable.GenerateHandle(_unknownEvent.ReadableEvent, out _unknownEventHandle) != Result.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_unknownEventHandle); + + Logger.Stub?.PrintStub(LogClass.ServiceAm); + + return ResultCode.Success; + } [CommandCmif(1001)] // 10.0.0+ // PrepareForJit() From e7591339b3c1af3a650c94f72b3f443ab6b5da26 Mon Sep 17 00:00:00 2001 From: LotP1 <68976644+LotP1@users.noreply.github.com> Date: Wed, 4 Jun 2025 20:52:44 +0200 Subject: [PATCH 2/8] remove stub --- .../ApplicationProxy/IApplicationFunctions.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs index caf1c3a4c..eaf3a73bb 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs @@ -665,8 +665,6 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_unknownEventHandle); - Logger.Stub?.PrintStub(LogClass.ServiceAm); - return ResultCode.Success; } From 288269df852ee2a1137ff34ebe0aa200ccb6f43c Mon Sep 17 00:00:00 2001 From: LotP1 <68976644+LotP1@users.noreply.github.com> Date: Mon, 23 Jun 2025 01:34:18 +0200 Subject: [PATCH 3/8] Add version comment --- .../ApplicationProxy/IApplicationFunctions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs index eaf3a73bb..9986bf824 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs @@ -651,7 +651,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati return ResultCode.Success; } - [CommandCmif(210)] + [CommandCmif(210)] // 20.0.0+ // GetUnknownEvent() -> handle public ResultCode GetUnknownEvent(ServiceCtx context) { From 503bd68f7f450f4f8656ed183331d30bdd8f7cb5 Mon Sep 17 00:00:00 2001 From: LotP1 <68976644+LotP1@users.noreply.github.com> Date: Mon, 23 Jun 2025 01:34:35 +0200 Subject: [PATCH 4/8] fix spelling --- .../Services/Hid/Types/SharedMemory/Common/RingLifo.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs index f567bbc3c..092d0215a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs @@ -39,9 +39,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common public ref AtomicStorage GetCurrentAtomicEntryRef() { - ulong countAvailaible = Math.Min(Math.Max(0, ReadCurrentCount()), 1); + ulong countAvailable = Math.Min(Math.Max(0, ReadCurrentCount()), 1); - if (countAvailaible == 0) + if (countAvailable == 0) { _storage[0] = default; @@ -54,7 +54,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common while (true) { - int inputEntryIndex = (int)((index + MaxEntries + 1 - countAvailaible) % MaxEntries); + int inputEntryIndex = (int)((index + MaxEntries + 1 - countAvailable) % MaxEntries); ref AtomicStorage result = ref storageSpan[inputEntryIndex]; @@ -63,9 +63,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common if (samplingNumber0 != samplingNumber1 && (result.SamplingNumber - result.SamplingNumber) != 1) { - ulong tempCount = Math.Min(ReadCurrentCount(), countAvailaible); + ulong tempCount = Math.Min(ReadCurrentCount(), countAvailable); - countAvailaible = Math.Min(tempCount, 1); + countAvailable = Math.Min(tempCount, 1); index = ReadCurrentIndex(); continue; From c5a8e2b230e943901616e4c966d89514a3b880d0 Mon Sep 17 00:00:00 2001 From: LotP1 <68976644+LotP1@users.noreply.github.com> Date: Mon, 23 Jun 2025 01:34:45 +0200 Subject: [PATCH 5/8] add missing field --- .../Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs index f79a2657e..c518cf95d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs @@ -41,6 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad public NpadLarkType LarkTypeRight; public NpadLuciaType LuciaType; public uint Unknown43EC; + public ulong SixAxisSensorPropertiesArray; [StructLayout(LayoutKind.Sequential, Size = 123, Pack = 1)] private struct Reserved2Struct { } From 1379b4f6b15db0edaef62960e720ac0c75e2e41e Mon Sep 17 00:00:00 2001 From: LotP1 <68976644+LotP1@users.noreply.github.com> Date: Mon, 23 Jun 2025 01:38:17 +0200 Subject: [PATCH 6/8] TotK boots with overriden audio REV15 --- .../Hid/Types/SharedMemory/Common/ISampledDataStruct.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledDataStruct.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledDataStruct.cs index 312075bc4..5a6aab495 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledDataStruct.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledDataStruct.cs @@ -50,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common ulong value = BinaryPrimitives.ReadUInt64LittleEndian(byteSpan); - return value; + return value << 1; } private static int GetSamplingNumberFieldOffset(ref T sampledDataStruct) where T : unmanaged, ISampledDataStruct From e004624cb80cc8d6f0a0bae56898d87b2202ec24 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Sat, 2 Aug 2025 01:28:41 -0500 Subject: [PATCH 7/8] fw 17 & 20 additions to snoop manager --- .../Audio/AudioUserIpcServer.cs | 2 + .../Sdk/Audio/Detail/AudioSnoopManager.cs | 42 +++++++++++++++++-- .../Sdk/Audio/Detail/IAudioSnoopManager.cs | 6 +++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx.Horizon/Audio/AudioUserIpcServer.cs b/src/Ryujinx.Horizon/Audio/AudioUserIpcServer.cs index 20c824e1e..1de123f7f 100644 --- a/src/Ryujinx.Horizon/Audio/AudioUserIpcServer.cs +++ b/src/Ryujinx.Horizon/Audio/AudioUserIpcServer.cs @@ -33,11 +33,13 @@ namespace Ryujinx.Horizon.Audio AudioOutManager audioOutManager = new(_managers.AudioOutputManager); AudioInManager audioInManager = new(_managers.AudioInputManager); FinalOutputRecorderManager finalOutputRecorderManager = new(); + AudioSnoopManager audioSnoopManager = new(); _serverManager.RegisterObjectForServer(audioRendererManager, ServiceName.Encode("audren:u"), MaxSessionsCount); _serverManager.RegisterObjectForServer(audioOutManager, ServiceName.Encode("audout:u"), MaxSessionsCount); _serverManager.RegisterObjectForServer(audioInManager, ServiceName.Encode("audin:u"), MaxSessionsCount); _serverManager.RegisterObjectForServer(finalOutputRecorderManager, ServiceName.Encode("audrec:u"), MaxSessionsCount); + _serverManager.RegisterObjectForServer(audioSnoopManager, ServiceName.Encode("auddev"), MaxSessionsCount); } public void ServiceRequests() diff --git a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioSnoopManager.cs b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioSnoopManager.cs index cf1fe3d1d..5eb31a14b 100644 --- a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioSnoopManager.cs +++ b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioSnoopManager.cs @@ -1,30 +1,64 @@ using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Sdk.Sf; +using Ryujinx.Horizon.Sdk.Sf.Hipc; +using System; namespace Ryujinx.Horizon.Sdk.Audio.Detail { partial class AudioSnoopManager : IAudioSnoopManager { + private byte[] _dspStatisticsParameter; + // Note: The interface changed completely on firmware 17.0.0, this implementation is for older firmware. - [CmifCommand(0)] + [CmifCommand(0)] // [6.0.0-16.1.0] public Result EnableDspUsageMeasurement() { return Result.Success; } - [CmifCommand(1)] + [CmifCommand(1)] // [6.0.0-16.1.0] public Result DisableDspUsageMeasurement() { return Result.Success; } - - [CmifCommand(6)] + + [CmifCommand(6)] // [6.0.0-16.1.0] public Result GetDspUsage(out uint usage) { usage = 0; return Result.Success; } + + [CmifCommand(0)] // 17.0.0+ + public Result GetDspStatistics(out uint statistics) => GetDspUsage(out statistics); + + [CmifCommand(1)] // 20.0.0+ + public Result GetAppletStateSummaries([Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span summaries) + { + // Since we do not have any real applets, return empty state summaries. + summaries.Clear(); + + return Result.Success; + } + + [CmifCommand(2)] // 20.0.0+ + public Result SetDspStatisticsParameter([Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan parameter) + { + _dspStatisticsParameter = null; + _dspStatisticsParameter = new byte[0x100]; + parameter.CopyTo(_dspStatisticsParameter); + + return Result.Success; + } + + [CmifCommand(3)] // 20.0.0+ + public Result GetDspStatisticsParameter([Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span parameter) + { + _dspStatisticsParameter.CopyTo(parameter); + + return Result.Success; + } } } diff --git a/src/Ryujinx.Horizon/Sdk/Audio/Detail/IAudioSnoopManager.cs b/src/Ryujinx.Horizon/Sdk/Audio/Detail/IAudioSnoopManager.cs index 72853886a..9a52beb30 100644 --- a/src/Ryujinx.Horizon/Sdk/Audio/Detail/IAudioSnoopManager.cs +++ b/src/Ryujinx.Horizon/Sdk/Audio/Detail/IAudioSnoopManager.cs @@ -1,5 +1,6 @@ using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Sdk.Sf; +using System; namespace Ryujinx.Horizon.Sdk.Audio.Detail { @@ -8,5 +9,10 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail Result EnableDspUsageMeasurement(); Result DisableDspUsageMeasurement(); Result GetDspUsage(out uint usage); + + Result GetDspStatistics(out uint statistics); + Result GetAppletStateSummaries(Span summaries); + Result SetDspStatisticsParameter(ReadOnlySpan parameter); + Result GetDspStatisticsParameter(Span parameter); } } From 774ff0fda169f3c68ad6a7d73fb8b695ad0283a8 Mon Sep 17 00:00:00 2001 From: LotP1 <68976644+LotP1@users.noreply.github.com> Date: Thu, 4 Sep 2025 01:18:29 +0200 Subject: [PATCH 8/8] Fix a crash when no controller is connected --- .../Types/SharedMemory/Npad/NpadCondition.cs | 23 +++++++++++++++++++ .../Hid/Types/SharedMemory/SharedMemory.cs | 7 ++++++ 2 files changed, 30 insertions(+) create mode 100644 src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCondition.cs diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCondition.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCondition.cs new file mode 100644 index 000000000..813020188 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCondition.cs @@ -0,0 +1,23 @@ +namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad +{ + struct NpadCondition + { +#pragma warning disable CS0414 // Field is assigned but its value is never used + private uint _00; + private uint _04; + private NpadJoyHoldType _holdType; + private uint _0C; +#pragma warning restore CS0414 // Field is assigned but its value is never used + + public static NpadCondition Create() + { + return new NpadCondition() + { + _00 = 0, + _04 = 1, + _holdType = NpadJoyHoldType.Horizontal, + _0C = 1, + }; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs index adbbbc78b..1ac796407 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs @@ -52,6 +52,12 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory /// [FieldOffset(0x3DC00)] public RingLifo DebugMouse; + + /// + /// Pad Condition. + /// + [FieldOffset(0x3e200)] + public NpadCondition Condition; public static SharedMemory Create() { @@ -61,6 +67,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory TouchScreen = RingLifo.Create(), Mouse = RingLifo.Create(), Keyboard = RingLifo.Create(), + Condition = NpadCondition.Create(), }; Span npadsSpan = result.Npads.AsSpan();