From 86741d3c922b710480eec7fc735969440210ef8b Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Tue, 14 Aug 2018 17:38:32 -0600 Subject: [PATCH] Extract main RomFS from XCIs --- hactoolnet/CliParser.cs | 1 + hactoolnet/Program.cs | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/hactoolnet/CliParser.cs b/hactoolnet/CliParser.cs index 5262cb56..71e418f6 100644 --- a/hactoolnet/CliParser.cs +++ b/hactoolnet/CliParser.cs @@ -165,6 +165,7 @@ namespace hactoolnet sb.AppendLine(" --securedir Specify secure XCI directory path."); sb.AppendLine(" --logodir Specify logo XCI directory path."); sb.AppendLine(" --outdir Specify XCI directory path."); + sb.AppendLine(" --romfsdir Specify main RomFS directory path."); sb.AppendLine("Switch FS options:"); sb.AppendLine(" --sdseed Set console unique seed for SD card NAX0 encryption."); sb.AppendLine(" --listapps List application info."); diff --git a/hactoolnet/Program.cs b/hactoolnet/Program.cs index 4042bca1..ea77cf95 100644 --- a/hactoolnet/Program.cs +++ b/hactoolnet/Program.cs @@ -221,6 +221,11 @@ namespace hactoolnet if (ctx.Options.OutDir != null && xci.RootPartition != null) { var root = xci.RootPartition; + if (root == null) + { + ctx.Logger.LogMessage("Could not find root partition"); + return; + } foreach (var sub in root.Files) { @@ -230,6 +235,45 @@ namespace hactoolnet subPfs.Extract(subDir, ctx.Logger); } } + + if (ctx.Options.RomfsOutDir != null) + { + if (xci.SecurePartition == null) + { + ctx.Logger.LogMessage("Could not find secure partition"); + return; + } + + Nca mainNca = null; + + foreach (var fileEntry in xci.SecurePartition.Files.Where(x => x.Name.EndsWith(".nca"))) + { + var ncaStream = xci.SecurePartition.OpenFile(fileEntry); + var nca = new Nca(ctx.Keyset, ncaStream, true); + + if (nca.Header.ContentType == ContentType.Program) + { + mainNca = nca; + } + } + + if (mainNca == null) + { + ctx.Logger.LogMessage("Could not find Program NCA"); + return; + } + + var romfsSection = mainNca.Sections.FirstOrDefault(x => x.Type == SectionType.Romfs); + + if (romfsSection == null) + { + ctx.Logger.LogMessage("NCA has no RomFS section"); + return; + } + + var romfs = new Romfs(mainNca.OpenSection(romfsSection.SectionNum, false)); + romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger); + } } }