2018-06-21 18:16:51 +02:00
|
|
|
|
using System;
|
2018-06-22 23:17:20 +02:00
|
|
|
|
using System.Collections.Generic;
|
2018-06-25 21:01:24 +02:00
|
|
|
|
using System.Diagnostics;
|
2018-06-21 18:16:51 +02:00
|
|
|
|
using System.IO;
|
2018-06-21 23:03:58 +02:00
|
|
|
|
using System.Linq;
|
2018-06-21 16:25:20 +02:00
|
|
|
|
using libhac;
|
2018-06-16 19:11:38 +02:00
|
|
|
|
|
2018-06-21 16:25:20 +02:00
|
|
|
|
namespace hactoolnet
|
2018-06-16 19:11:38 +02:00
|
|
|
|
{
|
2018-06-21 16:25:20 +02:00
|
|
|
|
public static class Program
|
2018-06-16 19:11:38 +02:00
|
|
|
|
{
|
|
|
|
|
static void Main(string[] args)
|
2018-06-21 18:16:51 +02:00
|
|
|
|
{
|
2018-06-25 21:01:24 +02:00
|
|
|
|
Console.WriteLine("Listing NCA files");
|
|
|
|
|
ListSdContents(args);
|
|
|
|
|
|
|
|
|
|
Console.WriteLine("Listing titles");
|
|
|
|
|
var watch = Stopwatch.StartNew();
|
|
|
|
|
|
2018-06-22 23:17:20 +02:00
|
|
|
|
DumpMeta(args);
|
2018-06-25 21:01:24 +02:00
|
|
|
|
watch.Stop();
|
|
|
|
|
Console.WriteLine(watch.Elapsed.TotalMilliseconds);
|
2018-06-21 18:16:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void DecryptNax0(string[] args)
|
2018-06-16 19:11:38 +02:00
|
|
|
|
{
|
2018-06-20 19:42:56 +02:00
|
|
|
|
var keyset = ExternalKeys.ReadKeyFile(args[0]);
|
|
|
|
|
keyset.SetSdSeed(args[1].ToBytes());
|
|
|
|
|
|
2018-06-25 21:01:24 +02:00
|
|
|
|
using (var nax0 = Nax0.CreateFromPath(keyset, args[2], args[3]))
|
2018-06-20 19:42:56 +02:00
|
|
|
|
{
|
2018-06-26 00:26:47 +02:00
|
|
|
|
var nca = new Nca(keyset, nax0.Stream, true);
|
2018-06-25 21:01:24 +02:00
|
|
|
|
|
|
|
|
|
using (var output = new FileStream(args[4], FileMode.Create))
|
|
|
|
|
using (var progress = new ProgressBar())
|
|
|
|
|
{
|
|
|
|
|
progress.LogMessage($"Title ID: {nca.Header.TitleId:X16}");
|
|
|
|
|
progress.LogMessage($"Writing {args[4]}");
|
|
|
|
|
nax0.Stream.CopyStream(output, nax0.Stream.Length, progress);
|
|
|
|
|
}
|
2018-06-20 19:42:56 +02:00
|
|
|
|
}
|
2018-06-16 19:11:38 +02:00
|
|
|
|
}
|
2018-06-21 18:16:51 +02:00
|
|
|
|
|
|
|
|
|
static void ListSdContents(string[] args)
|
2018-06-22 23:17:20 +02:00
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"Using key file {args[0]}");
|
|
|
|
|
Console.WriteLine($"SD seed {BitConverter.ToString(args[1].ToBytes())}");
|
|
|
|
|
Console.WriteLine($"SD path {args[2]}");
|
|
|
|
|
var keyset = ExternalKeys.ReadKeyFile(args[0]);
|
|
|
|
|
|
|
|
|
|
if (keyset.master_keys[0].IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("Need master key 0");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
keyset.SetSdSeed(args[1].ToBytes());
|
2018-06-26 00:26:47 +02:00
|
|
|
|
using (var sdfs = new SdFs(keyset, args[2]))
|
2018-06-22 23:17:20 +02:00
|
|
|
|
{
|
2018-06-26 00:26:47 +02:00
|
|
|
|
sdfs.OpenAllNcas();
|
|
|
|
|
|
|
|
|
|
foreach (Nca nca in sdfs.Ncas)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine(
|
|
|
|
|
$"{nca.Header.TitleId:X16} {nca.Header.ContentType.ToString().PadRight(10, ' ')} {nca.Name}");
|
|
|
|
|
}
|
2018-06-22 23:17:20 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void DumpMeta(string[] args)
|
2018-06-21 18:16:51 +02:00
|
|
|
|
{
|
|
|
|
|
var keyset = ExternalKeys.ReadKeyFile(args[0]);
|
|
|
|
|
keyset.SetSdSeed(args[1].ToBytes());
|
2018-06-26 00:26:47 +02:00
|
|
|
|
List<Nca> ncas;
|
|
|
|
|
using (var sdfs = new SdFs(keyset, args[2]))
|
|
|
|
|
{
|
|
|
|
|
sdfs.OpenAllNcas();
|
|
|
|
|
ncas = sdfs.Ncas;
|
2018-06-21 18:16:51 +02:00
|
|
|
|
|
2018-06-26 00:26:47 +02:00
|
|
|
|
var metadata = new List<Cnmt>();
|
2018-06-22 23:17:20 +02:00
|
|
|
|
|
2018-06-26 00:26:47 +02:00
|
|
|
|
using (var progress = new ProgressBar())
|
2018-06-22 23:17:20 +02:00
|
|
|
|
{
|
2018-06-26 00:26:47 +02:00
|
|
|
|
foreach (var nca in ncas.Where(x => x.Header.ContentType == ContentType.Meta))
|
2018-06-22 23:17:20 +02:00
|
|
|
|
{
|
2018-06-26 00:26:47 +02:00
|
|
|
|
foreach (var section in nca.Sections.Where(x => x.Header.FsType == SectionFsType.Pfs0))
|
2018-06-22 23:17:20 +02:00
|
|
|
|
{
|
2018-06-26 00:26:47 +02:00
|
|
|
|
var sect = nca.OpenSection(section.SectionNum);
|
|
|
|
|
var pfs0 = new Pfs0(sect);
|
|
|
|
|
|
|
|
|
|
foreach (var entry in pfs0.Entries)
|
|
|
|
|
{
|
|
|
|
|
var path = Path.Combine("meta", entry.Name);
|
|
|
|
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
|
|
|
|
var file = pfs0.GetFile(entry.Index);
|
|
|
|
|
|
|
|
|
|
metadata.Add(new Cnmt(new MemoryStream(file)));
|
|
|
|
|
File.WriteAllBytes(path, file);
|
|
|
|
|
}
|
2018-06-22 23:17:20 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-23 04:02:19 +02:00
|
|
|
|
|
2018-06-26 00:26:47 +02:00
|
|
|
|
foreach (var meta in metadata.OrderBy(x => x.TitleId))
|
2018-06-23 04:02:19 +02:00
|
|
|
|
{
|
2018-06-26 00:26:47 +02:00
|
|
|
|
progress.LogMessage($"{meta.TitleId:X16} v{meta.TitleVersion} {meta.Type}");
|
|
|
|
|
|
|
|
|
|
foreach (var content in meta.ContentEntries)
|
|
|
|
|
{
|
|
|
|
|
// Add an actual hexdump function
|
|
|
|
|
progress.LogMessage(
|
|
|
|
|
$" {BitConverter.ToString(content.NcaId).Replace("-", "")}.nca {content.Type}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
progress.LogMessage("");
|
2018-06-23 04:02:19 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-21 18:16:51 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-16 19:11:38 +02:00
|
|
|
|
}
|
|
|
|
|
}
|