public PsoFile Build(IPsoValue value) { MetaInitialize(); MetaBuildStructuresAndEnums(); var writer = new MetaDataWriter(Data.Endianess.BigEndian); writer.SelectBlockByNameHash(((PsoStructure)value).psoEntryInfo.NameHash); WriteStructure(writer, (PsoStructure)value); meta.DataMappingSection.Entries = new List <PsoDataMappingEntry>(); var ms = new MemoryStream(); ms.Position = 16; foreach (var block in writer.Blocks) { var metaDataBlock = new PsoDataMappingEntry(); metaDataBlock.NameHash = block.NameHash; metaDataBlock.Offset = (int)ms.Position; metaDataBlock.Length = (int)block.Stream.Length; var buf = new byte[block.Stream.Length]; block.Stream.Position = 0; block.Stream.Read(buf, 0, buf.Length); ms.Write(buf, 0, buf.Length); // fill... buf = new byte[16 - ms.Position % 16]; if (buf.Length != 16) { ms.Write(buf, 0, buf.Length); } meta.DataMappingSection.Entries.Add(metaDataBlock); } var totalBuf = new byte[ms.Length]; ms.Position = 0; ms.Read(totalBuf, 0, totalBuf.Length); meta.DataSection.Data = totalBuf; for (int i = 0; i < meta.DataMappingSection.Entries.Count; i++) { if (meta.DataMappingSection.Entries[i].NameHash == ((PsoStructure)value).psoEntryInfo.NameHash) { meta.DataMappingSection.RootIndex = i + 1; } } return(meta); }
public Meta_GTA5_pc Build(IMetaValue value) { MetaInitialize(); MetaBuildStructuresAndEnums(); var writer = new MetaDataWriter(); writer.SelectBlockByNameHash(((MetaStructure)value).info.StructureNameHash); WriteStructure(writer, (MetaStructure)value); for (int k = meta.StructureInfos.Count - 1; k >= 0; k--) { if (!usedStructureKeys.Contains(meta.StructureInfos[k].StructureKey)) { meta.StructureInfos.RemoveAt(k); } } meta.DataBlocks = new ResourceSimpleArray <DataBlock_GTA5_pc>(); foreach (var block in writer.Blocks) { var metaDataBlock = new DataBlock_GTA5_pc(); metaDataBlock.StructureNameHash = block.NameHash; metaDataBlock.Data = StreamToResourceBytes(block.Stream); meta.DataBlocks.Add(metaDataBlock); } for (int i = 0; i < meta.DataBlocks.Count; i++) { if (meta.DataBlocks[i].StructureNameHash == ((MetaStructure)value).info.StructureNameHash) { meta.RootBlockIndex = i + 1; } } return(meta); }
private void WriteStructure(MetaDataWriter writer, MetaStructure value) { var updateStack = new Stack <IMetaValue>(); // build stack for update... var structuresToCheck = new Stack <MetaStructure>(); structuresToCheck.Push(value); while (structuresToCheck.Count > 0) { var structureToCheck = structuresToCheck.Pop(); // add structure to list of occurring structures usedStructureKeys.Add(structureToCheck.info.StructureKey); foreach (var structureEntryToCheck in structureToCheck.Values) { if (structureEntryToCheck.Value is MetaArray) { updateStack.Push(structureEntryToCheck.Value); var arrayStructureEntryToCheck = structureEntryToCheck.Value as MetaArray; if (arrayStructureEntryToCheck.Entries != null) { for (int k = arrayStructureEntryToCheck.Entries.Count - 1; k >= 0; k--) { var x = arrayStructureEntryToCheck.Entries[k]; if (x is MetaStructure) { structuresToCheck.Push(x as MetaStructure); } if (x is MetaGeneric) { updateStack.Push(x); structuresToCheck.Push((MetaStructure)(x as MetaGeneric).Value); } } } } if (structureEntryToCheck.Value is MetaCharPointer) { updateStack.Push(structureEntryToCheck.Value); } if (structureEntryToCheck.Value is MetaDataBlockPointer) { updateStack.Push(structureEntryToCheck.Value); } if (structureEntryToCheck.Value is MetaGeneric) { updateStack.Push(structureEntryToCheck.Value); var genericStructureEntryToCheck = structureEntryToCheck.Value as MetaGeneric; structuresToCheck.Push((MetaStructure)genericStructureEntryToCheck.Value); } if (structureEntryToCheck.Value is MetaStructure) { structuresToCheck.Push((MetaStructure)structureEntryToCheck.Value); } } } // update structures... while (updateStack.Count > 0) { var v = updateStack.Pop(); if (v is MetaArray) { var arrayValue = (MetaArray)v; if (arrayValue.Entries != null) { if (arrayValue.info.DataType == StructureEntryDataType.Structure) { // WORKAROUND if (arrayValue.IsAlwaysAtZeroOffset) { writer.CreateBlockByNameHash(arrayValue.info.ReferenceKey); writer.Position = writer.Length; } else { writer.SelectBlockByNameHash(arrayValue.info.ReferenceKey); writer.Position = writer.Length; } } else { writer.SelectBlockByNameHash((int)arrayValue.info.DataType); writer.Position = writer.Length; } arrayValue.BlockIndex = writer.BlockIndex + 1; arrayValue.Offset = (int)writer.Position; arrayValue.NumberOfEntries = arrayValue.Entries.Count; foreach (var entry in arrayValue.Entries) { entry.Write(writer); } } else { arrayValue.BlockIndex = 0; arrayValue.Offset = 0; arrayValue.NumberOfEntries = 0; } } if (v is MetaCharPointer) { var charPointerValue = (MetaCharPointer)v; if (charPointerValue.Value != null) { writer.SelectBlockByNameHash(0x10); writer.Position = writer.Length; charPointerValue.DataBlockIndex = writer.BlockIndex + 1; charPointerValue.DataOffset = (int)writer.Position; charPointerValue.StringLength = charPointerValue.Value.Length; charPointerValue.StringCapacity = charPointerValue.Value.Length + 1; writer.Write(charPointerValue.Value); } else { charPointerValue.DataBlockIndex = 0; charPointerValue.DataOffset = 0; charPointerValue.StringLength = 0; charPointerValue.StringCapacity = 0; } } if (v is MetaDataBlockPointer) { var charPointerValue = (MetaDataBlockPointer)v; if (charPointerValue.Data != null) { writer.CreateBlockByNameHash(0x11); writer.Position = 0; charPointerValue.BlockIndex = writer.BlockIndex + 1; writer.Write(charPointerValue.Data); } else { charPointerValue.BlockIndex = 0; } } if (v is MetaGeneric) { var genericValue = (MetaGeneric)v; writer.SelectBlockByNameHash(((MetaStructure)genericValue.Value).info.StructureNameHash); writer.Position = writer.Length; genericValue.BlockIndex = writer.BlockIndex + 1; genericValue.Offset = (int)writer.Position / 16; genericValue.Value.Write(writer); } } // now only the root itself is left... writer.SelectBlockByNameHash(value.info.StructureNameHash); writer.Position = writer.Length; value.Write(writer); }
public MetaFile Build(IMetaValue value) { MetaInitialize(); MetaBuildStructuresAndEnums(); var writer = new MetaDataWriter(); writer.SelectBlockByNameHash(((MetaStructure)value).info.StructureNameHash); WriteStructure(writer, (MetaStructure)value); for (int k = meta.StructureInfos.Count - 1; k >= 0; k--) { if (!usedStructureKeys.Contains(meta.StructureInfos[k].StructureKey)) { meta.StructureInfos.RemoveAt(k); } } // TODO: refactor this hacky way to remove unused EnumInfos for (int e = meta.EnumInfos.Count - 1; e >= 0; e--) { bool required = false; for (int s = 0; s < meta.StructureInfos.Count; s++) { var entries = meta.StructureInfos[s].Entries; foreach (var entry in entries) { if (entry.ReferenceKey == meta.EnumInfos[e].EnumNameHash) { required = true; break; } } if (required) { break; } } if (!required) { meta.EnumInfos.RemoveAt(e); } } meta.DataBlocks = new ResourceSimpleArray <DataBlock>(); foreach (var block in writer.Blocks) { var metaDataBlock = new DataBlock(); metaDataBlock.StructureNameHash = block.NameHash; metaDataBlock.Data = StreamToResourceBytes(block.Stream); meta.DataBlocks.Add(metaDataBlock); } for (int i = 0; i < meta.DataBlocks.Count; i++) { if (meta.DataBlocks[i].StructureNameHash == ((MetaStructure)value).info.StructureNameHash) { meta.RootBlockIndex = i + 1; } } return(meta); }
private void WriteStructure(MetaDataWriter writer, PsoStructure value) { var updateStack = new Stack <IPsoValue>(); // build stack for update... var structuresToCheck = new Stack <PsoStructure>(); structuresToCheck.Push(value); while (structuresToCheck.Count > 0) { var structureToCheck = structuresToCheck.Pop(); // add structure to list of occurring structures usedStructureKeys.Add(structureToCheck.psoEntryInfo.NameHash); foreach (var structureEntryToCheck in structureToCheck.Values) { if (structureEntryToCheck.Value is PsoArray) { updateStack.Push(structureEntryToCheck.Value); var arrayStructureEntryToCheck = structureEntryToCheck.Value as PsoArray; if (arrayStructureEntryToCheck.Entries != null) { for (int k = arrayStructureEntryToCheck.Entries.Count - 1; k >= 0; k--) { var x = arrayStructureEntryToCheck.Entries[k]; if (x is PsoStructure) { structuresToCheck.Push(x as PsoStructure); } } } } if (structureEntryToCheck.Value is PsoStructure) { structuresToCheck.Push((PsoStructure)structureEntryToCheck.Value); } } } // update structures... while (updateStack.Count > 0) { var v = updateStack.Pop(); if (v is PsoArray) { var arrayValue = (PsoArray)v; if (arrayValue.Entries != null) { if (arrayValue.psoSection.Type == DataType.Structure) { writer.SelectBlockByNameHash((int)arrayValue.psoSection.ReferenceKey); writer.Position = writer.Length; } else if (arrayValue.psoSection.Type == DataType.INT_0Bh) { writer.SelectBlockByNameHash(6); writer.Position = writer.Length; } else { throw new Exception("Unknown array type."); } arrayValue.BlockIndex = writer.BlockIndex + 1; arrayValue.Offset = (int)writer.Position; arrayValue.NumberOfEntries = arrayValue.Entries.Count; foreach (var entry in arrayValue.Entries) { entry.Write(writer); } } else { arrayValue.BlockIndex = 0; arrayValue.Offset = 0; arrayValue.NumberOfEntries = 0; } } } // now only the root itself is left... writer.SelectBlockByNameHash(value.psoEntryInfo.NameHash); writer.Position = writer.Length; value.Write(writer); }