Exemplo n.º 1
0
        public void AddReplacer(AssetsFileInstance forFile, AssetsReplacer replacer, Stream?previewStream = null)
        {
            AssetID assetId = new AssetID(forFile.name, replacer.GetPathID());

            NewAssets[assetId] = replacer;
            if (previewStream == null)
            {
                MemoryStream     newStream = new MemoryStream();
                AssetsFileWriter newWriter = new AssetsFileWriter(newStream);
                replacer.Write(newWriter);
                newStream.Position     = 0;
                NewAssetDatas[assetId] = newStream;
            }
            else
            {
                NewAssetDatas[assetId] = previewStream;
            }

            if (ItemUpdated != null)
            {
                ItemUpdated(assetId);
            }

            Modified = true;
        }
Exemplo n.º 2
0
        public void RemoveReplacer(AssetsFileInstance forFile, AssetsReplacer replacer, bool closePreviewStream = true)
        {
            AssetID assetId = new AssetID(forFile.name, replacer.GetPathID());

            if (NewAssets.ContainsKey(assetId))
            {
                NewAssets.Remove(assetId);
            }
            if (NewAssetDatas.ContainsKey(assetId))
            {
                if (closePreviewStream)
                {
                    NewAssetDatas[assetId].Close();
                }
                NewAssetDatas.Remove(assetId);
            }

            if (ItemUpdated != null)
            {
                ItemUpdated(assetId);
            }

            if (NewAssets.Count == 0)
            {
                Modified = false;
            }
        }
Exemplo n.º 3
0
        private async void BtnImportRaw_Click(object?sender, Avalonia.Interactivity.RoutedEventArgs e)
        {
            if (await FailIfNothingSelected())
            {
                return;
            }

            OpenFileDialog ofd = new OpenFileDialog();

            ofd.Title   = "Open";
            ofd.Filters = new List <FileDialogFilter>()
            {
                new FileDialogFilter()
                {
                    Name = "Raw Unity Asset", Extensions = new List <string>()
                    {
                        "dat"
                    }
                }
            };

            string[] fileList = await ofd.ShowAsync(this);

            if (fileList.Length == 0)
            {
                return;
            }

            string file = fileList[0];

            if (file != null && file != string.Empty)
            {
                using (FileStream fs = File.OpenRead(file))
                {
                    AssetFileInfoEx selectedInfo = GetSelectedInfo();
                    long            selectedId   = selectedInfo.index;

                    AssetImportExport importer = new AssetImportExport();
                    byte[]            bytes    = importer.ImportRawAsset(fs);
                    AssetsReplacer    replacer = AssetImportExport.CreateAssetReplacer(assetsFile.file, selectedInfo, bytes);
                    newAssets[selectedId]     = replacer;
                    newAssetDatas[selectedId] = new MemoryStream(bytes);

                    SetSelectedFieldModified();
                    modified = true;
                }
            }
        }
Exemplo n.º 4
0
        public void AddReplacer(AssetsReplacer replacer, MemoryStream previewStream = null)
        {
            if (replacer == null)
            {
                return;
            }
            var forInstance = LoadedFiles[replacer.GetFileID()];
            var assetId     = new AssetID(forInstance.path, replacer.GetPathID());
            var index       = LoadedAssets.FindIndex(i => i.FileID == replacer.GetFileID() && i.PathID == replacer.GetPathID());
            var item        = LoadedAssets[index];

            if (NewAssets.ContainsKey(assetId))
            {
                RemoveReplacer(replacer);
            }

            NewAssets[assetId] = replacer;

            if (previewStream == null)
            {
                var newStream = new MemoryStream();
                var newWriter = new AssetsFileWriter(newStream);
                replacer.Write(newWriter);
                newStream.Position = 0;
                previewStream      = newStream;
            }

            NewAssetDatas[assetId] = previewStream;

            if (replacer is AssetsRemover)
            {
                LoadedContainers.Remove(assetId);
            }
            else
            {
                var cont = MakeAssetContainer(item, NewAssetDatas[assetId]);
                UpdateAssetInfo(cont, assetId, index);
            }

            Modified = true;
        }
