public static (byte[] info, int infoLen, byte[] data) BuildFormat6(UnityAssetsBundlePayload bundlePayload)
        {
            if (bundlePayload.Files.Length != bundlePayload.Blocks.Length)
            {
                throw new Exception($"Expected equal count of blocks(get {bundlePayload.Blocks.Length}) and files(get {bundlePayload.Files.Length}).");
            }
            if (bundlePayload.ReadAtEnd)
            {
                throw new NotImplementedException("Not support bundles with ReadAtEnd flag");
            }

            //build compressed data (Payload.Blocks)
            int infoLen;

            byte[] compressedInfoBytes;
            //byte[] entriesInfosBytes;
            byte[] compressedDataBytes;
            //var blocksInfos = new UnityAssetsBundleReader.BlockInfo[bundlePayload.Files.Length];

            using (var compressedDataStream = new MemoryStream())
            {
                var blocksInfosStream = new MemoryStream();
                var blocksInfosWriter = new EndianBinaryWriter(blocksInfosStream);

                var entriesStream = new MemoryStream();
                var entriesWriter = new EndianBinaryWriter(entriesStream);

                blocksInfosWriter.Write(bundlePayload.UnknownBytes);
                blocksInfosWriter.Write(bundlePayload.Blocks.Length);
                entriesWriter.Write(bundlePayload.Files.Length);

                var entryOffset = (long)0;
                for (int i = 0; i < bundlePayload.Files.Length; i++)
                {
                    var file = bundlePayload.Files[i];

                    entriesWriter.Write(entryOffset);
                    entriesWriter.Write((long)file.DataBytes.Length);
                    entriesWriter.Write(file.Flags);
                    entriesWriter.Write(file.Name);
                    entryOffset += file.DataBytes.Length;

                    var compressedEntry = Compress(file.DataBytes, bundlePayload.Blocks[i].CompressionType);
                    compressedDataStream.Write(compressedEntry);

                    blocksInfosWriter.Write((uint)file.DataBytes.LongLength);
                    blocksInfosWriter.Write((uint)compressedEntry.LongLength);
                    blocksInfosWriter.Write(bundlePayload.Blocks[i].Flags);
                }

                blocksInfosStream.Write(entriesStream.ToArray());
                infoLen             = (int)blocksInfosStream.Length;
                compressedInfoBytes = Compress(blocksInfosStream.ToArray(), bundlePayload.PayloadCompressionType);
                //entriesInfosBytes = entriesStream.ToArray();
                compressedDataBytes = compressedDataStream.ToArray();
            }

            return(compressedInfoBytes, infoLen, compressedDataBytes);
        }
Esempio n. 2
0
        private static UnityAssetsBundlePayload ReadFormat6(EndianBinaryReader bundleReader, bool padding = false)
        {
            var payload                 = new UnityAssetsBundlePayload();
            var payloadBundleSize       = bundleReader.ReadInt64();
            var payloadCompressedSize   = bundleReader.ReadInt32();
            var payloadDecompressedSize = bundleReader.ReadInt32();

            payload.Flags = bundleReader.ReadInt32();

            //
            if (padding)
            {
                bundleReader.ReadByte();
            }

            byte[] compressedBlocksInfoBytes;
            if (payload.ReadAtEnd)//at end of file
            {
                var position = bundleReader.Position;
                bundleReader.Position     = bundleReader.BaseStream.Length - payloadCompressedSize;
                compressedBlocksInfoBytes = bundleReader.ReadBytes(payloadCompressedSize);
                bundleReader.Position     = position;
            }
            else
            {
                compressedBlocksInfoBytes = bundleReader.ReadBytes(payloadCompressedSize);
            }

            //info
            var blocksInfoStream = DecompressToMemoryStream(compressedBlocksInfoBytes, payload.PayloadCompressionType, payloadDecompressedSize);

            using var blocksInfoReader = new EndianBinaryReader(blocksInfoStream);
            payload.UnknownBytes       = blocksInfoReader.ReadBytes(16);
            var payloadBlocksCount = blocksInfoReader.ReadInt32();

            payload.Blocks = new UnityAssetsBundlePayloadBlock[payloadBlocksCount];
            var blockInfos = new BlockInfo[payloadBlocksCount];

            for (var i = 0; i < payloadBlocksCount; i++)
            {
                blockInfos[i] = new BlockInfo()
                {
                    DecompressedSize = blocksInfoReader.ReadUInt32(),
                    CompressedSize   = blocksInfoReader.ReadUInt32(),
                    Flags            = blocksInfoReader.ReadInt16()
                };
                payload.Blocks[i] = new UnityAssetsBundlePayloadBlock()
                {
                    Flags = blockInfos[i].Flags
                };
            }


            //create stream with decompressed blocks
            var dataStream = new MemoryStream();

            foreach (var blockInfo in blockInfos)
            {
                var compressedBytes       = bundleReader.ReadBytes((int)blockInfo.CompressedSize);
                var decompressedMemStream = DecompressToMemoryStream(
                    compressedBytes,
                    blockInfo.CompressionType,
                    (int)blockInfo.DecompressedSize);
                decompressedMemStream.Position = 0;
                decompressedMemStream.CopyTo(dataStream, blockInfo.DecompressedSize);
            }
            dataStream.Position = 0; //reset

            using (dataStream)
            {
                var entryInfoCount = blocksInfoReader.ReadInt32();
                payload.Files = new UnityAssetsBundleStreamFile[entryInfoCount];
                for (var i = 0; i < payload.Files.Length; i++)
                {
                    var offset = blocksInfoReader.ReadInt64();
                    var size   = blocksInfoReader.ReadInt64();
                    var file   = new UnityAssetsBundleStreamFile
                    {
                        Flags     = blocksInfoReader.ReadInt32(),
                        Name      = blocksInfoReader.ReadStringToNull(),
                        DataBytes = new byte[size]
                    };

                    dataStream.Position = offset;
                    dataStream.Read(file.DataBytes, 0, (int)size);

                    payload.Files[i] = file;
                }
            }

            return(payload);
        }