Beispiel #1
0
        public SDKClassInfo(IntPtr address, RemoteProcess remoteProcess, PEImageBuffer peImageBuffer)
        {
            ClassInfo     typeInfo     = remoteProcess.Read <ClassInfo>(address);
            ClassInfoData typeInfoData = remoteProcess.Read <ClassInfoData>(typeInfo.m_InfoData);

            Name         = $"{remoteProcess.ReadString(typeInfoData.m_Name, 255)}";
            ThisTypeInfo = address;
            Type         = typeInfoData.GetNewEntryType();
            Flags        = typeInfoData.m_Flags;
            Alignment    = typeInfoData.m_Alignment;
            TotalSize    = typeInfoData.m_TotalSize;
            FieldCount   = typeInfoData.m_FieldCount;
            ParentClass  = typeInfoData.m_SuperClass;
            var superClassInfo = new SDKTypeInfo(ParentClass, remoteProcess);

            ParentClassName = $"{superClassInfo.Name}";

            // debug
            if (Name == "PoseTrackKeyframe")
            {
                Name = Name;
            }
            // end debug

            // fill fields list
            if (FieldCount == 0)
            {
                if ((ParentClass != IntPtr.Zero) && (TotalSize > superClassInfo.TotalSize))
                {
                    SDKFieldEntry fieldEntry;

                    fieldEntry.fieldType         = "char";
                    fieldEntry.fieldInternalType = "Uint8";
                    fieldEntry.fieldBasicType    = BasicTypesEnum.kTypeCode_Uint8;
                    fieldEntry.fieldName         = $"_0x{superClassInfo.TotalSize.ToString("X4")}[{TotalSize - superClassInfo.TotalSize}]";
                    fieldEntry.fieldOffset       = superClassInfo.TotalSize;
                    fieldEntry.fieldSize         = TotalSize - superClassInfo.TotalSize;
                    fieldEntry.lastFieldOffset   = 0;
                    fieldEntry.lastFieldSize     = 0;

                    Fields.Add(fieldEntry);

                    FieldCount++;
                }
                else if ((ParentClass == IntPtr.Zero) || (Name == ParentClassName))
                {
                    // reference oddity for (Name == ParentClassName) fb::IglooSubsystem : has itself as parent, 0 fields
                    SDKFieldEntry fieldEntry;

                    fieldEntry.fieldType         = "char";
                    fieldEntry.fieldInternalType = "Uint8";
                    fieldEntry.fieldBasicType    = BasicTypesEnum.kTypeCode_Uint8;
                    fieldEntry.fieldName         = $"_0x000[{TotalSize}]";
                    fieldEntry.fieldOffset       = 0;
                    fieldEntry.fieldSize         = TotalSize;
                    fieldEntry.lastFieldOffset   = 0;
                    fieldEntry.lastFieldSize     = 0;

                    Fields.Add(fieldEntry);

                    FieldCount++;
                }
            }
            else //if (FieldCount > 0)
            {
                for (int i = 0; i < FieldCount; i++)
                {
                    var fieldInfoData = remoteProcess.Read <FieldInfoData>((IntPtr)((Int64)typeInfoData.m_Fields + (i * 0x18)));

                    SDKFieldEntry fieldEntry;
                    var           fieldTypeInfo = new SDKTypeInfo(fieldInfoData.m_FieldTypePtr, remoteProcess);

                    // fix the odd field type with flags as 0x0000 or 0x2000
                    if ((fieldInfoData.m_Flags == 0) || (fieldInfoData.m_Flags == 0x2000))
                    {
                        fieldEntry.fieldType = fieldTypeInfo.FixTypeName(fieldTypeInfo.Name);
                    }
                    else
                    {
                        fieldEntry.fieldType = fieldTypeInfo.GetCppType(); //fieldTypeInfo.Name;
                    }
                    fieldEntry.fieldInternalType = fieldTypeInfo.Name;
                    fieldEntry.fieldBasicType    = fieldTypeInfo.Type;//fieldInfoData.GetEntryType();

                    fieldEntry.fieldName       = remoteProcess.ReadString(fieldInfoData.m_Name, 255);
                    fieldEntry.fieldOffset     = fieldInfoData.m_FieldOffset;
                    fieldEntry.fieldSize       = fieldTypeInfo.TotalSize;
                    fieldEntry.lastFieldOffset = lastFieldOffset;
                    fieldEntry.lastFieldSize   = lastFieldSize;

                    // fix error with some bools being flagged as int16_t
                    if ((fieldEntry.fieldType == "int16_t") && (fieldEntry.fieldSize == 1))
                    {
                        fieldEntry.fieldType         = "bool";
                        fieldEntry.fieldInternalType = "Boolean";
                        fieldEntry.fieldBasicType    = BasicTypesEnum.kTypeCode_Boolean;
                    }


                    Fields.Add(fieldEntry);

                    lastFieldOffset = fieldEntry.fieldOffset;
                    lastFieldSize   = fieldTypeInfo.TotalSize;
                }

                // the field array isn't sorted in offset order so fix that
                Fields = Fields.OrderBy(x => x.fieldOffset).ToList();

                // check if pads needed
                for (int i = 1; i < FieldCount; i++)
                {
                    lastFieldOffset = Fields.ElementAt(i - 1).fieldOffset;
                    lastFieldSize   = Fields.ElementAt(i - 1).fieldSize;

                    SDKFieldEntry fieldEntry;
                    fieldEntry = Fields.ElementAt(i);

                    fieldEntry.lastFieldOffset = lastFieldOffset;
                    fieldEntry.lastFieldSize   = lastFieldSize;

                    Fields[i] = fieldEntry;
                }

                for (int i = 0; i < FieldCount; i++)
                {
                    SDKFieldEntry fieldEntry;

                    if (i == (FieldCount - 1))
                    {
                        // last class member so check against total size
                        if (TotalSize > (Fields.ElementAt(i).fieldOffset + Fields.ElementAt(i).fieldSize))
                        {
                            fieldEntry.fieldType         = "char";
                            fieldEntry.fieldInternalType = "Uint8";
                            fieldEntry.fieldBasicType    = BasicTypesEnum.kTypeCode_Uint8;
                            fieldEntry.fieldName         = $"_0x{(Fields.ElementAt(i).fieldOffset + Fields.ElementAt(i).fieldSize).ToString("X4")}[{TotalSize - (Fields.ElementAt(i).fieldOffset + Fields.ElementAt(i).fieldSize)}]";
                            fieldEntry.fieldOffset       = Fields.ElementAt(i).fieldOffset + Fields.ElementAt(i).fieldSize;
                            fieldEntry.fieldSize         = TotalSize - (Fields.ElementAt(i).fieldOffset + Fields.ElementAt(i).fieldSize);
                            fieldEntry.lastFieldOffset   = Fields.ElementAt(i).fieldOffset;
                            fieldEntry.lastFieldSize     = Fields.ElementAt(i).fieldSize;

                            Fields.Add(fieldEntry);

                            FieldCount++;
                        }
                    }

                    if ((i == 0) && (ParentClass != IntPtr.Zero))
                    {
                        // first class member so check against parent size
                        if (superClassInfo.TotalSize < Fields.ElementAt(i).fieldOffset)
                        {
                            var debug = Fields.ElementAt(i).fieldOffset;
                            fieldEntry.fieldType         = "char";
                            fieldEntry.fieldInternalType = "Uint8";
                            fieldEntry.fieldBasicType    = BasicTypesEnum.kTypeCode_Uint8;
                            fieldEntry.fieldName         = $"_0x{superClassInfo.TotalSize.ToString("X4")}[{Fields.ElementAt(i).fieldOffset - superClassInfo.TotalSize}]";
                            fieldEntry.fieldOffset       = superClassInfo.TotalSize;
                            fieldEntry.fieldSize         = Fields.ElementAt(i).fieldOffset - superClassInfo.TotalSize;
                            fieldEntry.lastFieldOffset   = 0; // superClassInfo.TotalSize;
                            fieldEntry.lastFieldSize     = superClassInfo.TotalSize;

                            Fields.Insert(0, fieldEntry);

                            i++;
                            FieldCount++;
                        }
                    }
                    else
                    {
                        // inter-field pads. seems to be correct now :)
                        if (Fields.ElementAt(i).fieldOffset > (Fields.ElementAt(i).lastFieldOffset + Fields.ElementAt(i).lastFieldSize))
                        {
                            fieldEntry.fieldType         = "char";
                            fieldEntry.fieldInternalType = "Uint8";
                            fieldEntry.fieldBasicType    = BasicTypesEnum.kTypeCode_Uint8;
                            fieldEntry.fieldName         = $"_0x{(Fields.ElementAt(i).lastFieldOffset + Fields.ElementAt(i).lastFieldSize).ToString("X4")}[{Fields.ElementAt(i).fieldOffset - (Fields.ElementAt(i).lastFieldOffset + Fields.ElementAt(i).lastFieldSize)}]";
                            fieldEntry.fieldOffset       = Fields.ElementAt(i).lastFieldOffset + Fields.ElementAt(i).lastFieldSize;
                            fieldEntry.fieldSize         = Fields.ElementAt(i).fieldOffset - (Fields.ElementAt(i).lastFieldOffset + Fields.ElementAt(i).lastFieldSize);
                            fieldEntry.lastFieldOffset   = Fields.ElementAt(i).fieldOffset;
                            fieldEntry.lastFieldSize     = Fields.ElementAt(i).fieldSize;

                            Fields.Insert(i, fieldEntry);

                            i++;
                            FieldCount++;
                        }
                    }
                }
            }

            RuntimeId       = typeInfo.m_RuntimeId;
            Next            = typeInfo.m_Next;
            DefaultInstance = typeInfo.m_DefaultInstance;
            ClassId         = typeInfo.m_ClassId;
            GetVtable(remoteProcess, peImageBuffer);
        }
