private NavObjectModel NewObject(string line, ObjectSection objectSection)
        {
            string[] parts = line.Split(' ');

            if (objectSection != ObjectSection.Object)
            {
                return(null);
            }

            if (parts.Length == 0)
            {
                return(null);
            }

            if (parts[0] != "OBJECT")
            {
                return(null);
            }

            return(new NavObjectModel()
            {
                Type = parts[1],
                Id = ObjectHelper.GetInt(parts[2]),
                Name = ObjectHelper.GetObjectName(line)
            });
        }
Пример #2
0
        public override bool Visit(ObjectSection node)
        {
            traverse(node.fields);
            traverse(node.decls);

            return(true);
        }
        private void SetObjectProperties(string line, ObjectSection objectSection, ref NavObjectModel navObject)
        {
            if (objectSection != ObjectSection.ObjectProperties)
            {
                return;
            }

            string[] parts = line.Split('=');

            switch (ObjectHelper.RemoveIllChar(parts[0]))
            {
            case "Date":
                navObject.StringDate = ObjectHelper.RemoveIllChar(parts[1]);
                break;

            case "Time":
                navObject.StringTime = ObjectHelper.RemoveIllChar(parts[1]);
                break;

            case "Modified":
                navObject.Modified = ObjectHelper.GetBool(parts[1]);
                break;

            case "Version List":
                navObject.VersionList = ObjectHelper.GetVersionList(line, parts[0]);
                break;
            }
        }
Пример #4
0
 public override bool Visit(ObjectSection node)
 {
     traverse(node.fields);              // do not print
     Visit((Section)node);
     traverse(node.properties);          // do not print
     return(true);
 }
Пример #5
0
        public MprObjGrd(string id_rpt_obj, ObjectSection s)
        {
            ID = null;
            IDReport = id_rpt_obj;
            Name = "Grid" + DateTime.Now.ToLongTimeString();
            Category = ObjectCategory.Grid;
            Section = s;
            Index = 0;
            Printed = true;
            Type = ObjectType.Static;
            RotateAngle = 0;

            Rows = "";
            RowsSQL = "";
            Width = 1000;
            Location = new Point(0, 0);
            RowHeight = 70;
            ColumnHeaderHeight = 90;
            ColumnFooterHeight = 90;
            ColumnHeaderPrinted = true;
            ColumnFooterPrinted = true;
            Columns = new Collection<MprObjGrdCol>();
            TextStyle = new MprStlTxt();
            BoxStyle = new MprStlRect();
        }
        internal void Read(EndianBinaryReader reader, ObjectSection section = null)
        {
            uint signature = reader.ReadUInt32();

            reader.SeekCurrent(4);   // Unused flags

            int  meshCount, materialCount;
            long meshesOffset, materialsOffset;

            // X stores mesh/material count before the bounding sphere
            if (section?.Format == BinaryFormat.X)
            {
                meshCount       = reader.ReadInt32();
                materialCount   = reader.ReadInt32();
                BoundingSphere  = reader.ReadBoundingSphere();
                meshesOffset    = reader.ReadOffset();
                materialsOffset = reader.ReadOffset();

                reader.SkipNulls(4 * sizeof(uint));
                Flags = reader.ReadUInt32(); // TODO: Is this available in other games?
                reader.SkipNulls(sizeof(uint));
            }

            else
            {
                BoundingSphere  = reader.ReadBoundingSphere();
                meshCount       = reader.ReadInt32();
                meshesOffset    = reader.ReadOffset();
                materialCount   = reader.ReadInt32();
                materialsOffset = reader.ReadOffset();
            }

            reader.SkipNulls(10 * sizeof(uint));

            Meshes.Capacity = meshCount;

            for (int i = 0; i < meshCount; i++)
            {
                reader.ReadAtOffset(meshesOffset + i * Mesh.GetByteSize(section?.Format ?? BinaryFormat.DT), () =>
                {
                    var mesh = new Mesh();
                    mesh.Read(reader, section);
                    Meshes.Add(mesh);
                });
            }

            Materials.Capacity = materialCount;

            for (int i = 0; i < materialCount; i++)
            {
                reader.ReadAtOffset(materialsOffset + i * Material.BYTE_SIZE, () =>
                {
                    var material = new Material();
                    material.Read(reader);
                    Materials.Add(material);
                });
            }
        }
        private NavObjectModel CreateNewObject(string line, ObjectSection objectSection, NavObjectModel navObject)
        {
            NavObjectModel newNavObject = NewObject(line, objectSection);

            if (newNavObject != null)
            {
                navObject = newNavObject;
                _navObjects.Add(newNavObject.InternalId, newNavObject);
            }

            return(navObject);
        }
Пример #8
0
        protected void Given_Section(string name, SectionHeaderType type, uint flags, byte[] blob)
        {
            var os = new ObjectSection
            {
                Name    = name,
                Type    = type,
                Flags   = flags,
                Content = blob,
            };

            objectSections.Add(os);
        }
Пример #9
0
        public MprObjRect(string id_rpt_obj, ObjectSection s)
        {
            ID = null;
            IDReport = id_rpt_obj;
            Name = "Rectangle" + DateTime.Now.ToLongTimeString();
            Category = ObjectCategory.Rectangle;
            Section = s;
            Index = 0;
            Printed = true;
            Type = ObjectType.Static;
            RotateAngle = 0;

            Location = new Point(0, 0);
            Size = new System.Drawing.Size(500, 70);
            Style = new MprStlRect();
        }
Пример #10
0
        public MprObjLine(string id_rpt_obj, ObjectSection s)
        {
            ID = null;
            IDReport = id_rpt_obj;
            Name = "Line" + DateTime.Now.ToLongTimeString();
            Category = ObjectCategory.Line;
            Section = s;
            Index = 0;
            Printed = true;
            Type = ObjectType.Static;
            RotateAngle = 0;

            Point1 = new Point(0, 0);
            Point2 = new Point(500, 100);
            Style = new MprStlPen();
        }
        internal void Write(EndianBinaryWriter writer, ObjectSection section = null)
        {
            writer.Write(0x10000);
            writer.Write(0);

            if (section?.Format == BinaryFormat.X)
            {
                writer.Write(Meshes.Count);
                writer.Write(Materials.Count);
                writer.Write(BoundingSphere);
                writer.ScheduleWriteOffset(8, AlignmentMode.Left, WriteMeshes);
                writer.ScheduleWriteOffset(8, AlignmentMode.Left, WriteMaterials);
                writer.WriteNulls(4 * sizeof(uint));
                writer.Write(Flags);
                writer.WriteNulls(sizeof(uint));
            }
            else
            {
                writer.Write(BoundingSphere);
                writer.Write(Meshes.Count);
                writer.ScheduleWriteOffset(8, AlignmentMode.Left, WriteMeshes);
                writer.Write(Materials.Count);
                writer.ScheduleWriteOffset(8, AlignmentMode.Left, WriteMaterials);
            }

            writer.WriteNulls(10 * sizeof(uint));

            void WriteMeshes()
            {
                foreach (var mesh in Meshes)
                {
                    mesh.Write(writer, section);
                }
            }

            void WriteMaterials()
            {
                foreach (var material in Materials)
                {
                    material.Write(writer);
                }
            }
        }
Пример #12
0
        public MprObjImgFld(string id_rpt_obj, ObjectSection s)
        {
            ID = null;
            IDReport = id_rpt_obj;
            Name = "ImageField" + DateTime.Now.ToLongTimeString();
            Category = ObjectCategory.ImageField;
            Section = s;
            Index = 0;
            Printed = true;
            SizeMode = ImageSizeMode.Stretch;
            Type = ObjectType.Static;
            RotateAngle = 0;

            Location = new Point(0, 0);
            Size = new System.Drawing.Size(250, 250);
            Image = null;
            ImageFile = "";
            ImageSQL = "";
            Style = new MprStlRect();
        }
        private void ProcessLine(string line, ObjectSection objectSection, ref NavObjectModel navObject)
        {
            switch (objectSection)
            {
            case ObjectSection.Object:
                navObject = CreateNewObject(line, objectSection, navObject);
                break;

            case ObjectSection.ObjectProperties:
                SetObjectProperties(line, objectSection, ref navObject);
                navObject.ObjectProperties.Add(line);
                break;

            default:
                if (navObject != null)
                {
                    navObject.Code.Add(line);
                }
                break;
                //case ObjectSection.Properties:
                //    navObject.Properties.Add(line);
                //    break;
                //case ObjectSection.Fields:
                //    navObject.Fields.Add(line);
                //    break;
                //case ObjectSection.Keys:
                //    navObject.Keys.Add(line);
                //    break;
                //case ObjectSection.FieldGroups:
                //    navObject.FieldGroups.Add(line);
                //    break;
                //case ObjectSection.Code:
                //    navObject.Code.Add(line);
                //    break;
            }

            if (navObject != null)
            {
                navObject.ObjectLines.Add(line);
            }
        }
