Merge branch 'GreemDev:master' into master

This commit is contained in:
Vladimir Sokolov 2024-11-30 11:01:14 +10:00 committed by GitHub
commit 3e3de18976
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
100 changed files with 1235 additions and 122 deletions

3
.gitignore vendored
View File

@ -175,3 +175,6 @@ PublishProfiles/
# Glade backup files # Glade backup files
*.glade~ *.glade~
# Ignore MacOS Attribute Files
._*

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -36,9 +36,9 @@ namespace ARMeilleure.Common
/// </summary> /// </summary>
/// <param name="address">Guest address</param> /// <param name="address">Guest address</param>
/// <returns>Value of the <see cref="AddressTableLevel"/> from the specified guest <paramref name="address"/></returns> /// <returns>Value of the <see cref="AddressTableLevel"/> from the specified guest <paramref name="address"/></returns>
public int GetValue(ulong address) public long GetValue(ulong address)
{ {
return (int)((address & Mask) >> Index); return (long)((address & Mask) >> Index);
} }
} }
} }

View File

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

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -4,6 +4,7 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -2,7 +2,7 @@ namespace Ryujinx.Common.Configuration.Hid
{ {
public class KeyboardHotkeys public class KeyboardHotkeys
{ {
public Key ToggleVsync { get; set; } public Key ToggleVSyncMode { get; set; }
public Key Screenshot { get; set; } public Key Screenshot { get; set; }
public Key ShowUI { get; set; } public Key ShowUI { get; set; }
public Key Pause { get; set; } public Key Pause { get; set; }
@ -11,5 +11,7 @@ namespace Ryujinx.Common.Configuration.Hid
public Key ResScaleDown { get; set; } public Key ResScaleDown { get; set; }
public Key VolumeUp { get; set; } public Key VolumeUp { get; set; }
public Key VolumeDown { get; set; } public Key VolumeDown { get; set; }
public Key CustomVSyncIntervalIncrement { get; set; }
public Key CustomVSyncIntervalDecrement { get; set; }
} }
} }

View File

@ -0,0 +1,9 @@
namespace Ryujinx.Common.Configuration
{
public enum VSyncMode
{
Switch,
Unbounded,
Custom
}
}

View File

@ -4,6 +4,7 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants> <DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -238,7 +238,7 @@ namespace ARMeilleure.Common
{ {
TEntry* page = GetPage(address); TEntry* page = GetPage(address);
int index = Levels[^1].GetValue(address); long index = Levels[^1].GetValue(address);
EnsureMapped((IntPtr)(page + index)); EnsureMapped((IntPtr)(page + index));

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.GAL
void SetSize(int width, int height); void SetSize(int width, int height);
void ChangeVSyncMode(bool vsyncEnabled); void ChangeVSyncMode(VSyncMode vSyncMode);
void SetAntiAliasing(AntiAliasing antialiasing); void SetAntiAliasing(AntiAliasing antialiasing);
void SetScalingFilter(ScalingFilter type); void SetScalingFilter(ScalingFilter type);

View File

@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_impl.Window.SetSize(width, height); _impl.Window.SetSize(width, height);
} }
public void ChangeVSyncMode(bool vsyncEnabled) { } public void ChangeVSyncMode(VSyncMode vSyncMode) { }
public void SetAntiAliasing(AntiAliasing effect) { } public void SetAntiAliasing(AntiAliasing effect) { }

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@ -0,0 +1,9 @@
namespace Ryujinx.Graphics.GAL
{
public enum VSyncMode
{
Switch,
Unbounded,
Custom
}
}

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.OpenGL
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
} }
public void ChangeVSyncMode(bool vsyncEnabled) { } public void ChangeVSyncMode(VSyncMode vSyncMode) { }
public void SetSize(int width, int height) public void SetSize(int width, int height)
{ {

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@ -182,6 +182,16 @@ namespace Ryujinx.Graphics.Vulkan
return false; return false;
} }
} }
//Prevent the sum of descriptors from exceeding MaxPushDescriptors
int totalDescriptors = 0;
foreach (ResourceDescriptor desc in layout.Sets.First().Descriptors)
{
if (!reserved.Contains(desc.Binding))
totalDescriptors += desc.Count;
}
if (totalDescriptors > gd.Capabilities.MaxPushDescriptors)
return false;
return true; return true;
} }

View File

@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Vulkan
private int _width; private int _width;
private int _height; private int _height;
private bool _vsyncEnabled; private VSyncMode _vSyncMode;
private bool _swapchainIsDirty; private bool _swapchainIsDirty;
private VkFormat _format; private VkFormat _format;
private AntiAliasing _currentAntiAliasing; private AntiAliasing _currentAntiAliasing;
@ -139,7 +139,7 @@ namespace Ryujinx.Graphics.Vulkan
ImageArrayLayers = 1, ImageArrayLayers = 1,
PreTransform = capabilities.CurrentTransform, PreTransform = capabilities.CurrentTransform,
CompositeAlpha = ChooseCompositeAlpha(capabilities.SupportedCompositeAlpha), CompositeAlpha = ChooseCompositeAlpha(capabilities.SupportedCompositeAlpha),
PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled), PresentMode = ChooseSwapPresentMode(presentModes, _vSyncMode),
Clipped = true, Clipped = true,
}; };
@ -279,9 +279,9 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes, bool vsyncEnabled) private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes, VSyncMode vSyncMode)
{ {
if (!vsyncEnabled && availablePresentModes.Contains(PresentModeKHR.ImmediateKhr)) if (vSyncMode == VSyncMode.Unbounded && availablePresentModes.Contains(PresentModeKHR.ImmediateKhr))
{ {
return PresentModeKHR.ImmediateKhr; return PresentModeKHR.ImmediateKhr;
} }
@ -634,9 +634,10 @@ namespace Ryujinx.Graphics.Vulkan
_swapchainIsDirty = true; _swapchainIsDirty = true;
} }
public override void ChangeVSyncMode(bool vsyncEnabled) public override void ChangeVSyncMode(VSyncMode vSyncMode)
{ {
_vsyncEnabled = vsyncEnabled; _vSyncMode = vSyncMode;
//present mode may change, so mark the swapchain for recreation
_swapchainIsDirty = true; _swapchainIsDirty = true;
} }

View File

@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Vulkan
public abstract void Dispose(); public abstract void Dispose();
public abstract void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback); public abstract void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback);
public abstract void SetSize(int width, int height); public abstract void SetSize(int width, int height);
public abstract void ChangeVSyncMode(bool vsyncEnabled); public abstract void ChangeVSyncMode(VSyncMode vSyncMode);
public abstract void SetAntiAliasing(AntiAliasing effect); public abstract void SetAntiAliasing(AntiAliasing effect);
public abstract void SetScalingFilter(ScalingFilter scalerType); public abstract void SetScalingFilter(ScalingFilter scalerType);
public abstract void SetScalingFilterLevel(float scale); public abstract void SetScalingFilterLevel(float scale);

View File

@ -6,6 +6,7 @@
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath> <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
<IsRoslynComponent>true</IsRoslynComponent> <IsRoslynComponent>true</IsRoslynComponent>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -21,6 +21,7 @@ using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using Path = System.IO.Path; using Path = System.IO.Path;
namespace Ryujinx.HLE.FileSystem namespace Ryujinx.HLE.FileSystem
@ -474,6 +475,74 @@ namespace Ryujinx.HLE.FileSystem
FinishInstallation(temporaryDirectory, registeredDirectory); FinishInstallation(temporaryDirectory, registeredDirectory);
} }
public void InstallKeys(string keysSource, string installDirectory)
{
if (Directory.Exists(keysSource))
{
foreach (var filePath in Directory.EnumerateFiles(keysSource, "*.keys"))
{
VerifyKeysFile(filePath);
File.Copy(filePath, Path.Combine(installDirectory, Path.GetFileName(filePath)), true);
}
return;
}
if (!File.Exists(keysSource))
{
throw new FileNotFoundException("Keys file does not exist.");
}
FileInfo info = new(keysSource);
using FileStream file = File.OpenRead(keysSource);
switch (info.Extension)
{
case ".zip":
using (ZipArchive archive = ZipFile.OpenRead(keysSource))
{
InstallKeysFromZip(archive, installDirectory);
}
break;
case ".keys":
VerifyKeysFile(keysSource);
File.Copy(keysSource, Path.Combine(installDirectory, info.Name), true);
break;
default:
throw new InvalidFirmwarePackageException("Input file is not a valid key package");
}
}
private void InstallKeysFromZip(ZipArchive archive, string installDirectory)
{
string temporaryDirectory = Path.Combine(installDirectory, "temp");
if (Directory.Exists(temporaryDirectory))
{
Directory.Delete(temporaryDirectory, true);
}
Directory.CreateDirectory(temporaryDirectory);
foreach (var entry in archive.Entries)
{
if (Path.GetExtension(entry.FullName).Equals(".keys", StringComparison.OrdinalIgnoreCase))
{
string extractDestination = Path.Combine(temporaryDirectory, entry.Name);
entry.ExtractToFile(extractDestination, overwrite: true);
try
{
VerifyKeysFile(extractDestination);
File.Move(extractDestination, Path.Combine(installDirectory, entry.Name), true);
}
catch (Exception)
{
Directory.Delete(temporaryDirectory, true);
throw;
}
}
}
Directory.Delete(temporaryDirectory, true);
}
private void FinishInstallation(string temporaryDirectory, string registeredDirectory) private void FinishInstallation(string temporaryDirectory, string registeredDirectory)
{ {
if (Directory.Exists(registeredDirectory)) if (Directory.Exists(registeredDirectory))
@ -947,5 +1016,70 @@ namespace Ryujinx.HLE.FileSystem
return null; return null;
} }
public void VerifyKeysFile(string filePath)
{
// Verify the keys file format refers to https://github.com/Thealexbarney/LibHac/blob/master/KEYS.md
string genericPattern = @"^[a-z0-9_]+ = [a-z0-9]+$";
string titlePattern = @"^[a-z0-9]{32} = [a-z0-9]{32}$";
if (File.Exists(filePath))
{
// Read all lines from the file
string fileName = Path.GetFileName(filePath);
string[] lines = File.ReadAllLines(filePath);
bool verified = false;
switch (fileName)
{
case "prod.keys":
verified = verifyKeys(lines, genericPattern);
break;
case "title.keys":
verified = verifyKeys(lines, titlePattern);
break;
case "console.keys":
verified = verifyKeys(lines, genericPattern);
break;
case "dev.keys":
verified = verifyKeys(lines, genericPattern);
break;
default:
throw new FormatException($"Keys file name \"{fileName}\" not supported. Only \"prod.keys\", \"title.keys\", \"console.keys\", \"dev.keys\" are supported.");
}
if (!verified)
{
throw new FormatException($"Invalid \"{filePath}\" file format.");
}
} else
{
throw new FileNotFoundException($"Keys file not found at \"{filePath}\".");
}
}
private bool verifyKeys(string[] lines, string regex)
{
foreach (string line in lines)
{
if (!Regex.IsMatch(line, regex))
{
return false;
}
}
return true;
}
public bool AreKeysAlredyPresent(string pathToCheck)
{
string[] fileNames = { "prod.keys", "title.keys", "console.keys", "dev.keys" };
foreach (var file in fileNames)
{
if (File.Exists(Path.Combine(pathToCheck, file)))
{
return true;
}
}
return false;
}
} }
} }

View File

@ -223,9 +223,10 @@ namespace Ryujinx.HLE.FileSystem
{ {
KeySet ??= KeySet.CreateDefaultKeySet(); KeySet ??= KeySet.CreateDefaultKeySet();
string keyFile = null; string prodKeyFile = null;
string titleKeyFile = null; string titleKeyFile = null;
string consoleKeyFile = null; string consoleKeyFile = null;
string devKeyFile = null;
if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile) if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile)
{ {
@ -236,13 +237,14 @@ namespace Ryujinx.HLE.FileSystem
void LoadSetAtPath(string basePath) void LoadSetAtPath(string basePath)
{ {
string localKeyFile = Path.Combine(basePath, "prod.keys"); string localProdKeyFile = Path.Combine(basePath, "prod.keys");
string localTitleKeyFile = Path.Combine(basePath, "title.keys"); string localTitleKeyFile = Path.Combine(basePath, "title.keys");
string localConsoleKeyFile = Path.Combine(basePath, "console.keys"); string localConsoleKeyFile = Path.Combine(basePath, "console.keys");
string localDevKeyFile = Path.Combine(basePath, "dev.keys");
if (File.Exists(localKeyFile)) if (File.Exists(localProdKeyFile))
{ {
keyFile = localKeyFile; prodKeyFile = localProdKeyFile;
} }
if (File.Exists(localTitleKeyFile)) if (File.Exists(localTitleKeyFile))
@ -254,9 +256,14 @@ namespace Ryujinx.HLE.FileSystem
{ {
consoleKeyFile = localConsoleKeyFile; consoleKeyFile = localConsoleKeyFile;
} }
if (File.Exists(localDevKeyFile))
{
devKeyFile = localDevKeyFile;
}
} }
ExternalKeyReader.ReadKeyFile(KeySet, keyFile, titleKeyFile, consoleKeyFile, null); ExternalKeyReader.ReadKeyFile(KeySet, prodKeyFile, devKeyFile, titleKeyFile, consoleKeyFile, null);
} }
public void ImportTickets(IFileSystem fs) public void ImportTickets(IFileSystem fs)

View File

