public bool Unpack(AssetsFileReader reader, AssetsFileWriter writer) { reader.Position = 0; if (Read(reader, true)) { reader.Position = bundleHeader6.GetBundleInfoOffset(); MemoryStream blocksInfoStream; AssetsFileReader memReader; int compressedSize = (int)bundleHeader6.compressedSize; switch (bundleHeader6.GetCompressionType()) { case 1: using (MemoryStream mstream = new MemoryStream(reader.ReadBytes(compressedSize))) { blocksInfoStream = SevenZipHelper.StreamDecompress(mstream); } break; case 2: case 3: byte[] uncompressedBytes = new byte[bundleHeader6.decompressedSize]; using (MemoryStream mstream = new MemoryStream(reader.ReadBytes(compressedSize))) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(uncompressedBytes, 0, (int)bundleHeader6.decompressedSize); decoder.Dispose(); } blocksInfoStream = new MemoryStream(uncompressedBytes); break; default: blocksInfoStream = null; break; } if (bundleHeader6.GetCompressionType() != 0) { using (memReader = new AssetsFileReader(blocksInfoStream)) { memReader.Position = 0; bundleInf6.Read(0, memReader); } } AssetBundleHeader06 newBundleHeader6 = new AssetBundleHeader06() { signature = bundleHeader6.signature, fileVersion = bundleHeader6.fileVersion, minPlayerVersion = bundleHeader6.minPlayerVersion, fileEngineVersion = bundleHeader6.fileEngineVersion, totalFileSize = 0, compressedSize = bundleHeader6.decompressedSize, decompressedSize = bundleHeader6.decompressedSize, flags = bundleHeader6.flags & 0x40 //set compression and block position to 0 }; long fileSize = newBundleHeader6.GetFileDataOffset(); for (int i = 0; i < bundleInf6.blockCount; i++) { fileSize += bundleInf6.blockInf[i].decompressedSize; } newBundleHeader6.totalFileSize = fileSize; AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06() { checksumLow = 0, //-todo, figure out how to make real checksums, uabe sets these to 0 too checksumHigh = 0, blockCount = bundleInf6.blockCount, directoryCount = bundleInf6.directoryCount }; newBundleInf6.blockInf = new AssetBundleBlockInfo06[newBundleInf6.blockCount]; for (int i = 0; i < newBundleInf6.blockCount; i++) { newBundleInf6.blockInf[i] = new AssetBundleBlockInfo06() { compressedSize = bundleInf6.blockInf[i].decompressedSize, decompressedSize = bundleInf6.blockInf[i].decompressedSize, flags = (ushort)(bundleInf6.blockInf[i].flags & 0xC0) //set compression to none }; } newBundleInf6.dirInf = new AssetBundleDirectoryInfo06[newBundleInf6.directoryCount]; for (int i = 0; i < newBundleInf6.directoryCount; i++) { newBundleInf6.dirInf[i] = new AssetBundleDirectoryInfo06() { offset = bundleInf6.dirInf[i].offset, decompressedSize = bundleInf6.dirInf[i].decompressedSize, flags = bundleInf6.dirInf[i].flags, name = bundleInf6.dirInf[i].name }; } newBundleHeader6.Write(writer); if (newBundleHeader6.fileVersion >= 7) { writer.Align16(); } newBundleInf6.Write(writer); reader.Position = bundleHeader6.GetFileDataOffset(); for (int i = 0; i < newBundleInf6.blockCount; i++) { AssetBundleBlockInfo06 info = bundleInf6.blockInf[i]; switch (info.GetCompressionType()) { case 0: reader.BaseStream.CopyToCompat(writer.BaseStream, info.compressedSize); break; case 1: SevenZipHelper.StreamDecompress(reader.BaseStream, writer.BaseStream, info.compressedSize, info.decompressedSize); break; case 2: case 3: using (MemoryStream tempMs = new MemoryStream()) { reader.BaseStream.CopyToCompat(tempMs, info.compressedSize); tempMs.Position = 0; using (Lz4DecoderStream decoder = new Lz4DecoderStream(tempMs)) { decoder.CopyToCompat(writer.BaseStream, info.decompressedSize); } } break; } } return(true); } return(false); }
public bool Pack(AssetsFileReader reader, AssetsFileWriter writer, AssetBundleCompressionType compType, bool blockDirAtEnd = true) { reader.Position = 0; writer.Position = 0; if (Read(reader, false)) { AssetBundleHeader06 newHeader = new AssetBundleHeader06() { signature = bundleHeader6.signature, fileVersion = bundleHeader6.fileVersion, minPlayerVersion = bundleHeader6.minPlayerVersion, fileEngineVersion = bundleHeader6.fileEngineVersion, totalFileSize = 0, compressedSize = 0, decompressedSize = 0, flags = (uint)(0x43 | (blockDirAtEnd ? 0x80 : 0x00)) }; AssetBundleBlockAndDirectoryList06 newBlockAndDirList = new AssetBundleBlockAndDirectoryList06() { checksumLow = 0, checksumHigh = 0, blockCount = 0, blockInf = null, directoryCount = bundleInf6.directoryCount, dirInf = bundleInf6.dirInf }; //write header now and overwrite it later long startPos = writer.Position; newHeader.Write(writer); if (newHeader.fileVersion >= 7) { writer.Align16(); } int headerSize = (int)(writer.Position - startPos); long totalCompressedSize = 0; List <AssetBundleBlockInfo06> newBlocks = new List <AssetBundleBlockInfo06>(); List <Stream> newStreams = new List <Stream>(); //used if blockDirAtEnd == false long fileDataOffset = bundleHeader6.GetFileDataOffset(); int fileDataLength = (int)(bundleHeader6.totalFileSize - fileDataOffset); SegmentStream bundleDataStream = new SegmentStream(reader.BaseStream, fileDataOffset, fileDataLength); switch (compType) { case AssetBundleCompressionType.LZMA: { Stream writeStream; if (blockDirAtEnd) { writeStream = writer.BaseStream; } else { writeStream = GetTempFileStream(); } long writeStreamStart = writeStream.Position; SevenZipHelper.Compress(bundleDataStream, writeStream); uint writeStreamLength = (uint)(writeStream.Position - writeStreamStart); AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06() { compressedSize = writeStreamLength, decompressedSize = (uint)fileDataLength, flags = 0x41 }; totalCompressedSize += blockInfo.compressedSize; newBlocks.Add(blockInfo); if (!blockDirAtEnd) { newStreams.Add(writeStream); } break; } case AssetBundleCompressionType.LZ4: { //compress into 0x20000 blocks BinaryReader bundleDataReader = new BinaryReader(bundleDataStream); byte[] uncompressedBlock = bundleDataReader.ReadBytes(0x20000); while (uncompressedBlock.Length != 0) { Stream writeStream; if (blockDirAtEnd) { writeStream = writer.BaseStream; } else { writeStream = GetTempFileStream(); } byte[] compressedBlock = LZ4Codec.Encode32HC(uncompressedBlock, 0, uncompressedBlock.Length); if (compressedBlock.Length > uncompressedBlock.Length) { writeStream.Write(uncompressedBlock, 0, uncompressedBlock.Length); AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06() { compressedSize = (uint)uncompressedBlock.Length, decompressedSize = (uint)uncompressedBlock.Length, flags = 0x0 }; totalCompressedSize += blockInfo.compressedSize; newBlocks.Add(blockInfo); } else { writeStream.Write(compressedBlock, 0, compressedBlock.Length); AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06() { compressedSize = (uint)compressedBlock.Length, decompressedSize = (uint)uncompressedBlock.Length, flags = 0x3 }; totalCompressedSize += blockInfo.compressedSize; newBlocks.Add(blockInfo); } if (!blockDirAtEnd) { newStreams.Add(writeStream); } uncompressedBlock = bundleDataReader.ReadBytes(0x20000); } break; } case AssetBundleCompressionType.NONE: { AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06() { compressedSize = (uint)fileDataLength, decompressedSize = (uint)fileDataLength, flags = 0x00 }; totalCompressedSize += blockInfo.compressedSize; newBlocks.Add(blockInfo); if (blockDirAtEnd) { bundleDataStream.CopyToCompat(writer.BaseStream); } else { newStreams.Add(bundleDataStream); } break; } } newBlockAndDirList.blockInf = newBlocks.ToArray(); byte[] bundleInfoBytes; using (MemoryStream memStream = new MemoryStream()) { AssetsFileWriter infoWriter = new AssetsFileWriter(memStream); newBlockAndDirList.Write(infoWriter); bundleInfoBytes = memStream.ToArray(); } //listing is usually lz4 even if the data blocks are lzma byte[] bundleInfoBytesCom = LZ4Codec.Encode32HC(bundleInfoBytes, 0, bundleInfoBytes.Length); long totalFileSize = headerSize + bundleInfoBytesCom.Length + totalCompressedSize; newHeader.totalFileSize = totalFileSize; newHeader.decompressedSize = (uint)bundleInfoBytes.Length; newHeader.compressedSize = (uint)bundleInfoBytesCom.Length; if (!blockDirAtEnd) { writer.Write(bundleInfoBytesCom); foreach (Stream newStream in newStreams) { newStream.Position = 0; newStream.CopyToCompat(writer.BaseStream); newStream.Close(); } } else { writer.Write(bundleInfoBytesCom); } writer.Position = 0; newHeader.Write(writer); if (newHeader.fileVersion >= 7) { writer.Align16(); } return(true); } return(false); }