Esempio n. 1
0
 public MintScript(string name, byte[] version)
 {
     XData   = new XData(Endianness.Little, new byte[] { 2, 0 });
     Version = version;
     Name    = name;
     SData   = new List <byte>();
     XRef    = new List <byte[]>();
     Classes = new List <MintClass>();
 }
Esempio n. 2
0
        public MintScript(EndianBinaryReader reader, byte[] version)
        {
            XData   = new XData(reader);
            Version = version;

            uint nameOffs = reader.ReadUInt32();

            if (version[0] >= 7)
            {
                Hash = reader.ReadBytes(4);
            }
            else
            {
                Hash = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }
            };
            uint sdataOffs = reader.ReadUInt32();
            uint xrefOffs  = reader.ReadUInt32();
            uint classOffs = reader.ReadUInt32();

            reader.BaseStream.Seek(nameOffs, SeekOrigin.Begin);
            Name = Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadInt32()));

            reader.BaseStream.Seek(sdataOffs, SeekOrigin.Begin);
            SData = new List <byte>();
            SData.AddRange(reader.ReadBytes(reader.ReadInt32()));

            reader.BaseStream.Seek(xrefOffs, SeekOrigin.Begin);
            uint xrefCount = reader.ReadUInt32();

            XRef = new List <byte[]>();
            for (int i = 0; i < xrefCount; i++)
            {
                XRef.Add(reader.ReadBytes(4));
            }

            reader.BaseStream.Seek(classOffs, SeekOrigin.Begin);
            uint classCount = reader.ReadUInt32();

            Classes = new List <MintClass>();
            for (int i = 0; i < classCount; i++)
            {
                reader.BaseStream.Seek(classOffs + 4 + (i * 4), SeekOrigin.Begin);
                reader.BaseStream.Seek(reader.ReadUInt32(), SeekOrigin.Begin);
                Classes.Add(new MintClass(reader, this));
            }
        }
Esempio n. 3
0
        public void Read(EndianBinaryReader reader)
        {
            XData = new XData(reader);
            if (!XData.isValid())
            {
                return;
            }

            Version = reader.ReadBytes(4);
            int namespaceCount = reader.ReadInt32() - 1;

            reader.BaseStream.Seek(4, SeekOrigin.Current);
            int  scriptCount = reader.ReadInt32();
            uint scriptList  = reader.ReadUInt32();
            uint unk         = reader.ReadUInt32();

            reader.BaseStream.Seek(0x30, SeekOrigin.Begin);
            RootNamespaces = reader.ReadUInt32();

            Console.WriteLine($"Archive Header Data:" +
                              $"\n-XData-" +
                              $"\nMagic: {XData.Magic}" +
                              $"\nEndianness: {XData.Endianness}" +
                              $"\nFilesize: 0x{XData.Filesize:X8}" +
                              $"\n-Mint Archive-" +
                              $"\nVersion: {string.Join(".", Version)}" +
                              $"\nNamespaces: {namespaceCount}" +
                              $"\nRoot Namespaces: {RootNamespaces}" +
                              $"\nScripts: {scriptCount}" +
                              $"\nScript List Offset: 0x{scriptList:X8}" +
                              $"\nIndex Table Offset: 0x{0x34 + (namespaceCount * 0x14):X8}");

            Console.WriteLine("Reading Namespaces...");
            Namespaces = new List <Namespace>();
            for (int i = 0; i < namespaceCount; i++)
            {
                reader.BaseStream.Seek(0x34 + (i * 0x14), SeekOrigin.Begin);
                uint indexOffset   = reader.ReadUInt32();
                uint nameOffset    = reader.ReadUInt32();
                int  scrCount      = reader.ReadInt32();
                int  totalScripts  = reader.ReadInt32();
                int  childrenCount = reader.ReadInt32();

                reader.BaseStream.Seek(indexOffset, SeekOrigin.Begin);
                int index = reader.ReadInt32();
                reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
                string name = Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadInt32()));

                Namespaces.Add(new Namespace(index, name, scrCount, totalScripts, childrenCount));
            }

            Console.WriteLine("Reading index table...");
            IndexTable = new List <int>();
            reader.BaseStream.Seek(0x34 + (namespaceCount * 0x14), SeekOrigin.Begin);
            while (reader.BaseStream.Position < scriptList)
            {
                IndexTable.Add(reader.ReadInt32());
            }
            //Console.WriteLine(string.Join(",", IndexTable));

            Console.WriteLine("Reading scripts...");
            Scripts = new Dictionary <string, MintScript>();
            reader.BaseStream.Seek(scriptList, SeekOrigin.Begin);
            for (int i = 0; i < scriptCount; i++)
            {
                reader.BaseStream.Seek(scriptList + (i * 8), SeekOrigin.Begin);
                uint nameOffset   = reader.ReadUInt32();
                uint scriptOffset = reader.ReadUInt32();

                reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
                string name = Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadInt32()));

                reader.BaseStream.Seek(scriptOffset, SeekOrigin.Begin);
                XData scrX = new XData(reader);
                reader.BaseStream.Seek(scriptOffset, SeekOrigin.Begin);

                using (MemoryStream scr = new MemoryStream(reader.ReadBytes((int)scrX.Filesize)))
                    using (EndianBinaryReader scrReader = new EndianBinaryReader(scr))
                        Scripts.Add(name, new MintScript(new EndianBinaryReader(scr), Version));
            }

            reader.BaseStream.Seek(unk, SeekOrigin.Begin);
            //Console.WriteLine(reader.ReadUInt32());
        }
