Make sure meta nca is included in title

This commit is contained in:
Alex Barney 2018-06-26 19:42:01 -05:00
parent e4d9b46e60
commit f583d01248
4 changed files with 65 additions and 5 deletions

View file

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using libhac;
@ -20,10 +18,12 @@ namespace hactoolnet
ListTitles(sdfs);
//DecryptNax0(sdfs, "C0628FB07A89E9050BDA258F74868E8D");
DecryptTitle(sdfs, 0x0100000000010800);
}
static void DecryptNax0(SdFs sdFs, string name)
{
if (!sdFs.Ncas.ContainsKey(name)) return;
var nca = sdFs.Ncas[name];
using (var output = new FileStream($"{nca.NcaId}.nca", FileMode.Create))
using (var progress = new ProgressBar())
@ -35,6 +35,25 @@ namespace hactoolnet
}
}
static void DecryptTitle(SdFs sdFs, ulong titleId)
{
var title = sdFs.Titles[titleId];
var dirName = $"{titleId:X16}v{title.Version.Version}";
Directory.CreateDirectory(dirName);
foreach (var nca in title.Ncas)
{
using (var output = new FileStream(Path.Combine(dirName, nca.Filename), FileMode.Create))
using (var progress = new ProgressBar())
{
progress.LogMessage($"Writing {nca.Filename}");
nca.Stream.Position = 0;
nca.Stream.CopyStream(output, nca.Stream.Length, progress);
}
}
}
static SdFs LoadSdFs(string[] args)
{
var keyset = ExternalKeys.ReadKeyFile(args[0]);
@ -60,7 +79,7 @@ namespace hactoolnet
foreach (var content in title.Metadata.ContentEntries)
{
Console.WriteLine(
$" {BitConverter.ToString(content.NcaId).Replace("-", "")}.nca {content.Type} {Util.GetBytesReadable(content.Size)}");
$" {content.NcaId.ToHexString()}.nca {content.Type} {Util.GetBytesReadable(content.Size)}");
}
Console.WriteLine("");

View file

@ -9,6 +9,7 @@ namespace libhac
{
public NcaHeader Header { get; private set; }
public string NcaId { get; set; }
public string Filename { get; set; }
public bool HasRightsId { get; private set; }
public int CryptoType { get; private set; }
public byte[][] DecryptedKeys { get; } = Util.CreateJaggedArray<byte[][]>(4, 0x10);

View file

@ -31,7 +31,7 @@ namespace libhac
ReadTitles();
}
public void OpenAllNcas()
private void OpenAllNcas()
{
foreach (var file in Files)
{
@ -43,6 +43,8 @@ namespace libhac
Nax0s.Add(nax0);
nca = new Nca(Keyset, nax0.Stream, false);
nca.NcaId = Path.GetFileNameWithoutExtension(file);
var extention = nca.Header.ContentType == ContentType.Meta ? ".cnmt.nca" : ".nca";
nca.Filename = nca.NcaId + extention;
}
catch (Exception ex)
{
@ -53,7 +55,7 @@ namespace libhac
}
}
public void ReadTitles()
private void ReadTitles()
{
foreach (var nca in Ncas.Values.Where(x => x.Header.ContentType == ContentType.Meta))
{
@ -68,6 +70,18 @@ namespace libhac
title.Id = metadata.TitleId;
title.Version = new TitleVersion(metadata.TitleVersion);
title.Metadata = metadata;
title.Ncas.Add(nca);
foreach (var content in metadata.ContentEntries)
{
var ncaId = content.NcaId.ToHexString();
if (Ncas.TryGetValue(ncaId, out Nca contentNca))
{
title.Ncas.Add(contentNca);
}
}
Titles.Add(title.Id, title);
}
}

View file

@ -177,6 +177,32 @@ namespace libhac
return result;
}
private static readonly uint[] Lookup32 = CreateLookup32();
private static uint[] CreateLookup32()
{
var result = new uint[256];
for (int i = 0; i < 256; i++)
{
string s = i.ToString("X2");
result[i] = s[0] + ((uint)s[1] << 16);
}
return result;
}
public static string ToHexString(this byte[] bytes)
{
var lookup32 = Lookup32;
var result = new char[bytes.Length * 2];
for (int i = 0; i < bytes.Length; i++)
{
var val = lookup32[bytes[i]];
result[2 * i] = (char)val;
result[2 * i + 1] = (char)(val >> 16);
}
return new string(result);
}
internal static long MediaToReal(long media)
{
return MediaSize * media;