From 335eed75ef2898b4646b550f2605eb5a58380e87 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Thu, 10 Oct 2024 21:39:50 -0500 Subject: [PATCH] UI: Extract the 256x256 thumbnail too when extracting the logo. --- src/Ryujinx/Common/ApplicationHelper.cs | 45 ++++++++++--------- .../Controls/ApplicationContextMenu.axaml.cs | 23 ++++++++-- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/Ryujinx/Common/ApplicationHelper.cs b/src/Ryujinx/Common/ApplicationHelper.cs index 14773114c..4be9a1a01 100644 --- a/src/Ryujinx/Common/ApplicationHelper.cs +++ b/src/Ryujinx/Common/ApplicationHelper.cs @@ -141,20 +141,8 @@ namespace Ryujinx.Ava.Common } } - public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) + public static void ExtractSection(string destination, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) { - var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions - { - Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], - AllowMultiple = false, - }); - - if (result.Count == 0) - { - return; - } - - var destination = result[0].Path.LocalPath; var cancellationToken = new CancellationTokenSource(); UpdateWaitWindow waitingDialog = new( @@ -172,11 +160,11 @@ namespace Ryujinx.Ava.Common Nca patchNca = null; string extension = Path.GetExtension(titleFilePath).ToLower(); - if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci") + if (extension is ".nsp" or ".pfs0" or ".xci") { IFileSystem pfs; - if (extension == ".xci") + if (extension is ".xci") { pfs = new Xci(_virtualFileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure); } @@ -194,7 +182,7 @@ namespace Ryujinx.Ava.Common pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage()); - if (nca.Header.ContentType == NcaContentType.Program) + if (nca.Header.ContentType is NcaContentType.Program) { int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()) @@ -208,12 +196,12 @@ namespace Ryujinx.Ava.Common } } } - else if (extension == ".nca") + else if (extension is ".nca") { mainNca = new Nca(_virtualFileSystem.KeySet, file.AsStorage()); } - if (mainNca == null) + if (mainNca is null) { Logger.Error?.Print(LogClass.Application, "Extraction failure. The main NCA was not present in the selected file"); @@ -232,7 +220,7 @@ namespace Ryujinx.Ava.Common : IntegrityCheckLevel.None; (Nca updatePatchNca, _) = mainNca.GetUpdateData(_virtualFileSystem, checkLevel, programIndex, out _); - if (updatePatchNca != null) + if (updatePatchNca is not null) { patchNca = updatePatchNca; } @@ -242,7 +230,7 @@ namespace Ryujinx.Ava.Common try { bool sectionExistsInPatch = false; - if (patchNca != null) + if (patchNca is not null) { sectionExistsInPatch = patchNca.CanOpenSection(index); } @@ -309,6 +297,23 @@ namespace Ryujinx.Ava.Common extractorThread.Start(); } + + public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) + { + var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + { + Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], + AllowMultiple = false, + }); + + if (result.Count == 0) + { + return; + } + + ExtractSection(result[0].Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex); + } + public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token) { Result rc = fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath.ToU8Span(), OpenDirectoryMode.All); diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs index 068968650..b84015d6e 100644 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs @@ -1,6 +1,7 @@ using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; +using Avalonia.Platform.Storage; using LibHac.Fs; using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Ava.Common; @@ -325,13 +326,29 @@ namespace Ryujinx.Ava.UI.Controls { var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel; - if (viewModel?.SelectedApplication != null) + if (viewModel?.SelectedApplication is { } selectedApp) { - await ApplicationHelper.ExtractSection( - viewModel.StorageProvider, + var result = await viewModel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + { + Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], + AllowMultiple = false, + }); + + if (result.Count == 0) + { + return; + } + + ApplicationHelper.ExtractSection( + result[0].Path.LocalPath, NcaSectionType.Logo, viewModel.SelectedApplication.Path, viewModel.SelectedApplication.Name); + + var iconFile = await result[0].CreateFileAsync(selectedApp.IdString + ".png"); + await using var fileStream = await iconFile.OpenWriteAsync(); + + fileStream.Write(selectedApp.Icon); } }