Compare commits

...

12 Commits

Author SHA1 Message Date
maxdlpee
b6239e5f57 Fixed an oopsies 2024-12-07 23:53:17 -03:00
maxdlpee
c665451f07 Update es_ES part 2 2024-12-07 23:49:39 -03:00
maxdlpee
666295dda2 Update es_ES part 1 2024-12-07 22:14:31 -03:00
bangfire
8ae72c1a00 Fix Windows Terminal hide/show functions (#342)
https://stackoverflow.com/a/78577080
2024-12-07 07:17:39 -06:00
Evan Husted
06abba25c1 UI: Adapt accent color to the user's system.
https://amwx.github.io/FluentAvaloniaDocs/pages/FATheme/Accents#using-the-systems-accent-color
2024-12-07 06:22:46 -06:00
Evan Husted
de00a71690 UI: Fix missing total DLC count.
Fixes #347.
2024-12-07 05:48:11 -06:00
Evan Husted
315a1819c0 Attempt #2 2024-12-07 05:31:37 -06:00
Evan Husted
4ffb8aef12 Try and fix nullref 2024-12-07 05:21:16 -06:00
Evan Husted
290a6ad5de HLE: extract custom NACP data functionality into a static helper for generic reuse elsewhere, and clarify magic numbers. 2024-12-07 04:30:04 -06:00
Evan Husted
eda4f4349b headless: Actually log the command line errors 2024-12-07 04:06:22 -06:00
Evan Husted
5fbcb1f3a7 misc: chore: Cleanups & unused parameter removal 2024-12-07 04:06:22 -06:00
WilliamWsyHK
d00754477e Add Firmware keyword in log if it is indeed firmware (#343)
Co-authored-by: LotP1 <rasmus.stilling.pedersen1@gmail.com>
2024-12-07 04:03:01 -06:00
38 changed files with 259 additions and 213 deletions

View File

@@ -1,6 +1,8 @@
namespace Ryujinx.Common.Configuration.Hid.Controller namespace Ryujinx.Common.Configuration.Hid.Controller
{ {
public class JoyconConfigControllerStick<TButton, TStick> where TButton : unmanaged where TStick : unmanaged public class JoyconConfigControllerStick<TButton, TStick>
where TButton : unmanaged
where TStick : unmanaged
{ {
public TStick Joystick { get; set; } public TStick Joystick { get; set; }
public bool InvertStickX { get; set; } public bool InvertStickX { get; set; }

View File

@@ -26,7 +26,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
{ {
private static readonly TitleUpdateMetadataJsonSerializerContext _applicationSerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly TitleUpdateMetadataJsonSerializerContext _applicationSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
public static ProcessResult Load(this Nca nca, Switch device, Nca patchNca, Nca controlNca) public static ProcessResult Load(this Nca nca, Switch device, Nca patchNca, Nca controlNca, BlitStruct<ApplicationControlProperty>? customNacpData = null)
{ {
// Extract RomFs and ExeFs from NCA. // Extract RomFs and ExeFs from NCA.
IStorage romFs = nca.GetRomFs(device, patchNca); IStorage romFs = nca.GetRomFs(device, patchNca);
@@ -55,6 +55,10 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
{ {
nacpData = controlNca.GetNacp(device); nacpData = controlNca.GetNacp(device);
} }
else if (customNacpData != null) // if the Application doesn't provide a nacp file but the Application provides an override, use the provided nacp override
{
nacpData = (BlitStruct<ApplicationControlProperty>)customNacpData;
}
/* TODO: Rework this since it's wrong and doesn't work as it takes the DisplayVersion from a "potential" non-existent update. /* TODO: Rework this since it's wrong and doesn't work as it takes the DisplayVersion from a "potential" non-existent update.

View File

@@ -98,12 +98,12 @@ namespace Ryujinx.HLE.Loaders.Processes
return false; return false;
} }
public bool LoadNca(string path) public bool LoadNca(string path, BlitStruct<ApplicationControlProperty>? customNacpData = null)
{ {
FileStream file = new(path, FileMode.Open, FileAccess.Read); FileStream file = new(path, FileMode.Open, FileAccess.Read);
Nca nca = new(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage(false)); Nca nca = new(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage(false));
ProcessResult processResult = nca.Load(_device, null, null); ProcessResult processResult = nca.Load(_device, null, null, customNacpData);
if (processResult.ProcessId != 0 && _processesByPid.TryAdd(processResult.ProcessId, processResult)) if (processResult.ProcessId != 0 && _processesByPid.TryAdd(processResult.ProcessId, processResult))
{ {

View File

@@ -84,12 +84,19 @@ namespace Ryujinx.HLE.Loaders.Processes
return false; return false;
} }
bool isFirmware = ProgramId is >= 0x0100000000000819 and <= 0x010000000000081C;
bool isFirmwareApplication = ProgramId <= 0x0100000000007FFF;
string name = !isFirmware
? (isFirmwareApplication ? "Firmware Application " : "") + (!string.IsNullOrWhiteSpace(Name) ? Name : "<Unknown Name>")
: "Firmware";
// TODO: LibHac npdm currently doesn't support version field. // TODO: LibHac npdm currently doesn't support version field.
string version = ProgramId > 0x0100000000007FFF string version = !isFirmware
? DisplayVersion ? (!string.IsNullOrWhiteSpace(DisplayVersion) ? DisplayVersion : "<Unknown Version>")
: device.System.ContentManager.GetCurrentFirmwareVersion()?.VersionString ?? "?"; : device.System.ContentManager.GetCurrentFirmwareVersion()?.VersionString ?? "?";
Logger.Info?.Print(LogClass.Loader, $"Application Loaded: {Name} v{version} [{ProgramIdText}] [{(Is64Bit ? "64-bit" : "32-bit")}]"); Logger.Info?.Print(LogClass.Loader, $"Application Loaded: {name} v{version} [{ProgramIdText}] [{(Is64Bit ? "64-bit" : "32-bit")}]");
return true; return true;
} }

View File

@@ -0,0 +1,37 @@
using LibHac.Common;
using LibHac.Ns;
using System;
using System.Text;
namespace Ryujinx.HLE
{
public static class StructHelpers
{
public static BlitStruct<ApplicationControlProperty> CreateCustomNacpData(string name, string version)
{
// https://switchbrew.org/wiki/NACP
const int OffsetOfDisplayVersion = 0x3060;
// https://switchbrew.org/wiki/NACP#ApplicationTitle
const int TotalApplicationTitles = 0x10;
const int SizeOfApplicationTitle = 0x300;
const int OffsetOfApplicationPublisherStrings = 0x200;
var nacpData = new BlitStruct<ApplicationControlProperty>(1);
// name and publisher buffer
// repeat once for each locale (the ApplicationControlProperty has 16 locales)
for (int i = 0; i < TotalApplicationTitles; i++)
{
Encoding.ASCII.GetBytes(name).AsSpan().CopyTo(nacpData.ByteSpan[(i * SizeOfApplicationTitle)..]);
"Ryujinx"u8.CopyTo(nacpData.ByteSpan[(i * SizeOfApplicationTitle + OffsetOfApplicationPublisherStrings)..]);
}
// version buffer
Encoding.ASCII.GetBytes(version).AsSpan().CopyTo(nacpData.ByteSpan[OffsetOfDisplayVersion..]);
return nacpData;
}
}
}

View File

@@ -1,3 +1,5 @@
using LibHac.Common;
using LibHac.Ns;
using Ryujinx.Audio.Backends.CompatLayer; using Ryujinx.Audio.Backends.CompatLayer;
using Ryujinx.Audio.Integration; using Ryujinx.Audio.Integration;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
@@ -111,7 +113,7 @@ namespace Ryujinx.HLE
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, BlitStruct<ApplicationControlProperty>? customNacpData = null) => Processes.LoadNca(ncaFile, customNacpData);
public bool LoadNsp(string nspFile, ulong applicationId = 0) => Processes.LoadNsp(nspFile, applicationId); public bool LoadNsp(string nspFile, ulong applicationId = 0) => Processes.LoadNsp(nspFile, applicationId);
public bool LoadProgram(string fileName) => Processes.LoadNxo(fileName); public bool LoadProgram(string fileName) => Processes.LoadNxo(fileName);

View File

@@ -1,4 +1,5 @@
using CommandLine; using CommandLine;
using Gommon;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Common; using Ryujinx.Common;
@@ -96,8 +97,13 @@ namespace Ryujinx.Headless.SDL2
} }
Parser.Default.ParseArguments<Options>(args) Parser.Default.ParseArguments<Options>(args)
.WithParsed(Load) .WithParsed(Load)
.WithNotParsed(errors => errors.Output()); .WithNotParsed(errors =>
{
Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:");
errors.ForEach(err => Logger.Error?.PrintMsg(LogClass.Application, $" - {err.Tag}"));
});
} }
private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index) private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
@@ -579,8 +585,8 @@ namespace Ryujinx.Headless.SDL2
options.MultiplayerLanInterfaceId, options.MultiplayerLanInterfaceId,
Common.Configuration.Multiplayer.MultiplayerMode.Disabled, Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
false, false,
"", string.Empty,
"", string.Empty,
options.CustomVSyncInterval); options.CustomVSyncInterval);
return new Switch(configuration); return new Switch(configuration);

View File

@@ -1,5 +1,4 @@
using DynamicData; using DynamicData;
using DynamicData.Kernel;
using Gommon; using Gommon;
using LibHac; using LibHac;
using LibHac.Common; using LibHac.Common;
@@ -37,14 +36,13 @@ using System.Threading.Tasks;
using ContentType = LibHac.Ncm.ContentType; using ContentType = LibHac.Ncm.ContentType;
using MissingKeyException = LibHac.Common.Keys.MissingKeyException; using MissingKeyException = LibHac.Common.Keys.MissingKeyException;
using Path = System.IO.Path; using Path = System.IO.Path;
using SpanHelpers = LibHac.Common.SpanHelpers;
using TimeSpan = System.TimeSpan; using TimeSpan = System.TimeSpan;
namespace Ryujinx.UI.App.Common namespace Ryujinx.UI.App.Common
{ {
public class ApplicationLibrary public class ApplicationLibrary
{ {
public static string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com"; public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
public Language DesiredLanguage { get; set; } public Language DesiredLanguage { get; set; }
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated; public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
public event EventHandler<LdnGameDataReceivedEventArgs> LdnGameDataReceived; public event EventHandler<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
@@ -191,12 +189,9 @@ namespace Ryujinx.UI.App.Common
} }
} }
if (isExeFs) return isExeFs
{ ? GetApplicationFromExeFs(pfs, filePath)
return GetApplicationFromExeFs(pfs, filePath); : null;
}
return null;
} }
/// <exception cref="LibHac.Common.Keys.MissingKeyException">The configured key set is missing a key.</exception> /// <exception cref="LibHac.Common.Keys.MissingKeyException">The configured key set is missing a key.</exception>
@@ -512,10 +507,6 @@ namespace Ryujinx.UI.App.Common
case ".xci": case ".xci":
case ".nsp": case ".nsp":
{ {
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None;
using IFileSystem pfs = PartitionFileSystemUtils.OpenApplicationFileSystem(filePath, _virtualFileSystem); using IFileSystem pfs = PartitionFileSystemUtils.OpenApplicationFileSystem(filePath, _virtualFileSystem);
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca")) foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
@@ -604,7 +595,7 @@ namespace Ryujinx.UI.App.Common
controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None) controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None)
.OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read) .OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read)
.ThrowIfFailure(); .ThrowIfFailure();
nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), nacpFile.Get.Read(out _, 0, LibHac.Common.SpanHelpers.AsByteSpan(ref controlData),
ReadOption.None).ThrowIfFailure(); ReadOption.None).ThrowIfFailure();
var displayVersion = controlData.DisplayVersionString.ToString(); var displayVersion = controlData.DisplayVersionString.ToString();
@@ -827,7 +818,7 @@ namespace Ryujinx.UI.App.Common
{ {
_downloadableContents.Edit(it => _downloadableContents.Edit(it =>
{ {
DownloadableContentsHelper.SaveDownloadableContentsJson(_virtualFileSystem, application.IdBase, dlcs); DownloadableContentsHelper.SaveDownloadableContentsJson(application.IdBase, dlcs);
it.Remove(it.Items.Where(item => item.Dlc.TitleIdBase == application.IdBase)); it.Remove(it.Items.Where(item => item.Dlc.TitleIdBase == application.IdBase));
it.AddOrUpdate(dlcs); it.AddOrUpdate(dlcs);
@@ -839,7 +830,7 @@ namespace Ryujinx.UI.App.Common
{ {
_titleUpdates.Edit(it => _titleUpdates.Edit(it =>
{ {
TitleUpdatesHelper.SaveTitleUpdatesJson(_virtualFileSystem, application.IdBase, updates); TitleUpdatesHelper.SaveTitleUpdatesJson(application.IdBase, updates);
it.Remove(it.Items.Where(item => item.TitleUpdate.TitleIdBase == application.IdBase)); it.Remove(it.Items.Where(item => item.TitleUpdate.TitleIdBase == application.IdBase));
it.AddOrUpdate(updates); it.AddOrUpdate(updates);
@@ -1088,14 +1079,15 @@ namespace Ryujinx.UI.App.Common
private bool AddAndAutoSelectUpdate(TitleUpdateModel update) private bool AddAndAutoSelectUpdate(TitleUpdateModel update)
{ {
var currentlySelected = TitleUpdates.Items.FirstOrOptional(it => if (update == null) return false;
var currentlySelected = TitleUpdates.Items.FindFirst(it =>
it.TitleUpdate.TitleIdBase == update.TitleIdBase && it.IsSelected); it.TitleUpdate.TitleIdBase == update.TitleIdBase && it.IsSelected);
var shouldSelect = !currentlySelected.HasValue || var shouldSelect = currentlySelected.Check(curr => curr.TitleUpdate?.Version < update.Version);
currentlySelected.Value.TitleUpdate.Version < update.Version;
_titleUpdates.AddOrUpdate((update, shouldSelect)); _titleUpdates.AddOrUpdate((update, shouldSelect));
if (currentlySelected.HasValue && shouldSelect) if (currentlySelected.HasValue && shouldSelect)
{ {
_titleUpdates.AddOrUpdate((currentlySelected.Value.TitleUpdate, false)); _titleUpdates.AddOrUpdate((currentlySelected.Value.TitleUpdate, false));
@@ -1464,7 +1456,7 @@ namespace Ryujinx.UI.App.Common
if (addedNewDlc) if (addedNewDlc)
{ {
var gameDlcs = it.Items.Where(dlc => dlc.Dlc.TitleIdBase == application.IdBase).ToList(); var gameDlcs = it.Items.Where(dlc => dlc.Dlc.TitleIdBase == application.IdBase).ToList();
DownloadableContentsHelper.SaveDownloadableContentsJson(_virtualFileSystem, application.IdBase, DownloadableContentsHelper.SaveDownloadableContentsJson(application.IdBase,
gameDlcs); gameDlcs);
} }
} }
@@ -1483,11 +1475,11 @@ namespace Ryujinx.UI.App.Common
TitleUpdatesHelper.LoadTitleUpdatesJson(_virtualFileSystem, application.IdBase); TitleUpdatesHelper.LoadTitleUpdatesJson(_virtualFileSystem, application.IdBase);
it.AddOrUpdate(savedUpdates); it.AddOrUpdate(savedUpdates);
var selectedUpdate = savedUpdates.FirstOrOptional(update => update.IsSelected); var selectedUpdate = savedUpdates.FindFirst(update => update.IsSelected);
if (TryGetTitleUpdatesFromFile(application.Path, out var bundledUpdates)) if (TryGetTitleUpdatesFromFile(application.Path, out var bundledUpdates))
{ {
var savedUpdateLookup = savedUpdates.Select(update => update.Item1).ToHashSet(); var savedUpdateLookup = savedUpdates.Select(update => update.Update).ToHashSet();
bool updatesChanged = false; bool updatesChanged = false;
foreach (var update in bundledUpdates.OrderByDescending(bundled => bundled.Version)) foreach (var update in bundledUpdates.OrderByDescending(bundled => bundled.Version))
@@ -1495,12 +1487,11 @@ namespace Ryujinx.UI.App.Common
if (!savedUpdateLookup.Contains(update)) if (!savedUpdateLookup.Contains(update))
{ {
bool shouldSelect = false; bool shouldSelect = false;
if (!selectedUpdate.HasValue || selectedUpdate.Value.Item1.Version < update.Version) if (selectedUpdate.Check(su => su.Update?.Version < update.Version))
{ {
shouldSelect = true; shouldSelect = true;
if (selectedUpdate.HasValue) _titleUpdates.AddOrUpdate((selectedUpdate.Value.Update, false));
_titleUpdates.AddOrUpdate((selectedUpdate.Value.Item1, false)); selectedUpdate = (update, true);
selectedUpdate = DynamicData.Kernel.Optional<(TitleUpdateModel, bool IsSelected)>.Create((update, true));
} }
modifiedVersion = modifiedVersion || shouldSelect; modifiedVersion = modifiedVersion || shouldSelect;
@@ -1513,7 +1504,7 @@ namespace Ryujinx.UI.App.Common
if (updatesChanged) if (updatesChanged)
{ {
var gameUpdates = it.Items.Where(update => update.TitleUpdate.TitleIdBase == application.IdBase).ToList(); var gameUpdates = it.Items.Where(update => update.TitleUpdate.TitleIdBase == application.IdBase).ToList();
TitleUpdatesHelper.SaveTitleUpdatesJson(_virtualFileSystem, application.IdBase, gameUpdates); TitleUpdatesHelper.SaveTitleUpdatesJson(application.IdBase, gameUpdates);
} }
} }
}); });
@@ -1525,14 +1516,14 @@ namespace Ryujinx.UI.App.Common
private void SaveDownloadableContentsForGame(ulong titleIdBase) private void SaveDownloadableContentsForGame(ulong titleIdBase)
{ {
var dlcs = DownloadableContents.Items.Where(dlc => dlc.Dlc.TitleIdBase == titleIdBase).ToList(); var dlcs = DownloadableContents.Items.Where(dlc => dlc.Dlc.TitleIdBase == titleIdBase).ToList();
DownloadableContentsHelper.SaveDownloadableContentsJson(_virtualFileSystem, titleIdBase, dlcs); DownloadableContentsHelper.SaveDownloadableContentsJson(titleIdBase, dlcs);
} }
// Save the _currently tracked_ update state for the game // Save the _currently tracked_ update state for the game
private void SaveTitleUpdatesForGame(ulong titleIdBase) private void SaveTitleUpdatesForGame(ulong titleIdBase)
{ {
var updates = TitleUpdates.Items.Where(update => update.TitleUpdate.TitleIdBase == titleIdBase).ToList(); var updates = TitleUpdates.Items.Where(update => update.TitleUpdate.TitleIdBase == titleIdBase).ToList();
TitleUpdatesHelper.SaveTitleUpdatesJson(_virtualFileSystem, titleIdBase, updates); TitleUpdatesHelper.SaveTitleUpdatesJson(titleIdBase, updates);
} }
// ApplicationData isnt live-updating (e.g. when an update gets applied) and so this is meant to trigger a refresh // ApplicationData isnt live-updating (e.g. when an update gets applied) and so this is meant to trigger a refresh

View File

@@ -1,16 +1,12 @@
using ARMeilleure;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Vulkan; using Ryujinx.Graphics.Vulkan;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.UI.Common.Configuration.System; using Ryujinx.UI.Common.Configuration.System;
using Ryujinx.UI.Common.Configuration.UI; using Ryujinx.UI.Common.Configuration.UI;
using System; using System;
using System.Collections.Generic;
namespace Ryujinx.UI.Common.Configuration namespace Ryujinx.UI.Common.Configuration
{ {
@@ -21,10 +17,10 @@ namespace Ryujinx.UI.Common.Configuration
if (Instance != null) if (Instance != null)
{ {
throw new InvalidOperationException("Configuration is already initialized"); throw new InvalidOperationException("Configuration is already initialized");
} }
Instance = new ConfigurationState(); Instance = new ConfigurationState();
} }
public ConfigurationFileFormat ToFileFormat() public ConfigurationFileFormat ToFileFormat()
{ {

View File

@@ -7,6 +7,24 @@ namespace Ryujinx.UI.Common.Helper
{ {
public static partial class ConsoleHelper public static partial class ConsoleHelper
{ {
[SupportedOSPlatform("windows")]
[LibraryImport("kernel32")]
private static partial nint GetConsoleWindow();
[SupportedOSPlatform("windows")]
[LibraryImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool ShowWindow(nint hWnd, int nCmdShow);
[SupportedOSPlatform("windows")]
[LibraryImport("user32")]
private static partial nint GetForegroundWindow();
[SupportedOSPlatform("windows")]
[LibraryImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool SetForegroundWindow(nint hWnd);
public static bool SetConsoleWindowStateSupported => OperatingSystem.IsWindows(); public static bool SetConsoleWindowStateSupported => OperatingSystem.IsWindows();
public static void SetConsoleWindowState(bool show) public static void SetConsoleWindowState(bool show)
@@ -35,16 +53,11 @@ namespace Ryujinx.UI.Common.Helper
return; return;
} }
SetForegroundWindow(hWnd);
hWnd = GetForegroundWindow();
ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE); ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
} }
[SupportedOSPlatform("windows")]
[LibraryImport("kernel32")]
private static partial nint GetConsoleWindow();
[SupportedOSPlatform("windows")]
[LibraryImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool ShowWindow(nint hWnd, int nCmdShow);
} }
} }

View File

@@ -42,7 +42,7 @@ namespace Ryujinx.UI.Common.Helper
} }
} }
public static void SaveDownloadableContentsJson(VirtualFileSystem vfs, ulong applicationIdBase, List<(DownloadableContentModel, bool IsEnabled)> dlcs) public static void SaveDownloadableContentsJson(ulong applicationIdBase, List<(DownloadableContentModel, bool IsEnabled)> dlcs)
{ {
DownloadableContentContainer container = default; DownloadableContentContainer container = default;
List<DownloadableContentContainer> downloadableContentContainerList = new(); List<DownloadableContentContainer> downloadableContentContainerList = new();

View File

@@ -28,7 +28,7 @@ namespace Ryujinx.UI.Common.Helper
{ {
private static readonly TitleUpdateMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly TitleUpdateMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
public static List<(TitleUpdateModel, bool IsSelected)> LoadTitleUpdatesJson(VirtualFileSystem vfs, ulong applicationIdBase) public static List<(TitleUpdateModel Update, bool IsSelected)> LoadTitleUpdatesJson(VirtualFileSystem vfs, ulong applicationIdBase)
{ {
var titleUpdatesJsonPath = PathToGameUpdatesJson(applicationIdBase); var titleUpdatesJsonPath = PathToGameUpdatesJson(applicationIdBase);
@@ -49,7 +49,7 @@ namespace Ryujinx.UI.Common.Helper
} }
} }
public static void SaveTitleUpdatesJson(VirtualFileSystem vfs, ulong applicationIdBase, List<(TitleUpdateModel, bool IsSelected)> updates) public static void SaveTitleUpdatesJson(ulong applicationIdBase, List<(TitleUpdateModel, bool IsSelected)> updates)
{ {
var titleUpdateWindowData = new TitleUpdateMetadata var titleUpdateWindowData = new TitleUpdateMetadata
{ {
@@ -77,7 +77,7 @@ namespace Ryujinx.UI.Common.Helper
JsonHelper.SerializeToFile(titleUpdatesJsonPath, titleUpdateWindowData, _serializerContext.TitleUpdateMetadata); JsonHelper.SerializeToFile(titleUpdatesJsonPath, titleUpdateWindowData, _serializerContext.TitleUpdateMetadata);
} }
private static List<(TitleUpdateModel, bool IsSelected)> LoadTitleUpdates(VirtualFileSystem vfs, TitleUpdateMetadata titleUpdateMetadata, ulong applicationIdBase) private static List<(TitleUpdateModel Update, bool IsSelected)> LoadTitleUpdates(VirtualFileSystem vfs, TitleUpdateMetadata titleUpdateMetadata, ulong applicationIdBase)
{ {
var result = new List<(TitleUpdateModel, bool IsSelected)>(); var result = new List<(TitleUpdateModel, bool IsSelected)>();

View File

@@ -11,7 +11,7 @@
</ResourceDictionary> </ResourceDictionary>
</Application.Resources> </Application.Resources>
<Application.Styles> <Application.Styles>
<sty:FluentAvaloniaTheme PreferSystemTheme="False" /> <sty:FluentAvaloniaTheme PreferUserAccentColor="True" PreferSystemTheme="False" />
<StyleInclude Source="/Assets/Styles/Styles.xaml" /> <StyleInclude Source="/Assets/Styles/Styles.xaml" />
</Application.Styles> </Application.Styles>
</Application> </Application>

View File

@@ -3,6 +3,8 @@ using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Threading; using Avalonia.Threading;
using LibHac.Common;
using LibHac.Ns;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.Dummy; using Ryujinx.Audio.Backends.Dummy;
using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.OpenAL;
@@ -670,7 +672,7 @@ namespace Ryujinx.Ava
_cursorState = CursorStates.ForceChangeCursor; _cursorState = CursorStates.ForceChangeCursor;
} }
public async Task<bool> LoadGuestApplication() public async Task<bool> LoadGuestApplication(BlitStruct<ApplicationControlProperty>? customNacpData = null)
{ {
InitializeSwitchInstance(); InitializeSwitchInstance();
MainWindow.UpdateGraphicsConfig(); MainWindow.UpdateGraphicsConfig();
@@ -740,7 +742,7 @@ namespace Ryujinx.Ava
{ {
Logger.Info?.Print(LogClass.Application, "Loading as Firmware Title (NCA)."); Logger.Info?.Print(LogClass.Application, "Loading as Firmware Title (NCA).");
if (!Device.LoadNca(ApplicationPath)) if (!Device.LoadNca(ApplicationPath, customNacpData))
{ {
Device.Dispose(); Device.Dispose();

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "الغش متوفر لـ {0} [{1}]", "CheatWindowHeading": "الغش متوفر لـ {0} [{1}]",
"BuildId": "معرف البناء:", "BuildId": "معرف البناء:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "المحتويات القابلة للتنزيل {0}", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "Cheats verfügbar für {0} [{1}]", "CheatWindowHeading": "Cheats verfügbar für {0} [{1}]",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"BuildId": "BuildId:", "BuildId": "BuildId:",
"DlcWindowHeading": "DLC verfügbar für {0} [{1}]", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "Διαθέσιμα Cheats για {0} [{1}]", "CheatWindowHeading": "Διαθέσιμα Cheats για {0} [{1}]",
"BuildId": "BuildId:", "BuildId": "BuildId:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",

View File

@@ -802,7 +802,7 @@
"CheatWindowHeading": "Cheats Available for {0} [{1}]", "CheatWindowHeading": "Cheats Available for {0} [{1}]",
"BuildId": "BuildId:", "BuildId": "BuildId:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",

View File

@@ -31,14 +31,14 @@
"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", "MenuBarToolsInstallKeys": "Instalar Keys",
"MenuBarFileToolsInstallKeysFromFile": "Instalar keys de KEYS o ZIP", "MenuBarFileToolsInstallKeysFromFile": "Instalar keys de KEYS o ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Instalar keys de un directorio", "MenuBarFileToolsInstallKeysFromFolder": "Instalar keys de un directorio",
"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",
"MenuBarToolsXCITrimmer": "Recortar archivos XCI", "MenuBarToolsXCITrimmer": "Recortar archivos XCI",
"MenuBarView": "_View", "MenuBarView": "_Vista",
"MenuBarViewWindow": "Tamaño Ventana", "MenuBarViewWindow": "Tamaño Ventana",
"MenuBarViewWindow720": "720p", "MenuBarViewWindow720": "720p",
"MenuBarViewWindow1080": "1080p", "MenuBarViewWindow1080": "1080p",
@@ -148,6 +148,18 @@
"SettingsTabSystemSystemLanguageTraditionalChinese": "Chino tradicional", "SettingsTabSystemSystemLanguageTraditionalChinese": "Chino tradicional",
"SettingsTabSystemSystemTimeZone": "Zona horaria del sistema:", "SettingsTabSystemSystemTimeZone": "Zona horaria del sistema:",
"SettingsTabSystemSystemTime": "Hora del sistema:", "SettingsTabSystemSystemTime": "Hora del sistema:",
"SettingsTabSystemVSyncMode": "Sincronización vertical:",
"SettingsTabSystemEnableCustomVSyncInterval": "Activar tasa de refresco personalizada (Experimental)",
"SettingsTabSystemVSyncModeSwitch": "Switch",
"SettingsTabSystemVSyncModeUnbounded": "Sin límite",
"SettingsTabSystemVSyncModeCustom": "Tasa de refresco personalizada",
"SettingsTabSystemVSyncModeTooltip": "Sincronización vertical a emular. 'Switch' emula la tasa de refresco de 60Hz de la Switch. 'Sin límite' es una tasa de refresco sin límite.",
"SettingsTabSystemVSyncModeTooltipCustom": "Sincronización vertical a emular. 'Switch' emula la tasa de refresco de 60Hz de la Switch. 'Sin límite' es una tasa de refresco sin límite. 'Personalizada' emula la tasa de refresco especificada.",
"SettingsTabSystemEnableCustomVSyncIntervalTooltip": "Permite al usuario especificar una tasa de refresco personalizada. En algunos títulos, puede acelerar o ralentizar la lógica del juego. En otros, puede permitir limitar los FPS a cierto múltiplo de la tasa de refresco, o producir comportamiento impredecible. Ésta es una característica experimiental, sin garantías de como se afectará la jugabilidad. \n\nDesactívalo si no sabes que hacer.",
"SettingsTabSystemCustomVSyncIntervalValueTooltip": "El valor objetivo de la tasa de refresco personalizada.",
"SettingsTabSystemCustomVSyncIntervalSliderTooltip": "La tasa de refresco personalizada, como un porcentaje de la tasa de refresco normal de la Switch.",
"SettingsTabSystemCustomVSyncIntervalPercentage": "% de tasa de refresco personalizada:",
"SettingsTabSystemCustomVSyncIntervalValue": "Valor de tasa de refresco personalizada:",
"SettingsTabSystemEnableVsync": "Sincronización vertical", "SettingsTabSystemEnableVsync": "Sincronización vertical",
"SettingsTabSystemEnablePptc": "PPTC (Cache de Traducción de Perfil Persistente)", "SettingsTabSystemEnablePptc": "PPTC (Cache de Traducción de Perfil Persistente)",
"SettingsTabSystemEnableLowPowerPptc": "Cache PPTC de bajo consumo", "SettingsTabSystemEnableLowPowerPptc": "Cache PPTC de bajo consumo",
@@ -292,58 +304,58 @@
"ControllerSettingsSave": "Guardar", "ControllerSettingsSave": "Guardar",
"ControllerSettingsClose": "Cerrar", "ControllerSettingsClose": "Cerrar",
"KeyUnknown": "Desconocido", "KeyUnknown": "Desconocido",
"KeyShiftLeft": "Shift Left", "KeyShiftLeft": "Shift Izq.",
"KeyShiftRight": "Shift Right", "KeyShiftRight": "Shift Der.",
"KeyControlLeft": "Ctrl Left", "KeyControlLeft": "Ctrl Izq.",
"KeyMacControlLeft": "⌃ Left", "KeyMacControlLeft": "⌃ Izq.",
"KeyControlRight": "Ctrl Right", "KeyControlRight": "Ctrl Der.",
"KeyMacControlRight": "⌃ Right", "KeyMacControlRight": "⌃ Der.",
"KeyAltLeft": "Alt Left", "KeyAltLeft": "Alt Izq.",
"KeyMacAltLeft": "⌥ Left", "KeyMacAltLeft": "⌥ Izq.",
"KeyAltRight": "Alt Right", "KeyAltRight": "Alt Der.",
"KeyMacAltRight": "⌥ Right", "KeyMacAltRight": "⌥ Der.",
"KeyWinLeft": "⊞ Left", "KeyWinLeft": "⊞ Izq.",
"KeyMacWinLeft": "⌘ Left", "KeyMacWinLeft": "⌘ Izq.",
"KeyWinRight": "⊞ Right", "KeyWinRight": "⊞ Der.",
"KeyMacWinRight": "⌘ Right", "KeyMacWinRight": "⌘ Der.",
"KeyMenu": "Menu", "KeyMenu": "Menú",
"KeyUp": "Up", "KeyUp": "Arriba",
"KeyDown": "Down", "KeyDown": "Abajo",
"KeyLeft": "Left", "KeyLeft": "Izq.",
"KeyRight": "Right", "KeyRight": "Der.",
"KeyEnter": "Enter", "KeyEnter": "Enter",
"KeyEscape": "Escape", "KeyEscape": "Escape",
"KeySpace": "Space", "KeySpace": "Espacio",
"KeyTab": "Tab", "KeyTab": "Tab",
"KeyBackSpace": "Backspace", "KeyBackSpace": "Retroceso",
"KeyInsert": "Insert", "KeyInsert": "Insertar",
"KeyDelete": "Delete", "KeyDelete": "Suprimir",
"KeyPageUp": "Page Up", "KeyPageUp": "Av. Pág.",
"KeyPageDown": "Page Down", "KeyPageDown": "Re. Pág",
"KeyHome": "Home", "KeyHome": "Inicio",
"KeyEnd": "End", "KeyEnd": "Fin",
"KeyCapsLock": "Caps Lock", "KeyCapsLock": "Bloq. Mayús.",
"KeyScrollLock": "Scroll Lock", "KeyScrollLock": "Bloq. Despl.",
"KeyPrintScreen": "Print Screen", "KeyPrintScreen": "Impr. Pant.",
"KeyPause": "Pause", "KeyPause": "Pausa",
"KeyNumLock": "Num Lock", "KeyNumLock": "Bloq. Num.",
"KeyClear": "Clear", "KeyClear": "Clear",
"KeyKeypad0": "Keypad 0", "KeyKeypad0": "0 tec. num.",
"KeyKeypad1": "Keypad 1", "KeyKeypad1": "1 tec. num.",
"KeyKeypad2": "Keypad 2", "KeyKeypad2": "2 tec. num.",
"KeyKeypad3": "Keypad 3", "KeyKeypad3": "3 tec. num.",
"KeyKeypad4": "Keypad 4", "KeyKeypad4": "4 tec. num.",
"KeyKeypad5": "Keypad 5", "KeyKeypad5": "5 tec. num.",
"KeyKeypad6": "Keypad 6", "KeyKeypad6": "6 tec. num.",
"KeyKeypad7": "Keypad 7", "KeyKeypad7": "7 tec. num.",
"KeyKeypad8": "Keypad 8", "KeyKeypad8": "8 tec. num.",
"KeyKeypad9": "Keypad 9", "KeyKeypad9": "9 tec. num.",
"KeyKeypadDivide": "Keypad Divide", "KeyKeypadDivide": "Dividir tec. num.",
"KeyKeypadMultiply": "Keypad Multiply", "KeyKeypadMultiply": "Multiplicar tec. num.",
"KeyKeypadSubtract": "Keypad Subtract", "KeyKeypadSubtract": "Resta tec. num.",
"KeyKeypadAdd": "Keypad Add", "KeyKeypadAdd": "Suma tec. num.",
"KeyKeypadDecimal": "Keypad Decimal", "KeyKeypadDecimal": "Decimal tec. num.",
"KeyKeypadEnter": "Keypad Enter", "KeyKeypadEnter": "Enter tec. num.",
"KeyNumber0": "0", "KeyNumber0": "0",
"KeyNumber1": "1", "KeyNumber1": "1",
"KeyNumber2": "2", "KeyNumber2": "2",
@@ -366,32 +378,32 @@
"KeyPeriod": ".", "KeyPeriod": ".",
"KeySlash": "/", "KeySlash": "/",
"KeyBackSlash": "\\", "KeyBackSlash": "\\",
"KeyUnbound": "Unbound", "KeyUnbound": "S. reg.",
"GamepadLeftStick": "L Stick Button", "GamepadLeftStick": "Botón A. Izq.",
"GamepadRightStick": "R Stick Button", "GamepadRightStick": "Botón A. Der.",
"GamepadLeftShoulder": "Left Shoulder", "GamepadLeftShoulder": "Hombro izq.",
"GamepadRightShoulder": "Right Shoulder", "GamepadRightShoulder": "Hombro der.",
"GamepadLeftTrigger": "Left Trigger", "GamepadLeftTrigger": "Trigger izq.",
"GamepadRightTrigger": "Right Trigger", "GamepadRightTrigger": "Trigger der.",
"GamepadDpadUp": "Up", "GamepadDpadUp": "Arriba",
"GamepadDpadDown": "Down", "GamepadDpadDown": "Abajo",
"GamepadDpadLeft": "Left", "GamepadDpadLeft": "Izq.",
"GamepadDpadRight": "Right", "GamepadDpadRight": "Der.",
"GamepadMinus": "-", "GamepadMinus": "-",
"GamepadPlus": "+", "GamepadPlus": "+",
"GamepadGuide": "Guide", "GamepadGuide": "Guía",
"GamepadMisc1": "Misc", "GamepadMisc1": "Misc.",
"GamepadPaddle1": "Paddle 1", "GamepadPaddle1": "Paddle 1",
"GamepadPaddle2": "Paddle 2", "GamepadPaddle2": "Paddle 2",
"GamepadPaddle3": "Paddle 3", "GamepadPaddle3": "Paddle 3",
"GamepadPaddle4": "Paddle 4", "GamepadPaddle4": "Paddle 4",
"GamepadTouchpad": "Touchpad", "GamepadTouchpad": "Panel tác.",
"GamepadSingleLeftTrigger0": "Left Trigger 0", "GamepadSingleLeftTrigger0": "Trigger izq. 0",
"GamepadSingleRightTrigger0": "Right Trigger 0", "GamepadSingleRightTrigger0": "Trigger der. 0",
"GamepadSingleLeftTrigger1": "Left Trigger 1", "GamepadSingleLeftTrigger1": "Trigger izq. 1",
"GamepadSingleRightTrigger1": "Right Trigger 1", "GamepadSingleRightTrigger1": "Trigger der. 1",
"StickLeft": "Left Stick", "StickLeft": "Análogo izq.",
"StickRight": "Right Stick", "StickRight": "Análogo der.",
"UserProfilesSelectedUserProfile": "Perfil de usuario seleccionado:", "UserProfilesSelectedUserProfile": "Perfil de usuario seleccionado:",
"UserProfilesSaveProfileName": "Guardar nombre de perfil", "UserProfilesSaveProfileName": "Guardar nombre de perfil",
"UserProfilesChangeProfileImage": "Cambiar imagen de perfil", "UserProfilesChangeProfileImage": "Cambiar imagen de perfil",
@@ -408,8 +420,8 @@
"InputDialogTitle": "Cuadro de diálogo de entrada", "InputDialogTitle": "Cuadro de diálogo de entrada",
"InputDialogOk": "Aceptar", "InputDialogOk": "Aceptar",
"InputDialogCancel": "Cancelar", "InputDialogCancel": "Cancelar",
"InputDialogCancelling": "Cancelling", "InputDialogCancelling": "Cancelando",
"InputDialogClose": "Close", "InputDialogClose": "Cerrar",
"InputDialogAddNewProfileTitle": "Introducir nombre de perfil", "InputDialogAddNewProfileTitle": "Introducir nombre de perfil",
"InputDialogAddNewProfileHeader": "Por favor elige un nombre de usuario", "InputDialogAddNewProfileHeader": "Por favor elige un nombre de usuario",
"InputDialogAddNewProfileSubtext": "(Máximo de caracteres: {0})", "InputDialogAddNewProfileSubtext": "(Máximo de caracteres: {0})",
@@ -461,7 +473,7 @@
"DialogUpdaterExtractionMessage": "Extrayendo actualización...", "DialogUpdaterExtractionMessage": "Extrayendo actualización...",
"DialogUpdaterRenamingMessage": "Renombrando actualización...", "DialogUpdaterRenamingMessage": "Renombrando actualización...",
"DialogUpdaterAddingFilesMessage": "Aplicando actualización...", "DialogUpdaterAddingFilesMessage": "Aplicando actualización...",
"DialogUpdaterShowChangelogMessage": "Show Changelog", "DialogUpdaterShowChangelogMessage": "Mostrar reg. de cambios",
"DialogUpdaterCompleteMessage": "¡Actualización completa!", "DialogUpdaterCompleteMessage": "¡Actualización completa!",
"DialogUpdaterRestartMessage": "¿Quieres reiniciar Ryujinx?", "DialogUpdaterRestartMessage": "¿Quieres reiniciar Ryujinx?",
"DialogUpdaterNoInternetMessage": "¡No estás conectado a internet!", "DialogUpdaterNoInternetMessage": "¡No estás conectado a internet!",
@@ -733,11 +745,14 @@
"RyujinxUpdater": "Actualizador de Ryujinx", "RyujinxUpdater": "Actualizador de Ryujinx",
"SettingsTabHotkeys": "Atajos de teclado", "SettingsTabHotkeys": "Atajos de teclado",
"SettingsTabHotkeysHotkeys": "Atajos de teclado", "SettingsTabHotkeysHotkeys": "Atajos de teclado",
"SettingsTabHotkeysToggleVSyncModeHotkey": "Activar modo sincronización vertical:",
"SettingsTabHotkeysToggleVsyncHotkey": "Alternar la sincronización vertical:", "SettingsTabHotkeysToggleVsyncHotkey": "Alternar la sincronización vertical:",
"SettingsTabHotkeysScreenshotHotkey": "Captura de pantalla:", "SettingsTabHotkeysScreenshotHotkey": "Captura de pantalla:",
"SettingsTabHotkeysShowUiHotkey": "Mostrar interfaz:", "SettingsTabHotkeysShowUiHotkey": "Mostrar interfaz:",
"SettingsTabHotkeysPauseHotkey": "Pausar:", "SettingsTabHotkeysPauseHotkey": "Pausar:",
"SettingsTabHotkeysToggleMuteHotkey": "Silenciar:", "SettingsTabHotkeysToggleMuteHotkey": "Silenciar:",
"SettingsTabHotkeysIncrementCustomVSyncIntervalHotkey": "Aumentar tasa de refresco personalizada:",
"SettingsTabHotkeysDecrementCustomVSyncIntervalHotkey": "Reducir tasa de refresco personalizada:",
"ControllerMotionTitle": "Opciones de controles de movimiento", "ControllerMotionTitle": "Opciones de controles de movimiento",
"ControllerRumbleTitle": "Opciones de vibración", "ControllerRumbleTitle": "Opciones de vibración",
"SettingsSelectThemeFileDialogTitle": "Selecciona un archivo de tema", "SettingsSelectThemeFileDialogTitle": "Selecciona un archivo de tema",
@@ -787,7 +802,7 @@
"UpdateWindowBundledContentNotice": "Las actualizaciones agrupadas no pueden ser eliminadas, solamente deshabilitadas.", "UpdateWindowBundledContentNotice": "Las actualizaciones agrupadas no pueden ser eliminadas, solamente deshabilitadas.",
"CheatWindowHeading": "Cheats disponibles para {0} [{1}]", "CheatWindowHeading": "Cheats disponibles para {0} [{1}]",
"BuildId": "Id de compilación:", "BuildId": "Id de compilación:",
"DlcWindowHeading": "Contenido descargable disponible para {0} [{1}]", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "Se agregaron {0} nuevo(s) contenido(s) descargable(s)", "DlcWindowDlcAddedMessage": "Se agregaron {0} nuevo(s) contenido(s) descargable(s)",
"AutoloadDlcAddedMessage": "Se agregaron {0} nuevo(s) contenido(s) descargable(s)", "AutoloadDlcAddedMessage": "Se agregaron {0} nuevo(s) contenido(s) descargable(s)",
"AutoloadDlcRemovedMessage": "Se eliminaron {0} contenido(s) descargable(s) faltantes", "AutoloadDlcRemovedMessage": "Se eliminaron {0} contenido(s) descargable(s) faltantes",
@@ -837,7 +852,7 @@
"Recover": "Recuperar", "Recover": "Recuperar",
"UserProfilesRecoverHeading": "Datos de guardado fueron encontrados para las siguientes cuentas", "UserProfilesRecoverHeading": "Datos de guardado fueron encontrados para las siguientes cuentas",
"UserProfilesRecoverEmptyList": "No hay perfiles a recuperar", "UserProfilesRecoverEmptyList": "No hay perfiles a recuperar",
"GraphicsAATooltip": "Aplica antia-aliasing al rendereo del juego.\n\nFXAA desenfocará la mayor parte del la iamgen, mientras que SMAA intentará encontrar bordes irregulares y suavizarlos.\n\nNo se recomienda usar en conjunto con filtro de escala FSR.\n\nEsta opción puede ser modificada mientras que esté corriendo el juego haciendo click en \"Aplicar\" más abajo; simplemente puedes mover la ventana de configuración a un lado y experimentar hasta que encuentres tu estilo preferido para un juego.\n\nDejar en NADA si no está seguro.", "GraphicsAATooltip": "Aplica anti-aliasing al rendereo del juego.\n\nFXAA desenfocará la mayor parte del la iamgen, mientras que SMAA intentará encontrar bordes irregulares y suavizarlos.\n\nNo se recomienda usar en conjunto con filtro de escala FSR.\n\nEsta opción puede ser modificada mientras que esté corriendo el juego haciendo click en \"Aplicar\" más abajo; simplemente puedes mover la ventana de configuración a un lado y experimentar hasta que encuentres tu estilo preferido para un juego.\n\nDejar en NADA si no está seguro.",
"GraphicsAALabel": "Suavizado de bordes:", "GraphicsAALabel": "Suavizado de bordes:",
"GraphicsScalingFilterLabel": "Filtro de escalado:", "GraphicsScalingFilterLabel": "Filtro de escalado:",
"GraphicsScalingFilterTooltip": "Elija el filtro de escala que se aplicará al utilizar la escala de resolución.\n\nBilinear funciona bien para juegos 3D y es una opción predeterminada segura.\n\nSe recomienda el bilinear para juegos de pixel art.\n\nFSR 1.0 es simplemente un filtro de afilado, no se recomienda su uso con FXAA o SMAA.\n\nEsta opción se puede cambiar mientras se ejecuta un juego haciendo clic en \"Aplicar\" a continuación; simplemente puedes mover la ventana de configuración a un lado y experimentar hasta que encuentres tu estilo preferido para un juego.\n\nDéjelo en BILINEAR si no está seguro.", "GraphicsScalingFilterTooltip": "Elija el filtro de escala que se aplicará al utilizar la escala de resolución.\n\nBilinear funciona bien para juegos 3D y es una opción predeterminada segura.\n\nSe recomienda el bilinear para juegos de pixel art.\n\nFSR 1.0 es simplemente un filtro de afilado, no se recomienda su uso con FXAA o SMAA.\n\nEsta opción se puede cambiar mientras se ejecuta un juego haciendo clic en \"Aplicar\" a continuación; simplemente puedes mover la ventana de configuración a un lado y experimentar hasta que encuentres tu estilo preferido para un juego.\n\nDéjelo en BILINEAR si no está seguro.",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "Cheats disponibles pour {0} [{1}]", "CheatWindowHeading": "Cheats disponibles pour {0} [{1}]",
"BuildId": "BuildId :", "BuildId": "BuildId :",
"DlcWindowBundledContentNotice": "Les DLC inclus avec le jeu ne peuvent pas être supprimés mais peuvent être désactivés.", "DlcWindowBundledContentNotice": "Les DLC inclus avec le jeu ne peuvent pas être supprimés mais peuvent être désactivés.",
"DlcWindowHeading": "{0} Contenu(s) téléchargeable(s)", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} nouveau(x) contenu(s) téléchargeable(s) ajouté(s)", "DlcWindowDlcAddedMessage": "{0} nouveau(x) contenu(s) téléchargeable(s) ajouté(s)",
"AutoloadDlcAddedMessage": "{0} nouveau(x) contenu(s) téléchargeable(s) ajouté(s)", "AutoloadDlcAddedMessage": "{0} nouveau(x) contenu(s) téléchargeable(s) ajouté(s)",
"AutoloadDlcRemovedMessage": "{0} contenu(s) téléchargeable(s) manquant(s) supprimé(s)", "AutoloadDlcRemovedMessage": "{0} contenu(s) téléchargeable(s) manquant(s) supprimé(s)",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "Trucchi disponibili per {0} [{1}]", "CheatWindowHeading": "Trucchi disponibili per {0} [{1}]",
"BuildId": "ID Build", "BuildId": "ID Build",
"DlcWindowBundledContentNotice": "i DLC \"impacchettati\" non possono essere rimossi, ma solo disabilitati.", "DlcWindowBundledContentNotice": "i DLC \"impacchettati\" non possono essere rimossi, ma solo disabilitati.",
"DlcWindowHeading": "DLC disponibili per {0} [{1}]", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} nuovo/i contenuto/i scaricabile/i aggiunto/i", "DlcWindowDlcAddedMessage": "{0} nuovo/i contenuto/i scaricabile/i aggiunto/i",
"AutoloadDlcAddedMessage": "{0} contenuto/i scaricabile/i aggiunto/i", "AutoloadDlcAddedMessage": "{0} contenuto/i scaricabile/i aggiunto/i",
"AutoloadDlcRemovedMessage": "{0} contenuto/i scaricabile/i mancante/i rimosso/i", "AutoloadDlcRemovedMessage": "{0} contenuto/i scaricabile/i mancante/i rimosso/i",

View File

@@ -787,7 +787,7 @@
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "利用可能なチート {0} [{1}]", "CheatWindowHeading": "利用可能なチート {0} [{1}]",
"BuildId": "ビルドID:", "BuildId": "ビルドID:",
"DlcWindowHeading": "利用可能な DLC {0} [{1}]", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "{0} [{1}]에 사용 가능한 치트", "CheatWindowHeading": "{0} [{1}]에 사용 가능한 치트",
"BuildId": "빌드ID:", "BuildId": "빌드ID:",
"DlcWindowBundledContentNotice": "번들 DLC는 제거할 수 없으며 비활성화만 가능합니다.", "DlcWindowBundledContentNotice": "번들 DLC는 제거할 수 없으며 비활성화만 가능합니다.",
"DlcWindowHeading": "{1} ({2})에 내려받기 가능한 콘텐츠 {0}개 사용 가능", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0}개의 새로운 내려받기 가능한 콘텐츠가 추가됨", "DlcWindowDlcAddedMessage": "{0}개의 새로운 내려받기 가능한 콘텐츠가 추가됨",
"AutoloadDlcAddedMessage": "{0}개의 새로운 내려받기 가능한 콘텐츠가 추가됨", "AutoloadDlcAddedMessage": "{0}개의 새로운 내려받기 가능한 콘텐츠가 추가됨",
"AutoloadDlcRemovedMessage": "{0}개의 내려받기 가능한 콘텐츠가 제거됨", "AutoloadDlcRemovedMessage": "{0}개의 내려받기 가능한 콘텐츠가 제거됨",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "Kody Dostępne dla {0} [{1}]", "CheatWindowHeading": "Kody Dostępne dla {0} [{1}]",
"BuildId": "Identyfikator wersji:", "BuildId": "Identyfikator wersji:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} Zawartości do Pobrania dostępna dla {1} ({2})", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",

View File

@@ -787,7 +787,7 @@
"CheatWindowHeading": "Cheats disponíveis para {0} [{1}]", "CheatWindowHeading": "Cheats disponíveis para {0} [{1}]",
"BuildId": "ID da Build:", "BuildId": "ID da Build:",
"DlcWindowBundledContentNotice": "DLCs incorporadas não podem ser removidas, apenas desativadas.", "DlcWindowBundledContentNotice": "DLCs incorporadas não podem ser removidas, apenas desativadas.",
"DlcWindowHeading": "{0} DLCs disponíveis para {1} ({2})", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} novo(s) conteúdo(s) para download adicionado(s)", "DlcWindowDlcAddedMessage": "{0} novo(s) conteúdo(s) para download adicionado(s)",
"AutoloadDlcAddedMessage": "{0} novo(s) conteúdo(s) para download adicionado(s)", "AutoloadDlcAddedMessage": "{0} novo(s) conteúdo(s) para download adicionado(s)",
"AutoloadDlcRemovedMessage": "{0} conteúdo(s) para download ausente(s) removido(s)", "AutoloadDlcRemovedMessage": "{0} conteúdo(s) para download ausente(s) removido(s)",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "Доступные читы для {0} [{1}]", "CheatWindowHeading": "Доступные читы для {0} [{1}]",
"BuildId": "ID версии:", "BuildId": "ID версии:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} DLC", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "สูตรโกงมีให้สำหรับ {0} [{1}]", "CheatWindowHeading": "สูตรโกงมีให้สำหรับ {0} [{1}]",
"BuildId": "รหัสการสร้าง:", "BuildId": "รหัสการสร้าง:",
"DlcWindowBundledContentNotice": "แพ็ค DLC ไม่สามารถลบทิ้งได้ สามารถปิดใช้งานได้เท่านั้น", "DlcWindowBundledContentNotice": "แพ็ค DLC ไม่สามารถลบทิ้งได้ สามารถปิดใช้งานได้เท่านั้น",
"DlcWindowHeading": "{0} DLC ที่สามารถดาวน์โหลดได้", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} DLC ใหม่ที่เพิ่มเข้ามา", "DlcWindowDlcAddedMessage": "{0} DLC ใหม่ที่เพิ่มเข้ามา",
"AutoloadDlcAddedMessage": "{0} ใหม่ที่เพิ่มเข้ามา", "AutoloadDlcAddedMessage": "{0} ใหม่ที่เพิ่มเข้ามา",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "{0} için Hile mevcut [{1}]", "CheatWindowHeading": "{0} için Hile mevcut [{1}]",
"BuildId": "BuildId:", "BuildId": "BuildId:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "Коди доступні для {0} [{1}]", "CheatWindowHeading": "Коди доступні для {0} [{1}]",
"BuildId": "ID збірки:", "BuildId": "ID збірки:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "Вміст для завантаження, доступний для {1} ({2}): {0}", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",

View File

@@ -788,7 +788,7 @@
"CheatWindowHeading": "可用於 {0} [{1}] 的密技", "CheatWindowHeading": "可用於 {0} [{1}] 的密技",
"BuildId": "組建識別碼:", "BuildId": "組建識別碼:",
"DlcWindowBundledContentNotice": "附帶的 DLC 只能被停用而無法被刪除。", "DlcWindowBundledContentNotice": "附帶的 DLC 只能被停用而無法被刪除。",
"DlcWindowHeading": "{0} 個可下載內容", "DlcWindowHeading": "{0} DLC(s) available",
"DlcWindowDlcAddedMessage": "已加入 {0} 個 DLC", "DlcWindowDlcAddedMessage": "已加入 {0} 個 DLC",
"AutoloadDlcAddedMessage": "已加入 {0} 個 DLC", "AutoloadDlcAddedMessage": "已加入 {0} 個 DLC",
"AutoloadDlcRemovedMessage": "已刪除 {0} 個遺失的 DLC", "AutoloadDlcRemovedMessage": "已刪除 {0} 個遺失的 DLC",

View File

@@ -4,18 +4,6 @@
<ResourceDictionary x:Key="Default"> <ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
Color="{DynamicResource DataGridSelectionColor}" /> Color="{DynamicResource DataGridSelectionColor}" />
<SolidColorBrush x:Key="ThemeAccentColorBrush"
Color="{DynamicResource SystemAccentColor}" />
<SolidColorBrush x:Key="ThemeAccentBrush4"
Color="{DynamicResource ThemeAccentColor4}" />
<Color x:Key="SystemAccentColor">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorDark1">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorDark2">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorDark3">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorLight1">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorLight2">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorLight3">#FF00C3E3</Color>
<Color x:Key="ThemeAccentColor4">#FFe8e8e8</Color>
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color> <Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
<Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color> <Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color>
<Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color> <Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color>
@@ -26,6 +14,7 @@
<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="FavoriteApplicationIconColor">#fffcd12a</Color>
<Color x:Key="Switch">#FF2EEAC9</Color> <Color x:Key="Switch">#FF2EEAC9</Color>
<Color x:Key="Unbounded">#FFFF4554</Color> <Color x:Key="Unbounded">#FFFF4554</Color>
<Color x:Key="Custom">#6483F5</Color> <Color x:Key="Custom">#6483F5</Color>
@@ -33,18 +22,6 @@
<ResourceDictionary x:Key="Light"> <ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
Color="{DynamicResource DataGridSelectionColor}" /> Color="{DynamicResource DataGridSelectionColor}" />
<SolidColorBrush x:Key="ThemeAccentColorBrush"
Color="{DynamicResource SystemAccentColor}" />
<SolidColorBrush x:Key="ThemeAccentBrush4"
Color="{DynamicResource ThemeAccentColor4}" />
<Color x:Key="SystemAccentColor">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorDark1">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorDark2">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorDark3">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorLight1">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorLight2">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorLight3">#FF00C3E3</Color>
<Color x:Key="ThemeAccentColor4">#FFe8e8e8</Color>
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color> <Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
<Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color> <Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color>
<Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color> <Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color>
@@ -59,18 +36,7 @@
<ResourceDictionary x:Key="Dark"> <ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
Color="{DynamicResource DataGridSelectionColor}" /> Color="{DynamicResource DataGridSelectionColor}" />
<SolidColorBrush x:Key="ThemeAccentColorBrush"
Color="{DynamicResource SystemAccentColor}" />
<SolidColorBrush x:Key="ThemeAccentBrush4"
Color="{DynamicResource ThemeAccentColor4}" />
<Color x:Key="ControlFillColorSecondary">#008AA8</Color> <Color x:Key="ControlFillColorSecondary">#008AA8</Color>
<Color x:Key="SystemAccentColor">#FF00C3E3</Color>
<Color x:Key="SystemAccentColorDark1">#FF99b000</Color>
<Color x:Key="SystemAccentColorDark2">#FF006d7d</Color>
<Color x:Key="SystemAccentColorDark3">#FF00525E</Color>
<Color x:Key="SystemAccentColorLight1">#FF00dbff</Color>
<Color x:Key="SystemAccentColorLight2">#FF19dfff</Color>
<Color x:Key="SystemAccentColorLight3">#FF33e3ff</Color>
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color> <Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
<Color x:Key="ThemeContentBackgroundColor">#FF2D2D2D</Color> <Color x:Key="ThemeContentBackgroundColor">#FF2D2D2D</Color>
<Color x:Key="ThemeControlBorderColor">#FF505050</Color> <Color x:Key="ThemeControlBorderColor">#FF505050</Color>

View File

@@ -17,13 +17,13 @@ namespace Ryujinx.Ava.Common.Markup
public virtual string Name => "Item"; public virtual string Name => "Item";
public virtual Action<object, T?>? Setter => null; public virtual Action<object, T?>? Setter => null;
protected abstract T? GetValue(); protected abstract T? Value { get; }
protected virtual void ConfigureBindingExtension(CompiledBindingExtension _) { } protected virtual void ConfigureBindingExtension(CompiledBindingExtension _) { }
private ClrPropertyInfo PropertyInfo => private ClrPropertyInfo PropertyInfo =>
new(Name, new(Name,
_ => GetValue(), _ => Value,
Setter as Action<object, object?>, Setter as Action<object, object?>,
typeof(T)); typeof(T));

View File

@@ -6,17 +6,17 @@ namespace Ryujinx.Ava.Common.Markup
{ {
internal class IconExtension(string iconString) : BasicMarkupExtension<Icon> internal class IconExtension(string iconString) : BasicMarkupExtension<Icon>
{ {
protected override Icon GetValue() => new() { Value = iconString }; protected override Icon Value => new() { Value = iconString };
} }
internal class SpinningIconExtension(string iconString) : BasicMarkupExtension<Icon> internal class SpinningIconExtension(string iconString) : BasicMarkupExtension<Icon>
{ {
protected override Icon GetValue() => new() { Value = iconString, Animation = IconAnimation.Spin }; protected override Icon Value => new() { Value = iconString, Animation = IconAnimation.Spin };
} }
internal class LocaleExtension(LocaleKeys key) : BasicMarkupExtension<string> internal class LocaleExtension(LocaleKeys key) : BasicMarkupExtension<string>
{ {
protected override string GetValue() => LocaleManager.Instance[key]; protected override string Value => LocaleManager.Instance[key];
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension) protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
=> bindingExtension.Source = LocaleManager.Instance; => bindingExtension.Source = LocaleManager.Instance;

View File

@@ -91,7 +91,7 @@
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Top" VerticalAlignment="Top"
FontSize="16" FontSize="16"
Foreground="{DynamicResource SystemAccentColor}" Foreground="{DynamicResource FavoriteApplicationIconColor}"
IsVisible="{Binding Favorite}" IsVisible="{Binding Favorite}"
Symbol="StarFilled" /> Symbol="StarFilled" />
</Grid> </Grid>

View File

@@ -146,7 +146,7 @@
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Top" VerticalAlignment="Top"
FontSize="16" FontSize="16"
Foreground="{DynamicResource SystemAccentColor}" Foreground="{DynamicResource FavoriteApplicationIconColor}"
IsVisible="{Binding Favorite}" IsVisible="{Binding Favorite}"
Symbol="StarFilled" /> Symbol="StarFilled" />
</Grid> </Grid>

View File

@@ -10,6 +10,7 @@ using DynamicData;
using DynamicData.Binding; using DynamicData.Binding;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using LibHac.Common; using LibHac.Common;
using LibHac.Ns;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
@@ -1897,7 +1898,7 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public async Task LoadApplication(ApplicationData application, bool startFullscreen = false) public async Task LoadApplication(ApplicationData application, bool startFullscreen = false, BlitStruct<ApplicationControlProperty>? customNacpData = null)
{ {
if (AppHost != null) if (AppHost != null)
{ {
@@ -1935,7 +1936,7 @@ namespace Ryujinx.Ava.UI.ViewModels
this, this,
TopLevel); TopLevel);
if (!await AppHost.LoadGuestApplication()) if (!await AppHost.LoadGuestApplication(customNacpData))
{ {
AppHost.DisposeContext(); AppHost.DisposeContext();
AppHost = null; AppHost = null;

View File

@@ -3,7 +3,9 @@ using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Threading; using Avalonia.Threading;
using Gommon; using Gommon;
using LibHac.Common;
using LibHac.Ncm; using LibHac.Ncm;
using LibHac.Ns;
using LibHac.Tools.FsSystem.NcaUtils; using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
@@ -11,6 +13,7 @@ using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE;
using Ryujinx.UI.App.Common; using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common; using Ryujinx.UI.Common;
using Ryujinx.UI.Common.Configuration; using Ryujinx.UI.Common.Configuration;
@@ -19,6 +22,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
namespace Ryujinx.Ava.UI.Views.Main namespace Ryujinx.Ava.UI.Views.Main
{ {
@@ -123,18 +127,24 @@ namespace Ryujinx.Ava.UI.Views.Main
public async void OpenMiiApplet(object sender, RoutedEventArgs e) public async void OpenMiiApplet(object sender, RoutedEventArgs e)
{ {
string contentPath = ViewModel.ContentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program); const string AppletName = "miiEdit";
const ulong AppletProgramId = 0x0100000000001009;
const string AppletVersion = "1.0.0";
string contentPath = ViewModel.ContentManager.GetInstalledContentPath(AppletProgramId, StorageId.BuiltInSystem, NcaContentType.Program);
if (!string.IsNullOrEmpty(contentPath)) if (!string.IsNullOrEmpty(contentPath))
{ {
ApplicationData applicationData = new() ApplicationData applicationData = new()
{ {
Name = "miiEdit", Name = AppletName,
Id = 0x0100000000001009, Id = AppletProgramId,
Path = contentPath, Path = contentPath
}; };
var nacpData = StructHelpers.CreateCustomNacpData(AppletName, AppletVersion);
await ViewModel.LoadApplication(applicationData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen); await ViewModel.LoadApplication(applicationData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
} }
} }

View File

@@ -61,23 +61,17 @@ namespace Ryujinx.Ava.UI.Windows
private void RemoveDLC(object sender, RoutedEventArgs e) private void RemoveDLC(object sender, RoutedEventArgs e)
{ {
if (sender is Button button) if (sender is Button { DataContext: DownloadableContentModel dlc })
{ {
if (button.DataContext is DownloadableContentModel model) ViewModel.Remove(dlc);
{
ViewModel.Remove(model);
}
} }
} }
private void OpenLocation(object sender, RoutedEventArgs e) private void OpenLocation(object sender, RoutedEventArgs e)
{ {
if (sender is Button button) if (sender is Button { DataContext: DownloadableContentModel dlc })
{ {
if (button.DataContext is DownloadableContentModel model) OpenHelper.LocateFile(dlc.ContainerPath);
{
OpenHelper.LocateFile(model.ContainerPath);
}
} }
} }