public override long Write(AssetsFileWriter writer)
 {
     //memorystream for alignment issue
     using (MemoryStream ms = new MemoryStream())
         using (AssetsFileWriter w = new AssetsFileWriter(ms))
         {
             assetsFile.Write(w, -1, replacers, fileId, typeMeta);
             writer.Write(ms.ToArray());
         }
     return(writer.Position);
 }
示例#2
0
 //does NOT write the endianness byte for format < 9!
 public void Write(AssetsFileWriter writer)
 {
     writer.bigEndian = true;
     writer.Write(metadataSize);
     writer.Write(fileSize);
     writer.Write(format);
     writer.Write(firstFileOffset);
     writer.Write((byte)endianness);
     writer.bigEndian = endianness == 1 ? true : false;
     writer.Write(unknown);
 }
示例#3
0
 public void Write(AssetsFileWriter writer)
 {
     writer.Write(len);
     for (int i = 0; i < len; i++)
     {
         writer.Write(items[i].fileID);
         writer.Align();
         writer.Write(items[i].pathID);
         writer.Align();
     }
 }
示例#4
0
 public ulong Write(AssetsFileWriter writer, ulong filePos, int version)
 {
     writer.Write(classId);
     writer.Write(baseClass);
     name.Write(writer, filePos);
     writer.Write(fields.Count);
     for (int i = 0; i < fields.Count; i++)
     {
         fields[i].Write(writer, filePos, version);
     }
     return(writer.Position);
 }
        public override long WriteReplacer(AssetsFileWriter writer)
        {
            writer.Write((short)2); //replacer type
            writer.Write((byte)0);  //file type (0 bundle, 1 assets)
            writer.WriteCountStringInt16(oldName);
            writer.WriteCountStringInt16(newName);
            writer.Write(hasSerializedData);
            writer.Write(GetSize());
            Write(writer);

            return(writer.Position);
        }
 //does NOT write the endianness byte for format < 9!
 public ulong Write(ulong pos, AssetsFileWriter writer)
 {
     writer.bigEndian = true;
     writer.Write(metadataSize);
     writer.Write(fileSize);
     writer.Write(format);
     writer.Write(offs_firstFile);
     writer.Write((byte)endianness);
     writer.bigEndian = endianness == 1 ? true : false;
     writer.Write(unknown);
     return(writer.Position);
 }
示例#7
0
        public void Write(AssetsFileWriter writer)
        {
            writer.WriteNullTerminated(bufferedPath);
            guid.Write(writer);
            writer.Write(type);
            string assetPathTemp = assetPath;

            if (assetPathTemp.StartsWith("Resources\\") || assetPathTemp.StartsWith("Resources/"))
            {
                assetPathTemp = "library/" + assetPath.Substring(10);
            }
            writer.WriteNullTerminated(assetPathTemp);
        }
        public override long WriteReplacer(AssetsFileWriter writer)
        {
            writer.Write((short)0); //replacer type
            writer.Write((byte)1);  //file type (0 bundle, 1 assets)
            writer.Write((byte)1);  //idk, always 1
            writer.Write(0);        //always 0 even when fileid is something else
            writer.Write(pathID);
            writer.Write(classID);
            writer.Write(monoScriptIndex);
            writer.Write(0); //flags, which are ignored since this is a remover

            return(writer.Position);
        }
        public override long Write(AssetsFileWriter writer)
        {
            // Some parts of an assets file need to be aligned to a multiple of 4/8/16 bytes,
            // but for this to work correctly, the start of the file of course needs to be aligned too.
            // In a loose .assets file this is true by default, but inside a bundle file,
            // this might not be the case. Therefore wrap the bundle output stream in a SegmentStream
            // which will make it look like the start of the new assets file is at position 0
            SegmentStream    alignedStream = new SegmentStream(writer.BaseStream, writer.Position);
            AssetsFileWriter alignedWriter = new AssetsFileWriter(alignedStream);

            assetsFile.Write(alignedWriter, -1, assetReplacers);
            writer.Position = writer.BaseStream.Length;
            return(writer.Position);
        }
        public ulong Write(ulong absFilePos, AssetsFileWriter writer)
        {
            writer.Write(bufferedPath);
            guid.Write(writer.Position, writer);
            writer.Write(type);
            string assetPathTemp = assetPath;

            if (assetPathTemp.StartsWith("Resources\\"))
            {
                assetPathTemp = "library/" + assetPath.Substring(10);
            }
            writer.WriteNullTerminated(assetPathTemp);
            return(writer.Position);
        }
示例#11
0
 public void Write(AssetsFileWriter writer, uint format)
 {
     writer.Write(version);
     writer.Write(depth);
     writer.Write(isArray);
     writer.Write(typeStringOffset);
     writer.Write(nameStringOffset);
     writer.Write(size);
     writer.Write(index);
     writer.Write(flags);
     if (format >= 0x12)
     {
         writer.Write(unknown);
     }
 }
        public override long WriteReplacer(AssetsFileWriter writer)
        {
            writer.Write((short)4); //replacer type
            writer.Write((byte)0);  //file type (0 bundle, 1 assets)
            writer.WriteCountStringInt16(oldName);
            writer.WriteCountStringInt16(newName);
            writer.Write((byte)1); //probably hasSerializedData
            writer.Write((long)assetReplacers.Count);
            foreach (AssetsReplacer replacer in assetReplacers)
            {
                replacer.WriteReplacer(writer);
            }

            return(writer.Position);
        }
 public override long Write(AssetsFileWriter writer)
 {
     //todo, we have to write to ms because AssetsFile.Write
     //rewrites back at 0 which is the bundle header, not
     //the top of the assets file
     byte[] data;
     using (MemoryStream ms = new MemoryStream())
         using (AssetsFileWriter w = new AssetsFileWriter(ms))
         {
             assetsFile.Write(w, 0, replacers, fileId);
             data = ms.ToArray();
         }
     writer.Write(data);
     return(writer.Position);
 }
 public void Write(AssetsFileWriter writer, int version, byte flags)
 {
     writer.Write(classId);
     writer.Write(baseClass);
     name.Write(writer);
     if ((flags & 1) != 0)
     {
         assemblyFileName.Write(writer);
     }
     writer.Write(fields.Count);
     for (int i = 0; i < fields.Count; i++)
     {
         fields[i].Write(writer, version);
     }
 }
示例#15
0
 public ulong Write(ulong curFilePos, AssetsFileWriter writer, uint format)
 {
     writer.Write(version);
     writer.Write(depth);
     writer.Write(isArray);
     writer.Write(typeStringOffset);
     writer.Write(nameStringOffset);
     writer.Write(size);
     writer.Write(index);
     writer.Write(flags);
     if (format >= 0x12)
     {
         writer.Write(unknown);
     }
     return(writer.Position);
 }
        public void Write(AssetsFileWriter writer)
        {
            writer.WriteNullTerminated(bufferedPath);
            guid.Write(writer);
            writer.Write(type);
            string assetPathTemp = assetPath;

            if ((assetPath == "Resources/unity_builtin_extra" ||
                 assetPath == "Resources/unity default resources" ||
                 assetPath == "Resources/unity editor resources") &&
                originalAssetPath != string.Empty)
            {
                assetPathTemp = originalAssetPath;
            }
            writer.WriteNullTerminated(assetPathTemp);
        }
示例#17
0
        }//Minimum AssetsFile format : 6

        public void Write(AssetsFileWriter writer, uint version)
        {
            writer.WriteNullTerminated(unityVersion);
            writer.Write(this.version);
            writer.Write(hasTypeTree);
            fieldCount = unity5Types.Count;
            writer.Write(fieldCount);
            for (int i = 0; i < fieldCount; i++)
            {
                unity5Types[i].Write(hasTypeTree, writer, version);
            }
            if (version < 0x0E)
            {
                writer.WriteUInt24(dwUnknown);
            }
        }
示例#18
0
        public void Write(AssetsFileWriter writer)
        {
            header.Write(writer);
            writer.Write(classes.Count);
            for (int i = 0; i < classes.Count; i++)
            {
                classes[i].Write(writer, header.fileVersion, header.flags);
            }
            long stringTablePos = writer.Position;

            writer.Write(stringTable);
            long stringTableLen = writer.Position - stringTablePos;
            long fileSize       = writer.Position;

            header.stringTablePos   = (uint)stringTablePos;
            header.stringTableLen   = (uint)stringTableLen;
            header.uncompressedSize = (uint)fileSize;
            writer.Position         = 0;
            header.Write(writer);
        }
