Esempio n. 1
0
        /// <summary>
        /// Parses a RenderWare TXD texture dictionary from a byte array.
        /// </summary>
        /// <param name="data">The TXD data to read in binary form.</param>
        /// <returns>A new ExtendedSection object containing the parsed TXD data.</returns>
        public ExtendedSection Parse(byte[] data)
        {
            parserData   = data;
            parserOffset = 0;
            ExtendedSection root = CreateTree();

            return(root);
        }
Esempio n. 2
0
        private void ReadExtenedSection(ExtendedSection id)
        {
            if (id == ExtendedSection.Markers)
            {
                var count = reader.readVarInt();

                for (int i = 0; i < count; i++)
                {
                    var marker = new ProfileMarker();
                    marker.Frame     = _currentframe;
                    marker.Kind      = (MarkerKind)reader.readVarInt();
                    marker.ThreadId  = reader.ReadByte();
                    marker.UserValue = (int)reader.readVarInt();
                    var labelId = reader.readVarInt();
                    marker.Label     = labelId != 0 ? ppMap[(int)labelId] : "";
                    marker.Timestamp = reader.readVarInt64();

                    _markers.Add(marker);
                }
            }
        }
Esempio n. 3
0
        private ExtendedSection CreateTree()
        {
            ExtendedSection root   = null;
            ExtendedSection parent = null;

            while (true)
            {
                // 1. Check whether it's possible to create
                //    other sections inside the parent Section
                if (parent != null)
                {
                    var bytesReadSinceParentCreation = (parserOffset - parent.CreationOffset);
                    if (bytesReadSinceParentCreation == parent.Size)
                    {
                        // 1.1 Attempt to navigate the tree up, by setting
                        // the parent variable to its own Parent. If this
                        // is not possible, then break out of the loop.
                        if (parent.Parent != null)
                        {
                            parent = parent.Parent;
                            continue;
                        }
                        //else
                        //    Debug.Write(parent.GetTreeString());
                        break;
                    }
                    else if (bytesReadSinceParentCreation > parent.Size)
                    {
                        // 1.2 File structure error. Throw an exception.
                        throw new TxdParsingException();
                    }
                }

                // 2. Read the header information
                SectionType sectionType    = (SectionType)NextUInt32();
                UInt32      sectionSize    = NextUInt32();
                UInt32      sectionVersion = NextUInt32();
                int         startOffset    = parserOffset;

                // 3. Determine the type of section
                switch (sectionType)
                {
                // 3.1 In case of a complex section, we create a new
                // ExtendedSection object, and we set the parent
                // variable to the newly created instance
                case SectionType.RwExtension:
                case SectionType.RwTextureNative:
                case SectionType.RwTextureDictionary:
                    var extendedSection = new ExtendedSection()
                    {
                        Type           = sectionType,
                        Size           = sectionSize,
                        Version        = sectionVersion,
                        CreationOffset = parserOffset
                    };

                    if (root == null)
                    {
                        root = extendedSection;
                    }

                    if (parent != null)
                    {
                        parent.AddChild(extendedSection);
                    }

                    parent = extendedSection;
                    continue;

                // 3.2 In case of a data section, we need to know the
                // parent Section type in order to instantiate the
                // appropriate class and fill it with data in a
                // meaningful way
                case SectionType.RwData:
                    switch (parent.Type)     // parent cannot be null
                    {
                    case SectionType.RwTextureNative:
                        var textureNativeDataSection = new TextureNativeDataSection()
                        {
                            Type    = sectionType,
                            Size    = sectionSize,
                            Version = sectionVersion,
                            //
                            TextureVersion   = NextUInt32(),
                            FilterFlags      = NextUInt32(),
                            TextureName      = NextString(32),
                            AlphaName        = NextString(32),
                            AlphaFlags       = NextUInt32(),
                            D3DTextureFormat = (TextureFormats)NextUInt32(),
                            Width            = NextUInt16(),
                            Height           = NextUInt16(),
                            BitDepth         = NextByte(),
                            MipMapCount      = NextByte(),
                            TexCodeType      = NextByte(),
                            Compression      = NextByte()
                                               // TODO: to be implemented
                        };

                        if (textureNativeDataSection.BitDepth == 8)
                        {
                            for (int i = 0; i < (256 * 4); i++)
                            {
                                textureNativeDataSection.Palette.Add(NextByte());
                            }
                        }

                        textureNativeDataSection.DataSize = NextUInt32();
                        for (int i = 0; i < textureNativeDataSection.DataSize; i++)
                        {
                            textureNativeDataSection.Data.Add(NextByte());
                        }

                        if (textureNativeDataSection.MipMapCount > 1)
                        {
                            for (int i = 0; i < (textureNativeDataSection.MipMapCount - 1); i++)
                            {
                                TextureNativeDataSection.MipMap mipMap
                                    = new TextureNativeDataSection.MipMap()
                                    {
                                    MipMapDataSize = NextUInt32(),
                                    MipMapData     = new List <byte>()
                                    };
                                for (int j = 0; j < mipMap.MipMapDataSize; j++)
                                {
                                    mipMap.MipMapData.Add(NextByte());
                                }
                                textureNativeDataSection.MipMaps.Add(mipMap);
                            }
                        }

                        if (parserOffset != (startOffset + (int)textureNativeDataSection.Size))
                        {
                            parserOffset = (startOffset + (int)textureNativeDataSection.Size);
                            textureNativeDataSection.IsDamaged = true;
                        }
                        parent.AddChild(textureNativeDataSection);
                        continue;

                    case SectionType.RwTextureDictionary:
                        var textureDictionaryDataSection = new TextureDictionaryDataSection()
                        {
                            Type    = sectionType,
                            Size    = sectionSize,
                            Version = sectionVersion,
                            //
                            TextureCount = NextUInt16(),
                            Unknown1     = NextUInt16()
                        };

                        if (parserOffset != (startOffset + (int)textureDictionaryDataSection.Size))
                        {
                            parserOffset = (startOffset + (int)textureDictionaryDataSection.Size);
                            textureDictionaryDataSection.IsDamaged = true;
                        }
                        parent.AddChild(textureDictionaryDataSection);
                        continue;

                    default:
                        // Unreadable: skip the number of bytes defined in the section header
                        NextString((int)sectionSize);
                        continue;
                    }

                // In all other cases we simply skip the number of bytes
                // declared in the section header, without creating a Section
                // object, nor adding it to the tree
                default:
                    NextString((int)sectionSize);
                    continue;
                }
            }
            return(root);
        }
