aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Gtk3/UI/Windows/TitleUpdateWindow.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Gtk3/UI/Windows/TitleUpdateWindow.cs')
-rw-r--r--src/Ryujinx.Gtk3/UI/Windows/TitleUpdateWindow.cs92
1 files changed, 60 insertions, 32 deletions
diff --git a/src/Ryujinx.Gtk3/UI/Windows/TitleUpdateWindow.cs b/src/Ryujinx.Gtk3/UI/Windows/TitleUpdateWindow.cs
index 74b2330e..3ac972ea 100644
--- a/src/Ryujinx.Gtk3/UI/Windows/TitleUpdateWindow.cs
+++ b/src/Ryujinx.Gtk3/UI/Windows/TitleUpdateWindow.cs
@@ -2,14 +2,17 @@ using Gtk;
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Fsa;
-using LibHac.FsSystem;
+using LibHac.Ncm;
using LibHac.Ns;
using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Utilities;
using Ryujinx.HLE.FileSystem;
+using Ryujinx.HLE.Loaders.Processes.Extensions;
+using Ryujinx.HLE.Utilities;
using Ryujinx.UI.App.Common;
+using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Widgets;
using System;
using System.Collections.Generic;
@@ -24,7 +27,7 @@ namespace Ryujinx.UI.Windows
{
private readonly MainWindow _parent;
private readonly VirtualFileSystem _virtualFileSystem;
- private readonly string _titleId;
+ private readonly ApplicationData _applicationData;
private readonly string _updateJsonPath;
private TitleUpdateMetadata _titleUpdateWindowData;
@@ -38,17 +41,17 @@ namespace Ryujinx.UI.Windows
[GUI] RadioButton _noUpdateRadioButton;
#pragma warning restore CS0649, IDE0044
- public TitleUpdateWindow(MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : this(new Builder("Ryujinx.Gtk3.UI.Windows.TitleUpdateWindow.glade"), parent, virtualFileSystem, titleId, titleName) { }
+ public TitleUpdateWindow(MainWindow parent, VirtualFileSystem virtualFileSystem, ApplicationData applicationData) : this(new Builder("Ryujinx.Gtk3.UI.Windows.TitleUpdateWindow.glade"), parent, virtualFileSystem, applicationData) { }
- private TitleUpdateWindow(Builder builder, MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetRawOwnedObject("_titleUpdateWindow"))
+ private TitleUpdateWindow(Builder builder, MainWindow parent, VirtualFileSystem virtualFileSystem, ApplicationData applicationData) : base(builder.GetRawOwnedObject("_titleUpdateWindow"))
{
_parent = parent;
builder.Autoconnect(this);
- _titleId = titleId;
+ _applicationData = applicationData;
_virtualFileSystem = virtualFileSystem;
- _updateJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "updates.json");
+ _updateJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, applicationData.IdString, "updates.json");
_radioButtonToPathDictionary = new Dictionary<RadioButton, string>();
try
@@ -64,7 +67,10 @@ namespace Ryujinx.UI.Windows
};
}
- _baseTitleInfoLabel.Text = $"Updates Available for {titleName} [{titleId.ToUpper()}]";
+ _baseTitleInfoLabel.Text = $"Updates Available for {applicationData.Name} [{applicationData.IdString}]";
+
+ // Try to get updates from PFS first
+ AddUpdate(_applicationData.Path, true);
foreach (string path in _titleUpdateWindowData.Paths)
{
@@ -84,47 +90,69 @@ namespace Ryujinx.UI.Windows
}
}
- private void AddUpdate(string path)
+ private void AddUpdate(string path, bool ignoreNotFound = false)
{
- if (File.Exists(path))
+ if (!File.Exists(path) || _radioButtonToPathDictionary.ContainsValue(path))
{
- using FileStream file = new(path, FileMode.Open, FileAccess.Read);
+ return;
+ }
- PartitionFileSystem nsp = new();
- nsp.Initialize(file.AsStorage()).ThrowIfFailure();
+ IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
+ ? IntegrityCheckLevel.ErrorOnInvalid
+ : IntegrityCheckLevel.None;
- try
- {
- (Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(_virtualFileSystem, nsp, _titleId, 0);
+ try
+ {
+ using IFileSystem pfs = PartitionFileSystemUtils.OpenApplicationFileSystem(path, _virtualFileSystem);
- if (controlNca != null && patchNca != null)
- {
- ApplicationControlProperty controlData = new();
+ Dictionary<ulong, ContentMetaData> updates = pfs.GetContentData(ContentMetaType.Patch, _virtualFileSystem, checkLevel);
- using var nacpFile = new UniqueRef<IFile>();
+ Nca patchNca = null;
+ Nca controlNca = null;
- 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();
+ if (updates.TryGetValue(_applicationData.Id, out ContentMetaData update))
+ {
+ patchNca = update.GetNcaByType(_virtualFileSystem.KeySet, LibHac.Ncm.ContentType.Program);
+ controlNca = update.GetNcaByType(_virtualFileSystem.KeySet, LibHac.Ncm.ContentType.Control);
+ }
- RadioButton radioButton = new($"Version {controlData.DisplayVersionString.ToString()} - {path}");
- radioButton.JoinGroup(_noUpdateRadioButton);
+ if (controlNca != null && patchNca != null)
+ {
+ ApplicationControlProperty controlData = new();
- _availableUpdatesBox.Add(radioButton);
- _radioButtonToPathDictionary.Add(radioButton, path);
+ using var nacpFile = new UniqueRef<IFile>();
- radioButton.Show();
- radioButton.Active = true;
- }
- else
+ 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();
+
+ string radioLabel = $"Version {controlData.DisplayVersionString.ToString()} - {path}";
+
+ if (System.IO.Path.GetExtension(path).ToLower() == ".xci")
{
- GtkDialog.CreateErrorDialog("The specified file does not contain an update for the selected title!");
+ radioLabel = "Bundled: " + radioLabel;
}
+
+ RadioButton radioButton = new(radioLabel);
+ radioButton.JoinGroup(_noUpdateRadioButton);
+
+ _availableUpdatesBox.Add(radioButton);
+ _radioButtonToPathDictionary.Add(radioButton, path);
+
+ radioButton.Show();
+ radioButton.Active = true;
}
- catch (Exception exception)
+ else
{
- GtkDialog.CreateErrorDialog($"{exception.Message}. Errored File: {path}");
+ if (!ignoreNotFound)
+ {
+ GtkDialog.CreateErrorDialog("The specified file does not contain an update for the selected title!");
+ }
}
}
+ catch (Exception exception)
+ {
+ GtkDialog.CreateErrorDialog($"{exception.Message}. Errored File: {path}");
+ }
}
private void RemoveUpdates(bool removeSelectedOnly = false)