public IList <IArchiveFileInfo> Load(Stream input) { using var br = new BinaryReaderX(input, true); // Determine byte order br.BaseStream.Position = 4; br.ByteOrder = br.ReadType <ByteOrder>(); // Read header br.BaseStream.Position = 0; var header = br.ReadType <NarcHeader>(); // Read file entries var fatHeader = br.ReadType <NarcFatHeader>(); var entries = br.ReadMultiple <FatEntry>(fatHeader.fileCount); // Read FNT var fntOffset = (int)br.BaseStream.Position; var fntHeader = br.ReadType <NarcFntHeader>(); var gmifOffset = fntOffset + fntHeader.chunkSize; _hasNames = br.ReadInt32() >= 8; if (_hasNames) { return(NdsSupport.ReadFnt(br, fntOffset + 8, gmifOffset + 8, entries).ToList()); } return(entries.Select((x, i) => NdsSupport.CreateAfi(br.BaseStream, x.offset + gmifOffset + 8, x.Length, $"{i:00000000}.bin", i)).ToArray()); }
public IList <IArchiveFileInfo> Load(Stream input) { var result = new List <IArchiveFileInfo>(); using var br = new BinaryReaderX(input, true); // Read unit code input.Position = 0x12; var unitCode = br.ReadType <UnitCode>(); // Read header input.Position = 0; if (unitCode == UnitCode.NDS) { _ndsHeader = br.ReadType <NDSHeader>(); } else { _dsiHeader = br.ReadType <DSiHeader>(); } // Read ARM9 var arm9Offset = _ndsHeader?.arm9Offset ?? _dsiHeader.arm9Offset; var arm9Size = _ndsHeader?.arm9Size ?? _dsiHeader.arm9Size; result.Add(NdsSupport.CreateAfi(input, arm9Offset, arm9Size, "sys/arm9.bin")); // Read ARM9 Footer input.Position = arm9Offset + arm9Size; var nitroCode = br.ReadUInt32(); if (nitroCode == 0xDEC00621) { input.Position -= 4; _arm9Footer = br.ReadType <Arm9Footer>(); } // Read ARM9 Overlays var arm9OvlOffset = _ndsHeader?.arm9OverlayOffset ?? _dsiHeader.arm9OverlayOffset; var arm9OvlSize = _ndsHeader?.arm9OverlaySize ?? _dsiHeader.arm9OverlaySize; var arm9OvlEntryCount = arm9OvlSize / OverlayEntrySize; input.Position = arm9OvlOffset; IList <OverlayEntry> arm9OverlayEntries = Array.Empty <OverlayEntry>(); if (arm9OvlOffset != 0) { arm9OverlayEntries = br.ReadMultiple <OverlayEntry>(arm9OvlEntryCount); } // Read ARM7 var arm7Offset = _ndsHeader?.arm7Offset ?? _dsiHeader.arm7Offset; var arm7Size = _ndsHeader?.arm7Size ?? _dsiHeader.arm7Size; result.Add(NdsSupport.CreateAfi(input, arm7Offset, arm7Size, "sys/arm7.bin")); // Read ARM7 Overlays var arm7OvlOffset = _ndsHeader?.arm7OverlayOffset ?? _dsiHeader.arm7OverlayOffset; var arm7OvlSize = _ndsHeader?.arm7OverlaySize ?? _dsiHeader.arm7OverlaySize; var arm7OvlEntryCount = arm7OvlSize / OverlayEntrySize; input.Position = arm7OvlOffset; IList <OverlayEntry> arm7OverlayEntries = Array.Empty <OverlayEntry>(); if (arm7OvlOffset != 0) { arm7OverlayEntries = br.ReadMultiple <OverlayEntry>(arm7OvlEntryCount); } // Read FAT var fatOffset = _ndsHeader?.fatOffset ?? _dsiHeader.fatOffset; var fatSize = _ndsHeader?.fatSize ?? _dsiHeader.fatSize; var fatCount = fatSize / FatEntrySize; input.Position = fatOffset; var fileEntries = br.ReadMultiple <FatEntry>(fatCount); // Read FNT var fntOffset = _ndsHeader?.fntOffset ?? _dsiHeader.fntOffset; foreach (var file in NdsSupport.ReadFnt(br, fntOffset, 0, fileEntries)) { result.Add(file); } // Add banner var iconOffset = _ndsHeader?.iconOffset ?? _dsiHeader.iconOffset; var iconAfi = ReadIcon(br, iconOffset); if (iconAfi != null) { result.Add(iconAfi); } // Add overlay files foreach (var file in arm9OverlayEntries) { result.Add(NdsSupport.CreateAfi(input, fileEntries[file.fileId].offset, fileEntries[file.fileId].Length, Path.Combine("sys", "ovl", $"overlay9_{file.id:000}"), file)); } foreach (var file in arm7OverlayEntries) { result.Add(NdsSupport.CreateAfi(input, fileEntries[file.fileId].offset, fileEntries[file.fileId].Length, Path.Combine("sys", "ovl", $"overlay7_{file.id:000}"), file)); } return(result); }