示例#19
0
 public void Write(bool hasTypeTree, AssetsFileWriter writer, uint version)
 {
     writer.Write(classId);
     if (version >= 0x10)
     {
         writer.Write(unknown16_1);
     }
     if (version >= 0x11)
     {
         writer.Write(scriptIndex);
     }
     if ((version < 0x11 && classId < 0) || (version >= 0x11 && classId == 0x72))
     {
         writer.Write(scriptHash1);
         writer.Write(scriptHash2);
         writer.Write(scriptHash3);
         writer.Write(scriptHash4);
     }
     writer.Write(typeHash1);
     writer.Write(typeHash2);
     writer.Write(typeHash3);
     writer.Write(typeHash4);
     if (hasTypeTree)
     {
         writer.Write(typeFieldsExCount);
         writer.Write(stringTable.Length);
         for (int i = 0; i < typeFieldsExCount; i++)
         {
             typeFieldsEx[i].Write(writer, version);
         }
         writer.Write(stringTable);
         if (version >= 0x15)
         {
             writer.Write(dependenciesCount);
             for (int i = 0; i < dependenciesCount; i++)
             {
                 writer.Write(dependencies[i]);
             }
         }
     }
 }
        public ulong Write(AssetsFileWriter writer, ulong filePos, int optimizeStringTable, uint compress, bool writeStringTable = true)
        {
            header.Write(writer, writer.Position);
            writer.Write(classes.Count);
            for (int i = 0; i < classes.Count; i++)
            {
                classes[i].Write(writer, filePos, header.fileVersion);
            }
            ulong stringTablePos = writer.Position;

            writer.Write(stringTable);
            ulong stringTableLen = writer.Position - stringTablePos;
            ulong fileSize       = writer.Position;

            header.stringTablePos   = (uint)stringTablePos;
            header.stringTableLen   = (uint)stringTableLen;
            header.uncompressedSize = (uint)fileSize;
            writer.Position         = 0;
            header.Write(writer, writer.Position);
            return(0);
        }
        public override bool Init(AssetsFileReader entryReader, long entryPos, long entrySize, ClassDatabaseFile typeMeta = null)
        {
            if (assetsFile != null)
            {
                return(false);
            }

            this.typeMeta = typeMeta;

            entryReader.Position = entryPos;
            //memorystream for alignment issue
            MemoryStream     ms = new MemoryStream();
            AssetsFileReader r  = new AssetsFileReader(ms);
            AssetsFileWriter w  = new AssetsFileWriter(ms);

            {
                w.Write(entryReader.ReadBytes((int)entrySize));
                ms.Position = 0;
                assetsFile  = new AssetsFile(r);
            }
            return(true);
        }
        public void Write(AssetsFileWriter writer)
        {
            writer.bigEndian = false;
            writer.Write(Encoding.ASCII.GetBytes(header));
            writer.Write(fileVersion);
            if (fileVersion == 4)
            {
                writer.Write(flags);
            }
            switch (fileVersion)
            {
            case 1:
                writer.Write((byte)0);
                break;

            case 2:
                writer.Write(compressionType);
                break;

            case 3:
            case 4:
                writer.Write(compressionType);
                writer.Write(compressedSize);
                writer.Write(uncompressedSize);
                break;

            default:
                return;
            }
            writer.Write(unityVersionCount);
            for (int i = 0; i < unityVersionCount; i++)
            {
                writer.WriteCountString(unityVersions[i]);
            }
            writer.Write(stringTableLen);
            writer.Write(stringTablePos);
        }
        public void Write(AssetsFileWriter writer)
        {
            writer.bigEndian = false;
            writer.Write(Encoding.ASCII.GetBytes(header));
            writer.Write(fileVersion);
            if (fileVersion == 4)
            {
                writer.Write(flags);
            }
            switch (fileVersion)
            {
            case 1:
                break;

            case 3:
            case 4:
                if (compressionType != 0)
                {
                    throw new NotImplementedException("compressed cldb writing not supported");
                }
                writer.Write(compressionType);
                writer.Write(compressedSize);
                writer.Write(uncompressedSize);
                break;

            default:
                return;
            }
            writer.Write(unityVersionCount);
            for (int i = 0; i < unityVersionCount; i++)
            {
                writer.WriteCountString(unityVersions[i]);
            }
            writer.Write(stringTableLen);
            writer.Write(stringTablePos);
        }
示例#24
0
        public void Write(AssetsFileWriter writer)
        {
            writer.bigEndian = false;
            writer.Write(Encoding.ASCII.GetBytes(magic));
            writer.Write(fileVersion);
            writer.Write(compressionType);
            writer.Write(stringTableOffset);
            writer.Write(stringTableLenUncompressed);
            writer.Write(stringTableLenCompressed);
            if (fileVersion == 1)
            {
                writer.Write(fileBlockSize);
            }
            writer.Write(fileCount);
            for (int i = 0; i < fileCount; i++)
            {
                ClassDatabaseFileRef fileRef = files[i];
                writer.Write(fileRef.offset);
                writer.Write(fileRef.length);

                string fixedFileName = fileRef.name.PadRight(15, '\0').Substring(0, 15);
                writer.Write(Encoding.ASCII.GetBytes(fixedFileName));
            }
        }
示例#25
0
 public override long WriteReplacer(AssetsFileWriter writer)
 {
     throw new NotImplementedException("not implemented");
 }
示例#26
0
 public override long Write(AssetsFileWriter writer)
 {
     writer.Write(buffer);
     return(writer.Position);
 }
        public bool Write(AssetsFileWriter writer, List <BundleReplacer> replacers, ClassDatabaseFile typeMeta = null)
        {
            bundleHeader6.Write(writer);

            if (bundleHeader6.fileVersion >= 7)
            {
                writer.Align16();
            }

            AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06()
            {
                checksumLow  = 0,
                checksumHigh = 0
            };

            //I could map the assets to their blocks but I don't
            //have any more-than-1-block files to test on
            //this should work just fine as far as I know
            newBundleInf6.blockInf = new AssetBundleBlockInfo06[]
            {
                new AssetBundleBlockInfo06
                {
                    compressedSize   = 0,
                    decompressedSize = 0,
                    flags            = 0x40
                }
            };

            //assets that did not have their data modified but need
            //the original info to read from the original file
            var newToOriginalDirInfoLookup = new Dictionary <AssetBundleDirectoryInfo06, AssetBundleDirectoryInfo06>();
            List <AssetBundleDirectoryInfo06> originalDirInfos = new List <AssetBundleDirectoryInfo06>();
            List <AssetBundleDirectoryInfo06> dirInfos         = new List <AssetBundleDirectoryInfo06>();
            List <BundleReplacer>             currentReplacers = replacers.ToList();
            //this is kind of useless at the moment but leaving it here
            //because if the AssetsFile size can be precalculated in the
            //future, we can use this to skip rewriting sizes
            long currentOffset = 0;

            //write all original files, modify sizes if needed and skip those to be removed
            for (int i = 0; i < bundleInf6.directoryCount; i++)
            {
                AssetBundleDirectoryInfo06 info = bundleInf6.dirInf[i];
                originalDirInfos.Add(info);
                AssetBundleDirectoryInfo06 newInfo = new AssetBundleDirectoryInfo06()
                {
                    offset           = currentOffset,
                    decompressedSize = info.decompressedSize,
                    flags            = info.flags,
                    name             = info.name
                };
                BundleReplacer replacer = currentReplacers.FirstOrDefault(n => n.GetOriginalEntryName() == newInfo.name);
                if (replacer != null)
                {
                    currentReplacers.Remove(replacer);
                    if (replacer.GetReplacementType() == BundleReplacementType.AddOrModify)
                    {
                        newInfo = new AssetBundleDirectoryInfo06()
                        {
                            offset           = currentOffset,
                            decompressedSize = replacer.GetSize(),
                            flags            = info.flags,
                            name             = replacer.GetEntryName()
                        };
                    }
                    else if (replacer.GetReplacementType() == BundleReplacementType.Rename)
                    {
                        newInfo = new AssetBundleDirectoryInfo06()
                        {
                            offset           = currentOffset,
                            decompressedSize = info.decompressedSize,
                            flags            = info.flags,
                            name             = replacer.GetEntryName()
                        };
                        newToOriginalDirInfoLookup[newInfo] = info;
                    }
                    else if (replacer.GetReplacementType() == BundleReplacementType.Remove)
                    {
                        continue;
                    }
                }
                else
                {
                    newToOriginalDirInfoLookup[newInfo] = info;
                }

                if (newInfo.decompressedSize != -1)
                {
                    currentOffset += newInfo.decompressedSize;
                }

                dirInfos.Add(newInfo);
            }

            //write new files
            while (currentReplacers.Count > 0)
            {
                BundleReplacer replacer = currentReplacers[0];
                if (replacer.GetReplacementType() == BundleReplacementType.AddOrModify)
                {
                    AssetBundleDirectoryInfo06 info = new AssetBundleDirectoryInfo06()
                    {
                        offset           = currentOffset,
                        decompressedSize = replacer.GetSize(),
                        flags            = 0x04, //idk it just works (tm)
                        name             = replacer.GetEntryName()
                    };
                    currentOffset += info.decompressedSize;

                    dirInfos.Add(info);
                }
                currentReplacers.Remove(replacer);
            }

            //write the listings
            long bundleInfPos = writer.Position;

            newBundleInf6.dirInf = dirInfos.ToArray(); //this is only here to allocate enough space so it's fine if it's inaccurate
            newBundleInf6.Write(writer);

            long assetDataPos = writer.Position;

            //actually write the file data to the bundle now
            for (int i = 0; i < dirInfos.Count; i++)
            {
                AssetBundleDirectoryInfo06 info     = dirInfos[i];
                BundleReplacer             replacer = replacers.FirstOrDefault(n => n.GetEntryName() == info.name);
                if (replacer != null)
                {
                    if (replacer.GetReplacementType() == BundleReplacementType.AddOrModify)
                    {
                        long startPos = writer.Position;
                        long endPos   = replacer.Write(writer);
                        long size     = endPos - startPos;

                        dirInfos[i].decompressedSize = size;
                        dirInfos[i].offset           = startPos - assetDataPos;
                    }
                    else if (replacer.GetReplacementType() == BundleReplacementType.Remove)
                    {
                        continue;
                    }
                }
                else
                {
                    if (newToOriginalDirInfoLookup.TryGetValue(info, out AssetBundleDirectoryInfo06 originalInfo))
                    {
                        long startPos = writer.Position;

                        reader.Position = bundleHeader6.GetFileDataOffset() + originalInfo.offset;
                        reader.BaseStream.CopyToCompat(writer.BaseStream, originalInfo.decompressedSize);

                        dirInfos[i].offset = startPos - assetDataPos;
                    }
                }
            }

            //now that we know what the sizes are of the written files let's go back and fix them
            long finalSize = writer.Position;
            uint assetSize = (uint)(finalSize - assetDataPos);

            writer.Position = bundleInfPos;
            newBundleInf6.blockInf[0].decompressedSize = assetSize;
            newBundleInf6.blockInf[0].compressedSize   = assetSize;
            newBundleInf6.dirInf = dirInfos.ToArray();
            newBundleInf6.Write(writer);

            uint infoSize = (uint)(assetDataPos - bundleInfPos);

            writer.Position = 0;
            AssetBundleHeader06 newBundleHeader6 = new AssetBundleHeader06()
            {
                signature         = bundleHeader6.signature,
                fileVersion       = bundleHeader6.fileVersion,
                minPlayerVersion  = bundleHeader6.minPlayerVersion,
                fileEngineVersion = bundleHeader6.fileEngineVersion,
                totalFileSize     = finalSize,
                compressedSize    = infoSize,
                decompressedSize  = infoSize,
                flags             = bundleHeader6.flags & unchecked ((uint)~0x80) & unchecked ((uint)~0x3f) //unset info at end flag and compression value
            };

            newBundleHeader6.Write(writer);

            return(true);
        }
        public bool Pack(AssetsFileReader reader, AssetsFileWriter writer, AssetBundleCompressionType compType)
        {
            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             = 0x43
                };

                AssetBundleBlockAndDirectoryList06 newBlockAndDirList = new AssetBundleBlockAndDirectoryList06()
                {
                    checksumLow    = 0,
                    checksumHigh   = 0,
                    blockCount     = 0,
                    blockInf       = null,
                    directoryCount = bundleInf6.directoryCount,
                    dirInf         = bundleInf6.dirInf
                };

                List <AssetBundleBlockInfo06> newBlocks = new List <AssetBundleBlockInfo06>();

                reader.Position = bundleHeader6.GetFileDataOffset();
                int    fileDataLength = (int)(bundleHeader6.totalFileSize - reader.Position);
                byte[] fileData       = reader.ReadBytes(fileDataLength);

                //todo, we just write everything to memory and then write to file
                //we could calculate the blocks we need ahead of time and correctly
                //size the block listing before this so we can write directly to file
                byte[] compressedFileData;
                switch (compType)
                {
                case AssetBundleCompressionType.LZMA:
                {
                    compressedFileData = SevenZipHelper.Compress(fileData);
                    newBlocks.Add(new AssetBundleBlockInfo06()
                        {
                            compressedSize   = (uint)compressedFileData.Length,
                            decompressedSize = (uint)fileData.Length,
                            flags            = 0x41
                        });
                    break;
                }

                case AssetBundleCompressionType.LZ4:
                {
                    using (var memStreamCom = new MemoryStream())
                        using (var binaryWriter = new BinaryWriter(memStreamCom))
                        {
                            using (var memStreamUnc = new MemoryStream(fileData))
                                using (var binaryReader = new BinaryReader(memStreamUnc))
                                {
                                    //compress into 0x20000 blocks
                                    byte[] uncompressedBlock = binaryReader.ReadBytes(131072);
                                    while (uncompressedBlock.Length != 0)
                                    {
                                        byte[] compressedBlock = LZ4Codec.Encode32HC(uncompressedBlock, 0, uncompressedBlock.Length);

                                        if (compressedBlock.Length > uncompressedBlock.Length)
                                        {
                                            newBlocks.Add(new AssetBundleBlockInfo06()
                                                {
                                                    compressedSize   = (uint)uncompressedBlock.Length,
                                                    decompressedSize = (uint)uncompressedBlock.Length,
                                                    flags            = 0x0
                                                });
                                            binaryWriter.Write(uncompressedBlock);
                                        }
                                        else
                                        {
                                            newBlocks.Add(new AssetBundleBlockInfo06()
                                                {
                                                    compressedSize   = (uint)compressedBlock.Length,
                                                    decompressedSize = (uint)uncompressedBlock.Length,
                                                    flags            = 0x3
                                                });
                                            binaryWriter.Write(compressedBlock);
                                        }

                                        uncompressedBlock = binaryReader.ReadBytes(131072);
                                    }
                                }

                            compressedFileData = memStreamCom.ToArray();
                        }
                    break;
                }

                case AssetBundleCompressionType.NONE:
                {
                    compressedFileData = fileData;
                    newBlocks.Add(new AssetBundleBlockInfo06()
                        {
                            compressedSize   = (uint)fileData.Length,
                            decompressedSize = (uint)fileData.Length,
                            flags            = 0x00
                        });
                    break;
                }

                default:
                {
                    return(false);
                }
                }

                newBlockAndDirList.blockInf = newBlocks.ToArray();

                byte[] bundleInfoBytes;
                using (var memStream = new MemoryStream())
                {
                    var afw = new AssetsFileWriter(memStream);
                    newBlockAndDirList.Write(afw);
                    bundleInfoBytes = memStream.ToArray();
                }

                if (bundleInfoBytes == null || bundleInfoBytes.Length == 0)
                {
                    return(false);
                }

                //listing is usually lz4 even if the data blocks are lzma
                byte[] bundleInfoBytesCom = LZ4Codec.Encode32HC(bundleInfoBytes, 0, bundleInfoBytes.Length);

                byte[] bundleHeaderBytes = null;
                using (var memStream = new MemoryStream())
                {
                    var afw = new AssetsFileWriter(memStream);
                    newHeader.Write(afw);
                    bundleHeaderBytes = memStream.ToArray();
                }

                if (bundleHeaderBytes == null || bundleHeaderBytes.Length == 0)
                {
                    return(false);
                }

                uint totalFileSize = (uint)(bundleHeaderBytes.Length + bundleInfoBytesCom.Length + compressedFileData.Length);
                newHeader.totalFileSize    = totalFileSize;
                newHeader.decompressedSize = (uint)bundleInfoBytes.Length;
                newHeader.compressedSize   = (uint)bundleInfoBytesCom.Length;

                newHeader.Write(writer);
                if (newHeader.fileVersion >= 7)
                {
                    writer.Align16();
                }

                writer.Write(bundleInfoBytesCom);
                writer.Write(compressedFileData);

                return(true);
            }
            return(false);
        }
        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);
        }
示例#30
0
 public abstract long WriteReplacer(AssetsFileWriter writer);