Esempio n. 4
0
        public void Write(EndianBinaryWriter writer)
        {
            XData.Write(writer);

            writer.Write(Version);
            writer.Write(Namespaces.Count + 1);
            writer.Write(0x24);
            writer.Write(Scripts.Count);

            uint scrListOffs = (uint)(0x34 + (Namespaces.Count * 0x14) + (IndexTable.Count * 4));

            writer.Write(scrListOffs);
            //Script data end bound offset, -1 for now until we get there
            writer.Write(-1);
            writer.Write(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });

            //Namespace information
            writer.Write(RootNamespaces);
            for (int i = 0; i < Namespaces.Count; i++)
            {
                //Console.WriteLine($"{Namespaces[i].Name} - Index {Namespaces[i].Index}, In table: {IndexTable.Contains(Namespaces[i].Index)}, Index: {IndexTable.IndexOf(Namespaces[i].Index)}");
                if (!IndexTable.Contains(Namespaces[i].Index))
                {
                    writer.Write(scrListOffs);
                }
                else
                {
                    writer.Write((uint)(0x34 + (Namespaces.Count * 0x14) + (IndexTable.IndexOf(Namespaces[i].Index) * 4)));
                }

                writer.Write(-1); //Come back to this later for string writing
                writer.Write(Namespaces[i].Scripts);
                writer.Write(Namespaces[i].TotalScripts);
                writer.Write(Namespaces[i].ChildNamespaces);
            }
            //writer.Write(scrListOffs);
            for (int i = 0; i < IndexTable.Count; i++)
            {
                writer.Write(IndexTable[i]);
            }

            writer.BaseStream.Seek(scrListOffs, SeekOrigin.Begin);
            for (int i = 0; i < Scripts.Count; i++)
            {
                writer.Write(-1); //Come back to this later for string writing
                writer.Write(-1);
            }
            for (int i = 0; i < Scripts.Count; i++)
            {
                writer.BaseStream.Seek(scrListOffs + (i * 8) + 4, SeekOrigin.Begin);
                writer.Write((uint)writer.BaseStream.Length);
                writer.BaseStream.Seek(0, SeekOrigin.End);
                writer.Write(Scripts.Values.ToArray()[i].Write());

                while ((writer.BaseStream.Length & 0xF) != 0x0 &&
                       (writer.BaseStream.Length & 0xF) != 0x4 &&
                       (writer.BaseStream.Length & 0xF) != 0x8 &&
                       (writer.BaseStream.Length & 0xF) != 0xC)
                {
                    writer.Write((byte)0);
                }
            }
            writer.BaseStream.Seek(0x24, SeekOrigin.Begin);
            writer.Write((uint)writer.BaseStream.Length);
            writer.BaseStream.Seek(0, SeekOrigin.End);
            writer.Write((long)0);

            while ((writer.BaseStream.Length & 0xF) != 0x0 &&
                   (writer.BaseStream.Length & 0xF) != 0x4 &&
                   (writer.BaseStream.Length & 0xF) != 0x8 &&
                   (writer.BaseStream.Length & 0xF) != 0xC)
            {
                writer.Write((byte)0);
            }

            for (int i = 0; i < Namespaces.Count; i++)
            {
                writer.BaseStream.Seek(0x34 + (i * 20) + 4, SeekOrigin.Begin);
                writer.Write((uint)writer.BaseStream.Length);
                writer.BaseStream.Seek(0, SeekOrigin.End);
                WriteUtil.WriteString(writer, Namespaces[i].Name);
            }
            for (int i = 0; i < Scripts.Count; i++)
            {
                writer.BaseStream.Seek(scrListOffs + (i * 8), SeekOrigin.Begin);
                writer.Write((uint)writer.BaseStream.Length);
                writer.BaseStream.Seek(0, SeekOrigin.End);
                WriteUtil.WriteString(writer, Scripts.Keys.ToArray()[i]);
            }

            XData.UpdateFilesize(writer);
        }
Esempio n. 5
0
        public MintScript(string[] text, byte[] version)
        {
            string scriptDeclare = text[0];

            if (!scriptDeclare.StartsWith("script "))
            {
                MessageBox.Show("Error: Invalid Mint Script file.", "Mint Workshop", MessageBoxButtons.OK);
                return;
            }

            XData   = new XData(Endianness.Little, new byte[] { 2, 0 });
            Version = version;
            Name    = scriptDeclare.Substring(7);
            SData   = new List <byte>();
            XRef    = new List <byte[]>();
            Classes = new List <MintClass>();

            Regex classRegex = new Regex("\\b(class)\\b");
            Regex varRegex   = new Regex("\\b(var)\\b");
            Regex funcRegex  = new Regex("(\\(.*\\))");

            for (int l = 0; l < text.Length; l++)
            {
                string line = text[l].TrimStart(trimChars);
                if (line.StartsWith("//"))
                {
                    continue;
                }
                if (classRegex.IsMatch(line))
                {
                    string[]  classDeclaration = line.Split(' ');
                    int       classWord        = classDeclaration.ToList().IndexOf("class");
                    MintClass newClass         = new MintClass(classDeclaration[classWord + 1], 0, this);
                    for (int i = 0; i < classWord; i++)
                    {
                        if (classDeclaration[i].StartsWith("flag"))
                        {
                            newClass.Flags |= uint.Parse(classDeclaration[i].Substring(4), NumberStyles.HexNumber);
                        }
                        else if (FlagLabels.ClassFlags.ContainsValue(classDeclaration[i]))
                        {
                            newClass.Flags |= FlagLabels.ClassFlags.Keys.ToArray()[FlagLabels.ClassFlags.Values.ToList().IndexOf(classDeclaration[i])];
                        }
                        else
                        {
                            throw new Exception($"Unknown Class flag name \"{classDeclaration[i]}\"");
                        }
                    }

                    for (int cl = l; cl < text.Length; cl++)
                    {
                        string classLine = text[cl].TrimStart(trimChars);
                        if (classLine.StartsWith("//"))
                        {
                            continue;
                        }
                        if (varRegex.IsMatch(classLine))
                        {
                            string[]     varDeclaration = classLine.Split(' ');
                            int          varWord        = varDeclaration.ToList().IndexOf("var");
                            MintVariable newVar         = new MintVariable(varDeclaration[varWord + 2], varDeclaration[varWord + 1], 0, newClass);
                            for (int i = 0; i < varWord; i++)
                            {
                                if (varDeclaration[i].StartsWith("flag"))
                                {
                                    newVar.Flags |= uint.Parse(varDeclaration[i].Substring(4), NumberStyles.HexNumber);
                                }
                                else if (FlagLabels.VariableFlags.ContainsValue(varDeclaration[i]))
                                {
                                    newVar.Flags |= FlagLabels.VariableFlags.Keys.ToArray()[FlagLabels.VariableFlags.Values.ToList().IndexOf(varDeclaration[i])];
                                }
                                else
                                {
                                    throw new Exception($"Unknown Variable flag name \"{varDeclaration[i]}\"");
                                }
                            }
                            newClass.Variables.Add(newVar);
                        }
                        else if (funcRegex.IsMatch(classLine))
                        {
                            string[] funcDeclaration = classLine.Split(' ');
                            string   name            = "";
                            uint     funcFlags       = 0;
                            for (int i = 0; i < funcDeclaration.Length; i++)
                            {
                                if (funcDeclaration[i].StartsWith("flag"))
                                {
                                    funcFlags |= uint.Parse(funcDeclaration[i].Substring(4), NumberStyles.HexNumber);
                                }
                                else if (FlagLabels.FunctionFlags.ContainsValue(funcDeclaration[i]))
                                {
                                    funcFlags |= FlagLabels.FunctionFlags.Keys.ToArray()[FlagLabels.FunctionFlags.Values.ToList().IndexOf(funcDeclaration[i])];
                                }
                                else
                                {
                                    name = string.Join(" ", funcDeclaration.Skip(i));
                                    break;
                                }
                            }

                            MintFunction  newFunc      = new MintFunction(name, funcFlags, newClass);
                            List <string> instructions = new List <string>();
                            for (int fl = cl + 2; fl < text.Length; fl++)
                            {
                                string funcLine = text[fl].TrimStart(trimChars);
                                if (funcLine.StartsWith("//"))
                                {
                                    continue;
                                }
                                if (funcLine.StartsWith("}"))
                                {
                                    cl = fl;
                                    break;
                                }
                                instructions.Add(funcLine);
                            }
                            newFunc.Assemble(instructions.ToArray());
                            newFunc.DetectArguments();
                            newFunc.DetectRegisters();

                            newClass.Functions.Add(newFunc);
                        }
                        else if (classLine.StartsWith("const "))
                        {
                            string[] constDeclaration = classLine.Split(' ');
                            uint     value;
                            if (constDeclaration[3].StartsWith("0x"))
                            {
                                value = uint.Parse(constDeclaration[3].Substring(2), NumberStyles.HexNumber);
                            }
                            else
                            {
                                value = uint.Parse(constDeclaration[3]);
                            }

                            newClass.Constants.Add(new MintClass.MintConstant(constDeclaration[1], value));
                        }
                        else if (classLine.StartsWith("unkvalue "))
                        {
                            string[] unkDeclaration = classLine.Split(' ');
                            newClass.UnknownList.Add(uint.Parse(unkDeclaration[1]));
                        }
                        else if (classLine.StartsWith("unk2value "))
                        {
                            string[] unkDeclaration = classLine.Split(' ');
                            newClass.Unknown2List.Add(uint.Parse(unkDeclaration[1]));
                        }
                        else if (classLine.StartsWith("}"))
                        {
                            l = cl;
                            break;
                        }
                    }

                    Classes.Add(newClass);
                }
            }
        }
Esempio n. 6
0
        public byte[] Write()
        {
            using (MemoryStream stream = new MemoryStream())
                using (EndianBinaryWriter writer = new EndianBinaryWriter(stream, XData.Endianness))
                {
                    XData.Write(writer);

                    int  padding   = Version[0] >= 7 ? 0 : -1;
                    uint fileStart = (uint)writer.BaseStream.Position;
                    writer.Write(padding);
                    if (Version[0] >= 7)
                    {
                        writer.Write(Hash);
                    }
                    uint hSdataOffset = (uint)writer.BaseStream.Position;
                    writer.Write(Version[0] >= 7 ? 0x28 : 0x20);
                    writer.Write(padding);
                    writer.Write(padding);
                    if (Version[0] >= 7)
                    {
                        writer.Write(padding);
                    }

                    writer.Write(SData.Count);
                    writer.Write(SData.ToArray());
                    writer.Write((uint)0);
                    while ((writer.BaseStream.Length & 0xF) != 0x0 &&
                           (writer.BaseStream.Length & 0xF) != 0x4 &&
                           (writer.BaseStream.Length & 0xF) != 0x8 &&
                           (writer.BaseStream.Length & 0xF) != 0xC)
                    {
                        writer.Write((byte)0);
                    }

                    writer.BaseStream.Seek(hSdataOffset + 0x4, SeekOrigin.Begin);
                    writer.Write((uint)writer.BaseStream.Length);
                    writer.BaseStream.Seek(0, SeekOrigin.End);
                    writer.Write(XRef.Count);
                    for (int i = 0; i < XRef.Count; i++)
                    {
                        writer.Write(XRef[i]);
                    }

                    writer.BaseStream.Seek(hSdataOffset + 0x8, SeekOrigin.Begin);
                    writer.Write((uint)writer.BaseStream.Length);
                    writer.BaseStream.Seek(0, SeekOrigin.End);
                    uint classListOffs = (uint)writer.BaseStream.Position;
                    writer.Write(Classes.Count);
                    for (int i = 0; i < Classes.Count; i++)
                    {
                        writer.Write(padding);
                    }

                    List <uint>   classNameOffs = new List <uint>();
                    List <uint[]> varNameOffs   = new List <uint[]>();
                    List <uint[]> funcNameOffs  = new List <uint[]>();
                    List <uint[]> constNameOffs = new List <uint[]>();
                    for (int i = 0; i < Classes.Count; i++)
                    {
                        writer.BaseStream.Seek(classListOffs + 4 + (i * 4), SeekOrigin.Begin);
                        writer.Write((uint)writer.BaseStream.Length);
                        writer.BaseStream.Seek(0, SeekOrigin.End);

                        uint cl = (uint)writer.BaseStream.Position;
                        classNameOffs.Add(cl);

                        writer.Write(padding);
                        writer.Write(Classes[i].Hash);
                        writer.Write(padding);
                        writer.Write(padding);
                        writer.Write(padding);
                        if (Version[0] >= 2 || Version[1] >= 1)
                        {
                            writer.Write(padding);
                        }
                        if (Version[0] >= 7)
                        {
                            writer.Write(padding);
                        }
                        writer.Write(Classes[i].Flags);

                        bool writeVariables = true;
                        //if (Version[0] >= 7)
                        //    writeVariables = Classes[i].Variables.Count > 0;

                        List <uint> vOffs = new List <uint>();
                        if (writeVariables)
                        {
                            writer.BaseStream.Seek(cl + 0x8, SeekOrigin.Begin);
                            writer.Write((uint)writer.BaseStream.Length);
                            writer.BaseStream.Seek(0, SeekOrigin.End);

                            uint varListOffs = (uint)writer.BaseStream.Position;
                            writer.Write(Classes[i].Variables.Count);
                            for (int v = 0; v < Classes[i].Variables.Count; v++)
                            {
                                writer.Write((uint)(varListOffs + 4 + (Classes[i].Variables.Count * 4) + (v * 0x10)));
                            }
                            for (int v = 0; v < Classes[i].Variables.Count; v++)
                            {
                                vOffs.Add((uint)writer.BaseStream.Position);
                                writer.Write(padding);
                                writer.Write(Classes[i].Variables[v].Hash);
                                writer.Write(padding);
                                writer.Write(Classes[i].Variables[v].Flags);
                            }
                        }

                        bool writeFunctions = true;
                        //if (Version[0] >= 7)
                        //    writeFunctions = Classes[i].Functions.Count > 0;

                        List <uint> funcOffsList = new List <uint>();
                        if (writeFunctions)
                        {
                            writer.BaseStream.Seek(cl + 0xC, SeekOrigin.Begin);
                            writer.Write((uint)writer.BaseStream.Length);
                            writer.BaseStream.Seek(0, SeekOrigin.End);

                            uint funcListOffs = (uint)writer.BaseStream.Position;
                            writer.Write(Classes[i].Functions.Count);
                            for (int v = 0; v < Classes[i].Functions.Count; v++)
                            {
                                writer.Write(padding);
                            }
                            for (int v = 0; v < Classes[i].Functions.Count; v++)
                            {
                                writer.BaseStream.Seek(funcListOffs + 4 + (v * 4), SeekOrigin.Begin);
                                writer.Write((uint)writer.BaseStream.Length);
                                writer.BaseStream.Seek(0, SeekOrigin.End);

                                funcOffsList.Add((uint)writer.BaseStream.Length);
                                writer.Write(padding);
                                writer.Write(Classes[i].Functions[v].Hash);
                                if (Version[0] >= 7)
                                {
                                    writer.Write(Classes[i].Functions[v].Arguments);
                                    writer.Write(Classes[i].Functions[v].Registers);
                                }
                                if (Version[0] >= 2 || Version[1] >= 1) //Only 2.x and 1.1.x use function flags
                                {
                                    writer.Write((uint)writer.BaseStream.Position + 8);
                                    writer.Write(Classes[i].Functions[v].Flags);
                                }
                                else
                                {
                                    writer.Write((uint)writer.BaseStream.Position + 4);
                                }
                                for (int f = 0; f < Classes[i].Functions[v].Instructions.Count; f++)
                                {
                                    Classes[i].Functions[v].Instructions[f].Write(writer);
                                }
                            }
                        }

                        bool writeConstants = true;
                        if (Version[0] >= 7)
                        {
                            writeConstants = Classes[i].Constants.Count > 0;
                        }

                        List <uint> cOffs = new List <uint>();
                        if (writeConstants)
                        {
                            writer.BaseStream.Seek(cl + 0x10, SeekOrigin.Begin);
                            writer.Write((uint)writer.BaseStream.Length);
                            writer.BaseStream.Seek(0, SeekOrigin.End);

                            writer.Write(Classes[i].Constants.Count);
                            uint constListOffs = (uint)writer.BaseStream.Position;
                            for (int v = 0; v < Classes[i].Constants.Count; v++)
                            {
                                writer.Write((uint)(constListOffs + (Classes[i].Constants.Count * 4) + (v * 8)));
                            }
                            for (int v = 0; v < Classes[i].Constants.Count; v++)
                            {
                                cOffs.Add((uint)writer.BaseStream.Position);
                                writer.Write(padding);
                                writer.Write(Classes[i].Constants[v].Value);
                            }
                        }

                        bool writeUnkSection = false;
                        if (Version[0] >= 2 || Version[1] >= 1)
                        {
                            writeUnkSection = true;
                        }
                        else if (Version[0] >= 7)
                        {
                            writeUnkSection = Classes[i].UnknownList.Count > 0;
                        }

                        if (writeUnkSection)
                        {
                            writer.BaseStream.Seek(cl + 0x14, SeekOrigin.Begin);
                            writer.Write((uint)writer.BaseStream.Length);
                            writer.BaseStream.Seek(0, SeekOrigin.End);

                            writer.Write(Classes[i].UnknownList.Count);
                            for (int v = 0; v < Classes[i].UnknownList.Count; v++)
                            {
                                writer.Write(Classes[i].UnknownList[v]);
                            }
                        }

                        bool writeUnk2Section = false;
                        if (Version[0] >= 7)
                        {
                            writeUnk2Section = Classes[i].Unknown2List.Count > 0;
                        }

                        if (writeUnk2Section)
                        {
                            writer.BaseStream.Seek(cl + 0x18, SeekOrigin.Begin);
                            writer.Write((uint)writer.BaseStream.Length);
                            writer.BaseStream.Seek(0, SeekOrigin.End);

                            writer.Write(Classes[i].Unknown2List.Count);
                            for (int v = 0; v < Classes[i].Unknown2List.Count; v++)
                            {
                                writer.Write(Classes[i].Unknown2List[v]);
                            }
                        }

                        varNameOffs.Add(vOffs.ToArray());
                        funcNameOffs.Add(funcOffsList.ToArray());
                        constNameOffs.Add(cOffs.ToArray());
                    }

                    //String writing
                    writer.BaseStream.Seek(0x10, SeekOrigin.Begin);
                    writer.Write((uint)writer.BaseStream.Length);
                    writer.BaseStream.Seek(0, SeekOrigin.End);
                    WriteUtil.WriteString(writer, Name);

                    for (int i = 0; i < Classes.Count; i++)
                    {
                        writer.BaseStream.Seek(classNameOffs[i], SeekOrigin.Begin);
                        writer.Write((uint)writer.BaseStream.Length);
                        writer.BaseStream.Seek(0, SeekOrigin.End);
                        WriteUtil.WriteString(writer, Classes[i].Name);

                        if (Version[0] < 7 || Classes[i].Variables.Count > 0)
                        {
                            for (int v = 0; v < Classes[i].Variables.Count; v++)
                            {
                                uint vo = varNameOffs[i][v];
                                writer.BaseStream.Seek(vo, SeekOrigin.Begin);
                                writer.Write((uint)writer.BaseStream.Length);
                                writer.BaseStream.Seek(0, SeekOrigin.End);
                                WriteUtil.WriteString(writer, Classes[i].Variables[v].Name);

                                writer.BaseStream.Seek(vo + 0x8, SeekOrigin.Begin);
                                writer.Write((uint)writer.BaseStream.Length);
                                writer.BaseStream.Seek(0, SeekOrigin.End);
                                WriteUtil.WriteString(writer, Classes[i].Variables[v].Type);
                            }
                        }

                        if (Version[0] < 7 || Classes[i].Functions.Count > 0)
                        {
                            for (int v = 0; v < Classes[i].Functions.Count; v++)
                            {
                                writer.BaseStream.Seek(funcNameOffs[i][v], SeekOrigin.Begin);
                                writer.Write((uint)writer.BaseStream.Length);
                                writer.BaseStream.Seek(0, SeekOrigin.End);
                                WriteUtil.WriteString(writer, Classes[i].Functions[v].Name);
                            }
                        }

                        if (Version[0] < 7 || Classes[i].Constants.Count > 0)
                        {
                            for (int v = 0; v < Classes[i].Constants.Count; v++)
                            {
                                writer.BaseStream.Seek(constNameOffs[i][v], SeekOrigin.Begin);
                                writer.Write((uint)writer.BaseStream.Length);
                                writer.BaseStream.Seek(0, SeekOrigin.End);
                                WriteUtil.WriteString(writer, Classes[i].Constants[v].Name);
                            }
                        }
                    }

                    XData.UpdateFilesize(writer);
                    return(stream.GetBuffer().Take((int)XData.Filesize).ToArray());
                }
        }