public int GetSize(Meta_GTA5_pc meta, int typeKey) { switch (typeKey) { case 0x00000007: return(8); case 0x00000010: return(1); case 0x00000011: return(1); case 0x00000013: return(2); case 0x00000015: return(4); case 0x00000021: return(4); case 0x00000033: return(16); case 0x0000004A: return(4); default: return((int)GetInfo(meta, typeKey).StructureLength); } }
private void MetaInitialize() { meta = new Meta_GTA5_pc(); meta.VFT = 0x405bc808; meta.Unknown_4h = 1; meta.Unknown_10h = 0x50524430; meta.Unknown_14h = 0x0079; }
public static EnumInfo_GTA5_pc GetEnumInfo(Meta_GTA5_pc meta, int structureKey) { EnumInfo_GTA5_pc info = null; foreach (var x in meta.EnumInfos) { if (x.EnumNameHash == structureKey) { info = x; } } return(info); }
public static StructureInfo_GTA5_pc GetStructureInfo(Meta_GTA5_pc meta, int structureKey) { StructureInfo_GTA5_pc info = null; foreach (var x in meta.StructureInfos) { if (x.StructureNameHash == structureKey) { info = x; } } return(info); }
public MetaStructure(Meta_GTA5_pc meta, StructureInfo_GTA5_pc info) { this.meta = meta; this.info = info; }
public IMetaValue Parse(Meta_GTA5_pc meta) { var blockKeys = new List <int>(); var blocks = new List <List <IMetaValue> >(); ////////////////////////////////////////////////// // first step: flat conversion ////////////////////////////////////////////////// foreach (var block in meta.DataBlocks) { blockKeys.Add(block.StructureNameHash); switch (block.StructureNameHash) { case 0x00000007: blocks.Add(ReadBlock(block, () => new MetaGeneric())); // has no special type declaration in .meta -> pointer break; case 0x00000010: blocks.Add(ReadBlock(block, () => new MetaByte_A())); // char_array break; case 0x00000011: blocks.Add(ReadBlock(block, () => new MetaByte_B())); // has no special type declaration in .meta -> string break; case 0x00000013: blocks.Add(ReadBlock(block, () => new MetaInt16_B())); // probably short_array break; case 0x00000015: blocks.Add(ReadBlock(block, () => new MetaInt32_B())); // int_array break; case 0x00000021: blocks.Add(ReadBlock(block, () => new MetaFloat())); // float_array break; case 0x00000033: blocks.Add(ReadBlock(block, () => new MetaFloat4_XYZ())); // vector3_array break; case 0x0000004A: blocks.Add(ReadBlock(block, () => new MetaInt32_Hash())); // probably list of <Item>HASH_OF_SOME_NAME</Item> break; default: blocks.Add(ReadBlock(block, () => new MetaStructure(meta, GetInfo(meta, block.StructureNameHash)))); // has no special type declaration in .meta -> structure break; } } ////////////////////////////////////////////////// // second step: map references ////////////////////////////////////////////////// var referenced = new HashSet <IMetaValue>(); var stack = new Stack <IMetaValue>(); foreach (var block in blocks) { foreach (var entry in block) { stack.Push(entry); } } while (stack.Count > 0) { var entry = stack.Pop(); if (entry is MetaArray) { var arrayEntry = entry as MetaArray; var realBlockIndex = arrayEntry.BlockIndex - 1; if (realBlockIndex >= 0) { arrayEntry.Entries = new List <IMetaValue>(); var realEntryIndex = arrayEntry.Offset / GetSize(meta, blockKeys[realBlockIndex]); for (int i = 0; i < arrayEntry.NumberOfEntries; i++) { var x = blocks[realBlockIndex][realEntryIndex + i]; arrayEntry.Entries.Add(x); referenced.Add(x); } } } if (entry is MetaCharPointer) { var charPointerEntry = entry as MetaCharPointer; var realBlockIndex = charPointerEntry.DataBlockIndex - 1; if (realBlockIndex >= 0) { string value = ""; for (int i = 0; i < charPointerEntry.StringLength; i++) { var x = (MetaByte_A)blocks[realBlockIndex][i + charPointerEntry.DataOffset]; value += (char)x.Value; } charPointerEntry.Value = value; } } if (entry is MetaDataBlockPointer) { var dataPointerEntry = entry as MetaDataBlockPointer; var realBlockIndex = dataPointerEntry.BlockIndex - 1; if (realBlockIndex >= 0) { byte[] b = ToBytes(meta.DataBlocks[realBlockIndex].Data); dataPointerEntry.Data = b; } } if (entry is MetaGeneric) { var genericEntry = entry as MetaGeneric; var realBlockIndex = genericEntry.BlockIndex - 1; var realEntryIndex = genericEntry.Offset * 16 / GetSize(meta, blockKeys[realBlockIndex]); var x = blocks[realBlockIndex][realEntryIndex]; genericEntry.Value = x; referenced.Add(x); } if (entry is MetaStructure) { var structureEntry = entry as MetaStructure; foreach (var x in structureEntry.Values) { stack.Push(x.Value); } } } ////////////////////////////////////////////////// // third step: find root ////////////////////////////////////////////////// var rootSet = new HashSet <IMetaValue>(); foreach (var x in blocks) { foreach (var y in x) { if (y is MetaStructure && !referenced.Contains(y)) { rootSet.Add(y); } } } var res = rootSet.First(); if (res != blocks[(int)meta.RootBlockIndex - 1][0]) { throw new System.Exception("wrong root block index"); } return(res); }