Compare commits

..

28 Commits

Author SHA1 Message Date
Mary-nyan
09c9686498 misc: Use official names for NVDEC registers (#4192)
* misc: Uses official names for NVDEC registers

* Address gdkchan's comment

* Address comments
2023-01-02 14:48:46 +00:00
Mary-nyan
b6614c6ad5 chore: Update tests dependencies (#3978)
* chore: Update tests dependencies

* Apply TSR Berry suggestion to add a GC.SuppressFinalize in MemoryBlock.cs

* Ensure we wait for the test thread to be dead on PartialUnmap

* Use platform attribute for os specific tests

* Make P/Invoke methods private

* Downgrade NUnit3TestAdapter to 4.1.0

* test: Disable warning about platform compat for ThreadLocalMap()

Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
2023-01-01 17:35:29 +01:00
Emmanuel Hansen
b1d4b174a6 fix typo in left joycon sl binding (#4195) 2023-01-01 15:46:02 +01:00
Andrew Glaze
2b23463daa Filter hidden game files from the Game List (#4051)
* Filter “._” files from the game list

* Filter all hidden files from the game list

* Fix style

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

* merge OR expression into a pattern

* migrate from GetFiles/Directories to Enumerate

* Remove GetFilesInDirectory()

* Update Ryujinx.Ui.Common/App/ApplicationLibrary.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* add error handeling

* code cleanup

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-29 16:52:30 +01:00
gdkchan
9dfe81770a Use vector outputs for texture operations (#3939)
* Change AggregateType to include vector type counts

* Replace VariableType uses with AggregateType and delete VariableType

* Support new local vector types on SPIR-V and GLSL

* Start using vector outputs for texture operations

* Use vectors on more texture operations

* Use vector output for ImageLoad operations

* Replace all uses of single destination texture constructors with multi destination ones

* Update textureGatherOffsets replacement to split vector operations

* Shader cache version bump

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-29 16:09:34 +01:00
Luminoso-256
52c115a1f8 HLE: Add basic stubs to get Labo VR booting to title screen. (#4007)
* HLE: Add basic stubs to get Labo VR booting to title screen.

* Address code review

* Apply suggestions from code review (pt. 2)

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

* Apply suggestions from code review (pt. 3)

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Formatting: final batch?

Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Address last? bit of formatting

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-29 15:57:35 +01:00
riperiperi
e20abbf9cc Vulkan: Don't flush commands when creating most sync (#4087)
* Vulkan: Don't flush commands when creating most sync

When the WaitForIdle method is called, we create sync as some internal GPU method may read back written buffer data. Some games randomly intersperse compute dispatch into their render passes, which result in this happening an unbounded number of times depending on how many times they run compute.

Creating sync in Vulkan is expensive, as we need to flush the current command buffer so that it can be waited on. We have a limited number of active command buffers due to how we track resource usage, so submitting too many command buffers will force us to wait for them to return to the pool.

This PR allows less "important" sync (things which are less likely to be waited on) to wait on a command buffer's result without submitting it, instead relying on AutoFlush or another, more important sync to flush it later on.

Because of the possibility of us waiting for a command buffer that hasn't submitted yet, any thread needs to be able to force the active command buffer to submit. The ability to do this has been added to the backend multithreading via an "Interrupt", though it is not supported without multithreading.

OpenGL drivers should already be doing something similar so they don't blow up when creating lots of sync, which is why this hasn't been a problem for these games over there.

Improves Vulkan performance on Xenoblade DE, Pokemon Scarlet/Violet, and Zelda BOTW (still another large issue here)

* Add strict argument

This is technically a separate concern from whether the sync is a host syncpoint.

* Remove _interrupted variable

* Actually wait for the invoke

This is required by AMD GPUs, and also may have caused some issues on other GPUs.

* Remove unused using.

* I don't know why it added these ones.

* Address Feedback

* Fix typo
2022-12-29 15:39:04 +01:00
Isaac Marovitz
76671d63d4 Ava GUI: Restructure Ryujinx.Ava (#4165)
* Restructure `Ryujinx.Ava`

* Stylistic consistency

* Update Ryujinx.Ava/UI/Controls/UserEditor.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Controls/UserEditor.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Controls/UserSelector.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Controls/SaveManager.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Controls/SaveManager.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Fix redundancies

* Remove redunancies

* Add back elses

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2022-12-29 15:24:05 +01:00
TSRBerry
3d1a0bf374 [Headless] Fix for not receiving any SDL events on Linux (#4182)
* headless: Fix SDL events not working

* Add nuget.config
2022-12-29 15:09:18 +01:00
Mary-nyan
c20f3fbebd haydn: Add support for PCMFloat, PCM32 and PCM8 conversions (#4100)
* haydn: Add support for PCMFloat, PCM32 and PCM8 conversions

This adds support in the compatibility layer for other sample format
than PCM16.

This should help extends compatibility with soundio on devices that
doesn't expose PCM16.

I ommited PCM24 conversion for now as it's not simplest of all.

* Address TSRBerry's comment

* Address comments

* Fix conversion issue and clean up saturation usage

* Revert saturation changes

* Address gdkchan's comment
2022-12-28 19:34:30 -03:00
Berkan Diler
0d3b82477e Use new ArgumentNullException and ObjectDisposedException throw-helper API (#4163) 2022-12-27 20:27:11 +01:00
riperiperi
470be03c2f GPU: Add fallback when 16-bit formats are not supported (#4108)
* Add conversion for 16 bit RGBA formats (not supported in Rosetta)

* Rebase fix

Rebase fix

* Forgot to remove this

* Fix RGBA16 format conversion

* Add RGBA4 -> RGBA8 conversion

* Handle host stride alignment

* Address Feedback Part 1

* Can't count

* Don't zero out rgb when alpha is 0

* Separate RGBA4 and 5-bit component formats

Not sure of a better way to name them...

* Add A1B5G5R5 conversion

* Put this in the right place.

* Make format naming consistent for capabilities

* Change method names
2022-12-26 15:50:27 -03:00
Hunter
c963b3c804 Added Generic Math to BitUtils (#3929)
* Generic Math Update

Updated Several functions in Ryujinx.Common/Utilities/BitUtils to use generic math

* Updated BitUtil calls

* Removed Whitespace

* Switched decrement

* Fixed changed method calls.

The method calls were originally changed on accident due to me relying too much on intellisense doing stuff for me

* Update Ryujinx.Common/Utilities/BitUtils.cs

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

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-12-26 14:11:05 +00:00
gnisman
a4fdfb5f94 bsd::RecvFrom: verify output buffer size before writing socket address (#4135)
* bsd::RecvFrom: Ryujinx does not verify output buffer size before writing socket address

* Calculate the size of BsdSockAddr

* use bsdSockAddr variable

* Update Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSockAddr.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>

* set errno to ENOMEM in case we can't write the address to memory

* Update Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-26 13:49:26 +00:00
Berkan Diler
37d27c4c99 Some minor cleanups and optimizations (#4174)
* Replace Array.Clear(x, 0, x.Length) with Array.Clear(x)

* Use DateTime.UnixEpoch field

* Replace SHA256.ComputeHash calls with static SHA256.HashData call

More performant and avoids the need to initialize a SHA256 instance.
2022-12-24 14:30:39 -03:00
gdkchan
f906eb06c2 Implement a software ETC2 texture decoder (#4121)
* Implement a software ETC2 texture decoder

* Fix output size calculation for non-2D textures

* Address PR feedback
2022-12-21 20:39:58 -03:00
gdkchan
219f63ff4e Fix CPU FCVTN instruction implementation (slow path) (#4159)
* Fix CPU FCVTN instruction implementation (slow path)

* PPTC version bump
2022-12-21 23:05:58 +00:00
gdkchan
1cca3e99ab GPU: Force rebind when pool changes (#4129) 2022-12-21 17:35:28 -03:00
Ccl
55a23e5ec8 make UI display correct content in Chinese (#4155) 2022-12-21 17:20:37 -03:00
Mary-nyan
479d1fd8b0 hle: Handle GPU profiler and debugger device path correctly (#4138)
This fix a warning on "慟哭そして…" by handling correctly the debug mode
flag.

When debug mode isn't enabled, opening /dev/nvhost-dbg-gpu or /dev/nvhost-prof-gpu should fail with a not implemented error code.

This implement this behaviour and also define stubbed interfaces for
completness.
2022-12-21 18:23:11 +00:00
gdkchan
cb70e7bb30 Fix DrawArrays vertex buffer size (#4141) 2022-12-21 19:08:12 +01:00
riperiperi
c200a7b7c6 ARMeilleure: Hash _data pointer instead of value for Operand (#4156)
I noticed a weirdly high cost for dictionary accesses from MarkLabel etc. Turns out that the hash code was always the same for labels, so the whole point of having a dictionary was missed and it was putting everything in the same bucket. I made it always hash the _data pointer as that's a good source of identifiable and "random" data.
2022-12-21 02:28:18 +01:00
Emmanuel Hansen
6268170a10 fix sw kbd row collision (#4144) 2022-12-19 15:09:36 -03:00
gdkchan
ee0f9b03a4 Eliminate zero-extension moves in more cases on 32-bit games (#4140)
* Eliminate zero-extension moves in more cases on 32-bit games

* PPTC version bump

* Revert X86Optimizer changes
2022-12-19 14:45:58 -03:00
gdkchan
f93c5f006a Revert "ARMeilleure: Add initial support for AVX512(EVEX encoding) (#3663)" (#4145)
This reverts commit 295fbd0542.
2022-12-18 20:21:10 -03:00
Wunk
295fbd0542 ARMeilleure: Add initial support for AVX512(EVEX encoding) (#3663)
* ARMeilleure: Add AVX512{F,VL,DQ,BW} detection

Add `UseAvx512Ortho` and `UseAvx512OrthoFloat` optimization flags as
short-hands for `F+VL` and `F+VL+DQ`.

* ARMeilleure: Add initial support for EVEX instruction encoding

Does not implement rounding, or exception controls.

* ARMeilleure: Add `X86Vpternlogd`

Accelerates the vector-`Not` instruction.

* ARMeilleure: Add check for `OSXSAVE` for AVX{2,512}

* ARMeilleure: Add check for `XCR0` flags

Add XCR0 register checks for AVX and AVX512F, following the guidelines
from section 14.3 and 15.2 from the Intel Architecture Software
Developer's Manual.

* ARMeilleure: Increment InternalVersion

* ARMeilleure: Remove redundant `ReProtect` and `Dispose`, formatting

* ARMeilleure: Move XCR0 procedure to GetXcr0Eax

* ARMeilleure: Add `XCR0` to `FeatureInfo` structure

* ARMeilleure: Utilize `ReadOnlySpan` for Xcr0 assembly

Avoids an additional allocation

* ARMeilleure: Formatting fixes
2022-12-18 16:46:13 -03:00
Mary-nyan
d7310d7a1c hle: Fix wrong conversion in UserPresence.ToString (#4142)
This fixes an error from #3805 that caused a wrong conversion of ``AppKeyValueStorage`` to string.
As that information isn't really relevant without appropriate parsing, it was removed from ``ToString``.

This should get ride of "bell warning" in Mario Kart 8 when entering Time Trials.
2022-12-18 14:23:19 +00:00
dependabot[bot]
8c50943a2e nuget: bump Microsoft.NET.Test.Sdk from 17.4.0 to 17.4.1 (#4137)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.4.0 to 17.4.1.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.4.0...v17.4.1)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-17 01:19:04 +01:00
244 changed files with 3484 additions and 1938 deletions

3
.gitignore vendored
View File

@@ -125,6 +125,9 @@ ClientBin/
packages/* packages/*
*.config *.config
# Include nuget.config
!nuget.config
# RIA/Silverlight projects # RIA/Silverlight projects
Generated_Code/ Generated_Code/

View File

@@ -1587,6 +1587,12 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
// We can eliminate the move if source is already 32-bit and the registers are the same.
if (dest.Value == source.Value && source.Type == OperandType.I32)
{
return;
}
context.Assembler.Mov(dest, source, OperandType.I32); context.Assembler.Mov(dest, source, OperandType.I32);
} }

View File

@@ -80,10 +80,7 @@ namespace ARMeilleure.Common
{ {
get get
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
lock (_pages) lock (_pages)
{ {
@@ -100,10 +97,7 @@ namespace ARMeilleure.Common
/// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception> /// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception>
public AddressTable(Level[] levels) public AddressTable(Level[] levels)
{ {
if (levels == null) ArgumentNullException.ThrowIfNull(levels);
{
throw new ArgumentNullException(nameof(levels));
}
if (levels.Length < 2) if (levels.Length < 2)
{ {
@@ -141,10 +135,7 @@ namespace ARMeilleure.Common
/// <exception cref="ArgumentException"><paramref name="address"/> is not mapped</exception> /// <exception cref="ArgumentException"><paramref name="address"/> is not mapped</exception>
public ref TEntry GetValue(ulong address) public ref TEntry GetValue(ulong address)
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
if (!IsValid(address)) if (!IsValid(address))
{ {

View File

@@ -49,10 +49,7 @@ namespace ARMeilleure.Common
{ {
get get
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
return ref _countTable.GetValue(_index); return ref _countTable.GetValue(_index);
} }

View File

@@ -53,10 +53,7 @@ namespace ARMeilleure.Common
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception> /// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
public int Allocate() public int Allocate()
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
lock (_allocated) lock (_allocated)
{ {
@@ -83,10 +80,7 @@ namespace ARMeilleure.Common
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception> /// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
public void Free(int index) public void Free(int index)
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
lock (_allocated) lock (_allocated)
{ {
@@ -108,10 +102,7 @@ namespace ARMeilleure.Common
/// <exception cref="ArgumentException">Entry at <paramref name="index"/> is not allocated</exception> /// <exception cref="ArgumentException">Entry at <paramref name="index"/> is not allocated</exception>
public ref TEntry GetValue(int index) public ref TEntry GetValue(int index)
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
lock (_allocated) lock (_allocated)
{ {

View File

@@ -381,7 +381,7 @@ namespace ARMeilleure.Instructions
for (int index = 0; index < elems; index++) for (int index = 0; index < elems; index++)
{ {
Operand ne = context.VectorExtract(type, GetVec(op.Rn), 0); Operand ne = context.VectorExtract(type, GetVec(op.Rn), index);
if (sizeF == 0) if (sizeF == 0)
{ {
@@ -389,8 +389,6 @@ namespace ARMeilleure.Instructions
Operand e = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne); Operand e = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
context.LoadFromContext(); context.LoadFromContext();
e = context.ZeroExtend16(OperandType.I64, e);
res = EmitVectorInsert(context, res, e, part + index, 1); res = EmitVectorInsert(context, res, e, part + index, 1);
} }
else /* if (sizeF == 1) */ else /* if (sizeF == 1) */

View File

@@ -48,10 +48,7 @@ namespace ARMeilleure.IntermediateRepresentation
public void AddSuccessor(BasicBlock block) public void AddSuccessor(BasicBlock block)
{ {
if (block == null) ArgumentNullException.ThrowIfNull(block);
{
ThrowNull(nameof(block));
}
if ((uint)_succCount + 1 > MaxSuccessors) if ((uint)_succCount + 1 > MaxSuccessors)
{ {
@@ -100,10 +97,7 @@ namespace ARMeilleure.IntermediateRepresentation
public void SetSuccessor(int index, BasicBlock block) public void SetSuccessor(int index, BasicBlock block)
{ {
if (block == null) ArgumentNullException.ThrowIfNull(block);
{
ThrowNull(nameof(block));
}
if ((uint)index >= (uint)_succCount) if ((uint)index >= (uint)_succCount)
{ {
@@ -144,7 +138,6 @@ namespace ARMeilleure.IntermediateRepresentation
} }
} }
private static void ThrowNull(string name) => throw new ArgumentNullException(name);
private static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name); private static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name);
private static void ThrowSuccessorOverflow() => throw new OverflowException($"BasicBlock can only have {MaxSuccessors} successors."); private static void ThrowSuccessorOverflow() => throw new OverflowException($"BasicBlock can only have {MaxSuccessors} successors.");

View File

@@ -378,14 +378,7 @@ namespace ARMeilleure.IntermediateRepresentation
public override int GetHashCode() public override int GetHashCode()
{ {
if (Kind == OperandKind.LocalVariable) return ((ulong)_data).GetHashCode();
{
return base.GetHashCode();
}
else
{
return (int)Value ^ ((int)Kind << 16) ^ ((int)Type << 20);
}
} }
public bool Equals(Operand operand) public bool Equals(Operand operand)

View File

@@ -25,10 +25,7 @@ namespace ARMeilleure.Translation
public static Delegate GetDelegate(MethodInfo info) public static Delegate GetDelegate(MethodInfo info)
{ {
if (info == null) ArgumentNullException.ThrowIfNull(info);
{
throw new ArgumentNullException(nameof(info));
}
Type[] parameters = info.GetParameters().Select(pI => pI.ParameterType).ToArray(); Type[] parameters = info.GetParameters().Select(pI => pI.ParameterType).ToArray();
Type returnType = info.ReturnType; Type returnType = info.ReturnType;

View File

@@ -35,10 +35,7 @@ namespace ARMeilleure.Translation
public static IntPtr GetDelegateFuncPtr(MethodInfo info) public static IntPtr GetDelegateFuncPtr(MethodInfo info)
{ {
if (info == null) ArgumentNullException.ThrowIfNull(info);
{
throw new ArgumentNullException(nameof(info));
}
string key = GetKey(info); string key = GetKey(info);
@@ -52,10 +49,7 @@ namespace ARMeilleure.Translation
public static int GetDelegateIndex(MethodInfo info) public static int GetDelegateIndex(MethodInfo info)
{ {
if (info == null) ArgumentNullException.ThrowIfNull(info);
{
throw new ArgumentNullException(nameof(info));
}
string key = GetKey(info); string key = GetKey(info);

View File

@@ -67,10 +67,7 @@ namespace ARMeilleure.Translation
/// <returns>True if the value was added, false if the start key was already in the dictionary</returns> /// <returns>True if the value was added, false if the start key was already in the dictionary</returns>
public bool AddOrUpdate(K start, K end, V value, Func<K, V, V> updateFactoryCallback) public bool AddOrUpdate(K start, K end, V value, Func<K, V, V> updateFactoryCallback)
{ {
if (value == null) ArgumentNullException.ThrowIfNull(value);
{
throw new ArgumentNullException(nameof(value));
}
return BSTInsert(start, end, value, updateFactoryCallback, out IntervalTreeNode<K, V> node); return BSTInsert(start, end, value, updateFactoryCallback, out IntervalTreeNode<K, V> node);
} }
@@ -85,10 +82,7 @@ namespace ARMeilleure.Translation
/// <returns><paramref name="value"/> if <paramref name="start"/> is not yet on the tree, or the existing value otherwise</returns> /// <returns><paramref name="value"/> if <paramref name="start"/> is not yet on the tree, or the existing value otherwise</returns>
public V GetOrAdd(K start, K end, V value) public V GetOrAdd(K start, K end, V value)
{ {
if (value == null) ArgumentNullException.ThrowIfNull(value);
{
throw new ArgumentNullException(nameof(value));
}
BSTInsert(start, end, value, null, out IntervalTreeNode<K, V> node); BSTInsert(start, end, value, null, out IntervalTreeNode<K, V> node);
return node.Value; return node.Value;
@@ -152,10 +146,7 @@ namespace ARMeilleure.Translation
/// <returns>Node reference in the tree</returns> /// <returns>Node reference in the tree</returns>
private IntervalTreeNode<K, V> GetNode(K key) private IntervalTreeNode<K, V> GetNode(K key)
{ {
if (key == null) ArgumentNullException.ThrowIfNull(key);
{
throw new ArgumentNullException(nameof(key));
}
IntervalTreeNode<K, V> node = _root; IntervalTreeNode<K, V> node = _root;
while (node != null) while (node != null)

View File

@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 3713; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 4159; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";

View File

@@ -140,7 +140,7 @@ namespace ARMeilleure.Translation
} }
} }
Array.Clear(localDefs, 0, localDefs.Length); Array.Clear(localDefs);
} }
} }

View File

@@ -30,10 +30,7 @@ namespace ARMeilleure.Translation
{ {
get get
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
return _dispatchStub.Value; return _dispatchStub.Value;
} }
@@ -47,10 +44,7 @@ namespace ARMeilleure.Translation
{ {
get get
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
return _slowDispatchStub.Value; return _slowDispatchStub.Value;
} }
@@ -64,10 +58,7 @@ namespace ARMeilleure.Translation
{ {
get get
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(null);
}
return _dispatchLoop.Value; return _dispatchLoop.Value;
} }
@@ -81,7 +72,9 @@ namespace ARMeilleure.Translation
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
public TranslatorStubs(Translator translator) public TranslatorStubs(Translator translator)
{ {
_translator = translator ?? throw new ArgumentNullException(nameof(translator)); ArgumentNullException.ThrowIfNull(translator);
_translator = translator;
_dispatchStub = new(GenerateDispatchStub, isThreadSafe: true); _dispatchStub = new(GenerateDispatchStub, isThreadSafe: true);
_dispatchLoop = new(GenerateDispatchLoop, isThreadSafe: true); _dispatchLoop = new(GenerateDispatchLoop, isThreadSafe: true);
} }

View File

@@ -22,10 +22,10 @@
<PackageVersion Include="LibHac" Version="0.17.0" /> <PackageVersion Include="LibHac" Version="0.17.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" /> <PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" /> <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.0" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" /> <PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NUnit" Version="3.13.3" /> <PackageVersion Include="NUnit" Version="3.13.3" />
<PackageVersion Include="NUnit3TestAdapter" Version="3.17.0" /> <PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageVersion Include="OpenTK.Core" Version="4.7.5" /> <PackageVersion Include="OpenTK.Core" Version="4.7.5" />
<PackageVersion Include="OpenTK.Graphics" Version="4.7.5" /> <PackageVersion Include="OpenTK.Graphics" Version="4.7.5" />
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.5" /> <PackageVersion Include="OpenTK.OpenAL" Version="4.7.5" />

View File

@@ -51,6 +51,40 @@ namespace Ryujinx.Audio.Backends.CompatLayer
}; };
} }
private SampleFormat SelectHardwareSampleFormat(SampleFormat targetSampleFormat)
{
if (_realDriver.SupportsSampleFormat(targetSampleFormat))
{
return targetSampleFormat;
}
// Attempt conversion from PCM16.
if (targetSampleFormat == SampleFormat.PcmInt16)
{
// Prefer PCM32 if we need to convert.
if (_realDriver.SupportsSampleFormat(SampleFormat.PcmInt32))
{
return SampleFormat.PcmInt32;
}
// If not supported, PCM float provides the best quality with a cost lower than PCM24.
if (_realDriver.SupportsSampleFormat(SampleFormat.PcmFloat))
{
return SampleFormat.PcmFloat;
}
// TODO: Implement PCM24 conversion.
// If nothing is truly supported, attempt PCM8 at the cost of loosing quality.
if (_realDriver.SupportsSampleFormat(SampleFormat.PcmInt8))
{
return SampleFormat.PcmInt8;
}
}
throw new ArgumentException("No valid sample format configuration found!");
}
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume) public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
{ {
if (channelCount == 0) if (channelCount == 0)
@@ -77,15 +111,26 @@ namespace Ryujinx.Audio.Backends.CompatLayer
throw new NotImplementedException(); throw new NotImplementedException();
} }
SampleFormat hardwareSampleFormat = SelectHardwareSampleFormat(sampleFormat);
uint hardwareChannelCount = SelectHardwareChannelCount(channelCount); uint hardwareChannelCount = SelectHardwareChannelCount(channelCount);
IHardwareDeviceSession realSession = _realDriver.OpenDeviceSession(direction, memoryManager, sampleFormat, sampleRate, hardwareChannelCount, volume); IHardwareDeviceSession realSession = _realDriver.OpenDeviceSession(direction, memoryManager, hardwareSampleFormat, sampleRate, hardwareChannelCount, volume);
if (hardwareChannelCount == channelCount) if (hardwareChannelCount == channelCount && hardwareSampleFormat == sampleFormat)
{ {
return realSession; return realSession;
} }
if (hardwareSampleFormat != sampleFormat)
{
Logger.Warning?.Print(LogClass.Audio, $"{sampleFormat} isn't supported by the audio device, conversion to {hardwareSampleFormat} will happen.");
if (hardwareSampleFormat < sampleFormat)
{
Logger.Warning?.Print(LogClass.Audio, $"{hardwareSampleFormat} has lower quality than {sampleFormat}, expect some loss in audio fidelity.");
}
}
if (direction == Direction.Input) if (direction == Direction.Input)
{ {
Logger.Warning?.Print(LogClass.Audio, $"The selected audio backend doesn't support the requested audio input configuration, fallback to dummy..."); Logger.Warning?.Print(LogClass.Audio, $"The selected audio backend doesn't support the requested audio input configuration, fallback to dummy...");
@@ -103,7 +148,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
} }
// If we need to do post processing before sending to the hardware device, wrap around it. // If we need to do post processing before sending to the hardware device, wrap around it.
return new CompatLayerHardwareDeviceSession(realSessionOutputBase, channelCount); return new CompatLayerHardwareDeviceSession(realSessionOutputBase, sampleFormat, channelCount);
} }
public bool SupportsChannelCount(uint channelCount) public bool SupportsChannelCount(uint channelCount)

View File

@@ -1,5 +1,6 @@
using Ryujinx.Audio.Backends.Common; using Ryujinx.Audio.Backends.Common;
using Ryujinx.Audio.Common; using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Dsp;
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -8,11 +9,13 @@ namespace Ryujinx.Audio.Backends.CompatLayer
class CompatLayerHardwareDeviceSession : HardwareDeviceSessionOutputBase class CompatLayerHardwareDeviceSession : HardwareDeviceSessionOutputBase
{ {
private HardwareDeviceSessionOutputBase _realSession; private HardwareDeviceSessionOutputBase _realSession;
private SampleFormat _userSampleFormat;
private uint _userChannelCount; private uint _userChannelCount;
public CompatLayerHardwareDeviceSession(HardwareDeviceSessionOutputBase realSession, uint userChannelCount) : base(realSession.MemoryManager, realSession.RequestedSampleFormat, realSession.RequestedSampleRate, userChannelCount) public CompatLayerHardwareDeviceSession(HardwareDeviceSessionOutputBase realSession, SampleFormat userSampleFormat, uint userChannelCount) : base(realSession.MemoryManager, realSession.RequestedSampleFormat, realSession.RequestedSampleRate, userChannelCount)
{ {
_realSession = realSession; _realSession = realSession;
_userSampleFormat = userSampleFormat;
_userChannelCount = userChannelCount; _userChannelCount = userChannelCount;
} }
@@ -38,53 +41,86 @@ namespace Ryujinx.Audio.Backends.CompatLayer
public override void QueueBuffer(AudioBuffer buffer) public override void QueueBuffer(AudioBuffer buffer)
{ {
SampleFormat realSampleFormat = _realSession.RequestedSampleFormat;
if (_userSampleFormat != realSampleFormat)
{
if (_userSampleFormat != SampleFormat.PcmInt16)
{
throw new NotImplementedException("Converting formats other than PCM16 is not supported.");
}
int userSampleCount = buffer.Data.Length / BackendHelper.GetSampleSize(_userSampleFormat);
ReadOnlySpan<short> samples = MemoryMarshal.Cast<byte, short>(buffer.Data);
byte[] convertedSamples = new byte[BackendHelper.GetSampleSize(realSampleFormat) * userSampleCount];
switch (realSampleFormat)
{
case SampleFormat.PcmInt8:
PcmHelper.Convert(MemoryMarshal.Cast<byte, sbyte>(convertedSamples), samples);
break;
case SampleFormat.PcmInt32:
PcmHelper.Convert(MemoryMarshal.Cast<byte, int>(convertedSamples), samples);
break;
case SampleFormat.PcmFloat:
PcmHelper.ConvertSampleToPcmFloat(MemoryMarshal.Cast<byte, float>(convertedSamples), samples);
break;
default:
throw new NotImplementedException($"Sample format conversion from {_userSampleFormat} to {realSampleFormat} not implemented.");
}
buffer.Data = convertedSamples;
}
_realSession.QueueBuffer(buffer); _realSession.QueueBuffer(buffer);
} }
public override bool RegisterBuffer(AudioBuffer buffer, byte[] samples) public override bool RegisterBuffer(AudioBuffer buffer, byte[] samples)
{ {
if (RequestedSampleFormat != SampleFormat.PcmInt16)
{
throw new NotImplementedException("Downmixing formats other than PCM16 is not supported.");
}
if (samples == null) if (samples == null)
{ {
return false; return false;
} }
short[] downmixedBufferPCM16; if (_userChannelCount != _realSession.RequestedChannelCount)
ReadOnlySpan<short> samplesPCM16 = MemoryMarshal.Cast<byte, short>(samples);
if (_userChannelCount == 6)
{ {
downmixedBufferPCM16 = Downmixing.DownMixSurroundToStereo(samplesPCM16); if (_userSampleFormat != SampleFormat.PcmInt16)
if (_realSession.RequestedChannelCount == 1)
{ {
downmixedBufferPCM16 = Downmixing.DownMixStereoToMono(downmixedBufferPCM16); throw new NotImplementedException("Downmixing formats other than PCM16 is not supported.");
} }
}
else if (_userChannelCount == 2 && _realSession.RequestedChannelCount == 1)
{
downmixedBufferPCM16 = Downmixing.DownMixStereoToMono(samplesPCM16);
}
else
{
throw new NotImplementedException($"Downmixing from {_userChannelCount} to {_realSession.RequestedChannelCount} not implemented.");
}
byte[] downmixedBuffer = MemoryMarshal.Cast<short, byte>(downmixedBufferPCM16).ToArray(); ReadOnlySpan<short> samplesPCM16 = MemoryMarshal.Cast<byte, short>(samples);
if (_userChannelCount == 6)
{
samplesPCM16 = Downmixing.DownMixSurroundToStereo(samplesPCM16);
if (_realSession.RequestedChannelCount == 1)
{
samplesPCM16 = Downmixing.DownMixStereoToMono(samplesPCM16);
}
}
else if (_userChannelCount == 2 && _realSession.RequestedChannelCount == 1)
{
samplesPCM16 = Downmixing.DownMixStereoToMono(samplesPCM16);
}
else
{
throw new NotImplementedException($"Downmixing from {_userChannelCount} to {_realSession.RequestedChannelCount} not implemented.");
}
samples = MemoryMarshal.Cast<short, byte>(samplesPCM16).ToArray();
}
AudioBuffer fakeBuffer = new AudioBuffer AudioBuffer fakeBuffer = new AudioBuffer
{ {
BufferTag = buffer.BufferTag, BufferTag = buffer.BufferTag,
DataPointer = buffer.DataPointer, DataPointer = buffer.DataPointer,
DataSize = (ulong)downmixedBuffer.Length DataSize = (ulong)samples.Length
}; };
bool result = _realSession.RegisterBuffer(fakeBuffer, downmixedBuffer); bool result = _realSession.RegisterBuffer(fakeBuffer, samples);
if (result) if (result)
{ {

View File

@@ -23,7 +23,7 @@ namespace Ryujinx.Audio.Renderer.Common
if (size != 0) if (size != 0)
{ {
ulong alignedOffset = BitUtils.AlignUp(Offset, align); ulong alignedOffset = BitUtils.AlignUp<ulong>(Offset, (ulong)align);
if (alignedOffset + size <= (ulong)BackingMemory.Length) if (alignedOffset + size <= (ulong)BackingMemory.Length)
{ {
@@ -55,7 +55,7 @@ namespace Ryujinx.Audio.Renderer.Common
public static ulong GetTargetSize<T>(ulong currentSize, ulong count, int align) where T : unmanaged public static ulong GetTargetSize<T>(ulong currentSize, ulong count, int align) where T : unmanaged
{ {
return BitUtils.AlignUp(currentSize, align) + (ulong)Unsafe.SizeOf<T>() * count; return BitUtils.AlignUp<ulong>(currentSize, (ulong)align) + (ulong)Unsafe.SizeOf<T>() * count;
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp namespace Ryujinx.Audio.Renderer.Dsp
@@ -23,6 +24,44 @@ namespace Ryujinx.Audio.Renderer.Dsp
return GetCountToDecode(startSampleOffset, endSampleOffset, offset, count) * Unsafe.SizeOf<T>(); return GetCountToDecode(startSampleOffset, endSampleOffset, offset, count) * Unsafe.SizeOf<T>();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float ConvertSampleToPcmFloat(short sample)
{
return (float)sample / short.MaxValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short ConvertSampleToPcmInt16(float sample)
{
return Saturate(sample * short.MaxValue);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TOutput ConvertSample<TInput, TOutput>(TInput value) where TInput: INumber<TInput>, IMinMaxValue<TInput> where TOutput : INumber<TOutput>, IMinMaxValue<TOutput>
{
TInput conversionRate = TInput.CreateSaturating(TOutput.MaxValue / TOutput.CreateSaturating(TInput.MaxValue));
return TOutput.CreateSaturating(value * conversionRate);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Convert<TInput, TOutput>(Span<TOutput> output, ReadOnlySpan<TInput> input) where TInput : INumber<TInput>, IMinMaxValue<TInput> where TOutput : INumber<TOutput>, IMinMaxValue<TOutput>
{
for (int i = 0; i < input.Length; i++)
{
output[i] = ConvertSample<TInput, TOutput>(input[i]);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ConvertSampleToPcmFloat(Span<float> output, ReadOnlySpan<short> input)
{
for (int i = 0; i < input.Length; i++)
{
output[i] = ConvertSampleToPcmFloat(input[i]);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Decode(Span<short> output, ReadOnlySpan<short> input, int startSampleOffset, int endSampleOffset, int channelIndex, int channelCount) public static int Decode(Span<short> output, ReadOnlySpan<short> input, int startSampleOffset, int endSampleOffset, int channelIndex, int channelCount)
{ {
@@ -53,7 +92,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
for (int i = 0; i < decodedCount; i++) for (int i = 0; i < decodedCount; i++)
{ {
output[i] = (short)(input[i * channelCount + channelIndex] * short.MaxValue); output[i] = ConvertSampleToPcmInt16(input[i * channelCount + channelIndex]);
} }
return decodedCount; return decodedCount;

View File

@@ -167,7 +167,7 @@ namespace Ryujinx.Audio.Renderer.Server
return ResultCode.WorkBufferTooSmall; return ResultCode.WorkBufferTooSmall;
} }
_depopBuffer = workBufferAllocator.Allocate<float>((ulong)BitUtils.AlignUp(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment); _depopBuffer = workBufferAllocator.Allocate<float>(BitUtils.AlignUp<ulong>(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment);
if (_depopBuffer.IsEmpty) if (_depopBuffer.IsEmpty)
{ {
@@ -772,7 +772,7 @@ namespace Ryujinx.Audio.Renderer.Server
size = WorkBufferAllocator.GetTargetSize<float>(size, Constants.TargetSampleCount * (Constants.VoiceChannelCountMax + parameter.MixBufferCount) * (parameter.SinkCount + parameter.SubMixBufferCount), 0x10); size = WorkBufferAllocator.GetTargetSize<float>(size, Constants.TargetSampleCount * (Constants.VoiceChannelCountMax + parameter.MixBufferCount) * (parameter.SinkCount + parameter.SubMixBufferCount), 0x10);
// Depop buffer // Depop buffer
size = WorkBufferAllocator.GetTargetSize<float>(size, (ulong)BitUtils.AlignUp(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment); size = WorkBufferAllocator.GetTargetSize<float>(size, BitUtils.AlignUp<ulong>(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment);
// Voice // Voice
size = WorkBufferAllocator.GetTargetSize<VoiceState>(size, parameter.VoiceCount, VoiceState.Alignment); size = WorkBufferAllocator.GetTargetSize<VoiceState>(size, parameter.VoiceCount, VoiceState.Alignment);
@@ -804,10 +804,10 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
ulong performanceMetricsPerFramesSize = PerformanceManager.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter, ref behaviourContext) * (parameter.PerformanceMetricFramesCount + 1) + 0xC; ulong performanceMetricsPerFramesSize = PerformanceManager.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter, ref behaviourContext) * (parameter.PerformanceMetricFramesCount + 1) + 0xC;
size += BitUtils.AlignUp(performanceMetricsPerFramesSize, Constants.PerformanceMetricsPerFramesSizeAlignment); size += BitUtils.AlignUp<ulong>(performanceMetricsPerFramesSize, Constants.PerformanceMetricsPerFramesSizeAlignment);
} }
return BitUtils.AlignUp(size, Constants.WorkBufferAlignment); return BitUtils.AlignUp<ulong>(size, Constants.WorkBufferAlignment);
} }
public ResultCode QuerySystemEvent(out IWritableEvent systemEvent) public ResultCode QuerySystemEvent(out IWritableEvent systemEvent)

View File

@@ -4,6 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sty="using:FluentAvalonia.Styling"> xmlns:sty="using:FluentAvalonia.Styling">
<Application.Styles> <Application.Styles>
<sty:FluentAvaloniaTheme UseSystemThemeOnWindows="False" /> <sty:FluentAvaloniaTheme PreferSystemTheme="False" />
</Application.Styles> </Application.Styles>
</Application> </Application>

View File

@@ -5,8 +5,9 @@ using Avalonia.Styling;
using Avalonia.Threading; using Avalonia.Threading;
using FluentAvalonia.Styling; using FluentAvalonia.Styling;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;

View File

@@ -11,9 +11,10 @@ using Ryujinx.Audio.Integration;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;

View File

@@ -12,8 +12,9 @@ using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils; using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;

View File

@@ -1,4 +1,4 @@
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;

View File

@@ -3,7 +3,7 @@ using System.Runtime.Versioning;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Avalonia; using Avalonia;
namespace Ryujinx.Ava.Ui.Helper namespace Ryujinx.Ava.UI.Helper
{ {
public delegate void UpdateBoundsCallbackDelegate(Rect rect); public delegate void UpdateBoundsCallbackDelegate(Rect rect);

View File

@@ -7,8 +7,9 @@ using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Ryujinx.Ava; using Ryujinx.Ava;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Ui.Common.Helper; using Ryujinx.Ui.Common.Helper;

View File

@@ -1,7 +1,7 @@
using ARMeilleure.Translation.PTC; using ARMeilleure.Translation.PTC;
using Avalonia; using Avalonia;
using Avalonia.Threading; using Avalonia.Threading;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.GraphicsDriver; using Ryujinx.Common.GraphicsDriver;

View File

@@ -2,8 +2,9 @@ using Avalonia.Controls;
using Avalonia.Threading; using Avalonia.Threading;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.HOS.Applets; using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types; using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
@@ -11,7 +12,7 @@ using Ryujinx.HLE.Ui;
using System; using System;
using System.Threading; using System.Threading;
namespace Ryujinx.Ava.Ui.Applet namespace Ryujinx.Ava.UI.Applet
{ {
internal class AvaHostUiHandler : IHostUiHandler internal class AvaHostUiHandler : IHostUiHandler
{ {

View File

@@ -3,15 +3,16 @@ using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Threading; using Avalonia.Threading;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.HLE.Ui; using Ryujinx.HLE.Ui;
using System; using System;
using System.Threading; using System.Threading;
using HidKey = Ryujinx.Common.Configuration.Hid.Key; using HidKey = Ryujinx.Common.Configuration.Hid.Key;
namespace Ryujinx.Ava.Ui.Applet namespace Ryujinx.Ava.UI.Applet
{ {
class AvaloniaDynamicTextInputHandler : IDynamicTextInputHandler class AvaloniaDynamicTextInputHandler : IDynamicTextInputHandler
{ {

View File

@@ -1,9 +1,9 @@
using Avalonia.Media; using Avalonia.Media;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.HLE.Ui; using Ryujinx.HLE.Ui;
using System; using System;
namespace Ryujinx.Ava.Ui.Applet namespace Ryujinx.Ava.UI.Applet
{ {
class AvaloniaHostUiTheme : IHostUiTheme class AvaloniaHostUiTheme : IHostUiTheme
{ {

View File

@@ -1,11 +1,10 @@
<Window <Window
x:Class="Ryujinx.Ava.Ui.Applet.ErrorAppletWindow" x:Class="Ryujinx.Ava.UI.Applet.ErrorAppletWindow"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:window="clr-namespace:Ryujinx.Ava.Ui.Windows"
Title="{locale:Locale ErrorWindowTitle}" Title="{locale:Locale ErrorWindowTitle}"
Width="450" Width="450"
Height="340" Height="340"

View File

@@ -3,10 +3,10 @@ using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Threading; using Avalonia.Threading;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Windows;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Applet namespace Ryujinx.Ava.UI.Applet
{ {
internal partial class ErrorAppletWindow : StyleableWindow internal partial class ErrorAppletWindow : StyleableWindow
{ {

View File

@@ -1,10 +1,9 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.Ui.Controls.SwkbdAppletDialog" x:Class="Ryujinx.Ava.UI.Controls.SwkbdAppletDialog"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:window="clr-namespace:Ryujinx.Ava.Ui.Windows"
Width="400" Width="400"
mc:Ignorable="d" mc:Ignorable="d"
Focusable="True"> Focusable="True">
@@ -45,7 +44,7 @@
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<TextBox <TextBox
Name="Input" Name="Input"
Grid.Row="2" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Center" VerticalAlignment="Center"

View File

@@ -6,12 +6,13 @@ using Avalonia.Media;
using FluentAvalonia.Core; using FluentAvalonia.Core;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.HLE.HOS.Applets; using Ryujinx.HLE.HOS.Applets;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
internal partial class SwkbdAppletDialog : UserControl internal partial class SwkbdAppletDialog : UserControl
{ {

View File

@@ -1,19 +1,19 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.Ui.Controls.GameGridView" x:Class="Ryujinx.Ava.UI.Controls.GameGridView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Ryujinx.Ava.Ui.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox" xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
d:DesignHeight="450" d:DesignHeight="450"
d:DesignWidth="800" d:DesignWidth="800"
mc:Ignorable="d" mc:Ignorable="d"
Focusable="True"> Focusable="True">
<UserControl.Resources> <UserControl.Resources>
<controls:BitmapArrayValueConverter x:Key="ByteImage" /> <helpers:BitmapArrayValueConverter x:Key="ByteImage" />
<MenuFlyout x:Key="GameContextMenu" Opened="MenuBase_OnMenuOpened"> <MenuFlyout x:Key="GameContextMenu" Opened="MenuBase_OnMenuOpened">
<MenuItem <MenuItem
Command="{Binding ToggleFavorite}" Command="{Binding ToggleFavorite}"

View File

@@ -4,11 +4,12 @@ using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using LibHac.Common; using LibHac.Common;
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ui.App.Common; using Ryujinx.Ui.App.Common;
using System; using System;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class GameGridView : UserControl public partial class GameGridView : UserControl
{ {

View File

@@ -1,19 +1,18 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.Ui.Controls.GameListView" x:Class="Ryujinx.Ava.UI.Controls.GameListView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Ryujinx.Ava.Ui.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
d:DesignHeight="450" d:DesignHeight="450"
d:DesignWidth="800" d:DesignWidth="800"
mc:Ignorable="d" mc:Ignorable="d"
Focusable="True"> Focusable="True">
<UserControl.Resources> <UserControl.Resources>
<controls:BitmapArrayValueConverter x:Key="ByteImage" /> <helpers:BitmapArrayValueConverter x:Key="ByteImage" />
<MenuFlyout x:Key="GameContextMenu" Opened="MenuBase_OnMenuOpened"> <MenuFlyout x:Key="GameContextMenu" Opened="MenuBase_OnMenuOpened">
<MenuItem <MenuItem
Command="{Binding ToggleFavorite}" Command="{Binding ToggleFavorite}"

View File

@@ -4,11 +4,12 @@ using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using LibHac.Common; using LibHac.Common;
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ui.App.Common; using Ryujinx.Ui.App.Common;
using System; using System;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class GameListView : UserControl public partial class GameListView : UserControl
{ {

View File

@@ -1,5 +1,5 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.Ui.Controls.InputDialog" x:Class="Ryujinx.Ava.UI.Controls.InputDialog"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

View File

@@ -1,10 +1,11 @@
using Avalonia.Controls; using Avalonia.Controls;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class InputDialog : UserControl public partial class InputDialog : UserControl
{ {

View File

@@ -0,0 +1,16 @@
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="450"
x:Class="Ryujinx.Ava.UI.Controls.NavigationDialogHost"
Focusable="True">
<ui:Frame
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
x:Name="ContentFrame" />
</UserControl>

View File

@@ -3,13 +3,13 @@ using Avalonia.Controls;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using LibHac; using LibHac;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Account.Acc;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class NavigationDialogHost : UserControl public partial class NavigationDialogHost : UserControl
{ {

View File

@@ -0,0 +1,57 @@
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
mc:Ignorable="d"
x:Class="Ryujinx.Ava.UI.Controls.ProfileImageSelectionDialog"
Focusable="True">
<Grid
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Margin="5,10,5, 5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="70" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
FontWeight="Bold"
FontSize="18"
HorizontalAlignment="Center"
Grid.Row="1"
Text="{locale:Locale ProfileImageSelectionHeader}" />
<TextBlock
FontWeight="Bold"
Grid.Row="2"
Margin="10"
MaxWidth="400"
TextWrapping="Wrap"
HorizontalAlignment="Center"
TextAlignment="Center"
Text="{locale:Locale ProfileImageSelectionNote}" />
<StackPanel
Margin="5,0"
Spacing="10"
Grid.Row="4"
HorizontalAlignment="Center"
Orientation="Horizontal">
<Button
Name="Import"
Click="Import_OnClick"
Width="200">
<TextBlock Text="{locale:Locale ProfileImageSelectionImportImage}" />
</Button>
<Button
Name="SelectFirmwareImage"
IsEnabled="{Binding FirmwareFound}"
Click="SelectFirmwareImage_OnClick"
Width="200">
<TextBlock Text="{locale:Locale ProfileImageSelectionSelectAvatar}" />
</Button>
</StackPanel>
</Grid>
</UserControl>

View File

@@ -4,15 +4,15 @@ using Avalonia.VisualTree;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Navigation; using FluentAvalonia.UI.Navigation;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using SixLabors.ImageSharp; using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using System.IO; using System.IO;
using Image = SixLabors.ImageSharp.Image; using Image = SixLabors.ImageSharp.Image;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class ProfileImageSelectionDialog : UserControl public partial class ProfileImageSelectionDialog : UserControl
{ {

View File

@@ -0,0 +1,11 @@
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="450"
x:Class="Ryujinx.Ava.UI.Controls.RendererHost"
Focusable="True">
</UserControl>

View File

@@ -1,13 +1,14 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using SPB.Graphics.OpenGL; using SPB.Graphics.OpenGL;
using SPB.Windowing; using SPB.Windowing;
using System; using System;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class RendererHost : UserControl, IDisposable public partial class RendererHost : UserControl, IDisposable
{ {

View File

@@ -0,0 +1,175 @@
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="450"
Height="400"
Width="550"
x:Class="Ryujinx.Ava.UI.Controls.SaveManager"
Focusable="True">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid
Grid.Row="0"
HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel
Spacing="10"
Orientation="Horizontal"
HorizontalAlignment="Left"
VerticalAlignment="Center">
<Label
Content="{locale:Locale CommonSort}"
VerticalAlignment="Center" />
<ComboBox SelectedIndex="{Binding SortIndex}" Width="100">
<ComboBoxItem>
<Label
VerticalAlignment="Center"
HorizontalContentAlignment="Left"
Content="{locale:Locale Name}" />
</ComboBoxItem>
<ComboBoxItem>
<Label
VerticalAlignment="Center"
HorizontalContentAlignment="Left"
Content="{locale:Locale Size}" />
</ComboBoxItem>
</ComboBox>
<ComboBox SelectedIndex="{Binding OrderIndex}" Width="150">
<ComboBoxItem>
<Label
VerticalAlignment="Center"
HorizontalContentAlignment="Left"
Content="{locale:Locale OrderAscending}" />
</ComboBoxItem>
<ComboBoxItem>
<Label
VerticalAlignment="Center"
HorizontalContentAlignment="Left"
Content="{locale:Locale Descending}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
<Grid
Grid.Column="1"
HorizontalAlignment="Stretch"
Margin="10,0, 0, 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label
Content="{locale:Locale Search}"
VerticalAlignment="Center"/>
<TextBox
Margin="5,0,0,0"
Grid.Column="1"
HorizontalAlignment="Stretch"
Text="{Binding Search}"/>
</Grid>
</Grid>
<Border
Grid.Row="1"
Margin="0,5"
BorderThickness="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<ListBox
Name="SaveList"
Items="{Binding View}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="models:SaveModel">
<Grid HorizontalAlignment="Stretch" Margin="0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<Border
Height="42"
Margin="2"
Width="42"
Padding="10"
IsVisible="{Binding !InGameList}">
<ui:SymbolIcon
Symbol="Help"
FontSize="30"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<Image
IsVisible="{Binding InGameList}"
Margin="2"
Width="42"
Height="42"
Source="{Binding Icon,
Converter={StaticResource ByteImage}}" />
<TextBlock
MaxLines="3"
Width="320"
Margin="5"
TextWrapping="Wrap"
Text="{Binding Title}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel
Grid.Column="1"
Spacing="10"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Label
Content="{Binding SizeString}"
IsVisible="{Binding SizeAvailable}"
VerticalAlignment="Center"
HorizontalAlignment="Right" />
<Button
VerticalAlignment="Center"
HorizontalAlignment="Right"
Padding="10"
MinWidth="0"
MinHeight="0"
Name="OpenLocation"
Command="{Binding OpenLocation}">
<ui:SymbolIcon
Symbol="OpenFolder"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Button>
<Button
VerticalAlignment="Center"
HorizontalAlignment="Right"
Padding="10"
MinWidth="0"
MinHeight="0"
Name="Delete"
Command="{Binding Delete}">
<ui:SymbolIcon
Symbol="Delete"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Button>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
</Grid>
</UserControl>

View File

@@ -7,16 +7,16 @@ using LibHac.Fs;
using LibHac.Fs.Shim; using LibHac.Fs.Shim;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.UI.Models;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.Ui.App.Common; using Ryujinx.Ui.App.Common;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using UserProfile = Ryujinx.Ava.Ui.Models.UserProfile; using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class SaveManager : UserControl public partial class SaveManager : UserControl
{ {

View File

@@ -1,10 +1,9 @@
<Window <Window
x:Class="Ryujinx.Ava.Ui.Controls.UpdateWaitWindow" x:Class="Ryujinx.Ava.UI.Controls.UpdateWaitWindow"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:window="clr-namespace:Ryujinx.Ava.Ui.Windows"
Title="Ryujinx - Waiting" Title="Ryujinx - Waiting"
SizeToContent="WidthAndHeight" SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterOwner" WindowStartupLocation="CenterOwner"

View File

@@ -1,7 +1,7 @@
using Avalonia.Controls; using Avalonia.Controls;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Windows;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class UpdateWaitWindow : StyleableWindow public partial class UpdateWaitWindow : StyleableWindow
{ {

View File

@@ -1,21 +1,18 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.Ui.Controls.UserEditor" x:Class="Ryujinx.Ava.UI.Controls.UserEditor"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:controls="clr-namespace:Ryujinx.Ava.Ui.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="clr-namespace:Ryujinx.Ava.Ui.Models" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.Ui.ViewModels"
Margin="0" Margin="0"
MinWidth="500" MinWidth="500"
Padding="0" Padding="0"
mc:Ignorable="d" mc:Ignorable="d"
Focusable="True"> Focusable="True">
<UserControl.Resources> <UserControl.Resources>
<controls:BitmapArrayValueConverter x:Key="ByteImage" /> <helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources> </UserControl.Resources>
<Grid Margin="0"> <Grid Margin="0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@@ -43,13 +40,13 @@
Margin="5" Margin="5"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Click="ChangePictureButton_Click" Click="ChangePictureButton_Click"
Content="{Locale:Locale UserProfilesChangeProfileImage}" /> Content="{locale:Locale UserProfilesChangeProfileImage}" />
<Button <Button
Name="AddPictureButton" Name="AddPictureButton"
Margin="5" Margin="5"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Click="ChangePictureButton_Click" Click="ChangePictureButton_Click"
Content="{Locale:Locale UserProfilesSetProfileImage}" /> Content="{locale:Locale UserProfilesSetProfileImage}" />
</StackPanel> </StackPanel>
<StackPanel <StackPanel
Grid.Row="0" Grid.Row="0"
@@ -58,14 +55,14 @@
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Orientation="Vertical" Orientation="Vertical"
Spacing="10"> Spacing="10">
<TextBlock Text="{Locale:Locale UserProfilesName}" /> <TextBlock Text="{locale:Locale UserProfilesName}" />
<TextBox <TextBox
Name="NameBox" Name="NameBox"
Width="300" Width="300"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
MaxLength="{Binding MaxProfileNameLength}" MaxLength="{Binding MaxProfileNameLength}"
Text="{Binding Name}" /> Text="{Binding Name}" />
<TextBlock Name="IdText" Text="{Locale:Locale UserProfilesUserId}" /> <TextBlock Name="IdText" Text="{locale:Locale UserProfilesUserId}" />
<TextBlock Name="IdLabel" Text="{Binding UserId}" /> <TextBlock Name="IdLabel" Text="{Binding UserId}" />
</StackPanel> </StackPanel>
<StackPanel <StackPanel
@@ -78,12 +75,12 @@
<Button <Button
Name="SaveButton" Name="SaveButton"
Click="SaveButton_Click" Click="SaveButton_Click"
Content="{Locale:Locale Save}" /> Content="{locale:Locale Save}" />
<Button <Button
Name="CloseButton" Name="CloseButton"
HorizontalAlignment="Right" HorizontalAlignment="Right"
Click="CloseButton_Click" Click="CloseButton_Click"
Content="{Locale:Locale Discard}" /> Content="{locale:Locale Discard}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@@ -4,10 +4,11 @@ using Avalonia.Interactivity;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Navigation; using FluentAvalonia.UI.Navigation;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.UI.Helpers;
using UserProfile = Ryujinx.Ava.Ui.Models.UserProfile; using Ryujinx.Ava.UI.Models;
using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class UserEditor : UserControl public partial class UserEditor : UserControl
{ {

View File

@@ -1,17 +1,18 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="https://github.com/avaloniaui"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignWidth="800" xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
d:DesignHeight="450" xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
MinWidth="500" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
MinHeight="400" mc:Ignorable="d"
xmlns:Locale="clr-namespace:Ryujinx.Ava.Common.Locale" d:DesignWidth="800"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" d:DesignHeight="450"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.Ui.ViewModels" MinWidth="500"
x:Class="Ryujinx.Ava.Ui.Controls.UserRecoverer" MinHeight="400"
Focusable="True"> x:Class="Ryujinx.Ava.UI.Controls.UserRecoverer"
Focusable="True">
<Design.DataContext> <Design.DataContext>
<viewModels:UserProfileViewModel /> <viewModels:UserProfileViewModel />
</Design.DataContext> </Design.DataContext>
@@ -32,7 +33,7 @@
<ui:SymbolIcon Symbol="Back"/> <ui:SymbolIcon Symbol="Back"/>
</Button> </Button>
<TextBlock Grid.Row="1" <TextBlock Grid.Row="1"
Text="{Locale:Locale UserProfilesRecoverHeading}"/> Text="{locale:Locale UserProfilesRecoverHeading}"/>
<ListBox <ListBox
Margin="5" Margin="5"
Grid.Row="2" Grid.Row="2"
@@ -61,7 +62,7 @@
HorizontalAlignment="Right" HorizontalAlignment="Right"
Command="{Binding Recover}" Command="{Binding Recover}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Content="{Locale:Locale Recover}"/> Content="{locale:Locale Recover}"/>
</Grid> </Grid>
</Border> </Border>
</DataTemplate> </DataTemplate>

View File

@@ -4,10 +4,10 @@ using Avalonia.Interactivity;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Navigation; using FluentAvalonia.UI.Navigation;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.ViewModels;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class UserRecoverer : UserControl public partial class UserRecoverer : UserControl
{ {

View File

@@ -1,21 +1,20 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.Ui.Controls.UserSelector" x:Class="Ryujinx.Ava.UI.Controls.UserSelector"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:controls="clr-namespace:Ryujinx.Ava.Ui.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox" xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.Ui.ViewModels" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
d:DesignHeight="450" d:DesignHeight="450"
MinWidth="500" MinWidth="500"
d:DesignWidth="800" d:DesignWidth="800"
mc:Ignorable="d" mc:Ignorable="d"
Focusable="True"> Focusable="True">
<UserControl.Resources> <UserControl.Resources>
<controls:BitmapArrayValueConverter x:Key="ByteImage" /> <helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources> </UserControl.Resources>
<Design.DataContext> <Design.DataContext>
<viewModels:UserProfileViewModel /> <viewModels:UserProfileViewModel />
@@ -109,21 +108,21 @@
Grid.Column="0" Grid.Column="0"
Margin="2" Margin="2"
Command="{Binding AddUser}" Command="{Binding AddUser}"
Content="{Locale:Locale UserProfilesAddNewProfile}" /> Content="{locale:Locale UserProfilesAddNewProfile}" />
<Button <Button
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Grid.Row="0" Grid.Row="0"
Margin="2" Margin="2"
Grid.Column="1" Grid.Column="1"
Command="{Binding EditUser}" Command="{Binding EditUser}"
Content="{Locale:Locale UserProfilesEditProfile}" Content="{locale:Locale UserProfilesEditProfile}"
IsEnabled="{Binding IsSelectedProfiledEditable}" /> IsEnabled="{Binding IsSelectedProfiledEditable}" />
<Button <Button
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Grid.Row="1" Grid.Row="1"
Grid.Column="0" Grid.Column="0"
Margin="2" Margin="2"
Content="{Locale:Locale UserProfilesManageSaves}" Content="{locale:Locale UserProfilesManageSaves}"
Command="{Binding ManageSaves}" /> Command="{Binding ManageSaves}" />
<Button <Button
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
@@ -131,7 +130,7 @@
Grid.Column="1" Grid.Column="1"
Margin="2" Margin="2"
Command="{Binding DeleteUser}" Command="{Binding DeleteUser}"
Content="{Locale:Locale UserProfilesDeleteSelectedProfile}" Content="{locale:Locale UserProfilesDeleteSelectedProfile}"
IsEnabled="{Binding IsSelectedProfileDeletable}" /> IsEnabled="{Binding IsSelectedProfileDeletable}" />
<Button <Button
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
@@ -140,7 +139,7 @@
Grid.Column="0" Grid.Column="0"
Margin="2" Margin="2"
Command="{Binding RecoverLostAccounts}" Command="{Binding RecoverLostAccounts}"
Content="{Locale:Locale UserProfilesRecoverLostAccounts}" /> Content="{locale:Locale UserProfilesRecoverLostAccounts}" />
</Grid> </Grid>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@@ -2,10 +2,10 @@ using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Navigation; using FluentAvalonia.UI.Navigation;
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using UserProfile = Ryujinx.Ava.Ui.Models.UserProfile; using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Controls
{ {
public partial class UserSelector : UserControl public partial class UserSelector : UserControl
{ {

View File

@@ -1,7 +1,7 @@
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Ryujinx.Ui.App.Common; using Ryujinx.Ui.App.Common;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
public class ApplicationOpenedEventArgs : RoutedEventArgs public class ApplicationOpenedEventArgs : RoutedEventArgs
{ {

View File

@@ -2,7 +2,7 @@
using System; using System;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
[SupportedOSPlatform("linux")] [SupportedOSPlatform("linux")]
internal class AvaloniaGlxContext : SPB.Platform.GLX.GLXOpenGLContext internal class AvaloniaGlxContext : SPB.Platform.GLX.GLXOpenGLContext

View File

@@ -2,7 +2,7 @@
using System; using System;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
internal class AvaloniaWglContext : SPB.Platform.WGL.WGLOpenGLContext internal class AvaloniaWglContext : SPB.Platform.WGL.WGLOpenGLContext

View File

@@ -5,7 +5,7 @@ using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
internal class BitmapArrayValueConverter : IValueConverter internal class BitmapArrayValueConverter : IValueConverter
{ {

View File

@@ -8,7 +8,7 @@ using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
internal class ButtonKeyAssigner internal class ButtonKeyAssigner
{ {

View File

@@ -1,20 +1,19 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Primitives;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Threading; using Avalonia.Threading;
using FluentAvalonia.Core; using FluentAvalonia.Core;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
public static class ContentDialogHelper public static class ContentDialogHelper
{ {

View File

@@ -2,7 +2,7 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Platform; using Avalonia.Platform;
using Ryujinx.Ava.Ui.Helper; using Ryujinx.Ava.UI.Helper;
using SPB.Graphics; using SPB.Graphics;
using SPB.Platform; using SPB.Platform;
using SPB.Platform.GLX; using SPB.Platform.GLX;
@@ -10,9 +10,9 @@ using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading.Tasks; using System.Threading.Tasks;
using static Ryujinx.Ava.Ui.Controls.Win32NativeInterop; using static Ryujinx.Ava.UI.Helpers.Win32NativeInterop;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
public class EmbeddedWindow : NativeControlHost public class EmbeddedWindow : NativeControlHost
{ {
@@ -199,7 +199,7 @@ namespace Ryujinx.Ava.Ui.Controls
KeyModifiers.None)); KeyModifiers.None));
break; break;
} }
return DefWindowProc(hWnd, msg, (IntPtr)wParam, (IntPtr)lParam); return DefWindowProc(hWnd, msg, wParam, lParam);
} }
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]

View File

@@ -0,0 +1,9 @@
namespace Ryujinx.Ava.UI.Helpers
{
public enum Glyph
{
List,
Grid,
Chip
}
}

View File

@@ -4,7 +4,7 @@ using FluentAvalonia.UI.Controls;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
public class GlyphValueConverter : MarkupExtension public class GlyphValueConverter : MarkupExtension
{ {

View File

@@ -4,7 +4,7 @@ using Avalonia.Input;
using System; using System;
using System.Windows.Input; using System.Windows.Input;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
public class HotKeyControl : ContentControl, ICommandSource public class HotKeyControl : ContentControl, ICommandSource
{ {

View File

@@ -2,7 +2,7 @@ using Avalonia.OpenGL;
using SPB.Graphics.OpenGL; using SPB.Graphics.OpenGL;
using System; using System;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
internal static class IGlContextExtension internal static class IGlContextExtension
{ {

View File

@@ -4,7 +4,7 @@ using Ryujinx.Common.Configuration.Hid.Controller;
using System; using System;
using System.Globalization; using System.Globalization;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
internal class KeyValueConverter : IValueConverter internal class KeyValueConverter : IValueConverter
{ {

View File

@@ -2,7 +2,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Helpers
{ {
public sealed class MiniCommand<T> : MiniCommand, ICommand public sealed class MiniCommand<T> : MiniCommand, ICommand
{ {

View File

@@ -2,7 +2,7 @@ using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
public class OffscreenTextBox : TextBox public class OffscreenTextBox : TextBox
{ {

View File

@@ -1,16 +1,13 @@
using Avalonia;
using Avalonia.OpenGL;
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using SPB.Graphics; using SPB.Graphics;
using SPB.Graphics.OpenGL; using SPB.Graphics.OpenGL;
using SPB.Platform; using SPB.Platform;
using SPB.Platform.GLX;
using SPB.Platform.WGL; using SPB.Platform.WGL;
using SPB.Windowing; using SPB.Windowing;
using System; using System;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
public class OpenGLEmbeddedWindow : EmbeddedWindow public class OpenGLEmbeddedWindow : EmbeddedWindow
{ {

View File

@@ -1,7 +1,7 @@
using OpenTK; using OpenTK;
using System; using System;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
internal class OpenToolkitBindingsContext : IBindingsContext internal class OpenToolkitBindingsContext : IBindingsContext
{ {

View File

@@ -5,7 +5,7 @@ using SPB.Graphics.OpenGL;
using SPB.Platform; using SPB.Platform;
using SPB.Windowing; using SPB.Windowing;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
class SPBOpenGLContext : IOpenGLContext class SPBOpenGLContext : IOpenGLContext
{ {

View File

@@ -1,10 +1,10 @@
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ui.Common; using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Helper; using Ryujinx.Ui.Common.Helper;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
internal class UserErrorDialog internal class UserErrorDialog
{ {

View File

@@ -1,4 +1,4 @@
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
public enum UserResult public enum UserResult
{ {

View File

@@ -1,5 +1,4 @@
using Avalonia.Platform; using Avalonia.Platform;
using Ryujinx.Ava.Ui.Controls;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using SPB.Graphics.Vulkan; using SPB.Graphics.Vulkan;
using SPB.Platform.GLX; using SPB.Platform.GLX;
@@ -10,7 +9,7 @@ using SPB.Windowing;
using System; using System;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Ava.Ui namespace Ryujinx.Ava.UI.Helpers
{ {
public class VulkanEmbeddedWindow : EmbeddedWindow public class VulkanEmbeddedWindow : EmbeddedWindow
{ {

View File

@@ -2,7 +2,7 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.UI.Helpers
{ {
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
internal partial class Win32NativeInterop internal partial class Win32NativeInterop

View File

@@ -2,7 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
public class Amiibo public class Amiibo
{ {

View File

@@ -1,7 +1,7 @@
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using System; using System;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
public class CheatModel : BaseModel public class CheatModel : BaseModel
{ {

View File

@@ -3,7 +3,7 @@ using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
public class CheatsList : ObservableCollection<CheatModel> public class CheatsList : ObservableCollection<CheatModel>
{ {

View File

@@ -1,6 +1,6 @@
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
internal record ControllerModel(ControllerType Type, string Name); internal record ControllerModel(ControllerType Type, string Name);
} }

View File

@@ -1,4 +1,4 @@
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
public enum DeviceType public enum DeviceType
{ {

View File

@@ -1,6 +1,6 @@
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.ViewModels;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
public class DownloadableContentModel : BaseModel public class DownloadableContentModel : BaseModel
{ {

View File

@@ -3,7 +3,7 @@ using Ryujinx.Ui.App.Common;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Ava.Ui.Models.Generic namespace Ryujinx.Ava.UI.Models.Generic
{ {
internal class LastPlayedSortComparer : IComparer<ApplicationData> internal class LastPlayedSortComparer : IComparer<ApplicationData>
{ {

View File

@@ -1,11 +1,11 @@
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Configuration.Hid.Controller.Motion; using Ryujinx.Common.Configuration.Hid.Controller.Motion;
using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Configuration.Hid.Keyboard;
using System; using System;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
internal class InputConfiguration<Key, Stick> : BaseModel internal class InputConfiguration<Key, Stick> : BaseModel
{ {

View File

@@ -1,6 +1,6 @@
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
public record PlayerModel(PlayerIndex Id, string Name); public record PlayerModel(PlayerIndex Id, string Name);
} }

View File

@@ -1,4 +1,4 @@
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
public class ProfileImageModel public class ProfileImageModel
{ {

View File

@@ -4,9 +4,10 @@ using LibHac.Fs.Shim;
using LibHac.Ncm; using LibHac.Ncm;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.Ui.App.Common; using Ryujinx.Ui.App.Common;
using System; using System;
@@ -14,7 +15,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
public class SaveModel : BaseModel public class SaveModel : BaseModel
{ {

View File

@@ -1,6 +1,6 @@
using System; using System;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
internal class StatusUpdatedEventArgs : EventArgs internal class StatusUpdatedEventArgs : EventArgs
{ {

View File

@@ -1,8 +1,8 @@
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Account.Acc;
using System; using System;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
public class TempProfile : BaseModel public class TempProfile : BaseModel
{ {

View File

@@ -1,4 +1,4 @@
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
internal class TimeZone internal class TimeZone
{ {

View File

@@ -1,7 +1,7 @@
using LibHac.Ns; using LibHac.Ns;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
internal class TitleUpdateModel internal class TitleUpdateModel
{ {

View File

@@ -1,9 +1,9 @@
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Account.Acc;
using Profile = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile; using Profile = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
namespace Ryujinx.Ava.Ui.Models namespace Ryujinx.Ava.UI.Models
{ {
public class UserProfile : BaseModel public class UserProfile : BaseModel
{ {

View File

@@ -3,9 +3,10 @@ using Avalonia.Collections;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Threading; using Avalonia.Threading;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
@@ -19,7 +20,7 @@ using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class AmiiboWindowViewModel : BaseModel, IDisposable public class AmiiboWindowViewModel : BaseModel, IDisposable
{ {

View File

@@ -8,7 +8,7 @@ using LibHac.Ncm;
using LibHac.Tools.Fs; using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils; using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.UI.Models;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using SixLabors.ImageSharp; using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Png;
@@ -24,7 +24,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Color = Avalonia.Media.Color; using Color = Avalonia.Media.Color;
namespace Ryujinx.Ava.Ui.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
internal class AvatarProfileViewModel : BaseModel, IDisposable internal class AvatarProfileViewModel : BaseModel, IDisposable
{ {

View File

@@ -1,7 +1,7 @@
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace Ryujinx.Ava.Ui.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class BaseModel : INotifyPropertyChanged public class BaseModel : INotifyPropertyChanged
{ {

View File

@@ -5,9 +5,10 @@ using Avalonia.Svg.Skia;
using Avalonia.Threading; using Avalonia.Threading;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
@@ -28,7 +29,7 @@ using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.Gamepad
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId; using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
using Key = Ryujinx.Common.Configuration.Hid.Key; using Key = Ryujinx.Common.Configuration.Hid.Key;
namespace Ryujinx.Ava.Ui.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class ControllerSettingsViewModel : BaseModel, IDisposable public class ControllerSettingsViewModel : BaseModel, IDisposable
{ {

View File

@@ -12,8 +12,9 @@ using LibHac.Ncm;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
@@ -35,7 +36,7 @@ using System.Threading.Tasks;
using Path = System.IO.Path; using Path = System.IO.Path;
using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState; using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState;
namespace Ryujinx.Ava.Ui.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
internal class MainWindowViewModel : BaseModel internal class MainWindowViewModel : BaseModel
{ {

View File

@@ -9,8 +9,9 @@ using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Audio.Backends.SoundIo; using Ryujinx.Audio.Backends.SoundIo;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.GraphicsDriver; using Ryujinx.Common.GraphicsDriver;
@@ -25,9 +26,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using TimeZone = Ryujinx.Ava.Ui.Models.TimeZone; using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
namespace Ryujinx.Ava.Ui.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
internal class SettingsViewModel : BaseModel internal class SettingsViewModel : BaseModel
{ {
@@ -41,7 +42,6 @@ namespace Ryujinx.Ava.Ui.ViewModels
private float _customResolutionScale; private float _customResolutionScale;
private int _resolutionScale; private int _resolutionScale;
private int _graphicsBackendMultithreadingIndex; private int _graphicsBackendMultithreadingIndex;
private float _previousVolumeLevel;
private float _volume; private float _volume;
private bool _isVulkanAvailable = true; private bool _isVulkanAvailable = true;
private bool _directoryChanged = false; private bool _directoryChanged = false;
@@ -390,8 +390,6 @@ namespace Ryujinx.Ava.Ui.ViewModels
TimeOffset = dateTimeOffset.TimeOfDay; TimeOffset = dateTimeOffset.TimeOfDay;
KeyboardHotkeys = config.Hid.Hotkeys.Value; KeyboardHotkeys = config.Hid.Hotkeys.Value;
_previousVolumeLevel = Volume;
} }
public void SaveSettings() public void SaveSettings()
@@ -479,9 +477,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
config.ToFileFormat().SaveConfig(Program.ConfigurationPath); config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
MainWindow.UpdateGraphicsConfig(); MainWindow.UpdateGraphicsConfig();
_previousVolumeLevel = Volume;
if (_owner is SettingsWindow owner) if (_owner is SettingsWindow owner)
{ {
owner.ControllerSettings?.SaveCurrentProfile(); owner.ControllerSettings?.SaveCurrentProfile();

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