Exemplo n.º 5
0
        public void RemoveReplacer(AssetsReplacer replacer, bool closePreviewStream = true)
        {
            if (replacer == null)
            {
                return;
            }
            var forInstance = LoadedFiles[replacer.GetFileID()];
            var assetId     = new AssetID(forInstance.path, replacer.GetPathID());

            NewAssets.Remove(assetId);
            if (NewAssetDatas.ContainsKey(assetId))
            {
                if (closePreviewStream)
                {
                    NewAssetDatas[assetId].Close();
                }
                NewAssetDatas.Remove(assetId);
            }

            Modified = NewAssets.Count != 0;
        }
Exemplo n.º 6
0
        public void AddReplacer(AssetsFileInstance forFile, AssetsReplacer replacer, Stream? previewStream = null)
        {
            AssetsFile assetsFile = forFile.file;
            AssetID assetId = new AssetID(forFile.path, replacer.GetPathID());

            if (NewAssets.ContainsKey(assetId))
                RemoveReplacer(forFile, NewAssets[assetId], true);

            NewAssets[assetId] = replacer;

            //make stream to use as a replacement to the one from file
            if (previewStream == null)
            {
                MemoryStream newStream = new MemoryStream();
                AssetsFileWriter newWriter = new AssetsFileWriter(newStream);
                replacer.Write(newWriter);
                newStream.Position = 0;
                previewStream = newStream;
            }
            NewAssetDatas[assetId] = previewStream;

            if (!(replacer is AssetsRemover))
            {
                AssetsFileReader reader = new AssetsFileReader(previewStream);
                AssetContainer cont = new AssetContainer(
                    reader, 0, replacer.GetPathID(), (uint)replacer.GetClassID(),
                    replacer.GetMonoScriptID(), (uint)previewStream.Length, forFile);

                LoadedAssets[assetId] = cont;
            }
            else
            {
                LoadedAssets.Remove(assetId);
            }

            if (ItemUpdated != null)
                ItemUpdated(forFile, assetId);

            Modified = true;
        }
Exemplo n.º 7
0
        private async void BtnImportDump_Click(object?sender, Avalonia.Interactivity.RoutedEventArgs e)
        {
            if (await FailIfNothingSelected())
            {
                return;
            }

            OpenFileDialog ofd = new OpenFileDialog();

            ofd.Title   = "Open";
            ofd.Filters = new List <FileDialogFilter>()
            {
                new FileDialogFilter()
                {
                    Name = "UABE text dump", Extensions = new List <string>()
                    {
                        "txt"
                    }
                },
                new FileDialogFilter()
                {
                    Name = "UABE json dump", Extensions = new List <string>()
                    {
                        "json"
                    }
                }
            };

            string[] fileList = await ofd.ShowAsync(this);

            if (fileList.Length == 0)
            {
                return;
            }

            string file = fileList[0];

            if (file != null && file != string.Empty)
            {
                if (file.EndsWith(".json"))
                {
                    await MessageBoxUtil.ShowDialog(this, "Not implemented", "There's no json dump support yet, sorry.");

                    return;
                }

                using (FileStream fs = File.OpenRead(file))
                    using (StreamReader sr = new StreamReader(fs))
                    {
                        AssetFileInfoEx selectedInfo = GetSelectedInfo();
                        long            selectedId   = selectedInfo.index;

                        AssetImportExport importer = new AssetImportExport();
                        byte[]? bytes = importer.ImportTextAsset(sr);

                        if (bytes == null)
                        {
                            await MessageBoxUtil.ShowDialog(this, "Parse error", "Something went wrong when reading the dump file.");

                            return;
                        }

                        AssetsReplacer replacer = AssetImportExport.CreateAssetReplacer(assetsFile.file, selectedInfo, bytes);
                        newAssets[selectedId]     = replacer;
                        newAssetDatas[selectedId] = new MemoryStream(bytes);

                        SetSelectedFieldModified();
                        modified = true;
                    }
            }
        }
