misc: Code cleanups & improvements, again

This commit is contained in:
Evan Husted 2024-10-17 01:21:32 -05:00
parent a13cf098b4
commit 235083ad75
13 changed files with 75 additions and 156 deletions

View File

@ -10,6 +10,9 @@
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.10" /> <PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.10" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.18" /> <PackageVersion Include="Avalonia.Svg" Version="11.0.0.18" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.18" /> <PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.18" />
<PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.4.0" />
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/>
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/>
<PackageVersion Include="CommandLineParser" Version="2.9.1" /> <PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Concentus" Version="2.2.0" /> <PackageVersion Include="Concentus" Version="2.2.0" />
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" /> <PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
@ -34,6 +37,7 @@
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" /> <PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" /> <PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Gommon" Version="2.6.5" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" /> <PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" /> <PackageVersion Include="SharpZipLib" Version="1.4.2" />

View File

@ -6,7 +6,7 @@ namespace ARMeilleure
public static class Optimizations public static class Optimizations
{ {
// low-core count PPTC // low-core count PPTC
public static bool EcoFriendly { get; set; } = false; public static bool LowPower { get; set; } = false;
public static bool FastFP { get; set; } = true; public static bool FastFP { get; set; } = true;
@ -54,8 +54,8 @@ namespace ARMeilleure
internal static bool UseSse41 => UseSse41IfAvailable && X86HardwareCapabilities.SupportsSse41; internal static bool UseSse41 => UseSse41IfAvailable && X86HardwareCapabilities.SupportsSse41;
internal static bool UseSse42 => UseSse42IfAvailable && X86HardwareCapabilities.SupportsSse42; internal static bool UseSse42 => UseSse42IfAvailable && X86HardwareCapabilities.SupportsSse42;
internal static bool UsePopCnt => UsePopCntIfAvailable && X86HardwareCapabilities.SupportsPopcnt; internal static bool UsePopCnt => UsePopCntIfAvailable && X86HardwareCapabilities.SupportsPopcnt;
internal static bool UseAvx => UseAvxIfAvailable && X86HardwareCapabilities.SupportsAvx && !ForceLegacySse; internal static bool UseAvx => UseAvxIfAvailable && X86HardwareCapabilities.SupportsAvx && !ForceLegacySse;
internal static bool UseAvx512F => UseAvx512FIfAvailable && X86HardwareCapabilities.SupportsAvx512F && !ForceLegacySse; internal static bool UseAvx512F => UseAvx512FIfAvailable && X86HardwareCapabilities.SupportsAvx512F && !ForceLegacySse;
internal static bool UseAvx512Vl => UseAvx512VlIfAvailable && X86HardwareCapabilities.SupportsAvx512Vl && !ForceLegacySse; internal static bool UseAvx512Vl => UseAvx512VlIfAvailable && X86HardwareCapabilities.SupportsAvx512Vl && !ForceLegacySse;
internal static bool UseAvx512Bw => UseAvx512BwIfAvailable && X86HardwareCapabilities.SupportsAvx512Bw && !ForceLegacySse; internal static bool UseAvx512Bw => UseAvx512BwIfAvailable && X86HardwareCapabilities.SupportsAvx512Bw && !ForceLegacySse;
internal static bool UseAvx512Dq => UseAvx512DqIfAvailable && X86HardwareCapabilities.SupportsAvx512Dq && !ForceLegacySse; internal static bool UseAvx512Dq => UseAvx512DqIfAvailable && X86HardwareCapabilities.SupportsAvx512Dq && !ForceLegacySse;

View File

@ -799,11 +799,11 @@ namespace ARMeilleure.Translation.PTC
int degreeOfParallelism = Environment.ProcessorCount; int degreeOfParallelism = Environment.ProcessorCount;
if (Optimizations.EcoFriendly) if (Optimizations.LowPower)
degreeOfParallelism /= 3; degreeOfParallelism /= 3;
// If there are enough cores lying around, we leave one alone for other tasks. // If there are enough cores lying around, we leave one alone for other tasks.
if (degreeOfParallelism > 4 && !Optimizations.EcoFriendly) if (degreeOfParallelism > 4 && !Optimizations.LowPower)
{ {
degreeOfParallelism--; degreeOfParallelism--;
} }

View File

@ -10,6 +10,7 @@
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" /> <PackageReference Include="Microsoft.IO.RecyclableMemoryStream" />
<PackageReference Include="MsgPack.Cli" /> <PackageReference Include="MsgPack.Cli" />
<PackageReference Include="System.Management" /> <PackageReference Include="System.Management" />
<PackageReference Include="Gommon" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
int avCodecMajorVersion = avCodecRawVersion >> 16; int avCodecMajorVersion = avCodecRawVersion >> 16;
int avCodecMinorVersion = (avCodecRawVersion >> 8) & 0xFF; int avCodecMinorVersion = (avCodecRawVersion >> 8) & 0xFF;
// libavcodec 59.24 changed AvCodec to move its private API and also move the codec function to an union. // libavcodec 59.24 changed AvCodec to move its private API and also move the codec function to a union.
if (avCodecMajorVersion > 59 || (avCodecMajorVersion == 59 && avCodecMinorVersion > 24)) if (avCodecMajorVersion > 59 || (avCodecMajorVersion == 59 && avCodecMinorVersion > 24))
{ {
_decodeFrame = Marshal.GetDelegateForFunctionPointer<AVCodec_decode>(((FFCodec<AVCodec>*)_codec)->CodecCallback); _decodeFrame = Marshal.GetDelegateForFunctionPointer<AVCodec_decode>(((FFCodec<AVCodec>*)_codec)->CodecCallback);

View File

@ -26,8 +26,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
{ {
Surface outSurf = (Surface)output; Surface outSurf = (Surface)output;
if (outSurf.RequestedWidth != _oldOutputWidth || if (outSurf.RequestedWidth != _oldOutputWidth || outSurf.RequestedHeight != _oldOutputHeight)
outSurf.RequestedHeight != _oldOutputHeight)
{ {
_context.Dispose(); _context.Dispose();
_context = new FFmpegContext(AVCodecID.AV_CODEC_ID_H264); _context = new FFmpegContext(AVCodecID.AV_CODEC_ID_H264);
@ -38,7 +37,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
Span<byte> bs = Prepend(bitstream, SpsAndPpsReconstruction.Reconstruct(ref pictureInfo, _workBuffer)); Span<byte> bs = Prepend(bitstream, SpsAndPpsReconstruction.Reconstruct(ref pictureInfo, _workBuffer));
return _context.DecodeFrame(outSurf, bs) == 0; return _context.DecodeFrame(outSurf, bs) is 0;
} }
private static byte[] Prepend(ReadOnlySpan<byte> data, ReadOnlySpan<byte> prep) private static byte[] Prepend(ReadOnlySpan<byte> data, ReadOnlySpan<byte> prep)

View File

@ -3,23 +3,13 @@ using System.Numerics;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264 namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
{ {
struct H264BitStreamWriter struct H264BitStreamWriter(byte[] workBuffer)
{ {
private const int BufferSize = 8; private const int BufferSize = 8;
private readonly byte[] _workBuffer; private int _offset = 0;
private int _buffer = 0;
private int _offset; private int _bufferPos = 0;
private int _buffer;
private int _bufferPos;
public H264BitStreamWriter(byte[] workBuffer)
{
_workBuffer = workBuffer;
_offset = 0;
_buffer = 0;
_bufferPos = 0;
}
public void WriteBit(bool value) public void WriteBit(bool value)
{ {
@ -59,9 +49,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
private int GetFreeBufferBits() private int GetFreeBufferBits()
{ {
if (_bufferPos == BufferSize) if (_bufferPos == BufferSize)
{
Flush(); Flush();
}
return BufferSize - _bufferPos; return BufferSize - _bufferPos;
} }
@ -70,7 +58,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
{ {
if (_bufferPos != 0) if (_bufferPos != 0)
{ {
_workBuffer[_offset++] = (byte)_buffer; workBuffer[_offset++] = (byte)_buffer;
_buffer = 0; _buffer = 0;
_bufferPos = 0; _bufferPos = 0;
@ -84,10 +72,8 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
Flush(); Flush();
} }
public readonly Span<byte> AsSpan() public readonly Span<byte> AsSpan()
{ => new Span<byte>(workBuffer)[.._offset];
return new Span<byte>(_workBuffer)[.._offset];
}
public void WriteU(uint value, int valueSize) => WriteBits((int)value, valueSize); public void WriteU(uint value, int valueSize) => WriteBits((int)value, valueSize);
public void WriteSe(int value) => WriteExpGolombCodedInt(value); public void WriteSe(int value) => WriteExpGolombCodedInt(value);

View File

@ -68,36 +68,6 @@ namespace Ryujinx.HLE
#pragma warning restore IDE0055 #pragma warning restore IDE0055
} }
public bool LoadCart(string exeFsDir, string romFsFile = null)
{
return Processes.LoadUnpackedNca(exeFsDir, romFsFile);
}
public bool LoadXci(string xciFile, ulong applicationId = 0)
{
return Processes.LoadXci(xciFile, applicationId);
}
public bool LoadNca(string ncaFile)
{
return Processes.LoadNca(ncaFile);
}
public bool LoadNsp(string nspFile, ulong applicationId = 0)
{
return Processes.LoadNsp(nspFile, applicationId);
}
public bool LoadProgram(string fileName)
{
return Processes.LoadNxo(fileName);
}
public bool WaitFifo()
{
return Gpu.GPFifo.WaitForCommands();
}
public void ProcessFrame() public void ProcessFrame()
{ {
Gpu.ProcessShaderCacheQueue(); Gpu.ProcessShaderCacheQueue();
@ -105,40 +75,22 @@ namespace Ryujinx.HLE
Gpu.GPFifo.DispatchCalls(); Gpu.GPFifo.DispatchCalls();
} }
public bool ConsumeFrameAvailable() public bool LoadCart(string exeFsDir, string romFsFile = null) => Processes.LoadUnpackedNca(exeFsDir, romFsFile);
{ public bool LoadXci(string xciFile, ulong applicationId = 0) => Processes.LoadXci(xciFile, applicationId);
return Gpu.Window.ConsumeFrameAvailable(); public bool LoadNca(string ncaFile) => Processes.LoadNca(ncaFile);
} public bool LoadNsp(string nspFile, ulong applicationId = 0) => Processes.LoadNsp(nspFile, applicationId);
public bool LoadProgram(string fileName) => Processes.LoadNxo(fileName);
public void PresentFrame(Action swapBuffersCallback) public void SetVolume(float volume) => AudioDeviceDriver.Volume = Math.Clamp(volume, 0f, 1f);
{ public float GetVolume() => AudioDeviceDriver.Volume;
Gpu.Window.Present(swapBuffersCallback); public bool IsAudioMuted() => AudioDeviceDriver.Volume == 0;
}
public void SetVolume(float volume) public void EnableCheats() => ModLoader.EnableCheats(Processes.ActiveApplication.ProgramId, TamperMachine);
{
AudioDeviceDriver.Volume = Math.Clamp(volume, 0f, 1f);
}
public float GetVolume() public bool WaitFifo() => Gpu.GPFifo.WaitForCommands();
{ public bool ConsumeFrameAvailable() => Gpu.Window.ConsumeFrameAvailable();
return AudioDeviceDriver.Volume; public void PresentFrame(Action swapBuffersCallback) => Gpu.Window.Present(swapBuffersCallback);
} public void DisposeGpu() => Gpu.Dispose();
public void EnableCheats()
{
ModLoader.EnableCheats(Processes.ActiveApplication.ProgramId, TamperMachine);
}
public bool IsAudioMuted()
{
return AudioDeviceDriver.Volume == 0;
}
public void DisposeGpu()
{
Gpu.Dispose();
}
public void Dispose() public void Dispose()
{ {

View File

@ -396,7 +396,7 @@ namespace Ryujinx.Ava
} }
} }
private void SaveBitmapAsPng(SKBitmap bitmap, string path) private static void SaveBitmapAsPng(SKBitmap bitmap, string path)
{ {
using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100); using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
using var stream = File.OpenWrite(path); using var stream = File.OpenWrite(path);
@ -406,8 +406,6 @@ namespace Ryujinx.Ava
public void Start() public void Start()
{ {
ARMeilleure.Optimizations.EcoFriendly = ConfigurationState.Instance.System.EnableLowPowerPtc;
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {
_windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1); _windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1);
@ -540,9 +538,8 @@ namespace Ryujinx.Ava
private void Dispose() private void Dispose()
{ {
if (Device.Processes != null) if (Device.Processes != null)
{
MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText); MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText);
}
ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState; ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState;
ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState; ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState;

View File

@ -8,26 +8,20 @@ namespace Ryujinx.Ava.Common.Locale
{ {
internal class LocaleExtension(LocaleKeys key) : MarkupExtension internal class LocaleExtension(LocaleKeys key) : MarkupExtension
{ {
public LocaleKeys Key { get; } = key; private ClrPropertyInfo PropertyInfo
=> new(
"Item",
_ => LocaleManager.Instance[key],
null,
typeof(string)
);
public override object ProvideValue(IServiceProvider serviceProvider) public override object ProvideValue(IServiceProvider serviceProvider) =>
{ new CompiledBindingExtension(
var builder = new CompiledBindingPathBuilder(); new CompiledBindingPathBuilder()
.Property(PropertyInfo, PropertyInfoAccessorFactory.CreateInpcPropertyAccessor)
builder.Property( .Build()
new ClrPropertyInfo("Item", ) { Source = LocaleManager.Instance }
_ => LocaleManager.Instance[Key], .ProvideValue(serviceProvider);
null,
typeof(string)
),
PropertyInfoAccessorFactory.CreateInpcPropertyAccessor);
var binding = new CompiledBindingExtension(builder.Build())
{
Source = LocaleManager.Instance
};
return binding.ProvideValue(serviceProvider);
}
} }
} }

View File

@ -3,6 +3,7 @@ using Avalonia.Controls;
using Avalonia.Styling; using Avalonia.Styling;
using Avalonia.Threading; using Avalonia.Threading;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Gommon;
using LibHac; using LibHac;
using LibHac.Common; using LibHac.Common;
using LibHac.Fs; using LibHac.Fs;
@ -84,10 +85,7 @@ namespace Ryujinx.Ava.UI.Controls
Padding = new Thickness(0), Padding = new Thickness(0),
}; };
contentDialog.Closed += (sender, args) => contentDialog.Closed += (_, _) => content.ViewModel.Dispose();
{
content.ViewModel.Dispose();
};
Style footer = new(x => x.Name("DialogSpace").Child().OfType<Border>()); Style footer = new(x => x.Name("DialogSpace").Child().OfType<Border>());
footer.Setters.Add(new Setter(IsVisibleProperty, false)); footer.Setters.Add(new Setter(IsVisibleProperty, false));
@ -109,12 +107,9 @@ namespace Ryujinx.Ava.UI.Controls
ViewModel.Profiles.Clear(); ViewModel.Profiles.Clear();
ViewModel.LostProfiles.Clear(); ViewModel.LostProfiles.Clear();
var profiles = AccountManager.GetAllUsers().OrderBy(x => x.Name); AccountManager.GetAllUsers()
.OrderBy(x => x.Name)
foreach (var profile in profiles) .ForEach(profile => ViewModel.Profiles.Add(new UserProfile(profile, this)));
{
ViewModel.Profiles.Add(new UserProfile(profile, this));
}
var saveDataFilter = SaveDataFilter.Make(programId: default, saveType: SaveDataType.Account, default, saveDataId: default, index: default); var saveDataFilter = SaveDataFilter.Make(programId: default, saveType: SaveDataType.Account, default, saveDataId: default, index: default);

View File

@ -84,7 +84,7 @@ namespace Ryujinx.Ava.UI.Helpers
return await ShowContentDialog(title, content, primaryButton, secondaryButton, closeButton, primaryButtonResult, deferResetEvent, deferCloseAction); return await ShowContentDialog(title, content, primaryButton, secondaryButton, closeButton, primaryButtonResult, deferResetEvent, deferCloseAction);
} }
public async static Task<UserResult> ShowDeferredContentDialog( public static Task<UserResult> ShowDeferredContentDialog(
StyleableWindow window, StyleableWindow window,
string title, string title,
string primaryText, string primaryText,
@ -98,7 +98,7 @@ namespace Ryujinx.Ava.UI.Helpers
{ {
bool startedDeferring = false; bool startedDeferring = false;
return await ShowTextDialog( return ShowTextDialog(
title, title,
primaryText, primaryText,
secondaryText, secondaryText,
@ -148,8 +148,8 @@ namespace Ryujinx.Ava.UI.Helpers
{ {
Grid content = new() Grid content = new()
{ {
RowDefinitions = new RowDefinitions { new(), new() }, RowDefinitions = [new(), new()],
ColumnDefinitions = new ColumnDefinitions { new(GridLength.Auto), new() }, ColumnDefinitions = [new(GridLength.Auto), new()],
MinHeight = 80, MinHeight = 80,
}; };
@ -194,14 +194,13 @@ namespace Ryujinx.Ava.UI.Helpers
return content; return content;
} }
public static async Task<UserResult> CreateInfoDialog( public static Task<UserResult> CreateInfoDialog(
string primary, string primary,
string secondaryText, string secondaryText,
string acceptButton, string acceptButton,
string closeButton, string closeButton,
string title) string title)
{ => ShowTextDialog(
return await ShowTextDialog(
title, title,
primary, primary,
secondaryText, secondaryText,
@ -209,17 +208,15 @@ namespace Ryujinx.Ava.UI.Helpers
"", "",
closeButton, closeButton,
(int)Symbol.Important); (int)Symbol.Important);
}
internal static async Task<UserResult> CreateConfirmationDialog( internal static Task<UserResult> CreateConfirmationDialog(
string primaryText, string primaryText,
string secondaryText, string secondaryText,
string acceptButtonText, string acceptButtonText,
string cancelButtonText, string cancelButtonText,
string title, string title,
UserResult primaryButtonResult = UserResult.Yes) UserResult primaryButtonResult = UserResult.Yes)
{ => ShowTextDialog(
return await ShowTextDialog(
string.IsNullOrWhiteSpace(title) ? LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle] : title, string.IsNullOrWhiteSpace(title) ? LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle] : title,
primaryText, primaryText,
secondaryText, secondaryText,
@ -228,21 +225,17 @@ namespace Ryujinx.Ava.UI.Helpers
cancelButtonText, cancelButtonText,
(int)Symbol.Help, (int)Symbol.Help,
primaryButtonResult); primaryButtonResult);
}
internal static async Task<UserResult> CreateLocalizedConfirmationDialog( internal static Task<UserResult> CreateLocalizedConfirmationDialog(string primaryText, string secondaryText)
string primaryText, => CreateConfirmationDialog(
string secondaryText) =>
await CreateConfirmationDialog(
primaryText, primaryText,
secondaryText, secondaryText,
LocaleManager.Instance[LocaleKeys.InputDialogYes], LocaleManager.Instance[LocaleKeys.InputDialogYes],
LocaleManager.Instance[LocaleKeys.InputDialogNo], LocaleManager.Instance[LocaleKeys.InputDialogNo],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
internal static async Task CreateUpdaterInfoDialog(string primary, string secondaryText) internal static Task CreateUpdaterInfoDialog(string primary, string secondaryText)
{ => ShowTextDialog(
await ShowTextDialog(
LocaleManager.Instance[LocaleKeys.DialogUpdaterTitle], LocaleManager.Instance[LocaleKeys.DialogUpdaterTitle],
primary, primary,
secondaryText, secondaryText,
@ -250,11 +243,9 @@ namespace Ryujinx.Ava.UI.Helpers
"", "",
LocaleManager.Instance[LocaleKeys.InputDialogOk], LocaleManager.Instance[LocaleKeys.InputDialogOk],
(int)Symbol.Important); (int)Symbol.Important);
}
internal static async Task CreateWarningDialog(string primary, string secondaryText) internal static Task CreateWarningDialog(string primary, string secondaryText)
{ => ShowTextDialog(
await ShowTextDialog(
LocaleManager.Instance[LocaleKeys.DialogWarningTitle], LocaleManager.Instance[LocaleKeys.DialogWarningTitle],
primary, primary,
secondaryText, secondaryText,
@ -262,13 +253,12 @@ namespace Ryujinx.Ava.UI.Helpers
"", "",
LocaleManager.Instance[LocaleKeys.InputDialogOk], LocaleManager.Instance[LocaleKeys.InputDialogOk],
(int)Symbol.Important); (int)Symbol.Important);
}
internal static async Task CreateErrorDialog(string errorMessage, string secondaryErrorMessage = "") internal static Task CreateErrorDialog(string errorMessage, string secondaryErrorMessage = "")
{ {
Logger.Error?.Print(LogClass.Application, errorMessage); Logger.Error?.Print(LogClass.Application, errorMessage);
await ShowTextDialog( return ShowTextDialog(
LocaleManager.Instance[LocaleKeys.DialogErrorTitle], LocaleManager.Instance[LocaleKeys.DialogErrorTitle],
LocaleManager.Instance[LocaleKeys.DialogErrorMessage], LocaleManager.Instance[LocaleKeys.DialogErrorMessage],
errorMessage, errorMessage,

View File

@ -5,6 +5,7 @@ using Ryujinx.Ava.UI.Windows;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.UI.App.Common; using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Helper; using Ryujinx.UI.Common.Helper;
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -18,7 +19,7 @@ namespace Ryujinx.Ava.UI.Models
public ulong SaveId { get; } public ulong SaveId { get; }
public ProgramId TitleId { get; } public ProgramId TitleId { get; }
public string TitleIdString => $"{TitleId.Value:X16}"; public string TitleIdString => TitleId.ToString();
public UserId UserId { get; } public UserId UserId { get; }
public bool InGameList { get; } public bool InGameList { get; }
public string Title { get; } public string Title { get; }
@ -46,7 +47,7 @@ namespace Ryujinx.Ava.UI.Models
TitleId = info.ProgramId; TitleId = info.ProgramId;
UserId = info.UserId; UserId = info.UserId;
var appData = MainWindow.MainWindowViewModel.Applications.FirstOrDefault(x => x.IdString.ToUpper() == TitleIdString); var appData = MainWindow.ViewModel.Applications.FirstOrDefault(x => x.IdString.Equals(TitleIdString, StringComparison.OrdinalIgnoreCase));
InGameList = appData != null; InGameList = appData != null;