Compare commits
42 Commits
Canary-1.2
...
Canary-1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44632e5d8b | ||
|
|
551d2c1134 | ||
|
|
25cc9b24b4 | ||
|
|
638c616ab7 | ||
|
|
109f0fc659 | ||
|
|
dfcb8a7fc0 | ||
|
|
d87d3235e9 | ||
|
|
f3a9cecf72 | ||
|
|
97a1bbdd74 | ||
|
|
e379fad5da | ||
|
|
c76f32a4ee | ||
|
|
7bdf013ba6 | ||
|
|
e07130ecc3 | ||
|
|
dd02c8e25d | ||
|
|
bed3835718 | ||
|
|
2b06826922 | ||
|
|
a23c6bf547 | ||
|
|
27cdf876a2 | ||
|
|
b0c0e8f7ad | ||
|
|
2317c06364 | ||
|
|
c12a59ecd6 | ||
|
|
57c22a1f32 | ||
|
|
f7976753fd | ||
|
|
b45a65fbdc | ||
|
|
c410474d83 | ||
|
|
ffdc419417 | ||
|
|
da3f4e1d3a | ||
|
|
69d79322bb | ||
|
|
c3af1dbf1a | ||
|
|
10ac381525 | ||
|
|
e104ee6be3 | ||
|
|
e65d1ec6c9 | ||
|
|
534f92506b | ||
|
|
10d20c1ae3 | ||
|
|
e294a79975 | ||
|
|
ec06a86899 | ||
|
|
2e4de17472 | ||
|
|
9227cbe5a7 | ||
|
|
332bcdfaf1 | ||
|
|
1c8276197f | ||
|
|
a3596ba858 | ||
|
|
3ffcc72117 |
@@ -97,7 +97,7 @@ If you are planning to contribute or just want to learn more about this project
|
|||||||
|
|
||||||
- **Input**
|
- **Input**
|
||||||
|
|
||||||
We currently have support for keyboard, mouse, touch input, JoyCon input support, and nearly all controllers.
|
We currently have support for keyboard, mouse, touch input, Joy-Con input support, and nearly all controllers.
|
||||||
Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
||||||
In all scenarios, you can set up everything inside the input configuration menu.
|
In all scenarios, you can set up everything inside the input configuration menu.
|
||||||
|
|
||||||
|
|||||||
@@ -631,6 +631,7 @@
|
|||||||
010030D012FF6000,"Bus Driver Simulator",,playable,2022-10-17 13:55:27
|
010030D012FF6000,"Bus Driver Simulator",,playable,2022-10-17 13:55:27
|
||||||
0100A9101418C000,"BUSTAFELLOWS",nvdec,playable,2020-10-17 20:04:41
|
0100A9101418C000,"BUSTAFELLOWS",nvdec,playable,2020-10-17 20:04:41
|
||||||
0100177005C8A000,"BUTCHER",,playable,2021-01-11 18:50:17
|
0100177005C8A000,"BUTCHER",,playable,2021-01-11 18:50:17
|
||||||
|
01008c2019598000,"Bluey: The Videogame",,playable,2025-02-11 04:38:00
|
||||||
01000B900D8B0000,"Cadence of Hyrule: Crypt of the NecroDancer Featuring The Legend of Zelda",slow;nvdec,playable,2024-04-01 22:43:40
|
01000B900D8B0000,"Cadence of Hyrule: Crypt of the NecroDancer Featuring The Legend of Zelda",slow;nvdec,playable,2024-04-01 22:43:40
|
||||||
010065700EE06000,"Cadence of Hyrule: Crypt of the NecroDancer Featuring The Legend of Zelda Demo",demo;gpu;nvdec,ingame,2021-02-14 21:48:15
|
010065700EE06000,"Cadence of Hyrule: Crypt of the NecroDancer Featuring The Legend of Zelda Demo",demo;gpu;nvdec,ingame,2021-02-14 21:48:15
|
||||||
01005C00117A8000,"Café Enchanté",,playable,2020-11-13 14:54:25
|
01005C00117A8000,"Café Enchanté",,playable,2020-11-13 14:54:25
|
||||||
@@ -1382,6 +1383,9 @@
|
|||||||
0100763015C2E000,"Gunvolt Chronicles: Luminous Avenger iX 2",crash;Needs Update,nothing,2022-04-29 15:34:34
|
0100763015C2E000,"Gunvolt Chronicles: Luminous Avenger iX 2",crash;Needs Update,nothing,2022-04-29 15:34:34
|
||||||
01002C8018554000,"Gurimugurimoa OnceMore Demo",,playable,2022-07-29 22:07:31
|
01002C8018554000,"Gurimugurimoa OnceMore Demo",,playable,2022-07-29 22:07:31
|
||||||
0100AC601DCA8000,"GYLT",crash,ingame,2024-03-18 20:16:51
|
0100AC601DCA8000,"GYLT",crash,ingame,2024-03-18 20:16:51
|
||||||
|
0100c3c012718000,"Grand Theft Auto: III – The Definitive Edition",gpu;UE4,ingame,2022-10-31 20:13:52
|
||||||
|
0100182014022000,"Grand Theft Auto: Vice City – The Definitive Edition",gpu;UE4,ingame,2022-10-31 20:13:52
|
||||||
|
010065a014024000,"Grand Theft Auto: San Andreas – The Definitive Edition",gpu;UE4,ingame,2022-10-31 20:13:52
|
||||||
0100822012D76000,"HAAK",gpu,ingame,2023-02-19 14:31:05
|
0100822012D76000,"HAAK",gpu,ingame,2023-02-19 14:31:05
|
||||||
01007E100EFA8000,"Habroxia",,playable,2020-06-16 23:04:42
|
01007E100EFA8000,"Habroxia",,playable,2020-06-16 23:04:42
|
||||||
0100535012974000,"Hades",vulkan,playable,2022-10-05 10:45:21
|
0100535012974000,"Hades",vulkan,playable,2022-10-05 10:45:21
|
||||||
@@ -2729,7 +2733,7 @@
|
|||||||
0100C2500FC20000,"Splatoon™ 3",ldn-works;opengl-backend-bug;LAN;amd-vendor-bug,playable,2024-08-04 23:49:11
|
0100C2500FC20000,"Splatoon™ 3",ldn-works;opengl-backend-bug;LAN;amd-vendor-bug,playable,2024-08-04 23:49:11
|
||||||
0100BA0018500000,"Splatoon™ 3: Splatfest World Premiere",gpu;online-broken;demo,ingame,2022-09-19 03:17:12
|
0100BA0018500000,"Splatoon™ 3: Splatfest World Premiere",gpu;online-broken;demo,ingame,2022-09-19 03:17:12
|
||||||
010062800D39C000,"SpongeBob SquarePants: Battle for Bikini Bottom - Rehydrated",online-broken;UE4;ldn-broken;vulkan-backend-bug,playable,2023-08-01 19:29:34
|
010062800D39C000,"SpongeBob SquarePants: Battle for Bikini Bottom - Rehydrated",online-broken;UE4;ldn-broken;vulkan-backend-bug,playable,2023-08-01 19:29:34
|
||||||
01009FB0172F4000,"SpongeBob SquarePants: The Cosmic Shake",gpu;UE4,ingame,2023-08-01 19:29:53
|
01009FB0172F4000,"SpongeBob SquarePants: The Cosmic Shake",gpu;UE4,ingame,2024-03-04 16:35:00
|
||||||
010097C01336A000,"Spooky Chase",,playable,2022-11-04 12:17:44
|
010097C01336A000,"Spooky Chase",,playable,2022-11-04 12:17:44
|
||||||
0100C6100D75E000,"Spooky Ghosts Dot Com",,playable,2021-06-15 15:16:11
|
0100C6100D75E000,"Spooky Ghosts Dot Com",,playable,2021-06-15 15:16:11
|
||||||
0100DE9005170000,"Sports Party",nvdec,playable,2021-03-05 13:40:42
|
0100DE9005170000,"Sports Party",nvdec,playable,2021-03-05 13:40:42
|
||||||
|
|||||||
|
@@ -24,7 +24,7 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||||
|
|
||||||
private static CacheMemoryAllocator _cacheAllocator;
|
private static List<CacheMemoryAllocator> _cacheAllocators = [];
|
||||||
|
|
||||||
private static readonly List<CacheEntry> _cacheEntries = [];
|
private static readonly List<CacheEntry> _cacheEntries = [];
|
||||||
|
|
||||||
@@ -40,37 +40,48 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
public static void Initialize(IJitMemoryAllocator allocator)
|
public static void Initialize(IJitMemoryAllocator allocator)
|
||||||
{
|
{
|
||||||
if (_initialized)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
if (_initialized)
|
if (_initialized)
|
||||||
{
|
{
|
||||||
return;
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
JitUnwindWindows.RemoveFunctionTableHandler(
|
||||||
|
_jitRegions[0].Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < _jitRegions.Count; i++)
|
||||||
|
{
|
||||||
|
_jitRegions[i].Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
_jitRegions.Clear();
|
||||||
|
_cacheAllocators.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_activeRegionIndex = 0;
|
||||||
|
|
||||||
ReservedRegion firstRegion = new(allocator, CacheSize);
|
ReservedRegion firstRegion = new(allocator, CacheSize);
|
||||||
_jitRegions.Add(firstRegion);
|
_jitRegions.Add(firstRegion);
|
||||||
_activeRegionIndex = 0;
|
|
||||||
|
CacheMemoryAllocator firstCacheAllocator = new(CacheSize);
|
||||||
|
_cacheAllocators.Add(firstCacheAllocator);
|
||||||
|
|
||||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
JitUnwindWindows.InstallFunctionTableHandler(
|
JitUnwindWindows.InstallFunctionTableHandler(
|
||||||
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
|
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +147,7 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
||||||
{
|
{
|
||||||
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
_cacheAllocators[_activeRegionIndex].Free(funcOffset, AlignCodeSize(entry.Size));
|
||||||
_cacheEntries.RemoveAt(entryIndex);
|
_cacheEntries.RemoveAt(entryIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,30 +178,24 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
{
|
{
|
||||||
codeSize = AlignCodeSize(codeSize);
|
codeSize = AlignCodeSize(codeSize);
|
||||||
|
|
||||||
for (int i = _activeRegionIndex; i < _jitRegions.Count; i++)
|
int allocOffset = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
|
||||||
{
|
|
||||||
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
|
||||||
|
|
||||||
if (allocOffset >= 0)
|
if (allocOffset >= 0)
|
||||||
{
|
{
|
||||||
_jitRegions[i].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
_jitRegions[_activeRegionIndex].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
||||||
_activeRegionIndex = i;
|
|
||||||
return allocOffset;
|
return allocOffset;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int exhaustedRegion = _activeRegionIndex;
|
int exhaustedRegion = _activeRegionIndex;
|
||||||
ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize);
|
ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize);
|
||||||
_jitRegions.Add(newRegion);
|
_jitRegions.Add(newRegion);
|
||||||
_activeRegionIndex = _jitRegions.Count - 1;
|
_activeRegionIndex = _jitRegions.Count - 1;
|
||||||
|
|
||||||
int newRegionNumber = _activeRegionIndex;
|
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {_activeRegionIndex} ({((long)(_activeRegionIndex + 1) * CacheSize).Bytes()} Total Allocation).");
|
||||||
|
|
||||||
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {newRegionNumber} ({((long)(newRegionNumber + 1) * CacheSize).Bytes()} Total Allocation).");
|
_cacheAllocators.Add(new CacheMemoryAllocator(CacheSize));
|
||||||
|
|
||||||
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
int allocOffsetNew = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
|
||||||
|
|
||||||
int allocOffsetNew = _cacheAllocator.Allocate(codeSize);
|
|
||||||
if (allocOffsetNew < 0)
|
if (allocOffsetNew < 0)
|
||||||
{
|
{
|
||||||
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
nint context,
|
nint context,
|
||||||
[MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll);
|
[MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll);
|
||||||
|
|
||||||
|
[LibraryImport("kernel32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
private static unsafe partial bool RtlDeleteFunctionTable(
|
||||||
|
ulong tableIdentifier);
|
||||||
|
|
||||||
private static GetRuntimeFunctionCallback _getRuntimeFunctionCallback;
|
private static GetRuntimeFunctionCallback _getRuntimeFunctionCallback;
|
||||||
|
|
||||||
private static int _sizeOfRuntimeFunction;
|
private static int _sizeOfRuntimeFunction;
|
||||||
@@ -91,6 +96,23 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void RemoveFunctionTableHandler(nint codeCachePointer)
|
||||||
|
{
|
||||||
|
ulong codeCachePtr = (ulong)codeCachePointer.ToInt64();
|
||||||
|
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
result = RtlDeleteFunctionTable(codeCachePtr | 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Failure removing function table callback.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, nint context)
|
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, nint context)
|
||||||
{
|
{
|
||||||
int offset = (int)((long)controlPc - context.ToInt64());
|
int offset = (int)((long)controlPc - context.ToInt64());
|
||||||
|
|||||||
@@ -5,15 +5,34 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
namespace Ryujinx.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
|
public enum OperatingSystemType
|
||||||
|
{
|
||||||
|
MacOS,
|
||||||
|
Linux,
|
||||||
|
Windows
|
||||||
|
}
|
||||||
|
|
||||||
public static class RunningPlatform
|
public static class RunningPlatform
|
||||||
{
|
{
|
||||||
|
public static readonly OperatingSystemType CurrentOS
|
||||||
|
= IsMacOS
|
||||||
|
? OperatingSystemType.MacOS
|
||||||
|
: IsWindows
|
||||||
|
? OperatingSystemType.Windows
|
||||||
|
: IsLinux
|
||||||
|
? OperatingSystemType.Linux
|
||||||
|
: throw new PlatformNotSupportedException();
|
||||||
|
|
||||||
|
public static Architecture Architecture => RuntimeInformation.OSArchitecture;
|
||||||
|
public static Architecture CurrentProcessArchitecture => RuntimeInformation.ProcessArchitecture;
|
||||||
|
|
||||||
public static bool IsMacOS => OperatingSystem.IsMacOS();
|
public static bool IsMacOS => OperatingSystem.IsMacOS();
|
||||||
public static bool IsWindows => OperatingSystem.IsWindows();
|
public static bool IsWindows => OperatingSystem.IsWindows();
|
||||||
public static bool IsLinux => OperatingSystem.IsLinux();
|
public static bool IsLinux => OperatingSystem.IsLinux();
|
||||||
|
|
||||||
public static bool IsArm => RuntimeInformation.OSArchitecture is Architecture.Arm64;
|
public static bool IsArm => Architecture is Architecture.Arm64;
|
||||||
|
|
||||||
public static bool IsX64 => RuntimeInformation.OSArchitecture is Architecture.X64;
|
public static bool IsX64 => Architecture is Architecture.X64;
|
||||||
|
|
||||||
public static bool IsIntelMac => IsMacOS && IsX64;
|
public static bool IsIntelMac => IsMacOS && IsX64;
|
||||||
public static bool IsArmMac => IsMacOS && IsArm;
|
public static bool IsArmMac => IsMacOS && IsArm;
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Common.Configuration;
|
|
||||||
using Ryujinx.Common.Helper;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Common
|
namespace Ryujinx.Common
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Graphics.GAL.Multithreading;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
@@ -10,6 +12,20 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
|
|
||||||
bool PreferThreading { get; }
|
bool PreferThreading { get; }
|
||||||
|
|
||||||
|
public IRenderer TryMakeThreaded(BackendThreading backendThreading = BackendThreading.Auto)
|
||||||
|
{
|
||||||
|
if (backendThreading is BackendThreading.On ||
|
||||||
|
(backendThreading is BackendThreading.Auto && PreferThreading))
|
||||||
|
{
|
||||||
|
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({backendThreading}): True");
|
||||||
|
return new ThreadedRenderer(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({backendThreading}): False");
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
IPipeline Pipeline { get; }
|
IPipeline Pipeline { get; }
|
||||||
|
|
||||||
IWindow Window { get; }
|
IWindow Window { get; }
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm
|
|||||||
|
|
||||||
private readonly LanDiscovery _lanDiscovery;
|
private readonly LanDiscovery _lanDiscovery;
|
||||||
|
|
||||||
public LdnMitmClient(HLEConfiguration config)
|
public LdnMitmClient(HleConfiguration config)
|
||||||
{
|
{
|
||||||
UnicastIPAddressInformation localIpInterface = NetworkHelpers.GetLocalInterface(config.MultiplayerLanInterfaceId).Item2;
|
UnicastIPAddressInformation localIpInterface = NetworkHelpers.GetLocalInterface(config.MultiplayerLanInterfaceId).Item2;
|
||||||
|
|
||||||
|
|||||||
@@ -51,13 +51,13 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu
|
|||||||
private string _passphrase;
|
private string _passphrase;
|
||||||
private byte[] _gameVersion = new byte[0x10];
|
private byte[] _gameVersion = new byte[0x10];
|
||||||
|
|
||||||
private readonly HLEConfiguration _config;
|
private readonly HleConfiguration _config;
|
||||||
|
|
||||||
public event EventHandler<NetworkChangeEventArgs> NetworkChange;
|
public event EventHandler<NetworkChangeEventArgs> NetworkChange;
|
||||||
|
|
||||||
public ProxyConfig Config { get; private set; }
|
public ProxyConfig Config { get; private set; }
|
||||||
|
|
||||||
public LdnMasterProxyClient(string address, int port, HLEConfiguration config) : base(address, port)
|
public LdnMasterProxyClient(string address, int port, HleConfiguration config) : base(address, port)
|
||||||
{
|
{
|
||||||
if (ProxyHelpers.SupportsNoDelay())
|
if (ProxyHelpers.SupportsNoDelay())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy;
|
using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy;
|
||||||
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|||||||
@@ -15,55 +15,55 @@ namespace Ryujinx.HLE
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// HLE configuration.
|
/// HLE configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class HLEConfiguration
|
public class HleConfiguration
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The virtual file system used by the FS service.
|
/// The virtual file system used by the FS service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal readonly VirtualFileSystem VirtualFileSystem;
|
internal VirtualFileSystem VirtualFileSystem { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The manager for handling a LibHac Horizon instance.
|
/// The manager for handling a LibHac Horizon instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal readonly LibHacHorizonManager LibHacHorizonManager;
|
internal LibHacHorizonManager LibHacHorizonManager { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The account manager used by the account service.
|
/// The account manager used by the account service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal readonly AccountManager AccountManager;
|
internal AccountManager AccountManager { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The content manager used by the NCM service.
|
/// The content manager used by the NCM service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal readonly ContentManager ContentManager;
|
internal ContentManager ContentManager { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The persistent information between run for multi-application capabilities.
|
/// The persistent information between run for multi-application capabilities.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
public readonly UserChannelPersistence UserChannelPersistence;
|
public UserChannelPersistence UserChannelPersistence { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The GPU renderer to use for all GPU operations.
|
/// The GPU renderer to use for all GPU operations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal readonly IRenderer GpuRenderer;
|
internal IRenderer GpuRenderer { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The audio device driver to use for all audio operations.
|
/// The audio device driver to use for all audio operations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal readonly IHardwareDeviceDriver AudioDeviceDriver;
|
internal IHardwareDeviceDriver AudioDeviceDriver { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The handler for various UI related operations needed outside of HLE.
|
/// The handler for various UI related operations needed outside of HLE.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
internal readonly IHostUIHandler HostUIHandler;
|
internal IHostUIHandler HostUIHandler { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Control the memory configuration used by the emulation context.
|
/// Control the memory configuration used by the emulation context.
|
||||||
@@ -195,15 +195,7 @@ namespace Ryujinx.HLE
|
|||||||
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
public EnabledDirtyHack[] Hacks { internal get; set; }
|
public EnabledDirtyHack[] Hacks { internal get; set; }
|
||||||
|
|
||||||
public HLEConfiguration(VirtualFileSystem virtualFileSystem,
|
public HleConfiguration(MemoryConfiguration memoryConfiguration,
|
||||||
LibHacHorizonManager libHacHorizonManager,
|
|
||||||
ContentManager contentManager,
|
|
||||||
AccountManager accountManager,
|
|
||||||
UserChannelPersistence userChannelPersistence,
|
|
||||||
IRenderer gpuRenderer,
|
|
||||||
IHardwareDeviceDriver audioDeviceDriver,
|
|
||||||
MemoryConfiguration memoryConfiguration,
|
|
||||||
IHostUIHandler hostUIHandler,
|
|
||||||
SystemLanguage systemLanguage,
|
SystemLanguage systemLanguage,
|
||||||
RegionCode region,
|
RegionCode region,
|
||||||
VSyncMode vSyncMode,
|
VSyncMode vSyncMode,
|
||||||
@@ -227,15 +219,7 @@ namespace Ryujinx.HLE
|
|||||||
int customVSyncInterval,
|
int customVSyncInterval,
|
||||||
EnabledDirtyHack[] dirtyHacks = null)
|
EnabledDirtyHack[] dirtyHacks = null)
|
||||||
{
|
{
|
||||||
VirtualFileSystem = virtualFileSystem;
|
|
||||||
LibHacHorizonManager = libHacHorizonManager;
|
|
||||||
AccountManager = accountManager;
|
|
||||||
ContentManager = contentManager;
|
|
||||||
UserChannelPersistence = userChannelPersistence;
|
|
||||||
GpuRenderer = gpuRenderer;
|
|
||||||
AudioDeviceDriver = audioDeviceDriver;
|
|
||||||
MemoryConfiguration = memoryConfiguration;
|
MemoryConfiguration = memoryConfiguration;
|
||||||
HostUIHandler = hostUIHandler;
|
|
||||||
SystemLanguage = systemLanguage;
|
SystemLanguage = systemLanguage;
|
||||||
Region = region;
|
Region = region;
|
||||||
VSyncMode = vSyncMode;
|
VSyncMode = vSyncMode;
|
||||||
@@ -259,5 +243,30 @@ namespace Ryujinx.HLE
|
|||||||
MultiplayerLdnServer = multiplayerLdnServer;
|
MultiplayerLdnServer = multiplayerLdnServer;
|
||||||
Hacks = dirtyHacks ?? [];
|
Hacks = dirtyHacks ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the pre-configured services to use for this <see cref="HleConfiguration"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
public HleConfiguration Configure(
|
||||||
|
VirtualFileSystem virtualFileSystem,
|
||||||
|
LibHacHorizonManager libHacHorizonManager,
|
||||||
|
ContentManager contentManager,
|
||||||
|
AccountManager accountManager,
|
||||||
|
UserChannelPersistence userChannelPersistence,
|
||||||
|
IRenderer gpuRenderer,
|
||||||
|
IHardwareDeviceDriver audioDeviceDriver,
|
||||||
|
IHostUIHandler hostUIHandler
|
||||||
|
)
|
||||||
|
{
|
||||||
|
VirtualFileSystem = virtualFileSystem;
|
||||||
|
LibHacHorizonManager = libHacHorizonManager;
|
||||||
|
AccountManager = accountManager;
|
||||||
|
ContentManager = contentManager;
|
||||||
|
UserChannelPersistence = userChannelPersistence;
|
||||||
|
GpuRenderer = gpuRenderer;
|
||||||
|
AudioDeviceDriver = audioDeviceDriver;
|
||||||
|
HostUIHandler = hostUIHandler;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,16 +71,24 @@ namespace Ryujinx.HLE.Loaders.Mods
|
|||||||
int patchOffset = (int)offset;
|
int patchOffset = (int)offset;
|
||||||
int patchSize = patch.Length;
|
int patchSize = patch.Length;
|
||||||
|
|
||||||
if (patchOffset < protectedOffset || patchOffset > memory.Length)
|
if (patchOffset < protectedOffset)
|
||||||
{
|
{
|
||||||
continue; // Add warning?
|
Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch protected memory ({patchOffset:x} is within protected boundary of {protectedOffset:x}).");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patchOffset > memory.Length)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch out of bounds memory (offset {patchOffset} ({patchOffset:x}) exceeds memory buffer length {memory.Length}).");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
patchOffset -= protectedOffset;
|
patchOffset -= protectedOffset;
|
||||||
|
|
||||||
if (patchOffset + patchSize > memory.Length)
|
if (patchOffset + patchSize > memory.Length)
|
||||||
{
|
{
|
||||||
patchSize = memory.Length - patchOffset; // Add warning?
|
Logger.Warning?.Print(LogClass.ModLoader, $"Patch offset ({patchOffset:x}) + size ({patchSize}) is greater than the size of the memory buffer ({memory.Length}). Attempting to fix this...");
|
||||||
|
patchSize = memory.Length - patchOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.ModLoader, $"Patching address offset {patchOffset:x} <= {BitConverter.ToString(patch).Replace('-', ' ')} len={patchSize}");
|
Logger.Info?.Print(LogClass.ModLoader, $"Patching address offset {patchOffset:x} <= {BitConverter.ToString(patch).Replace('-', ' ')} len={patchSize}");
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Ryujinx.HLE
|
|||||||
{
|
{
|
||||||
public static Switch Shared { get; private set; }
|
public static Switch Shared { get; private set; }
|
||||||
|
|
||||||
public HLEConfiguration Configuration { get; }
|
public HleConfiguration Configuration { get; }
|
||||||
public IHardwareDeviceDriver AudioDeviceDriver { get; }
|
public IHardwareDeviceDriver AudioDeviceDriver { get; }
|
||||||
public MemoryBlock Memory { get; }
|
public MemoryBlock Memory { get; }
|
||||||
public GpuContext Gpu { get; }
|
public GpuContext Gpu { get; }
|
||||||
@@ -44,7 +44,7 @@ namespace Ryujinx.HLE
|
|||||||
|
|
||||||
public DirtyHacks DirtyHacks { get; }
|
public DirtyHacks DirtyHacks { get; }
|
||||||
|
|
||||||
public Switch(HLEConfiguration configuration)
|
public Switch(HleConfiguration configuration)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
|
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
|
||||||
ArgumentNullException.ThrowIfNull(configuration.AudioDeviceDriver);
|
ArgumentNullException.ThrowIfNull(configuration.AudioDeviceDriver);
|
||||||
@@ -94,16 +94,20 @@ namespace Ryujinx.HLE
|
|||||||
Gpu.GPFifo.DispatchCalls();
|
Gpu.GPFifo.DispatchCalls();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void IncrementCustomVSyncInterval()
|
public int IncrementCustomVSyncInterval()
|
||||||
{
|
{
|
||||||
CustomVSyncInterval += 1;
|
CustomVSyncInterval += 1;
|
||||||
UpdateVSyncInterval();
|
UpdateVSyncInterval();
|
||||||
|
|
||||||
|
return CustomVSyncInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DecrementCustomVSyncInterval()
|
public int DecrementCustomVSyncInterval()
|
||||||
{
|
{
|
||||||
CustomVSyncInterval -= 1;
|
CustomVSyncInterval -= 1;
|
||||||
UpdateVSyncInterval();
|
UpdateVSyncInterval();
|
||||||
|
|
||||||
|
return CustomVSyncInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateVSyncInterval()
|
public void UpdateVSyncInterval()
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<Styles
|
<Styles
|
||||||
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:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
|
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||||
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia">
|
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<Border Height="2000"
|
<Border Height="2000"
|
||||||
@@ -30,7 +31,8 @@
|
|||||||
<Button
|
<Button
|
||||||
Name="btnRem"
|
Name="btnRem"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Content="Add" />
|
Content="Add"
|
||||||
|
Classes="red"/>
|
||||||
<TextBox
|
<TextBox
|
||||||
Width="100"
|
Width="100"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
@@ -41,7 +43,13 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<ui:NumberBox Value="1" />
|
<ui:NumberBox Value="1" />
|
||||||
|
<MenuItem
|
||||||
|
Header="123 0000"
|
||||||
|
ToolTip.Tip="What this"/>
|
||||||
|
<TextBlock
|
||||||
|
Classes="globalConfigMarker"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
</Border>
|
</Border>
|
||||||
</Design.PreviewWith>
|
</Design.PreviewWith>
|
||||||
<Style Selector="DropDownButton">
|
<Style Selector="DropDownButton">
|
||||||
@@ -331,6 +339,14 @@
|
|||||||
<Setter Property="Margin"
|
<Setter Property="Margin"
|
||||||
Value="0,5,0,0" />
|
Value="0,5,0,0" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style Selector="TextBlock.globalConfigMarker" >
|
||||||
|
<Setter Property="Foreground" Value="SeaGreen"/>
|
||||||
|
<Setter Property="Margin" Value="5,0,0,0"/>
|
||||||
|
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||||
|
<Setter Property="Text" Value="{ext:Locale GameSpecificConfigurationGlobal}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="StackPanel.globalConfigMarker">
|
||||||
|
</Style>
|
||||||
<Style Selector="ContextMenu">
|
<Style Selector="ContextMenu">
|
||||||
<Setter Property="BorderBrush"
|
<Setter Property="BorderBrush"
|
||||||
Value="{DynamicResource MenuFlyoutPresenterBorderBrush}" />
|
Value="{DynamicResource MenuFlyoutPresenterBorderBrush}" />
|
||||||
@@ -373,6 +389,19 @@
|
|||||||
<Setter Property="Background"
|
<Setter Property="Background"
|
||||||
Value="{DynamicResource AppListHoverBackgroundColor}" />
|
Value="{DynamicResource AppListHoverBackgroundColor}" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style Selector="Button.red /template/ ContentPresenter">
|
||||||
|
<Setter Property="CornerRadius" Value="4"/>
|
||||||
|
<Setter Property="Background" Value="red"/>
|
||||||
|
<Setter Property="Foreground" Value="White"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Button.red:pointerover /template/ ContentPresenter">
|
||||||
|
<Setter Property="CornerRadius" Value="4"/>
|
||||||
|
<Setter Property="Background" Value="{DynamicResource WarningBackgroundColor}" />
|
||||||
|
<Setter Property="Foreground" Value="White"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Styles.Resources>
|
<Styles.Resources>
|
||||||
<SolidColorBrush x:Key="ThemeAccentColorBrush"
|
<SolidColorBrush x:Key="ThemeAccentColorBrush"
|
||||||
Color="{DynamicResource SystemAccentColor}" />
|
Color="{DynamicResource SystemAccentColor}" />
|
||||||
@@ -411,7 +440,7 @@
|
|||||||
<x:Double x:Key="ControlContentThemeFontSize">13</x:Double>
|
<x:Double x:Key="ControlContentThemeFontSize">13</x:Double>
|
||||||
<x:Double x:Key="MenuItemHeight">26</x:Double>
|
<x:Double x:Key="MenuItemHeight">26</x:Double>
|
||||||
<x:Double x:Key="TabItemMinHeight">28</x:Double>
|
<x:Double x:Key="TabItemMinHeight">28</x:Double>
|
||||||
<x:Double x:Key="ContentDialogMaxWidth">900</x:Double>
|
<x:Double x:Key="ContentDialogMaxWidth">700</x:Double>
|
||||||
<x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
|
<x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
|
||||||
</Styles.Resources>
|
</Styles.Resources>
|
||||||
</Styles>
|
</Styles>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
<ResourceDictionary.ThemeDictionaries>
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
<ResourceDictionary x:Key="Default">
|
<ResourceDictionary x:Key="Default">
|
||||||
@@ -12,11 +12,13 @@
|
|||||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||||
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
||||||
|
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
||||||
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
||||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||||
<Color x:Key="Switch">#FF2EEAC9</Color>
|
<Color x:Key="Switch">#FF2EEAC9</Color>
|
||||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||||
<Color x:Key="Custom">#6483F5</Color>
|
<Color x:Key="Custom">#6483F5</Color>
|
||||||
|
<Color x:Key="Warning">#800080</Color>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
<ResourceDictionary x:Key="Light">
|
<ResourceDictionary x:Key="Light">
|
||||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||||
@@ -29,11 +31,13 @@
|
|||||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||||
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
||||||
|
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
||||||
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
||||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||||
<Color x:Key="Switch">#13c3a4</Color>
|
<Color x:Key="Switch">#13c3a4</Color>
|
||||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||||
<Color x:Key="Custom">#6483F5</Color>
|
<Color x:Key="Custom">#6483F5</Color>
|
||||||
|
<Color x:Key="Warning">#800080</Color>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
<ResourceDictionary x:Key="Dark">
|
<ResourceDictionary x:Key="Dark">
|
||||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||||
@@ -46,11 +50,13 @@
|
|||||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color>
|
<Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color>
|
||||||
<Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color>
|
<Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color>
|
||||||
<Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color>
|
<Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color>
|
||||||
|
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
||||||
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
||||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||||
<Color x:Key="Switch">#FF2EEAC9</Color>
|
<Color x:Key="Switch">#FF2EEAC9</Color>
|
||||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||||
<Color x:Key="Custom">#6483F5</Color>
|
<Color x:Key="Custom">#6483F5</Color>
|
||||||
|
<Color x:Key="Warning">#FFA500</Color>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
@@ -464,7 +464,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Abrir Pasta de Capturas de Tela",
|
"pt_BR": "Abrir Pasta de Capturas de Tela",
|
||||||
"ru_RU": "Открыть папку со скриншотами",
|
"ru_RU": "Открыть папку со скриншотами",
|
||||||
"sv_SE": "",
|
"sv_SE": "Öppna skärmbildsmappen",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Відкрити теку скріншотів",
|
"uk_UA": "Відкрити теку скріншотів",
|
||||||
@@ -1564,7 +1564,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Desenvolvido por {0}",
|
"pt_BR": "Desenvolvido por {0}",
|
||||||
"ru_RU": "Разработана {0}",
|
"ru_RU": "Разработана {0}",
|
||||||
"sv_SE": "",
|
"sv_SE": "Utvecklat av {0}",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Розроблено: {0}",
|
"uk_UA": "Розроблено: {0}",
|
||||||
@@ -1864,7 +1864,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Compatibilidade:",
|
"pt_BR": "Compatibilidade:",
|
||||||
"ru_RU": "Совместимость:",
|
"ru_RU": "Совместимость:",
|
||||||
"sv_SE": "",
|
"sv_SE": "Kompatibilitet:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Сумісність:",
|
"uk_UA": "Сумісність:",
|
||||||
@@ -1889,7 +1889,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "ID do Título:",
|
"pt_BR": "ID do Título:",
|
||||||
"ru_RU": "ID приложения",
|
"ru_RU": "ID приложения",
|
||||||
"sv_SE": "",
|
"sv_SE": "Titel-id:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "ID гри:",
|
"uk_UA": "ID гри:",
|
||||||
@@ -1914,7 +1914,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Jogos Hospedados: {0}",
|
"pt_BR": "Jogos Hospedados: {0}",
|
||||||
"ru_RU": "Запущенно игр: {0}",
|
"ru_RU": "Запущенно игр: {0}",
|
||||||
"sv_SE": "",
|
"sv_SE": "Värdskap för spel: {0}",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Розміщені ігри: {0}",
|
"uk_UA": "Розміщені ігри: {0}",
|
||||||
@@ -1939,7 +1939,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Jogadores Online: {0}",
|
"pt_BR": "Jogadores Online: {0}",
|
||||||
"ru_RU": "Игроков онлайн: {0}",
|
"ru_RU": "Игроков онлайн: {0}",
|
||||||
"sv_SE": "",
|
"sv_SE": "Online-spelare: {0}",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Гравців онлайн: {0}",
|
"uk_UA": "Гравців онлайн: {0}",
|
||||||
@@ -2289,7 +2289,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Limpar Cache PPTC",
|
"pt_BR": "Limpar Cache PPTC",
|
||||||
"ru_RU": "Очистить кэш PPTC",
|
"ru_RU": "Очистить кэш PPTC",
|
||||||
"sv_SE": "",
|
"sv_SE": "Rensa PPTC-cache",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Очистити кеш PPTC",
|
"uk_UA": "Очистити кеш PPTC",
|
||||||
@@ -2314,7 +2314,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Apaga os arquivos de cache PPTC do aplicativo",
|
"pt_BR": "Apaga os arquivos de cache PPTC do aplicativo",
|
||||||
"ru_RU": "Удаляет все файлы кэша PPTC для приложения",
|
"ru_RU": "Удаляет все файлы кэша PPTC для приложения",
|
||||||
"sv_SE": "",
|
"sv_SE": "Tar bort alla PPTC-cachefiler för applikationen",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Видаляє всі файли кешу PPTC для застосунку",
|
"uk_UA": "Видаляє всі файли кешу PPTC для застосунку",
|
||||||
@@ -2747,6 +2747,56 @@
|
|||||||
"zh_TW": "建立桌面捷徑,啟動選取的應用程式"
|
"zh_TW": "建立桌面捷徑,啟動選取的應用程式"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "GameListContextMenuCreateCustomConfiguration",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Create Custom Configuration",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "Создать пользовательскую конфигурацию",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "GameListContextMenuEditCustomConfiguration",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Edit Custom Configuration",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "Изменить пользовательскую конфигурацию",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "GameListContextMenuCreateShortcutToolTipMacOS",
|
"ID": "GameListContextMenuCreateShortcutToolTipMacOS",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -2772,6 +2822,56 @@
|
|||||||
"zh_TW": "在 macOS 的應用程式資料夾中建立捷徑,啟動選取的應用程式"
|
"zh_TW": "在 macOS 的應用程式資料夾中建立捷徑,啟動選取的應用程式"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "CreateCustomConfigurationToolTip",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "ينشئ تكوينًا مستقلًا للعبة الحالية",
|
||||||
|
"de_DE": "Erstellt eine unabhängige Konfiguration für das aktuelle Spiel",
|
||||||
|
"el_GR": "Δημιουργεί μια ανεξάρτητη διαμόρφωση για το τρέχον παιχνίδι",
|
||||||
|
"en_US": "Creates an independent configuration for the selected game",
|
||||||
|
"es_ES": "Crea una configuración independiente para el juego actual",
|
||||||
|
"fr_FR": "Crée une configuration indépendante pour le jeu en cours",
|
||||||
|
"he_IL": "יוצר תצורה עצמאית למשחק הנוכחי",
|
||||||
|
"it_IT": "Crea una configurazione indipendente per il gioco attuale",
|
||||||
|
"ja_JP": "現在のゲーム用の独立した設定を作成します",
|
||||||
|
"ko_KR": "현재 게임에 대한 독립적인 설정을 생성합니다",
|
||||||
|
"no_NO": "Oppretter en uavhengig konfigurasjon for det gjeldende spillet",
|
||||||
|
"pl_PL": "Tworzy niezależną konfigurację dla bieżącej gry",
|
||||||
|
"pt_BR": "Cria uma configuração independente para o jogo atual",
|
||||||
|
"ru_RU": "Создает независимую конфигурацию для текущей игры",
|
||||||
|
"sv_SE": "Skapar en oberoende konfiguration för det aktuella spelet",
|
||||||
|
"th_TH": "สร้างการกำหนดค่าที่เป็นอิสระสำหรับเกมปัจจุบัน",
|
||||||
|
"tr_TR": "Mevcut oyun için bağımsız bir yapılandırma oluşturur",
|
||||||
|
"uk_UA": "Створює незалежну конфігурацію для поточної гри",
|
||||||
|
"zh_CN": "为当前游戏创建独立的配置",
|
||||||
|
"zh_TW": "為當前遊戲創建獨立的配置"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "EditCustomConfigurationToolTip",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Edit your existing independent configuration for the selected game",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "Отредактировать существующую независимую конфигурацию для выбранной игры.",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "GameListContextMenuShowCompatEntry",
|
"ID": "GameListContextMenuShowCompatEntry",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -2789,7 +2889,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Mostrar Dados de Compatibilidade",
|
"pt_BR": "Mostrar Dados de Compatibilidade",
|
||||||
"ru_RU": "Показать записи о совместимости",
|
"ru_RU": "Показать записи о совместимости",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa kompatibilitetspost",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Iнформація про сумісність",
|
"uk_UA": "Iнформація про сумісність",
|
||||||
@@ -2814,7 +2914,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Exibe o jogo selecionado na Lista de Compatibilidade, que normalmente pode ser acessada pelo menu Ajuda.",
|
"pt_BR": "Exibe o jogo selecionado na Lista de Compatibilidade, que normalmente pode ser acessada pelo menu Ajuda.",
|
||||||
"ru_RU": "Отобразить выбранную игру в списке совместимости, доступ к которому вы обычно можете получить через меню Справки.",
|
"ru_RU": "Отобразить выбранную игру в списке совместимости, доступ к которому вы обычно можете получить через меню Справки.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa valt spel i kompatibilitetslistan som du normalt sett kan komma åt via hjälpmenyn.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Показати цю гру в Списку Сумісності. Список сумісності також можна зайти в меню Довідки.",
|
"uk_UA": "Показати цю гру в Списку Сумісності. Список сумісності також можна зайти в меню Довідки.",
|
||||||
@@ -2839,7 +2939,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Mostrar Informações do Jogo",
|
"pt_BR": "Mostrar Informações do Jogo",
|
||||||
"ru_RU": "Показать информацию об игре",
|
"ru_RU": "Показать информацию об игре",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa spelinformation",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Інформація про гру",
|
"uk_UA": "Інформація про гру",
|
||||||
@@ -2864,7 +2964,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Exibe estatísticas e detalhes sobre o jogo selecionado.",
|
"pt_BR": "Exibe estatísticas e detalhes sobre o jogo selecionado.",
|
||||||
"ru_RU": "Показывать статистику и подробную информацию о выбранной игре.",
|
"ru_RU": "Показывать статистику и подробную информацию о выбранной игре.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Visa statistik och detaljer om det aktuella spelet.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Показати статистику та деталі обраної гри.",
|
"uk_UA": "Показати статистику та деталі обраної гри.",
|
||||||
@@ -3297,6 +3397,31 @@
|
|||||||
"zh_TW": "設定"
|
"zh_TW": "設定"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "SettingsWithInfo",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "{0} - إعدادات",
|
||||||
|
"de_DE": "Einstellungen - {0}",
|
||||||
|
"el_GR": "Ρυθμίσεις - {0}",
|
||||||
|
"en_US": "Settings - {0}",
|
||||||
|
"es_ES": "Configuración - {0}",
|
||||||
|
"fr_FR": "Paramètres - {0}",
|
||||||
|
"he_IL": "{0} - הגדרות",
|
||||||
|
"it_IT": "Impostazioni - {0}",
|
||||||
|
"ja_JP": "設定 - {0}",
|
||||||
|
"ko_KR": "설정 - {0}",
|
||||||
|
"no_NO": "Innstillinger - {0}",
|
||||||
|
"pl_PL": "Ustawienia - {0}",
|
||||||
|
"pt_BR": "Configurações - {0}",
|
||||||
|
"ru_RU": "Параметры - {0}",
|
||||||
|
"sv_SE": "Inställningar - {0}",
|
||||||
|
"th_TH": "ตั้งค่า - {0}",
|
||||||
|
"tr_TR": "Ayarlar - {0}",
|
||||||
|
"uk_UA": "Налаштування - {0}",
|
||||||
|
"zh_CN": "设置 - {0}",
|
||||||
|
"zh_TW": "設定 - {0}"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "SettingsTabGeneral",
|
"ID": "SettingsTabGeneral",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -3389,7 +3514,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Verificar Atualizações:",
|
"pt_BR": "Verificar Atualizações:",
|
||||||
"ru_RU": "Проверка наличия обновлений",
|
"ru_RU": "Проверка наличия обновлений",
|
||||||
"sv_SE": "",
|
"sv_SE": "Leta efter uppdateringar:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Перевірка оновлень:",
|
"uk_UA": "Перевірка оновлень:",
|
||||||
@@ -3414,7 +3539,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Desligado",
|
"pt_BR": "Desligado",
|
||||||
"ru_RU": "Отключить",
|
"ru_RU": "Отключить",
|
||||||
"sv_SE": "",
|
"sv_SE": "Av",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Вимкнути",
|
"uk_UA": "Вимкнути",
|
||||||
@@ -3439,7 +3564,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ao Abrir",
|
"pt_BR": "Ao Abrir",
|
||||||
"ru_RU": "При запуске",
|
"ru_RU": "При запуске",
|
||||||
"sv_SE": "",
|
"sv_SE": "Fråga",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запитувати щоразу",
|
"uk_UA": "Запитувати щоразу",
|
||||||
@@ -3464,7 +3589,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "2° Plano",
|
"pt_BR": "2° Plano",
|
||||||
"ru_RU": "В фоне",
|
"ru_RU": "В фоне",
|
||||||
"sv_SE": "",
|
"sv_SE": "Bakgrund",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Оновлювати в фоні",
|
"uk_UA": "Оновлювати в фоні",
|
||||||
@@ -3489,7 +3614,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ao Perder o Foco:",
|
"pt_BR": "Ao Perder o Foco:",
|
||||||
"ru_RU": "При выходе эмулятора из фокуса",
|
"ru_RU": "При выходе эмулятора из фокуса",
|
||||||
"sv_SE": "",
|
"sv_SE": "När emulatorn tappar fokus:",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "При втраті фокуса емулятором:",
|
"uk_UA": "При втраті фокуса емулятором:",
|
||||||
@@ -3514,7 +3639,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Não Fazer Nada",
|
"pt_BR": "Não Fazer Nada",
|
||||||
"ru_RU": "Ничего не делать",
|
"ru_RU": "Ничего не делать",
|
||||||
"sv_SE": "",
|
"sv_SE": "Gör ingenting",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Нічого не робити",
|
"uk_UA": "Нічого не робити",
|
||||||
@@ -3539,7 +3664,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Bloquear Controles",
|
"pt_BR": "Bloquear Controles",
|
||||||
"ru_RU": "Блокировать управление",
|
"ru_RU": "Блокировать управление",
|
||||||
"sv_SE": "",
|
"sv_SE": "Blockera inmatning",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Блокувати введення",
|
"uk_UA": "Блокувати введення",
|
||||||
@@ -3564,7 +3689,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ficar Mudo",
|
"pt_BR": "Ficar Mudo",
|
||||||
"ru_RU": "Отключить звук",
|
"ru_RU": "Отключить звук",
|
||||||
"sv_SE": "",
|
"sv_SE": "Stäng av ljudet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Вимкнути звук",
|
"uk_UA": "Вимкнути звук",
|
||||||
@@ -3589,7 +3714,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Bloquear Controles & Ficar Mudo",
|
"pt_BR": "Bloquear Controles & Ficar Mudo",
|
||||||
"ru_RU": "Блокировать управление и отключить звук",
|
"ru_RU": "Блокировать управление и отключить звук",
|
||||||
"sv_SE": "",
|
"sv_SE": "Blockera inmatningar och stäng av ljudet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Блокувати введення та Вимкнути звук",
|
"uk_UA": "Блокувати введення та Вимкнути звук",
|
||||||
@@ -3614,7 +3739,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Pausar a Emulação",
|
"pt_BR": "Pausar a Emulação",
|
||||||
"ru_RU": "Поставить паузу",
|
"ru_RU": "Поставить паузу",
|
||||||
"sv_SE": "",
|
"sv_SE": "Pausa emuleringen",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Поставити на паузу",
|
"uk_UA": "Поставити на паузу",
|
||||||
@@ -3689,7 +3814,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Desativar Controles Quando Estiver Fora de Foco",
|
"pt_BR": "Desativar Controles Quando Estiver Fora de Foco",
|
||||||
"ru_RU": "Отключает управление при выходе из фокуса",
|
"ru_RU": "Отключает управление при выходе из фокуса",
|
||||||
"sv_SE": "",
|
"sv_SE": "Inaktivera inmatning när fokus tappas",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "",
|
"uk_UA": "",
|
||||||
@@ -3698,28 +3823,53 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ID": "SettingsTabGeneralShowTitleBar",
|
"ID": "SettingsTabGeneralShowOldUI",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
"ar_SA": "",
|
"ar_SA": "",
|
||||||
"de_DE": "",
|
"de_DE": "",
|
||||||
"el_GR": "",
|
"el_GR": "",
|
||||||
"en_US": "Show Title Bar (Requires restart)",
|
"en_US": "Show Original UI Style (Requires restart)",
|
||||||
"es_ES": "Mostrar Barra de Título (Requiere reinicio)",
|
"es_ES": "",
|
||||||
"fr_FR": "Afficher Barre de Titre (Nécessite redémarrage)",
|
"fr_FR": "",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "Mostra barra del titolo (Richiede il riavvio)",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "제목 표시줄 표시(다시 시작해야 함)",
|
"ko_KR": "",
|
||||||
"no_NO": "Vis tittellinje (krever omstart)",
|
"no_NO": "Vis original UI-stil (krever omstart)",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Mostrar Barra de Título (Requer reinicialização)",
|
"pt_BR": "",
|
||||||
"ru_RU": "Показать строку заголовка (требуется перезапуск)",
|
"ru_RU": "",
|
||||||
"sv_SE": "Visa titelrad (kräver omstart)",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Показувати рядок заголовка (Потрібен перезапуск)",
|
"uk_UA": "",
|
||||||
"zh_CN": "显示标题栏 (需要重启)",
|
"zh_CN": "",
|
||||||
"zh_TW": "顯示「標題列」 (需要重新開啟Ryujinx)"
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "SettingsTabGeneralShowOldUIToolTip",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Show the older Avalonia Ryujinx UI reminiscent of Ryujinx 1.1.1403. This is enabled by default on platforms that are not Windows.\nThe classic-style title bar is back and major window layout reworkings are reversed; such as the settings navigation placement above this tooltip.",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "Vis det eldre Avalonia Ryujinx-grensesnittet som minner om Ryujinx 1.1.1403. Dette er aktivert som standard på plattformer som ikke er Windows.\nTittellinjen i klassisk stil er tilbake, og store omarbeidinger av vindusoppsettet er reversert, for eksempel plasseringen av innstillingsnavigasjonen over dette verktøytipset.",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -4714,7 +4864,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Sincronizar com o Sistema PC",
|
"pt_BR": "Sincronizar com o Sistema PC",
|
||||||
"ru_RU": "Соответствовать времени в системе",
|
"ru_RU": "Соответствовать времени в системе",
|
||||||
"sv_SE": "",
|
"sv_SE": "Matcha systemtid",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "",
|
"uk_UA": "",
|
||||||
@@ -4888,7 +5038,7 @@
|
|||||||
"no_NO": "Lyd Inn/Ut",
|
"no_NO": "Lyd Inn/Ut",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Выход/Вход звука",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -5139,7 +5289,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ignorar Applet do Controlador",
|
"pt_BR": "Ignorar Applet do Controlador",
|
||||||
"ru_RU": "Игнорировать апплет контроллера",
|
"ru_RU": "Игнорировать апплет контроллера",
|
||||||
"sv_SE": "",
|
"sv_SE": "Ignorera kontroller-applet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Ігнорувати Аплет Контролера",
|
"uk_UA": "Ігнорувати Аплет Контролера",
|
||||||
@@ -5989,7 +6139,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Habilitar Logs da IU",
|
"pt_BR": "Habilitar Logs da IU",
|
||||||
"ru_RU": "Включить журнал интерфейса",
|
"ru_RU": "Включить журнал интерфейса",
|
||||||
"sv_SE": "",
|
"sv_SE": "Aktivera gränssnittsloggar",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Увімкнути журнали інтерфейсу",
|
"uk_UA": "Увімкнути журнали інтерфейсу",
|
||||||
@@ -6389,7 +6539,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Redefinir Configurações",
|
"pt_BR": "Redefinir Configurações",
|
||||||
"ru_RU": "Сбросить настройки",
|
"ru_RU": "Сбросить настройки",
|
||||||
"sv_SE": "",
|
"sv_SE": "Nollställ inställningar",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Скинути налаштування",
|
"uk_UA": "Скинути налаштування",
|
||||||
@@ -6414,7 +6564,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Quero redefinir minhas configurações.",
|
"pt_BR": "Quero redefinir minhas configurações.",
|
||||||
"ru_RU": "Я хочу сбросить свои настройки.",
|
"ru_RU": "Я хочу сбросить свои настройки.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Jag vill nollställa mina inställningar.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Я хочу скинути налаштування.",
|
"uk_UA": "Я хочу скинути налаштування.",
|
||||||
@@ -6438,7 +6588,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Ок",
|
||||||
"sv_SE": "Ok",
|
"sv_SE": "Ok",
|
||||||
"th_TH": "ตกลง",
|
"th_TH": "ตกลง",
|
||||||
"tr_TR": "Tamam",
|
"tr_TR": "Tamam",
|
||||||
@@ -6888,7 +7038,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "Pro Kontroler",
|
"pl_PL": "Pro Kontroler",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Pro контроллер",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "โปรคอนโทรลเลอร์",
|
"th_TH": "โปรคอนโทรลเลอร์",
|
||||||
"tr_TR": "Profesyonel Kumanda",
|
"tr_TR": "Profesyonel Kumanda",
|
||||||
@@ -8389,7 +8539,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Velocidade do Arco-íris",
|
"pt_BR": "Velocidade do Arco-íris",
|
||||||
"ru_RU": "Скорость переливания",
|
"ru_RU": "Скорость переливания",
|
||||||
"sv_SE": "",
|
"sv_SE": "Regnbågshastighet",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "",
|
"uk_UA": "",
|
||||||
@@ -12647,6 +12797,31 @@
|
|||||||
"zh_TW": "正在下載更新..."
|
"zh_TW": "正在下載更新..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "DialogRebooterMessage",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "من فضلك انتظر، المحاكي في طور إعادة التشغيل",
|
||||||
|
"de_DE": "Bitte warten Sie, der Emulator wird neu gestartet",
|
||||||
|
"el_GR": "Παρακαλώ περιμένετε, ο εξομοιωτής επανεκκινείται",
|
||||||
|
"en_US": "Please wait, the emulator is restarting",
|
||||||
|
"es_ES": "Por favor, espere, el emulador se está reiniciando",
|
||||||
|
"fr_FR": "Veuillez patienter, l'émulateur est en train de redémarrer",
|
||||||
|
"he_IL": "אנא המתן, המחקה מתארגן מחדש",
|
||||||
|
"it_IT": "Attendere prego, l'emulatore si sta riavviando",
|
||||||
|
"ja_JP": "お待ちください、エミュレーターが再起動しています",
|
||||||
|
"ko_KR": "잠시만 기다려 주세요, 에뮬레이터가 재시작 중입니다",
|
||||||
|
"no_NO": "Vennligst vent, emulatoren starter på nytt",
|
||||||
|
"pl_PL": "Proszę czekać, emulator jest w trakcie ponownego uruchamiania",
|
||||||
|
"pt_BR": "Por favor, aguarde, o emulador está reiniciando",
|
||||||
|
"ru_RU": "Пожалуйста, подождите, эмулятор перезапускается",
|
||||||
|
"sv_SE": "Vänligen vänta, emulatorn startar om",
|
||||||
|
"th_TH": "กรุณารอสักครู่, ตัวจำลองกำลังเริ่มใหม่",
|
||||||
|
"tr_TR": "Lütfen bekleyin, emülatör yeniden başlatılıyor",
|
||||||
|
"uk_UA": "Будь ласка, зачекайте, емулятор перезавантажується",
|
||||||
|
"zh_CN": "请稍等,模拟器正在重新启动",
|
||||||
|
"zh_TW": "請稍候,模擬器正在重新啟動"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "DialogUpdaterExtractionMessage",
|
"ID": "DialogUpdaterExtractionMessage",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -13664,7 +13839,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Você está prestes a limpar todos os dados PPTC de:\n\n{0}\n\nTem certeza de que deseja continuar?",
|
"pt_BR": "Você está prestes a limpar todos os dados PPTC de:\n\n{0}\n\nTem certeza de que deseja continuar?",
|
||||||
"ru_RU": "Вы собираетесь удалить все данные PPTC из:\n\n{0}\n\nВы уверены, что хотите продолжить?",
|
"ru_RU": "Вы собираетесь удалить все данные PPTC из:\n\n{0}\n\nВы уверены, что хотите продолжить?",
|
||||||
"sv_SE": "",
|
"sv_SE": "Du är på väg att ta bort allt PPTC-data från:\n\n{0}\n\nÄr du säker på att du vill fortsätta?",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Ви збираєтесь видалити всі дані PPTC з:\n\n{0}\n\nБажаєте продовжити цю операцію?",
|
"uk_UA": "Ви збираєтесь видалити всі дані PPTC з:\n\n{0}\n\nБажаєте продовжити цю операцію?",
|
||||||
@@ -16514,7 +16689,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "A caixa de diálogo do Applet do controlador não aparecerá se o controle for desconectado enquanto um aplicativo estiver em execução.\n\nDeixe a opção DESLIGADO se não tiver certeza.",
|
"pt_BR": "A caixa de diálogo do Applet do controlador não aparecerá se o controle for desconectado enquanto um aplicativo estiver em execução.\n\nDeixe a opção DESLIGADO se não tiver certeza.",
|
||||||
"ru_RU": "Диалоговое окно апплета контроллера не будет отображаться, если геймпад отключен во время работы приложения.\n\nОставьте выключенным, если не уверены.",
|
"ru_RU": "Диалоговое окно апплета контроллера не будет отображаться, если геймпад отключен во время работы приложения.\n\nОставьте выключенным, если не уверены.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Handkontroller-appleten kommer inte att visas om gamepaden är frånkopplad under tiden en applikation körs.\n\nLämna AV om du är osäker.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Діалогове вікно Аплету Контролера не з'явиться, якщо геймпад було відключено під час роботи програми.\n\nЗалиште вимкненим якщо не впевнені.",
|
"uk_UA": "Діалогове вікно Аплету Контролера не з'явиться, якщо геймпад було відключено під час роботи програми.\n\nЗалиште вимкненим якщо не впевнені.",
|
||||||
@@ -16989,7 +17164,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Imprime mensagens de log do Avalonia (UI) no console.",
|
"pt_BR": "Imprime mensagens de log do Avalonia (UI) no console.",
|
||||||
"ru_RU": "Выводит сообщения журнала Avalonia (интерфейс) в консоли.",
|
"ru_RU": "Выводит сообщения журнала Avalonia (интерфейс) в консоли.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Skriver ut loggmeddelanden från Avalonia (användargränssnittet) i konsollen.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Виводити повідомлення журналу Avalonia (UI) в консоль",
|
"uk_UA": "Виводити повідомлення журналу Avalonia (UI) в консоль",
|
||||||
@@ -17189,7 +17364,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Abre a pasta de capturas de tela do Ryujinx",
|
"pt_BR": "Abre a pasta de capturas de tela do Ryujinx",
|
||||||
"ru_RU": "Открывает папку скриншотов Ryujinx",
|
"ru_RU": "Открывает папку скриншотов Ryujinx",
|
||||||
"sv_SE": "",
|
"sv_SE": "Öppna Ryujinx skärmbildsmapp",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Відкрити теку куди зберігаються скріншоти Ryujinx",
|
"uk_UA": "Відкрити теку куди зберігаються скріншоти Ryujinx",
|
||||||
@@ -17939,7 +18114,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Atualização Disponível!",
|
"pt_BR": "Atualização Disponível!",
|
||||||
"ru_RU": "Доступно обновление!",
|
"ru_RU": "Доступно обновление!",
|
||||||
"sv_SE": "",
|
"sv_SE": "Uppdatering finns tillgänglig!",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Доступне оновлення!",
|
"uk_UA": "Доступне оновлення!",
|
||||||
@@ -19522,6 +19697,31 @@
|
|||||||
"zh_TW": "{0} 更新程式"
|
"zh_TW": "{0} 更新程式"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "RyujinxRebooter",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "إعادة تشغيل {0}",
|
||||||
|
"de_DE": "Neustart von {0}",
|
||||||
|
"el_GR": "Επανεκκίνηση {0}",
|
||||||
|
"en_US": "{0} Reboot",
|
||||||
|
"es_ES": "Reinicio de {0}",
|
||||||
|
"fr_FR": "Redémarrage de {0}",
|
||||||
|
"he_IL": "אתחול {0}",
|
||||||
|
"it_IT": "Riavvio di {0}",
|
||||||
|
"ja_JP": "{0} 再起動",
|
||||||
|
"ko_KR": "{0} 재부팅",
|
||||||
|
"no_NO": "Omstart av {0}",
|
||||||
|
"pl_PL": "Ponowne uruchomienie {0}",
|
||||||
|
"pt_BR": "Reinício de {0}",
|
||||||
|
"ru_RU": "{0} Перезагрузка",
|
||||||
|
"sv_SE": "Ominläsning av {0}",
|
||||||
|
"th_TH": "เริ่มต้นใหม่ {0}",
|
||||||
|
"tr_TR": "{0} Yeniden Başlatma",
|
||||||
|
"uk_UA": "Перезавантаження {0}",
|
||||||
|
"zh_CN": "{0} 重启",
|
||||||
|
"zh_TW": "{0} 重新啟動"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "SettingsTabHotkeys",
|
"ID": "SettingsTabHotkeys",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -19838,7 +20038,7 @@
|
|||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "Амибо",
|
||||||
"sv_SE": "",
|
"sv_SE": "",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
@@ -23647,6 +23847,31 @@
|
|||||||
"zh_TW": "上次更新時間: {0}"
|
"zh_TW": "上次更新時間: {0}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "CompatibilityListTitle",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Compatibility List - {0} entries",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "CompatibilityListWarning",
|
"ID": "CompatibilityListWarning",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -23697,6 +23922,31 @@
|
|||||||
"zh_TW": "搜尋相容性列表紀錄..."
|
"zh_TW": "搜尋相容性列表紀錄..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "CompatibilityListSearchBoxWatermarkWithCount",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Search {0} compatibility entries...",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "Søk i {0} kompatibilitetsoppføringer...",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "CompatibilityListOpen",
|
"ID": "CompatibilityListOpen",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -23889,7 +24139,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inicializa e roda sem travamentos ou bugs de GPU de qualquer tipo, e em uma velocidade rápida o suficiente para ser aproveitado em um PC comum.",
|
"pt_BR": "Inicializa e roda sem travamentos ou bugs de GPU de qualquer tipo, e em uma velocidade rápida o suficiente para ser aproveitado em um PC comum.",
|
||||||
"ru_RU": "Запускается и работает без любого рода сбоев или графисечких ошибок и на скорости, достаточной для работы на обычном ПК.",
|
"ru_RU": "Запускается и работает без любого рода сбоев или графисечких ошибок и на скорости, достаточной для работы на обычном ПК.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar upp och spelas utan några krascher eller GPU-fel av några slag och med en hastighet som är snabb nog för bra upplevelse på en genomsnittlig PC.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається та оптимально працює (без збоїв або графічних багів) на середньостатистичному комп'ютері.",
|
"uk_UA": "Запускається та оптимально працює (без збоїв або графічних багів) на середньостатистичному комп'ютері.",
|
||||||
@@ -23914,7 +24164,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inicializa e entra no jogo, mas sofre de um ou mais dos seguintes: travamentos, deadlocks, bugs de GPU, áudio ruim que distrai ou é simplesmente muito lento. O jogo ainda pode ser jogado até o fim, mas não da forma como foi criado para ser jogado.",
|
"pt_BR": "Inicializa e entra no jogo, mas sofre de um ou mais dos seguintes: travamentos, deadlocks, bugs de GPU, áudio ruim que distrai ou é simplesmente muito lento. O jogo ainda pode ser jogado até o fim, mas não da forma como foi criado para ser jogado.",
|
||||||
"ru_RU": "Запускается и работает, но возникает одна или несколько из следующих проблем: сбои, взаимоблокировки, ошибки GPU, отвлекающие звуки или просто слишком медленная работа. Возможно, игру всё же удастся пройти до конца, но не так, как она задумана.",
|
"ru_RU": "Запускается и работает, но возникает одна или несколько из следующих проблем: сбои, взаимоблокировки, ошибки GPU, отвлекающие звуки или просто слишком медленная работа. Возможно, игру всё же удастся пройти до конца, но не так, как она задумана.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar och går in i spelet men lider av ett eller flera av följande: kraschar, deadlocks, GPU-buggar, distraherande dåligt ljud eller är helt enkelt för långsamt. Spelet kan fortfarande spelas hela vägen igenom, men inte så som spelet är avsett att spelas.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається, але в грі на вас чекатимуть одна або декілька наступних проблем: збої, зависання, графічні баги, спотворений звук або ж гра загалом працюватиме надто повільно. Можливо, її все ще можна пройти, але досвід буде не найкращим.",
|
"uk_UA": "Запускається, але в грі на вас чекатимуть одна або декілька наступних проблем: збої, зависання, графічні баги, спотворений звук або ж гра загалом працюватиме надто повільно. Можливо, її все ще можна пройти, але досвід буде не найкращим.",
|
||||||
@@ -23939,7 +24189,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inicializa e passa da tela de título, mas não entra no jogo principal.",
|
"pt_BR": "Inicializa e passa da tela de título, mas não entra no jogo principal.",
|
||||||
"ru_RU": "Загружается титульный экран и можно перейти дальше, но сама игра не работает.",
|
"ru_RU": "Загружается титульный экран и можно перейти дальше, но сама игра не работает.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar upp och går förbi titelskärmen men tar sig inte in i huvudspelet.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається та проходить початковий екран, але пограти не вийде.",
|
"uk_UA": "Запускається та проходить початковий екран, але пограти не вийде.",
|
||||||
@@ -23964,7 +24214,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Inizializa, mas não passa da tela de título.",
|
"pt_BR": "Inizializa, mas não passa da tela de título.",
|
||||||
"ru_RU": "Загружается, но не проходит дальше титульного экрана.",
|
"ru_RU": "Загружается, но не проходит дальше титульного экрана.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar upp men tar sig inte förbi titelskärmen.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Запускається, але не відображає навіть початкового екрану.",
|
"uk_UA": "Запускається, але не відображає навіть початкового екрану.",
|
||||||
@@ -23989,7 +24239,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Não inicializa ou não mostra sinais de atividade.",
|
"pt_BR": "Não inicializa ou não mostra sinais de atividade.",
|
||||||
"ru_RU": "Не запускается или не подаёт признаков жизни.",
|
"ru_RU": "Не запускается или не подаёт признаков жизни.",
|
||||||
"sv_SE": "",
|
"sv_SE": "Startar inte upp eller visar någon form av aktivitet.",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Взагалі не запускається.",
|
"uk_UA": "Взагалі не запускається.",
|
||||||
@@ -23997,6 +24247,56 @@
|
|||||||
"zh_TW": ""
|
"zh_TW": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "GameSpecificConfigurationHeader",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Custom Config",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "GameSpecificConfigurationGlobal",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "(Global)",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "ExtractAocListHeader",
|
"ID": "ExtractAocListHeader",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@@ -24039,7 +24339,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Imagem da Presença do Discord",
|
"pt_BR": "Imagem da Presença do Discord",
|
||||||
"ru_RU": "Изображение для статуса активности",
|
"ru_RU": "Изображение для статуса активности",
|
||||||
"sv_SE": "",
|
"sv_SE": "Bild för Rich Presence",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Зображення картки активності Discord",
|
"uk_UA": "Зображення картки активності Discord",
|
||||||
@@ -24064,7 +24364,7 @@
|
|||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Presença Dinâmica do Discord",
|
"pt_BR": "Presença Dinâmica do Discord",
|
||||||
"ru_RU": "Динамический статус активности",
|
"ru_RU": "Динамический статус активности",
|
||||||
"sv_SE": "",
|
"sv_SE": "Dynamisk Rich Presence",
|
||||||
"th_TH": "",
|
"th_TH": "",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Динамічна картка активності Discord",
|
"uk_UA": "Динамічна картка активності Discord",
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ 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.Windows;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
@@ -216,11 +216,7 @@ namespace Ryujinx.Ava.Common
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
|
(Nca updatePatchNca, _) = mainNca.GetUpdateData(_virtualFileSystem, ConfigurationState.Instance.System.IntegrityCheckLevel, programIndex, out _);
|
||||||
? IntegrityCheckLevel.ErrorOnInvalid
|
|
||||||
: IntegrityCheckLevel.None;
|
|
||||||
|
|
||||||
(Nca updatePatchNca, _) = mainNca.GetUpdateData(_virtualFileSystem, checkLevel, programIndex, out _);
|
|
||||||
if (updatePatchNca is not null)
|
if (updatePatchNca is not null)
|
||||||
{
|
{
|
||||||
patchNca = updatePatchNca;
|
patchNca = updatePatchNca;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Gommon;
|
using Gommon;
|
||||||
|
using Ryujinx.Ava.Systems;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using System;
|
using System;
|
||||||
@@ -25,7 +26,21 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
public LocaleManager()
|
public LocaleManager()
|
||||||
{
|
{
|
||||||
_localeStrings = new Dictionary<LocaleKeys, string>();
|
_localeStrings = new Dictionary<LocaleKeys, string>();
|
||||||
_dynamicValues = new ConcurrentDictionary<LocaleKeys, object[]>();
|
_dynamicValues = new ConcurrentDictionary<LocaleKeys, object[]>(new Dictionary<LocaleKeys, object[]>
|
||||||
|
{
|
||||||
|
{ LocaleKeys.DialogConfirmationTitle, [RyujinxApp.FullAppName] },
|
||||||
|
{ LocaleKeys.DialogUpdaterTitle, [RyujinxApp.FullAppName] },
|
||||||
|
{ LocaleKeys.DialogErrorTitle, [RyujinxApp.FullAppName] },
|
||||||
|
{ LocaleKeys.DialogWarningTitle, [RyujinxApp.FullAppName] },
|
||||||
|
{ LocaleKeys.DialogExitTitle, [RyujinxApp.FullAppName] },
|
||||||
|
{ LocaleKeys.DialogStopEmulationTitle, [RyujinxApp.FullAppName] },
|
||||||
|
{ LocaleKeys.RyujinxInfo, [RyujinxApp.FullAppName] },
|
||||||
|
{ LocaleKeys.RyujinxConfirm, [RyujinxApp.FullAppName] },
|
||||||
|
{ LocaleKeys.RyujinxUpdater, [RyujinxApp.FullAppName] },
|
||||||
|
{ LocaleKeys.RyujinxRebooter, [RyujinxApp.FullAppName] },
|
||||||
|
{ LocaleKeys.CompatibilityListSearchBoxWatermarkWithCount, [CompatibilityDatabase.Entries.Length] },
|
||||||
|
{ LocaleKeys.CompatibilityListTitle, [CompatibilityDatabase.Entries.Length] }
|
||||||
|
});
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
@@ -44,16 +59,6 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
|
|
||||||
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDynamicValues(LocaleKeys.DialogConfirmationTitle, RyujinxApp.FullAppName);
|
|
||||||
SetDynamicValues(LocaleKeys.DialogUpdaterTitle, RyujinxApp.FullAppName);
|
|
||||||
SetDynamicValues(LocaleKeys.DialogErrorTitle, RyujinxApp.FullAppName);
|
|
||||||
SetDynamicValues(LocaleKeys.DialogWarningTitle, RyujinxApp.FullAppName);
|
|
||||||
SetDynamicValues(LocaleKeys.DialogExitTitle, RyujinxApp.FullAppName);
|
|
||||||
SetDynamicValues(LocaleKeys.DialogStopEmulationTitle, RyujinxApp.FullAppName);
|
|
||||||
SetDynamicValues(LocaleKeys.RyujinxInfo, RyujinxApp.FullAppName);
|
|
||||||
SetDynamicValues(LocaleKeys.RyujinxConfirm, RyujinxApp.FullAppName);
|
|
||||||
SetDynamicValues(LocaleKeys.RyujinxUpdater, RyujinxApp.FullAppName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string this[LocaleKeys key]
|
public string this[LocaleKeys key]
|
||||||
|
|||||||
@@ -24,4 +24,17 @@ namespace Ryujinx.Ava.Common.Markup
|
|||||||
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
||||||
=> bindingExtension.Source = LocaleManager.Instance;
|
=> bindingExtension.Source = LocaleManager.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class WindowTitleExtension(LocaleKeys key, bool includeVersion) : BasicMarkupExtension<string>
|
||||||
|
{
|
||||||
|
public WindowTitleExtension(LocaleKeys key) : this(key, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Name => "WindowTitleTranslation";
|
||||||
|
protected override string Value => RyujinxApp.FormatTitle(key, includeVersion);
|
||||||
|
|
||||||
|
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
||||||
|
=> bindingExtension.Source = LocaleManager.Instance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ namespace Ryujinx.Ava.Common
|
|||||||
|
|
||||||
internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog
|
internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog
|
||||||
{
|
{
|
||||||
private readonly XCITrimmerViewModel _viewModel;
|
private readonly XciTrimmerViewModel _viewModel;
|
||||||
|
|
||||||
public TrimmerWindow(XCITrimmerViewModel viewModel)
|
public TrimmerWindow(XciTrimmerViewModel viewModel)
|
||||||
{
|
{
|
||||||
_viewModel = viewModel;
|
_viewModel = viewModel;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ using DiscordRPC;
|
|||||||
using LibHac.Tools.FsSystem;
|
using LibHac.Tools.FsSystem;
|
||||||
using Ryujinx.Audio.Backends.SDL2;
|
using Ryujinx.Audio.Backends.SDL2;
|
||||||
using Ryujinx.Ava;
|
using Ryujinx.Ava;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems;
|
||||||
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
@@ -11,7 +12,6 @@ using Ryujinx.Common.Configuration.Hid.Keyboard;
|
|||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.GAL.Multithreading;
|
|
||||||
using Ryujinx.Graphics.OpenGL;
|
using Ryujinx.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.Vulkan;
|
using Ryujinx.Graphics.Vulkan;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
@@ -312,26 +312,10 @@ namespace Ryujinx.Headless
|
|||||||
return new OpenGLRenderer();
|
return new OpenGLRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)
|
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options) =>
|
||||||
{
|
new(
|
||||||
BackendThreading threadingMode = options.BackendThreading;
|
new HleConfiguration(
|
||||||
|
|
||||||
bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
|
||||||
|
|
||||||
if (threadedGAL)
|
|
||||||
{
|
|
||||||
renderer = new ThreadedRenderer(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
HLEConfiguration configuration = new(_virtualFileSystem,
|
|
||||||
_libHacHorizonManager,
|
|
||||||
_contentManager,
|
|
||||||
_accountManager,
|
|
||||||
_userChannelPersistence,
|
|
||||||
renderer,
|
|
||||||
new SDL2HardwareDeviceDriver(),
|
|
||||||
options.DramSize,
|
options.DramSize,
|
||||||
window,
|
|
||||||
options.SystemLanguage,
|
options.SystemLanguage,
|
||||||
options.SystemRegion,
|
options.SystemRegion,
|
||||||
options.VSyncMode,
|
options.VSyncMode,
|
||||||
@@ -352,9 +336,18 @@ namespace Ryujinx.Headless
|
|||||||
false,
|
false,
|
||||||
string.Empty,
|
string.Empty,
|
||||||
string.Empty,
|
string.Empty,
|
||||||
options.CustomVSyncInterval);
|
options.CustomVSyncInterval
|
||||||
|
)
|
||||||
return new Switch(configuration);
|
.Configure(
|
||||||
}
|
_virtualFileSystem,
|
||||||
|
_libHacHorizonManager,
|
||||||
|
_contentManager,
|
||||||
|
_accountManager,
|
||||||
|
_userChannelPersistence,
|
||||||
|
renderer.TryMakeThreaded(options.BackendThreading),
|
||||||
|
new SDL2HardwareDeviceDriver(),
|
||||||
|
window
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using CommandLine;
|
using CommandLine;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava;
|
using Ryujinx.Ava;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using CommandLine;
|
using CommandLine;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
|
using Ryujinx.Ava.Systems.Configuration.System;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
@@ -37,7 +38,7 @@ namespace Ryujinx.Headless
|
|||||||
EnableInternetAccess = configurationState.System.EnableInternetAccess;
|
EnableInternetAccess = configurationState.System.EnableInternetAccess;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(DisableFsIntegrityChecks)))
|
if (NeedsOverride(nameof(DisableFsIntegrityChecks)))
|
||||||
DisableFsIntegrityChecks = configurationState.System.EnableFsIntegrityChecks;
|
DisableFsIntegrityChecks = !configurationState.System.EnableFsIntegrityChecks;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(FsGlobalAccessLogMode)))
|
if (NeedsOverride(nameof(FsGlobalAccessLogMode)))
|
||||||
FsGlobalAccessLogMode = configurationState.System.FsGlobalAccessLogMode;
|
FsGlobalAccessLogMode = configurationState.System.FsGlobalAccessLogMode;
|
||||||
@@ -58,10 +59,10 @@ namespace Ryujinx.Headless
|
|||||||
DisableDockedMode = !configurationState.System.EnableDockedMode;
|
DisableDockedMode = !configurationState.System.EnableDockedMode;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(SystemLanguage)))
|
if (NeedsOverride(nameof(SystemLanguage)))
|
||||||
SystemLanguage = (SystemLanguage)(int)configurationState.System.Language.Value;
|
SystemLanguage = configurationState.System.Language.Value.ToHLE();
|
||||||
|
|
||||||
if (NeedsOverride(nameof(SystemRegion)))
|
if (NeedsOverride(nameof(SystemRegion)))
|
||||||
SystemRegion = (RegionCode)(int)configurationState.System.Region.Value;
|
SystemRegion = configurationState.System.Region.Value.ToHLE();
|
||||||
|
|
||||||
if (NeedsOverride(nameof(SystemTimeZone)))
|
if (NeedsOverride(nameof(SystemTimeZone)))
|
||||||
SystemTimeZone = configurationState.System.TimeZone;
|
SystemTimeZone = configurationState.System.TimeZone;
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ using Gommon;
|
|||||||
using Projektanker.Icons.Avalonia;
|
using Projektanker.Icons.Avalonia;
|
||||||
using Projektanker.Icons.Avalonia.FontAwesome;
|
using Projektanker.Icons.Avalonia.FontAwesome;
|
||||||
using Projektanker.Icons.Avalonia.MaterialDesign;
|
using Projektanker.Icons.Avalonia.MaterialDesign;
|
||||||
|
using Ryujinx.Ava.Systems;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
|
using Ryujinx.Ava.Systems.Configuration.System;
|
||||||
using Ryujinx.Ava.Utilities.SystemInfo;
|
using Ryujinx.Ava.Utilities.SystemInfo;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
@@ -32,8 +34,10 @@ namespace Ryujinx.Ava
|
|||||||
public static double DesktopScaleFactor { get; set; } = 1.0;
|
public static double DesktopScaleFactor { get; set; } = 1.0;
|
||||||
public static string Version { get; private set; }
|
public static string Version { get; private set; }
|
||||||
public static string ConfigurationPath { get; private set; }
|
public static string ConfigurationPath { get; private set; }
|
||||||
|
public static string GlobalConfigurationPath { get; private set; }
|
||||||
public static bool PreviewerDetached { get; private set; }
|
public static bool PreviewerDetached { get; private set; }
|
||||||
public static bool UseHardwareAcceleration { get; private set; }
|
public static bool UseHardwareAcceleration { get; private set; }
|
||||||
|
public static string BackendThreadingArg { get; private set; }
|
||||||
|
|
||||||
[LibraryImport("user32.dll", SetLastError = true)]
|
[LibraryImport("user32.dll", SetLastError = true)]
|
||||||
public static partial int MessageBoxA(nint hWnd, [MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string caption, uint type);
|
public static partial int MessageBoxA(nint hWnd, [MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string caption, uint type);
|
||||||
@@ -156,11 +160,38 @@ namespace Ryujinx.Ava
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetDirGameUserConfig(string gameId, bool rememberGlobalDir = false, bool changeFolderForGame = false)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(gameId))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string gameDir = Path.Combine(AppDataManager.GamesDirPath, gameId, ReleaseInformation.ConfigName);
|
||||||
|
|
||||||
|
// Should load with the game if there is a custom setting for the game
|
||||||
|
if (rememberGlobalDir)
|
||||||
|
{
|
||||||
|
GlobalConfigurationPath = ConfigurationPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeFolderForGame)
|
||||||
|
{
|
||||||
|
ConfigurationPath = gameDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gameDir;
|
||||||
|
}
|
||||||
|
|
||||||
public static void ReloadConfig()
|
public static void ReloadConfig()
|
||||||
{
|
{
|
||||||
|
//It is necessary that when a user setting appears, the global setting remains available
|
||||||
|
GlobalConfigurationPath = null;
|
||||||
|
|
||||||
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
||||||
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
||||||
|
|
||||||
|
|
||||||
// Now load the configuration as the other subsystems are now registered
|
// Now load the configuration as the other subsystems are now registered
|
||||||
if (File.Exists(localConfigurationPath))
|
if (File.Exists(localConfigurationPath))
|
||||||
{
|
{
|
||||||
@@ -217,6 +248,11 @@ namespace Ryujinx.Ava
|
|||||||
_ => ConfigurationState.Instance.Graphics.BackendThreading
|
_ => ConfigurationState.Instance.Graphics.BackendThreading
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (CommandLineState.OverrideBackendThreadingAfterReboot is not null)
|
||||||
|
{
|
||||||
|
BackendThreadingArg = CommandLineState.OverrideBackendThreadingAfterReboot;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if docked mode was overriden.
|
// Check if docked mode was overriden.
|
||||||
if (CommandLineState.OverrideDockedMode.HasValue)
|
if (CommandLineState.OverrideDockedMode.HasValue)
|
||||||
ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value;
|
ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value;
|
||||||
@@ -232,6 +268,33 @@ namespace Ryujinx.Ava
|
|||||||
_ => ConfigurationState.Instance.HideCursor,
|
_ => ConfigurationState.Instance.HideCursor,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if memoryManagerMode was overridden.
|
||||||
|
if (CommandLineState.OverrideMemoryManagerMode is not null)
|
||||||
|
if (Enum.TryParse(CommandLineState.OverrideMemoryManagerMode, true, out MemoryManagerMode result))
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.System.MemoryManagerMode.Value = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if PPTC was overridden.
|
||||||
|
if (CommandLineState.OverridePPTC is not null)
|
||||||
|
if (Enum.TryParse(CommandLineState.OverridePPTC, true, out bool result))
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.System.EnablePtc.Value = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if region was overridden.
|
||||||
|
if (CommandLineState.OverrideSystemRegion is not null)
|
||||||
|
if (Enum.TryParse(CommandLineState.OverrideSystemRegion, true, out HLE.HOS.SystemState.RegionCode result))
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.System.Region.Value = result.ToUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if language was overridden.
|
||||||
|
if (CommandLineState.OverrideSystemLanguage is not null)
|
||||||
|
if (Enum.TryParse(CommandLineState.OverrideSystemLanguage, true, out HLE.HOS.SystemState.SystemLanguage result))
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.System.Language.Value = result.ToUI();
|
||||||
|
}
|
||||||
|
|
||||||
// Check if hardware-acceleration was overridden.
|
// Check if hardware-acceleration was overridden.
|
||||||
if (CommandLineState.OverrideHardwareAcceleration != null)
|
if (CommandLineState.OverrideHardwareAcceleration != null)
|
||||||
|
|||||||
@@ -91,10 +91,12 @@
|
|||||||
<Content Include="..\..\distribution\legal\THIRDPARTY.md">
|
<Content Include="..\..\distribution\legal\THIRDPARTY.md">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
<TargetPath>THIRDPARTY.md</TargetPath>
|
<TargetPath>THIRDPARTY.md</TargetPath>
|
||||||
|
<Visible>False</Visible>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="..\..\LICENSE.txt">
|
<Content Include="..\..\LICENSE.txt">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
<TargetPath>LICENSE.txt</TargetPath>
|
<TargetPath>LICENSE.txt</TargetPath>
|
||||||
|
<Visible>False</Visible>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -112,6 +114,10 @@
|
|||||||
<AvaloniaResource Include="UI\**\*.xaml">
|
<AvaloniaResource Include="UI\**\*.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AvaloniaResource>
|
</AvaloniaResource>
|
||||||
|
<AvaloniaResource Include="Assets\Fonts\Mono\JetBrainsMonoNL-Bold.ttf" />
|
||||||
|
<AvaloniaResource Include="Assets\Fonts\Mono\JetBrainsMonoNL-BoldItalic.ttf" />
|
||||||
|
<AvaloniaResource Include="Assets\Fonts\Mono\JetBrainsMonoNL-Italic.ttf" />
|
||||||
|
<AvaloniaResource Include="Assets\Fonts\Mono\JetBrainsMonoNL-Regular.ttf" />
|
||||||
<AvaloniaResource Include="Assets\Fonts\SegoeFluentIcons.ttf" />
|
<AvaloniaResource Include="Assets\Fonts\SegoeFluentIcons.ttf" />
|
||||||
<AvaloniaResource Include="Assets\Styles\Themes.xaml">
|
<AvaloniaResource Include="Assets\Styles\Themes.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using Avalonia.Threading;
|
|||||||
using DiscordRPC;
|
using DiscordRPC;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Ns;
|
using LibHac.Ns;
|
||||||
using LibHac.Tools.FsSystem;
|
|
||||||
using Ryujinx.Audio.Backends.Dummy;
|
using Ryujinx.Audio.Backends.Dummy;
|
||||||
using Ryujinx.Audio.Backends.OpenAL;
|
using Ryujinx.Audio.Backends.OpenAL;
|
||||||
using Ryujinx.Audio.Backends.SDL2;
|
using Ryujinx.Audio.Backends.SDL2;
|
||||||
@@ -21,8 +20,8 @@ using Ryujinx.Ava.UI.Renderer;
|
|||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
using Ryujinx.Common.Configuration.Multiplayer;
|
||||||
@@ -35,11 +34,9 @@ using Ryujinx.Graphics.GAL.Multithreading;
|
|||||||
using Ryujinx.Graphics.Gpu;
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.Graphics.OpenGL;
|
using Ryujinx.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.Vulkan;
|
using Ryujinx.Graphics.Vulkan;
|
||||||
using Ryujinx.HLE;
|
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
@@ -62,7 +59,7 @@ using Size = Avalonia.Size;
|
|||||||
using Switch = Ryujinx.HLE.Switch;
|
using Switch = Ryujinx.HLE.Switch;
|
||||||
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
|
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
|
||||||
|
|
||||||
namespace Ryujinx.Ava
|
namespace Ryujinx.Ava.Systems
|
||||||
{
|
{
|
||||||
internal class AppHost
|
internal class AppHost
|
||||||
{
|
{
|
||||||
@@ -470,7 +467,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar);
|
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
|
||||||
});
|
});
|
||||||
|
|
||||||
_viewModel.SetUiProgressHandlers(Device);
|
_viewModel.SetUiProgressHandlers(Device);
|
||||||
@@ -872,7 +869,7 @@ namespace Ryujinx.Ava
|
|||||||
Device?.System.TogglePauseEmulation(false);
|
Device?.System.TogglePauseEmulation(false);
|
||||||
|
|
||||||
_viewModel.IsPaused = false;
|
_viewModel.IsPaused = false;
|
||||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar);
|
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
|
||||||
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
|
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -881,7 +878,7 @@ namespace Ryujinx.Ava
|
|||||||
Device?.System.TogglePauseEmulation(true);
|
Device?.System.TogglePauseEmulation(true);
|
||||||
|
|
||||||
_viewModel.IsPaused = true;
|
_viewModel.IsPaused = true;
|
||||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar, LocaleManager.Instance[LocaleKeys.Paused]);
|
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]);
|
||||||
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
|
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,53 +899,19 @@ namespace Ryujinx.Ava
|
|||||||
_ => new OpenGLRenderer()
|
_ => new OpenGLRenderer()
|
||||||
};
|
};
|
||||||
|
|
||||||
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
|
||||||
|
|
||||||
bool isGALThreaded = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
|
||||||
if (isGALThreaded)
|
|
||||||
{
|
|
||||||
renderer = new ThreadedRenderer(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {isGALThreaded}");
|
|
||||||
|
|
||||||
// Initialize Configuration.
|
// Initialize Configuration.
|
||||||
MemoryConfiguration memoryConfiguration = ConfigurationState.Instance.System.DramSize.Value;
|
Device = new Switch(ConfigurationState.Instance.CreateHleConfiguration()
|
||||||
|
.Configure(
|
||||||
Device = new Switch(new HLEConfiguration(
|
|
||||||
VirtualFileSystem,
|
VirtualFileSystem,
|
||||||
_viewModel.LibHacHorizonManager,
|
_viewModel.LibHacHorizonManager,
|
||||||
ContentManager,
|
ContentManager,
|
||||||
_accountManager,
|
_accountManager,
|
||||||
_userChannelPersistence,
|
_userChannelPersistence,
|
||||||
renderer,
|
renderer.TryMakeThreaded(ConfigurationState.Instance.Graphics.BackendThreading),
|
||||||
InitializeAudio(),
|
InitializeAudio(),
|
||||||
memoryConfiguration,
|
_viewModel.UiHandler
|
||||||
_viewModel.UiHandler,
|
)
|
||||||
(SystemLanguage)ConfigurationState.Instance.System.Language.Value,
|
);
|
||||||
(RegionCode)ConfigurationState.Instance.System.Region.Value,
|
|
||||||
ConfigurationState.Instance.Graphics.VSyncMode,
|
|
||||||
ConfigurationState.Instance.System.EnableDockedMode,
|
|
||||||
ConfigurationState.Instance.System.EnablePtc,
|
|
||||||
ConfigurationState.Instance.System.EnableInternetAccess,
|
|
||||||
ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
|
||||||
ConfigurationState.Instance.System.FsGlobalAccessLogMode,
|
|
||||||
ConfigurationState.Instance.System.MatchSystemTime
|
|
||||||
? 0
|
|
||||||
: ConfigurationState.Instance.System.SystemTimeOffset,
|
|
||||||
ConfigurationState.Instance.System.TimeZone,
|
|
||||||
ConfigurationState.Instance.System.MemoryManagerMode,
|
|
||||||
ConfigurationState.Instance.System.IgnoreMissingServices,
|
|
||||||
ConfigurationState.Instance.Graphics.AspectRatio,
|
|
||||||
ConfigurationState.Instance.System.AudioVolume,
|
|
||||||
ConfigurationState.Instance.System.UseHypervisor,
|
|
||||||
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value,
|
|
||||||
ConfigurationState.Instance.Multiplayer.Mode,
|
|
||||||
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
|
||||||
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
|
||||||
ConfigurationState.Instance.Multiplayer.GetLdnServer(),
|
|
||||||
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value,
|
|
||||||
ConfigurationState.Instance.Hacks.ShowDirtyHacks ? ConfigurationState.Instance.Hacks.EnabledHacks : null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IHardwareDeviceDriver InitializeAudio()
|
private static IHardwareDeviceDriver InitializeAudio()
|
||||||
@@ -1113,6 +1076,13 @@ namespace Ryujinx.Ava
|
|||||||
});
|
});
|
||||||
|
|
||||||
(RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true);
|
(RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true);
|
||||||
|
|
||||||
|
// Reload settings when the game is turned off
|
||||||
|
// (resets custom settings if there were any)
|
||||||
|
Program.ReloadConfig();
|
||||||
|
|
||||||
|
// Reload application list (changes the status of the user setting if it was added or removed during the game)
|
||||||
|
Dispatcher.UIThread.Post(() => RyujinxApp.MainWindow.LoadApplications());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitStatus()
|
public void InitStatus()
|
||||||
@@ -1175,6 +1145,9 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
private void UpdateShaderCount()
|
private void UpdateShaderCount()
|
||||||
{
|
{
|
||||||
|
if (_displayCount is 0 && _renderer.ProgramCount is 0)
|
||||||
|
return;
|
||||||
|
|
||||||
// If there is a mismatch between total program compile and previous count
|
// If there is a mismatch between total program compile and previous count
|
||||||
// this means new shaders have been compiled and should be displayed.
|
// this means new shaders have been compiled and should be displayed.
|
||||||
if (_renderer.ProgramCount != _previousCount)
|
if (_renderer.ProgramCount != _previousCount)
|
||||||
@@ -1248,12 +1221,10 @@ namespace Ryujinx.Ava
|
|||||||
VSyncModeToggle();
|
VSyncModeToggle();
|
||||||
break;
|
break;
|
||||||
case KeyboardHotkeyState.CustomVSyncIntervalDecrement:
|
case KeyboardHotkeyState.CustomVSyncIntervalDecrement:
|
||||||
Device.DecrementCustomVSyncInterval();
|
_viewModel.CustomVSyncInterval = Device.DecrementCustomVSyncInterval();
|
||||||
_viewModel.CustomVSyncInterval -= 1;
|
|
||||||
break;
|
break;
|
||||||
case KeyboardHotkeyState.CustomVSyncIntervalIncrement:
|
case KeyboardHotkeyState.CustomVSyncIntervalIncrement:
|
||||||
Device.IncrementCustomVSyncInterval();
|
_viewModel.CustomVSyncInterval = Device.IncrementCustomVSyncInterval();
|
||||||
_viewModel.CustomVSyncInterval += 1;
|
|
||||||
break;
|
break;
|
||||||
case KeyboardHotkeyState.Screenshot:
|
case KeyboardHotkeyState.Screenshot:
|
||||||
ScreenshotRequested = true;
|
ScreenshotRequested = true;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.AppLibrary
|
namespace Ryujinx.Ava.Systems.AppLibrary
|
||||||
{
|
{
|
||||||
public class ApplicationCountUpdatedEventArgs : EventArgs
|
public class ApplicationCountUpdatedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
@@ -9,8 +9,8 @@ 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.Utilities.Compat;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Utilities.PlayReport;
|
using Ryujinx.Ava.Systems.PlayReport;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.Loaders.Processes.Extensions;
|
using Ryujinx.HLE.Loaders.Processes.Extensions;
|
||||||
@@ -18,11 +18,12 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.AppLibrary
|
namespace Ryujinx.Ava.Systems.AppLibrary
|
||||||
{
|
{
|
||||||
public class ApplicationData
|
public class ApplicationData
|
||||||
{
|
{
|
||||||
public bool Favorite { get; set; }
|
public bool Favorite { get; set; }
|
||||||
|
public bool HasIndependentConfiguration { get; set; }
|
||||||
public byte[] Icon { get; set; }
|
public byte[] Icon { get; set; }
|
||||||
public string Name { get; set; } = "Unknown";
|
public string Name { get; set; } = "Unknown";
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
{
|
{
|
||||||
_id = value;
|
_id = value;
|
||||||
|
|
||||||
Compatibility = CompatibilityCsv.Find(value);
|
Compatibility = CompatibilityDatabase.Find(value);
|
||||||
RichPresenceSpec = PlayReports.Analyzer.TryGetSpec(IdString, out GameSpec gameSpec)
|
RichPresenceSpec = PlayReports.Analyzer.TryGetSpec(IdString, out GameSpec gameSpec)
|
||||||
? gameSpec
|
? gameSpec
|
||||||
: default(Optional<GameSpec>);
|
: default(Optional<GameSpec>);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.AppLibrary
|
namespace Ryujinx.Ava.Systems.AppLibrary
|
||||||
{
|
{
|
||||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
[JsonSerializable(typeof(ApplicationMetadata))]
|
[JsonSerializable(typeof(ApplicationMetadata))]
|
||||||
@@ -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.Models;
|
using Ryujinx.Ava.Common.Models;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
|
using Ryujinx.Ava.Systems.Configuration.System;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
using Ryujinx.Common.Configuration.Multiplayer;
|
||||||
@@ -38,7 +39,7 @@ using MissingKeyException = LibHac.Common.Keys.MissingKeyException;
|
|||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
using TimeSpan = System.TimeSpan;
|
using TimeSpan = System.TimeSpan;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.AppLibrary
|
namespace Ryujinx.Ava.Systems.AppLibrary
|
||||||
{
|
{
|
||||||
public class ApplicationLibrary
|
public class ApplicationLibrary
|
||||||
{
|
{
|
||||||
@@ -532,6 +533,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
data.Favorite = appMetadata.Favorite;
|
data.Favorite = appMetadata.Favorite;
|
||||||
data.TimePlayed = appMetadata.TimePlayed;
|
data.TimePlayed = appMetadata.TimePlayed;
|
||||||
data.LastPlayed = appMetadata.LastPlayed;
|
data.LastPlayed = appMetadata.LastPlayed;
|
||||||
|
data.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(data.IdBaseString, false, false)); // Just check user config
|
||||||
}
|
}
|
||||||
|
|
||||||
data.FileExtension = Path.GetExtension(applicationPath).TrimStart('.').ToUpper();
|
data.FileExtension = Path.GetExtension(applicationPath).TrimStart('.').ToUpper();
|
||||||
@@ -616,15 +618,11 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
case ".xci":
|
case ".xci":
|
||||||
case ".nsp":
|
case ".nsp":
|
||||||
{
|
{
|
||||||
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
|
|
||||||
? IntegrityCheckLevel.ErrorOnInvalid
|
|
||||||
: IntegrityCheckLevel.None;
|
|
||||||
|
|
||||||
using IFileSystem pfs =
|
using IFileSystem pfs =
|
||||||
PartitionFileSystemUtils.OpenApplicationFileSystem(filePath, _virtualFileSystem);
|
PartitionFileSystemUtils.OpenApplicationFileSystem(filePath, _virtualFileSystem);
|
||||||
|
|
||||||
Dictionary<ulong, ContentMetaData> updates =
|
Dictionary<ulong, ContentMetaData> updates =
|
||||||
pfs.GetContentData(ContentMetaType.Patch, _virtualFileSystem, checkLevel);
|
pfs.GetContentData(ContentMetaType.Patch, _virtualFileSystem, ConfigurationState.Instance.System.IntegrityCheckLevel);
|
||||||
|
|
||||||
if (updates.Count == 0)
|
if (updates.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.AppLibrary
|
namespace Ryujinx.Ava.Systems.AppLibrary
|
||||||
{
|
{
|
||||||
public class ApplicationMetadata
|
public class ApplicationMetadata
|
||||||
{
|
{
|
||||||
@@ -4,7 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.AppLibrary
|
namespace Ryujinx.Ava.Systems.AppLibrary
|
||||||
{
|
{
|
||||||
public struct LdnGameData
|
public struct LdnGameData
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.AppLibrary
|
namespace Ryujinx.Ava.Systems.AppLibrary
|
||||||
{
|
{
|
||||||
public class LdnGameDataReceivedEventArgs : EventArgs
|
public class LdnGameDataReceivedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.AppLibrary
|
namespace Ryujinx.Ava.Systems.AppLibrary
|
||||||
{
|
{
|
||||||
[JsonSerializable(typeof(IEnumerable<LdnGameData>))]
|
[JsonSerializable(typeof(IEnumerable<LdnGameData>))]
|
||||||
internal partial class LdnGameDataSerializerContext : JsonSerializerContext;
|
internal partial class LdnGameDataSerializerContext : JsonSerializerContext;
|
||||||
@@ -9,26 +9,11 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Compat
|
namespace Ryujinx.Ava.Systems
|
||||||
{
|
{
|
||||||
public struct ColumnIndices(Func<ReadOnlySpan<char>, int> getIndex)
|
public class CompatibilityDatabase
|
||||||
{
|
{
|
||||||
public const string TitleIdCol = "\"title_id\"";
|
static CompatibilityDatabase() => Load();
|
||||||
public const string GameNameCol = "\"game_name\"";
|
|
||||||
public const string LabelsCol = "\"labels\"";
|
|
||||||
public const string StatusCol = "\"status\"";
|
|
||||||
public const string LastUpdatedCol = "\"last_updated\"";
|
|
||||||
|
|
||||||
public readonly int TitleId = getIndex(TitleIdCol);
|
|
||||||
public readonly int GameName = getIndex(GameNameCol);
|
|
||||||
public readonly int Labels = getIndex(LabelsCol);
|
|
||||||
public readonly int Status = getIndex(StatusCol);
|
|
||||||
public readonly int LastUpdated = getIndex(LastUpdatedCol);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CompatibilityCsv
|
|
||||||
{
|
|
||||||
static CompatibilityCsv() => Load();
|
|
||||||
|
|
||||||
public static void Load()
|
public static void Load()
|
||||||
{
|
{
|
||||||
@@ -65,16 +50,6 @@ namespace Ryujinx.Ava.Utilities.Compat
|
|||||||
|
|
||||||
public static CompatibilityEntry Find(ulong titleId)
|
public static CompatibilityEntry Find(ulong titleId)
|
||||||
=> Find(titleId.ToString("X16"));
|
=> Find(titleId.ToString("X16"));
|
||||||
|
|
||||||
public static LocaleKeys? GetStatus(string titleId)
|
|
||||||
=> Find(titleId)?.Status;
|
|
||||||
|
|
||||||
public static LocaleKeys? GetStatus(ulong titleId) => GetStatus(titleId.ToString("X16"));
|
|
||||||
|
|
||||||
public static string GetLabels(string titleId)
|
|
||||||
=> Find(titleId)?.FormattedIssueLabels;
|
|
||||||
|
|
||||||
public static string GetLabels(ulong titleId) => GetLabels(titleId.ToString("X16"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CompatibilityEntry
|
public class CompatibilityEntry
|
||||||
@@ -135,6 +110,7 @@ namespace Ryujinx.Ava.Utilities.Compat
|
|||||||
|
|
||||||
public string FormattedIssueLabels => Labels
|
public string FormattedIssueLabels => Labels
|
||||||
.Select(FormatLabelName)
|
.Select(FormatLabelName)
|
||||||
|
.Where(x => x != null)
|
||||||
.JoinToString(", ");
|
.JoinToString(", ");
|
||||||
|
|
||||||
public override string ToString() =>
|
public override string ToString() =>
|
||||||
@@ -158,7 +134,6 @@ namespace Ryujinx.Ava.Utilities.Compat
|
|||||||
"gui" => "GUI",
|
"gui" => "GUI",
|
||||||
"help wanted" => "Help Wanted",
|
"help wanted" => "Help Wanted",
|
||||||
"horizon" => "Horizon",
|
"horizon" => "Horizon",
|
||||||
"infra" => "Project Infra",
|
|
||||||
"invalid" => "Invalid",
|
"invalid" => "Invalid",
|
||||||
"kernel" => "Kernel",
|
"kernel" => "Kernel",
|
||||||
"ldn" => "LDN",
|
"ldn" => "LDN",
|
||||||
@@ -172,9 +147,9 @@ namespace Ryujinx.Ava.Utilities.Compat
|
|||||||
"ldn-untested" => "LDN Untested",
|
"ldn-untested" => "LDN Untested",
|
||||||
"ldn-broken" => "LDN Broken",
|
"ldn-broken" => "LDN Broken",
|
||||||
"ldn-partial" => "Partial LDN",
|
"ldn-partial" => "Partial LDN",
|
||||||
"nvdec" => "NVDEC",
|
"nvdec" => "GPU Video Decoding",
|
||||||
"services" => "NX Services",
|
"services" => "HLE Services",
|
||||||
"services-horizon" => "Horizon OS Services",
|
"services-horizon" => "New HLE Services",
|
||||||
"slow" => "Runs Slow",
|
"slow" => "Runs Slow",
|
||||||
"crash" => "Crashes",
|
"crash" => "Crashes",
|
||||||
"deadlock" => "Deadlock",
|
"deadlock" => "Deadlock",
|
||||||
@@ -182,7 +157,7 @@ namespace Ryujinx.Ava.Utilities.Compat
|
|||||||
"opengl" => "OpenGL",
|
"opengl" => "OpenGL",
|
||||||
"opengl-backend-bug" => "OpenGL Backend Bug",
|
"opengl-backend-bug" => "OpenGL Backend Bug",
|
||||||
"vulkan-backend-bug" => "Vulkan Backend Bug",
|
"vulkan-backend-bug" => "Vulkan Backend Bug",
|
||||||
"mac-bug" => "Mac-specific Bug(s)",
|
"mac-bug" => "Mac-specific Problems",
|
||||||
"amd-vendor-bug" => "AMD GPU Bug",
|
"amd-vendor-bug" => "AMD GPU Bug",
|
||||||
"intel-vendor-bug" => "Intel GPU Bug",
|
"intel-vendor-bug" => "Intel GPU Bug",
|
||||||
"loader-allocator" => "Loader Allocator",
|
"loader-allocator" => "Loader Allocator",
|
||||||
@@ -191,18 +166,22 @@ namespace Ryujinx.Ava.Utilities.Compat
|
|||||||
"UE4" => "Unreal Engine 4",
|
"UE4" => "Unreal Engine 4",
|
||||||
"homebrew" => "Homebrew Content",
|
"homebrew" => "Homebrew Content",
|
||||||
"online-broken" => "Online Broken",
|
"online-broken" => "Online Broken",
|
||||||
_ => Capitalize(labelName)
|
_ => null
|
||||||
};
|
};
|
||||||
|
|
||||||
public static string Capitalize(string value)
|
|
||||||
{
|
|
||||||
if (value == string.Empty)
|
|
||||||
return string.Empty;
|
|
||||||
|
|
||||||
char firstChar = value[0];
|
|
||||||
string rest = value[1..];
|
|
||||||
|
|
||||||
return $"{char.ToUpper(firstChar)}{rest}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct ColumnIndices(Func<ReadOnlySpan<char>, int> getIndex)
|
||||||
|
{
|
||||||
|
private const string TitleIdCol = "\"title_id\"";
|
||||||
|
private const string GameNameCol = "\"game_name\"";
|
||||||
|
private const string LabelsCol = "\"labels\"";
|
||||||
|
private const string StatusCol = "\"status\"";
|
||||||
|
private const string LastUpdatedCol = "\"last_updated\"";
|
||||||
|
|
||||||
|
public readonly int TitleId = getIndex(TitleIdCol);
|
||||||
|
public readonly int GameName = getIndex(GameNameCol);
|
||||||
|
public readonly int Labels = getIndex(LabelsCol);
|
||||||
|
public readonly int Status = getIndex(StatusCol);
|
||||||
|
public readonly int LastUpdated = getIndex(LastUpdatedCol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration
|
namespace Ryujinx.Ava.Systems.Configuration
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<AudioBackend>))]
|
[JsonConverter(typeof(TypedStringEnumConverter<AudioBackend>))]
|
||||||
public enum AudioBackend
|
public enum AudioBackend
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
using Ryujinx.Ava.Systems.Configuration.System;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
using Ryujinx.Ava.Systems.Configuration.UI;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
using Ryujinx.Common.Configuration.Multiplayer;
|
||||||
@@ -8,14 +8,14 @@ using Ryujinx.Common.Utilities;
|
|||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration
|
namespace Ryujinx.Ava.Systems.Configuration
|
||||||
{
|
{
|
||||||
public class ConfigurationFileFormat
|
public class ConfigurationFileFormat
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current version of the file format
|
/// The current version of the file format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int CurrentVersion = 67;
|
public const int CurrentVersion = 68;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version of the configuration file format
|
/// Version of the configuration file format
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration
|
namespace Ryujinx.Ava.Systems.Configuration
|
||||||
{
|
{
|
||||||
internal static class ConfigurationFileFormatSettings
|
internal static class ConfigurationFileFormatSettings
|
||||||
{
|
{
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration
|
namespace Ryujinx.Ava.Systems.Configuration
|
||||||
{
|
{
|
||||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
[JsonSerializable(typeof(ConfigurationFileFormat))]
|
[JsonSerializable(typeof(ConfigurationFileFormat))]
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
using Ryujinx.Ava.Systems.Configuration.System;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
using Ryujinx.Ava.Systems.Configuration.UI;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
@@ -14,13 +14,14 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using RyuLogger = Ryujinx.Common.Logging.Logger;
|
using RyuLogger = Ryujinx.Common.Logging.Logger;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration
|
namespace Ryujinx.Ava.Systems.Configuration
|
||||||
{
|
{
|
||||||
public partial class ConfigurationState
|
public partial class ConfigurationState
|
||||||
{
|
{
|
||||||
public void Load(ConfigurationFileFormat cff, string configurationFilePath)
|
public void Load(ConfigurationFileFormat cff, string configurationFilePath, string titleId = "")
|
||||||
{
|
{
|
||||||
bool configurationFileUpdated = false;
|
bool configurationFileUpdated = false;
|
||||||
|
bool shouldLoadFromFile = string.IsNullOrEmpty(titleId);
|
||||||
|
|
||||||
if (cff.Version is < 0 or > ConfigurationFileFormat.CurrentVersion)
|
if (cff.Version is < 0 or > ConfigurationFileFormat.CurrentVersion)
|
||||||
{
|
{
|
||||||
@@ -43,14 +44,14 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
configurationFileUpdated = true;
|
configurationFileUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
|
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
|
||||||
CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart;
|
UpdateCheckerType.Value = shouldLoadFromFile ? cff.UpdateCheckerType : UpdateCheckerType.Value; // Get from global config only
|
||||||
UpdateCheckerType.Value = cff.UpdateCheckerType;
|
|
||||||
FocusLostActionType.Value = cff.FocusLostActionType;
|
FocusLostActionType.Value = cff.FocusLostActionType;
|
||||||
ShowConfirmExit.Value = cff.ShowConfirmExit;
|
ShowConfirmExit.Value = shouldLoadFromFile ? cff.ShowConfirmExit : ShowConfirmExit.Value; // Get from global config only
|
||||||
RememberWindowState.Value = cff.RememberWindowState;
|
RememberWindowState.Value = shouldLoadFromFile ? cff.RememberWindowState : RememberWindowState.Value; // Get from global config only
|
||||||
ShowTitleBar.Value = cff.ShowTitleBar;
|
ShowOldUI.Value = shouldLoadFromFile ? cff.ShowTitleBar : ShowOldUI.Value; // Get from global config only
|
||||||
EnableHardwareAcceleration.Value = cff.EnableHardwareAcceleration;
|
EnableHardwareAcceleration.Value = shouldLoadFromFile ? cff.EnableHardwareAcceleration : EnableHardwareAcceleration.Value; // Get from global config only
|
||||||
HideCursor.Value = cff.HideCursor;
|
HideCursor.Value = cff.HideCursor;
|
||||||
|
|
||||||
Logger.EnableFileLog.Value = cff.EnableFileLog;
|
Logger.EnableFileLog.Value = cff.EnableFileLog;
|
||||||
@@ -87,8 +88,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
System.Language.Value = cff.SystemLanguage;
|
System.Language.Value = cff.SystemLanguage;
|
||||||
System.Region.Value = cff.SystemRegion;
|
System.Region.Value = cff.SystemRegion;
|
||||||
System.TimeZone.Value = cff.SystemTimeZone;
|
System.TimeZone.Value = cff.SystemTimeZone;
|
||||||
System.SystemTimeOffset.Value = cff.SystemTimeOffset;
|
System.SystemTimeOffset.Value = shouldLoadFromFile ? cff.SystemTimeOffset : System.SystemTimeOffset.Value; // Get from global config only
|
||||||
System.MatchSystemTime.Value = cff.MatchSystemTime;
|
System.MatchSystemTime.Value = shouldLoadFromFile ? cff.MatchSystemTime : System.MatchSystemTime.Value; // Get from global config only
|
||||||
System.EnableDockedMode.Value = cff.DockedMode;
|
System.EnableDockedMode.Value = cff.DockedMode;
|
||||||
System.EnablePtc.Value = cff.EnablePtc;
|
System.EnablePtc.Value = cff.EnablePtc;
|
||||||
System.EnableLowPowerPtc.Value = cff.EnableLowPowerPtc;
|
System.EnableLowPowerPtc.Value = cff.EnableLowPowerPtc;
|
||||||
@@ -103,46 +104,47 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
System.IgnoreControllerApplet.Value = cff.IgnoreApplet;
|
System.IgnoreControllerApplet.Value = cff.IgnoreApplet;
|
||||||
System.UseHypervisor.Value = cff.UseHypervisor;
|
System.UseHypervisor.Value = cff.UseHypervisor;
|
||||||
|
|
||||||
UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn;
|
UI.GuiColumns.FavColumn.Value = shouldLoadFromFile ? cff.GuiColumns.FavColumn : UI.GuiColumns.FavColumn.Value;
|
||||||
UI.GuiColumns.IconColumn.Value = cff.GuiColumns.IconColumn;
|
UI.GuiColumns.IconColumn.Value = shouldLoadFromFile ? cff.GuiColumns.IconColumn : UI.GuiColumns.IconColumn.Value;
|
||||||
UI.GuiColumns.AppColumn.Value = cff.GuiColumns.AppColumn;
|
UI.GuiColumns.AppColumn.Value = shouldLoadFromFile ? cff.GuiColumns.AppColumn : UI.GuiColumns.AppColumn.Value;
|
||||||
UI.GuiColumns.DevColumn.Value = cff.GuiColumns.DevColumn;
|
UI.GuiColumns.DevColumn.Value = shouldLoadFromFile ? cff.GuiColumns.DevColumn : UI.GuiColumns.DevColumn.Value;
|
||||||
UI.GuiColumns.VersionColumn.Value = cff.GuiColumns.VersionColumn;
|
UI.GuiColumns.VersionColumn.Value = shouldLoadFromFile ? cff.GuiColumns.VersionColumn : UI.GuiColumns.VersionColumn.Value;
|
||||||
UI.GuiColumns.TimePlayedColumn.Value = cff.GuiColumns.TimePlayedColumn;
|
UI.GuiColumns.TimePlayedColumn.Value = shouldLoadFromFile ? cff.GuiColumns.TimePlayedColumn : UI.GuiColumns.TimePlayedColumn.Value;
|
||||||
UI.GuiColumns.LastPlayedColumn.Value = cff.GuiColumns.LastPlayedColumn;
|
UI.GuiColumns.LastPlayedColumn.Value = shouldLoadFromFile ? cff.GuiColumns.LastPlayedColumn : UI.GuiColumns.LastPlayedColumn.Value;
|
||||||
UI.GuiColumns.FileExtColumn.Value = cff.GuiColumns.FileExtColumn;
|
UI.GuiColumns.FileExtColumn.Value = shouldLoadFromFile ? cff.GuiColumns.FileExtColumn : UI.GuiColumns.FileExtColumn.Value;
|
||||||
UI.GuiColumns.FileSizeColumn.Value = cff.GuiColumns.FileSizeColumn;
|
UI.GuiColumns.FileSizeColumn.Value = shouldLoadFromFile ? cff.GuiColumns.FileSizeColumn : UI.GuiColumns.FileSizeColumn.Value;
|
||||||
UI.GuiColumns.PathColumn.Value = cff.GuiColumns.PathColumn;
|
UI.GuiColumns.PathColumn.Value = shouldLoadFromFile ? cff.GuiColumns.PathColumn : UI.GuiColumns.PathColumn.Value;
|
||||||
UI.ColumnSort.SortColumnId.Value = cff.ColumnSort.SortColumnId;
|
UI.ColumnSort.SortColumnId.Value = shouldLoadFromFile ? cff.ColumnSort.SortColumnId : UI.ColumnSort.SortColumnId.Value;
|
||||||
UI.ColumnSort.SortAscending.Value = cff.ColumnSort.SortAscending;
|
UI.ColumnSort.SortAscending.Value = shouldLoadFromFile ? cff.ColumnSort.SortAscending : UI.ColumnSort.SortAscending.Value;
|
||||||
UI.GameDirs.Value = cff.GameDirs;
|
UI.GameDirs.Value = shouldLoadFromFile ? cff.GameDirs : UI.GameDirs.Value;
|
||||||
UI.AutoloadDirs.Value = cff.AutoloadDirs ?? [];
|
UI.AutoloadDirs.Value = shouldLoadFromFile ? (cff.AutoloadDirs ?? []) : UI.AutoloadDirs.Value;
|
||||||
UI.ShownFileTypes.NSP.Value = cff.ShownFileTypes.NSP;
|
UI.ShownFileTypes.NSP.Value = shouldLoadFromFile ? cff.ShownFileTypes.NSP : UI.ShownFileTypes.NSP.Value;
|
||||||
UI.ShownFileTypes.PFS0.Value = cff.ShownFileTypes.PFS0;
|
UI.ShownFileTypes.PFS0.Value = shouldLoadFromFile ? cff.ShownFileTypes.PFS0 : UI.ShownFileTypes.PFS0.Value;
|
||||||
UI.ShownFileTypes.XCI.Value = cff.ShownFileTypes.XCI;
|
UI.ShownFileTypes.XCI.Value = shouldLoadFromFile ? cff.ShownFileTypes.XCI : UI.ShownFileTypes.XCI.Value;
|
||||||
UI.ShownFileTypes.NCA.Value = cff.ShownFileTypes.NCA;
|
UI.ShownFileTypes.NCA.Value = shouldLoadFromFile ? cff.ShownFileTypes.NCA : UI.ShownFileTypes.NCA.Value;
|
||||||
UI.ShownFileTypes.NRO.Value = cff.ShownFileTypes.NRO;
|
UI.ShownFileTypes.NRO.Value = shouldLoadFromFile ? cff.ShownFileTypes.NRO : UI.ShownFileTypes.NRO.Value;
|
||||||
UI.ShownFileTypes.NSO.Value = cff.ShownFileTypes.NSO;
|
UI.ShownFileTypes.NSO.Value = shouldLoadFromFile ? cff.ShownFileTypes.NSO : UI.ShownFileTypes.NSO.Value;
|
||||||
UI.LanguageCode.Value = cff.LanguageCode;
|
UI.LanguageCode.Value = shouldLoadFromFile ? cff.LanguageCode : UI.LanguageCode.Value;
|
||||||
UI.BaseStyle.Value = cff.BaseStyle;
|
UI.BaseStyle.Value = shouldLoadFromFile ? cff.BaseStyle : UI.BaseStyle.Value;
|
||||||
UI.GameListViewMode.Value = cff.GameListViewMode;
|
UI.GameListViewMode.Value = shouldLoadFromFile ? cff.GameListViewMode : UI.GameListViewMode.Value;
|
||||||
UI.ShowNames.Value = cff.ShowNames;
|
UI.ShowNames.Value = shouldLoadFromFile ? cff.ShowNames : UI.ShowNames.Value;
|
||||||
UI.IsAscendingOrder.Value = cff.IsAscendingOrder;
|
UI.IsAscendingOrder.Value = shouldLoadFromFile ? cff.IsAscendingOrder : UI.IsAscendingOrder.Value;
|
||||||
UI.GridSize.Value = cff.GridSize;
|
UI.GridSize.Value = shouldLoadFromFile ? cff.GridSize : UI.GridSize.Value;
|
||||||
UI.ApplicationSort.Value = cff.ApplicationSort;
|
UI.ApplicationSort.Value = shouldLoadFromFile ? cff.ApplicationSort : UI.ApplicationSort.Value;
|
||||||
UI.StartFullscreen.Value = cff.StartFullscreen;
|
UI.StartFullscreen.Value = shouldLoadFromFile ? cff.StartFullscreen : UI.StartFullscreen.Value;
|
||||||
UI.StartNoUI.Value = cff.StartNoUI;
|
UI.StartNoUI.Value = shouldLoadFromFile ? cff.StartNoUI : UI.StartNoUI.Value;
|
||||||
UI.ShowConsole.Value = cff.ShowConsole;
|
UI.ShowConsole.Value = shouldLoadFromFile ? cff.ShowConsole : UI.ShowConsole.Value;
|
||||||
UI.WindowStartup.WindowSizeWidth.Value = cff.WindowStartup.WindowSizeWidth;
|
UI.WindowStartup.WindowSizeWidth.Value = shouldLoadFromFile ? cff.WindowStartup.WindowSizeWidth : UI.WindowStartup.WindowSizeWidth.Value;
|
||||||
UI.WindowStartup.WindowSizeHeight.Value = cff.WindowStartup.WindowSizeHeight;
|
UI.WindowStartup.WindowSizeHeight.Value = shouldLoadFromFile ? cff.WindowStartup.WindowSizeHeight : UI.WindowStartup.WindowSizeHeight.Value;
|
||||||
UI.WindowStartup.WindowPositionX.Value = cff.WindowStartup.WindowPositionX;
|
UI.WindowStartup.WindowPositionX.Value = shouldLoadFromFile ? cff.WindowStartup.WindowPositionX : UI.WindowStartup.WindowPositionX.Value;
|
||||||
UI.WindowStartup.WindowPositionY.Value = cff.WindowStartup.WindowPositionY;
|
UI.WindowStartup.WindowPositionY.Value = shouldLoadFromFile ? cff.WindowStartup.WindowPositionY : UI.WindowStartup.WindowPositionY.Value;
|
||||||
UI.WindowStartup.WindowMaximized.Value = cff.WindowStartup.WindowMaximized;
|
UI.WindowStartup.WindowMaximized.Value = shouldLoadFromFile ? cff.WindowStartup.WindowMaximized : UI.WindowStartup.WindowMaximized.Value;
|
||||||
|
|
||||||
|
|
||||||
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
||||||
Hid.EnableMouse.Value = cff.EnableMouse;
|
Hid.EnableMouse.Value = cff.EnableMouse;
|
||||||
Hid.DisableInputWhenOutOfFocus.Value = cff.DisableInputWhenOutOfFocus;
|
Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus: Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only
|
||||||
Hid.Hotkeys.Value = cff.Hotkeys;
|
Hid.Hotkeys.Value = shouldLoadFromFile ? cff.Hotkeys : Hid.Hotkeys.Value; // Get from global config only
|
||||||
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
||||||
Hid.RainbowSpeed.Value = cff.RainbowSpeed;
|
Hid.RainbowSpeed.Value = cff.RainbowSpeed;
|
||||||
|
|
||||||
@@ -439,6 +441,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
(65, static cff => cff.UpdateCheckerType = cff.CheckUpdatesOnStart ? UpdaterType.PromptAtStartup : UpdaterType.Off),
|
(65, static cff => cff.UpdateCheckerType = cff.CheckUpdatesOnStart ? UpdaterType.PromptAtStartup : UpdaterType.Off),
|
||||||
(66, static cff => cff.DisableInputWhenOutOfFocus = false),
|
(66, static cff => cff.DisableInputWhenOutOfFocus = false),
|
||||||
(67, static cff => cff.FocusLostActionType = cff.DisableInputWhenOutOfFocus ? FocusLostType.BlockInput : FocusLostType.DoNothing)
|
(67, static cff => cff.FocusLostActionType = cff.DisableInputWhenOutOfFocus ? FocusLostType.BlockInput : FocusLostType.DoNothing)
|
||||||
|
// 68 was the version that added per-game configs; the file structure did not change
|
||||||
|
// the version was increased so external tools could know that your Ryujinx version has per-game config capabilities.
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
using ARMeilleure;
|
using ARMeilleure;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using LibHac.Tools.FsSystem;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
using Ryujinx.Ava.Systems.Configuration.System;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
using Ryujinx.Ava.Systems.Configuration.UI;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
@@ -15,7 +15,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using RyuLogger = Ryujinx.Common.Logging.Logger;
|
using RyuLogger = Ryujinx.Common.Logging.Logger;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration
|
namespace Ryujinx.Ava.Systems.Configuration
|
||||||
{
|
{
|
||||||
public partial class ConfigurationState
|
public partial class ConfigurationState
|
||||||
{
|
{
|
||||||
@@ -351,6 +351,10 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> EnableFsIntegrityChecks { get; private set; }
|
public ReactiveObject<bool> EnableFsIntegrityChecks { get; private set; }
|
||||||
|
|
||||||
|
public IntegrityCheckLevel IntegrityCheckLevel => EnableFsIntegrityChecks
|
||||||
|
? IntegrityCheckLevel.ErrorOnInvalid
|
||||||
|
: IntegrityCheckLevel.None;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables FS access log output to the console. Possible modes are 0-3
|
/// Enables FS access log output to the console. Possible modes are 0-3
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -779,11 +783,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> EnableDiscordIntegration { get; private set; }
|
public ReactiveObject<bool> EnableDiscordIntegration { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks for updates when Ryujinx starts when enabled
|
|
||||||
/// </summary>
|
|
||||||
public ReactiveObject<bool> CheckUpdatesOnStart { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification.
|
/// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -805,9 +804,9 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
public ReactiveObject<bool> RememberWindowState { get; private set; }
|
public ReactiveObject<bool> RememberWindowState { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables or disables the redesigned title bar
|
/// Disable the new title bar layout & window layout changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> ShowTitleBar { get; private set; }
|
public ReactiveObject<bool> ShowOldUI { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables hardware-accelerated rendering for Avalonia
|
/// Enables hardware-accelerated rendering for Avalonia
|
||||||
@@ -828,15 +827,44 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
Hid = new HidSection();
|
Hid = new HidSection();
|
||||||
Multiplayer = new MultiplayerSection();
|
Multiplayer = new MultiplayerSection();
|
||||||
Hacks = new HacksSection();
|
Hacks = new HacksSection();
|
||||||
EnableDiscordIntegration = new ReactiveObject<bool>();
|
|
||||||
CheckUpdatesOnStart = new ReactiveObject<bool>();
|
|
||||||
UpdateCheckerType = new ReactiveObject<UpdaterType>();
|
UpdateCheckerType = new ReactiveObject<UpdaterType>();
|
||||||
FocusLostActionType = new ReactiveObject<FocusLostType>();
|
FocusLostActionType = new ReactiveObject<FocusLostType>();
|
||||||
|
HideCursor = new ReactiveObject<HideCursorMode>();
|
||||||
|
EnableDiscordIntegration = new ReactiveObject<bool>();
|
||||||
ShowConfirmExit = new ReactiveObject<bool>();
|
ShowConfirmExit = new ReactiveObject<bool>();
|
||||||
RememberWindowState = new ReactiveObject<bool>();
|
RememberWindowState = new ReactiveObject<bool>();
|
||||||
ShowTitleBar = new ReactiveObject<bool>();
|
ShowOldUI = new ReactiveObject<bool>();
|
||||||
EnableHardwareAcceleration = new ReactiveObject<bool>();
|
EnableHardwareAcceleration = new ReactiveObject<bool>();
|
||||||
HideCursor = new ReactiveObject<HideCursorMode>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HleConfiguration CreateHleConfiguration() =>
|
||||||
|
new(
|
||||||
|
System.DramSize,
|
||||||
|
System.Language.Value.ToHLE(),
|
||||||
|
System.Region.Value.ToHLE(),
|
||||||
|
Graphics.VSyncMode,
|
||||||
|
System.EnableDockedMode,
|
||||||
|
System.EnablePtc,
|
||||||
|
System.EnableInternetAccess,
|
||||||
|
System.EnableFsIntegrityChecks
|
||||||
|
? IntegrityCheckLevel.ErrorOnInvalid
|
||||||
|
: IntegrityCheckLevel.None,
|
||||||
|
System.FsGlobalAccessLogMode,
|
||||||
|
System.MatchSystemTime
|
||||||
|
? 0
|
||||||
|
: System.SystemTimeOffset,
|
||||||
|
System.TimeZone,
|
||||||
|
System.MemoryManagerMode,
|
||||||
|
System.IgnoreMissingServices,
|
||||||
|
Graphics.AspectRatio,
|
||||||
|
System.AudioVolume,
|
||||||
|
System.UseHypervisor,
|
||||||
|
Multiplayer.LanInterfaceId,
|
||||||
|
Multiplayer.Mode,
|
||||||
|
Multiplayer.DisableP2p,
|
||||||
|
Multiplayer.LdnPassphrase,
|
||||||
|
Instance.Multiplayer.GetLdnServer(),
|
||||||
|
Instance.Graphics.CustomVSyncInterval,
|
||||||
|
Instance.Hacks.ShowDirtyHacks ? Instance.Hacks.EnabledHacks : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
using Ryujinx.Ava.Systems.Configuration.System;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
using Ryujinx.Ava.Systems.Configuration.UI;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||||
@@ -9,7 +9,7 @@ using Ryujinx.HLE;
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration
|
namespace Ryujinx.Ava.Systems.Configuration
|
||||||
{
|
{
|
||||||
public partial class ConfigurationState
|
public partial class ConfigurationState
|
||||||
{
|
{
|
||||||
@@ -56,12 +56,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
MatchSystemTime = System.MatchSystemTime,
|
MatchSystemTime = System.MatchSystemTime,
|
||||||
DockedMode = System.EnableDockedMode,
|
DockedMode = System.EnableDockedMode,
|
||||||
EnableDiscordIntegration = EnableDiscordIntegration,
|
EnableDiscordIntegration = EnableDiscordIntegration,
|
||||||
CheckUpdatesOnStart = CheckUpdatesOnStart,
|
|
||||||
UpdateCheckerType = UpdateCheckerType,
|
UpdateCheckerType = UpdateCheckerType,
|
||||||
FocusLostActionType = FocusLostActionType,
|
FocusLostActionType = FocusLostActionType,
|
||||||
ShowConfirmExit = ShowConfirmExit,
|
ShowConfirmExit = ShowConfirmExit,
|
||||||
RememberWindowState = RememberWindowState,
|
RememberWindowState = RememberWindowState,
|
||||||
ShowTitleBar = ShowTitleBar,
|
ShowTitleBar = ShowOldUI,
|
||||||
EnableHardwareAcceleration = EnableHardwareAcceleration,
|
EnableHardwareAcceleration = EnableHardwareAcceleration,
|
||||||
HideCursor = HideCursor,
|
HideCursor = HideCursor,
|
||||||
VSyncMode = Graphics.VSyncMode,
|
VSyncMode = Graphics.VSyncMode,
|
||||||
@@ -183,7 +182,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
FocusLostActionType.Value = FocusLostType.DoNothing;
|
FocusLostActionType.Value = FocusLostType.DoNothing;
|
||||||
ShowConfirmExit.Value = true;
|
ShowConfirmExit.Value = true;
|
||||||
RememberWindowState.Value = true;
|
RememberWindowState.Value = true;
|
||||||
ShowTitleBar.Value = !OperatingSystem.IsWindows();
|
ShowOldUI.Value = !OperatingSystem.IsWindows();
|
||||||
EnableHardwareAcceleration.Value = true;
|
EnableHardwareAcceleration.Value = true;
|
||||||
HideCursor.Value = HideCursorMode.OnIdle;
|
HideCursor.Value = HideCursorMode.OnIdle;
|
||||||
Graphics.VSyncMode.Value = VSyncMode.Switch;
|
Graphics.VSyncMode.Value = VSyncMode.Switch;
|
||||||
@@ -328,4 +327,4 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
return GraphicsBackend.OpenGl;
|
return GraphicsBackend.OpenGl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
using static Ryujinx.Ava.Utilities.Configuration.ConfigurationState.UISection;
|
using static Ryujinx.Ava.Systems.Configuration.ConfigurationState.UISection;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration
|
namespace Ryujinx.Ava.Systems.Configuration
|
||||||
{
|
{
|
||||||
public enum FileTypes
|
public enum FileTypes
|
||||||
{
|
{
|
||||||
@@ -4,7 +4,7 @@ using Ryujinx.Common.Logging.Targets;
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration
|
namespace Ryujinx.Ava.Systems.Configuration
|
||||||
{
|
{
|
||||||
public static class LoggerModule
|
public static class LoggerModule
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration.System
|
namespace Ryujinx.Ava.Systems.Configuration.System
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<Language>))]
|
[JsonConverter(typeof(TypedStringEnumConverter<Language>))]
|
||||||
public enum Language
|
public enum Language
|
||||||
@@ -25,4 +25,13 @@ namespace Ryujinx.Ava.Utilities.Configuration.System
|
|||||||
TraditionalChinese,
|
TraditionalChinese,
|
||||||
BrazilianPortuguese,
|
BrazilianPortuguese,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class LanguageEnumHelper
|
||||||
|
{
|
||||||
|
public static Language ToUI(this HLE.HOS.SystemState.SystemLanguage hleLanguage)
|
||||||
|
=> (Language)hleLanguage;
|
||||||
|
|
||||||
|
public static HLE.HOS.SystemState.SystemLanguage ToHLE(this Language uiLanguage)
|
||||||
|
=> (HLE.HOS.SystemState.SystemLanguage)uiLanguage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
26
src/Ryujinx/Systems/Configuration/System/Region.cs
Normal file
26
src/Ryujinx/Systems/Configuration/System/Region.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Ryujinx.Common.Utilities;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.Systems.Configuration.System
|
||||||
|
{
|
||||||
|
[JsonConverter(typeof(TypedStringEnumConverter<Region>))]
|
||||||
|
public enum Region
|
||||||
|
{
|
||||||
|
Japan,
|
||||||
|
USA,
|
||||||
|
Europe,
|
||||||
|
Australia,
|
||||||
|
China,
|
||||||
|
Korea,
|
||||||
|
Taiwan,
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RegionEnumHelper
|
||||||
|
{
|
||||||
|
public static Region ToUI(this HLE.HOS.SystemState.RegionCode hleRegion)
|
||||||
|
=> (Region)hleRegion;
|
||||||
|
|
||||||
|
public static HLE.HOS.SystemState.RegionCode ToHLE(this Region uiRegion)
|
||||||
|
=> (HLE.HOS.SystemState.RegionCode)uiRegion;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ryujinx.Ava.Utilities.Configuration.UI
|
namespace Ryujinx.Ava.Systems.Configuration.UI
|
||||||
{
|
{
|
||||||
public struct ColumnSort
|
public struct ColumnSort
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration.UI
|
namespace Ryujinx.Ava.Systems.Configuration.UI
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<FocusLostType>))]
|
[JsonConverter(typeof(TypedStringEnumConverter<FocusLostType>))]
|
||||||
public enum FocusLostType
|
public enum FocusLostType
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ryujinx.Ava.Utilities.Configuration.UI
|
namespace Ryujinx.Ava.Systems.Configuration.UI
|
||||||
{
|
{
|
||||||
public struct GuiColumns
|
public struct GuiColumns
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ryujinx.Ava.Utilities.Configuration.UI
|
namespace Ryujinx.Ava.Systems.Configuration.UI
|
||||||
{
|
{
|
||||||
public struct ShownFileTypes
|
public struct ShownFileTypes
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Configuration.UI
|
namespace Ryujinx.Ava.Systems.Configuration.UI
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<UpdaterType>))]
|
[JsonConverter(typeof(TypedStringEnumConverter<UpdaterType>))]
|
||||||
public enum UpdaterType
|
public enum UpdaterType
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ryujinx.Ava.Utilities.Configuration.UI
|
namespace Ryujinx.Ava.Systems.Configuration.UI
|
||||||
{
|
{
|
||||||
public struct WindowStartup
|
public struct WindowStartup
|
||||||
{
|
{
|
||||||
@@ -1,18 +1,17 @@
|
|||||||
using DiscordRPC;
|
using DiscordRPC;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Ava.Utilities.PlayReport;
|
using Ryujinx.Ava.Systems.PlayReport;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
using Ryujinx.HLE.Loaders.Processes;
|
using Ryujinx.HLE.Loaders.Processes;
|
||||||
using Ryujinx.Horizon;
|
using Ryujinx.Horizon;
|
||||||
using Ryujinx.Horizon.Prepo.Types;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.Ava
|
namespace Ryujinx.Ava.Systems
|
||||||
{
|
{
|
||||||
public static class DiscordIntegrationModule
|
public static class DiscordIntegrationModule
|
||||||
{
|
{
|
||||||
@@ -124,7 +123,7 @@ namespace Ryujinx.Ava
|
|||||||
_currentApp = null;
|
_currentApp = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HandlePlayReport(PlayReport playReport)
|
private static void HandlePlayReport(Horizon.Prepo.Types.PlayReport playReport)
|
||||||
{
|
{
|
||||||
if (_discordClient is null) return;
|
if (_discordClient is null) return;
|
||||||
if (!TitleIDs.CurrentApplication.Value.HasValue) return;
|
if (!TitleIDs.CurrentApplication.Value.HasValue) return;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -7,7 +7,7 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.PlayReport
|
namespace Ryujinx.Ava.Systems.PlayReport
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entrypoint for the Play Report analysis system.
|
/// The entrypoint for the Play Report analysis system.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ryujinx.Ava.Utilities.PlayReport
|
namespace Ryujinx.Ava.Systems.PlayReport
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The delegate type that powers single value formatters.<br/>
|
/// The delegate type that powers single value formatters.<br/>
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
using MsgPack;
|
using MsgPack;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.PlayReport
|
namespace Ryujinx.Ava.Systems.PlayReport
|
||||||
{
|
{
|
||||||
public abstract class MatchedValue<T>
|
public abstract class MatchedValue<T>
|
||||||
{
|
{
|
||||||
@@ -5,7 +5,7 @@ using System.Buffers.Binary;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.PlayReport
|
namespace Ryujinx.Ava.Systems.PlayReport
|
||||||
{
|
{
|
||||||
public partial class PlayReports
|
public partial class PlayReports
|
||||||
{
|
{
|
||||||
@@ -60,11 +60,12 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
_ => FormattedValue.ForceReset
|
_ => FormattedValue.ForceReset
|
||||||
};
|
};
|
||||||
|
|
||||||
private static FormattedValue PokemonSVUnionCircle(SingleValue value)
|
private static FormattedValue PokemonSV(MultiValue values)
|
||||||
=> value.Matched.BoxedValue is 0 ? "Playing Alone" : "Playing in a group";
|
{
|
||||||
|
|
||||||
private static FormattedValue PokemonSVArea(SingleValue value)
|
string playStatus = values.Matched[0].BoxedValue is 0 ? "Playing Alone" : "Playing in a group";
|
||||||
=> value.Matched.StringValue switch
|
|
||||||
|
FormattedValue locations = values.Matched[1].ToString() switch
|
||||||
{
|
{
|
||||||
// Base Game Locations
|
// Base Game Locations
|
||||||
"a_w01" => "South Area One",
|
"a_w01" => "South Area One",
|
||||||
@@ -92,11 +93,14 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
"a_w24" => "South Paldean Sea",
|
"a_w24" => "South Paldean Sea",
|
||||||
"a_w25" => "West Paldean Sea",
|
"a_w25" => "West Paldean Sea",
|
||||||
"a_w26" => "East Paldean Sea",
|
"a_w26" => "East Paldean Sea",
|
||||||
"a_w27" => "Nouth Paldean Sea",
|
"a_w27" => "North Paldean Sea",
|
||||||
//TODO DLC Locations
|
//TODO DLC Locations
|
||||||
_ => FormattedValue.ForceReset
|
_ => FormattedValue.ForceReset
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return$"{playStatus} in {locations}";
|
||||||
|
}
|
||||||
|
|
||||||
private static FormattedValue SuperSmashBrosUltimate_Mode(SparseMultiValue values)
|
private static FormattedValue SuperSmashBrosUltimate_Mode(SparseMultiValue values)
|
||||||
{
|
{
|
||||||
// Check if the PlayReport is for a challenger approach or an achievement.
|
// Check if the PlayReport is for a challenger approach or an achievement.
|
||||||
@@ -115,6 +119,11 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
return $"Achievement Unlocked - ID: {anniversary}";
|
return $"Achievement Unlocked - ID: {anniversary}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (values.Matched.ContainsKey("is_created"))
|
||||||
|
{
|
||||||
|
return "Edited a Custom Stage!";
|
||||||
|
}
|
||||||
|
|
||||||
if (values.Matched.ContainsKey("adv_slot"))
|
if (values.Matched.ContainsKey("adv_slot"))
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.PlayReport
|
namespace Ryujinx.Ava.Systems.PlayReport
|
||||||
{
|
{
|
||||||
public static partial class PlayReports
|
public static partial class PlayReports
|
||||||
{
|
{
|
||||||
@@ -59,9 +59,8 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
.AddSpec(
|
.AddSpec(
|
||||||
["0100a3d008c5c000", "01008f6008c5e000"],
|
["0100a3d008c5c000", "01008f6008c5e000"],
|
||||||
spec => spec
|
spec => spec
|
||||||
.WithDescription("based on what area of Paldea you're exploring.")
|
.WithDescription("based on if you're playing alone or in a group and what area of Paldea you're exploring.")
|
||||||
.AddValueFormatter("area_no", PokemonSVArea)
|
.AddMultiValueFormatter(["team_circle", "area_no"], PokemonSV)
|
||||||
.AddValueFormatter("team_circle", PokemonSVUnionCircle)
|
|
||||||
)
|
)
|
||||||
.AddSpec(
|
.AddSpec(
|
||||||
"01006a800016e000",
|
"01006a800016e000",
|
||||||
@@ -71,7 +70,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
[
|
[
|
||||||
// Metadata to figure out what PlayReport we have.
|
// Metadata to figure out what PlayReport we have.
|
||||||
"match_mode", "match_submode", "anniversary", "fighter", "reason", "challenge_count",
|
"match_mode", "match_submode", "anniversary", "fighter", "reason", "challenge_count",
|
||||||
"adv_slot",
|
"adv_slot", "is_created",
|
||||||
// List of Fighters
|
// List of Fighters
|
||||||
"player_1_fighter", "player_2_fighter", "player_3_fighter", "player_4_fighter",
|
"player_1_fighter", "player_2_fighter", "player_3_fighter", "player_4_fighter",
|
||||||
"player_5_fighter", "player_6_fighter", "player_7_fighter", "player_8_fighter",
|
"player_5_fighter", "player_6_fighter", "player_7_fighter", "player_8_fighter",
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
using MsgPack;
|
using MsgPack;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.PlayReport
|
namespace Ryujinx.Ava.Systems.PlayReport
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A mapping of title IDs to value formatter specs.
|
/// A mapping of title IDs to value formatter specs.
|
||||||
@@ -103,7 +103,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
/// matching a specific set of keys that could exist in a Play Report for the previously specified title IDs.
|
/// matching a specific set of keys that could exist in a Play Report for the previously specified title IDs.
|
||||||
/// <br/><br/>
|
/// <br/><br/>
|
||||||
/// The 'Sparse' multi-value formatters do not require every key to be present.
|
/// The 'Sparse' multi-value formatters do not require every key to be present.
|
||||||
/// If you need this requirement, use <see cref="AddMultiValueFormatter(string[], Ryujinx.Ava.Utilities.PlayReport.MultiValueFormatter)"/>.
|
/// If you need this requirement, use <see cref="AddMultiValueFormatter(string[], MultiValueFormatter)"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reportKeys">The key names to match.</param>
|
/// <param name="reportKeys">The key names to match.</param>
|
||||||
/// <param name="valueFormatter">The function which can format the values.</param>
|
/// <param name="valueFormatter">The function which can format the values.</param>
|
||||||
@@ -118,7 +118,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
/// matching a specific set of keys that could exist in a Play Report for the previously specified title IDs.
|
/// matching a specific set of keys that could exist in a Play Report for the previously specified title IDs.
|
||||||
/// <br/><br/>
|
/// <br/><br/>
|
||||||
/// The 'Sparse' multi-value formatters do not require every key to be present.
|
/// The 'Sparse' multi-value formatters do not require every key to be present.
|
||||||
/// If you need this requirement, use <see cref="AddMultiValueFormatter(int, string[], Ryujinx.Ava.Utilities.PlayReport.MultiValueFormatter)"/>.
|
/// If you need this requirement, use <see cref="AddMultiValueFormatter(int, string[], MultiValueFormatter)"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="priority">The resolution priority of this value formatter. Higher resolves sooner.</param>
|
/// <param name="priority">The resolution priority of this value formatter. Higher resolves sooner.</param>
|
||||||
/// <param name="reportKeys">The key names to match.</param>
|
/// <param name="reportKeys">The key names to match.</param>
|
||||||
@@ -3,7 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.PlayReport
|
namespace Ryujinx.Ava.Systems.PlayReport
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The base input data to a ValueFormatter delegate,
|
/// The base input data to a ValueFormatter delegate,
|
||||||
74
src/Ryujinx/Systems/Rebooter.cs
Normal file
74
src/Ryujinx/Systems/Rebooter.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using FluentAvalonia.UI.Controls;
|
||||||
|
using Ryujinx.Ava.Common.Locale;
|
||||||
|
using Ryujinx.Ava.Utilities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.Systems
|
||||||
|
{
|
||||||
|
internal static class Rebooter
|
||||||
|
{
|
||||||
|
|
||||||
|
private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
|
||||||
|
|
||||||
|
|
||||||
|
public static void RebootAppWithGame(string gamePath, List<string> args)
|
||||||
|
{
|
||||||
|
_ = Reboot(gamePath, args);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task Reboot(string gamePath, List<string> args)
|
||||||
|
{
|
||||||
|
|
||||||
|
bool shouldRestart = true;
|
||||||
|
|
||||||
|
TaskDialog taskDialog = new()
|
||||||
|
{
|
||||||
|
Header = LocaleManager.Instance[LocaleKeys.RyujinxRebooter],
|
||||||
|
SubHeader = LocaleManager.Instance[LocaleKeys.DialogRebooterMessage],
|
||||||
|
IconSource = new SymbolIconSource { Symbol = Symbol.Games },
|
||||||
|
XamlRoot = RyujinxApp.MainWindow,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (shouldRestart)
|
||||||
|
{
|
||||||
|
List<string> arguments = CommandLineState.Arguments.ToList();
|
||||||
|
string executableDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
|
||||||
|
var dialogTask = taskDialog.ShowAsync(true);
|
||||||
|
await Task.Delay(500);
|
||||||
|
|
||||||
|
// Find the process name.
|
||||||
|
string ryuName = Path.GetFileName(Environment.ProcessPath) ?? string.Empty;
|
||||||
|
|
||||||
|
// Fallback if the executable could not be found.
|
||||||
|
if (ryuName.Length == 0 || !Path.Exists(Path.Combine(executableDirectory, ryuName)))
|
||||||
|
{
|
||||||
|
ryuName = OperatingSystem.IsWindows() ? "Ryujinx.exe" : "Ryujinx";
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessStartInfo processStart = new(ryuName)
|
||||||
|
{
|
||||||
|
UseShellExecute = true,
|
||||||
|
WorkingDirectory = executableDirectory,
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var arg in args)
|
||||||
|
{
|
||||||
|
processStart.ArgumentList.Add(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
processStart.ArgumentList.Add(gamePath);
|
||||||
|
|
||||||
|
Process.Start(processStart);
|
||||||
|
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Ava
|
namespace Ryujinx.Ava.Systems
|
||||||
{
|
{
|
||||||
internal static class Updater
|
internal static class Updater
|
||||||
{
|
{
|
||||||
@@ -44,16 +44,8 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
private static string _buildVer;
|
private static string _buildVer;
|
||||||
|
|
||||||
private static readonly string _platformExt =
|
|
||||||
RunningPlatform.IsMacOS
|
private static readonly string _platformExt = BuildPlatformExtension();
|
||||||
? "macos_universal.app.tar.gz"
|
|
||||||
: RunningPlatform.IsWindows
|
|
||||||
? "win_x64.zip"
|
|
||||||
: RunningPlatform.IsX64Linux
|
|
||||||
? "linux_x64.tar.gz"
|
|
||||||
: RunningPlatform.IsArmLinux
|
|
||||||
? "linux_arm64.tar.gz"
|
|
||||||
: throw new PlatformNotSupportedException();
|
|
||||||
|
|
||||||
private static string _buildUrl;
|
private static string _buildUrl;
|
||||||
private static long _buildSize;
|
private static long _buildSize;
|
||||||
@@ -780,5 +772,34 @@ namespace Ryujinx.Ava
|
|||||||
public static void CleanupUpdate() =>
|
public static void CleanupUpdate() =>
|
||||||
Directory.GetFiles(_homeDir, "*.ryuold", SearchOption.AllDirectories)
|
Directory.GetFiles(_homeDir, "*.ryuold", SearchOption.AllDirectories)
|
||||||
.ForEach(File.Delete);
|
.ForEach(File.Delete);
|
||||||
|
|
||||||
|
private static string BuildPlatformExtension()
|
||||||
|
{
|
||||||
|
if (RunningPlatform.IsMacOS)
|
||||||
|
return "macos_universal.app.tar.gz";
|
||||||
|
|
||||||
|
#pragma warning disable CS8509 // It is exhaustive for any values this can contain.
|
||||||
|
string osPrefix = RunningPlatform.CurrentOS switch
|
||||||
|
{
|
||||||
|
OperatingSystemType.Linux => "linux",
|
||||||
|
OperatingSystemType.Windows => "win"
|
||||||
|
};
|
||||||
|
|
||||||
|
string archSuffix = RunningPlatform.Architecture switch
|
||||||
|
{
|
||||||
|
Architecture.Arm64 => "arm64",
|
||||||
|
Architecture.X64 => "x64",
|
||||||
|
_ => throw new PlatformNotSupportedException($"Unknown architecture {Enum.GetName(RunningPlatform.Architecture)}."),
|
||||||
|
};
|
||||||
|
|
||||||
|
string fileExtension = RunningPlatform.CurrentOS switch
|
||||||
|
#pragma warning restore CS8509
|
||||||
|
{
|
||||||
|
OperatingSystemType.Linux => "tar.gz",
|
||||||
|
OperatingSystemType.Windows => "zip"
|
||||||
|
};
|
||||||
|
|
||||||
|
return $"{osPrefix}_{archSuffix}.{fileExtension}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ using Ryujinx.Ava.UI.Controls;
|
|||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
using Ryujinx.HLE.HOS.Applets;
|
using Ryujinx.HLE.HOS.Applets;
|
||||||
@@ -95,7 +95,7 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
_parent.SettingsWindow =
|
_parent.SettingsWindow =
|
||||||
new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
|
new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
|
||||||
|
|
||||||
await _parent.SettingsWindow.ShowDialog(window);
|
await StyleableAppWindow.ShowAsync(_parent.SettingsWindow, window);
|
||||||
|
|
||||||
_parent.SettingsWindow = null;
|
_parent.SettingsWindow = null;
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,7 @@
|
|||||||
<viewModels:ProfileSelectorDialogViewModel />
|
<viewModels:ProfileSelectorDialogViewModel />
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
|
|
||||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RowDefinitions="*,Auto">
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Border
|
<Border
|
||||||
CornerRadius="5"
|
CornerRadius="5"
|
||||||
|
|||||||
@@ -9,17 +9,14 @@ using Ryujinx.Ava.UI.ViewModels;
|
|||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
|
using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
|
||||||
using UserProfileSft = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
|
using UserProfileSft = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Applet
|
namespace Ryujinx.Ava.UI.Applet
|
||||||
{
|
{
|
||||||
public partial class ProfileSelectorDialog : UserControl
|
public partial class ProfileSelectorDialog : RyujinxControl<ProfileSelectorDialogViewModel>
|
||||||
{
|
{
|
||||||
public ProfileSelectorDialogViewModel ViewModel { get; set; }
|
|
||||||
|
|
||||||
public ProfileSelectorDialog(ProfileSelectorDialogViewModel viewModel)
|
public ProfileSelectorDialog(ProfileSelectorDialogViewModel viewModel)
|
||||||
{
|
{
|
||||||
DataContext = ViewModel = viewModel;
|
DataContext = ViewModel = viewModel;
|
||||||
|
|||||||
@@ -19,6 +19,18 @@
|
|||||||
Header="{ext:Locale GameListContextMenuCreateShortcut}"
|
Header="{ext:Locale GameListContextMenuCreateShortcut}"
|
||||||
Icon="{ext:Icon fa-solid fa-bookmark}"
|
Icon="{ext:Icon fa-solid fa-bookmark}"
|
||||||
ToolTip.Tip="{OnPlatform Default={ext:Locale GameListContextMenuCreateShortcutToolTip}, macOS={ext:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
|
ToolTip.Tip="{OnPlatform Default={ext:Locale GameListContextMenuCreateShortcutToolTip}, macOS={ext:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
|
||||||
|
<MenuItem
|
||||||
|
Click="EditGameConfiguration_Click"
|
||||||
|
IsVisible="{Binding SelectedApplication.HasIndependentConfiguration}"
|
||||||
|
Header="{ext:Locale GameListContextMenuEditCustomConfiguration}"
|
||||||
|
Icon="{ext:Icon fa-solid fa-gear}"
|
||||||
|
ToolTip.Tip="{ext:Locale EditCustomConfigurationToolTip}" />
|
||||||
|
<MenuItem
|
||||||
|
Click="EditGameConfiguration_Click"
|
||||||
|
IsVisible="{Binding !SelectedApplication.HasIndependentConfiguration}"
|
||||||
|
Header="{ext:Locale GameListContextMenuCreateCustomConfiguration}"
|
||||||
|
Icon="{ext:Icon fa-solid fa-gear}"
|
||||||
|
ToolTip.Tip="{ext:Locale CreateCustomConfigurationToolTip}" />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
IsVisible="{Binding HasCompatibilityEntry}"
|
IsVisible="{Binding HasCompatibilityEntry}"
|
||||||
Click="OpenApplicationCompatibility_Click"
|
Click="OpenApplicationCompatibility_Click"
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ using Ryujinx.Ava.UI.Helpers;
|
|||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using Ryujinx.Ava.Utilities.Compat;
|
using Ryujinx.Ava.UI.Views.Dialog;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
@@ -26,6 +26,7 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
{
|
{
|
||||||
public class ApplicationContextMenu : MenuFlyout
|
public class ApplicationContextMenu : MenuFlyout
|
||||||
{
|
{
|
||||||
|
|
||||||
public ApplicationContextMenu()
|
public ApplicationContextMenu()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -79,23 +80,26 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
public async void OpenTitleUpdateManager_Click(object sender, RoutedEventArgs args)
|
public async void OpenTitleUpdateManager_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await TitleUpdateWindow.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication);
|
await TitleUpdateManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void OpenDownloadableContentManager_Click(object sender, RoutedEventArgs args)
|
public async void OpenDownloadableContentManager_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await DownloadableContentManagerWindow.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication);
|
await DownloadableContentManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void OpenCheatManager_Click(object sender, RoutedEventArgs args)
|
public async void OpenCheatManager_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await new CheatWindow(
|
await StyleableAppWindow.ShowAsync(
|
||||||
|
new CheatWindow(
|
||||||
viewModel.VirtualFileSystem,
|
viewModel.VirtualFileSystem,
|
||||||
viewModel.SelectedApplication.IdString,
|
viewModel.SelectedApplication.IdString,
|
||||||
viewModel.SelectedApplication.Name,
|
viewModel.SelectedApplication.Name,
|
||||||
viewModel.SelectedApplication.Path).ShowDialog((Window)viewModel.TopLevel);
|
viewModel.SelectedApplication.Path
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenModsDirectory_Click(object sender, RoutedEventArgs args)
|
public void OpenModsDirectory_Click(object sender, RoutedEventArgs args)
|
||||||
@@ -123,7 +127,7 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
public async void OpenModManager_Click(object sender, RoutedEventArgs args)
|
public async void OpenModManager_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await ModManagerWindow.Show(
|
await ModManagerView.Show(
|
||||||
viewModel.SelectedApplication.Id,
|
viewModel.SelectedApplication.Id,
|
||||||
viewModel.SelectedApplication.IdBase,
|
viewModel.SelectedApplication.IdBase,
|
||||||
viewModel.ApplicationLibrary,
|
viewModel.ApplicationLibrary,
|
||||||
@@ -200,7 +204,7 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
if (backupDir.Exists)
|
if (backupDir.Exists)
|
||||||
{
|
{
|
||||||
cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache"));
|
cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache"));
|
||||||
cacheFiles.AddRange(mainDir.EnumerateFiles("*.info"));
|
cacheFiles.AddRange(backupDir.EnumerateFiles("*.info"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cacheFiles.Count > 0)
|
if (cacheFiles.Count > 0)
|
||||||
@@ -387,10 +391,23 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async void EditGameConfiguration_Click(object sender, RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
|
{
|
||||||
|
await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(viewModel));
|
||||||
|
|
||||||
|
// just checking for file presence
|
||||||
|
viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false));
|
||||||
|
|
||||||
|
viewModel.RefreshView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async void OpenApplicationCompatibility_Click(object sender, RoutedEventArgs args)
|
public async void OpenApplicationCompatibility_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await CompatibilityList.Show(viewModel.SelectedApplication.IdString);
|
await CompatibilityListWindow.Show(viewModel.SelectedApplication.IdString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void OpenApplicationData_Click(object sender, RoutedEventArgs args)
|
public async void OpenApplicationData_Click(object sender, RoutedEventArgs args)
|
||||||
|
|||||||
@@ -23,13 +23,12 @@ using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
|
|||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Controls
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
public partial class NavigationDialogHost : UserControl
|
public partial class NavigationDialogHost : RyujinxControl<UserProfileViewModel>
|
||||||
{
|
{
|
||||||
public AccountManager AccountManager { get; }
|
public AccountManager AccountManager { get; }
|
||||||
public ContentManager ContentManager { get; }
|
public ContentManager ContentManager { get; }
|
||||||
public VirtualFileSystem VirtualFileSystem { get; }
|
public VirtualFileSystem VirtualFileSystem { get; }
|
||||||
public HorizonClient HorizonClient { get; }
|
public HorizonClient HorizonClient { get; }
|
||||||
public UserProfileViewModel ViewModel { get; set; }
|
|
||||||
|
|
||||||
public NavigationDialogHost()
|
public NavigationDialogHost()
|
||||||
{
|
{
|
||||||
|
|||||||
24
src/Ryujinx/UI/Controls/RyujinxControl.cs
Normal file
24
src/Ryujinx/UI/Controls/RyujinxControl.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
using Gommon;
|
||||||
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
|
{
|
||||||
|
public class RyujinxControl<TViewModel> : UserControl where TViewModel : BaseModel
|
||||||
|
{
|
||||||
|
public TViewModel ViewModel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (DataContext is not TViewModel viewModel)
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Underlying DataContext is not of type {typeof(TViewModel).AsPrettyString()}; " +
|
||||||
|
$"Actual type is {DataContext?.GetType().AsPrettyString()}");
|
||||||
|
|
||||||
|
return viewModel;
|
||||||
|
}
|
||||||
|
set => DataContext = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/Ryujinx/UI/Controls/RyujinxLogo.cs
Normal file
28
src/Ryujinx/UI/Controls/RyujinxLogo.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
|
{
|
||||||
|
public class RyujinxLogo : Image
|
||||||
|
{
|
||||||
|
// The UI specifically uses a thicker bordered variant of the icon to avoid crunching out the border at lower resolutions.
|
||||||
|
// For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
|
||||||
|
// The border gets reduced to colored pixels in the 4 corners.
|
||||||
|
public static readonly Bitmap Bitmap =
|
||||||
|
new(Assembly.GetAssembly(typeof(MainWindowViewModel))!
|
||||||
|
.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!);
|
||||||
|
|
||||||
|
public RyujinxLogo()
|
||||||
|
{
|
||||||
|
Margin = new Thickness(7, 7, 7, 0);
|
||||||
|
Height = 25;
|
||||||
|
Width = 25;
|
||||||
|
Source = Bitmap;
|
||||||
|
IsVisible = !ConfigurationState.Instance.ShowOldUI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Helpers
|
namespace Ryujinx.Ava.UI.Helpers
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
|
using Avalonia.Input;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Styling;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using FluentAvalonia.Core;
|
using FluentAvalonia.Core;
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
@@ -20,6 +22,23 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||||||
private static bool _isChoiceDialogOpen;
|
private static bool _isChoiceDialogOpen;
|
||||||
private static ContentDialogOverlayWindow _contentDialogOverlayWindow;
|
private static ContentDialogOverlayWindow _contentDialogOverlayWindow;
|
||||||
|
|
||||||
|
public static ContentDialog ApplyStyles(
|
||||||
|
this ContentDialog contentDialog,
|
||||||
|
double closeButtonWidth = 80,
|
||||||
|
HorizontalAlignment buttonSpaceAlignment = HorizontalAlignment.Right)
|
||||||
|
{
|
||||||
|
Style closeButton = new(x => x.Name("CloseButton"));
|
||||||
|
closeButton.Setters.Add(new Setter(Layoutable.WidthProperty, closeButtonWidth));
|
||||||
|
|
||||||
|
Style closeButtonParent = new(x => x.Name("CommandSpace"));
|
||||||
|
closeButtonParent.Setters.Add(new Setter(Layoutable.HorizontalAlignmentProperty, buttonSpaceAlignment));
|
||||||
|
|
||||||
|
contentDialog.Styles.Add(closeButton);
|
||||||
|
contentDialog.Styles.Add(closeButtonParent);
|
||||||
|
|
||||||
|
return contentDialog;
|
||||||
|
}
|
||||||
|
|
||||||
private async static Task<UserResult> ShowContentDialog(
|
private async static Task<UserResult> ShowContentDialog(
|
||||||
string title,
|
string title,
|
||||||
object content,
|
object content,
|
||||||
@@ -39,19 +58,19 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||||||
SecondaryButtonText = secondaryButton,
|
SecondaryButtonText = secondaryButton,
|
||||||
CloseButtonText = closeButton,
|
CloseButtonText = closeButton,
|
||||||
Content = content,
|
Content = content,
|
||||||
PrimaryButtonCommand = MiniCommand.Create(() =>
|
PrimaryButtonCommand = Commands.Create(() =>
|
||||||
{
|
{
|
||||||
result = primaryButtonResult;
|
result = primaryButtonResult;
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
contentDialog.SecondaryButtonCommand = MiniCommand.Create(() =>
|
contentDialog.SecondaryButtonCommand = Commands.Create(() =>
|
||||||
{
|
{
|
||||||
result = UserResult.No;
|
result = UserResult.No;
|
||||||
contentDialog.PrimaryButtonClick -= deferCloseAction;
|
contentDialog.PrimaryButtonClick -= deferCloseAction;
|
||||||
});
|
});
|
||||||
|
|
||||||
contentDialog.CloseButtonCommand = MiniCommand.Create(() =>
|
contentDialog.CloseButtonCommand = Commands.Create(() =>
|
||||||
{
|
{
|
||||||
result = UserResult.Cancel;
|
result = UserResult.Cancel;
|
||||||
contentDialog.PrimaryButtonClick -= deferCloseAction;
|
contentDialog.PrimaryButtonClick -= deferCloseAction;
|
||||||
@@ -385,6 +404,10 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||||||
ShowInTaskbar = false,
|
ShowInTaskbar = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
_contentDialogOverlayWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
|
||||||
|
#endif
|
||||||
|
|
||||||
parent.PositionChanged += OverlayOnPositionChanged;
|
parent.PositionChanged += OverlayOnPositionChanged;
|
||||||
|
|
||||||
void OverlayOnPositionChanged(object sender, PixelPointEventArgs e)
|
void OverlayOnPositionChanged(object sender, PixelPointEventArgs e)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using Avalonia.Data.Converters;
|
|||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ using SkiaSharp;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Windows
|
namespace Ryujinx.Ava.UI.Helpers
|
||||||
{
|
{
|
||||||
static class IconColorPicker
|
public static class IconColorPicker
|
||||||
{
|
{
|
||||||
private const int ColorsPerLine = 64;
|
private const int ColorsPerLine = 64;
|
||||||
private const int TotalColors = ColorsPerLine * ColorsPerLine;
|
private const int TotalColors = ColorsPerLine * ColorsPerLine;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Avalonia.Logging;
|
using Avalonia.Logging;
|
||||||
using Avalonia.Utilities;
|
using Avalonia.Utilities;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Input;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Helpers
|
|
||||||
{
|
|
||||||
public sealed class MiniCommand<T> : MiniCommand, ICommand
|
|
||||||
{
|
|
||||||
private readonly Action<T> _callback;
|
|
||||||
private bool _busy;
|
|
||||||
private readonly Func<T, Task> _asyncCallback;
|
|
||||||
|
|
||||||
public MiniCommand(Action<T> callback)
|
|
||||||
{
|
|
||||||
_callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MiniCommand(Func<T, Task> callback)
|
|
||||||
{
|
|
||||||
_asyncCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Busy
|
|
||||||
{
|
|
||||||
get => _busy;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_busy = value;
|
|
||||||
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override event EventHandler CanExecuteChanged;
|
|
||||||
public override bool CanExecute(object parameter) => !_busy;
|
|
||||||
|
|
||||||
public override async void Execute(object parameter)
|
|
||||||
{
|
|
||||||
if (Busy)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Busy = true;
|
|
||||||
if (_callback != null)
|
|
||||||
{
|
|
||||||
_callback((T)parameter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await _asyncCallback((T)parameter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Busy = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class MiniCommand : ICommand
|
|
||||||
{
|
|
||||||
public static MiniCommand Create(Action callback) => new MiniCommand<object>(_ => callback());
|
|
||||||
public static MiniCommand Create<TArg>(Action<TArg> callback) => new MiniCommand<TArg>(callback);
|
|
||||||
public static MiniCommand CreateFromTask(Func<Task> callback) => new MiniCommand<object>(_ => callback());
|
|
||||||
public static MiniCommand CreateFromTask<TArg>(Func<TArg, Task> callback) => new MiniCommand<TArg>(callback);
|
|
||||||
|
|
||||||
public abstract bool CanExecute(object parameter);
|
|
||||||
public abstract void Execute(object parameter);
|
|
||||||
public abstract event EventHandler CanExecuteChanged;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|||||||
260
src/Ryujinx/UI/Models/Input/StickVisualizer.cs
Normal file
260
src/Ryujinx/UI/Models/Input/StickVisualizer.cs
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||||
|
using Ryujinx.Input;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Models.Input
|
||||||
|
{
|
||||||
|
public class StickVisualizer : BaseModel, IDisposable
|
||||||
|
{
|
||||||
|
public const int DrawStickPollRate = 50; // Milliseconds per poll.
|
||||||
|
public const int DrawStickCircumference = 5;
|
||||||
|
public const float DrawStickScaleFactor = DrawStickCanvasCenter;
|
||||||
|
public const int DrawStickCanvasSize = 100;
|
||||||
|
public const int DrawStickBorderSize = DrawStickCanvasSize + 5;
|
||||||
|
public const float DrawStickCanvasCenter = (DrawStickCanvasSize - DrawStickCircumference) / 2;
|
||||||
|
public const float MaxVectorLength = DrawStickCanvasSize / 2;
|
||||||
|
|
||||||
|
public CancellationTokenSource PollTokenSource;
|
||||||
|
public CancellationToken PollToken;
|
||||||
|
|
||||||
|
private static float _vectorLength;
|
||||||
|
private static float _vectorMultiplier;
|
||||||
|
|
||||||
|
private bool disposedValue;
|
||||||
|
|
||||||
|
private DeviceType _type;
|
||||||
|
public DeviceType Type
|
||||||
|
{
|
||||||
|
get => _type;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_type = value;
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GamepadInputConfig _gamepadConfig;
|
||||||
|
public GamepadInputConfig GamepadConfig
|
||||||
|
{
|
||||||
|
get => _gamepadConfig;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_gamepadConfig = value;
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private KeyboardInputConfig _keyboardConfig;
|
||||||
|
public KeyboardInputConfig KeyboardConfig
|
||||||
|
{
|
||||||
|
get => _keyboardConfig;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_keyboardConfig = value;
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private (float, float) _uiStickLeft;
|
||||||
|
public (float, float) UiStickLeft
|
||||||
|
{
|
||||||
|
get => (_uiStickLeft.Item1 * DrawStickScaleFactor, _uiStickLeft.Item2 * DrawStickScaleFactor);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_uiStickLeft = value;
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
OnPropertyChanged(nameof(UiStickRightX));
|
||||||
|
OnPropertyChanged(nameof(UiStickRightY));
|
||||||
|
OnPropertyChanged(nameof(UiDeadzoneRight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private (float, float) _uiStickRight;
|
||||||
|
public (float, float) UiStickRight
|
||||||
|
{
|
||||||
|
get => (_uiStickRight.Item1 * DrawStickScaleFactor, _uiStickRight.Item2 * DrawStickScaleFactor);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_uiStickRight = value;
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
OnPropertyChanged(nameof(UiStickLeftX));
|
||||||
|
OnPropertyChanged(nameof(UiStickLeftY));
|
||||||
|
OnPropertyChanged(nameof(UiDeadzoneLeft));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float UiStickLeftX => ClampVector(UiStickLeft).Item1;
|
||||||
|
public float UiStickLeftY => ClampVector(UiStickLeft).Item2;
|
||||||
|
public float UiStickRightX => ClampVector(UiStickRight).Item1;
|
||||||
|
public float UiStickRightY => ClampVector(UiStickRight).Item2;
|
||||||
|
|
||||||
|
public int UiStickCircumference => DrawStickCircumference;
|
||||||
|
public int UiCanvasSize => DrawStickCanvasSize;
|
||||||
|
public int UiStickBorderSize => DrawStickBorderSize;
|
||||||
|
|
||||||
|
public float? UiDeadzoneLeft => _gamepadConfig?.DeadzoneLeft * DrawStickCanvasSize - DrawStickCircumference;
|
||||||
|
public float? UiDeadzoneRight => _gamepadConfig?.DeadzoneRight * DrawStickCanvasSize - DrawStickCircumference;
|
||||||
|
|
||||||
|
private InputViewModel Parent;
|
||||||
|
|
||||||
|
public StickVisualizer(InputViewModel parent)
|
||||||
|
{
|
||||||
|
Parent = parent;
|
||||||
|
|
||||||
|
PollTokenSource = new CancellationTokenSource();
|
||||||
|
PollToken = PollTokenSource.Token;
|
||||||
|
|
||||||
|
Task.Run(Initialize, PollToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateConfig(object config)
|
||||||
|
{
|
||||||
|
if (config is ControllerInputViewModel padConfig)
|
||||||
|
{
|
||||||
|
GamepadConfig = padConfig.Config;
|
||||||
|
Type = DeviceType.Controller;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (config is KeyboardInputViewModel keyConfig)
|
||||||
|
{
|
||||||
|
KeyboardConfig = keyConfig.Config;
|
||||||
|
Type = DeviceType.Keyboard;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type = DeviceType.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Initialize()
|
||||||
|
{
|
||||||
|
(float, float) leftBuffer;
|
||||||
|
(float, float) rightBuffer;
|
||||||
|
|
||||||
|
while (!PollToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
leftBuffer = (0f, 0f);
|
||||||
|
rightBuffer = (0f, 0f);
|
||||||
|
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case DeviceType.Keyboard:
|
||||||
|
IKeyboard keyboard = (IKeyboard)Parent.AvaloniaKeyboardDriver.GetGamepad("0");
|
||||||
|
|
||||||
|
if (keyboard != null)
|
||||||
|
{
|
||||||
|
KeyboardStateSnapshot snapshot = keyboard.GetKeyboardStateSnapshot();
|
||||||
|
|
||||||
|
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickRight))
|
||||||
|
{
|
||||||
|
leftBuffer.Item1 += 1;
|
||||||
|
}
|
||||||
|
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickLeft))
|
||||||
|
{
|
||||||
|
leftBuffer.Item1 -= 1;
|
||||||
|
}
|
||||||
|
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickUp))
|
||||||
|
{
|
||||||
|
leftBuffer.Item2 += 1;
|
||||||
|
}
|
||||||
|
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickDown))
|
||||||
|
{
|
||||||
|
leftBuffer.Item2 -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickRight))
|
||||||
|
{
|
||||||
|
rightBuffer.Item1 += 1;
|
||||||
|
}
|
||||||
|
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickLeft))
|
||||||
|
{
|
||||||
|
rightBuffer.Item1 -= 1;
|
||||||
|
}
|
||||||
|
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickUp))
|
||||||
|
{
|
||||||
|
rightBuffer.Item2 += 1;
|
||||||
|
}
|
||||||
|
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickDown))
|
||||||
|
{
|
||||||
|
rightBuffer.Item2 -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
UiStickLeft = leftBuffer;
|
||||||
|
UiStickRight = rightBuffer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeviceType.Controller:
|
||||||
|
IGamepad controller = Parent.SelectedGamepad;
|
||||||
|
|
||||||
|
if (controller != null)
|
||||||
|
{
|
||||||
|
leftBuffer = controller.GetStick((StickInputId)GamepadConfig.LeftJoystick);
|
||||||
|
rightBuffer = controller.GetStick((StickInputId)GamepadConfig.RightJoystick);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeviceType.None:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException($"Unable to poll device type \"{Type}\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
UiStickLeft = leftBuffer;
|
||||||
|
UiStickRight = rightBuffer;
|
||||||
|
|
||||||
|
await Task.Delay(DrawStickPollRate, PollToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
PollTokenSource.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static (float, float) ClampVector((float, float) vect)
|
||||||
|
{
|
||||||
|
_vectorMultiplier = 1;
|
||||||
|
_vectorLength = MathF.Sqrt((vect.Item1 * vect.Item1) + (vect.Item2 * vect.Item2));
|
||||||
|
|
||||||
|
if (_vectorLength > MaxVectorLength)
|
||||||
|
{
|
||||||
|
_vectorMultiplier = MaxVectorLength / _vectorLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
vect.Item1 = vect.Item1 * _vectorMultiplier + DrawStickCanvasCenter;
|
||||||
|
vect.Item2 = vect.Item2 * _vectorMultiplier + DrawStickCanvasCenter;
|
||||||
|
|
||||||
|
return vect;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!disposedValue)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
PollTokenSource.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyboardConfig = null;
|
||||||
|
GamepadConfig = null;
|
||||||
|
Parent = null;
|
||||||
|
|
||||||
|
disposedValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(disposing: true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ using LibHac.Fs;
|
|||||||
using LibHac.Ncm;
|
using LibHac.Ncm;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
using SPB.Graphics;
|
using SPB.Graphics;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Renderer
|
namespace Ryujinx.Ava.UI.Renderer
|
||||||
@@ -39,32 +37,6 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||||||
_ => throw new NotImplementedException()
|
_ => throw new NotImplementedException()
|
||||||
};
|
};
|
||||||
|
|
||||||
public RendererHost(string titleId)
|
|
||||||
{
|
|
||||||
Focusable = true;
|
|
||||||
FlowDirection = FlowDirection.LeftToRight;
|
|
||||||
|
|
||||||
EmbeddedWindow =
|
|
||||||
#pragma warning disable CS8524
|
|
||||||
ConfigurationState.Instance.Graphics.GraphicsBackend.Value switch
|
|
||||||
#pragma warning restore CS8524
|
|
||||||
{
|
|
||||||
GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(),
|
|
||||||
GraphicsBackend.Vulkan => new EmbeddedWindowVulkan(),
|
|
||||||
};
|
|
||||||
|
|
||||||
string backendText = EmbeddedWindow switch
|
|
||||||
{
|
|
||||||
EmbeddedWindowVulkan => "Vulkan",
|
|
||||||
EmbeddedWindowOpenGL => "OpenGL",
|
|
||||||
_ => throw new NotImplementedException()
|
|
||||||
};
|
|
||||||
|
|
||||||
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend ({ConfigurationState.Instance.Graphics.GraphicsBackend.Value}): {backendText}");
|
|
||||||
|
|
||||||
Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,4 +17,9 @@
|
|||||||
<sty:FluentAvaloniaTheme PreferUserAccentColor="True" PreferSystemTheme="False" />
|
<sty:FluentAvaloniaTheme PreferUserAccentColor="True" PreferSystemTheme="False" />
|
||||||
<StyleInclude Source="/Assets/Styles/Styles.xaml" />
|
<StyleInclude Source="/Assets/Styles/Styles.xaml" />
|
||||||
</Application.Styles>
|
</Application.Styles>
|
||||||
|
<NativeMenu.Menu>
|
||||||
|
<NativeMenu>
|
||||||
|
<NativeMenuItem Header="About Ryujinx" Click="AboutRyujinx_OnClick" />
|
||||||
|
</NativeMenu>
|
||||||
|
</NativeMenu.Menu>
|
||||||
</Application>
|
</Application>
|
||||||
@@ -7,12 +7,12 @@ using Avalonia.Styling;
|
|||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using FluentAvalonia.UI.Windowing;
|
using FluentAvalonia.UI.Windowing;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Common;
|
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities;
|
using Ryujinx.Ava.Utilities;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
|
using Ryujinx.Ava.UI.Views.Dialog;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
@@ -147,5 +147,10 @@ namespace Ryujinx.Ava
|
|||||||
Current is RyujinxApp { PlatformSettings: not null } app
|
Current is RyujinxApp { PlatformSettings: not null } app
|
||||||
? ConvertThemeVariant(app.PlatformSettings.GetColorValues().ThemeVariant)
|
? ConvertThemeVariant(app.PlatformSettings.GetColorValues().ThemeVariant)
|
||||||
: ThemeVariant.Default;
|
: ThemeVariant.Default;
|
||||||
|
|
||||||
|
private async void AboutRyujinx_OnClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
await AboutView.Show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,8 @@ using Avalonia.Styling;
|
|||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Common;
|
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using Ryujinx.Ava.Utilities.PlayReport;
|
using Ryujinx.Ava.Systems.PlayReport;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.Systems;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities.Compat
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
public class CompatibilityViewModel : BaseModel
|
public class CompatibilityViewModel : BaseModel, IDisposable
|
||||||
{
|
{
|
||||||
private bool _onlyShowOwnedGames = true;
|
private readonly ApplicationLibrary _appLibrary;
|
||||||
|
|
||||||
private IEnumerable<CompatibilityEntry> _currentEntries = CompatibilityCsv.Entries;
|
private IEnumerable<CompatibilityEntry> _currentEntries = CompatibilityDatabase.Entries;
|
||||||
private string[] _ownedGameTitleIds = [];
|
private string[] _ownedGameTitleIds = [];
|
||||||
|
|
||||||
public IEnumerable<CompatibilityEntry> CurrentEntries => OnlyShowOwnedGames
|
public IEnumerable<CompatibilityEntry> CurrentEntries => OnlyShowOwnedGames
|
||||||
@@ -20,14 +21,26 @@ namespace Ryujinx.Ava.Utilities.Compat
|
|||||||
|
|
||||||
public CompatibilityViewModel() {}
|
public CompatibilityViewModel() {}
|
||||||
|
|
||||||
|
private void AppCountUpdated(object _, ApplicationCountUpdatedEventArgs __)
|
||||||
|
=> _ownedGameTitleIds = _appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
|
||||||
|
|
||||||
public CompatibilityViewModel(ApplicationLibrary appLibrary)
|
public CompatibilityViewModel(ApplicationLibrary appLibrary)
|
||||||
{
|
{
|
||||||
appLibrary.ApplicationCountUpdated += (_, _)
|
_appLibrary = appLibrary;
|
||||||
=> _ownedGameTitleIds = appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
|
|
||||||
|
|
||||||
_ownedGameTitleIds = appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
|
AppCountUpdated(null, null);
|
||||||
|
|
||||||
|
_appLibrary.ApplicationCountUpdated += AppCountUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IDisposable.Dispose()
|
||||||
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
_appLibrary.ApplicationCountUpdated -= AppCountUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _onlyShowOwnedGames = true;
|
||||||
|
|
||||||
public bool OnlyShowOwnedGames
|
public bool OnlyShowOwnedGames
|
||||||
{
|
{
|
||||||
get => _onlyShowOwnedGames;
|
get => _onlyShowOwnedGames;
|
||||||
@@ -45,11 +58,11 @@ namespace Ryujinx.Ava.Utilities.Compat
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(searchTerm))
|
if (string.IsNullOrEmpty(searchTerm))
|
||||||
{
|
{
|
||||||
SetEntries(CompatibilityCsv.Entries);
|
SetEntries(CompatibilityDatabase.Entries);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetEntries(CompatibilityCsv.Entries.Where(x =>
|
SetEntries(CompatibilityDatabase.Entries.Where(x =>
|
||||||
x.GameName.ContainsIgnoreCase(searchTerm)
|
x.GameName.ContainsIgnoreCase(searchTerm)
|
||||||
|| x.TitleId.Check(tid => tid.ContainsIgnoreCase(searchTerm))));
|
|| x.TitleId.Check(tid => tid.ContainsIgnoreCase(searchTerm))));
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Ryujinx.Ava.Common.Models;
|
using Ryujinx.Ava.Common.Models;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using FluentAvalonia.UI.Controls;
|
|||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Common.Models;
|
using Ryujinx.Ava.Common.Models;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|||||||
@@ -10,7 +10,29 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
{
|
{
|
||||||
public partial class ControllerInputViewModel : BaseModel
|
public partial class ControllerInputViewModel : BaseModel
|
||||||
{
|
{
|
||||||
[ObservableProperty] private GamepadInputConfig _config;
|
private GamepadInputConfig _config;
|
||||||
|
public GamepadInputConfig Config
|
||||||
|
{
|
||||||
|
get => _config;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_config = value;
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private StickVisualizer _visualizer;
|
||||||
|
public StickVisualizer Visualizer
|
||||||
|
{
|
||||||
|
get => _visualizer;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_visualizer = value;
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool _isLeft;
|
private bool _isLeft;
|
||||||
public bool IsLeft
|
public bool IsLeft
|
||||||
@@ -42,9 +64,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
public InputViewModel ParentModel { get; }
|
public InputViewModel ParentModel { get; }
|
||||||
|
|
||||||
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config)
|
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config, StickVisualizer visualizer)
|
||||||
{
|
{
|
||||||
ParentModel = model;
|
ParentModel = model;
|
||||||
|
Visualizer = visualizer;
|
||||||
model.NotifyChangesEvent += OnParentModelChanged;
|
model.NotifyChangesEvent += OnParentModelChanged;
|
||||||
OnParentModelChanged();
|
OnParentModelChanged();
|
||||||
config.PropertyChanged += (_, args) =>
|
config.PropertyChanged += (_, args) =>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using Ryujinx.Ava.UI.Helpers;
|
|||||||
using Ryujinx.Ava.UI.Models;
|
using Ryujinx.Ava.UI.Models;
|
||||||
using Ryujinx.Ava.UI.Models.Input;
|
using Ryujinx.Ava.UI.Models.Input;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
@@ -49,7 +49,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
private int _controller;
|
private int _controller;
|
||||||
private string _controllerImage;
|
private string _controllerImage;
|
||||||
private int _device;
|
private int _device;
|
||||||
[ObservableProperty] private object _configViewModel;
|
private object _configViewModel;
|
||||||
[ObservableProperty] private string _profileName;
|
[ObservableProperty] private string _profileName;
|
||||||
private bool _isLoaded;
|
private bool _isLoaded;
|
||||||
|
|
||||||
@@ -74,6 +74,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed));
|
OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public StickVisualizer VisualStick { get; private set; }
|
||||||
|
|
||||||
public ObservableCollection<PlayerModel> PlayerIndexes { get; set; }
|
public ObservableCollection<PlayerModel> PlayerIndexes { get; set; }
|
||||||
public ObservableCollection<(DeviceType Type, string Id, string Name)> Devices { get; set; }
|
public ObservableCollection<(DeviceType Type, string Id, string Name)> Devices { get; set; }
|
||||||
@@ -94,6 +95,19 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
public bool IsModified { get; set; }
|
public bool IsModified { get; set; }
|
||||||
public event Action NotifyChangesEvent;
|
public event Action NotifyChangesEvent;
|
||||||
|
|
||||||
|
public object ConfigViewModel
|
||||||
|
{
|
||||||
|
get => _configViewModel;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_configViewModel = value;
|
||||||
|
|
||||||
|
VisualStick.UpdateConfig(value);
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public PlayerIndex PlayerIdChoose
|
public PlayerIndex PlayerIdChoose
|
||||||
{
|
{
|
||||||
get => _playerIdChoose;
|
get => _playerIdChoose;
|
||||||
@@ -269,6 +283,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
Devices = [];
|
Devices = [];
|
||||||
ProfilesList = [];
|
ProfilesList = [];
|
||||||
DeviceList = [];
|
DeviceList = [];
|
||||||
|
VisualStick = new StickVisualizer(this);
|
||||||
|
|
||||||
ControllerImage = ProControllerResource;
|
ControllerImage = ProControllerResource;
|
||||||
|
|
||||||
@@ -289,12 +304,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
if (Config is StandardKeyboardInputConfig keyboardInputConfig)
|
if (Config is StandardKeyboardInputConfig keyboardInputConfig)
|
||||||
{
|
{
|
||||||
ConfigViewModel = new KeyboardInputViewModel(this, new KeyboardInputConfig(keyboardInputConfig));
|
ConfigViewModel = new KeyboardInputViewModel(this, new KeyboardInputConfig(keyboardInputConfig), VisualStick);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config is StandardControllerInputConfig controllerInputConfig)
|
if (Config is StandardControllerInputConfig controllerInputConfig)
|
||||||
{
|
{
|
||||||
ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig));
|
ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig), VisualStick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -893,6 +908,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
_mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
|
_mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
|
||||||
|
|
||||||
|
VisualStick.Dispose();
|
||||||
|
|
||||||
SelectedGamepad?.Dispose();
|
SelectedGamepad?.Dispose();
|
||||||
|
|
||||||
AvaloniaKeyboardDriver.Dispose();
|
AvaloniaKeyboardDriver.Dispose();
|
||||||
|
|||||||
@@ -6,7 +6,29 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
{
|
{
|
||||||
public partial class KeyboardInputViewModel : BaseModel
|
public partial class KeyboardInputViewModel : BaseModel
|
||||||
{
|
{
|
||||||
[ObservableProperty] private KeyboardInputConfig _config;
|
private KeyboardInputConfig _config;
|
||||||
|
public KeyboardInputConfig Config
|
||||||
|
{
|
||||||
|
get => _config;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_config = value;
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private StickVisualizer _visualizer;
|
||||||
|
public StickVisualizer Visualizer
|
||||||
|
{
|
||||||
|
get => _visualizer;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_visualizer = value;
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool _isLeft;
|
private bool _isLeft;
|
||||||
public bool IsLeft
|
public bool IsLeft
|
||||||
@@ -38,9 +60,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
public readonly InputViewModel ParentModel;
|
public readonly InputViewModel ParentModel;
|
||||||
|
|
||||||
public KeyboardInputViewModel(InputViewModel model, KeyboardInputConfig config)
|
public KeyboardInputViewModel(InputViewModel model, KeyboardInputConfig config, StickVisualizer visualizer)
|
||||||
{
|
{
|
||||||
ParentModel = model;
|
ParentModel = model;
|
||||||
|
Visualizer = visualizer;
|
||||||
model.NotifyChangesEvent += OnParentModelChanged;
|
model.NotifyChangesEvent += OnParentModelChanged;
|
||||||
OnParentModelChanged();
|
OnParentModelChanged();
|
||||||
Config = config;
|
Config = config;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
|||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Media.Imaging;
|
|
||||||
using Avalonia.Platform.Storage;
|
using Avalonia.Platform.Storage;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
@@ -17,14 +16,15 @@ using LibHac.Ns;
|
|||||||
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.Systems;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
using Ryujinx.Ava.UI.Controls;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Models;
|
using Ryujinx.Ava.UI.Models;
|
||||||
using Ryujinx.Ava.UI.Models.Generic;
|
using Ryujinx.Ava.UI.Models.Generic;
|
||||||
using Ryujinx.Ava.UI.Renderer;
|
using Ryujinx.Ava.UI.Renderer;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
@@ -46,7 +46,6 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Key = Ryujinx.Input.Key;
|
using Key = Ryujinx.Input.Key;
|
||||||
@@ -137,13 +136,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
// Key is Title ID
|
// Key is Title ID
|
||||||
public SafeDictionary<string, LdnGameData.Array> LdnData = [];
|
public SafeDictionary<string, LdnGameData.Array> LdnData = [];
|
||||||
|
|
||||||
// The UI specifically uses a thicker bordered variant of the icon to avoid crunching out the border at lower resolutions.
|
|
||||||
// For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
|
|
||||||
// The border gets reduced to colored pixels in the 4 corners.
|
|
||||||
public static readonly Bitmap IconBitmap =
|
|
||||||
new(Assembly.GetAssembly(typeof(MainWindowViewModel))!
|
|
||||||
.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!);
|
|
||||||
|
|
||||||
public MainWindow Window { get; init; }
|
public MainWindow Window { get; init; }
|
||||||
|
|
||||||
internal AppHost AppHost { get; set; }
|
internal AppHost AppHost { get; set; }
|
||||||
@@ -356,6 +348,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ListSelectedApplication = value;
|
||||||
|
GridSelectedApplication = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
|
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
|
||||||
@@ -1551,8 +1548,50 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool InitializeUserConfig(ApplicationData application)
|
||||||
|
{
|
||||||
|
// Code where conditions will be met before loading the user configuration (Global Config)
|
||||||
|
BackendThreading backendThreadingValue = ConfigurationState.Instance.Graphics.BackendThreading.Value;
|
||||||
|
string BackendThreadingInit = Program.BackendThreadingArg;
|
||||||
|
|
||||||
|
if (BackendThreadingInit is null)
|
||||||
|
{
|
||||||
|
BackendThreadingInit = ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a configuration is found in the "/games/xxxxxxxxxxxxxx" folder, the program will load the user setting.
|
||||||
|
string idGame = application.IdBaseString;
|
||||||
|
if (ConfigurationFileFormat.TryLoad(Program.GetDirGameUserConfig(idGame), out ConfigurationFileFormat configurationFileFormat))
|
||||||
|
{
|
||||||
|
// Loads the user configuration, having previously changed the global configuration to the user configuration
|
||||||
|
ConfigurationState.Instance.Load(configurationFileFormat, Program.GetDirGameUserConfig(idGame, true, true), idGame);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code where conditions will be executed after loading user configuration
|
||||||
|
if (ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() != BackendThreadingInit)
|
||||||
|
{
|
||||||
|
|
||||||
|
List<string> Arguments = new List<string>
|
||||||
|
{
|
||||||
|
"--bt", ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() // BackendThreading
|
||||||
|
};
|
||||||
|
|
||||||
|
Rebooter.RebootAppWithGame(application.Path, Arguments);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task LoadApplication(ApplicationData application, bool startFullscreen = false, BlitStruct<ApplicationControlProperty>? customNacpData = null)
|
public async Task LoadApplication(ApplicationData application, bool startFullscreen = false, BlitStruct<ApplicationControlProperty>? customNacpData = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (InitializeUserConfig(application))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (AppHost != null)
|
if (AppHost != null)
|
||||||
{
|
{
|
||||||
await ContentDialogHelper.CreateInfoDialog(
|
await ContentDialogHelper.CreateInfoDialog(
|
||||||
@@ -1613,6 +1652,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
|
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
|
||||||
gameThread.Start();
|
gameThread.Start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SwitchToRenderer(bool startFullscreen) =>
|
public void SwitchToRenderer(bool startFullscreen) =>
|
||||||
@@ -1699,7 +1739,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
string titleId = AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper();
|
string titleId = AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper();
|
||||||
AmiiboWindow window = new(ShowAll, LastScannedAmiiboId, titleId);
|
AmiiboWindow window = new(ShowAll, LastScannedAmiiboId, titleId);
|
||||||
|
|
||||||
await window.ShowDialog(Window);
|
await StyleableAppWindow.ShowAsync(window);
|
||||||
|
|
||||||
if (window.IsScanned)
|
if (window.IsScanned)
|
||||||
{
|
{
|
||||||
@@ -1746,7 +1786,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
if (WindowState is not WindowState.Normal)
|
if (WindowState is not WindowState.Normal)
|
||||||
{
|
{
|
||||||
WindowState = WindowState.Normal;
|
WindowState = WindowState.Normal;
|
||||||
Window.TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowTitleBar;
|
Window.TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowOldUI;
|
||||||
|
|
||||||
if (IsGameRunning)
|
if (IsGameRunning)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using Gommon;
|
|||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Models;
|
using Ryujinx.Ava.UI.Models;
|
||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Systems.AppLibrary;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.ViewModels
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Avalonia.Collections;
|
using Avalonia.Collections;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
@@ -11,9 +12,9 @@ using Ryujinx.Ava.Common.Locale;
|
|||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Models.Input;
|
using Ryujinx.Ava.UI.Models.Input;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
using Ryujinx.Ava.Systems.Configuration.System;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
using Ryujinx.Ava.Systems.Configuration.UI;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
using Ryujinx.Common.Configuration.Multiplayer;
|
||||||
using Ryujinx.Common.GraphicsDriver;
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
@@ -27,6 +28,7 @@ using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -68,6 +70,19 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
public SettingsHacksViewModel DirtyHacks { get; }
|
public SettingsHacksViewModel DirtyHacks { get; }
|
||||||
|
|
||||||
|
private readonly bool _isGameRunning;
|
||||||
|
private Bitmap _gameIcon;
|
||||||
|
private string _gameTitle;
|
||||||
|
private string _gamePath;
|
||||||
|
private string _gameId;
|
||||||
|
public bool IsGameRunning => _isGameRunning;
|
||||||
|
public Bitmap GameIcon => _gameIcon;
|
||||||
|
public string GamePath => _gamePath;
|
||||||
|
public string GameTitle => _gameTitle;
|
||||||
|
public string GameId => _gameId;
|
||||||
|
public bool IsGameTitleNotNull => !string.IsNullOrEmpty(GameTitle);
|
||||||
|
public double PanelOpacity => IsGameTitleNotNull ? 0.5 : 1;
|
||||||
|
|
||||||
public int ResolutionScale
|
public int ResolutionScale
|
||||||
{
|
{
|
||||||
get => _resolutionScale;
|
get => _resolutionScale;
|
||||||
@@ -115,11 +130,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
|
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
|
||||||
|
|
||||||
public bool EnableDiscordIntegration { get; set; }
|
public bool EnableDiscordIntegration { get; set; }
|
||||||
public bool CheckUpdatesOnStart { get; set; }
|
|
||||||
public bool ShowConfirmExit { get; set; }
|
public bool ShowConfirmExit { get; set; }
|
||||||
public bool IgnoreApplet { get; set; }
|
public bool IgnoreApplet { get; set; }
|
||||||
public bool RememberWindowState { get; set; }
|
public bool RememberWindowState { get; set; }
|
||||||
public bool ShowTitleBar { get; set; }
|
public bool ShowOldUI { get; set; }
|
||||||
public int HideCursor { get; set; }
|
public int HideCursor { get; set; }
|
||||||
public int UpdateCheckerType { get; set; }
|
public int UpdateCheckerType { get; set; }
|
||||||
public bool EnableDockedMode { get; set; }
|
public bool EnableDockedMode { get; set; }
|
||||||
@@ -335,7 +349,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
public bool IsInvalidLdnPassphraseVisible { get; set; }
|
public bool IsInvalidLdnPassphraseVisible { get; set; }
|
||||||
|
|
||||||
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
|
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this(false)
|
||||||
{
|
{
|
||||||
_virtualFileSystem = virtualFileSystem;
|
_virtualFileSystem = virtualFileSystem;
|
||||||
_contentManager = contentManager;
|
_contentManager = contentManager;
|
||||||
@@ -348,7 +362,51 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsViewModel()
|
public SettingsViewModel(
|
||||||
|
VirtualFileSystem virtualFileSystem,
|
||||||
|
ContentManager contentManager,
|
||||||
|
bool gameRunning,
|
||||||
|
string gamePath,
|
||||||
|
string gameName,
|
||||||
|
string gameId,
|
||||||
|
byte[] gameIconData,
|
||||||
|
bool enableToLoadCustomConfig) : this(enableToLoadCustomConfig)
|
||||||
|
{
|
||||||
|
_virtualFileSystem = virtualFileSystem;
|
||||||
|
_contentManager = contentManager;
|
||||||
|
|
||||||
|
if (gameIconData != null && gameIconData.Length > 0)
|
||||||
|
{
|
||||||
|
using (var ms = new MemoryStream(gameIconData))
|
||||||
|
{
|
||||||
|
_gameIcon = new Bitmap(ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_isGameRunning = gameRunning;
|
||||||
|
_gamePath = gamePath;
|
||||||
|
_gameTitle = gameName;
|
||||||
|
_gameId = gameId;
|
||||||
|
|
||||||
|
if (enableToLoadCustomConfig) // During the game. If there is no user config, then load the global config window
|
||||||
|
{
|
||||||
|
string gameDir = Program.GetDirGameUserConfig(gameId, false, true);
|
||||||
|
if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat))
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadCurrentConfiguration(); // Needed to load custom configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Program.PreviewerDetached)
|
||||||
|
{
|
||||||
|
Task.Run(LoadTimeZones);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SettingsViewModel(bool noLoadGlobalConfig = false)
|
||||||
{
|
{
|
||||||
GameDirectories = [];
|
GameDirectories = [];
|
||||||
AutoloadDirectories = [];
|
AutoloadDirectories = [];
|
||||||
@@ -363,6 +421,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
if (Program.PreviewerDetached)
|
if (Program.PreviewerDetached)
|
||||||
{
|
{
|
||||||
Task.Run(LoadAvailableGpus);
|
Task.Run(LoadAvailableGpus);
|
||||||
|
|
||||||
|
// if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call
|
||||||
LoadCurrentConfiguration();
|
LoadCurrentConfiguration();
|
||||||
|
|
||||||
DirtyHacks = new SettingsHacksViewModel(this);
|
DirtyHacks = new SettingsHacksViewModel(this);
|
||||||
@@ -476,10 +536,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
// User Interface
|
// User Interface
|
||||||
EnableDiscordIntegration = config.EnableDiscordIntegration;
|
EnableDiscordIntegration = config.EnableDiscordIntegration;
|
||||||
CheckUpdatesOnStart = config.CheckUpdatesOnStart;
|
|
||||||
ShowConfirmExit = config.ShowConfirmExit;
|
ShowConfirmExit = config.ShowConfirmExit;
|
||||||
RememberWindowState = config.RememberWindowState;
|
RememberWindowState = config.RememberWindowState;
|
||||||
ShowTitleBar = config.ShowTitleBar;
|
ShowOldUI = config.ShowOldUI;
|
||||||
HideCursor = (int)config.HideCursor.Value;
|
HideCursor = (int)config.HideCursor.Value;
|
||||||
UpdateCheckerType = (int)config.UpdateCheckerType.Value;
|
UpdateCheckerType = (int)config.UpdateCheckerType.Value;
|
||||||
FocusLostActionType = (int)config.FocusLostActionType.Value;
|
FocusLostActionType = (int)config.FocusLostActionType.Value;
|
||||||
@@ -585,15 +644,14 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
// User Interface
|
// User Interface
|
||||||
config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
|
config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
|
||||||
config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
|
|
||||||
config.ShowConfirmExit.Value = ShowConfirmExit;
|
config.ShowConfirmExit.Value = ShowConfirmExit;
|
||||||
config.RememberWindowState.Value = RememberWindowState;
|
config.RememberWindowState.Value = RememberWindowState;
|
||||||
config.ShowTitleBar.Value = ShowTitleBar;
|
config.ShowOldUI.Value = ShowOldUI;
|
||||||
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
||||||
config.UpdateCheckerType.Value = (UpdaterType)UpdateCheckerType;
|
config.UpdateCheckerType.Value = (UpdaterType)UpdateCheckerType;
|
||||||
config.FocusLostActionType.Value = (FocusLostType)FocusLostActionType;
|
config.FocusLostActionType.Value = (FocusLostType)FocusLostActionType;
|
||||||
config.UI.GameDirs.Value = [..GameDirectories];
|
config.UI.GameDirs.Value = [.. GameDirectories];
|
||||||
config.UI.AutoloadDirs.Value = [..AutoloadDirectories];
|
config.UI.AutoloadDirs.Value = [.. AutoloadDirectories];
|
||||||
|
|
||||||
config.UI.BaseStyle.Value = BaseStyleIndex switch
|
config.UI.BaseStyle.Value = BaseStyleIndex switch
|
||||||
{
|
{
|
||||||
@@ -711,15 +769,39 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void RevertIfNotSaved()
|
private static void RevertIfNotSaved()
|
||||||
|
{
|
||||||
|
// maybe this is an unnecessary check(all options need to be tested)
|
||||||
|
if (string.IsNullOrEmpty(Program.GlobalConfigurationPath))
|
||||||
{
|
{
|
||||||
Program.ReloadConfig();
|
Program.ReloadConfig();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ApplyButton()
|
public void ApplyButton()
|
||||||
{
|
{
|
||||||
SaveSettings();
|
SaveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DeleteConfigGame()
|
||||||
|
{
|
||||||
|
string gameDir = Program.GetDirGameUserConfig(GameId,false,false);
|
||||||
|
|
||||||
|
if (File.Exists(gameDir))
|
||||||
|
{
|
||||||
|
File.Delete(gameDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
RevertIfNotSaved();
|
||||||
|
CloseWindow?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveUserConfig()
|
||||||
|
{
|
||||||
|
SaveSettings();
|
||||||
|
RevertIfNotSaved(); // Revert global configuration after saving user configuration
|
||||||
|
CloseWindow?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
public void OkButton()
|
public void OkButton()
|
||||||
{
|
{
|
||||||
SaveSettings();
|
SaveSettings();
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user