/// <summary> /// Deserializes a BIN archive. /// </summary> /// <param name="source">BIN archive as BinaryFormat.</param> /// <returns>The NodeContainerFormat.</returns> public NodeContainerFormat Convert(BinaryFormat source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (source.Stream.Length < 0x10) { throw new FormatException("Not a valid BIN file."); } source.Stream.Seek(0); var reader = new DataReader(source.Stream) { Endianness = _params.Endianness, }; BinFileHeader header = reader.Read <BinFileHeader>(); if (header.MagicNumber != 0x00077DF9) { throw new FormatException($"Unrecognized file magic number: {header.MagicNumber:X8}"); } NodeContainerFormat result = new (); for (int i = 0; i < header.FileCount; i++) { string fileSubPath = string.Empty; string fileName = $"{i + 1:0000}"; if (_params.FileNames.Count > 0 && i < _params.FileNames.Count) { string[] path = _params.FileNames[i].Split('/'); fileSubPath = string.Join('/', path[0..^ 1]);
/// <summary> /// Serializes a BIN archive. /// </summary> /// <param name="source">Collection of files as NodeContainerFormat.</param> /// <returns>The BinaryFormat.</returns> public BinaryFormat Convert(NodeContainerFormat source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (source.Root.Children.Count == 0) { throw new FormatException("No files selected."); } _params.Stream ??= DataStreamFactory.FromMemory(); _params.Stream.Seek(0); var writer = new DataWriter(_params.Stream) { Endianness = _params.Endianness, }; if (_params.BlockSize == 0) { _params.BlockSize = 0x800; } BinFileHeader header = new BinFileHeader { MagicNumber = 0x00077DF9, BlockSize = _params.BlockSize, FileCount = source.Root.Children.Count, Padding = 0, }; writer.WriteOfType(header); int headerSize = 0x10 + (header.FileCount * 0x10); writer.Stream.SetLength(headerSize); for (int i = 0; i < source.Root.Children.Count; i++) { Node node = source.Root.Children[i]; writer.Stream.Seek(0, SeekOrigin.End); writer.WritePadding(0x00, header.BlockSize); long startBlock = writer.Stream.Position / header.BlockSize; writer.Stream.Seek(0x10 + (i * 0x10), SeekOrigin.Begin); writer.Write(startBlock); FileType type = node.Tags["Type"]; switch (type) { case FileType.Empty: writer.Write(0); // size writer.Write(0); // inflated size break; case FileType.Dummy: writer.Write(0x70); // size writer.Write(0x835F837E); // inflated size writer.Stream.Seek(0, SeekOrigin.End); writer.Write(_dummy); break; case FileType.Normal: writer.Write((int)node.Stream.Length); // size writer.Write(0); // inflated size writer.Stream.Seek(0, SeekOrigin.End); node.Stream.WriteTo(writer.Stream); break; case FileType.Compressed: writer.Write((int)node.Stream.Length); // size writer.Write((int)node.Tags["InflatedSize"]); // inflated size writer.Stream.Seek(0, SeekOrigin.End); node.Stream.WriteTo(writer.Stream); break; case FileType.CompressedAlternateEndian: var alternateEndianness = _params.Endianness == EndiannessMode.BigEndian ? EndiannessMode.LittleEndian : EndiannessMode.BigEndian; writer.Write((int)node.Stream.Length); // size writer.Endianness = alternateEndianness; writer.Write((int)node.Tags["InflatedSize"]); // inflated size writer.Endianness = _params.Endianness; writer.Stream.Seek(0, SeekOrigin.End); node.Stream.WriteTo(writer.Stream); break; default: throw new FormatException($"Unsupported file type: {type}"); } } return(new BinaryFormat(_params.Stream)); }