Пример #1
0
        private object ExportField(GFF.FieldDefinition def, long offset, ExportState state)
        {
            var input = this.Data;
            input.Seek(offset + def.Offset, SeekOrigin.Begin);

            if (def.IsReference == true && def.IsList == true)
            {
                var listOffset = input.ReadValueU32(LittleEndian);
                if (listOffset == 0xFFFFFFFF)
                {
                    return null;
                }

                input.Seek(listOffset, SeekOrigin.Begin);
                var count = input.ReadValueU32(LittleEndian);

                long itemOffset = input.Position;
                var list = new List<object>();
                for (uint i = 0; i < count; i++)
                {
                    list.Add(this.ExportGeneric(state));
                    itemOffset += 8;
                    input.Seek(itemOffset, SeekOrigin.Begin);
                }
                return list;
            }
            else if (def.IsList == true)
            {
                //var type = GFF.Builtin.ToNativeType(def.Type);

                var listOffset = input.ReadValueU32(LittleEndian);
                if (listOffset == 0xFFFFFFFF)
                {
                    /*if (def.Type == GFF.FieldType.UInt8)
                    {
                        return new byte[0];
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }*/
                    return null;
                }

                input.Seek(listOffset, SeekOrigin.Begin);
                var count = input.ReadValueU32(LittleEndian);

                switch (def.Type)
                {
                    case GFF.FieldType.String:
                    {
                        long itemOffset = input.Position;
                        var list = new List<string>();
                        for (uint i = 0; i < count; i++)
                        {
                            var dataOffset = input.ReadValueU32(LittleEndian);
                            if (dataOffset == 0xFFFFFFFF)
                            {
                                list.Add(null);
                            }
                            else
                            {
                                if (this.FileVersion < 1)
                                {
                                    input.Seek(dataOffset, SeekOrigin.Begin);
                                    var length = input.ReadValueU32(LittleEndian);
                                    list.Add(input.ReadString(length * 2, true,
                                        LittleEndian == true ? Encoding.Unicode : Encoding.BigEndianUnicode));
                                }
                                else
                                {
                                    list.Add(this.StringTable[(int)dataOffset]);
                                }
                            }

                            itemOffset += 4;
                            input.Seek(itemOffset, SeekOrigin.Begin);
                        }

                        return list;
                    }

                    case GFF.FieldType.Structure:
                    {
                        long itemOffset = input.Position;
                        var subdef = this.Structures[def.StructureId];
                        var list = new List<KeyValue>();
                        for (uint i = 0; i < count; i++)
                        {
                            list.Add(this.ExportStructure(
                                subdef, itemOffset, state));
                            itemOffset += subdef.DataSize;
                        }
                        return list;
                    }

                    default:
                    {
                        if (def.Type == GFF.FieldType.UInt8)
                        {
                            var list = new byte[count];
                            input.Read(list, 0, list.Length);
                            return list;
                        }
                        else
                        {
                            var type = GFF.Builtin.ToNativeType(def.Type);
                            var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
                            for (uint i = 0; i < count; i++)
                            {
                                list.Add(GFF.Builtin.Deserialize(input, def.Type, LittleEndian));
                            }
                            return list;
                        }
                    }
                }
            }
            else
            {
                if (def.IsReference == true &&
                    def.Type == GFF.FieldType.Generic)
                {
                    return this.ExportGeneric(state);
                }
                else if (def.IsReference == true)
                {
                    var referenceOffset = input.ReadValueU32(LittleEndian);
                    if (referenceOffset == 0xFFFFFFFF)
                    {
                        return null;
                    }
                    else if (state.References.ContainsKey(referenceOffset) == true)
                    {
                        return state.References[referenceOffset];
                    }

                    input.Seek(referenceOffset, SeekOrigin.Begin);
                }

                switch (def.Type)
                {
                    case GFF.FieldType.Generic:
                    {
                        throw new FormatException();
                    }

                    case GFF.FieldType.String:
                    {
                        var dataOffset = input.ReadValueU32(LittleEndian);
                        if (dataOffset == 0xFFFFFFFF)
                        {
                            return "";
                        }

                        if (this.FileVersion < 1)
                        {
                            input.Seek(dataOffset, SeekOrigin.Begin);
                            var count = input.ReadValueU32(LittleEndian);
                            return input.ReadString(count * 2, true,
                                LittleEndian == true ? Encoding.Unicode : Encoding.BigEndianUnicode);
                        }
                        else
                        {
                            return this.StringTable[(int)dataOffset];
                        }
                    }

                    case GFF.FieldType.TalkString:
                    {
                        var tlk = new GFF.Builtins.TalkString();
                        tlk.Id = input.ReadValueU32(LittleEndian);

                        var dataOffset = input.ReadValueU32(LittleEndian);
                        if (dataOffset == 0xFFFFFFFF)
                        {
                            tlk.String = null;
                        }
                        else if (dataOffset == 0)
                        {
                            tlk.String = "";
                        }
                        else
                        {
                            if (this.FileVersion < 1)
                            {
                                input.Seek(dataOffset, SeekOrigin.Begin);
                                var count = input.ReadValueU32(LittleEndian);
                                tlk.String = input.ReadString(count * 2, true,
                                    LittleEndian == true ? Encoding.Unicode : Encoding.BigEndianUnicode);
                            }
                            else
                            {
                                tlk.String = this.StringTable[(int)dataOffset];
                            }
                        }

                        return tlk;
                    }

                    case GFF.FieldType.Structure:
                    {
                        var subdef = this.Structures[def.StructureId];
                        return this.ExportStructure(subdef, input.Position, state);
                    }

                    default:
                    {
                        return GFF.Builtin.Deserialize(input, def.Type, LittleEndian);
                    }
                }
            }
        }
