aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThog <me@thog.eu>2020-04-23 21:21:32 +0200
committerGitHub <noreply@github.com>2020-04-23 21:21:32 +0200
commitfba8651213001b79604c0429ed5ebe5845f08d61 (patch)
tree46528fc393c1e0f7c696ace330e48d7b97657313
parent72b560d15cd53684a6421685b5721e5eaba9aa74 (diff)
ui: Make ExtractSection supports updates (#1150)
This adds update support to the section extractor.
-rw-r--r--Ryujinx/Ui/GameTableContextMenu.cs53
1 files changed, 51 insertions, 2 deletions
diff --git a/Ryujinx/Ui/GameTableContextMenu.cs b/Ryujinx/Ui/GameTableContextMenu.cs
index 0796d95d..5db34ecb 100644
--- a/Ryujinx/Ui/GameTableContextMenu.cs
+++ b/Ryujinx/Ui/GameTableContextMenu.cs
@@ -8,6 +8,8 @@ using LibHac.FsSystem;
using LibHac.FsSystem.NcaUtils;
using LibHac.Ncm;
using LibHac.Ns;
+using LibHac.Spl;
+using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem;
using System;
@@ -17,7 +19,8 @@ using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;
-
+using Utf8Json;
+using Utf8Json.Resolvers;
using static LibHac.Fs.ApplicationSaveDataManagement;
using GUI = Gtk.Builder.ObjectAttribute;
@@ -195,7 +198,7 @@ namespace Ryujinx.Ui
SecondaryText = $"Extracting {ncaSectionType} section from {System.IO.Path.GetFileName(sourceFile)}...",
WindowPosition = WindowPosition.Center
};
-
+
int dialogResponse = _dialog.Run();
if (dialogResponse == (int)ResponseType.Cancel || dialogResponse == (int)ResponseType.DeleteEvent)
{
@@ -264,6 +267,52 @@ namespace Ryujinx.Ui
return;
}
+ string titleUpdateMetadataPath = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", mainNca.Header.TitleId.ToString("x16"), "updates.json");
+
+ if (File.Exists(titleUpdateMetadataPath))
+ {
+ using (Stream stream = File.OpenRead(titleUpdateMetadataPath))
+ {
+ IJsonFormatterResolver resolver = CompositeResolver.Create(StandardResolver.AllowPrivateSnakeCase);
+ string updatePath = JsonSerializer.Deserialize<TitleUpdateMetadata>(stream, resolver).Selected;
+
+ if (File.Exists(updatePath))
+ {
+ FileStream updateFile = new FileStream(updatePath, FileMode.Open, FileAccess.Read);
+ PartitionFileSystem nsp = new PartitionFileSystem(updateFile.AsStorage());
+
+ foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik"))
+ {
+ Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read);
+
+ if (result.IsSuccess())
+ {
+ Ticket ticket = new Ticket(ticketFile.AsStream());
+
+ _virtualFileSystem.KeySet.ExternalKeySet.Add(new LibHac.Fs.RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(_virtualFileSystem.KeySet)));
+ }
+ }
+
+ foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
+ {
+ nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+ Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
+
+ if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != mainNca.Header.TitleId.ToString("x16"))
+ {
+ break;
+ }
+
+ if (nca.Header.ContentType == NcaContentType.Program)
+ {
+ patchNca = nca;
+ }
+ }
+ }
+ }
+ }
+
int index = Nca.GetSectionIndexFromType(ncaSectionType, mainNca.Header.ContentType);
IFileSystem ncaFileSystem = patchNca != null ? mainNca.OpenFileSystemWithPatch(patchNca, index, IntegrityCheckLevel.ErrorOnInvalid)