@ -9,6 +9,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.UI; using Ryujinx.HLE.UI;
using System; using System;
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
namespace Ryujinx.HLE namespace Ryujinx.HLE
{ {
@ -84,9 +85,14 @@ namespace Ryujinx.HLE
internal readonly RegionCode Region; internal readonly RegionCode Region;
/// <summary> /// <summary>
/// Control the initial state of the vertical sync in the SurfaceFlinger service. /// Control the initial state of the present interval in the SurfaceFlinger service (previously Vsync).
/// </summary> /// </summary>
internal readonly bool EnableVsync; internal readonly VSyncMode VSyncMode;
/// <summary>
/// Control the custom VSync interval, if enabled and active.
/// </summary>
internal readonly int CustomVSyncInterval;
/// <summary> /// <summary>
/// Control the initial state of the docked mode. /// Control the initial state of the docked mode.
@ -195,7 +201,7 @@ namespace Ryujinx.HLE
IHostUIHandler hostUIHandler, IHostUIHandler hostUIHandler,
SystemLanguage systemLanguage, SystemLanguage systemLanguage,
RegionCode region, RegionCode region,
bool enableVsync, VSyncMode vSyncMode,
bool enableDockedMode, bool enableDockedMode,
bool enablePtc, bool enablePtc,
bool enableInternetAccess, bool enableInternetAccess,
@ -212,7 +218,8 @@ namespace Ryujinx.HLE
MultiplayerMode multiplayerMode, MultiplayerMode multiplayerMode,
bool multiplayerDisableP2p, bool multiplayerDisableP2p,
string multiplayerLdnPassphrase, string multiplayerLdnPassphrase,
string multiplayerLdnServer) string multiplayerLdnServer,
int customVSyncInterval)
{ {
VirtualFileSystem = virtualFileSystem; VirtualFileSystem = virtualFileSystem;
LibHacHorizonManager = libHacHorizonManager; LibHacHorizonManager = libHacHorizonManager;
@ -225,7 +232,8 @@ namespace Ryujinx.HLE
HostUIHandler = hostUIHandler; HostUIHandler = hostUIHandler;
SystemLanguage = systemLanguage; SystemLanguage = systemLanguage;
Region = region; Region = region;
EnableVsync = enableVsync; VSyncMode = vSyncMode;
CustomVSyncInterval = customVSyncInterval;
EnableDockedMode = enableDockedMode; EnableDockedMode = enableDockedMode;
EnablePtc = enablePtc; EnablePtc = enablePtc;
EnableInternetAccess = enableInternetAccess; EnableInternetAccess = enableInternetAccess;

View File

@ -10,13 +10,12 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{ {
class SurfaceFlinger : IConsumerListener, IDisposable class SurfaceFlinger : IConsumerListener, IDisposable
{ {
private const int TargetFps = 60;
private readonly Switch _device; private readonly Switch _device;
private readonly Dictionary<long, Layer> _layers; private readonly Dictionary<long, Layer> _layers;
@ -32,6 +31,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private readonly long _spinTicks; private readonly long _spinTicks;
private readonly long _1msTicks; private readonly long _1msTicks;
private VSyncMode _vSyncMode;
private long _targetVSyncInterval;
private int _swapInterval; private int _swapInterval;
private int _swapIntervalDelay; private int _swapIntervalDelay;
@ -88,7 +90,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
} }
else else
{ {
_ticksPerFrame = Stopwatch.Frequency / TargetFps; _ticksPerFrame = Stopwatch.Frequency / _device.TargetVSyncInterval;
_targetVSyncInterval = _device.TargetVSyncInterval;
} }
} }
@ -370,15 +373,20 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
if (acquireStatus == Status.Success) if (acquireStatus == Status.Success)
{ {
// If device vsync is disabled, reflect the change. if (_device.VSyncMode == VSyncMode.Unbounded)
if (!_device.EnableDeviceVsync)
{ {
if (_swapInterval != 0) if (_swapInterval != 0)
{ {
UpdateSwapInterval(0); UpdateSwapInterval(0);
_vSyncMode = _device.VSyncMode;
} }
} }
else if (item.SwapInterval != _swapInterval) else if (_device.VSyncMode != _vSyncMode)
{
UpdateSwapInterval(_device.VSyncMode == VSyncMode.Unbounded ? 0 : item.SwapInterval);
_vSyncMode = _device.VSyncMode;
}
else if (item.SwapInterval != _swapInterval || _device.TargetVSyncInterval != _targetVSyncInterval)
{ {
UpdateSwapInterval(item.SwapInterval); UpdateSwapInterval(item.SwapInterval);
} }

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -27,7 +27,11 @@ namespace Ryujinx.HLE
public TamperMachine TamperMachine { get; } public TamperMachine TamperMachine { get; }
public IHostUIHandler UIHandler { get; } public IHostUIHandler UIHandler { get; }
public bool EnableDeviceVsync { get; set; } public VSyncMode VSyncMode { get; set; } = VSyncMode.Switch;
public bool CustomVSyncIntervalEnabled { get; set; } = false;
public int CustomVSyncInterval { get; set; }
public long TargetVSyncInterval { get; set; } = 60;
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable; public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
@ -59,12 +63,14 @@ namespace Ryujinx.HLE
System.State.SetLanguage(Configuration.SystemLanguage); System.State.SetLanguage(Configuration.SystemLanguage);
System.State.SetRegion(Configuration.Region); System.State.SetRegion(Configuration.Region);
EnableDeviceVsync = Configuration.EnableVsync; VSyncMode = Configuration.VSyncMode;
CustomVSyncInterval = Configuration.CustomVSyncInterval;
System.State.DockedMode = Configuration.EnableDockedMode; System.State.DockedMode = Configuration.EnableDockedMode;
System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default; System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default;
System.EnablePtc = Configuration.EnablePtc; System.EnablePtc = Configuration.EnablePtc;
System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel; System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel;
System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode; System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode;
UpdateVSyncInterval();
#pragma warning restore IDE0055 #pragma warning restore IDE0055
} }
@ -75,6 +81,34 @@ namespace Ryujinx.HLE
Gpu.GPFifo.DispatchCalls(); Gpu.GPFifo.DispatchCalls();
} }
public void IncrementCustomVSyncInterval()
{
CustomVSyncInterval += 1;
UpdateVSyncInterval();
}
public void DecrementCustomVSyncInterval()
{
CustomVSyncInterval -= 1;
UpdateVSyncInterval();
}
public void UpdateVSyncInterval()
{
switch (VSyncMode)
{
case VSyncMode.Custom:
TargetVSyncInterval = CustomVSyncInterval;
break;
case VSyncMode.Switch:
TargetVSyncInterval = 60;
break;
case VSyncMode.Unbounded:
TargetVSyncInterval = 1;
break;
}
}
public bool LoadCart(string exeFsDir, string romFsFile = null) => Processes.LoadUnpackedNca(exeFsDir, romFsFile); public bool LoadCart(string exeFsDir, string romFsFile = null) => Processes.LoadUnpackedNca(exeFsDir, romFsFile);
public bool LoadXci(string xciFile, ulong applicationId = 0) => Processes.LoadXci(xciFile, applicationId); public bool LoadXci(string xciFile, ulong applicationId = 0) => Processes.LoadXci(xciFile, applicationId);
public bool LoadNca(string ncaFile) => Processes.LoadNca(ncaFile); public bool LoadNca(string ncaFile) => Processes.LoadNca(ncaFile);

View File

@ -115,8 +115,11 @@ namespace Ryujinx.Headless.SDL2
[Option("fs-global-access-log-mode", Required = false, Default = 0, HelpText = "Enables FS access log output to the console.")] [Option("fs-global-access-log-mode", Required = false, Default = 0, HelpText = "Enables FS access log output to the console.")]
public int FsGlobalAccessLogMode { get; set; } public int FsGlobalAccessLogMode { get; set; }
[Option("disable-vsync", Required = false, HelpText = "Disables Vertical Sync.")] [Option("vsync-mode", Required = false, Default = VSyncMode.Switch, HelpText = "Sets the emulated VSync mode (Switch, Unbounded, or Custom).")]
public bool DisableVSync { get; set; } public VSyncMode VSyncMode { get; set; }
[Option("custom-refresh-rate", Required = false, Default = 90, HelpText = "Sets the custom refresh rate target value (integer).")]
public int CustomVSyncInterval { get; set; }
[Option("disable-shader-cache", Required = false, HelpText = "Disables Shader cache.")] [Option("disable-shader-cache", Required = false, HelpText = "Disables Shader cache.")]
public bool DisableShaderCache { get; set; } public bool DisableShaderCache { get; set; }

View File

@ -563,7 +563,7 @@ namespace Ryujinx.Headless.SDL2
window, window,
options.SystemLanguage, options.SystemLanguage,
options.SystemRegion, options.SystemRegion,
!options.DisableVSync, options.VSyncMode,
!options.DisableDockedMode, !options.DisableDockedMode,
!options.DisablePTC, !options.DisablePTC,
options.EnableInternetAccess, options.EnableInternetAccess,
@ -580,7 +580,8 @@ namespace Ryujinx.Headless.SDL2
Common.Configuration.Multiplayer.MultiplayerMode.Disabled, Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
false, false,
"", "",
""); "",
options.CustomVSyncInterval);
return new Switch(configuration); return new Switch(configuration);
} }

View File

@ -9,6 +9,7 @@
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants> <DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
<SigningCertificate Condition=" '$(SigningCertificate)' == '' ">-</SigningCertificate> <SigningCertificate Condition=" '$(SigningCertificate)' == '' ">-</SigningCertificate>
<TieredPGO>true</TieredPGO> <TieredPGO>true</TieredPGO>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Headless.SDL2 namespace Ryujinx.Headless.SDL2
{ {
class StatusUpdatedEventArgs( class StatusUpdatedEventArgs(
bool vSyncEnabled, string vSyncMode,
string dockedMode, string dockedMode,
string aspectRatio, string aspectRatio,
string gameStatus, string gameStatus,
@ -11,7 +11,7 @@ namespace Ryujinx.Headless.SDL2
string gpuName) string gpuName)
: EventArgs : EventArgs
{ {
public bool VSyncEnabled = vSyncEnabled; public string VSyncMode = vSyncMode;
public string DockedMode = dockedMode; public string DockedMode = dockedMode;
public string AspectRatio = aspectRatio; public string AspectRatio = aspectRatio;
public string GameStatus = gameStatus; public string GameStatus = gameStatus;

View File

@ -314,7 +314,7 @@ namespace Ryujinx.Headless.SDL2
} }
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs( StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
Device.EnableDeviceVsync, Device.VSyncMode.ToString(),
dockedMode, dockedMode,
Device.Configuration.AspectRatio.ToText(), Device.Configuration.AspectRatio.ToText(),
$"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)", $"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -4,6 +4,7 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -4,6 +4,7 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View File

@ -10,6 +10,7 @@
<TargetOS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">linux</TargetOS> <TargetOS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">linux</TargetOS>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<RunSettingsFilePath>$(MSBuildProjectDirectory)\.runsettings</RunSettingsFilePath> <RunSettingsFilePath>$(MSBuildProjectDirectory)\.runsettings</RunSettingsFilePath>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View File

@ -1,3 +1,4 @@
using Ryujinx.Common;
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;
@ -16,7 +17,7 @@ namespace Ryujinx.UI.Common.Configuration
/// <summary> /// <summary>
/// The current version of the file format /// The current version of the file format
/// </summary> /// </summary>
public const int CurrentVersion = 56; public const int CurrentVersion = 57;
/// <summary> /// <summary>
/// Version of the configuration file format /// Version of the configuration file format
@ -191,8 +192,25 @@ namespace Ryujinx.UI.Common.Configuration
/// <summary> /// <summary>
/// Enables or disables Vertical Sync /// Enables or disables Vertical Sync
/// </summary> /// </summary>
/// <remarks>Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions)</remarks>
/// TODO: Remove this when those older versions aren't in use anymore.
public bool EnableVsync { get; set; } public bool EnableVsync { get; set; }
/// <summary>
/// Current VSync mode; 60 (Switch), unbounded ("Vsync off"), or custom
/// </summary>
public VSyncMode VSyncMode { get; set; }
/// <summary>
/// Enables or disables the custom present interval
/// </summary>
public bool EnableCustomVSyncInterval { get; set; }
/// <summary>
/// The custom present interval value
/// </summary>
public int CustomVSyncInterval { get; set; }
/// <summary> /// <summary>
/// Enables or disables Shader cache /// Enables or disables Shader cache
/// </summary> /// </summary>

View File

@ -82,7 +82,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVsync = Key.F1, ToggleVSyncMode = Key.F1,
}; };
configurationFileUpdated = true; configurationFileUpdated = true;
@ -276,7 +276,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVsync = Key.F1, ToggleVSyncMode = Key.F1,
Screenshot = Key.F8, Screenshot = Key.F8,
}; };
@ -289,7 +289,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVsync = Key.F1, ToggleVSyncMode = Key.F1,
Screenshot = Key.F8, Screenshot = Key.F8,
ShowUI = Key.F4, ShowUI = Key.F4,
}; };
@ -332,7 +332,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync, ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = configurationFileFormat.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI, ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = Key.F5, Pause = Key.F5,
@ -347,7 +347,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync, ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = configurationFileFormat.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI, ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause, Pause = configurationFileFormat.Hotkeys.Pause,
@ -421,7 +421,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync, ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = configurationFileFormat.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI, ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause, Pause = configurationFileFormat.Hotkeys.Pause,
@ -448,7 +448,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync, ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = configurationFileFormat.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI, ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause, Pause = configurationFileFormat.Hotkeys.Pause,
@ -611,6 +611,33 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileUpdated = true; configurationFileUpdated = true;
} }
if (configurationFileFormat.Version < 57)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 57.");
configurationFileFormat.VSyncMode = VSyncMode.Switch;
configurationFileFormat.EnableCustomVSyncInterval = false;
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = Key.F1,
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
VolumeUp = configurationFileFormat.Hotkeys.VolumeUp,
VolumeDown = configurationFileFormat.Hotkeys.VolumeDown,
CustomVSyncIntervalIncrement = Key.Unbound,
CustomVSyncIntervalDecrement = Key.Unbound,
};
configurationFileFormat.CustomVSyncInterval = 120;
configurationFileUpdated = true;
}
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.ResScale.Value = configurationFileFormat.ResScale; Graphics.ResScale.Value = configurationFileFormat.ResScale;
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
@ -646,7 +673,9 @@ namespace Ryujinx.UI.Common.Configuration
ShowTitleBar.Value = configurationFileFormat.ShowTitleBar; ShowTitleBar.Value = configurationFileFormat.ShowTitleBar;
EnableHardwareAcceleration.Value = configurationFileFormat.EnableHardwareAcceleration; EnableHardwareAcceleration.Value = configurationFileFormat.EnableHardwareAcceleration;
HideCursor.Value = configurationFileFormat.HideCursor; HideCursor.Value = configurationFileFormat.HideCursor;
Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync; Graphics.VSyncMode.Value = configurationFileFormat.VSyncMode;
Graphics.EnableCustomVSyncInterval.Value = configurationFileFormat.EnableCustomVSyncInterval;
Graphics.CustomVSyncInterval.Value = configurationFileFormat.CustomVSyncInterval;
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression; Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE; Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE;

View File

@ -1,4 +1,4 @@
using ARMeilleure; using ARMeilleure;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
@ -474,9 +474,19 @@ namespace Ryujinx.UI.Common.Configuration
public ReactiveObject<string> ShadersDumpPath { get; private set; } public ReactiveObject<string> ShadersDumpPath { get; private set; }
/// <summary> /// <summary>
/// Enables or disables Vertical Sync /// Toggles the present interval mode. Options are Switch (60Hz), Unbounded (previously Vsync off), and Custom, if enabled.
/// </summary> /// </summary>
public ReactiveObject<bool> EnableVsync { get; private set; } public ReactiveObject<VSyncMode> VSyncMode { get; private set; }
/// <summary>
/// Enables or disables the custom present interval mode.
/// </summary>
public ReactiveObject<bool> EnableCustomVSyncInterval { get; private set; }
/// <summary>
/// Changes the custom present interval.
/// </summary>
public ReactiveObject<int> CustomVSyncInterval { get; private set; }
/// <summary> /// <summary>
/// Enables or disables Shader cache /// Enables or disables Shader cache
@ -536,8 +546,12 @@ namespace Ryujinx.UI.Common.Configuration
AspectRatio = new ReactiveObject<AspectRatio>(); AspectRatio = new ReactiveObject<AspectRatio>();
AspectRatio.LogChangesToValue(nameof(AspectRatio)); AspectRatio.LogChangesToValue(nameof(AspectRatio));
ShadersDumpPath = new ReactiveObject<string>(); ShadersDumpPath = new ReactiveObject<string>();
EnableVsync = new ReactiveObject<bool>(); VSyncMode = new ReactiveObject<VSyncMode>();
EnableVsync.LogChangesToValue(nameof(EnableVsync)); VSyncMode.LogChangesToValue(nameof(VSyncMode));
EnableCustomVSyncInterval = new ReactiveObject<bool>();
EnableCustomVSyncInterval.LogChangesToValue(nameof(EnableCustomVSyncInterval));
CustomVSyncInterval = new ReactiveObject<int>();
CustomVSyncInterval.LogChangesToValue(nameof(CustomVSyncInterval));
EnableShaderCache = new ReactiveObject<bool>(); EnableShaderCache = new ReactiveObject<bool>();
EnableShaderCache.LogChangesToValue(nameof(EnableShaderCache)); EnableShaderCache.LogChangesToValue(nameof(EnableShaderCache));
EnableTextureRecompression = new ReactiveObject<bool>(); EnableTextureRecompression = new ReactiveObject<bool>();

View File

@ -64,7 +64,9 @@ namespace Ryujinx.UI.Common.Configuration
ShowTitleBar = ShowTitleBar, ShowTitleBar = ShowTitleBar,
EnableHardwareAcceleration = EnableHardwareAcceleration, EnableHardwareAcceleration = EnableHardwareAcceleration,
HideCursor = HideCursor, HideCursor = HideCursor,
EnableVsync = Graphics.EnableVsync, VSyncMode = Graphics.VSyncMode,
EnableCustomVSyncInterval = Graphics.EnableCustomVSyncInterval,
CustomVSyncInterval = Graphics.CustomVSyncInterval,
EnableShaderCache = Graphics.EnableShaderCache, EnableShaderCache = Graphics.EnableShaderCache,
EnableTextureRecompression = Graphics.EnableTextureRecompression, EnableTextureRecompression = Graphics.EnableTextureRecompression,
EnableMacroHLE = Graphics.EnableMacroHLE, EnableMacroHLE = Graphics.EnableMacroHLE,
@ -179,7 +181,9 @@ namespace Ryujinx.UI.Common.Configuration
ShowTitleBar.Value = !OperatingSystem.IsWindows(); ShowTitleBar.Value = !OperatingSystem.IsWindows();
EnableHardwareAcceleration.Value = true; EnableHardwareAcceleration.Value = true;
HideCursor.Value = HideCursorMode.OnIdle; HideCursor.Value = HideCursorMode.OnIdle;
Graphics.EnableVsync.Value = true; Graphics.VSyncMode.Value = VSyncMode.Switch;
Graphics.CustomVSyncInterval.Value = 120;
Graphics.EnableCustomVSyncInterval.Value = false;
Graphics.EnableShaderCache.Value = true; Graphics.EnableShaderCache.Value = true;
Graphics.EnableTextureRecompression.Value = false; Graphics.EnableTextureRecompression.Value = false;
Graphics.EnableMacroHLE.Value = true; Graphics.EnableMacroHLE.Value = true;
@ -240,7 +244,7 @@ namespace Ryujinx.UI.Common.Configuration
Hid.EnableMouse.Value = false; Hid.EnableMouse.Value = false;
Hid.Hotkeys.Value = new KeyboardHotkeys Hid.Hotkeys.Value = new KeyboardHotkeys
{ {
ToggleVsync = Key.F1, ToggleVSyncMode = Key.F1,
ToggleMute = Key.F2, ToggleMute = Key.F2,
Screenshot = Key.F8, Screenshot = Key.F8,
ShowUI = Key.F4, ShowUI = Key.F4,

View File

@ -247,6 +247,7 @@ namespace Ryujinx.UI.Common
"0100dbf01000a000", // Burnout Paradise Remastered "0100dbf01000a000", // Burnout Paradise Remastered
"0100744001588000", // Cars 3: Driven to Win "0100744001588000", // Cars 3: Driven to Win
"0100b41013c82000", // Cruis'n Blast "0100b41013c82000", // Cruis'n Blast
"01001b300b9be000", // Diablo III: Eternal Collection
"01008c8012920000", // Dying Light Platinum Edition "01008c8012920000", // Dying Light Platinum Edition
"010073c01af34000", // LEGO Horizon Adventures "010073c01af34000", // LEGO Horizon Adventures
"0100770008dd8000", // Monster Hunter Generations Ultimate "0100770008dd8000", // Monster Hunter Generations Ultimate

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -5,6 +5,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -57,6 +57,8 @@ using Key = Ryujinx.Input.Key;
using MouseButton = Ryujinx.Input.MouseButton; using MouseButton = Ryujinx.Input.MouseButton;
using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter; using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter;
using Size = Avalonia.Size; using Size = Avalonia.Size;
using Switch = Ryujinx.HLE.Switch;
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
namespace Ryujinx.Ava namespace Ryujinx.Ava
{ {
@ -203,6 +205,9 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter; ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter;
ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel; ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel;
ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Event += UpdateColorSpacePassthrough; ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Event += UpdateColorSpacePassthrough;
ConfigurationState.Instance.Graphics.VSyncMode.Event += UpdateVSyncMode;
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Event += UpdateCustomVSyncIntervalValue;
ConfigurationState.Instance.Graphics.EnableCustomVSyncInterval.Event += UpdateCustomVSyncIntervalEnabled;
ConfigurationState.Instance.System.EnableInternetAccess.Event += UpdateEnableInternetAccessState; ConfigurationState.Instance.System.EnableInternetAccess.Event += UpdateEnableInternetAccessState;
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState; ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState;
@ -295,6 +300,66 @@ namespace Ryujinx.Ava
_renderer.Window?.SetColorSpacePassthrough((bool)ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Value); _renderer.Window?.SetColorSpacePassthrough((bool)ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Value);
} }
public void UpdateVSyncMode(object sender, ReactiveEventArgs<VSyncMode> e)
{
if (Device != null)
{
Device.VSyncMode = e.NewValue;
Device.UpdateVSyncInterval();
}
_renderer.Window?.ChangeVSyncMode((Ryujinx.Graphics.GAL.VSyncMode)e.NewValue);
_viewModel.ShowCustomVSyncIntervalPicker = (e.NewValue == VSyncMode.Custom);
}
public void VSyncModeToggle()
{
VSyncMode oldVSyncMode = Device.VSyncMode;
VSyncMode newVSyncMode = VSyncMode.Switch;
bool customVSyncIntervalEnabled = ConfigurationState.Instance.Graphics.EnableCustomVSyncInterval.Value;
switch (oldVSyncMode)
{
case VSyncMode.Switch:
newVSyncMode = VSyncMode.Unbounded;
break;
case VSyncMode.Unbounded:
if (customVSyncIntervalEnabled)
{
newVSyncMode = VSyncMode.Custom;
}
else
{
newVSyncMode = VSyncMode.Switch;
}
break;
case VSyncMode.Custom:
newVSyncMode = VSyncMode.Switch;
break;
}
UpdateVSyncMode(this, new ReactiveEventArgs<VSyncMode>(oldVSyncMode, newVSyncMode));
}
private void UpdateCustomVSyncIntervalValue(object sender, ReactiveEventArgs<int> e)
{
if (Device != null)
{
Device.TargetVSyncInterval = e.NewValue;
Device.UpdateVSyncInterval();
}
}
private void UpdateCustomVSyncIntervalEnabled(object sender, ReactiveEventArgs<bool> e)
{
if (Device != null)
{
Device.CustomVSyncIntervalEnabled = e.NewValue;
Device.UpdateVSyncInterval();
}
}
private void ShowCursor() private void ShowCursor()
{ {
Dispatcher.UIThread.Post(() => Dispatcher.UIThread.Post(() =>
@ -505,12 +570,6 @@ namespace Ryujinx.Ava
Device.Configuration.MultiplayerDisableP2p = e.NewValue; Device.Configuration.MultiplayerDisableP2p = e.NewValue;
} }
public void ToggleVSync()
{
Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
_renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
}
public void Stop() public void Stop()
{ {
_isActive = false; _isActive = false;
@ -864,7 +923,7 @@ namespace Ryujinx.Ava
_viewModel.UiHandler, _viewModel.UiHandler,
(SystemLanguage)ConfigurationState.Instance.System.Language.Value, (SystemLanguage)ConfigurationState.Instance.System.Language.Value,
(RegionCode)ConfigurationState.Instance.System.Region.Value, (RegionCode)ConfigurationState.Instance.System.Region.Value,
ConfigurationState.Instance.Graphics.EnableVsync, ConfigurationState.Instance.Graphics.VSyncMode,
ConfigurationState.Instance.System.EnableDockedMode, ConfigurationState.Instance.System.EnableDockedMode,
ConfigurationState.Instance.System.EnablePtc, ConfigurationState.Instance.System.EnablePtc,
ConfigurationState.Instance.System.EnableInternetAccess, ConfigurationState.Instance.System.EnableInternetAccess,
@ -881,7 +940,8 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.Multiplayer.Mode, ConfigurationState.Instance.Multiplayer.Mode,
ConfigurationState.Instance.Multiplayer.DisableP2p, ConfigurationState.Instance.Multiplayer.DisableP2p,
ConfigurationState.Instance.Multiplayer.LdnPassphrase, ConfigurationState.Instance.Multiplayer.LdnPassphrase,
ConfigurationState.Instance.Multiplayer.LdnServer)); ConfigurationState.Instance.Multiplayer.LdnServer,
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value));
} }
private static IHardwareDeviceDriver InitializeAudio() private static IHardwareDeviceDriver InitializeAudio()
@ -1002,7 +1062,7 @@ namespace Ryujinx.Ava
Device.Gpu.SetGpuThread(); Device.Gpu.SetGpuThread();
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token); Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
_renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync); _renderer.Window.ChangeVSyncMode((Ryujinx.Graphics.GAL.VSyncMode)Device.VSyncMode);
while (_isActive) while (_isActive)
{ {
@ -1063,6 +1123,7 @@ namespace Ryujinx.Ava
{ {
// Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued. // Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued.
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance[LocaleKeys.Docked] : LocaleManager.Instance[LocaleKeys.Handheld]; string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance[LocaleKeys.Docked] : LocaleManager.Instance[LocaleKeys.Handheld];
string vSyncMode = Device.VSyncMode.ToString();
UpdateShaderCount(); UpdateShaderCount();
@ -1072,7 +1133,7 @@ namespace Ryujinx.Ava
} }
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs( StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
Device.EnableDeviceVsync, vSyncMode,
LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%", LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%",
dockedMode, dockedMode,
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
@ -1175,8 +1236,16 @@ namespace Ryujinx.Ava
{ {
switch (currentHotkeyState) switch (currentHotkeyState)
{ {
case KeyboardHotkeyState.ToggleVSync: case KeyboardHotkeyState.ToggleVSyncMode:
ToggleVSync(); VSyncModeToggle();
break;
case KeyboardHotkeyState.CustomVSyncIntervalDecrement:
Device.DecrementCustomVSyncInterval();
_viewModel.CustomVSyncInterval -= 1;
break;
case KeyboardHotkeyState.CustomVSyncIntervalIncrement:
Device.IncrementCustomVSyncInterval();
_viewModel.CustomVSyncInterval += 1;
break; break;
case KeyboardHotkeyState.Screenshot: case KeyboardHotkeyState.Screenshot:
ScreenshotRequested = true; ScreenshotRequested = true;
@ -1263,9 +1332,9 @@ namespace Ryujinx.Ava
{ {
KeyboardHotkeyState state = KeyboardHotkeyState.None; KeyboardHotkeyState state = KeyboardHotkeyState.None;
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleVsync)) if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleVSyncMode))
{ {
state = KeyboardHotkeyState.ToggleVSync; state = KeyboardHotkeyState.ToggleVSyncMode;
} }
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot)) else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot))
{ {
@ -1299,6 +1368,14 @@ namespace Ryujinx.Ava
{ {
state = KeyboardHotkeyState.VolumeDown; state = KeyboardHotkeyState.VolumeDown;
} }
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.CustomVSyncIntervalIncrement))
{
state = KeyboardHotkeyState.CustomVSyncIntervalIncrement;
}
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.CustomVSyncIntervalDecrement))
{
state = KeyboardHotkeyState.CustomVSyncIntervalDecrement;
}
return state; return state;
} }

View File

