private static void ExportTextOffset(AdfFile.InstanceInfo ii, AdfFile.InstanceMemberInfo imi, XmlWriter writer)
        {
            int offset           = imi.Data.ReadValueS32();
            int stringArrayIndex = 0;

            foreach (var m in ii.Members)
            {
                if (m.Id == 2)
                {
                    break;
                }
                ++stringArrayIndex;
            }
            var stringArray = ii.Members[stringArrayIndex];

            List <byte> accum = new List <byte>();

            for (int i = offset; true; ++i)
            {
                byte current = (byte)stringArray.Members[i].Data.ReadByte();
                stringArray.Members[i].Data.Position = 0;

                if (current != 0)
                {
                    accum.Add(current);
                }
                else // write the string
                {
                    string t = Encoding.UTF8.GetString(accum.ToArray());
                    writer.WriteValue(t);
                    break;
                }
            }
        }
        private static void ExportInstanceMember(AdfFile.InstanceInfo ii, AdfFile.InstanceMemberInfo imi, XmlWriter writer)
        {
            writer.WriteStartElement("member");
            if (!String.IsNullOrEmpty(imi.Name))
            {
                writer.WriteAttributeString("name", imi.Name);
            }
            writer.WriteAttributeString("gbltype", imi.Type.ToString());
            if (imi.isReferenceToId)
            {
                writer.WriteAttributeString("is-reference", "yay");
            }
            if (imi.Id >= 0 || imi.isReferenceToId)
            {
                writer.WriteAttributeString("id", imi.Id.ToString());
            }
            if (imi.HasOwnCopyOfInlineArrays)
            {
                writer.WriteAttributeString("own-copy-of-inline-arrays", "yay");
            }

            if (imi.Name == "TextOffset" || imi.Name == "NameOffset") // hardcoded :( thingy to handle string lookup
            {
                writer.WriteAttributeString("type", "int32");
                ExportTextOffset(ii, imi, writer);
                writer.WriteEndElement();
                return;
            }

            // normal (except for the inlining of arrays)
            if (imi.Type == TypeDefinitionType.Primitive)
            {
                switch (imi.TypeHash)
                {
                case AdfTypeHashes.Primitive.Int8:
                    writer.WriteAttributeString("type", "int8");
                    writer.WriteValue(imi.Data.ReadValueS8().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.UInt8:
                    writer.WriteAttributeString("type", "uint8");
                    writer.WriteValue(imi.Data.ReadValueU8().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.Int16:
                    writer.WriteAttributeString("type", "int16");
                    writer.WriteValue(imi.Data.ReadValueS16().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.UInt16:
                    writer.WriteAttributeString("type", "uint16");
                    writer.WriteValue(imi.Data.ReadValueU16().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.Int32:
                    writer.WriteAttributeString("type", "int32");
                    writer.WriteValue(imi.Data.ReadValueS32().ToString("X8", CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.UInt32:
                    writer.WriteAttributeString("type", "uint32");
                    writer.WriteValue(imi.Data.ReadValueU32().ToString("X8", CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.Float:
                    writer.WriteAttributeString("type", "float");
                    // G18 'cause it may seems stupid but that's what it takes to have matching checksums
                    writer.WriteValue(imi.Data.ReadValueF32().ToString("G18", CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.Int64:
                    writer.WriteAttributeString("type", "int64");
                    writer.WriteValue(imi.Data.ReadValueS64().ToString("G", CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.UInt64:
                    writer.WriteAttributeString("type", "uint64");
                    writer.WriteValue(imi.Data.ReadValueU64().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.Double:
                    writer.WriteValue(imi.Data.ReadValueF64().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.String:
                    writer.WriteAttributeString("type", "string");
                    if (imi.ReferenceToString == true)
                    {
                        writer.WriteAttributeString("reference-string-from", imi.StringTableId.ToString(CultureInfo.InvariantCulture));
                    }
                    writer.WriteValue(imi.StringData);
                    break;
                }
            }
            else
            {
                writer.WriteAttributeString("type-hash", imi.TypeDef.NameHash.ToString(CultureInfo.InvariantCulture));
                writer.WriteAttributeString("type", imi.TypeDef.Name);
                switch (imi.Type)
                {
                case TypeDefinitionType.Array:     // we have a ref, get the ID and inline it:
                    if (imi.Id != 2 && imi.isReferenceToId == true)
                    {
                        int index = 0;
                        foreach (var m in ii.Members)
                        {
                            if (m.Id == imi.Id)
                            {
                                break;
                            }
                            ++index;
                        }
                        ExportInstanceMember(ii, ii.Members[index], writer);
                    }
                    else if (imi.Id == 2 && imi.isReferenceToId == true)
                    {
                    }
                    break;

                case TypeDefinitionType.InlineArray:
                    break;

                case TypeDefinitionType.Structure:
                    break;

                case TypeDefinitionType.StringHash:
                    writer.WriteValue(imi.StringData);
                    break;
                }
            }

            foreach (var member in imi.Members)
            {
                ExportInstanceMember(ii, member, writer);
            }

            writer.WriteEndElement();
        }
Esempio n. 3
0
        private static void ImportInstanceInfo(XPathNavigator instanceNode, AdfFile adf)
        {
            InstanceInfo instance = new InstanceInfo()
            {
                Name     = instanceNode.GetAttribute("name", ""),
                NameHash = uint.Parse(instanceNode.GetAttribute("name-hash", "")),
            };

            TypeDefinitionType type;

            Enum.TryParse(instanceNode.GetAttribute("type", ""), out type);
            uint   typeHash   = uint.Parse(instanceNode.GetAttribute("type-hash", ""), CultureInfo.InvariantCulture);
            string typeString = instanceNode.GetAttribute("type-name", "");

            instance.Type     = adf.Runtime.GetTypeDefinition(typeHash);
            instance.TypeHash = instance.Type.NameHash;

            if (!int.TryParse(instanceNode.GetAttribute("inline-array-copy-index", ""), out instance.InlineArrayIndex))
            {
                instance.InlineArrayIndex = -1;
            }
            if (!uint.TryParse(instanceNode.GetAttribute("inline-array-copy-minsz", ""), out instance.MinInlineArraySize))
            {
                instance.MinInlineArraySize = 0;
            }

            if (type != instance.Type.Type)
            {
                throw new InvalidOperationException("do not touch things like type and type-name in the xml file, yo");
            }

            instance.Members = new List <AdfFile.InstanceMemberInfo>();

            // Hold the contents of the last Array (A[int8])
            List <byte> stringArray = new List <byte>();

            // parse members
            instance.Members.Add(null); // prepare the future
            var memberNode = instanceNode.SelectSingleNode("member");

            instance.Members[0] = (ImportInstanceMemberInfo(memberNode, instance, adf, stringArray));

            var stringArrayMemberIndex = 0;

            foreach (var member in instance.Members)
            {
                if (member.Id == 2)
                {
                    break;
                }
                ++stringArrayMemberIndex;
            }
            var stringArrayMember = instance.Members[stringArrayMemberIndex];

            // Generate the string array (type is array of int8)
            foreach (byte b in stringArray) // the foreach is sooo overkill...
            {
                var subMember = new AdfFile.InstanceMemberInfo()
                {
                    Type     = TypeDefinitionType.Primitive,
                    TypeHash = AdfTypeHashes.Primitive.Int8,
                    Name     = null,
                };
                subMember.Data.WriteByte(b);
                stringArrayMember.Members.Add(subMember);
            }

            // add instance to ADF structure
            adf.AddInstanceInfo(instance);
        }
Esempio n. 4
0
        private static AdfFile.InstanceMemberInfo ImportTextOffset(XPathNavigator memberNode, AdfFile.InstanceMemberInfo member, InstanceInfo ii, AdfFile adf, List <byte> stringArray)
        {
            member.TypeHash = AdfTypeHashes.Primitive.UInt32;
            member.Data.WriteValueU32((uint)stringArray.Count); // write the offset

            byte[] str = Encoding.UTF8.GetBytes(memberNode.Value);
            stringArray.AddRange(str);
            stringArray.Add(0); // the null byte to terminate the string

            return(member);
        }
Esempio n. 5
0
        private static AdfFile.InstanceMemberInfo ImportInstanceMemberInfo(XPathNavigator memberNode, AdfFile.InstanceInfo ii, AdfFile adf, List <byte> stringArray)
        {
            AdfFile.InstanceMemberInfo member = new AdfFile.InstanceMemberInfo();

            member.Name = memberNode.GetAttribute("name", "");
            string stringId  = memberNode.GetAttribute("id", "");
            string ownIACopy = memberNode.GetAttribute("own-copy-of-inline-arrays", "");

            if (!string.IsNullOrEmpty(stringId))
            {
                member.Id = long.Parse(stringId, CultureInfo.InvariantCulture);
            }
            else
            {
                member.Id = -1;
            }
            member.isReferenceToId = !string.IsNullOrEmpty(memberNode.GetAttribute("is-reference", ""));
            if (!string.IsNullOrEmpty(ownIACopy))
            {
                member.HasOwnCopyOfInlineArrays = true;
            }

            Enum.TryParse(memberNode.GetAttribute("gbltype", ""), out member.Type);
            string typeString = memberNode.GetAttribute("type", "");

            if (member.Name == "TextOffset" || member.Name == "NameOffset") // hardcoded :( thingy to handle string lookup
            {
                return(ImportTextOffset(memberNode, member, ii, adf, stringArray));
            }

            // Load the value
            if (member.Type == TypeDefinitionType.Primitive)
            {
                switch (typeString)
                {
                case "int8":
                    member.Data.WriteValueS8(sbyte.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Int8;
                    break;

                case "uint8":
                    member.Data.WriteValueU8(byte.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.UInt8;
                    break;

                case "int16":
                    member.Data.WriteValueS16(short.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Int16;
                    break;

                case "uint16":
                    member.Data.WriteValueU16(ushort.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.UInt16;
                    break;

                case "int32":
                    member.Data.WriteValueS32(int.Parse(memberNode.Value, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Int32;
                    break;

                case "uint32":
                    member.Data.WriteValueU32(uint.Parse(memberNode.Value, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.UInt32;
                    break;

                case "int64":
                    member.Data.WriteValueS64(long.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Int64;
                    break;

                case "uint64":
                    member.Data.WriteValueU64(ulong.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.UInt64;
                    break;

                case "float":
                    member.Data.WriteValueF32(float.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Float;
                    break;

                case "double":
                    member.Data.WriteValueF64(double.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Double;
                    break;

                case "string":
                    string strRef = memberNode.GetAttribute("reference-string-from", "");
                    if (!string.IsNullOrEmpty(strRef))
                    {
                        member.ReferenceToString = true;
                        member.StringTableId     = int.Parse(strRef, CultureInfo.InvariantCulture);
                    }
                    member.StringData = memberNode.Value;
                    member.TypeHash   = AdfTypeHashes.String;
                    break;
                }
            }
            else
            {
                uint typeHash = uint.Parse(memberNode.GetAttribute("type-hash", ""), CultureInfo.InvariantCulture);
                member.TypeDef  = adf.Runtime.GetTypeDefinition(typeHash);
                member.TypeHash = typeHash;
                if (member.TypeDef.Type != member.Type)
                {
                    throw new InvalidOperationException("do not touch things like type and type-name in the xml file, yo");
                }

                if (member.Type == TypeDefinitionType.StringHash)
                {
                    member.StringData = memberNode.Value;
                }

                if (member.Type == TypeDefinitionType.Array && member.isReferenceToId == true && member.Id != -1)
                {
                    // No child, create an empty element
                    if (!memberNode.HasChildren)
                    {
                        var subMember = new AdfFile.InstanceMemberInfo()
                        {
                            Name                     = member.Name,
                            Id                       = member.Id,
                            isReferenceToId          = false,
                            Type                     = member.Type,
                            TypeHash                 = member.TypeHash,
                            TypeDef                  = member.TypeDef,
                            HasOwnCopyOfInlineArrays = false,  // maybe _that_ will cause some issues...
                        };
                        ii.Members.Add(subMember);
                        return(member);
                    }
                    // the child node is in fact a global element.
                    XPathNavigator subMemberNode = memberNode.SelectSingleNode("member");
                    ii.Members.Add(ImportInstanceMemberInfo(subMemberNode, ii, adf, stringArray));
                    return(member);
                }
            }

            // handle sub members
            var subMembersList = memberNode.Select("member");

            foreach (XPathNavigator subMemberNode in subMembersList)
            {
                var subMember = ImportInstanceMemberInfo(subMemberNode, ii, adf, stringArray);
                if (member.Name != "SortedPairs") // another hardcoded thing
                {
                    member.Members.Add(subMember);
                }
                else // insert the new member at the right place
                {
                    subMember.Members[0].Data.Position = 0;
                    uint hash = subMember.Members[0].Data.ReadValueU32();
                    subMember.Members[0].Data.Position = 0;
                    int i = 0;
                    for (; i < member.Members.Count; ++i)
                    {
                        member.Members[i].Members[0].Data.Position = 0;
                        uint cmpHash = member.Members[i].Members[0].Data.ReadValueU32();
                        member.Members[i].Members[0].Data.Position = 0;
                        if (cmpHash > hash)
                        {
                            break;
                        }
                    }
                    member.Members.Insert(i, subMember);
                }
            }

            return(member);
        }
        private static void ExportInstanceMember(AdfFile.InstanceMemberInfo imi, XmlWriter writer)
        {
            writer.WriteStartElement("member");
            if (!String.IsNullOrEmpty(imi.Name))
            {
                writer.WriteAttributeString("name", imi.Name);
            }
            writer.WriteAttributeString("gbltype", imi.Type.ToString());
            if (imi.isReferenceToId)
            {
                writer.WriteAttributeString("is-reference", "yay");
            }
            if (imi.Id >= 0 || imi.isReferenceToId)
            {
                writer.WriteAttributeString("id", imi.Id.ToString());
            }
            if (imi.HasOwnCopyOfInlineArrays)
            {
                writer.WriteAttributeString("own-copy-of-inline-arrays", "yay");
            }
            if (imi.FileOffset > 0)
            {
                writer.WriteAttributeString("offset-in-file", imi.FileOffset.ToString("X8", CultureInfo.InvariantCulture));
            }
            if (imi.Type == TypeDefinitionType.Primitive)
            {
                switch (imi.TypeHash)
                {
                case AdfTypeHashes.Primitive.Int8:
                    writer.WriteAttributeString("type", "int8");
                    writer.WriteValue(imi.Data.ReadValueS8().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.UInt8:
                    writer.WriteAttributeString("type", "uint8");
                    writer.WriteValue(imi.Data.ReadValueU8().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.Int16:
                    writer.WriteAttributeString("type", "int16");
                    writer.WriteValue(imi.Data.ReadValueS16().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.UInt16:
                    writer.WriteAttributeString("type", "uint16");
                    writer.WriteValue(imi.Data.ReadValueU16().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.Int32:
                    writer.WriteAttributeString("type", "int32");
                    writer.WriteValue(imi.Data.ReadValueS32().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.UInt32:
                    writer.WriteAttributeString("type", "uint32");
                    writer.WriteValue(imi.Data.ReadValueU32().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.Float:
                    writer.WriteAttributeString("type", "float");
                    // G18 'cause it may seems stupid but that's what it takes to have matching checksums
                    writer.WriteValue(imi.Data.ReadValueF32().ToString("G18", CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.Int64:
                    writer.WriteAttributeString("type", "int64");
                    writer.WriteValue(imi.Data.ReadValueS64().ToString("G", CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.UInt64:
                    writer.WriteAttributeString("type", "uint64");
                    writer.WriteValue(imi.Data.ReadValueU64().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.Primitive.Double:
                    writer.WriteValue(imi.Data.ReadValueF64().ToString(CultureInfo.InvariantCulture));
                    break;

                case AdfTypeHashes.String:
                    writer.WriteAttributeString("type", "string");
                    if (imi.ReferenceToString == true)
                    {
                        writer.WriteAttributeString("reference-string-from", imi.StringTableId.ToString(CultureInfo.InvariantCulture));
                    }
                    writer.WriteValue(imi.StringData);
                    break;
                }
            }
            else
            {
                writer.WriteAttributeString("type-hash", imi.TypeDef.NameHash.ToString(CultureInfo.InvariantCulture));
                writer.WriteAttributeString("type", imi.TypeDef.Name);
                switch (imi.Type)
                {
                case TypeDefinitionType.Array:
                    break;

                case TypeDefinitionType.InlineArray:
                    break;

                case TypeDefinitionType.Structure:
                    break;

                case TypeDefinitionType.StringHash:
                    writer.WriteValue(imi.StringData);
                    break;
                }
            }

            bool isString = false;

            if (imi.Type == TypeDefinitionType.Array && imi.TypeDef.ElementTypeHash == AdfTypeHashes.Primitive.Int8 &&
                imi.Members.Count > 1)
            {
                // check if that's a string. First thing: the name should be *text* or *string* (for stringlookups)
                // Second thing, it should end with 0
                sbyte last = (sbyte)imi.Members.Last().Data.ReadByte();
                imi.Members.Last().Data.Position = 0;
                var nameMatchingRegexp = new System.Text.RegularExpressions.Regex("(.*Text.*)|(.*String.*)");
                if (last == 0 && nameMatchingRegexp.IsMatch(imi.Name))
                {
                    isString = true; // yeah try the string
                    writer.WriteAttributeString("int8-array-is-string-array", "yay");
                    // write the string
                    List <byte> accum = new List <byte>();
                    foreach (var member in imi.Members)
                    {
                        byte current = (byte)member.Data.ReadByte();
                        if (current != 0)
                        {
                            accum.Add(current);
                        }
                        else // write the string
                        {
                            writer.WriteStartElement("inline-string");
                            string t = Encoding.UTF8.GetString(accum.ToArray());
                            accum.Clear();
                            writer.WriteValue(t);
                            writer.WriteEndElement();
                        }
                    }
                }
            }

            if (!isString)
            {
                foreach (var member in imi.Members)
                {
                    ExportInstanceMember(member, writer);
                }
            }

            writer.WriteEndElement();
        }
Esempio n. 7
0
        private static AdfFile.InstanceMemberInfo ImportInstanceMemberInfo(XPathNavigator memberNode, AdfFile adf)
        {
            AdfFile.InstanceMemberInfo member = new AdfFile.InstanceMemberInfo();

            member.Name = memberNode.GetAttribute("name", "");
            string stringId  = memberNode.GetAttribute("id", "");
            string ownIACopy = memberNode.GetAttribute("own-copy-of-inline-arrays", "");

            if (!string.IsNullOrEmpty(stringId))
            {
                member.Id = long.Parse(stringId, CultureInfo.InvariantCulture);
            }
            member.isReferenceToId = !string.IsNullOrEmpty(memberNode.GetAttribute("is-reference", ""));
            if (!string.IsNullOrEmpty(ownIACopy))
            {
                member.HasOwnCopyOfInlineArrays = true;
            }

            Enum.TryParse(memberNode.GetAttribute("gbltype", ""), out member.Type);
            string typeString = memberNode.GetAttribute("type", "");

            // Load the value
            if (member.Type == TypeDefinitionType.Primitive)
            {
                switch (typeString)
                {
                case "int8":
                    member.Data.WriteValueS8(sbyte.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Int8;
                    break;

                case "uint8":
                    member.Data.WriteValueU8(byte.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.UInt8;
                    break;

                case "int16":
                    member.Data.WriteValueS16(short.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Int16;
                    break;

                case "uint16":
                    member.Data.WriteValueU16(ushort.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.UInt16;
                    break;

                case "int32":
                    member.Data.WriteValueS32(int.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Int32;
                    break;

                case "uint32":
                    member.Data.WriteValueU32(uint.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.UInt32;
                    break;

                case "int64":
                    member.Data.WriteValueS64(long.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Int64;
                    break;

                case "uint64":
                    member.Data.WriteValueU64(ulong.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.UInt64;
                    break;

                case "float":
                    member.Data.WriteValueF32(float.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Float;
                    break;

                case "double":
                    member.Data.WriteValueF64(double.Parse(memberNode.Value, CultureInfo.InvariantCulture));
                    member.TypeHash = AdfTypeHashes.Primitive.Double;
                    break;

                case "string":
                    string strRef = memberNode.GetAttribute("reference-string-from", "");
                    if (!string.IsNullOrEmpty(strRef))
                    {
                        member.ReferenceToString = true;
                        member.StringTableId     = int.Parse(strRef, CultureInfo.InvariantCulture);
                    }
                    member.StringData = memberNode.Value;
                    member.TypeHash   = AdfTypeHashes.String;
                    break;
                }
            }
            else
            {
                uint typeHash = uint.Parse(memberNode.GetAttribute("type-hash", ""), CultureInfo.InvariantCulture);
                member.TypeDef  = adf.Runtime.GetTypeDefinition(typeHash);
                member.TypeHash = typeHash;
                if (member.TypeDef.Type != member.Type)
                {
                    throw new InvalidOperationException("do not touch things like type and type-name in the xml file, yo");
                }

                if (member.Type == TypeDefinitionType.StringHash)
                {
                    member.StringData = memberNode.Value;
                }
            }

            // handle sub members
            if (memberNode.GetAttribute("int8-array-is-string-array", "") == "yay")
            {
                // we found an array of inline-strings
                var subMembersList = memberNode.Select("inline-string");
                foreach (XPathNavigator subMemberNode in subMembersList)
                {
                    // it is an inline string. Get its value and write the string
                    byte[] str = Encoding.UTF8.GetBytes(subMemberNode.Value);
                    foreach (byte b in str)
                    {
                        AdfFile.InstanceMemberInfo subMember = new AdfFile.InstanceMemberInfo();
                        subMember.TypeHash = AdfTypeHashes.Primitive.Int8;
                        subMember.Type     = TypeDefinitionType.Primitive;
                        subMember.Data.WriteValueU8(b);
                        member.Members.Add(subMember);
                    }
                    AdfFile.InstanceMemberInfo lastByteMember = new AdfFile.InstanceMemberInfo();
                    lastByteMember.TypeHash = AdfTypeHashes.Primitive.Int8;
                    lastByteMember.Type     = TypeDefinitionType.Primitive;
                    lastByteMember.Data.WriteValueU8(0);
                    member.Members.Add(lastByteMember);
                }
            }
            else
            {
                var subMembersList = memberNode.Select("member");
                foreach (XPathNavigator subMemberNode in subMembersList)
                {
                    member.Members.Add(ImportInstanceMemberInfo(subMemberNode, adf));
                }
            }

            return(member);
        }