UI: Add Skyrim, KAFTL & HW:AOC to RPC.

Minor code improvements and comment fixes.
This commit is contained in:
Evan Husted 2024-10-16 19:23:11 -05:00
parent 280b94fc0c
commit 1800ecc1b4
13 changed files with 68 additions and 122 deletions

View File

@ -8,7 +8,7 @@ namespace Ryujinx.Common
public static class StreamExtensions public static class StreamExtensions
{ {
/// <summary> /// <summary>
/// Writes a <cref="ReadOnlySpan<int>" /> to this stream. /// Writes a <see cref="ReadOnlySpan{int}" /> to this stream.
/// ///
/// This default implementation converts each buffer value to a stack-allocated /// This default implementation converts each buffer value to a stack-allocated
/// byte array, then writes it to the Stream using <cref="System.Stream.Write(byte[])" />. /// byte array, then writes it to the Stream using <cref="System.Stream.Write(byte[])" />.
@ -66,8 +66,8 @@ namespace Ryujinx.Common
} }
/// <summary> /// <summary>
// Writes a four-byte unsigned integer to this stream. The current position /// Writes a four-byte unsigned integer to this stream. The current position
// of the stream is advanced by four. /// of the stream is advanced by four.
/// </summary> /// </summary>
/// <param name="stream">The stream to be written to</param> /// <param name="stream">The stream to be written to</param>
/// <param name="value">The value to be written</param> /// <param name="value">The value to be written</param>

View File

@ -107,7 +107,7 @@ namespace Ryujinx.Common
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong XorShift64(ulong v64, int shift) private static ulong XorShift64(ulong v64, int shift)
{ {
Debug.Assert(0 <= shift && shift < 64); Debug.Assert(shift is >= 0 and < 64);
return v64 ^ (v64 >> shift); return v64 ^ (v64 >> shift);
} }

View File

