1
1
mirror of https://github.com/ryujinx-mirror/ryujinx.git synced 2025-10-03 10:15:51 -05:00

Revert "Add support for multi game XCIs (#5638)" (#5914)

This reverts commit 5c3cfb84c0.
This commit is contained in:
gdkchan
2023-11-11 23:35:30 -03:00
committed by GitHub
parent 6228331fd1
commit 51065d9129
33 changed files with 819 additions and 1171 deletions

View File

@@ -1,9 +1,7 @@
using Gtk;
using LibHac.Tools.FsSystem;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS;
using Ryujinx.Ui.App.Common;
using Ryujinx.Ui.Common.Configuration;
using System;
using System.Collections.Generic;
using System.IO;
@@ -29,13 +27,8 @@ namespace Ryujinx.Ui.Windows
private CheatWindow(Builder builder, VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) : base(builder.GetRawOwnedObject("_cheatWindow"))
{
builder.Autoconnect(this);
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None;
_baseTitleInfoLabel.Text = $"Cheats Available for {titleName} [{titleId:X16}]";
_buildIdTextView.Buffer.Text = $"BuildId: {ApplicationData.GetBuildId(virtualFileSystem, checkLevel, titlePath)}";
_buildIdTextView.Buffer.Text = $"BuildId: {ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath)}";
string modsBasePath = ModLoader.GetModsBasePath();
string titleModsPath = ModLoader.GetTitleDir(modsBasePath, titleId.ToString("X16"));

View File

@@ -9,12 +9,9 @@ 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.Ui.App.Common;
using Ryujinx.Ui.Widgets;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using GUI = Gtk.Builder.ObjectAttribute;
@@ -23,7 +20,7 @@ namespace Ryujinx.Ui.Windows
public class DlcWindow : Window
{
private readonly VirtualFileSystem _virtualFileSystem;
private readonly string _applicationId;
private readonly string _titleId;
private readonly string _dlcJsonPath;
private readonly List<DownloadableContentContainer> _dlcContainerList;
@@ -35,16 +32,16 @@ namespace Ryujinx.Ui.Windows
[GUI] TreeSelection _dlcTreeSelection;
#pragma warning restore CS0649, IDE0044
public DlcWindow(VirtualFileSystem virtualFileSystem, string titleId, ApplicationData title) : this(new Builder("Ryujinx.Ui.Windows.DlcWindow.glade"), virtualFileSystem, titleId, title) { }
public DlcWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName) : this(new Builder("Ryujinx.Ui.Windows.DlcWindow.glade"), virtualFileSystem, titleId, titleName) { }
private DlcWindow(Builder builder, VirtualFileSystem virtualFileSystem, string applicationId, ApplicationData title) : base(builder.GetRawOwnedObject("_dlcWindow"))
private DlcWindow(Builder builder, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetRawOwnedObject("_dlcWindow"))
{
builder.Autoconnect(this);
_applicationId = applicationId;
_titleId = titleId;
_virtualFileSystem = virtualFileSystem;
_dlcJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _applicationId, "dlc.json");
_baseTitleInfoLabel.Text = $"DLC Available for {title.Name} [{applicationId.ToUpper()}]";
_dlcJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "dlc.json");
_baseTitleInfoLabel.Text = $"DLC Available for {titleName} [{titleId.ToUpper()}]";
try
{
@@ -75,12 +72,9 @@ namespace Ryujinx.Ui.Windows
};
_dlcTreeView.AppendColumn("Enabled", enableToggle, "active", 0);
_dlcTreeView.AppendColumn("ApplicationId", new CellRendererText(), "text", 1);
_dlcTreeView.AppendColumn("TitleId", new CellRendererText(), "text", 1);
_dlcTreeView.AppendColumn("Path", new CellRendererText(), "text", 2);
// NOTE: Try to load downloadable contents from PFS first.
AddDlc(title.Path, true);
foreach (DownloadableContentContainer dlcContainer in _dlcContainerList)
{
if (File.Exists(dlcContainer.ContainerPath))
@@ -95,10 +89,7 @@ namespace Ryujinx.Ui.Windows
using FileStream containerFile = File.OpenRead(dlcContainer.ContainerPath);
PartitionFileSystem pfs = new();
if (pfs.Initialize(containerFile.AsStorage()).IsFailure())
{
continue;
}
pfs.Initialize(containerFile.AsStorage()).ThrowIfFailure();
_virtualFileSystem.ImportTickets(pfs);
@@ -137,57 +128,6 @@ namespace Ryujinx.Ui.Windows
return null;
}
private void AddDlc(string path, bool ignoreNotFound = false)
{
if (!File.Exists(path))
{
return;
}
using FileStream containerFile = File.OpenRead(path);
PartitionFileSystem pfs = new();
pfs.Initialize(containerFile.AsStorage()).ThrowIfFailure();
bool containsDlc = false;
_virtualFileSystem.ImportTickets(pfs);
TreeIter? parentIter = null;
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
{
using var ncaFile = new UniqueRef<IFile>();
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
Nca nca = TryCreateNca(ncaFile.Get.AsStorage(), path);
if (nca == null)
{
continue;
}
if (nca.Header.ContentType == NcaContentType.PublicData)
{
if (nca.GetProgramIdBase() != (ulong.Parse(_applicationId, NumberStyles.HexNumber) & ~0x1FFFUL))
{
break;
}
parentIter ??= ((TreeStore)_dlcTreeView.Model).AppendValues(true, "", path);
((TreeStore)_dlcTreeView.Model).AppendValues(parentIter.Value, true, nca.Header.TitleId.ToString("X16"), fileEntry.FullPath);
containsDlc = true;
}
}
if (!containsDlc && !ignoreNotFound)
{
GtkDialog.CreateErrorDialog("The specified file does not contain DLC for the selected title!");
}
}
private void AddButton_Clicked(object sender, EventArgs args)
{
FileChooserNative fileChooser = new("Select DLC files", this, FileChooserAction.Open, "Add", "Cancel")
@@ -207,7 +147,52 @@ namespace Ryujinx.Ui.Windows
{
foreach (string containerPath in fileChooser.Filenames)
{
AddDlc(containerPath);
if (!File.Exists(containerPath))
{
return;
}
using FileStream containerFile = File.OpenRead(containerPath);
PartitionFileSystem pfs = new();
pfs.Initialize(containerFile.AsStorage()).ThrowIfFailure();
bool containsDlc = false;
_virtualFileSystem.ImportTickets(pfs);
TreeIter? parentIter = null;
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
{
using var ncaFile = new UniqueRef<IFile>();
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
Nca nca = TryCreateNca(ncaFile.Get.AsStorage(), containerPath);
if (nca == null)
{
continue;
}
if (nca.Header.ContentType == NcaContentType.PublicData)
{
if ((nca.Header.TitleId & 0xFFFFFFFFFFFFE000).ToString("x16") != _titleId)
{
break;
}
parentIter ??= ((TreeStore)_dlcTreeView.Model).AppendValues(true, "", containerPath);
((TreeStore)_dlcTreeView.Model).AppendValues(parentIter.Value, true, nca.Header.TitleId.ToString("X16"), fileEntry.FullPath);
containsDlc = true;
}
}
if (!containsDlc)
{
GtkDialog.CreateErrorDialog("The specified file does not contain DLC for the selected title!");
}
}
}

View File

@@ -4,15 +4,12 @@ using LibHac.Fs;
using LibHac.Fs.Fsa;
using LibHac.FsSystem;
using LibHac.Ns;
using LibHac.Tools.Fs;
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.Ui.App.Common;
using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Widgets;
using System;
using System.Collections.Generic;
@@ -27,7 +24,7 @@ namespace Ryujinx.Ui.Windows
{
private readonly MainWindow _parent;
private readonly VirtualFileSystem _virtualFileSystem;
private readonly ApplicationData _title;
private readonly string _titleId;
private readonly string _updateJsonPath;
private TitleUpdateMetadata _titleUpdateWindowData;
@@ -41,17 +38,17 @@ namespace Ryujinx.Ui.Windows
[GUI] RadioButton _noUpdateRadioButton;
#pragma warning restore CS0649, IDE0044
public TitleUpdateWindow(MainWindow parent, VirtualFileSystem virtualFileSystem, ApplicationData applicationData) : this(new Builder("Ryujinx.Ui.Windows.TitleUpdateWindow.glade"), parent, virtualFileSystem, applicationData) { }
public TitleUpdateWindow(MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : this(new Builder("Ryujinx.Ui.Windows.TitleUpdateWindow.glade"), parent, virtualFileSystem, titleId, titleName) { }
private TitleUpdateWindow(Builder builder, MainWindow parent, VirtualFileSystem virtualFileSystem, ApplicationData applicationData) : base(builder.GetRawOwnedObject("_titleUpdateWindow"))
private TitleUpdateWindow(Builder builder, MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetRawOwnedObject("_titleUpdateWindow"))
{
_parent = parent;
builder.Autoconnect(this);
_title = applicationData;
_titleId = titleId;
_virtualFileSystem = virtualFileSystem;
_updateJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, applicationData.IdString, "updates.json");
_updateJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "updates.json");
_radioButtonToPathDictionary = new Dictionary<RadioButton, string>();
try
@@ -67,10 +64,7 @@ namespace Ryujinx.Ui.Windows
};
}
_baseTitleInfoLabel.Text = $"Updates Available for {applicationData.Name} [{applicationData.IdString}]";
// Try to get updates from PFS first
AddUpdate(_title.Path, true);
_baseTitleInfoLabel.Text = $"Updates Available for {titleName} [{titleId.ToUpper()}]";
foreach (string path in _titleUpdateWindowData.Paths)
{
@@ -90,41 +84,18 @@ namespace Ryujinx.Ui.Windows
}
}
private void AddUpdate(string path, bool ignoreNotFound = false)
private void AddUpdate(string path)
{
if (File.Exists(path))
{
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None;
using FileStream file = new(path, FileMode.Open, FileAccess.Read);
IFileSystem pfs;
PartitionFileSystem nsp = new();
nsp.Initialize(file.AsStorage()).ThrowIfFailure();
try
{
if (System.IO.Path.GetExtension(path).ToLower() == ".xci")
{
pfs = new Xci(_virtualFileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure);
}
else
{
var pfsTemp = new PartitionFileSystem();
pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
pfs = pfsTemp;
}
Dictionary<ulong, ContentCollection> updates = pfs.GetUpdateData(_virtualFileSystem, checkLevel);
Nca patchNca = null;
Nca controlNca = null;
if (updates.TryGetValue(_title.Id, out ContentCollection update))
{
patchNca = update.GetNcaByType(_virtualFileSystem.KeySet, LibHac.Ncm.ContentType.Program);
controlNca = update.GetNcaByType(_virtualFileSystem.KeySet, LibHac.Ncm.ContentType.Control);
}
(Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(_virtualFileSystem, nsp, _titleId, 0);
if (controlNca != null && patchNca != null)
{
@@ -135,14 +106,7 @@ namespace Ryujinx.Ui.Windows
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")
{
radioLabel = "Bundled: " + radioLabel;
}
RadioButton radioButton = new(radioLabel);
RadioButton radioButton = new($"Version {controlData.DisplayVersionString.ToString()} - {path}");
radioButton.JoinGroup(_noUpdateRadioButton);
_availableUpdatesBox.Add(radioButton);
@@ -153,10 +117,7 @@ namespace Ryujinx.Ui.Windows
}
else
{
if (!ignoreNotFound)
{
GtkDialog.CreateErrorDialog("The specified file does not contain an update for the selected title!");
}
GtkDialog.CreateErrorDialog("The specified file does not contain an update for the selected title!");
}
}
catch (Exception exception)