Compare commits

..

30 Commits

Author SHA1 Message Date
90432946ac Avalonia - Display language names in their corresponding language under "Change Language" (#3490)
* change languages to their native names

* fix Chinese language names

* Update MainWindow.axaml
2022-08-26 19:12:11 +02:00
9bad71afbf bsd: Fix Poll writting in input buffer (#3630)
This is a very old oversight on our Poll implementation.
This worked so far reliably because games and homebrews pass the same
buffer as input and output.
2022-08-26 18:10:45 +02:00
923089a298 Fast path for Inline-to-Memory texture data transfers (#3610)
* Fast path for Inline-to-Memory texture data transfers

* Only do it for block linear textures to be on the safe side
2022-08-26 02:16:41 +00:00
d9aa15eb24 pctl: Implement EndFreeCommunication
This PR Implement `EndFreeCommunication` (checked by RE). Nothing more.

Closes #2420
2022-08-25 23:18:37 +02:00
12c89a61f9 misc: Fix missing null terminator for strings with pchtxt (#3629)
As title say.
2022-08-25 19:59:15 +00:00
f5235fff29 ARMeilleure: Hardware accelerate SHA256 (#3585)
* ARMeilleure/HardwareCapabilities: Add Sha

* ARMeilleure/Intrinsic: Add X86Sha256Rnds2

* ARmeilleure: Hardware accelerate SHA256H/SHA256H2

* ARMeilleure/Intrinsic: Add X86Sha256Msg1, X86Sha256Msg2

* ARMeilleure/Intrinsic: Add X86Palignr

* ARMeilleure: Hardware accelerate SHA256SU0, SHA256SU1

* PTC: Bump InternalVersion
2022-08-25 10:12:13 +00:00
eba682b767 Implement some 32-bit Thumb instructions (#3614)
* Implement some 32-bit Thumb instructions

* Optimize OpCode32MemMult using PopCount
2022-08-25 09:59:34 +00:00
b994dafe7a Update PPTC dialog text to match label and tooltip (#3618)
* Update PPTC dialog text to match label and tooltip

* Update to requested text

* Reverting spaces

* Adding newline back in
2022-08-24 08:25:49 +00:00
54421760c3 Check if game directories have been updated before refreshing GUI (#3607)
* Check if game directories have been updated before refreshing list on save.

* Cleanup spacing

* Add Avalonia and reset value after saving

* Fix Avalonia

* Fix multiple directories not being added in GTK
2022-08-21 13:07:28 +00:00
88a0e720cb Use RGBA16 vertex format if RGB16 is not supported on Vulkan (#3552)
* Use RGBA16 vertex format if RGB16 is not supported on Vulkan

* Catch all shader compilation exceptions
2022-08-20 16:20:27 -03:00
53cc9e0561 Change 'Purge PPTC Cache' label & tooltip to reflect function behavior (#3601)
* Change PPTC purge label & tooltip

* Change Avalonia labels
2022-08-19 23:39:59 +00:00
7defc59b9d A few minor documentation fixes. (#3599)
* A few minor documentation fixes.

* Removed more invalid inheritdoc instances.
2022-08-19 18:21:06 -03:00
951700fdd8 Removed unused usings. (#3593)
* Removed unused usings.

* Added back using, now that it's used.

* Removed extra whitespace.
2022-08-18 18:04:54 +02:00
eb6430f103 Skipped over the last "Count" key explicitly, instead of relying on an exception. (#3595) 2022-08-18 02:00:27 +02:00
80a879cb44 Fix SpirV parse failure (#3597)
* Added .ToString overrides, to help diagnose and debug SpirV generated code.

* Added Spirv to team shared dictionary, so the word will not show up as a warning.

* Fixed bug where we were creating invalid constants (bool 0i and float 0i)

* Update Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Spv.Generator/Instruction.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Adjusted spacing to match style of the rest of the code.

* Added handler for FP64(double) as well, for undefined aggregate types.

* Made the operand labels a static dictionary, to avoid re-allocation on each call.
Replaced Contains/Get with a TryGetValue, to reduce the number of dictionary lookups.

* Added newline between AllOperands and ToString().

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-08-18 01:49:43 +02:00
2197f41506 Removed extra semicolons. (#3594) 2022-08-17 09:05:15 +02:00
c8f9292bab Avalonia - Couple fixes and improvements to vulkan (#3483)
* drop split devices, rebase

* add fallback to opengl if vulkan is not available

* addressed review

* ensure present image references are incremented and decremented when necessary

* allow changing vsync for vulkan

* fix screenshot on avalonia vulkan

* save favorite when toggled

* improve sync between popups

* use separate devices for each new window

* fix crash when closing window

* addressed review

* don't create the main window with immediate mode

* change skia vk delegate to method

* update vulkan throwonerror

* addressed review
2022-08-16 16:32:37 +00:00
0ec933a615 Vulkan: Add ETC2 texture formats (#3576) 2022-08-16 15:42:42 +02:00
2135b6a51a am: Stub SetWirelessPriorityMode, SetWirelessPriorityMode and GetHdcpAuthenticationState (#3535)
This PR some calls in `am` service:
- ISelfController: SetWirelessPriorityMode, SaveCurrentScreenshot (Partially checked by RE).
- ICommonStateGetter: GetHdcpAuthenticationState

Close #1831 and close #3527
2022-08-15 11:12:08 +00:00
00e35d9bf6 ControllerApplet: Override player counts when SingleMode is set (#3571) 2022-08-15 09:46:08 +02:00
6dfb6ccf8c PreAllocator: Check if instruction supports a Vex prefix in IsVexSameOperandDestSrc1 (#3587) 2022-08-14 17:35:08 -03:00
e87e8b012c Fix texture bindings using wrong sampler pool in some cases (#3583) 2022-08-14 14:00:30 -03:00
e8f1ca8427 OpenGL: Limit vertex buffer range for non-indexed draws (#3542)
* Limit vertex buffer range for non-indexed draws

* Fix typo
2022-08-11 20:21:56 -03:00
ad47bd2d4e Fix blend with RGBX color formats (#3553) 2022-08-11 18:23:25 -03:00
a5ff0024fb Rename ToSpan to AsSpan (#3556) 2022-08-11 18:07:37 -03:00
f9661a54d2 add Japanese translation to Avalonia UI (#3489)
* add Japanese translation to Avalonia UI

* translate language names

* fix raised in the review
2022-08-11 17:55:14 -03:00
66e7fdb871 OpenGL: Fix clears of unbound color targets (#3564) 2022-08-08 17:39:22 +00:00
2bb9b33da1 Implement Arm32 Sha256 and MRS Rd, CPSR instructions (#3544)
* Implement Arm32 Sha256 and MRS Rd, CPSR instructions

* Add tests using Arm64 outputs
2022-08-05 19:03:50 +02:00
1080f64df9 Implement HLE macros for render target clears (#3528)
* Implement HLE macros for render target clears

* Add constants for the offsets
2022-08-04 21:30:08 +00:00
c48a75979f Fix Multithreaded Compilation of Shader Cache on OpenGL (#3540)
This was broken by the Vulkan changes - OpenGL was building host caches at boot on one thread, which is very notably slower than when it is multithreaded.

This was caused by trying to get the program binary immediately after compilation started, which blocks. Now it does it after compilation has completed.
2022-08-03 19:37:56 -03:00
293 changed files with 3244 additions and 1370 deletions

View File

@ -58,7 +58,6 @@ namespace ARMeilleure.CodeGen.Linking
/// <param name="a">First instance</param>
/// <param name="b">Second instance</param>
/// <returns><see langword="true"/> if not equal; otherwise <see langword="false"/></returns>
/// <inheritdoc/>
public static bool operator !=(Symbol a, Symbol b)
{
return !(a == b);

View File

@ -1,6 +1,4 @@
using ARMeilleure.Common;
using ARMeilleure.IntermediateRepresentation;
using System;
namespace ARMeilleure.CodeGen.RegisterAllocators
{

View File

@ -4,6 +4,11 @@ namespace ARMeilleure.CodeGen.X86
{
partial class Assembler
{
public static bool SupportsVexPrefix(X86Instruction inst)
{
return _instTable[(int)inst].Flags.HasFlag(InstructionFlags.Vex);
}
private const int BadOp = 0;
[Flags]
@ -152,6 +157,7 @@ namespace ARMeilleure.CodeGen.X86
Add(X86Instruction.Paddd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffe, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Paddq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd4, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Paddw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffd, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Palignr, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0f, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pand, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdb, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pandn, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdf, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pavgb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe0, InstructionFlags.Vex | InstructionFlags.Prefix66));
@ -234,6 +240,9 @@ namespace ARMeilleure.CodeGen.X86
Add(X86Instruction.Rsqrtss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Sar, new InstructionInfo(0x070000d3, 0x070000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Setcc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f90, InstructionFlags.Reg8Dest));
Add(X86Instruction.Sha256Msg1, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cc, InstructionFlags.None));
Add(X86Instruction.Sha256Msg2, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cd, InstructionFlags.None));
Add(X86Instruction.Sha256Rnds2, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cb, InstructionFlags.None));
Add(X86Instruction.Shl, new InstructionInfo(0x040000d3, 0x040000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Shr, new InstructionInfo(0x050000d3, 0x050000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Shufpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstructionFlags.Vex | InstructionFlags.Prefix66));

View File

@ -1,5 +1,4 @@
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.CodeGen.X86
{

View File

@ -12,21 +12,28 @@ namespace ARMeilleure.CodeGen.X86
return;
}
(_, _, int ecx, int edx) = X86Base.CpuId(0x00000001, 0x00000000);
(int maxNum, _, _, _) = X86Base.CpuId(0x00000000, 0x00000000);
FeatureInfoEdx = (FeatureFlagsEdx)edx;
FeatureInfoEcx = (FeatureFlagsEcx)ecx;
(_, _, int ecx1, int edx1) = X86Base.CpuId(0x00000001, 0x00000000);
FeatureInfo1Edx = (FeatureFlags1Edx)edx1;
FeatureInfo1Ecx = (FeatureFlags1Ecx)ecx1;
if (maxNum >= 7)
{
(_, int ebx7, _, _) = X86Base.CpuId(0x00000007, 0x00000000);
FeatureInfo7Ebx = (FeatureFlags7Ebx)ebx7;
}
}
[Flags]
public enum FeatureFlagsEdx
public enum FeatureFlags1Edx
{
Sse = 1 << 25,
Sse2 = 1 << 26
}
[Flags]
public enum FeatureFlagsEcx
public enum FeatureFlags1Ecx
{
Sse3 = 1 << 0,
Pclmulqdq = 1 << 1,
@ -40,21 +47,31 @@ namespace ARMeilleure.CodeGen.X86
F16c = 1 << 29
}
public static FeatureFlagsEdx FeatureInfoEdx { get; }
public static FeatureFlagsEcx FeatureInfoEcx { get; }
[Flags]
public enum FeatureFlags7Ebx
{
Avx2 = 1 << 5,
Sha = 1 << 29
}
public static bool SupportsSse => FeatureInfoEdx.HasFlag(FeatureFlagsEdx.Sse);
public static bool SupportsSse2 => FeatureInfoEdx.HasFlag(FeatureFlagsEdx.Sse2);
public static bool SupportsSse3 => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Sse3);
public static bool SupportsPclmulqdq => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Pclmulqdq);
public static bool SupportsSsse3 => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Ssse3);
public static bool SupportsFma => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Fma);
public static bool SupportsSse41 => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Sse41);
public static bool SupportsSse42 => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Sse42);
public static bool SupportsPopcnt => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Popcnt);
public static bool SupportsAesni => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Aes);
public static bool SupportsAvx => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.Avx);
public static bool SupportsF16c => FeatureInfoEcx.HasFlag(FeatureFlagsEcx.F16c);
public static FeatureFlags1Edx FeatureInfo1Edx { get; }
public static FeatureFlags1Ecx FeatureInfo1Ecx { get; }
public static FeatureFlags7Ebx FeatureInfo7Ebx { get; } = 0;
public static bool SupportsSse => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse);
public static bool SupportsSse2 => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse2);
public static bool SupportsSse3 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse3);
public static bool SupportsPclmulqdq => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Pclmulqdq);
public static bool SupportsSsse3 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Ssse3);
public static bool SupportsFma => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Fma);
public static bool SupportsSse41 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse41);
public static bool SupportsSse42 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse42);
public static bool SupportsPopcnt => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Popcnt);
public static bool SupportsAesni => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Aes);
public static bool SupportsAvx => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Avx);
public static bool SupportsAvx2 => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx2) && SupportsAvx;
public static bool SupportsF16c => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.F16c);
public static bool SupportsSha => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Sha);
public static bool ForceLegacySse { get; set; }

View File

@ -82,6 +82,7 @@ namespace ARMeilleure.CodeGen.X86
Add(Intrinsic.X86Paddd, new IntrinsicInfo(X86Instruction.Paddd, IntrinsicType.Binary));
Add(Intrinsic.X86Paddq, new IntrinsicInfo(X86Instruction.Paddq, IntrinsicType.Binary));
Add(Intrinsic.X86Paddw, new IntrinsicInfo(X86Instruction.Paddw, IntrinsicType.Binary));
Add(Intrinsic.X86Palignr, new IntrinsicInfo(X86Instruction.Palignr, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Pand, new IntrinsicInfo(X86Instruction.Pand, IntrinsicType.Binary));
Add(Intrinsic.X86Pandn, new IntrinsicInfo(X86Instruction.Pandn, IntrinsicType.Binary));
Add(Intrinsic.X86Pavgb, new IntrinsicInfo(X86Instruction.Pavgb, IntrinsicType.Binary));
@ -151,6 +152,9 @@ namespace ARMeilleure.CodeGen.X86
Add(Intrinsic.X86Roundss, new IntrinsicInfo(X86Instruction.Roundss, IntrinsicType.BinaryImm));
Add(Intrinsic.X86Rsqrtps, new IntrinsicInfo(X86Instruction.Rsqrtps, IntrinsicType.Unary));
Add(Intrinsic.X86Rsqrtss, new IntrinsicInfo(X86Instruction.Rsqrtss, IntrinsicType.Unary));
Add(Intrinsic.X86Sha256Msg1, new IntrinsicInfo(X86Instruction.Sha256Msg1, IntrinsicType.Binary));
Add(Intrinsic.X86Sha256Msg2, new IntrinsicInfo(X86Instruction.Sha256Msg2, IntrinsicType.Binary));
Add(Intrinsic.X86Sha256Rnds2, new IntrinsicInfo(X86Instruction.Sha256Rnds2, IntrinsicType.Ternary));
Add(Intrinsic.X86Shufpd, new IntrinsicInfo(X86Instruction.Shufpd, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Shufps, new IntrinsicInfo(X86Instruction.Shufps, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Sqrtpd, new IntrinsicInfo(X86Instruction.Sqrtpd, IntrinsicType.Unary));

View File

@ -308,11 +308,13 @@ namespace ARMeilleure.CodeGen.X86
case Instruction.Extended:
{
bool isBlend = node.Intrinsic == Intrinsic.X86Blendvpd ||
node.Intrinsic == Intrinsic.X86Blendvps ||
node.Intrinsic == Intrinsic.X86Pblendvb;
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
if ((node.Intrinsic == Intrinsic.X86Blendvpd ||
node.Intrinsic == Intrinsic.X86Blendvps ||
node.Intrinsic == Intrinsic.X86Pblendvb) &&
!HardwareCapabilities.SupportsVexEncoding)
// SHA256RNDS2 always has an implied XMM0 as a last operand.
if ((isBlend && !HardwareCapabilities.SupportsVexEncoding) || node.Intrinsic == Intrinsic.X86Sha256Rnds2)
{
Operand xmm0 = Xmm(X86Register.Xmm0, OperandType.V128);
@ -1297,11 +1299,15 @@ namespace ARMeilleure.CodeGen.X86
{
if (IsIntrinsic(operation.Instruction))
{
IntrinsicInfo info = IntrinsicTable.GetInfo(operation.Intrinsic);
bool hasVex = HardwareCapabilities.SupportsVexEncoding && Assembler.SupportsVexPrefix(info.Inst);
bool isUnary = operation.SourcesCount < 2;
bool hasVecDest = operation.Destination != default && operation.Destination.Type == OperandType.V128;
return !HardwareCapabilities.SupportsVexEncoding && !isUnary && hasVecDest;
return !hasVex && !isUnary && hasVecDest;
}
return false;

View File

@ -98,6 +98,7 @@ namespace ARMeilleure.CodeGen.X86
Paddd,
Paddq,
Paddw,
Palignr,
Pand,
Pandn,
Pavgb,
@ -180,6 +181,9 @@ namespace ARMeilleure.CodeGen.X86
Rsqrtss,
Sar,
Setcc,
Sha256Msg1,
Sha256Msg2,
Sha256Rnds2,
Shl,
Shr,
Shufpd,

View File

@ -206,7 +206,7 @@ namespace ARMeilleure.Common
/// <typeparam name="T">Type of elements</typeparam>
/// <param name="length">Number of elements</param>
/// <param name="fill">Fill value</param>
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword=""="false"/></param>
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword="false"/></param>
/// <returns>Allocated block</returns>
private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
{

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
namespace ARMeilleure.Common
{

View File

@ -9,6 +9,9 @@ namespace ARMeilleure.Common
class Counter<T> : IDisposable where T : unmanaged
{
private bool _disposed;
/// <summary>
/// Index in the <see cref="EntryTable{T}"/>
/// </summary>
private readonly int _index;
private readonly EntryTable<T> _countTable;
@ -17,7 +20,6 @@ namespace ARMeilleure.Common
/// <see cref="EntryTable{T}"/> instance and index.
/// </summary>
/// <param name="countTable"><see cref="EntryTable{T}"/> instance</param>
/// <param name="index">Index in the <see cref="EntryTable{T}"/></param>
/// <exception cref="ArgumentNullException"><paramref name="countTable"/> is <see langword="null"/></exception>
/// <exception cref="ArgumentException"><typeparamref name="T"/> is unsupported</exception>
public Counter(EntryTable<T> countTable)
@ -68,7 +70,7 @@ namespace ARMeilleure.Common
/// <summary>
/// Releases all unmanaged and optionally managed resources used by the <see cref="Counter{T}"/> instance.
/// </summary>
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resources</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)

View File

@ -0,0 +1,8 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32MemRsImm : IOpCode32Mem
{
int Rm { get; }
ShiftType ShiftType { get; }
}
}

View File

@ -1,3 +1,5 @@
using System.Numerics;
namespace ARMeilleure.Decoders
{
class OpCode32MemMult : OpCode32, IOpCode32MemMult
@ -23,14 +25,7 @@ namespace ARMeilleure.Decoders
RegisterMask = opCode & 0xffff;
int regsSize = 0;
for (int index = 0; index < 16; index++)
{
regsSize += (RegisterMask >> index) & 1;
}
regsSize *= 4;
int regsSize = BitOperations.PopCount((uint)RegisterMask) * 4;
if (!u)
{

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
class OpCode32MemRsImm : OpCode32Mem
class OpCode32MemRsImm : OpCode32Mem, IOpCode32MemRsImm
{
public int Rm { get; }
public ShiftType ShiftType { get; }

View File

@ -0,0 +1,16 @@
namespace ARMeilleure.Decoders
{
class OpCode32Mrs : OpCode32
{
public bool R { get; }
public int Rd { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Mrs(inst, address, opCode);
public OpCode32Mrs(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
R = ((opCode >> 22) & 1) != 0;
Rd = (opCode >> 12) & 0xf;
}
}
}

View File

@ -1,10 +1,10 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16BImmCmp : OpCodeT16
class OpCodeT16BImmCmp : OpCodeT16, IOpCode32BImm
{
public int Rn { get; }
public int Immediate { get; }
public long Immediate { get; }
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16BImmCmp(inst, address, opCode);

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Reflection.Emit;
namespace ARMeilleure.Decoders
{

View File

@ -1,6 +1,4 @@
using ARMeilleure.Instructions;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCodeT32BImm20 : OpCodeT32, IOpCode32BImm
{

View File

@ -0,0 +1,31 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32MemImm8D : OpCodeT32, IOpCode32Mem
{
public int Rt { get; }
public int Rt2 { get; }
public int Rn { get; }
public bool WBack { get; }
public bool IsLoad { get; }
public bool Index { get; }
public bool Add { get; }
public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32MemImm8D(inst, address, opCode);
public OpCodeT32MemImm8D(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rt2 = (opCode >> 8) & 0xf;
Rt = (opCode >> 12) & 0xf;
Rn = (opCode >> 16) & 0xf;
Index = ((opCode >> 24) & 1) != 0;
Add = ((opCode >> 23) & 1) != 0;
WBack = ((opCode >> 21) & 1) != 0;
Immediate = opCode & 0xff;
IsLoad = ((opCode >> 20) & 1) != 0;
}
}
}

View File

@ -0,0 +1,24 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32MemLdEx : OpCodeT32, IOpCode32MemEx
{
public int Rd => 0;
public int Rt { get; }
public int Rn { get; }
public bool WBack => false;
public bool IsLoad => true;
public bool Index => false;
public bool Add => false;
public int Immediate => 0;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32MemLdEx(inst, address, opCode);
public OpCodeT32MemLdEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rt = (opCode >> 12) & 0xf;
Rn = (opCode >> 16) & 0xf;
}
}
}

View File

@ -0,0 +1,52 @@
using System.Numerics;
namespace ARMeilleure.Decoders
{
class OpCodeT32MemMult : OpCodeT32, IOpCode32MemMult
{
public int Rn { get; }
public int RegisterMask { get; }
public int Offset { get; }
public int PostOffset { get; }
public bool IsLoad { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32MemMult(inst, address, opCode);
public OpCodeT32MemMult(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rn = (opCode >> 16) & 0xf;
bool isLoad = (opCode & (1 << 20)) != 0;
bool w = (opCode & (1 << 21)) != 0;
bool u = (opCode & (1 << 23)) != 0;
bool p = (opCode & (1 << 24)) != 0;
RegisterMask = opCode & 0xffff;
int regsSize = BitOperations.PopCount((uint)RegisterMask) * 4;
if (!u)
{
Offset -= regsSize;
}
if (u == p)
{
Offset += 4;
}
if (w)
{
PostOffset = u ? regsSize : -regsSize;
}
else
{
PostOffset = 0;
}
IsLoad = isLoad;
}
}
}

View File

@ -0,0 +1,30 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32MemRsImm : OpCodeT32, IOpCode32MemRsImm
{
public int Rt { get; }
public int Rn { get; }
public int Rm { get; }
public ShiftType ShiftType => ShiftType.Lsl;
public bool WBack => false;
public bool IsLoad { get; }
public bool Index => true;
public bool Add => true;
public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32MemRsImm(inst, address, opCode);
public OpCodeT32MemRsImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rm = (opCode >> 0) & 0xf;
Rt = (opCode >> 12) & 0xf;
Rn = (opCode >> 16) & 0xf;
IsLoad = (opCode & (1 << 20)) != 0;
Immediate = (opCode >> 4) & 3;
}
}
}

View File

@ -0,0 +1,25 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32MemStEx : OpCodeT32, IOpCode32MemEx
{
public int Rd { get; }
public int Rt { get; }
public int Rn { get; }
public bool WBack => false;
public bool IsLoad => false;
public bool Index => false;
public bool Add => false;
public int Immediate => 0;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32MemStEx(inst, address, opCode);
public OpCodeT32MemStEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 0) & 0xf;
Rt = (opCode >> 12) & 0xf;
Rn = (opCode >> 16) & 0xf;
}
}
}

View File

@ -704,6 +704,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00110100xxxxxxxxxxxxxxxxxxxx", InstName.Movt, InstEmit32.Movt, OpCode32AluImm16.Create);
SetA32("<<<<1110xxx1xxxxxxxx111xxxx1xxxx", InstName.Mrc, InstEmit32.Mrc, OpCode32System.Create);
SetA32("<<<<11000101xxxxxxxx111xxxxxxxxx", InstName.Mrrc, InstEmit32.Mrrc, OpCode32System.Create);
SetA32("<<<<00010x001111xxxx000000000000", InstName.Mrs, InstEmit32.Mrs, OpCode32Mrs.Create);
SetA32("<<<<00010x10xxxx111100000000xxxx", InstName.Msr, InstEmit32.Msr, OpCode32MsrReg.Create);
SetA32("<<<<0000000xxxxx0000xxxx1001xxxx", InstName.Mul, InstEmit32.Mul, OpCode32AluMla.Create);
SetA32("<<<<0011111x0000xxxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCode32AluImm.Create);
@ -792,185 +793,189 @@ namespace ARMeilleure.Decoders
SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, OpCode32AluUx.Create);
// FP & SIMD
SetA32("111100111x110000xxx0001101x0xxx0", InstName.Aesd_V, InstEmit32.Aesd_V, OpCode32Simd.Create);
SetA32("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, OpCode32Simd.Create);
SetA32("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, OpCode32Simd.Create);
SetA32("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, OpCode32Simd.Create);
SetA32("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, OpCode32SimdRegLong.Create);
SetA32("<<<<11101x110000xxxx101x11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, OpCode32SimdS.Create);
SetA32("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create);
SetA32("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create);
SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, OpCode32SimdReg.Create);
SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, OpCode32SimdRegS.Create);
SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx0000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, OpCode32SimdRegLong.Create);
SetA32("1111001x1x<<xxxxxxxx0001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, OpCode32SimdRegWide.Create);
SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, OpCode32SimdBinary.Create);
SetA32("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, OpCode32SimdBinary.Create);
SetA32("1111001x1x000xxxxxxx<<x10x11xxxx", InstName.Vbic, InstEmit32.Vbic_II, OpCode32SimdImm.Create);
SetA32("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, OpCode32SimdBinary.Create);
SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, OpCode32SimdBinary.Create);
SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, OpCode32SimdBinary.Create);
SetA32("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, OpCode32SimdReg.Create);
SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, OpCode32SimdReg.Create);
SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, OpCode32SimdCmpZ.Create);
SetA32("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, OpCode32SimdReg.Create);
SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, OpCode32SimdReg.Create);
SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, OpCode32SimdCmpZ.Create);
SetA32("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, OpCode32SimdReg.Create);
SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, OpCode32SimdReg.Create);
SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, OpCode32SimdCmpZ.Create);
SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, OpCode32SimdCmpZ.Create);
SetA32("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create);
SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, OpCode32SimdS.Create);
SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, OpCode32SimdS.Create);
SetA32("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create);
SetA32("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, OpCode32SimdS.Create); // FP 32 and 64, scalar.
SetA32("<<<<11101x11110xxxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // FP32 to int.
SetA32("<<<<11101x111000xxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // Int to FP32.
SetA32("111111101x1111xxxxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_RM, OpCode32SimdCvtFI.Create); // The many FP32 to int encodings (fp).
SetA32("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create); // FP and integer, vector.
SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, OpCode32SimdRegS.Create);
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, OpCode32SimdDupGP.Create);
SetA32("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create);
SetA32("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create);
SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create);
SetA32("<<<<11101x10xxxxxxxx101xx0x0xxxx", InstName.Vfma, InstEmit32.Vfma_S, OpCode32SimdRegS.Create);
SetA32("111100100x00xxxxxxxx1100xxx1xxxx", InstName.Vfma, InstEmit32.Vfma_V, OpCode32SimdReg.Create);
SetA32("<<<<11101x10xxxxxxxx101xx1x0xxxx", InstName.Vfms, InstEmit32.Vfms_S, OpCode32SimdRegS.Create);
SetA32("111100100x10xxxxxxxx1100xxx1xxxx", InstName.Vfms, InstEmit32.Vfms_V, OpCode32SimdReg.Create);
SetA32("<<<<11101x01xxxxxxxx101xx1x0xxxx", InstName.Vfnma, InstEmit32.Vfnma_S, OpCode32SimdRegS.Create);
SetA32("<<<<11101x01xxxxxxxx101xx0x0xxxx", InstName.Vfnms, InstEmit32.Vfnms_S, OpCode32SimdRegS.Create);
SetA32("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, OpCode32SimdReg.Create);
SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create);
SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 1.
SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 2.
SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 3.
SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 4.
SetA32("111101001x10xxxxxxxxxx01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create);
SetA32("111101000x10xxxxxxxx100xxxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype).
SetA32("111101000x10xxxxxxxx0011xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2.
SetA32("111101001x10xxxxxxxxxx10xxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create);
SetA32("111101000x10xxxxxxxx010xxxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("111101001x10xxxxxxxxxx11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create);
SetA32("111101000x10xxxxxxxx000xxxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11010x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x01xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11010x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, OpCode32SimdMemImm.Create);
SetA32("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, OpCode32SimdReg.Create);
SetA32("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, OpCode32SimdReg.Create);
SetA32("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, OpCode32SimdReg.Create);
SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, OpCode32SimdReg.Create);
SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_S, OpCode32SimdRegS.Create);
SetA32("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, OpCode32SimdReg.Create);
SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.Vminnm_S, OpCode32SimdRegS.Create);
SetA32("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, OpCode32SimdRegElem.Create);
SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, OpCode32SimdReg.Create);
SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, OpCode32SimdRegS.Create);
SetA32("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, OpCode32SimdRegElem.Create);
SetA32("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, OpCode32SimdRegS.Create);
SetA32("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, OpCode32SimdReg.Create);
SetA32("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxx01010x0x0xxxx", InstName.Vmlsl, InstEmit32.Vmlsl_I, OpCode32SimdRegLong.Create);
SetA32("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // From gen purpose.
SetA32("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // To gen purpose.
SetA32("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and single precision x2.
SetA32("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and double precision.
SetA32("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, OpCode32SimdMovGp.Create); // To/from gen purpose and single precision.
SetA32("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q vector I32.
SetA32("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm44.Create); // Scalar f16/32/64 based on size 01 10 11.
SetA32("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I16.
SetA32("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q (dt - from cmode).
SetA32("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I64.
SetA32("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, OpCode32SimdS.Create);
SetA32("1111001x1x001000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
SetA32("1111001x1x010000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
SetA32("1111001x1x100000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
SetA32("111100111x11xx10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, OpCode32SimdCmpZ.Create);
SetA32("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, OpCode32SimdSpecial.Create);
SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, OpCode32SimdSpecial.Create);
SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, OpCode32SimdRegElem.Create);
SetA32("111100100x<<xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create);
SetA32("111100110x00xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create);
SetA32("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, OpCode32SimdRegS.Create);
SetA32("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxx01010x1x0xxxx", InstName.Vmull, InstEmit32.Vmull_1, OpCode32SimdRegElemLong.Create);
SetA32("1111001x1x<<xxxxxxx01100x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create);
SetA32("111100101xx0xxxxxxx01110x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create); // P8/P64
SetA32("111100111x110000xxxx01011xx0xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, OpCode32SimdBinary.Create);
SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create); // D/Q vector I32.
SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create);
SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create);
SetA32("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, OpCode32SimdS.Create);
SetA32("111100111x11<<01xxxx00111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create);
SetA32("111100111x111001xxxx01111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create);
SetA32("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, OpCode32SimdRegS.Create);
SetA32("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, OpCode32SimdRegS.Create);
SetA32("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create);
SetA32("111100100x11xxxxxxxx0001xxx1xxxx", InstName.Vorn, InstEmit32.Vorn_I, OpCode32SimdBinary.Create);
SetA32("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, OpCode32SimdBinary.Create);
SetA32("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create);
SetA32("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create);
SetA32("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create);
SetA32("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create);
SetA32("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create);
SetA32("1111001x0x<<xxxxxxxx1010x0x1xxxx", InstName.Vpmin, InstEmit32.Vpmin_I, OpCode32SimdReg.Create);
SetA32("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, OpCode32SimdReg.Create);
SetA32("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create);
SetA32("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create);
SetA32("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create);
SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, OpCode32SimdSqrte.Create);
SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, OpCode32SimdReg.Create);
SetA32("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, OpCode32SimdRev.Create);
SetA32("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create);
SetA32("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create);
SetA32("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create);
SetA32("1111001x1x>>>xxxxxxx0010>xx1xxxx", InstName.Vrshr, InstEmit32.Vrshr, OpCode32SimdShImm.Create);
SetA32("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, OpCode32SimdSqrte.Create);
SetA32("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, OpCode32SimdReg.Create);
SetA32("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create);
SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create);
SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create);
SetA32("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create); // A1 encoding.
SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create);
SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create);
SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create);
SetA32("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create);
SetA32("111101001x00xxxxxxxx<<00xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create);
SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 1.
SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 2.
SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 3.
SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 4.
SetA32("111101001x00xxxxxxxx<<01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create);
SetA32("111101000x00xxxxxxxx100xxxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype).
SetA32("111101000x00xxxxxxxx0011xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2.
SetA32("111101001x00xxxxxxxx<<10xxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create);
SetA32("111101000x00xxxxxxxx010xxxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("111101001x00xxxxxxxx<<11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create);
SetA32("111101000x00xxxxxxxx000xxxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11010x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x00xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, OpCode32SimdMemImm.Create);
SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, OpCode32SimdReg.Create);
SetA32("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, OpCode32SimdRegS.Create);
SetA32("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx0011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create);
SetA32("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create);
SetA32("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create);
SetA32("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create);
SetA32("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create);
SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create);
SetA32("111100111x110000xxx0001101x0xxx0", InstName.Aesd_V, InstEmit32.Aesd_V, OpCode32Simd.Create);
SetA32("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, OpCode32Simd.Create);
SetA32("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, OpCode32Simd.Create);
SetA32("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, OpCode32Simd.Create);
SetA32("111100110x00xxx0xxx01100x1x0xxx0", InstName.Sha256h_V, InstEmit32.Sha256h_V, OpCode32SimdReg.Create);
SetA32("111100110x01xxx0xxx01100x1x0xxx0", InstName.Sha256h2_V, InstEmit32.Sha256h2_V, OpCode32SimdReg.Create);
SetA32("111100111x111010xxx0001111x0xxx0", InstName.Sha256su0_V, InstEmit32.Sha256su0_V, OpCode32Simd.Create);
SetA32("111100110x10xxx0xxx01100x1x0xxx0", InstName.Sha256su1_V, InstEmit32.Sha256su1_V, OpCode32SimdReg.Create);
SetA32("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, OpCode32SimdRegLong.Create);
SetA32("<<<<11101x110000xxxx101x11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, OpCode32SimdS.Create);
SetA32("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create);
SetA32("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create);
SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, OpCode32SimdReg.Create);
SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, OpCode32SimdRegS.Create);
SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx0000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, OpCode32SimdRegLong.Create);
SetA32("1111001x1x<<xxxxxxxx0001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, OpCode32SimdRegWide.Create);
SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, OpCode32SimdBinary.Create);
SetA32("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, OpCode32SimdBinary.Create);
SetA32("1111001x1x000xxxxxxx<<x10x11xxxx", InstName.Vbic, InstEmit32.Vbic_II, OpCode32SimdImm.Create);
SetA32("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, OpCode32SimdBinary.Create);
SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, OpCode32SimdBinary.Create);
SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, OpCode32SimdBinary.Create);
SetA32("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, OpCode32SimdReg.Create);
SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, OpCode32SimdReg.Create);
SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, OpCode32SimdCmpZ.Create);
SetA32("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, OpCode32SimdReg.Create);
SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, OpCode32SimdReg.Create);
SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, OpCode32SimdCmpZ.Create);
SetA32("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, OpCode32SimdReg.Create);
SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, OpCode32SimdReg.Create);
SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, OpCode32SimdCmpZ.Create);
SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, OpCode32SimdCmpZ.Create);
SetA32("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create);
SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, OpCode32SimdS.Create);
SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, OpCode32SimdS.Create);
SetA32("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create);
SetA32("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, OpCode32SimdS.Create); // FP 32 and 64, scalar.
SetA32("<<<<11101x11110xxxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // FP32 to int.
SetA32("<<<<11101x111000xxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // Int to FP32.
SetA32("111111101x1111xxxxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_RM, OpCode32SimdCvtFI.Create); // The many FP32 to int encodings (fp).
SetA32("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create); // FP and integer, vector.
SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, OpCode32SimdRegS.Create);
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, OpCode32SimdDupGP.Create);
SetA32("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create);
SetA32("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create);
SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create);
SetA32("<<<<11101x10xxxxxxxx101xx0x0xxxx", InstName.Vfma, InstEmit32.Vfma_S, OpCode32SimdRegS.Create);
SetA32("111100100x00xxxxxxxx1100xxx1xxxx", InstName.Vfma, InstEmit32.Vfma_V, OpCode32SimdReg.Create);
SetA32("<<<<11101x10xxxxxxxx101xx1x0xxxx", InstName.Vfms, InstEmit32.Vfms_S, OpCode32SimdRegS.Create);
SetA32("111100100x10xxxxxxxx1100xxx1xxxx", InstName.Vfms, InstEmit32.Vfms_V, OpCode32SimdReg.Create);
SetA32("<<<<11101x01xxxxxxxx101xx1x0xxxx", InstName.Vfnma, InstEmit32.Vfnma_S, OpCode32SimdRegS.Create);
SetA32("<<<<11101x01xxxxxxxx101xx0x0xxxx", InstName.Vfnms, InstEmit32.Vfnms_S, OpCode32SimdRegS.Create);
SetA32("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, OpCode32SimdReg.Create);
SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create);
SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 1.
SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 2.
SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 3.
SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 4.
SetA32("111101001x10xxxxxxxxxx01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create);
SetA32("111101000x10xxxxxxxx100xxxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype).
SetA32("111101000x10xxxxxxxx0011xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2.
SetA32("111101001x10xxxxxxxxxx10xxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create);
SetA32("111101000x10xxxxxxxx010xxxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("111101001x10xxxxxxxxxx11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create);
SetA32("111101000x10xxxxxxxx000xxxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11010x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x01xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11010x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, OpCode32SimdMemImm.Create);
SetA32("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, OpCode32SimdReg.Create);
SetA32("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, OpCode32SimdReg.Create);
SetA32("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, OpCode32SimdReg.Create);
SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, OpCode32SimdReg.Create);
SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_S, OpCode32SimdRegS.Create);
SetA32("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, OpCode32SimdReg.Create);
SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.Vminnm_S, OpCode32SimdRegS.Create);
SetA32("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, OpCode32SimdRegElem.Create);
SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, OpCode32SimdReg.Create);
SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, OpCode32SimdRegS.Create);
SetA32("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, OpCode32SimdRegElem.Create);
SetA32("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, OpCode32SimdRegS.Create);
SetA32("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, OpCode32SimdReg.Create);
SetA32("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxx01010x0x0xxxx", InstName.Vmlsl, InstEmit32.Vmlsl_I, OpCode32SimdRegLong.Create);
SetA32("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // From gen purpose.
SetA32("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // To gen purpose.
SetA32("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and single precision x2.
SetA32("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and double precision.
SetA32("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, OpCode32SimdMovGp.Create); // To/from gen purpose and single precision.
SetA32("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q vector I32.
SetA32("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm44.Create); // Scalar f16/32/64 based on size 01 10 11.
SetA32("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I16.
SetA32("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q (dt - from cmode).
SetA32("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I64.
SetA32("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, OpCode32SimdS.Create);
SetA32("1111001x1x001000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
SetA32("1111001x1x010000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
SetA32("1111001x1x100000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
SetA32("111100111x11xx10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, OpCode32SimdCmpZ.Create);
SetA32("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, OpCode32SimdSpecial.Create);
SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, OpCode32SimdSpecial.Create);
SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, OpCode32SimdRegElem.Create);
SetA32("111100100x<<xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create);
SetA32("111100110x00xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create);
SetA32("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, OpCode32SimdRegS.Create);
SetA32("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxx01010x1x0xxxx", InstName.Vmull, InstEmit32.Vmull_1, OpCode32SimdRegElemLong.Create);
SetA32("1111001x1x<<xxxxxxx01100x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create);
SetA32("111100101xx0xxxxxxx01110x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create); // P8/P64
SetA32("111100111x110000xxxx01011xx0xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, OpCode32SimdBinary.Create);
SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create); // D/Q vector I32.
SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create);
SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create);
SetA32("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, OpCode32SimdS.Create);
SetA32("111100111x11<<01xxxx00111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create);
SetA32("111100111x111001xxxx01111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create);
SetA32("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, OpCode32SimdRegS.Create);
SetA32("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, OpCode32SimdRegS.Create);
SetA32("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create);
SetA32("111100100x11xxxxxxxx0001xxx1xxxx", InstName.Vorn, InstEmit32.Vorn_I, OpCode32SimdBinary.Create);
SetA32("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, OpCode32SimdBinary.Create);
SetA32("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create);
SetA32("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create);
SetA32("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create);
SetA32("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create);
SetA32("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create);
SetA32("1111001x0x<<xxxxxxxx1010x0x1xxxx", InstName.Vpmin, InstEmit32.Vpmin_I, OpCode32SimdReg.Create);
SetA32("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, OpCode32SimdReg.Create);
SetA32("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create);
SetA32("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create);
SetA32("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create);
SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, OpCode32SimdSqrte.Create);
SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, OpCode32SimdReg.Create);
SetA32("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, OpCode32SimdRev.Create);
SetA32("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create);
SetA32("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create);
SetA32("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create);
SetA32("1111001x1x>>>xxxxxxx0010>xx1xxxx", InstName.Vrshr, InstEmit32.Vrshr, OpCode32SimdShImm.Create);
SetA32("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, OpCode32SimdSqrte.Create);
SetA32("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, OpCode32SimdReg.Create);
SetA32("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create);
SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create);
SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create);
SetA32("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create); // A1 encoding.
SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create);
SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create);
SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create);
SetA32("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create);
SetA32("111101001x00xxxxxxxx<<00xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create);
SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 1.
SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 2.
SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 3.
SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 4.
SetA32("111101001x00xxxxxxxx<<01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create);
SetA32("111101000x00xxxxxxxx100xxxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype).
SetA32("111101000x00xxxxxxxx0011xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2.
SetA32("111101001x00xxxxxxxx<<10xxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create);
SetA32("111101000x00xxxxxxxx010xxxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("111101001x00xxxxxxxx<<11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create);
SetA32("111101000x00xxxxxxxx000xxxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11010x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x00xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, OpCode32SimdMemImm.Create);
SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, OpCode32SimdReg.Create);
SetA32("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, OpCode32SimdRegS.Create);
SetA32("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx0011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create);
SetA32("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create);
SetA32("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create);
SetA32("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create);
SetA32("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create);
SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create);
#endregion
#region "OpCode Table (AArch32, T16)"
@ -1065,14 +1070,19 @@ namespace ARMeilleure.Decoders
SetT32("11110x011011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluImm.Create);
SetT32("11101010100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluRsImm.Create);
SetT32("11110x00100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluImm.Create);
SetT32("111010001101xxxxxxxx111111101111", InstName.Ldaex, InstEmit32.Ldaex, OpCodeT32MemLdEx.Create);
SetT32("1110100010x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT32MemMult.Create);
SetT32("1110100100x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT32MemMult.Create);
SetT32("111110000101xxxx<<<<10x1xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
SetT32("111110000101xxxx<<<<1100xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
SetT32("111110000101xxxx<<<<11x1xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
SetT32("111110001101xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm12.Create);
SetT32("111110000101<<<<xxxx000000xxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemRsImm.Create);
SetT32("111110000001xxxx<<<<10x1xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
SetT32("111110000001xxxx<<<<1100xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
SetT32("111110000001xxxx<<<<11x1xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
SetT32("111110001001xxxxxxxxxxxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm12.Create);
SetT32("1110100>x1>1<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd, InstEmit32.Ldrd, OpCodeT32MemImm8D.Create);
SetT32("111110000011xxxx<<<<10x1xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
SetT32("111110000011xxxx<<<<1100xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
SetT32("111110000011xxxx<<<<11x1xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
@ -1097,10 +1107,15 @@ namespace ARMeilleure.Decoders
SetT32("11110x01110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluImm.Create);
SetT32("11101011011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluRsImm.Create);
SetT32("11110x01011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluImm.Create);
SetT32("111010001100xxxxxxxx11111110xxxx", InstName.Stlex, InstEmit32.Stlex, OpCodeT32MemStEx.Create);
SetT32("1110100010x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT32MemMult.Create);
SetT32("1110100100x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT32MemMult.Create);
SetT32("111110000100xxxxxxxx1<<>xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create);
SetT32("111110001100xxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm12.Create);
SetT32("111110000100<<<<xxxx000000xxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemRsImm.Create);
SetT32("111110000000xxxxxxxx1<<>xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create);
SetT32("111110001000xxxxxxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm12.Create);
SetT32("1110100>x1>0<<<<xxxxxxxxxxxxxxxx", InstName.Strd, InstEmit32.Strd, OpCodeT32MemImm8D.Create);
SetT32("111110000010xxxxxxxx1<<>xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create);
SetT32("111110001010xxxxxxxxxxxxxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm12.Create);
SetT32("11101011101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluRsImm.Create);

View File

@ -1,7 +1,5 @@
using ARMeilleure.Decoders;
using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitFlowHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions

View File

@ -88,7 +88,7 @@ namespace ARMeilleure.Instructions
{
OpCodeT16BImmCmp op = (OpCodeT16BImmCmp)context.CurrOp;
Operand value = GetIntOrZR(context, op.Rn);
Operand value = GetIntA32(context, op.Rn);
Operand lblTarget = context.GetLabel((ulong)op.Immediate);
if (onNotZero)

View File

@ -547,7 +547,7 @@ namespace ARMeilleure.Instructions
{
switch (context.CurrOp)
{
case OpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
case IOpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
case IOpCode32MemReg op: return GetIntA32(context, op.Rm);
@ -564,7 +564,7 @@ namespace ARMeilleure.Instructions
return new InvalidOperationException($"Invalid OpCode type \"{opCode?.GetType().Name ?? "null"}\".");
}
public static Operand GetMShiftedByImmediate(ArmEmitterContext context, OpCode32MemRsImm op, bool setCarry)
public static Operand GetMShiftedByImmediate(ArmEmitterContext context, IOpCode32MemRsImm op, bool setCarry)
{
Operand m = GetIntA32(context, op.Rm);

View File

@ -2,8 +2,6 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitFlowHelper;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper;

View File

@ -100,7 +100,7 @@ namespace ARMeilleure.Instructions
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)), d, n, m);
Operand res = InstEmitSimdHashHelper.EmitSha256h(context, d, n, m, part2: false);
context.Copy(GetVec(op.Rd), res);
}
@ -113,7 +113,7 @@ namespace ARMeilleure.Instructions
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)), d, n, m);
Operand res = InstEmitSimdHashHelper.EmitSha256h(context, n, d, m, part2: true);
context.Copy(GetVec(op.Rd), res);
}
@ -125,7 +125,7 @@ namespace ARMeilleure.Instructions
Operand d = GetVec(op.Rd);
Operand n = GetVec(op.Rn);
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)), d, n);
Operand res = InstEmitSimdHashHelper.EmitSha256su0(context, d, n);
context.Copy(GetVec(op.Rd), res);
}
@ -138,7 +138,7 @@ namespace ARMeilleure.Instructions
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)), d, n, m);
Operand res = InstEmitSimdHashHelper.EmitSha256su1(context, d, n, m);
context.Copy(GetVec(op.Rd), res);
}

View File

@ -0,0 +1,64 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitHelper;
namespace ARMeilleure.Instructions
{
static partial class InstEmit32
{
#region "Sha256"
public static void Sha256h_V(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
Operand d = GetVecA32(op.Qd);
Operand n = GetVecA32(op.Qn);
Operand m = GetVecA32(op.Qm);
Operand res = InstEmitSimdHashHelper.EmitSha256h(context, d, n, m, part2: false);
context.Copy(GetVecA32(op.Qd), res);
}
public static void Sha256h2_V(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
Operand d = GetVecA32(op.Qd);
Operand n = GetVecA32(op.Qn);
Operand m = GetVecA32(op.Qm);
Operand res = InstEmitSimdHashHelper.EmitSha256h(context, n, d, m, part2: true);
context.Copy(GetVecA32(op.Qd), res);
}
public static void Sha256su0_V(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
Operand d = GetVecA32(op.Qd);
Operand m = GetVecA32(op.Qm);
Operand res = InstEmitSimdHashHelper.EmitSha256su0(context, d, m);
context.Copy(GetVecA32(op.Qd), res);
}
public static void Sha256su1_V(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
Operand d = GetVecA32(op.Qd);
Operand n = GetVecA32(op.Qn);
Operand m = GetVecA32(op.Qm);
Operand res = InstEmitSimdHashHelper.EmitSha256su1(context, d, n, m);
context.Copy(GetVecA32(op.Qd), res);
}
#endregion
}
}

View File

@ -0,0 +1,56 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions
{
static class InstEmitSimdHashHelper
{
public static Operand EmitSha256h(ArmEmitterContext context, Operand x, Operand y, Operand w, bool part2)
{
if (Optimizations.UseSha)
{
Operand src1 = context.AddIntrinsic(Intrinsic.X86Shufps, y, x, Const(0xbb));
Operand src2 = context.AddIntrinsic(Intrinsic.X86Shufps, y, x, Const(0x11));
Operand w2 = context.AddIntrinsic(Intrinsic.X86Punpckhqdq, w, w);
Operand round2 = context.AddIntrinsic(Intrinsic.X86Sha256Rnds2, src1, src2, w);
Operand round4 = context.AddIntrinsic(Intrinsic.X86Sha256Rnds2, src2, round2, w2);
Operand res = context.AddIntrinsic(Intrinsic.X86Shufps, round4, round2, Const(part2 ? 0x11 : 0xbb));
return res;
}
String method = part2 ? nameof(SoftFallback.HashUpper) : nameof(SoftFallback.HashLower);
return context.Call(typeof(SoftFallback).GetMethod(method), x, y, w);
}
public static Operand EmitSha256su0(ArmEmitterContext context, Operand x, Operand y)
{
if (Optimizations.UseSha)
{
return context.AddIntrinsic(Intrinsic.X86Sha256Msg1, x, y);
}
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)), x, y);
}
public static Operand EmitSha256su1(ArmEmitterContext context, Operand x, Operand y, Operand z)
{
if (Optimizations.UseSha && Optimizations.UseSsse3)
{
Operand extr = context.AddIntrinsic(Intrinsic.X86Palignr, z, y, Const(4));
Operand tmp = context.AddIntrinsic(Intrinsic.X86Paddd, extr, x);
Operand res = context.AddIntrinsic(Intrinsic.X86Sha256Msg2, tmp, z);
return res;
}
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)), x, y, z);
}
}
}

View File

@ -169,6 +169,31 @@ namespace ARMeilleure.Instructions
SetIntA32(context, op.CRn, context.ConvertI64ToI32(context.ShiftRightUI(result, Const(32))));
}
public static void Mrs(ArmEmitterContext context)
{
OpCode32Mrs op = (OpCode32Mrs)context.CurrOp;
if (op.R)
{
throw new NotImplementedException("SPSR");
}
else
{
Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
Operand qSh = context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag));
Operand spsr = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
spsr = context.BitwiseOr(spsr, qSh);
// TODO: Remaining flags.
SetIntA32(context, op.Rd, spsr);
}
}
public static void Msr(ArmEmitterContext context)
{
OpCode32MsrReg op = (OpCode32MsrReg)context.CurrOp;

View File

@ -2,8 +2,6 @@ using ARMeilleure.Memory;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{

View File

@ -1129,7 +1129,7 @@ namespace ARMeilleure.Instructions
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
}
public static V128 HashUpper(V128 hash_efgh, V128 hash_abcd, V128 wk)
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
}

View File

@ -71,6 +71,7 @@ namespace ARMeilleure.IntermediateRepresentation
X86Paddd,
X86Paddq,
X86Paddw,
X86Palignr,
X86Pand,
X86Pandn,
X86Pavgb,
@ -140,6 +141,9 @@ namespace ARMeilleure.IntermediateRepresentation
X86Roundss,
X86Rsqrtps,
X86Rsqrtss,
X86Sha256Msg1,
X86Sha256Msg2,
X86Sha256Rnds2,
X86Shufpd,
X86Shufps,
X86Sqrtpd,

View File

@ -21,6 +21,7 @@ namespace ARMeilleure
public static bool UseFmaIfAvailable { get; set; } = true;
public static bool UseAesniIfAvailable { get; set; } = true;
public static bool UsePclmulqdqIfAvailable { get; set; } = true;
public static bool UseShaIfAvailable { get; set; } = true;
public static bool ForceLegacySse
{
@ -40,5 +41,6 @@ namespace ARMeilleure
internal static bool UseFma => UseFmaIfAvailable && HardwareCapabilities.SupportsFma;
internal static bool UseAesni => UseAesniIfAvailable && HardwareCapabilities.SupportsAesni;
internal static bool UsePclmulqdq => UsePclmulqdqIfAvailable && HardwareCapabilities.SupportsPclmulqdq;
internal static bool UseSha => UseShaIfAvailable && HardwareCapabilities.SupportsSha;
}
}

View File

@ -1,5 +1,4 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace ARMeilleure.Signal

View File

@ -14,7 +14,7 @@ namespace ARMeilleure.Translation
public BasicBlock Entry { get; }
public IntrusiveList<BasicBlock> Blocks { get; }
public BasicBlock[] PostOrderBlocks => _postOrderBlocks;
public int[] PostOrderMap => _postOrderMap;
public int[] PostOrderMap => _postOrderMap;
public ControlFlowGraph(BasicBlock entry, IntrusiveList<BasicBlock> blocks, int localsCount)
{

View File

@ -344,7 +344,7 @@ namespace ARMeilleure.Translation
}
/// <summary>
/// Removes the value from the dictionary after searching for it with <paramref name="key">.
/// Removes the value from the dictionary after searching for it with <paramref name="key"/>.
/// </summary>
/// <param name="key">Key to search for</param>
/// <returns>Number of deleted values</returns>

View File

@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 3439; //! To be incremented manually for each change to the ARMeilleure project.
private const uint InternalVersion = 3585; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";
@ -946,9 +946,12 @@ namespace ARMeilleure.Translation.PTC
return BitConverter.IsLittleEndian;
}
private static ulong GetFeatureInfo()
private static FeatureInfo GetFeatureInfo()
{
return (ulong)HardwareCapabilities.FeatureInfoEdx << 32 | (uint)HardwareCapabilities.FeatureInfoEcx;
return new FeatureInfo(
(uint)HardwareCapabilities.FeatureInfo1Ecx,
(uint)HardwareCapabilities.FeatureInfo1Edx,
(uint)HardwareCapabilities.FeatureInfo7Ebx);
}
private static byte GetMemoryManagerMode()
@ -968,7 +971,7 @@ namespace ARMeilleure.Translation.PTC
return osPlatform;
}
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 50*/)]
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 54*/)]
private struct OuterHeader
{
public ulong Magic;
@ -976,7 +979,7 @@ namespace ARMeilleure.Translation.PTC
public uint CacheFileVersion;
public bool Endianness;
public ulong FeatureInfo;
public FeatureInfo FeatureInfo;
public byte MemoryManagerMode;
public uint OSPlatform;
@ -999,6 +1002,9 @@ namespace ARMeilleure.Translation.PTC
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 12*/)]
private record struct FeatureInfo(uint FeatureInfo0, uint FeatureInfo1, uint FeatureInfo2);
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 128*/)]
private struct InnerHeader
{

View File

@ -4,7 +4,6 @@ using Ryujinx.Memory;
using Ryujinx.SDL2.Common;
using System;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Threading;
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;

View File

@ -4,7 +4,6 @@ using Ryujinx.Common.Logging;
using Ryujinx.Memory;
using System;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Threading;
using static SDL2.SDL;

View File

@ -1,5 +1,4 @@
using System;
namespace SoundIOSharp
namespace SoundIOSharp
{
public struct SoundIOSampleRateRange
{

View File

@ -1,7 +1,6 @@
using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter;
using System;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command
{

View File

@ -1,5 +1,4 @@
using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Memory;
using System;
using System.Runtime.CompilerServices;

View File

@ -1,6 +1,5 @@
using Ryujinx.Audio.Renderer.Parameter.Sink;
using Ryujinx.Audio.Renderer.Server.MemoryPool;
using System;
using System.Diagnostics;
namespace Ryujinx.Audio.Renderer.Dsp.Command

View File

@ -6,7 +6,6 @@ using Ryujinx.Memory;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command

View File

@ -1,5 +1,3 @@
using System;
namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public class CopyMixBufferCommand : ICommand

View File

@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command

View File

@ -2,7 +2,6 @@ using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter.Effect;
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command
{

View File

@ -3,7 +3,6 @@ using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Parameter.Effect;
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command

View File

@ -1,6 +1,5 @@
using Ryujinx.Audio.Renderer.Server.Upsampler;
using System;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command
{

View File

@ -76,7 +76,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion))
{
voiceState.Pitch.ToSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer);
voiceState.Pitch.AsSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer);
tempBufferIndex += pitchMaxLength;
}
@ -239,7 +239,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
ResamplerHelper.Resample(outputBuffer, tempBuffer, sampleRateRatio, ref fraction, sampleCountToProcess, info.SrcQuality, y != sourceSampleCountToProcess || info.Pitch != 1.0f);
tempBuffer.Slice(sampleCountToDecode, pitchMaxLength).CopyTo(voiceState.Pitch.ToSpan());
tempBuffer.Slice(sampleCountToDecode, pitchMaxLength).CopyTo(voiceState.Pitch.AsSpan());
}
i += sampleCountToProcess;

View File

@ -24,8 +24,8 @@ namespace Ryujinx.Audio.Renderer.Parameter.Effect
/// </summary>
public void Reset()
{
InputMax.ToSpan().Fill(0.0f);
CompressionGainMin.ToSpan().Fill(1.0f);
InputMax.AsSpan().Fill(0.0f);
CompressionGainMin.AsSpan().Fill(1.0f);
}
}
}

View File

@ -7,7 +7,6 @@ using Ryujinx.Audio.Renderer.Server.Performance;
using Ryujinx.Audio.Renderer.Server.Sink;
using Ryujinx.Audio.Renderer.Server.Upsampler;
using Ryujinx.Audio.Renderer.Server.Voice;
using Ryujinx.Common.Memory;
using System;
using CpuAddress = System.UInt64;

View File

@ -141,7 +141,7 @@ namespace Ryujinx.Audio.Renderer.Server
Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state).Slice(VoiceUpdateState.BiquadStateOffset, VoiceUpdateState.BiquadStateSize * Constants.VoiceBiquadFilterCount);
Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory);
_commandBuffer.GenerateGroupedBiquadFilter(baseIndex, voiceState.BiquadFilters.ToSpan(), stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId);
_commandBuffer.GenerateGroupedBiquadFilter(baseIndex, voiceState.BiquadFilters.AsSpan(), stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId);
}
else
{
@ -337,8 +337,8 @@ namespace Ryujinx.Audio.Renderer.Server
GeneratePerformance(ref performanceEntry, PerformanceCommand.Type.Start, nodeId);
}
GenerateVoiceMix(channelResource.Mix.ToSpan(),
channelResource.PreviousMix.ToSpan(),
GenerateVoiceMix(channelResource.Mix.AsSpan(),
channelResource.PreviousMix.AsSpan(),
dspStateMemory,
mix.BufferOffset,
mix.BufferCount,
@ -505,8 +505,8 @@ namespace Ryujinx.Audio.Renderer.Server
BiquadFilterParameter parameter = new BiquadFilterParameter();
parameter.Enable = true;
effect.Parameter.Denominator.ToSpan().CopyTo(parameter.Denominator.ToSpan());
effect.Parameter.Numerator.ToSpan().CopyTo(parameter.Numerator.ToSpan());
effect.Parameter.Denominator.AsSpan().CopyTo(parameter.Denominator.AsSpan());
effect.Parameter.Numerator.AsSpan().CopyTo(parameter.Numerator.AsSpan());
for (int i = 0; i < effect.Parameter.ChannelCount; i++)
{
@ -923,8 +923,8 @@ namespace Ryujinx.Audio.Renderer.Server
if (useCustomDownMixingCommand)
{
_commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset,
sink.Parameter.Input.ToSpan(),
sink.Parameter.Input.ToSpan(),
sink.Parameter.Input.AsSpan(),
sink.Parameter.Input.AsSpan(),
sink.DownMixCoefficients,
Constants.InvalidNodeId);
}
@ -932,8 +932,8 @@ namespace Ryujinx.Audio.Renderer.Server
else if (_rendererContext.ChannelCount == 2 && sink.Parameter.InputCount == 6)
{
_commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset,
sink.Parameter.Input.ToSpan(),
sink.Parameter.Input.ToSpan(),
sink.Parameter.Input.AsSpan(),
sink.Parameter.Input.AsSpan(),
Constants.DefaultSurroundToStereoCoefficients,
Constants.InvalidNodeId);
}
@ -945,7 +945,7 @@ namespace Ryujinx.Audio.Renderer.Server
_commandBuffer.GenerateUpsample(finalMix.BufferOffset,
sink.UpsamplerState,
sink.Parameter.InputCount,
sink.Parameter.Input.ToSpan(),
sink.Parameter.Input.AsSpan(),
commandList.BufferCount,
commandList.SampleCount,
commandList.SampleRate,

View File

@ -1,9 +1,5 @@
using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Dsp.Command;
using Ryujinx.Audio.Renderer.Parameter.Effect;
using System;
using System.Diagnostics;
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter;
namespace Ryujinx.Audio.Renderer.Server
{

View File

@ -63,10 +63,10 @@ namespace Ryujinx.Audio.Renderer.Server.Sink
else
{
Parameter.DownMixParameterEnabled = inputDeviceParameter.DownMixParameterEnabled;
inputDeviceParameter.DownMixParameter.ToSpan().CopyTo(Parameter.DownMixParameter.ToSpan());
inputDeviceParameter.DownMixParameter.AsSpan().CopyTo(Parameter.DownMixParameter.AsSpan());
}
Parameter.DownMixParameter.ToSpan().CopyTo(DownMixCoefficients.AsSpan());
Parameter.DownMixParameter.AsSpan().CopyTo(DownMixCoefficients.AsSpan());
errorInfo = new BehaviourParameter.ErrorInfo();
outStatus = new SinkOutStatus();

View File

@ -119,7 +119,7 @@ namespace Ryujinx.Audio.Renderer.Server
ref VoiceChannelResource resource = ref context.GetChannelResource(i);
resource.Id = parameter.Id;
parameter.Mix.ToSpan().CopyTo(resource.Mix.ToSpan());
parameter.Mix.AsSpan().CopyTo(resource.Mix.AsSpan());
resource.IsUsed = parameter.IsUsed;
}
@ -587,7 +587,7 @@ namespace Ryujinx.Audio.Renderer.Server
{
ref BehaviourErrorInfoOutStatus outStatus = ref SpanIOHelper.GetWriteRef<BehaviourErrorInfoOutStatus>(ref _output)[0];
_behaviourContext.CopyErrorInfo(outStatus.ErrorInfos.ToSpan(), out outStatus.ErrorInfosCount);
_behaviourContext.CopyErrorInfo(outStatus.ErrorInfos.AsSpan(), out outStatus.ErrorInfosCount);
OutputHeader.BehaviourSize = (uint)Unsafe.SizeOf<BehaviourErrorInfoOutStatus>();
OutputHeader.TotalSize += OutputHeader.BehaviourSize;

View File

@ -34,7 +34,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
public void UpdateState()
{
Mix.ToSpan().CopyTo(PreviousMix.ToSpan());
Mix.AsSpan().CopyTo(PreviousMix.AsSpan());
}
}
}

View File

@ -202,7 +202,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
Pitch = 0.0f;
Volume = 0.0f;
PreviousVolume = 0.0f;
BiquadFilters.ToSpan().Fill(new BiquadFilterParameter());
BiquadFilters.AsSpan().Fill(new BiquadFilterParameter());
WaveBuffersCount = 0;
WaveBuffersIndex = 0;
MixId = Constants.UnusedMixId;
@ -288,7 +288,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
ChannelsCount = parameter.ChannelCount;
Pitch = parameter.Pitch;
Volume = parameter.Volume;
parameter.BiquadFilters.ToSpan().CopyTo(BiquadFilters.ToSpan());
parameter.BiquadFilters.AsSpan().CopyTo(BiquadFilters.AsSpan());
WaveBuffersCount = parameter.WaveBuffersCount;
WaveBuffersIndex = parameter.WaveBuffersIndex;
@ -308,7 +308,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
SplitterId = Constants.UnusedSplitterId;
}
parameter.ChannelResourceIds.ToSpan().CopyTo(ChannelResourceIds.ToSpan());
parameter.ChannelResourceIds.AsSpan().CopyTo(ChannelResourceIds.AsSpan());
DecodingBehaviour behaviour = DecodingBehaviour.Default;
@ -638,7 +638,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
voiceUpdateState.Offset = 0;
voiceUpdateState.PlayedSampleCount = 0;
voiceUpdateState.Pitch.ToSpan().Fill(0);
voiceUpdateState.Pitch.AsSpan().Fill(0);
voiceUpdateState.Fraction = 0;
voiceUpdateState.LoopContext = new Dsp.State.AdpcmLoopContext();
}
@ -650,7 +650,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
case Types.PlayState.Stopped:
case Types.PlayState.Paused:
foreach (ref WaveBuffer wavebuffer in WaveBuffers.ToSpan())
foreach (ref WaveBuffer wavebuffer in WaveBuffers.AsSpan())
{
wavebuffer.BufferAddressInfo.GetReference(true);
wavebuffer.ContextAddressInfo.GetReference(true);

View File

@ -12,6 +12,7 @@ using Ryujinx.Audio.Integration;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Backend.Vulkan;
using Ryujinx.Ava.Ui.Controls;
using Ryujinx.Ava.Ui.Models;
using Ryujinx.Ava.Ui.Vulkan;
@ -334,6 +335,8 @@ namespace Ryujinx.Ava
return;
}
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface.Display.ChangeVSyncMode(true);
_isStopped = true;
_isActive = false;
}
@ -596,12 +599,13 @@ namespace Ryujinx.Ava
if (Program.UseVulkan)
{
var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
renderer = new VulkanRenderer(vulkan.Instance.InternalHandle,
vulkan.Device.InternalHandle,
vulkan.MainSurface.Device.InternalHandle,
vulkan.PhysicalDevice.InternalHandle,
vulkan.Device.Queue.InternalHandle,
vulkan.MainSurface.Device.Queue.InternalHandle,
vulkan.PhysicalDevice.QueueFamilyIndex,
vulkan.Device.Lock);
vulkan.MainSurface.Device.Lock);
}
else
{
@ -775,7 +779,10 @@ namespace Ryujinx.Ava
Width = (int)e.Width;
Height = (int)e.Height;
SetRendererWindowSize(e);
if (!Program.UseVulkan)
{
SetRendererWindowSize(e);
}
}
private void MainLoop()
@ -815,12 +822,11 @@ namespace Ryujinx.Ava
_renderer.ScreenCaptured += Renderer_ScreenCaptured;
if (!Program.UseVulkan)
{
(_renderer as OpenGLRenderer).InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext((Renderer as OpenGLRendererControl).GameContext));
(_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext((Renderer as OpenGLRendererControl).GameContext));
Renderer.MakeCurrent();
}
Renderer.MakeCurrent();
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
Device.Gpu.Renderer.Initialize(_glLogLevel);
@ -837,8 +843,6 @@ namespace Ryujinx.Ava
Renderer.Start();
Renderer.QueueRender();
while (_isActive)
{
if (Device.WaitFifo())
@ -889,6 +893,16 @@ namespace Ryujinx.Ava
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}"));
if (Program.UseVulkan)
{
var platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
if (platformInterface.MainSurface.Display.IsSurfaceChanged())
{
SetRendererWindowSize(new Size(Width, Height));
return;
}
}
Renderer.Present(image);
}
@ -970,6 +984,9 @@ namespace Ryujinx.Ava
{
case KeyboardHotkeyState.ToggleVSync:
Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
break;
case KeyboardHotkeyState.Screenshot:
ScreenshotRequested = true;

View File

@ -52,8 +52,8 @@
"GameListContextMenuOpenModsDirectory": "Open Mods Directory",
"GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods",
"GameListContextMenuCacheManagement": "Cache Management",
"GameListContextMenuCacheManagementPurgePptc": "Purge PPTC Cache",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Deletes Application's PPTC cache",
"GameListContextMenuCacheManagementPurgePptc": "Queue PPTC Rebuild",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Trigger PPTC to rebuild at boot time on the next game launch",
"GameListContextMenuCacheManagementPurgeShaderCache": "Purge Shader Cache",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Deletes Application's shader cache",
"GameListContextMenuCacheManagementOpenPptcDirectory": "Open PPTC Directory",
@ -350,7 +350,7 @@
"DialogProfileDeleteProfileTitle": "Deleting Profile",
"DialogProfileDeleteProfileMessage": "This action is irreversible, are you sure you want to continue?",
"DialogWarning": "Warning",
"DialogPPTCDeletionMessage": "You are about to delete the PPTC cache for :\n\n{0}\n\nAre you sure you want to proceed?",
"DialogPPTCDeletionMessage": "You are about to queue a PPTC rebuild on the next boot of:\n\n{0}\n\nAre you sure you want to proceed?",
"DialogPPTCDeletionErrorMessage": "Error purging PPTC cache at {0}: {1}",
"DialogShaderDeletionMessage": "You are about to delete the Shader cache for :\n\n{0}\n\nAre you sure you want to proceed?",
"DialogShaderDeletionErrorMessage": "Error purging Shader cache at {0}: {1}",

View File

@ -0,0 +1,581 @@
{
"MenuBarFileOpenApplet": "アプレットを開く",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます",
"SettingsTabInputDirectMouseAccess": "マウス直接アクセス",
"SettingsTabSystemMemoryManagerMode": "メモリ管理モード:",
"SettingsTabSystemMemoryManagerModeSoftware": "ソフトウェア",
"SettingsTabSystemMemoryManagerModeHost": "ホスト (高速)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "ホスト, チェックなし (最高速, 安全でない)",
"MenuBarFile": "ファイル(_F)",
"MenuBarFileOpenFromFile": "ファイルからアプリケーションをロード(_L)",
"MenuBarFileOpenUnpacked": "展開されたゲームをロード",
"MenuBarFileOpenEmuFolder": "Ryujinx フォルダを開く",
"MenuBarFileOpenLogsFolder": "ログフォルダを開く",
"MenuBarFileExit": "終了(_E)",
"MenuBarOptions": "オプション",
"MenuBarOptionsToggleFullscreen": "全画面切り替え",
"MenuBarOptionsStartGamesInFullscreen": "全画面モードでゲームを開始",
"MenuBarOptionsStopEmulation": "エミュレーションを停止",
"MenuBarOptionsSettings": "設定(_S)",
"MenuBarOptionsManageUserProfiles": "ユーザプロファイルを管理(_M)",
"MenuBarActions": "アクション(_A)",
"MenuBarOptionsSimulateWakeUpMessage": "スリープ復帰メッセージをシミュレート",
"MenuBarActionsScanAmiibo": "Amiibo をスキャン",
"MenuBarTools": "ツール(_T)",
"MenuBarToolsInstallFirmware": "ファームウェアをインストール",
"MenuBarFileToolsInstallFirmwareFromFile": "XCI または ZIP からファームウェアをインストール",
"MenuBarFileToolsInstallFirmwareFromDirectory": "ディレクトリからファームウェアをインストール",
"MenuBarHelp": "ヘルプ",
"MenuBarHelpCheckForUpdates": "アップデートを確認",
"MenuBarHelpAbout": "Ryujinx について",
"MenuSearch": "検索...",
"GameListHeaderFavorite": "お気に入り",
"GameListHeaderIcon": "アイコン",
"GameListHeaderApplication": "名称",
"GameListHeaderDeveloper": "開発元",
"GameListHeaderVersion": "バージョン",
"GameListHeaderTimePlayed": "プレイ時間",
"GameListHeaderLastPlayed": "最終プレイ日時",
"GameListHeaderFileExtension": "ファイル拡張子",
"GameListHeaderFileSize": "ファイルサイズ",
"GameListHeaderPath": "パス",
"GameListContextMenuOpenUserSaveDirectory": "セーブディレクトリを開く",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "アプリケーションのユーザセーブデータを格納するディレクトリを開きます",
"GameListContextMenuOpenUserDeviceDirectory": "デバイスディレクトリを開く",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "アプリケーションのデバイスセーブデータを格納するディレクトリを開きます",
"GameListContextMenuOpenUserBcatDirectory": "BCATディレクトリを開く",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "アプリケーションの BCAT セーブデータを格納するディレクトリを開きます",
"GameListContextMenuManageTitleUpdates": "アップデートを管理",
"GameListContextMenuManageTitleUpdatesToolTip": "タイトルのアップデート管理ウインドウを開きます",
"GameListContextMenuManageDlc": "DLCを管理",
"GameListContextMenuManageDlcToolTip": "DLC管理ウインドウを開きます",
"GameListContextMenuOpenModsDirectory": "Modディレクトリを開く",
"GameListContextMenuOpenModsDirectoryToolTip": "アプリケーションの Mod データを格納するディレクトリを開きます",
"GameListContextMenuCacheManagement": "キャッシュ管理",
"GameListContextMenuCacheManagementPurgePptc": "PPTC キャッシュを破棄",
"GameListContextMenuCacheManagementPurgePptcToolTip": "アプリケーションの PPTC キャッシュを破棄します",
"GameListContextMenuCacheManagementPurgeShaderCache": "シェーダキャッシュを破棄",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "アプリケーションのシェーダキャッシュを破棄します",
"GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC ディレクトリを開く",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "アプリケーションの PPTC キャッシュを格納するディレクトリを開きます",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "シェーダキャッシュディレクトリを開く",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "アプリケーションのシェーダキャッシュを格納するディレクトリを開きます",
"GameListContextMenuExtractData": "データを展開",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "現在のアプリケーション設定(アップデート含む)から ExeFS セクションを展開します",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "現在のアプリケーション設定(アップデート含む)から RomFS セクションを展開します",
"GameListContextMenuExtractDataLogo": "ロゴ",
"GameListContextMenuExtractDataLogoToolTip": "現在のアプリケーション設定(アップデート含む)からロゴセクションを展開します",
"StatusBarGamesLoaded": "{0}/{1} ゲーム",
"StatusBarSystemVersion": "システムバージョン: {0}",
"Settings": "設定",
"SettingsTabGeneral": "ユーザインタフェース",
"SettingsTabGeneralGeneral": "一般",
"SettingsTabGeneralEnableDiscordRichPresence": "Discord リッチプレゼンスを有効",
"SettingsTabGeneralCheckUpdatesOnLaunch": "起動時にアップデートを確認",
"SettingsTabGeneralShowConfirmExitDialog": "\"終了を確認\" ダイアログを表示",
"SettingsTabGeneralHideCursorOnIdle": "アイドル時にカーソルを隠す",
"SettingsTabGeneralGameDirectories": "ゲームディレクトリ",
"SettingsTabGeneralAdd": "追加",
"SettingsTabGeneralRemove": "削除",
"SettingsTabSystem": "システム",
"SettingsTabSystemCore": "コア",
"SettingsTabSystemSystemRegion": "地域:",
"SettingsTabSystemSystemRegionJapan": "日本",
"SettingsTabSystemSystemRegionUSA": "アメリカ",
"SettingsTabSystemSystemRegionEurope": "ヨーロッパ",
"SettingsTabSystemSystemRegionAustralia": "オーストラリア",
"SettingsTabSystemSystemRegionChina": "中国",
"SettingsTabSystemSystemRegionKorea": "韓国",
"SettingsTabSystemSystemRegionTaiwan": "台湾",
"SettingsTabSystemSystemLanguage": "言語:",
"SettingsTabSystemSystemLanguageJapanese": "日本語",
"SettingsTabSystemSystemLanguageAmericanEnglish": "英語(アメリカ)",
"SettingsTabSystemSystemLanguageFrench": "フランス語",
"SettingsTabSystemSystemLanguageGerman": "ドイツ語",
"SettingsTabSystemSystemLanguageItalian": "イタリア語",
"SettingsTabSystemSystemLanguageSpanish": "スペイン語",
"SettingsTabSystemSystemLanguageChinese": "中国語",
"SettingsTabSystemSystemLanguageKorean": "韓国語",
"SettingsTabSystemSystemLanguageDutch": "オランダ語",
"SettingsTabSystemSystemLanguagePortuguese": "ポルトガル語",
"SettingsTabSystemSystemLanguageRussian": "ロシア語",
"SettingsTabSystemSystemLanguageTaiwanese": "台湾語",
"SettingsTabSystemSystemLanguageBritishEnglish": "英語(イギリス)",
"SettingsTabSystemSystemLanguageCanadianFrench": "フランス語(カナダ)",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "スペイン語(ラテンアメリカ)",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "中国語",
"SettingsTabSystemSystemLanguageTraditionalChinese": "台湾語",
"SettingsTabSystemSystemTimeZone": "タイムゾーン:",
"SettingsTabSystemSystemTime": "時刻:",
"SettingsTabSystemEnableVsync": "VSync",
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableFsIntegrityChecks": "ファイルシステム整合性チェック",
"SettingsTabSystemAudioBackend": "音声バックエンド:",
"SettingsTabSystemAudioBackendDummy": "ダミー",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "ハック",
"SettingsTabSystemHacksNote": " (挙動が不安定になる可能性があります)",
"SettingsTabSystemExpandDramSize": "DRAMサイズを6GBに拡大",
"SettingsTabSystemIgnoreMissingServices": "未実装サービスを無視",
"SettingsTabGraphics": "グラフィクス",
"SettingsTabGraphicsEnhancements": "拡張",
"SettingsTabGraphicsEnableShaderCache": "シェーダキャッシュ",
"SettingsTabGraphicsAnisotropicFiltering": "異方性フィルタリング:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "自動",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
"SettingsTabGraphicsResolutionScale": "解像度:",
"SettingsTabGraphicsResolutionScaleCustom": "カスタム (非推奨)",
"SettingsTabGraphicsResolutionScaleNative": "ネイティブ (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "アスペクト比:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "ウインドウサイズに合わせる",
"SettingsTabGraphicsDeveloperOptions": "開発者向けオプション",
"SettingsTabGraphicsShaderDumpPath": "グラフィクス シェーダダンプパス:",
"SettingsTabLogging": "ロギング",
"SettingsTabLoggingLogging": "ロギング",
"SettingsTabLoggingEnableLoggingToFile": "ファイルへのロギングを有効",
"SettingsTabLoggingEnableStubLogs": "Stub ログを有効",
"SettingsTabLoggingEnableInfoLogs": "Info ログを有効",
"SettingsTabLoggingEnableWarningLogs": "Warning ログを有効",
"SettingsTabLoggingEnableErrorLogs": "Error ログを有効",
"SettingsTabLoggingEnableTraceLogs": "Trace ログを有効",
"SettingsTabLoggingEnableGuestLogs": "Guest ログを有効",
"SettingsTabLoggingEnableFsAccessLogs": "Fs アクセスログを有効",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs グローバルアクセスログモード:",
"SettingsTabLoggingDeveloperOptions": "開発者オプション (警告: パフォーマンスが低下します)",
"SettingsTabLoggingOpenglLogLevel": "OpenGL ログレベル:",
"SettingsTabLoggingOpenglLogLevelNone": "なし",
"SettingsTabLoggingOpenglLogLevelError": "エラー",
"SettingsTabLoggingOpenglLogLevelPerformance": "パフォーマンス低下",
"SettingsTabLoggingOpenglLogLevelAll": "すべて",
"SettingsTabLoggingEnableDebugLogs": "デバッグログを有効",
"SettingsTabInput": "入力",
"SettingsTabInputEnableDockedMode": "ドッキングモード",
"SettingsTabInputDirectKeyboardAccess": "キーボード直接アクセス",
"SettingsButtonSave": "セーブ",
"SettingsButtonClose": "閉じる",
"SettingsButtonApply": "適用",
"ControllerSettingsPlayer": "プレイヤー",
"ControllerSettingsPlayer1": "プレイヤー 1",
"ControllerSettingsPlayer2": "プレイヤー 2",
"ControllerSettingsPlayer3": "プレイヤー 3",
"ControllerSettingsPlayer4": "プレイヤー 4",
"ControllerSettingsPlayer5": "プレイヤー 5",
"ControllerSettingsPlayer6": "プレイヤー 6",
"ControllerSettingsPlayer7": "プレイヤー 7",
"ControllerSettingsPlayer8": "プレイヤー 8",
"ControllerSettingsHandheld": "携帯",
"ControllerSettingsInputDevice": "入力デバイス",
"ControllerSettingsRefresh": "更新",
"ControllerSettingsDeviceDisabled": "無効",
"ControllerSettingsControllerType": "コントローラ種別",
"ControllerSettingsControllerTypeHandheld": "携帯",
"ControllerSettingsControllerTypeProController": "Pro コントローラ",
"ControllerSettingsControllerTypeJoyConPair": "JoyCon ペア",
"ControllerSettingsControllerTypeJoyConLeft": "JoyCon 左",
"ControllerSettingsControllerTypeJoyConRight": "JoyCon 右",
"ControllerSettingsProfile": "プロファイル",
"ControllerSettingsProfileDefault": "デフォルト",
"ControllerSettingsLoad": "ロード",
"ControllerSettingsAdd": "追加",
"ControllerSettingsRemove": "削除",
"ControllerSettingsButtons": "ボタン",
"ControllerSettingsButtonA": "A",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "十字キー",
"ControllerSettingsDPadUp": "上",
"ControllerSettingsDPadDown": "下",
"ControllerSettingsDPadLeft": "左",
"ControllerSettingsDPadRight": "右",
"ControllerSettingsLStick": "左スティック",
"ControllerSettingsLStickButton": "ボタン",
"ControllerSettingsLStickUp": "上",
"ControllerSettingsLStickDown": "下",
"ControllerSettingsLStickLeft": "左",
"ControllerSettingsLStickRight": "右",
"ControllerSettingsLStickStick": "スティック",
"ControllerSettingsLStickInvertXAxis": "X軸を反転",
"ControllerSettingsLStickInvertYAxis": "Y軸を反転",
"ControllerSettingsLStickDeadzone": "遊び:",
"ControllerSettingsRStick": "右スティック",
"ControllerSettingsRStickButton": "ボタン",
"ControllerSettingsRStickUp": "上",
"ControllerSettingsRStickDown": "下",
"ControllerSettingsRStickLeft": "左",
"ControllerSettingsRStickRight": "右",
"ControllerSettingsRStickStick": "スティック",
"ControllerSettingsRStickInvertXAxis": "X軸を反転",
"ControllerSettingsRStickInvertYAxis": "Y軸を反転",
"ControllerSettingsRStickDeadzone": "遊び:",
"ControllerSettingsTriggersLeft": "左トリガー",
"ControllerSettingsTriggersRight": "右トリガー",
"ControllerSettingsTriggersButtonsLeft": "左トリガーボタン",
"ControllerSettingsTriggersButtonsRight": "右トリガーボタン",
"ControllerSettingsTriggers": "トリガー",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "左ボタン",
"ControllerSettingsExtraButtonsRight": "右ボタン",
"ControllerSettingsMisc": "その他",
"ControllerSettingsTriggerThreshold": "トリガーしきい値:",
"ControllerSettingsMotion": "モーション",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook 互換モーションを使用",
"ControllerSettingsMotionControllerSlot": "コントローラ スロット:",
"ControllerSettingsMotionMirrorInput": "入力反転",
"ControllerSettingsMotionRightJoyConSlot": "JoyCon 右 スロット:",
"ControllerSettingsMotionServerHost": "サーバ:",
"ControllerSettingsMotionGyroSensitivity": "ジャイロ感度:",
"ControllerSettingsMotionGyroDeadzone": "ジャイロ遊び:",
"ControllerSettingsSave": "セーブ",
"ControllerSettingsClose": "閉じる",
"UserProfilesSelectedUserProfile": "選択されたユーザプロファイル:",
"UserProfilesSaveProfileName": "プロファイル名をセーブ",
"UserProfilesChangeProfileImage": "プロファイル画像を変更",
"UserProfilesAvailableUserProfiles": "利用可能なユーザプロファイル:",
"UserProfilesAddNewProfile": "プロファイルを作成",
"UserProfilesDeleteSelectedProfile": "削除",
"UserProfilesClose": "閉じる",
"ProfileImageSelectionTitle": "プロファイル画像選択",
"ProfileImageSelectionHeader": "プロファイル画像を選択",
"ProfileImageSelectionNote": "カスタム画像をインポート, またはファームウェア内のアバターを選択できます",
"ProfileImageSelectionImportImage": "画像ファイルをインポート",
"ProfileImageSelectionSelectAvatar": "ファームウェア内のアバターを選択",
"InputDialogTitle": "入力ダイアログ",
"InputDialogOk": "OK",
"InputDialogCancel": "キャンセル",
"InputDialogAddNewProfileTitle": "プロファイル名を選択",
"InputDialogAddNewProfileHeader": "プロファイル名を入力してください",
"InputDialogAddNewProfileSubtext": "(最大長: {0})",
"AvatarChoose": "選択",
"AvatarSetBackgroundColor": "背景色を指定",
"AvatarClose": "閉じる",
"ControllerSettingsLoadProfileToolTip": "プロファイルをロード",
"ControllerSettingsAddProfileToolTip": "プロファイルを追加",
"ControllerSettingsRemoveProfileToolTip": "プロファイルを削除",
"ControllerSettingsSaveProfileToolTip": "プロファイルをセーブ",
"MenuBarFileToolsTakeScreenshot": "スクリーンショットを撮影",
"MenuBarFileToolsHideUi": "UIを隠す",
"GameListContextMenuToggleFavorite": "お気に入りを切り替え",
"GameListContextMenuToggleFavoriteToolTip": "ゲームをお気に入りに含めるかどうかを切り替えます",
"SettingsTabGeneralTheme": "テーマ",
"SettingsTabGeneralThemeCustomTheme": "カスタムテーマパス",
"SettingsTabGeneralThemeBaseStyle": "基本スタイル",
"SettingsTabGeneralThemeBaseStyleDark": "ダーク",
"SettingsTabGeneralThemeBaseStyleLight": "ライト",
"SettingsTabGeneralThemeEnableCustomTheme": "カスタムテーマを有効",
"ButtonBrowse": "参照",
"ControllerSettingsConfigureGeneral": "設定",
"ControllerSettingsRumble": "振動",
"ControllerSettingsRumbleStrongMultiplier": "強振動の補正値",
"ControllerSettingsRumbleWeakMultiplier": "弱振動の補正値",
"DialogMessageSaveNotAvailableMessage": "{0} [{1:x16}] のセーブデータはありません",
"DialogMessageSaveNotAvailableCreateSaveMessage": "このゲームのセーブデータを作成してよろしいですか?",
"DialogConfirmationTitle": "Ryujinx - 確認",
"DialogUpdaterTitle": "Ryujinx - アップデータ",
"DialogErrorTitle": "Ryujinx - エラー",
"DialogWarningTitle": "Ryujinx - 警告",
"DialogExitTitle": "Ryujinx - 終了",
"DialogErrorMessage": "エラーが発生しました",
"DialogExitMessage": "Ryujinx を閉じてよろしいですか?",
"DialogExitSubMessage": "セーブされていないのデータはすべて失われます!",
"DialogMessageCreateSaveErrorMessage": "セーブデータ: {0} の作成中にエラーが発生しました",
"DialogMessageFindSaveErrorMessage": "セーブデータ: {0} の検索中にエラーが発生しました",
"FolderDialogExtractTitle": "展開フォルダを選択",
"DialogNcaExtractionMessage": "{1} から {0} セクションを展開中...",
"DialogNcaExtractionTitle": "Ryujinx - NCA セクション展開",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "展開に失敗しました. 選択されたファイルにはメイン NCA が存在しません.",
"DialogNcaExtractionCheckLogErrorMessage": "展開に失敗しました. 詳細はログを確認してください.",
"DialogNcaExtractionSuccessMessage": "展開が正常終了しました",
"DialogUpdaterConvertFailedMessage": "現在の Ryujinx バージョンの変換に失敗しました.",
"DialogUpdaterCancelUpdateMessage": "アップデータをキャンセル中!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "最新バージョンの Ryujinx を使用中です!",
"DialogUpdaterFailedToGetVersionMessage": "Github からのリリース情報取得時にエラーが発生しました. Github Actions でリリースファイルを作成中かもしれません. 後ほどもう一度試してみてください.",
"DialogUpdaterConvertFailedGithubMessage": "Github から取得した Ryujinx バージョンの変換に失敗しました.",
"DialogUpdaterDownloadingMessage": "アップデートをダウンロード中...",
"DialogUpdaterExtractionMessage": "アップデートを展開中...",
"DialogUpdaterRenamingMessage": "アップデートをリネーム中...",
"DialogUpdaterAddingFilesMessage": "新規アップデートを追加中...",
"DialogUpdaterCompleteMessage": "アップデート完了!",
"DialogUpdaterRestartMessage": "すぐに Ryujinx を再起動しますか?",
"DialogUpdaterArchNotSupportedMessage": "サポート外のアーキテクチャです!",
"DialogUpdaterArchNotSupportedSubMessage": "(x64 システムのみサポートしています!)",
"DialogUpdaterNoInternetMessage": "インターネットに接続されていません!",
"DialogUpdaterNoInternetSubMessage": "インターネット接続が正常動作しているか確認してください!",
"DialogUpdaterDirtyBuildMessage": "Dirty ビルドの Ryujinx はアップデートできません!",
"DialogUpdaterDirtyBuildSubMessage": "サポートされているバージョンをお探しなら, https://ryujinx.org/ で Ryujinx をダウンロードしてください.",
"DialogRestartRequiredMessage": "再起動が必要",
"DialogThemeRestartMessage": "テーマがセーブされました. テーマを適用するには再起動が必要です.",
"DialogThemeRestartSubMessage": "再起動しますか",
"DialogFirmwareInstallEmbeddedMessage": "このゲームに含まれるファームウェアをインストールしてよろしいですか? (ファームウェア {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "ファームウェアがインストールされていませんが, ゲームに含まれるファームウェア {0} をインストールできます.\\nエミュレータが開始します.",
"DialogFirmwareNoFirmwareInstalledMessage": "ファームウェアがインストールされていません",
"DialogFirmwareInstalledMessage": "ファームウェア {0} がインストールされました",
"DialogOpenSettingsWindowLabel": "設定ウインドウを開く",
"DialogControllerAppletTitle": "コントローラアプレット",
"DialogMessageDialogErrorExceptionMessage": "メッセージダイアログ表示エラー: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "ソフトウェアキーボード表示エラー: {0}",
"DialogErrorAppletErrorExceptionMessage": "エラーアプレットダイアログ表示エラー: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nこのエラーへの対処方法については, セットアップガイドを参照してください.",
"DialogUserErrorDialogTitle": "Ryujinx エラー ({0})",
"DialogAmiiboApiTitle": "Amiibo API",
"DialogAmiiboApiFailFetchMessage": "API からの情報取得中にエラーが発生しました.",
"DialogAmiiboApiConnectErrorMessage": "Amiibo API サーバに接続できませんでした. サーバがダウンしているか, インターネット接続に問題があるかもしれません.",
"DialogProfileInvalidProfileErrorMessage": "プロファイル {0} は現在の入力設定システムと互換性がありません.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "デフォルトのプロファイルは上書きできません",
"DialogProfileDeleteProfileTitle": "プロファイルを削除中",
"DialogProfileDeleteProfileMessage": "このアクションは元に戻せません. 本当に続けてよろしいですか?",
"DialogWarning": "警告",
"DialogPPTCDeletionMessage": "PPTC キャッシュを破棄しようとしています:\n\n{0}\n\n実行してよろしいですか?",
"DialogPPTCDeletionErrorMessage": "PPTC キャッシュ破棄エラー {0}: {1}",
"DialogShaderDeletionMessage": "シェーダキャッシュを破棄しようとしています:\n\n{0}\n\n実行してよろしいですか?",
"DialogShaderDeletionErrorMessage": "シェーダキャッシュ破棄エラー {0}: {1}",
"DialogRyujinxErrorMessage": "エラーが発生しました",
"DialogInvalidTitleIdErrorMessage": "UI エラー: 選択されたゲームは有効なタイトル ID を保持していません",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "{0} には有効なシステムファームウェアがありません.",
"DialogFirmwareInstallerFirmwareInstallTitle": "ファームウェア {0} をインストール",
"DialogFirmwareInstallerFirmwareInstallMessage": "システムバージョン {0} がインストールされます.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\n現在のシステムバージョン {0} を置き換えます.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n続けてよろしいですか?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "ファームウェアをインストール中...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "システムバージョン {0} が正常にインストールされました.",
"DialogUserProfileDeletionWarningMessage": "選択されたプロファイルを削除すると,プロファイルがひとつも存在しなくなります",
"DialogUserProfileDeletionConfirmMessage": "選択されたプロファイルを削除しますか",
"DialogControllerSettingsModifiedConfirmMessage": "現在のコントローラ設定が更新されました.",
"DialogControllerSettingsModifiedConfirmSubMessage": "セーブしますか?",
"DialogDlcLoadNcaErrorMessage": "{0}. エラー発生ファイル: {1}",
"DialogDlcNoDlcErrorMessage": "選択されたファイルはこのタイトル用の DLC ではありません!",
"DialogPerformanceCheckLoggingEnabledMessage": "トレースロギングを有効にします. これは開発者のみに有用な機能です.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "パフォーマンス最適化のためには,トレースロギングを無効にすることを推奨します. トレースロギングを無効にしてよろしいですか?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "シェーダダンプを有効にします. これは開発者のみに有用な機能です.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "パフォーマンス最適化のためには, シェーダダンプを無効にすることを推奨します. シェーダダンプを無効にしてよろしいですか?",
"DialogLoadAppGameAlreadyLoadedMessage": "ゲームはすでにロード済みです",
"DialogLoadAppGameAlreadyLoadedSubMessage": "別のゲームを起動する前に, エミュレーションを停止またはエミュレータを閉じてください.",
"DialogUpdateAddUpdateErrorMessage": "選択されたファイルはこのタイトル用のアップデートではありません!",
"DialogSettingsBackendThreadingWarningTitle": "警告 - バックエンドスレッディング",
"DialogSettingsBackendThreadingWarningMessage": "このオプションの変更を完全に適用するには Ryujinx の再起動が必要です. プラットフォームによっては, Ryujinx のものを使用する前に手動でドライバ自身のマルチスレッディングを無効にする必要があるかもしれません.",
"SettingsTabGraphicsFeaturesOptions": "機能",
"SettingsTabGraphicsBackendMultithreading": "グラフィクスバックエンドのマルチスレッド実行:",
"CommonAuto": "自動",
"CommonOff": "オフ",
"CommonOn": "オン",
"InputDialogYes": "はい",
"InputDialogNo": "いいえ",
"DialogProfileInvalidProfileNameErrorMessage": "プロファイル名に無効な文字が含まれています. 再度試してみてください.",
"MenuBarOptionsPauseEmulation": "中断",
"MenuBarOptionsResumeEmulation": "再開",
"AboutUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx のウェブサイトを開きます.",
"AboutDisclaimerMessage": "Ryujinx は Nintendo™ および\nそのパートナー企業とは一切関係ありません.",
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) は\nAmiibo エミュレーションに使用されています.",
"AboutPatreonUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Patreon ページを開きます.",
"AboutGithubUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Github ページを開きます.",
"AboutDiscordUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Discord サーバを開きます.",
"AboutTwitterUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Twitter ページを開きます.",
"AboutRyujinxAboutTitle": "Ryujinx について:",
"AboutRyujinxAboutContent": "Ryujinx は Nintendo Switch™ のエミュレータです.\nPatreon で私達の活動を支援してください.\n最新の情報は Twitter または Discord から取得できます.\n貢献したい開発者の方は GitHub または Discord で詳細をご確認ください.",
"AboutRyujinxMaintainersTitle": "開発者:",
"AboutRyujinxMaintainersContentTooltipMessage": "クリックするとデフォルトのブラウザで 貢献者のページを開きます.",
"AboutRyujinxSupprtersTitle": "Patreon での支援者:",
"AmiiboSeriesLabel": "Amiibo シリーズ",
"AmiiboCharacterLabel": "キャラクタ",
"AmiiboScanButtonLabel": "スキャン",
"AmiiboOptionsShowAllLabel": "すべての Amiibo を表示",
"AmiiboOptionsUsRandomTagLabel": "ハック: ランダムな Uuid を使用",
"DlcManagerTableHeadingEnabledLabel": "有効",
"DlcManagerTableHeadingTitleIdLabel": "タイトルID",
"DlcManagerTableHeadingContainerPathLabel": "コンテナパス",
"DlcManagerTableHeadingFullPathLabel": "フルパス",
"DlcManagerRemoveAllButton": "すべて削除",
"MenuBarOptionsChangeLanguage": "言語を変更",
"CommonSort": "並べ替え",
"CommonShowNames": "名称を表示",
"CommonFavorite": "お気に入り",
"OrderAscending": "昇順",
"OrderDescending": "降順",
"SettingsTabGraphicsFeatures": "機能",
"ErrorWindowTitle": "エラーウインドウ",
"ToggleDiscordTooltip": "Discord の \"現在プレイ中\" アクティビティに Ryujinx を表示するかどうかを選択します",
"AddGameDirBoxTooltip": "リストに追加するゲームディレクトリを入力します",
"AddGameDirTooltip": "リストにゲームディレクトリを追加します",
"RemoveGameDirTooltip": "選択したゲームディレクトリを削除します",
"CustomThemeCheckTooltip": "エミュレータのメニュー外観を変更するためカスタム Avalonia テーマを使用します",
"CustomThemePathTooltip": "カスタム GUI テーマのパスです",
"CustomThemeBrowseTooltip": "カスタム GUI テーマを参照します",
"DockModeToggleTooltip": "有効にすると,ドッキングされた Nintendo Switch をエミュレートします.多くのゲームではグラフィクス品質が向上します.\n無効にすると,携帯モードの Nintendo Switch をエミュレートします.グラフィクスの品質は低下します.\n\nドッキングモード有効ならプレイヤー1の,無効なら携帯の入力を設定してください.\n\nよくわからない場合はオンのままにしてください.",
"DirectKeyboardTooltip": "キーボード直接アクセス (HID) に対応します. キーボードをテキスト入力デバイスとして使用できます.",
"DirectMouseTooltip": "マウス直接アクセス (HID) に対応します. マウスをポインティングデバイスとして使用できます.",
"RegionTooltip": "システムの地域を変更します",
"LanguageTooltip": "システムの言語を変更します",
"TimezoneTooltip": "システムのタイムゾーンを変更します",
"TimeTooltip": "システムの時刻を変更します",
"VSyncToggleTooltip": "エミュレートされたゲーム機の垂直同期です. 多くのゲームにおいて, フレームリミッタとして機能します. 無効にすると, ゲームが高速で実行されたり, ロード中に時間がかかったり, 止まったりすることがあります.\n\n設定したホットキーで, ゲーム内で切り替え可能です. 無効にする場合は, この操作を行うことをおすすめします.\n\nよくわからない場合はオンのままにしてください.",
"PptcToggleTooltip": "翻訳されたJIT関数をセーブすることで, ゲームをロードするたびに毎回翻訳する処理を不要とします.\n\n一度ゲームを起動すれば,二度目以降の起動時遅延を大きく軽減できます.\n\nよくわからない場合はオンのままにしてください.",
"FsIntegrityToggleTooltip": "ゲーム起動時にファイル破損をチェックし,破損が検出されたらログにハッシュエラーを表示します..\n\nパフォーマンスには影響なく, トラブルシューティングに役立ちます.\n\nよくわからない場合はオンのままにしてください.",
"AudioBackendTooltip": "音声レンダリングに使用するバックエンドを変更します.\n\nSDL2 が優先され, OpenAL と SoundIO はフォールバックとして使用されます. ダミーは音声出力しません.\n\nよくわからない場合は SDL2 を設定してください.",
"MemoryManagerTooltip": "ゲストメモリのマップ/アクセス方式を変更します. エミュレートされるCPUのパフォーマンスに大きな影響を与えます.\n\nよくわからない場合は「ホスト,チェックなし」を設定してください.",
"MemoryManagerSoftwareTooltip": "アドレス変換にソフトウェアページテーブルを使用します. 非常に正確ですがパフォーマンスが大きく低下します.",
"MemoryManagerHostTooltip": "ホストのアドレス空間にメモリを直接マップします.JITのコンパイルと実行速度が大きく向上します.",
"MemoryManagerUnsafeTooltip": "メモリを直接マップしますが, アクセス前にゲストのアドレス空間内のアドレスをマスクしません. より高速になりますが, 安全性が犠牲になります. ゲストアプリケーションは Ryujinx のどこからでもメモリにアクセスできるので,このモードでは信頼できるプログラムだけを実行するようにしてください.",
"DRamTooltip": "エミュレートされたシステムのメモリ容量を 4GB から 6GB に増加します.\n\n高解像度のテクスチャパックや 4K解像度の mod を使用する場合に有用です. パフォーマンスを改善するものではありません.\n\nよくわからない場合はオフのままにしてください.",
"IgnoreMissingServicesTooltip": "未実装の Horizon OS サービスを無視します. 特定のゲームにおいて起動時のクラッシュを回避できる場合があります.\n\nよくわからない場合はオフのままにしてください.",
"GraphicsBackendThreadingTooltip": "グラフィクスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
"GalThreadingTooltip": "グラフィクスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
"ShaderCacheToggleTooltip": "ディスクシェーダキャッシュをセーブし,次回以降の実行時遅延を軽減します.\n\nよくわからない場合はオンのままにしてください.",
"ResolutionScaleTooltip": "レンダリングに適用される解像度の倍率です",
"ResolutionScaleEntryTooltip": "1.5 のような整数でない倍率を指定すると,問題が発生したりクラッシュしたりする場合があります.",
"AnisotropyTooltip": "異方性フィルタリングのレベルです (ゲームが要求する値を使用する場合は「自動」を設定してください)",
"AspectRatioTooltip": "レンダリングに適用されるアスペクト比です.",
"ShaderDumpPathTooltip": "グラフィクス シェーダダンプのパスです",
"FileLogTooltip": "コンソール出力されるログをディスク上のログファイルにセーブします. パフォーマンスには影響を与えません.",
"StubLogTooltip": "stub ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"InfoLogTooltip": "info ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"WarnLogTooltip": "warning ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"ErrorLogTooltip": "error ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"TraceLogTooltip": "trace ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"GuestLogTooltip": "guest ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"FileAccessLogTooltip": "ファイルアクセスログメッセージをコンソールに出力します.",
"FSAccessLogModeTooltip": "コンソールへのファイルシステムアクセスログ出力を有効にします.0-3 のモードが有効です",
"DeveloperOptionTooltip": "使用上の注意",
"OpenGlLogLevel": "適切なログレベルを有効にする必要があります",
"DebugLogTooltip": "デバッグログメッセージをコンソールに出力します.\n\nログが読みづらくなり,エミュレータのパフォーマンスが低下するため,開発者から特別な指示がある場合のみ使用してください.",
"LoadApplicationFileTooltip": "ロードする Switch 互換のファイルを選択するためファイルエクスプローラを開きます",
"LoadApplicationFolderTooltip": "ロードする Switch 互換の展開済みアプリケーションを選択するためファイルエクスプローラを開きます",
"OpenRyujinxFolderTooltip": "Ryujinx ファイルシステムフォルダを開きます",
"OpenRyujinxLogsTooltip": "ログが格納されるフォルダを開きます",
"ExitTooltip": "Ryujinx を終了します",
"OpenSettingsTooltip": "設定ウインドウを開きます",
"OpenProfileManagerTooltip": "ユーザプロファイル管理ウインドウを開きます",
"StopEmulationTooltip": "ゲームのエミュレーションを停止してゲーム選択画面に戻ります",
"CheckUpdatesTooltip": "Ryujinx のアップデートを確認します",
"OpenAboutTooltip": "Ryujinx についてのウインドウを開きます",
"GridSize": "グリッドサイズ",
"GridSizeTooltip": "グリッドサイズを変更します",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "ポルトガル語(ブラジル)",
"AboutRyujinxContributorsButtonHeader": "すべての貢献者を確認",
"SettingsTabSystemAudioVolume": "音量: ",
"AudioVolumeTooltip": "音量を変更します",
"SettingsTabSystemEnableInternetAccess": "ゲストインターネットアクセス / LAN モード",
"EnableInternetAccessTooltip": "エミュレートしたアプリケーションをインターネットに接続できるようにします.\n\nLAN モードを持つゲーム同士は,この機能を有効にして同じアクセスポイントに接続すると接続できます. 実機も含まれます.\n\n任天堂のサーバーには接続できません. インターネットに接続しようとすると,特定のゲームでクラッシュすることがあります.\n\nよくわからない場合はオフのままにしてください.",
"GameListContextMenuManageCheatToolTip": "チートを管理します",
"GameListContextMenuManageCheat": "チートを管理",
"ControllerSettingsStickRange": "範囲:",
"DialogStopEmulationTitle": "Ryujinx - エミュレーションを停止",
"DialogStopEmulationMessage": "エミュレーションを停止してよろしいですか?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "音声",
"SettingsTabNetwork": "ネットワーク",
"SettingsTabNetworkConnection": "ネットワーク接続",
"SettingsTabCpuCache": "CPU キャッシュ",
"SettingsTabCpuMemory": "CPU メモリ",
"DialogUpdaterFlatpakNotSupportedMessage": "FlatHub を使用して Ryujinx をアップデートしてください.",
"UpdaterDisabledWarningTitle": "アップデータは無効です!",
"GameListContextMenuOpenSdModsDirectory": "Atmosphere Mods ディレクトリを開く",
"GameListContextMenuOpenSdModsDirectoryToolTip": "アプリケーションの Mod データを格納する SD カードの Atmosphere ディレクトリを開きます. 実際のハードウェア用にパッケージされた Mod データに有用です.",
"ControllerSettingsRotate90": "時計回りに 90° 回転",
"IconSize": "アイコンサイズ",
"IconSizeTooltip": "ゲームアイコンのサイズを変更します",
"MenuBarOptionsShowConsole": "コンソールを表示",
"ShaderCachePurgeError": "シェーダキャッシュの破棄エラー {0}: {1}",
"UserErrorNoKeys": "Keys がありません",
"UserErrorNoFirmware": "ファームウェアがありません",
"UserErrorFirmwareParsingFailed": "ファームウェアのパーズエラー",
"UserErrorApplicationNotFound": "アプリケーションがありません",
"UserErrorUnknown": "不明なエラー",
"UserErrorUndefined": "未定義エラー",
"UserErrorNoKeysDescription": "'prod.keys' が見つかりませんでした",
"UserErrorNoFirmwareDescription": "インストールされたファームウェアが見つかりませんでした",
"UserErrorFirmwareParsingFailedDescription": "ファームウェアをパーズできませんでした.通常,古いキーが原因です.",
"UserErrorApplicationNotFoundDescription": "指定されたパスに有効なアプリケーションがありませんでした.",
"UserErrorUnknownDescription": "不明なエラーが発生しました!",
"UserErrorUndefinedDescription": "未定義のエラーが発生しました! 発生すべきものではないので,開発者にご連絡ください!",
"OpenSetupGuideMessage": "セットアップガイドを開く",
"NoUpdate": "アップデートなし",
"TitleUpdateVersionLabel": "バージョン {0} - {1}",
"RyujinxInfo": "Ryujinx - 情報",
"RyujinxConfirm": "Ryujinx - 確認",
"FileDialogAllTypes": "すべての種別",
"Never": "Never",
"SwkbdMinCharacters": "最低 {0} 文字必要です",
"SwkbdMinRangeCharacters": "{0}-{1} 文字にしてください",
"SoftwareKeyboard": "ソフトウェアキーボード",
"DialogControllerAppletMessagePlayerRange": "アプリケーションは {0} 名のプレイヤーを要求しています:\n\n種別: {1}\n\nプレイヤー: {2}\n\n{3}設定を開き各プレイヤーの入力設定を行ってから閉じるを押してください.",
"DialogControllerAppletMessage": "アプリケーションは {0} 名のプレイヤーを要求しています:\n\n種別: {1}\n\nプレイヤー: {2}\n\n{3}設定を開き各プレイヤーの入力設定を行ってから閉じるを押してください.",
"DialogControllerAppletDockModeSet": "ドッキングモードに設定されました. 携帯モードは無効になります.\n\n",
"UpdaterRenaming": "古いファイルをリネーム中...",
"UpdaterRenameFailed": "ファイルをリネームできませんでした: {0}",
"UpdaterAddingFiles": "新規ファイルを追加中...",
"UpdaterExtracting": "アップデートを展開中...",
"UpdaterDownloading": "アップデートをダウンロード中...",
"Game": "ゲーム",
"Docked": "ドッキング",
"Handheld": "携帯",
"ConnectionError": "接続エラー.",
"AboutPageDeveloperListMore": "{0}, その他大勢...",
"ApiError": "API エラー.",
"LoadingHeading": "ロード中: {0}",
"CompilingPPTC": "PTC をコンパイル中",
"CompilingShaders": "シェーダをコンパイル中",
"AllKeyboards": "すべてキーボード",
"OpenFileDialogTitle": "開くファイルを選択",
"OpenFolderDialogTitle": "展開されたゲームフォルダを選択",
"AllSupportedFormats": "すべての対応フォーマット",
"RyujinxUpdater": "Ryujinx アップデータ",
"SettingsTabHotkeys": "キーボード ホットキー",
"SettingsTabHotkeysHotkeys": "キーボード ホットキー",
"SettingsTabHotkeysToggleVsyncHotkey": "VSync 切り替え:",
"SettingsTabHotkeysScreenshotHotkey": "スクリーンショット:",
"SettingsTabHotkeysShowUiHotkey": "UI表示:",
"SettingsTabHotkeysPauseHotkey": "中断:",
"SettingsTabHotkeysToggleMuteHotkey": "ミュート:",
"ControllerMotionTitle": "モーションコントロール設定",
"ControllerRumbleTitle": "振動設定",
"SettingsSelectThemeFileDialogTitle": "テーマファイルを選択",
"SettingsXamlThemeFile": "Xaml テーマファイル",
"AvatarWindowTitle": "アカウント - アバター管理",
"Amiibo": "Amiibo",
"Unknown": "不明",
"Usage": "使用法",
"Writable": "書き込み可能",
"SelectDlcDialogTitle": "DLC ファイルを選択",
"SelectUpdateDialogTitle": "アップデートファイルを選択",
"UserProfileWindowTitle": "ユーザプロファイルを管理",
"CheatWindowTitle": "チート管理",
"DlcWindowTitle": "DLC 管理",
"UpdateWindowTitle": "アップデート管理",
"CheatWindowHeading": "利用可能なチート {0} [{1}]",
"DlcWindowHeading": "利用可能な DLC {0} [{1}]",
"UserProfilesEditProfile": "編集",
"Cancel": "キャンセル",
"Save": "セーブ",
"Discard": "破棄",
"UserProfilesSetProfileImage": "プロファイル画像を設定",
"UserProfileEmptyNameError": "名前が必要です",
"UserProfileNoImageError": "プロファイル画像が必要です",
"GameUpdateWindowHeading": "利用可能なアップデート {0} [{1}]",
"SettingsTabHotkeysResScaleUpHotkey": "解像度を上げる:",
"SettingsTabHotkeysResScaleDownHotkey": "解像度を下げる:"
}

View File

@ -24,7 +24,6 @@ using System.Buffers;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using static LibHac.Fs.ApplicationSaveDataManagement;
using Path = System.IO.Path;
namespace Ryujinx.Ava.Common

View File

@ -1,7 +1,6 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Threading;
using Ryujinx.Input;
using System;
using System.Numerics;

View File

@ -16,8 +16,6 @@ using Ryujinx.Graphics.Vulkan;
using Ryujinx.Modules;
using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration;
using Silk.NET.Vulkan.Extensions.EXT;
using Silk.NET.Vulkan.Extensions.KHR;
using System;
using System.Collections.Generic;
using System.IO;
@ -94,7 +92,6 @@ namespace Ryujinx.Ava
.With(new Ui.Vulkan.VulkanOptions()
{
ApplicationName = "Ryujinx.Graphics.Vulkan",
VulkanVersion = new Version(1, 2),
MaxQueueCount = 2,
PreferDiscreteGpu = true,
PreferredDevice = !PreviewerDetached ? "" : ConfigurationState.Instance.Graphics.PreferredGpu.Value,
@ -181,6 +178,18 @@ namespace Ryujinx.Ava
UseVulkan = PreviewerDetached ? ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan : false;
if (UseVulkan)
{
if (VulkanRenderer.GetPhysicalDevices().Length == 0)
{
UseVulkan = false;
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl;
Logger.Warning?.PrintMsg(LogClass.Application, "A suitable Vulkan physical device is not available. Falling back to OpenGL");
}
}
if (UseVulkan)
{
// With a custom gpu backend, avalonia doesn't enable dpi awareness, so the backend must handle it. This isn't so for the opengl backed,

View File

@ -118,6 +118,7 @@
<None Remove="Assets\Locales\fr_FR.json" />
<None Remove="Assets\Locales\de_DE.json" />
<None Remove="Assets\Locales\it_IT.json" />
<None Remove="Assets\Locales\ja_JP.json" />
<None Remove="Assets\Locales\ko_KR.json" />
<None Remove="Assets\Locales\pt_BR.json" />
<None Remove="Assets\Locales\ru_RU.json" />
@ -136,6 +137,7 @@
<EmbeddedResource Include="Assets\Locales\fr_FR.json" />
<EmbeddedResource Include="Assets\Locales\de_DE.json" />
<EmbeddedResource Include="Assets\Locales\it_IT.json" />
<EmbeddedResource Include="Assets\Locales\ja_JP.json" />
<EmbeddedResource Include="Assets\Locales\ko_KR.json" />
<EmbeddedResource Include="Assets\Locales\pt_BR.json" />
<EmbeddedResource Include="Assets\Locales\ru_RU.json" />

View File

@ -10,7 +10,6 @@ using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationPr
using Ryujinx.HLE.Ui;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Applet
{

View File

@ -1,7 +1,6 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Windows;

View File

@ -1,7 +1,6 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using FluentAvalonia.Core;
using FluentAvalonia.UI.Controls;

View File

@ -7,7 +7,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
{
public static void ThrowOnError(this Result result)
{
if (result != Result.Success)
// Only negative result codes are errors.
if ((int)result < (int)Result.Success)
{
throw new Exception($"Unexpected API error \"{result}\".");
}

View File

@ -1,26 +1,90 @@
using System;
using Avalonia;
using Avalonia.Skia;
using Ryujinx.Ava.Ui.Vulkan;
using Ryujinx.Ava.Ui.Vulkan.Surfaces;
using Silk.NET.Vulkan;
using SkiaSharp;
namespace Ryujinx.Ava.Ui.Backend.Vulkan
{
internal class VulkanRenderTarget : ISkiaGpuRenderTarget
{
public GRContext GrContext { get; set; }
public GRContext GrContext { get; private set; }
private readonly VulkanSurfaceRenderTarget _surface;
private readonly VulkanPlatformInterface _vulkanPlatformInterface;
private readonly IVulkanPlatformSurface _vulkanPlatformSurface;
private GRVkBackendContext _grVkBackend;
public VulkanRenderTarget(VulkanPlatformInterface vulkanPlatformInterface, IVulkanPlatformSurface vulkanPlatformSurface)
{
_surface = vulkanPlatformInterface.CreateRenderTarget(vulkanPlatformSurface);
_vulkanPlatformInterface = vulkanPlatformInterface;
_vulkanPlatformSurface = vulkanPlatformSurface;
Initialize();
}
private void Initialize()
{
GRVkGetProcedureAddressDelegate getProc = GetVulkanProcAddress;
_grVkBackend = new GRVkBackendContext()
{
VkInstance = _surface.Device.Handle,
VkPhysicalDevice = _vulkanPlatformInterface.PhysicalDevice.Handle,
VkDevice = _surface.Device.Handle,
VkQueue = _surface.Device.Queue.Handle,
GraphicsQueueIndex = _vulkanPlatformInterface.PhysicalDevice.QueueFamilyIndex,
GetProcedureAddress = getProc
};
GrContext = GRContext.CreateVulkan(_grVkBackend);
var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>();
if (gpu.MaxResourceBytes.HasValue)
{
GrContext.SetResourceCacheLimit(gpu.MaxResourceBytes.Value);
}
}
private IntPtr GetVulkanProcAddress(string name, IntPtr instanceHandle, IntPtr deviceHandle)
{
IntPtr addr;
if (deviceHandle != IntPtr.Zero)
{
addr = _vulkanPlatformInterface.Api.GetDeviceProcAddr(new Device(deviceHandle), name);
if (addr != IntPtr.Zero)
{
return addr;
}
addr = _vulkanPlatformInterface.Api.GetDeviceProcAddr(new Device(_surface.Device.Handle), name);
if (addr != IntPtr.Zero)
{
return addr;
}
}
addr = _vulkanPlatformInterface.Api.GetInstanceProcAddr(new Instance(_vulkanPlatformInterface.Instance.Handle), name);
if (addr == IntPtr.Zero)
{
addr = _vulkanPlatformInterface.Api.GetInstanceProcAddr(new Instance(instanceHandle), name);
}
return addr;
}
public void Dispose()
{
_grVkBackend.Dispose();
GrContext.Dispose();
_surface.Dispose();
}
@ -45,20 +109,22 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
{
GrContext.ResetContext();
var image = _surface.GetImage();
var imageInfo = new GRVkImageInfo()
{
CurrentQueueFamily = disp.QueueFamilyIndex,
Format = _surface.ImageFormat,
Image = _surface.Image.Handle,
ImageLayout = (uint)_surface.Image.CurrentLayout,
ImageTiling = (uint)_surface.Image.Tiling,
Format = (uint)image.Format,
Image = image.Handle,
ImageLayout = (uint)image.CurrentLayout,
ImageTiling = (uint)image.Tiling,
ImageUsageFlags = _surface.UsageFlags,
LevelCount = _surface.MipLevels,
SampleCount = 1,
Protected = false,
Alloc = new GRVkAlloc()
{
Memory = _surface.Image.MemoryHandle,
Memory = image.MemoryHandle,
Flags = 0,
Offset = 0,
Size = _surface.MemorySize

View File

@ -13,71 +13,12 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
public class VulkanSkiaGpu : ISkiaGpu
{
private readonly VulkanPlatformInterface _vulkan;
private readonly long? _maxResourceBytes;
private GRVkBackendContext _grVkBackend;
private bool _initialized;
public GRContext GrContext { get; private set; }
public long? MaxResourceBytes { get; }
public VulkanSkiaGpu(long? maxResourceBytes)
{
_vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
_maxResourceBytes = maxResourceBytes;
}
private void Initialize()
{
if (_initialized)
{
return;
}
_initialized = true;
GRVkGetProcedureAddressDelegate getProc = (string name, IntPtr instanceHandle, IntPtr deviceHandle) =>
{
IntPtr addr = IntPtr.Zero;
if (deviceHandle != IntPtr.Zero)
{
addr = _vulkan.Device.Api.GetDeviceProcAddr(new Device(deviceHandle), name);
if (addr != IntPtr.Zero)
{
return addr;
}
addr = _vulkan.Device.Api.GetDeviceProcAddr(new Device(_vulkan.Device.Handle), name);
if (addr != IntPtr.Zero)
{
return addr;
}
}
addr = _vulkan.Device.Api.GetInstanceProcAddr(new Instance(_vulkan.Instance.Handle), name);
if (addr == IntPtr.Zero)
{
addr = _vulkan.Device.Api.GetInstanceProcAddr(new Instance(instanceHandle), name);
}
return addr;
};
_grVkBackend = new GRVkBackendContext()
{
VkInstance = _vulkan.Device.Handle,
VkPhysicalDevice = _vulkan.PhysicalDevice.Handle,
VkDevice = _vulkan.Device.Handle,
VkQueue = _vulkan.Device.Queue.Handle,
GraphicsQueueIndex = _vulkan.PhysicalDevice.QueueFamilyIndex,
GetProcedureAddress = getProc
};
GrContext = GRContext.CreateVulkan(_grVkBackend);
if (_maxResourceBytes.HasValue)
{
GrContext.SetResourceCacheLimit(_maxResourceBytes.Value);
}
MaxResourceBytes = maxResourceBytes;
}
public ISkiaGpuRenderTarget TryCreateRenderTarget(IEnumerable<object> surfaces)
@ -106,10 +47,6 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
VulkanRenderTarget vulkanRenderTarget = new VulkanRenderTarget(_vulkan, window);
Initialize();
vulkanRenderTarget.GrContext = GrContext;
return vulkanRenderTarget;
}

View File

@ -1,5 +1,6 @@
using System;
using Avalonia;
using Ryujinx.Graphics.Vulkan;
using Silk.NET.Vulkan;
namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
@ -7,24 +8,35 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
internal class VulkanSurfaceRenderTarget : IDisposable
{
private readonly VulkanPlatformInterface _platformInterface;
private readonly Format _format;
public VulkanImage Image { get; private set; }
public bool IsCorrupted { get; private set; } = true;
private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer;
private VulkanImage Image { get; set; }
private object _lock = new object();
public uint MipLevels => Image.MipLevels;
public VulkanDevice Device { get; }
public VulkanSurfaceRenderTarget(VulkanPlatformInterface platformInterface, VulkanSurface surface)
{
_platformInterface = platformInterface;
Display = VulkanDisplay.CreateDisplay(platformInterface.Instance, platformInterface.Device,
platformInterface.PhysicalDevice, surface);
var device = VulkanInitialization.CreateDevice(platformInterface.Api,
platformInterface.PhysicalDevice.InternalHandle,
platformInterface.PhysicalDevice.QueueFamilyIndex,
VulkanInitialization.GetSupportedExtensions(platformInterface.Api, platformInterface.PhysicalDevice.InternalHandle),
platformInterface.PhysicalDevice.QueueCount);
Device = new VulkanDevice(device, platformInterface.PhysicalDevice, platformInterface.Api);
Display = VulkanDisplay.CreateDisplay(
platformInterface.Instance,
Device,
platformInterface.PhysicalDevice,
surface);
Surface = surface;
// Skia seems to only create surfaces from images with unorm format
IsRgba = Display.SurfaceFormat.Format >= Format.R8G8B8A8Unorm &&
Display.SurfaceFormat.Format <= Format.R8G8B8A8Srgb;
@ -33,13 +45,13 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
public bool IsRgba { get; }
public uint ImageFormat => (uint) _format;
public uint ImageFormat => (uint)_format;
public ulong MemorySize => Image.MemorySize;
public VulkanDisplay Display { get; }
public VulkanDisplay Display { get; private set; }
public VulkanSurface Surface { get; }
public VulkanSurface Surface { get; private set; }
public uint UsageFlags => Image.UsageFlags;
@ -47,46 +59,76 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
public void Dispose()
{
_platformInterface.Device.WaitIdle();
DestroyImage();
Display?.Dispose();
Surface?.Dispose();
lock (_lock)
{
DestroyImage();
Display?.Dispose();
Surface?.Dispose();
Device?.Dispose();
Display = null;
Surface = null;
}
}
public VulkanSurfaceRenderingSession BeginDraw(float scaling)
{
var session = new VulkanSurfaceRenderingSession(Display, _platformInterface.Device, this, scaling);
if (Image == null)
{
RecreateImage();
}
if (IsCorrupted)
{
IsCorrupted = false;
DestroyImage();
CreateImage();
}
else
{
Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr);
}
_commandBuffer?.WaitForFence();
_commandBuffer = null;
var session = new VulkanSurfaceRenderingSession(Display, Device, this, scaling);
Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr);
return session;
}
public void Invalidate()
public void RecreateImage()
{
IsCorrupted = true;
DestroyImage();
CreateImage();
}
private void CreateImage()
{
Size = Display.Size;
Image = new VulkanImage(_platformInterface.Device, _platformInterface.PhysicalDevice, _platformInterface.Device.CommandBufferPool, ImageFormat, Size);
Image = new VulkanImage(Device, _platformInterface.PhysicalDevice, Display.CommandBufferPool, ImageFormat, Size);
}
private void DestroyImage()
{
_platformInterface.Device.WaitIdle();
_commandBuffer?.WaitForFence();
_commandBuffer = null;
Image?.Dispose();
Image = null;
}
public VulkanImage GetImage()
{
return Image;
}
public void EndDraw()
{
lock (_lock)
{
if (Display == null)
{
return;
}
_commandBuffer = Display.StartPresentation();
Display.BlitImageToCurrentImage(this, _commandBuffer.InternalHandle);
Display.EndPresentation(_commandBuffer);
}
}
}
}

View File

@ -10,6 +10,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
private readonly CommandPool _commandPool;
private readonly List<VulkanCommandBuffer> _usedCommandBuffers = new();
private readonly object _lock = new object();
public unsafe VulkanCommandBufferPool(VulkanDevice device, VulkanPhysicalDevice physicalDevice)
{
@ -36,9 +37,12 @@ namespace Ryujinx.Ava.Ui.Vulkan
Level = CommandBufferLevel.Primary
};
_device.Api.AllocateCommandBuffers(_device.InternalHandle, commandBufferAllocateInfo, out var commandBuffer);
lock (_lock)
{
_device.Api.AllocateCommandBuffers(_device.InternalHandle, commandBufferAllocateInfo, out var commandBuffer);
return commandBuffer;
return commandBuffer;
}
}
public VulkanCommandBuffer CreateCommandBuffer()
@ -48,7 +52,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
public void FreeUsedCommandBuffers()
{
lock (_usedCommandBuffers)
lock (_lock)
{
foreach (var usedCommandBuffer in _usedCommandBuffers)
{
@ -61,7 +65,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
private void DisposeCommandBuffer(VulkanCommandBuffer commandBuffer)
{
lock (_usedCommandBuffers)
lock (_lock)
{
_usedCommandBuffers.Add(commandBuffer);
}
@ -69,8 +73,11 @@ namespace Ryujinx.Ava.Ui.Vulkan
public void Dispose()
{
FreeUsedCommandBuffers();
_device.Api.DestroyCommandPool(_device.InternalHandle, _commandPool, Span<AllocationCallbacks>.Empty);
lock (_lock)
{
FreeUsedCommandBuffers();
_device.Api.DestroyCommandPool(_device.InternalHandle, _commandPool, Span<AllocationCallbacks>.Empty);
}
}
public class VulkanCommandBuffer : IDisposable
@ -80,6 +87,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
private readonly Fence _fence;
private bool _hasEnded;
private bool _hasStarted;
private bool _isDisposed;
private object _lock = new object();
public IntPtr Handle => InternalHandle.Handle;
@ -101,6 +110,22 @@ namespace Ryujinx.Ava.Ui.Vulkan
device.Api.CreateFence(device.InternalHandle, fenceCreateInfo, null, out _fence);
}
public void WaitForFence()
{
if (_isDisposed)
{
return;
}
lock (_lock)
{
if (!_isDisposed)
{
_device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue);
}
}
}
public void BeginRecording()
{
if (!_hasStarted)
@ -173,9 +198,17 @@ namespace Ryujinx.Ava.Ui.Vulkan
public void Dispose()
{
_device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue);
_device.Api.FreeCommandBuffers(_device.InternalHandle, _commandBufferPool._commandPool, 1, InternalHandle);
_device.Api.DestroyFence(_device.InternalHandle, _fence, Span<AllocationCallbacks>.Empty);
lock (_lock)
{
if (!_isDisposed)
{
_isDisposed = true;
_device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue);
_device.Api.FreeCommandBuffers(_device.InternalHandle, _commandBufferPool._commandPool, 1, InternalHandle);
_device.Api.DestroyFence(_device.InternalHandle, _fence, Span<AllocationCallbacks>.Empty);
}
}
}
}
}

View File

@ -14,12 +14,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
api.GetDeviceQueue(apiHandle, physicalDevice.QueueFamilyIndex, 0, out var queue);
var vulkanQueue = new VulkanQueue(this, queue);
Queue = vulkanQueue;
Queue = new VulkanQueue(this, queue);
PresentQueue = vulkanQueue;
CommandBufferPool = new VulkanCommandBufferPool(this, physicalDevice);
PresentQueue = Queue;
}
public IntPtr Handle => InternalHandle.Handle;
@ -29,13 +26,12 @@ namespace Ryujinx.Ava.Ui.Vulkan
public VulkanQueue Queue { get; private set; }
public VulkanQueue PresentQueue { get; }
public VulkanCommandBufferPool CommandBufferPool { get; }
public void Dispose()
{
WaitIdle();
CommandBufferPool?.Dispose();
Queue = null;
Api.DestroyDevice(InternalHandle, Span<AllocationCallbacks>.Empty);
}
internal void Submit(SubmitInfo submitInfo, Fence fence = default)

View File

@ -3,7 +3,6 @@ using System.Linq;
using System.Threading;
using Avalonia;
using Ryujinx.Ava.Ui.Vulkan.Surfaces;
using Ryujinx.Ui.Common.Configuration;
using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.KHR;
@ -15,16 +14,19 @@ namespace Ryujinx.Ava.Ui.Vulkan
private readonly VulkanInstance _instance;
private readonly VulkanPhysicalDevice _physicalDevice;
private readonly VulkanSemaphorePair _semaphorePair;
private readonly VulkanDevice _device;
private uint _nextImage;
private readonly VulkanSurface _surface;
private SurfaceFormatKHR _surfaceFormat;
private SwapchainKHR _swapchain;
private Extent2D _swapchainExtent;
private Image[] _swapchainImages;
private VulkanDevice _device { get; }
private ImageView[] _swapchainImageViews = new ImageView[0];
private ImageView[] _swapchainImageViews = Array.Empty<ImageView>();
private bool _vsyncStateChanged;
private bool _vsyncEnabled;
private bool _surfaceChanged;
public event EventHandler Presented;
public VulkanCommandBufferPool CommandBufferPool { get; set; }
@ -73,6 +75,14 @@ namespace Ryujinx.Ava.Ui.Vulkan
CommandBufferPool.Dispose();
}
public bool IsSurfaceChanged()
{
var changed = _surfaceChanged;
_surfaceChanged = false;
return changed;
}
private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device,
VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent,
SwapchainKHR? oldswapchain = null, bool vsyncEnabled = true)
@ -193,22 +203,23 @@ namespace Ryujinx.Ava.Ui.Vulkan
}
var modes = presentModes.ToList();
var presentMode = PresentModeKHR.PresentModeFifoKhr;
if (!vsyncEnabled && modes.Contains(PresentModeKHR.PresentModeImmediateKhr))
{
presentMode = PresentModeKHR.PresentModeImmediateKhr;
return PresentModeKHR.PresentModeImmediateKhr;
}
else if (modes.Contains(PresentModeKHR.PresentModeMailboxKhr))
{
presentMode = PresentModeKHR.PresentModeMailboxKhr;
return PresentModeKHR.PresentModeMailboxKhr;
}
else if (modes.Contains(PresentModeKHR.PresentModeImmediateKhr))
else if (modes.Contains(PresentModeKHR.PresentModeFifoKhr))
{
presentMode = PresentModeKHR.PresentModeImmediateKhr;
return PresentModeKHR.PresentModeFifoKhr;
}
else
{
return PresentModeKHR.PresentModeImmediateKhr;
}
return presentMode;
}
internal static VulkanDisplay CreateDisplay(VulkanInstance instance, VulkanDevice device,
@ -266,6 +277,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
_swapchain = CreateSwapchain(_instance, _device, _physicalDevice, _surface, out _swapchainExtent, _swapchain, _vsyncEnabled);
CreateSwapchainImages();
_surfaceChanged = true;
}
private unsafe ImageView CreateSwapchainImageView(Image swapchainImage, Format format)
@ -306,7 +319,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
return true;
}
internal VulkanCommandBufferPool.VulkanCommandBuffer StartPresentation(VulkanSurfaceRenderTarget renderTarget)
internal VulkanCommandBufferPool.VulkanCommandBuffer StartPresentation()
{
_nextImage = 0;
while (true)
@ -346,8 +359,10 @@ namespace Ryujinx.Ava.Ui.Vulkan
internal void BlitImageToCurrentImage(VulkanSurfaceRenderTarget renderTarget, CommandBuffer commandBuffer)
{
var image = renderTarget.GetImage();
VulkanMemoryHelper.TransitionLayout(_device, commandBuffer,
renderTarget.Image.InternalHandle.Value, (ImageLayout)renderTarget.Image.CurrentLayout,
image.InternalHandle.Value, (ImageLayout)image.CurrentLayout,
AccessFlags.AccessNoneKhr,
ImageLayout.TransferSrcOptimal,
AccessFlags.AccessTransferReadBit,
@ -381,7 +396,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
}
};
_device.Api.CmdBlitImage(commandBuffer, renderTarget.Image.InternalHandle.Value,
_device.Api.CmdBlitImage(commandBuffer, image.InternalHandle.Value,
ImageLayout.TransferSrcOptimal,
_swapchainImages[_nextImage],
ImageLayout.TransferDstOptimal,
@ -390,9 +405,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
Filter.Linear);
VulkanMemoryHelper.TransitionLayout(_device, commandBuffer,
renderTarget.Image.InternalHandle.Value, ImageLayout.TransferSrcOptimal,
image.InternalHandle.Value, ImageLayout.TransferSrcOptimal,
AccessFlags.AccessTransferReadBit,
(ImageLayout)renderTarget.Image.CurrentLayout,
(ImageLayout)image.CurrentLayout,
AccessFlags.AccessNoneKhr,
renderTarget.MipLevels);
}
@ -434,6 +449,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
}
CommandBufferPool.FreeUsedCommandBuffers();
Presented?.Invoke(this, null);
}
}
}

View File

@ -148,20 +148,18 @@ namespace Ryujinx.Ava.Ui.Vulkan
_currentAccessFlags = destinationAccessFlags;
}
public void TransitionLayout(uint destinationLayout, uint destinationAccessFlags)
public void Dispose()
{
TransitionLayout((ImageLayout)destinationLayout, (AccessFlags)destinationAccessFlags);
}
if (InternalHandle != null)
{
_device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, Span<AllocationCallbacks>.Empty);
_device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, Span<AllocationCallbacks>.Empty);
_device.Api.FreeMemory(_device.InternalHandle, _imageMemory, Span<AllocationCallbacks>.Empty);
public unsafe void Dispose()
{
_device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, null);
_device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, null);
_device.Api.FreeMemory(_device.InternalHandle, _imageMemory, null);
_imageView = default;
InternalHandle = default;
_imageMemory = default;
_imageView = default;
InternalHandle = null;
_imageMemory = default;
}
}
}
}

View File

@ -57,8 +57,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
var applicationInfo = new ApplicationInfo
{
PApplicationName = (byte*)applicationName,
ApiVersion = new Version32((uint)options.VulkanVersion.Major, (uint)options.VulkanVersion.Minor,
(uint)options.VulkanVersion.Build),
ApiVersion = Vk.Version12.Value,
PEngineName = (byte*)engineName,
EngineVersion = new Version32(1, 0, 0),
ApplicationVersion = new Version32(1, 0, 0)

View File

@ -11,11 +11,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
/// </summary>
public string ApplicationName { get; set; }
/// <summary>
/// Specifies the Vulkan API version to use
/// </summary>
public Version VulkanVersion { get; set; } = new Version(1, 1, 0);
/// <summary>
/// Specifies additional extensions to enable if available on the instance
/// </summary>

View File

@ -18,13 +18,11 @@ namespace Ryujinx.Ava.Ui.Vulkan
public VulkanPhysicalDevice PhysicalDevice { get; private set; }
public VulkanInstance Instance { get; }
public VulkanDevice Device { get; set; }
public Vk Api { get; private set; }
public VulkanSurfaceRenderTarget MainSurface { get; set; }
public void Dispose()
{
Device?.Dispose();
Instance?.Dispose();
Api?.Dispose();
}
@ -54,16 +52,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
{
var surface = VulkanSurface.CreateSurface(Instance, platformSurface);
if (Device == null)
if (PhysicalDevice == null)
{
PhysicalDevice = VulkanPhysicalDevice.FindSuitablePhysicalDevice(Instance, surface, _options.PreferDiscreteGpu, _options.PreferredDevice);
var device = VulkanInitialization.CreateDevice(Instance.Api,
PhysicalDevice.InternalHandle,
PhysicalDevice.QueueFamilyIndex,
VulkanInitialization.GetSupportedExtensions(Instance.Api, PhysicalDevice.InternalHandle),
PhysicalDevice.QueueCount);
Device = new VulkanDevice(device, PhysicalDevice, Instance.Api);
}
var renderTarget = new VulkanSurfaceRenderTarget(this, surface);
@ -71,7 +62,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
if (MainSurface == null && surface != null)
{
MainSurface = renderTarget;
MainSurface.Display.ChangeVSyncMode(false);
}
return renderTarget;

View File

@ -9,7 +9,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
{
private readonly VulkanDevice _device;
private readonly VulkanSurfaceRenderTarget _renderTarget;
private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer;
public VulkanSurfaceRenderingSession(VulkanDisplay display, VulkanDevice device,
VulkanSurfaceRenderTarget renderTarget, float scaling)
@ -32,17 +31,13 @@ namespace Ryujinx.Ava.Ui.Vulkan
{
if (!Display.EnsureSwapchainAvailable())
{
_renderTarget.Invalidate();
_renderTarget.RecreateImage();
}
}
public void Dispose()
{
_commandBuffer = Display.StartPresentation(_renderTarget);
Display.BlitImageToCurrentImage(_renderTarget, _commandBuffer.InternalHandle);
Display.EndPresentation(_commandBuffer);
_renderTarget.EndDraw();
}
}
}

View File

@ -1,9 +1,7 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models;
using Ryujinx.Ava.Ui.Windows;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Controls

View File

@ -37,7 +37,7 @@ namespace Ryujinx.Ava.Ui.Controls
public override void DestroyBackgroundContext()
{
_image = null;
Image = null;
if (_fence != IntPtr.Zero)
{
@ -57,6 +57,8 @@ namespace Ryujinx.Ava.Ui.Controls
Dispatcher.UIThread.InvokeAsync(() =>
{
Image = (int)image;
InvalidateVisual();
}).Wait();
if (_fence != IntPtr.Zero)
@ -66,7 +68,7 @@ namespace Ryujinx.Ava.Ui.Controls
_fence = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None);
QueueRender();
InvalidateVisual();
_gameBackgroundWindow.SwapBuffers();
}

View File

@ -11,25 +11,7 @@ namespace Ryujinx.Ava.Ui.Controls
{
internal abstract class RendererControl : Control
{
protected object _image;
static RendererControl()
{
AffectsRender<RendererControl>(ImageProperty);
}
public readonly static StyledProperty<object> ImageProperty =
AvaloniaProperty.Register<RendererControl, object>(
nameof(Image),
0,
inherits: true,
defaultBindingMode: BindingMode.TwoWay);
protected object Image
{
get => _image;
set => SetAndRaise(ImageProperty, ref _image, value);
}
protected object Image { get; set; }
public event EventHandler<EventArgs> RendererInitialized;
public event EventHandler<Size> SizeChanged;
@ -60,8 +42,6 @@ namespace Ryujinx.Ava.Ui.Controls
if (!rect.IsEmpty)
{
RenderSize = rect.Size * VisualRoot.RenderScaling;
DrawOperation?.Dispose();
DrawOperation = CreateDrawOperation();
}
}
@ -97,17 +77,11 @@ namespace Ryujinx.Ava.Ui.Controls
RendererInitialized?.Invoke(this, EventArgs.Empty);
}
public void QueueRender()
{
Program.RenderTimer.TickNow();
}
internal abstract void Present(object image);
internal void Start()
{
IsStarted = true;
QueueRender();
}
internal void Stop()

View File

@ -1,6 +1,4 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Ryujinx.Ava.Ui.Windows;
namespace Ryujinx.Ava.Ui.Controls

View File

@ -1,4 +1,5 @@
using Avalonia;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Skia;
@ -11,20 +12,23 @@ using Silk.NET.Vulkan;
using SkiaSharp;
using SPB.Windowing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace Ryujinx.Ava.Ui.Controls
{
internal class VulkanRendererControl : RendererControl
{
private const int MaxImagesInFlight = 3;
private VulkanPlatformInterface _platformInterface;
private ConcurrentQueue<PresentImageInfo> _imagesInFlight;
private PresentImageInfo _currentImage;
public VulkanRendererControl(GraphicsDebugLevel graphicsDebugLevel) : base(graphicsDebugLevel)
{
_platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
_imagesInFlight = new ConcurrentQueue<PresentImageInfo>();
}
public override void DestroyBackgroundContext()
@ -37,6 +41,40 @@ namespace Ryujinx.Ava.Ui.Controls
return new VulkanDrawOperation(this);
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
_imagesInFlight.Clear();
if (_platformInterface.MainSurface.Display != null)
{
_platformInterface.MainSurface.Display.Presented -= Window_Presented;
}
_currentImage?.Put();
_currentImage = null;
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
_platformInterface.MainSurface.Display.Presented += Window_Presented;
}
private void Window_Presented(object sender, EventArgs e)
{
_platformInterface.MainSurface.Device.QueueWaitIdle();
_currentImage?.Put();
_currentImage = null;
}
public override void Render(DrawingContext context)
{
base.Render(context);
}
protected override void CreateWindow()
{
}
@ -51,12 +89,29 @@ namespace Ryujinx.Ava.Ui.Controls
internal override void Present(object image)
{
Dispatcher.UIThread.InvokeAsync(() =>
{
Image = image;
}).Wait();
Image = image;
QueueRender();
_imagesInFlight.Enqueue((PresentImageInfo)image);
if (_imagesInFlight.Count > MaxImagesInFlight)
{
_imagesInFlight.TryDequeue(out _);
}
Dispatcher.UIThread.Post(InvalidateVisual);
}
private PresentImageInfo GetImage()
{
lock (_imagesInFlight)
{
if (!_imagesInFlight.TryDequeue(out _currentImage))
{
_currentImage = (PresentImageInfo)Image;
}
return _currentImage;
}
}
private class VulkanDrawOperation : ICustomDrawOperation
@ -64,6 +119,7 @@ namespace Ryujinx.Ava.Ui.Controls
public Rect Bounds { get; }
private readonly VulkanRendererControl _control;
private bool _isDestroyed;
public VulkanDrawOperation(VulkanRendererControl control)
{
@ -73,7 +129,12 @@ namespace Ryujinx.Ava.Ui.Controls
public void Dispose()
{
if (_isDestroyed)
{
return;
}
_isDestroyed = true;
}
public bool Equals(ICustomDrawOperation other)
@ -86,30 +147,33 @@ namespace Ryujinx.Ava.Ui.Controls
return Bounds.Contains(p);
}
public void Render(IDrawingContextImpl context)
public unsafe void Render(IDrawingContextImpl context)
{
if (_control.Image == null || _control.RenderSize.Width == 0 || _control.RenderSize.Height == 0)
if (_isDestroyed || _control.Image == null || _control.RenderSize.Width == 0 || _control.RenderSize.Height == 0 ||
context is not ISkiaDrawingContextImpl skiaDrawingContextImpl)
{
return;
}
var image = (PresentImageInfo)_control.Image;
var image = _control.GetImage();
if (context is not ISkiaDrawingContextImpl skiaDrawingContextImpl)
if (!image.State.IsValid)
{
_control._currentImage = null;
return;
}
_control._platformInterface.Device.QueueWaitIdle();
var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>();
image.Get();
var imageInfo = new GRVkImageInfo()
{
CurrentQueueFamily = _control._platformInterface.PhysicalDevice.QueueFamilyIndex,
Format = (uint)Format.R8G8B8A8Unorm,
Image = image.Image.Handle,
ImageLayout = (uint)ImageLayout.ColorAttachmentOptimal,
ImageLayout = (uint)ImageLayout.TransferSrcOptimal,
ImageTiling = (uint)ImageTiling.Optimal,
ImageUsageFlags = (uint)(ImageUsageFlags.ImageUsageColorAttachmentBit
| ImageUsageFlags.ImageUsageTransferSrcBit
@ -127,13 +191,15 @@ namespace Ryujinx.Ava.Ui.Controls
};
using var backendTexture = new GRBackendRenderTarget(
(int)_control.RenderSize.Width,
(int)_control.RenderSize.Height,
(int)image.Extent.Width,
(int)image.Extent.Height,
1,
imageInfo);
var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
using var surface = SKSurface.Create(
gpu.GrContext,
skiaDrawingContextImpl.GrContext,
backendTexture,
GRSurfaceOrigin.TopLeft,
SKColorType.Rgba8888);
@ -143,10 +209,11 @@ namespace Ryujinx.Ava.Ui.Controls
return;
}
var rect = new Rect(new Point(), _control.RenderSize);
var rect = new Rect(new Point(), new Size(image.Extent.Width, image.Extent.Height));
using var snapshot = surface.Snapshot();
skiaDrawingContextImpl.SkCanvas.DrawImage(snapshot, rect.ToSKRect(), _control.Bounds.ToSKRect(), new SKPaint());
skiaDrawingContextImpl.SkCanvas.DrawImage(snapshot, rect.ToSKRect(), _control.Bounds.ToSKRect(),
new SKPaint());
}
}
}

View File

@ -3,7 +3,6 @@ using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Svg.Skia;
using Avalonia.Threading;
using Avalonia.VisualTree;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Controls;
@ -24,7 +23,6 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;

View File

@ -38,6 +38,8 @@ namespace Ryujinx.Ava.Ui.ViewModels
{
internal class MainWindowViewModel : BaseModel
{
private const int HotKeyPressDelayMs = 500;
private readonly MainWindow _owner;
private ObservableCollection<ApplicationData> _applications;
private string _aspectStatusText;
@ -54,6 +56,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
private bool _isLoading;
private int _progressMaximum;
private int _progressValue;
private long _lastFullscreenToggle = Environment.TickCount64;
private bool _showLoadProgress;
private bool _showMenuAndStatusBar = true;
private bool _showStatusSeparator;
@ -929,6 +932,13 @@ namespace Ryujinx.Ava.Ui.ViewModels
public void ToggleFullscreen()
{
if (Environment.TickCount64 - _lastFullscreenToggle < HotKeyPressDelayMs)
{
return;
}
_lastFullscreenToggle = Environment.TickCount64;
WindowState state = _owner.WindowState;
if (state == WindowState.FullScreen)
@ -1085,6 +1095,11 @@ namespace Ryujinx.Ava.Ui.ViewModels
{
selection.Favorite = !selection.Favorite;
_owner.ApplicationLibrary.LoadAndSaveMetaData(selection.TitleId, appMetadata =>
{
appMetadata.Favorite = selection.Favorite;
});
RefreshView();
}
}

View File

@ -48,6 +48,11 @@ namespace Ryujinx.Ava.Ui.ViewModels
private int _graphicsBackendMultithreadingIndex;
private float _previousVolumeLevel;
private float _volume;
private bool _isVulkanAvailable = true;
private bool _directoryChanged = false;
private List<string> _gpuIds = new List<string>();
private KeyboardHotkeys _keyboardHotkeys;
private int _graphicsBackendIndex;
public int ResolutionScale
{
@ -97,6 +102,28 @@ namespace Ryujinx.Ava.Ui.ViewModels
}
}
public bool IsVulkanAvailable
{
get => _isVulkanAvailable;
set
{
_isVulkanAvailable = value;
OnPropertyChanged();
}
}
public bool DirectoryChanged
{
get => _directoryChanged;
set
{
_directoryChanged = value;
OnPropertyChanged();
}
}
public bool EnableDiscordIntegration { get; set; }
public bool CheckUpdatesOnStart { get; set; }
public bool ShowConfirmExit { get; set; }
@ -143,10 +170,10 @@ namespace Ryujinx.Ava.Ui.ViewModels
public int BaseStyleIndex { get; set; }
public int GraphicsBackendIndex
{
get => graphicsBackendIndex;
get => _graphicsBackendIndex;
set
{
graphicsBackendIndex = value;
_graphicsBackendIndex = value;
OnPropertyChanged();
OnPropertyChanged(nameof(IsVulkanSelected));
}
@ -170,14 +197,9 @@ namespace Ryujinx.Ava.Ui.ViewModels
public DateTimeOffset DateOffset { get; set; }
public TimeSpan TimeOffset { get; set; }
public AvaloniaList<TimeZone> TimeZones { get; set; }
public AvaloniaList<string> GameDirectories { get; set; }
public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; }
private KeyboardHotkeys _keyboardHotkeys;
private int graphicsBackendIndex;
private List<string> _gpuIds = new List<string>();
public KeyboardHotkeys KeyboardHotkeys
{
get => _keyboardHotkeys;
@ -233,20 +255,31 @@ namespace Ryujinx.Ava.Ui.ViewModels
if (!Program.UseVulkan)
{
var devices = VulkanRenderer.GetPhysicalDevices();
foreach (var device in devices)
if (devices.Length == 0)
{
_gpuIds.Add(device.Id);
names.Add($"{device.Name} {(device.IsDiscrete ? "(dGpu)" : "")}");
IsVulkanAvailable = false;
GraphicsBackendIndex = 1;
}
else
{
foreach (var device in devices)
{
_gpuIds.Add(device.Id);
names.Add($"{device.Name} {(device.IsDiscrete ? "(dGPU)" : "")}");
}
}
}
else
{
foreach (var device in VulkanPhysicalDevice.SuitableDevices)
{
_gpuIds.Add(VulkanInitialization.StringFromIdPair(device.Value.VendorID, device.Value.DeviceID));
_gpuIds.Add(
VulkanInitialization.StringFromIdPair(device.Value.VendorID, device.Value.DeviceID));
var value = device.Value;
var name = value.DeviceName;
names.Add($"{Marshal.PtrToStringAnsi((IntPtr)name)} {(device.Value.DeviceType == PhysicalDeviceType.DiscreteGpu ? "(dGpu)" : "")}");
names.Add(
$"{Marshal.PtrToStringAnsi((IntPtr)name)} {(device.Value.DeviceType == PhysicalDeviceType.DiscreteGpu ? "(dGPU)" : "")}");
}
}
@ -376,10 +409,14 @@ namespace Ryujinx.Ava.Ui.ViewModels
public async Task SaveSettings()
{
List<string> gameDirs = new List<string>(GameDirectories);
ConfigurationState config = ConfigurationState.Instance;
if (_directoryChanged)
{
List<string> gameDirs = new List<string>(GameDirectories);
config.Ui.GameDirs.Value = gameDirs;
}
if (_validTzRegions.Contains(TimeZone))
{
config.System.TimeZone.Value = TimeZone;
@ -444,7 +481,6 @@ namespace Ryujinx.Ava.Ui.ViewModels
config.System.SystemTimeOffset.Value = systemTimeOffset.Seconds;
config.Graphics.ShadersDumpPath.Value = ShaderDumpPath;
config.Ui.GameDirs.Value = gameDirs;
config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode;
config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode;

View File

@ -1,5 +1,4 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Threading;

View File

@ -1,4 +1,3 @@
using Avalonia;
using Avalonia.Interactivity;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models;

View File

@ -1,11 +1,9 @@
using Avalonia;
using Avalonia.Collections;
using Avalonia.Collections;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

View File

@ -131,52 +131,56 @@
<MenuItem Header="{locale:Locale MenuBarOptionsChangeLanguage}">
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="en_US"
Header="American English" />
CommandParameter="de_DE"
Header="Deutsch" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="pt_BR"
Header="Brazilian Portuguese" />
CommandParameter="en_US"
Header="English (US)" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="es_ES"
Header="Castilian Spanish" />
Header="Español (ES)" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="fr_FR"
Header="French" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="de_DE"
Header="German" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="el_GR"
Header="Greek" />
Header="Français" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="it_IT"
Header="Italian" />
Header="Italiano" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ko_KR"
Header="Korean" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ru_RU"
Header="Russian" />
CommandParameter="pt_BR"
Header="Português (BR)" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="tr_TR"
Header="Turkish" />
Header="Türkçe" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="el_GR"
Header="Ελληνικά" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ru_RU"
Header="Русский" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="zh_CN"
Header="Simplified Chinese" />
Header="简体中文" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="zh_TW"
Header="Traditional Chinese (Taiwan)" />
Header="繁體中文" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ja_JP"
Header="日本語" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ko_KR"
Header="한국어" />
</MenuItem>
<Separator />
<MenuItem

View File

@ -12,7 +12,6 @@ using Ryujinx.Ava.Ui.Applet;
using Ryujinx.Ava.Ui.Controls;
using Ryujinx.Ava.Ui.Models;
using Ryujinx.Ava.Ui.ViewModels;
using Ryujinx.Ava.Ui.Vulkan;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu;
@ -27,7 +26,6 @@ using Ryujinx.Ui.Common.Configuration;
using SixLabors.ImageSharp.PixelFormats;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@ -656,7 +654,12 @@ namespace Ryujinx.Ava.Ui.Windows
{
AppHost = null;
Dispatcher.UIThread.Post(Close);
Dispatcher.UIThread.Post(() =>
{
MainContent = null;
Close();
});
};
AppHost?.Stop();

View File

@ -519,7 +519,7 @@
HorizontalContentAlignment="Left"
ToolTip.Tip="{locale:Locale SettingsTabGraphicsBackendTooltip}"
SelectedIndex="{Binding GraphicsBackendIndex}">
<ComboBoxItem>
<ComboBoxItem IsVisible="{Binding IsVulkanAvailable}">
<TextBlock Text="Vulkan" />
</ComboBoxItem>
<ComboBoxItem>

View File

@ -162,6 +162,7 @@ namespace Ryujinx.Ava.Ui.Windows
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.GameDirectories.Contains(path))
{
ViewModel.GameDirectories.Add(path);
ViewModel.DirectoryChanged = true;
}
else
{
@ -170,6 +171,7 @@ namespace Ryujinx.Ava.Ui.Windows
if (!string.IsNullOrWhiteSpace(path))
{
ViewModel.GameDirectories.Add(path);
ViewModel.DirectoryChanged = true;
}
}
}
@ -181,6 +183,7 @@ namespace Ryujinx.Ava.Ui.Windows
foreach (string path in selected)
{
ViewModel.GameDirectories.Remove(path);
ViewModel.DirectoryChanged = true;
}
}
@ -232,10 +235,12 @@ namespace Ryujinx.Ava.Ui.Windows
ControllerSettings?.SaveCurrentProfile();
if (Owner is MainWindow window)
if (Owner is MainWindow window && ViewModel.DirectoryChanged)
{
window.ViewModel.LoadApplications();
}
ViewModel.DirectoryChanged = false;
}
protected override void OnClosed(EventArgs e)

View File

@ -1,4 +1,3 @@
using Avalonia;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Threading;
@ -18,7 +17,6 @@ using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

View File

@ -1,5 +1,3 @@
using Avalonia;
using Avalonia.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Modules;
using System;

Some files were not shown because too many files have changed in this diff Show More