예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }