private static bool ValidateStructure(
     GFF.StructureDefinition def,
     Type nativeType)
 {
     // i'm too lazy to write this code right now :)
     return(true);
 }
        private void ImportTypeStructure(GFF.StructureDefinition def, object instance, long offset, ref long newOffset)
        {
            var type = instance.GetType();

            if (ValidateStructure(def, type) == false)
            {
                throw new FormatException("structure validation failed");
            }

            var reflected = GFF.ReflectedStructureType.For(type);

            foreach (var fieldDef in def.Fields)
            {
                var value = reflected.GetField(instance, fieldDef.Id);
                this.ImportTypeField(fieldDef, reflected.GetFieldType(fieldDef.Id), value, offset, ref newOffset);
            }
        }
        private object ExportTypeStructure(GFF.StructureDefinition def, Type type, long offset)
        {
            if (ValidateStructure(def, type) == false)
            {
                throw new FormatException("structure validation failed");
            }

            var instance  = Activator.CreateInstance(type);
            var reflected = GFF.ReflectedStructureType.For(type);

            foreach (var fieldDef in def.Fields)
            {
                var value = this.ExportTypeField(
                    fieldDef, reflected.GetFieldType(fieldDef.Id), offset);
                reflected.SetField(instance, fieldDef.Id, value);
            }

            return(instance);
        }
예제 #4
0
        private void ImportStructure(GFF.StructureDefinition def, GenericKeyValue data, long offset, ref long newOffset, ImportState state)
        {
            foreach (var fieldDef in def.Fields)
            {
                if (fieldDef.Id == 16208)
                {
                }

                GenericKeyValue value;
                if (data.Values.ContainsKey(fieldDef.Id) == false)
                {
                    //throw new InvalidOperationException();
                    value = new GenericKeyValue(fieldDef.Type, null);
                }
                else
                {
                    value = data[fieldDef.Id];
                }
                this.ImportField(fieldDef, value, offset, ref newOffset, state);
            }
        }
예제 #5
0
        private GenericKeyValue ExportStructure(GFF.StructureDefinition def, long offset, ExportState state)
        {
            var kv = new GenericKeyValue(GFF.FieldType.Structure, null);

            kv.StructureId = def.Id;

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

                if (value is GenericKeyValue)
                {
                    kv[fieldDef.Id] = (GenericKeyValue)value;
                }
                else
                {
                    kv[fieldDef.Id] = new GenericKeyValue(fieldDef.Type, value);
                }
            }
            return(kv);
        }
        private void ImportTypeToStructures(Type root)
        {
            var structs = new List <GFF.StructureDefinition>();
            var map     = new Dictionary <Type, GFF.StructureDefinition>();

            var types = new List <Type>();
            var queue = new Queue <Type>();

            queue.Enqueue(root);

            // discover non-native types we need to add
            while (queue.Count > 0)
            {
                var type = queue.Dequeue();
                types.Add(type);

                foreach (var field in type.GetFields())
                {
                    var subtype = field.FieldType;

                    if (GFF.Builtin.FromNativeType(subtype) != GFF.FieldType.Structure)
                    {
                        continue;
                    }

                    if (subtype.IsGenericType == true &&
                        subtype.GetGenericTypeDefinition() == typeof(List <>))
                    {
                        subtype = subtype.GetGenericArguments()[0];
                    }

                    if (types.Contains(subtype) == true ||
                        queue.Contains(subtype) == true)
                    {
                        continue;
                    }

                    queue.Enqueue(subtype);
                }
            }

            if (types.Count > 0xFFFF)
            {
                throw new InvalidOperationException();
            }

            // now define them
            foreach (var type in types)
            {
                var structDef = new GFF.StructureDefinition();
                var reflected = GFF.ReflectedStructureType.For(type);

                map.Add(type, structDef);
                structs.Add(structDef);

                structDef.Id = reflected.Id;

                uint offset = 0;
                foreach (var kvp in reflected.Fields)
                {
                    var subtype = kvp.Value.Field.FieldType;

                    var fieldDef = new GFF.FieldDefinition();

                    if (subtype.IsGenericType == true &&
                        subtype.GetGenericTypeDefinition() == typeof(List <>))
                    {
                        subtype         = subtype.GetGenericArguments()[0];
                        fieldDef.Flags |= GFF.FieldFlags.IsList;
                    }
                    else if (subtype.IsArray == true)
                    {
                        fieldDef.Flags |= GFF.FieldFlags.IsList;
                    }

                    fieldDef.Id   = kvp.Key;
                    fieldDef.Type = GFF.Builtin
                                    .FromNativeType(subtype, kvp.Value.Type);
                    fieldDef.Offset     = offset;
                    fieldDef.NativeType = subtype;

                    structDef.Fields.Add(fieldDef);

                    if ((fieldDef.Flags & GFF.FieldFlags.IsList) != 0)
                    {
                        offset += 4;
                    }
                    else if (fieldDef.Type == GFF.FieldType.Structure)
                    {
                        throw new NotImplementedException();
                    }
                    else
                    {
                        offset += GFF.Builtin.SizeOf(fieldDef.Type);
                    }
                }

                structDef.DataSize = offset;
            }

            // update ids
            foreach (var type in types)
            {
                var structDef = map[type];

                foreach (var fieldDef in structDef.Fields)
                {
                    if (fieldDef.Type == GFF.FieldType.Structure)
                    {
                        var structRef = map[fieldDef.NativeType];

                        int index = structs.IndexOf(structRef);
                        if (index < 0)
                        {
                            throw new InvalidOperationException();
                        }

                        fieldDef.StructureReference = structRef;
                        fieldDef.StructureId        = (ushort)index;
                    }
                }
            }

            this.Structures = structs;
        }
 private TType ExportTypeStructure <TType>(GFF.StructureDefinition def, long offset)
     where TType : class, new()
 {
     return((TType)ExportTypeStructure(def, typeof(TType), offset));
 }
