コード例 #1
0
        //set fileID to -1 if all replacers are for this .assets file but don't have the fileID set to the same one
        //typeMeta is used to add the type information (hash and type fields) for format >= 0x10 if necessary
        public void Write(AssetsFileWriter writer, ulong filePos, List <AssetsReplacer> replacers, uint fileID, ClassDatabaseFile typeMeta = null)
        {
            header.Write(writer);

            for (int i = 0; i < replacers.Count; i++)
            {
                AssetsReplacer replacer = replacers[i];
                if (!typeTree.unity5Types.Any(t => t.classId == replacer.GetClassID()))
                {
                    Type_0D type = new Type_0D()
                    {
                        classId           = replacer.GetClassID(),
                        unknown16_1       = 0,
                        scriptIndex       = 0xFFFF,
                        typeHash1         = 0,
                        typeHash2         = 0,
                        typeHash3         = 0,
                        typeHash4         = 0,
                        typeFieldsExCount = 0,
                        stringTableLen    = 0,
                        stringTable       = ""
                    };
                    typeTree.unity5Types.Concat(new Type_0D[] { type });
                }
            }
            typeTree.Write(writer, header.format);

            int initialSize  = (int)(AssetFileInfo.GetSize(header.format) * AssetCount);
            int newSize      = (int)(AssetFileInfo.GetSize(header.format) * (AssetCount + replacers.Count));
            int appendedSize = newSize - initialSize;

            reader.Position = AssetTablePos;

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

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

                assetInfos.Add(newInfo);
            }

            //-write new assets
            while (currentReplacers.Count > 0)
            {
                AssetsReplacer replacer = currentReplacers.First();
                if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_AddOrModify)
                {
                    int classIndex;
                    if (replacer.GetMonoScriptID() == 0xFFFF)
                    {
                        classIndex = typeTree.unity5Types.FindIndex(t => t.classId == replacer.GetClassID());
                    }
                    else
                    {
                        classIndex = typeTree.unity5Types.FindIndex(t => t.classId == replacer.GetClassID() && t.scriptIndex == replacer.GetMonoScriptID());
                    }
                    AssetFileInfo info = new AssetFileInfo()
                    {
                        index               = replacer.GetPathID(),
                        curFileOffset       = currentOffset,
                        curFileSize         = (uint)replacer.GetSize(),
                        curFileTypeOrIndex  = 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(header.format, writer);
            }

            preloadTable.Write(writer);

            dependencies.Write(writer);

            //temporary fix for secondarytypecount and friends
            if (header.format >= 14)
            {
                writer.Write(0);       //secondaryTypeCount
                writer.Write((byte)0); //unknownString length
            }

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

            //-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 = replacers.FirstOrDefault(n => n.GetPathID() == info.index);
                if (replacer != null)
                {
                    if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_AddOrModify)
                    {
                        replacer.Write(writer);
                        if (i != assetInfos.Count - 1)
                        {
                            writer.Align8();
                        }
                    }
                    else if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_Remove)
                    {
                        continue;
                    }
                }
                else
                {
                    AssetFileInfo originalInfo = originalAssetInfos.FirstOrDefault(n => n.index == info.index);
                    if (originalInfo != null)
                    {
                        reader.Position = header.firstFileOffset + originalInfo.curFileOffset;
                        byte[] assetData = reader.ReadBytes((int)originalInfo.curFileSize);
                        writer.Write(assetData);
                        if (i != assetInfos.Count - 1)
                        {
                            writer.Align8();
                        }
                    }
                }
            }

            header.firstFileOffset = offs_firstFile;

            long fileSizeMarker = writer.Position;

            reader.Position = header.firstFileOffset;

            writer.Position     = 0;
            header.metadataSize = metadataSize;
            header.fileSize     = (uint)fileSizeMarker;
            header.Write(writer);
        }
コード例 #2
0
        //set fileID to -1 if all replacers are for this .assets file but don't have the fileID set to the same one
        //typeMeta is used to add the type information (hash and type fields) for format >= 0x10 if necessary
        public ulong Write(AssetsFileWriter writer, ulong filePos, AssetsReplacer[] pReplacers, uint fileID, ClassDatabaseFile typeMeta = null)
        {
            header.Write(writer.Position, writer);

            for (int i = 0; i < pReplacers.Length; i++)
            {
                AssetsReplacer replacer = pReplacers[i];
                if (!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      = ""
                    };
                    typeTree.pTypes_Unity5.Concat(new Type_0D[] { type });
                }
            }
            typeTree.Write(writer.Position, writer, header.format);

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

            reader.Position = 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 < AssetCount; i++)
            {
                AssetFileInfo info = new AssetFileInfo();
                info.Read(header.format, reader.Position, reader, reader.bigEndian);
                originalAssetInfos.Add(info);
                AssetsReplacer replacer = currentReplacers.FirstOrDefault(n => n.GetPathID() == info.index);
                if (replacer != null)
                {
                    if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_AddOrModify)
                    {
                        int classIndex = Array.FindIndex(typeTree.pTypes_Unity5, t => t.classId == replacer.GetClassID());
                        info = new AssetFileInfo()
                        {
                            index               = replacer.GetPathID(),
                            offs_curFile        = currentOffset,
                            curFileSize         = (uint)classIndex,
                            curFileTypeOrIndex  = (uint)replacer.GetClassID(),
                            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(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(header.format, writer.Position, writer);
            }

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

            dependencies.Write(writer.Position, writer, 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);
            }

            header.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)
                    {
                        reader.Position = header.offs_firstFile + originalInfo.offs_curFile;
                        byte[] assetData = reader.ReadBytes((int)originalInfo.curFileSize);
                        writer.Write(assetData);
                        writer.Align8();
                    }
                }
            }

            ulong fileSizeMarker = writer.Position;

            reader.Position = header.offs_firstFile;

            writer.Position     = 0;
            header.metadataSize = metadataSize;
            header.fileSize     = (uint)fileSizeMarker;
            header.Write(writer.Position, writer);
            return(writer.Position);
        }