Exemplo n.º 8
0
        private static object ParseReplacer(AssetsFileReader reader, bool prefReplacersInMemory)
        {
            short replacerType = reader.ReadInt16();
            byte  fileType     = reader.ReadByte();

            if (fileType == 0) //BundleReplacer
            {
                string oldName                  = reader.ReadCountStringInt16();
                string newName                  = reader.ReadCountStringInt16();
                bool   hasSerializedData        = reader.ReadByte() != 0; //guess
                long   replacerCount            = reader.ReadInt64();
                List <AssetsReplacer> replacers = new List <AssetsReplacer>();
                for (int i = 0; i < replacerCount; i++)
                {
                    AssetsReplacer assetReplacer = (AssetsReplacer)ParseReplacer(reader, prefReplacersInMemory);
                    replacers.Add(assetReplacer);
                }

                if (replacerType == 4) //BundleReplacerFromAssets
                {
                    //we have to null the assetsfile here and call init later
                    BundleReplacer replacer = new BundleReplacerFromAssets(oldName, newName, null, replacers, 0);
                    return(replacer);
                }
            }
            else if (fileType == 1)                         //AssetsReplacer
            {
                byte   unknown01       = reader.ReadByte(); //always 1
                int    fileId          = reader.ReadInt32();
                long   pathId          = reader.ReadInt64();
                int    classId         = reader.ReadInt32();
                ushort monoScriptIndex = reader.ReadUInt16();

                List <AssetPPtr> preloadDependencies = new List <AssetPPtr>();
                int preloadDependencyCount           = reader.ReadInt32();
                for (int i = 0; i < preloadDependencyCount; i++)
                {
                    AssetPPtr pptr = new AssetPPtr(reader.ReadInt32(), reader.ReadInt64());
                    preloadDependencies.Add(pptr);
                }

                if (replacerType == 0) //remover
                {
                    AssetsReplacer replacer = new AssetsRemover(fileId, pathId, classId, monoScriptIndex);
                    if (preloadDependencyCount != 0)
                    {
                        replacer.SetPreloadDependencies(preloadDependencies);
                    }

                    return(replacer);
                }
                else if (replacerType == 2) //adder/replacer?
                {
                    Hash128?          propertiesHash = null;
                    Hash128?          scriptHash     = null;
                    ClassDatabaseFile?classData      = null;
                    AssetsReplacer    replacer;

                    bool flag1 = reader.ReadByte() != 0; //no idea, couldn't get it to be 1
                    if (flag1)
                    {
                        throw new NotSupportedException("you just found a file with the mysterious flag1 set, send the file to nes");
                    }

                    bool flag2 = reader.ReadByte() != 0; //has properties hash
                    if (flag2)
                    {
                        propertiesHash = new Hash128(reader);
                    }

                    bool flag3 = reader.ReadByte() != 0; //has script hash
                    if (flag3)
                    {
                        scriptHash = new Hash128(reader);
                    }

                    bool flag4 = reader.ReadByte() != 0; //has cldb
                    if (flag4)
                    {
                        classData = new ClassDatabaseFile();
                        classData.Read(reader);
                    }

                    long bufLength = reader.ReadInt64();
                    if (prefReplacersInMemory)
                    {
                        byte[] buf = reader.ReadBytes((int)bufLength);
                        replacer = new AssetsReplacerFromMemory(fileId, pathId, classId, monoScriptIndex, buf);
                    }
                    else
                    {
                        replacer = new AssetsReplacerFromStream(fileId, pathId, classId, monoScriptIndex, reader.BaseStream, reader.Position, bufLength);
                    }

                    if (propertiesHash != null)
                    {
                        replacer.SetPropertiesHash(propertiesHash.Value);
                    }
                    if (scriptHash != null)
                    {
                        replacer.SetScriptIDHash(scriptHash.Value);
                    }
                    if (scriptHash != null)
                    {
                        replacer.SetTypeInfo(classData, null, false); //idk what the last two are supposed to do
                    }
                    if (preloadDependencyCount != 0)
                    {
                        replacer.SetPreloadDependencies(preloadDependencies);
                    }

                    return(replacer);
                }
            }
            return(null);
        }
Exemplo n.º 9
0
        //AssetsFile
        public static ulong WriteFix(this AssetsFile file, AssetsFileWriter writer, ulong filePos, AssetsReplacer[] pReplacers, uint fileID, ClassDatabaseFile typeMeta = null)
        {
            file.header.Write(writer.Position, writer);

            for (int i = 0; i < pReplacers.Length; i++)
            {
                AssetsReplacer replacer = pReplacers[i];
                if (!file.typeTree.pTypes_Unity5.Any(t => t.classId == replacer.GetClassID()))
                {
                    Type_0D type = new Type_0D()
                    {
                        classId           = replacer.GetClassID(),
                        unknown16_1       = 0,
                        scriptIndex       = 0xFFFF,
                        unknown5          = 0,
                        unknown6          = 0,
                        unknown7          = 0,
                        unknown8          = 0,
                        typeFieldsExCount = 0,
                        stringTableLen    = 0,
                        pStringTable      = ""
                    };
                    file.typeTree.pTypes_Unity5.Concat(new Type_0D[] { type });
                }
            }
            file.typeTree.Write(writer.Position, writer, file.header.format);

            int initialSize  = (int)(AssetFileInfo.GetSize(file.header.format) * file.AssetCount);
            int newSize      = (int)(AssetFileInfo.GetSize(file.header.format) * (file.AssetCount + pReplacers.Length));
            int appendedSize = newSize - initialSize;

            file.reader.Position = file.AssetTablePos;

            List <AssetFileInfo>  originalAssetInfos = new List <AssetFileInfo>();
            List <AssetFileInfo>  assetInfos         = new List <AssetFileInfo>();
            List <AssetsReplacer> currentReplacers   = pReplacers.ToList();
            uint currentOffset = 0;

            //-write all original assets, modify sizes if needed and skip those to be removed
            for (int i = 0; i < file.AssetCount; i++)
            {
                AssetFileInfo info = new AssetFileInfo();
                info.Read(file.header.format, file.reader.Position, file.reader, file.reader.bigEndian);
                originalAssetInfos.Add(info);
                AssetsReplacer replacer = currentReplacers.FirstOrDefault(n => n.GetPathID() == info.index);
                if (replacer != null)
                {
                    currentReplacers.Remove(replacer);
                    if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_AddOrModify)
                    {
                        int classIndex = Array.FindIndex(file.typeTree.pTypes_Unity5, t => t.classId == replacer.GetClassID());
                        info = new AssetFileInfo()
                        {
                            index               = replacer.GetPathID(),
                            offs_curFile        = currentOffset,
                            curFileSize         = (uint)replacer.GetSize(),
                            curFileTypeOrIndex  = (uint)classIndex,
                            inheritedUnityClass = (ushort)replacer.GetClassID(), //-what is this
                            scriptIndex         = replacer.GetMonoScriptID(),
                            unknown1            = 0
                        };
                    }
                    else if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_Remove)
                    {
                        continue;
                    }
                }
                currentOffset += info.curFileSize;
                uint pad = 8 - (currentOffset % 8);
                if (pad != 8)
                {
                    currentOffset += pad;
                }

                assetInfos.Add(info);
            }

            //-write new assets
            while (currentReplacers.Count > 0)
            {
                AssetsReplacer replacer = currentReplacers.First();
                if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_AddOrModify)
                {
                    int           classIndex = Array.FindIndex(file.typeTree.pTypes_Unity5, t => t.classId == replacer.GetClassID());
                    AssetFileInfo info       = new AssetFileInfo()
                    {
                        index               = replacer.GetPathID(),
                        offs_curFile        = currentOffset,
                        curFileSize         = (uint)replacer.GetSize(),
                        curFileTypeOrIndex  = (uint)classIndex,
                        inheritedUnityClass = (ushort)replacer.GetClassID(),
                        scriptIndex         = replacer.GetMonoScriptID(),
                        unknown1            = 0
                    };
                    currentOffset += info.curFileSize;
                    uint pad = 8 - (currentOffset % 8);
                    if (pad != 8)
                    {
                        currentOffset += pad;
                    }

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

            writer.Write(assetInfos.Count);
            writer.Align();
            for (int i = 0; i < assetInfos.Count; i++)
            {
                assetInfos[i].Write(file.header.format, writer.Position, writer);
            }

            file.preloadTable.Write(writer.Position, writer, file.header.format);

            file.dependencies.Write(writer.Position, writer, file.header.format);

            uint metadataSize = (uint)writer.Position - 0x13;

            //-for padding only. if all initial data before assetData is more than 0x1000, this is skipped
            while (writer.Position < 0x1000 /*header.offs_firstFile*/)
            {
                writer.Write((byte)0x00);
            }

            writer.Align16();

            uint offs_firstFile = (uint)writer.Position;

            for (int i = 0; i < assetInfos.Count; i++)
            {
                AssetFileInfo  info     = assetInfos[i];
                AssetsReplacer replacer = pReplacers.FirstOrDefault(n => n.GetPathID() == info.index);
                if (replacer != null)
                {
                    if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_AddOrModify)
                    {
                        replacer.Write(writer.Position, writer);
                        writer.Align8();
                    }
                    else if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_Remove)
                    {
                        continue;
                    }
                }
                else
                {
                    AssetFileInfo originalInfo = originalAssetInfos.FirstOrDefault(n => n.index == info.index);
                    if (originalInfo != null)
                    {
                        file.reader.Position = file.header.offs_firstFile + originalInfo.offs_curFile;
                        byte[] assetData = file.reader.ReadBytes((int)originalInfo.curFileSize);
                        writer.Write(assetData);
                        writer.Align8();
                    }
                }
            }

            file.header.offs_firstFile = offs_firstFile;

            ulong fileSizeMarker = writer.Position;

            file.reader.Position = file.header.offs_firstFile;

            writer.Position          = 0;
            file.header.metadataSize = metadataSize;
            file.header.fileSize     = (uint)fileSizeMarker;
            file.header.Write(writer.Position, writer);
            return(writer.Position);
        }