예제 #8
0
        public void Deserialize(Stream input)
        {
            input.Seek(0, SeekOrigin.Begin);

            var magic = input.ReadValueU32(Endian.Big);

            if (magic != 0x47464620)
            {
                throw new FormatException();
            }

            var version = input.ReadValueU32(Endian.Big);

            if (version != 0x56342E30 && // 4.0
                version != 0x56342E31)   // 4.1
            {
                throw new FormatException("unsupported version");
            }

            this.FileVersion   = (byte)(version - 0x56342E30);
            this.FilePlatform  = input.ReadValueEnum <GFF.FilePlatform>(Endian.Big);
            this.FormatType    = input.ReadValueEnum <GFF.FormatType>(Endian.Big);
            this.FormatVersion = input.ReadValueU32(Endian.Big);

            var endian = this.FilePlatform == GFF.FilePlatform.PC ? Endian.Little : Endian.Big;

            var structCount  = input.ReadValueU32(endian);
            var stringCount  = this.FileVersion < 1 ? 0 : input.ReadValueU32(endian);
            var stringOffset = this.FileVersion < 1 ? 0 : input.ReadValueU32(endian);
            var dataOffset   = input.ReadValueU32(endian);

            if (this.FileVersion < 1)
            {
                stringOffset = dataOffset;
            }
            else
            {
                if (dataOffset < stringOffset)
                {
                    throw new FormatException();
                }
            }

            this.Structures.Clear();
            for (uint i = 0; i < structCount; i++)
            {
                var structDef = new GFF.StructureDefinition();
                //structDef.Id = input.ReadValueU32(endian);
                structDef.Id = input.ReadValueU32(Endian.Big);
                var fieldCount  = input.ReadValueU32(endian);
                var fieldOffset = input.ReadValueU32(endian);
                structDef.DataSize = input.ReadValueU32(endian);

                long nextOffset = input.Position;

                structDef.Fields.Clear();
                input.Seek(fieldOffset, SeekOrigin.Begin);
                for (uint j = 0; j < fieldCount; j++)
                {
                    var fieldDef = new GFF.FieldDefinition();
                    fieldDef.Id = input.ReadValueS32(endian);
                    var rawFlags = input.ReadValueU32(endian);
                    fieldDef.Offset = input.ReadValueU32(endian);

                    var type  = (ushort)(rawFlags & 0xFFFF);
                    var flags = (GFF.FieldFlags)((rawFlags >> 16) & 0xFFFF);

                    if ((flags & GFF.FieldFlags.IsStructure) != 0)
                    {
                        flags               &= ~GFF.FieldFlags.IsStructure;
                        fieldDef.Type        = GFF.FieldType.Structure;
                        fieldDef.StructureId = type;
                    }
                    else
                    {
                        fieldDef.Type = (GFF.FieldType)type;
                    }

                    fieldDef.Flags = flags;
                    structDef.Fields.Add(fieldDef);
                }

                this.Structures.Add(structDef);
                input.Seek(nextOffset, SeekOrigin.Begin);
            }

            if (this.FileVersion >= 1)
            {
                input.Seek(stringOffset, SeekOrigin.Begin);
                this.StringTable = new List <string>();
                for (uint i = 0; i < stringCount; i++)
                {
                    this.StringTable.Add(input.ReadStringZ(Encoding.UTF8));
                }
            }

            input.Seek(dataOffset, SeekOrigin.Begin);
            this.Data = input.ReadToMemoryStream(input.Length - dataOffset);
        }
예제 #9
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, "}}");
        }
예제 #10
0
        public void Deserialize(Stream input)
        {
            input.Seek(0, SeekOrigin.Begin);

            var magic = input.ReadValueU32(false);
            if (magic != 0x47464620)
            {
                throw new FormatException();
            }

            var version = input.ReadValueU32(false);
            if (version != 0x56342E30 && // 4.0
                version != 0x56342E31) // 4.1
            {
                throw new FormatException("unsupported version");
            }

            this.FileVersion = (byte)(version - 0x56342E30);
            this.FilePlatform = input.ReadValueEnum<GFF.FilePlatform>(false);
            this.FormatType = input.ReadValueEnum<GFF.FormatType>(false);
            this.FormatVersion = input.ReadValueU32(false);

            var littleEndian = this.FilePlatform == GFF.FilePlatform.PC;

            var structCount = input.ReadValueU32(littleEndian);
            var stringCount = this.FileVersion < 1 ? 0 : input.ReadValueU32(littleEndian);
            var stringOffset = this.FileVersion < 1 ? 0 : input.ReadValueU32(littleEndian);
            var dataOffset = input.ReadValueU32(littleEndian);

            if (this.FileVersion < 1)
            {
                stringOffset = dataOffset;
            }
            else
            {
                if (dataOffset < stringOffset)
                {
                    throw new FormatException();
                }
            }

            this.Structures.Clear();
            for (uint i = 0; i < structCount; i++)
            {
                var structDef = new GFF.StructureDefinition();
                //structDef.Id = input.ReadValueU32(littleEndian);
                structDef.Id = input.ReadValueU32(false);
                var fieldCount = input.ReadValueU32(littleEndian);
                var fieldOffset = input.ReadValueU32(littleEndian);
                structDef.DataSize = input.ReadValueU32(littleEndian);

                long nextOffset = input.Position;

                structDef.Fields.Clear();
                input.Seek(fieldOffset, SeekOrigin.Begin);
                for (uint j = 0; j < fieldCount; j++)
                {
                    var fieldDef = new GFF.FieldDefinition();
                    fieldDef.Id = input.ReadValueS32(littleEndian);
                    var rawFlags = input.ReadValueU32(littleEndian);
                    fieldDef.Offset = input.ReadValueU32(littleEndian);

                    var type = (ushort)(rawFlags & 0xFFFF);
                    var flags = (GFF.FieldFlags)((rawFlags >> 16) & 0xFFFF);

                    if ((flags & GFF.FieldFlags.IsStructure) != 0)
                    {
                        flags &= ~GFF.FieldFlags.IsStructure;
                        fieldDef.Type = GFF.FieldType.Structure;
                        fieldDef.StructureId = type;
                    }
                    else
                    {
                        fieldDef.Type = (GFF.FieldType)type;
                    }

                    fieldDef.Flags = flags;
                    structDef.Fields.Add(fieldDef);
                }

                this.Structures.Add(structDef);
                input.Seek(nextOffset, SeekOrigin.Begin);
            }

            if (this.FileVersion >= 1)
            {
                input.Seek(stringOffset, SeekOrigin.Begin);
                this.StringTable = new List<string>();
                for (uint i = 0; i < stringCount; i++)
                {
                    this.StringTable.Add(input.ReadStringZ(Encoding.UTF8));
                }
            }

            input.Seek(dataOffset, SeekOrigin.Begin);
            this.Data = input.ReadToMemoryStream(input.Length - dataOffset);
        }