forked from Mirror/Ryujinx
[Ryujinx.Common] Address dotnet-format issues (#5358)
* dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Silence dotnet format IDE0059 warnings * Address or silence dotnet format IDE1006 warnings * Address dotnet format CA1816 warnings * Address or silence dotnet format CA2211 warnings * Silence CA1806 and CA1834 issues * Fix formatting for switch expressions * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Revert formatting changes for while and for-loops * Format if-blocks correctly * Run dotnet format whitespace after rebase * Run dotnet format style after rebase * Run dotnet format analyzers after rebase * Run dotnet format after rebase and remove unused usings - analyzers - style - whitespace * Add comments to disabled warnings * Remove a few unused parameters * Replace MmeShadowScratch with Array256<uint> * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Run dotnet format after rebase * Address IDE0251 warnings * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * First dotnet format pass * Second dotnet format pass * Fix build issues * Fix StructArrayHelpers.cs * Apply suggestions from code review Co-authored-by: Ac_K <Acoustik666@gmail.com> * Fix return statements * Fix naming rule violations * Update src/Ryujinx.Common/Utilities/StreamUtils.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Add trailing commas * Address review feedback * Address review feedback * Rename remaining type parameters to TKey and TValue * Fix manual formatting for logging levels * Fix spacing before comments --------- Co-authored-by: Ac_K <Acoustik666@gmail.com>
This commit is contained in:
parent
0a75b73fa4
commit
fc20d9b925
96 changed files with 965 additions and 969 deletions
|
@ -7,9 +7,9 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An Augmented Interval Tree based off of the "TreeDictionary"'s Red-Black Tree. Allows fast overlap checking of ranges.
|
/// An Augmented Interval Tree based off of the "TreeDictionary"'s Red-Black Tree. Allows fast overlap checking of ranges.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="K">Key</typeparam>
|
/// <typeparam name="TKey">Key</typeparam>
|
||||||
/// <typeparam name="V">Value</typeparam>
|
/// <typeparam name="TValue">Value</typeparam>
|
||||||
public class IntervalTree<K, V> : IntrusiveRedBlackTreeImpl<IntervalTreeNode<K, V>> where K : IComparable<K>
|
public class IntervalTree<TKey, TValue> : IntrusiveRedBlackTreeImpl<IntervalTreeNode<TKey, TValue>> where TKey : IComparable<TKey>
|
||||||
{
|
{
|
||||||
private const int ArrayGrowthSize = 32;
|
private const int ArrayGrowthSize = 32;
|
||||||
|
|
||||||
|
@ -22,11 +22,11 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="overlaps">Overlaps array to place results in</param>
|
/// <param name="overlaps">Overlaps array to place results in</param>
|
||||||
/// <returns>Number of values found</returns>
|
/// <returns>Number of values found</returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||||
public int Get(K key, ref V[] overlaps)
|
public int Get(TKey key, ref TValue[] overlaps)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
IntervalTreeNode<K, V> node = GetNode(key);
|
IntervalTreeNode<TKey, TValue> node = GetNode(key);
|
||||||
|
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
|
@ -39,7 +39,7 @@ namespace Ryujinx.Common.Collections
|
||||||
}
|
}
|
||||||
|
|
||||||
int overlapsCount = 0;
|
int overlapsCount = 0;
|
||||||
foreach (RangeNode<K, V> value in node.Values)
|
foreach (RangeNode<TKey, TValue> value in node.Values)
|
||||||
{
|
{
|
||||||
overlaps[overlapsCount++] = value.Value;
|
overlaps[overlapsCount++] = value.Value;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="overlapCount">Index to start writing results into the array. Defaults to 0</param>
|
/// <param name="overlapCount">Index to start writing results into the array. Defaults to 0</param>
|
||||||
/// <returns>Number of values found</returns>
|
/// <returns>Number of values found</returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="start"/> or <paramref name="end"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="start"/> or <paramref name="end"/> is null</exception>
|
||||||
public int Get(K start, K end, ref V[] overlaps, int overlapCount = 0)
|
public int Get(TKey start, TKey end, ref TValue[] overlaps, int overlapCount = 0)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(start);
|
ArgumentNullException.ThrowIfNull(start);
|
||||||
ArgumentNullException.ThrowIfNull(end);
|
ArgumentNullException.ThrowIfNull(end);
|
||||||
|
@ -73,7 +73,7 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="end">End of the range to insert</param>
|
/// <param name="end">End of the range to insert</param>
|
||||||
/// <param name="value">Value to add</param>
|
/// <param name="value">Value to add</param>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="start"/>, <paramref name="end"/> or <paramref name="value"/> are null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="start"/>, <paramref name="end"/> or <paramref name="value"/> are null</exception>
|
||||||
public void Add(K start, K end, V value)
|
public void Add(TKey start, TKey end, TValue value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(start);
|
ArgumentNullException.ThrowIfNull(start);
|
||||||
ArgumentNullException.ThrowIfNull(end);
|
ArgumentNullException.ThrowIfNull(end);
|
||||||
|
@ -89,7 +89,7 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="value">Value to remove</param>
|
/// <param name="value">Value to remove</param>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||||
/// <returns>Number of deleted values</returns>
|
/// <returns>Number of deleted values</returns>
|
||||||
public int Remove(K key, V value)
|
public int Remove(TKey key, TValue value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
|
@ -104,9 +104,9 @@ namespace Ryujinx.Common.Collections
|
||||||
/// Adds all the nodes in the dictionary into <paramref name="list"/>.
|
/// Adds all the nodes in the dictionary into <paramref name="list"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A list of all RangeNodes sorted by Key Order</returns>
|
/// <returns>A list of all RangeNodes sorted by Key Order</returns>
|
||||||
public List<RangeNode<K, V>> AsList()
|
public List<RangeNode<TKey, TValue>> AsList()
|
||||||
{
|
{
|
||||||
List<RangeNode<K, V>> list = new List<RangeNode<K, V>>();
|
List<RangeNode<TKey, TValue>> list = new();
|
||||||
|
|
||||||
AddToList(Root, list);
|
AddToList(Root, list);
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ namespace Ryujinx.Common.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node">The node to search for RangeNodes within</param>
|
/// <param name="node">The node to search for RangeNodes within</param>
|
||||||
/// <param name="list">The list to add RangeNodes to</param>
|
/// <param name="list">The list to add RangeNodes to</param>
|
||||||
private void AddToList(IntervalTreeNode<K, V> node, List<RangeNode<K, V>> list)
|
private void AddToList(IntervalTreeNode<TKey, TValue> node, List<RangeNode<TKey, TValue>> list)
|
||||||
{
|
{
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
|
@ -142,11 +142,11 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="key">Key of the node to get</param>
|
/// <param name="key">Key of the node to get</param>
|
||||||
/// <returns>Node reference in the tree</returns>
|
/// <returns>Node reference in the tree</returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||||
private IntervalTreeNode<K, V> GetNode(K key)
|
private IntervalTreeNode<TKey, TValue> GetNode(TKey key)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
IntervalTreeNode<K, V> node = Root;
|
IntervalTreeNode<TKey, TValue> node = Root;
|
||||||
while (node != null)
|
while (node != null)
|
||||||
{
|
{
|
||||||
int cmp = key.CompareTo(node.Start);
|
int cmp = key.CompareTo(node.Start);
|
||||||
|
@ -173,7 +173,7 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="end">End of the range</param>
|
/// <param name="end">End of the range</param>
|
||||||
/// <param name="overlaps">Overlaps array to place results in</param>
|
/// <param name="overlaps">Overlaps array to place results in</param>
|
||||||
/// <param name="overlapCount">Overlaps count to update</param>
|
/// <param name="overlapCount">Overlaps count to update</param>
|
||||||
private void GetValues(IntervalTreeNode<K, V> node, K start, K end, ref V[] overlaps, ref int overlapCount)
|
private void GetValues(IntervalTreeNode<TKey, TValue> node, TKey start, TKey end, ref TValue[] overlaps, ref int overlapCount)
|
||||||
{
|
{
|
||||||
if (node == null || start.CompareTo(node.Max) >= 0)
|
if (node == null || start.CompareTo(node.Max) >= 0)
|
||||||
{
|
{
|
||||||
|
@ -188,7 +188,7 @@ namespace Ryujinx.Common.Collections
|
||||||
if (start.CompareTo(node.End) < 0)
|
if (start.CompareTo(node.End) < 0)
|
||||||
{
|
{
|
||||||
// Contains this node. Add overlaps to list.
|
// Contains this node. Add overlaps to list.
|
||||||
foreach (RangeNode<K,V> overlap in node.Values)
|
foreach (RangeNode<TKey, TValue> overlap in node.Values)
|
||||||
{
|
{
|
||||||
if (start.CompareTo(overlap.End) < 0)
|
if (start.CompareTo(overlap.End) < 0)
|
||||||
{
|
{
|
||||||
|
@ -212,9 +212,9 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="start">Start of the range to insert</param>
|
/// <param name="start">Start of the range to insert</param>
|
||||||
/// <param name="end">End of the range to insert</param>
|
/// <param name="end">End of the range to insert</param>
|
||||||
/// <param name="value">Value to insert</param>
|
/// <param name="value">Value to insert</param>
|
||||||
private void Insert(K start, K end, V value)
|
private void Insert(TKey start, TKey end, TValue value)
|
||||||
{
|
{
|
||||||
IntervalTreeNode<K, V> newNode = BSTInsert(start, end, value);
|
IntervalTreeNode<TKey, TValue> newNode = BSTInsert(start, end, value);
|
||||||
RestoreBalanceAfterInsertion(newNode);
|
RestoreBalanceAfterInsertion(newNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,10 +223,10 @@ namespace Ryujinx.Common.Collections
|
||||||
/// This should only be called if the max increases - not for rebalancing or removals.
|
/// This should only be called if the max increases - not for rebalancing or removals.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node">The node to start propagating from</param>
|
/// <param name="node">The node to start propagating from</param>
|
||||||
private void PropagateIncrease(IntervalTreeNode<K, V> node)
|
private static void PropagateIncrease(IntervalTreeNode<TKey, TValue> node)
|
||||||
{
|
{
|
||||||
K max = node.Max;
|
TKey max = node.Max;
|
||||||
IntervalTreeNode<K, V> ptr = node;
|
IntervalTreeNode<TKey, TValue> ptr = node;
|
||||||
|
|
||||||
while ((ptr = ptr.Parent) != null)
|
while ((ptr = ptr.Parent) != null)
|
||||||
{
|
{
|
||||||
|
@ -246,13 +246,13 @@ namespace Ryujinx.Common.Collections
|
||||||
/// This fully recalculates the max value from all children when there is potential for it to decrease.
|
/// This fully recalculates the max value from all children when there is potential for it to decrease.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node">The node to start propagating from</param>
|
/// <param name="node">The node to start propagating from</param>
|
||||||
private void PropagateFull(IntervalTreeNode<K, V> node)
|
private static void PropagateFull(IntervalTreeNode<TKey, TValue> node)
|
||||||
{
|
{
|
||||||
IntervalTreeNode<K, V> ptr = node;
|
IntervalTreeNode<TKey, TValue> ptr = node;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
K max = ptr.End;
|
TKey max = ptr.End;
|
||||||
|
|
||||||
if (ptr.Left != null && ptr.Left.Max.CompareTo(max) > 0)
|
if (ptr.Left != null && ptr.Left.Max.CompareTo(max) > 0)
|
||||||
{
|
{
|
||||||
|
@ -278,10 +278,10 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="end">End of the range to insert</param>
|
/// <param name="end">End of the range to insert</param>
|
||||||
/// <param name="value">Value to insert</param>
|
/// <param name="value">Value to insert</param>
|
||||||
/// <returns>The inserted Node</returns>
|
/// <returns>The inserted Node</returns>
|
||||||
private IntervalTreeNode<K, V> BSTInsert(K start, K end, V value)
|
private IntervalTreeNode<TKey, TValue> BSTInsert(TKey start, TKey end, TValue value)
|
||||||
{
|
{
|
||||||
IntervalTreeNode<K, V> parent = null;
|
IntervalTreeNode<TKey, TValue> parent = null;
|
||||||
IntervalTreeNode<K, V> node = Root;
|
IntervalTreeNode<TKey, TValue> node = Root;
|
||||||
|
|
||||||
while (node != null)
|
while (node != null)
|
||||||
{
|
{
|
||||||
|
@ -297,7 +297,7 @@ namespace Ryujinx.Common.Collections
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node.Values.Add(new RangeNode<K, V>(start, end, value));
|
node.Values.Add(new RangeNode<TKey, TValue>(start, end, value));
|
||||||
|
|
||||||
if (end.CompareTo(node.End) > 0)
|
if (end.CompareTo(node.End) > 0)
|
||||||
{
|
{
|
||||||
|
@ -313,7 +313,7 @@ namespace Ryujinx.Common.Collections
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IntervalTreeNode<K, V> newNode = new IntervalTreeNode<K, V>(start, end, value, parent);
|
IntervalTreeNode<TKey, TValue> newNode = new(start, end, value, parent);
|
||||||
if (newNode.Parent == null)
|
if (newNode.Parent == null)
|
||||||
{
|
{
|
||||||
Root = newNode;
|
Root = newNode;
|
||||||
|
@ -338,9 +338,9 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="key">Key to search for</param>
|
/// <param name="key">Key to search for</param>
|
||||||
/// <param name="value">Value to delete</param>
|
/// <param name="value">Value to delete</param>
|
||||||
/// <returns>Number of deleted values</returns>
|
/// <returns>Number of deleted values</returns>
|
||||||
private int Delete(K key, V value)
|
private int Delete(TKey key, TValue value)
|
||||||
{
|
{
|
||||||
IntervalTreeNode<K, V> nodeToDelete = GetNode(key);
|
IntervalTreeNode<TKey, TValue> nodeToDelete = GetNode(key);
|
||||||
|
|
||||||
if (nodeToDelete == null)
|
if (nodeToDelete == null)
|
||||||
{
|
{
|
||||||
|
@ -362,7 +362,7 @@ namespace Ryujinx.Common.Collections
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntervalTreeNode<K, V> replacementNode;
|
IntervalTreeNode<TKey, TValue> replacementNode;
|
||||||
|
|
||||||
if (LeftOf(nodeToDelete) == null || RightOf(nodeToDelete) == null)
|
if (LeftOf(nodeToDelete) == null || RightOf(nodeToDelete) == null)
|
||||||
{
|
{
|
||||||
|
@ -373,7 +373,7 @@ namespace Ryujinx.Common.Collections
|
||||||
replacementNode = PredecessorOf(nodeToDelete);
|
replacementNode = PredecessorOf(nodeToDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntervalTreeNode<K, V> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
|
IntervalTreeNode<TKey, TValue> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
|
||||||
|
|
||||||
if (tmp != null)
|
if (tmp != null)
|
||||||
{
|
{
|
||||||
|
@ -413,7 +413,7 @@ namespace Ryujinx.Common.Collections
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
protected override void RotateLeft(IntervalTreeNode<K, V> node)
|
protected override void RotateLeft(IntervalTreeNode<TKey, TValue> node)
|
||||||
{
|
{
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
|
@ -423,7 +423,7 @@ namespace Ryujinx.Common.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RotateRight(IntervalTreeNode<K, V> node)
|
protected override void RotateRight(IntervalTreeNode<TKey, TValue> node)
|
||||||
{
|
{
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
|
@ -433,7 +433,7 @@ namespace Ryujinx.Common.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsKey(K key)
|
public bool ContainsKey(TKey key)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
|
@ -444,15 +444,15 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a value and its start and end keys.
|
/// Represents a value and its start and end keys.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="K"></typeparam>
|
/// <typeparam name="TKey"></typeparam>
|
||||||
/// <typeparam name="V"></typeparam>
|
/// <typeparam name="TValue"></typeparam>
|
||||||
public readonly struct RangeNode<K, V>
|
public readonly struct RangeNode<TKey, TValue>
|
||||||
{
|
{
|
||||||
public readonly K Start;
|
public readonly TKey Start;
|
||||||
public readonly K End;
|
public readonly TKey End;
|
||||||
public readonly V Value;
|
public readonly TValue Value;
|
||||||
|
|
||||||
public RangeNode(K start, K end, V value)
|
public RangeNode(TKey start, TKey end, TValue value)
|
||||||
{
|
{
|
||||||
Start = start;
|
Start = start;
|
||||||
End = end;
|
End = end;
|
||||||
|
@ -463,36 +463,36 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a node in the IntervalTree which contains start and end keys of type K, and a value of generic type V.
|
/// Represents a node in the IntervalTree which contains start and end keys of type K, and a value of generic type V.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="K">Key type of the node</typeparam>
|
/// <typeparam name="TKey">Key type of the node</typeparam>
|
||||||
/// <typeparam name="V">Value type of the node</typeparam>
|
/// <typeparam name="TValue">Value type of the node</typeparam>
|
||||||
public class IntervalTreeNode<K, V> : IntrusiveRedBlackTreeNode<IntervalTreeNode<K, V>>
|
public class IntervalTreeNode<TKey, TValue> : IntrusiveRedBlackTreeNode<IntervalTreeNode<TKey, TValue>>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The start of the range.
|
/// The start of the range.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal K Start;
|
internal TKey Start;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The end of the range - maximum of all in the Values list.
|
/// The end of the range - maximum of all in the Values list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal K End;
|
internal TKey End;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum end value of this node and all its children.
|
/// The maximum end value of this node and all its children.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal K Max;
|
internal TKey Max;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Values contained on the node that shares a common Start value.
|
/// Values contained on the node that shares a common Start value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal List<RangeNode<K, V>> Values;
|
internal List<RangeNode<TKey, TValue>> Values;
|
||||||
|
|
||||||
internal IntervalTreeNode(K start, K end, V value, IntervalTreeNode<K, V> parent)
|
internal IntervalTreeNode(TKey start, TKey end, TValue value, IntervalTreeNode<TKey, TValue> parent)
|
||||||
{
|
{
|
||||||
Start = start;
|
Start = start;
|
||||||
End = end;
|
End = end;
|
||||||
Max = end;
|
Max = end;
|
||||||
Values = new List<RangeNode<K, V>> { new RangeNode<K, V>(start, end, value) };
|
Values = new List<RangeNode<TKey, TValue>> { new RangeNode<TKey, TValue>(start, end, value) };
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,11 +180,6 @@ namespace Ryujinx.Common.Collections
|
||||||
parent.Right = child;
|
parent.Right = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ParentOf(element) == old)
|
|
||||||
{
|
|
||||||
parent = element;
|
|
||||||
}
|
|
||||||
|
|
||||||
element.Color = old.Color;
|
element.Color = old.Color;
|
||||||
element.Left = old.Left;
|
element.Left = old.Left;
|
||||||
element.Right = old.Right;
|
element.Right = old.Right;
|
||||||
|
@ -258,11 +253,11 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="tree">Tree to search at</param>
|
/// <param name="tree">Tree to search at</param>
|
||||||
/// <param name="key">Key of the node to be found</param>
|
/// <param name="key">Key of the node to be found</param>
|
||||||
/// <returns>Node that is equal to <paramref name="key"/></returns>
|
/// <returns>Node that is equal to <paramref name="key"/></returns>
|
||||||
public static N GetNodeByKey<N, K>(this IntrusiveRedBlackTree<N> tree, K key)
|
public static TNode GetNodeByKey<TNode, TKey>(this IntrusiveRedBlackTree<TNode> tree, TKey key)
|
||||||
where N : IntrusiveRedBlackTreeNode<N>, IComparable<N>, IComparable<K>
|
where TNode : IntrusiveRedBlackTreeNode<TNode>, IComparable<TNode>, IComparable<TKey>
|
||||||
where K : struct
|
where TKey : struct
|
||||||
{
|
{
|
||||||
N node = tree.RootNode;
|
TNode node = tree.RootNode;
|
||||||
while (node != null)
|
while (node != null)
|
||||||
{
|
{
|
||||||
int cmp = node.CompareTo(key);
|
int cmp = node.CompareTo(key);
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Ryujinx.Common.Collections
|
||||||
{
|
{
|
||||||
protected const bool Black = true;
|
protected const bool Black = true;
|
||||||
protected const bool Red = false;
|
protected const bool Red = false;
|
||||||
protected T Root = null;
|
protected T Root;
|
||||||
|
|
||||||
internal T RootNode => Root;
|
internal T RootNode => Root;
|
||||||
|
|
||||||
|
|
|
@ -13,4 +13,4 @@ namespace Ryujinx.Common.Collections
|
||||||
public T Predecessor => IntrusiveRedBlackTreeImpl<T>.PredecessorOf((T)this);
|
public T Predecessor => IntrusiveRedBlackTreeImpl<T>.PredecessorOf((T)this);
|
||||||
public T Successor => IntrusiveRedBlackTreeImpl<T>.SuccessorOf((T)this);
|
public T Successor => IntrusiveRedBlackTreeImpl<T>.SuccessorOf((T)this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,9 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dictionary that provides the ability for O(logN) Lookups for keys that exist in the Dictionary, and O(logN) lookups for keys immediately greater than or less than a specified key.
|
/// Dictionary that provides the ability for O(logN) Lookups for keys that exist in the Dictionary, and O(logN) lookups for keys immediately greater than or less than a specified key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="K">Key</typeparam>
|
/// <typeparam name="TKey">Key</typeparam>
|
||||||
/// <typeparam name="V">Value</typeparam>
|
/// <typeparam name="TValue">Value</typeparam>
|
||||||
public class TreeDictionary<K, V> : IntrusiveRedBlackTreeImpl<Node<K, V>>, IDictionary<K, V> where K : IComparable<K>
|
public class TreeDictionary<TKey, TValue> : IntrusiveRedBlackTreeImpl<Node<TKey, TValue>>, IDictionary<TKey, TValue> where TKey : IComparable<TKey>
|
||||||
{
|
{
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="key">Key of the node value to get</param>
|
/// <param name="key">Key of the node value to get</param>
|
||||||
/// <returns>Value associated w/ <paramref name="key"/></returns>
|
/// <returns>Value associated w/ <paramref name="key"/></returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||||
public V Get(K key)
|
public TValue Get(TKey key)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
Node<K, V> node = GetNode(key);
|
Node<TKey, TValue> node = GetNode(key);
|
||||||
|
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,7 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="key">Key of the node to add</param>
|
/// <param name="key">Key of the node to add</param>
|
||||||
/// <param name="value">Value of the node to add</param>
|
/// <param name="value">Value of the node to add</param>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> or <paramref name="value"/> are null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> or <paramref name="value"/> are null</exception>
|
||||||
public void Add(K key, V value)
|
public void Add(TKey key, TValue value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
ArgumentNullException.ThrowIfNull(value);
|
||||||
|
@ -55,7 +55,7 @@ namespace Ryujinx.Common.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">Key of the node to remove</param>
|
/// <param name="key">Key of the node to remove</param>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||||
public void Remove(K key)
|
public void Remove(TKey key)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
|
@ -71,9 +71,9 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="key">Key for which to find the floor value of</param>
|
/// <param name="key">Key for which to find the floor value of</param>
|
||||||
/// <returns>Key of node immediately less than <paramref name="key"/></returns>
|
/// <returns>Key of node immediately less than <paramref name="key"/></returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||||
public K Floor(K key)
|
public TKey Floor(TKey key)
|
||||||
{
|
{
|
||||||
Node<K, V> node = FloorNode(key);
|
Node<TKey, TValue> node = FloorNode(key);
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
return node.Key;
|
return node.Key;
|
||||||
|
@ -87,9 +87,9 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="key">Key for which to find the ceiling node of</param>
|
/// <param name="key">Key for which to find the ceiling node of</param>
|
||||||
/// <returns>Key of node immediately greater than <paramref name="key"/></returns>
|
/// <returns>Key of node immediately greater than <paramref name="key"/></returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||||
public K Ceiling(K key)
|
public TKey Ceiling(TKey key)
|
||||||
{
|
{
|
||||||
Node<K, V> node = CeilingNode(key);
|
Node<TKey, TValue> node = CeilingNode(key);
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
return node.Key;
|
return node.Key;
|
||||||
|
@ -102,12 +102,12 @@ namespace Ryujinx.Common.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">Key to find the successor of</param>
|
/// <param name="key">Key to find the successor of</param>
|
||||||
/// <returns>Value</returns>
|
/// <returns>Value</returns>
|
||||||
public K SuccessorOf(K key)
|
public TKey SuccessorOf(TKey key)
|
||||||
{
|
{
|
||||||
Node<K, V> node = GetNode(key);
|
Node<TKey, TValue> node = GetNode(key);
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
Node<K, V> successor = SuccessorOf(node);
|
Node<TKey, TValue> successor = SuccessorOf(node);
|
||||||
|
|
||||||
return successor != null ? successor.Key : default;
|
return successor != null ? successor.Key : default;
|
||||||
}
|
}
|
||||||
|
@ -119,12 +119,12 @@ namespace Ryujinx.Common.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">Key to find the predecessor of</param>
|
/// <param name="key">Key to find the predecessor of</param>
|
||||||
/// <returns>Value</returns>
|
/// <returns>Value</returns>
|
||||||
public K PredecessorOf(K key)
|
public TKey PredecessorOf(TKey key)
|
||||||
{
|
{
|
||||||
Node<K, V> node = GetNode(key);
|
Node<TKey, TValue> node = GetNode(key);
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
Node<K, V> predecessor = PredecessorOf(node);
|
Node<TKey, TValue> predecessor = PredecessorOf(node);
|
||||||
|
|
||||||
return predecessor != null ? predecessor.Key : default;
|
return predecessor != null ? predecessor.Key : default;
|
||||||
}
|
}
|
||||||
|
@ -137,19 +137,19 @@ namespace Ryujinx.Common.Collections
|
||||||
/// The key/value pairs will be added in Level Order.
|
/// The key/value pairs will be added in Level Order.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="list">List to add the tree pairs into</param>
|
/// <param name="list">List to add the tree pairs into</param>
|
||||||
public List<KeyValuePair<K, V>> AsLevelOrderList()
|
public List<KeyValuePair<TKey, TValue>> AsLevelOrderList()
|
||||||
{
|
{
|
||||||
List<KeyValuePair<K, V>> list = new List<KeyValuePair<K, V>>();
|
List<KeyValuePair<TKey, TValue>> list = new();
|
||||||
|
|
||||||
Queue<Node<K, V>> nodes = new Queue<Node<K, V>>();
|
Queue<Node<TKey, TValue>> nodes = new();
|
||||||
|
|
||||||
if (this.Root != null)
|
if (this.Root != null)
|
||||||
{
|
{
|
||||||
nodes.Enqueue(this.Root);
|
nodes.Enqueue(this.Root);
|
||||||
}
|
}
|
||||||
while (nodes.TryDequeue(out Node<K, V> node))
|
while (nodes.TryDequeue(out Node<TKey, TValue> node))
|
||||||
{
|
{
|
||||||
list.Add(new KeyValuePair<K, V>(node.Key, node.Value));
|
list.Add(new KeyValuePair<TKey, TValue>(node.Key, node.Value));
|
||||||
if (node.Left != null)
|
if (node.Left != null)
|
||||||
{
|
{
|
||||||
nodes.Enqueue(node.Left);
|
nodes.Enqueue(node.Left);
|
||||||
|
@ -166,9 +166,9 @@ namespace Ryujinx.Common.Collections
|
||||||
/// Adds all the nodes in the dictionary into <paramref name="list"/>.
|
/// Adds all the nodes in the dictionary into <paramref name="list"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A list of all KeyValuePairs sorted by Key Order</returns>
|
/// <returns>A list of all KeyValuePairs sorted by Key Order</returns>
|
||||||
public List<KeyValuePair<K, V>> AsList()
|
public List<KeyValuePair<TKey, TValue>> AsList()
|
||||||
{
|
{
|
||||||
List<KeyValuePair<K, V>> list = new List<KeyValuePair<K, V>>();
|
List<KeyValuePair<TKey, TValue>> list = new();
|
||||||
|
|
||||||
AddToList(Root, list);
|
AddToList(Root, list);
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ namespace Ryujinx.Common.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node">The node to search for nodes within</param>
|
/// <param name="node">The node to search for nodes within</param>
|
||||||
/// <param name="list">The list to add node to</param>
|
/// <param name="list">The list to add node to</param>
|
||||||
private void AddToList(Node<K, V> node, List<KeyValuePair<K, V>> list)
|
private void AddToList(Node<TKey, TValue> node, List<KeyValuePair<TKey, TValue>> list)
|
||||||
{
|
{
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
|
@ -193,7 +193,7 @@ namespace Ryujinx.Common.Collections
|
||||||
|
|
||||||
AddToList(node.Left, list);
|
AddToList(node.Left, list);
|
||||||
|
|
||||||
list.Add(new KeyValuePair<K, V>(node.Key, node.Value));
|
list.Add(new KeyValuePair<TKey, TValue>(node.Key, node.Value));
|
||||||
|
|
||||||
AddToList(node.Right, list);
|
AddToList(node.Right, list);
|
||||||
}
|
}
|
||||||
|
@ -204,11 +204,11 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="key">Key of the node to get</param>
|
/// <param name="key">Key of the node to get</param>
|
||||||
/// <returns>Node reference in the tree</returns>
|
/// <returns>Node reference in the tree</returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||||
private Node<K, V> GetNode(K key)
|
private Node<TKey, TValue> GetNode(TKey key)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
Node<K, V> node = Root;
|
Node<TKey, TValue> node = Root;
|
||||||
while (node != null)
|
while (node != null)
|
||||||
{
|
{
|
||||||
int cmp = key.CompareTo(node.Key);
|
int cmp = key.CompareTo(node.Key);
|
||||||
|
@ -235,9 +235,9 @@ namespace Ryujinx.Common.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">Key of the node to insert</param>
|
/// <param name="key">Key of the node to insert</param>
|
||||||
/// <param name="value">Value of the node to insert</param>
|
/// <param name="value">Value of the node to insert</param>
|
||||||
private void Insert(K key, V value)
|
private void Insert(TKey key, TValue value)
|
||||||
{
|
{
|
||||||
Node<K, V> newNode = BSTInsert(key, value);
|
Node<TKey, TValue> newNode = BSTInsert(key, value);
|
||||||
RestoreBalanceAfterInsertion(newNode);
|
RestoreBalanceAfterInsertion(newNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,10 +251,10 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="key">Key of the node to insert</param>
|
/// <param name="key">Key of the node to insert</param>
|
||||||
/// <param name="value">Value of the node to insert</param>
|
/// <param name="value">Value of the node to insert</param>
|
||||||
/// <returns>The inserted Node</returns>
|
/// <returns>The inserted Node</returns>
|
||||||
private Node<K, V> BSTInsert(K key, V value)
|
private Node<TKey, TValue> BSTInsert(TKey key, TValue value)
|
||||||
{
|
{
|
||||||
Node<K, V> parent = null;
|
Node<TKey, TValue> parent = null;
|
||||||
Node<K, V> node = Root;
|
Node<TKey, TValue> node = Root;
|
||||||
|
|
||||||
while (node != null)
|
while (node != null)
|
||||||
{
|
{
|
||||||
|
@ -274,7 +274,7 @@ namespace Ryujinx.Common.Collections
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Node<K, V> newNode = new Node<K, V>(key, value, parent);
|
Node<TKey, TValue> newNode = new(key, value, parent);
|
||||||
if (newNode.Parent == null)
|
if (newNode.Parent == null)
|
||||||
{
|
{
|
||||||
Root = newNode;
|
Root = newNode;
|
||||||
|
@ -296,14 +296,17 @@ namespace Ryujinx.Common.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">Key of the node to delete</param>
|
/// <param name="key">Key of the node to delete</param>
|
||||||
/// <returns>The deleted Node</returns>
|
/// <returns>The deleted Node</returns>
|
||||||
private Node<K, V> Delete(K key)
|
private Node<TKey, TValue> Delete(TKey key)
|
||||||
{
|
{
|
||||||
// O(1) Retrieval
|
// O(1) Retrieval
|
||||||
Node<K, V> nodeToDelete = GetNode(key);
|
Node<TKey, TValue> nodeToDelete = GetNode(key);
|
||||||
|
|
||||||
if (nodeToDelete == null) return null;
|
if (nodeToDelete == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Node<K, V> replacementNode;
|
Node<TKey, TValue> replacementNode;
|
||||||
|
|
||||||
if (LeftOf(nodeToDelete) == null || RightOf(nodeToDelete) == null)
|
if (LeftOf(nodeToDelete) == null || RightOf(nodeToDelete) == null)
|
||||||
{
|
{
|
||||||
|
@ -314,7 +317,7 @@ namespace Ryujinx.Common.Collections
|
||||||
replacementNode = PredecessorOf(nodeToDelete);
|
replacementNode = PredecessorOf(nodeToDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node<K, V> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
|
Node<TKey, TValue> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
|
||||||
|
|
||||||
if (tmp != null)
|
if (tmp != null)
|
||||||
{
|
{
|
||||||
|
@ -354,11 +357,11 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="key">Key for which to find the floor node of</param>
|
/// <param name="key">Key for which to find the floor node of</param>
|
||||||
/// <returns>Node whose key is immediately less than or equal to <paramref name="key"/>, or null if no such node is found.</returns>
|
/// <returns>Node whose key is immediately less than or equal to <paramref name="key"/>, or null if no such node is found.</returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||||
private Node<K, V> FloorNode(K key)
|
private Node<TKey, TValue> FloorNode(TKey key)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
Node<K, V> tmp = Root;
|
Node<TKey, TValue> tmp = Root;
|
||||||
|
|
||||||
while (tmp != null)
|
while (tmp != null)
|
||||||
{
|
{
|
||||||
|
@ -382,8 +385,8 @@ namespace Ryujinx.Common.Collections
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Node<K, V> parent = tmp.Parent;
|
Node<TKey, TValue> parent = tmp.Parent;
|
||||||
Node<K, V> ptr = tmp;
|
Node<TKey, TValue> ptr = tmp;
|
||||||
while (parent != null && ptr == parent.Left)
|
while (parent != null && ptr == parent.Left)
|
||||||
{
|
{
|
||||||
ptr = parent;
|
ptr = parent;
|
||||||
|
@ -406,11 +409,11 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <param name="key">Key for which to find the ceiling node of</param>
|
/// <param name="key">Key for which to find the ceiling node of</param>
|
||||||
/// <returns>Node whose key is immediately greater than or equal to <paramref name="key"/>, or null if no such node is found.</returns>
|
/// <returns>Node whose key is immediately greater than or equal to <paramref name="key"/>, or null if no such node is found.</returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||||
private Node<K, V> CeilingNode(K key)
|
private Node<TKey, TValue> CeilingNode(TKey key)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
Node<K, V> tmp = Root;
|
Node<TKey, TValue> tmp = Root;
|
||||||
|
|
||||||
while (tmp != null)
|
while (tmp != null)
|
||||||
{
|
{
|
||||||
|
@ -434,8 +437,8 @@ namespace Ryujinx.Common.Collections
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Node<K, V> parent = tmp.Parent;
|
Node<TKey, TValue> parent = tmp.Parent;
|
||||||
Node<K, V> ptr = tmp;
|
Node<TKey, TValue> ptr = tmp;
|
||||||
while (parent != null && ptr == parent.Right)
|
while (parent != null && ptr == parent.Right)
|
||||||
{
|
{
|
||||||
ptr = parent;
|
ptr = parent;
|
||||||
|
@ -457,44 +460,44 @@ namespace Ryujinx.Common.Collections
|
||||||
#region Interface Implementations
|
#region Interface Implementations
|
||||||
|
|
||||||
// Method descriptions are not provided as they are already included as part of the interface.
|
// Method descriptions are not provided as they are already included as part of the interface.
|
||||||
public bool ContainsKey(K key)
|
public bool ContainsKey(TKey key)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
return GetNode(key) != null;
|
return GetNode(key) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IDictionary<K, V>.Remove(K key)
|
bool IDictionary<TKey, TValue>.Remove(TKey key)
|
||||||
{
|
{
|
||||||
int count = Count;
|
int count = Count;
|
||||||
Remove(key);
|
Remove(key);
|
||||||
return count > Count;
|
return count > Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetValue(K key, [MaybeNullWhen(false)] out V value)
|
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(key);
|
ArgumentNullException.ThrowIfNull(key);
|
||||||
|
|
||||||
Node<K, V> node = GetNode(key);
|
Node<TKey, TValue> node = GetNode(key);
|
||||||
value = node != null ? node.Value : default;
|
value = node != null ? node.Value : default;
|
||||||
return node != null;
|
return node != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(KeyValuePair<K, V> item)
|
public void Add(KeyValuePair<TKey, TValue> item)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(item.Key);
|
ArgumentNullException.ThrowIfNull(item.Key);
|
||||||
|
|
||||||
Add(item.Key, item.Value);
|
Add(item.Key, item.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Contains(KeyValuePair<K, V> item)
|
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||||
{
|
{
|
||||||
if (item.Key == null)
|
if (item.Key == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node<K, V> node = GetNode(item.Key);
|
Node<TKey, TValue> node = GetNode(item.Key);
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
return node.Key.Equals(item.Key) && node.Value.Equals(item.Value);
|
return node.Key.Equals(item.Key) && node.Value.Equals(item.Value);
|
||||||
|
@ -502,27 +505,27 @@ namespace Ryujinx.Common.Collections
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex)
|
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||||
{
|
{
|
||||||
if (arrayIndex < 0 || array.Length - arrayIndex < this.Count)
|
if (arrayIndex < 0 || array.Length - arrayIndex < this.Count)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
SortedList<K, V> list = GetKeyValues();
|
SortedList<TKey, TValue> list = GetKeyValues();
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
for (int i = arrayIndex; i < array.Length && offset < list.Count; i++)
|
for (int i = arrayIndex; i < array.Length && offset < list.Count; i++)
|
||||||
{
|
{
|
||||||
array[i] = new KeyValuePair<K, V>(list.Keys[i], list.Values[i]);
|
array[i] = new KeyValuePair<TKey, TValue>(list.Keys[i], list.Values[i]);
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove(KeyValuePair<K, V> item)
|
public bool Remove(KeyValuePair<TKey, TValue> item)
|
||||||
{
|
{
|
||||||
Node<K, V> node = GetNode(item.Key);
|
Node<TKey, TValue> node = GetNode(item.Key);
|
||||||
|
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
|
@ -539,7 +542,7 @@ namespace Ryujinx.Common.Collections
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
|
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||||
{
|
{
|
||||||
return GetKeyValues().GetEnumerator();
|
return GetKeyValues().GetEnumerator();
|
||||||
}
|
}
|
||||||
|
@ -549,13 +552,13 @@ namespace Ryujinx.Common.Collections
|
||||||
return GetKeyValues().GetEnumerator();
|
return GetKeyValues().GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICollection<K> Keys => GetKeyValues().Keys;
|
public ICollection<TKey> Keys => GetKeyValues().Keys;
|
||||||
|
|
||||||
public ICollection<V> Values => GetKeyValues().Values;
|
public ICollection<TValue> Values => GetKeyValues().Values;
|
||||||
|
|
||||||
public bool IsReadOnly => false;
|
public bool IsReadOnly => false;
|
||||||
|
|
||||||
public V this[K key]
|
public TValue this[TKey key]
|
||||||
{
|
{
|
||||||
get => Get(key);
|
get => Get(key);
|
||||||
set => Add(key, value);
|
set => Add(key, value);
|
||||||
|
@ -569,16 +572,16 @@ namespace Ryujinx.Common.Collections
|
||||||
/// Returns a sorted list of all the node keys / values in the tree.
|
/// Returns a sorted list of all the node keys / values in the tree.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>List of node keys</returns>
|
/// <returns>List of node keys</returns>
|
||||||
private SortedList<K, V> GetKeyValues()
|
private SortedList<TKey, TValue> GetKeyValues()
|
||||||
{
|
{
|
||||||
SortedList<K, V> set = new SortedList<K, V>();
|
SortedList<TKey, TValue> set = new();
|
||||||
Queue<Node<K, V>> queue = new Queue<Node<K, V>>();
|
Queue<Node<TKey, TValue>> queue = new();
|
||||||
if (Root != null)
|
if (Root != null)
|
||||||
{
|
{
|
||||||
queue.Enqueue(Root);
|
queue.Enqueue(Root);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (queue.TryDequeue(out Node<K, V> node))
|
while (queue.TryDequeue(out Node<TKey, TValue> node))
|
||||||
{
|
{
|
||||||
set.Add(node.Key, node.Value);
|
set.Add(node.Key, node.Value);
|
||||||
if (null != node.Left)
|
if (null != node.Left)
|
||||||
|
@ -600,14 +603,14 @@ namespace Ryujinx.Common.Collections
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a node in the TreeDictionary which contains a key and value of generic type K and V, respectively.
|
/// Represents a node in the TreeDictionary which contains a key and value of generic type K and V, respectively.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="K">Key of the node</typeparam>
|
/// <typeparam name="TKey">Key of the node</typeparam>
|
||||||
/// <typeparam name="V">Value of the node</typeparam>
|
/// <typeparam name="TValue">Value of the node</typeparam>
|
||||||
public class Node<K, V> : IntrusiveRedBlackTreeNode<Node<K, V>> where K : IComparable<K>
|
public class Node<TKey, TValue> : IntrusiveRedBlackTreeNode<Node<TKey, TValue>> where TKey : IComparable<TKey>
|
||||||
{
|
{
|
||||||
internal K Key;
|
internal TKey Key;
|
||||||
internal V Value;
|
internal TValue Value;
|
||||||
|
|
||||||
internal Node(K key, V value, Node<K, V> parent)
|
internal Node(TKey key, TValue value, Node<TKey, TValue> parent)
|
||||||
{
|
{
|
||||||
Key = key;
|
Key = key;
|
||||||
Value = value;
|
Value = value;
|
||||||
|
|
|
@ -11,6 +11,6 @@ namespace Ryujinx.Common.Configuration
|
||||||
SmaaLow,
|
SmaaLow,
|
||||||
SmaaMedium,
|
SmaaMedium,
|
||||||
SmaaHigh,
|
SmaaHigh,
|
||||||
SmaaUltra
|
SmaaUltra,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
UserProfile,
|
UserProfile,
|
||||||
Portable,
|
Portable,
|
||||||
Custom
|
Custom,
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LaunchMode Mode { get; private set; }
|
public static LaunchMode Mode { get; private set; }
|
||||||
|
@ -34,7 +34,7 @@ namespace Ryujinx.Common.Configuration
|
||||||
private const string DefaultModsDir = "mods";
|
private const string DefaultModsDir = "mods";
|
||||||
|
|
||||||
public static string CustomModsPath { get; set; }
|
public static string CustomModsPath { get; set; }
|
||||||
public static string CustomSdModsPath {get; set; }
|
public static string CustomSdModsPath { get; set; }
|
||||||
public static string CustomNandPath { get; set; } // TODO: Actually implement this into VFS
|
public static string CustomNandPath { get; set; } // TODO: Actually implement this into VFS
|
||||||
public static string CustomSdCardPath { get; set; } // TODO: Actually implement this into VFS
|
public static string CustomSdCardPath { get; set; } // TODO: Actually implement this into VFS
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ namespace Ryujinx.Common.Configuration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetModsPath() => CustomModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultModsDir)).FullName;
|
public static string GetModsPath() => CustomModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultModsDir)).FullName;
|
||||||
public static string GetSdModsPath() => CustomSdModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultSdcardDir, "atmosphere")).FullName;
|
public static string GetSdModsPath() => CustomSdModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultSdcardDir, "atmosphere")).FullName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Ryujinx.Common.Configuration
|
||||||
Fixed16x10,
|
Fixed16x10,
|
||||||
Fixed21x9,
|
Fixed21x9,
|
||||||
Fixed32x9,
|
Fixed32x9,
|
||||||
Stretched
|
Stretched,
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AspectRatioExtensions
|
public static class AspectRatioExtensions
|
||||||
|
@ -25,12 +25,14 @@ namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
return aspectRatio switch
|
return aspectRatio switch
|
||||||
{
|
{
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
AspectRatio.Fixed4x3 => 4.0f,
|
AspectRatio.Fixed4x3 => 4.0f,
|
||||||
AspectRatio.Fixed16x9 => 16.0f,
|
AspectRatio.Fixed16x9 => 16.0f,
|
||||||
AspectRatio.Fixed16x10 => 16.0f,
|
AspectRatio.Fixed16x10 => 16.0f,
|
||||||
AspectRatio.Fixed21x9 => 21.0f,
|
AspectRatio.Fixed21x9 => 21.0f,
|
||||||
AspectRatio.Fixed32x9 => 32.0f,
|
AspectRatio.Fixed32x9 => 32.0f,
|
||||||
_ => 16.0f
|
_ => 16.0f,
|
||||||
|
#pragma warning restore IDE0055
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,12 +40,14 @@ namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
return aspectRatio switch
|
return aspectRatio switch
|
||||||
{
|
{
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
AspectRatio.Fixed4x3 => 3.0f,
|
AspectRatio.Fixed4x3 => 3.0f,
|
||||||
AspectRatio.Fixed16x9 => 9.0f,
|
AspectRatio.Fixed16x9 => 9.0f,
|
||||||
AspectRatio.Fixed16x10 => 10.0f,
|
AspectRatio.Fixed16x10 => 10.0f,
|
||||||
AspectRatio.Fixed21x9 => 9.0f,
|
AspectRatio.Fixed21x9 => 9.0f,
|
||||||
AspectRatio.Fixed32x9 => 9.0f,
|
AspectRatio.Fixed32x9 => 9.0f,
|
||||||
_ => 9.0f
|
_ => 9.0f,
|
||||||
|
#pragma warning restore IDE0055
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,13 +55,15 @@ namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
return aspectRatio switch
|
return aspectRatio switch
|
||||||
{
|
{
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
AspectRatio.Fixed4x3 => "4:3",
|
AspectRatio.Fixed4x3 => "4:3",
|
||||||
AspectRatio.Fixed16x9 => "16:9",
|
AspectRatio.Fixed16x9 => "16:9",
|
||||||
AspectRatio.Fixed16x10 => "16:10",
|
AspectRatio.Fixed16x10 => "16:10",
|
||||||
AspectRatio.Fixed21x9 => "21:9",
|
AspectRatio.Fixed21x9 => "21:9",
|
||||||
AspectRatio.Fixed32x9 => "32:9",
|
AspectRatio.Fixed32x9 => "32:9",
|
||||||
_ => "Stretched"
|
_ => "Stretched",
|
||||||
|
#pragma warning restore IDE0055
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,4 @@ namespace Ryujinx.Common.Configuration
|
||||||
[JsonPropertyName("dlc_nca_list")]
|
[JsonPropertyName("dlc_nca_list")]
|
||||||
public List<DownloadableContentNca> DownloadableContentNcaList { get; set; }
|
public List<DownloadableContentNca> DownloadableContentNcaList { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,4 @@ namespace Ryujinx.Common.Configuration
|
||||||
public partial class DownloadableContentJsonSerializerContext : JsonSerializerContext
|
public partial class DownloadableContentJsonSerializerContext : JsonSerializerContext
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ namespace Ryujinx.Common.Configuration
|
||||||
[JsonPropertyName("path")]
|
[JsonPropertyName("path")]
|
||||||
public string FullPath { get; set; }
|
public string FullPath { get; set; }
|
||||||
[JsonPropertyName("title_id")]
|
[JsonPropertyName("title_id")]
|
||||||
public ulong TitleId { get; set; }
|
public ulong TitleId { get; set; }
|
||||||
[JsonPropertyName("is_enabled")]
|
[JsonPropertyName("is_enabled")]
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,6 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||||
SingleLeftTrigger1,
|
SingleLeftTrigger1,
|
||||||
SingleRightTrigger1,
|
SingleRightTrigger1,
|
||||||
|
|
||||||
Count
|
Count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration.Hid.Controller
|
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||||
{
|
{
|
||||||
public class GenericControllerInputConfig<Button, Stick> : GenericInputConfigurationCommon<Button> where Button : unmanaged where Stick : unmanaged
|
public class GenericControllerInputConfig<TButton, TStick> : GenericInputConfigurationCommon<TButton> where TButton : unmanaged where TStick : unmanaged
|
||||||
{
|
{
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
private float _deadzoneLeft;
|
private float _deadzoneLeft;
|
||||||
|
@ -16,12 +16,12 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Left JoyCon Controller Stick Bindings
|
/// Left JoyCon Controller Stick Bindings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public JoyconConfigControllerStick<Button, Stick> LeftJoyconStick { get; set; }
|
public JoyconConfigControllerStick<TButton, TStick> LeftJoyconStick { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Right JoyCon Controller Stick Bindings
|
/// Right JoyCon Controller Stick Bindings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public JoyconConfigControllerStick<Button, Stick> RightJoyconStick { get; set; }
|
public JoyconConfigControllerStick<TButton, TStick> RightJoyconStick { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Controller Left Analog Stick Deadzone
|
/// Controller Left Analog Stick Deadzone
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
namespace Ryujinx.Common.Configuration.Hid.Controller
|
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||||
{
|
{
|
||||||
public class JoyconConfigControllerStick<Button, Stick> where Button: unmanaged where Stick: unmanaged
|
public class JoyconConfigControllerStick<TButton, TStick> where TButton : unmanaged where TStick : unmanaged
|
||||||
{
|
{
|
||||||
public Stick Joystick { get; set; }
|
public TStick Joystick { get; set; }
|
||||||
public bool InvertStickX { get; set; }
|
public bool InvertStickX { get; set; }
|
||||||
public bool InvertStickY { get; set; }
|
public bool InvertStickY { get; set; }
|
||||||
public bool Rotate90CW { get; set; }
|
public bool Rotate90CW { get; set; }
|
||||||
public Button StickButton { get; set; }
|
public TButton StickButton { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
||||||
{
|
{
|
||||||
class JsonMotionConfigControllerConverter : JsonConverter<MotionConfigController>
|
class JsonMotionConfigControllerConverter : JsonConverter<MotionConfigController>
|
||||||
{
|
{
|
||||||
private static readonly MotionConfigJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly MotionConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
private static MotionInputBackendType GetMotionInputBackendType(ref Utf8JsonReader reader)
|
private static MotionInputBackendType GetMotionInputBackendType(ref Utf8JsonReader reader)
|
||||||
{
|
{
|
||||||
|
@ -55,8 +55,8 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
||||||
|
|
||||||
return motionBackendType switch
|
return motionBackendType switch
|
||||||
{
|
{
|
||||||
MotionInputBackendType.GamepadDriver => JsonSerializer.Deserialize(ref reader, SerializerContext.StandardMotionConfigController),
|
MotionInputBackendType.GamepadDriver => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardMotionConfigController),
|
||||||
MotionInputBackendType.CemuHook => JsonSerializer.Deserialize(ref reader, SerializerContext.CemuHookMotionConfigController),
|
MotionInputBackendType.CemuHook => JsonSerializer.Deserialize(ref reader, _serializerContext.CemuHookMotionConfigController),
|
||||||
_ => throw new InvalidOperationException($"Unknown backend type {motionBackendType}"),
|
_ => throw new InvalidOperationException($"Unknown backend type {motionBackendType}"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -66,10 +66,10 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
||||||
switch (value.MotionBackend)
|
switch (value.MotionBackend)
|
||||||
{
|
{
|
||||||
case MotionInputBackendType.GamepadDriver:
|
case MotionInputBackendType.GamepadDriver:
|
||||||
JsonSerializer.Serialize(writer, value as StandardMotionConfigController, SerializerContext.StandardMotionConfigController);
|
JsonSerializer.Serialize(writer, value as StandardMotionConfigController, _serializerContext.StandardMotionConfigController);
|
||||||
break;
|
break;
|
||||||
case MotionInputBackendType.CemuHook:
|
case MotionInputBackendType.CemuHook:
|
||||||
JsonSerializer.Serialize(writer, value as CemuHookMotionConfigController, SerializerContext.CemuHookMotionConfigController);
|
JsonSerializer.Serialize(writer, value as CemuHookMotionConfigController, _serializerContext.CemuHookMotionConfigController);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException($"Unknown motion backend type {value.MotionBackend}");
|
throw new ArgumentException($"Unknown motion backend type {value.MotionBackend}");
|
||||||
|
|
|
@ -9,4 +9,4 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
||||||
public partial class MotionConfigJsonSerializerContext : JsonSerializerContext
|
public partial class MotionConfigJsonSerializerContext : JsonSerializerContext
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
|
|
||||||
Count
|
Count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,14 +10,14 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||||
public enum ControllerType
|
public enum ControllerType
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
ProController = 1 << 0,
|
ProController = 1 << 0,
|
||||||
Handheld = 1 << 1,
|
Handheld = 1 << 1,
|
||||||
JoyconPair = 1 << 2,
|
JoyconPair = 1 << 2,
|
||||||
JoyconLeft = 1 << 3,
|
JoyconLeft = 1 << 3,
|
||||||
JoyconRight = 1 << 4,
|
JoyconRight = 1 << 4,
|
||||||
Invalid = 1 << 5,
|
Invalid = 1 << 5,
|
||||||
Pokeball = 1 << 6,
|
Pokeball = 1 << 6,
|
||||||
SystemExternal = 1 << 29,
|
SystemExternal = 1 << 29,
|
||||||
System = 1 << 30
|
System = 1 << 30,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
namespace Ryujinx.Common.Configuration.Hid
|
namespace Ryujinx.Common.Configuration.Hid
|
||||||
{
|
{
|
||||||
public class GenericInputConfigurationCommon<Button> : InputConfig where Button : unmanaged
|
public class GenericInputConfigurationCommon<TButton> : InputConfig where TButton : unmanaged
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Left JoyCon Controller Bindings
|
/// Left JoyCon Controller Bindings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LeftJoyconCommonConfig<Button> LeftJoycon { get; set; }
|
public LeftJoyconCommonConfig<TButton> LeftJoycon { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Right JoyCon Controller Bindings
|
/// Right JoyCon Controller Bindings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RightJoyconCommonConfig<Button> RightJoycon { get; set; }
|
public RightJoyconCommonConfig<TButton> RightJoycon { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||||
/// Player's Index for the controller
|
/// Player's Index for the controller
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PlayerIndex PlayerIndex { get; set; }
|
public PlayerIndex PlayerIndex { get; set; }
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
@ -38,4 +38,4 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,4 +11,4 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||||
public partial class InputConfigJsonSerializerContext : JsonSerializerContext
|
public partial class InputConfigJsonSerializerContext : JsonSerializerContext
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||||
{
|
{
|
||||||
public class JsonInputConfigConverter : JsonConverter<InputConfig>
|
public class JsonInputConfigConverter : JsonConverter<InputConfig>
|
||||||
{
|
{
|
||||||
private static readonly InputConfigJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
private static InputBackendType GetInputBackendType(ref Utf8JsonReader reader)
|
private static InputBackendType GetInputBackendType(ref Utf8JsonReader reader)
|
||||||
{
|
{
|
||||||
|
@ -57,8 +57,8 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||||
|
|
||||||
return backendType switch
|
return backendType switch
|
||||||
{
|
{
|
||||||
InputBackendType.WindowKeyboard => JsonSerializer.Deserialize(ref reader, SerializerContext.StandardKeyboardInputConfig),
|
InputBackendType.WindowKeyboard => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardKeyboardInputConfig),
|
||||||
InputBackendType.GamepadSDL2 => JsonSerializer.Deserialize(ref reader, SerializerContext.StandardControllerInputConfig),
|
InputBackendType.GamepadSDL2 => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardControllerInputConfig),
|
||||||
_ => throw new InvalidOperationException($"Unknown backend type {backendType}"),
|
_ => throw new InvalidOperationException($"Unknown backend type {backendType}"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -68,10 +68,10 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||||
switch (value.Backend)
|
switch (value.Backend)
|
||||||
{
|
{
|
||||||
case InputBackendType.WindowKeyboard:
|
case InputBackendType.WindowKeyboard:
|
||||||
JsonSerializer.Serialize(writer, value as StandardKeyboardInputConfig, SerializerContext.StandardKeyboardInputConfig);
|
JsonSerializer.Serialize(writer, value as StandardKeyboardInputConfig, _serializerContext.StandardKeyboardInputConfig);
|
||||||
break;
|
break;
|
||||||
case InputBackendType.GamepadSDL2:
|
case InputBackendType.GamepadSDL2:
|
||||||
JsonSerializer.Serialize(writer, value as StandardControllerInputConfig, SerializerContext.StandardControllerInputConfig);
|
JsonSerializer.Serialize(writer, value as StandardControllerInputConfig, _serializerContext.StandardControllerInputConfig);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException($"Unknown backend type {value.Backend}");
|
throw new ArgumentException($"Unknown backend type {value.Backend}");
|
||||||
|
|
|
@ -138,6 +138,6 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||||
BackSlash,
|
BackSlash,
|
||||||
Unbound,
|
Unbound,
|
||||||
|
|
||||||
Count
|
Count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
namespace Ryujinx.Common.Configuration.Hid.Keyboard
|
namespace Ryujinx.Common.Configuration.Hid.Keyboard
|
||||||
{
|
{
|
||||||
public class GenericKeyboardInputConfig<Key> : GenericInputConfigurationCommon<Key> where Key : unmanaged
|
public class GenericKeyboardInputConfig<TKey> : GenericInputConfigurationCommon<TKey> where TKey : unmanaged
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Left JoyCon Controller Stick Bindings
|
/// Left JoyCon Controller Stick Bindings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public JoyconConfigKeyboardStick<Key> LeftJoyconStick { get; set; }
|
public JoyconConfigKeyboardStick<TKey> LeftJoyconStick { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Right JoyCon Controller Stick Bindings
|
/// Right JoyCon Controller Stick Bindings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public JoyconConfigKeyboardStick<Key> RightJoyconStick { get; set; }
|
public JoyconConfigKeyboardStick<TKey> RightJoyconStick { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
namespace Ryujinx.Common.Configuration.Hid.Keyboard
|
namespace Ryujinx.Common.Configuration.Hid.Keyboard
|
||||||
{
|
{
|
||||||
public class JoyconConfigKeyboardStick<Key> where Key: unmanaged
|
public class JoyconConfigKeyboardStick<TKey> where TKey : unmanaged
|
||||||
{
|
{
|
||||||
public Key StickUp { get; set; }
|
public TKey StickUp { get; set; }
|
||||||
public Key StickDown { get; set; }
|
public TKey StickDown { get; set; }
|
||||||
public Key StickLeft { get; set; }
|
public TKey StickLeft { get; set; }
|
||||||
public Key StickRight { get; set; }
|
public TKey StickRight { get; set; }
|
||||||
public Key StickButton { get; set; }
|
public TKey StickButton { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,4 +14,4 @@
|
||||||
public Key VolumeUp { get; set; }
|
public Key VolumeUp { get; set; }
|
||||||
public Key VolumeDown { get; set; }
|
public Key VolumeDown { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
namespace Ryujinx.Common.Configuration.Hid
|
namespace Ryujinx.Common.Configuration.Hid
|
||||||
{
|
{
|
||||||
public class LeftJoyconCommonConfig<Button>
|
public class LeftJoyconCommonConfig<TButton>
|
||||||
{
|
{
|
||||||
public Button ButtonMinus { get; set; }
|
public TButton ButtonMinus { get; set; }
|
||||||
public Button ButtonL { get; set; }
|
public TButton ButtonL { get; set; }
|
||||||
public Button ButtonZl { get; set; }
|
public TButton ButtonZl { get; set; }
|
||||||
public Button ButtonSl { get; set; }
|
public TButton ButtonSl { get; set; }
|
||||||
public Button ButtonSr { get; set; }
|
public TButton ButtonSr { get; set; }
|
||||||
public Button DpadUp { get; set; }
|
public TButton DpadUp { get; set; }
|
||||||
public Button DpadDown { get; set; }
|
public TButton DpadDown { get; set; }
|
||||||
public Button DpadLeft { get; set; }
|
public TButton DpadLeft { get; set; }
|
||||||
public Button DpadRight { get; set; }
|
public TButton DpadRight { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,16 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<PlayerIndex>))]
|
[JsonConverter(typeof(TypedStringEnumConverter<PlayerIndex>))]
|
||||||
public enum PlayerIndex
|
public enum PlayerIndex
|
||||||
{
|
{
|
||||||
Player1 = 0,
|
Player1 = 0,
|
||||||
Player2 = 1,
|
Player2 = 1,
|
||||||
Player3 = 2,
|
Player3 = 2,
|
||||||
Player4 = 3,
|
Player4 = 3,
|
||||||
Player5 = 4,
|
Player5 = 4,
|
||||||
Player6 = 5,
|
Player6 = 5,
|
||||||
Player7 = 6,
|
Player7 = 6,
|
||||||
Player8 = 7,
|
Player8 = 7,
|
||||||
Handheld = 8,
|
Handheld = 8,
|
||||||
Unknown = 9,
|
Unknown = 9,
|
||||||
Auto = 10 // Shouldn't be used directly
|
Auto = 10, // Shouldn't be used directly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
namespace Ryujinx.Common.Configuration.Hid
|
namespace Ryujinx.Common.Configuration.Hid
|
||||||
{
|
{
|
||||||
public class RightJoyconCommonConfig<Button>
|
public class RightJoyconCommonConfig<TButton>
|
||||||
{
|
{
|
||||||
public Button ButtonPlus { get; set; }
|
public TButton ButtonPlus { get; set; }
|
||||||
public Button ButtonR { get; set; }
|
public TButton ButtonR { get; set; }
|
||||||
public Button ButtonZr { get; set; }
|
public TButton ButtonZr { get; set; }
|
||||||
public Button ButtonSl { get; set; }
|
public TButton ButtonSl { get; set; }
|
||||||
public Button ButtonSr { get; set; }
|
public TButton ButtonSr { get; set; }
|
||||||
public Button ButtonX { get; set; }
|
public TButton ButtonX { get; set; }
|
||||||
public Button ButtonB { get; set; }
|
public TButton ButtonB { get; set; }
|
||||||
public Button ButtonY { get; set; }
|
public TButton ButtonY { get; set; }
|
||||||
public Button ButtonA { get; set; }
|
public TButton ButtonA { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@ namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
Never,
|
Never,
|
||||||
OnIdle,
|
OnIdle,
|
||||||
Always
|
Always,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,6 @@ namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
Bilinear,
|
Bilinear,
|
||||||
Nearest,
|
Nearest,
|
||||||
Fsr
|
Fsr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
public struct TitleUpdateMetadata
|
public struct TitleUpdateMetadata
|
||||||
{
|
{
|
||||||
public string Selected { get; set; }
|
public string Selected { get; set; }
|
||||||
public List<string> Paths { get; set; }
|
public List<string> Paths { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,4 +7,4 @@ namespace Ryujinx.Common.Configuration
|
||||||
public partial class TitleUpdateMetadataJsonSerializerContext : JsonSerializerContext
|
public partial class TitleUpdateMetadataJsonSerializerContext : JsonSerializerContext
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.IO;
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
@ -7,8 +6,7 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
public static class BinaryReaderExtensions
|
public static class BinaryReaderExtensions
|
||||||
{
|
{
|
||||||
public unsafe static T ReadStruct<T>(this BinaryReader reader)
|
public static T ReadStruct<T>(this BinaryReader reader) where T : unmanaged
|
||||||
where T : unmanaged
|
|
||||||
{
|
{
|
||||||
return MemoryMarshal.Cast<byte, T>(reader.ReadBytes(Unsafe.SizeOf<T>()))[0];
|
return MemoryMarshal.Cast<byte, T>(reader.ReadBytes(Unsafe.SizeOf<T>()))[0];
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,7 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
public static class BinaryWriterExtensions
|
public static class BinaryWriterExtensions
|
||||||
{
|
{
|
||||||
public unsafe static void WriteStruct<T>(this BinaryWriter writer, T value)
|
public static void WriteStruct<T>(this BinaryWriter writer, T value) where T : unmanaged
|
||||||
where T : unmanaged
|
|
||||||
{
|
{
|
||||||
ReadOnlySpan<byte> data = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateReadOnlySpan(ref value, 1));
|
ReadOnlySpan<byte> data = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateReadOnlySpan(ref value, 1));
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||||
Set(text);
|
Set(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Get()
|
public readonly string Get()
|
||||||
{
|
{
|
||||||
fixed (byte* data = _data)
|
fixed (byte* data = _data)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set(string text)
|
public readonly void Set(string text)
|
||||||
{
|
{
|
||||||
text += '\0';
|
text += '\0';
|
||||||
fixed (char* textPtr = text)
|
fixed (char* textPtr = text)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||||
unsafe struct NvdrsApplicationV4
|
struct NvdrsApplicationV4
|
||||||
{
|
{
|
||||||
public uint Version;
|
public uint Version;
|
||||||
public uint IsPredefined;
|
public uint IsPredefined;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
unsafe struct NvdrsProfile
|
struct NvdrsProfile
|
||||||
{
|
{
|
||||||
public uint Version;
|
public uint Version;
|
||||||
public NvapiUnicodeString ProfileName;
|
public NvapiUnicodeString ProfileName;
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit, Size = 0x3020)]
|
[StructLayout(LayoutKind.Explicit, Size = 0x3020)]
|
||||||
unsafe struct NvdrsSetting
|
struct NvdrsSetting
|
||||||
{
|
{
|
||||||
[FieldOffset(0x0)]
|
[FieldOffset(0x0)]
|
||||||
public uint Version;
|
public uint Version;
|
||||||
|
|
|
@ -97,27 +97,26 @@ namespace Ryujinx.Common.GraphicsDriver
|
||||||
|
|
||||||
Check(NvAPI_DRS_LoadSettings(handle));
|
Check(NvAPI_DRS_LoadSettings(handle));
|
||||||
|
|
||||||
IntPtr profileHandle;
|
|
||||||
|
|
||||||
// Check if the profile already exists.
|
// Check if the profile already exists.
|
||||||
|
|
||||||
int status = NvAPI_DRS_FindProfileByName(handle, new NvapiUnicodeString(ProfileName), out profileHandle);
|
int status = NvAPI_DRS_FindProfileByName(handle, new NvapiUnicodeString(ProfileName), out nint profileHandle);
|
||||||
|
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
{
|
{
|
||||||
NvdrsProfile profile = new NvdrsProfile {
|
NvdrsProfile profile = new()
|
||||||
Version = MakeVersion<NvdrsProfile>(1),
|
{
|
||||||
IsPredefined = 0,
|
Version = MakeVersion<NvdrsProfile>(1),
|
||||||
GpuSupport = uint.MaxValue
|
IsPredefined = 0,
|
||||||
|
GpuSupport = uint.MaxValue,
|
||||||
};
|
};
|
||||||
profile.ProfileName.Set(ProfileName);
|
profile.ProfileName.Set(ProfileName);
|
||||||
Check(NvAPI_DRS_CreateProfile(handle, ref profile, out profileHandle));
|
Check(NvAPI_DRS_CreateProfile(handle, ref profile, out profileHandle));
|
||||||
|
|
||||||
NvdrsApplicationV4 application = new NvdrsApplicationV4
|
NvdrsApplicationV4 application = new()
|
||||||
{
|
{
|
||||||
Version = MakeVersion<NvdrsApplicationV4>(4),
|
Version = MakeVersion<NvdrsApplicationV4>(4),
|
||||||
IsPredefined = 0,
|
IsPredefined = 0,
|
||||||
Flags = 3 // IsMetro, IsCommandLine
|
Flags = 3, // IsMetro, IsCommandLine
|
||||||
};
|
};
|
||||||
application.AppName.Set("Ryujinx.exe");
|
application.AppName.Set("Ryujinx.exe");
|
||||||
application.UserFriendlyName.Set("Ryujinx");
|
application.UserFriendlyName.Set("Ryujinx");
|
||||||
|
@ -127,7 +126,7 @@ namespace Ryujinx.Common.GraphicsDriver
|
||||||
Check(NvAPI_DRS_CreateApplication(handle, profileHandle, ref application));
|
Check(NvAPI_DRS_CreateApplication(handle, profileHandle, ref application));
|
||||||
}
|
}
|
||||||
|
|
||||||
NvdrsSetting setting = new NvdrsSetting
|
NvdrsSetting setting = new()
|
||||||
{
|
{
|
||||||
Version = MakeVersion<NvdrsSetting>(1),
|
Version = MakeVersion<NvdrsSetting>(1),
|
||||||
SettingId = Nvapi.OglThreadControlId,
|
SettingId = Nvapi.OglThreadControlId,
|
||||||
|
@ -136,7 +135,7 @@ namespace Ryujinx.Common.GraphicsDriver
|
||||||
IsCurrentPredefined = 0,
|
IsCurrentPredefined = 0,
|
||||||
IsPredefinedValid = 0,
|
IsPredefinedValid = 0,
|
||||||
CurrentValue = targetValue,
|
CurrentValue = targetValue,
|
||||||
PredefinedValue = targetValue
|
PredefinedValue = targetValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
Check(NvAPI_DRS_SetSetting(handle, profileHandle, ref setting));
|
Check(NvAPI_DRS_SetSetting(handle, profileHandle, ref setting));
|
||||||
|
@ -154,10 +153,8 @@ namespace Ryujinx.Common.GraphicsDriver
|
||||||
{
|
{
|
||||||
return Marshal.GetDelegateForFunctionPointer<T>(ptr);
|
return Marshal.GetDelegateForFunctionPointer<T>(ptr);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Ryujinx.Common
|
||||||
High = high;
|
High = high;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public readonly override string ToString()
|
||||||
{
|
{
|
||||||
return $"{High:x16}{Low:x16}";
|
return $"{High:x16}{Low:x16}";
|
||||||
}
|
}
|
||||||
|
@ -30,17 +30,17 @@ namespace Ryujinx.Common
|
||||||
return !x.Equals(y);
|
return !x.Equals(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public readonly override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
return obj is Hash128 hash128 && Equals(hash128);
|
return obj is Hash128 hash128 && Equals(hash128);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(Hash128 cmpObj)
|
public readonly bool Equals(Hash128 cmpObj)
|
||||||
{
|
{
|
||||||
return Low == cmpObj.Low && High == cmpObj.High;
|
return Low == cmpObj.Low && High == cmpObj.High;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public readonly override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCode.Combine(Low, High);
|
return HashCode.Combine(Low, High);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,11 @@ namespace Ryujinx.Common.Logging.Formatters
|
||||||
{
|
{
|
||||||
internal class DefaultLogFormatter : ILogFormatter
|
internal class DefaultLogFormatter : ILogFormatter
|
||||||
{
|
{
|
||||||
private static readonly ObjectPool<StringBuilder> StringBuilderPool = SharedPools.Default<StringBuilder>();
|
private static readonly ObjectPool<StringBuilder> _stringBuilderPool = SharedPools.Default<StringBuilder>();
|
||||||
|
|
||||||
public string Format(LogEventArgs args)
|
public string Format(LogEventArgs args)
|
||||||
{
|
{
|
||||||
StringBuilder sb = StringBuilderPool.Allocate();
|
StringBuilder sb = _stringBuilderPool.Allocate();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -44,8 +44,8 @@ namespace Ryujinx.Common.Logging.Formatters
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
StringBuilderPool.Release(sb);
|
_stringBuilderPool.Release(sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.Common.Logging.Formatters
|
||||||
{
|
{
|
||||||
internal static class DynamicObjectFormatter
|
internal static class DynamicObjectFormatter
|
||||||
{
|
{
|
||||||
private static readonly ObjectPool<StringBuilder> StringBuilderPool = SharedPools.Default<StringBuilder>();
|
private static readonly ObjectPool<StringBuilder> _stringBuilderPool = SharedPools.Default<StringBuilder>();
|
||||||
|
|
||||||
public static string? Format(object? dynamicObject)
|
public static string? Format(object? dynamicObject)
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@ namespace Ryujinx.Common.Logging.Formatters
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder sb = StringBuilderPool.Allocate();
|
StringBuilder sb = _stringBuilderPool.Allocate();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,7 @@ namespace Ryujinx.Common.Logging.Formatters
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
StringBuilderPool.Release(sb);
|
_stringBuilderPool.Release(sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ namespace Ryujinx.Common.Logging.Formatters
|
||||||
|
|
||||||
if (typeof(Array).IsAssignableFrom(prop.PropertyType))
|
if (typeof(Array).IsAssignableFrom(prop.PropertyType))
|
||||||
{
|
{
|
||||||
Array? array = (Array?) prop.GetValue(dynamicObject);
|
Array? array = (Array?)prop.GetValue(dynamicObject);
|
||||||
|
|
||||||
if (array is not null)
|
if (array is not null)
|
||||||
{
|
{
|
||||||
|
@ -81,4 +81,4 @@ namespace Ryujinx.Common.Logging.Formatters
|
||||||
sb.Append('}');
|
sb.Append('}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
{
|
{
|
||||||
string Format(LogEventArgs args);
|
string Format(LogEventArgs args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,6 @@ namespace Ryujinx.Common.Logging
|
||||||
SurfaceFlinger,
|
SurfaceFlinger,
|
||||||
TamperMachine,
|
TamperMachine,
|
||||||
Ui,
|
Ui,
|
||||||
Vic
|
Vic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,18 +6,18 @@ namespace Ryujinx.Common.Logging
|
||||||
{
|
{
|
||||||
public readonly LogLevel Level;
|
public readonly LogLevel Level;
|
||||||
public readonly TimeSpan Time;
|
public readonly TimeSpan Time;
|
||||||
public readonly string ThreadName;
|
public readonly string ThreadName;
|
||||||
|
|
||||||
public readonly string Message;
|
public readonly string Message;
|
||||||
public readonly object Data;
|
public readonly object Data;
|
||||||
|
|
||||||
public LogEventArgs(LogLevel level, TimeSpan time, string threadName, string message, object data = null)
|
public LogEventArgs(LogLevel level, TimeSpan time, string threadName, string message, object data = null)
|
||||||
{
|
{
|
||||||
Level = level;
|
Level = level;
|
||||||
Time = time;
|
Time = time;
|
||||||
ThreadName = threadName;
|
ThreadName = threadName;
|
||||||
Message = message;
|
Message = message;
|
||||||
Data = data;
|
Data = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Common.Logging
|
||||||
{
|
{
|
||||||
public LogLevel Level { get; }
|
public LogLevel Level { get; }
|
||||||
public TimeSpan Time { get; }
|
public TimeSpan Time { get; }
|
||||||
public string ThreadName { get; }
|
public string ThreadName { get; }
|
||||||
|
|
||||||
public string Message { get; }
|
public string Message { get; }
|
||||||
public string Data { get; }
|
public string Data { get; }
|
||||||
|
@ -16,11 +16,11 @@ namespace Ryujinx.Common.Logging
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public LogEventArgsJson(LogLevel level, TimeSpan time, string threadName, string message, string data = null)
|
public LogEventArgsJson(LogLevel level, TimeSpan time, string threadName, string message, string data = null)
|
||||||
{
|
{
|
||||||
Level = level;
|
Level = level;
|
||||||
Time = time;
|
Time = time;
|
||||||
ThreadName = threadName;
|
ThreadName = threadName;
|
||||||
Message = message;
|
Message = message;
|
||||||
Data = data;
|
Data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LogEventArgsJson FromLogEventArgs(LogEventArgs args)
|
public static LogEventArgsJson FromLogEventArgs(LogEventArgs args)
|
||||||
|
@ -28,4 +28,4 @@ namespace Ryujinx.Common.Logging
|
||||||
return new LogEventArgsJson(args.Level, args.Time, args.ThreadName, args.Message, DynamicObjectFormatter.Format(args.Data));
|
return new LogEventArgsJson(args.Level, args.Time, args.ThreadName, args.Message, DynamicObjectFormatter.Format(args.Data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,4 +6,4 @@ namespace Ryujinx.Common.Logging
|
||||||
internal partial class LogEventJsonSerializerContext : JsonSerializerContext
|
internal partial class LogEventJsonSerializerContext : JsonSerializerContext
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,11 @@ namespace Ryujinx.Common.Logging
|
||||||
{
|
{
|
||||||
public static class Logger
|
public static class Logger
|
||||||
{
|
{
|
||||||
private static readonly Stopwatch m_Time;
|
private static readonly Stopwatch _time;
|
||||||
|
|
||||||
private static readonly bool[] m_EnabledClasses;
|
private static readonly bool[] _enabledClasses;
|
||||||
|
|
||||||
private static readonly List<ILogTarget> m_LogTargets;
|
private static readonly List<ILogTarget> _logTargets;
|
||||||
|
|
||||||
private static readonly StdErrAdapter _stdErrAdapter;
|
private static readonly StdErrAdapter _stdErrAdapter;
|
||||||
|
|
||||||
|
@ -32,27 +32,27 @@ namespace Ryujinx.Common.Logging
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void PrintMsg(LogClass logClass, string message)
|
public void PrintMsg(LogClass logClass, string message)
|
||||||
{
|
{
|
||||||
if (m_EnabledClasses[(int)logClass])
|
if (_enabledClasses[(int)logClass])
|
||||||
{
|
{
|
||||||
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, "", message)));
|
Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, "", message)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void Print(LogClass logClass, string message, [CallerMemberName] string caller = "")
|
public void Print(LogClass logClass, string message, [CallerMemberName] string caller = "")
|
||||||
{
|
{
|
||||||
if (m_EnabledClasses[(int)logClass])
|
if (_enabledClasses[(int)logClass])
|
||||||
{
|
{
|
||||||
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message)));
|
Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void Print(LogClass logClass, string message, object data, [CallerMemberName] string caller = "")
|
public void Print(LogClass logClass, string message, object data, [CallerMemberName] string caller = "")
|
||||||
{
|
{
|
||||||
if (m_EnabledClasses[(int)logClass])
|
if (_enabledClasses[(int)logClass])
|
||||||
{
|
{
|
||||||
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message), data));
|
Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message), data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,71 +60,71 @@ namespace Ryujinx.Common.Logging
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void PrintStack(LogClass logClass, string message, [CallerMemberName] string caller = "")
|
public void PrintStack(LogClass logClass, string message, [CallerMemberName] string caller = "")
|
||||||
{
|
{
|
||||||
if (m_EnabledClasses[(int)logClass])
|
if (_enabledClasses[(int)logClass])
|
||||||
{
|
{
|
||||||
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message), new StackTrace(true)));
|
Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message), new StackTrace(true)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void PrintStub(LogClass logClass, string message = "", [CallerMemberName] string caller = "")
|
public void PrintStub(LogClass logClass, string message = "", [CallerMemberName] string caller = "")
|
||||||
{
|
{
|
||||||
if (m_EnabledClasses[(int)logClass])
|
if (_enabledClasses[(int)logClass])
|
||||||
{
|
{
|
||||||
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed. " + message)));
|
Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed. " + message)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void PrintStub(LogClass logClass, object data, [CallerMemberName] string caller = "")
|
public void PrintStub(LogClass logClass, object data, [CallerMemberName] string caller = "")
|
||||||
{
|
{
|
||||||
if (m_EnabledClasses[(int)logClass])
|
if (_enabledClasses[(int)logClass])
|
||||||
{
|
{
|
||||||
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed."), data));
|
Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed."), data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void PrintStub(LogClass logClass, string message, object data, [CallerMemberName] string caller = "")
|
public void PrintStub(LogClass logClass, string message, object data, [CallerMemberName] string caller = "")
|
||||||
{
|
{
|
||||||
if (m_EnabledClasses[(int)logClass])
|
if (_enabledClasses[(int)logClass])
|
||||||
{
|
{
|
||||||
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed. " + message), data));
|
Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed. " + message), data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void PrintRawMsg(string message)
|
public void PrintRawMsg(string message)
|
||||||
{
|
{
|
||||||
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, message));
|
Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static string FormatMessage(LogClass Class, string Caller, string Message) => $"{Class} {Caller}: {Message}";
|
private static string FormatMessage(LogClass logClass, string caller, string message) => $"{logClass} {caller}: {message}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Log? Debug { get; private set; }
|
public static Log? Debug { get; private set; }
|
||||||
public static Log? Info { get; private set; }
|
public static Log? Info { get; private set; }
|
||||||
public static Log? Warning { get; private set; }
|
public static Log? Warning { get; private set; }
|
||||||
public static Log? Error { get; private set; }
|
public static Log? Error { get; private set; }
|
||||||
public static Log? Guest { get; private set; }
|
public static Log? Guest { get; private set; }
|
||||||
public static Log? AccessLog { get; private set; }
|
public static Log? AccessLog { get; private set; }
|
||||||
public static Log? Stub { get; private set; }
|
public static Log? Stub { get; private set; }
|
||||||
public static Log? Trace { get; private set; }
|
public static Log? Trace { get; private set; }
|
||||||
public static Log Notice { get; } // Always enabled
|
public static Log Notice { get; } // Always enabled
|
||||||
|
|
||||||
static Logger()
|
static Logger()
|
||||||
{
|
{
|
||||||
m_EnabledClasses = new bool[Enum.GetNames<LogClass>().Length];
|
_enabledClasses = new bool[Enum.GetNames<LogClass>().Length];
|
||||||
|
|
||||||
for (int index = 0; index < m_EnabledClasses.Length; index++)
|
for (int index = 0; index < _enabledClasses.Length; index++)
|
||||||
{
|
{
|
||||||
m_EnabledClasses[index] = true;
|
_enabledClasses[index] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_LogTargets = new List<ILogTarget>();
|
_logTargets = new List<ILogTarget>();
|
||||||
|
|
||||||
m_Time = Stopwatch.StartNew();
|
_time = Stopwatch.StartNew();
|
||||||
|
|
||||||
// Logger should log to console by default
|
// Logger should log to console by default
|
||||||
AddTarget(new AsyncLogTargetWrapper(
|
AddTarget(new AsyncLogTargetWrapper(
|
||||||
|
@ -145,12 +145,12 @@ namespace Ryujinx.Common.Logging
|
||||||
|
|
||||||
public static void RestartTime()
|
public static void RestartTime()
|
||||||
{
|
{
|
||||||
m_Time.Restart();
|
_time.Restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ILogTarget GetTarget(string targetName)
|
private static ILogTarget GetTarget(string targetName)
|
||||||
{
|
{
|
||||||
foreach (var target in m_LogTargets)
|
foreach (var target in _logTargets)
|
||||||
{
|
{
|
||||||
if (target.Name.Equals(targetName))
|
if (target.Name.Equals(targetName))
|
||||||
{
|
{
|
||||||
|
@ -163,7 +163,7 @@ namespace Ryujinx.Common.Logging
|
||||||
|
|
||||||
public static void AddTarget(ILogTarget target)
|
public static void AddTarget(ILogTarget target)
|
||||||
{
|
{
|
||||||
m_LogTargets.Add(target);
|
_logTargets.Add(target);
|
||||||
|
|
||||||
Updated += target.Log;
|
Updated += target.Log;
|
||||||
}
|
}
|
||||||
|
@ -176,7 +176,7 @@ namespace Ryujinx.Common.Logging
|
||||||
{
|
{
|
||||||
Updated -= logTarget.Log;
|
Updated -= logTarget.Log;
|
||||||
|
|
||||||
m_LogTargets.Remove(logTarget);
|
_logTargets.Remove(logTarget);
|
||||||
|
|
||||||
logTarget.Dispose();
|
logTarget.Dispose();
|
||||||
}
|
}
|
||||||
|
@ -188,18 +188,18 @@ namespace Ryujinx.Common.Logging
|
||||||
|
|
||||||
_stdErrAdapter.Dispose();
|
_stdErrAdapter.Dispose();
|
||||||
|
|
||||||
foreach (var target in m_LogTargets)
|
foreach (var target in _logTargets)
|
||||||
{
|
{
|
||||||
target.Dispose();
|
target.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_LogTargets.Clear();
|
_logTargets.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IReadOnlyCollection<LogLevel> GetEnabledLevels()
|
public static IReadOnlyCollection<LogLevel> GetEnabledLevels()
|
||||||
{
|
{
|
||||||
var logs = new Log?[] { Debug, Info, Warning, Error, Guest, AccessLog, Stub, Trace };
|
var logs = new[] { Debug, Info, Warning, Error, Guest, AccessLog, Stub, Trace };
|
||||||
List<LogLevel> levels = new List<LogLevel>(logs.Length);
|
List<LogLevel> levels = new(logs.Length);
|
||||||
foreach (var log in logs)
|
foreach (var log in logs)
|
||||||
{
|
{
|
||||||
if (log.HasValue)
|
if (log.HasValue)
|
||||||
|
@ -215,21 +215,23 @@ namespace Ryujinx.Common.Logging
|
||||||
{
|
{
|
||||||
switch (logLevel)
|
switch (logLevel)
|
||||||
{
|
{
|
||||||
case LogLevel.Debug : Debug = enabled ? new Log(LogLevel.Debug) : new Log?(); break;
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
case LogLevel.Info : Info = enabled ? new Log(LogLevel.Info) : new Log?(); break;
|
case LogLevel.Debug : Debug = enabled ? new Log(LogLevel.Debug) : new Log?(); break;
|
||||||
case LogLevel.Warning : Warning = enabled ? new Log(LogLevel.Warning) : new Log?(); break;
|
case LogLevel.Info : Info = enabled ? new Log(LogLevel.Info) : new Log?(); break;
|
||||||
case LogLevel.Error : Error = enabled ? new Log(LogLevel.Error) : new Log?(); break;
|
case LogLevel.Warning : Warning = enabled ? new Log(LogLevel.Warning) : new Log?(); break;
|
||||||
case LogLevel.Guest : Guest = enabled ? new Log(LogLevel.Guest) : new Log?(); break;
|
case LogLevel.Error : Error = enabled ? new Log(LogLevel.Error) : new Log?(); break;
|
||||||
case LogLevel.AccessLog : AccessLog = enabled ? new Log(LogLevel.AccessLog): new Log?(); break;
|
case LogLevel.Guest : Guest = enabled ? new Log(LogLevel.Guest) : new Log?(); break;
|
||||||
case LogLevel.Stub : Stub = enabled ? new Log(LogLevel.Stub) : new Log?(); break;
|
case LogLevel.AccessLog : AccessLog = enabled ? new Log(LogLevel.AccessLog) : new Log?(); break;
|
||||||
case LogLevel.Trace : Trace = enabled ? new Log(LogLevel.Trace) : new Log?(); break;
|
case LogLevel.Stub : Stub = enabled ? new Log(LogLevel.Stub) : new Log?(); break;
|
||||||
|
case LogLevel.Trace : Trace = enabled ? new Log(LogLevel.Trace) : new Log?(); break;
|
||||||
default: throw new ArgumentException("Unknown Log Level");
|
default: throw new ArgumentException("Unknown Log Level");
|
||||||
|
#pragma warning restore IDE0055
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetEnable(LogClass logClass, bool enabled)
|
public static void SetEnable(LogClass logClass, bool enabled)
|
||||||
{
|
{
|
||||||
m_EnabledClasses[(int)logClass] = enabled;
|
_enabledClasses[(int)logClass] = enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,16 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Discard the overflowing item
|
/// Discard the overflowing item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Discard = 1
|
Discard = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AsyncLogTargetWrapper : ILogTarget
|
public class AsyncLogTargetWrapper : ILogTarget
|
||||||
{
|
{
|
||||||
private ILogTarget _target;
|
private readonly ILogTarget _target;
|
||||||
|
|
||||||
private Thread _messageThread;
|
private readonly Thread _messageThread;
|
||||||
|
|
||||||
private BlockingCollection<LogEventArgs> _messageQueue;
|
private readonly BlockingCollection<LogEventArgs> _messageQueue;
|
||||||
|
|
||||||
private readonly int _overflowTimeout;
|
private readonly int _overflowTimeout;
|
||||||
|
|
||||||
|
@ -35,11 +35,12 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
|
|
||||||
public AsyncLogTargetWrapper(ILogTarget target, int queueLimit, AsyncLogTargetOverflowAction overflowAction)
|
public AsyncLogTargetWrapper(ILogTarget target, int queueLimit, AsyncLogTargetOverflowAction overflowAction)
|
||||||
{
|
{
|
||||||
_target = target;
|
_target = target;
|
||||||
_messageQueue = new BlockingCollection<LogEventArgs>(queueLimit);
|
_messageQueue = new BlockingCollection<LogEventArgs>(queueLimit);
|
||||||
_overflowTimeout = overflowAction == AsyncLogTargetOverflowAction.Block ? -1 : 0;
|
_overflowTimeout = overflowAction == AsyncLogTargetOverflowAction.Block ? -1 : 0;
|
||||||
|
|
||||||
_messageThread = new Thread(() => {
|
_messageThread = new Thread(() =>
|
||||||
|
{
|
||||||
while (!_messageQueue.IsCompleted)
|
while (!_messageQueue.IsCompleted)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -55,10 +56,11 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
// on the next iteration.
|
// on the next iteration.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
{
|
||||||
_messageThread.Name = "Logger.MessageThread";
|
Name = "Logger.MessageThread",
|
||||||
_messageThread.IsBackground = true;
|
IsBackground = true,
|
||||||
|
};
|
||||||
_messageThread.Start();
|
_messageThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,8 +74,9 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
_messageQueue.CompleteAdding();
|
_messageQueue.CompleteAdding();
|
||||||
_messageThread.Join();
|
_messageThread.Join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,20 +11,21 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
|
|
||||||
string ILogTarget.Name { get => _name; }
|
string ILogTarget.Name { get => _name; }
|
||||||
|
|
||||||
private static ConsoleColor GetLogColor(LogLevel level) => level switch {
|
private static ConsoleColor GetLogColor(LogLevel level) => level switch
|
||||||
LogLevel.Info => ConsoleColor.White,
|
{
|
||||||
|
LogLevel.Info => ConsoleColor.White,
|
||||||
LogLevel.Warning => ConsoleColor.Yellow,
|
LogLevel.Warning => ConsoleColor.Yellow,
|
||||||
LogLevel.Error => ConsoleColor.Red,
|
LogLevel.Error => ConsoleColor.Red,
|
||||||
LogLevel.Stub => ConsoleColor.DarkGray,
|
LogLevel.Stub => ConsoleColor.DarkGray,
|
||||||
LogLevel.Notice => ConsoleColor.Cyan,
|
LogLevel.Notice => ConsoleColor.Cyan,
|
||||||
LogLevel.Trace => ConsoleColor.DarkCyan,
|
LogLevel.Trace => ConsoleColor.DarkCyan,
|
||||||
_ => ConsoleColor.Gray,
|
_ => ConsoleColor.Gray,
|
||||||
};
|
};
|
||||||
|
|
||||||
public ConsoleLogTarget(string name)
|
public ConsoleLogTarget(string name)
|
||||||
{
|
{
|
||||||
_formatter = new DefaultLogFormatter();
|
_formatter = new DefaultLogFormatter();
|
||||||
_name = name;
|
_name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Log(object sender, LogEventArgs args)
|
public void Log(object sender, LogEventArgs args)
|
||||||
|
@ -36,7 +37,8 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
{
|
{
|
||||||
public class FileLogTarget : ILogTarget
|
public class FileLogTarget : ILogTarget
|
||||||
{
|
{
|
||||||
private readonly StreamWriter _logWriter;
|
private readonly StreamWriter _logWriter;
|
||||||
private readonly ILogFormatter _formatter;
|
private readonly ILogFormatter _formatter;
|
||||||
private readonly string _name;
|
private readonly string _name;
|
||||||
|
|
||||||
string ILogTarget.Name { get => _name; }
|
string ILogTarget.Name { get => _name; }
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
public FileLogTarget(string path, string name, FileShare fileShare, FileMode fileMode)
|
public FileLogTarget(string path, string name, FileShare fileShare, FileMode fileMode)
|
||||||
{
|
{
|
||||||
// Ensure directory is present
|
// Ensure directory is present
|
||||||
DirectoryInfo logDir = new DirectoryInfo(Path.Combine(path, "Logs"));
|
DirectoryInfo logDir = new(Path.Combine(path, "Logs"));
|
||||||
logDir.Create();
|
logDir.Create();
|
||||||
|
|
||||||
// Clean up old logs, should only keep 3
|
// Clean up old logs, should only keep 3
|
||||||
|
@ -33,9 +33,9 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
string version = ReleaseInformation.GetVersion();
|
string version = ReleaseInformation.GetVersion();
|
||||||
|
|
||||||
// Get path for the current time
|
// Get path for the current time
|
||||||
path = Path.Combine(logDir.FullName, $"Ryujinx_{version}_{DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")}.log");
|
path = Path.Combine(logDir.FullName, $"Ryujinx_{version}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log");
|
||||||
|
|
||||||
_name = name;
|
_name = name;
|
||||||
_logWriter = new StreamWriter(File.Open(path, fileMode, FileAccess.Write, fileShare));
|
_logWriter = new StreamWriter(File.Open(path, fileMode, FileAccess.Write, fileShare));
|
||||||
_formatter = new DefaultLogFormatter();
|
_formatter = new DefaultLogFormatter();
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
_logWriter.WriteLine("---- End of Log ----");
|
_logWriter.WriteLine("---- End of Log ----");
|
||||||
_logWriter.Flush();
|
_logWriter.Flush();
|
||||||
_logWriter.Dispose();
|
_logWriter.Dispose();
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Logging.Targets
|
namespace Ryujinx.Common.Logging.Targets
|
||||||
{
|
{
|
||||||
public class JsonLogTarget : ILogTarget
|
public class JsonLogTarget : ILogTarget
|
||||||
{
|
{
|
||||||
private Stream _stream;
|
private readonly Stream _stream;
|
||||||
private bool _leaveOpen;
|
private readonly bool _leaveOpen;
|
||||||
private string _name;
|
private readonly string _name;
|
||||||
|
|
||||||
string ILogTarget.Name { get => _name; }
|
string ILogTarget.Name { get => _name; }
|
||||||
|
|
||||||
public JsonLogTarget(Stream stream, string name)
|
public JsonLogTarget(Stream stream, string name)
|
||||||
{
|
{
|
||||||
_stream = stream;
|
_stream = stream;
|
||||||
_name = name;
|
_name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonLogTarget(Stream stream, bool leaveOpen)
|
public JsonLogTarget(Stream stream, bool leaveOpen)
|
||||||
{
|
{
|
||||||
_stream = stream;
|
_stream = stream;
|
||||||
_leaveOpen = leaveOpen;
|
_leaveOpen = leaveOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ namespace Ryujinx.Common.Logging.Targets
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
if (!_leaveOpen)
|
if (!_leaveOpen)
|
||||||
{
|
{
|
||||||
_stream.Dispose();
|
_stream.Dispose();
|
||||||
|
|
|
@ -16,12 +16,12 @@ namespace Ryujinx.Common.Memory
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Null pointer.
|
/// Null pointer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static ArrayPtr<T> Null => new ArrayPtr<T>() { _ptr = IntPtr.Zero };
|
public static ArrayPtr<T> Null => new() { _ptr = IntPtr.Zero };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the pointer is null, false otherwise.
|
/// True if the pointer is null, false otherwise.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsNull => _ptr == IntPtr.Zero;
|
public readonly bool IsNull => _ptr == IntPtr.Zero;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of elements on the array.
|
/// Number of elements on the array.
|
||||||
|
@ -37,7 +37,7 @@ namespace Ryujinx.Common.Memory
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="index">Index of the element</param>
|
/// <param name="index">Index of the element</param>
|
||||||
/// <returns>Reference to the element at the given index</returns>
|
/// <returns>Reference to the element at the given index</returns>
|
||||||
public ref T this[int index] => ref Unsafe.AsRef<T>((T*)_ptr + index);
|
public readonly ref T this[int index] => ref Unsafe.AsRef<T>((T*)_ptr + index);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new array from a given reference.
|
/// Creates a new array from a given reference.
|
||||||
|
@ -81,7 +81,7 @@ namespace Ryujinx.Common.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="start">Index where the new array should start</param>
|
/// <param name="start">Index where the new array should start</param>
|
||||||
/// <returns>New array starting at the specified position</returns>
|
/// <returns>New array starting at the specified position</returns>
|
||||||
public ArrayPtr<T> Slice(int start) => new ArrayPtr<T>(ref this[start], Length - start);
|
public ArrayPtr<T> Slice(int start) => new(ref this[start], Length - start);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a span from the array.
|
/// Gets a span from the array.
|
||||||
|
@ -93,19 +93,19 @@ namespace Ryujinx.Common.Memory
|
||||||
/// Gets the array base pointer.
|
/// Gets the array base pointer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Base pointer</returns>
|
/// <returns>Base pointer</returns>
|
||||||
public T* ToPointer() => (T*)_ptr;
|
public readonly T* ToPointer() => (T*)_ptr;
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public readonly override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
return obj is ArrayPtr<T> other && Equals(other);
|
return obj is ArrayPtr<T> other && Equals(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals([AllowNull] ArrayPtr<T> other)
|
public readonly bool Equals([AllowNull] ArrayPtr<T> other)
|
||||||
{
|
{
|
||||||
return _ptr == other._ptr && Length == other.Length;
|
return _ptr == other._ptr && Length == other.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public readonly override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCode.Combine(_ptr, Length);
|
return HashCode.Combine(_ptr, Length);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Ryujinx.Common.Memory
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
byte[] array = _array;
|
byte[] array = _array;
|
||||||
|
|
||||||
ObjectDisposedException.ThrowIf(array is null, this);
|
ObjectDisposedException.ThrowIf(array is null, this);
|
||||||
|
|
||||||
return new Memory<byte>(array, 0, _length);
|
return new Memory<byte>(array, 0, _length);
|
||||||
|
@ -40,7 +40,7 @@ namespace Ryujinx.Common.Memory
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
var array = Interlocked.Exchange(ref _array, null);
|
var array = Interlocked.Exchange(ref _array, null);
|
||||||
|
|
||||||
if (array != null)
|
if (array != null)
|
||||||
{
|
{
|
||||||
ArrayPool<byte>.Shared.Return(array);
|
ArrayPool<byte>.Shared.Return(array);
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Common.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class ByteMemoryPool
|
public sealed partial class ByteMemoryPool
|
||||||
{
|
{
|
||||||
private static readonly ByteMemoryPool _shared = new ByteMemoryPool();
|
private static readonly ByteMemoryPool _shared = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a <see cref="ByteMemoryPool"/> instance. Private to force access through
|
/// Constructs a <see cref="ByteMemoryPool"/> instance. Private to force access through
|
||||||
|
@ -27,7 +27,7 @@ namespace Ryujinx.Common.Memory
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the maximum buffer size supported by this pool.
|
/// Returns the maximum buffer size supported by this pool.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int MaxBufferSize => Array.MaxLength;
|
public static int MaxBufferSize => Array.MaxLength;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>.
|
/// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>.
|
||||||
|
@ -36,7 +36,7 @@ namespace Ryujinx.Common.Memory
|
||||||
/// <param name="length">The buffer's required length in bytes</param>
|
/// <param name="length">The buffer's required length in bytes</param>
|
||||||
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
||||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
public IMemoryOwner<byte> Rent(long length)
|
public static IMemoryOwner<byte> Rent(long length)
|
||||||
=> RentImpl(checked((int)length));
|
=> RentImpl(checked((int)length));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -46,7 +46,7 @@ namespace Ryujinx.Common.Memory
|
||||||
/// <param name="length">The buffer's required length in bytes</param>
|
/// <param name="length">The buffer's required length in bytes</param>
|
||||||
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
||||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
public IMemoryOwner<byte> Rent(ulong length)
|
public static IMemoryOwner<byte> Rent(ulong length)
|
||||||
=> RentImpl(checked((int)length));
|
=> RentImpl(checked((int)length));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -56,7 +56,7 @@ namespace Ryujinx.Common.Memory
|
||||||
/// <param name="length">The buffer's required length in bytes</param>
|
/// <param name="length">The buffer's required length in bytes</param>
|
||||||
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
||||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
public IMemoryOwner<byte> Rent(int length)
|
public static IMemoryOwner<byte> Rent(int length)
|
||||||
=> RentImpl(length);
|
=> RentImpl(length);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.Common.Memory
|
||||||
/// <param name="length">The buffer's required length in bytes</param>
|
/// <param name="length">The buffer's required length in bytes</param>
|
||||||
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
||||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
public IMemoryOwner<byte> RentCleared(long length)
|
public static IMemoryOwner<byte> RentCleared(long length)
|
||||||
=> RentCleared(checked((int)length));
|
=> RentCleared(checked((int)length));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -76,7 +76,7 @@ namespace Ryujinx.Common.Memory
|
||||||
/// <param name="length">The buffer's required length in bytes</param>
|
/// <param name="length">The buffer's required length in bytes</param>
|
||||||
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
||||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
public IMemoryOwner<byte> RentCleared(ulong length)
|
public static IMemoryOwner<byte> RentCleared(ulong length)
|
||||||
=> RentCleared(checked((int)length));
|
=> RentCleared(checked((int)length));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -86,12 +86,12 @@ namespace Ryujinx.Common.Memory
|
||||||
/// <param name="length">The buffer's required length in bytes</param>
|
/// <param name="length">The buffer's required length in bytes</param>
|
||||||
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
|
||||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
public IMemoryOwner<byte> RentCleared(int length)
|
public static IMemoryOwner<byte> RentCleared(int length)
|
||||||
{
|
{
|
||||||
var buffer = RentImpl(length);
|
var buffer = RentImpl(length);
|
||||||
|
|
||||||
buffer.Memory.Span.Clear();
|
buffer.Memory.Span.Clear();
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace Ryujinx.Common.Memory
|
||||||
{
|
{
|
||||||
public static class MemoryStreamManager
|
public static class MemoryStreamManager
|
||||||
{
|
{
|
||||||
private static readonly RecyclableMemoryStreamManager _shared = new RecyclableMemoryStreamManager();
|
private static readonly RecyclableMemoryStreamManager _shared = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// We don't expose the <c>RecyclableMemoryStreamManager</c> directly because version 2.x
|
/// We don't expose the <c>RecyclableMemoryStreamManager</c> directly because version 2.x
|
||||||
|
@ -19,7 +19,7 @@ namespace Ryujinx.Common.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A <c>RecyclableMemoryStream</c></returns>
|
/// <returns>A <c>RecyclableMemoryStream</c></returns>
|
||||||
public static RecyclableMemoryStream GetStream()
|
public static RecyclableMemoryStream GetStream()
|
||||||
=> new RecyclableMemoryStream(_shared);
|
=> new(_shared);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieve a new <c>MemoryStream</c> object with the contents copied from the provided
|
/// Retrieve a new <c>MemoryStream</c> object with the contents copied from the provided
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers;
|
using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Memory.PartialUnmaps
|
namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||||
|
@ -14,15 +13,15 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||||
public int WriteLock;
|
public int WriteLock;
|
||||||
public int ReaderCount;
|
public int ReaderCount;
|
||||||
|
|
||||||
public static int WriteLockOffset;
|
public static readonly int WriteLockOffset;
|
||||||
public static int ReaderCountOffset;
|
public static readonly int ReaderCountOffset;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Populates the field offsets for use when emitting native code.
|
/// Populates the field offsets for use when emitting native code.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static NativeReaderWriterLock()
|
static NativeReaderWriterLock()
|
||||||
{
|
{
|
||||||
NativeReaderWriterLock instance = new NativeReaderWriterLock();
|
NativeReaderWriterLock instance = new();
|
||||||
|
|
||||||
WriteLockOffset = OffsetOf(ref instance, ref instance.WriteLock);
|
WriteLockOffset = OffsetOf(ref instance, ref instance.WriteLock);
|
||||||
ReaderCountOffset = OffsetOf(ref instance, ref instance.ReaderCount);
|
ReaderCountOffset = OffsetOf(ref instance, ref instance.ReaderCount);
|
||||||
|
@ -35,7 +34,9 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||||
{
|
{
|
||||||
// Must take write lock for a very short time to become a reader.
|
// Must take write lock for a very short time to become a reader.
|
||||||
|
|
||||||
while (Interlocked.CompareExchange(ref WriteLock, 1, 0) != 0) { }
|
while (Interlocked.CompareExchange(ref WriteLock, 1, 0) != 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Interlocked.Increment(ref ReaderCount);
|
Interlocked.Increment(ref ReaderCount);
|
||||||
|
|
||||||
|
@ -60,11 +61,15 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||||
|
|
||||||
Interlocked.Decrement(ref ReaderCount);
|
Interlocked.Decrement(ref ReaderCount);
|
||||||
|
|
||||||
while (Interlocked.CompareExchange(ref WriteLock, 1, 0) != 0) { }
|
while (Interlocked.CompareExchange(ref WriteLock, 1, 0) != 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for reader count to drop to 0, then take the lock again as the only reader.
|
// Wait for reader count to drop to 0, then take the lock again as the only reader.
|
||||||
|
|
||||||
while (Interlocked.CompareExchange(ref ReaderCount, 1, 0) != 0) { }
|
while (Interlocked.CompareExchange(ref ReaderCount, 1, 0) != 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.InteropServices.Marshalling;
|
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers;
|
using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Memory.PartialUnmaps
|
namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||||
|
@ -35,7 +33,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||||
[return: MarshalAs (UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
private static partial bool CloseHandle(IntPtr hObject);
|
private static partial bool CloseHandle(IntPtr hObject);
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
|
@ -48,7 +46,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static unsafe PartialUnmapState()
|
static unsafe PartialUnmapState()
|
||||||
{
|
{
|
||||||
PartialUnmapState instance = new PartialUnmapState();
|
PartialUnmapState instance = new();
|
||||||
|
|
||||||
PartialUnmapLockOffset = OffsetOf(ref instance, ref instance.PartialUnmapLock);
|
PartialUnmapLockOffset = OffsetOf(ref instance, ref instance.PartialUnmapLock);
|
||||||
PartialUnmapsCountOffset = OffsetOf(ref instance, ref instance.PartialUnmapsCount);
|
PartialUnmapsCountOffset = OffsetOf(ref instance, ref instance.PartialUnmapsCount);
|
||||||
|
@ -160,4 +158,4 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers;
|
using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Memory.PartialUnmaps
|
namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||||
|
@ -18,15 +17,15 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||||
public Array20<int> ThreadIds;
|
public Array20<int> ThreadIds;
|
||||||
public Array20<T> Structs;
|
public Array20<T> Structs;
|
||||||
|
|
||||||
public static int ThreadIdsOffset;
|
public static readonly int ThreadIdsOffset;
|
||||||
public static int StructsOffset;
|
public static readonly int StructsOffset;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Populates the field offsets for use when emitting native code.
|
/// Populates the field offsets for use when emitting native code.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static ThreadLocalMap()
|
static ThreadLocalMap()
|
||||||
{
|
{
|
||||||
ThreadLocalMap<T> instance = new ThreadLocalMap<T>();
|
ThreadLocalMap<T> instance = new();
|
||||||
|
|
||||||
ThreadIdsOffset = OffsetOf(ref instance, ref instance.ThreadIds);
|
ThreadIdsOffset = OffsetOf(ref instance, ref instance.ThreadIds);
|
||||||
StructsOffset = OffsetOf(ref instance, ref instance.Structs);
|
StructsOffset = OffsetOf(ref instance, ref instance.Structs);
|
||||||
|
|
|
@ -15,17 +15,17 @@ namespace Ryujinx.Common.Memory
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Null pointer.
|
/// Null pointer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Ptr<T> Null => new Ptr<T>() { _ptr = IntPtr.Zero };
|
public static Ptr<T> Null => new() { _ptr = IntPtr.Zero };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the pointer is null, false otherwise.
|
/// True if the pointer is null, false otherwise.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsNull => _ptr == IntPtr.Zero;
|
public readonly bool IsNull => _ptr == IntPtr.Zero;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a reference to the value.
|
/// Gets a reference to the value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ref T Value => ref Unsafe.AsRef<T>((void*)_ptr);
|
public readonly ref T Value => ref Unsafe.AsRef<T>((void*)_ptr);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new pointer to an unmanaged resource.
|
/// Creates a new pointer to an unmanaged resource.
|
||||||
|
@ -40,17 +40,17 @@ namespace Ryujinx.Common.Memory
|
||||||
_ptr = (IntPtr)Unsafe.AsPointer(ref value);
|
_ptr = (IntPtr)Unsafe.AsPointer(ref value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public readonly override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
return obj is Ptr<T> other && Equals(other);
|
return obj is Ptr<T> other && Equals(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals([AllowNull] Ptr<T> other)
|
public readonly bool Equals([AllowNull] Ptr<T> other)
|
||||||
{
|
{
|
||||||
return _ptr == other._ptr;
|
return _ptr == other._ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public readonly override int GetHashCode()
|
||||||
{
|
{
|
||||||
return _ptr.GetHashCode();
|
return _ptr.GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Common.Memory
|
||||||
{
|
{
|
||||||
private ReadOnlySpan<byte> _input;
|
private ReadOnlySpan<byte> _input;
|
||||||
|
|
||||||
public int Length => _input.Length;
|
public readonly int Length => _input.Length;
|
||||||
|
|
||||||
public SpanReader(ReadOnlySpan<byte> input)
|
public SpanReader(ReadOnlySpan<byte> input)
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ namespace Ryujinx.Common.Memory
|
||||||
{
|
{
|
||||||
T value = MemoryMarshal.Cast<byte, T>(_input)[0];
|
T value = MemoryMarshal.Cast<byte, T>(_input)[0];
|
||||||
|
|
||||||
_input = _input.Slice(Unsafe.SizeOf<T>());
|
_input = _input[Unsafe.SizeOf<T>()..];
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -37,16 +37,16 @@ namespace Ryujinx.Common.Memory
|
||||||
|
|
||||||
value = MemoryMarshal.Cast<byte, T>(_input)[0];
|
value = MemoryMarshal.Cast<byte, T>(_input)[0];
|
||||||
|
|
||||||
_input = _input.Slice(valueSize);
|
_input = _input[valueSize..];
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlySpan<byte> GetSpan(int size)
|
public ReadOnlySpan<byte> GetSpan(int size)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<byte> data = _input.Slice(0, size);
|
ReadOnlySpan<byte> data = _input[..size];
|
||||||
|
|
||||||
_input = _input.Slice(size);
|
_input = _input[size..];
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -56,19 +56,19 @@ namespace Ryujinx.Common.Memory
|
||||||
return GetSpan((int)Math.Min((uint)_input.Length, (uint)size));
|
return GetSpan((int)Math.Min((uint)_input.Length, (uint)size));
|
||||||
}
|
}
|
||||||
|
|
||||||
public T ReadAt<T>(int offset) where T : unmanaged
|
public readonly T ReadAt<T>(int offset) where T : unmanaged
|
||||||
{
|
{
|
||||||
return MemoryMarshal.Cast<byte, T>(_input.Slice(offset))[0];
|
return MemoryMarshal.Cast<byte, T>(_input[offset..])[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlySpan<byte> GetSpanAt(int offset, int size)
|
public readonly ReadOnlySpan<byte> GetSpanAt(int offset, int size)
|
||||||
{
|
{
|
||||||
return _input.Slice(offset, size);
|
return _input.Slice(offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Skip(int size)
|
public void Skip(int size)
|
||||||
{
|
{
|
||||||
_input = _input.Slice(size);
|
_input = _input[size..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Common.Memory
|
||||||
{
|
{
|
||||||
private Span<byte> _output;
|
private Span<byte> _output;
|
||||||
|
|
||||||
public int Length => _output.Length;
|
public readonly int Length => _output.Length;
|
||||||
|
|
||||||
public SpanWriter(Span<byte> output)
|
public SpanWriter(Span<byte> output)
|
||||||
{
|
{
|
||||||
|
@ -18,28 +18,28 @@ namespace Ryujinx.Common.Memory
|
||||||
public void Write<T>(T value) where T : unmanaged
|
public void Write<T>(T value) where T : unmanaged
|
||||||
{
|
{
|
||||||
MemoryMarshal.Cast<byte, T>(_output)[0] = value;
|
MemoryMarshal.Cast<byte, T>(_output)[0] = value;
|
||||||
_output = _output.Slice(Unsafe.SizeOf<T>());
|
_output = _output[Unsafe.SizeOf<T>()..];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(ReadOnlySpan<byte> data)
|
public void Write(ReadOnlySpan<byte> data)
|
||||||
{
|
{
|
||||||
data.CopyTo(_output.Slice(0, data.Length));
|
data.CopyTo(_output[..data.Length]);
|
||||||
_output = _output.Slice(data.Length);
|
_output = _output[data.Length..];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteAt<T>(int offset, T value) where T : unmanaged
|
public readonly void WriteAt<T>(int offset, T value) where T : unmanaged
|
||||||
{
|
{
|
||||||
MemoryMarshal.Cast<byte, T>(_output.Slice(offset))[0] = value;
|
MemoryMarshal.Cast<byte, T>(_output[offset..])[0] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteAt(int offset, ReadOnlySpan<byte> data)
|
public readonly void WriteAt(int offset, ReadOnlySpan<byte> data)
|
||||||
{
|
{
|
||||||
data.CopyTo(_output.Slice(offset, data.Length));
|
data.CopyTo(_output.Slice(offset, data.Length));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Skip(int size)
|
public void Skip(int size)
|
||||||
{
|
{
|
||||||
_output = _output.Slice(size);
|
_output = _output[size..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,654 +1,658 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
#pragma warning disable CS0169, IDE0051 // Remove unused private member
|
||||||
namespace Ryujinx.Common.Memory
|
namespace Ryujinx.Common.Memory
|
||||||
{
|
{
|
||||||
public struct Array1<T> : IArray<T> where T : unmanaged
|
public struct Array1<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
T _e0;
|
T _e0;
|
||||||
public int Length => 1;
|
public readonly int Length => 1;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 1);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array2<T> : IArray<T> where T : unmanaged
|
public struct Array2<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array1<T> _other;
|
Array1<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 2;
|
||||||
public int Length => 2;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 2);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array3<T> : IArray<T> where T : unmanaged
|
public struct Array3<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array2<T> _other;
|
Array2<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 3;
|
||||||
public int Length => 3;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 3);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array4<T> : IArray<T> where T : unmanaged
|
public struct Array4<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array3<T> _other;
|
Array3<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 4;
|
||||||
public int Length => 4;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 4);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array5<T> : IArray<T> where T : unmanaged
|
public struct Array5<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array4<T> _other;
|
Array4<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 5;
|
||||||
public int Length => 5;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 5);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array6<T> : IArray<T> where T : unmanaged
|
public struct Array6<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array5<T> _other;
|
Array5<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 6;
|
||||||
public int Length => 6;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 6);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array7<T> : IArray<T> where T : unmanaged
|
public struct Array7<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array6<T> _other;
|
Array6<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 7;
|
||||||
public int Length => 7;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 7);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array8<T> : IArray<T> where T : unmanaged
|
public struct Array8<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array7<T> _other;
|
Array7<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 8;
|
||||||
public int Length => 8;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 8);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array9<T> : IArray<T> where T : unmanaged
|
public struct Array9<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array8<T> _other;
|
Array8<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 9;
|
||||||
public int Length => 9;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 9);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array10<T> : IArray<T> where T : unmanaged
|
public struct Array10<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array9<T> _other;
|
Array9<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 10;
|
||||||
public int Length => 10;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 10);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array11<T> : IArray<T> where T : unmanaged
|
public struct Array11<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array10<T> _other;
|
Array10<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 11;
|
||||||
public int Length => 11;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 11);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array12<T> : IArray<T> where T : unmanaged
|
public struct Array12<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array11<T> _other;
|
Array11<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 12;
|
||||||
public int Length => 12;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 12);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array13<T> : IArray<T> where T : unmanaged
|
public struct Array13<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array12<T> _other;
|
Array12<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 13;
|
||||||
public int Length => 13;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 13);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array14<T> : IArray<T> where T : unmanaged
|
public struct Array14<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array13<T> _other;
|
Array13<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 14;
|
||||||
public int Length => 14;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 14);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array15<T> : IArray<T> where T : unmanaged
|
public struct Array15<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array14<T> _other;
|
Array14<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 15;
|
||||||
public int Length => 15;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 15);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array16<T> : IArray<T> where T : unmanaged
|
public struct Array16<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array15<T> _other;
|
Array15<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 16;
|
||||||
public int Length => 16;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 16);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array17<T> : IArray<T> where T : unmanaged
|
public struct Array17<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array16<T> _other;
|
Array16<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 17;
|
||||||
public int Length => 17;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 17);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array18<T> : IArray<T> where T : unmanaged
|
public struct Array18<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array17<T> _other;
|
Array17<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 18;
|
||||||
public int Length => 18;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 18);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array19<T> : IArray<T> where T : unmanaged
|
public struct Array19<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array18<T> _other;
|
Array18<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 19;
|
||||||
public int Length => 19;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 19);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array20<T> : IArray<T> where T : unmanaged
|
public struct Array20<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array19<T> _other;
|
Array19<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 20;
|
||||||
public int Length => 20;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 20);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array21<T> : IArray<T> where T : unmanaged
|
public struct Array21<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array20<T> _other;
|
Array20<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 21;
|
||||||
public int Length => 21;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 21);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array22<T> : IArray<T> where T : unmanaged
|
public struct Array22<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array21<T> _other;
|
Array21<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 22;
|
||||||
public int Length => 22;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 22);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array23<T> : IArray<T> where T : unmanaged
|
public struct Array23<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array22<T> _other;
|
Array22<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 23;
|
||||||
public int Length => 23;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 23);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array24<T> : IArray<T> where T : unmanaged
|
public struct Array24<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array23<T> _other;
|
Array23<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 24;
|
public readonly int Length => 24;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 24);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array25<T> : IArray<T> where T : unmanaged
|
public struct Array25<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array24<T> _other;
|
Array24<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 25;
|
public readonly int Length => 25;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 25);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array26<T> : IArray<T> where T : unmanaged
|
public struct Array26<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array25<T> _other;
|
Array25<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 26;
|
public readonly int Length => 26;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 26);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array27<T> : IArray<T> where T : unmanaged
|
public struct Array27<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array26<T> _other;
|
Array26<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 27;
|
public readonly int Length => 27;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 27);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array28<T> : IArray<T> where T : unmanaged
|
public struct Array28<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array27<T> _other;
|
Array27<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 28;
|
public readonly int Length => 28;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 28);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array29<T> : IArray<T> where T : unmanaged
|
public struct Array29<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array28<T> _other;
|
Array28<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 29;
|
public readonly int Length => 29;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 29);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array30<T> : IArray<T> where T : unmanaged
|
public struct Array30<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array29<T> _other;
|
Array29<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 30;
|
public readonly int Length => 30;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 30);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array31<T> : IArray<T> where T : unmanaged
|
public struct Array31<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array30<T> _other;
|
Array30<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 31;
|
public readonly int Length => 31;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 31);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array32<T> : IArray<T> where T : unmanaged
|
public struct Array32<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array31<T> _other;
|
Array31<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 32;
|
public readonly int Length => 32;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 32);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array33<T> : IArray<T> where T : unmanaged
|
public struct Array33<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array32<T> _other;
|
Array32<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 33;
|
public readonly int Length => 33;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 33);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array34<T> : IArray<T> where T : unmanaged
|
public struct Array34<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array33<T> _other;
|
Array33<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 34;
|
public readonly int Length => 34;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 34);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array35<T> : IArray<T> where T : unmanaged
|
public struct Array35<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array34<T> _other;
|
Array34<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 35;
|
public readonly int Length => 35;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 35);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array36<T> : IArray<T> where T : unmanaged
|
public struct Array36<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array35<T> _other;
|
Array35<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 36;
|
public readonly int Length => 36;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 36);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array37<T> : IArray<T> where T : unmanaged
|
public struct Array37<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array36<T> _other;
|
Array36<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 37;
|
public readonly int Length => 37;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 37);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array38<T> : IArray<T> where T : unmanaged
|
public struct Array38<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array37<T> _other;
|
Array37<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 38;
|
public readonly int Length => 38;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 38);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array39<T> : IArray<T> where T : unmanaged
|
public struct Array39<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array38<T> _other;
|
Array38<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 39;
|
public readonly int Length => 39;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 39);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array40<T> : IArray<T> where T : unmanaged
|
public struct Array40<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array39<T> _other;
|
Array39<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 40;
|
public readonly int Length => 40;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 40);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array41<T> : IArray<T> where T : unmanaged
|
public struct Array41<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array40<T> _other;
|
Array40<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 41;
|
public readonly int Length => 41;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 41);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array42<T> : IArray<T> where T : unmanaged
|
public struct Array42<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array41<T> _other;
|
Array41<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 42;
|
public readonly int Length => 42;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 42);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array43<T> : IArray<T> where T : unmanaged
|
public struct Array43<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array42<T> _other;
|
Array42<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 43;
|
public readonly int Length => 43;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 43);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array44<T> : IArray<T> where T : unmanaged
|
public struct Array44<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array43<T> _other;
|
Array43<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 44;
|
public readonly int Length => 44;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 44);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array45<T> : IArray<T> where T : unmanaged
|
public struct Array45<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array44<T> _other;
|
Array44<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 45;
|
public readonly int Length => 45;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 45);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array46<T> : IArray<T> where T : unmanaged
|
public struct Array46<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array45<T> _other;
|
Array45<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 46;
|
public readonly int Length => 46;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 46);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array47<T> : IArray<T> where T : unmanaged
|
public struct Array47<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array46<T> _other;
|
Array46<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 47;
|
public readonly int Length => 47;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 47);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array48<T> : IArray<T> where T : unmanaged
|
public struct Array48<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array47<T> _other;
|
Array47<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 48;
|
public readonly int Length => 48;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 48);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array49<T> : IArray<T> where T : unmanaged
|
public struct Array49<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array48<T> _other;
|
Array48<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 49;
|
public readonly int Length => 49;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 49);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array50<T> : IArray<T> where T : unmanaged
|
public struct Array50<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array49<T> _other;
|
Array49<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 50;
|
public readonly int Length => 50;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 50);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array51<T> : IArray<T> where T : unmanaged
|
public struct Array51<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array50<T> _other;
|
Array50<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 51;
|
public readonly int Length => 51;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 51);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array52<T> : IArray<T> where T : unmanaged
|
public struct Array52<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array51<T> _other;
|
Array51<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 52;
|
public readonly int Length => 52;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 52);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array53<T> : IArray<T> where T : unmanaged
|
public struct Array53<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array52<T> _other;
|
Array52<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 53;
|
public readonly int Length => 53;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 53);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array54<T> : IArray<T> where T : unmanaged
|
public struct Array54<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array53<T> _other;
|
Array53<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 54;
|
public readonly int Length => 54;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 54);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array55<T> : IArray<T> where T : unmanaged
|
public struct Array55<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array54<T> _other;
|
Array54<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 55;
|
public readonly int Length => 55;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 55);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array56<T> : IArray<T> where T : unmanaged
|
public struct Array56<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array55<T> _other;
|
Array55<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 56;
|
public readonly int Length => 56;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 56);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array57<T> : IArray<T> where T : unmanaged
|
public struct Array57<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array56<T> _other;
|
Array56<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 57;
|
public readonly int Length => 57;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 57);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array58<T> : IArray<T> where T : unmanaged
|
public struct Array58<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array57<T> _other;
|
Array57<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 58;
|
public readonly int Length => 58;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 58);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array59<T> : IArray<T> where T : unmanaged
|
public struct Array59<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array58<T> _other;
|
Array58<T> _other;
|
||||||
#pragma warning restore CS0169
|
|
||||||
public int Length => 59;
|
public readonly int Length => 59;
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 59);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array60<T> : IArray<T> where T : unmanaged
|
public struct Array60<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array59<T> _other;
|
Array59<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 60;
|
||||||
public int Length => 60;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 60);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array61<T> : IArray<T> where T : unmanaged
|
public struct Array61<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array60<T> _other;
|
Array60<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 61;
|
||||||
public int Length => 61;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 61);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array62<T> : IArray<T> where T : unmanaged
|
public struct Array62<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array61<T> _other;
|
Array61<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 62;
|
||||||
public int Length => 62;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 62);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array63<T> : IArray<T> where T : unmanaged
|
public struct Array63<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array62<T> _other;
|
Array62<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 63;
|
||||||
public int Length => 63;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 63);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array64<T> : IArray<T> where T : unmanaged
|
public struct Array64<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array63<T> _other;
|
Array63<T> _other;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 64;
|
||||||
public int Length => 64;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 64);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Array73<T> : IArray<T> where T : unmanaged
|
public struct Array73<T> : IArray<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0169
|
|
||||||
T _e0;
|
T _e0;
|
||||||
Array64<T> _other;
|
Array64<T> _other;
|
||||||
Array8<T> _other2;
|
Array8<T> _other2;
|
||||||
#pragma warning restore CS0169
|
public readonly int Length => 73;
|
||||||
public int Length => 73;
|
|
||||||
public ref T this[int index] => ref AsSpan()[index];
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 73);
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Array127<T> : IArray<T> where T : unmanaged
|
||||||
|
{
|
||||||
|
T _e0;
|
||||||
|
Array64<T> _other;
|
||||||
|
Array62<T> _other2;
|
||||||
|
public readonly int Length => 127;
|
||||||
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Array128<T> : IArray<T> where T : unmanaged
|
||||||
|
{
|
||||||
|
T _e0;
|
||||||
|
Array64<T> _other;
|
||||||
|
Array63<T> _other2;
|
||||||
|
public readonly int Length => 128;
|
||||||
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Array256<T> : IArray<T> where T : unmanaged
|
||||||
|
{
|
||||||
|
T _e0;
|
||||||
|
Array128<T> _other;
|
||||||
|
Array127<T> _other2;
|
||||||
|
public readonly int Length => 256;
|
||||||
|
public ref T this[int index] => ref AsSpan()[index];
|
||||||
|
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CS0169, IDE0051
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Ryujinx.Common.Memory
|
||||||
|
|
||||||
byte _element;
|
byte _element;
|
||||||
|
|
||||||
public int Length => Size;
|
public readonly int Length => Size;
|
||||||
public ref byte this[int index] => ref AsSpan()[index];
|
public ref byte this[int index] => ref AsSpan()[index];
|
||||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace Ryujinx.Common.Memory
|
||||||
|
|
||||||
byte _element;
|
byte _element;
|
||||||
|
|
||||||
public int Length => Size;
|
public readonly int Length => Size;
|
||||||
public ref byte this[int index] => ref AsSpan()[index];
|
public ref byte this[int index] => ref AsSpan()[index];
|
||||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace Ryujinx.Common.Memory
|
||||||
|
|
||||||
byte _element;
|
byte _element;
|
||||||
|
|
||||||
public int Length => Size;
|
public readonly int Length => Size;
|
||||||
public ref byte this[int index] => ref AsSpan()[index];
|
public ref byte this[int index] => ref AsSpan()[index];
|
||||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ namespace Ryujinx.Common.Memory
|
||||||
|
|
||||||
byte _element;
|
byte _element;
|
||||||
|
|
||||||
public int Length => Size;
|
public readonly int Length => Size;
|
||||||
public ref byte this[int index] => ref AsSpan()[index];
|
public ref byte this[int index] => ref AsSpan()[index];
|
||||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ namespace Ryujinx.Common.Memory
|
||||||
|
|
||||||
byte _element;
|
byte _element;
|
||||||
|
|
||||||
public int Length => Size;
|
public readonly int Length => Size;
|
||||||
public ref byte this[int index] => ref AsSpan()[index];
|
public ref byte this[int index] => ref AsSpan()[index];
|
||||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ namespace Ryujinx.Common.Memory
|
||||||
|
|
||||||
byte _element;
|
byte _element;
|
||||||
|
|
||||||
public int Length => Size;
|
public readonly int Length => Size;
|
||||||
public ref byte this[int index] => ref AsSpan()[index];
|
public ref byte this[int index] => ref AsSpan()[index];
|
||||||
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Ryujinx.Common
|
namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
public static class PerformanceCounter
|
public static class PerformanceCounter
|
||||||
{
|
{
|
||||||
private static double _ticksToNs;
|
private static readonly double _ticksToNs;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the number of ticks in 1 day.
|
/// Represents the number of ticks in 1 day.
|
||||||
|
@ -71,12 +71,12 @@ namespace Ryujinx.Common
|
||||||
static PerformanceCounter()
|
static PerformanceCounter()
|
||||||
{
|
{
|
||||||
TicksPerMillisecond = Stopwatch.Frequency / 1000;
|
TicksPerMillisecond = Stopwatch.Frequency / 1000;
|
||||||
TicksPerSecond = Stopwatch.Frequency;
|
TicksPerSecond = Stopwatch.Frequency;
|
||||||
TicksPerMinute = TicksPerSecond * 60;
|
TicksPerMinute = TicksPerSecond * 60;
|
||||||
TicksPerHour = TicksPerMinute * 60;
|
TicksPerHour = TicksPerMinute * 60;
|
||||||
TicksPerDay = TicksPerHour * 24;
|
TicksPerDay = TicksPerHour * 24;
|
||||||
|
|
||||||
_ticksToNs = 1000000000.0 / Stopwatch.Frequency;
|
_ticksToNs = 1000000000.0 / Stopwatch.Frequency;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
public ObjectPool(Func<T> factory, int size)
|
public ObjectPool(Func<T> factory, int size)
|
||||||
{
|
{
|
||||||
_items = new T[size - 1];
|
_items = new T[size - 1];
|
||||||
_factory = factory;
|
_factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
private static class DefaultPool<T>
|
private static class DefaultPool<T>
|
||||||
where T : class, new()
|
where T : class, new()
|
||||||
{
|
{
|
||||||
public static readonly ObjectPool<T> Instance = new ObjectPool<T>(() => new T(), 20);
|
public static readonly ObjectPool<T> Instance = new(() => new T(), 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ObjectPool<T> Default<T>()
|
public static ObjectPool<T> Default<T>()
|
||||||
|
|
|
@ -9,10 +9,7 @@ namespace Ryujinx.Common.Pools
|
||||||
|
|
||||||
public static ref T[] Get()
|
public static ref T[] Get()
|
||||||
{
|
{
|
||||||
if (_array == null)
|
_array ??= new T[1];
|
||||||
{
|
|
||||||
_array = new T[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ref _array;
|
return ref _array;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
public class ReactiveObject<T>
|
public class ReactiveObject<T>
|
||||||
{
|
{
|
||||||
private ReaderWriterLock _readerWriterLock = new ReaderWriterLock();
|
private readonly ReaderWriterLock _readerWriterLock = new();
|
||||||
private bool _isInitialized = false;
|
private bool _isInitialized;
|
||||||
private T _value;
|
private T _value;
|
||||||
|
|
||||||
public event EventHandler<ReactiveEventArgs<T>> Event;
|
public event EventHandler<ReactiveEventArgs<T>> Event;
|
||||||
|
@ -30,7 +30,7 @@ namespace Ryujinx.Common
|
||||||
bool oldIsInitialized = _isInitialized;
|
bool oldIsInitialized = _isInitialized;
|
||||||
|
|
||||||
_isInitialized = true;
|
_isInitialized = true;
|
||||||
_value = value;
|
_value = value;
|
||||||
|
|
||||||
_readerWriterLock.ReleaseWriterLock();
|
_readerWriterLock.ReleaseWriterLock();
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,11 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
private const string FlatHubChannelOwner = "flathub";
|
private const string FlatHubChannelOwner = "flathub";
|
||||||
|
|
||||||
public static string BuildVersion = "%%RYUJINX_BUILD_VERSION%%";
|
public const string BuildVersion = "%%RYUJINX_BUILD_VERSION%%";
|
||||||
public static string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%";
|
public const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%";
|
||||||
public static string ReleaseChannelName = "%%RYUJINX_TARGET_RELEASE_CHANNEL_NAME%%";
|
public const string ReleaseChannelName = "%%RYUJINX_TARGET_RELEASE_CHANNEL_NAME%%";
|
||||||
public static string ReleaseChannelOwner = "%%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER%%";
|
public const string ReleaseChannelOwner = "%%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER%%";
|
||||||
public static string ReleaseChannelRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_REPO%%";
|
public const string ReleaseChannelRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_REPO%%";
|
||||||
|
|
||||||
public static bool IsValid()
|
public static bool IsValid()
|
||||||
{
|
{
|
||||||
|
@ -34,10 +34,8 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
return BuildVersion;
|
return BuildVersion;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
||||||
return Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FORCE_EXTERNAL_BASE_DIR
|
#if FORCE_EXTERNAL_BASE_DIR
|
||||||
|
@ -57,4 +55,4 @@ namespace Ryujinx.Common
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
{
|
{
|
||||||
["model name"] = null,
|
["model name"] = null,
|
||||||
["Processor"] = null,
|
["Processor"] = null,
|
||||||
["Hardware"] = null
|
["Hardware"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
ParseKeyValues("/proc/cpuinfo", cpuDict);
|
ParseKeyValues("/proc/cpuinfo", cpuDict);
|
||||||
|
@ -31,7 +31,7 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
var memDict = new Dictionary<string, string>(StringComparer.Ordinal)
|
var memDict = new Dictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
["MemTotal"] = null,
|
["MemTotal"] = null,
|
||||||
["MemAvailable"] = null
|
["MemAvailable"] = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
ParseKeyValues("/proc/meminfo", memDict);
|
ParseKeyValues("/proc/meminfo", memDict);
|
||||||
|
@ -56,25 +56,30 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
|
|
||||||
int count = itemDict.Count;
|
int count = itemDict.Count;
|
||||||
|
|
||||||
using (StreamReader file = new StreamReader(filePath))
|
using StreamReader file = new(filePath);
|
||||||
|
|
||||||
|
string line;
|
||||||
|
while ((line = file.ReadLine()) != null)
|
||||||
{
|
{
|
||||||
string line;
|
string[] kvPair = line.Split(':', 2, StringSplitOptions.TrimEntries);
|
||||||
while ((line = file.ReadLine()) != null)
|
|
||||||
|
if (kvPair.Length < 2)
|
||||||
{
|
{
|
||||||
string[] kvPair = line.Split(':', 2, StringSplitOptions.TrimEntries);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (kvPair.Length < 2) continue;
|
string key = kvPair[0];
|
||||||
|
|
||||||
string key = kvPair[0];
|
if (itemDict.TryGetValue(key, out string value) && value == null)
|
||||||
|
{
|
||||||
|
itemDict[key] = kvPair[1];
|
||||||
|
|
||||||
if (itemDict.TryGetValue(key, out string value) && value == null)
|
if (--count <= 0)
|
||||||
{
|
{
|
||||||
itemDict[key] = kvPair[1];
|
break;
|
||||||
|
|
||||||
if (--count <= 0) break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
{
|
{
|
||||||
string cpuName = GetCpuidCpuName();
|
string cpuName = GetCpuidCpuName();
|
||||||
|
|
||||||
if (cpuName == null && sysctlbyname("machdep.cpu.brand_string", out cpuName) != 0)
|
if (cpuName == null && SysctlByName("machdep.cpu.brand_string", out cpuName) != 0)
|
||||||
{
|
{
|
||||||
cpuName = "Unknown";
|
cpuName = "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong totalRAM = 0;
|
ulong totalRAM = 0;
|
||||||
|
|
||||||
if (sysctlbyname("hw.memsize", ref totalRAM) != 0) // Bytes
|
if (SysctlByName("hw.memsize", ref totalRAM) != 0) // Bytes
|
||||||
{
|
{
|
||||||
totalRAM = 0;
|
totalRAM = 0;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
[LibraryImport(SystemLibraryName, SetLastError = true)]
|
[LibraryImport(SystemLibraryName, SetLastError = true)]
|
||||||
private static partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, IntPtr oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
|
private static partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, IntPtr oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
|
||||||
|
|
||||||
private static int sysctlbyname(string name, IntPtr oldValue, ref ulong oldSize)
|
private static int SysctlByName(string name, IntPtr oldValue, ref ulong oldSize)
|
||||||
{
|
{
|
||||||
if (sysctlbyname(name, oldValue, ref oldSize, IntPtr.Zero, 0) == -1)
|
if (sysctlbyname(name, oldValue, ref oldSize, IntPtr.Zero, 0) == -1)
|
||||||
{
|
{
|
||||||
|
@ -77,23 +77,23 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int sysctlbyname<T>(string name, ref T oldValue)
|
private static int SysctlByName<T>(string name, ref T oldValue)
|
||||||
{
|
{
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
ulong oldValueSize = (ulong)Unsafe.SizeOf<T>();
|
ulong oldValueSize = (ulong)Unsafe.SizeOf<T>();
|
||||||
|
|
||||||
return sysctlbyname(name, (IntPtr)Unsafe.AsPointer(ref oldValue), ref oldValueSize);
|
return SysctlByName(name, (IntPtr)Unsafe.AsPointer(ref oldValue), ref oldValueSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int sysctlbyname(string name, out string oldValue)
|
private static int SysctlByName(string name, out string oldValue)
|
||||||
{
|
{
|
||||||
oldValue = default;
|
oldValue = default;
|
||||||
|
|
||||||
ulong strSize = 0;
|
ulong strSize = 0;
|
||||||
|
|
||||||
int res = sysctlbyname(name, IntPtr.Zero, ref strSize);
|
int res = SysctlByName(name, IntPtr.Zero, ref strSize);
|
||||||
|
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
{
|
{
|
||||||
|
@ -103,7 +103,7 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
{
|
{
|
||||||
fixed (byte* rawDataPtr = rawData)
|
fixed (byte* rawDataPtr = rawData)
|
||||||
{
|
{
|
||||||
res = sysctlbyname(name, (IntPtr)rawDataPtr, ref strSize);
|
res = SysctlByName(name, (IntPtr)rawDataPtr, ref strSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
|
@ -152,6 +152,6 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
[LibraryImport(SystemLibraryName, SetLastError = true)]
|
[LibraryImport(SystemLibraryName, SetLastError = true)]
|
||||||
private static partial int host_statistics64(uint host_priv, int host_flavor, ref VMStatistics64 host_info64_out, ref uint host_info64_outCnt);
|
private static partial int host_statistics64(uint hostPriv, int hostFlavor, ref VMStatistics64 hostInfo64Out, ref uint hostInfo64OutCnt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,12 +43,10 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
{
|
{
|
||||||
return new MacOSSystemInfo();
|
return new MacOSSystemInfo();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Error?.Print(LogClass.Application, "SystemInfo unsupported on this platform");
|
|
||||||
|
|
||||||
return new SystemInfo();
|
Logger.Error?.Print(LogClass.Application, "SystemInfo unsupported on this platform");
|
||||||
}
|
|
||||||
|
return new SystemInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
// x86 exposes a 48 byte ASCII "CPU brand" string via CPUID leaves 0x80000002-0x80000004.
|
// x86 exposes a 48 byte ASCII "CPU brand" string via CPUID leaves 0x80000002-0x80000004.
|
||||||
|
@ -77,4 +75,4 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
return string.IsNullOrEmpty(name) ? null : name;
|
return string.IsNullOrEmpty(name) ? null : name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,13 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
|
|
||||||
private static (ulong Total, ulong Available) GetMemoryStats()
|
private static (ulong Total, ulong Available) GetMemoryStats()
|
||||||
{
|
{
|
||||||
MemoryStatusEx memStatus = new MemoryStatusEx();
|
MemoryStatusEx memStatus = new();
|
||||||
if (GlobalMemoryStatusEx(ref memStatus))
|
if (GlobalMemoryStatusEx(ref memStatus))
|
||||||
{
|
{
|
||||||
return (memStatus.TotalPhys, memStatus.AvailPhys); // Bytes
|
return (memStatus.TotalPhys, memStatus.AvailPhys); // Bytes
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
Logger.Error?.Print(LogClass.Application, $"GlobalMemoryStatusEx failed. Error {Marshal.GetLastWin32Error():X}");
|
||||||
Logger.Error?.Print(LogClass.Application, $"GlobalMemoryStatusEx failed. Error {Marshal.GetLastWin32Error():X}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0, 0);
|
return (0, 0);
|
||||||
}
|
}
|
||||||
|
@ -86,4 +84,4 @@ namespace Ryujinx.Common.SystemInfo
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
{
|
{
|
||||||
ES_CONTINUOUS = 0x80000000,
|
ES_CONTINUOUS = 0x80000000,
|
||||||
ES_DISPLAY_REQUIRED = 0x00000002,
|
ES_DISPLAY_REQUIRED = 0x00000002,
|
||||||
ES_SYSTEM_REQUIRED = 0x00000001
|
ES_SYSTEM_REQUIRED = 0x00000001,
|
||||||
}
|
}
|
||||||
|
|
||||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||||
|
@ -23,12 +23,12 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED);
|
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static public void Restore()
|
static public void Restore()
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
|
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
private static partial int XCloseDisplay(IntPtr display);
|
private static partial int XCloseDisplay(IntPtr display);
|
||||||
|
|
||||||
private static readonly double _standardDpiScale = 96.0;
|
private static readonly double _standardDpiScale = 96.0;
|
||||||
private static readonly double _maxScaleFactor = 1.25;
|
private static readonly double _maxScaleFactor = 1.25;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marks the application as DPI-Aware when running on the Windows operating system.
|
/// Marks the application as DPI-Aware when running on the Windows operating system.
|
||||||
|
@ -63,14 +63,14 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
string dpiString = Marshal.PtrToStringAnsi(XGetDefault(display, "Xft", "dpi"));
|
string dpiString = Marshal.PtrToStringAnsi(XGetDefault(display, "Xft", "dpi"));
|
||||||
if (dpiString == null || !double.TryParse(dpiString, NumberStyles.Any, CultureInfo.InvariantCulture, out userDpiScale))
|
if (dpiString == null || !double.TryParse(dpiString, NumberStyles.Any, CultureInfo.InvariantCulture, out userDpiScale))
|
||||||
{
|
{
|
||||||
userDpiScale = (double)XDisplayWidth(display, 0) * 25.4 / (double)XDisplayWidthMM(display, 0);
|
userDpiScale = XDisplayWidth(display, 0) * 25.4 / XDisplayWidthMM(display, 0);
|
||||||
}
|
}
|
||||||
XCloseDisplay(display);
|
_ = XCloseDisplay(display);
|
||||||
}
|
}
|
||||||
else if (xdgSessionType == "wayland")
|
else if (xdgSessionType == "wayland")
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
Logger.Warning?.Print(LogClass.Application, $"Couldn't determine monitor DPI: Wayland not yet supported");
|
Logger.Warning?.Print(LogClass.Application, "Couldn't determine monitor DPI: Wayland not yet supported");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,14 +28,14 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
{
|
{
|
||||||
public int GdiplusVersion;
|
public int GdiplusVersion;
|
||||||
|
|
||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649 // Field is never assigned to
|
||||||
public IntPtr DebugEventCallback;
|
public IntPtr DebugEventCallback;
|
||||||
public int SuppressBackgroundThread;
|
public int SuppressBackgroundThread;
|
||||||
public int SuppressExternalCodecs;
|
public int SuppressExternalCodecs;
|
||||||
public int StartupParameters;
|
public int StartupParameters;
|
||||||
#pragma warning restore CS0649
|
#pragma warning restore CS0649
|
||||||
|
|
||||||
public static StartupInputEx Default => new StartupInputEx
|
public static StartupInputEx Default => new()
|
||||||
{
|
{
|
||||||
// We assume Windows 8 and upper
|
// We assume Windows 8 and upper
|
||||||
GdiplusVersion = 2,
|
GdiplusVersion = 2,
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
{
|
{
|
||||||
public partial class StdErrAdapter : IDisposable
|
public partial class StdErrAdapter : IDisposable
|
||||||
{
|
{
|
||||||
private bool _disposable = false;
|
private bool _disposable;
|
||||||
private Stream _pipeReader;
|
private Stream _pipeReader;
|
||||||
private Stream _pipeWriter;
|
private Stream _pipeWriter;
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
private CancellationTokenSource _cancellationTokenSource;
|
||||||
|
@ -41,7 +41,7 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
_worker = Task.Run(async () => await EventWorkerAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
|
_worker = Task.Run(async () => await EventWorkerAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
|
||||||
_disposable = true;
|
_disposable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[SupportedOSPlatform("linux")]
|
[SupportedOSPlatform("linux")]
|
||||||
[SupportedOSPlatform("macos")]
|
[SupportedOSPlatform("macos")]
|
||||||
private async Task EventWorkerAsync(CancellationToken cancellationToken)
|
private async Task EventWorkerAsync(CancellationToken cancellationToken)
|
||||||
|
@ -53,13 +53,15 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
Logger.Error?.PrintRawMsg(line);
|
Logger.Error?.PrintRawMsg(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
if (_disposable)
|
if (_disposable)
|
||||||
{
|
{
|
||||||
_disposable = false;
|
_disposable = false;
|
||||||
|
|
||||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
_cancellationTokenSource.Cancel();
|
_cancellationTokenSource.Cancel();
|
||||||
|
@ -70,11 +72,6 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LibraryImport("libc", SetLastError = true)]
|
[LibraryImport("libc", SetLastError = true)]
|
||||||
private static partial int dup2(int fd, int fd2);
|
private static partial int dup2(int fd, int fd2);
|
||||||
|
|
||||||
|
@ -83,27 +80,25 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
|
|
||||||
private static (int, int) MakePipe()
|
private static (int, int) MakePipe()
|
||||||
{
|
{
|
||||||
Span<int> pipefd = stackalloc int[2];
|
Span<int> pipefd = stackalloc int[2];
|
||||||
|
|
||||||
if (pipe(pipefd) == 0)
|
if (pipe(pipefd) == 0)
|
||||||
{
|
{
|
||||||
return (pipefd[0], pipefd[1]);
|
return (pipefd[0], pipefd[1]);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
throw new();
|
||||||
throw new();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[SupportedOSPlatform("linux")]
|
[SupportedOSPlatform("linux")]
|
||||||
[SupportedOSPlatform("macos")]
|
[SupportedOSPlatform("macos")]
|
||||||
private static Stream CreateFileDescriptorStream(int fd)
|
private static Stream CreateFileDescriptorStream(int fd)
|
||||||
{
|
{
|
||||||
return new FileStream(
|
return new FileStream(
|
||||||
new SafeFileHandle((IntPtr)fd, ownsHandle: true),
|
new SafeFileHandle(fd, ownsHandle: true),
|
||||||
FileAccess.ReadWrite
|
FileAccess.ReadWrite
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
{
|
{
|
||||||
public uint wPeriodMin;
|
public uint wPeriodMin;
|
||||||
public uint wPeriodMax;
|
public uint wPeriodMax;
|
||||||
};
|
}
|
||||||
|
|
||||||
[LibraryImport("winmm.dll", EntryPoint = "timeGetDevCaps", SetLastError = true)]
|
[LibraryImport("winmm.dll", EntryPoint = "timeGetDevCaps", SetLastError = true)]
|
||||||
private static partial uint TimeGetDevCaps(ref TimeCaps timeCaps, uint sizeTimeCaps);
|
private static partial uint TimeGetDevCaps(ref TimeCaps timeCaps, uint sizeTimeCaps);
|
||||||
|
@ -111,4 +111,4 @@ namespace Ryujinx.Common.SystemInterop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.Common
|
namespace Ryujinx.Common
|
||||||
|
@ -27,10 +26,10 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
value--;
|
value--;
|
||||||
|
|
||||||
value |= (value >> 1);
|
value |= (value >> 1);
|
||||||
value |= (value >> 2);
|
value |= (value >> 2);
|
||||||
value |= (value >> 4);
|
value |= (value >> 4);
|
||||||
value |= (value >> 8);
|
value |= (value >> 8);
|
||||||
value |= (value >> 16);
|
value |= (value >> 16);
|
||||||
|
|
||||||
return ++value;
|
return ++value;
|
||||||
|
@ -48,10 +47,10 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
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);
|
||||||
value = ((value & 0xcccccccccccccccc) >> 2 ) | ((value & 0x3333333333333333) << 2 );
|
value = ((value & 0xcccccccccccccccc) >> 2) | ((value & 0x3333333333333333) << 2);
|
||||||
value = ((value & 0xf0f0f0f0f0f0f0f0) >> 4 ) | ((value & 0x0f0f0f0f0f0f0f0f) << 4 );
|
value = ((value & 0xf0f0f0f0f0f0f0f0) >> 4) | ((value & 0x0f0f0f0f0f0f0f0f) << 4);
|
||||||
value = ((value & 0xff00ff00ff00ff00) >> 8 ) | ((value & 0x00ff00ff00ff00ff) << 8 );
|
value = ((value & 0xff00ff00ff00ff00) >> 8) | ((value & 0x00ff00ff00ff00ff) << 8);
|
||||||
value = ((value & 0xffff0000ffff0000) >> 16) | ((value & 0x0000ffff0000ffff) << 16);
|
value = ((value & 0xffff0000ffff0000) >> 16) | ((value & 0x0000ffff0000ffff) << 16);
|
||||||
|
|
||||||
return (value >> 32) | (value << 32);
|
return (value >> 32) | (value << 32);
|
||||||
|
|
|
@ -54,4 +54,4 @@ namespace Ryujinx.Common.Utilities
|
||||||
return (value & ~mask) | ((toInsert << lsb) & mask);
|
return (value & ~mask) | ((toInsert << lsb) & mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ namespace Ryujinx.Common.Utilities
|
||||||
[StructLayout(LayoutKind.Sequential, Size = 16)]
|
[StructLayout(LayoutKind.Sequential, Size = 16)]
|
||||||
public struct Buffer16
|
public struct Buffer16
|
||||||
{
|
{
|
||||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy0;
|
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly ulong _dummy0;
|
||||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy1;
|
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly ulong _dummy1;
|
||||||
|
|
||||||
public byte this[int i]
|
public byte this[int i]
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,4 +8,4 @@ namespace Ryujinx.Common.Utilities
|
||||||
public partial class CommonJsonContext : JsonSerializerContext
|
public partial class CommonJsonContext : JsonSerializerContext
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
using Ryujinx.Common.Memory;
|
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -10,11 +9,11 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
public static class EmbeddedResources
|
public static class EmbeddedResources
|
||||||
{
|
{
|
||||||
private readonly static Assembly ResourceAssembly;
|
private readonly static Assembly _resourceAssembly;
|
||||||
|
|
||||||
static EmbeddedResources()
|
static EmbeddedResources()
|
||||||
{
|
{
|
||||||
ResourceAssembly = Assembly.GetAssembly(typeof(EmbeddedResources));
|
_resourceAssembly = Assembly.GetAssembly(typeof(EmbeddedResources));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] Read(string filename)
|
public static byte[] Read(string filename)
|
||||||
|
@ -33,28 +32,24 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
public static byte[] Read(Assembly assembly, string filename)
|
public static byte[] Read(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
using (var stream = GetStream(assembly, filename))
|
using var stream = GetStream(assembly, filename);
|
||||||
|
if (stream == null)
|
||||||
{
|
{
|
||||||
if (stream == null)
|
return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return StreamUtils.StreamToBytes(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return StreamUtils.StreamToBytes(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async static Task<byte[]> ReadAsync(Assembly assembly, string filename)
|
public async static Task<byte[]> ReadAsync(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
using (var stream = GetStream(assembly, filename))
|
using var stream = GetStream(assembly, filename);
|
||||||
|
if (stream == null)
|
||||||
{
|
{
|
||||||
if (stream == null)
|
return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await StreamUtils.StreamToBytesAsync(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return await StreamUtils.StreamToBytesAsync(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReadAllText(string filename)
|
public static string ReadAllText(string filename)
|
||||||
|
@ -73,34 +68,26 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
public static string ReadAllText(Assembly assembly, string filename)
|
public static string ReadAllText(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
using (var stream = GetStream(assembly, filename))
|
using var stream = GetStream(assembly, filename);
|
||||||
|
if (stream == null)
|
||||||
{
|
{
|
||||||
if (stream == null)
|
return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var reader = new StreamReader(stream))
|
|
||||||
{
|
|
||||||
return reader.ReadToEnd();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using var reader = new StreamReader(stream);
|
||||||
|
return reader.ReadToEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async static Task<string> ReadAllTextAsync(Assembly assembly, string filename)
|
public async static Task<string> ReadAllTextAsync(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
using (var stream = GetStream(assembly, filename))
|
using var stream = GetStream(assembly, filename);
|
||||||
|
if (stream == null)
|
||||||
{
|
{
|
||||||
if (stream == null)
|
return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var reader = new StreamReader(stream))
|
|
||||||
{
|
|
||||||
return await reader.ReadToEndAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using var reader = new StreamReader(stream);
|
||||||
|
return await reader.ReadToEndAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stream GetStream(string filename)
|
public static Stream GetStream(string filename)
|
||||||
|
@ -112,8 +99,8 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
public static Stream GetStream(Assembly assembly, string filename)
|
public static Stream GetStream(Assembly assembly, string filename)
|
||||||
{
|
{
|
||||||
var namespace_ = assembly.GetName().Name;
|
var @namespace = assembly.GetName().Name;
|
||||||
var manifestUri = namespace_ + "." + filename.Replace('/', '.');
|
var manifestUri = @namespace + "." + filename.Replace('/', '.');
|
||||||
|
|
||||||
var stream = assembly.GetManifestResourceStream(manifestUri);
|
var stream = assembly.GetManifestResourceStream(manifestUri);
|
||||||
|
|
||||||
|
@ -142,7 +129,7 @@ namespace Ryujinx.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ResourceAssembly, filename);
|
return (_resourceAssembly, filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
public static class HexUtils
|
public static class HexUtils
|
||||||
{
|
{
|
||||||
private static readonly char[] HexChars = "0123456789ABCDEF".ToCharArray();
|
private static readonly char[] _hexChars = "0123456789ABCDEF".ToCharArray();
|
||||||
|
|
||||||
private const int HexTableColumnWidth = 8;
|
private const int HexTableColumnWidth = 8;
|
||||||
private const int HexTableColumnSpace = 3;
|
private const int HexTableColumnSpace = 3;
|
||||||
|
@ -39,20 +39,20 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
|
int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
|
||||||
|
|
||||||
StringBuilder result = new StringBuilder(expectedLines * lineLength);
|
StringBuilder result = new(expectedLines * lineLength);
|
||||||
|
|
||||||
for (int i = 0; i < bytesLength; i += bytesPerLine)
|
for (int i = 0; i < bytesLength; i += bytesPerLine)
|
||||||
{
|
{
|
||||||
line[0] = HexChars[(i >> 28) & 0xF];
|
line[0] = _hexChars[(i >> 28) & 0xF];
|
||||||
line[1] = HexChars[(i >> 24) & 0xF];
|
line[1] = _hexChars[(i >> 24) & 0xF];
|
||||||
line[2] = HexChars[(i >> 20) & 0xF];
|
line[2] = _hexChars[(i >> 20) & 0xF];
|
||||||
line[3] = HexChars[(i >> 16) & 0xF];
|
line[3] = _hexChars[(i >> 16) & 0xF];
|
||||||
line[4] = HexChars[(i >> 12) & 0xF];
|
line[4] = _hexChars[(i >> 12) & 0xF];
|
||||||
line[5] = HexChars[(i >> 8) & 0xF];
|
line[5] = _hexChars[(i >> 8) & 0xF];
|
||||||
line[6] = HexChars[(i >> 4) & 0xF];
|
line[6] = _hexChars[(i >> 4) & 0xF];
|
||||||
line[7] = HexChars[(i >> 0) & 0xF];
|
line[7] = _hexChars[(i >> 0) & 0xF];
|
||||||
|
|
||||||
int hexColumn = firstHexColumn;
|
int hexColumn = firstHexColumn;
|
||||||
int charColumn = firstCharColumn;
|
int charColumn = firstCharColumn;
|
||||||
|
|
||||||
for (int j = 0; j < bytesPerLine; j++)
|
for (int j = 0; j < bytesPerLine; j++)
|
||||||
|
@ -64,17 +64,17 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
if (i + j >= bytesLength)
|
if (i + j >= bytesLength)
|
||||||
{
|
{
|
||||||
line[hexColumn] = ' ';
|
line[hexColumn] = ' ';
|
||||||
line[hexColumn + 1] = ' ';
|
line[hexColumn + 1] = ' ';
|
||||||
line[charColumn] = ' ';
|
line[charColumn] = ' ';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
byte b = bytes[i + j];
|
byte b = bytes[i + j];
|
||||||
|
|
||||||
line[hexColumn] = HexChars[(b >> 4) & 0xF];
|
line[hexColumn] = _hexChars[(b >> 4) & 0xF];
|
||||||
line[hexColumn + 1] = HexChars[b & 0xF];
|
line[hexColumn + 1] = _hexChars[b & 0xF];
|
||||||
line[charColumn] = (b < 32 ? '·' : (char)b);
|
line[charColumn] = (b < 32 ? '·' : (char)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
hexColumn += 3;
|
hexColumn += 3;
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.Common.Utilities
|
||||||
{
|
{
|
||||||
public class JsonHelper
|
public class JsonHelper
|
||||||
{
|
{
|
||||||
private static readonly JsonNamingPolicy SnakeCasePolicy = new SnakeCaseNamingPolicy();
|
private static readonly JsonNamingPolicy _snakeCasePolicy = new SnakeCaseNamingPolicy();
|
||||||
private const int DefaultFileWriteBufferSize = 4096;
|
private const int DefaultFileWriteBufferSize = 4096;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -21,11 +21,11 @@ namespace Ryujinx.Common.Utilities
|
||||||
{
|
{
|
||||||
JsonSerializerOptions options = new()
|
JsonSerializerOptions options = new()
|
||||||
{
|
{
|
||||||
DictionaryKeyPolicy = SnakeCasePolicy,
|
DictionaryKeyPolicy = _snakeCasePolicy,
|
||||||
PropertyNamingPolicy = SnakeCasePolicy,
|
PropertyNamingPolicy = _snakeCasePolicy,
|
||||||
WriteIndented = indented,
|
WriteIndented = indented,
|
||||||
AllowTrailingCommas = true,
|
AllowTrailingCommas = true,
|
||||||
ReadCommentHandling = JsonCommentHandling.Skip
|
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||||
};
|
};
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
|
@ -95,4 +95,4 @@ namespace Ryujinx.Common.Utilities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,8 @@ namespace Ryujinx.Common.Utilities
|
||||||
{
|
{
|
||||||
return Format(obj);
|
return Format(obj);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return obj.ToString();
|
||||||
return obj.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Format(MessagePackObject obj)
|
public static string Format(MessagePackObject obj)
|
||||||
|
@ -179,19 +177,17 @@ namespace Ryujinx.Common.Utilities
|
||||||
{
|
{
|
||||||
return unchecked((char)('0' + b));
|
return unchecked((char)('0' + b));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return unchecked((char)('A' + (b - 10)));
|
||||||
return unchecked((char)('A' + (b - 10)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class IndentedStringBuilder
|
internal class IndentedStringBuilder
|
||||||
{
|
{
|
||||||
const string DefaultIndent = " ";
|
const string DefaultIndent = " ";
|
||||||
|
|
||||||
private int _indentCount = 0;
|
private int _indentCount;
|
||||||
private int _newLineIndex = 0;
|
private int _newLineIndex;
|
||||||
private StringBuilder _builder;
|
private readonly StringBuilder _builder;
|
||||||
|
|
||||||
public string IndentString { get; set; } = DefaultIndent;
|
public string IndentString { get; set; } = DefaultIndent;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Ryujinx.Common.Utilities
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPInterfaceProperties targetProperties = null;
|
IPInterfaceProperties targetProperties = null;
|
||||||
UnicastIPAddressInformation targetAddressInfo = null;
|
UnicastIPAddressInformation targetAddressInfo = null;
|
||||||
|
|
||||||
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
|
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
|
||||||
|
@ -63,4 +63,4 @@ namespace Ryujinx.Common.Utilities
|
||||||
return (targetProperties, targetAddressInfo);
|
return (targetProperties, targetAddressInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using Microsoft.IO;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Common.Memory;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -10,22 +9,21 @@ namespace Ryujinx.Common.Utilities
|
||||||
{
|
{
|
||||||
public static byte[] StreamToBytes(Stream input)
|
public static byte[] StreamToBytes(Stream input)
|
||||||
{
|
{
|
||||||
using (MemoryStream stream = MemoryStreamManager.Shared.GetStream())
|
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
||||||
{
|
|
||||||
input.CopyTo(stream);
|
|
||||||
|
|
||||||
return stream.ToArray();
|
|
||||||
}
|
input.CopyTo(stream);
|
||||||
|
|
||||||
|
return stream.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<byte[]> StreamToBytesAsync(Stream input, CancellationToken cancellationToken = default)
|
public static async Task<byte[]> StreamToBytesAsync(Stream input, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
using (MemoryStream stream = MemoryStreamManager.Shared.GetStream())
|
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
||||||
{
|
|
||||||
await input.CopyToAsync(stream, cancellationToken);
|
|
||||||
|
|
||||||
return stream.ToArray();
|
await input.CopyToAsync(stream, cancellationToken);
|
||||||
}
|
|
||||||
|
return stream.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,4 +34,4 @@ namespace Ryujinx.Common.Utilities
|
||||||
writer.WriteStringValue(value.ToString());
|
writer.WriteStringValue(value.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,4 +15,4 @@ namespace Ryujinx.Common.Utilities
|
||||||
return new UInt128((ulong)Random.Shared.NextInt64(), (ulong)Random.Shared.NextInt64());
|
return new UInt128((ulong)Random.Shared.NextInt64(), (ulong)Random.Shared.NextInt64());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,7 @@ namespace Ryujinx.Common
|
||||||
private const ulong Prime64_4 = 0x85EBCA77C2B2AE63UL;
|
private const ulong Prime64_4 = 0x85EBCA77C2B2AE63UL;
|
||||||
private const ulong Prime64_5 = 0x27D4EB2F165667C5UL;
|
private const ulong Prime64_5 = 0x27D4EB2F165667C5UL;
|
||||||
|
|
||||||
private static readonly ulong[] Xxh3InitAcc = new ulong[]
|
private static readonly ulong[] _xxh3InitAcc = {
|
||||||
{
|
|
||||||
Prime32_3,
|
Prime32_3,
|
||||||
Prime64_1,
|
Prime64_1,
|
||||||
Prime64_2,
|
Prime64_2,
|
||||||
|
@ -40,7 +39,7 @@ namespace Ryujinx.Common
|
||||||
Prime64_4,
|
Prime64_4,
|
||||||
Prime32_2,
|
Prime32_2,
|
||||||
Prime64_5,
|
Prime64_5,
|
||||||
Prime32_1
|
Prime32_1,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> Xxh3KSecret => new byte[]
|
private static ReadOnlySpan<byte> Xxh3KSecret => new byte[]
|
||||||
|
@ -56,23 +55,24 @@ namespace Ryujinx.Common
|
||||||
0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
|
0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
|
||||||
0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
|
0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
|
||||||
0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
|
0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
|
||||||
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e
|
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
|
||||||
};
|
};
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static ulong Mult32To64(ulong x, ulong y)
|
private static ulong Mult32To64(ulong x, ulong y)
|
||||||
{
|
{
|
||||||
return (ulong)(uint)x * (ulong)(uint)y;
|
return (uint)x * (ulong)(uint)y;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static Hash128 Mult64To128(ulong lhs, ulong rhs)
|
private static Hash128 Mult64To128(ulong lhs, ulong rhs)
|
||||||
{
|
{
|
||||||
ulong high = Math.BigMul(lhs, rhs, out ulong low);
|
ulong high = Math.BigMul(lhs, rhs, out ulong low);
|
||||||
|
|
||||||
return new Hash128
|
return new Hash128
|
||||||
{
|
{
|
||||||
Low = low,
|
Low = low,
|
||||||
High = high
|
High = high,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ namespace Ryujinx.Common
|
||||||
private static ulong Mul128Fold64(ulong lhs, ulong rhs)
|
private static ulong Mul128Fold64(ulong lhs, ulong rhs)
|
||||||
{
|
{
|
||||||
Hash128 product = Mult64To128(lhs, rhs);
|
Hash128 product = Mult64To128(lhs, rhs);
|
||||||
|
|
||||||
return product.Low ^ product.High;
|
return product.Low ^ product.High;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +88,7 @@ namespace Ryujinx.Common
|
||||||
private static ulong XorShift64(ulong v64, int shift)
|
private static ulong XorShift64(ulong v64, int shift)
|
||||||
{
|
{
|
||||||
Debug.Assert(0 <= shift && shift < 64);
|
Debug.Assert(0 <= shift && shift < 64);
|
||||||
|
|
||||||
return v64 ^ (v64 >> shift);
|
return v64 ^ (v64 >> shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +98,7 @@ namespace Ryujinx.Common
|
||||||
h64 = XorShift64(h64, 37);
|
h64 = XorShift64(h64, 37);
|
||||||
h64 *= 0x165667919E3779F9UL;
|
h64 *= 0x165667919E3779F9UL;
|
||||||
h64 = XorShift64(h64, 32);
|
h64 = XorShift64(h64, 32);
|
||||||
|
|
||||||
return h64;
|
return h64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +110,7 @@ namespace Ryujinx.Common
|
||||||
h64 ^= h64 >> 29;
|
h64 ^= h64 >> 29;
|
||||||
h64 *= Prime64_3;
|
h64 *= Prime64_3;
|
||||||
h64 ^= h64 >> 32;
|
h64 ^= h64 >> 32;
|
||||||
|
|
||||||
return h64;
|
return h64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,8 +169,8 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
for (int i = 0; i < AccNb; i++)
|
for (int i = 0; i < AccNb; i++)
|
||||||
{
|
{
|
||||||
ulong dataVal = BinaryPrimitives.ReadUInt64LittleEndian(input.Slice(i * sizeof(ulong)));
|
ulong dataVal = BinaryPrimitives.ReadUInt64LittleEndian(input[(i * sizeof(ulong))..]);
|
||||||
ulong dataKey = dataVal ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(i * sizeof(ulong)));
|
ulong dataKey = dataVal ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[(i * sizeof(ulong))..]);
|
||||||
acc[i ^ 1] += dataVal;
|
acc[i ^ 1] += dataVal;
|
||||||
acc[i] += Mult32To64((uint)dataKey, dataKey >> 32);
|
acc[i] += Mult32To64((uint)dataKey, dataKey >> 32);
|
||||||
}
|
}
|
||||||
|
@ -236,7 +240,7 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
for (int i = 0; i < AccNb; i++)
|
for (int i = 0; i < AccNb; i++)
|
||||||
{
|
{
|
||||||
ulong key64 = BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(i * sizeof(ulong)));
|
ulong key64 = BinaryPrimitives.ReadUInt64LittleEndian(secret[(i * sizeof(ulong))..]);
|
||||||
ulong acc64 = acc[i];
|
ulong acc64 = acc[i];
|
||||||
acc64 = XorShift64(acc64, 47);
|
acc64 = XorShift64(acc64, 47);
|
||||||
acc64 ^= key64;
|
acc64 ^= key64;
|
||||||
|
@ -251,8 +255,8 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
for (int n = 0; n < nbStripes; n++)
|
for (int n = 0; n < nbStripes; n++)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<byte> inData = input.Slice(n * StripeLen);
|
ReadOnlySpan<byte> inData = input[(n * StripeLen)..];
|
||||||
Xxh3Accumulate512(acc, inData, secret.Slice(n * SecretConsumeRate));
|
Xxh3Accumulate512(acc, inData, secret[(n * SecretConsumeRate)..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,18 +270,18 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
for (int n = 0; n < nbBlocks; n++)
|
for (int n = 0; n < nbBlocks; n++)
|
||||||
{
|
{
|
||||||
Xxh3Accumulate(acc, input.Slice(n * blockLen), secret, nbStripesPerBlock);
|
Xxh3Accumulate(acc, input[(n * blockLen)..], secret, nbStripesPerBlock);
|
||||||
Xxh3ScrambleAcc(acc, secret.Slice(secret.Length - StripeLen));
|
Xxh3ScrambleAcc(acc, secret[^StripeLen..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(input.Length > StripeLen);
|
Debug.Assert(input.Length > StripeLen);
|
||||||
|
|
||||||
int nbStripes = (input.Length - 1 - (blockLen * nbBlocks)) / StripeLen;
|
int nbStripes = (input.Length - 1 - (blockLen * nbBlocks)) / StripeLen;
|
||||||
Debug.Assert(nbStripes <= (secret.Length / SecretConsumeRate));
|
Debug.Assert(nbStripes <= (secret.Length / SecretConsumeRate));
|
||||||
Xxh3Accumulate(acc, input.Slice(nbBlocks * blockLen), secret, nbStripes);
|
Xxh3Accumulate(acc, input[(nbBlocks * blockLen)..], secret, nbStripes);
|
||||||
|
|
||||||
ReadOnlySpan<byte> p = input.Slice(input.Length - StripeLen);
|
ReadOnlySpan<byte> p = input[^StripeLen..];
|
||||||
Xxh3Accumulate512(acc, p, secret.Slice(secret.Length - StripeLen - SecretLastAccStart));
|
Xxh3Accumulate512(acc, p, secret[(secret.Length - StripeLen - SecretLastAccStart)..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
@ -285,7 +289,7 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
return Mul128Fold64(
|
return Mul128Fold64(
|
||||||
acc[0] ^ BinaryPrimitives.ReadUInt64LittleEndian(secret),
|
acc[0] ^ BinaryPrimitives.ReadUInt64LittleEndian(secret),
|
||||||
acc[1] ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(8)));
|
acc[1] ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[8..]));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
@ -295,7 +299,7 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
result64 += Xxh3Mix2Accs(acc.Slice(2 * i), secret.Slice(16 * i));
|
result64 += Xxh3Mix2Accs(acc[(2 * i)..], secret[(16 * i)..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Xxh3Avalanche(result64);
|
return Xxh3Avalanche(result64);
|
||||||
|
@ -305,7 +309,7 @@ namespace Ryujinx.Common
|
||||||
private static Hash128 Xxh3HashLong128bInternal(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret)
|
private static Hash128 Xxh3HashLong128bInternal(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret)
|
||||||
{
|
{
|
||||||
Span<ulong> acc = stackalloc ulong[AccNb];
|
Span<ulong> acc = stackalloc ulong[AccNb];
|
||||||
Xxh3InitAcc.CopyTo(acc);
|
_xxh3InitAcc.CopyTo(acc);
|
||||||
|
|
||||||
Xxh3HashLongInternalLoop(acc, input, secret);
|
Xxh3HashLongInternalLoop(acc, input, secret);
|
||||||
|
|
||||||
|
@ -314,11 +318,11 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
return new Hash128
|
return new Hash128
|
||||||
{
|
{
|
||||||
Low = Xxh3MergeAccs(acc, secret.Slice(SecretMergeAccsStart), (ulong)input.Length * Prime64_1),
|
Low = Xxh3MergeAccs(acc, secret[SecretMergeAccsStart..], (ulong)input.Length * Prime64_1),
|
||||||
High = Xxh3MergeAccs(
|
High = Xxh3MergeAccs(
|
||||||
acc,
|
acc,
|
||||||
secret.Slice(secret.Length - acc.Length * sizeof(ulong) - SecretMergeAccsStart),
|
secret[(secret.Length - acc.Length * sizeof(ulong) - SecretMergeAccsStart)..],
|
||||||
~((ulong)input.Length * Prime64_2))
|
~((ulong)input.Length * Prime64_2)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,15 +336,15 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
uint combinedL = ((uint)c1 << 16) | ((uint)c2 << 24) | c3 | ((uint)input.Length << 8);
|
uint combinedL = ((uint)c1 << 16) | ((uint)c2 << 24) | c3 | ((uint)input.Length << 8);
|
||||||
uint combinedH = BitOperations.RotateLeft(BinaryPrimitives.ReverseEndianness(combinedL), 13);
|
uint combinedH = BitOperations.RotateLeft(BinaryPrimitives.ReverseEndianness(combinedL), 13);
|
||||||
ulong bitFlipL = (BinaryPrimitives.ReadUInt32LittleEndian(secret) ^ BinaryPrimitives.ReadUInt32LittleEndian(secret.Slice(4))) + seed;
|
ulong bitFlipL = (BinaryPrimitives.ReadUInt32LittleEndian(secret) ^ BinaryPrimitives.ReadUInt32LittleEndian(secret[4..])) + seed;
|
||||||
ulong bitFlipH = (BinaryPrimitives.ReadUInt32LittleEndian(secret.Slice(8)) ^ BinaryPrimitives.ReadUInt32LittleEndian(secret.Slice(12))) - seed;
|
ulong bitFlipH = (BinaryPrimitives.ReadUInt32LittleEndian(secret[8..]) ^ BinaryPrimitives.ReadUInt32LittleEndian(secret[12..])) - seed;
|
||||||
ulong keyedLo = combinedL ^ bitFlipL;
|
ulong keyedLo = combinedL ^ bitFlipL;
|
||||||
ulong keyedHi = combinedH ^ bitFlipH;
|
ulong keyedHi = combinedH ^ bitFlipH;
|
||||||
|
|
||||||
return new Hash128
|
return new Hash128
|
||||||
{
|
{
|
||||||
Low = Xxh64Avalanche(keyedLo),
|
Low = Xxh64Avalanche(keyedLo),
|
||||||
High = Xxh64Avalanche(keyedHi)
|
High = Xxh64Avalanche(keyedHi),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,9 +355,9 @@ namespace Ryujinx.Common
|
||||||
seed ^= BinaryPrimitives.ReverseEndianness((uint)seed) << 32;
|
seed ^= BinaryPrimitives.ReverseEndianness((uint)seed) << 32;
|
||||||
|
|
||||||
uint inputLo = BinaryPrimitives.ReadUInt32LittleEndian(input);
|
uint inputLo = BinaryPrimitives.ReadUInt32LittleEndian(input);
|
||||||
uint inputHi = BinaryPrimitives.ReadUInt32LittleEndian(input.Slice(input.Length - 4));
|
uint inputHi = BinaryPrimitives.ReadUInt32LittleEndian(input[^4..]);
|
||||||
ulong input64 = inputLo + ((ulong)inputHi << 32);
|
ulong input64 = inputLo + ((ulong)inputHi << 32);
|
||||||
ulong bitFlip = (BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(16)) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(24))) + seed;
|
ulong bitFlip = (BinaryPrimitives.ReadUInt64LittleEndian(secret[16..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[24..])) + seed;
|
||||||
ulong keyed = input64 ^ bitFlip;
|
ulong keyed = input64 ^ bitFlip;
|
||||||
|
|
||||||
Hash128 m128 = Mult64To128(keyed, Prime64_1 + ((ulong)input.Length << 2));
|
Hash128 m128 = Mult64To128(keyed, Prime64_1 + ((ulong)input.Length << 2));
|
||||||
|
@ -365,6 +369,7 @@ namespace Ryujinx.Common
|
||||||
m128.Low *= 0x9FB21C651E98DF25UL;
|
m128.Low *= 0x9FB21C651E98DF25UL;
|
||||||
m128.Low = XorShift64(m128.Low, 28);
|
m128.Low = XorShift64(m128.Low, 28);
|
||||||
m128.High = Xxh3Avalanche(m128.High);
|
m128.High = Xxh3Avalanche(m128.High);
|
||||||
|
|
||||||
return m128;
|
return m128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,10 +377,10 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
Debug.Assert(9 <= input.Length && input.Length <= 16);
|
Debug.Assert(9 <= input.Length && input.Length <= 16);
|
||||||
|
|
||||||
ulong bitFlipL = (BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(32)) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(40))) - seed;
|
ulong bitFlipL = (BinaryPrimitives.ReadUInt64LittleEndian(secret[32..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[40..])) - seed;
|
||||||
ulong bitFlipH = (BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(48)) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(56))) + seed;
|
ulong bitFlipH = (BinaryPrimitives.ReadUInt64LittleEndian(secret[48..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[56..])) + seed;
|
||||||
ulong inputLo = BinaryPrimitives.ReadUInt64LittleEndian(input);
|
ulong inputLo = BinaryPrimitives.ReadUInt64LittleEndian(input);
|
||||||
ulong inputHi = BinaryPrimitives.ReadUInt64LittleEndian(input.Slice(input.Length - 8));
|
ulong inputHi = BinaryPrimitives.ReadUInt64LittleEndian(input[^8..]);
|
||||||
|
|
||||||
Hash128 m128 = Mult64To128(inputLo ^ inputHi ^ bitFlipL, Prime64_1);
|
Hash128 m128 = Mult64To128(inputLo ^ inputHi ^ bitFlipL, Prime64_1);
|
||||||
m128.Low += ((ulong)input.Length - 1) << 54;
|
m128.Low += ((ulong)input.Length - 1) << 54;
|
||||||
|
@ -387,6 +392,7 @@ namespace Ryujinx.Common
|
||||||
h128.High += m128.High * Prime64_2;
|
h128.High += m128.High * Prime64_2;
|
||||||
h128.Low = Xxh3Avalanche(h128.Low);
|
h128.Low = Xxh3Avalanche(h128.Low);
|
||||||
h128.High = Xxh3Avalanche(h128.High);
|
h128.High = Xxh3Avalanche(h128.High);
|
||||||
|
|
||||||
return h128;
|
return h128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,40 +404,43 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
return Xxh3Len9To16128b(input, secret, seed);
|
return Xxh3Len9To16128b(input, secret, seed);
|
||||||
}
|
}
|
||||||
else if (input.Length >= 4)
|
|
||||||
|
if (input.Length >= 4)
|
||||||
{
|
{
|
||||||
return Xxh3Len4To8128b(input, secret, seed);
|
return Xxh3Len4To8128b(input, secret, seed);
|
||||||
}
|
}
|
||||||
else if (input.Length != 0)
|
|
||||||
|
if (input.Length != 0)
|
||||||
{
|
{
|
||||||
return Xxh3Len1To3128b(input, secret, seed);
|
return Xxh3Len1To3128b(input, secret, seed);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
Hash128 h128 = new();
|
||||||
Hash128 h128 = new Hash128();
|
ulong bitFlipL = BinaryPrimitives.ReadUInt64LittleEndian(secret[64..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[72..]);
|
||||||
ulong bitFlipL = BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(64)) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(72));
|
ulong bitFlipH = BinaryPrimitives.ReadUInt64LittleEndian(secret[80..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[88..]);
|
||||||
ulong bitFlipH = BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(80)) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(88));
|
h128.Low = Xxh64Avalanche(seed ^ bitFlipL);
|
||||||
h128.Low = Xxh64Avalanche(seed ^ bitFlipL);
|
h128.High = Xxh64Avalanche(seed ^ bitFlipH);
|
||||||
h128.High = Xxh64Avalanche(seed ^ bitFlipH);
|
|
||||||
return h128;
|
return h128;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong Xxh3Mix16b(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret, ulong seed)
|
private static ulong Xxh3Mix16b(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret, ulong seed)
|
||||||
{
|
{
|
||||||
ulong inputLo = BinaryPrimitives.ReadUInt64LittleEndian(input);
|
ulong inputLo = BinaryPrimitives.ReadUInt64LittleEndian(input);
|
||||||
ulong inputHi = BinaryPrimitives.ReadUInt64LittleEndian(input.Slice(8));
|
ulong inputHi = BinaryPrimitives.ReadUInt64LittleEndian(input[8..]);
|
||||||
|
|
||||||
return Mul128Fold64(
|
return Mul128Fold64(
|
||||||
inputLo ^ (BinaryPrimitives.ReadUInt64LittleEndian(secret) + seed),
|
inputLo ^ (BinaryPrimitives.ReadUInt64LittleEndian(secret) + seed),
|
||||||
inputHi ^ (BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(8)) - seed));
|
inputHi ^ (BinaryPrimitives.ReadUInt64LittleEndian(secret[8..]) - seed));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Hash128 Xxh128Mix32b(Hash128 acc, ReadOnlySpan<byte> input, ReadOnlySpan<byte> input2, ReadOnlySpan<byte> secret, ulong seed)
|
private static Hash128 Xxh128Mix32b(Hash128 acc, ReadOnlySpan<byte> input, ReadOnlySpan<byte> input2, ReadOnlySpan<byte> secret, ulong seed)
|
||||||
{
|
{
|
||||||
acc.Low += Xxh3Mix16b(input, secret, seed);
|
acc.Low += Xxh3Mix16b(input, secret, seed);
|
||||||
acc.Low ^= BinaryPrimitives.ReadUInt64LittleEndian(input2) + BinaryPrimitives.ReadUInt64LittleEndian(input2.Slice(8));
|
acc.Low ^= BinaryPrimitives.ReadUInt64LittleEndian(input2) + BinaryPrimitives.ReadUInt64LittleEndian(input2[8..]);
|
||||||
acc.High += Xxh3Mix16b(input2, secret.Slice(16), seed);
|
acc.High += Xxh3Mix16b(input2, secret[16..], seed);
|
||||||
acc.High ^= BinaryPrimitives.ReadUInt64LittleEndian(input) + BinaryPrimitives.ReadUInt64LittleEndian(input.Slice(8));
|
acc.High ^= BinaryPrimitives.ReadUInt64LittleEndian(input) + BinaryPrimitives.ReadUInt64LittleEndian(input[8..]);
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,10 +449,10 @@ namespace Ryujinx.Common
|
||||||
Debug.Assert(secret.Length >= SecretSizeMin);
|
Debug.Assert(secret.Length >= SecretSizeMin);
|
||||||
Debug.Assert(16 < input.Length && input.Length <= 128);
|
Debug.Assert(16 < input.Length && input.Length <= 128);
|
||||||
|
|
||||||
Hash128 acc = new Hash128
|
Hash128 acc = new()
|
||||||
{
|
{
|
||||||
Low = (ulong)input.Length * Prime64_1,
|
Low = (ulong)input.Length * Prime64_1,
|
||||||
High = 0
|
High = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (input.Length > 32)
|
if (input.Length > 32)
|
||||||
|
@ -452,21 +461,22 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
if (input.Length > 96)
|
if (input.Length > 96)
|
||||||
{
|
{
|
||||||
acc = Xxh128Mix32b(acc, input.Slice(48), input.Slice(input.Length - 64), secret.Slice(96), seed);
|
acc = Xxh128Mix32b(acc, input[48..], input[^64..], secret[96..], seed);
|
||||||
}
|
}
|
||||||
acc = Xxh128Mix32b(acc, input.Slice(32), input.Slice(input.Length - 48), secret.Slice(64), seed);
|
acc = Xxh128Mix32b(acc, input[32..], input[^48..], secret[64..], seed);
|
||||||
}
|
}
|
||||||
acc = Xxh128Mix32b(acc, input.Slice(16), input.Slice(input.Length - 32), secret.Slice(32), seed);
|
acc = Xxh128Mix32b(acc, input[16..], input[^32..], secret[32..], seed);
|
||||||
}
|
}
|
||||||
acc = Xxh128Mix32b(acc, input, input.Slice(input.Length - 16), secret, seed);
|
acc = Xxh128Mix32b(acc, input, input[^16..], secret, seed);
|
||||||
|
|
||||||
Hash128 h128 = new Hash128
|
Hash128 h128 = new()
|
||||||
{
|
{
|
||||||
Low = acc.Low + acc.High,
|
Low = acc.Low + acc.High,
|
||||||
High = acc.Low * Prime64_1 + acc.High * Prime64_4 + ((ulong)input.Length - seed) * Prime64_2
|
High = acc.Low * Prime64_1 + acc.High * Prime64_4 + ((ulong)input.Length - seed) * Prime64_2,
|
||||||
};
|
};
|
||||||
h128.Low = Xxh3Avalanche(h128.Low);
|
h128.Low = Xxh3Avalanche(h128.Low);
|
||||||
h128.High = 0UL - Xxh3Avalanche(h128.High);
|
h128.High = 0UL - Xxh3Avalanche(h128.High);
|
||||||
|
|
||||||
return h128;
|
return h128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +485,7 @@ namespace Ryujinx.Common
|
||||||
Debug.Assert(secret.Length >= SecretSizeMin);
|
Debug.Assert(secret.Length >= SecretSizeMin);
|
||||||
Debug.Assert(128 < input.Length && input.Length <= 240);
|
Debug.Assert(128 < input.Length && input.Length <= 240);
|
||||||
|
|
||||||
Hash128 acc = new Hash128();
|
Hash128 acc = new();
|
||||||
|
|
||||||
int nbRounds = input.Length / 32;
|
int nbRounds = input.Length / 32;
|
||||||
acc.Low = (ulong)input.Length * Prime64_1;
|
acc.Low = (ulong)input.Length * Prime64_1;
|
||||||
|
@ -483,7 +493,7 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
acc = Xxh128Mix32b(acc, input.Slice(32 * i), input.Slice(32 * i + 16), secret.Slice(32 * i), seed);
|
acc = Xxh128Mix32b(acc, input[(32 * i)..], input[(32 * i + 16)..], secret[(32 * i)..], seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
acc.Low = Xxh3Avalanche(acc.Low);
|
acc.Low = Xxh3Avalanche(acc.Low);
|
||||||
|
@ -492,18 +502,19 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
for (int i = 4; i < nbRounds; i++)
|
for (int i = 4; i < nbRounds; i++)
|
||||||
{
|
{
|
||||||
acc = Xxh128Mix32b(acc, input.Slice(32 * i), input.Slice(32 * i + 16), secret.Slice(MidSizeStartOffset + 32 * (i - 4)), seed);
|
acc = Xxh128Mix32b(acc, input[(32 * i)..], input[(32 * i + 16)..], secret[(MidSizeStartOffset + 32 * (i - 4))..], seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
acc = Xxh128Mix32b(acc, input.Slice(input.Length - 16), input.Slice(input.Length - 32), secret.Slice(SecretSizeMin - MidSizeLastOffset - 16), 0UL - seed);
|
acc = Xxh128Mix32b(acc, input[^16..], input[^32..], secret[(SecretSizeMin - MidSizeLastOffset - 16)..], 0UL - seed);
|
||||||
|
|
||||||
Hash128 h128 = new Hash128
|
Hash128 h128 = new()
|
||||||
{
|
{
|
||||||
Low = acc.Low + acc.High,
|
Low = acc.Low + acc.High,
|
||||||
High = acc.Low * Prime64_1 + acc.High * Prime64_4 + ((ulong)input.Length - seed) * Prime64_2
|
High = acc.Low * Prime64_1 + acc.High * Prime64_4 + ((ulong)input.Length - seed) * Prime64_2,
|
||||||
};
|
};
|
||||||
h128.Low = Xxh3Avalanche(h128.Low);
|
h128.Low = Xxh3Avalanche(h128.Low);
|
||||||
h128.High = 0UL - Xxh3Avalanche(h128.High);
|
h128.High = 0UL - Xxh3Avalanche(h128.High);
|
||||||
|
|
||||||
return h128;
|
return h128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,18 +526,18 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
return Xxh3Len0To16128b(input, secret, seed);
|
return Xxh3Len0To16128b(input, secret, seed);
|
||||||
}
|
}
|
||||||
else if (input.Length <= 128)
|
|
||||||
|
if (input.Length <= 128)
|
||||||
{
|
{
|
||||||
return Xxh3Len17To128128b(input, secret, seed);
|
return Xxh3Len17To128128b(input, secret, seed);
|
||||||
}
|
}
|
||||||
else if (input.Length <= 240)
|
|
||||||
|
if (input.Length <= 240)
|
||||||
{
|
{
|
||||||
return Xxh3Len129To240128b(input, secret, seed);
|
return Xxh3Len129To240128b(input, secret, seed);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return Xxh3HashLong128bInternal(input, secret);
|
||||||
return Xxh3HashLong128bInternal(input, secret);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Hash128 ComputeHash(ReadOnlySpan<byte> input)
|
public static Hash128 ComputeHash(ReadOnlySpan<byte> input)
|
||||||
|
|
|
@ -69,8 +69,8 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
|
||||||
|
|
||||||
ReadOnlyMemory<byte> input = context.Memory.GetSpan(inputPosition, (int)inputSize).ToArray();
|
ReadOnlyMemory<byte> input = context.Memory.GetSpan(inputPosition, (int)inputSize).ToArray();
|
||||||
|
|
||||||
using (IMemoryOwner<byte> outputOwner = ByteMemoryPool.Shared.RentCleared(outputSize))
|
using (IMemoryOwner<byte> outputOwner = ByteMemoryPool.RentCleared(outputSize))
|
||||||
using (IMemoryOwner<byte> performanceOutputOwner = ByteMemoryPool.Shared.RentCleared(performanceOutputSize))
|
using (IMemoryOwner<byte> performanceOutputOwner = ByteMemoryPool.RentCleared(performanceOutputSize))
|
||||||
{
|
{
|
||||||
Memory<byte> output = outputOwner.Memory;
|
Memory<byte> output = outputOwner.Memory;
|
||||||
Memory<byte> performanceOutput = performanceOutputOwner.Memory;
|
Memory<byte> performanceOutput = performanceOutputOwner.Memory;
|
||||||
|
@ -214,4 +214,4 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -439,7 +439,7 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
{
|
{
|
||||||
const int messageSize = 0x100;
|
const int messageSize = 0x100;
|
||||||
|
|
||||||
using IMemoryOwner<byte> reqDataOwner = ByteMemoryPool.Shared.Rent(messageSize);
|
using IMemoryOwner<byte> reqDataOwner = ByteMemoryPool.Rent(messageSize);
|
||||||
|
|
||||||
Span<byte> reqDataSpan = reqDataOwner.Memory.Span;
|
Span<byte> reqDataSpan = reqDataOwner.Memory.Span;
|
||||||
|
|
||||||
|
|
|
@ -85,10 +85,10 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
|
|
||||||
ReadOnlySpan<byte> inputParcel = context.Memory.GetSpan(dataPos, (int)dataSize);
|
ReadOnlySpan<byte> inputParcel = context.Memory.GetSpan(dataPos, (int)dataSize);
|
||||||
|
|
||||||
using (IMemoryOwner<byte> outputParcelOwner = ByteMemoryPool.Shared.RentCleared(replySize))
|
using (IMemoryOwner<byte> outputParcelOwner = ByteMemoryPool.RentCleared(replySize))
|
||||||
{
|
{
|
||||||
Span<byte> outputParcel = outputParcelOwner.Memory.Span;
|
Span<byte> outputParcel = outputParcelOwner.Memory.Span;
|
||||||
|
|
||||||
ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel);
|
ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel);
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
|
@ -106,4 +106,4 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
|
|
||||||
protected abstract ResultCode OnTransact(int binderId, uint code, uint flags, ReadOnlySpan<byte> inputParcel, Span<byte> outputParcel);
|
protected abstract ResultCode OnTransact(int binderId, uint code, uint flags, ReadOnlySpan<byte> inputParcel, Span<byte> outputParcel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue