mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
hactoolnet: Use new NCA APIs
This commit is contained in:
parent
c267826dd1
commit
c73493b505
7 changed files with 47 additions and 79 deletions
|
@ -10,7 +10,7 @@ namespace LibHac.IO.NcaUtils
|
|||
{
|
||||
private const int HeaderSize = 0xc00;
|
||||
private const int HeaderSectorSize = 0x200;
|
||||
|
||||
|
||||
public NcaHeader Header { get; }
|
||||
public string NcaId { get; set; }
|
||||
public string Filename { get; set; }
|
||||
|
@ -91,6 +91,11 @@ namespace LibHac.IO.NcaUtils
|
|||
return sect.Header.EncryptionType == NcaEncryptionType.None || !IsMissingTitleKey && string.IsNullOrWhiteSpace(MissingKeyName);
|
||||
}
|
||||
|
||||
public bool CanOpenSection(NcaSectionType type)
|
||||
{
|
||||
return CanOpenSection(GetSectionIndexFromType(type));
|
||||
}
|
||||
|
||||
private IStorage OpenEncryptedStorage(int index)
|
||||
{
|
||||
if (index < 0 || index > 3) throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
@ -275,11 +280,9 @@ namespace LibHac.IO.NcaUtils
|
|||
return Sections[index] != null;
|
||||
}
|
||||
|
||||
public bool SectionIsDecryptable(int index)
|
||||
public bool SectionExists(NcaSectionType type)
|
||||
{
|
||||
if (!SectionExists(index)) return false;
|
||||
|
||||
return Sections[index].Header.EncryptionType == NcaEncryptionType.None || !IsMissingTitleKey && string.IsNullOrWhiteSpace(MissingKeyName);
|
||||
return SectionExists(GetSectionIndexFromType(type));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -363,7 +366,7 @@ namespace LibHac.IO.NcaUtils
|
|||
{
|
||||
if (Header != null)
|
||||
{
|
||||
return Header.Version;
|
||||
return Header.Version;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -25,16 +25,27 @@ namespace LibHac.IO.NcaUtils
|
|||
.WriteAllBytes(filename, logger);
|
||||
}
|
||||
|
||||
public static void ExportSection(this Nca nca, NcaSectionType type, string filename, bool raw = false,
|
||||
IntegrityCheckLevel integrityCheckLevel = IntegrityCheckLevel.None, IProgressReport logger = null)
|
||||
{
|
||||
nca.OpenStorage(type, integrityCheckLevel, raw)
|
||||
.WriteAllBytes(filename, logger);
|
||||
}
|
||||
|
||||
public static void ExtractSection(this Nca nca, int index, string outputDir,
|
||||
IntegrityCheckLevel integrityCheckLevel = IntegrityCheckLevel.None, IProgressReport logger = null)
|
||||
{
|
||||
if (index < 0 || index > 3) throw new IndexOutOfRangeException();
|
||||
if (!nca.SectionIsDecryptable(index)) return;
|
||||
|
||||
IFileSystem fs = nca.OpenFileSystem(index, integrityCheckLevel);
|
||||
fs.Extract(outputDir, logger);
|
||||
}
|
||||
|
||||
public static void ExtractSection(this Nca nca, NcaSectionType type, string outputDir,
|
||||
IntegrityCheckLevel integrityCheckLevel = IntegrityCheckLevel.None, IProgressReport logger = null)
|
||||
{
|
||||
IFileSystem fs = nca.OpenFileSystem(type, integrityCheckLevel);
|
||||
fs.Extract(outputDir, logger);
|
||||
}
|
||||
|
||||
public static Validity VerifyNca(this Nca nca, IProgressReport logger = null, bool quiet = false)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
|
|
|
@ -193,13 +193,6 @@ namespace LibHac.IO.NcaUtils
|
|||
}
|
||||
}
|
||||
|
||||
public enum ProgramPartitionType
|
||||
{
|
||||
Code,
|
||||
Data,
|
||||
Logo
|
||||
};
|
||||
|
||||
public enum NcaSectionType
|
||||
{
|
||||
Code,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using LibHac;
|
||||
using LibHac.IO;
|
||||
|
@ -46,13 +45,13 @@ namespace hactoolnet
|
|||
nca.ExtractSection(i, ctx.Options.SectionOutDir[i], ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
|
||||
if (ctx.Options.Validate && nca.Sections[i] != null)
|
||||
if (ctx.Options.Validate && nca.SectionExists(i))
|
||||
{
|
||||
nca.VerifySection(i, ctx.Logger);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.Options.ListRomFs && nca.Sections[1] != null)
|
||||
if (ctx.Options.ListRomFs && nca.CanOpenSection(NcaSectionType.Data))
|
||||
{
|
||||
IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, ctx.Options.IntegrityLevel);
|
||||
|
||||
|
@ -64,35 +63,26 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.RomfsOutDir != null || ctx.Options.RomfsOut != null || ctx.Options.ReadBench)
|
||||
{
|
||||
NcaSection section = nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs || x?.Type == SectionType.Bktr);
|
||||
|
||||
if (section == null)
|
||||
if (!nca.SectionExists(NcaSectionType.Data))
|
||||
{
|
||||
ctx.Logger.LogMessage("NCA has no RomFS section");
|
||||
return;
|
||||
}
|
||||
|
||||
if (section.Type == SectionType.Bktr && ctx.Options.BaseNca == null)
|
||||
{
|
||||
ctx.Logger.LogMessage("Cannot save BKTR section without base RomFS");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.Options.RomfsOut != null)
|
||||
{
|
||||
nca.ExportSection(section.SectionNum, ctx.Options.RomfsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
nca.ExportSection(NcaSectionType.Data, ctx.Options.RomfsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
|
||||
if (ctx.Options.RomfsOutDir != null)
|
||||
{
|
||||
IFileSystem romfs = nca.OpenFileSystem(section.SectionNum, ctx.Options.IntegrityLevel);
|
||||
romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger);
|
||||
nca.ExtractSection(NcaSectionType.Data, ctx.Options.RomfsOutDir, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
|
||||
if (ctx.Options.ReadBench)
|
||||
{
|
||||
long bytesToRead = 1024L * 1024 * 1024 * 5;
|
||||
IStorage storage = nca.OpenStorage(section.SectionNum, ctx.Options.IntegrityLevel);
|
||||
IStorage storage = nca.OpenStorage(NcaSectionType.Data, ctx.Options.IntegrityLevel);
|
||||
var dest = new NullStorage(storage.Length);
|
||||
|
||||
int iterations = (int)(bytesToRead / storage.Length) + 1;
|
||||
|
@ -119,9 +109,7 @@ namespace hactoolnet
|
|||
return;
|
||||
}
|
||||
|
||||
NcaSection section = nca.Sections[(int)ProgramPartitionType.Code];
|
||||
|
||||
if (section == null)
|
||||
if (!nca.SectionExists(NcaSectionType.Code))
|
||||
{
|
||||
ctx.Logger.LogMessage("Could not find an ExeFS section");
|
||||
return;
|
||||
|
@ -129,13 +117,12 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.ExefsOut != null)
|
||||
{
|
||||
nca.ExportSection(section.SectionNum, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
nca.ExportSection(NcaSectionType.Code, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
|
||||
if (ctx.Options.ExefsOutDir != null)
|
||||
{
|
||||
IFileSystem pfs = nca.OpenFileSystem(section.SectionNum, ctx.Options.IntegrityLevel);
|
||||
pfs.Extract(ctx.Options.ExefsOutDir, ctx.Logger);
|
||||
nca.ExtractSection(NcaSectionType.Code, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +186,7 @@ namespace hactoolnet
|
|||
NcaSection sect = nca.Sections[i];
|
||||
if (sect == null) continue;
|
||||
|
||||
bool isExefs = nca.Header.ContentType == ContentType.Program && i == (int)ProgramPartitionType.Code;
|
||||
bool isExefs = nca.Header.ContentType == ContentType.Program && i == 0;
|
||||
|
||||
sb.AppendLine($" Section {i}:");
|
||||
PrintItem(sb, colLen, " Offset:", $"0x{sect.Offset:x12}");
|
||||
|
|
|
@ -10,13 +10,14 @@ namespace hactoolnet
|
|||
{
|
||||
using (var file = new LocalStorage(ctx.Options.InFile, FileAccess.Read))
|
||||
{
|
||||
var romfs = new RomFsFileSystem(file);
|
||||
Process(ctx, romfs);
|
||||
Process(ctx, file);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Process(Context ctx, RomFsFileSystem romfs)
|
||||
public static void Process(Context ctx, IStorage romfsStorage)
|
||||
{
|
||||
var romfs = new RomFsFileSystem(romfsStorage);
|
||||
|
||||
if (ctx.Options.ListRomFs)
|
||||
{
|
||||
foreach (DirectoryEntry entry in romfs.EnumerateEntries())
|
||||
|
@ -29,7 +30,6 @@ namespace hactoolnet
|
|||
{
|
||||
using (var outFile = new FileStream(ctx.Options.RomfsOut, FileMode.Create, FileAccess.ReadWrite))
|
||||
{
|
||||
IStorage romfsStorage = romfs.GetBaseStorage();
|
||||
romfsStorage.CopyToStream(outFile, romfsStorage.Length, ctx.Logger);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,9 +69,7 @@ namespace hactoolnet
|
|||
return;
|
||||
}
|
||||
|
||||
NcaSection section = title.MainNca.Sections[(int)ProgramPartitionType.Code];
|
||||
|
||||
if (section == null)
|
||||
if (!title.MainNca.SectionExists(NcaSectionType.Code))
|
||||
{
|
||||
ctx.Logger.LogMessage($"Main NCA for title {id:X16} has no ExeFS section");
|
||||
return;
|
||||
|
@ -79,12 +77,12 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.ExefsOutDir != null)
|
||||
{
|
||||
title.MainNca.ExtractSection(section.SectionNum, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
title.MainNca.ExtractSection(NcaSectionType.Code, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
|
||||
if (ctx.Options.ExefsOut != null)
|
||||
{
|
||||
title.MainNca.ExportSection(section.SectionNum, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
title.MainNca.ExportSection(NcaSectionType.Code, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,24 +107,13 @@ namespace hactoolnet
|
|||
return;
|
||||
}
|
||||
|
||||
NcaSection section = title.MainNca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs || x?.Type == SectionType.Bktr);
|
||||
|
||||
if (section == null)
|
||||
if (!title.MainNca.SectionExists(NcaSectionType.Data))
|
||||
{
|
||||
ctx.Logger.LogMessage($"Main NCA for title {id:X16} has no RomFS section");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.Options.RomfsOutDir != null)
|
||||
{
|
||||
IFileSystem romfs = title.MainNca.OpenFileSystem(section.SectionNum, ctx.Options.IntegrityLevel);
|
||||
romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger);
|
||||
}
|
||||
|
||||
if (ctx.Options.RomfsOut != null)
|
||||
{
|
||||
title.MainNca.ExportSection(section.SectionNum, ctx.Options.RomfsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
ProcessRomfs.Process(ctx, title.MainNca.OpenStorage(NcaSectionType.Data, ctx.Options.IntegrityLevel, false));
|
||||
}
|
||||
|
||||
if (ctx.Options.OutDir != null)
|
||||
|
|
|
@ -72,9 +72,7 @@ namespace hactoolnet
|
|||
return;
|
||||
}
|
||||
|
||||
NcaSection exefsSection = mainNca.Sections[(int)ProgramPartitionType.Code];
|
||||
|
||||
if (exefsSection == null)
|
||||
if (!mainNca.SectionExists(NcaSectionType.Code))
|
||||
{
|
||||
ctx.Logger.LogMessage("NCA has no ExeFS section");
|
||||
return;
|
||||
|
@ -82,12 +80,12 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.ExefsOutDir != null)
|
||||
{
|
||||
mainNca.ExtractSection(exefsSection.SectionNum, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
mainNca.ExtractSection(NcaSectionType.Code, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
|
||||
if (ctx.Options.ExefsOut != null)
|
||||
{
|
||||
mainNca.ExportSection(exefsSection.SectionNum, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
mainNca.ExportSection(NcaSectionType.Code, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,24 +99,13 @@ namespace hactoolnet
|
|||
return;
|
||||
}
|
||||
|
||||
NcaSection romfsSection = mainNca.Sections.FirstOrDefault(x => x.Type == SectionType.Romfs);
|
||||
|
||||
if (romfsSection == null)
|
||||
if (!mainNca.SectionExists(NcaSectionType.Data))
|
||||
{
|
||||
ctx.Logger.LogMessage("NCA has no RomFS section");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.Options.RomfsOutDir != null)
|
||||
{
|
||||
IFileSystem romfs = mainNca.OpenFileSystem(romfsSection.SectionNum, ctx.Options.IntegrityLevel);
|
||||
romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger);
|
||||
}
|
||||
|
||||
if (ctx.Options.RomfsOut != null)
|
||||
{
|
||||
mainNca.ExportSection(romfsSection.SectionNum, ctx.Options.RomfsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger);
|
||||
}
|
||||
ProcessRomfs.Process(ctx, mainNca.OpenStorage(NcaSectionType.Data, ctx.Options.IntegrityLevel, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue