mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add an NRO reader (#44)
This commit is contained in:
parent
22416f66bf
commit
42ce382bf5
1 changed files with 154 additions and 0 deletions
154
src/LibHac/Nro.cs
Normal file
154
src/LibHac/Nro.cs
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
using System.IO;
|
||||||
|
using LibHac.IO;
|
||||||
|
|
||||||
|
namespace LibHac
|
||||||
|
{
|
||||||
|
public class Nro
|
||||||
|
{
|
||||||
|
public NroStart Start { get; }
|
||||||
|
public NroHeader Header { get; }
|
||||||
|
public NroAssetHeader AssetHeader { get; }
|
||||||
|
private IStorage Storage { get; }
|
||||||
|
private IStorage AssetStorage { get; }
|
||||||
|
|
||||||
|
public Nro(IStorage storage)
|
||||||
|
{
|
||||||
|
Storage = storage;
|
||||||
|
var reader = new BinaryReader(Storage.AsStream());
|
||||||
|
Start = new NroStart(reader);
|
||||||
|
Header = new NroHeader(reader);
|
||||||
|
|
||||||
|
if (Header.Magic != "NRO0")
|
||||||
|
throw new InvalidDataException("NRO0 magic is incorrect!");
|
||||||
|
|
||||||
|
if (Header.Size < Storage.GetSize())
|
||||||
|
{
|
||||||
|
AssetStorage = Storage.Slice(Header.Size);
|
||||||
|
var assetReader = new BinaryReader(AssetStorage.AsStream());
|
||||||
|
|
||||||
|
AssetHeader = new NroAssetHeader(assetReader);
|
||||||
|
if (AssetHeader.Magic != "ASET")
|
||||||
|
throw new InvalidDataException("ASET magic is incorrect!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IStorage OpenNroSegment(NroSegmentType type, bool leaveOpen)
|
||||||
|
{
|
||||||
|
NroSegment segment = Header.NroSegments[(int)type];
|
||||||
|
|
||||||
|
if (segment.Size <= 0) return new NullStorage(0);
|
||||||
|
|
||||||
|
return Storage.Slice(segment.FileOffset, segment.Size, leaveOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IStorage OpenNroAssetSection(NroAssetType type, bool leaveOpen)
|
||||||
|
{
|
||||||
|
NroAssetSection header = AssetHeader.NroAssetSections[(int)type];
|
||||||
|
|
||||||
|
if (header.Size <= 0) return new NullStorage(0);
|
||||||
|
|
||||||
|
return AssetStorage.Slice(header.FileOffset, header.Size, leaveOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NroStart
|
||||||
|
{
|
||||||
|
public int Mod0Offset { get; }
|
||||||
|
|
||||||
|
public NroStart(BinaryReader reader)
|
||||||
|
{
|
||||||
|
reader.BaseStream.Position += 4;
|
||||||
|
Mod0Offset = reader.ReadInt32();
|
||||||
|
reader.BaseStream.Position += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NroHeader
|
||||||
|
{
|
||||||
|
public string Magic { get; }
|
||||||
|
public uint Version { get; }
|
||||||
|
public uint Size { get; }
|
||||||
|
public uint BssSize { get; }
|
||||||
|
public byte[] BuildId { get; }
|
||||||
|
|
||||||
|
public NroSegment[] NroSegments { get; } = new NroSegment[0x3];
|
||||||
|
|
||||||
|
public NroHeader(BinaryReader reader)
|
||||||
|
{
|
||||||
|
Magic = reader.ReadAscii(4);
|
||||||
|
Version = reader.ReadUInt32();
|
||||||
|
Size = reader.ReadUInt32();
|
||||||
|
reader.BaseStream.Position += 4;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
NroSegments[i] = new NroSegment(reader, (NroSegmentType)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
BssSize = reader.ReadUInt32();
|
||||||
|
reader.BaseStream.Position += 4;
|
||||||
|
BuildId = reader.ReadBytes(0x20);
|
||||||
|
reader.BaseStream.Position += 0x20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum NroSegmentType
|
||||||
|
{
|
||||||
|
Text = 0,
|
||||||
|
Ro,
|
||||||
|
Data
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NroSegment
|
||||||
|
{
|
||||||
|
public NroSegmentType Type { get; }
|
||||||
|
public uint FileOffset { get; }
|
||||||
|
public uint Size { get; }
|
||||||
|
|
||||||
|
public NroSegment(BinaryReader reader, NroSegmentType type)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
FileOffset = reader.ReadUInt32();
|
||||||
|
Size = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NroAssetHeader
|
||||||
|
{
|
||||||
|
public string Magic { get; }
|
||||||
|
public uint Version { get; }
|
||||||
|
public NroAssetSection[] NroAssetSections { get; } = new NroAssetSection[0x3];
|
||||||
|
|
||||||
|
public NroAssetHeader(BinaryReader reader)
|
||||||
|
{
|
||||||
|
Magic = reader.ReadAscii(4);
|
||||||
|
Version = reader.ReadUInt32();
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
NroAssetSections[i] = new NroAssetSection(reader, (NroAssetType)i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum NroAssetType
|
||||||
|
{
|
||||||
|
Icon = 0,
|
||||||
|
Nacp,
|
||||||
|
RomFs
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NroAssetSection
|
||||||
|
{
|
||||||
|
public NroAssetType Type { get; }
|
||||||
|
public uint FileOffset { get; }
|
||||||
|
public uint Size { get; }
|
||||||
|
|
||||||
|
public NroAssetSection(BinaryReader reader, NroAssetType type)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
FileOffset = (uint)reader.ReadUInt64();
|
||||||
|
Size = (uint)reader.ReadUInt64();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue