///public bool Pack(AssetsFileReader reader, LPARAM lPar, AssetsFileWriter writer, LPARAM writerPar);
        public bool IsAssetsFile(AssetsFileReader reader, AssetBundleDirectoryInfo06 entry)
        {
            //todo - not fully implemented
            long offset = bundleHeader6.GetFileDataOffset() + entry.offset;

            if (entry.decompressedSize < 0x20)
            {
                return(false);
            }

            reader.Position = offset;
            string possibleBundleHeader = reader.ReadStringLength(7);

            if (possibleBundleHeader == "UnityFS")
            {
                return(false);
            }

            reader.Position = offset + 0x08;
            int possibleFormat = reader.ReadInt32();

            if (possibleFormat > 99)
            {
                return(false);
            }

            reader.Position = offset + 0x14;
            string possibleVersion = reader.ReadNullTerminated();
            string emptyVersion    = Regex.Replace(possibleVersion, "[a-zA-Z0-9\\.]", "");
            string fullVersion     = Regex.Replace(possibleVersion, "[^a-zA-Z0-9\\.]", "");

            return(emptyVersion == "" && fullVersion.Length > 0);
        }
        public bool IsAssetsFile(AssetsFileReader reader, AssetBundleDirectoryInfo06 entry)
        {
            //todo - not fully implemented
            long offset = bundleHeader6.GetFileDataOffset() + entry.offset;

            if (entry.decompressedSize < 0x30)
            {
                return(false);
            }

            reader.Position = offset;
            string possibleBundleHeader = reader.ReadStringLength(7);

            if (possibleBundleHeader == "UnityFS")
            {
                return(false);
            }

            reader.Position = offset + 0x08;
            int possibleFormat = reader.ReadInt32();

            if (possibleFormat > 99)
            {
                return(false);
            }

            reader.Position = offset + 0x14;

            if (possibleFormat >= 0x16)
            {
                reader.Position += 0x1c;
            }

            string possibleVersion = "";
            char   curChar;

            while (reader.Position < reader.BaseStream.Length && (curChar = (char)reader.ReadByte()) != 0x00)
            {
                possibleVersion += curChar;
                if (possibleVersion.Length > 0xFF)
                {
                    return(false);
                }
            }

            string emptyVersion = Regex.Replace(possibleVersion, "[a-zA-Z0-9\\.]", "");
            string fullVersion  = Regex.Replace(possibleVersion, "[^a-zA-Z0-9\\.]", "");

            return(emptyVersion == "" && fullVersion.Length > 0);
        }
 internal void GetFileRange(int index, out long offset, out long length)
 {
     if (bundleHeader3 != null)
     {
         AssetsBundleEntry entry = assetsLists3.entries[index];
         offset = bundleHeader3.bundleDataOffs + entry.offset;
         length = entry.length;
     }
     else if (bundleHeader6 != null)
     {
         AssetBundleDirectoryInfo06 entry = bundleInf6.dirInf[index];
         offset = bundleHeader6.GetFileDataOffset() + entry.offset;
         length = entry.decompressedSize;
     }
     else
     {
         throw new NotSupportedException();
     }
 }
        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 IsAssetsFile(AssetsFileReader reader, AssetBundleDirectoryInfo06 entry)
        {
            long offset = bundleHeader6.GetFileDataOffset() + entry.offset;

            return(AssetsFile.IsAssetsFile(reader, offset, entry.decompressedSize));
        }