static TypeDescriptor DiscoverMessageDescriptors(Mem32 mem, Dictionary <int, TypeDescriptor> table, int offset) { if (offset == 0) { return(null); } string name = mem[offset + 4].CStringPtr; int unkValue = mem[offset + 8].Int32; var fields = mem[offset + 12].Ptr; if (fields.Offset == 0) { var basicType = TypeDescriptor.AllocateBasicType(name); basicType.Name = name; basicType.UnkValue = unkValue; table.Add(offset, basicType); return(basicType); } StructureTypeDescriptor typeDesc; GameMessageInfo gmi; if (_gameMessageLookUp.TryGetValue(offset, out gmi)) { var gm = TypeDescriptor.AllocateGameMessage(name); gm.Size = gmi.Size; gm.NetworkIds = gmi.Opcodes.ToArray(); typeDesc = gm; } else { typeDesc = TypeDescriptor.AllocateStructure(name); } typeDesc.Name = name; typeDesc.UnkValue = unkValue; table.Add(offset, typeDesc); List <FieldDescriptor> list = new List <FieldDescriptor>(); for (; ;) { FieldDescriptor f = new FieldDescriptor(); f.Name = fields.CStringPtr; int type = fields[4].Int32; if (mem[type + 4].CStringPtr != "DT_NULL" && !table.TryGetValue(type, out f.Type)) { f.Type = DiscoverMessageDescriptors(mem, table, type); } f.Offset = fields[8].Int32; var defaultValuePtr = fields[12].Ptr; f.Min = fields[0x10].Int32; f.Max = fields[0x14].Int32; f.Flags = fields[0x18].Int32; type = fields[0x1C].Int32; if (mem[type + 4].CStringPtr != "DT_NULL" && !table.TryGetValue(type, out f.SubType)) { f.SubType = DiscoverMessageDescriptors(mem, table, type); } f.VariableOffset = fields[0x20].Int32; f.ArrayLength = fields[0x24].Int32; f.ArrayLengthOffset = fields[0x28].Int32; f.EncodedBits = fields[0x2C].UInt16; f.EncodedBits2 = fields[0x2E].UInt16; f.SnoType = fields[0x30].Int32; f.TagMapRelated = fields[0x34].Int32; var enumFields = fields[0x38].Ptr; if (enumFields.Offset != 0) { List <Tuple <string, int> > enums = new List <Tuple <string, int> >(); for (; ;) { if (enumFields[4].Int32 == 0) { break; } enums.Add(new Tuple <string, int>(enumFields[4].CStringPtr, enumFields.Int32)); enumFields = enumFields[8]; } f.EnumFields = enums.ToArray(); } f.FlagIndex = fields[0x3C].Int32; int funcA = fields[0x40].Int32; // TODO int funcB = fields[0x44].Int32; // TODO f.DspIndex = fields[0x48].Int32; var str = fields[0x4C].CString; // 0x4C 64 bytes, unused string //if (str != string.Empty) Console.WriteLine(str); list.Add(f); if (fields.Int32 == 0) { break; } fields = fields[140]; } typeDesc.Fields = list.ToArray(); return(typeDesc); }