Пример #2
0
        private void ImportStructure(GFF.StructureDefinition def, KeyValue data, long offset, ref long newOffset, ImportState state)
        {
            foreach (var fieldDef in def.Fields)
            {
                if (fieldDef.Id == 16208)
                {
                }

                KeyValue value;
                if (data.Values.ContainsKey(fieldDef.Id) == false)
                {
                    //throw new InvalidOperationException();
                    value = new KeyValue(fieldDef.Type, null);
                }
                else
                {
                    value = data[fieldDef.Id];
                }
                this.ImportField(fieldDef, value, offset, ref newOffset, state);
            }
        }
Пример #3
0
        private KeyValue ExportStructure(GFF.StructureDefinition def, long offset, ExportState state)
        {
            var kv = new KeyValue(GFF.FieldType.Structure, null);
            kv.StructureId = def.Id;

            foreach (var fieldDef in def.Fields)
            {
                var value = this.ExportField(fieldDef, offset, state);

                if (value is KeyValue)
                {
                    kv[fieldDef.Id] = (KeyValue)value;
                }
                else
                {
                    kv[fieldDef.Id] = new KeyValue(fieldDef.Type, value);
                }
            }
            return kv;
        }
Пример #4
0
        private void ImportField(GFF.FieldDefinition def, KeyValue data, long offset, ref long newOffset, ImportState state)
        {
            var output = this.Data;
            output.Seek(offset + def.Offset, SeekOrigin.Begin);

            if (def.IsList == true)
            {
                if (def.IsReference == true &&
                    (data.Value != null || def.Type != GFF.FieldType.Generic))
                {
                    throw new NotSupportedException();
                }

                var list = (IList)data.Value;
                if (list == null)
                {
                    output.WriteValueU32(0xFFFFFFFF, LittleEndian);
                }
                else
                {
                    output.WriteValueU32((uint)newOffset, LittleEndian);

                    output.Seek(newOffset, SeekOrigin.Begin);
                    output.WriteValueS32(list.Count, LittleEndian);
                    newOffset += 4;

                    uint itemSize;
                    if (def.Type == GFF.FieldType.Structure)
                    {
                        var subdef = this.Structures[def.StructureId];
                        itemSize = subdef.DataSize;
                    }
                    else
                    {
                        itemSize = GFF.Builtin.SizeOf(def.Type);
                    }

                    newOffset += list.Count * itemSize;

                    switch (def.Type)
                    {
                        case GFF.FieldType.String:
                        {
                            throw new NotImplementedException();
                        }

                        case GFF.FieldType.Structure:
                        {
                            var subdef = this.Structures[def.StructureId];

                            long itemOffset = output.Position;
                            foreach (var item in list)
                            {
                                this.ImportStructure(
                                    subdef,
                                    (KeyValue)item,
                                    itemOffset,
                                    ref newOffset,
                                    state);
                                itemOffset += itemSize;
                            }

                            break;
                        }

                        default:
                        {
                            if (def.Type == GFF.FieldType.UInt8 &&
                                list.GetType() == typeof(byte[]))
                            {
                                var bytes = (byte[])list;
                                output.Write(bytes, 0, bytes.Length);
                            }
                            else
                            {
                                long itemOffset = output.Position;
                                foreach (var item in list)
                                {
                                    GFF.Builtin.Serialize(output, def.Type, item, LittleEndian);
                                    itemOffset += itemSize;
                                }
                            }

                            break;
                        }
                    }
                }
            }
            else
            {
                if (def.IsReference == true &&
                    def.Type != GFF.FieldType.Structure)
                {
                    throw new NotSupportedException();
                }

                switch (def.Type)
                {
                    case GFF.FieldType.String:
                    {
                        var s = data.As<string>();

                        if (s == null || s.Length == 0)
                        {
                            output.WriteValueU32(0xFFFFFFFF, LittleEndian);
                        }
                        else
                        {
                            var length = s.Length + 1;

                            output.WriteValueU32((uint)newOffset, LittleEndian);

                            output.Seek(newOffset, SeekOrigin.Begin);
                            output.WriteValueS32(length, LittleEndian);
                            output.WriteString(s, LittleEndian ? Encoding.Unicode : Encoding.BigEndianUnicode);
                            output.WriteValueU16(0, LittleEndian);
                            newOffset += 4 + (2 * length);
                        }

                        break;
                    }

                    case GFF.FieldType.TalkString:
                    {
                        var s = data.As<GFF.Builtins.TalkString>();
                        output.WriteValueU32(s.Id, LittleEndian);

                        if (s.String == null)
                        {
                            output.WriteValueU32(0xFFFFFFFF, LittleEndian);
                        }
                        else if (s.String.Length == 0)
                        {
                            output.WriteValueU32(0, LittleEndian);
                        }
                        else
                        {
                            var length = s.String.Length + 1;

                            output.WriteValueU32((uint)newOffset, LittleEndian);

                            output.Seek(newOffset, SeekOrigin.Begin);
                            output.WriteValueS32(length, LittleEndian);
                            output.WriteString(s.String, LittleEndian ? Encoding.Unicode : Encoding.BigEndianUnicode);
                            output.WriteValueU16(0, LittleEndian);
                            newOffset += 4 + (2 * length);
                        }

                        break;
                    }

                    case GFF.FieldType.Structure:
                    {
                        if (def.IsReference == true)
                        {
                            if (data == null || data.Values == null)
                            {
                                output.WriteValueU32(0xFFFFFFFF, LittleEndian);
                            }
                            else
                            {
                                output.WriteValueU32((uint)newOffset, LittleEndian);
                                output.Seek(newOffset, SeekOrigin.Begin);

                                var subdef = this.Structures[def.StructureId];
                                newOffset += subdef.DataSize;

                                this.ImportStructure(
                                    subdef,
                                    data,
                                    output.Position,
                                    ref newOffset,
                                    state);
                            }
                        }
                        else
                        {
                            var subdef = this.Structures[def.StructureId];
                            this.ImportStructure(
                            subdef,
                            data,
                            output.Position,
                            ref newOffset,
                            state);
                        }
                        break;
                    }

                    default:
                    {
                        GFF.Builtin.Serialize(output, def.Type, data.Value, LittleEndian);
                        break;
                    }
                }
            }
        }
Пример #5
0
        private void PrintStructure(GFF.StructureDefinition def, int level)
        {
            var queue = new Queue<GFF.StructureDefinition>();
            if (Printed.Contains(def) == false)
            {
                Printed.Add(def);
            }

            PrintLine(level, "[GFF.StructureDefinition(0x{0:X8})] // {1}", def.Id, ParseId(def.Id));
            PrintLine(level, "public class {0}", ParseId(def.Id));
            PrintLine(level, "{{");

            foreach (var fieldDef in def.Fields)
            {
                string type;

                if (fieldDef.Type == GFF.FieldType.Structure)
                {
                    var subdef = this.Structures[fieldDef.StructureId];
                    type = ParseId(subdef.Id);

                    if (queue.Contains(subdef) == false)
                    {
                        queue.Enqueue(subdef);
                    }
                }
                else
                {
                    type = fieldDef.Type.ToString();
                }

                if (fieldDef.Type == GFF.FieldType.Color ||
                    fieldDef.Type == GFF.FieldType.Matrix4x4 ||
                    fieldDef.Type == GFF.FieldType.Quaternion ||
                    fieldDef.Type == GFF.FieldType.TalkString ||
                    fieldDef.Type == GFF.FieldType.Vector3 ||
                    fieldDef.Type == GFF.FieldType.Vector4)
                {
                    type = "GFF.Builtins." + type;
                }

                if (fieldDef.Type == GFF.FieldType.UInt8 &&
                    fieldDef.IsList == true)
                {
                    type = "byte[]";
                }
                else if (fieldDef.IsList == true)
                {
                    type = "List<" + type + ">";
                }

                if (fieldDef.IsReference == true)
                {
                    type = "*" + type;
                }

                PrintLine(level + 1, "");
                PrintLine(level + 1, "[GFF.FieldDefinition({0})]", fieldDef.Id);
                PrintLine(level + 1, "public {0} Unknown{1};", type, fieldDef.Id);
            }

            if (queue.Count > 0)
            {
                while (queue.Count > 0)
                {
                    PrintLine(level + 1, "");
                    PrintStructure(queue.Dequeue(), level + 1);
                }
            }

            PrintLine(level, "}}");
        }