Esempio n. 4
0
        private ExtendedSection CreateTree()
        {
            ExtendedSection root   = null;
            ExtendedSection parent = null;

            while (true)
            {
                // 1. Check whether it's possible to create
                //    other sections inside the parent Section
                if (parent != null)
                {
                    var bytesReadSinceParentCreation = (parserOffset - parent.CreationOffset);
                    if (bytesReadSinceParentCreation == parent.Size)
                    {
                        // 1.1 Attempt to navigate the tree up, by setting
                        // the parent variable to its own Parent. If this
                        // is not possible, then break out of the loop.
                        if (parent.Parent != null)
                        {
                            parent = parent.Parent;
                            continue;
                        }
                        //else
                        //    Debug.Write(parent.GetTreeString());
                        break;
                    }
                    else if (bytesReadSinceParentCreation > parent.Size)
                    {
                        // 1.2 File structure error. Throw an exception.
                        throw new DffParsingException();
                    }
                }

                // 2. Read the header information
                SectionType sectionType    = (SectionType)NextUInt32();
                uint        sectionSize    = NextUInt32();
                uint        sectionVersion = NextUInt32();
                int         startOffset    = parserOffset;

                // 3. Determine the type of section
                switch (sectionType)
                {
                // 3.1 In case of a complex section, we create a new
                // ExtendedSection object, and we call this function
                // recursively with 'parent' set to the new instance
                case SectionType.RwClump:
                case SectionType.RwFrameList:
                case SectionType.RwExtension:
                case SectionType.RwGeometryList:
                case SectionType.RwGeometry:
                case SectionType.RwMaterialList:
                case SectionType.RwMaterial:
                case SectionType.RwTexture:
                case SectionType.RwAtomic:
                case SectionType.RwLight:
                    var extendedSection = new ExtendedSection()
                    {
                        Type           = sectionType,
                        Size           = sectionSize,
                        Version        = sectionVersion,
                        CreationOffset = parserOffset
                    };

                    if (root == null)
                    {
                        root = extendedSection;
                    }

                    if (parent != null)
                    {
                        parent.AddChild(extendedSection);
                    }

                    parent = extendedSection;
                    continue;

                // 3.2 In case of a data section, we need to know the
                // parent Section type in order to instantiate the
                // appropriate class and fill it with data in a
                // meaningful way
                case SectionType.RwData:
                    switch (parent.Type)     // parent cannot be null
                    {
                    case SectionType.RwClump:
                        var clumpDataSection = new ClumpDataSection()
                        {
                            Type    = sectionType,
                            Size    = sectionSize,
                            Version = sectionVersion,
                            //
                            ObjectCount = NextUInt32(),
                            Unknown1    = NextUInt32(),
                            Unknown2    = NextUInt32()
                        };

                        if (parserOffset != (startOffset + (int)clumpDataSection.Size))
                        {
                            parserOffset = (startOffset + (int)clumpDataSection.Size);
                            clumpDataSection.IsDamaged = true;
                        }
                        parent.AddChild(clumpDataSection);
                        continue;

                    case SectionType.RwFrameList:
                        var frameListDataSection = new FrameListDataSection()
                        {
                            Type    = sectionType,
                            Size    = sectionSize,
                            Version = sectionVersion,
                            //
                            FrameCount = NextUInt32()
                        };

                        for (int i = 0; i < frameListDataSection.FrameCount; i++)
                        {
                            frameListDataSection.FrameInformation.Add(new FrameListDataSection.FrameStruct()
                            {
                                RotationalMatrix = new float[, ]
                                {
                                    { NextFloat(), NextFloat(), NextFloat() },
                                    { NextFloat(), NextFloat(), NextFloat() },
                                    { NextFloat(), NextFloat(), NextFloat() }
                                },
                                CoordinatesOffset = new float[]
                                {
                                    NextFloat(),
                                    NextFloat(),
                                    NextFloat()
                                },
                                Parent   = NextUInt32(),
                                Unknown1 = NextUInt32()
                            });
                        }
                        if (parserOffset != (startOffset + (int)frameListDataSection.Size))
                        {
                            parserOffset = (startOffset + (int)frameListDataSection.Size);
                            frameListDataSection.IsDamaged = true;
                        }
                        parent.AddChild(frameListDataSection);
                        continue;

                    case SectionType.RwGeometryList:
                        var geometryListDataSection = new GeometryListDataSection()
                        {
                            Type    = sectionType,
                            Size    = sectionSize,
                            Version = sectionVersion,
                            //
                            GeometryCount = NextUInt32()
                        };
                        if (parserOffset != (startOffset + (int)geometryListDataSection.Size))
                        {
                            parserOffset = (startOffset + (int)geometryListDataSection.Size);
                            geometryListDataSection.IsDamaged = true;
                        }
                        parent.AddChild(geometryListDataSection);
                        continue;

                    case SectionType.RwGeometry:
                        var geometryDataSection = new GeometryDataSection()
                        {
                            Type    = sectionType,
                            Size    = sectionSize,
                            Version = sectionVersion,
                            //
                            Flags             = (GeometryDataFlags)NextUInt16(),
                            UVMapCount        = NextByte(),
                            HasNativeGeometry = NextByte(),
                            TriangleCount     = NextUInt32(),
                            VertexCount       = NextUInt32(),
                            MorphCount        = NextUInt32()
                        };

                        if (geometryDataSection.Version < 0x34000)
                        {
                            NextString(12);
                        }

                        if (geometryDataSection.HasNativeGeometry == 0)
                        {
                            if ((geometryDataSection.Flags & GeometryDataFlags.RwObjectVertexColor) != GeometryDataFlags.None)
                            {
                                for (int i = 0; i < geometryDataSection.VertexCount; i++)
                                {
                                    geometryDataSection.VertexColors.Add(new GeometryDataSection.VertexColor()
                                    {
                                        R = NextByte(),
                                        G = NextByte(),
                                        B = NextByte(),
                                        A = NextByte(),
                                    });
                                }
                            }

                            if ((geometryDataSection.Flags & GeometryDataFlags.RwObjectVertexUv) != GeometryDataFlags.None)
                            {
                                for (int i = 0; i < geometryDataSection.VertexCount; i++)
                                {
                                    geometryDataSection.VertexUVs.Add(new GeometryDataSection.VertexUV()
                                    {
                                        U = NextFloat(),
                                        V = NextFloat()
                                    });
                                }
                                geometryDataSection.UVMapCount = 1;
                            }

                            if ((geometryDataSection.Flags & GeometryDataFlags.RwObjectVertexTextured) != GeometryDataFlags.None)
                            {
                                for (int i = 0; i < geometryDataSection.UVMapCount; i++)
                                {
                                    geometryDataSection.VertexUVs.Add(new GeometryDataSection.VertexUV()
                                    {
                                        U = NextFloat(),
                                        V = NextFloat()
                                    });
                                }
                            }

                            for (int i = 0; i < geometryDataSection.TriangleCount; i++)
                            {
                                geometryDataSection.Triangles.Add(new GeometryDataSection.Triangle()
                                {
                                    Vertex2 = NextUInt16(),
                                    Vertex1 = NextUInt16(),
                                    Flags   = NextUInt16(),
                                    Vertex3 = NextUInt16()
                                });
                            }
                        }

                        geometryDataSection.BoundingSphereX      = NextFloat();
                        geometryDataSection.BoundingSphereY      = NextFloat();
                        geometryDataSection.BoundingSphereZ      = NextFloat();
                        geometryDataSection.BoundingSphereRadius = NextFloat();
                        geometryDataSection.HasPosition          = NextUInt32();
                        geometryDataSection.HasNormals           = NextUInt32();

                        if (geometryDataSection.HasNativeGeometry == 0)
                        {
                            for (int i = 0; i < geometryDataSection.VertexCount; i++)
                            {
                                geometryDataSection.Vertices.Add(new GeometryDataSection.Vertex()
                                {
                                    X = NextFloat(),
                                    Y = NextFloat(),
                                    Z = NextFloat()
                                });
                            }

                            if ((geometryDataSection.Flags & GeometryDataFlags.RwObjectVertexNormal)
                                != GeometryDataFlags.None)
                            {
                                for (int i = 0; i < geometryDataSection.VertexCount; i++)
                                {
                                    geometryDataSection.Normals.Add(new GeometryDataSection.Normal()
                                    {
                                        X = NextFloat(),
                                        Y = NextFloat(),
                                        Z = NextFloat()
                                    });
                                }
                            }
                        }
                        if (parserOffset != (startOffset + (int)geometryDataSection.Size))
                        {
                            parserOffset = (startOffset + (int)geometryDataSection.Size);
                            geometryDataSection.IsDamaged = true;
                        }
                        parent.AddChild(geometryDataSection);
                        continue;

                    case SectionType.RwMaterialList:
                        var materialListDataSection = new MaterialListDataSection()
                        {
                            Type    = sectionType,
                            Size    = sectionSize,
                            Version = sectionVersion,
                            //
                            MaterialCount = NextUInt32(),
                            Unknown1      = NextUInt32()
                        };
                        if (parserOffset != (startOffset + (int)materialListDataSection.Size))
                        {
                            parserOffset = (startOffset + (int)materialListDataSection.Size);
                            materialListDataSection.IsDamaged = true;
                        }
                        parent.AddChild(materialListDataSection);
                        continue;

                    case SectionType.RwMaterial:
                        var materialDataSection = new MaterialDataSection()
                        {
                            Type    = sectionType,
                            Size    = sectionSize,
                            Version = sectionVersion,
                            //
                            Unknown1 = NextUInt32(),
                            Color    = new MaterialDataSection.MaterialColor()
                            {
                                R = NextByte(),
                                G = NextByte(),
                                B = NextByte(),
                                A = NextByte()
                            },
                            Unknown2     = NextUInt32(),
                            TextureCount = NextUInt32(),
                            Unknown3     = new float[]
                            {
                                NextFloat(),
                                NextFloat(),
                                NextFloat()
                            }
                        };
                        if (parserOffset != (startOffset + (int)materialDataSection.Size))
                        {
                            parserOffset = (startOffset + (int)materialDataSection.Size);
                            materialDataSection.IsDamaged = true;
                        }
                        parent.AddChild(materialDataSection);
                        continue;

                    case SectionType.RwTexture:
                        var textureDataSection = new TextureDataSection()
                        {
                            Type    = sectionType,
                            Size    = sectionSize,
                            Version = sectionVersion,
                            //
                            TextureFilterModeFlags = NextUInt16(),
                            Unknown1 = NextUInt16()
                        };
                        if (parserOffset != (startOffset + (int)textureDataSection.Size))
                        {
                            parserOffset = (startOffset + (int)textureDataSection.Size);
                            textureDataSection.IsDamaged = true;
                        }
                        parent.AddChild(textureDataSection);
                        continue;

                    case SectionType.RwAtomic:
                        var atomicDataSection = new AtomicDataSection()
                        {
                            Type    = sectionType,
                            Size    = sectionSize,
                            Version = sectionVersion,
                            //
                            FrameNumber    = NextUInt32(),
                            GeometryNumber = NextUInt32(),
                            Unknown1       = NextUInt32(),
                            Unknown2       = NextUInt32()
                        };
                        if (parserOffset != (startOffset + (int)atomicDataSection.Size))
                        {
                            parserOffset = (startOffset + (int)atomicDataSection.Size);
                            atomicDataSection.IsDamaged = true;
                        }
                        parent.AddChild(atomicDataSection);
                        continue;

                    default:
                        // Unreadable: skip the number of bytes defined in the section header
                        NextString((int)sectionSize);
                        continue;
                    }

                // 3.3 In case of special data formats, we parse their content
                //     accordingly
                case SectionType.RwFrame:
                    var frameSection = new FrameDataSection()
                    {
                        Type    = sectionType,
                        Size    = sectionSize,
                        Version = sectionVersion,
                    };
                    frameSection.FrameName = NextString((int)frameSection.Size);
                    if (parserOffset != (startOffset + (int)frameSection.Size))
                    {
                        parserOffset           = (startOffset + (int)frameSection.Size);
                        frameSection.IsDamaged = true;
                    }
                    parent.AddChild(frameSection);
                    continue;

                case SectionType.RwString:
                    var stringDataSection = new StringDataSection()
                    {
                        Type    = sectionType,
                        Size    = sectionSize,
                        Version = sectionVersion,
                    };
                    stringDataSection.String = NextString((int)stringDataSection.Size);
                    if (parserOffset != (startOffset + (int)stringDataSection.Size))
                    {
                        parserOffset = (startOffset + (int)stringDataSection.Size);
                        stringDataSection.IsDamaged = true;
                    }
                    parent.AddChild(stringDataSection);
                    continue;

                case SectionType.RwMaterialSplit:
                    var materialSplitDataSection = new MaterialSplitDataSection()
                    {
                        Type    = sectionType,
                        Size    = sectionSize,
                        Version = sectionVersion,
                        //
                        FaceType   = NextUInt32(),
                        SplitCount = NextUInt32(),
                        FaceCount  = NextUInt32()
                    };
                    for (int i = 0; i < materialSplitDataSection.SplitCount; i++)
                    {
                        var split = new MaterialSplitDataSection.Split()
                        {
                            IndexCount = NextUInt32(),
                            Material   = NextUInt32(),
                            Indices    = new List <UInt32>()
                        };
                        materialSplitDataSection.Splits.Add(split);
                        for (int j = 0; j < split.IndexCount; j++)
                        {
                            split.Indices.Add(NextUInt32());
                        }
                    }
                    if (parserOffset != (startOffset + (int)materialSplitDataSection.Size))
                    {
                        parserOffset = (startOffset + (int)materialSplitDataSection.Size);
                        materialSplitDataSection.IsDamaged = true;
                    }
                    parent.AddChild(materialSplitDataSection);
                    continue;

                case SectionType.RwAnimPlugin:
                    var animPluginDataSection = new AnimPluginDataSection()
                    {
                        Type    = sectionType,
                        Size    = sectionSize,
                        Version = sectionVersion,
                        //
                        Unknown1  = NextUInt32(),
                        BoneId    = NextUInt32(),
                        BoneCount = NextUInt32(),
                        Unknown2  = NextUInt32(),
                        Unknown3  = NextUInt32()
                    };
                    for (int i = 0; i < animPluginDataSection.BoneCount; i++)
                    {
                        animPluginDataSection.Bones.Add(new AnimPluginDataSection.BoneInformation()
                        {
                            Id    = NextUInt32(),
                            Index = NextUInt32(),
                            Type  = NextUInt32()
                        });
                    }
                    if (parserOffset != (startOffset + (int)animPluginDataSection.Size))
                    {
                        parserOffset = (startOffset + (int)animPluginDataSection.Size);
                        animPluginDataSection.IsDamaged = true;
                    }
                    parent.AddChild(animPluginDataSection);
                    continue;

                // In all other cases we simply skip the number of bytes
                // declared in the section header, without creating a Section
                // object, nor adding it to the tree
                default:
                    NextString((int)sectionSize);
                    continue;
                }
            }
            return(root);
        }