@ -1,6 +1,7 @@
{ {
"Language": "اَلْعَرَبِيَّةُ", "Language": "اَلْعَرَبِيَّةُ",
"MenuBarFileOpenApplet": "فتح التطبيق المصغر", "MenuBarFileOpenApplet": "فتح التطبيق المصغر",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "‫افتح تطبيق تحرير Mii في الوضع المستقل", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "‫افتح تطبيق تحرير Mii في الوضع المستقل",
"SettingsTabInputDirectMouseAccess": "الوصول المباشر للفأرة", "SettingsTabInputDirectMouseAccess": "الوصول المباشر للفأرة",
"SettingsTabSystemMemoryManagerMode": "وضع إدارة الذاكرة:", "SettingsTabSystemMemoryManagerMode": "وضع إدارة الذاكرة:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "تثبيت البرنامج الثابت", "MenuBarToolsInstallFirmware": "تثبيت البرنامج الثابت",
"MenuBarFileToolsInstallFirmwareFromFile": "تثبيت برنامج ثابت من XCI أو ZIP", "MenuBarFileToolsInstallFirmwareFromFile": "تثبيت برنامج ثابت من XCI أو ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "تثبيت برنامج ثابت من مجلد", "MenuBarFileToolsInstallFirmwareFromDirectory": "تثبيت برنامج ثابت من مجلد",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "إدارة أنواع الملفات", "MenuBarToolsManageFileTypes": "إدارة أنواع الملفات",
"MenuBarToolsInstallFileTypes": "تثبيت أنواع الملفات", "MenuBarToolsInstallFileTypes": "تثبيت أنواع الملفات",
"MenuBarToolsUninstallFileTypes": "إزالة أنواع الملفات", "MenuBarToolsUninstallFileTypes": "إزالة أنواع الملفات",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\nهل تريد المتابعة؟", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\nهل تريد المتابعة؟",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "تثبيت البرنامج الثابت...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "تثبيت البرنامج الثابت...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "تم تثبيت إصدار النظام {0} بنجاح.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "تم تثبيت إصدار النظام {0} بنجاح.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "لن تكون هناك ملفات الشخصية أخرى لفتحها إذا تم حذف الملف الشخصي المحدد", "DialogUserProfileDeletionWarningMessage": "لن تكون هناك ملفات الشخصية أخرى لفتحها إذا تم حذف الملف الشخصي المحدد",
"DialogUserProfileDeletionConfirmMessage": "هل تريد حذف الملف الشخصي المحدد", "DialogUserProfileDeletionConfirmMessage": "هل تريد حذف الملف الشخصي المحدد",
"DialogUserProfileUnsavedChangesTitle": "تحذير - التغييرات غير محفوظة", "DialogUserProfileUnsavedChangesTitle": "تحذير - التغييرات غير محفوظة",

View File

@ -1,6 +1,7 @@
{ {
"Language": "Deutsch", "Language": "Deutsch",
"MenuBarFileOpenApplet": "Öffne Anwendung", "MenuBarFileOpenApplet": "Öffne Anwendung",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Öffnet das Mii-Editor-Applet im Standalone-Modus", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Öffnet das Mii-Editor-Applet im Standalone-Modus",
"SettingsTabInputDirectMouseAccess": "Direkter Mauszugriff", "SettingsTabInputDirectMouseAccess": "Direkter Mauszugriff",
"SettingsTabSystemMemoryManagerMode": "Speichermanagermodus:", "SettingsTabSystemMemoryManagerMode": "Speichermanagermodus:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Firmware installieren", "MenuBarToolsInstallFirmware": "Firmware installieren",
"MenuBarFileToolsInstallFirmwareFromFile": "Firmware von einer XCI- oder einer ZIP-Datei installieren", "MenuBarFileToolsInstallFirmwareFromFile": "Firmware von einer XCI- oder einer ZIP-Datei installieren",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Firmware aus einem Verzeichnis installieren", "MenuBarFileToolsInstallFirmwareFromDirectory": "Firmware aus einem Verzeichnis installieren",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Dateitypen verwalten", "MenuBarToolsManageFileTypes": "Dateitypen verwalten",
"MenuBarToolsInstallFileTypes": "Dateitypen installieren", "MenuBarToolsInstallFileTypes": "Dateitypen installieren",
"MenuBarToolsUninstallFileTypes": "Dateitypen deinstallieren", "MenuBarToolsUninstallFileTypes": "Dateitypen deinstallieren",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nMöchtest du fortfahren?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nMöchtest du fortfahren?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Firmware wird installiert...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Firmware wird installiert...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Systemversion {0} wurde erfolgreich installiert.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Systemversion {0} wurde erfolgreich installiert.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Es können keine anderen Profile geöffnet werden, wenn das ausgewählte Profil gelöscht wird.", "DialogUserProfileDeletionWarningMessage": "Es können keine anderen Profile geöffnet werden, wenn das ausgewählte Profil gelöscht wird.",
"DialogUserProfileDeletionConfirmMessage": "Möchtest du das ausgewählte Profil löschen?", "DialogUserProfileDeletionConfirmMessage": "Möchtest du das ausgewählte Profil löschen?",
"DialogUserProfileUnsavedChangesTitle": "Warnung - Nicht gespeicherte Änderungen", "DialogUserProfileUnsavedChangesTitle": "Warnung - Nicht gespeicherte Änderungen",

View File

@ -1,6 +1,7 @@
{ {
"Language": "Ελληνικά", "Language": "Ελληνικά",
"MenuBarFileOpenApplet": "Άνοιγμα Applet", "MenuBarFileOpenApplet": "Άνοιγμα Applet",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία",
"SettingsTabInputDirectMouseAccess": "Άμεση Πρόσβαση Ποντικιού", "SettingsTabInputDirectMouseAccess": "Άμεση Πρόσβαση Ποντικιού",
"SettingsTabSystemMemoryManagerMode": "Λειτουργία Διαχείρισης Μνήμης:", "SettingsTabSystemMemoryManagerMode": "Λειτουργία Διαχείρισης Μνήμης:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Εγκατάσταση Firmware", "MenuBarToolsInstallFirmware": "Εγκατάσταση Firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Εγκατάσταση Firmware από XCI ή ZIP", "MenuBarFileToolsInstallFirmwareFromFile": "Εγκατάσταση Firmware από XCI ή ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Εγκατάσταση Firmware από τοποθεσία", "MenuBarFileToolsInstallFirmwareFromDirectory": "Εγκατάσταση Firmware από τοποθεσία",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Διαχείριση τύπων αρχείων", "MenuBarToolsManageFileTypes": "Διαχείριση τύπων αρχείων",
"MenuBarToolsInstallFileTypes": "Εγκαταστήσετε τύπους αρχείων.", "MenuBarToolsInstallFileTypes": "Εγκαταστήσετε τύπους αρχείων.",
"MenuBarToolsUninstallFileTypes": "Απεγκαταστήσετε τύπους αρχείων", "MenuBarToolsUninstallFileTypes": "Απεγκαταστήσετε τύπους αρχείων",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nΘέλετε να συνεχίσετε;", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nΘέλετε να συνεχίσετε;",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Εγκατάσταση Firmware...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Εγκατάσταση Firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Η έκδοση συστήματος {0} εγκαταστάθηκε με επιτυχία.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Η έκδοση συστήματος {0} εγκαταστάθηκε με επιτυχία.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Δεν θα υπάρχουν άλλα προφίλ εάν διαγραφεί το επιλεγμένο", "DialogUserProfileDeletionWarningMessage": "Δεν θα υπάρχουν άλλα προφίλ εάν διαγραφεί το επιλεγμένο",
"DialogUserProfileDeletionConfirmMessage": "Θέλετε να διαγράψετε το επιλεγμένο προφίλ", "DialogUserProfileDeletionConfirmMessage": "Θέλετε να διαγράψετε το επιλεγμένο προφίλ",
"DialogUserProfileUnsavedChangesTitle": "Προσοχή - Μην Αποθηκευμένες Αλλαγές.", "DialogUserProfileUnsavedChangesTitle": "Προσοχή - Μην Αποθηκευμένες Αλλαγές.",

View File

@ -1,6 +1,7 @@
{ {
"Language": "English (US)", "Language": "English (US)",
"MenuBarFileOpenApplet": "Open Applet", "MenuBarFileOpenApplet": "Open Applet",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Open Mii Editor Applet in Standalone mode", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Open Mii Editor Applet in Standalone mode",
"SettingsTabInputDirectMouseAccess": "Direct Mouse Access", "SettingsTabInputDirectMouseAccess": "Direct Mouse Access",
"SettingsTabSystemMemoryManagerMode": "Memory Manager Mode:", "SettingsTabSystemMemoryManagerMode": "Memory Manager Mode:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Install Firmware", "MenuBarToolsInstallFirmware": "Install Firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Install a firmware from XCI or ZIP", "MenuBarFileToolsInstallFirmwareFromFile": "Install a firmware from XCI or ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Install a firmware from a directory", "MenuBarFileToolsInstallFirmwareFromDirectory": "Install a firmware from a directory",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Manage file types", "MenuBarToolsManageFileTypes": "Manage file types",
"MenuBarToolsInstallFileTypes": "Install file types", "MenuBarToolsInstallFileTypes": "Install file types",
"MenuBarToolsUninstallFileTypes": "Uninstall file types", "MenuBarToolsUninstallFileTypes": "Uninstall file types",
@ -142,9 +146,20 @@
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Latin American Spanish", "SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Latin American Spanish",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Simplified Chinese", "SettingsTabSystemSystemLanguageSimplifiedChinese": "Simplified Chinese",
"SettingsTabSystemSystemLanguageTraditionalChinese": "Traditional Chinese", "SettingsTabSystemSystemLanguageTraditionalChinese": "Traditional Chinese",
"SettingsTabSystemSystemTimeZone": "System TimeZone:", "SettingsTabSystemSystemTimeZone": "System Time Zone:",
"SettingsTabSystemSystemTime": "System Time:", "SettingsTabSystemSystemTime": "System Time:",
"SettingsTabSystemEnableVsync": "VSync", "SettingsTabSystemVSyncMode": "VSync:",
"SettingsTabSystemEnableCustomVSyncInterval": "Enable custom refresh rate (Experimental)",
"SettingsTabSystemVSyncModeSwitch": "Switch",
"SettingsTabSystemVSyncModeUnbounded": "Unbounded",
"SettingsTabSystemVSyncModeCustom": "Custom Refresh Rate",
"SettingsTabSystemVSyncModeTooltip": "Emulated Vertical Sync. 'Switch' emulates the Switch's refresh rate of 60Hz. 'Unbounded' is an unbounded refresh rate.",
"SettingsTabSystemVSyncModeTooltipCustom": "Emulated Vertical Sync. 'Switch' emulates the Switch's refresh rate of 60Hz. 'Unbounded' is an unbounded refresh rate. 'Custom' emulates the specified custom refresh rate.",
"SettingsTabSystemEnableCustomVSyncIntervalTooltip": "Allows the user to specify an emulated refresh rate. In some titles, this may speed up or slow down the rate of gameplay logic. In other titles, it may allow for capping FPS at some multiple of the refresh rate, or lead to unpredictable behavior. This is an experimental feature, with no guarantees for how gameplay will be affected. \n\nLeave OFF if unsure.",
"SettingsTabSystemCustomVSyncIntervalValueTooltip": "The custom refresh rate target value.",
"SettingsTabSystemCustomVSyncIntervalSliderTooltip": "The custom refresh rate, as a percentage of the normal Switch refresh rate.",
"SettingsTabSystemCustomVSyncIntervalPercentage": "Custom Refresh Rate %:",
"SettingsTabSystemCustomVSyncIntervalValue": "Custom Refresh Rate Value:",
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)", "SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC cache", "SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC cache",
"SettingsTabSystemEnableFsIntegrityChecks": "FS Integrity Checks", "SettingsTabSystemEnableFsIntegrityChecks": "FS Integrity Checks",
@ -153,6 +168,7 @@
"SettingsTabSystemAudioBackendOpenAL": "OpenAL", "SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO", "SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2", "SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemCustomVSyncInterval": "Interval",
"SettingsTabSystemHacks": "Hacks", "SettingsTabSystemHacks": "Hacks",
"SettingsTabSystemHacksNote": "May cause instability", "SettingsTabSystemHacksNote": "May cause instability",
"SettingsTabSystemDramSize": "DRAM size:", "SettingsTabSystemDramSize": "DRAM size:",
@ -505,6 +521,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDo you want to continue?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installing firmware...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installing firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "System version {0} successfully installed.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "System version {0} successfully installed.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "There would be no other profiles to be opened if selected profile is deleted", "DialogUserProfileDeletionWarningMessage": "There would be no other profiles to be opened if selected profile is deleted",
"DialogUserProfileDeletionConfirmMessage": "Do you want to delete the selected profile", "DialogUserProfileDeletionConfirmMessage": "Do you want to delete the selected profile",
"DialogUserProfileUnsavedChangesTitle": "Warning - Unsaved Changes", "DialogUserProfileUnsavedChangesTitle": "Warning - Unsaved Changes",
@ -720,11 +743,13 @@
"RyujinxUpdater": "Ryujinx Updater", "RyujinxUpdater": "Ryujinx Updater",
"SettingsTabHotkeys": "Keyboard Hotkeys", "SettingsTabHotkeys": "Keyboard Hotkeys",
"SettingsTabHotkeysHotkeys": "Keyboard Hotkeys", "SettingsTabHotkeysHotkeys": "Keyboard Hotkeys",
"SettingsTabHotkeysToggleVsyncHotkey": "Toggle VSync:", "SettingsTabHotkeysToggleVSyncModeHotkey": "Toggle VSync mode:",
"SettingsTabHotkeysScreenshotHotkey": "Screenshot:", "SettingsTabHotkeysScreenshotHotkey": "Screenshot:",
"SettingsTabHotkeysShowUiHotkey": "Show UI:", "SettingsTabHotkeysShowUiHotkey": "Show UI:",
"SettingsTabHotkeysPauseHotkey": "Pause:", "SettingsTabHotkeysPauseHotkey": "Pause:",
"SettingsTabHotkeysToggleMuteHotkey": "Mute:", "SettingsTabHotkeysToggleMuteHotkey": "Mute:",
"SettingsTabHotkeysIncrementCustomVSyncIntervalHotkey": "Raise custom refresh rate",
"SettingsTabHotkeysDecrementCustomVSyncIntervalHotkey": "Lower custom refresh rate",
"ControllerMotionTitle": "Motion Control Settings", "ControllerMotionTitle": "Motion Control Settings",
"ControllerRumbleTitle": "Rumble Settings", "ControllerRumbleTitle": "Rumble Settings",
"SettingsSelectThemeFileDialogTitle": "Select Theme File", "SettingsSelectThemeFileDialogTitle": "Select Theme File",

View File

@ -1,6 +1,7 @@
{ {
"Language": "Español (ES)", "Language": "Español (ES)",
"MenuBarFileOpenApplet": "Abrir applet", "MenuBarFileOpenApplet": "Abrir applet",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abre el editor de Mii en modo autónomo", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abre el editor de Mii en modo autónomo",
"SettingsTabInputDirectMouseAccess": "Acceso directo al ratón", "SettingsTabInputDirectMouseAccess": "Acceso directo al ratón",
"SettingsTabSystemMemoryManagerMode": "Modo del administrador de memoria:", "SettingsTabSystemMemoryManagerMode": "Modo del administrador de memoria:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Instalar firmware", "MenuBarToolsInstallFirmware": "Instalar firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Instalar firmware desde un archivo XCI o ZIP", "MenuBarFileToolsInstallFirmwareFromFile": "Instalar firmware desde un archivo XCI o ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Instalar firmware desde una carpeta", "MenuBarFileToolsInstallFirmwareFromDirectory": "Instalar firmware desde una carpeta",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Administrar tipos de archivo", "MenuBarToolsManageFileTypes": "Administrar tipos de archivo",
"MenuBarToolsInstallFileTypes": "Instalar tipos de archivo", "MenuBarToolsInstallFileTypes": "Instalar tipos de archivo",
"MenuBarToolsUninstallFileTypes": "Desinstalar tipos de archivo", "MenuBarToolsUninstallFileTypes": "Desinstalar tipos de archivo",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n¿Continuar?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n¿Continuar?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalando firmware...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalando firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Versión de sistema {0} instalada con éxito.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Versión de sistema {0} instalada con éxito.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Si eliminas el perfil seleccionado no quedará ningún otro perfil", "DialogUserProfileDeletionWarningMessage": "Si eliminas el perfil seleccionado no quedará ningún otro perfil",
"DialogUserProfileDeletionConfirmMessage": "¿Quieres eliminar el perfil seleccionado?", "DialogUserProfileDeletionConfirmMessage": "¿Quieres eliminar el perfil seleccionado?",
"DialogUserProfileUnsavedChangesTitle": "Advertencia - Cambios sin guardar", "DialogUserProfileUnsavedChangesTitle": "Advertencia - Cambios sin guardar",

View File

@ -1,6 +1,7 @@
{ {
"Language": "Français", "Language": "Français",
"MenuBarFileOpenApplet": "Ouvrir un programme", "MenuBarFileOpenApplet": "Ouvrir un programme",
"MenuBarFileOpenAppletOpenMiiApplet": "Éditeur de Mii",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Ouvrir l'éditeur Mii en mode Standalone", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Ouvrir l'éditeur Mii en mode Standalone",
"SettingsTabInputDirectMouseAccess": "Accès direct à la souris", "SettingsTabInputDirectMouseAccess": "Accès direct à la souris",
"SettingsTabSystemMemoryManagerMode": "Mode de gestion de la mémoire :", "SettingsTabSystemMemoryManagerMode": "Mode de gestion de la mémoire :",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Installer un firmware", "MenuBarToolsInstallFirmware": "Installer un firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Installer un firmware depuis un fichier XCI ou ZIP", "MenuBarFileToolsInstallFirmwareFromFile": "Installer un firmware depuis un fichier XCI ou ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Installer un firmware depuis un dossier", "MenuBarFileToolsInstallFirmwareFromDirectory": "Installer un firmware depuis un dossier",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Gérer les types de fichiers", "MenuBarToolsManageFileTypes": "Gérer les types de fichiers",
"MenuBarToolsInstallFileTypes": "Installer les types de fichiers", "MenuBarToolsInstallFileTypes": "Installer les types de fichiers",
"MenuBarToolsUninstallFileTypes": "Désinstaller les types de fichiers", "MenuBarToolsUninstallFileTypes": "Désinstaller les types de fichiers",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVoulez-vous continuer ?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVoulez-vous continuer ?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installation du firmware...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installation du firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Version du système {0} installée avec succès.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Version du système {0} installée avec succès.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Il n'y aurait aucun autre profil à ouvrir si le profil sélectionné est supprimé", "DialogUserProfileDeletionWarningMessage": "Il n'y aurait aucun autre profil à ouvrir si le profil sélectionné est supprimé",
"DialogUserProfileDeletionConfirmMessage": "Voulez-vous supprimer le profil sélectionné ?", "DialogUserProfileDeletionConfirmMessage": "Voulez-vous supprimer le profil sélectionné ?",
"DialogUserProfileUnsavedChangesTitle": "Avertissement - Modifications non enregistrées", "DialogUserProfileUnsavedChangesTitle": "Avertissement - Modifications non enregistrées",

View File

@ -1,6 +1,7 @@
{ {
"Language": "עִברִית", "Language": "עִברִית",
"MenuBarFileOpenApplet": "פתח יישומון", "MenuBarFileOpenApplet": "פתח יישומון",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "פתח את יישומון עורך ה- Mii במצב עצמאי", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "פתח את יישומון עורך ה- Mii במצב עצמאי",
"SettingsTabInputDirectMouseAccess": "גישה ישירה לעכבר", "SettingsTabInputDirectMouseAccess": "גישה ישירה לעכבר",
"SettingsTabSystemMemoryManagerMode": "מצב מנהל זיכרון:", "SettingsTabSystemMemoryManagerMode": "מצב מנהל זיכרון:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "התקן קושחה", "MenuBarToolsInstallFirmware": "התקן קושחה",
"MenuBarFileToolsInstallFirmwareFromFile": "התקן קושחה מקובץ- ZIP/XCI", "MenuBarFileToolsInstallFirmwareFromFile": "התקן קושחה מקובץ- ZIP/XCI",
"MenuBarFileToolsInstallFirmwareFromDirectory": "התקן קושחה מתוך תקייה", "MenuBarFileToolsInstallFirmwareFromDirectory": "התקן קושחה מתוך תקייה",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "ניהול סוגי קבצים", "MenuBarToolsManageFileTypes": "ניהול סוגי קבצים",
"MenuBarToolsInstallFileTypes": "סוגי קבצי התקנה", "MenuBarToolsInstallFileTypes": "סוגי קבצי התקנה",
"MenuBarToolsUninstallFileTypes": "סוגי קבצי הסרה", "MenuBarToolsUninstallFileTypes": "סוגי קבצי הסרה",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nהאם ברצונך להמשיך?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nהאם ברצונך להמשיך?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "מתקין קושחה...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "מתקין קושחה...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "גרסת המערכת {0} הותקנה בהצלחה.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "גרסת המערכת {0} הותקנה בהצלחה.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "לא יהיו פרופילים אחרים שייפתחו אם הפרופיל שנבחר יימחק", "DialogUserProfileDeletionWarningMessage": "לא יהיו פרופילים אחרים שייפתחו אם הפרופיל שנבחר יימחק",
"DialogUserProfileDeletionConfirmMessage": "האם ברצונך למחוק את הפרופיל שנבחר", "DialogUserProfileDeletionConfirmMessage": "האם ברצונך למחוק את הפרופיל שנבחר",
"DialogUserProfileUnsavedChangesTitle": "אזהרה - שינויים לא שמורים", "DialogUserProfileUnsavedChangesTitle": "אזהרה - שינויים לא שמורים",

View File

@ -1,6 +1,7 @@
{ {
"Language": "Italiano", "Language": "Italiano",
"MenuBarFileOpenApplet": "Apri applet", "MenuBarFileOpenApplet": "Apri applet",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Apri l'applet Mii Editor in modalità Standalone", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Apri l'applet Mii Editor in modalità Standalone",
"SettingsTabInputDirectMouseAccess": "Accesso diretto al mouse", "SettingsTabInputDirectMouseAccess": "Accesso diretto al mouse",
"SettingsTabSystemMemoryManagerMode": "Modalità di gestione della memoria:", "SettingsTabSystemMemoryManagerMode": "Modalità di gestione della memoria:",
@ -27,6 +28,9 @@
"MenuBarToolsInstallFirmware": "Installa firmware", "MenuBarToolsInstallFirmware": "Installa firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Installa un firmware da file XCI o ZIP", "MenuBarFileToolsInstallFirmwareFromFile": "Installa un firmware da file XCI o ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Installa un firmare da una cartella", "MenuBarFileToolsInstallFirmwareFromDirectory": "Installa un firmare da una cartella",
"MenuBarToolsInstallKeys": "Installa Chiavi",
"MenuBarFileToolsInstallKeysFromFile": "Installa Chiavi da file KEYS o ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Installa Chiavi da una Cartella",
"MenuBarToolsManageFileTypes": "Gestisci i tipi di file", "MenuBarToolsManageFileTypes": "Gestisci i tipi di file",
"MenuBarToolsInstallFileTypes": "Installa i tipi di file", "MenuBarToolsInstallFileTypes": "Installa i tipi di file",
"MenuBarToolsUninstallFileTypes": "Disinstalla i tipi di file", "MenuBarToolsUninstallFileTypes": "Disinstalla i tipi di file",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVuoi continuare?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVuoi continuare?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installazione del firmware...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installazione del firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "La versione del sistema {0} è stata installata.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "La versione del sistema {0} è stata installata.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "E' stato trovato un file di chiavi invalido ' {0}",
"DialogKeysInstallerKeysInstallTitle": "Installa Chavi",
"DialogKeysInstallerKeysInstallMessage": "Un nuovo file di Chiavi sarà intallato.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nQuesto potrebbe sovrascrivere alcune delle Chiavi già installate.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nVuoi continuare?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installando le chiavi...",
"DialogKeysInstallerKeysInstallSuccessMessage": "Nuovo file di chiavi installato con successo.",
"DialogUserProfileDeletionWarningMessage": "Non ci sarebbero altri profili da aprire se il profilo selezionato viene cancellato", "DialogUserProfileDeletionWarningMessage": "Non ci sarebbero altri profili da aprire se il profilo selezionato viene cancellato",
"DialogUserProfileDeletionConfirmMessage": "Vuoi eliminare il profilo selezionato?", "DialogUserProfileDeletionConfirmMessage": "Vuoi eliminare il profilo selezionato?",
"DialogUserProfileUnsavedChangesTitle": "Attenzione - Modifiche Non Salvate", "DialogUserProfileUnsavedChangesTitle": "Attenzione - Modifiche Non Salvate",

View File

@ -1,6 +1,7 @@
{ {
"Language": "日本語", "Language": "日本語",
"MenuBarFileOpenApplet": "アプレットを開く", "MenuBarFileOpenApplet": "アプレットを開く",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます",
"SettingsTabInputDirectMouseAccess": "マウス直接アクセス", "SettingsTabInputDirectMouseAccess": "マウス直接アクセス",
"SettingsTabSystemMemoryManagerMode": "メモリ管理モード:", "SettingsTabSystemMemoryManagerMode": "メモリ管理モード:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "ファームウェアをインストール", "MenuBarToolsInstallFirmware": "ファームウェアをインストール",
"MenuBarFileToolsInstallFirmwareFromFile": "XCI または ZIP からファームウェアをインストール", "MenuBarFileToolsInstallFirmwareFromFile": "XCI または ZIP からファームウェアをインストール",
"MenuBarFileToolsInstallFirmwareFromDirectory": "ディレクトリからファームウェアをインストール", "MenuBarFileToolsInstallFirmwareFromDirectory": "ディレクトリからファームウェアをインストール",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "ファイル形式を管理", "MenuBarToolsManageFileTypes": "ファイル形式を管理",
"MenuBarToolsInstallFileTypes": "ファイル形式をインストール", "MenuBarToolsInstallFileTypes": "ファイル形式をインストール",
"MenuBarToolsUninstallFileTypes": "ファイル形式をアンインストール", "MenuBarToolsUninstallFileTypes": "ファイル形式をアンインストール",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n続けてよろしいですか?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n続けてよろしいですか?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "ファームウェアをインストール中...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "ファームウェアをインストール中...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "システムバージョン {0} が正常にインストールされました.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "システムバージョン {0} が正常にインストールされました.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "選択されたプロファイルを削除すると,プロファイルがひとつも存在しなくなります", "DialogUserProfileDeletionWarningMessage": "選択されたプロファイルを削除すると,プロファイルがひとつも存在しなくなります",
"DialogUserProfileDeletionConfirmMessage": "選択されたプロファイルを削除しますか", "DialogUserProfileDeletionConfirmMessage": "選択されたプロファイルを削除しますか",
"DialogUserProfileUnsavedChangesTitle": "警告 - 保存されていない変更", "DialogUserProfileUnsavedChangesTitle": "警告 - 保存されていない変更",

View File

@ -1,6 +1,7 @@
{ {
"Language": "한국어", "Language": "한국어",
"MenuBarFileOpenApplet": "애플릿 열기", "MenuBarFileOpenApplet": "애플릿 열기",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "독립 실행형 모드로 Mii 편집기 애플릿 열기", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "독립 실행형 모드로 Mii 편집기 애플릿 열기",
"SettingsTabInputDirectMouseAccess": "마우스 직접 접근", "SettingsTabInputDirectMouseAccess": "마우스 직접 접근",
"SettingsTabSystemMemoryManagerMode": "메모리 관리자 모드 :", "SettingsTabSystemMemoryManagerMode": "메모리 관리자 모드 :",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "펌웨어 설치", "MenuBarToolsInstallFirmware": "펌웨어 설치",
"MenuBarFileToolsInstallFirmwareFromFile": "XCI 또는 ZIP으로 펌웨어 설치", "MenuBarFileToolsInstallFirmwareFromFile": "XCI 또는 ZIP으로 펌웨어 설치",
"MenuBarFileToolsInstallFirmwareFromDirectory": "디렉터리에서 펌웨어 설치", "MenuBarFileToolsInstallFirmwareFromDirectory": "디렉터리에서 펌웨어 설치",
"MenuBarToolsInstallKeys": "설치 키",
"MenuBarFileToolsInstallKeysFromFile": "키나 ZIP에서 키 설치",
"MenuBarFileToolsInstallKeysFromFolder": "디렉터리에서 키 설치",
"MenuBarToolsManageFileTypes": "파일 형식 관리", "MenuBarToolsManageFileTypes": "파일 형식 관리",
"MenuBarToolsInstallFileTypes": "파일 형식 설치", "MenuBarToolsInstallFileTypes": "파일 형식 설치",
"MenuBarToolsUninstallFileTypes": "파일 형식 제거", "MenuBarToolsUninstallFileTypes": "파일 형식 제거",
@ -457,7 +461,7 @@
"DialogUpdaterExtractionMessage": "업데이트 추출 중...", "DialogUpdaterExtractionMessage": "업데이트 추출 중...",
"DialogUpdaterRenamingMessage": "이름 변경 업데이트...", "DialogUpdaterRenamingMessage": "이름 변경 업데이트...",
"DialogUpdaterAddingFilesMessage": "새 업데이트 추가 중...", "DialogUpdaterAddingFilesMessage": "새 업데이트 추가 중...",
"DialogUpdaterShowChangelogMessage": "Show Changelog", "DialogUpdaterShowChangelogMessage": "변경 로그 보기",
"DialogUpdaterCompleteMessage": "업데이트가 완료되었습니다!", "DialogUpdaterCompleteMessage": "업데이트가 완료되었습니다!",
"DialogUpdaterRestartMessage": "지금 Ryujinx를 다시 시작하시겠습니까?", "DialogUpdaterRestartMessage": "지금 Ryujinx를 다시 시작하시겠습니까?",
"DialogUpdaterNoInternetMessage": "인터넷에 연결되어 있지 않습니다!", "DialogUpdaterNoInternetMessage": "인터넷에 연결되어 있지 않습니다!",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n계속하시겠습니까?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n계속하시겠습니까?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "펌웨어 설치 중...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "펌웨어 설치 중...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "시스템 버전 {0}이(가) 설치되었습니다.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "시스템 버전 {0}이(가) 설치되었습니다.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "{0}에서 잘못된 키 파일이 발견",
"DialogKeysInstallerKeysInstallTitle": "설치 키",
"DialogKeysInstallerKeysInstallMessage": "새로운 키 파일이 설치됩니다.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\n이로 인해 현재 설치된 키 중 일부가 대체될 수 있습니다.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\n계속하시겠습니까?",
"DialogKeysInstallerKeysInstallWaitMessage": "키 설치 중...",
"DialogKeysInstallerKeysInstallSuccessMessage": "새로운 키 파일이 성공적으로 설치되었습니다.",
"DialogUserProfileDeletionWarningMessage": "선택한 프로필을 삭제하면 다른 프로필을 열 수 없음", "DialogUserProfileDeletionWarningMessage": "선택한 프로필을 삭제하면 다른 프로필을 열 수 없음",
"DialogUserProfileDeletionConfirmMessage": "선택한 프로필을 삭제하시겠습니까?", "DialogUserProfileDeletionConfirmMessage": "선택한 프로필을 삭제하시겠습니까?",
"DialogUserProfileUnsavedChangesTitle": "경고 - 저장되지 않은 변경 사항", "DialogUserProfileUnsavedChangesTitle": "경고 - 저장되지 않은 변경 사항",

View File

@ -1,6 +1,7 @@
{ {
"Language": "Polski", "Language": "Polski",
"MenuBarFileOpenApplet": "Otwórz Aplet", "MenuBarFileOpenApplet": "Otwórz Aplet",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Otwórz aplet Mii Editor w trybie indywidualnym", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Otwórz aplet Mii Editor w trybie indywidualnym",
"SettingsTabInputDirectMouseAccess": "Bezpośredni dostęp do myszy", "SettingsTabInputDirectMouseAccess": "Bezpośredni dostęp do myszy",
"SettingsTabSystemMemoryManagerMode": "Tryb menedżera pamięci:", "SettingsTabSystemMemoryManagerMode": "Tryb menedżera pamięci:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Zainstaluj oprogramowanie", "MenuBarToolsInstallFirmware": "Zainstaluj oprogramowanie",
"MenuBarFileToolsInstallFirmwareFromFile": "Zainstaluj oprogramowanie z XCI lub ZIP", "MenuBarFileToolsInstallFirmwareFromFile": "Zainstaluj oprogramowanie z XCI lub ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Zainstaluj oprogramowanie z katalogu", "MenuBarFileToolsInstallFirmwareFromDirectory": "Zainstaluj oprogramowanie z katalogu",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Zarządzaj rodzajami plików", "MenuBarToolsManageFileTypes": "Zarządzaj rodzajami plików",
"MenuBarToolsInstallFileTypes": "Typy plików instalacyjnych", "MenuBarToolsInstallFileTypes": "Typy plików instalacyjnych",
"MenuBarToolsUninstallFileTypes": "Typy plików dezinstalacyjnych", "MenuBarToolsUninstallFileTypes": "Typy plików dezinstalacyjnych",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nCzy chcesz kontynuować?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nCzy chcesz kontynuować?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalowanie firmware'u...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalowanie firmware'u...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Wersja systemu {0} została pomyślnie zainstalowana.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Wersja systemu {0} została pomyślnie zainstalowana.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Nie będzie innych profili do otwarcia, jeśli wybrany profil zostanie usunięty", "DialogUserProfileDeletionWarningMessage": "Nie będzie innych profili do otwarcia, jeśli wybrany profil zostanie usunięty",
"DialogUserProfileDeletionConfirmMessage": "Czy chcesz usunąć wybrany profil", "DialogUserProfileDeletionConfirmMessage": "Czy chcesz usunąć wybrany profil",
"DialogUserProfileUnsavedChangesTitle": "Uwaga - Niezapisane zmiany", "DialogUserProfileUnsavedChangesTitle": "Uwaga - Niezapisane zmiany",

View File

@ -1,6 +1,7 @@
{ {
"Language": "Português (BR)", "Language": "Português (BR)",
"MenuBarFileOpenApplet": "Abrir Applet", "MenuBarFileOpenApplet": "Abrir Applet",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abrir editor Mii em modo avulso", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abrir editor Mii em modo avulso",
"SettingsTabInputDirectMouseAccess": "Acesso direto ao mouse", "SettingsTabInputDirectMouseAccess": "Acesso direto ao mouse",
"SettingsTabSystemMemoryManagerMode": "Modo de gerenciamento de memória:", "SettingsTabSystemMemoryManagerMode": "Modo de gerenciamento de memória:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "_Instalar firmware", "MenuBarToolsInstallFirmware": "_Instalar firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Instalar firmware a partir de um arquivo ZIP/XCI", "MenuBarFileToolsInstallFirmwareFromFile": "Instalar firmware a partir de um arquivo ZIP/XCI",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Instalar firmware a partir de um diretório", "MenuBarFileToolsInstallFirmwareFromDirectory": "Instalar firmware a partir de um diretório",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Gerenciar tipos de arquivo", "MenuBarToolsManageFileTypes": "Gerenciar tipos de arquivo",
"MenuBarToolsInstallFileTypes": "Instalar tipos de arquivo", "MenuBarToolsInstallFileTypes": "Instalar tipos de arquivo",
"MenuBarToolsUninstallFileTypes": "Desinstalar tipos de arquivos", "MenuBarToolsUninstallFileTypes": "Desinstalar tipos de arquivos",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDeseja continuar?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDeseja continuar?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalando firmware...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalando firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Versão do sistema {0} instalada com sucesso.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Versão do sistema {0} instalada com sucesso.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Não haveria nenhum perfil selecionado se o perfil atual fosse deletado", "DialogUserProfileDeletionWarningMessage": "Não haveria nenhum perfil selecionado se o perfil atual fosse deletado",
"DialogUserProfileDeletionConfirmMessage": "Deseja deletar o perfil selecionado", "DialogUserProfileDeletionConfirmMessage": "Deseja deletar o perfil selecionado",
"DialogUserProfileUnsavedChangesTitle": "Alerta - Alterações não salvas", "DialogUserProfileUnsavedChangesTitle": "Alerta - Alterações não salvas",

View File

@ -1,6 +1,7 @@
{ {
"Language": "Русский (RU)", "Language": "Русский (RU)",
"MenuBarFileOpenApplet": "Открыть апплет", "MenuBarFileOpenApplet": "Открыть апплет",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Открывает апплет Mii Editor в автономном режиме", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Открывает апплет Mii Editor в автономном режиме",
"SettingsTabInputDirectMouseAccess": "Прямой ввод мыши", "SettingsTabInputDirectMouseAccess": "Прямой ввод мыши",
"SettingsTabSystemMemoryManagerMode": "Режим менеджера памяти:", "SettingsTabSystemMemoryManagerMode": "Режим менеджера памяти:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Установка прошивки", "MenuBarToolsInstallFirmware": "Установка прошивки",
"MenuBarFileToolsInstallFirmwareFromFile": "Установить прошивку из XCI или ZIP", "MenuBarFileToolsInstallFirmwareFromFile": "Установить прошивку из XCI или ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Установить прошивку из папки", "MenuBarFileToolsInstallFirmwareFromDirectory": "Установить прошивку из папки",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Управление типами файлов", "MenuBarToolsManageFileTypes": "Управление типами файлов",
"MenuBarToolsInstallFileTypes": "Установить типы файлов", "MenuBarToolsInstallFileTypes": "Установить типы файлов",
"MenuBarToolsUninstallFileTypes": "Удалить типы файлов", "MenuBarToolsUninstallFileTypes": "Удалить типы файлов",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nПродолжить?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nПродолжить?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Установка прошивки...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Установка прошивки...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Прошивка версии {0} успешно установлена.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Прошивка версии {0} успешно установлена.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Если выбранный профиль будет удален, другие профили не будут открываться.", "DialogUserProfileDeletionWarningMessage": "Если выбранный профиль будет удален, другие профили не будут открываться.",
"DialogUserProfileDeletionConfirmMessage": "Удалить выбранный профиль?", "DialogUserProfileDeletionConfirmMessage": "Удалить выбранный профиль?",
"DialogUserProfileUnsavedChangesTitle": "Внимание - Несохраненные изменения", "DialogUserProfileUnsavedChangesTitle": "Внимание - Несохраненные изменения",

View File

@ -1,6 +1,7 @@
{ {
"Language": "ภาษาไทย", "Language": "ภาษาไทย",
"MenuBarFileOpenApplet": "เปิด Applet", "MenuBarFileOpenApplet": "เปิด Applet",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "เปิดโปรแกรม Mii Editor Applet", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "เปิดโปรแกรม Mii Editor Applet",
"SettingsTabInputDirectMouseAccess": "เข้าถึงเมาส์ได้โดยตรง", "SettingsTabInputDirectMouseAccess": "เข้าถึงเมาส์ได้โดยตรง",
"SettingsTabSystemMemoryManagerMode": "โหมดจัดการหน่วยความจำ:", "SettingsTabSystemMemoryManagerMode": "โหมดจัดการหน่วยความจำ:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "ติดตั้งเฟิร์มแวร์", "MenuBarToolsInstallFirmware": "ติดตั้งเฟิร์มแวร์",
"MenuBarFileToolsInstallFirmwareFromFile": "ติดตั้งเฟิร์มแวร์จาก ไฟล์ XCI หรือ ไฟล์ ZIP", "MenuBarFileToolsInstallFirmwareFromFile": "ติดตั้งเฟิร์มแวร์จาก ไฟล์ XCI หรือ ไฟล์ ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "ติดตั้งเฟิร์มแวร์จากไดเร็กทอรี", "MenuBarFileToolsInstallFirmwareFromDirectory": "ติดตั้งเฟิร์มแวร์จากไดเร็กทอรี",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "จัดการประเภทไฟล์", "MenuBarToolsManageFileTypes": "จัดการประเภทไฟล์",
"MenuBarToolsInstallFileTypes": "ติดตั้งประเภทไฟล์", "MenuBarToolsInstallFileTypes": "ติดตั้งประเภทไฟล์",
"MenuBarToolsUninstallFileTypes": "ถอนการติดตั้งประเภทไฟล์", "MenuBarToolsUninstallFileTypes": "ถอนการติดตั้งประเภทไฟล์",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nคุณต้องการดำเนินการต่อหรือไม่?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nคุณต้องการดำเนินการต่อหรือไม่?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "กำลังติดตั้งเฟิร์มแวร์...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "กำลังติดตั้งเฟิร์มแวร์...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "ระบบเวอร์ชั่น {0} ติดตั้งเรียบร้อยแล้ว", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "ระบบเวอร์ชั่น {0} ติดตั้งเรียบร้อยแล้ว",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "จะไม่มีโปรไฟล์อื่นให้เปิดหากโปรไฟล์ที่เลือกถูกลบ", "DialogUserProfileDeletionWarningMessage": "จะไม่มีโปรไฟล์อื่นให้เปิดหากโปรไฟล์ที่เลือกถูกลบ",
"DialogUserProfileDeletionConfirmMessage": "คุณต้องการลบโปรไฟล์ที่เลือกหรือไม่?", "DialogUserProfileDeletionConfirmMessage": "คุณต้องการลบโปรไฟล์ที่เลือกหรือไม่?",
"DialogUserProfileUnsavedChangesTitle": "คำเตือน - มีการเปลี่ยนแปลงที่ไม่ได้บันทึก", "DialogUserProfileUnsavedChangesTitle": "คำเตือน - มีการเปลี่ยนแปลงที่ไม่ได้บันทึก",

View File

@ -1,6 +1,7 @@
{ {
"Language": "Türkçe", "Language": "Türkçe",
"MenuBarFileOpenApplet": "Applet'i Aç", "MenuBarFileOpenApplet": "Applet'i Aç",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Mii Editör Applet'ini Bağımsız Mod'da Aç", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Mii Editör Applet'ini Bağımsız Mod'da Aç",
"SettingsTabInputDirectMouseAccess": "Doğrudan Mouse Erişimi", "SettingsTabInputDirectMouseAccess": "Doğrudan Mouse Erişimi",
"SettingsTabSystemMemoryManagerMode": "Hafıza Yönetim Modu:", "SettingsTabSystemMemoryManagerMode": "Hafıza Yönetim Modu:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Yazılım Yükle", "MenuBarToolsInstallFirmware": "Yazılım Yükle",
"MenuBarFileToolsInstallFirmwareFromFile": "XCI veya ZIP'ten Yazılım Yükle", "MenuBarFileToolsInstallFirmwareFromFile": "XCI veya ZIP'ten Yazılım Yükle",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Bir Dizin Üzerinden Yazılım Yükle", "MenuBarFileToolsInstallFirmwareFromDirectory": "Bir Dizin Üzerinden Yazılım Yükle",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Dosya uzantılarını yönet", "MenuBarToolsManageFileTypes": "Dosya uzantılarını yönet",
"MenuBarToolsInstallFileTypes": "Dosya uzantılarını yükle", "MenuBarToolsInstallFileTypes": "Dosya uzantılarını yükle",
"MenuBarToolsUninstallFileTypes": "Dosya uzantılarını kaldır", "MenuBarToolsUninstallFileTypes": "Dosya uzantılarını kaldır",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDevam etmek istiyor musunuz?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDevam etmek istiyor musunuz?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Firmware yükleniyor...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Firmware yükleniyor...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Sistem sürümü {0} başarıyla yüklendi.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Sistem sürümü {0} başarıyla yüklendi.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Seçilen profil silinirse kullanılabilen başka profil kalmayacak", "DialogUserProfileDeletionWarningMessage": "Seçilen profil silinirse kullanılabilen başka profil kalmayacak",
"DialogUserProfileDeletionConfirmMessage": "Seçilen profili silmek istiyor musunuz", "DialogUserProfileDeletionConfirmMessage": "Seçilen profili silmek istiyor musunuz",
"DialogUserProfileUnsavedChangesTitle": "Uyarı - Kaydedilmemiş Değişiklikler", "DialogUserProfileUnsavedChangesTitle": "Uyarı - Kaydedilmemiş Değişiklikler",

View File

@ -1,6 +1,7 @@
{ {
"Language": "Українська", "Language": "Українська",
"MenuBarFileOpenApplet": "Відкрити аплет", "MenuBarFileOpenApplet": "Відкрити аплет",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Відкрити аплет Mii Editor в автономному режимі", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Відкрити аплет Mii Editor в автономному режимі",
"SettingsTabInputDirectMouseAccess": "Прямий доступ мишею", "SettingsTabInputDirectMouseAccess": "Прямий доступ мишею",
"SettingsTabSystemMemoryManagerMode": "Режим диспетчера пам’яті:", "SettingsTabSystemMemoryManagerMode": "Режим диспетчера пам’яті:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "Установити прошивку", "MenuBarToolsInstallFirmware": "Установити прошивку",
"MenuBarFileToolsInstallFirmwareFromFile": "Установити прошивку з XCI або ZIP", "MenuBarFileToolsInstallFirmwareFromFile": "Установити прошивку з XCI або ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Установити прошивку з теки", "MenuBarFileToolsInstallFirmwareFromDirectory": "Установити прошивку з теки",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Керувати типами файлів", "MenuBarToolsManageFileTypes": "Керувати типами файлів",
"MenuBarToolsInstallFileTypes": "Установити типи файлів", "MenuBarToolsInstallFileTypes": "Установити типи файлів",
"MenuBarToolsUninstallFileTypes": "Видалити типи файлів", "MenuBarToolsUninstallFileTypes": "Видалити типи файлів",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nВи хочете продовжити?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nВи хочете продовжити?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Встановлення прошивки...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Встановлення прошивки...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Версію системи {0} успішно встановлено.", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Версію системи {0} успішно встановлено.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "Якщо вибраний профіль буде видалено, інші профілі не відкриватимуться", "DialogUserProfileDeletionWarningMessage": "Якщо вибраний профіль буде видалено, інші профілі не відкриватимуться",
"DialogUserProfileDeletionConfirmMessage": "Ви хочете видалити вибраний профіль", "DialogUserProfileDeletionConfirmMessage": "Ви хочете видалити вибраний профіль",
"DialogUserProfileUnsavedChangesTitle": "Увага — Незбережені зміни", "DialogUserProfileUnsavedChangesTitle": "Увага — Незбережені зміни",

View File

@ -1,6 +1,7 @@
{ {
"Language": "简体中文", "Language": "简体中文",
"MenuBarFileOpenApplet": "打开小程序", "MenuBarFileOpenApplet": "打开小程序",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打开独立的 Mii 小程序", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "打开独立的 Mii 小程序",
"SettingsTabInputDirectMouseAccess": "直通鼠标操作", "SettingsTabInputDirectMouseAccess": "直通鼠标操作",
"SettingsTabSystemMemoryManagerMode": "内存管理模式:", "SettingsTabSystemMemoryManagerMode": "内存管理模式:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "安装系统固件", "MenuBarToolsInstallFirmware": "安装系统固件",
"MenuBarFileToolsInstallFirmwareFromFile": "从 XCI 或 ZIP 文件中安装系统固件", "MenuBarFileToolsInstallFirmwareFromFile": "从 XCI 或 ZIP 文件中安装系统固件",
"MenuBarFileToolsInstallFirmwareFromDirectory": "从文件夹中安装系统固件", "MenuBarFileToolsInstallFirmwareFromDirectory": "从文件夹中安装系统固件",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "管理文件扩展名", "MenuBarToolsManageFileTypes": "管理文件扩展名",
"MenuBarToolsInstallFileTypes": "关联文件扩展名", "MenuBarToolsInstallFileTypes": "关联文件扩展名",
"MenuBarToolsUninstallFileTypes": "取消关联扩展名", "MenuBarToolsUninstallFileTypes": "取消关联扩展名",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n是否继续", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n是否继续",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "安装系统固件中...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "安装系统固件中...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "成功安装系统固件版本 {0} 。", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "成功安装系统固件版本 {0} 。",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "删除后将没有可用的账户", "DialogUserProfileDeletionWarningMessage": "删除后将没有可用的账户",
"DialogUserProfileDeletionConfirmMessage": "是否删除所选账户", "DialogUserProfileDeletionConfirmMessage": "是否删除所选账户",
"DialogUserProfileUnsavedChangesTitle": "警告 - 有未保存的更改", "DialogUserProfileUnsavedChangesTitle": "警告 - 有未保存的更改",

View File

@ -1,6 +1,7 @@
{ {
"Language": "繁體中文 (台灣)", "Language": "繁體中文 (台灣)",
"MenuBarFileOpenApplet": "開啟小程式", "MenuBarFileOpenApplet": "開啟小程式",
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "在獨立模式下開啟 Mii 編輯器小程式", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "在獨立模式下開啟 Mii 編輯器小程式",
"SettingsTabInputDirectMouseAccess": "滑鼠直接存取", "SettingsTabInputDirectMouseAccess": "滑鼠直接存取",
"SettingsTabSystemMemoryManagerMode": "記憶體管理員模式:", "SettingsTabSystemMemoryManagerMode": "記憶體管理員模式:",
@ -30,6 +31,9 @@
"MenuBarToolsInstallFirmware": "安裝韌體", "MenuBarToolsInstallFirmware": "安裝韌體",
"MenuBarFileToolsInstallFirmwareFromFile": "從 XCI 或 ZIP 安裝韌體", "MenuBarFileToolsInstallFirmwareFromFile": "從 XCI 或 ZIP 安裝韌體",
"MenuBarFileToolsInstallFirmwareFromDirectory": "從資料夾安裝韌體", "MenuBarFileToolsInstallFirmwareFromDirectory": "從資料夾安裝韌體",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "管理檔案類型", "MenuBarToolsManageFileTypes": "管理檔案類型",
"MenuBarToolsInstallFileTypes": "安裝檔案類型", "MenuBarToolsInstallFileTypes": "安裝檔案類型",
"MenuBarToolsUninstallFileTypes": "移除檔案類型", "MenuBarToolsUninstallFileTypes": "移除檔案類型",
@ -505,6 +509,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n您確定要繼續嗎?", "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n您確定要繼續嗎?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "正在安裝韌體...", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "正在安裝韌體...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "成功安裝系統版本 {0}。", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "成功安裝系統版本 {0}。",
"DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "如果刪除選取的設定檔,將無法開啟其他設定檔", "DialogUserProfileDeletionWarningMessage": "如果刪除選取的設定檔,將無法開啟其他設定檔",
"DialogUserProfileDeletionConfirmMessage": "您是否要刪除所選設定檔", "DialogUserProfileDeletionConfirmMessage": "您是否要刪除所選設定檔",
"DialogUserProfileUnsavedChangesTitle": "警告 - 未儲存的變更", "DialogUserProfileUnsavedChangesTitle": "警告 - 未儲存的變更",

View File

@ -26,8 +26,9 @@
<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="SecondaryTextColor">#A0000000</Color> <Color x:Key="SecondaryTextColor">#A0000000</Color>
<Color x:Key="VsyncEnabled">#FF2EEAC9</Color> <Color x:Key="Switch">#FF2EEAC9</Color>
<Color x:Key="VsyncDisabled">#FFFF4554</Color> <Color x:Key="Unbounded">#FFFF4554</Color>
<Color x:Key="Custom">#6483F5</Color>
</ResourceDictionary> </ResourceDictionary>
<ResourceDictionary x:Key="Light"> <ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"

View File

@ -3,7 +3,7 @@ namespace Ryujinx.Ava.Common
public enum KeyboardHotkeyState public enum KeyboardHotkeyState
{ {
None, None,
ToggleVSync, ToggleVSyncMode,
Screenshot, Screenshot,
ShowUI, ShowUI,
Pause, Pause,
@ -12,5 +12,7 @@ namespace Ryujinx.Ava.Common
ResScaleDown, ResScaleDown,
VolumeUp, VolumeUp,
VolumeDown, VolumeDown,
CustomVSyncIntervalIncrement,
CustomVSyncIntervalDecrement,
} }
} }

View File

@ -11,6 +11,7 @@
<TieredPGO>true</TieredPGO> <TieredPGO>true</TieredPGO>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<ApplicationManifest>app.manifest</ApplicationManifest> <ApplicationManifest>app.manifest</ApplicationManifest>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))"> <Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">

View File

@ -5,13 +5,13 @@ namespace Ryujinx.Ava.UI.Models.Input
{ {
public class HotkeyConfig : BaseModel public class HotkeyConfig : BaseModel
{ {
private Key _toggleVsync; private Key _toggleVSyncMode;
public Key ToggleVsync public Key ToggleVSyncMode
{ {
get => _toggleVsync; get => _toggleVSyncMode;
set set
{ {
_toggleVsync = value; _toggleVSyncMode = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
@ -104,11 +104,33 @@ namespace Ryujinx.Ava.UI.Models.Input
} }
} }
private Key _customVSyncIntervalIncrement;
public Key CustomVSyncIntervalIncrement
{
get => _customVSyncIntervalIncrement;
set
{
_customVSyncIntervalIncrement = value;
OnPropertyChanged();
}
}
private Key _customVSyncIntervalDecrement;
public Key CustomVSyncIntervalDecrement
{
get => _customVSyncIntervalDecrement;
set
{
_customVSyncIntervalDecrement = value;
OnPropertyChanged();
}
}
public HotkeyConfig(KeyboardHotkeys config) public HotkeyConfig(KeyboardHotkeys config)
{ {
if (config != null) if (config != null)
{ {
ToggleVsync = config.ToggleVsync; ToggleVSyncMode = config.ToggleVSyncMode;
Screenshot = config.Screenshot; Screenshot = config.Screenshot;
ShowUI = config.ShowUI; ShowUI = config.ShowUI;
Pause = config.Pause; Pause = config.Pause;
@ -117,6 +139,8 @@ namespace Ryujinx.Ava.UI.Models.Input
ResScaleDown = config.ResScaleDown; ResScaleDown = config.ResScaleDown;
VolumeUp = config.VolumeUp; VolumeUp = config.VolumeUp;
VolumeDown = config.VolumeDown; VolumeDown = config.VolumeDown;
CustomVSyncIntervalIncrement = config.CustomVSyncIntervalIncrement;
CustomVSyncIntervalDecrement = config.CustomVSyncIntervalDecrement;
} }
} }
@ -124,7 +148,7 @@ namespace Ryujinx.Ava.UI.Models.Input
{ {
var config = new KeyboardHotkeys var config = new KeyboardHotkeys
{ {
ToggleVsync = ToggleVsync, ToggleVSyncMode = ToggleVSyncMode,
Screenshot = Screenshot, Screenshot = Screenshot,
ShowUI = ShowUI, ShowUI = ShowUI,
Pause = Pause, Pause = Pause,
@ -133,6 +157,8 @@ namespace Ryujinx.Ava.UI.Models.Input
ResScaleDown = ResScaleDown, ResScaleDown = ResScaleDown,
VolumeUp = VolumeUp, VolumeUp = VolumeUp,
VolumeDown = VolumeDown, VolumeDown = VolumeDown,
CustomVSyncIntervalIncrement = CustomVSyncIntervalIncrement,
CustomVSyncIntervalDecrement = CustomVSyncIntervalDecrement,
}; };
return config; return config;

View File

@ -47,7 +47,7 @@ namespace Ryujinx.Ava.UI.Models
TitleId = info.ProgramId; TitleId = info.ProgramId;
UserId = info.UserId; UserId = info.UserId;
var appData = App.MainWindow.ViewModel.Applications.FirstOrDefault(x => x.IdString.Equals(TitleIdString, StringComparison.OrdinalIgnoreCase)); var appData = MainWindow.MainWindowViewModel.Applications.FirstOrDefault(x => x.IdString.Equals(TitleIdString, StringComparison.OrdinalIgnoreCase));
InGameList = appData != null; InGameList = appData != null;

View File

@ -4,18 +4,17 @@ namespace Ryujinx.Ava.UI.Models
{ {
internal class StatusUpdatedEventArgs : EventArgs internal class StatusUpdatedEventArgs : EventArgs
{ {
public bool VSyncEnabled { get; } public string VSyncMode { get; }
public string VolumeStatus { get; } public string VolumeStatus { get; }
public string AspectRatio { get; } public string AspectRatio { get; }
public string DockedMode { get; } public string DockedMode { get; }
public string FifoStatus { get; } public string FifoStatus { get; }
public string GameStatus { get; } public string GameStatus { get; }
public uint ShaderCount { get; } public uint ShaderCount { get; }
public StatusUpdatedEventArgs(bool vSyncEnabled, string volumeStatus, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus, uint shaderCount) public StatusUpdatedEventArgs(string vSyncMode, string volumeStatus, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus, uint shaderCount)
{ {
VSyncEnabled = vSyncEnabled; VSyncMode = vSyncMode;
VolumeStatus = volumeStatus; VolumeStatus = volumeStatus;
DockedMode = dockedMode; DockedMode = dockedMode;
AspectRatio = aspectRatio; AspectRatio = aspectRatio;

View File

@ -63,6 +63,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private string _searchText; private string _searchText;
private Timer _searchTimer; private Timer _searchTimer;
private string _dockedStatusText; private string _dockedStatusText;
private string _vSyncModeText;
private string _fifoStatusText; private string _fifoStatusText;
private string _gameStatusText; private string _gameStatusText;
private string _volumeStatusText; private string _volumeStatusText;
@ -80,7 +81,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private bool _showStatusSeparator; private bool _showStatusSeparator;
private Brush _progressBarForegroundColor; private Brush _progressBarForegroundColor;
private Brush _progressBarBackgroundColor; private Brush _progressBarBackgroundColor;
private Brush _vsyncColor; private Brush _vSyncModeColor;
private byte[] _selectedIcon; private byte[] _selectedIcon;
private bool _isAppletMenuActive; private bool _isAppletMenuActive;
private int _statusBarProgressMaximum; private int _statusBarProgressMaximum;
@ -111,6 +112,8 @@ namespace Ryujinx.Ava.UI.ViewModels
private WindowState _windowState; private WindowState _windowState;
private double _windowWidth; private double _windowWidth;
private double _windowHeight; private double _windowHeight;
private int _customVSyncInterval;
private int _customVSyncIntervalPercentageProxy;
private bool _isActive; private bool _isActive;
private bool _isSubMenuOpen; private bool _isSubMenuOpen;
@ -145,6 +148,7 @@ namespace Ryujinx.Ava.UI.ViewModels
Volume = ConfigurationState.Instance.System.AudioVolume; Volume = ConfigurationState.Instance.System.AudioVolume;
} }
CustomVSyncInterval = ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value;
} }
public void Initialize( public void Initialize(
@ -447,17 +451,87 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public Brush VsyncColor public Brush VSyncModeColor
{ {
get => _vsyncColor; get => _vSyncModeColor;
set set
{ {
_vsyncColor = value; _vSyncModeColor = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
public bool ShowCustomVSyncIntervalPicker
{
get
{
if (_isGameRunning)
{
return AppHost.Device.VSyncMode ==
VSyncMode.Custom;
}
else
{
return false;
}
}
set
{
OnPropertyChanged();
}
}
public int CustomVSyncIntervalPercentageProxy
{
get => _customVSyncIntervalPercentageProxy;
set
{
int newInterval = (int)((value / 100f) * 60);
_customVSyncInterval = newInterval;
_customVSyncIntervalPercentageProxy = value;
if (_isGameRunning)
{
AppHost.Device.CustomVSyncInterval = newInterval;
AppHost.Device.UpdateVSyncInterval();
}
OnPropertyChanged((nameof(CustomVSyncInterval)));
OnPropertyChanged((nameof(CustomVSyncIntervalPercentageText)));
}
}
public string CustomVSyncIntervalPercentageText
{
get
{
string text = CustomVSyncIntervalPercentageProxy.ToString() + "%";
return text;
}
set
{
}
}
public int CustomVSyncInterval
{
get => _customVSyncInterval;
set
{
_customVSyncInterval = value;
int newPercent = (int)((value / 60f) * 100);
_customVSyncIntervalPercentageProxy = newPercent;
if (_isGameRunning)
{
AppHost.Device.CustomVSyncInterval = value;
AppHost.Device.UpdateVSyncInterval();
}
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy));
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText));
OnPropertyChanged();
}
}
public byte[] SelectedIcon public byte[] SelectedIcon
{ {
get => _selectedIcon; get => _selectedIcon;
@ -578,6 +652,17 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public string VSyncModeText
{
get => _vSyncModeText;
set
{
_vSyncModeText = value;
OnPropertyChanged();
}
}
public string DockedStatusText public string DockedStatusText
{ {
get => _dockedStatusText; get => _dockedStatusText;
@ -1186,6 +1271,108 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
private async Task HandleKeysInstallation(string filename)
{
try
{
string systemDirectory = AppDataManager.KeysDirPath;
if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && Directory.Exists(AppDataManager.KeysDirPathUser))
{
systemDirectory = AppDataManager.KeysDirPathUser;
}
string dialogTitle = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallTitle);
string dialogMessage = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallMessage);
bool alreadyKesyInstalled = ContentManager.AreKeysAlredyPresent(systemDirectory);
if (alreadyKesyInstalled)
{
dialogMessage += LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallSubMessage);
}
dialogMessage += LocaleManager.Instance[LocaleKeys.DialogKeysInstallerKeysInstallConfirmMessage];
UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
dialogTitle,
dialogMessage,
LocaleManager.Instance[LocaleKeys.InputDialogYes],
LocaleManager.Instance[LocaleKeys.InputDialogNo],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
UpdateWaitWindow waitingDialog = new(dialogTitle, LocaleManager.Instance[LocaleKeys.DialogKeysInstallerKeysInstallWaitMessage]);
if (result == UserResult.Yes)
{
Logger.Info?.Print(LogClass.Application, $"Installing Keys");
Thread thread = new(() =>
{
Dispatcher.UIThread.InvokeAsync(delegate
{
waitingDialog.Show();
});
try
{
ContentManager.InstallKeys(filename, systemDirectory);
Dispatcher.UIThread.InvokeAsync(async delegate
{
waitingDialog.Close();
string message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallSuccessMessage);
await ContentDialogHelper.CreateInfoDialog(
dialogTitle,
message,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
string.Empty,
LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
Logger.Info?.Print(LogClass.Application, message);
});
}
catch (Exception ex)
{
Dispatcher.UIThread.InvokeAsync(async () =>
{
waitingDialog.Close();
string message = ex.Message;
if(ex is FormatException)
{
message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename);
}
await ContentDialogHelper.CreateErrorDialog(message);
});
}
finally
{
VirtualFileSystem.ReloadKeySet();
}
})
{
Name = "GUI.KeysInstallerThread",
};
thread.Start();
}
}
catch (MissingKeyException ex)
{
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime)
{
Logger.Error?.Print(LogClass.Application, ex.ToString());
await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys);
}
}
catch (Exception ex)
{
await ContentDialogHelper.CreateErrorDialog(ex.Message);
}
}
private void ProgressHandler<T>(T state, int current, int total) where T : Enum private void ProgressHandler<T>(T state, int current, int total) where T : Enum
{ {
Dispatcher.UIThread.Post(() => Dispatcher.UIThread.Post(() =>
@ -1292,17 +1479,18 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
Dispatcher.UIThread.InvokeAsync(() => Dispatcher.UIThread.InvokeAsync(() =>
{ {
Application.Current!.Styles.TryGetResource(args.VSyncEnabled Application.Current!.Styles.TryGetResource(args.VSyncMode,
? "VsyncEnabled"
: "VsyncDisabled",
Application.Current.ActualThemeVariant, Application.Current.ActualThemeVariant,
out object color); out object color);
if (color is Color clr) if (color is Color clr)
{ {
VsyncColor = new SolidColorBrush(clr); VSyncModeColor = new SolidColorBrush(clr);
} }
VSyncModeText = args.VSyncMode == "Custom" ? "Custom" : "VSync";
ShowCustomVSyncIntervalPicker =
args.VSyncMode == VSyncMode.Custom.ToString();
DockedStatusText = args.DockedMode; DockedStatusText = args.DockedMode;
AspectRatioStatusText = args.AspectRatio; AspectRatioStatusText = args.AspectRatio;
GameStatusText = args.GameStatus; GameStatusText = args.GameStatus;
@ -1473,6 +1661,53 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public async Task InstallKeysFromFile()
{
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = false,
FileTypeFilter = new List<FilePickerFileType>
{
new(LocaleManager.Instance[LocaleKeys.FileDialogAllTypes])
{
Patterns = new[] { "*.keys", "*.zip" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" },
MimeTypes = new[] { "application/keys", "application/zip" },
},
new("KEYS")
{
Patterns = new[] { "*.keys" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
MimeTypes = new[] { "application/keys" },
},
new("ZIP")
{
Patterns = new[] { "*.zip" },
AppleUniformTypeIdentifiers = new[] { "public.zip-archive" },
MimeTypes = new[] { "application/zip" },
},
},
});
if (result.Count > 0)
{
await HandleKeysInstallation(result[0].Path.LocalPath);
}
}
public async Task InstallKeysFromFolder()
{
var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
AllowMultiple = false,
});
if (result.Count > 0)
{
await HandleKeysInstallation(result[0].Path.LocalPath);
}
}
public void OpenRyujinxFolder() public void OpenRyujinxFolder()
{ {
OpenHelper.OpenFolder(AppDataManager.BaseDirPath); OpenHelper.OpenFolder(AppDataManager.BaseDirPath);
@ -1495,6 +1730,27 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public void ToggleVSyncMode()
{
AppHost.VSyncModeToggle();
OnPropertyChanged(nameof(ShowCustomVSyncIntervalPicker));
}
public void VSyncModeSettingChanged()
{
if (_isGameRunning)
{
AppHost.Device.CustomVSyncInterval = ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value;
AppHost.Device.UpdateVSyncInterval();
}
CustomVSyncInterval = ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value;
OnPropertyChanged(nameof(ShowCustomVSyncIntervalPicker));
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy));
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText));
OnPropertyChanged(nameof(CustomVSyncInterval));
}
public async Task ExitCurrentState() public async Task ExitCurrentState()
{ {
if (WindowState is WindowState.FullScreen) if (WindowState is WindowState.FullScreen)

View File

@ -52,6 +52,10 @@ namespace Ryujinx.Ava.UI.ViewModels
private int _graphicsBackendIndex; private int _graphicsBackendIndex;
private int _scalingFilter; private int _scalingFilter;
private int _scalingFilterLevel; private int _scalingFilterLevel;
private int _customVSyncInterval;
private bool _enableCustomVSyncInterval;
private int _customVSyncIntervalPercentageProxy;
private VSyncMode _vSyncMode;
public event Action CloseWindow; public event Action CloseWindow;
public event Action SaveSettingsEvent; public event Action SaveSettingsEvent;
@ -154,7 +158,74 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableDockedMode { get; set; } public bool EnableDockedMode { get; set; }
public bool EnableKeyboard { get; set; } public bool EnableKeyboard { get; set; }
public bool EnableMouse { get; set; } public bool EnableMouse { get; set; }
public bool EnableVsync { get; set; } public VSyncMode VSyncMode
{
get => _vSyncMode;
set
{
if (value == VSyncMode.Custom ||
value == VSyncMode.Switch ||
value == VSyncMode.Unbounded)
{
_vSyncMode = value;
OnPropertyChanged();
}
}
}
public int CustomVSyncIntervalPercentageProxy
{
get => _customVSyncIntervalPercentageProxy;
set
{
int newInterval = (int)((value / 100f) * 60);
_customVSyncInterval = newInterval;
_customVSyncIntervalPercentageProxy = value;
OnPropertyChanged((nameof(CustomVSyncInterval)));
OnPropertyChanged((nameof(CustomVSyncIntervalPercentageText)));
}
}
public string CustomVSyncIntervalPercentageText
{
get
{
string text = CustomVSyncIntervalPercentageProxy.ToString() + "%";
return text;
}
}
public bool EnableCustomVSyncInterval
{
get => _enableCustomVSyncInterval;
set
{
_enableCustomVSyncInterval = value;
if (_vSyncMode == VSyncMode.Custom && !value)
{
VSyncMode = VSyncMode.Switch;
}
else if (value)
{
VSyncMode = VSyncMode.Custom;
}
OnPropertyChanged();
}
}
public int CustomVSyncInterval
{
get => _customVSyncInterval;
set
{
_customVSyncInterval = value;
int newPercent = (int)((value / 60f) * 100);
_customVSyncIntervalPercentageProxy = newPercent;
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy));
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText));
OnPropertyChanged();
}
}
public bool EnablePptc { get; set; } public bool EnablePptc { get; set; }
public bool EnableLowPowerPptc { get; set; } public bool EnableLowPowerPptc { get; set; }
public bool EnableInternetAccess { get; set; } public bool EnableInternetAccess { get; set; }
@ -484,7 +555,9 @@ namespace Ryujinx.Ava.UI.ViewModels
CurrentDate = currentDateTime.Date; CurrentDate = currentDateTime.Date;
CurrentTime = currentDateTime.TimeOfDay; CurrentTime = currentDateTime.TimeOfDay;
EnableVsync = config.Graphics.EnableVsync; EnableCustomVSyncInterval = config.Graphics.EnableCustomVSyncInterval.Value;
CustomVSyncInterval = config.Graphics.CustomVSyncInterval;
VSyncMode = config.Graphics.VSyncMode;
EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks; EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks;
DramSize = config.System.DramSize; DramSize = config.System.DramSize;
IgnoreMissingServices = config.System.IgnoreMissingServices; IgnoreMissingServices = config.System.IgnoreMissingServices;
@ -590,7 +663,9 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds()); config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds());
config.Graphics.EnableVsync.Value = EnableVsync; config.Graphics.VSyncMode.Value = VSyncMode;
config.Graphics.EnableCustomVSyncInterval.Value = EnableCustomVSyncInterval;
config.Graphics.CustomVSyncInterval.Value = CustomVSyncInterval;
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks; config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
config.System.DramSize.Value = DramSize; config.System.DramSize.Value = DramSize;
config.System.IgnoreMissingServices.Value = IgnoreMissingServices; config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
@ -660,6 +735,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.ToFileFormat().SaveConfig(Program.ConfigurationPath); config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
MainWindow.UpdateGraphicsConfig(); MainWindow.UpdateGraphicsConfig();
MainWindow.MainWindowViewModel.VSyncModeSettingChanged();
SaveSettingsEvent?.Invoke(); SaveSettingsEvent?.Invoke();

View File

@ -58,7 +58,7 @@
<MenuItem Header="{ext:Locale MenuBarFileOpenApplet}" IsEnabled="{Binding IsAppletMenuActive}" Icon="{ext:Icon mdi-launch}"> <MenuItem Header="{ext:Locale MenuBarFileOpenApplet}" IsEnabled="{Binding IsAppletMenuActive}" Icon="{ext:Icon mdi-launch}">
<MenuItem <MenuItem
Click="OpenMiiApplet" Click="OpenMiiApplet"
Header="Mii Edit Applet" Header="{ext:Locale MenuBarFileOpenAppletOpenMiiApplet}"
Icon="{ext:Icon fa-solid fa-person}" Icon="{ext:Icon fa-solid fa-person}"
ToolTip.Tip="{ext:Locale MenuBarFileOpenAppletOpenMiiAppletToolTip}" /> ToolTip.Tip="{ext:Locale MenuBarFileOpenAppletOpenMiiAppletToolTip}" />
</MenuItem> </MenuItem>
@ -260,6 +260,10 @@
IsEnabled="{Binding IsGameRunning}" /> IsEnabled="{Binding IsGameRunning}" />
</MenuItem> </MenuItem>
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarTools}"> <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarTools}">
<MenuItem Header="{ext:Locale MenuBarToolsInstallKeys}" Icon="{ext:Icon fa-solid fa-key}" IsEnabled="{Binding EnableNonGameRunningControls}">
<MenuItem Command="{Binding InstallKeysFromFile}" Header="{ext:Locale MenuBarFileToolsInstallKeysFromFile}" Icon="{ext:Icon mdi-file-cog}" />
<MenuItem Command="{Binding InstallKeysFromFolder}" Header="{ext:Locale MenuBarFileToolsInstallKeysFromFolder}" Icon="{ext:Icon mdi-folder-cog}" />
</MenuItem>
<MenuItem Header="{ext:Locale MenuBarToolsInstallFirmware}" Icon="{ext:Icon fa-solid fa-download}" IsEnabled="{Binding EnableNonGameRunningControls}"> <MenuItem Header="{ext:Locale MenuBarToolsInstallFirmware}" Icon="{ext:Icon fa-solid fa-download}" IsEnabled="{Binding EnableNonGameRunningControls}">
<MenuItem Command="{Binding InstallFirmwareFromFile}" Header="{ext:Locale MenuBarFileToolsInstallFirmwareFromFile}" Icon="{ext:Icon mdi-file-cog}" /> <MenuItem Command="{Binding InstallFirmwareFromFile}" Header="{ext:Locale MenuBarFileToolsInstallFirmwareFromFile}" Icon="{ext:Icon mdi-file-cog}" />
<MenuItem Command="{Binding InstallFirmwareFromFolder}" Header="{ext:Locale MenuBarFileToolsInstallFirmwareFromDirectory}" Icon="{ext:Icon mdi-folder-cog}" /> <MenuItem Command="{Binding InstallFirmwareFromFolder}" Header="{ext:Locale MenuBarFileToolsInstallFirmwareFromDirectory}" Icon="{ext:Icon mdi-folder-cog}" />

View File

@ -79,15 +79,59 @@
MaxHeight="18" MaxHeight="18"
Orientation="Horizontal"> Orientation="Horizontal">
<TextBlock <TextBlock
Name="VsyncStatus" Name="VSyncMode"
Margin="5,0,5,0" Margin="5,0,5,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Center" VerticalAlignment="Center"
Foreground="{Binding VsyncColor}" Foreground="{Binding VSyncModeColor}"
IsVisible="{Binding !ShowLoadProgress}" IsVisible="{Binding !ShowLoadProgress}"
PointerReleased="VsyncStatus_PointerReleased" PointerReleased="VSyncMode_PointerReleased"
Text="VSync" Text="{Binding VSyncModeText}"
TextAlignment="Start" /> TextAlignment="Start"/>
<Button MinWidth="0"
Width="20"
IsVisible="{Binding ShowCustomVSyncIntervalPicker}"
Margin="-5,0,5,0"
Background="Transparent"
BorderThickness="0">
<ui:SymbolIcon Symbol="Settings"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Width="14"
Height="14"/>
<Button.Styles>
<Style Selector=":checked">
<Style Selector="^:checked ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundColor}" />
</Style>
</Style>
<Style Selector="Border#SeparatorBorder">
<Setter Property="Opacity" Value="0" />
</Style>
</Button.Styles>
<Button.Flyout>
<Flyout Placement="Top" ShowMode="TransientWithDismissOnPointerMoveAway">
<StackPanel Margin="0,0,0,0"
Orientation="Horizontal">
<Slider Value="{Binding CustomVSyncIntervalPercentageProxy}"
MinWidth="175"
Margin="0,-3,0,0"
Height="32"
Padding="0,-5"
TickFrequency="1"
IsSnapToTickEnabled="True"
LargeChange="10"
SmallChange="1"
VerticalAlignment="Center"
Minimum="10"
Maximum="400" />
<TextBlock Margin="5,0"
Width="40"
Text="{Binding CustomVSyncIntervalPercentageText}"/>
</StackPanel>
</Flyout>
</Button.Flyout>
</Button>
<Border <Border
Width="2" Width="2"
Height="12" Height="12"

View File

@ -38,11 +38,10 @@ namespace Ryujinx.Ava.UI.Views.Main
} }
} }
private void VsyncStatus_PointerReleased(object sender, PointerReleasedEventArgs e) private void VSyncMode_PointerReleased(object sender, PointerReleasedEventArgs e)
{ {
Window.ViewModel.AppHost.ToggleVSync(); Window.ViewModel.ToggleVSyncMode();
Logger.Info?.Print(LogClass.Application, $"VSync Mode toggled to: {Window.ViewModel.AppHost.Device.VSyncMode}");
Logger.Info?.Print(LogClass.Application, $"VSync toggled to: {Window.ViewModel.AppHost.Device.EnableDeviceVsync}");
} }
private void DockedStatus_PointerReleased(object sender, PointerReleasedEventArgs e) private void DockedStatus_PointerReleased(object sender, PointerReleasedEventArgs e)

View File

@ -1,4 +1,4 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsHotkeysView" x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsHotkeysView"
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"
@ -50,9 +50,9 @@
Classes="h1" Classes="h1"
Text="{ext:Locale SettingsTabHotkeysHotkeys}" /> Text="{ext:Locale SettingsTabHotkeysHotkeys}" />
<StackPanel> <StackPanel>
<TextBlock Text="{ext:Locale SettingsTabHotkeysToggleVsyncHotkey}" /> <TextBlock Text="{ext:Locale SettingsTabHotkeysToggleVSyncModeHotkey}" />
<ToggleButton Name="ToggleVsync"> <ToggleButton Name="ToggleVSyncMode">
<TextBlock Text="{Binding KeyboardHotkey.ToggleVsync, Converter={StaticResource Key}}" /> <TextBlock Text="{Binding KeyboardHotkey.ToggleVSyncMode, Converter={StaticResource Key}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>
@ -103,6 +103,18 @@
<TextBlock Text="{Binding KeyboardHotkey.VolumeDown, Converter={StaticResource Key}}" /> <TextBlock Text="{Binding KeyboardHotkey.VolumeDown, Converter={StaticResource Key}}" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabHotkeysIncrementCustomVSyncIntervalHotkey}" />
<ToggleButton Name="CustomVSyncIntervalIncrement">
<TextBlock Text="{Binding KeyboardHotkey.CustomVSyncIntervalIncrement, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock Text="{ext:Locale SettingsTabHotkeysDecrementCustomVSyncIntervalHotkey}" />
<ToggleButton Name="CustomVSyncIntervalDecrement">
<TextBlock Text="{Binding KeyboardHotkey.CustomVSyncIntervalDecrement, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
</StackPanel> </StackPanel>
</Border> </Border>
</ScrollViewer> </ScrollViewer>

View File

@ -82,8 +82,8 @@ namespace Ryujinx.Ava.UI.Views.Settings
switch (button.Name) switch (button.Name)
{ {
case "ToggleVsync": case "ToggleVSyncMode":
viewModel.KeyboardHotkey.ToggleVsync = buttonValue.AsHidType<Key>(); viewModel.KeyboardHotkey.ToggleVSyncMode = buttonValue.AsHidType<Key>();
break; break;
case "Screenshot": case "Screenshot":
viewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType<Key>(); viewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType<Key>();
@ -109,6 +109,12 @@ namespace Ryujinx.Ava.UI.Views.Settings
case "VolumeDown": case "VolumeDown":
viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType<Key>(); viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType<Key>();
break; break;
case "CustomVSyncIntervalIncrement":
viewModel.KeyboardHotkey.CustomVSyncIntervalIncrement = buttonValue.AsHidType<Key>();
break;
case "CustomVSyncIntervalDecrement":
viewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = buttonValue.AsHidType<Key>();
break;
} }
} }
}; };

View File

@ -4,6 +4,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
@ -181,11 +182,68 @@
Width="350" Width="350"
ToolTip.Tip="{ext:Locale TimeTooltip}" /> ToolTip.Tip="{ext:Locale TimeTooltip}" />
</StackPanel> </StackPanel>
<CheckBox IsChecked="{Binding EnableVsync}"> <StackPanel Margin="0,0,0,10"
Orientation="Horizontal">
<TextBlock <TextBlock
Text="{ext:Locale SettingsTabSystemEnableVsync}" VerticalAlignment="Center"
ToolTip.Tip="{ext:Locale VSyncToggleTooltip}" /> Text="{ext:Locale SettingsTabSystemVSyncMode}"
</CheckBox> ToolTip.Tip="{ext:Locale SettingsTabSystemVSyncModeTooltip}"
Width="250" />
<ComboBox
IsVisible="{Binding EnableCustomVSyncInterval}"
SelectedIndex="{Binding VSyncMode}"
ToolTip.Tip="{ext:Locale SettingsTabSystemVSyncModeTooltipCustom}"
HorizontalContentAlignment="Left"
Width="350">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemVSyncModeSwitch}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemVSyncModeUnbounded}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemVSyncModeCustom}" />
</ComboBoxItem>
</ComboBox>
<ComboBox
IsVisible="{Binding !EnableCustomVSyncInterval}"
SelectedIndex="{Binding VSyncMode}"
ToolTip.Tip="{ext:Locale SettingsTabSystemVSyncModeTooltip}"
HorizontalContentAlignment="Left"
Width="350">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemVSyncModeSwitch}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemVSyncModeUnbounded}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel IsVisible="{Binding EnableCustomVSyncInterval}"
Margin="0,0,0,10"
Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemCustomVSyncIntervalPercentage}"
ToolTip.Tip="{ext:Locale SettingsTabSystemCustomVSyncIntervalValueTooltip}"
Width="250" />
<Slider Value="{Binding CustomVSyncIntervalPercentageProxy}"
ToolTip.Tip="{ext:Locale SettingsTabSystemCustomVSyncIntervalSliderTooltip}"
MinWidth="175"
Margin="10,-3,0,0"
Height="32"
Padding="0,-5"
TickFrequency="1"
IsSnapToTickEnabled="True"
LargeChange="10"
SmallChange="1"
VerticalAlignment="Center"
Minimum="10"
Maximum="400" />
<TextBlock Margin="5,0"
Width="40"
Text="{Binding CustomVSyncIntervalPercentageText}"/>
</StackPanel>
<CheckBox IsChecked="{Binding EnableFsIntegrityChecks}"> <CheckBox IsChecked="{Binding EnableFsIntegrityChecks}">
<TextBlock <TextBlock
Text="{ext:Locale SettingsTabSystemEnableFsIntegrityChecks}" Text="{ext:Locale SettingsTabSystemEnableFsIntegrityChecks}"
@ -244,6 +302,11 @@
ToolTip.Tip="{ext:Locale IgnoreAppletTooltip}"> ToolTip.Tip="{ext:Locale IgnoreAppletTooltip}">
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreApplet}" /> <TextBlock Text="{ext:Locale SettingsTabSystemIgnoreApplet}" />
</CheckBox> </CheckBox>
<CheckBox
IsChecked="{Binding EnableCustomVSyncInterval}"
ToolTip.Tip="{ext:Locale SettingsTabSystemEnableCustomVSyncIntervalTooltip}">
<TextBlock Text="{ext:Locale SettingsTabSystemEnableCustomVSyncInterval}" />
</CheckBox>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</Border> </Border>

View File

@ -38,6 +38,8 @@ namespace Ryujinx.Ava.UI.Windows
{ {
public partial class MainWindow : StyleableAppWindow public partial class MainWindow : StyleableAppWindow
{ {
internal static MainWindowViewModel MainWindowViewModel { get; private set; }
public MainWindowViewModel ViewModel { get; } public MainWindowViewModel ViewModel { get; }
internal readonly AvaHostUIHandler UiHandler; internal readonly AvaHostUIHandler UiHandler;
@ -73,7 +75,7 @@ namespace Ryujinx.Ava.UI.Windows
public MainWindow() public MainWindow()
{ {
DataContext = ViewModel = new MainWindowViewModel DataContext = ViewModel = MainWindowViewModel = new MainWindowViewModel
{ {
Window = this Window = this
}; };

View File

@ -109,7 +109,6 @@
HorizontalAlignment="Right" HorizontalAlignment="Right"
ReverseOrder="{Binding IsMacOS}"> ReverseOrder="{Binding IsMacOS}">
<Button <Button
HotKey="Enter"
Classes="accent" Classes="accent"
Content="{ext:Locale SettingsButtonOk}" Content="{ext:Locale SettingsButtonOk}"
Command="{Binding OkButton}" /> Command="{Binding OkButton}" />

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
</Project> </Project>