Пример #14
0
        internal void Write(EndianBinaryWriter writer, ObjectSection section = null)
        {
            writer.Write(0);
            writer.Write(BoundingSphere);
            writer.Write(MaterialIndex);

            if (MaterialUVIndices?.Length == 8)
            {
                writer.Write(MaterialUVIndices);
            }
            else
            {
                writer.WriteNulls(8);
            }

            writer.Write(BoneIndices != null ? BoneIndices.Length : 0);
            writer.ScheduleWriteOffsetIf(BoneIndices != null, 4, AlignmentMode.Left,
                                         () => { writer.Write(BoneIndices); });
            writer.Write(BoneIndices != null ? 4 : 0);

            writer.Write(( int )PrimitiveType);
            writer.Write(1);
            writer.Write(Indices.Length);

            // Modern Format
            if (section != null)
            {
                writer.Write(( uint )section.IndexData.AddIndices(Indices));
                writer.WriteNulls(section.Format == BinaryFormat.X ? 24 : 20);
                writer.Write(BoundingBox);
                writer.Write(Field00);
                writer.Write(0);
            }

            else
            {
                writer.ScheduleWriteOffset(4, AlignmentMode.Left, () => { writer.Write(Indices); });

                writer.WriteNulls(32);
            }
        }
Пример #15
0
        internal void Read(EndianBinaryReader reader, ObjectSection section = null)
        {
            reader.SeekCurrent(4);
            BoundingSphere    = reader.ReadBoundingSphere();
            MaterialIndex     = reader.ReadInt32();
            MaterialUVIndices = reader.ReadBytes(8);
            int  boneIndexCount    = reader.ReadInt32();
            long boneIndicesOffset = reader.ReadOffset();
            uint field00           = reader.ReadUInt32();

            PrimitiveType = ( PrimitiveType )reader.ReadUInt32();
            int  field01       = reader.ReadInt32();
            int  indexCount    = reader.ReadInt32();
            uint indicesOffset = reader.ReadUInt32();

            if (section != null)
            {
                reader.SeekCurrent(section.Format == BinaryFormat.X ? 0x18 : 0x14);
                BoundingBox = reader.ReadBoundingBox();
                Field00     = reader.ReadInt32();
            }
            else
            {
                BoundingBox = BoundingSphere.ToBoundingBox();
            }

            reader.ReadAtOffsetIf(field00 == 4, boneIndicesOffset,
                                  () => { BoneIndices = reader.ReadUInt16s(boneIndexCount); });

            if (section == null)
            {
                reader.ReadAtOffset(indicesOffset, () => { Indices = reader.ReadUInt16s(indexCount); });
            }
            else
            {
                var indexReader = section.IndexData.Reader;

                indexReader.SeekBegin(section.IndexData.DataOffset + indicesOffset);
                Indices = indexReader.ReadUInt16s(indexCount);
            }
        }
Пример #16
0
        public MprObjTxtFld(string id_rpt_obj, ObjectSection s)
        {
            ID = null;
            IDReport = id_rpt_obj;
            Name = "TextField" + DateTime.Now.ToLongTimeString();
            Category = ObjectCategory.TextField;
            Section = s;
            Index = 0;
            Printed = true;
            Type = ObjectType.Static;
            RotateAngle = 0;

            Text = "TextField" + DateTime.Now.ToLongTimeString();
            TextSQL = "";
            Location = new Point(0, 0);
            Size = new System.Drawing.Size(500, 70);
            TextStyle = new MprStlTxt();
            Shape = ObjectShape.Rectangle;
            RectangleStyle = new MprStlRect();
            EllipseStyle = new MprStlEllp();
        }
        public void RunImportFromObjectFile(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return;
            }

            if (!File.Exists(filePath))
            {
                return;
            }

            if (!IsTxtFile(filePath))
            {
                return;
            }

            ObjectSection  currObjectSection = ObjectSection.Unknown;
            NavObjectModel currNavObject     = null;

            var lines = File.ReadAllLines(filePath, Encoding.Default);

            int totalLineCount = lines.Length;

            for (int i = 0; i < totalLineCount; i++)
            {
                ObjectSection objectSection = ObjectHelper.FindObjectSection(lines[i]);
                if (objectSection != ObjectSection.Unknown)
                {
                    currObjectSection = objectSection;
                }

                ProcessLine(lines[i], currObjectSection, ref currNavObject);

                // FireFileReadEvent(i, totalLineCount);
            }
        }
Пример #18
0
 public virtual T Visit(ObjectSection node)
 {
     Visit((Section)node);
     return(traverse(node.fields));
 }
Пример #19
0
        private static retType AISSectionLoad( AISGen devAISGen, ObjectFile file, ObjectSection section)
        {
            Byte[] secData = file.secRead(section);
              Byte[] srcCRCData = new Byte[section.size + 8];

              Debug.DebugMSG("AISSectionLoad for section " + section.name + " from file " + file.FileName + ".");

              // If we are doing section-by-section CRC, then zero out the CRC value
              if (devAISGen.aisCRCType == AisCRCCheckType.SECTION_CRC)
              {
            devAISGen.devCRC.ResetCRC();
              }

              // Add section load to the output
              devAISGen.InsertAISSectionLoad((UInt32) section.loadAddr, (UInt32) section.size, secData);

              // Copy bytes to CRC byte array for future CRC calculation
              if (devAISGen.aisCRCType != AisCRCCheckType.NO_CRC)
              {
            if (devAISGen.devEndian != devAISGen.devAISEndian)
            {
              Endian.swapEndian(BitConverter.GetBytes(section.loadAddr)).CopyTo(srcCRCData, 0);
              Endian.swapEndian(BitConverter.GetBytes(section.size)).CopyTo(srcCRCData, 4);
            }
            else
            {
              BitConverter.GetBytes(section.loadAddr).CopyTo(srcCRCData, 0);
              BitConverter.GetBytes(section.size).CopyTo(srcCRCData, 4);
            }

              }

              // Now write contents to CRC array
              for (UInt32 k = 0; k < section.size; k+=4)
              {
            // Copy bytes to array for future CRC calculation
            if (devAISGen.aisCRCType != AisCRCCheckType.NO_CRC)
            {
              Byte[] temp = new Byte[4];
              Array.Copy(secData,k,temp,0,4);
              if (devAISGen.devEndian != devAISGen.devAISEndian)
              {
            Endian.swapEndian(temp).CopyTo(srcCRCData, (8 + k));
              }
              else
              {
            temp.CopyTo(srcCRCData, (8 + k));
              }
            }
              }

              // Add this section's memory range, checking for overlap
              AddMemoryRange(devAISGen, (UInt32) section.loadAddr, (UInt32) (section.loadAddr+section.size-1));

              // Perform CRC calculation of the section's contents
              if (devAISGen.aisCRCType != AisCRCCheckType.NO_CRC)
              {
            devAISGen.devCRC.CalculateCRC(srcCRCData);
            if (devAISGen.aisCRCType == AisCRCCheckType.SECTION_CRC)
            {
              // Write CRC request command, value, and jump value to temp AIS file
              devAISGen.InsertAISRequestCRC(((Int32)(-1) * (Int32)(section.size + 12 + 12)));
            }
              }

              return retType.SUCCESS;
        }
Пример #20
0
        internal void Write(EndianBinaryWriter writer, ObjectSection section = null)
        {
            writer.Write(0);
            writer.Write(BoundingSphere);
            writer.Write(SubMeshes.Count);

            writer.ScheduleWriteOffset(8, AlignmentMode.Left, () =>
            {
                foreach (var subMesh in SubMeshes)
                {
                    subMesh.Write(writer, section);
                }
            });

            int vertexSize = 0;
            VertexFormatAttributes vertexFormat = default;

            if (section != null)
            {
                vertexFormat = VertexFormatAttributes.UsesModernStorage;
                vertexSize   = BoneWeights != null ? 56 : 44;
            }

            else
            {
                if (Positions != null)
                {
                    vertexFormat |= VertexFormatAttributes.Position;
                    vertexSize   += 12;
                }

                if (Normals != null)
                {
                    vertexFormat |= VertexFormatAttributes.Normal;
                    vertexSize   += 12;
                }

                if (Tangents != null)
                {
                    vertexFormat |= VertexFormatAttributes.Tangent;
                    vertexSize   += 16;
                }

                if (TexCoords0 != null)
                {
                    vertexFormat |= VertexFormatAttributes.TexCoord0;
                    vertexSize   += 8;
                }

                if (TexCoords1 != null)
                {
                    vertexFormat |= VertexFormatAttributes.TexCoord1;
                    vertexSize   += 8;
                }

                if (TexCoords2 != null)
                {
                    vertexFormat |= VertexFormatAttributes.TexCoord2;
                    vertexSize   += 8;
                }

                if (TexCoords3 != null)
                {
                    vertexFormat |= VertexFormatAttributes.TexCoord3;
                    vertexSize   += 8;
                }

                if (Colors0 != null)
                {
                    vertexFormat |= VertexFormatAttributes.Color0;
                    vertexSize   += 16;
                }

                if (Colors1 != null)
                {
                    vertexFormat |= VertexFormatAttributes.Color1;
                    vertexSize   += 16;
                }

                if (BoneWeights != null)
                {
                    vertexFormat |= VertexFormatAttributes.BoneWeight | VertexFormatAttributes.BoneIndex;
                    vertexSize   += 32;
                }
            }

            writer.Write(( int )vertexFormat);
            writer.Write(vertexSize);
            writer.Write(Positions.Length);

            if (section != null)
            {
                WriteVertexAttributesModern();
            }

            else
            {
                WriteVertexAttributesClassic();
            }

            writer.Write(( int )Flags);

            writer.Write(section != null ? (BoneWeights != null ? 4 : 2) : 0);

            writer.WriteNulls(6 * sizeof(uint));     // Reserved

            writer.Write(Name, StringBinaryFormat.FixedLength, 64);

            void WriteVertexAttributesClassic()
            {
                for (int i = 0; i < 20; i++)
                {
                    var attribute = ( VertexFormatAttributes )(1 << i);

                    writer.ScheduleWriteOffsetIf((vertexFormat & attribute) != 0, ( int )attribute + 1, 4, AlignmentMode.Left, () =>
                    {
                        switch (attribute)
                        {
                        case VertexFormatAttributes.Position:
                            writer.Write(Positions);
                            break;

                        case VertexFormatAttributes.Normal:
                            writer.Write(Normals);
                            break;

                        case VertexFormatAttributes.Tangent:
                            writer.Write(Tangents);
                            break;

                        case VertexFormatAttributes.TexCoord0:
                            writer.Write(TexCoords0);
                            break;

                        case VertexFormatAttributes.TexCoord1:
                            writer.Write(TexCoords1);
                            break;

                        case VertexFormatAttributes.TexCoord2:
                            writer.Write(TexCoords2);
                            break;

                        case VertexFormatAttributes.TexCoord3:
                            writer.Write(TexCoords3);
                            break;

                        case VertexFormatAttributes.Color0:
                            writer.Write(Colors0);
                            break;

                        case VertexFormatAttributes.Color1:
                            writer.Write(Colors1);
                            break;

                        case VertexFormatAttributes.BoneWeight:
                            foreach (var weight in BoneWeights)
                            {
                                writer.Write(weight.Weight1);
                                writer.Write(weight.Weight2);
                                writer.Write(weight.Weight3);
                                writer.Write(weight.Weight4);
                            }

                            break;

                        case VertexFormatAttributes.BoneIndex:
                            foreach (var weight in BoneWeights)
                            {
                                writer.Write(weight.Index1 < 0 ? -1f : weight.Index1 * 3.0f);
                                writer.Write(weight.Index2 < 0 ? -1f : weight.Index2 * 3.0f);
                                writer.Write(weight.Index3 < 0 ? -1f : weight.Index3 * 3.0f);
                                writer.Write(weight.Index4 < 0 ? -1f : weight.Index4 * 3.0f);
                            }

                            break;
                        }
                    });
                }
            }

            void WriteVertexAttributesModern()
            {
                int byteSize = writer.AddressSpace.GetByteSize();

                writer.Align(byteSize);
                writer.WriteNulls(13 * byteSize);
                writer.WriteOffset(section.VertexData.AddSubMesh(this, vertexSize));
                writer.WriteNulls(6 * byteSize);
            }
        }