Beispiel #2
0
        static void Main(string[] args)
        {
            RemoteProcess remoteProcess = new RemoteProcess("starwarsbattlefrontii");

            List <SDKEnumFieldInfo> enumList   = new List <SDKEnumFieldInfo>();
            List <SDKValueTypeInfo> structList = new List <SDKValueTypeInfo>();
            List <SDKClassInfo>     classList  = new List <SDKClassInfo>();

            //bool forIDA = false;    // set true to adjust output for IDA import (Array<> becomes pointer to type)

            remoteProcess.OpenProcessMemory();

            var peImageBuffer = new PEImageBuffer(remoteProcess);

            var firstTypeInfoPtr = peImageBuffer.FindOffset("48 8B 05 ? ? ? ? 48 89 41 08 48 89 0D ? ? ? ?");
            var firstTypeInfo    = remoteProcess.Read <IntPtr>((IntPtr)firstTypeInfoPtr);

            Console.WriteLine($"Image Base : 0x{remoteProcess.ImageBase.ToString("X9")}");
            Console.WriteLine($"Image Size : 0x{remoteProcess.ImageSize.ToString("X9")}");
            Console.WriteLine("");
            Console.WriteLine($"OFFSET_FirstTypeInfo : 0x{firstTypeInfoPtr.ToString("X9")}");

            var next = firstTypeInfo;

            Console.WriteLine("Processing...");
            var count = 1;

            // testing in reclass
            var classcount  = 1;
            var structcount = 1;
            var enumcount   = 1;

            var tasks      = new List <Task>();
            var tasksCount = 0;
            var thisNext   = next;

            while (remoteProcess.IsValidImagePtr(next))
            {
                var typeInfo = new SDKTypeInfo(next, remoteProcess);

                var type = typeInfo.Type;
                if (typeInfo.Name.Contains('('))
                {
                    // some functions apparently defined, skip for now investigate later
                    type = BasicTypesEnum.kTypeCode_Void;
                }
                if ((typeInfo.Name.Contains("Float32")) || (typeInfo.Name.Contains("char")))
                {
                    // uneeded class
                    type = BasicTypesEnum.kTypeCode_Void;
                }

                switch (type)
                {
                case BasicTypesEnum.kTypeCode_Enum:
                {
                    enumList.Add(new SDKEnumFieldInfo(next, remoteProcess));
                    ++enumcount;
                }
                break;

                case BasicTypesEnum.kTypeCode_ValueType:
                {
                    structList.Add(new SDKValueTypeInfo(next, remoteProcess));
                    ++structcount;
                }
                break;

                case BasicTypesEnum.kTypeCode_Class:
                {
                    classList.Add(new SDKClassInfo(next, remoteProcess, peImageBuffer));


                    //if (tasksCount == Environment.ProcessorCount)
                    //{
                    //    Task.WaitAll(tasks.ToArray());
                    //    tasksCount = 0;
                    //}

                    //// experimental multitasking of the classes to speed up finding vtables
                    //thisNext = next;

                    //tasks.Add(
                    //    Task.Run(() =>
                    //    {
                    //        var cInfo = new SDKClassInfo(thisNext, remoteProcess, peImageBuffer);
                    //        classList.Add(cInfo);
                    //    }
                    //    ));

                    //++tasksCount;

                    ++classcount;
                }
                break;

                case BasicTypesEnum.kTypeCode_BasicTypeCount:
                {
                    Console.WriteLine($"{typeInfo.Name}");
                }
                break;

                default:
                    break;
                }

                next = typeInfo.Next;

                ++count;
            }

            Task.WaitAll(tasks.ToArray());

            ProcessHeaders.CreateHeaders(ref enumList, ref structList, ref classList);

//            var enumLines = new List<string>();

//            if (!forIDA)
//            {
//                enumLines.Add("#pragma once");
//                enumLines.Add("");
//                enumLines.Add("namespace fb");
//                enumLines.Add("{");
//            }

//            foreach (SDKEnumFieldInfo enumInfo in enumList)
//            {
//                enumLines.Add("////////////////////////////////////////");
//                enumLines.Add($"// Runtime Id : {enumInfo.RuntimeId}");
//                enumLines.Add($"// TypeInfo : 0x{enumInfo.ThisTypeInfo.ToString("X9")}");

//                enumLines.Add($"enum {enumInfo.Name}");

//                enumLines.Add("{");

//                for (int i = 0; i < enumInfo.FieldCount; i++)
//                {
//                    string end = ",";
//                    if (i == enumInfo.FieldCount - 1)
//                    {
//                        end = "";
//                    }

//                    // fix some small issues related to having all the enums in the same file
//                    var fieldName = enumInfo.Fields.ElementAt(i).fieldName;
//                    if ((enumInfo.Name == "CutsceneActorType") || (enumInfo.Name == "DSJetpackMovementMode") || (enumInfo.Name == "AIPathLinkDirection"))
//                    {
//                        fieldName = $"{fieldName}_";
//                    }

//                    enumLines.Add($"    {fieldName}{end} //0x{i.ToString("X4")}");
//                }

//                enumLines.Add("};");
//                enumLines.Add("");
//            }

//            if (!forIDA)
//            {
//                enumLines.Add("}");
//            }

//            // sort structs for dependencies
//            int infoCount = 0;
//            while (infoCount < structList.Count)
//            {
//                var item = structList.ElementAt(infoCount);

//                foreach (SDKFieldEntry field in item.Fields)
//                {
//                    var fieldIndex = 0;
//                    var fieldTypeName = field.fieldType;

//                    if (fieldTypeName.Contains("-Array"))
//                    {
//                        fieldTypeName = field.fieldType.Substring(0, field.fieldType.Length - 6);
//                    }

//                    if ((field.fieldBasicType == BasicTypesEnum.kTypeCode_ValueType)
//                        || (field.fieldBasicType == BasicTypesEnum.kTypeCode_Array))
//                    {
//                        foreach (SDKValueTypeInfo fieldInfo in structList)
//                        {
//                            if (fieldInfo.Name == fieldTypeName)
//                            {
//                                fieldIndex = structList.IndexOf(fieldInfo);
//                            }
//                        }

//                        if (fieldIndex != 0)
//                        {
//                            var itemIndex = structList.IndexOf(item);

//                            // if we find the field item lower than the owning type, drop the owning type below it
//                            if (fieldIndex > itemIndex)
//                            {
//                                var tempInfo = structList.ElementAt(itemIndex);
//                                structList.RemoveAt(itemIndex);
//                                structList.Insert(fieldIndex, tempInfo);

//                                // start the list again
//                                infoCount = 0;
//                                break;
//                            }
//                        }
//                    }
//                }

//                ++infoCount;
//            }

//            var structLines = new List<string>();

//            if (!forIDA)
//            {
//                structLines.Add("#pragma once");
//                structLines.Add("");
//                structLines.Add("namespace fb");
//                structLines.Add("{");
//            }

//            foreach (SDKValueTypeInfo structInfo in structList)
//            {
//                structLines.Add("////////////////////////////////////////");
//                structLines.Add($"// Runtime Id : {structInfo.RuntimeId}");
//                structLines.Add($"// TypeInfo : 0x{structInfo.ThisTypeInfo.ToString("X9")}");

//                structLines.Add($"struct {structInfo.Name}");

//                structLines.Add("{");

//                for (int i = 0; i < structInfo.FieldCount; i++)
//                {
//                    var fieldType = structInfo.Fields.ElementAt(i).fieldType;
//                    var postfix = "";

//                    if (fieldType.Contains("-Array"))
//                    {
//                        fieldType = fieldType.Substring(0, fieldType.Length - 6);
//                    }

//                    fieldType = FixTypeName(fieldType);

//                    if ((structInfo.Fields.ElementAt(i).fieldBasicType == BasicTypesEnum.kTypeCode_Class) && (fieldType != "float"))
//                    {
//                        postfix = "*";
//                    }

//                    if (structInfo.Fields.ElementAt(i).fieldBasicType == BasicTypesEnum.kTypeCode_Array)
//                    {
//                        if (forIDA)
//                        {
//                            postfix = "*";
//                        }
//                        else
//                        {
//                            fieldType = $"Array<{fieldType}>";
//                        }
//                    }

//                    structLines.Add($"    {fieldType}{postfix} {structInfo.Fields.ElementAt(i).fieldName}; //0x{structInfo.Fields.ElementAt(i).fieldOffset.ToString("X4")}");
//                }

//                structLines.Add("};");
//                structLines.Add("");
//            }

//            if (!forIDA)
//            {
//                structLines.Add("}");
//            }

//            // sort by classid
//            classList = classList.OrderBy(x => x.ClassId).ToList();

//            var nameLines = new List<string>
//            {
//                "from idautils import *",
//                "from idc import *",
//                "from idaapi import *",
//                "",
//                "def MakeNames():",
//                "    startEa = SegByBase(SegByName(\"HEADER\"))",
//                "    imageend = 0",
//                "",
//                "    for ea in Segments():",
//                "        imageend = SegEnd(ea)",
//                ""
//            };
//            var classLines = new List<string>();

//            if (!forIDA)
//            {
//                classLines.Add("#pragma once");
//                classLines.Add("");
//                classLines.Add("namespace fb");
//                classLines.Add("{");
//            }

//            var declarationLines = new List<string>();

//            if (!forIDA)
//            {
//                declarationLines.Add("#pragma once");
//                declarationLines.Add("");
//                declarationLines.Add("namespace fb");
//                declarationLines.Add("{");
//            }

//            foreach (SDKClassInfo classInfo in classList)
//            {
//                classLines.Add("////////////////////////////////////////");
//                classLines.Add($"// Class Id : {classInfo.ClassId}");
//                classLines.Add($"// Runtime Id : {classInfo.RuntimeId}");
//                classLines.Add($"// TypeInfo : 0x{classInfo.ThisTypeInfo.ToString("X9")}");
//                classLines.Add($"// Default Instance : 0x{classInfo.DefaultInstance.ToString("X9")}");
//                classLines.Add($"// Vtable : 0x{classInfo.VTable.ToString("X9")}");

//                classLines.Add($"#ifndef _{classInfo.Name}_");
//                classLines.Add($"#define _{classInfo.Name}_");

//                if ((classInfo.ParentClassName != classInfo.Name) && (classInfo.ParentClassName != ""))
//                {
//                    classLines.Add($"class {classInfo.Name} : {classInfo.ParentClassName}");
//                }
//                else
//                {
//                    classLines.Add($"class {classInfo.Name}");
//                }

//                classLines.Add("{");

//                if (classInfo.FieldCount > 0)
//                {
//                    classLines.Add("public:");
//                }

//                for (int i = 0; i < classInfo.FieldCount; i++)
//                {
//                    var fieldType = classInfo.Fields.ElementAt(i).fieldType;
//                    var postfix = "";

//                    if (fieldType.Contains("-Array"))
//                    {
//                        fieldType = fieldType.Substring(0, fieldType.Length - 6);
//                    }

//                    fieldType = FixTypeName(fieldType);

//                    if ((classInfo.Fields.ElementAt(i).fieldBasicType == BasicTypesEnum.kTypeCode_Class) && (fieldType != "float"))
//                    {
//                        postfix = "*";
//                    }

//                    if (classInfo.Fields.ElementAt(i).fieldBasicType == BasicTypesEnum.kTypeCode_Array)
//                    {
//                        if (forIDA)
//                        {
//                            postfix = "*";
//                        }
//                        else
//                        {
//                            fieldType = $"Array<{fieldType}>";
//                        }
//                    }

//                    classLines.Add($"    {fieldType}{postfix} {classInfo.Fields.ElementAt(i).fieldName}; //0x{classInfo.Fields.ElementAt(i).fieldOffset.ToString("X4")}");
//                }

//                classLines.Add("};");
//                classLines.Add($"//0x{classInfo.TotalSize.ToString("X4")}");

//                classLines.Add($"#endif");

//                classLines.Add("");

//                declarationLines.Add($"class {classInfo.Name};");

//                // idapython stuff
//                /*
//                 * Python>MakeNames()
//14356C140: can't rename byte as 'PlayerAbilityWeaponInfoEntityData_vtbl' because this byte can't have a name (it is a tail byte).
//14356C178: can't rename byte as 'PlayerAbilityWeaponUpgradeInfoEntityData_vtbl' because this byte can't have a name (it is a tail byte).
//1413481DC: can't rename byte as 'ClientWheelComponent_vtbl' because this byte can't have a name (it is a tail byte).
//141948644: can't rename byte as 'ServerVehicleHealthComponent_vtbl' because this byte can't have a name (it is a tail byte).
//                 */
//                if (classInfo.GetTypeFunction != IntPtr.Zero)
//                {
//                    nameLines.Add($"    MakeName(0x{classInfo.GetTypeFunction.ToString("X9")}, \"{classInfo.Name}_GetType\")");
//                }

//                if (classInfo.VTable != IntPtr.Zero)
//                {
//                    nameLines.Add($"    MakeName(0x{classInfo.VTable.ToString("X9")}, \"{classInfo.Name}_vtbl\")");
//                }
//            }

//            if (!forIDA)
//            {
//                classLines.Add("}");
//            }

//            if (!forIDA)
//            {
//                declarationLines.Add("}");
//            }

//            System.IO.File.WriteAllLines(@".\Enums.h", enumLines);
//            System.IO.File.WriteAllLines(@".\Structs.h", structLines);
//            System.IO.File.WriteAllLines(@".\Declarations.h", declarationLines);
//            System.IO.File.WriteAllLines(@".\Classes.h", classLines);
//            System.IO.File.WriteAllLines(@".\MakeNames.py", nameLines);

//            // c++ import header
//            var cppImportLines = new List<string>
//            {
//                "#pragma once",
//                "",
//                "namespace fb {",
//                "    struct Guid",
//                "    {",
//                "        unsigned long	m_Data1;	//0x0000",
//                "        unsigned short	m_Data2;	//0x0004",
//                "        unsigned short	m_Data3;	//0x0006",
//                "        unsigned char	m_Data4[8];	//0x0008",
//                "    };",
//                "    //Size=0x0010",
//                "",
//                "    typedef __m128 BoxedValueRef;",
//                "    typedef uint64_t ResourceRef;",
//                "    typedef uint64_t TypeRef;",
//                "    typedef uint64_t FileRef;",
//                "",
//                "    typedef struct",
//                "    {",
//                "     char pad[0x14];",
//                "    } SHA1;",
//                "    //Size=0x0014",
//                "",
//                "    template <typename T>",
//                "    class Array",
//                "    {",
//                "    private:",
//                "      T* m_firstElement;",
//                "",
//                "    public:",
//                "        T At(INT nIndex)",
//                "        {",
//                "            if (m_firstElement == NULL)",
//                "                return *(T*)((UINT64)NULL);",
//                "",
//                "            return *(T*)((UINT64)m_firstElement + (nIndex * sizeof(T)));",
//                "         };",
//                "",
//                "         T operator [](INT index) { return At(index); }",
//                "    };",
//                "",
//                "    #include \"Declarations.h\"",
//                "    #include \"Enums.h\"",
//                "    #include \"Structs.h\"",
//                "    #include \"Classes.h\"",
//                "",
//            };

//            // IDA import header
//            var idaImportLines = new List<string>
//            {
//                "from idautils import *",
//                "from idc import *",
//                "from idaapi import *",
//                "",
//                "def MakeNames():",
//                "    startEa = SegByBase(SegByName(\"HEADER\"))",
//                "    imageend = 0",
//                "",
//                "    for ea in Segments():",
//                "        imageend = SegEnd(ea)",
//                ""
//            };

            Console.WriteLine($"Found {count} TypeInfo entries.");
            Console.WriteLine($"Found {classcount} ClassInfo entries.");
            Console.WriteLine($"Found {structcount} ValueTypeInfo entries.");
            Console.WriteLine($"Found {enumcount} EnumFieldInfo entries.");

            Console.WriteLine("Done. Press a key to quit.");

            remoteProcess.CloseProcessMemory();

            Console.ReadLine();
        }
        public SDKValueTypeInfo(IntPtr address, RemoteProcess remoteProcess)
        {
            ValueTypeInfo     typeInfo     = remoteProcess.Read <ValueTypeInfo>(address);
            ValueTypeInfoData typeInfoData = remoteProcess.Read <ValueTypeInfoData>(typeInfo.m_InfoData);

            Name         = $"{remoteProcess.ReadString(typeInfoData.m_Name, 255)}";
            ThisTypeInfo = address;
            Type         = typeInfoData.GetNewEntryType();
            Flags        = typeInfoData.m_Flags;
            Alignment    = typeInfoData.m_Alignment;
            TotalSize    = typeInfoData.m_TotalSize;
            FieldCount   = typeInfoData.m_FieldCount;
            RuntimeId    = typeInfo.m_RuntimeId;
            Next         = typeInfo.m_Next;

            // fill fields list
            if (FieldCount == 0)
            {
                SDKFieldEntry fieldEntry;

                fieldEntry.fieldType         = "char";
                fieldEntry.fieldInternalType = "Uint8";
                fieldEntry.fieldBasicType    = BasicTypesEnum.kTypeCode_Uint8;
                fieldEntry.fieldName         = $"_0x000[{TotalSize}]";
                fieldEntry.fieldOffset       = 0;
                fieldEntry.fieldSize         = TotalSize;
                fieldEntry.lastFieldOffset   = 0;
                fieldEntry.lastFieldSize     = 0;

                Fields.Add(fieldEntry);

                FieldCount++;
            }
            else
            {
                for (int i = 0; i < FieldCount; i++)
                {
                    var fieldInfoData = remoteProcess.Read <FieldInfoData>((IntPtr)((Int64)typeInfoData.m_Fields + (i * 0x18)));

                    SDKFieldEntry fieldEntry;
                    var           fieldTypeInfo = new SDKTypeInfo(fieldInfoData.m_FieldTypePtr, remoteProcess);

                    // fix the odd field type with flags as 0x0000 or 0x2000
                    if ((fieldInfoData.m_Flags == 0) || (fieldInfoData.m_Flags == 0x2000))
                    {
                        fieldEntry.fieldType = fieldTypeInfo.FixTypeName(fieldTypeInfo.Name);
                    }
                    else
                    {
                        fieldEntry.fieldType = fieldTypeInfo.GetCppType(); //fieldTypeInfo.Name;
                    }

                    fieldEntry.fieldInternalType = fieldTypeInfo.Name;
                    fieldEntry.fieldBasicType    = fieldTypeInfo.Type;//fieldInfoData.GetEntryType();

                    fieldEntry.fieldName       = remoteProcess.ReadString(fieldInfoData.m_Name, 255);
                    fieldEntry.fieldOffset     = fieldInfoData.m_FieldOffset;
                    fieldEntry.fieldSize       = fieldTypeInfo.TotalSize;
                    fieldEntry.lastFieldOffset = lastFieldOffset;
                    fieldEntry.lastFieldSize   = lastFieldSize;

                    // fix error with some bools being flagged as int16_t
                    if ((fieldEntry.fieldType == "int16_t") && (fieldEntry.fieldSize == 1))
                    {
                        fieldEntry.fieldType = "bool";
                    }


                    Fields.Add(fieldEntry);

                    lastFieldOffset = fieldEntry.fieldOffset;
                    lastFieldSize   = fieldTypeInfo.TotalSize;
                }

                // the field array isn't always sorted in offset order so fix that
                Fields = Fields.OrderBy(x => x.fieldOffset).ToList();

                // check if pads needed
                for (int i = 1; i < FieldCount; i++)
                {
                    lastFieldOffset = Fields.ElementAt(i - 1).fieldOffset;
                    lastFieldSize   = Fields.ElementAt(i - 1).fieldSize;

                    SDKFieldEntry fieldEntry;
                    fieldEntry = Fields.ElementAt(i);

                    fieldEntry.lastFieldOffset = lastFieldOffset;
                    fieldEntry.lastFieldSize   = lastFieldSize;

                    Fields[i] = fieldEntry;
                }

                for (int i = 0; i < FieldCount; i++)
                {
                    SDKFieldEntry fieldEntry;

                    if (i == (FieldCount - 1))
                    {
                        // last class member so check against total size
                        if (TotalSize > (Fields.ElementAt(i).fieldOffset + Fields.ElementAt(i).fieldSize))
                        {
                            fieldEntry.fieldType         = "char";
                            fieldEntry.fieldInternalType = "Uint8";
                            fieldEntry.fieldBasicType    = BasicTypesEnum.kTypeCode_Uint8;
                            fieldEntry.fieldName         = $"_0x{(Fields.ElementAt(i).fieldOffset + Fields.ElementAt(i).fieldSize).ToString("X4")}[{TotalSize - (Fields.ElementAt(i).fieldOffset + Fields.ElementAt(i).fieldSize)}]";
                            fieldEntry.fieldOffset       = Fields.ElementAt(i).fieldOffset + Fields.ElementAt(i).fieldSize;
                            fieldEntry.fieldSize         = TotalSize - (Fields.ElementAt(i).fieldOffset + Fields.ElementAt(i).fieldSize);
                            fieldEntry.lastFieldOffset   = Fields.ElementAt(i).fieldOffset;
                            fieldEntry.lastFieldSize     = Fields.ElementAt(i).fieldSize;

                            Fields.Add(fieldEntry);

                            FieldCount++;
                        }
                    }
                    else
                    {
                        // inter-field pads. seems to be correct now :)
                        if (Fields.ElementAt(i).fieldOffset > (Fields.ElementAt(i).lastFieldOffset + Fields.ElementAt(i).lastFieldSize))
                        {
                            fieldEntry.fieldType         = "char";
                            fieldEntry.fieldInternalType = "Uint8";
                            fieldEntry.fieldBasicType    = BasicTypesEnum.kTypeCode_Uint8;
                            fieldEntry.fieldName         = $"_0x{(Fields.ElementAt(i).lastFieldOffset + Fields.ElementAt(i).lastFieldSize).ToString("X4")}[{Fields.ElementAt(i).fieldOffset - (Fields.ElementAt(i).lastFieldOffset + Fields.ElementAt(i).lastFieldSize)}]";
                            fieldEntry.fieldOffset       = Fields.ElementAt(i).lastFieldOffset + Fields.ElementAt(i).lastFieldSize;
                            fieldEntry.fieldSize         = Fields.ElementAt(i).fieldOffset - (Fields.ElementAt(i).lastFieldOffset + Fields.ElementAt(i).lastFieldSize);
                            fieldEntry.lastFieldOffset   = Fields.ElementAt(i).fieldOffset;
                            fieldEntry.lastFieldSize     = Fields.ElementAt(i).fieldSize;

                            Fields.Insert(i, fieldEntry);

                            i++;
                            FieldCount++;
                        }
                    }
                }
            }
        }