diff options
author | gdkchan <gab.dark.100@gmail.com> | 2023-11-11 23:35:30 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-11 23:35:30 -0300 |
commit | 51065d91290e41a9d2518f44c9bdf83a9b0017ab (patch) | |
tree | 4964520c8d5dbb1000b8eec4a024744df1a3e4ee /src/Ryujinx | |
parent | 6228331fd1fb63a32d929bf1cae7f709bc9fd271 (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.cs | 8 | ||||
-rw-r--r-- | src/Ryujinx/Ui/MainWindow.cs | 95 | ||||
-rw-r--r-- | src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs | 89 | ||||
-rw-r--r-- | src/Ryujinx/Ui/Windows/CheatWindow.cs | 9 | ||||
-rw-r--r-- | src/Ryujinx/Ui/Windows/DlcWindow.cs | 123 | ||||
-rw-r--r-- | src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs | 63 |
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) |