private static IReadOnlyList <AssetFileEntry> FillAssetsFilesFromOldFormat(EndianBinaryReader reader, int offset) { var fileCount = reader.ReadInt32(); var assetFilesInMemory = new AssetFileEntry[fileCount]; for (var i = 0; i < fileCount; ++i) { var fileName = reader.ReadStringToNull(); var fileOffset = reader.ReadInt32(); fileOffset += offset; var fileSize = reader.ReadInt32(); var originalPosition = reader.Position; reader.Position = fileOffset; var buf = new byte[fileSize]; reader.Read(buf, 0, fileSize); reader.Position = originalPosition; var memory = new MemoryStream(buf, false); var memoryFile = new AssetFileEntry(memory, fileName, false); assetFilesInMemory[i] = memoryFile; } return(assetFilesInMemory); }
private static IReadOnlyList <AssetFileEntry> ReadFormat6(EndianBinaryReader reader, bool padding) { var bundleSize = reader.ReadInt64(); var compressedSize = reader.ReadInt32(); var uncompressedSize = reader.ReadInt32(); var flag = reader.ReadInt32(); if (padding) { reader.ReadByte(); } byte[] blocksInfoBytes; if ((flag & 0x80) == 0) { blocksInfoBytes = reader.ReadBytes(compressedSize); } else { var originalPosition = reader.Position; reader.Position = reader.BaseStream.Length - compressedSize; blocksInfoBytes = reader.ReadBytes(compressedSize); reader.Position = originalPosition; } Stream extraStream; byte[] rawBytes; switch (flag & 0x3f) { case 0: extraStream = new MemoryStream(blocksInfoBytes, false); break; case 1: rawBytes = SevenZip.Compression.LZMA.SevenZipHelper.Decompress(blocksInfoBytes); extraStream = new MemoryStream(rawBytes, false); break; case 2: case 3: rawBytes = new byte[uncompressedSize]; var resultSize = LZ4Codec.Decode(blocksInfoBytes, 0, blocksInfoBytes.Length, rawBytes, 0, uncompressedSize); extraStream = new MemoryStream(rawBytes, false); break; default: throw new ArgumentOutOfRangeException(nameof(flag), flag, null); } AssetFileEntry[] assetFilesInMemory; using (var blocksInfoReader = new EndianBinaryReader(extraStream, Endian.BigEndian)) { blocksInfoReader.Position = 0x10; var blockCount = blocksInfoReader.ReadInt32(); using (var assetsDataStream = new MemoryStream()) { for (var i = 0; i < blockCount; ++i) { uncompressedSize = blocksInfoReader.ReadInt32(); compressedSize = blocksInfoReader.ReadInt32(); flag = blocksInfoReader.ReadInt16(); var compressedBytes = reader.ReadBytes(compressedSize); byte[] uncompressedBytes; switch (flag & 0x3f) { case 0: assetsDataStream.Write(compressedBytes, 0, compressedSize); break; case 1: uncompressedBytes = SevenZip.Compression.LZMA.SevenZipHelper.Decompress(compressedBytes); assetsDataStream.Write(uncompressedBytes, 0, uncompressedSize); break; case 2: case 3: uncompressedBytes = new byte[uncompressedSize]; var resultSize = LZ4Codec.Decode(compressedBytes, 0, compressedBytes.Length, uncompressedBytes, 0, uncompressedSize); assetsDataStream.Write(uncompressedBytes, 0, uncompressedSize); break; default: throw new ArgumentOutOfRangeException(nameof(flag), flag, null); } } assetsDataStream.Position = 0; using (var assetsDataReader = new EndianBinaryReader(assetsDataStream, Endian.BigEndian)) { var entryCount = blocksInfoReader.ReadInt32(); var temporaryAssetFiles = new List <AssetFileEntry>(); for (var i = 0; i < entryCount; ++i) { var entryOffset = blocksInfoReader.ReadInt64(); var entrySize = blocksInfoReader.ReadInt64(); var flags = blocksInfoReader.ReadInt32(); // My guess is: flags=0 => "empty shell"; flags!=0(==4) => real file var fileName = blocksInfoReader.ReadStringToNull(); assetsDataReader.Position = entryOffset; var buf = new byte[entrySize]; assetsDataReader.Read(buf, 0, (int)entrySize); var memory = new MemoryStream(buf, false); var memoryFile = new AssetFileEntry(memory, fileName, false); if (flags != 0) { temporaryAssetFiles.Add(memoryFile); } } assetFilesInMemory = temporaryAssetFiles.ToArray(); } } } extraStream.Dispose(); return(assetFilesInMemory); }