private void ReadScheme() { using (PartialStream stream = new PartialStream(m_stream, m_offset, m_size)) { using (EndianReader reader = new EndianReader(stream, EndianType.BigEndian)) { Header.Read(reader); } using (BundleFileReader reader = new BundleFileReader(stream, EndianType.BigEndian, Header.Generation)) { if (reader.Generation < BundleGeneration.BF_530_x) { using (SmartStream dataStream = ReadPre530Metadata(reader)) { ReadPre530Blocks(dataStream); } } else { using (SmartStream dataStream = Read530Metadata(reader)) { Read530Blocks(dataStream); } } } } }
private SmartStream ReadPre530Metadata(BundleFileReader reader) { switch (Header.Type) { case BundleType.UnityRaw: { Metadata.Read(reader); return(m_stream.CreateReference()); } case BundleType.UnityWeb: { // read only last chunk. wtf? ChunkInfo chunkInfo = Header.ChunkInfos[Header.ChunkInfos.Count - 1]; using (SmartStream stream = SmartStream.CreateMemory(new byte[chunkInfo.DecompressedSize])) { SevenZipHelper.DecompressLZMASizeStream(reader.BaseStream, chunkInfo.CompressedSize, stream); using (BundleFileReader decompressReader = new BundleFileReader(stream, reader.EndianType, reader.Generation)) { Metadata.Read(decompressReader); } return(stream.CreateReference()); } } default: throw new NotSupportedException($"Bundle type {Header.Type} isn't supported before 530 generation"); } }
public void Read(BundleFileReader reader) { if (IsReadBlockInfo(reader.Generation)) { // unknown 0x10 reader.BaseStream.Position += 0x10; BlockInfos = reader.ReadBundleArray <BlockInfo>(); } int count = reader.ReadInt32(); Dictionary <string, BundleFileEntry> entries = new Dictionary <string, BundleFileEntry>(count); for (int i = 0; i < count; i++) { BundleFileEntry entry = reader.ReadBundle <BundleFileEntry>(); entries.Add(entry.Name, entry); } Entries = entries; }
private SmartStream Read530Metadata(BundleFileReader reader) { if (Header.Flags.IsMetadataAtTheEnd()) { reader.BaseStream.Position = Header.BundleSize - Header.MetadataCompressedSize; } BundleCompressType metaCompression = Header.Flags.GetCompression(); switch (metaCompression) { case BundleCompressType.None: { Metadata.Read(reader); long expectedPosition = Header.Flags.IsMetadataAtTheEnd() ? Header.BundleSize : Header.HeaderSize + Header.MetadataDecompressedSize; if (reader.BaseStream.Position != expectedPosition) { throw new Exception($"Read {reader.BaseStream.Position - Header.HeaderSize} but expected {Header.MetadataDecompressedSize}"); } } break; case BundleCompressType.LZMA: { using (MemoryStream stream = new MemoryStream(new byte[Header.MetadataDecompressedSize])) { SevenZipHelper.DecompressLZMASizeStream(reader.BaseStream, Header.MetadataCompressedSize, stream); using (BundleFileReader decompressReader = new BundleFileReader(stream, reader.EndianType, reader.Generation)) { Metadata.Read(decompressReader); } if (stream.Position != Header.MetadataDecompressedSize) { throw new Exception($"Read {stream.Position} but expected {Header.MetadataDecompressedSize}"); } } } break; case BundleCompressType.LZ4: case BundleCompressType.LZ4HZ: { using (MemoryStream stream = new MemoryStream(new byte[Header.MetadataDecompressedSize])) { using (Lz4DecodeStream decodeStream = new Lz4DecodeStream(reader.BaseStream, Header.MetadataCompressedSize)) { long read = decodeStream.Read(stream, Header.MetadataDecompressedSize); if (read != Header.MetadataDecompressedSize || decodeStream.IsDataLeft) { throw new Exception($"Read {read} but expected {Header.MetadataDecompressedSize}"); } } stream.Position = 0; using (BundleFileReader decompressReader = new BundleFileReader(stream, reader.EndianType, reader.Generation)) { Metadata.Read(decompressReader); } if (stream.Position != Header.MetadataDecompressedSize) { throw new Exception($"Read {stream.Position} but expected {Header.MetadataDecompressedSize}"); } } } break; default: throw new NotSupportedException($"Bundle compression '{metaCompression}' isn't supported"); } return(m_stream.CreateReference()); }