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);
+ }
}
}