From 8232ff7ed667cc2c847c9bc2b92608b67d095ecf Mon Sep 17 00:00:00 2001 From: MonsterDruide1 <5958456@gmail.com> Date: Wed, 28 Sep 2022 14:23:24 +0200 Subject: [PATCH] hactoolnet: Add NPDM converter --- README.md | 2 ++ src/hactoolnet/CliParser.cs | 6 +++++- src/hactoolnet/Options.cs | 4 +++- src/hactoolnet/ProcessNpdm.cs | 27 +++++++++++++++++++++++++++ src/hactoolnet/Program.cs | 3 +++ 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/hactoolnet/ProcessNpdm.cs diff --git a/README.md b/README.md index 2fd499c0..e819f89a 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,8 @@ NCA options: --romfsdir Specify RomFS directory path. --listromfs List files in RomFS. --basenca Set Base NCA to use with update partitions. +NPDM options: + --json Specify file path for saving JSON representation of program permissions to. KIP1 options: --uncompressed Specify file path for saving uncompressed KIP1. RomFS options: diff --git a/src/hactoolnet/CliParser.cs b/src/hactoolnet/CliParser.cs index f8ae51c6..a6a249dc 100644 --- a/src/hactoolnet/CliParser.cs +++ b/src/hactoolnet/CliParser.cs @@ -68,6 +68,7 @@ internal static class CliParser new CliOption("title", 1, (o, a) => o.TitleId = ParseTitleId(o, a[0])), new CliOption("bench", 1, (o, a) => o.BenchType = a[0]), new CliOption("cpufreq", 1, (o, a) => o.CpuFrequencyGhz = ParseDouble(o, a[0])), + new CliOption("json", 1, (o, a) => o.JsonFile = a[0]), new CliOption("replacefile", 2, (o, a) => { @@ -190,6 +191,7 @@ internal static class CliParser case "ini1": return FileType.Ini1; case "ndv0": return FileType.Ndv0; case "bench": return FileType.Bench; + case "npdm": return FileType.Npdm; } options.ParseErrorMessage ??= "Specified type is invalid."; @@ -274,6 +276,8 @@ internal static class CliParser sb.AppendLine(" --romfsdir Specify RomFS directory path."); sb.AppendLine(" --listromfs List files in RomFS."); sb.AppendLine(" --basenca Set Base NCA to use with update partitions."); + sb.AppendLine("NPDM options:"); + sb.AppendLine(" --json Specify file path for saving JSON representation of program permissions to."); sb.AppendLine("KIP1 options:"); sb.AppendLine(" --uncompressed Specify file path for saving uncompressed KIP1."); sb.AppendLine("RomFS options:"); @@ -370,4 +374,4 @@ internal static class CliParser public int ArgsNeeded { get; } public Action Assigner { get; } } -} \ No newline at end of file +} diff --git a/src/hactoolnet/Options.cs b/src/hactoolnet/Options.cs index a0ab9032..420eb1ff 100644 --- a/src/hactoolnet/Options.cs +++ b/src/hactoolnet/Options.cs @@ -63,6 +63,7 @@ internal class Options public ulong TitleId; public string BenchType; public double CpuFrequencyGhz; + public string JsonFile; public string ParseErrorMessage; public bool IsParseSuccessful; @@ -99,7 +100,8 @@ internal enum FileType Kip1, Ini1, Ndv0, - Bench + Bench, + Npdm } internal class Context diff --git a/src/hactoolnet/ProcessNpdm.cs b/src/hactoolnet/ProcessNpdm.cs new file mode 100644 index 00000000..d5b411c9 --- /dev/null +++ b/src/hactoolnet/ProcessNpdm.cs @@ -0,0 +1,27 @@ +using System.IO; +using System.Text.Json; +using LibHac.FsSystem; +using LibHac.Tools.FsSystem; +using LibHac.Tools.Npdm; + +namespace hactoolnet; + +internal static class ProcessNpdm +{ + public static void Process(Context ctx) + { + using (var file = new LocalStorage(ctx.Options.InFile, FileAccess.Read)) + { + var npdm = new NpdmBinary(file.AsStream(), ctx.KeySet); + + if(ctx.Options.JsonFile != null) + { + string json = JsonSerializer.Serialize(npdm, new JsonSerializerOptions + { + WriteIndented = true + }); + File.WriteAllText(ctx.Options.JsonFile, json); + } + } + } +} \ No newline at end of file diff --git a/src/hactoolnet/Program.cs b/src/hactoolnet/Program.cs index 9a540320..2be33d1e 100644 --- a/src/hactoolnet/Program.cs +++ b/src/hactoolnet/Program.cs @@ -182,6 +182,9 @@ public static class Program case FileType.Bench: ProcessBench.Process(ctx); break; + case FileType.Npdm: + ProcessNpdm.Process(ctx); + break; default: throw new ArgumentOutOfRangeException(); }