Exemplo n.º 10
0
        public static byte[] CreateBundleFromLevel(AssetsManager am, /*byte[] data,*/ AssetsFileInstance inst, string sceneName, DiffFile diffFile, string bunPath)
        {
            AssetsFile      file  = inst.file;
            AssetsFileTable table = inst.table;

            string folderName = Path.GetDirectoryName(inst.path);
            //string sceneName = Path.GetFileNameWithoutExtension(inst.path) + "_mod";

            List <AssetsReplacer> assetsSA = new List <AssetsReplacer>();

            List <AssetFileInfoEx> infos = table.pAssetFileInfo.ToList();

            //List<int> typeIds = new List<int>();
            //foreach (AssetFileInfoEx info in infos)
            //{
            //    int typeId = (int)info.curFileType;
            //    if (!typeIds.Contains(typeId) && typeId != 0x72)
            //        typeIds.Add(typeId);
            //}

            assetsSA.Add(PreloadData.CreatePreloadData(1));
            assetsSA.Add(BundleMeta.CreateBundleInformation(sceneName, 2));

            //todo: pull from original assets file, cldb is not always update to date
            List <Type_0D> types = new List <Type_0D>();
            //foreach (int typeId in typeIds)
            //{
            //    types.Add(C2T5.Cldb2TypeTree(am.classFile, typeId));
            //}

            List <Type_0D> typesSA = new List <Type_0D>
            {
                C2T5.Cldb2TypeTree(am.classFile, 0x96), //PreloadData
                C2T5.Cldb2TypeTree(am.classFile, 0x8E)  //AssetBundle
            };

            const string ver = "2017.4.10f1";

            List <AssetsReplacer> replacers = new List <AssetsReplacer>();

            //UnityEngine.Debug.Log("HKWE DM " + diffFile.magic);
            //UnityEngine.Debug.Log("HKWE GC " + diffFile.changes.Count + diffFile.adds.Count + diffFile.removes.Count);
            //AssetsReplacerFromMemory mem = MoveTest.RunMoveTest(table.getAssetInfo(2642), am.GetATI(file, table.getAssetInfo(2642)).GetBaseField(), 2642) as AssetsReplacerFromMemory;
            foreach (GameObjectChange goChange in diffFile.changes)
            {
                //UnityEngine.Debug.Log("HKWE GO " + goChange.pathId);
                foreach (ComponentChangeOrAdd compChange in goChange.changes)
                {
                    AssetFileInfoEx     goInfo      = table.getAssetInfo((ulong)goChange.pathId);
                    AssetTypeValueField goBaseField = am.GetATI(file, goInfo).GetBaseField();

                    AssetTypeValueField         compPptr = goBaseField.Get("m_Component").Get("Array")[(uint)compChange.componentIndex].Get("component");
                    AssetsManager.AssetExternal compExt  = am.GetExtAsset(inst, compPptr);

                    AssetFileInfoEx     compInfo      = compExt.info;
                    AssetTypeValueField compBaseField = compExt.instance.GetBaseField();

                    //UnityEngine.Debug.Log("HKWE LR " + compInfo.index);
                    AssetsReplacer imAlreadyReplacer = ComponentDiffReplacer.DiffComponent(compInfo, compBaseField, am.classFile, compChange, compInfo.index);
                    replacers.Add(imAlreadyReplacer);
                }
            }
            AssetsManager amBun = new AssetsManager();                                                                          //we create a new manager because the two filenames will probably conflict

            amBun.classFile = am.classFile;                                                                                     //we can just reuse the classfile which is kinda hacky
            AssetsFileInstance bunInst = amBun.LoadAssetsFile(new MemoryStream(GetBundleData(bunPath, 0)), "HKWEDiffs", false); //placeholder path since we have no deps

            //rearrange the pathids immediately after the
            //last one from the level to keep unity happy
            ulong levelLargestPathID = 0;

            foreach (AssetFileInfoEx inf in table.pAssetFileInfo)
            {
                if (inf.index > levelLargestPathID)
                {
                    levelLargestPathID = inf.index;
                }
            }
            ReferenceCrawler.ReorderIds(amBun, bunInst, levelLargestPathID + 1);

            byte[] bunSAInst = GetBundleData(bunPath, 1);
            //HashSet<ulong> addedDeps = new HashSet<ulong>();
            foreach (AssetFileInfoEx inf in bunInst.table.pAssetFileInfo)
            {
                replacers.Add(MakeReplacer(inf.index, am, bunInst, inst, inf, bunSAInst, types));
            }
            //foreach (GameObjectInfo inf in diffFile.infos)
            //{
            //    Debug.Log("7");
            //    ulong bunPathId = GetBundlePathId(amBun, bunInst, inf);
            //
            //    AssetFileInfoEx objInf = bunInst.table.getAssetInfo(bunPathId);
            //    replacers.Add(MakeReplacer(bunPathId, am, bunInst, inst, objInf, bunSAInst, types));
            //
            //    List<ulong> deps = ReferenceCrawler.CrawlPPtrs(amBun, bunInst, bunPathId);
            //    foreach (ulong dep in deps)
            //    {
            //        if (!addedDeps.Contains(dep))
            //        {
            //            addedDeps.Add(dep);
            //            AssetFileInfoEx depInf = bunInst.table.getAssetInfo(dep);
            //            //if (depInf.curFileType == 0x01 || depInf.curFileType == 0x04 || depInf.curFileType == 0xD4 || depInf.curFileType == 0x15 || depInf.curFileType == 0xD5)
            //            //{
            //            //    continue;
            //            //}
            //            replacers.Add(MakeReplacer(dep, am, bunInst, inst, depInf, bunSAInst, types));
            //        }
            //    }
            //    ////its possible to get a collision but very unlikely since unity already randomizes ids which are 8 bytes long
            //    ////there's nothing here to test if a collision would be created so just hope that you don't win the lottery
            //    //ulong bunPathId = GetBundlePathId(amBun, bunInst, inf);
            //    ////AssetFileInfoEx afInf = bunInst.table.getAssetInfo(bunPathId);
            //    ////replacers.Add(MakeReplacer(bunPathId, afInf, bunInst.stream));
            //    //List<ulong> deps = ReferenceCrawler.CrawlPPtrs(am, bunInst, bunPathId);
            //    ////if (info.curFileType == 0x01 || info.curFileType == 0x04 || info.curFileType == 0xD4)
            //    ////{
            //    ////    continue;
            //    ////}
            //    //foreach (ulong dep in deps)
            //    //{
            //    //    AssetFileInfoEx depInf = bunInst.table.getAssetInfo(dep);
            //    //    //MakeReplacer(dep, am, bunInst, inst, depInf, bunSAInst, types);
            //    //    AssetsReplacerFromMemory ar = MakeReplacer(dep, am, bunInst, inst, depInf, bunSAInst, types);
            //    //    //todo- I guess this was just for testing purposes to block out everything, remove this at some point
            //    //    if (depInf.curFileType == 0x01 || depInf.curFileType == 0x04 || depInf.curFileType == 0xD4 || depInf.curFileType == 0x15 || depInf.curFileType == 0xD5) //depInf.curFileType == 0x1C
            //    //    {
            //    //        continue;
            //    //    }
            //    //    replacers.Add(ar);
            //    //}
            //}

            byte[] data = null;
            using (MemoryStream ms = new MemoryStream())
                using (AssetsFileWriter writer = new AssetsFileWriter(ms))
                {
                    //file.typeTree.hasTypeTree = true; //so we don't have to calculate hashes
                    //foreach (Type_0D type in file.typeTree.pTypes_Unity5)
                    //{
                    //    if (!types.Any(t => t.classId == type.classId))
                    //    {
                    //        types.Insert(0, C2T5.Cldb2TypeTree(am.classFile, type.classId));
                    //    }
                    //}
                    file.typeTree.pTypes_Unity5 = file.typeTree.pTypes_Unity5.Concat(types.ToArray()).ToArray();
                    //file.typeTree.pTypes_Unity5 = types.ToArray();
                    file.typeTree.fieldCount = (uint)file.typeTree.pTypes_Unity5.Length;
                    //file.typeTree.fieldCount = (uint)types.Count;
                    file.Write(writer, 0, replacers.ToArray(), 0);
                    data = ms.ToArray();
                }
            //File.WriteAllBytes("_bundlefinal1.unity3d", data);

            byte[]     blankDataSA = BundleCreator.CreateBlankAssets(ver, typesSA);
            AssetsFile blankFileSA = new AssetsFile(new AssetsFileReader(new MemoryStream(blankDataSA)));

            byte[] dataSA = null;
            using (MemoryStream ms = new MemoryStream())
                using (AssetsFileWriter writer = new AssetsFileWriter(ms))
                {
                    blankFileSA.Write(writer, 0, assetsSA.ToArray(), 0);
                    dataSA = ms.ToArray();
                }

            using (MemoryStream ms = new MemoryStream())
                using (AssetsFileWriter writer = new AssetsFileWriter(ms))
                {
                    AssetsBundleFile bundle = BundleCreator.CreateBlankBundle(ver, data.Length, dataSA.Length, sceneName);
                    bundle.Write(writer);
                    writer.Write(dataSA);
                    writer.Write(data);
                    return(ms.ToArray());
                }
        }