コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }