Пример #1
0
        private void ReadParameters(byte[] file, int address, int count)
        {
            for (int i = 0; i < count; i++)
            {
                switch ((ParameterType)ByteConverter.ToInt32(file, address))
                {
                case ParameterType.VtxAttrFmt:
                    VtxAttrFmtParameter vtx_param = new VtxAttrFmtParameter();
                    vtx_param.Read(file, address + 4);
                    Parameters.Add(vtx_param);
                    break;

                case ParameterType.IndexAttributeFlags:
                    IndexAttributeParameter index_param = new IndexAttributeParameter();
                    index_param.Read(file, address + 4);
                    Parameters.Add(index_param);
                    break;

                case ParameterType.Lighting:
                    LightingParameter light_param = new LightingParameter();
                    light_param.Read(file, address + 4);
                    Parameters.Add(light_param);
                    break;

                case ParameterType.BlendAlpha:
                    BlendAlphaParameter blend_param = new BlendAlphaParameter();
                    blend_param.Read(file, address + 4);
                    Parameters.Add(blend_param);
                    break;

                case ParameterType.AmbientColor:
                    AmbientColorParameter ambient_param = new AmbientColorParameter();
                    ambient_param.Read(file, address + 4);
                    Parameters.Add(ambient_param);
                    break;

                case ParameterType.Texture:
                    TextureParameter texture_param = new TextureParameter();
                    texture_param.Read(file, address + 4);
                    Parameters.Add(texture_param);
                    break;

                case ParameterType.Unknown_9:
                    Unknown9Parameter unk9_param = new Unknown9Parameter();
                    unk9_param.Read(file, address + 4);
                    Parameters.Add(unk9_param);
                    break;

                case ParameterType.TexCoordGen:
                    TexCoordGenParameter mip_param = new TexCoordGenParameter();
                    mip_param.Read(file, address + 4);
                    Parameters.Add(mip_param);
                    break;
                }

                address += 8;
            }
        }
Пример #2
0
        /// <summary>
        /// Create a parameter object from a file and address
        /// </summary>
        /// <param name="file">The file contents</param>
        /// <param name="address">The address at which the parameter is located</param>
        /// <returns>Any of the parameter types</returns>
        public static GCParameter Read(byte[] file, int address)
        {
            GCParameter   result    = null;
            ParameterType paramType = (ParameterType)BitConverter.ToUInt32(file, address);

            switch (paramType)
            {
            case ParameterType.VtxAttrFmt:
                result = new VtxAttrFmtParameter(GCVertexAttribute.Null);
                break;

            case ParameterType.IndexAttributeFlags:
                result = new IndexAttributeParameter();
                break;

            case ParameterType.Lighting:
                result = new LightingParameter();
                break;

            case ParameterType.BlendAlpha:
                result = new BlendAlphaParameter();
                break;

            case ParameterType.AmbientColor:
                result = new AmbientColorParameter();
                break;

            case ParameterType.Texture:
                result = new TextureParameter();
                break;

            case ParameterType.Unknown_9:
                result = new Unknown9Parameter();
                break;

            case ParameterType.TexCoordGen:
                result = new TexCoordGenParameter();
                break;
            }

            result.data = ByteConverter.ToUInt32(file, address + 4);

            return(result);
        }
Пример #3
0
        public Mesh(byte[] file, int address, uint imageBase, IndexAttributeParameter index = null)
        {
            Parameters = new List <Parameter>();
            Primitives = new List <Primitive>();

            int parameters_offset = (int)(ByteConverter.ToInt32(file, address) - imageBase);
            int parameters_count  = ByteConverter.ToInt32(file, address + 4);

            int primitives_offset = (int)(ByteConverter.ToInt32(file, address + 8) - imageBase);
            int primitives_size   = ByteConverter.ToInt32(file, address + 12);

            ReadParameters(file, parameters_offset, parameters_count);

            IndexAttributeParameter index_param = (IndexAttributeParameter)Parameters.Find(x => x.ParameterType == ParameterType.IndexAttributeFlags);

            if (index_param == null)
            {
                index_param = index;
            }

            ReadPrimitives(file, primitives_offset, primitives_size, index_param);
        }
Пример #4
0
        public void Load(byte[] file, int address, uint imageBase, int count, GeometryType geometry_type)
        {
            for (int i = 0; i < count; i++)
            {
                Mesh new_mesh = new Mesh(file, address, imageBase, cur_attributes);

                if (new_mesh.Parameters.Exists(x => x.ParameterType == ParameterType.IndexAttributeFlags))
                {
                    cur_attributes = (IndexAttributeParameter)new_mesh.Parameters.Find(x => x.ParameterType == ParameterType.IndexAttributeFlags);
                }

                if (geometry_type == GeometryType.Translucent)
                {
                    TranslucentMeshes.Add(new_mesh);
                }
                else
                {
                    OpaqueMeshes.Add(new_mesh);
                }

                address += 16;
            }
        }
Пример #5
0
        public void WriteGeometryData(BinaryWriter writer, uint imageBase)
        {
            using (MemoryStream opaque = new MemoryStream(), translucent = new MemoryStream())
            {
                BinaryWriter opaque_writer = new BinaryWriter(opaque);
                BinaryWriter trans_writer  = new BinaryWriter(translucent);

                // First, write the mesh parameters for the two groups.

                foreach (Mesh m in OpaqueMeshes)
                {
                    opaque_writer.Write((int)(writer.BaseStream.Length + imageBase));
                    opaque_writer.Write((int)m.Parameters.Count);
                    opaque_writer.Write((int)0);                     // Placeholder for index data pointer
                    opaque_writer.Write((int)0);                     // Placeholder for index data size

                    foreach (Parameter p in m.Parameters)
                    {
                        p.Write(writer);
                    }
                }

                foreach (Mesh m in TranslucentMeshes)
                {
                    trans_writer.Write((int)(writer.BaseStream.Length + imageBase));
                    trans_writer.Write((int)m.Parameters.Count);
                    trans_writer.Write((int)0);                     // Placeholder for index data pointer
                    trans_writer.Write((int)0);                     // Placeholder for index data size

                    foreach (Parameter p in m.Parameters)
                    {
                        p.Write(writer);
                    }
                }

                // Reset the geometry header writers
                opaque_writer.Seek(0, SeekOrigin.Begin);
                trans_writer.Seek(0, SeekOrigin.Begin);

                // Second, write the primitive data for each mesh.

                IndexAttributeParameter cur_index_param = null;                 // This will hold the index parameters that are currently in use

                foreach (Mesh m in OpaqueMeshes)
                {
                    long init_file_pos = writer.BaseStream.Position;

                    opaque_writer.Seek(8, SeekOrigin.Current);
                    opaque_writer.Write((int)(init_file_pos + imageBase));

                    // Switch the index parameters if this mesh specifies new ones
                    if (m.Parameters.Exists(x => x.ParameterType == ParameterType.IndexAttributeFlags))
                    {
                        cur_index_param = (IndexAttributeParameter)m.Parameters.Find(x => x.ParameterType == ParameterType.IndexAttributeFlags);
                    }

                    foreach (Primitive p in m.Primitives)
                    {
                        p.Write(writer, cur_index_param);
                    }

                    PadMesh(writer, writer.BaseStream.Position - init_file_pos);

                    // Write the primitive data size
                    opaque_writer.Write((int)(writer.BaseStream.Position - init_file_pos));
                }

                foreach (Mesh m in TranslucentMeshes)
                {
                    long init_file_pos = writer.BaseStream.Position;

                    trans_writer.Seek(8, SeekOrigin.Current);
                    trans_writer.Write((int)(init_file_pos + imageBase));

                    // Switch the index parameters if this mesh specifies new ones
                    if (m.Parameters.Exists(x => x.ParameterType == ParameterType.IndexAttributeFlags))
                    {
                        cur_index_param = (IndexAttributeParameter)m.Parameters.Find(x => x.ParameterType == ParameterType.IndexAttributeFlags);
                    }

                    foreach (Primitive p in m.Primitives)
                    {
                        p.Write(writer, cur_index_param);
                    }

                    PadMesh(writer, writer.BaseStream.Position - init_file_pos);

                    // Write the primitive data size
                    trans_writer.Write((int)(writer.BaseStream.Position - init_file_pos));
                }

                // Lastly, append the mesh header data and update the file header.

                if (OpaqueMeshes.Count > 0)
                {
                    writer.Seek(8, SeekOrigin.Begin);
                    writer.Write((int)(writer.BaseStream.Length + imageBase));
                    writer.Seek(0, SeekOrigin.End);
                    writer.Write(opaque.ToArray());
                }

                if (TranslucentMeshes.Count > 0)
                {
                    writer.Seek(12, SeekOrigin.Begin);
                    writer.Write((int)(writer.BaseStream.Length + imageBase));
                    writer.Seek(0, SeekOrigin.End);
                    writer.Write(translucent.ToArray());
                }
            }
        }
Пример #6
0
        public void Write(BinaryWriter writer, IndexAttributeParameter attribute_parameters)
        {
            writer.Write((byte)PrimitiveType);

            byte[] big_endian_count = BitConverter.GetBytes((ushort)Vertices.Count);
            Array.Reverse(big_endian_count);
            writer.Write(big_endian_count);

            bool has_color  = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasColor);
            bool has_normal = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasNormal);
            bool has_uv     = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasUV);

            bool is_position_16bit = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.Position16BitIndex);
            bool is_color_16bit    = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.Color16BitIndex);
            bool is_normal_16bit   = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.Normal16BitIndex);
            bool is_uv_16bit       = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.UV16BitIndex);

            foreach (Vertex v in Vertices)
            {
                // Position should always exist

                if (is_position_16bit)
                {
                    byte[] big_endian_pos = BitConverter.GetBytes((ushort)v.PositionIndex);
                    Array.Reverse(big_endian_pos);
                    writer.Write(big_endian_pos);
                }
                else
                {
                    writer.Write((byte)v.PositionIndex);
                }

                if (has_normal)
                {
                    if (is_normal_16bit)
                    {
                        byte[] big_endian_nrm = BitConverter.GetBytes((ushort)v.NormalIndex);
                        Array.Reverse(big_endian_nrm);
                        writer.Write(big_endian_nrm);
                    }
                    else
                    {
                        writer.Write((byte)v.NormalIndex);
                    }
                }

                if (has_color)
                {
                    if (is_color_16bit)
                    {
                        byte[] big_endian_col = BitConverter.GetBytes((ushort)v.Color0Index);
                        Array.Reverse(big_endian_col);
                        writer.Write(big_endian_col);
                    }
                    else
                    {
                        writer.Write((byte)v.Color0Index);
                    }
                }

                if (has_uv)
                {
                    if (is_uv_16bit)
                    {
                        byte[] big_endian_uv = BitConverter.GetBytes((ushort)v.UVIndex);
                        Array.Reverse(big_endian_uv);
                        writer.Write(big_endian_uv);
                    }
                    else
                    {
                        writer.Write((byte)v.UVIndex);
                    }
                }
            }
        }
Пример #7
0
        private void ReadPrimitives(byte[] file, int address, int size, IndexAttributeParameter index_parameter)
        {
            int end_pos = address + size;

            while (address < end_pos)
            {
                if (file[address] == 0)
                {
                    address++;
                    continue;
                }

                Primitive prim = new Primitive((GXPrimitiveType)file[address]);

                short  raw_index_count = ByteConverter.ToInt16(file, address + 1);
                byte[] raw_index_bytes = ByteConverter.GetBytes(raw_index_count);

                int real_index_count = ByteConverter.ToInt16(new byte[] { raw_index_bytes[1], raw_index_bytes[0] }, 0);

                address += 3;

                for (int i = 0; i < real_index_count; i++)
                {
                    Vertex vert = new Vertex();

                    if (index_parameter.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasPosition))
                    {
                        bool is_16bit = index_parameter.IndexAttributes.HasFlag(
                            IndexAttributeParameter.IndexAttributeFlags.Position16BitIndex);

                        ushort raw_pos_index = is_16bit ? ByteConverter.ToUInt16(file, address) : file[address];

                        if (!is_16bit)
                        {
                            vert.PositionIndex = raw_pos_index;
                            address++;
                        }
                        else
                        {
                            byte[] pos_bytes = BitConverter.GetBytes(raw_pos_index);
                            Array.Reverse(pos_bytes);

                            vert.PositionIndex = BitConverter.ToUInt16(pos_bytes, 0);
                            address           += 2;
                        }
                    }
                    if (index_parameter.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasNormal))
                    {
                        bool is_16bit = index_parameter.IndexAttributes.HasFlag(
                            IndexAttributeParameter.IndexAttributeFlags.Normal16BitIndex);

                        ushort raw_nrm_index = is_16bit ? ByteConverter.ToUInt16(file, address) : file[address];

                        if (!is_16bit)
                        {
                            vert.NormalIndex = raw_nrm_index;
                            address++;
                        }
                        else
                        {
                            byte[] nrm_bytes = BitConverter.GetBytes(raw_nrm_index);
                            Array.Reverse(nrm_bytes);

                            vert.Color0Index = BitConverter.ToUInt16(nrm_bytes, 0);
                            address         += 2;
                        }
                    }
                    if (index_parameter.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasColor))
                    {
                        bool is_16bit = index_parameter.IndexAttributes.HasFlag(
                            IndexAttributeParameter.IndexAttributeFlags.Color16BitIndex);

                        ushort raw_col_index = is_16bit ? ByteConverter.ToUInt16(file, address) : file[address];

                        if (!is_16bit)
                        {
                            vert.Color0Index = raw_col_index;
                            address++;
                        }
                        else
                        {
                            byte[] col_bytes = BitConverter.GetBytes(raw_col_index);
                            Array.Reverse(col_bytes);

                            vert.Color0Index = BitConverter.ToUInt16(col_bytes, 0);
                            address         += 2;
                        }
                    }
                    if (index_parameter.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasUV))
                    {
                        bool is_16bit = index_parameter.IndexAttributes.HasFlag(
                            IndexAttributeParameter.IndexAttributeFlags.UV16BitIndex);

                        ushort raw_tex_index = is_16bit ? ByteConverter.ToUInt16(file, address) : file[address];

                        if (!is_16bit)
                        {
                            vert.UVIndex = raw_tex_index;
                            address++;
                        }
                        else
                        {
                            byte[] tex_bytes = BitConverter.GetBytes(raw_tex_index);
                            Array.Reverse(tex_bytes);

                            vert.UVIndex = BitConverter.ToUInt16(tex_bytes, 0);
                            address     += 2;
                        }
                    }

                    prim.Vertices.Add(vert);
                }

                Primitives.Add(prim);
            }
        }