diff --git a/Ryujinx.Audio/Renderer/Common/EffectType.cs b/Ryujinx.Audio/Renderer/Common/EffectType.cs
index 2c50b9eb0..7128db4ce 100644
--- a/Ryujinx.Audio/Renderer/Common/EffectType.cs
+++ b/Ryujinx.Audio/Renderer/Common/EffectType.cs
@@ -48,6 +48,11 @@ namespace Ryujinx.Audio.Renderer.Common
///
/// Effect to capture mixes (via auxiliary buffers).
///
- CaptureBuffer
+ CaptureBuffer,
+
+ ///
+ /// Effect applying a compressor filter (DRC).
+ ///
+ Compressor,
}
}
\ No newline at end of file
diff --git a/Ryujinx.Audio/Renderer/Common/PerformanceDetailType.cs b/Ryujinx.Audio/Renderer/Common/PerformanceDetailType.cs
index 8467ed8d7..805d55183 100644
--- a/Ryujinx.Audio/Renderer/Common/PerformanceDetailType.cs
+++ b/Ryujinx.Audio/Renderer/Common/PerformanceDetailType.cs
@@ -14,6 +14,7 @@ namespace Ryujinx.Audio.Renderer.Common
Reverb3d,
PcmFloat,
Limiter,
- CaptureBuffer
+ CaptureBuffer,
+ Compressor
}
}
\ No newline at end of file
diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs
index dfe7f8862..9ce181b17 100644
--- a/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs
+++ b/Ryujinx.Audio/Renderer/Dsp/Command/CommandType.cs
@@ -31,6 +31,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
LimiterVersion1,
LimiterVersion2,
GroupedBiquadFilter,
- CaptureBuffer
+ CaptureBuffer,
+ Compressor
}
}
\ No newline at end of file
diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs b/Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs
new file mode 100644
index 000000000..8c3442935
--- /dev/null
+++ b/Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs
@@ -0,0 +1,173 @@
+using System;
+using System.Diagnostics;
+using Ryujinx.Audio.Renderer.Dsp.Effect;
+using Ryujinx.Audio.Renderer.Dsp.State;
+using Ryujinx.Audio.Renderer.Parameter.Effect;
+
+namespace Ryujinx.Audio.Renderer.Dsp.Command
+{
+ public class CompressorCommand : ICommand
+ {
+ private const int FixedPointPrecision = 15;
+
+ public bool Enabled { get; set; }
+
+ public int NodeId { get; }
+
+ public CommandType CommandType => CommandType.Compressor;
+
+ public uint EstimatedProcessingTime { get; set; }
+
+ public CompressorParameter Parameter => _parameter;
+ public Memory State { get; }
+ public ushort[] OutputBufferIndices { get; }
+ public ushort[] InputBufferIndices { get; }
+ public bool IsEffectEnabled { get; }
+
+ private CompressorParameter _parameter;
+
+ public CompressorCommand(uint bufferOffset, CompressorParameter parameter, Memory state, bool isEnabled, int nodeId)
+ {
+ Enabled = true;
+ NodeId = nodeId;
+ _parameter = parameter;
+ State = state;
+
+ IsEffectEnabled = isEnabled;
+
+ InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
+ OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
+
+ for (int i = 0; i < _parameter.ChannelCount; i++)
+ {
+ InputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Input[i]);
+ OutputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Output[i]);
+ }
+ }
+
+ public void Process(CommandList context)
+ {
+ ref CompressorState state = ref State.Span[0];
+
+ if (IsEffectEnabled)
+ {
+ if (_parameter.Status == Server.Effect.UsageState.Invalid)
+ {
+ state = new CompressorState(ref _parameter);
+ }
+ else if (_parameter.Status == Server.Effect.UsageState.New)
+ {
+ state.UpdateParameter(ref _parameter);
+ }
+ }
+
+ ProcessCompressor(context, ref state);
+ }
+
+ private unsafe void ProcessCompressor(CommandList context, ref CompressorState state)
+ {
+ Debug.Assert(_parameter.IsChannelCountValid());
+
+ if (IsEffectEnabled && _parameter.IsChannelCountValid())
+ {
+ Span inputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
+ Span outputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
+ Span channelInput = stackalloc float[Parameter.ChannelCount];
+ ExponentialMovingAverage inputMovingAverage = state.InputMovingAverage;
+ float unknown4 = state.Unknown4;
+ ExponentialMovingAverage compressionGainAverage = state.CompressionGainAverage;
+ float previousCompressionEmaAlpha = state.PreviousCompressionEmaAlpha;
+
+ for (int i = 0; i < _parameter.ChannelCount; i++)
+ {
+ inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]);
+ outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]);
+ }
+
+ for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
+ {
+ for (int channelIndex = 0; channelIndex < _parameter.ChannelCount; channelIndex++)
+ {
+ channelInput[channelIndex] = *((float*)inputBuffers[channelIndex] + sampleIndex);
+ }
+
+ float newMean = inputMovingAverage.Update(FloatingPointHelper.MeanSquare(channelInput), _parameter.InputGain);
+ float y = FloatingPointHelper.Log10(newMean) * 10.0f;
+ float z = 0.0f;
+
+ bool unknown10OutOfRange = false;
+
+ if (newMean < 1.0e-10f)
+ {
+ z = 1.0f;
+
+ unknown10OutOfRange = state.Unknown10 < -100.0f;
+ }
+
+ if (y >= state.Unknown10 || unknown10OutOfRange)
+ {
+ float tmpGain;
+
+ if (y >= state.Unknown14)
+ {
+ tmpGain = ((1.0f / Parameter.Ratio) - 1.0f) * (y - Parameter.Threshold);
+ }
+ else
+ {
+ tmpGain = (y - state.Unknown10) * ((y - state.Unknown10) * -state.CompressorGainReduction);
+ }
+
+ z = FloatingPointHelper.DecibelToLinearExtended(tmpGain);
+ }
+
+ float unknown4New = z;
+ float compressionEmaAlpha;
+
+ if ((unknown4 - z) <= 0.08f)
+ {
+ compressionEmaAlpha = Parameter.ReleaseCoefficient;
+
+ if ((unknown4 - z) >= -0.08f)
+ {
+ if (MathF.Abs(compressionGainAverage.Read() - z) >= 0.001f)
+ {
+ unknown4New = unknown4;
+ }
+
+ compressionEmaAlpha = previousCompressionEmaAlpha;
+ }
+ }
+ else
+ {
+ compressionEmaAlpha = Parameter.AttackCoefficient;
+ }
+
+ float compressionGain = compressionGainAverage.Update(z, compressionEmaAlpha);
+
+ for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++)
+ {
+ *((float*)outputBuffers[channelIndex] + sampleIndex) = channelInput[channelIndex] * compressionGain * state.OutputGain;
+ }
+
+ unknown4 = unknown4New;
+ previousCompressionEmaAlpha = compressionEmaAlpha;
+ }
+
+ state.InputMovingAverage = inputMovingAverage;
+ state.Unknown4 = unknown4;
+ state.CompressionGainAverage = compressionGainAverage;
+ state.PreviousCompressionEmaAlpha = previousCompressionEmaAlpha;
+ }
+ else
+ {
+ for (int i = 0; i < Parameter.ChannelCount; i++)
+ {
+ if (InputBufferIndices[i] != OutputBufferIndices[i])
+ {
+ context.CopyBuffer(OutputBufferIndices[i], InputBufferIndices[i]);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs b/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs
index 9cfef736e..a464ad704 100644
--- a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs
+++ b/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs
@@ -90,32 +90,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
float inputCoefficient = Parameter.ReleaseCoefficient;
- if (sampleInputMax > state.DectectorAverage[channelIndex])
+ if (sampleInputMax > state.DetectorAverage[channelIndex].Read())
{
inputCoefficient = Parameter.AttackCoefficient;
}
- state.DectectorAverage[channelIndex] += inputCoefficient * (sampleInputMax - state.DectectorAverage[channelIndex]);
-
+ float detectorValue = state.DetectorAverage[channelIndex].Update(sampleInputMax, inputCoefficient);
float attenuation = 1.0f;
- if (state.DectectorAverage[channelIndex] > Parameter.Threshold)
+ if (detectorValue > Parameter.Threshold)
{
- attenuation = Parameter.Threshold / state.DectectorAverage[channelIndex];
+ attenuation = Parameter.Threshold / detectorValue;
}
float outputCoefficient = Parameter.ReleaseCoefficient;
- if (state.CompressionGain[channelIndex] > attenuation)
+ if (state.CompressionGainAverage[channelIndex].Read() > attenuation)
{
outputCoefficient = Parameter.AttackCoefficient;
}
- state.CompressionGain[channelIndex] += outputCoefficient * (attenuation - state.CompressionGain[channelIndex]);
+ float compressionGain = state.CompressionGainAverage[channelIndex].Update(attenuation, outputCoefficient);
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
- float outputSample = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain;
+ float outputSample = delayedSample * compressionGain * Parameter.OutputGain;
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
diff --git a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs b/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs
index 46c95e4f9..950de97b8 100644
--- a/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs
+++ b/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs
@@ -101,32 +101,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
float inputCoefficient = Parameter.ReleaseCoefficient;
- if (sampleInputMax > state.DectectorAverage[channelIndex])
+ if (sampleInputMax > state.DetectorAverage[channelIndex].Read())
{
inputCoefficient = Parameter.AttackCoefficient;
}
- state.DectectorAverage[channelIndex] += inputCoefficient * (sampleInputMax - state.DectectorAverage[channelIndex]);
-
+ float detectorValue = state.DetectorAverage[channelIndex].Update(sampleInputMax, inputCoefficient);
float attenuation = 1.0f;
- if (state.DectectorAverage[channelIndex] > Parameter.Threshold)
+ if (detectorValue > Parameter.Threshold)
{
- attenuation = Parameter.Threshold / state.DectectorAverage[channelIndex];
+ attenuation = Parameter.Threshold / detectorValue;
}
float outputCoefficient = Parameter.ReleaseCoefficient;
- if (state.CompressionGain[channelIndex] > attenuation)
+ if (state.CompressionGainAverage[channelIndex].Read() > attenuation)
{
outputCoefficient = Parameter.AttackCoefficient;
}
- state.CompressionGain[channelIndex] += outputCoefficient * (attenuation - state.CompressionGain[channelIndex]);
+ float compressionGain = state.CompressionGainAverage[channelIndex].Update(attenuation, outputCoefficient);
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
- float outputSample = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain;
+ float outputSample = delayedSample * compressionGain * Parameter.OutputGain;
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
@@ -144,7 +143,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ref LimiterStatistics statistics = ref MemoryMarshal.Cast(ResultState.Span[0].SpecificData)[0];
statistics.InputMax[channelIndex] = Math.Max(statistics.InputMax[channelIndex], sampleInputMax);
- statistics.CompressionGainMin[channelIndex] = Math.Min(statistics.CompressionGainMin[channelIndex], state.CompressionGain[channelIndex]);
+ statistics.CompressionGainMin[channelIndex] = Math.Min(statistics.CompressionGainMin[channelIndex], compressionGain);
}
}
}
diff --git a/Ryujinx.Audio/Renderer/Dsp/Effect/ExponentialMovingAverage.cs b/Ryujinx.Audio/Renderer/Dsp/Effect/ExponentialMovingAverage.cs
new file mode 100644
index 000000000..78e46bf96
--- /dev/null
+++ b/Ryujinx.Audio/Renderer/Dsp/Effect/ExponentialMovingAverage.cs
@@ -0,0 +1,26 @@
+using System.Runtime.CompilerServices;
+
+namespace Ryujinx.Audio.Renderer.Dsp.Effect
+{
+ public struct ExponentialMovingAverage
+ {
+ private float _mean;
+
+ public ExponentialMovingAverage(float mean)
+ {
+ _mean = mean;
+ }
+
+ public float Read()
+ {
+ return _mean;
+ }
+
+ public float Update(float value, float alpha)
+ {
+ _mean += alpha * (value - _mean);
+
+ return _mean;
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Renderer/Dsp/FixedPointHelper.cs b/Ryujinx.Audio/Renderer/Dsp/FixedPointHelper.cs
index 0d0ff2ae6..280e47c0c 100644
--- a/Ryujinx.Audio/Renderer/Dsp/FixedPointHelper.cs
+++ b/Ryujinx.Audio/Renderer/Dsp/FixedPointHelper.cs
@@ -16,6 +16,12 @@ namespace Ryujinx.Audio.Renderer.Dsp
return (float)value / (1 << qBits);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float ConvertFloat(float value, int qBits)
+ {
+ return value / (1 << qBits);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ToFixed(float value, int qBits)
{
diff --git a/Ryujinx.Audio/Renderer/Dsp/FloatingPointHelper.cs b/Ryujinx.Audio/Renderer/Dsp/FloatingPointHelper.cs
index 226def46a..6645e20a3 100644
--- a/Ryujinx.Audio/Renderer/Dsp/FloatingPointHelper.cs
+++ b/Ryujinx.Audio/Renderer/Dsp/FloatingPointHelper.cs
@@ -1,4 +1,5 @@
using System;
+using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp
@@ -46,6 +47,53 @@ namespace Ryujinx.Audio.Renderer.Dsp
return MathF.Pow(10, x);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Log10(float x)
+ {
+ // NOTE: Nintendo uses an approximation of log10, we don't.
+ // As such, we support the same ranges as Nintendo to avoid unexpected behaviours.
+ return MathF.Pow(10, MathF.Max(x, 1.0e-10f));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float MeanSquare(ReadOnlySpan inputs)
+ {
+ float res = 0.0f;
+
+ foreach (float input in inputs)
+ {
+ res += (input * input);
+ }
+
+ res /= inputs.Length;
+
+ return res;
+ }
+
+ ///
+ /// Map decibel to linear.
+ ///
+ /// The decibel value to convert
+ /// Converted linear value/returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float DecibelToLinear(float db)
+ {
+ return MathF.Pow(10.0f, db / 20.0f);
+ }
+
+ ///
+ /// Map decibel to linear in [0, 2] range.
+ ///
+ /// The decibel value to convert
+ /// Converted linear value in [0, 2] range
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float DecibelToLinearExtended(float db)
+ {
+ float tmp = MathF.Log2(DecibelToLinear(db));
+
+ return MathF.Truncate(tmp) + MathF.Pow(2.0f, tmp - MathF.Truncate(tmp));
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float DegreesToRadians(float degrees)
{
diff --git a/Ryujinx.Audio/Renderer/Dsp/State/CompressorState.cs b/Ryujinx.Audio/Renderer/Dsp/State/CompressorState.cs
new file mode 100644
index 000000000..76aff8072
--- /dev/null
+++ b/Ryujinx.Audio/Renderer/Dsp/State/CompressorState.cs
@@ -0,0 +1,51 @@
+using Ryujinx.Audio.Renderer.Dsp.Effect;
+using Ryujinx.Audio.Renderer.Parameter.Effect;
+
+namespace Ryujinx.Audio.Renderer.Dsp.State
+{
+ public class CompressorState
+ {
+ public ExponentialMovingAverage InputMovingAverage;
+ public float Unknown4;
+ public ExponentialMovingAverage CompressionGainAverage;
+ public float CompressorGainReduction;
+ public float Unknown10;
+ public float Unknown14;
+ public float PreviousCompressionEmaAlpha;
+ public float MakeupGain;
+ public float OutputGain;
+
+ public CompressorState(ref CompressorParameter parameter)
+ {
+ InputMovingAverage = new ExponentialMovingAverage(0.0f);
+ Unknown4 = 1.0f;
+ CompressionGainAverage = new ExponentialMovingAverage(1.0f);
+
+ UpdateParameter(ref parameter);
+ }
+
+ public void UpdateParameter(ref CompressorParameter parameter)
+ {
+ float threshold = parameter.Threshold;
+ float ratio = 1.0f / parameter.Ratio;
+ float attackCoefficient = parameter.AttackCoefficient;
+ float makeupGain;
+
+ if (parameter.MakeupGainEnabled)
+ {
+ makeupGain = (threshold * 0.5f * (ratio - 1.0f)) - 3.0f;
+ }
+ else
+ {
+ makeupGain = 0.0f;
+ }
+
+ PreviousCompressionEmaAlpha = attackCoefficient;
+ MakeupGain = makeupGain;
+ CompressorGainReduction = (1.0f - ratio) / Constants.ChannelCountMax;
+ Unknown10 = threshold - 1.5f;
+ Unknown14 = threshold + 1.5f;
+ OutputGain = FloatingPointHelper.DecibelToLinearExtended(parameter.OutputGain + makeupGain);
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Renderer/Dsp/State/LimiterState.cs b/Ryujinx.Audio/Renderer/Dsp/State/LimiterState.cs
index 92ed13fff..0560757c9 100644
--- a/Ryujinx.Audio/Renderer/Dsp/State/LimiterState.cs
+++ b/Ryujinx.Audio/Renderer/Dsp/State/LimiterState.cs
@@ -1,3 +1,4 @@
+using Ryujinx.Audio.Renderer.Dsp.Effect;
using Ryujinx.Audio.Renderer.Parameter.Effect;
using System;
@@ -5,20 +6,20 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
{
public class LimiterState
{
- public float[] DectectorAverage;
- public float[] CompressionGain;
+ public ExponentialMovingAverage[] DetectorAverage;
+ public ExponentialMovingAverage[] CompressionGainAverage;
public float[] DelayedSampleBuffer;
public int[] DelayedSampleBufferPosition;
public LimiterState(ref LimiterParameter parameter, ulong workBuffer)
{
- DectectorAverage = new float[parameter.ChannelCount];
- CompressionGain = new float[parameter.ChannelCount];
+ DetectorAverage = new ExponentialMovingAverage[parameter.ChannelCount];
+ CompressionGainAverage = new ExponentialMovingAverage[parameter.ChannelCount];
DelayedSampleBuffer = new float[parameter.ChannelCount * parameter.DelayBufferSampleCountMax];
DelayedSampleBufferPosition = new int[parameter.ChannelCount];
- DectectorAverage.AsSpan().Fill(0.0f);
- CompressionGain.AsSpan().Fill(1.0f);
+ DetectorAverage.AsSpan().Fill(new ExponentialMovingAverage(0.0f));
+ CompressionGainAverage.AsSpan().Fill(new ExponentialMovingAverage(1.0f));
DelayedSampleBufferPosition.AsSpan().Fill(0);
DelayedSampleBuffer.AsSpan().Fill(0.0f);
diff --git a/Ryujinx.Audio/Renderer/Parameter/Effect/CompressorParameter.cs b/Ryujinx.Audio/Renderer/Parameter/Effect/CompressorParameter.cs
new file mode 100644
index 000000000..0be376088
--- /dev/null
+++ b/Ryujinx.Audio/Renderer/Parameter/Effect/CompressorParameter.cs
@@ -0,0 +1,115 @@
+using Ryujinx.Audio.Renderer.Server.Effect;
+using Ryujinx.Common.Memory;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Audio.Renderer.Parameter.Effect
+{
+ ///
+ /// for .
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct CompressorParameter
+ {
+ ///
+ /// The input channel indices that will be used by the .
+ ///
+ public Array6 Input;
+
+ ///
+ /// The output channel indices that will be used by the .
+ ///
+ public Array6 Output;
+
+ ///
+ /// The maximum number of channels supported.
+ ///
+ public ushort ChannelCountMax;
+
+ ///
+ /// The total channel count used.
+ ///
+ public ushort ChannelCount;
+
+ ///
+ /// The target sample rate.
+ ///
+ /// This is in kHz.
+ public int SampleRate;
+
+ ///
+ /// The threshold.
+ ///
+ public float Threshold;
+
+ ///
+ /// The compressor ratio.
+ ///
+ public float Ratio;
+
+ ///
+ /// The attack time.
+ /// This is in microseconds.
+ ///
+ public int AttackTime;
+
+ ///
+ /// The release time.
+ /// This is in microseconds.
+ ///
+ public int ReleaseTime;
+
+ ///
+ /// The input gain.
+ ///
+ public float InputGain;
+
+ ///
+ /// The attack coefficient.
+ ///
+ public float AttackCoefficient;
+
+ ///
+ /// The release coefficient.
+ ///
+ public float ReleaseCoefficient;
+
+ ///
+ /// The output gain.
+ ///
+ public float OutputGain;
+
+ ///
+ /// The current usage status of the effect on the client side.
+ ///
+ public UsageState Status;
+
+ ///
+ /// Indicate if the makeup gain should be used.
+ ///
+ [MarshalAs(UnmanagedType.I1)]
+ public bool MakeupGainEnabled;
+
+ ///
+ /// Reserved/padding.
+ ///
+ private Array2 _reserved;
+
+ ///
+ /// Check if the is valid.
+ ///
+ /// Returns true if the is valid.
+ public bool IsChannelCountValid()
+ {
+ return EffectInParameterVersion1.IsChannelCountValid(ChannelCount);
+ }
+
+ ///
+ /// Check if the is valid.
+ ///
+ /// Returns true if the is valid.
+ public bool IsChannelCountMaxValid()
+ {
+ return EffectInParameterVersion1.IsChannelCountValid(ChannelCountMax);
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs b/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs
index adf5294ea..821947a98 100644
--- a/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs
+++ b/Ryujinx.Audio/Renderer/Server/BehaviourContext.cs
@@ -44,7 +44,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// was added to supply the count of update done sent to the DSP.
/// A new version of the command estimator was added to address timing changes caused by the voice changes.
/// Additionally, the rendering limit percent was incremented to 80%.
- ///
+ ///
///
/// This was added in system update 6.0.0
public const int Revision5 = 5 << 24;
@@ -93,6 +93,7 @@ namespace Ryujinx.Audio.Renderer.Server
///
/// REV11:
/// The "legacy" effects (Delay, Reverb and Reverb 3D) were updated to match the standard channel mapping used by the audio renderer.
+ /// A new effect was added: Compressor. This effect is effectively implemented with a DRC.
/// A new version of the command estimator was added to address timing changes caused by the legacy effects changes.
/// A voice drop parameter was added in 15.0.0: This allows an application to amplify or attenuate the estimated time of DSP commands.
///
diff --git a/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs b/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs
index e0741cc6e..905cb2054 100644
--- a/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs
+++ b/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs
@@ -469,6 +469,18 @@ namespace Ryujinx.Audio.Renderer.Server
}
}
+ public void GenerateCompressorEffect(uint bufferOffset, CompressorParameter parameter, Memory state, bool isEnabled, int nodeId)
+ {
+ if (parameter.IsChannelCountValid())
+ {
+ CompressorCommand command = new CompressorCommand(bufferOffset, parameter, state, isEnabled, nodeId);
+
+ command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
+
+ AddCommand(command);
+ }
+ }
+
///
/// Generate a new .
///
diff --git a/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs b/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs
index 87e5c77f9..afc1e39b7 100644
--- a/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs
+++ b/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs
@@ -606,6 +606,17 @@ namespace Ryujinx.Audio.Renderer.Server
}
}
+ private void GenerateCompressorEffect(uint bufferOffset, CompressorEffect effect, int nodeId)
+ {
+ Debug.Assert(effect.Type == EffectType.Compressor);
+
+ _commandBuffer.GenerateCompressorEffect(bufferOffset,
+ effect.Parameter,
+ effect.State,
+ effect.IsEnabled,
+ nodeId);
+ }
+
private void GenerateEffect(ref MixState mix, int effectId, BaseEffect effect)
{
int nodeId = mix.NodeId;
@@ -650,6 +661,9 @@ namespace Ryujinx.Audio.Renderer.Server
case EffectType.CaptureBuffer:
GenerateCaptureEffect(mix.BufferOffset, (CaptureBufferEffect)effect, nodeId);
break;
+ case EffectType.Compressor:
+ GenerateCompressorEffect(mix.BufferOffset, (CompressorEffect)effect, nodeId);
+ break;
default:
throw new NotImplementedException($"Unsupported effect type {effect.Type}");
}
diff --git a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion1.cs b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion1.cs
index 32c52dc43..63dc9ca96 100644
--- a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion1.cs
+++ b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion1.cs
@@ -179,5 +179,10 @@ namespace Ryujinx.Audio.Renderer.Server
{
return 0;
}
+
+ public uint Estimate(CompressorCommand command)
+ {
+ return 0;
+ }
}
}
\ No newline at end of file
diff --git a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs
index 15800c993..7ee491cd6 100644
--- a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs
+++ b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs
@@ -543,5 +543,10 @@ namespace Ryujinx.Audio.Renderer.Server
{
return 0;
}
+
+ public uint Estimate(CompressorCommand command)
+ {
+ return 0;
+ }
}
}
\ No newline at end of file
diff --git a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs
index 6c6e2828c..b79ca1369 100644
--- a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs
+++ b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs
@@ -747,5 +747,10 @@ namespace Ryujinx.Audio.Renderer.Server
{
return 0;
}
+
+ public virtual uint Estimate(CompressorCommand command)
+ {
+ return 0;
+ }
}
}
\ No newline at end of file
diff --git a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs
index 961d92aa6..2ed7e6a5b 100644
--- a/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs
+++ b/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs
@@ -232,5 +232,79 @@ namespace Ryujinx.Audio.Renderer.Server
}
}
}
+
+ public override uint Estimate(CompressorCommand command)
+ {
+ Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
+
+ if (_sampleCount == 160)
+ {
+ if (command.Enabled)
+ {
+ switch (command.Parameter.ChannelCount)
+ {
+ case 1:
+ return 34431;
+ case 2:
+ return 44253;
+ case 4:
+ return 63827;
+ case 6:
+ return 83361;
+ default:
+ throw new NotImplementedException($"{command.Parameter.ChannelCount}");
+ }
+ }
+ else
+ {
+ switch (command.Parameter.ChannelCount)
+ {
+ case 1:
+ return (uint)630.12f;
+ case 2:
+ return (uint)638.27f;
+ case 4:
+ return (uint)705.86f;
+ case 6:
+ return (uint)782.02f;
+ default:
+ throw new NotImplementedException($"{command.Parameter.ChannelCount}");
+ }
+ }
+ }
+
+ if (command.Enabled)
+ {
+ switch (command.Parameter.ChannelCount)
+ {
+ case 1:
+ return 51095;
+ case 2:
+ return 65693;
+ case 4:
+ return 95383;
+ case 6:
+ return 124510;
+ default:
+ throw new NotImplementedException($"{command.Parameter.ChannelCount}");
+ }
+ }
+ else
+ {
+ switch (command.Parameter.ChannelCount)
+ {
+ case 1:
+ return (uint)840.14f;
+ case 2:
+ return (uint)826.1f;
+ case 4:
+ return (uint)901.88f;
+ case 6:
+ return (uint)965.29f;
+ default:
+ throw new NotImplementedException($"{command.Parameter.ChannelCount}");
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs b/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs
index 35314aca5..825b3bf76 100644
--- a/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs
+++ b/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs
@@ -262,6 +262,8 @@ namespace Ryujinx.Audio.Renderer.Server.Effect
return PerformanceDetailType.Limiter;
case EffectType.CaptureBuffer:
return PerformanceDetailType.CaptureBuffer;
+ case EffectType.Compressor:
+ return PerformanceDetailType.Compressor;
default:
throw new NotImplementedException($"{Type}");
}
diff --git a/Ryujinx.Audio/Renderer/Server/Effect/CompressorEffect.cs b/Ryujinx.Audio/Renderer/Server/Effect/CompressorEffect.cs
new file mode 100644
index 000000000..f4e5ae829
--- /dev/null
+++ b/Ryujinx.Audio/Renderer/Server/Effect/CompressorEffect.cs
@@ -0,0 +1,67 @@
+using Ryujinx.Audio.Renderer.Common;
+using Ryujinx.Audio.Renderer.Dsp.State;
+using Ryujinx.Audio.Renderer.Parameter.Effect;
+using Ryujinx.Audio.Renderer.Parameter;
+using Ryujinx.Audio.Renderer.Server.MemoryPool;
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Audio.Renderer.Server.Effect
+{
+ ///
+ /// Server state for a compressor effect.
+ ///
+ public class CompressorEffect : BaseEffect
+ {
+ ///
+ /// The compressor parameter.
+ ///
+ public CompressorParameter Parameter;
+
+ ///
+ /// The compressor state.
+ ///
+ public Memory State { get; }
+
+ ///
+ /// Create a new .
+ ///
+ public CompressorEffect()
+ {
+ State = new CompressorState[1];
+ }
+
+ public override EffectType TargetEffectType => EffectType.Compressor;
+
+ public override ulong GetWorkBuffer(int index)
+ {
+ return GetSingleBuffer();
+ }
+
+ public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameterVersion1 parameter, PoolMapper mapper)
+ {
+ // Nintendo doesn't do anything here but we still require updateErrorInfo to be initialised.
+ updateErrorInfo = new BehaviourParameter.ErrorInfo();
+ }
+
+ public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameterVersion2 parameter, PoolMapper mapper)
+ {
+ Debug.Assert(IsTypeValid(ref parameter));
+
+ UpdateParameterBase(ref parameter);
+
+ Parameter = MemoryMarshal.Cast(parameter.SpecificData)[0];
+ IsEnabled = parameter.IsEnabled;
+
+ updateErrorInfo = new BehaviourParameter.ErrorInfo();
+ }
+
+ public override void UpdateForCommandGeneration()
+ {
+ UpdateUsageStateForCommandGeneration();
+
+ Parameter.Status = UsageState.Enabled;
+ }
+ }
+}
diff --git a/Ryujinx.Audio/Renderer/Server/ICommandProcessingTimeEstimator.cs b/Ryujinx.Audio/Renderer/Server/ICommandProcessingTimeEstimator.cs
index e365a86c0..4872ddb3a 100644
--- a/Ryujinx.Audio/Renderer/Server/ICommandProcessingTimeEstimator.cs
+++ b/Ryujinx.Audio/Renderer/Server/ICommandProcessingTimeEstimator.cs
@@ -35,5 +35,6 @@ namespace Ryujinx.Audio.Renderer.Server
uint Estimate(LimiterCommandVersion2 command);
uint Estimate(GroupedBiquadFilterCommand command);
uint Estimate(CaptureBufferCommand command);
+ uint Estimate(CompressorCommand command);
}
}
\ No newline at end of file
diff --git a/Ryujinx.Audio/Renderer/Server/StateUpdater.cs b/Ryujinx.Audio/Renderer/Server/StateUpdater.cs
index 0c2cfa7ea..0446cd8c6 100644
--- a/Ryujinx.Audio/Renderer/Server/StateUpdater.cs
+++ b/Ryujinx.Audio/Renderer/Server/StateUpdater.cs
@@ -240,6 +240,10 @@ namespace Ryujinx.Audio.Renderer.Server
case EffectType.CaptureBuffer:
effect = new CaptureBufferEffect();
break;
+ case EffectType.Compressor:
+ effect = new CompressorEffect();
+ break;
+
default:
throw new NotImplementedException($"EffectType {parameter.Type} not implemented!");
}
diff --git a/Ryujinx.Ava/Assets/Locales/de_DE.json b/Ryujinx.Ava/Assets/Locales/de_DE.json
index fd151eb52..d2b3b6587 100644
--- a/Ryujinx.Ava/Assets/Locales/de_DE.json
+++ b/Ryujinx.Ava/Assets/Locales/de_DE.json
@@ -157,11 +157,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Aktiviere Fs Zugriff-Logs",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs Globaler Zugriff-Log-Modus:",
"SettingsTabLoggingDeveloperOptions": "Entwickleroptionen (WARNUNG: Beeinträchtigt die Leistung)",
- "SettingsTabLoggingOpenglLogLevel": "OpenGL Logstufe:",
- "SettingsTabLoggingOpenglLogLevelNone": "Keine",
- "SettingsTabLoggingOpenglLogLevelError": "Fehler",
- "SettingsTabLoggingOpenglLogLevelPerformance": "Verlangsamungen",
- "SettingsTabLoggingOpenglLogLevelAll": "Alle",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "Keine",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "Fehler",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Verlangsamungen",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "Alle",
"SettingsTabLoggingEnableDebugLogs": "Aktiviere Debug-Log",
"SettingsTabInput": "Eingabe",
"SettingsTabInputEnableDockedMode": "Docked Modus",
diff --git a/Ryujinx.Ava/Assets/Locales/el_GR.json b/Ryujinx.Ava/Assets/Locales/el_GR.json
index 31c397902..31d489744 100644
--- a/Ryujinx.Ava/Assets/Locales/el_GR.json
+++ b/Ryujinx.Ava/Assets/Locales/el_GR.json
@@ -157,11 +157,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Ενεργοποίηση Καταγραφής Πρόσβασης FS",
"SettingsTabLoggingFsGlobalAccessLogMode": "Λειτουργία Καταγραφής Καθολικής Πρόσβασης FS:",
"SettingsTabLoggingDeveloperOptions": "Επιλογές Προγραμματιστή (ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Η απόδοση Θα μειωθεί)",
- "SettingsTabLoggingOpenglLogLevel": "Επίπεδο Καταγραφής OpenGL:",
- "SettingsTabLoggingOpenglLogLevelNone": "Κανένα",
- "SettingsTabLoggingOpenglLogLevelError": "Σφάλμα",
- "SettingsTabLoggingOpenglLogLevelPerformance": "Επιβραδύνσεις",
- "SettingsTabLoggingOpenglLogLevelAll": "Όλα",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "Κανένα",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "Σφάλμα",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Επιβραδύνσεις",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "Όλα",
"SettingsTabLoggingEnableDebugLogs": "Ενεργοποίηση Αρχείων Καταγραφής Εντοπισμού Σφαλμάτων",
"SettingsTabInput": "Χειρισμός",
"SettingsTabInputEnableDockedMode": "Ενεργοποίηση Docked Mode",
diff --git a/Ryujinx.Ava/Assets/Locales/en_US.json b/Ryujinx.Ava/Assets/Locales/en_US.json
index be3071cc9..aa49a78f0 100644
--- a/Ryujinx.Ava/Assets/Locales/en_US.json
+++ b/Ryujinx.Ava/Assets/Locales/en_US.json
@@ -157,11 +157,11 @@
"SettingsTabLoggingEnableFsAccessLogs": "Enable Fs Access Logs",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs Global Access Log Mode:",
"SettingsTabLoggingDeveloperOptions": "Developer Options (WARNING: Will reduce performance)",
- "SettingsTabLoggingOpenglLogLevel": "OpenGL Log Level:",
- "SettingsTabLoggingOpenglLogLevelNone": "None",
- "SettingsTabLoggingOpenglLogLevelError": "Error",
- "SettingsTabLoggingOpenglLogLevelPerformance": "Slowdowns",
- "SettingsTabLoggingOpenglLogLevelAll": "All",
+ "SettingsTabLoggingGraphicsBackendLogLevel": "Graphics Backend Log Level:",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "None",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "Error",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Slowdowns",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "All",
"SettingsTabLoggingEnableDebugLogs": "Enable Debug Logs",
"SettingsTabInput": "Input",
"SettingsTabInputEnableDockedMode": "Docked Mode",
diff --git a/Ryujinx.Ava/Assets/Locales/es_ES.json b/Ryujinx.Ava/Assets/Locales/es_ES.json
index 8c74be4f6..d095e5ea1 100644
--- a/Ryujinx.Ava/Assets/Locales/es_ES.json
+++ b/Ryujinx.Ava/Assets/Locales/es_ES.json
@@ -157,11 +157,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Habilitar registros de Fs Access",
"SettingsTabLoggingFsGlobalAccessLogMode": "Modo de registros Fs Global Access:",
"SettingsTabLoggingDeveloperOptions": "Opciones de desarrollador (ADVERTENCIA: empeorarán el rendimiento)",
- "SettingsTabLoggingOpenglLogLevel": "Nivel de registro de OpenGL:",
- "SettingsTabLoggingOpenglLogLevelNone": "Nada",
- "SettingsTabLoggingOpenglLogLevelError": "Errores",
- "SettingsTabLoggingOpenglLogLevelPerformance": "Ralentizaciones",
- "SettingsTabLoggingOpenglLogLevelAll": "Todo",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "Nada",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "Errores",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Ralentizaciones",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "Todo",
"SettingsTabLoggingEnableDebugLogs": "Habilitar registros de debug",
"SettingsTabInput": "Entrada",
"SettingsTabInputEnableDockedMode": "Modo dock/TV",
diff --git a/Ryujinx.Ava/Assets/Locales/fr_FR.json b/Ryujinx.Ava/Assets/Locales/fr_FR.json
index 396746cfc..8c8d2d056 100644
--- a/Ryujinx.Ava/Assets/Locales/fr_FR.json
+++ b/Ryujinx.Ava/Assets/Locales/fr_FR.json
@@ -150,11 +150,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Activer les journaux des accès au système de fichiers",
"SettingsTabLoggingFsGlobalAccessLogMode": "Niveau des journaux des accès au système de fichiers:",
"SettingsTabLoggingDeveloperOptions": "Options développeur (ATTENTION: Cela peut réduire les performances)",
- "SettingsTabLoggingOpenglLogLevel": "Niveau des journaux OpenGL:",
- "SettingsTabLoggingOpenglLogLevelNone": "Aucun",
- "SettingsTabLoggingOpenglLogLevelError": "Erreur",
- "SettingsTabLoggingOpenglLogLevelPerformance": "Ralentissements",
- "SettingsTabLoggingOpenglLogLevelAll": "Tout",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "Aucun",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "Erreur",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Ralentissements",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "Tout",
"SettingsTabLoggingEnableDebugLogs": "Activer les journaux de debug",
"SettingsTabInput": "Contrôles",
"SettingsTabInputEnableDockedMode": "Active le mode station d'accueil",
diff --git a/Ryujinx.Ava/Assets/Locales/it_IT.json b/Ryujinx.Ava/Assets/Locales/it_IT.json
index 52154fde1..a3ec683f3 100644
--- a/Ryujinx.Ava/Assets/Locales/it_IT.json
+++ b/Ryujinx.Ava/Assets/Locales/it_IT.json
@@ -157,11 +157,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Attiva Fs Access Logs",
"SettingsTabLoggingFsGlobalAccessLogMode": "Modalità log accesso globale Fs:",
"SettingsTabLoggingDeveloperOptions": "Opzioni da sviluppatore (AVVISO: Ridurrà le prestazioni)",
- "SettingsTabLoggingOpenglLogLevel": "Livello di log OpenGL:",
- "SettingsTabLoggingOpenglLogLevelNone": "Nessuno",
- "SettingsTabLoggingOpenglLogLevelError": "Errore",
- "SettingsTabLoggingOpenglLogLevelPerformance": "Rallentamenti",
- "SettingsTabLoggingOpenglLogLevelAll": "Tutto",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "Nessuno",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "Errore",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Rallentamenti",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "Tutto",
"SettingsTabLoggingEnableDebugLogs": "Attiva logs di debug",
"SettingsTabInput": "Input",
"SettingsTabInputEnableDockedMode": "Attiva modalità TV",
@@ -558,8 +557,8 @@
"SettingsSelectThemeFileDialogTitle" : "Seleziona file del tema",
"SettingsXamlThemeFile" : "File del tema xaml",
"SettingsTabHotkeysResScaleUpHotkey": "Aumentare la risoluzione:",
- "SettingsTabHotkeysResScaleDownHotkey": "Diminuire la risoluzione:"
- "AvatarWindowTitle": "Gestisci account - Avatar"
+ "SettingsTabHotkeysResScaleDownHotkey": "Diminuire la risoluzione:",
+ "AvatarWindowTitle": "Gestisci account - Avatar",
"Amiibo": "Amiibo",
"Unknown": "Sconosciuto",
"Usage": "Utilizzo",
diff --git a/Ryujinx.Ava/Assets/Locales/ja_JP.json b/Ryujinx.Ava/Assets/Locales/ja_JP.json
index ef9eea894..571f098f6 100644
--- a/Ryujinx.Ava/Assets/Locales/ja_JP.json
+++ b/Ryujinx.Ava/Assets/Locales/ja_JP.json
@@ -157,11 +157,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Fs アクセスログを有効",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs グローバルアクセスログモード:",
"SettingsTabLoggingDeveloperOptions": "開発者オプション (警告: パフォーマンスが低下します)",
- "SettingsTabLoggingOpenglLogLevel": "OpenGL ログレベル:",
- "SettingsTabLoggingOpenglLogLevelNone": "なし",
- "SettingsTabLoggingOpenglLogLevelError": "エラー",
- "SettingsTabLoggingOpenglLogLevelPerformance": "パフォーマンス低下",
- "SettingsTabLoggingOpenglLogLevelAll": "すべて",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "なし",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "エラー",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "パフォーマンス低下",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "すべて",
"SettingsTabLoggingEnableDebugLogs": "デバッグログを有効",
"SettingsTabInput": "入力",
"SettingsTabInputEnableDockedMode": "ドッキングモード",
diff --git a/Ryujinx.Ava/Assets/Locales/ko_KR.json b/Ryujinx.Ava/Assets/Locales/ko_KR.json
index 72650d638..3b6cfc427 100644
--- a/Ryujinx.Ava/Assets/Locales/ko_KR.json
+++ b/Ryujinx.Ava/Assets/Locales/ko_KR.json
@@ -156,11 +156,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Fs 액세스 로그 켜기",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs 전역 액세스 로그 모드 :",
"SettingsTabLoggingDeveloperOptions": "개발자 옵션 (경고 : 성능이 저하됩니다.)",
- "SettingsTabLoggingOpenglLogLevel": "OpenGL 로그 수준 :",
- "SettingsTabLoggingOpenglLogLevelNone": "없음",
- "SettingsTabLoggingOpenglLogLevelError": "오류",
- "SettingsTabLoggingOpenglLogLevelPerformance": "감속",
- "SettingsTabLoggingOpenglLogLevelAll": "모두",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "없음",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "오류",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "감속",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "모두",
"SettingsTabLoggingEnableDebugLogs": "디버그 로그 사용",
"SettingsTabInput": "입력",
"SettingsTabInputEnableDockedMode": "도킹 모드 활성화",
diff --git a/Ryujinx.Ava/Assets/Locales/pl_PL.json b/Ryujinx.Ava/Assets/Locales/pl_PL.json
index 544548122..7a376be7d 100644
--- a/Ryujinx.Ava/Assets/Locales/pl_PL.json
+++ b/Ryujinx.Ava/Assets/Locales/pl_PL.json
@@ -157,11 +157,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Włącz Logi Dostępu do Systemu Plików",
"SettingsTabLoggingFsGlobalAccessLogMode": "Tryb Globalnych Logów Systemu Plików:",
"SettingsTabLoggingDeveloperOptions": "Opcje programistyczne (OSTRZEŻENIE: Zmniejszą wydajność)",
- "SettingsTabLoggingOpenglLogLevel": "Poziom Logów OpenGL:",
- "SettingsTabLoggingOpenglLogLevelNone": "Żadne",
- "SettingsTabLoggingOpenglLogLevelError": "Błędy",
- "SettingsTabLoggingOpenglLogLevelPerformance": "Spowolnienia",
- "SettingsTabLoggingOpenglLogLevelAll": "Wszystkie",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "Żadne",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "Błędy",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Spowolnienia",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "Wszystkie",
"SettingsTabLoggingEnableDebugLogs": "Włącz Logi Debugowania",
"SettingsTabInput": "Sterowanie",
"SettingsTabInputEnableDockedMode": "Tryb Zadokowany",
diff --git a/Ryujinx.Ava/Assets/Locales/pt_BR.json b/Ryujinx.Ava/Assets/Locales/pt_BR.json
index 58a370cdc..81fa569b5 100644
--- a/Ryujinx.Ava/Assets/Locales/pt_BR.json
+++ b/Ryujinx.Ava/Assets/Locales/pt_BR.json
@@ -157,11 +157,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Habilitar logs de acesso ao sistema de arquivos",
"SettingsTabLoggingFsGlobalAccessLogMode": "Modo global de logs do sistema de arquivos:",
"SettingsTabLoggingDeveloperOptions": "Opções do desenvolvedor (AVISO: Vai reduzir a performance)",
- "SettingsTabLoggingOpenglLogLevel": "Nível de log do OpenGL:",
- "SettingsTabLoggingOpenglLogLevelNone": "Nenhum",
- "SettingsTabLoggingOpenglLogLevelError": "Erro",
- "SettingsTabLoggingOpenglLogLevelPerformance": "Lentidão",
- "SettingsTabLoggingOpenglLogLevelAll": "Todos",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "Nenhum",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "Erro",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Lentidão",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "Todos",
"SettingsTabLoggingEnableDebugLogs": "Habilitar logs de depuração",
"SettingsTabInput": "Controle",
"SettingsTabInputEnableDockedMode": "Habilitar modo TV",
diff --git a/Ryujinx.Ava/Assets/Locales/ru_RU.json b/Ryujinx.Ava/Assets/Locales/ru_RU.json
index 27ada3d46..b4202e800 100644
--- a/Ryujinx.Ava/Assets/Locales/ru_RU.json
+++ b/Ryujinx.Ava/Assets/Locales/ru_RU.json
@@ -156,11 +156,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Включить журналы доступа Fs",
"SettingsTabLoggingFsGlobalAccessLogMode": "Режим журнала глобального доступа Fs:",
"SettingsTabLoggingDeveloperOptions": "Параметры разработчика (ВНИМАНИЕ: снизит производительность)",
- "SettingsTabLoggingOpenglLogLevel": "Уровень журнала OpenGL:",
- "SettingsTabLoggingOpenglLogLevelNone": "Ничего",
- "SettingsTabLoggingOpenglLogLevelError": "Ошибка",
- "SettingsTabLoggingOpenglLogLevelPerformance": "Замедления",
- "SettingsTabLoggingOpenglLogLevelAll": "Всё",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "Ничего",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "Ошибка",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Замедления",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "Всё",
"SettingsTabLoggingEnableDebugLogs": "Включить журналы отладки",
"SettingsTabInput": "Управление",
"SettingsTabInputEnableDockedMode": "Включить режим закрепления",
diff --git a/Ryujinx.Ava/Assets/Locales/tr_TR.json b/Ryujinx.Ava/Assets/Locales/tr_TR.json
index 106f84895..3f7baca74 100644
--- a/Ryujinx.Ava/Assets/Locales/tr_TR.json
+++ b/Ryujinx.Ava/Assets/Locales/tr_TR.json
@@ -157,11 +157,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "Fs Erişim Loglarını Etkinleştir",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs Evrensel Erişim Log Modu:",
"SettingsTabLoggingDeveloperOptions": "Geliştirici Seçenekleri (UYARI: Performansı düşürecektir)",
- "SettingsTabLoggingOpenglLogLevel": "OpenGL Log Seviyesi:",
- "SettingsTabLoggingOpenglLogLevelNone": "Hiç",
- "SettingsTabLoggingOpenglLogLevelError": "Hata",
- "SettingsTabLoggingOpenglLogLevelPerformance": "Yavaşlamalar",
- "SettingsTabLoggingOpenglLogLevelAll": "Her Şey",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "Hiç",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "Hata",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Yavaşlamalar",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "Her Şey",
"SettingsTabLoggingEnableDebugLogs": "Hata Ayıklama Loglarını Etkinleştir",
"SettingsTabInput": "Giriş Yöntemi",
"SettingsTabInputEnableDockedMode": "Docked Modunu Etkinleştir",
diff --git a/Ryujinx.Ava/Assets/Locales/zh_CN.json b/Ryujinx.Ava/Assets/Locales/zh_CN.json
index 19e70386c..09c89e4e8 100644
--- a/Ryujinx.Ava/Assets/Locales/zh_CN.json
+++ b/Ryujinx.Ava/Assets/Locales/zh_CN.json
@@ -157,11 +157,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "记录文件访问",
"SettingsTabLoggingFsGlobalAccessLogMode": "记录全局文件访问模式:",
"SettingsTabLoggingDeveloperOptions": "开发者选项 (警告: 会降低性能)",
- "SettingsTabLoggingOpenglLogLevel": "OpenGL日志级别:",
- "SettingsTabLoggingOpenglLogLevelNone": "无",
- "SettingsTabLoggingOpenglLogLevelError": "错误",
- "SettingsTabLoggingOpenglLogLevelPerformance": "减速",
- "SettingsTabLoggingOpenglLogLevelAll": "全部",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "无",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "错误",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "减速",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "全部",
"SettingsTabLoggingEnableDebugLogs": "启用调试日志",
"SettingsTabInput": "输入",
"SettingsTabInputEnableDockedMode": "主机模式",
diff --git a/Ryujinx.Ava/Assets/Locales/zh_TW.json b/Ryujinx.Ava/Assets/Locales/zh_TW.json
index d1f28c12b..856e04599 100644
--- a/Ryujinx.Ava/Assets/Locales/zh_TW.json
+++ b/Ryujinx.Ava/Assets/Locales/zh_TW.json
@@ -157,11 +157,10 @@
"SettingsTabLoggingEnableFsAccessLogs": "記錄檔案存取",
"SettingsTabLoggingFsGlobalAccessLogMode": "記錄全域檔案存取模式:",
"SettingsTabLoggingDeveloperOptions": "開發者選項 (警告: 會降低效能)",
- "SettingsTabLoggingOpenglLogLevel": "OpenGL 日誌級別:",
- "SettingsTabLoggingOpenglLogLevelNone": "無",
- "SettingsTabLoggingOpenglLogLevelError": "錯誤",
- "SettingsTabLoggingOpenglLogLevelPerformance": "減速",
- "SettingsTabLoggingOpenglLogLevelAll": "全部",
+ "SettingsTabLoggingGraphicsBackendLogLevelNone": "無",
+ "SettingsTabLoggingGraphicsBackendLogLevelError": "錯誤",
+ "SettingsTabLoggingGraphicsBackendLogLevelPerformance": "減速",
+ "SettingsTabLoggingGraphicsBackendLogLevelAll": "全部",
"SettingsTabLoggingEnableDebugLogs": "啟用除錯日誌",
"SettingsTabInput": "輸入",
"SettingsTabInputEnableDockedMode": "Docked 模式",
diff --git a/Ryujinx.Ava/Input/AvaloniaKeyboard.cs b/Ryujinx.Ava/Input/AvaloniaKeyboard.cs
index 5b888bf57..d40ebbd2b 100644
--- a/Ryujinx.Ava/Input/AvaloniaKeyboard.cs
+++ b/Ryujinx.Ava/Input/AvaloniaKeyboard.cs
@@ -4,7 +4,6 @@ using Ryujinx.Input;
using System;
using System.Collections.Generic;
using System.Numerics;
-
using ConfigKey = Ryujinx.Common.Configuration.Hid.Key;
using Key = Ryujinx.Input.Key;
@@ -13,30 +12,37 @@ namespace Ryujinx.Ava.Input
internal class AvaloniaKeyboard : IKeyboard
{
private readonly List _buttonsUserMapping;
- private readonly AvaloniaKeyboardDriver _driver;
+ private readonly AvaloniaKeyboardDriver _driver;
+ private StandardKeyboardInputConfig _configuration;
private readonly object _userMappingLock = new();
- private StandardKeyboardInputConfig _configuration;
-
- private bool HasConfiguration => _configuration != null;
-
- public string Id { get; }
+ public string Id { get; }
public string Name { get; }
- public bool IsConnected => true;
+ public bool IsConnected => true;
+ public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
- public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
+ private class ButtonMappingEntry
+ {
+ public readonly Key From;
+ public readonly GamepadButtonInputId To;
+
+ public ButtonMappingEntry(GamepadButtonInputId to, Key from)
+ {
+ To = to;
+ From = from;
+ }
+ }
public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name)
{
- _driver = driver;
- Id = id;
- Name = name;
_buttonsUserMapping = new List();
- }
- public void Dispose() { }
+ _driver = driver;
+ Id = id;
+ Name = name;
+ }
public KeyboardStateSnapshot GetKeyboardStateSnapshot()
{
@@ -46,11 +52,11 @@ namespace Ryujinx.Ava.Input
public GamepadStateSnapshot GetMappedStateSnapshot()
{
KeyboardStateSnapshot rawState = GetKeyboardStateSnapshot();
- GamepadStateSnapshot result = default;
+ GamepadStateSnapshot result = default;
lock (_userMappingLock)
{
- if (!HasConfiguration)
+ if (_configuration == null)
{
return result;
}
@@ -62,17 +68,17 @@ namespace Ryujinx.Ava.Input
continue;
}
- // Do not touch state of the button already pressed
+ // NOTE: Do not touch state of the button already pressed.
if (!result.IsPressed(entry.To))
{
result.SetPressed(entry.To, rawState.IsPressed(entry.From));
}
}
- (short leftStickX, short leftStickY) = GetStickValues(ref rawState, _configuration.LeftJoyconStick);
+ (short leftStickX, short leftStickY) = GetStickValues(ref rawState, _configuration.LeftJoyconStick);
(short rightStickX, short rightStickY) = GetStickValues(ref rawState, _configuration.RightJoyconStick);
- result.SetStick(StickInputId.Left, ConvertRawStickValue(leftStickX), ConvertRawStickValue(leftStickY));
+ result.SetStick(StickInputId.Left, ConvertRawStickValue(leftStickX), ConvertRawStickValue(leftStickY));
result.SetStick(StickInputId.Right, ConvertRawStickValue(rightStickX), ConvertRawStickValue(rightStickY));
}
@@ -114,29 +120,29 @@ namespace Ryujinx.Ava.Input
_buttonsUserMapping.Clear();
- // Left joycon
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, (Key)_configuration.LeftJoyconStick.StickButton));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, (Key)_configuration.LeftJoycon.DpadUp));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadDown, (Key)_configuration.LeftJoycon.DpadDown));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadLeft, (Key)_configuration.LeftJoycon.DpadLeft));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadRight, (Key)_configuration.LeftJoycon.DpadRight));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Minus, (Key)_configuration.LeftJoycon.ButtonMinus));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftShoulder, (Key)_configuration.LeftJoycon.ButtonL));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftTrigger, (Key)_configuration.LeftJoycon.ButtonZl));
+ // Left JoyCon
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, (Key)_configuration.LeftJoyconStick.StickButton));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, (Key)_configuration.LeftJoycon.DpadUp));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadDown, (Key)_configuration.LeftJoycon.DpadDown));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadLeft, (Key)_configuration.LeftJoycon.DpadLeft));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadRight, (Key)_configuration.LeftJoycon.DpadRight));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Minus, (Key)_configuration.LeftJoycon.ButtonMinus));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftShoulder, (Key)_configuration.LeftJoycon.ButtonL));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftTrigger, (Key)_configuration.LeftJoycon.ButtonZl));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger0, (Key)_configuration.LeftJoycon.ButtonSr));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, (Key)_configuration.LeftJoycon.ButtonSl));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, (Key)_configuration.LeftJoycon.ButtonSl));
- // Finally right joycon
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick, (Key)_configuration.RightJoyconStick.StickButton));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A, (Key)_configuration.RightJoycon.ButtonA));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.B, (Key)_configuration.RightJoycon.ButtonB));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.X, (Key)_configuration.RightJoycon.ButtonX));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Y, (Key)_configuration.RightJoycon.ButtonY));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Plus, (Key)_configuration.RightJoycon.ButtonPlus));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightShoulder, (Key)_configuration.RightJoycon.ButtonR));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightTrigger, (Key)_configuration.RightJoycon.ButtonZr));
+ // Right JoyCon
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick, (Key)_configuration.RightJoyconStick.StickButton));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A, (Key)_configuration.RightJoycon.ButtonA));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.B, (Key)_configuration.RightJoycon.ButtonB));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.X, (Key)_configuration.RightJoycon.ButtonX));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Y, (Key)_configuration.RightJoycon.ButtonY));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Plus, (Key)_configuration.RightJoycon.ButtonPlus));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightShoulder, (Key)_configuration.RightJoycon.ButtonR));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightTrigger, (Key)_configuration.RightJoycon.ButtonZr));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger1, (Key)_configuration.RightJoycon.ButtonSr));
- _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, (Key)_configuration.RightJoycon.ButtonSl));
+ _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, (Key)_configuration.RightJoycon.ButtonSl));
}
}
@@ -190,16 +196,6 @@ namespace Ryujinx.Ava.Input
_driver?.ResetKeys();
}
- private class ButtonMappingEntry
- {
- public readonly Key From;
- public readonly GamepadButtonInputId To;
-
- public ButtonMappingEntry(GamepadButtonInputId to, Key from)
- {
- To = to;
- From = from;
- }
- }
+ public void Dispose() { }
}
}
\ No newline at end of file
diff --git a/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs b/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs
index 910de1860..31a53c32c 100644
--- a/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs
+++ b/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs
@@ -4,7 +4,6 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Input;
using System;
using System.Collections.Generic;
-
using AvaKey = Avalonia.Input.Key;
using Key = Ryujinx.Input.Key;
@@ -13,24 +12,23 @@ namespace Ryujinx.Ava.Input
internal class AvaloniaKeyboardDriver : IGamepadDriver
{
private static readonly string[] _keyboardIdentifers = new string[1] { "0" };
- private readonly Control _control;
+ private readonly Control _control;
private readonly HashSet _pressedKeys;
public event EventHandler KeyPressed;
public event EventHandler KeyRelease;
- public event EventHandler TextInput;
-
- public string DriverName => "Avalonia";
+ public event EventHandler TextInput;
+ public string DriverName => "AvaloniaKeyboardDriver";
public ReadOnlySpan GamepadsIds => _keyboardIdentifers;
public AvaloniaKeyboardDriver(Control control)
{
- _control = control;
+ _control = control;
_pressedKeys = new HashSet();
- _control.KeyDown += OnKeyPress;
- _control.KeyUp += OnKeyRelease;
+ _control.KeyDown += OnKeyPress;
+ _control.KeyUp += OnKeyRelease;
_control.TextInput += Control_TextInput;
}
@@ -41,21 +39,16 @@ namespace Ryujinx.Ava.Input
public event Action OnGamepadConnected
{
- add { }
+ add { }
remove { }
}
public event Action OnGamepadDisconnected
{
- add { }
+ add { }
remove { }
}
- public void Dispose()
- {
- Dispose(true);
- }
-
public IGamepad GetGamepad(string id)
{
if (!_keyboardIdentifers[0].Equals(id))
@@ -70,15 +63,13 @@ namespace Ryujinx.Ava.Input
{
if (disposing)
{
- _control.KeyUp -= OnKeyPress;
+ _control.KeyUp -= OnKeyPress;
_control.KeyDown -= OnKeyRelease;
}
}
protected void OnKeyPress(object sender, KeyEventArgs args)
{
- AvaKey key = args.Key;
-
_pressedKeys.Add(args.Key);
KeyPressed?.Invoke(this, args);
@@ -98,7 +89,7 @@ namespace Ryujinx.Ava.Input
return false;
}
- AvaloniaMappingHelper.TryGetAvaKey(key, out var nativeKey);
+ AvaloniaKeyboardMappingHelper.TryGetAvaKey(key, out var nativeKey);
return _pressedKeys.Contains(nativeKey);
}
@@ -107,5 +98,10 @@ namespace Ryujinx.Ava.Input
{
_pressedKeys.Clear();
}
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
}
}
\ No newline at end of file
diff --git a/Ryujinx.Ava/Input/AvaloniaMappingHelper.cs b/Ryujinx.Ava/Input/AvaloniaKeyboardMappingHelper.cs
similarity index 92%
rename from Ryujinx.Ava/Input/AvaloniaMappingHelper.cs
rename to Ryujinx.Ava/Input/AvaloniaKeyboardMappingHelper.cs
index e1ef3ebc3..8400ddad6 100644
--- a/Ryujinx.Ava/Input/AvaloniaMappingHelper.cs
+++ b/Ryujinx.Ava/Input/AvaloniaKeyboardMappingHelper.cs
@@ -5,7 +5,7 @@ using AvaKey = Avalonia.Input.Key;
namespace Ryujinx.Ava.Input
{
- internal static class AvaloniaMappingHelper
+ internal static class AvaloniaKeyboardMappingHelper
{
private static readonly AvaKey[] _keyMapping = new AvaKey[(int)Key.Count]
{
@@ -149,11 +149,11 @@ namespace Ryujinx.Ava.Input
private static readonly Dictionary _avaKeyMapping;
- static AvaloniaMappingHelper()
+ static AvaloniaKeyboardMappingHelper()
{
var inputKeys = Enum.GetValues(typeof(Key));
- // Avalonia.Input.Key is not contiguous and quite large, so use a dictionary instead of an array.
+ // NOTE: Avalonia.Input.Key is not contiguous and quite large, so use a dictionary instead of an array.
_avaKeyMapping = new Dictionary();
foreach (var key in inputKeys)
@@ -167,15 +167,13 @@ namespace Ryujinx.Ava.Input
public static bool TryGetAvaKey(Key key, out AvaKey avaKey)
{
- var keyExist = (int)key < _keyMapping.Length;
+ avaKey = AvaKey.None;
+
+ bool keyExist = (int)key < _keyMapping.Length;
if (keyExist)
{
avaKey = _keyMapping[(int)key];
}
- else
- {
- avaKey = AvaKey.None;
- }
return keyExist;
}
diff --git a/Ryujinx.Ava/Input/AvaloniaMouse.cs b/Ryujinx.Ava/Input/AvaloniaMouse.cs
index a3ca2ff81..3a9c91c0d 100644
--- a/Ryujinx.Ava/Input/AvaloniaMouse.cs
+++ b/Ryujinx.Ava/Input/AvaloniaMouse.cs
@@ -10,15 +10,12 @@ namespace Ryujinx.Ava.Input
{
private AvaloniaMouseDriver _driver;
- public GamepadFeaturesFlag Features => throw new NotImplementedException();
-
- public string Id => "0";
-
+ public string Id => "0";
public string Name => "AvaloniaMouse";
- public bool IsConnected => true;
-
- public bool[] Buttons => _driver.PressedButtons;
+ public bool IsConnected => true;
+ public GamepadFeaturesFlag Features => throw new NotImplementedException();
+ public bool[] Buttons => _driver.PressedButtons;
public AvaloniaMouse(AvaloniaMouseDriver driver)
{
diff --git a/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs b/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
index 9ad0310a5..eb58752ce 100644
--- a/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
+++ b/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
@@ -11,35 +11,50 @@ namespace Ryujinx.Ava.Input
{
internal class AvaloniaMouseDriver : IGamepadDriver
{
- private Control _widget;
- private bool _isDisposed;
- private Size _size;
+ private Control _widget;
+ private bool _isDisposed;
+ private Size _size;
private readonly Window _window;
- public bool[] PressedButtons { get; }
-
+ public bool[] PressedButtons { get; }
public Vector2 CurrentPosition { get; private set; }
- public Vector2 Scroll { get; private set; }
+ public Vector2 Scroll { get; private set; }
+
+ public string DriverName => "AvaloniaMouseDriver";
+ public ReadOnlySpan GamepadsIds => new[] { "0" };
public AvaloniaMouseDriver(Window window, Control parent)
{
_widget = parent;
_window = window;
- _widget.PointerMoved += Parent_PointerMovedEvent;
- _widget.PointerPressed += Parent_PointerPressEvent;
- _widget.PointerReleased += Parent_PointerReleaseEvent;
+ _widget.PointerMoved += Parent_PointerMovedEvent;
+ _widget.PointerPressed += Parent_PointerPressEvent;
+ _widget.PointerReleased += Parent_PointerReleaseEvent;
_widget.PointerWheelChanged += Parent_ScrollEvent;
- _window.PointerMoved += Parent_PointerMovedEvent;
- _window.PointerPressed += Parent_PointerPressEvent;
- _window.PointerReleased += Parent_PointerReleaseEvent;
+ _window.PointerMoved += Parent_PointerMovedEvent;
+ _window.PointerPressed += Parent_PointerPressEvent;
+ _window.PointerReleased += Parent_PointerReleaseEvent;
_window.PointerWheelChanged += Parent_ScrollEvent;
PressedButtons = new bool[(int)MouseButton.Count];
_size = new Size((int)parent.Bounds.Width, (int)parent.Bounds.Height);
- parent.GetObservable(Control.BoundsProperty).Subscribe(Resized);
+
+ parent.GetObservable(Visual.BoundsProperty).Subscribe(Resized);
+ }
+
+ public event Action OnGamepadConnected
+ {
+ add { }
+ remove { }
+ }
+
+ public event Action OnGamepadDisconnected
+ {
+ add { }
+ remove { }
}
private void Resized(Rect rect)
@@ -59,14 +74,12 @@ namespace Ryujinx.Ava.Input
private void Parent_PointerPressEvent(object o, PointerPressedEventArgs args)
{
- var pointerProperties = args.GetCurrentPoint(_widget).Properties;
-
- PressedButtons[(int)pointerProperties.PointerUpdateKind] = true;
+ PressedButtons[(int)args.GetCurrentPoint(_widget).Properties.PointerUpdateKind] = true;
}
private void Parent_PointerMovedEvent(object o, PointerEventArgs args)
{
- var position = args.GetPosition(_widget);
+ Point position = args.GetPosition(_widget);
CurrentPosition = new Vector2((float)position.X, (float)position.Y);
}
@@ -96,22 +109,6 @@ namespace Ryujinx.Ava.Input
return _size;
}
- public string DriverName => "Avalonia";
-
- public event Action OnGamepadConnected
- {
- add { }
- remove { }
- }
-
- public event Action OnGamepadDisconnected
- {
- add { }
- remove { }
- }
-
- public ReadOnlySpan GamepadsIds => new[] { "0" };
-
public IGamepad GetGamepad(string id)
{
return new AvaloniaMouse(this);
@@ -126,14 +123,14 @@ namespace Ryujinx.Ava.Input
_isDisposed = true;
- _widget.PointerMoved -= Parent_PointerMovedEvent;
- _widget.PointerPressed -= Parent_PointerPressEvent;
- _widget.PointerReleased -= Parent_PointerReleaseEvent;
+ _widget.PointerMoved -= Parent_PointerMovedEvent;
+ _widget.PointerPressed -= Parent_PointerPressEvent;
+ _widget.PointerReleased -= Parent_PointerReleaseEvent;
_widget.PointerWheelChanged -= Parent_ScrollEvent;
- _window.PointerMoved -= Parent_PointerMovedEvent;
- _window.PointerPressed -= Parent_PointerPressEvent;
- _window.PointerReleased -= Parent_PointerReleaseEvent;
+ _window.PointerMoved -= Parent_PointerMovedEvent;
+ _window.PointerPressed -= Parent_PointerPressEvent;
+ _window.PointerReleased -= Parent_PointerReleaseEvent;
_window.PointerWheelChanged -= Parent_ScrollEvent;
_widget = null;
diff --git a/Ryujinx.Ava/Ryujinx.Ava.csproj b/Ryujinx.Ava/Ryujinx.Ava.csproj
index c7b0eadc5..6d963a403 100644
--- a/Ryujinx.Ava/Ryujinx.Ava.csproj
+++ b/Ryujinx.Ava/Ryujinx.Ava.csproj
@@ -28,7 +28,7 @@
-
+
diff --git a/Ryujinx.Ava/Ui/Applet/AvaloniaDynamicTextInputHandler.cs b/Ryujinx.Ava/Ui/Applet/AvaloniaDynamicTextInputHandler.cs
index 02a99c1d1..ee0d435b0 100644
--- a/Ryujinx.Ava/Ui/Applet/AvaloniaDynamicTextInputHandler.cs
+++ b/Ryujinx.Ava/Ui/Applet/AvaloniaDynamicTextInputHandler.cs
@@ -68,7 +68,7 @@ namespace Ryujinx.Ava.Ui.Applet
private void AvaloniaDynamicTextInputHandler_KeyRelease(object sender, Avalonia.Input.KeyEventArgs e)
{
- var key = (HidKey)AvaloniaMappingHelper.ToInputKey(e.Key);
+ var key = (HidKey)AvaloniaKeyboardMappingHelper.ToInputKey(e.Key);
if (!(KeyReleasedEvent?.Invoke(key)).GetValueOrDefault(true))
{
@@ -88,7 +88,7 @@ namespace Ryujinx.Ava.Ui.Applet
private void AvaloniaDynamicTextInputHandler_KeyPressed(object sender, KeyEventArgs e)
{
- var key = (HidKey)AvaloniaMappingHelper.ToInputKey(e.Key);
+ var key = (HidKey)AvaloniaKeyboardMappingHelper.ToInputKey(e.Key);
if (!(KeyPressedEvent?.Invoke(key)).GetValueOrDefault(true))
{
diff --git a/Ryujinx.Ava/Ui/Models/FileSizeSortComparer.cs b/Ryujinx.Ava/Ui/Models/FileSizeSortComparer.cs
deleted file mode 100644
index d4ac1412f..000000000
--- a/Ryujinx.Ava/Ui/Models/FileSizeSortComparer.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Ryujinx.Ui.App.Common;
-using System.Collections;
-
-namespace Ryujinx.Ava.Ui.Models
-{
- internal class FileSizeSortComparer : IComparer
- {
- public int Compare(object x, object y)
- {
- string aValue = (x as ApplicationData).TimePlayed;
- string bValue = (y as ApplicationData).TimePlayed;
-
- if (aValue[^3..] == "GiB")
- {
- aValue = (float.Parse(aValue[0..^3]) * 1024).ToString();
- }
- else
- {
- aValue = aValue[0..^3];
- }
-
- if (bValue[^3..] == "GiB")
- {
- bValue = (float.Parse(bValue[0..^3]) * 1024).ToString();
- }
- else
- {
- bValue = bValue[0..^3];
- }
-
- if (float.Parse(aValue) > float.Parse(bValue))
- {
- return -1;
- }
- else if (float.Parse(bValue) > float.Parse(aValue))
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/Models/Generic/FileSizeSortComparer.cs b/Ryujinx.Ava/Ui/Models/Generic/FileSizeSortComparer.cs
deleted file mode 100644
index 08b1754c2..000000000
--- a/Ryujinx.Ava/Ui/Models/Generic/FileSizeSortComparer.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Ryujinx.Ui.App.Common;
-using System.Collections.Generic;
-
-namespace Ryujinx.Ava.Ui.Models.Generic
-{
- internal class FileSizeSortComparer : IComparer
- {
- public FileSizeSortComparer() { }
- public FileSizeSortComparer(bool isAscending) { _order = isAscending ? 1 : -1; }
-
- private int _order;
-
- public int Compare(ApplicationData x, ApplicationData y)
- {
- string aValue = x.FileSize;
- string bValue = y.FileSize;
-
- if (aValue[^3..] == "GiB")
- {
- aValue = (float.Parse(aValue[0..^3]) * 1024).ToString();
- }
- else
- {
- aValue = aValue[0..^3];
- }
-
- if (bValue[^3..] == "GiB")
- {
- bValue = (float.Parse(bValue[0..^3]) * 1024).ToString();
- }
- else
- {
- bValue = bValue[0..^3];
- }
-
- if (float.Parse(aValue) > float.Parse(bValue))
- {
- return -1 * _order;
- }
- else if (float.Parse(bValue) > float.Parse(aValue))
- {
- return 1 * _order;
- }
- else
- {
- return 0;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/Models/Generic/TimePlayedSortComparer.cs b/Ryujinx.Ava/Ui/Models/Generic/TimePlayedSortComparer.cs
deleted file mode 100644
index da26d1950..000000000
--- a/Ryujinx.Ava/Ui/Models/Generic/TimePlayedSortComparer.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using Ryujinx.Ui.App.Common;
-using System.Collections.Generic;
-
-namespace Ryujinx.Ava.Ui.Models.Generic
-{
- internal class TimePlayedSortComparer : IComparer
- {
- public TimePlayedSortComparer() { }
- public TimePlayedSortComparer(bool isAscending) { _order = isAscending ? 1 : -1; }
-
- private int _order;
-
- public int Compare(ApplicationData x, ApplicationData y)
- {
- string aValue = x.TimePlayed;
- string bValue = y.TimePlayed;
-
- if (aValue.Length > 4 && aValue[^4..] == "mins")
- {
- aValue = (float.Parse(aValue[0..^5]) * 60).ToString();
- }
- else if (aValue.Length > 3 && aValue[^3..] == "hrs")
- {
- aValue = (float.Parse(aValue[0..^4]) * 3600).ToString();
- }
- else if (aValue.Length > 4 && aValue[^4..] == "days")
- {
- aValue = (float.Parse(aValue[0..^5]) * 86400).ToString();
- }
- else
- {
- aValue = aValue[0..^1];
- }
-
- if (bValue.Length > 4 && bValue[^4..] == "mins")
- {
- bValue = (float.Parse(bValue[0..^5]) * 60).ToString();
- }
- else if (bValue.Length > 3 && bValue[^3..] == "hrs")
- {
- bValue = (float.Parse(bValue[0..^4]) * 3600).ToString();
- }
- else if (bValue.Length > 4 && bValue[^4..] == "days")
- {
- bValue = (float.Parse(bValue[0..^5]) * 86400).ToString();
- }
- else
- {
- bValue = bValue[0..^1];
- }
-
- if (float.Parse(aValue) > float.Parse(bValue))
- {
- return -1 * _order;
- }
- else if (float.Parse(bValue) > float.Parse(aValue))
- {
- return 1 * _order;
- }
- else
- {
- return 0;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/Models/LastPlayedSortComparer.cs b/Ryujinx.Ava/Ui/Models/LastPlayedSortComparer.cs
deleted file mode 100644
index c5c22fb26..000000000
--- a/Ryujinx.Ava/Ui/Models/LastPlayedSortComparer.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Ryujinx.Ui.App.Common;
-using System;
-using System.Collections;
-
-namespace Ryujinx.Ava.Ui.Models
-{
- internal class LastPlayedSortComparer : IComparer
- {
- public int Compare(object x, object y)
- {
- string aValue = (x as ApplicationData).LastPlayed;
- string bValue = (y as ApplicationData).LastPlayed;
-
- if (aValue == "Never")
- {
- aValue = DateTime.UnixEpoch.ToString();
- }
-
- if (bValue == "Never")
- {
- bValue = DateTime.UnixEpoch.ToString();
- }
-
- return DateTime.Compare(DateTime.Parse(bValue), DateTime.Parse(aValue));
- }
- }
-}
\ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/Models/TimePlayedSortComparer.cs b/Ryujinx.Ava/Ui/Models/TimePlayedSortComparer.cs
deleted file mode 100644
index 3613c8c7c..000000000
--- a/Ryujinx.Ava/Ui/Models/TimePlayedSortComparer.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using Ryujinx.Ui.App.Common;
-using System.Collections;
-
-namespace Ryujinx.Ava.Ui.Models
-{
- internal class TimePlayedSortComparer : IComparer
- {
- public int Compare(object x, object y)
- {
- string aValue = (x as ApplicationData).TimePlayed;
- string bValue = (y as ApplicationData).TimePlayed;
-
- if (aValue.Length > 4 && aValue[^4..] == "mins")
- {
- aValue = (float.Parse(aValue[0..^5]) * 60).ToString();
- }
- else if (aValue.Length > 3 && aValue[^3..] == "hrs")
- {
- aValue = (float.Parse(aValue[0..^4]) * 3600).ToString();
- }
- else if (aValue.Length > 4 && aValue[^4..] == "days")
- {
- aValue = (float.Parse(aValue[0..^5]) * 86400).ToString();
- }
- else
- {
- aValue = aValue[0..^1];
- }
-
- if (bValue.Length > 4 && bValue[^4..] == "mins")
- {
- bValue = (float.Parse(bValue[0..^5]) * 60).ToString();
- }
- else if (bValue.Length > 3 && bValue[^3..] == "hrs")
- {
- bValue = (float.Parse(bValue[0..^4]) * 3600).ToString();
- }
- else if (bValue.Length > 4 && bValue[^4..] == "days")
- {
- bValue = (float.Parse(bValue[0..^5]) * 86400).ToString();
- }
- else
- {
- bValue = bValue[0..^1];
- }
-
- if (float.Parse(aValue) > float.Parse(bValue))
- {
- return -1;
- }
- else if (float.Parse(bValue) > float.Parse(aValue))
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs
index 0db20792a..06513e37c 100644
--- a/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs
+++ b/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs
@@ -502,8 +502,10 @@ namespace Ryujinx.Ava.Ui.ViewModels
return SortMode switch
{
ApplicationSort.LastPlayed => new Models.Generic.LastPlayedSortComparer(IsAscending),
- ApplicationSort.FileSize => new Models.Generic.FileSizeSortComparer(IsAscending),
- ApplicationSort.TotalTimePlayed => new Models.Generic.TimePlayedSortComparer(IsAscending),
+ ApplicationSort.FileSize => IsAscending ? SortExpressionComparer.Ascending(app => app.FileSizeBytes)
+ : SortExpressionComparer.Descending(app => app.FileSizeBytes),
+ ApplicationSort.TotalTimePlayed => IsAscending ? SortExpressionComparer.Ascending(app => app.TimePlayedNum)
+ : SortExpressionComparer.Descending(app => app.TimePlayedNum),
ApplicationSort.Title => IsAscending ? SortExpressionComparer.Ascending(app => app.TitleName)
: SortExpressionComparer.Descending(app => app.TitleName),
ApplicationSort.Favorite => !IsAscending ? SortExpressionComparer.Ascending(app => app.Favorite)
@@ -881,17 +883,17 @@ namespace Ryujinx.Ava.Ui.ViewModels
public void LoadConfigurableHotKeys()
{
- if (AvaloniaMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey))
+ if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey))
{
ShowUiKey = new KeyGesture(showUiKey, KeyModifiers.None);
}
- if (AvaloniaMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey))
+ if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey))
{
ScreenshotKey = new KeyGesture(screenshotKey, KeyModifiers.None);
}
- if (AvaloniaMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey))
+ if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey))
{
PauseKey = new KeyGesture(pauseKey, KeyModifiers.None);
}
diff --git a/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml b/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml
index 30a34fbfb..c8c9f59a8 100644
--- a/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml
+++ b/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml
@@ -876,7 +876,7 @@
-
+
-
+
+ Text="{locale:Locale SettingsTabLoggingGraphicsBackendLogLevelPerformance}" />
-
+
diff --git a/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
index d2eb5ccff..2bdb85bf0 100644
--- a/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
- private const uint CodeGenVersion = 4011;
+ private const uint CodeGenVersion = 4037;
private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data";
diff --git a/Ryujinx.Graphics.Shader/Translation/Rewriter.cs b/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
index c8dab9de3..c4d2c5d90 100644
--- a/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
@@ -21,10 +21,11 @@ namespace Ryujinx.Graphics.Shader.Translation
{
BasicBlock block = blocks[blkIndex];
- for (LinkedListNode node = block.Operations.First; node != null; node = node.Next)
+ for (LinkedListNode node = block.Operations.First; node != null;)
{
if (node.Value is not Operation operation)
{
+ node = node.Next;
continue;
}
@@ -43,10 +44,7 @@ namespace Ryujinx.Graphics.Shader.Translation
}
}
- if (UsesGlobalMemory(operation.Inst))
- {
- node = RewriteGlobalAccess(node, config);
- }
+ LinkedListNode nextNode = node.Next;
if (operation is TextureOperation texOp)
{
@@ -59,7 +57,15 @@ namespace Ryujinx.Graphics.Shader.Translation
node = InsertSnormNormalization(node, config);
}
}
+
+ nextNode = node.Next;
}
+ else if (UsesGlobalMemory(operation.Inst))
+ {
+ nextNode = RewriteGlobalAccess(node, config)?.Next ?? nextNode;
+ }
+
+ node = nextNode;
}
}
}
@@ -72,7 +78,7 @@ namespace Ryujinx.Graphics.Shader.Translation
bool isStg16Or8 = operation.Inst == Instruction.StoreGlobal16 || operation.Inst == Instruction.StoreGlobal8;
bool isWrite = isAtomic || operation.Inst == Instruction.StoreGlobal || isStg16Or8;
- Operation storageOp;
+ Operation storageOp = null;
Operand PrependOperation(Instruction inst, params Operand[] sources)
{
@@ -120,49 +126,56 @@ namespace Ryujinx.Graphics.Shader.Translation
sbSlot = PrependOperation(Instruction.ConditionalSelect, inRange, Const(slot), sbSlot);
}
- Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment());
-
- Operand baseAddrTrunc = PrependOperation(Instruction.BitwiseAnd, sbBaseAddrLow, alignMask);
- Operand byteOffset = PrependOperation(Instruction.Subtract, addrLow, baseAddrTrunc);
-
- Operand[] sources = new Operand[operation.SourcesCount];
-
- sources[0] = sbSlot;
-
- if (isStg16Or8)
+ if (config.AccessibleStorageBuffersMask != 0)
{
- sources[1] = byteOffset;
- }
- else
- {
- sources[1] = PrependOperation(Instruction.ShiftRightU32, byteOffset, Const(2));
- }
+ Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment());
- for (int index = 2; index < operation.SourcesCount; index++)
- {
- sources[index] = operation.GetSource(index);
- }
+ Operand baseAddrTrunc = PrependOperation(Instruction.BitwiseAnd, sbBaseAddrLow, alignMask);
+ Operand byteOffset = PrependOperation(Instruction.Subtract, addrLow, baseAddrTrunc);
- if (isAtomic)
- {
- Instruction inst = (operation.Inst & ~Instruction.MrMask) | Instruction.MrStorage;
+ Operand[] sources = new Operand[operation.SourcesCount];
- storageOp = new Operation(inst, operation.Dest, sources);
- }
- else if (operation.Inst == Instruction.LoadGlobal)
- {
- storageOp = new Operation(Instruction.LoadStorage, operation.Dest, sources);
- }
- else
- {
- Instruction storeInst = operation.Inst switch
+ sources[0] = sbSlot;
+
+ if (isStg16Or8)
{
- Instruction.StoreGlobal16 => Instruction.StoreStorage16,
- Instruction.StoreGlobal8 => Instruction.StoreStorage8,
- _ => Instruction.StoreStorage
- };
+ sources[1] = byteOffset;
+ }
+ else
+ {
+ sources[1] = PrependOperation(Instruction.ShiftRightU32, byteOffset, Const(2));
+ }
- storageOp = new Operation(storeInst, null, sources);
+ for (int index = 2; index < operation.SourcesCount; index++)
+ {
+ sources[index] = operation.GetSource(index);
+ }
+
+ if (isAtomic)
+ {
+ Instruction inst = (operation.Inst & ~Instruction.MrMask) | Instruction.MrStorage;
+
+ storageOp = new Operation(inst, operation.Dest, sources);
+ }
+ else if (operation.Inst == Instruction.LoadGlobal)
+ {
+ storageOp = new Operation(Instruction.LoadStorage, operation.Dest, sources);
+ }
+ else
+ {
+ Instruction storeInst = operation.Inst switch
+ {
+ Instruction.StoreGlobal16 => Instruction.StoreStorage16,
+ Instruction.StoreGlobal8 => Instruction.StoreStorage8,
+ _ => Instruction.StoreStorage
+ };
+
+ storageOp = new Operation(storeInst, null, sources);
+ }
+ }
+ else if (operation.Dest != null)
+ {
+ storageOp = new Operation(Instruction.Copy, operation.Dest, Const(0));
}
for (int index = 0; index < operation.SourcesCount; index++)
@@ -171,10 +184,18 @@ namespace Ryujinx.Graphics.Shader.Translation
}
LinkedListNode oldNode = node;
+ LinkedList oldNodeList = oldNode.List;
- node = node.List.AddBefore(node, storageOp);
+ if (storageOp != null)
+ {
+ node = node.List.AddBefore(node, storageOp);
+ }
+ else
+ {
+ node = null;
+ }
- node.List.Remove(oldNode);
+ oldNodeList.Remove(oldNode);
return node;
}
diff --git a/Ryujinx.HLE/Ryujinx.HLE.csproj b/Ryujinx.HLE/Ryujinx.HLE.csproj
index 1ec92a449..82f3483cd 100644
--- a/Ryujinx.HLE/Ryujinx.HLE.csproj
+++ b/Ryujinx.HLE/Ryujinx.HLE.csproj
@@ -26,7 +26,7 @@
-
+
diff --git a/Ryujinx.Horizon.Generators/Ryujinx.Horizon.Generators.csproj b/Ryujinx.Horizon.Generators/Ryujinx.Horizon.Generators.csproj
index 22b07eab4..0fd79794f 100644
--- a/Ryujinx.Horizon.Generators/Ryujinx.Horizon.Generators.csproj
+++ b/Ryujinx.Horizon.Generators/Ryujinx.Horizon.Generators.csproj
@@ -9,7 +9,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/Ryujinx.Tests/Audio/Renderer/Parameter/Effect/CompressorParameterTests.cs b/Ryujinx.Tests/Audio/Renderer/Parameter/Effect/CompressorParameterTests.cs
new file mode 100644
index 000000000..24b834fcb
--- /dev/null
+++ b/Ryujinx.Tests/Audio/Renderer/Parameter/Effect/CompressorParameterTests.cs
@@ -0,0 +1,16 @@
+using NUnit.Framework;
+using Ryujinx.Audio.Renderer.Parameter.Effect;
+using System.Runtime.CompilerServices;
+
+namespace Ryujinx.Tests.Audio.Renderer.Parameter.Effect
+{
+ class CompressorParameterTests
+ {
+ [Test]
+ public void EnsureTypeSize()
+ {
+ Assert.AreEqual(0x38, Unsafe.SizeOf());
+ }
+ }
+}
+
diff --git a/Ryujinx.Ui.Common/App/ApplicationData.cs b/Ryujinx.Ui.Common/App/ApplicationData.cs
index 758a03bab..ba430172f 100644
--- a/Ryujinx.Ui.Common/App/ApplicationData.cs
+++ b/Ryujinx.Ui.Common/App/ApplicationData.cs
@@ -12,9 +12,11 @@ namespace Ryujinx.Ui.App.Common
public string Developer { get; set; }
public string Version { get; set; }
public string TimePlayed { get; set; }
+ public double TimePlayedNum { get; set; }
public string LastPlayed { get; set; }
public string FileExtension { get; set; }
public string FileSize { get; set; }
+ public double FileSizeBytes { get; set; }
public string Path { get; set; }
public BlitStruct ControlHolder { get; set; }
}
diff --git a/Ryujinx.Ui.Common/App/ApplicationLibrary.cs b/Ryujinx.Ui.Common/App/ApplicationLibrary.cs
index 466b2b952..1af7dc064 100644
--- a/Ryujinx.Ui.Common/App/ApplicationLibrary.cs
+++ b/Ryujinx.Ui.Common/App/ApplicationLibrary.cs
@@ -465,9 +465,11 @@ namespace Ryujinx.Ui.App.Common
Developer = developer,
Version = version,
TimePlayed = ConvertSecondsToReadableString(appMetadata.TimePlayed),
+ TimePlayedNum = appMetadata.TimePlayed,
LastPlayed = appMetadata.LastPlayed,
FileExtension = Path.GetExtension(applicationPath).ToUpper().Remove(0, 1),
FileSize = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + " MiB" : fileSize.ToString("0.##") + " GiB",
+ FileSizeBytes = fileSize,
Path = applicationPath,
ControlHolder = controlHolder
};
diff --git a/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs b/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs
index 18cf7640c..ae183fea7 100644
--- a/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs
+++ b/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs
@@ -680,7 +680,7 @@ namespace Ryujinx.Ui.Common.Configuration
Hid.EnableMouse.Value = false;
Hid.Hotkeys.Value = new KeyboardHotkeys
{
- ToggleVsync = Key.Tab,
+ ToggleVsync = Key.F1,
ToggleMute = Key.F2,
Screenshot = Key.F8,
ShowUi = Key.F4,
@@ -818,7 +818,7 @@ namespace Ryujinx.Ui.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
- ToggleVsync = Key.Tab
+ ToggleVsync = Key.F1
};
configurationFileUpdated = true;
@@ -999,7 +999,7 @@ namespace Ryujinx.Ui.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
- ToggleVsync = Key.Tab,
+ ToggleVsync = Key.F1,
Screenshot = Key.F8
};
@@ -1012,7 +1012,7 @@ namespace Ryujinx.Ui.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
- ToggleVsync = Key.Tab,
+ ToggleVsync = Key.F1,
Screenshot = Key.F8,
ShowUi = Key.F4
};
diff --git a/Ryujinx/Ui/Helper/SortHelper.cs b/Ryujinx/Ui/Helper/SortHelper.cs
index 33ae1bb28..4def89323 100644
--- a/Ryujinx/Ui/Helper/SortHelper.cs
+++ b/Ryujinx/Ui/Helper/SortHelper.cs
@@ -9,46 +9,56 @@ namespace Ryujinx.Ui.Helper
{
string aValue = model.GetValue(a, 5).ToString();
string bValue = model.GetValue(b, 5).ToString();
+ float aFloat;
+ float bFloat;
- if (aValue.Length > 4 && aValue[^4..] == "mins")
+ if (aValue.Length > 7 && aValue[^7..] == "minutes")
{
- aValue = (float.Parse(aValue[0..^5]) * 60).ToString();
+ aValue = aValue.Replace("minutes", "");
+ aFloat = (float.Parse(aValue) * 60);
}
- else if (aValue.Length > 3 && aValue[^3..] == "hrs")
+ else if (aValue.Length > 5 && aValue[^5..] == "hours")
{
- aValue = (float.Parse(aValue[0..^4]) * 3600).ToString();
+ aValue = aValue.Replace("hours", "");
+ aFloat = (float.Parse(aValue) * 3600);
}
else if (aValue.Length > 4 && aValue[^4..] == "days")
{
- aValue = (float.Parse(aValue[0..^5]) * 86400).ToString();
+ aValue = aValue.Replace("days", "");
+ aFloat = (float.Parse(aValue) * 86400);
}
else
{
- aValue = aValue[0..^1];
+ aValue = aValue.Replace("seconds", "");
+ aFloat = float.Parse(aValue);
}
- if (bValue.Length > 4 && bValue[^4..] == "mins")
+ if (bValue.Length > 7 && bValue[^7..] == "minutes")
{
- bValue = (float.Parse(bValue[0..^5]) * 60).ToString();
+ bValue = bValue.Replace("minutes", "");
+ bFloat = (float.Parse(bValue) * 60);
}
- else if (bValue.Length > 3 && bValue[^3..] == "hrs")
+ else if (bValue.Length > 5 && bValue[^5..] == "hours")
{
- bValue = (float.Parse(bValue[0..^4]) * 3600).ToString();
+ bValue = bValue.Replace("hours", "");
+ bFloat = (float.Parse(bValue) * 3600);
}
else if (bValue.Length > 4 && bValue[^4..] == "days")
{
- bValue = (float.Parse(bValue[0..^5]) * 86400).ToString();
+ bValue = bValue.Replace("days", "");
+ bFloat = (float.Parse(bValue) * 86400);
}
else
{
- bValue = bValue[0..^1];
+ bValue = bValue[0..^8];
+ bFloat = float.Parse(bValue);
}
- if (float.Parse(aValue) > float.Parse(bValue))
+ if (aFloat > bFloat)
{
return -1;
}
- else if (float.Parse(bValue) > float.Parse(aValue))
+ else if (bFloat > aFloat)
{
return 1;
}