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