aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-11-11 23:35:30 -0300
committerGitHub <noreply@github.com>2023-11-11 23:35:30 -0300
commit51065d91290e41a9d2518f44c9bdf83a9b0017ab (patch)
tree4964520c8d5dbb1000b8eec4a024744df1a3e4ee /src/Ryujinx
parent6228331fd1fb63a32d929bf1cae7f709bc9fd271 (diff)
Revert "Add support for multi game XCIs (#5638)" (#5914)1.1.1079
This reverts commit 5c3cfb84c09b0566da677425915afa0b2d76da55.
Diffstat (limited to 'src/Ryujinx')
-rw-r--r--src/Ryujinx/Program.cs8
-rw-r--r--src/Ryujinx/Ui/MainWindow.cs95
-rw-r--r--src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs89
-rw-r--r--src/Ryujinx/Ui/Windows/CheatWindow.cs9
-rw-r--r--src/Ryujinx/Ui/Windows/DlcWindow.cs123
-rw-r--r--src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs63
6 files changed, 141 insertions, 246 deletions
diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs
index 14062481..afb6a992 100644
--- a/src/Ryujinx/Program.cs
+++ b/src/Ryujinx/Program.cs
@@ -7,7 +7,6 @@ using Ryujinx.Common.SystemInterop;
using Ryujinx.Modules;
using Ryujinx.SDL2.Common;
using Ryujinx.Ui;
-using Ryujinx.Ui.App.Common;
using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
@@ -333,12 +332,7 @@ namespace Ryujinx
if (CommandLineState.LaunchPathArg != null)
{
- ApplicationData applicationData = new()
- {
- Path = CommandLineState.LaunchPathArg,
- };
-
- mainWindow.RunApplication(applicationData, CommandLineState.StartFullscreenArg);
+ mainWindow.RunApplication(CommandLineState.LaunchPathArg, CommandLineState.StartFullscreenArg);
}
if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false))
diff --git a/src/Ryujinx/Ui/MainWindow.cs b/src/Ryujinx/Ui/MainWindow.cs
index 884f6687..8b0b35e6 100644
--- a/src/Ryujinx/Ui/MainWindow.cs
+++ b/src/Ryujinx/Ui/MainWindow.cs
@@ -39,7 +39,6 @@ using Silk.NET.Vulkan;
using SPB.Graphics.Vulkan;
using System;
using System.Diagnostics;
-using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;
@@ -71,7 +70,7 @@ namespace Ryujinx.Ui
private bool _gameLoaded;
private bool _ending;
- private ApplicationData _currentApplicationData = null;
+ private string _currentEmulatedGamePath = null;
private string _lastScannedAmiiboId = "";
private bool _lastScannedAmiiboShowAll = false;
@@ -182,12 +181,8 @@ namespace Ryujinx.Ui
_accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, CommandLineState.Profile);
_userChannelPersistence = new UserChannelPersistence();
- IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
- ? IntegrityCheckLevel.ErrorOnInvalid
- : IntegrityCheckLevel.None;
-
// Instantiate GUI objects.
- _applicationLibrary = new ApplicationLibrary(_virtualFileSystem, checkLevel);
+ _applicationLibrary = new ApplicationLibrary(_virtualFileSystem);
_uiHandler = new GtkHostUiHandler(this);
_deviceExitStatus = new AutoResetEvent(false);
@@ -789,7 +784,7 @@ namespace Ryujinx.Ui
}
}
- private bool LoadApplication(string path, ulong titleId, bool isFirmwareTitle)
+ private bool LoadApplication(string path, bool isFirmwareTitle)
{
SystemVersion firmwareVersion = _contentManager.GetCurrentFirmwareVersion();
@@ -863,7 +858,7 @@ namespace Ryujinx.Ui
case ".xci":
Logger.Info?.Print(LogClass.Application, "Loading as XCI.");
- return _emulationContext.LoadXci(path, titleId);
+ return _emulationContext.LoadXci(path);
case ".nca":
Logger.Info?.Print(LogClass.Application, "Loading as NCA.");
@@ -872,7 +867,7 @@ namespace Ryujinx.Ui
case ".pfs0":
Logger.Info?.Print(LogClass.Application, "Loading as NSP.");
- return _emulationContext.LoadNsp(path, titleId);
+ return _emulationContext.LoadNsp(path);
default:
Logger.Info?.Print(LogClass.Application, "Loading as Homebrew.");
try
@@ -893,7 +888,7 @@ namespace Ryujinx.Ui
return false;
}
- public void RunApplication(ApplicationData application, bool startFullscreen = false)
+ public void RunApplication(string path, bool startFullscreen = false)
{
if (_gameLoaded)
{
@@ -915,14 +910,14 @@ namespace Ryujinx.Ui
bool isFirmwareTitle = false;
- if (application.Path.StartsWith("@SystemContent"))
+ if (path.StartsWith("@SystemContent"))
{
- application.Path = VirtualFileSystem.SwitchPathToSystemPath(application.Path);
+ path = VirtualFileSystem.SwitchPathToSystemPath(path);
isFirmwareTitle = true;
}
- if (!LoadApplication(application.Path, application.Id, isFirmwareTitle))
+ if (!LoadApplication(path, isFirmwareTitle))
{
_emulationContext.Dispose();
SwitchToGameTable();
@@ -932,7 +927,7 @@ namespace Ryujinx.Ui
SetupProgressUiHandlers();
- _currentApplicationData = application;
+ _currentEmulatedGamePath = path;
_deviceExitStatus.Reset();
@@ -1173,7 +1168,7 @@ namespace Ryujinx.Ui
_tableStore.AppendValues(
args.AppData.Favorite,
new Gdk.Pixbuf(args.AppData.Icon, 75, 75),
- $"{args.AppData.Name}\n{args.AppData.IdString.ToUpper()}",
+ $"{args.AppData.TitleName}\n{args.AppData.TitleId.ToUpper()}",
args.AppData.Developer,
args.AppData.Version,
args.AppData.TimePlayedString,
@@ -1261,22 +1256,9 @@ namespace Ryujinx.Ui
{
_gameTableSelection.GetSelected(out TreeIter treeIter);
- ApplicationData application = new()
- {
- Favorite = (bool)_tableStore.GetValue(treeIter, 0),
- Name = ((string)_tableStore.GetValue(treeIter, 2)).Split('\n')[0],
- Id = ulong.Parse(((string)_tableStore.GetValue(treeIter, 2)).Split('\n')[1], NumberStyles.HexNumber),
- Developer = (string)_tableStore.GetValue(treeIter, 3),
- Version = (string)_tableStore.GetValue(treeIter, 4),
- TimePlayed = ValueFormatUtils.ParseTimeSpan((string)_tableStore.GetValue(treeIter, 5)),
- LastPlayed = ValueFormatUtils.ParseDateTime((string)_tableStore.GetValue(treeIter, 6)),
- FileExtension = (string)_tableStore.GetValue(treeIter, 7),
- FileSize = ValueFormatUtils.ParseFileSize((string)_tableStore.GetValue(treeIter, 8)),
- Path = (string)_tableStore.GetValue(treeIter, 9),
- ControlHolder = (BlitStruct<ApplicationControlProperty>)_tableStore.GetValue(treeIter, 10),
- };
+ string path = (string)_tableStore.GetValue(treeIter, 9);
- RunApplication(application);
+ RunApplication(path);
}
private void VSyncStatus_Clicked(object sender, ButtonReleaseEventArgs args)
@@ -1334,22 +1316,13 @@ namespace Ryujinx.Ui
return;
}
- ApplicationData application = new()
- {
- Favorite = (bool)_tableStore.GetValue(treeIter, 0),
- Name = ((string)_tableStore.GetValue(treeIter, 2)).Split('\n')[0],
- Id = ulong.Parse(((string)_tableStore.GetValue(treeIter, 2)).Split('\n')[1], NumberStyles.HexNumber),
- Developer = (string)_tableStore.GetValue(treeIter, 3),
- Version = (string)_tableStore.GetValue(treeIter, 4),
- TimePlayed = ValueFormatUtils.ParseTimeSpan((string)_tableStore.GetValue(treeIter, 5)),
- LastPlayed = ValueFormatUtils.ParseDateTime((string)_tableStore.GetValue(treeIter, 6)),
- FileExtension = (string)_tableStore.GetValue(treeIter, 7),
- FileSize = ValueFormatUtils.ParseFileSize((string)_tableStore.GetValue(treeIter, 8)),
- Path = (string)_tableStore.GetValue(treeIter, 9),
- ControlHolder = (BlitStruct<ApplicationControlProperty>)_tableStore.GetValue(treeIter, 10),
- };
+ string titleFilePath = _tableStore.GetValue(treeIter, 9).ToString();
+ string titleName = _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[0];
+ string titleId = _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[1].ToLower();
+
+ BlitStruct<ApplicationControlProperty> controlData = (BlitStruct<ApplicationControlProperty>)_tableStore.GetValue(treeIter, 10);
- _ = new GameTableContextMenu(this, _virtualFileSystem, _accountManager, _libHacHorizonManager.RyujinxClient, application);
+ _ = new GameTableContextMenu(this, _virtualFileSystem, _accountManager, _libHacHorizonManager.RyujinxClient, titleFilePath, titleName, titleId, controlData);
}
private void Load_Application_File(object sender, EventArgs args)
@@ -1371,12 +1344,7 @@ namespace Ryujinx.Ui
if (fileChooser.Run() == (int)ResponseType.Accept)
{
- ApplicationData applicationData = new()
- {
- Path = fileChooser.Filename,
- };
-
- RunApplication(applicationData);
+ RunApplication(fileChooser.Filename);
}
}
@@ -1386,13 +1354,7 @@ namespace Ryujinx.Ui
if (fileChooser.Run() == (int)ResponseType.Accept)
{
- ApplicationData applicationData = new()
- {
- Name = System.IO.Path.GetFileNameWithoutExtension(fileChooser.Filename),
- Path = fileChooser.Filename,
- };
-
- RunApplication(applicationData);
+ RunApplication(fileChooser.Filename);
}
}
@@ -1407,14 +1369,7 @@ namespace Ryujinx.Ui
{
string contentPath = _contentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
- ApplicationData applicationData = new()
- {
- Name = "miiEdit",
- Id = 0x0100000000001009ul,
- Path = contentPath,
- };
-
- RunApplication(applicationData);
+ RunApplication(contentPath);
}
private void Open_Ryu_Folder(object sender, EventArgs args)
@@ -1690,13 +1645,13 @@ namespace Ryujinx.Ui
{
_userChannelPersistence.ShouldRestart = false;
- RunApplication(_currentApplicationData);
+ RunApplication(_currentEmulatedGamePath);
}
else
{
// otherwise, clear state.
_userChannelPersistence = new UserChannelPersistence();
- _currentApplicationData = null;
+ _currentEmulatedGamePath = null;
_actionMenu.Sensitive = false;
_firmwareInstallFile.Sensitive = true;
_firmwareInstallDirectory.Sensitive = true;
@@ -1758,7 +1713,7 @@ namespace Ryujinx.Ui
_emulationContext.Processes.ActiveApplication.ProgramId,
_emulationContext.Processes.ActiveApplication.ApplicationControlProperties
.Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString(),
- _currentApplicationData.Path);
+ _currentEmulatedGamePath);
window.Destroyed += CheatWindow_Destroyed;
window.Show();
diff --git a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs b/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
index 6903c941..5af181b0 100644
--- a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
+++ b/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
@@ -16,7 +16,6 @@ using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS;
using Ryujinx.HLE.HOS.Services.Account.Acc;
-using Ryujinx.HLE.Loaders.Processes.Extensions;
using Ryujinx.Ui.App.Common;
using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
@@ -24,6 +23,7 @@ using Ryujinx.Ui.Windows;
using System;
using System.Buffers;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;
@@ -36,13 +36,17 @@ namespace Ryujinx.Ui.Widgets
private readonly VirtualFileSystem _virtualFileSystem;
private readonly AccountManager _accountManager;
private readonly HorizonClient _horizonClient;
+ private readonly BlitStruct<ApplicationControlProperty> _controlData;
- private readonly ApplicationData _title;
+ private readonly string _titleFilePath;
+ private readonly string _titleName;
+ private readonly string _titleIdText;
+ private readonly ulong _titleId;
private MessageDialog _dialog;
private bool _cancel;
- public GameTableContextMenu(MainWindow parent, VirtualFileSystem virtualFileSystem, AccountManager accountManager, HorizonClient horizonClient, ApplicationData applicationData)
+ public GameTableContextMenu(MainWindow parent, VirtualFileSystem virtualFileSystem, AccountManager accountManager, HorizonClient horizonClient, string titleFilePath, string titleName, string titleId, BlitStruct<ApplicationControlProperty> controlData)
{
_parent = parent;
@@ -51,13 +55,23 @@ namespace Ryujinx.Ui.Widgets
_virtualFileSystem = virtualFileSystem;
_accountManager = accountManager;
_horizonClient = horizonClient;
- _title = applicationData;
+ _titleFilePath = titleFilePath;
+ _titleName = titleName;
+ _titleIdText = titleId;
+ _controlData = controlData;
- _openSaveUserDirMenuItem.Sensitive = !Utilities.IsZeros(_title.ControlHolder.ByteSpan) && _title.ControlHolder.Value.UserAccountSaveDataSize > 0;
- _openSaveDeviceDirMenuItem.Sensitive = !Utilities.IsZeros(_title.ControlHolder.ByteSpan) && _title.ControlHolder.Value.DeviceSaveDataSize > 0;
- _openSaveBcatDirMenuItem.Sensitive = !Utilities.IsZeros(_title.ControlHolder.ByteSpan) && _title.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
+ if (!ulong.TryParse(_titleIdText, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _titleId))
+ {
+ GtkDialog.CreateErrorDialog("The selected game did not have a valid Title Id");
+
+ return;
+ }
+
+ _openSaveUserDirMenuItem.Sensitive = !Utilities.IsZeros(controlData.ByteSpan) && controlData.Value.UserAccountSaveDataSize > 0;
+ _openSaveDeviceDirMenuItem.Sensitive = !Utilities.IsZeros(controlData.ByteSpan) && controlData.Value.DeviceSaveDataSize > 0;
+ _openSaveBcatDirMenuItem.Sensitive = !Utilities.IsZeros(controlData.ByteSpan) && controlData.Value.BcatDeliveryCacheStorageSize > 0;
- string fileExt = System.IO.Path.GetExtension(_title.Path).ToLower();
+ string fileExt = System.IO.Path.GetExtension(_titleFilePath).ToLower();
bool hasNca = fileExt == ".nca" || fileExt == ".nsp" || fileExt == ".pfs0" || fileExt == ".xci";
_extractRomFsMenuItem.Sensitive = hasNca;
@@ -123,7 +137,7 @@ namespace Ryujinx.Ui.Widgets
private void OpenSaveDir(in SaveDataFilter saveDataFilter)
{
- if (!TryFindSaveData(_title.Name, _title.Id, _title.ControlHolder, in saveDataFilter, out ulong saveDataId))
+ if (!TryFindSaveData(_titleName, _titleId, _controlData, in saveDataFilter, out ulong saveDataId))
{
return;
}
@@ -176,7 +190,7 @@ namespace Ryujinx.Ui.Widgets
{
Title = "Ryujinx - NCA Section Extractor",
Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png"),
- SecondaryText = $"Extracting {ncaSectionType} section from {System.IO.Path.GetFileName(_title.Path)}...",
+ SecondaryText = $"Extracting {ncaSectionType} section from {System.IO.Path.GetFileName(_titleFilePath)}...",
WindowPosition = WindowPosition.Center,
};
@@ -188,18 +202,18 @@ namespace Ryujinx.Ui.Widgets
}
});
- using FileStream file = new(_title.Path, FileMode.Open, FileAccess.Read);
+ using FileStream file = new(_titleFilePath, FileMode.Open, FileAccess.Read);
Nca mainNca = null;
Nca patchNca = null;
- if ((System.IO.Path.GetExtension(_title.Path).ToLower() == ".nsp") ||
- (System.IO.Path.GetExtension(_title.Path).ToLower() == ".pfs0") ||
- (System.IO.Path.GetExtension(_title.Path).ToLower() == ".xci"))
+ if ((System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".nsp") ||
+ (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".pfs0") ||
+ (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".xci"))
{
IFileSystem pfs;
- if (System.IO.Path.GetExtension(_title.Path).ToLower() == ".xci")
+ if (System.IO.Path.GetExtension(_titleFilePath) == ".xci")
{
Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage());
@@ -235,7 +249,7 @@ namespace Ryujinx.Ui.Widgets
}
}
}
- else if (System.IO.Path.GetExtension(_title.Path).ToLower() == ".nca")
+ else if (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".nca")
{
mainNca = new Nca(_virtualFileSystem.KeySet, file.AsStorage());
}
@@ -252,11 +266,7 @@ namespace Ryujinx.Ui.Widgets
return;
}
- IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
- ? IntegrityCheckLevel.ErrorOnInvalid
- : IntegrityCheckLevel.None;
-
- (Nca updatePatchNca, _) = mainNca.GetUpdateData(_virtualFileSystem, checkLevel, programIndex, out _);
+ (Nca updatePatchNca, _) = ApplicationLibrary.GetGameUpdateData(_virtualFileSystem, mainNca.Header.TitleId.ToString("x16"), programIndex, out _);
if (updatePatchNca != null)
{
@@ -450,44 +460,44 @@ namespace Ryujinx.Ui.Widgets
private void OpenSaveUserDir_Clicked(object sender, EventArgs args)
{
var userId = new LibHac.Fs.UserId((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low);
- var saveDataFilter = SaveDataFilter.Make(_title.Id, saveType: default, userId, saveDataId: default, index: default);
+ var saveDataFilter = SaveDataFilter.Make(_titleId, saveType: default, userId, saveDataId: default, index: default);
OpenSaveDir(in saveDataFilter);
}
private void OpenSaveDeviceDir_Clicked(object sender, EventArgs args)
{
- var saveDataFilter = SaveDataFilter.Make(_title.Id, SaveDataType.Device, userId: default, saveDataId: default, index: default);
+ var saveDataFilter = SaveDataFilter.Make(_titleId, SaveDataType.Device, userId: default, saveDataId: default, index: default);
OpenSaveDir(in saveDataFilter);
}
private void OpenSaveBcatDir_Clicked(object sender, EventArgs args)
{
- var saveDataFilter = SaveDataFilter.Make(_title.Id, SaveDataType.Bcat, userId: default, saveDataId: default, index: default);
+ var saveDataFilter = SaveDataFilter.Make(_titleId, SaveDataType.Bcat, userId: default, saveDataId: default, index: default);
OpenSaveDir(in saveDataFilter);
}
private void ManageTitleUpdates_Clicked(object sender, EventArgs args)
{
- new TitleUpdateWindow(_parent, _virtualFileSystem, _title).Show();
+ new TitleUpdateWindow(_parent, _virtualFileSystem, _titleIdText, _titleName).Show();
}
private void ManageDlc_Clicked(object sender, EventArgs args)
{
- new DlcWindow(_virtualFileSystem, _title.IdString, _title).Show();
+ new DlcWindow(_virtualFileSystem, _titleIdText, _titleName).Show();
}
private void ManageCheats_Clicked(object sender, EventArgs args)
{
- new CheatWindow(_virtualFileSystem, _title.Id, _title.Name, _title.Path).Show();
+ new CheatWindow(_virtualFileSystem, _titleId, _titleName, _titleFilePath).Show();
}
private void OpenTitleModDir_Clicked(object sender, EventArgs args)
{
string modsBasePath = ModLoader.GetModsBasePath();
- string titleModsPath = ModLoader.GetTitleDir(modsBasePath, _title.IdString);
+ string titleModsPath = ModLoader.GetTitleDir(modsBasePath, _titleIdText);
OpenHelper.OpenFolder(titleModsPath);
}
@@ -495,7 +505,7 @@ namespace Ryujinx.Ui.Widgets
private void OpenTitleSdModDir_Clicked(object sender, EventArgs args)
{
string sdModsBasePath = ModLoader.GetSdModsBasePath();
- string titleModsPath = ModLoader.GetTitleDir(sdModsBasePath, _title.IdString);
+ string titleModsPath = ModLoader.GetTitleDir(sdModsBasePath, _titleIdText);
OpenHelper.OpenFolder(titleModsPath);
}
@@ -517,7 +527,7 @@ namespace Ryujinx.Ui.Widgets
private void OpenPtcDir_Clicked(object sender, EventArgs args)
{
- string ptcDir = System.IO.Path.Combine(AppDataManager.GamesDirPath, _title.IdString, "cache", "cpu");
+ string ptcDir = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu");
string mainPath = System.IO.Path.Combine(ptcDir, "0");
string backupPath = System.IO.Path.Combine(ptcDir, "1");
@@ -534,7 +544,7 @@ namespace Ryujinx.Ui.Widgets
private void OpenShaderCacheDir_Clicked(object sender, EventArgs args)
{
- string shaderCacheDir = System.IO.Path.Combine(AppDataManager.GamesDirPath, _title.IdString, "cache", "shader");
+ string shaderCacheDir = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "shader");
if (!Directory.Exists(shaderCacheDir))
{
@@ -546,10 +556,10 @@ namespace Ryujinx.Ui.Widgets
private void PurgePtcCache_Clicked(object sender, EventArgs args)
{
- DirectoryInfo mainDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _title.IdString, "cache", "cpu", "0"));
- DirectoryInfo backupDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _title.IdString, "cache", "cpu", "1"));
+ DirectoryInfo mainDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu", "0"));
+ DirectoryInfo backupDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu", "1"));
- MessageDialog warningDialog = GtkDialog.CreateConfirmationDialog("Warning", $"You are about to queue a PPTC rebuild on the next boot of:\n\n<b>{_title.Name}</b>\n\nAre you sure you want to proceed?");
+ MessageDialog warningDialog = GtkDialog.CreateConfirmationDialog("Warning", $"You are about to queue a PPTC rebuild on the next boot of:\n\n<b>{_titleName}</b>\n\nAre you sure you want to proceed?");
List<FileInfo> cacheFiles = new();
@@ -583,9 +593,9 @@ namespace Ryujinx.Ui.Widgets
private void PurgeShaderCache_Clicked(object sender, EventArgs args)
{
- DirectoryInfo shaderCacheDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _title.IdString, "cache", "shader"));
+ DirectoryInfo shaderCacheDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "shader"));
- using MessageDialog warningDialog = GtkDialog.CreateConfirmationDialog("Warning", $"You are about to delete the shader cache for :\n\n<b>{_title.Name}</b>\n\nAre you sure you want to proceed?");
+ using MessageDialog warningDialog = GtkDialog.CreateConfirmationDialog("Warning", $"You are about to delete the shader cache for :\n\n<b>{_titleName}</b>\n\nAre you sure you want to proceed?");
List<DirectoryInfo> oldCacheDirectories = new();
List<FileInfo> newCacheFiles = new();
@@ -627,11 +637,8 @@ namespace Ryujinx.Ui.Widgets
private void CreateShortcut_Clicked(object sender, EventArgs args)
{
- IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
- ? IntegrityCheckLevel.ErrorOnInvalid
- : IntegrityCheckLevel.None;
- byte[] appIcon = new ApplicationLibrary(_virtualFileSystem, checkLevel).GetApplicationIcon(_title.Path, ConfigurationState.Instance.System.Language, _title.Id);
- ShortcutHelper.CreateAppShortcut(_title.Path, _title.Name, _title.IdString, appIcon);
+ byte[] appIcon = new ApplicationLibrary(_virtualFileSystem).GetApplicationIcon(_titleFilePath, ConfigurationState.Instance.System.Language);
+ ShortcutHelper.CreateAppShortcut(_titleFilePath, _titleName, _titleIdText, appIcon);
}
}
}
diff --git a/src/Ryujinx/Ui/Windows/CheatWindow.cs b/src/Ryujinx/Ui/Windows/CheatWindow.cs
index 9bbae1c6..1eca732b 100644
--- a/src/Ryujinx/Ui/Windows/CheatWindow.cs
+++ b/src/Ryujinx/Ui/Windows/CheatWindow.cs
@@ -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"));
diff --git a/src/Ryujinx/Ui/Windows/DlcWindow.cs b/src/Ryujinx/Ui/Windows/DlcWindow.cs
index dbffc420..9f717946 100644
--- a/src/Ryujinx/Ui/Windows/DlcWindow.cs
+++ b/src/Ryujinx/Ui/Windows/DlcWindow.cs
@@ -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!");
+ }
}
}
diff --git a/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs b/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs
index 2f7f14f1..51918eea 100644
--- a/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs
+++ b/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs
@@ -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)