Пример #21
0
        internal void Read(EndianBinaryReader reader, ObjectSection section = null)
        {
            reader.SeekCurrent(4);   // Unused flags

            BoundingSphere = reader.ReadBoundingSphere();

            int  subMeshCount    = reader.ReadInt32();
            long subMeshesOffset = reader.ReadOffset();

            var vertexFormat     = ( VertexFormatAttributes )reader.ReadUInt32();
            int vertexSize       = reader.ReadInt32();
            int vertexCount      = reader.ReadInt32();
            var attributeOffsets = reader.ReadOffsets(20);

            Flags = ( MeshFlags )reader.ReadInt32();

            uint attributeFlags = reader.ReadUInt32();

            reader.SkipNulls(6 * sizeof(uint));

            Name = reader.ReadString(StringBinaryFormat.FixedLength, 64);

            reader.ReadAtOffset(subMeshesOffset, () =>
            {
                SubMeshes.Capacity = subMeshCount;

                for (int i = 0; i < subMeshCount; i++)
                {
                    var subMesh = new SubMesh();
                    subMesh.Read(reader, section);
                    SubMeshes.Add(subMesh);
                }
            });

            // Modern Format
            if ((vertexFormat & VertexFormatAttributes.UsesModernStorage) != 0)
            {
                ReadVertexAttributesModern();
            }

            else
            {
                ReadVertexAttributesClassic();
            }

            void ReadVertexAttributesClassic()
            {
                Vector4[] boneWeights = null;
                Vector4[] boneIndices = null;

                for (int i = 0; i < attributeOffsets.Length; i++)
                {
                    var attribute = ( VertexFormatAttributes )(1 << i);

                    reader.ReadAtOffsetIf((vertexFormat & attribute) != 0, attributeOffsets[i], () =>
                    {
                        switch (attribute)
                        {
                        case VertexFormatAttributes.Position:
                            Positions = reader.ReadVector3s(vertexCount);
                            break;

                        case VertexFormatAttributes.Normal:
                            Normals = reader.ReadVector3s(vertexCount);
                            break;

                        case VertexFormatAttributes.Tangent:
                            Tangents = reader.ReadVector4s(vertexCount);
                            break;

                        case VertexFormatAttributes.TexCoord0:
                            TexCoords0 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttributes.TexCoord1:
                            TexCoords1 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttributes.TexCoord2:
                            TexCoords2 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttributes.TexCoord3:
                            TexCoords3 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttributes.Color0:
                            Colors0 = reader.ReadColors(vertexCount);
                            break;

                        case VertexFormatAttributes.Color1:
                            Colors1 = reader.ReadColors(vertexCount);
                            break;

                        case VertexFormatAttributes.BoneWeight:
                            boneWeights = reader.ReadVector4s(vertexCount);
                            break;

                        case VertexFormatAttributes.BoneIndex:
                            boneIndices = reader.ReadVector4s(vertexCount);
                            break;

                        default:
                            Console.WriteLine("Unhandled vertex format element: {0}", attribute);
                            break;
                        }
                    });
                }

                if (boneWeights == null || boneIndices == null)
                {
                    return;
                }

                BoneWeights = new BoneWeight[vertexCount];

                for (int i = 0; i < vertexCount; i++)
                {
                    var weight4 = boneWeights[i];
                    var index4  = Vector4.Divide(boneIndices[i], 3);

                    var boneWeight = new BoneWeight
                    {
                        Weight1 = weight4.X,
                        Weight2 = weight4.Y,
                        Weight3 = weight4.Z,
                        Weight4 = weight4.W,
                        Index1  = ( int )index4.X,
                        Index2  = ( int )index4.Y,
                        Index3  = ( int )index4.Z,
                        Index4  = ( int )index4.W
                    };

                    boneWeight.Validate();

                    BoneWeights[i] = boneWeight;
                }
            }

            void ReadVertexAttributesModern()
            {
                Positions  = new Vector3[vertexCount];
                Normals    = new Vector3[vertexCount];
                Tangents   = new Vector4[vertexCount];
                TexCoords0 = new Vector2[vertexCount];
                TexCoords1 = new Vector2[vertexCount];

                if (attributeFlags == 10)
                {
                    TexCoords2 = new Vector2[vertexCount];
                    TexCoords3 = new Vector2[vertexCount];
                }
                else if (attributeFlags == 6)
                {
                    TexCoords2 = new Vector2[vertexCount];
                }

                Colors0 = new Color[vertexCount];

                if (attributeFlags == 4)
                {
                    BoneWeights = new BoneWeight[vertexCount];
                }

                bool hasTangents = false;

                EndianBinaryReader vertexReader;
                long baseOffset;

                if (section != null)
                {
                    vertexReader = section.VertexData.Reader;
                    baseOffset   = section.VertexData.DataOffset;
                }
                else
                {
                    vertexReader = reader;
                    baseOffset   = reader.BaseOffset;
                }

                long current = reader.Position;

                for (int i = 0; i < vertexCount; i++)
                {
                    vertexReader.SeekBegin(baseOffset + attributeOffsets[13] + vertexSize * i);

                    Positions[i] = vertexReader.ReadVector3();
                    Normals[i]   = vertexReader.ReadVector3(VectorBinaryFormat.Int16);
                    vertexReader.SeekCurrent(2);
                    Tangents[i]   = vertexReader.ReadVector4(VectorBinaryFormat.Int16);
                    TexCoords0[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                    TexCoords1[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);

                    if (attributeFlags == 10)
                    {
                        TexCoords2[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                        TexCoords3[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                    }
                    else if (attributeFlags == 6)
                    {
                        TexCoords2[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                    }

                    Colors0[i] = vertexReader.ReadColor(VectorBinaryFormat.Half);

                    if (attributeFlags == 4)
                    {
                        var boneWeight = new BoneWeight
                        {
                            Weight1 = vertexReader.ReadUInt16() / 32767f,
                            Weight2 = vertexReader.ReadUInt16() / 32767f,
                            Weight3 = vertexReader.ReadUInt16() / 32767f,
                            Weight4 = vertexReader.ReadUInt16() / 32767f,
                            Index1  = vertexReader.ReadByte() / 3,
                            Index2  = vertexReader.ReadByte() / 3,
                            Index3  = vertexReader.ReadByte() / 3,
                            Index4  = vertexReader.ReadByte() / 3
                        };

                        boneWeight.Validate();

                        BoneWeights[i] = boneWeight;
                    }

                    // Normalize normal because precision
                    Normals[i] = Vector3.Normalize(Normals[i]);

                    // Checks to get rid of useless data after reading
                    if (Tangents[i] != Vector4.Zero)
                    {
                        hasTangents = true;
                    }
                }

                if (!hasTangents)
                {
                    Tangents = null;
                }

                reader.SeekBegin(current);
            }

            if (Tangents == null)
            {
                return;
            }

            for (int i = 0; i < Tangents.Length; i++)
            {
                int direction = Math.Sign(Tangents[i].W);
                var tangent   = Vector3.Normalize(new Vector3(Tangents[i].X, Tangents[i].Y, Tangents[i].Z));

                Tangents[i] = new Vector4(tangent, direction);
            }
        }
Пример #22
0
        private static void writeSection(EndianBinaryWriter writer, ObjectSection section, byte[] contents)
        {
            // RPRC section contents:
            //  u32 type;
            //  u64 da;
            //  u32 len;
            //  u8 content[...] = { len bytes of binary data };

            uint type = 1;  // 1: TEXT, 2: DATA (TODO use both?)
            ulong addr = section.loadAddr;
            uint size = (uint)section.size;

            // write section to file
            writer.Write(type);
            writer.Write(addr);
            writer.Write(size);
            writer.Write(contents);
        }
        internal void Read(EndianBinaryReader reader, ObjectSection section = null)
        {
            reader.SeekCurrent(4);   // Unused flags

            BoundingSphere = reader.ReadBoundingSphere();

            MaterialIndex   = reader.ReadUInt32();
            TexCoordIndices = reader.ReadBytes(8);

            int  boneIndexCount    = reader.ReadInt32();
            long boneIndicesOffset = reader.ReadOffset();

            BonesPerVertex = reader.ReadUInt32();

            PrimitiveType = ( PrimitiveType )reader.ReadUInt32();
            IndexFormat   = ( IndexFormat )reader.ReadInt32();
            int  indexCount    = reader.ReadInt32();
            long indicesOffset = reader.ReadOffset();

            Flags = ( SubMeshFlags )reader.ReadInt32();

            if (section != null)
            {
                reader.SkipNulls(4 * sizeof(uint));
                BoundingBox = reader.ReadBoundingBox();
                reader.SeekCurrent(sizeof(uint));     // Max Index
            }

            else
            {
                BoundingBox = BoundingSphere.ToBoundingBox();
                reader.SkipNulls(6 * sizeof(uint));
            }

            IndexOffset = reader.ReadUInt32();

            if (section?.Format == BinaryFormat.X)
            {
                reader.SeekCurrent(4);
            }

            reader.ReadAtOffsetIf(BonesPerVertex == 4, boneIndicesOffset,
                                  () => { BoneIndices = reader.ReadUInt16s(boneIndexCount); });

            if (section == null)
            {
                reader.ReadAtOffset(indicesOffset, () => { ReadIndices(reader); });
            }

            else
            {
                long current = reader.Position;
                {
                    var indexReader = section.IndexData.Reader;

                    indexReader.SeekBegin(section.IndexData.DataOffset + indicesOffset);
                    ReadIndices(indexReader);
                }

                reader.SeekBegin(current);
            }

            void ReadIndices(EndianBinaryReader r)
            {
                Indices = new uint[indexCount];

                switch (IndexFormat)
                {
                case IndexFormat.UInt8:
                    for (int i = 0; i < Indices.Length; i++)
                    {
                        byte index = r.ReadByte();
                        Indices[i] = index == 0xFF ? 0xFFFFFFFF : index;
                    }

                    break;

                case IndexFormat.UInt16:
                    for (int i = 0; i < Indices.Length; i++)
                    {
                        ushort index = r.ReadUInt16();
                        Indices[i] = index == 0xFFFF ? 0xFFFFFFFF : index;
                    }

                    break;

                case IndexFormat.UInt32:
                    for (int i = 0; i < Indices.Length; i++)
                    {
                        Indices[i] = r.ReadUInt32();
                    }

                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
        }
Пример #24
0
        private void ParseBinaryFile(UInt64 address)
        {
            // Output console message
              Console.WriteLine("Parsing the input file, {0}.", fileName);

              // Set endian to little
              endian = Endian.LittleEndian;

              // Set section count
              sectionCount = 1;
              loadableSectionCount = 1;
              symbolCount  = 0;

              binFile.Seek(0, SeekOrigin.Begin);
              EndianBinaryReader ebr = new EndianBinaryReader(binFile, endian);

              sections      = new ObjectSection[sectionCount];
              sections[0]   = new ObjectSection();

              sections[0].name         = fileName;
              sections[0].loadAddr     = address;
              sections[0].runAddr      = address;
              sections[0].size         = (UInt64) binFile.Length;
              sections[0].size         = ((sections[0].size + 3) >> 2) << 2;
              sections[0].binFileAddr  = 0x00000000;
              sections[0].isLoadable   = true;

              loadableSections    = new ObjectSection[loadableSectionCount];
              loadableSections[0] = sections[0];
        }
Пример #25
0
        /// <summary>
        /// AIS Section Load command generation
        /// </summary>
        /// <param name="cf">The COFFfile object that the section comes from.</param>
        /// <param name="secHeader">The Hashtable object of the section header to load.</param>
        /// <param name="devAISGen">The specific device AIS generator object.</param>
        /// <returns>retType enumerator indicating success or failure.</returns>
        private static retType AISSecureSectionLoad( AISGen devAISGen, ObjectFile file, ObjectSection section, Boolean encryptSection)
        {
            Byte[] secData = file.secRead(section);

              // Write Section_Load AIS command, load address, and size
              if (encryptSection)
              {
            Byte[] encData = null;

            // Encrypt data using CTS algorithm
            try
            {
              encData = AesManagedUtil.AesCTSEncrypt(secData,devAISGen.customerEncryptionKey,devAISGen.CEKInitialValue);
            }
            catch(Exception e)
            {
              Console.WriteLine("Exception during encryption operation: {0}",e.Message);
              return retType.FAIL;
            }

            if (encData != null)
            {
              devAISGen.InsertAISEncSectionLoad((UInt32) section.loadAddr, (UInt32) section.size, secData, encData);
            }
            else
            {
              Console.WriteLine("Section encryption failed.");
              return retType.FAIL;
            }
              }
              else
              {
            devAISGen.InsertAISSectionLoad((UInt32) section.loadAddr, (UInt32) section.size, secData);
              }

              // Add this section's memory range, checking for overlap
              AddMemoryRange(devAISGen, (UInt32) section.loadAddr, (UInt32) (section.loadAddr+section.size-1));

              return retType.SUCCESS;
        }
Пример #26
0
        internal void Write(EndianBinaryWriter writer, ObjectSection section = null)
        {
            writer.Write(0);
            writer.Write(BoundingSphere);
            writer.Write(SubMeshes.Count);
            writer.ScheduleWriteOffset(4, AlignmentMode.Left, () =>
            {
                foreach (var subMesh in SubMeshes)
                {
                    subMesh.Write(writer, section);
                }
            });

            int stride = 0;
            VertexFormatAttribute attributes = default;

            if (section != null)
            {
                attributes = VertexFormatAttribute.UsesModernStorage;
                if (BoneWeights != null)
                {
                    stride = 56;
                }
                else
                {
                    stride = 44;
                }
            }

            else
            {
                if (Vertices != null)
                {
                    attributes |= VertexFormatAttribute.Vertex;
                    stride     += 12;
                }

                if (Normals != null)
                {
                    attributes |= VertexFormatAttribute.Normal;
                    stride     += 12;
                }

                if (Tangents != null)
                {
                    attributes |= VertexFormatAttribute.Tangent;
                    stride     += 16;
                }

                if (UVChannel1 != null)
                {
                    attributes |= VertexFormatAttribute.UVChannel1;
                    stride     += 8;
                }

                if (UVChannel2 != null)
                {
                    attributes |= VertexFormatAttribute.UVChannel2;
                    stride     += 8;
                }

                if (Colors != null)
                {
                    attributes |= VertexFormatAttribute.Color;
                    stride     += 16;
                }

                if (BoneWeights != null)
                {
                    attributes |= VertexFormatAttribute.BoneWeight | VertexFormatAttribute.BoneIndex;
                    stride     += 32;
                }
            }

            writer.Write(( int )attributes);
            writer.Write(stride);
            writer.Write(Vertices.Length);

            if (section != null)
            {
                WriteVertexAttributesModern();
            }
            else
            {
                WriteVertexAttributesClassic();
            }

            writer.Write(Name, StringBinaryFormat.FixedLength, 64);

            void WriteVertexAttributesClassic()
            {
                for (int i = 0; i < 28; i++)
                {
                    var attribute = ( VertexFormatAttribute )(1 << i);

                    writer.ScheduleWriteOffsetIf((attributes & attribute) != 0, 4, AlignmentMode.Left, () =>
                    {
                        switch (attribute)
                        {
                        case VertexFormatAttribute.Vertex:
                            writer.Write(Vertices);
                            break;

                        case VertexFormatAttribute.Normal:
                            writer.Write(Normals);
                            break;

                        case VertexFormatAttribute.Tangent:
                            writer.Write(Tangents);
                            break;

                        case VertexFormatAttribute.UVChannel1:
                            writer.Write(UVChannel1);
                            break;

                        case VertexFormatAttribute.UVChannel2:
                            writer.Write(UVChannel2);
                            break;

                        case VertexFormatAttribute.Color:
                            writer.Write(Colors);
                            break;

                        case VertexFormatAttribute.BoneWeight:
                            foreach (var weight in BoneWeights)
                            {
                                writer.Write(weight.Weight1);
                                writer.Write(weight.Weight2);
                                writer.Write(weight.Weight3);
                                writer.Write(weight.Weight4);
                            }

                            break;

                        case VertexFormatAttribute.BoneIndex:
                            foreach (var weight in BoneWeights)
                            {
                                writer.Write(weight.Index1 < 0 ? -1f : weight.Index1 * 3.0f);
                                writer.Write(weight.Index2 < 0 ? -1f : weight.Index2 * 3.0f);
                                writer.Write(weight.Index3 < 0 ? -1f : weight.Index3 * 3.0f);
                                writer.Write(weight.Index4 < 0 ? -1f : weight.Index4 * 3.0f);
                            }

                            break;
                        }
                    });
                }
            }

            void WriteVertexAttributesModern()
            {
                writer.WriteNulls(section.Format == BinaryFormat.X ? 0x6C : 0x34);
                writer.Write(( uint )section.VertexData.AddSubMesh(this, stride));
                writer.WriteNulls(section.Format == BinaryFormat.X ? 0x38 : 0x1C);
                writer.Write(BoneWeights != null ? 4 : 2);
                writer.WriteNulls(0x18);
            }
        }
Пример #27
0
        void PrintSection(ObjectSection c, int yStartSection)
        {
            foreach (
                DataRow rObj in Cfg.DbRpt.DataTable("SELECT " + MprTblObj.id_obj + ", " + MprTblObj.cat_obj + ", " + MprTblObj.rotate_angle_obj + ", " + MprTblObj.location_obj +
                " FROM " + MprTblObj.TableName +
                " WHERE " + MprTblObj.id_rpt_obj + "=" + Rpt.ID +
                " AND " + MprTblObj.section_obj + "='" + c + "' ORDER BY " + MprTblObj.index_obj).Rows
                )
            {
                Point loc = UtlConvert.ToIH(UtlConvert.ToPoint(rObj[MprTblObj.location_obj].ToString()));
                loc.Y += yStartSection;

                G.TranslateTransform(loc.X, loc.Y);
                G.RotateTransform(int.Parse(rObj[MprTblObj.rotate_angle_obj].ToString()));

                switch (UtlMprVwr.ToObjectCategory(rObj[MprTblObj.cat_obj].ToString()))
                {
                    case ObjectCategory.TextField:
                        PrintObjTxtFld(rObj[MprTblObj.id_obj].ToString());
                        break;
                    case ObjectCategory.ImageField:
                        PrintObjImgFld(rObj[MprTblObj.id_obj].ToString());
                        break;
                    case ObjectCategory.Line:
                        PrintObjLine(rObj[MprTblObj.id_obj].ToString());
                        break;
                    case ObjectCategory.Rectangle:
                        PrintObjRect(rObj[MprTblObj.id_obj].ToString());
                        break;
                    case ObjectCategory.Ellipse:
                        PrintObjEllp(rObj[MprTblObj.id_obj].ToString());
                        break;
                    case ObjectCategory.Grid:
                        PrintObjGrid(rObj[MprTblObj.id_obj].ToString());
                        break;
                    default: break;
                }

                G.RotateTransform(-int.Parse(rObj[MprTblObj.rotate_angle_obj].ToString()));
                G.TranslateTransform(-loc.X, -loc.Y);
            }
        }
Пример #28
0
        /// <summary>
        /// Parse the section headers.
        /// </summary>
        private void ParseSectionHdrs()
        {
            UInt32 numBytesInSectionHdr;
              EndianBinaryReader ebr = new EndianBinaryReader(binFile, endian);

              if (hdr.c_version == COFF_Version.COFF2)
              {
            numBytesInSectionHdr = 48;
              }
              else if (hdr.c_version == COFF_Version.COFF1)
              {
            numBytesInSectionHdr = 40;
              }
              else
              {
            numBytesInSectionHdr = 0;
              }

              sectionRef  = new Hashtable[sectionCount];
              sections    = new ObjectSection[sectionCount];

              for (UInt16 secNum = 0; secNum < sectionCount; secNum++)
              {
            sectionRef[secNum] = new Hashtable();
            sections[secNum]   = new ObjectSection();

            ebr.BaseStream.Seek(numBytesInSectionHdr * secNum + COFFHeaderSize + hdr.c_ehsize, SeekOrigin.Begin);
            sections[secNum].name         = COFF_getName();

            ebr.BaseStream.Seek(numBytesInSectionHdr * secNum + COFFHeaderSize + hdr.c_ehsize + 8, SeekOrigin.Begin);
            sections[secNum].runAddr      = (UInt64) ebr.ReadUInt32();
            sections[secNum].loadAddr     = (UInt64) ebr.ReadUInt32();
            sections[secNum].size         = (UInt64) ebr.ReadUInt32();
            sections[secNum].size         = ((sections[secNum].size + 3) >> 2) << 2;
            sections[secNum].binFileAddr  = (UInt64) ebr.ReadUInt32();

            sectionRef[secNum]["reloPtr"] = ebr.ReadUInt32();
            sectionRef[secNum]["linePtr"] = ebr.ReadUInt32();

            if (hdr.c_version == COFF_Version.COFF2)
            {
              sectionRef[secNum].Add("numRelos", ebr.ReadUInt32());
              sectionRef[secNum].Add("numLines", ebr.ReadUInt32());
              sectionRef[secNum].Add("flags", ebr.ReadUInt32());
              sectionRef[secNum].Add("reserved", (UInt32) ebr.ReadUInt16());
              sectionRef[secNum].Add("memPage", (UInt32) ebr.ReadUInt16());
            }
            else
            {
              sectionRef[secNum].Add("numRelos", (UInt32) ebr.ReadUInt16());
              sectionRef[secNum].Add("numLines", (UInt32) ebr.ReadUInt16());
              sectionRef[secNum].Add("flags", (UInt32) ebr.ReadUInt16());
              sectionRef[secNum].Add("reserved", (UInt32) ebr.ReadByte());
              sectionRef[secNum].Add("memPage", (UInt32) ebr.ReadByte());
            }

            //Check to see if section is bootable
            UInt32 flags = (UInt32)sectionRef[secNum]["flags"];
            sectionRef[secNum]["bootable"] = false;
            if ((flags & ((UInt32)(COFF_SectionType.TEXT | COFF_SectionType.DATA))) != 0)
            {
              if ((flags & ((UInt32)COFF_SectionType.COPY)) == 0)
              {
            if (sections[secNum].size != 0)
            {
              headerRef["numBootSections"] = ((UInt32)headerRef["numBootSections"]) + 1;
              sectionRef[secNum]["bootable"] = true;
            }
              }
            }

            // Check to see if section is loadable
            sections[secNum].isLoadable = false;
            if ( ( sections[secNum].binFileAddr != 0 ) && ( sections[secNum].size != 0 ) )
            {
              if ((flags & ((UInt32)(COFF_SectionType.BSS |        // No BSS sections
                        COFF_SectionType.COPY |                // No COPY sections
                        COFF_SectionType.NOLOAD |              // No NOLOAD sections
                        COFF_SectionType.DUMMY))               // No DUMMY sections
               ) == 0)
              {
            sections[secNum].isLoadable = true;
            loadableSectionCount++;
              }
            }

            Debug.DebugMSG("ObjectSection sections[" + secNum + "] = \n{");
            Debug.DebugMSG("\tname = " + sections[secNum].name + ",");
            Debug.DebugMSG("\tsize = " + sections[secNum].size.ToString("X8") + ",");
            Debug.DebugMSG("\trunAddr = " + sections[secNum].runAddr.ToString("X8") + ",");
            Debug.DebugMSG("\tloadAddr = " + sections[secNum].loadAddr.ToString("X8") + ",");
            Debug.DebugMSG("\tisLoadable = " + sections[secNum].isLoadable + ",");
            Debug.DebugMSG("\tbinFileAddr = " + sections[secNum].binFileAddr.ToString("X8"));
            Debug.DebugMSG("}");
              }

              // Fill in the loadableSections array
              loadableSections = new ObjectSection[loadableSectionCount];
              for (UInt32 secNum = 0,loadableSecNum=0; secNum < sectionCount; secNum++)
              {
            if (sections[secNum].isLoadable)
            {
              loadableSections[loadableSecNum] = sections[secNum];
              loadableSecNum++;
            }
              }

              // Finally, sort the loadable sections array by load address
              Array.Sort<ObjectSection>(loadableSections);

              Debug.DebugMSG("Parse Section Headers Done");
        }
        internal void Write(EndianBinaryWriter writer, ObjectSection section = null)
        {
            writer.Write(0);
            writer.Write(BoundingSphere);
            writer.Write(MaterialIndex);

            if (TexCoordIndices?.Length == 8)
            {
                writer.Write(TexCoordIndices);
            }

            else
            {
                writer.WriteNulls(8);
            }

            writer.Write(BoneIndices?.Length ?? 0);
            writer.ScheduleWriteOffsetIf(BoneIndices != null, 4, AlignmentMode.Left,
                                         () => { writer.Write(BoneIndices); });
            writer.Write(BonesPerVertex);

            writer.Write(( int )PrimitiveType);
            writer.Write(( int )IndexFormat);
            writer.Write(Indices.Length);

            // Modern Format
            if (section != null)
            {
                writer.WriteOffset(section.IndexData.AddSubMesh(this));
                writer.Write(( int )Flags);

                writer.WriteNulls(4 * sizeof(uint));

                writer.Write(BoundingBox);

                switch (IndexFormat)
                {
                case IndexFormat.UInt8:
                    writer.WriteNulls(3);
                    writer.Write(( byte )Indices.Max());
                    break;

                case IndexFormat.UInt16:
                    writer.WriteNulls(2);
                    writer.Write(( ushort )Indices.Max());
                    break;

                case IndexFormat.UInt32:
                    writer.Write(Indices.Max());
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            else
            {
                writer.ScheduleWriteOffset(8, AlignmentMode.Left, () =>
                {
                    switch (IndexFormat)
                    {
                    case IndexFormat.UInt8:
                        foreach (uint index in Indices)
                        {
                            writer.Write(( byte )index);
                        }

                        break;

                    case IndexFormat.UInt16:
                        foreach (uint index in Indices)
                        {
                            writer.Write(( ushort )index);
                        }

                        break;

                    case IndexFormat.UInt32:
                        foreach (uint index in Indices)
                        {
                            writer.Write(index);
                        }

                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                });
                writer.Write(( int )Flags);
                writer.WriteNulls(6 * sizeof(uint));
            }

            writer.Write(IndexOffset);

            if (section?.Format == BinaryFormat.X)
            {
                writer.WriteNulls(sizeof(uint));
            }
        }
Пример #30
0
 public override bool Visit(ObjectSection node)
 {
     Visit((Section)node);
     TraverseSetParent(node, node.fields);
     return(true);
 }
Пример #31
0
        private static bool sectionOverlap(ObjectSection section, ObjectSection[] externSections)
        {
            // note: s1, s2 are the beginning and end locations of this section in memory
            ulong s1 = section.loadAddr,
                s2 = section.loadAddr + section.size - 1,
                x1, x2;

            foreach (ObjectSection exSection in externSections)
            {
                // note: x1, x2 are the beginning and end locations of the external section in memory
                x1 = exSection.loadAddr;
                x2 = exSection.loadAddr + exSection.size - 1;

                // sections collide if any of the following is true:
                // 1) s1 is inside the external section
                // 2) s2 is inside the external section
                // 3) s1 is before the external section and s2 is after it
                if ((s1 >= x1 && s1 <= x2) ||
                    (s2 >= x1 && s2 <= x2) ||
                    (s1 < x1 && s2 > x2))
                    return true;
            }

            return false;
        }
Пример #32
0
        /// <summary>
        /// Checks if current context is inside an object (method usually).
        /// If given an argument, checks if this ObjectSection is the defining scope
        /// </summary>
        public bool IsContextInObject(ObjectSection sec = null)
        {
            var osec = GetDeclaringObjectSection();

            return(sec != null && !ReferenceEquals(osec, sec));
        }
Пример #33
0
        internal void Read(EndianBinaryReader reader, ObjectSection section = null)
        {
            reader.SeekCurrent(4);
            BoundingSphere = reader.ReadBoundingSphere();
            int  subMeshCount    = reader.ReadInt32();
            long subMeshesOffset = reader.ReadOffset();
            var  attributes      = ( VertexFormatAttribute )reader.ReadUInt32();
            int  stride          = reader.ReadInt32();
            int  vertexCount     = reader.ReadInt32();
            var  elemItems       = reader.ReadUInt32s(section?.Format == BinaryFormat.X ? 49 : 28);

            Name = reader.ReadString(StringBinaryFormat.FixedLength, 64);

            SubMeshes.Capacity = subMeshCount;
            for (int i = 0; i < subMeshCount; i++)
            {
                reader.ReadAtOffset(subMeshesOffset + i * SubMesh.GetByteSize(section?.Format ?? BinaryFormat.DT),
                                    () =>
                {
                    var subMesh = new SubMesh();
                    subMesh.Read(reader, section);
                    SubMeshes.Add(subMesh);
                });
            }

            // Modern Format
            if (section != null)
            {
                ReadVertexAttributesModern();
            }
            else
            {
                ReadVertexAttributesClassic();
            }

            void ReadVertexAttributesClassic()
            {
                Vector4[] boneWeights = null;
                Vector4[] boneIndices = null;

                for (int i = 0; i < 28; i++)
                {
                    var attribute = ( VertexFormatAttribute )(1 << i);

                    reader.ReadAtOffsetIf((attributes & attribute) != 0, elemItems[i], () =>
                    {
                        switch (attribute)
                        {
                        case VertexFormatAttribute.Vertex:
                            Vertices = reader.ReadVector3s(vertexCount);
                            break;

                        case VertexFormatAttribute.Normal:
                            Normals = reader.ReadVector3s(vertexCount);
                            break;

                        case VertexFormatAttribute.Tangent:
                            Tangents = reader.ReadVector4s(vertexCount);
                            break;

                        case VertexFormatAttribute.UVChannel1:
                            UVChannel1 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttribute.UVChannel2:
                            UVChannel2 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttribute.Color:
                            Colors = reader.ReadColors(vertexCount);
                            break;

                        case VertexFormatAttribute.BoneWeight:
                            boneWeights = reader.ReadVector4s(vertexCount);
                            break;

                        case VertexFormatAttribute.BoneIndex:
                            boneIndices = reader.ReadVector4s(vertexCount);
                            break;

                        default:
                            Console.WriteLine("Unhandled vertex format element: {0}", attribute);
                            break;
                        }
                    });
                }

                if (boneWeights != null && boneIndices != null)
                {
                    BoneWeights = new BoneWeight[vertexCount];
                    for (int i = 0; i < vertexCount; i++)
                    {
                        var weight4 = boneWeights[i];
                        var index4  = Vector4.Divide(boneIndices[i], 3);

                        var boneWeight = new BoneWeight
                        {
                            Weight1 = weight4.X,
                            Weight2 = weight4.Y,
                            Weight3 = weight4.Z,
                            Weight4 = weight4.W,
                            Index1  = ( int )index4.X,
                            Index2  = ( int )index4.Y,
                            Index3  = ( int )index4.Z,
                            Index4  = ( int )index4.W
                        };
                        boneWeight.Validate();

                        BoneWeights[i] = boneWeight;
                    }
                }
            }

            void ReadVertexAttributesModern()
            {
                uint dataOffset     = elemItems[section.Format == BinaryFormat.X ? 27 : 13];
                uint attributeFlags = elemItems[section.Format == BinaryFormat.X ? 42 : 21];

                if (attributeFlags == 2 || attributeFlags == 4)
                {
                    Vertices   = new Vector3[vertexCount];
                    Normals    = new Vector3[vertexCount];
                    Tangents   = new Vector4[vertexCount];
                    UVChannel1 = new Vector2[vertexCount];
                    UVChannel2 = new Vector2[vertexCount];
                    Colors     = new Color[vertexCount];

                    if (attributeFlags == 4)
                    {
                        BoneWeights = new BoneWeight[vertexCount];
                    }

                    bool hasTangents   = false;
                    bool hasUVChannel2 = false;
                    bool hasColors     = false;

                    var vertexReader = section.VertexData.Reader;
                    for (int i = 0; i < vertexCount; i++)
                    {
                        vertexReader.SeekBegin(section.VertexData.DataOffset + dataOffset + stride * i);
                        Vertices[i] = vertexReader.ReadVector3();
                        Normals[i]  = vertexReader.ReadVector3(VectorBinaryFormat.Int16);
                        vertexReader.SeekCurrent(2);
                        Tangents[i]   = vertexReader.ReadVector4(VectorBinaryFormat.Int16);
                        UVChannel1[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                        UVChannel2[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                        Colors[i]     = vertexReader.ReadColor(VectorBinaryFormat.Half);

                        if (attributeFlags == 4)
                        {
                            var boneWeight = new BoneWeight
                            {
                                Weight1 = vertexReader.ReadUInt16() / 32767f,
                                Weight2 = vertexReader.ReadUInt16() / 32767f,
                                Weight3 = vertexReader.ReadUInt16() / 32767f,
                                Weight4 = vertexReader.ReadUInt16() / 32767f,
                                Index1  = vertexReader.ReadByte() / 3,
                                Index2  = vertexReader.ReadByte() / 3,
                                Index3  = vertexReader.ReadByte() / 3,
                                Index4  = vertexReader.ReadByte() / 3
                            };
                            boneWeight.Validate();

                            BoneWeights[i] = boneWeight;
                        }

                        // Normalize normal because precision
                        Normals[i] = Vector3.Normalize(Normals[i]);

                        // Checks to get rid of useless data after reading
                        if (Tangents[i] != Vector4.Zero)
                        {
                            hasTangents = true;
                        }
                        if (UVChannel1[i] != UVChannel2[i])
                        {
                            hasUVChannel2 = true;
                        }
                        if (!Colors[i].Equals(Color.White))
                        {
                            hasColors = true;
                        }
                    }

                    if (!hasTangents)
                    {
                        Tangents = null;
                    }
                    if (!hasUVChannel2)
                    {
                        UVChannel2 = null;
                    }
                    if (!hasColors)
                    {
                        Colors = null;
                    }
                }

                if (Tangents != null)
                {
                    for (int i = 0; i < Tangents.Length; i++)
                    {
                        int direction = Math.Sign(Tangents[i].W);
                        var tangent   =
                            Vector3.Normalize(new Vector3(Tangents[i].X, Tangents[i].Y, Tangents[i].Z));

                        Tangents[i] = new Vector4(tangent, direction);
                    }
                }
            }
        }
Пример #34
0
        /// <summary>
        /// Parse the section headers.
        /// </summary>
        private void ParseSectionHdrs()
        {
            UInt32 byteSize, wordSize, numBytesInSectionHdr;
              UInt64 flags;
              ELF_SectionHeader secHdr;
              EndianBinaryReader ebr = new EndianBinaryReader(binFile, endian);

              numBytesInSectionHdr = hdr.e_shentsize;

              Debug.DebugMSG("Parsing ELF Sections Headers");

              if (sectionCount == (UInt32) ELF_SectionIndex.SHN_UNDEF)
              {
            // Get the actual number of sections from the sh_size field of the
            // 0th section header table entry
            secHdr = ReadSectionHeader(0);
            sectionCount = (UInt32) secHdr.sh_size;
            headerRef["numSectionHdrs"] = (UInt32) secHdr.sh_size;
              }

              // Get Section Header String Table Section Header Index and Section Header String Table Section Address
              if (hdr.e_shstrndx == (UInt16) ELF_SectionIndex.SHN_UNDEF)
              {
            headerRef["stringTableAddr"] = null;
            headerRef["stringHeaderTableIndex"] = null;
            secHdr = new ELF_SectionHeader();
              }
              else if (hdr.e_shstrndx == (UInt16) ELF_SectionIndex.SHN_XINDEX)
              {
            secHdr = ReadSectionHeader(0);
            headerRef["stringHeaderTableIndex"] = (UInt32) secHdr.sh_link;
            secHdr = ReadSectionHeader((UInt32) headerRef["stringHeaderTableIndex"]);
            headerRef["stringTableAddr"] = (UInt64) secHdr.sh_addr;
              }
              else
              {
            headerRef["stringHeaderTableIndex"] = (UInt32) hdr.e_shstrndx;
            secHdr = ReadSectionHeader((UInt32) headerRef["stringHeaderTableIndex"]);
            headerRef["stringTableAddr"] = (UInt64) (secHdr.sh_offset);
              }
              Debug.DebugMSG("Section Header Table Index for Section Header String Table: " + (UInt32)headerRef["stringHeaderTableIndex"]);
              Debug.DebugMSG("String Section Start Addr: 0x" + ((UInt64)headerRef["stringTableAddr"]).ToString("X8"));

              // Verify that the section header string table section is flagged as a string section
              flags = (UInt64) secHdr.sh_flags;
              Debug.DebugMSG("secHdr.sh_flags = " + secHdr.sh_flags.ToString());
              if ( ( flags & ((UInt64) ELF_SectionFlag.SHF_STRINGS) ) == 0 )
              {
            Debug.DebugMSG("WARNING: Section Header String Section is not flagged with SHF_STRINGS");
              }
              if (secHdr.sh_type != ELF_SectionType.SHT_STRTAB)
              {
            throw new Exception("Section Header String Section is not of type SHT_STRTAB.");
              }

              if ( hdr.e_phnum == 0x0)
              {
            throw new Exception("Load addresses cannot be calculated without program header.");
              }

              // Cycle through all sections, collecting info about each (name, type, etc.)
              sectionRef  = new Hashtable[sectionCount];
              sections    = new ObjectSection[sectionCount];
              for (UInt32 secNum = 0; secNum < sectionCount; secNum++)
              {
            sectionRef[secNum]  = new Hashtable();
            sections[secNum]    = new ObjectSection();
            secHdr = ReadSectionHeader((UInt32) secNum);

            ebr.BaseStream.Seek((Int64)(secHdr.sh_name + (UInt64)headerRef["stringTableAddr"]), SeekOrigin.Begin);
            sectionRef[secNum]["name"]      = ELF_getStringFromStringTable();
            sectionRef[secNum]["type"]      = (ELF_SectionType) secHdr.sh_type;
            sectionRef[secNum]["phyAddr"]   = (UInt64) secHdr.sh_addr;
            sectionRef[secNum]["virAddr"]   = (UInt64) secHdr.sh_addr;
            sectionRef[secNum]["fileAddr"]  = (UInt64) secHdr.sh_offset;

            byteSize = (UInt32) secHdr.sh_size;
            wordSize = (byteSize + 3) >> 2;
            byteSize = wordSize << 2;
            sectionRef[secNum]["byteSize"]  = byteSize;
            sectionRef[secNum]["wordSize"] = wordSize;
            sectionRef[secNum]["flags"] = (UInt64) secHdr.sh_flags;

            flags = (UInt64) sectionRef[secNum]["flags"];

            // FIXME: Check to see if section should be copied to target
            sectionRef[secNum]["copyToTarget"] = false;
            if ( ( ((UInt64) sectionRef[secNum]["phyAddr"])   != 0 ) &&
             ( ((UInt32) sectionRef[secNum]["byteSize"])  != 0 ) &&
             ( ELF_SectionType.SHT_NULL                   != (ELF_SectionType)sectionRef[secNum]["type"] ) &&
             ( ELF_SectionType.SHT_NOBITS                 != (ELF_SectionType)sectionRef[secNum]["type"] ) &&
             ( ELF_SectionType.SHT_SYMTAB                 != (ELF_SectionType)sectionRef[secNum]["type"] ) &&
             ( ELF_SectionType.SHT_DYNSYM                 != (ELF_SectionType)sectionRef[secNum]["type"] ) &&
             ( ELF_SectionType.SHT_STRTAB                 != (ELF_SectionType)sectionRef[secNum]["type"] )             )
            {
              if ( ( ELF_SectionType.SHT_PROGBITS == (ELF_SectionType)sectionRef[secNum]["type"] ) &&
               ( (flags | ((UInt64) ELF_SectionFlag.SHF_ALLOC)) != 0x0 ) )
              {
            headerRef["numTargetSections"] = ((UInt32)headerRef["numTargetSections"]) + 1;
            sectionRef[secNum]["copyToTarget"] = true;
              }
            }

            // If we think this section should be copied to target, make sure it is
            // in a loadable ELF program segment.  If it is, then update physical
            // and virtual addresses. If not, then mark it as such.
            if ((Boolean) sectionRef[secNum]["copyToTarget"])
            {
              Boolean segmentFoundForSection = false;
              for (UInt32 segmentNum = 0; segmentNum < (UInt32)hdr.e_phnum; segmentNum++)
              {
            ELF_SegmentHeader segmentHdr = ReadSegmentHeader((UInt32) segmentNum);

            // If the segment is of load type, check to see if the current section resides in it
            if (segmentHdr.p_type == ELF_SegmentType.PT_LOAD)
            {
              // Check if data is in the file, and if so then check if the section
              // is within this current segment
              if ( ( segmentHdr.p_filesz                         != 0                      ) &&
                   ( segmentHdr.p_vaddr                          <= (UInt64) secHdr.sh_addr) &&
                   ( (segmentHdr.p_vaddr + segmentHdr.p_filesz)  >  (UInt64) secHdr.sh_addr) &&
                   ( segmentHdr.p_offset                         <= (UInt64) secHdr.sh_offset) &&
                   ( (segmentHdr.p_offset + segmentHdr.p_filesz) >  (UInt64) secHdr.sh_offset) )

              {
                sectionRef[secNum]["phyAddr"] = (UInt64) segmentHdr.p_paddr + ( secHdr.sh_addr - segmentHdr.p_vaddr);
                segmentFoundForSection = true;
              }
            }
              }
              if (!segmentFoundForSection)
              {
            // This section is not actually in a loadable ELF program segment, indicate that
            sectionRef[secNum]["copyToTarget"] = false;
              }
            }

            sections[secNum].name         = (String) sectionRef[secNum]["name"];
            sections[secNum].size         = (UInt32) sectionRef[secNum]["byteSize"];
            sections[secNum].runAddr      = (UInt64) sectionRef[secNum]["virAddr"];
            sections[secNum].loadAddr     = (UInt64) sectionRef[secNum]["phyAddr"];
            sections[secNum].isLoadable   = (Boolean) sectionRef[secNum]["copyToTarget"];
            if (sections[secNum].isLoadable)
            {
              loadableSectionCount++;
            }
            sections[secNum].binFileAddr  = (UInt64) sectionRef[secNum]["fileAddr"];

            Debug.DebugMSG("ObjectSection sections[" + secNum + "] = \n{");
            Debug.DebugMSG("\tname = " + sections[secNum].name + ",");
            Debug.DebugMSG("\tsize = " + sections[secNum].size.ToString("X8") + ",");
            Debug.DebugMSG("\trunAddr = " + sections[secNum].runAddr.ToString("X8") + ",");
            Debug.DebugMSG("\tloadAddr = " + sections[secNum].loadAddr.ToString("X8") + ",");
            Debug.DebugMSG("\tisLoadable = " + sections[secNum].isLoadable + ",");
            Debug.DebugMSG("\tbinFileAddr = " + sections[secNum].binFileAddr.ToString("X8"));
            Debug.DebugMSG("}");
              }

              // Fill in the loadableSections array
              loadableSections = new ObjectSection[loadableSectionCount];
              for (UInt32 secNum = 0,loadableSecNum=0; secNum < sectionCount; secNum++)
              {
            if (sections[secNum].isLoadable)
            {
              loadableSections[loadableSecNum] = sections[secNum];
              loadableSecNum++;
            }
              }

              // Finally, sort the loadable sections array by load address
              Array.Sort<ObjectSection>(loadableSections);

              Debug.DebugMSG("Parse Section Headers Done");
        }