diff --git a/hactoolnet/Program.cs b/hactoolnet/Program.cs index e040ee3b..c9c01066 100644 --- a/hactoolnet/Program.cs +++ b/hactoolnet/Program.cs @@ -10,7 +10,8 @@ namespace hactoolnet { static void Main(string[] args) { - FileReadTest(args); + ListSdfs(args); + //FileReadTest(args); //ReadNca(); //ListSdfs(args); //ReadNcaSdfs(args); @@ -36,17 +37,12 @@ namespace hactoolnet var title = sdfs.Titles[0x0100E95004038000]; var nca = title.ProgramNca; var romfsStream = nca.OpenSection(1, false); - var romfs = new Romfs(romfsStream); - var file = romfs.OpenFile("/bf2.ard"); + var file = romfs.OpenFile("/stream/voice/us/127/127390101.nop"); - using (var progress = new ProgressBar()) - using (var output = new FileStream("bf2.ard", FileMode.Create)) + using (var output = new FileStream("127390101.nop", FileMode.Create)) { - var watch = Stopwatch.StartNew(); - file.CopyStream(output, file.Length / 100, progress); - watch.Stop(); - progress.LogMessage(watch.Elapsed.TotalSeconds.ToString()); + file.CopyTo(output); } } @@ -133,6 +129,7 @@ namespace hactoolnet { foreach (var title in sdfs.Titles.Values.OrderBy(x => x.Id)) { + Console.WriteLine(title.Name); Console.WriteLine($"{title.Id:X16} v{title.Version.Version} ({title.Version}) {title.Metadata.Type}"); foreach (var content in title.Metadata.ContentEntries) diff --git a/libhac/Romfs.cs b/libhac/Romfs.cs index 0359d970..39887eb8 100644 --- a/libhac/Romfs.cs +++ b/libhac/Romfs.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -20,8 +19,6 @@ namespace libhac public Romfs(Stream stream) { - var watch = Stopwatch.StartNew(); - byte[] dirMetaTable; byte[] fileMetaTable; using (var reader = new BinaryReader(stream, Encoding.Default, true)) @@ -61,10 +58,6 @@ namespace libhac ResolveFilenames(); FileDict = Files.ToDictionary(x => x.FullPath, x => x); Stream = stream; - - watch.Stop(); - Console.WriteLine(watch.Elapsed.TotalMilliseconds); - Console.WriteLine(Files.Count); } public Stream OpenFile(string filename) @@ -78,6 +71,18 @@ namespace libhac return stream; } + public byte[] GetFile(string filename) + { + var stream = OpenFile(filename); + var file = new byte[stream.Length]; + using (var ms = new MemoryStream(file)) + { + stream.CopyTo(ms); + } + + return file; + } + public bool FileExists(string filename) => FileDict.ContainsKey(filename); private void SetReferences() @@ -118,7 +123,7 @@ namespace libhac dir = dir.Parent; } - for (int i = list.Count-1; i >= 0; i--) + for (int i = list.Count - 1; i >= 0; i--) { sb.Append(list[i]); } diff --git a/libhac/SdFs.cs b/libhac/SdFs.cs index d61bfcb9..0224d625 100644 --- a/libhac/SdFs.cs +++ b/libhac/SdFs.cs @@ -29,6 +29,7 @@ namespace libhac Files = Directory.GetFiles(ContentsDir, "00", SearchOption.AllDirectories).Select(Path.GetDirectoryName).ToArray(); OpenAllNcas(); ReadTitles(); + ReadControls(); } private void OpenAllNcas() @@ -97,6 +98,20 @@ namespace libhac } } + private void ReadControls() + { + foreach (var title in Titles.Values.Where(x => x.ControlNca != null)) + { + var romfs = new Romfs(title.ControlNca.OpenSection(0, false)); + var control = romfs.GetFile("/control.nacp"); + Directory.CreateDirectory("control"); + File.WriteAllBytes($"control/{title.Id:X16}.nacp", control); + + var reader = new BinaryReader(new MemoryStream(control)); + title.Name = reader.ReadUtf8Z(); + } + } + private void DisposeNcas() { foreach (Nca nca in Ncas.Values) @@ -123,6 +138,7 @@ namespace libhac public List Ncas { get; } = new List(); public Cnmt Metadata { get; internal set; } + public string Name { get; internal set; } public Nca MetaNca { get; internal set; } public Nca ProgramNca { get; internal set; } public Nca ControlNca { get; internal set; } diff --git a/libhac/Util.cs b/libhac/Util.cs index a645ee1b..733d727a 100644 --- a/libhac/Util.cs +++ b/libhac/Util.cs @@ -93,6 +93,21 @@ namespace libhac return text; } + public static string ReadUtf8Z(this BinaryReader reader) + { + var start = reader.BaseStream.Position; + + // Read until we hit the end of the stream (-1) or a zero + while (reader.BaseStream.ReadByte() - 1 > 0) { } + + int size = (int)(reader.BaseStream.Position - start - 1); + reader.BaseStream.Position = start; + + string text = reader.ReadUtf8(size); + reader.BaseStream.Position++; // Skip the null byte + return text; + } + public static string ReadAscii(this BinaryReader reader, int size) { return Encoding.ASCII.GetString(reader.ReadBytes(size), 0, size);