Compare commits
14 commits
870ae7ffaa
...
c201ed6491
Author | SHA1 | Date | |
---|---|---|---|
|
c201ed6491 | ||
|
6ce49a2dc7 | ||
|
ccd330ba0f | ||
|
811c2651f2 | ||
|
7e3f6af6c6 | ||
|
32628bb8a3 | ||
|
190791a1c9 | ||
|
965ee0d016 | ||
|
1c4f8b8175 | ||
|
c1c8aaee0f | ||
|
d1aa76d22d | ||
|
9cf64e612f | ||
|
e2122a532d | ||
|
2d14384a7d |
11 changed files with 126 additions and 56 deletions
|
@ -1,21 +1,28 @@
|
||||||
|
using Ryujinx.Common.GraphicsDriver.NVAPI;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Common.GraphicsDriver
|
namespace Ryujinx.Common.GraphicsDriver
|
||||||
{
|
{
|
||||||
public static class DriverUtilities
|
public static class DriverUtilities
|
||||||
{
|
{
|
||||||
public static void ToggleOGLThreading(bool enabled)
|
public static void ToggleOglThreading(bool enabled)
|
||||||
{
|
{
|
||||||
Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString().ToLower());
|
Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString().ToLower());
|
||||||
Environment.SetEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
|
Environment.SetEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
|
||||||
|
|
||||||
|
ToggleNvDriverSetting(NvapiSettingId.OglThreadControlId, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ToggleNvDriverSetting(NvapiSettingId id, bool enabled)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
NVThreadedOptimization.SetThreadedOptimization(enabled);
|
NVDriverHelper.SetControlOption(id, enabled);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// NVAPI is not available, or couldn't change the application profile.
|
Logger.Info?.Print(LogClass.Application, "NVAPI was unreachable, no changes were made.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,23 @@
|
||||||
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||||
{
|
{
|
||||||
enum Nvapi : uint
|
public enum NvapiSettingId : uint
|
||||||
{
|
{
|
||||||
OglThreadControlId = 0x20C1221E,
|
OglThreadControlId = 0x20C1221E,
|
||||||
|
OglCplPreferDxPresentId = 0x20D690F8,
|
||||||
|
}
|
||||||
|
|
||||||
OglThreadControlDefault = 0,
|
enum OglThreadControl : uint
|
||||||
OglThreadControlEnable = 1,
|
{
|
||||||
OglThreadControlDisable = 2,
|
Default = 0,
|
||||||
|
Enabled = 1,
|
||||||
|
Disabled = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only present in driver versions >= 526.47
|
||||||
|
enum OglCplDxPresent : uint
|
||||||
|
{
|
||||||
|
Disabled = 0,
|
||||||
|
Enabled = 1,
|
||||||
|
Default = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||||
[FieldOffset(0x4)]
|
[FieldOffset(0x4)]
|
||||||
public NvapiUnicodeString SettingName;
|
public NvapiUnicodeString SettingName;
|
||||||
[FieldOffset(0x1004)]
|
[FieldOffset(0x1004)]
|
||||||
public Nvapi SettingId;
|
public NvapiSettingId SettingId;
|
||||||
[FieldOffset(0x1008)]
|
[FieldOffset(0x1008)]
|
||||||
public NvdrsSettingType SettingType;
|
public NvdrsSettingType SettingType;
|
||||||
[FieldOffset(0x100C)]
|
[FieldOffset(0x100C)]
|
||||||
|
|
|
@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Common.GraphicsDriver
|
namespace Ryujinx.Common.GraphicsDriver
|
||||||
{
|
{
|
||||||
static partial class NVThreadedOptimization
|
static partial class NVDriverHelper
|
||||||
{
|
{
|
||||||
private const string ProfileName = "Ryujinx Nvidia Profile";
|
private const string ProfileName = "Ryujinx Nvidia Profile";
|
||||||
|
|
||||||
|
@ -49,6 +49,9 @@ namespace Ryujinx.Common.GraphicsDriver
|
||||||
private delegate int NvAPI_DRS_DestroySessionDelegate(IntPtr handle);
|
private delegate int NvAPI_DRS_DestroySessionDelegate(IntPtr handle);
|
||||||
private static NvAPI_DRS_DestroySessionDelegate NvAPI_DRS_DestroySession;
|
private static NvAPI_DRS_DestroySessionDelegate NvAPI_DRS_DestroySession;
|
||||||
|
|
||||||
|
private static IntPtr _handle;
|
||||||
|
private static nint _profileHandle;
|
||||||
|
|
||||||
private static bool _initialized;
|
private static bool _initialized;
|
||||||
|
|
||||||
private static void Check(int status)
|
private static void Check(int status)
|
||||||
|
@ -80,17 +83,8 @@ namespace Ryujinx.Common.GraphicsDriver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint MakeVersion<T>(uint version) where T : unmanaged
|
private static void SetupNvProfile()
|
||||||
{
|
{
|
||||||
return (uint)Unsafe.SizeOf<T>() | version << 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetThreadedOptimization(bool enabled)
|
|
||||||
{
|
|
||||||
Initialize();
|
|
||||||
|
|
||||||
uint targetValue = (uint)(enabled ? Nvapi.OglThreadControlEnable : Nvapi.OglThreadControlDisable);
|
|
||||||
|
|
||||||
Check(NvAPI_Initialize());
|
Check(NvAPI_Initialize());
|
||||||
|
|
||||||
Check(NvAPI_DRS_CreateSession(out IntPtr handle));
|
Check(NvAPI_DRS_CreateSession(out IntPtr handle));
|
||||||
|
@ -98,7 +92,6 @@ namespace Ryujinx.Common.GraphicsDriver
|
||||||
Check(NvAPI_DRS_LoadSettings(handle));
|
Check(NvAPI_DRS_LoadSettings(handle));
|
||||||
|
|
||||||
// Check if the profile already exists.
|
// Check if the profile already exists.
|
||||||
|
|
||||||
int status = NvAPI_DRS_FindProfileByName(handle, new NvapiUnicodeString(ProfileName), out nint profileHandle);
|
int status = NvAPI_DRS_FindProfileByName(handle, new NvapiUnicodeString(ProfileName), out nint profileHandle);
|
||||||
|
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
|
@ -126,10 +119,32 @@ namespace Ryujinx.Common.GraphicsDriver
|
||||||
Check(NvAPI_DRS_CreateApplication(handle, profileHandle, ref application));
|
Check(NvAPI_DRS_CreateApplication(handle, profileHandle, ref application));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handle = handle;
|
||||||
|
_profileHandle = profileHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static uint MakeVersion<T>(uint version) where T : unmanaged
|
||||||
|
{
|
||||||
|
return (uint)Unsafe.SizeOf<T>() | version << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetControlOption(NvapiSettingId id, bool enabled)
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
|
||||||
|
SetupNvProfile();
|
||||||
|
|
||||||
|
uint targetValue = id switch
|
||||||
|
{
|
||||||
|
NvapiSettingId.OglThreadControlId => (uint)(enabled ? OglThreadControl.Enabled : OglThreadControl.Disabled),
|
||||||
|
NvapiSettingId.OglCplPreferDxPresentId => (uint)(enabled ? OglCplDxPresent.Enabled : OglCplDxPresent.Disabled),
|
||||||
|
_ => throw new ArgumentException($"Invalid NVAPI setting id: 0x{id:X}"),
|
||||||
|
};
|
||||||
|
|
||||||
NvdrsSetting setting = new()
|
NvdrsSetting setting = new()
|
||||||
{
|
{
|
||||||
Version = MakeVersion<NvdrsSetting>(1),
|
Version = MakeVersion<NvdrsSetting>(1),
|
||||||
SettingId = Nvapi.OglThreadControlId,
|
SettingId = id,
|
||||||
SettingType = NvdrsSettingType.NvdrsDwordType,
|
SettingType = NvdrsSettingType.NvdrsDwordType,
|
||||||
SettingLocation = NvdrsSettingLocation.NvdrsCurrentProfileLocation,
|
SettingLocation = NvdrsSettingLocation.NvdrsCurrentProfileLocation,
|
||||||
IsCurrentPredefined = 0,
|
IsCurrentPredefined = 0,
|
||||||
|
@ -138,11 +153,10 @@ namespace Ryujinx.Common.GraphicsDriver
|
||||||
PredefinedValue = targetValue,
|
PredefinedValue = targetValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
Check(NvAPI_DRS_SetSetting(handle, profileHandle, ref setting));
|
Check(NvAPI_DRS_SetSetting(_handle, _profileHandle, ref setting));
|
||||||
|
Check(NvAPI_DRS_SaveSettings(_handle));
|
||||||
|
|
||||||
Check(NvAPI_DRS_SaveSettings(handle));
|
NvAPI_DRS_DestroySession(_handle);
|
||||||
|
|
||||||
NvAPI_DRS_DestroySession(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static T NvAPI_Delegate<T>(uint id) where T : class
|
private static T NvAPI_Delegate<T>(uint id) where T : class
|
|
@ -667,8 +667,36 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
if (PrepareOutputBuffer(cbs, hostSize, buffer, out VkBuffer copyToBuffer, out BufferHolder tempCopyHolder))
|
if (PrepareOutputBuffer(cbs, hostSize, buffer, out VkBuffer copyToBuffer, out BufferHolder tempCopyHolder))
|
||||||
{
|
{
|
||||||
|
// No barrier necessary, as this is a temporary copy buffer.
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BufferHolder.InsertBufferBarrier(
|
||||||
|
_gd,
|
||||||
|
cbs.CommandBuffer,
|
||||||
|
copyToBuffer,
|
||||||
|
BufferHolder.DefaultAccessFlags,
|
||||||
|
AccessFlags.TransferWriteBit,
|
||||||
|
PipelineStageFlags.AllCommandsBit,
|
||||||
|
PipelineStageFlags.TransferBit,
|
||||||
|
offset,
|
||||||
|
outSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
InsertImageBarrier(
|
||||||
|
_gd.Api,
|
||||||
|
cbs.CommandBuffer,
|
||||||
|
image,
|
||||||
|
TextureStorage.DefaultAccessMask,
|
||||||
|
AccessFlags.TransferReadBit,
|
||||||
|
PipelineStageFlags.AllCommandsBit,
|
||||||
|
PipelineStageFlags.TransferBit,
|
||||||
|
Info.Format.ConvertAspectFlags(),
|
||||||
|
FirstLayer + layer,
|
||||||
|
FirstLevel + level,
|
||||||
|
1,
|
||||||
|
1);
|
||||||
|
|
||||||
CopyFromOrToBuffer(cbs.CommandBuffer, copyToBuffer, image, hostSize, true, layer, level, 1, 1, singleSlice: true, offset, stride);
|
CopyFromOrToBuffer(cbs.CommandBuffer, copyToBuffer, image, hostSize, true, layer, level, 1, 1, singleSlice: true, offset, stride);
|
||||||
|
|
||||||
|
@ -677,6 +705,19 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
CopyDataToOutputBuffer(cbs, tempCopyHolder, autoBuffer, hostSize, range.Offset);
|
CopyDataToOutputBuffer(cbs, tempCopyHolder, autoBuffer, hostSize, range.Offset);
|
||||||
tempCopyHolder.Dispose();
|
tempCopyHolder.Dispose();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BufferHolder.InsertBufferBarrier(
|
||||||
|
_gd,
|
||||||
|
cbs.CommandBuffer,
|
||||||
|
copyToBuffer,
|
||||||
|
AccessFlags.TransferWriteBit,
|
||||||
|
BufferHolder.DefaultAccessFlags,
|
||||||
|
PipelineStageFlags.TransferBit,
|
||||||
|
PipelineStageFlags.AllCommandsBit,
|
||||||
|
offset,
|
||||||
|
outSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReadOnlySpan<byte> GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer)
|
private ReadOnlySpan<byte> GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer)
|
||||||
|
|
|
@ -2,6 +2,7 @@ using Gtk;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.GraphicsDriver;
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
|
using Ryujinx.Common.GraphicsDriver.NVAPI;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.SystemInterop;
|
using Ryujinx.Common.SystemInterop;
|
||||||
using Ryujinx.Modules;
|
using Ryujinx.Modules;
|
||||||
|
@ -239,7 +240,10 @@ namespace Ryujinx
|
||||||
|
|
||||||
// Enable OGL multithreading on the driver, when available.
|
// Enable OGL multithreading on the driver, when available.
|
||||||
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
||||||
DriverUtilities.ToggleOGLThreading(threadingMode == BackendThreading.Off);
|
DriverUtilities.ToggleOglThreading(threadingMode == BackendThreading.Off);
|
||||||
|
|
||||||
|
// Enable DXGI present mode on the driver, when available.
|
||||||
|
DriverUtilities.ToggleNvDriverSetting(NvapiSettingId.OglCplPreferDxPresentId, true);
|
||||||
|
|
||||||
// Initialize Gtk.
|
// Initialize Gtk.
|
||||||
Application.Init();
|
Application.Init();
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
using Ryujinx.Common.Configuration.Multiplayer;
|
||||||
using Ryujinx.Common.GraphicsDriver;
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
|
using Ryujinx.Common.GraphicsDriver.NVAPI;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
||||||
using Ryujinx.UI.Common.Configuration;
|
using Ryujinx.UI.Common.Configuration;
|
||||||
|
@ -610,7 +611,7 @@ namespace Ryujinx.UI.Windows
|
||||||
BackendThreading backendThreading = Enum.Parse<BackendThreading>(_galThreading.ActiveId);
|
BackendThreading backendThreading = Enum.Parse<BackendThreading>(_galThreading.ActiveId);
|
||||||
if (ConfigurationState.Instance.Graphics.BackendThreading != backendThreading)
|
if (ConfigurationState.Instance.Graphics.BackendThreading != backendThreading)
|
||||||
{
|
{
|
||||||
DriverUtilities.ToggleOGLThreading(backendThreading == BackendThreading.Off);
|
DriverUtilities.ToggleOglThreading(backendThreading == BackendThreading.Off);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active;
|
ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active;
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.GraphicsDriver;
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
|
using Ryujinx.Common.GraphicsDriver.NVAPI;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.SystemInterop;
|
using Ryujinx.Common.SystemInterop;
|
||||||
using Ryujinx.Modules;
|
using Ryujinx.Modules;
|
||||||
|
@ -112,7 +113,10 @@ namespace Ryujinx.Ava
|
||||||
PrintSystemInfo();
|
PrintSystemInfo();
|
||||||
|
|
||||||
// Enable OGL multithreading on the driver, when available.
|
// Enable OGL multithreading on the driver, when available.
|
||||||
DriverUtilities.ToggleOGLThreading(ConfigurationState.Instance.Graphics.BackendThreading == BackendThreading.Off);
|
DriverUtilities.ToggleOglThreading(ConfigurationState.Instance.Graphics.BackendThreading == BackendThreading.Off);
|
||||||
|
|
||||||
|
// Enable Dxgi present on the driver, when available.
|
||||||
|
DriverUtilities.ToggleNvDriverSetting(NvapiSettingId.OglCplPreferDxPresentId, true);
|
||||||
|
|
||||||
// Check if keys exists.
|
// Check if keys exists.
|
||||||
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
|
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
using LibHac.Ns;
|
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Models
|
namespace Ryujinx.Ava.UI.Models
|
||||||
{
|
{
|
||||||
public class TitleUpdateModel
|
public class TitleUpdateModel
|
||||||
{
|
{
|
||||||
public ApplicationControlProperty Control { get; }
|
public uint Version { get; }
|
||||||
public string Path { get; }
|
public string Path { get; }
|
||||||
|
public string Label { get; }
|
||||||
|
|
||||||
public string Label => LocaleManager.Instance.UpdateAndGetDynamicValue(
|
public TitleUpdateModel(uint version, string displayVersion, string path)
|
||||||
System.IO.Path.GetExtension(Path)?.ToLower() == ".xci" ? LocaleKeys.TitleBundledUpdateVersionLabel : LocaleKeys.TitleUpdateVersionLabel,
|
|
||||||
Control.DisplayVersionString.ToString()
|
|
||||||
);
|
|
||||||
|
|
||||||
public TitleUpdateModel(ApplicationControlProperty control, string path)
|
|
||||||
{
|
{
|
||||||
Control = control;
|
Version = version;
|
||||||
|
Label = LocaleManager.Instance.UpdateAndGetDynamicValue(
|
||||||
|
System.IO.Path.GetExtension(path)?.ToLower() == ".xci" ? LocaleKeys.TitleBundledUpdateVersionLabel : LocaleKeys.TitleUpdateVersionLabel,
|
||||||
|
displayVersion
|
||||||
|
);
|
||||||
Path = path;
|
Path = path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
using Ryujinx.Common.Configuration.Multiplayer;
|
||||||
using Ryujinx.Common.GraphicsDriver;
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
|
using Ryujinx.Common.GraphicsDriver.NVAPI;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.Vulkan;
|
using Ryujinx.Graphics.Vulkan;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
|
@ -545,7 +546,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
||||||
if (ConfigurationState.Instance.Graphics.BackendThreading != (BackendThreading)GraphicsBackendMultithreadingIndex)
|
if (ConfigurationState.Instance.Graphics.BackendThreading != (BackendThreading)GraphicsBackendMultithreadingIndex)
|
||||||
{
|
{
|
||||||
DriverUtilities.ToggleOGLThreading(GraphicsBackendMultithreadingIndex == (int)BackendThreading.Off);
|
DriverUtilities.ToggleOglThreading(GraphicsBackendMultithreadingIndex == (int)BackendThreading.Off);
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Graphics.BackendThreading.Value = (BackendThreading)GraphicsBackendMultithreadingIndex;
|
config.Graphics.BackendThreading.Value = (BackendThreading)GraphicsBackendMultithreadingIndex;
|
||||||
|
|
|
@ -131,26 +131,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
|
||||||
public void SortUpdates()
|
public void SortUpdates()
|
||||||
{
|
{
|
||||||
var list = TitleUpdates.ToList();
|
var sortedUpdates = TitleUpdates.OrderByDescending(update => update.Version);
|
||||||
|
|
||||||
list.Sort((first, second) =>
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(first.Control.DisplayVersionString.ToString()))
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(second.Control.DisplayVersionString.ToString()))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Version.Parse(first.Control.DisplayVersionString.ToString()).CompareTo(Version.Parse(second.Control.DisplayVersionString.ToString())) * -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
Views.Clear();
|
Views.Clear();
|
||||||
Views.Add(new BaseModel());
|
Views.Add(new BaseModel());
|
||||||
Views.AddRange(list);
|
Views.AddRange(sortedUpdates);
|
||||||
|
|
||||||
if (SelectedUpdate == null)
|
if (SelectedUpdate == null)
|
||||||
{
|
{
|
||||||
|
@ -204,7 +189,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||||
nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
|
nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
|
||||||
|
|
||||||
var update = new TitleUpdateModel(controlData, path);
|
var displayVersion = controlData.DisplayVersionString.ToString();
|
||||||
|
var update = new TitleUpdateModel(content.Version.Version, displayVersion, path);
|
||||||
|
|
||||||
TitleUpdates.Add(update);
|
TitleUpdates.Add(update);
|
||||||
|
|
||||||
if (selected)
|
if (selected)
|
||||||
|
|
Loading…
Add table
Reference in a new issue