@ -4,23 +4,18 @@ namespace Ryujinx.Common
{ {
public static class BitUtils public static class BitUtils
{ {
public static T AlignUp<T>(T value, T size) public static T AlignUp<T>(T value, T size) where T : IBinaryInteger<T>
where T : IBinaryInteger<T> => (value + (size - T.One)) & -size;
{
return (value + (size - T.One)) & -size;
}
public static T AlignDown<T>(T value, T size) public static T AlignDown<T>(T value, T size) where T : IBinaryInteger<T>
where T : IBinaryInteger<T> => value & -size;
{
return value & -size;
}
public static T DivRoundUp<T>(T value, T dividend) public static T DivRoundUp<T>(T value, T dividend) where T : IBinaryInteger<T>
where T : IBinaryInteger<T> => (value + (dividend - T.One)) / dividend;
{
return (value + (dividend - T.One)) / dividend; public static int Pow2RoundDown(int value) => BitOperations.IsPow2(value) ? value : Pow2RoundUp(value) >> 1;
}
public static long ReverseBits64(long value) => (long)ReverseBits64((ulong)value);
public static int Pow2RoundUp(int value) public static int Pow2RoundUp(int value)
{ {
@ -35,16 +30,6 @@ namespace Ryujinx.Common
return ++value; return ++value;
} }
public static int Pow2RoundDown(int value)
{
return BitOperations.IsPow2(value) ? value : Pow2RoundUp(value) >> 1;
}
public static long ReverseBits64(long value)
{
return (long)ReverseBits64((ulong)value);
}
private static ulong ReverseBits64(ulong value) private static ulong ReverseBits64(ulong value)
{ {
value = ((value & 0xaaaaaaaaaaaaaaaa) >> 1) | ((value & 0x5555555555555555) << 1); value = ((value & 0xaaaaaaaaaaaaaaaa) >> 1) | ((value & 0x5555555555555555) << 1);

View File

@ -243,7 +243,7 @@ namespace Ryujinx.Graphics.OpenGL
// This is required to disable [0, 1] clamping for SNorm outputs on compatibility profiles. // This is required to disable [0, 1] clamping for SNorm outputs on compatibility profiles.
// This call is expected to fail if we're running with a core profile, // This call is expected to fail if we're running with a core profile,
// as this clamp target was deprecated, but that's fine as a core profile // as this clamp target was deprecated, but that's fine as a core profile
// should already have the desired behaviour were outputs are not clamped. // should already have the desired behaviour where outputs are not clamped.
GL.ClampColor(ClampColorTarget.ClampFragmentColor, ClampColorMode.False); GL.ClampColor(ClampColorTarget.ClampFragmentColor, ClampColorMode.False);
} }

View File

@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Texture
if (subsetCount == 0) if (subsetCount == 0)
{ {
// Mode is invalid, the spec mandates that hardware fills the block with // Mode is invalid, the spec mandates that hardware fills the block with
// a opaque black color. // an opaque black color.
for (int ty = 0; ty < h; ty++) for (int ty = 0; ty < h; ty++)
{ {
int baseOffs = ty * width; int baseOffs = ty * width;

View File

@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Texture
private readonly BlockLinearLayout _layoutConverter; private readonly BlockLinearLayout _layoutConverter;
// Variables for built in iteration. // Variables for built-in iteration.
private int _yPart; private int _yPart;
public OffsetCalculator( public OffsetCalculator(
@ -73,69 +73,50 @@ namespace Ryujinx.Graphics.Texture
public int GetOffset(int x, int y) public int GetOffset(int x, int y)
{ {
if (_isLinear) if (_isLinear)
{
return x * _bytesPerPixel + y * _stride; return x * _bytesPerPixel + y * _stride;
}
else return _layoutConverter.GetOffset(x, y, 0);
{
return _layoutConverter.GetOffset(x, y, 0);
}
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetOffset(int x) public int GetOffset(int x)
{ {
if (_isLinear) if (_isLinear)
{
return x * _bytesPerPixel + _yPart; return x * _bytesPerPixel + _yPart;
}
else return _layoutConverter.GetOffset(x);
{
return _layoutConverter.GetOffset(x);
}
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetOffsetWithLineOffset64(int x) public int GetOffsetWithLineOffset64(int x)
{ {
if (_isLinear) if (_isLinear)
{
return x + _yPart; return x + _yPart;
}
else return _layoutConverter.GetOffsetWithLineOffset64(x);
{
return _layoutConverter.GetOffsetWithLineOffset64(x);
}
} }
public (int offset, int size) GetRectangleRange(int x, int y, int width, int height) public (int offset, int size) GetRectangleRange(int x, int y, int width, int height)
{ {
if (_isLinear) if (!_isLinear)
{
int start = y * Math.Abs(_stride) + x * _bytesPerPixel;
int end = (y + height - 1) * Math.Abs(_stride) + (x + width) * _bytesPerPixel;
return (y * _stride + x * _bytesPerPixel, end - start);
}
else
{
return _layoutConverter.GetRectangleRange(x, y, width, height); return _layoutConverter.GetRectangleRange(x, y, width, height);
}
int start = y * Math.Abs(_stride) + x * _bytesPerPixel;
int end = (y + height - 1) * Math.Abs(_stride) + (x + width) * _bytesPerPixel;
return (y * _stride + x * _bytesPerPixel, end - start);
} }
public bool LayoutMatches(OffsetCalculator other) public bool LayoutMatches(OffsetCalculator other)
{ {
if (_isLinear) if (_isLinear)
{
return other._isLinear && return other._isLinear &&
_width == other._width && _width == other._width &&
_height == other._height && _height == other._height &&
_stride == other._stride && _stride == other._stride &&
_bytesPerPixel == other._bytesPerPixel; _bytesPerPixel == other._bytesPerPixel;
}
else
{ return !other._isLinear && _layoutConverter.LayoutMatches(other._layoutConverter);
return !other._isLinear && _layoutConverter.LayoutMatches(other._layoutConverter);
}
} }
} }
} }

View File

@ -25,7 +25,7 @@ namespace Ryujinx.HLE.Generators
var name = GetFullName(className, context).Replace("global::", ""); var name = GetFullName(className, context).Replace("global::", "");
if (!name.StartsWith("Ryujinx.HLE.HOS.Services")) if (!name.StartsWith("Ryujinx.HLE.HOS.Services"))
continue; continue;
var constructors = className.ChildNodes().Where(x => x.IsKind(SyntaxKind.ConstructorDeclaration)).Select(y => y as ConstructorDeclarationSyntax); var constructors = className.ChildNodes().Where(x => x.IsKind(SyntaxKind.ConstructorDeclaration)).Select(y => y as ConstructorDeclarationSyntax).ToArray();
if (!constructors.Any(x => x.ParameterList.Parameters.Count >= 1)) if (!constructors.Any(x => x.ParameterList.Parameters.Count >= 1))
continue; continue;

View File

@ -15,7 +15,10 @@ namespace Ryujinx.UI.Common
{ {
public static Timestamps StartedAt { get; set; } public static Timestamps StartedAt { get; set; }
private static readonly string _description = $"v{ReleaseInformation.Version} {ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}@{ReleaseInformation.BuildGitHash}"; private static readonly string _description = ReleaseInformation.IsValid
? $"v{ReleaseInformation.Version} {ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}@{ReleaseInformation.BuildGitHash}"
: "dev build";
private const string ApplicationId = "1293250299716173864"; private const string ApplicationId = "1293250299716173864";
private const int ApplicationByteLimit = 128; private const int ApplicationByteLimit = 128;
@ -76,7 +79,7 @@ namespace Ryujinx.UI.Common
SmallImageText = TruncateToByteLength(_description) SmallImageText = TruncateToByteLength(_description)
}, },
Details = TruncateToByteLength($"Playing {appMeta.Title}"), Details = TruncateToByteLength($"Playing {appMeta.Title}"),
State = appMeta.LastPlayed.HasValue State = appMeta.LastPlayed.HasValue && appMeta.TimePlayed.TotalSeconds > 5
? $"Total play time: {appMeta.TimePlayed.Humanize(2, false)}" ? $"Total play time: {appMeta.TimePlayed.Humanize(2, false)}"
: "Never played", : "Never played",
Timestamps = Timestamps.Now Timestamps = Timestamps.Now
@ -115,7 +118,8 @@ namespace Ryujinx.UI.Common
_discordClient?.Dispose(); _discordClient?.Dispose();
} }
private static readonly string[] _discordGameAssetKeys = [ private static readonly string[] _discordGameAssetKeys =
[
"01002da013484000", // The Legend of Zelda: Skyward Sword HD "01002da013484000", // The Legend of Zelda: Skyward Sword HD
"01007ef00011e000", // The Legend of Zelda: Breath of the Wild "01007ef00011e000", // The Legend of Zelda: Breath of the Wild
"0100f2c0115b6000", // The Legend of Zelda: Tears of the Kingdom "0100f2c0115b6000", // The Legend of Zelda: Tears of the Kingdom
@ -145,9 +149,12 @@ namespace Ryujinx.UI.Common
"0100c2500fc20000", // Splatoon 3 "0100c2500fc20000", // Splatoon 3
"0100ba0018500000", // Splatoon 3: Splatfest World Premiere "0100ba0018500000", // Splatoon 3: Splatfest World Premiere
"01000a10041ea000", // The Elder Scrolls V: Skyrim
"01007820196a6000", // Red Dead Redemption "01007820196a6000", // Red Dead Redemption
"0100744001588000", // Cars 3: Driven to Win "0100744001588000", // Cars 3: Driven to Win
"01002b00111a2000", // Hyrule Warriors: Age of Calamity
"01006f8002326000", // Animal Crossing: New Horizons "01006f8002326000", // Animal Crossing: New Horizons
"01004d300c5ae000", // Kirby and the Forgotten Land
"0100853015e86000", // No Man's Sky "0100853015e86000", // No Man's Sky
"01008d100d43e000", // Saints Row IV "01008d100d43e000", // Saints Row IV
"0100de600beee000", // Saints Row: The Third - The Full Package "0100de600beee000", // Saints Row: The Third - The Full Package

View File

@ -10,20 +10,7 @@ namespace Ryujinx.Ava.UI.Controls
protected override void OnPointerWheelChanged(PointerWheelEventArgs e) protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
{ {
var newValue = Value + e.Delta.Y * TickFrequency; Value = Math.Clamp(Value + e.Delta.Y * TickFrequency, Minimum, Maximum);
if (newValue < Minimum)
{
Value = Minimum;
}
else if (newValue > Maximum)
{
Value = Maximum;
}
else
{
Value = newValue;
}
e.Handled = true; e.Handled = true;
} }

View File

@ -230,6 +230,16 @@ namespace Ryujinx.Ava.UI.Helpers
primaryButtonResult); primaryButtonResult);
} }
internal static async Task<UserResult> CreateLocalizedConfirmationDialog(
string primaryText,
string secondaryText) =>
await CreateConfirmationDialog(
primaryText,
secondaryText,
LocaleManager.Instance[LocaleKeys.InputDialogYes],
LocaleManager.Instance[LocaleKeys.InputDialogNo],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
internal static async Task CreateUpdaterInfoDialog(string primary, string secondaryText) internal static async Task CreateUpdaterInfoDialog(string primary, string secondaryText)
{ {
await ShowTextDialog( await ShowTextDialog(

View File

@ -1,4 +1,4 @@
<UserControl <UserControl
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@ -22,13 +22,8 @@
VerticalAlignment="Bottom" VerticalAlignment="Bottom"
Background="{DynamicResource ThemeContentBackgroundColor}" Background="{DynamicResource ThemeContentBackgroundColor}"
DockPanel.Dock="Bottom" DockPanel.Dock="Bottom"
IsVisible="{Binding ShowMenuAndStatusBar}"> IsVisible="{Binding ShowMenuAndStatusBar}"
<Grid.ColumnDefinitions> ColumnDefinitions="Auto,Auto,*,Auto">
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel <StackPanel
Grid.Column="0" Grid.Column="0"
Margin="5" Margin="5"

View File

@ -50,10 +50,8 @@ namespace Ryujinx.Ava.UI.Windows
private void Button_OnClick(object sender, RoutedEventArgs e) private void Button_OnClick(object sender, RoutedEventArgs e)
{ {
if (sender is Button { Tag: { } url }) if (sender is Button { Tag: string url })
{ OpenHelper.OpenUrl(url);
OpenHelper.OpenUrl(url.ToString());
}
} }
private void AmiiboLabel_OnPointerPressed(object sender, PointerPressedEventArgs e) private void AmiiboLabel_OnPointerPressed(object sender, PointerPressedEventArgs e)

View File

@ -19,20 +19,12 @@ namespace Ryujinx.Ava.UI.Windows
private const int CutOffLuminosity = 64; private const int CutOffLuminosity = 64;
private readonly struct PaletteColor private readonly struct PaletteColor(int qck, byte r, byte g, byte b)
{ {
public int Qck { get; } public int Qck { get; } = qck;
public byte R { get; } public byte R { get; } = r;
public byte G { get; } public byte G { get; } = g;
public byte B { get; } public byte B { get; } = b;
public PaletteColor(int qck, byte r, byte g, byte b)
{
Qck = qck;
R = r;
G = g;
B = b;
}
} }
public static SKColor GetFilteredColor(SKBitmap image) public static SKColor GetFilteredColor(SKBitmap image)
@ -164,16 +156,6 @@ namespace Ryujinx.Ava.UI.Windows
return score; return score;
} }
private static int BalanceHitCount(int hitCount, int maxHitCount)
{
return (hitCount << 8) / maxHitCount;
}
private static int GetColorApproximateLuminosity(byte r, byte g, byte b)
{
return (r + g + b) / 3;
}
private static int GetColorSaturation(PaletteColor color) private static int GetColorSaturation(PaletteColor color)
{ {
int cMax = Math.Max(Math.Max(color.R, color.G), color.B); int cMax = Math.Max(Math.Max(color.R, color.G), color.B);
@ -188,10 +170,11 @@ namespace Ryujinx.Ava.UI.Windows
return (delta << 8) / cMax; return (delta << 8) / cMax;
} }
private static int GetColorValue(PaletteColor color) private static int GetColorValue(PaletteColor color) => Math.Max(Math.Max(color.R, color.G), color.B);
{
return Math.Max(Math.Max(color.R, color.G), color.B); private static int BalanceHitCount(int hitCount, int maxHitCount) => (hitCount << 8) / maxHitCount;
}
private static int GetColorApproximateLuminosity(byte r, byte g, byte b) => (r + g + b) / 3;
private static int GetQuantizedColorKey(byte r, byte g, byte b) private static int GetQuantizedColorKey(byte r, byte g, byte b)
{ {