mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-06-28 06:46:24 +02:00
parent
417df486b1
commit
361d0c5632
622 changed files with 3080 additions and 2652 deletions
|
@ -122,7 +122,7 @@ namespace Ryujinx.Common.Collections
|
|||
/// </summary>
|
||||
/// <param name="node">The node to search for RangeNodes within</param>
|
||||
/// <param name="list">The list to add RangeNodes to</param>
|
||||
private void AddToList(IntervalTreeNode<TKey, TValue> node, List<RangeNode<TKey, TValue>> list)
|
||||
private static void AddToList(IntervalTreeNode<TKey, TValue> node, List<RangeNode<TKey, TValue>> list)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
|
@ -163,6 +163,7 @@ namespace Ryujinx.Common.Collections
|
|||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -173,7 +174,7 @@ namespace Ryujinx.Common.Collections
|
|||
/// <param name="end">End of the range</param>
|
||||
/// <param name="overlaps">Overlaps array to place results in</param>
|
||||
/// <param name="overlapCount">Overlaps count to update</param>
|
||||
private void GetValues(IntervalTreeNode<TKey, TValue> node, TKey start, TKey end, ref TValue[] overlaps, ref int overlapCount)
|
||||
private static void GetValues(IntervalTreeNode<TKey, TValue> node, TKey start, TKey end, ref TValue[] overlaps, ref int overlapCount)
|
||||
{
|
||||
if (node == null || start.CompareTo(node.Max) >= 0)
|
||||
{
|
||||
|
@ -313,6 +314,7 @@ namespace Ryujinx.Common.Collections
|
|||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
IntervalTreeNode<TKey, TValue> newNode = new(start, end, value, parent);
|
||||
if (newNode.Parent == null)
|
||||
{
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace Ryujinx.Common.Collections
|
|||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -112,6 +113,7 @@ namespace Ryujinx.Common.Collections
|
|||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
newNode.Parent = parent;
|
||||
if (parent == null)
|
||||
{
|
||||
|
@ -125,6 +127,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
parent.Right = newNode;
|
||||
}
|
||||
|
||||
Count++;
|
||||
return newNode;
|
||||
}
|
||||
|
@ -274,6 +277,7 @@ namespace Ryujinx.Common.Collections
|
|||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,12 +39,14 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
return Minimum(node.Right);
|
||||
}
|
||||
|
||||
T parent = node.Parent;
|
||||
while (parent != null && node == parent.Right)
|
||||
{
|
||||
node = parent;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
@ -59,12 +61,14 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
return Maximum(node.Left);
|
||||
}
|
||||
|
||||
T parent = node.Parent;
|
||||
while (parent != null && node == parent.Left)
|
||||
{
|
||||
node = parent;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
@ -120,6 +124,7 @@ namespace Ryujinx.Common.Collections
|
|||
RotateLeft(ParentOf(ptr));
|
||||
sibling = RightOf(ParentOf(ptr));
|
||||
}
|
||||
|
||||
if (ColorOf(LeftOf(sibling)) == Black && ColorOf(RightOf(sibling)) == Black)
|
||||
{
|
||||
SetColor(sibling, Red);
|
||||
|
@ -134,6 +139,7 @@ namespace Ryujinx.Common.Collections
|
|||
RotateRight(sibling);
|
||||
sibling = RightOf(ParentOf(ptr));
|
||||
}
|
||||
|
||||
SetColor(sibling, ColorOf(ParentOf(ptr)));
|
||||
SetColor(ParentOf(ptr), Black);
|
||||
SetColor(RightOf(sibling), Black);
|
||||
|
@ -152,6 +158,7 @@ namespace Ryujinx.Common.Collections
|
|||
RotateRight(ParentOf(ptr));
|
||||
sibling = LeftOf(ParentOf(ptr));
|
||||
}
|
||||
|
||||
if (ColorOf(RightOf(sibling)) == Black && ColorOf(LeftOf(sibling)) == Black)
|
||||
{
|
||||
SetColor(sibling, Red);
|
||||
|
@ -166,6 +173,7 @@ namespace Ryujinx.Common.Collections
|
|||
RotateLeft(sibling);
|
||||
sibling = LeftOf(ParentOf(ptr));
|
||||
}
|
||||
|
||||
SetColor(sibling, ColorOf(ParentOf(ptr)));
|
||||
SetColor(ParentOf(ptr), Black);
|
||||
SetColor(LeftOf(sibling), Black);
|
||||
|
@ -174,6 +182,7 @@ namespace Ryujinx.Common.Collections
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetColor(ptr, Black);
|
||||
}
|
||||
|
||||
|
@ -200,6 +209,7 @@ namespace Ryujinx.Common.Collections
|
|||
balanceNode = ParentOf(balanceNode);
|
||||
RotateLeft(balanceNode);
|
||||
}
|
||||
|
||||
SetColor(ParentOf(balanceNode), Black);
|
||||
SetColor(ParentOf(ParentOf(balanceNode)), Red);
|
||||
RotateRight(ParentOf(ParentOf(balanceNode)));
|
||||
|
@ -223,12 +233,14 @@ namespace Ryujinx.Common.Collections
|
|||
balanceNode = ParentOf(balanceNode);
|
||||
RotateRight(balanceNode);
|
||||
}
|
||||
|
||||
SetColor(ParentOf(balanceNode), Black);
|
||||
SetColor(ParentOf(ParentOf(balanceNode)), Red);
|
||||
RotateLeft(ParentOf(ParentOf(balanceNode)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetColor(Root, Black);
|
||||
}
|
||||
|
||||
|
@ -242,6 +254,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
node.Right.Parent = node;
|
||||
}
|
||||
|
||||
T nodeParent = ParentOf(node);
|
||||
right.Parent = nodeParent;
|
||||
if (nodeParent == null)
|
||||
|
@ -256,6 +269,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
nodeParent.Right = right;
|
||||
}
|
||||
|
||||
right.Left = node;
|
||||
node.Parent = right;
|
||||
}
|
||||
|
@ -271,6 +285,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
node.Left.Parent = node;
|
||||
}
|
||||
|
||||
T nodeParent = ParentOf(node);
|
||||
left.Parent = nodeParent;
|
||||
if (nodeParent == null)
|
||||
|
@ -285,6 +300,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
nodeParent.Left = left;
|
||||
}
|
||||
|
||||
left.Right = node;
|
||||
node.Parent = left;
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
return node.Key;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
|
@ -94,6 +95,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
return node.Key;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
|
@ -111,6 +113,7 @@ namespace Ryujinx.Common.Collections
|
|||
|
||||
return successor != null ? successor.Key : default;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
|
@ -128,6 +131,7 @@ namespace Ryujinx.Common.Collections
|
|||
|
||||
return predecessor != null ? predecessor.Key : default;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
|
@ -147,6 +151,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
nodes.Enqueue(this.Root);
|
||||
}
|
||||
|
||||
while (nodes.TryDequeue(out Node<TKey, TValue> node))
|
||||
{
|
||||
list.Add(new KeyValuePair<TKey, TValue>(node.Key, node.Value));
|
||||
|
@ -154,11 +159,13 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
nodes.Enqueue(node.Left);
|
||||
}
|
||||
|
||||
if (node.Right != null)
|
||||
{
|
||||
nodes.Enqueue(node.Right);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -184,7 +191,7 @@ namespace Ryujinx.Common.Collections
|
|||
/// </summary>
|
||||
/// <param name="node">The node to search for nodes within</param>
|
||||
/// <param name="list">The list to add node to</param>
|
||||
private void AddToList(Node<TKey, TValue> node, List<KeyValuePair<TKey, TValue>> list)
|
||||
private static void AddToList(Node<TKey, TValue> node, List<KeyValuePair<TKey, TValue>> list)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
|
@ -225,6 +232,7 @@ namespace Ryujinx.Common.Collections
|
|||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -274,6 +282,7 @@ namespace Ryujinx.Common.Collections
|
|||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
Node<TKey, TValue> newNode = new(key, value, parent);
|
||||
if (newNode.Parent == null)
|
||||
{
|
||||
|
@ -287,6 +296,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
parent.Right = newNode;
|
||||
}
|
||||
|
||||
Count++;
|
||||
return newNode;
|
||||
}
|
||||
|
@ -392,6 +402,7 @@ namespace Ryujinx.Common.Collections
|
|||
ptr = parent;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
@ -400,6 +411,7 @@ namespace Ryujinx.Common.Collections
|
|||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -444,6 +456,7 @@ namespace Ryujinx.Common.Collections
|
|||
ptr = parent;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
@ -452,6 +465,7 @@ namespace Ryujinx.Common.Collections
|
|||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -502,6 +516,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
return node.Key.Equals(item.Key) && node.Value.Equals(item.Value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -588,6 +603,7 @@ namespace Ryujinx.Common.Collections
|
|||
{
|
||||
queue.Enqueue(node.Left);
|
||||
}
|
||||
|
||||
if (null != node.Right)
|
||||
{
|
||||
queue.Enqueue(node.Right);
|
||||
|
|
|
@ -280,6 +280,7 @@ namespace Ryujinx.Common.Configuration
|
|||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Unable to resolve the symlink for Ryujinx application data: {symlinkException}. Follow the symlink at {correctApplicationDataDirectoryPath} and move your data back to the Application Support folder.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -304,6 +305,7 @@ namespace Ryujinx.Common.Configuration
|
|||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Unable to resolve the symlink for Ryujinx application data: {symlinkException}. Follow the symlink at {correctApplicationDataDirectoryPath} and move your data back to the Application Support folder.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,8 +35,8 @@ namespace Ryujinx.Common.Configuration
|
|||
#pragma warning restore IDE0055
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static float ToFloatY(this AspectRatio aspectRatio)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Gommon;
|
||||
using Gommon;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -17,9 +17,9 @@ namespace Ryujinx.Common.Configuration
|
|||
{
|
||||
public DirtyHack Hack => hack;
|
||||
public int Value => value;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public ulong Pack() => Raw.PackBitFields(PackedFormat);
|
||||
|
||||
public static EnabledDirtyHack Unpack(ulong packedHack)
|
||||
|
@ -28,26 +28,26 @@ namespace Ryujinx.Common.Configuration
|
|||
// ReSharper disable once PatternAlwaysMatches
|
||||
if (unpackedFields is not [uint hack, uint value])
|
||||
throw new Exception("The unpack operation on the integer resulted in an invalid unpacked result.");
|
||||
|
||||
|
||||
return new EnabledDirtyHack((DirtyHack)hack, (int)value);
|
||||
}
|
||||
|
||||
|
||||
private uint[] Raw => [(uint)Hack, (uint)Value.CoerceAtLeast(0)];
|
||||
|
||||
|
||||
public static readonly byte[] PackedFormat = [8, 32];
|
||||
}
|
||||
|
||||
public class DirtyHacks : Dictionary<DirtyHack, int>
|
||||
{
|
||||
public DirtyHacks(IEnumerable<EnabledDirtyHack> hacks)
|
||||
public DirtyHacks(IEnumerable<EnabledDirtyHack> hacks)
|
||||
=> hacks.ForEach(edh => Add(edh.Hack, edh.Value));
|
||||
|
||||
public DirtyHacks(ulong[] packedHacks) : this(packedHacks.Select(EnabledDirtyHack.Unpack)) {}
|
||||
public DirtyHacks(ulong[] packedHacks) : this(packedHacks.Select(EnabledDirtyHack.Unpack)) { }
|
||||
|
||||
public ulong[] PackEntries()
|
||||
public ulong[] PackEntries()
|
||||
=> Entries.Select(it => it.Pack()).ToArray();
|
||||
|
||||
public EnabledDirtyHack[] Entries
|
||||
|
||||
public EnabledDirtyHack[] Entries
|
||||
=> this
|
||||
.Select(it => new EnabledDirtyHack(it.Key, it.Value))
|
||||
.ToArray();
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
|
|||
/// Controller Rumble Settings
|
||||
/// </summary>
|
||||
public RumbleConfigController Rumble { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Controller LED Settings
|
||||
/// </summary>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||
{
|
||||
public class JoyconConfigControllerStick<TButton, TStick>
|
||||
where TButton : unmanaged
|
||||
public class JoyconConfigControllerStick<TButton, TStick>
|
||||
where TButton : unmanaged
|
||||
where TStick : unmanaged
|
||||
{
|
||||
public TStick Joystick { get; set; }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||
{
|
||||
public class LedConfigController
|
||||
{
|
||||
|
@ -6,17 +6,17 @@
|
|||
/// Enable LED color changing by the emulator
|
||||
/// </summary>
|
||||
public bool EnableLed { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the color and disables the LED entirely.
|
||||
/// </summary>
|
||||
public bool TurnOffLed { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the color and uses the rainbow color functionality for the LED.
|
||||
/// </summary>
|
||||
public bool UseRainbow { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Packed RGB int of the color
|
||||
/// </summary>
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace Ryujinx.Common.Configuration
|
|||
Unbounded,
|
||||
Custom
|
||||
}
|
||||
|
||||
|
||||
public static class VSyncModeExtensions
|
||||
{
|
||||
public static VSyncMode Next(this VSyncMode vsync, bool customEnabled = false) =>
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
|||
int index = text.IndexOf('\0');
|
||||
if (index > -1)
|
||||
{
|
||||
text = text.Remove(index);
|
||||
text = text[..index];
|
||||
}
|
||||
|
||||
return text;
|
||||
|
|
|
@ -528,7 +528,7 @@ namespace Ryujinx.Common
|
|||
|
||||
private static Hash128 Xxh3Len1To3128b(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret, ulong seed)
|
||||
{
|
||||
Debug.Assert(1 <= input.Length && input.Length <= 3);
|
||||
Debug.Assert(input.Length is >= 1 and <= 3);
|
||||
|
||||
byte c1 = input[0];
|
||||
byte c2 = input[input.Length >> 1];
|
||||
|
@ -550,7 +550,7 @@ namespace Ryujinx.Common
|
|||
|
||||
private static Hash128 Xxh3Len4To8128b(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret, ulong seed)
|
||||
{
|
||||
Debug.Assert(4 <= input.Length && input.Length <= 8);
|
||||
Debug.Assert(input.Length is >= 4 and <= 8);
|
||||
|
||||
seed ^= BinaryPrimitives.ReverseEndianness((uint)seed) << 32;
|
||||
|
||||
|
@ -575,7 +575,7 @@ namespace Ryujinx.Common
|
|||
|
||||
private static Hash128 Xxh3Len9To16128b(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret, ulong seed)
|
||||
{
|
||||
Debug.Assert(9 <= input.Length && input.Length <= 16);
|
||||
Debug.Assert(input.Length is >= 9 and <= 16);
|
||||
|
||||
ulong bitFlipL = (BinaryPrimitives.ReadUInt64LittleEndian(secret[32..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[40..])) - seed;
|
||||
ulong bitFlipH = (BinaryPrimitives.ReadUInt64LittleEndian(secret[48..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[56..])) + seed;
|
||||
|
@ -647,7 +647,7 @@ namespace Ryujinx.Common
|
|||
private static Hash128 Xxh3Len17To128128b(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret, ulong seed)
|
||||
{
|
||||
Debug.Assert(secret.Length >= SecretSizeMin);
|
||||
Debug.Assert(16 < input.Length && input.Length <= 128);
|
||||
Debug.Assert(input.Length is > 16 and <= 128);
|
||||
|
||||
Hash128 acc = new()
|
||||
{
|
||||
|
@ -663,10 +663,13 @@ namespace Ryujinx.Common
|
|||
{
|
||||
acc = Xxh128Mix32b(acc, input[48..], input[^64..], secret[96..], seed);
|
||||
}
|
||||
|
||||
acc = Xxh128Mix32b(acc, input[32..], input[^48..], secret[64..], seed);
|
||||
}
|
||||
|
||||
acc = Xxh128Mix32b(acc, input[16..], input[^32..], secret[32..], seed);
|
||||
}
|
||||
|
||||
acc = Xxh128Mix32b(acc, input, input[^16..], secret, seed);
|
||||
|
||||
Hash128 h128 = new()
|
||||
|
@ -683,7 +686,7 @@ namespace Ryujinx.Common
|
|||
private static Hash128 Xxh3Len129To240128b(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret, ulong seed)
|
||||
{
|
||||
Debug.Assert(secret.Length >= SecretSizeMin);
|
||||
Debug.Assert(128 < input.Length && input.Length <= 240);
|
||||
Debug.Assert(input.Length is > 128 and <= 240);
|
||||
|
||||
Hash128 acc = new();
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Ryujinx.Common.Helper
|
|||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("user32")]
|
||||
private static partial nint GetForegroundWindow();
|
||||
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("user32")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Ryujinx.Common.Helper
|
|||
public static partial void SHChangeNotify(uint wEventId, uint uFlags, nint dwItem1, nint dwItem2);
|
||||
|
||||
public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows());
|
||||
|
||||
|
||||
public static bool AreMimeTypesRegistered
|
||||
{
|
||||
get
|
||||
|
@ -92,21 +92,21 @@ namespace Ryujinx.Common.Helper
|
|||
[SupportedOSPlatform("windows")]
|
||||
private static bool AreMimeTypesRegisteredWindows()
|
||||
{
|
||||
return _fileExtensions.Aggregate(false,
|
||||
return _fileExtensions.Aggregate(false,
|
||||
(current, ext) => current | CheckRegistering(ext)
|
||||
);
|
||||
|
||||
|
||||
static bool CheckRegistering(string ext)
|
||||
{
|
||||
RegistryKey key = Registry.CurrentUser.OpenSubKey(@$"Software\Classes\{ext}");
|
||||
|
||||
RegistryKey openCmd = key?.OpenSubKey(@"shell\open\command");
|
||||
|
||||
|
||||
if (openCmd is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
string keyValue = (string)openCmd.GetValue(string.Empty);
|
||||
|
||||
return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName));
|
||||
|
@ -116,7 +116,7 @@ namespace Ryujinx.Common.Helper
|
|||
[SupportedOSPlatform("windows")]
|
||||
private static bool InstallWindowsMimeTypes(bool uninstall = false)
|
||||
{
|
||||
bool registered = _fileExtensions.Aggregate(false,
|
||||
bool registered = _fileExtensions.Aggregate(false,
|
||||
(current, ext) => current | RegisterExtension(ext, uninstall)
|
||||
);
|
||||
|
||||
|
@ -124,7 +124,7 @@ namespace Ryujinx.Common.Helper
|
|||
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, nint.Zero, nint.Zero);
|
||||
|
||||
return registered;
|
||||
|
||||
|
||||
static bool RegisterExtension(string ext, bool uninstall = false)
|
||||
{
|
||||
string keyString = @$"Software\Classes\{ext}";
|
||||
|
@ -136,6 +136,7 @@ namespace Ryujinx.Common.Helper
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Logger.Debug?.Print(LogClass.Application, $"Removing type association {ext}");
|
||||
Registry.CurrentUser.DeleteSubKeyTree(keyString);
|
||||
Logger.Debug?.Print(LogClass.Application, $"Removed type association {ext}");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Text.RegularExpressions;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Ryujinx.Common.Helper
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Gommon;
|
||||
using Gommon;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
|
@ -7,10 +7,10 @@ namespace Ryujinx.Common.Helper
|
|||
public class RefEvent<T>
|
||||
{
|
||||
public delegate void Handler(ref T arg);
|
||||
|
||||
|
||||
private readonly Lock _subLock = new();
|
||||
private readonly List<Handler> _subscriptions = [];
|
||||
|
||||
|
||||
public bool HasSubscribers
|
||||
{
|
||||
get
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
@ -9,14 +9,14 @@ namespace Ryujinx.Common.Helper
|
|||
{
|
||||
MacOS,
|
||||
Linux,
|
||||
Windows
|
||||
Windows
|
||||
}
|
||||
|
||||
|
||||
public static class RunningPlatform
|
||||
{
|
||||
public static readonly OperatingSystemType CurrentOS
|
||||
= IsMacOS
|
||||
? OperatingSystemType.MacOS
|
||||
public static readonly OperatingSystemType CurrentOS
|
||||
= IsMacOS
|
||||
? OperatingSystemType.MacOS
|
||||
: IsWindows
|
||||
? OperatingSystemType.Windows
|
||||
: IsLinux
|
||||
|
@ -25,21 +25,21 @@ namespace Ryujinx.Common.Helper
|
|||
|
||||
public static Architecture Architecture => RuntimeInformation.OSArchitecture;
|
||||
public static Architecture CurrentProcessArchitecture => RuntimeInformation.ProcessArchitecture;
|
||||
|
||||
|
||||
public static bool IsMacOS => OperatingSystem.IsMacOS();
|
||||
public static bool IsWindows => OperatingSystem.IsWindows();
|
||||
public static bool IsLinux => OperatingSystem.IsLinux();
|
||||
|
||||
|
||||
public static bool IsArm => Architecture is Architecture.Arm64;
|
||||
|
||||
|
||||
public static bool IsX64 => Architecture is Architecture.X64;
|
||||
|
||||
public static bool IsIntelMac => IsMacOS && IsX64;
|
||||
public static bool IsArmMac => IsMacOS && IsArm;
|
||||
|
||||
|
||||
public static bool IsX64Windows => IsWindows && IsX64;
|
||||
public static bool IsArmWindows => IsWindows && IsArm;
|
||||
|
||||
|
||||
public static bool IsX64Linux => IsLinux && IsX64;
|
||||
public static bool IsArmLinux => IsLinux && IsArmMac;
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ namespace Ryujinx.Common.Logging
|
|||
_time.Restart();
|
||||
}
|
||||
|
||||
private static ILogTarget GetTarget(string targetName)
|
||||
private static ILogTarget GetTarget(string targetName)
|
||||
=> _logTargets.FirstOrDefault(target => target.Name.Equals(targetName));
|
||||
|
||||
public static void AddTarget(ILogTarget target)
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Ryujinx.Common.Logging.Targets
|
|||
{
|
||||
public class ConsoleLogTarget : ILogTarget
|
||||
{
|
||||
private readonly ILogFormatter _formatter;
|
||||
private readonly DefaultLogFormatter _formatter;
|
||||
|
||||
private readonly string _name;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Common.Logging.Targets
|
|||
public class FileLogTarget : ILogTarget
|
||||
{
|
||||
private readonly StreamWriter _logWriter;
|
||||
private readonly ILogFormatter _formatter;
|
||||
private readonly DefaultLogFormatter _formatter;
|
||||
private readonly string _name;
|
||||
|
||||
string ILogTarget.Name { get => _name; }
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace Ryujinx.Common.PreciseSleep
|
|||
// Too many threads on the pool.
|
||||
return false;
|
||||
}
|
||||
|
||||
_waitEvent.WaitOne(1);
|
||||
_pool.IgnoreSignal();
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ namespace Ryujinx.Common
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LogChangesToValue(string valueName, LogClass logClass = LogClass.Configuration)
|
||||
|
||||
public void LogChangesToValue(string valueName, LogClass logClass = LogClass.Configuration)
|
||||
=> Event += (_, e) => ReactiveObjectHelper.LogValueChange(logClass, e, valueName);
|
||||
|
||||
public static implicit operator T(ReactiveObject<T> obj) => obj.Value;
|
||||
|
@ -55,12 +55,12 @@ namespace Ryujinx.Common
|
|||
{
|
||||
if (eventArgs.AreValuesEqual)
|
||||
return;
|
||||
|
||||
|
||||
string message = string.Create(CultureInfo.InvariantCulture, $"{valueName} set to: {eventArgs.NewValue}");
|
||||
|
||||
Logger.Info?.Print(logClass, message);
|
||||
}
|
||||
|
||||
|
||||
public static void Toggle(this ReactiveObject<bool> rBoolean) => rBoolean.Value = !rBoolean.Value;
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ namespace Ryujinx.Common
|
|||
|
||||
if (OldValue == null && NewValue != null)
|
||||
return false;
|
||||
|
||||
|
||||
if (OldValue != null && NewValue == null)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -27,19 +27,19 @@ namespace Ryujinx.Common
|
|||
!ConfigFileName.StartsWith("%%");
|
||||
|
||||
public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel);
|
||||
|
||||
|
||||
public static bool IsReleaseBuild => IsValid && ReleaseChannelName.Equals(ReleaseChannel);
|
||||
|
||||
public static string Version => IsValid ? BuildVersion : Assembly.GetEntryAssembly()!.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
||||
|
||||
public static string GetChangelogUrl(Version currentVersion, Version newVersion, ReleaseChannels.Channel releaseChannel) =>
|
||||
IsCanaryBuild
|
||||
IsCanaryBuild
|
||||
? $"https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-{currentVersion}...Canary-{newVersion}"
|
||||
: GetChangelogForVersion(newVersion, releaseChannel);
|
||||
|
||||
|
||||
public static string GetChangelogForVersion(Version version, ReleaseChannels.Channel releaseChannel) =>
|
||||
$"https://github.com/{releaseChannel}/releases/{version}";
|
||||
|
||||
|
||||
public static async Task<ReleaseChannels> GetReleaseChannelsAsync(HttpClient httpClient)
|
||||
{
|
||||
ReleaseChannelPair releaseChannelPair = await httpClient.GetFromJsonAsync("https://ryujinx.app/api/release-channels", ReleaseChannelPairContext.Default.ReleaseChannelPair);
|
||||
|
@ -57,7 +57,7 @@ namespace Ryujinx.Common
|
|||
|
||||
public readonly Channel Stable;
|
||||
public readonly Channel Canary;
|
||||
|
||||
|
||||
public readonly struct Channel
|
||||
{
|
||||
public Channel(string raw)
|
||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.Common
|
|||
Owner = parts[0];
|
||||
Repo = parts[1];
|
||||
}
|
||||
|
||||
|
||||
public readonly string Owner;
|
||||
public readonly string Repo;
|
||||
|
||||
|
@ -76,7 +76,7 @@ namespace Ryujinx.Common
|
|||
$"https://api.github.com/repos/{ToString()}/releases/latest";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[JsonSerializable(typeof(ReleaseChannelPair))]
|
||||
partial class ReleaseChannelPairContext : JsonSerializerContext;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Common
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace Ryujinx.Common
|
||||
namespace Ryujinx.Common
|
||||
{
|
||||
public static class SharedConstants
|
||||
{
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace Ryujinx.Common.SystemInterop
|
|||
{
|
||||
string xdgSessionType = Environment.GetEnvironmentVariable("XDG_SESSION_TYPE")?.ToLower();
|
||||
|
||||
if (xdgSessionType == null || xdgSessionType == "x11")
|
||||
if (xdgSessionType is null or "x11")
|
||||
{
|
||||
nint display = XOpenDisplay(null);
|
||||
string dpiString = Marshal.PtrToStringAnsi(XGetDefault(display, "Xft", "dpi"));
|
||||
|
@ -65,6 +65,7 @@ namespace Ryujinx.Common.SystemInterop
|
|||
{
|
||||
userDpiScale = XDisplayWidth(display, 0) * 25.4 / XDisplayWidthMM(display, 0);
|
||||
}
|
||||
|
||||
_ = XCloseDisplay(display);
|
||||
}
|
||||
else if (xdgSessionType == "wayland")
|
||||
|
|
|
@ -12,8 +12,8 @@ namespace Ryujinx.Common.SystemInterop
|
|||
public partial class StdErrAdapter : IDisposable
|
||||
{
|
||||
private bool _disposable;
|
||||
private Stream _pipeReader;
|
||||
private Stream _pipeWriter;
|
||||
private FileStream _pipeReader;
|
||||
private FileStream _pipeWriter;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
private Task _worker;
|
||||
|
||||
|
@ -46,7 +46,7 @@ namespace Ryujinx.Common.SystemInterop
|
|||
[SupportedOSPlatform("macos")]
|
||||
private async Task EventWorkerAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
using TextReader reader = new StreamReader(_pipeReader, leaveOpen: true);
|
||||
using StreamReader reader = new(_pipeReader, leaveOpen: true);
|
||||
string line;
|
||||
while (cancellationToken.IsCancellationRequested == false && (line = await reader.ReadLineAsync(cancellationToken)) != null)
|
||||
{
|
||||
|
@ -92,13 +92,12 @@ namespace Ryujinx.Common.SystemInterop
|
|||
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
private static Stream CreateFileDescriptorStream(int fd)
|
||||
private static FileStream CreateFileDescriptorStream(int fd)
|
||||
{
|
||||
return new FileStream(
|
||||
new SafeFileHandle(fd, ownsHandle: true),
|
||||
FileAccess.ReadWrite
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ namespace Ryujinx.Common
|
|||
public static class TitleIDs
|
||||
{
|
||||
public static ReactiveObject<Optional<string>> CurrentApplication { get; } = new();
|
||||
|
||||
public static string GetDiscordGameAsset(string titleId)
|
||||
|
||||
public static string GetDiscordGameAsset(string titleId)
|
||||
=> DiscordGameAssetKeys.Contains(titleId) ? titleId : "game";
|
||||
|
||||
public static readonly string[] DiscordGameAssetKeys =
|
||||
|
|
|
@ -40,10 +40,10 @@ namespace Ryujinx.Common
|
|||
|
||||
return (value >> 32) | (value << 32);
|
||||
}
|
||||
|
||||
|
||||
// Never actually written bit packing logic before, so I looked it up.
|
||||
// This code is from https://gist.github.com/Alan-FGR/04938e93e2bffdf5802ceb218a37c195
|
||||
|
||||
|
||||
public static ulong PackBitFields(this uint[] values, byte[] bitFields)
|
||||
{
|
||||
ulong retVal = values[0]; //we set the first value right away
|
||||
|
@ -52,6 +52,7 @@ namespace Ryujinx.Common
|
|||
retVal <<= bitFields[f]; // we shift the previous value
|
||||
retVal += values[f];// and add our current value
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -68,6 +69,7 @@ namespace Ryujinx.Common
|
|||
int leftShift = 64 - curPos; // we figure how much left shift we gotta apply for the other numbers to overflow into oblivion
|
||||
retArr[f] = (uint)((packed << leftShift) >> leftShift + lastEnd); // we do magic
|
||||
}
|
||||
|
||||
return retArr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace Ryujinx.Common.Utilities
|
|||
|
||||
public static string SanitizeFileName(string fileName)
|
||||
{
|
||||
HashSet<char> reservedChars = new(Path.GetInvalidFileNameChars());
|
||||
HashSet<char> reservedChars = [.. Path.GetInvalidFileNameChars()];
|
||||
return string.Concat(fileName.Select(c => reservedChars.Contains(c) ? '_' : c));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,13 +28,13 @@ namespace Ryujinx.Common.Utilities
|
|||
ReadCommentHandling = JsonCommentHandling.Skip
|
||||
};
|
||||
|
||||
public static string Serialize<T>(T value, JsonTypeInfo<T> typeInfo)
|
||||
public static string Serialize<T>(T value, JsonTypeInfo<T> typeInfo)
|
||||
=> JsonSerializer.Serialize(value, typeInfo);
|
||||
|
||||
public static T Deserialize<T>(string value, JsonTypeInfo<T> typeInfo)
|
||||
public static T Deserialize<T>(string value, JsonTypeInfo<T> typeInfo)
|
||||
=> JsonSerializer.Deserialize(value, typeInfo);
|
||||
|
||||
public static T Deserialize<T>(ReadOnlySpan<byte> utf8Value, JsonTypeInfo<T> typeInfo)
|
||||
public static T Deserialize<T>(ReadOnlySpan<byte> utf8Value, JsonTypeInfo<T> typeInfo)
|
||||
=> JsonSerializer.Deserialize<T>(utf8Value, typeInfo);
|
||||
|
||||
public static void SerializeToFile<T>(string filePath, T value, JsonTypeInfo<T> typeInfo)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Gommon;
|
||||
using Gommon;
|
||||
using Ryujinx.Common.Helper;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
@ -31,12 +31,12 @@ namespace Ryujinx.Common.Utilities
|
|||
{
|
||||
CyclingEnabled = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static float Speed { get; set; } = 1;
|
||||
|
||||
private static readonly Lock _lock = new();
|
||||
|
||||
|
||||
private static Color _color = Color.Blue;
|
||||
|
||||
public static ref Color Color
|
||||
|
@ -55,7 +55,7 @@ namespace Ryujinx.Common.Utilities
|
|||
lock (_lock)
|
||||
{
|
||||
_color = HsbToRgb((_color.GetHue() + Speed) / 360);
|
||||
|
||||
|
||||
_updatedHandler.Call(ref _color);
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ namespace Ryujinx.Common.Utilities
|
|||
public static void Reset()
|
||||
{
|
||||
_updatedHandler.Clear();
|
||||
|
||||
|
||||
lock (_lock)
|
||||
_color = Color.Blue;
|
||||
}
|
||||
|
@ -124,6 +124,7 @@ namespace Ryujinx.Common.Utilities
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Color.FromArgb(Convert.ToByte(255), Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace Ryujinx.Common.Utilities
|
|||
|
||||
public static async Task<byte[]> StreamToBytesAsync(Stream input, CancellationToken cancellationToken = default)
|
||||
{
|
||||
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
||||
using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
||||
|
||||
await input.CopyToAsync(stream, cancellationToken);
|
||||
|
||||
|
|
|
@ -183,7 +183,6 @@ namespace Ryujinx.Common.Utilities
|
|||
{
|
||||
CloseReaders();
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -205,7 +204,7 @@ namespace Ryujinx.Common.Utilities
|
|||
|
||||
while (true)
|
||||
{
|
||||
if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested)
|
||||
if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -257,7 +256,7 @@ namespace Ryujinx.Common.Utilities
|
|||
{
|
||||
return OperationOutcome.Cancelled;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
return OperationOutcome.FreeSpaceCheckFailed;
|
||||
}
|
||||
|
@ -294,7 +293,7 @@ namespace Ryujinx.Common.Utilities
|
|||
{
|
||||
|
||||
#if !XCI_TRIMMER_READ_ONLY_MODE
|
||||
outfileStream.SetLength(TrimmedFileSizeB);
|
||||
outfileStream.SetLength(TrimmedFileSizeB);
|
||||
#endif
|
||||
return OperationOutcome.Successful;
|
||||
}
|
||||
|
@ -367,7 +366,7 @@ namespace Ryujinx.Common.Utilities
|
|||
{
|
||||
return OperationOutcome.Cancelled;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
return OperationOutcome.Successful;
|
||||
}
|
||||
|
@ -404,9 +403,9 @@ namespace Ryujinx.Common.Utilities
|
|||
}
|
||||
|
||||
long bytesToWrite = Math.Min(XCIFileTrimmer.BufferSize, bytesLeftToWriteB);
|
||||
|
||||
|
||||
#if !XCI_TRIMMER_READ_ONLY_MODE
|
||||
outfileStream.Write(buffer, 0, (int)bytesToWrite);
|
||||
outfileStream.Write(buffer, 0, (int)bytesToWrite);
|
||||
#endif
|
||||
|
||||
bytesLeftToWriteB -= bytesToWrite;
|
||||
|
@ -511,6 +510,7 @@ namespace Ryujinx.Common.Utilities
|
|||
Log?.Write(LogType.Error, $"The source file doesn't look like an XCI file as the Cartridge Size is incorrect (0x{cartSizeId:X2})");
|
||||
return false;
|
||||
}
|
||||
|
||||
_cartSizeB = cartSizeNGB * XCIFileTrimmer.CartSizeMBinFormattedGB * XCIFileTrimmer.BytesInAMegabyte;
|
||||
|
||||
// Read data size
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue