SDK20 and REV15 support

* Fixed an issue where games would boot loop because of an incorrect HID state.

  * Turns out the SamplingNumber of the atomic input storage doesn't match the SamplingNumber of the input state held by the atomic storage, instead it is exactly double the value in the input state.

* Added new Condition struct to the HID Shared memory and populate it with dummy data to fix the no-controller crash (already merged).

* The audio renderer has been mostly updated to rev15, allowing rev15 games to launch.

  * Biquad filters now use floats.

  * Several structures have been renamed to match the SDK names, making it easier to compare functionality. A few names are still missing and will be changed at a later date.

  * The new commands from rev15 have been added to the CommandType enum, but they are still missing from the code itself.

    * Due to changes in the SDK layout, the time estimation functions are either missing or very well hidden (or Ghidra search functionality is useless). We can't fully implement the new commands until the timing data has been located.

  * A few minor tweaks to the code have been made to more accurately match the SDK.
This commit is contained in:
LotP
2025-10-27 08:50:57 -05:00
committed by KeatonTheBot
parent 41eb6f5dc4
commit 1ef09717d2
83 changed files with 2343 additions and 1195 deletions
@@ -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()
@@ -23,10 +23,10 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail
{
_registry = registry;
BehaviourContext behaviourContext = new();
behaviourContext.SetUserRevision((int)revision);
BehaviourInfo behaviourInfo = new();
behaviourInfo.SetUserRevision((int)revision);
_isUsbDeviceSupported = behaviourContext.IsAudioUsbDeviceOutputSupported();
_isUsbDeviceSupported = behaviourInfo.IsAudioUsbDeviceOutputSupported();
_sessions = registry.GetSessionByAppletResourceId(appletResourceId.Id);
Os.CreateSystemEvent(out _audioEvent, EventClearMode.AutoClear, interProcess: true);
@@ -60,7 +60,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail
[CmifCommand(1)]
public Result GetWorkBufferSize(out long workBufferSize, AudioRendererParameterInternal parameter)
{
if (BehaviourContext.CheckValidRevision(parameter.Configuration.Revision))
if (BehaviourInfo.CheckValidRevision(parameter.Configuration.Revision))
{
workBufferSize = (long)Ryujinx.Audio.Renderer.Server.AudioRendererManager.GetWorkBufferSize(ref parameter.Configuration);
@@ -72,7 +72,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail
{
workBufferSize = 0;
Logger.Warning?.Print(LogClass.ServiceAudio, $"Library Revision REV{BehaviourContext.GetRevisionNumber(parameter.Configuration.Revision)} is not supported!");
Logger.Warning?.Print(LogClass.ServiceAudio, $"Library Revision REV{BehaviourInfo.GetRevisionNumber(parameter.Configuration.Revision)} is not supported!");
return AudioResult.UnsupportedRevision;
}
@@ -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<byte> 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<byte> 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<byte> parameter)
{
_dspStatisticsParameter.CopyTo(parameter);
return Result.Success;
}
}
}
@@ -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<byte> summaries);
Result SetDspStatisticsParameter(ReadOnlySpan<byte> parameter);
Result GetDspStatisticsParameter(Span<byte> parameter);
}
}