Example #1
0
        private void WriteHashTable(BinaryWriter Writer, List <string> Elems)
        {
            Elems = Elems.Where(x => x != null).Distinct().ToList();

            Writer.Write((uint)Elems.Count);

            foreach (string Elem in Elems)
            {
                GFNV1 FNV = new GFNV1();

                byte[] Buffer = Encoding.ASCII.GetBytes(Elem);

                Array.Resize(ref Buffer, 0x40);

                foreach (byte b in Buffer)
                {
                    if (b == 0)
                    {
                        break;
                    }

                    FNV.Hash(b);
                }

                Writer.Write(FNV.HashCode);
                Writer.Write(Buffer);
            }
        }
Example #2
0
        public GFHashName(string Name)
        {
            GFNV1 FNV = new GFNV1();

            FNV.Hash(Name);

            Hash = FNV.HashCode;

            this.Name = Name;
        }
Example #3
0
        public GFModel(BinaryReader Reader, string ModelName) : this()
        {
            Name = ModelName;

            uint MagicNumber   = Reader.ReadUInt32();
            uint SectionsCount = Reader.ReadUInt32();

            GFSection.SkipPadding(Reader.BaseStream);

            GFSection ModelSection = new GFSection(Reader);

            GFHashName[] ShaderNames   = ReadHashTable(Reader);
            GFHashName[] TextureNames  = ReadHashTable(Reader);
            GFHashName[] MaterialNames = ReadHashTable(Reader);
            GFHashName[] MeshNames     = ReadHashTable(Reader);

            BBoxMinVector = Reader.ReadVector4();
            BBoxMaxVector = Reader.ReadVector4();
            Transform     = Reader.ReadMatrix4x4();

            //TODO: Investigate what is this (maybe Tile permissions?)
            uint  UnknownDataLength = Reader.ReadUInt32();
            uint  UnknownDataOffset = Reader.ReadUInt32();
            ulong Padding           = Reader.ReadUInt64();

            Reader.BaseStream.Seek(UnknownDataOffset + UnknownDataLength, SeekOrigin.Current);

            int BonesCount = Reader.ReadInt32();

            Reader.BaseStream.Seek(0xc, SeekOrigin.Current);

            for (int Index = 0; Index < BonesCount; Index++)
            {
                Skeleton.Add(new GFBone(Reader));
            }

            GFSection.SkipPadding(Reader.BaseStream);

            int LUTsCount = Reader.ReadInt32();
            int LUTLength = Reader.ReadInt32();

            GFSection.SkipPadding(Reader.BaseStream);

            for (int Index = 0; Index < LUTsCount; Index++)
            {
                LUTs.Add(new GFLUT(Reader, LUTLength));
            }

            for (int Index = 0; Index < MaterialNames.Length; Index++)
            {
                Materials.Add(new GFMaterial(Reader));
            }

            for (int Index = 0; Index < MeshNames.Length; Index++)
            {
                Meshes.Add(new GFMesh(Reader));
            }

            foreach (GFLUT LUT in LUTs)
            {
                foreach (GFHashName HN in TextureNames)
                {
                    GFNV1 FNV = new GFNV1();

                    FNV.Hash(HN.Name);

                    if (LUT.HashId == FNV.HashCode)
                    {
                        LUT.Name = HN.Name;

                        break;
                    }
                }
            }
        }
Example #4
0
        public void Write(BinaryWriter Writer)
        {
            long StartPosition = Writer.BaseStream.Position;

            new GFSection(MagicStr).Write(Writer);

            GFNV1 FNV = new GFNV1();

            FNV.Hash(Name);

            Writer.Write(FNV.HashCode);
            Writer.WritePaddedString(Name, 0x40);

            Writer.Write(0u);

            Writer.Write(BBoxMinVector);
            Writer.Write(BBoxMaxVector);

            Writer.Write((uint)SubMeshes.Count);

            Writer.Write(BoneIndicesPerVertex);

            Writer.Write(0xfffffffffffffffful);
            Writer.Write(0xfffffffffffffffful);

            for (int Index = 0; Index < SubMeshes.Count; Index++)
            {
                GFSubMesh SM = SubMeshes[Index];

                PICACommandWriter CmdWriter;

                /* Enable commands */
                CmdWriter = new PICACommandWriter();

                ulong BufferFormats     = 0;
                ulong BufferAttributes  = 0;
                ulong BufferPermutation = 0;
                int   AttributesTotal   = 0;

                //Normal Attributes
                for (int Attr = 0; Attr < SM.Attributes.Count; Attr++)
                {
                    PICAAttribute Attrib = SM.Attributes[Attr];

                    int Shift = AttributesTotal++ *4;

                    ulong AttribFmt;

                    AttribFmt  = (ulong)Attrib.Format;
                    AttribFmt |= (ulong)((Attrib.Elements - 1) & 3) << 2;

                    BufferFormats     |= AttribFmt << Shift;
                    BufferPermutation |= (ulong)Attrib.Name << Shift;
                    BufferAttributes  |= (ulong)Attr << Shift;
                }

                BufferAttributes |= (ulong)(SM.VertexStride & 0xff) << 48;
                BufferAttributes |= (ulong)SM.Attributes.Count << 60;

                //Fixed Attributes
                foreach (PICAFixedAttribute Attrib in SM.FixedAttributes)
                {
                    BufferFormats |= 1ul << (48 + AttributesTotal);

                    BufferPermutation |= (ulong)Attrib.Name << AttributesTotal++ *4;
                }

                BufferFormats |= (ulong)(AttributesTotal - 1) << 60;

                CmdWriter.SetCommand(PICARegister.GPUREG_VSH_INPUTBUFFER_CONFIG, 0xa0000000u | (uint)(AttributesTotal - 1), 0xb);

                CmdWriter.SetCommand(PICARegister.GPUREG_VSH_NUM_ATTR, (uint)(AttributesTotal - 1), 1);

                CmdWriter.SetCommand(PICARegister.GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW, (uint)(BufferPermutation >> 0));
                CmdWriter.SetCommand(PICARegister.GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH, (uint)(BufferPermutation >> 32));

                CmdWriter.SetCommand(PICARegister.GPUREG_ATTRIBBUFFERS_LOC, true,
                                     0x03000000u, //Base Address (Place holder)
                                     (uint)(BufferFormats >> 0),
                                     (uint)(BufferFormats >> 32),
                                     0x99999999u, //Attributes Buffer Address (Place holder)
                                     (uint)(BufferAttributes >> 0),
                                     (uint)(BufferAttributes >> 32));

                for (int Attr = 0; Attr < SM.FixedAttributes.Count; Attr++)
                {
                    PICAFixedAttribute Attrib = SM.FixedAttributes[Attr];

                    float Scale =
                        Attrib.Name == PICAAttributeName.Color ||
                        Attrib.Name == PICAAttributeName.BoneWeight ? GFMesh.Scales[1] : 1;

                    PICAFixedAttribute ScaledAttribute = new PICAFixedAttribute()
                    {
                        Name  = Attrib.Name,
                        Value = new PICAVectorFloat24(Attrib.Value.X, Attrib.Value.Y, Attrib.Value.Z, Attrib.Value.W) / Scale
                    };

                    CmdWriter.SetCommand(PICARegister.GPUREG_FIXEDATTRIB_INDEX, true,
                                         (uint)(SM.Attributes.Count + Attr),
                                         ScaledAttribute.Value.Word0,
                                         ScaledAttribute.Value.Word1,
                                         ScaledAttribute.Value.Word2);
                }

                CmdWriter.WriteEnd();

                WriteCmdsBuff(Writer, CmdWriter.GetBuffer(), Index * 3);

                /* Disable commands */
                CmdWriter = new PICACommandWriter();

                //Assuming that the Position isn't used as Fixed Attribute since this doesn't make sense.
                CmdWriter.SetCommand(PICARegister.GPUREG_ATTRIBBUFFER0_OFFSET, true, 0, 0, 0);

                for (int Attr = 1; Attr < 12; Attr++)
                {
                    CmdWriter.SetCommand(PICARegister.GPUREG_ATTRIBBUFFER0_CONFIG2 + Attr * 3, 0);

                    if (SM.FixedAttributes?.Any(x => (int)x.Name == Attr) ?? false)
                    {
                        CmdWriter.SetCommand(PICARegister.GPUREG_FIXEDATTRIB_INDEX, true, (uint)Attr, 0, 0, 0);
                    }
                }

                CmdWriter.WriteEnd();

                WriteCmdsBuff(Writer, CmdWriter.GetBuffer(), Index * 3 + 1);

                /* Index commands */
                CmdWriter = new PICACommandWriter();

                uint IdxFmtAddr = SM.IsIdx8Bits
                    ? 0x01999999u
                    : 0x81999999u;

                CmdWriter.SetCommand(PICARegister.GPUREG_RESTART_PRIMITIVE, true);

                CmdWriter.SetCommand(PICARegister.GPUREG_INDEXBUFFER_CONFIG, IdxFmtAddr);

                CmdWriter.SetCommand(PICARegister.GPUREG_NUMVERTICES, (uint)SM.Indices.Length);

                CmdWriter.SetCommand(PICARegister.GPUREG_START_DRAW_FUNC0, false, 1);

                CmdWriter.SetCommand(PICARegister.GPUREG_DRAWELEMENTS, true);

                CmdWriter.SetCommand(PICARegister.GPUREG_START_DRAW_FUNC0, true, 1);

                CmdWriter.SetCommand(PICARegister.GPUREG_VTX_FUNC, true);

                CmdWriter.SetCommand(PICARegister.GPUREG_PRIMITIVE_CONFIG, (uint)SM.PrimitiveMode << 8, 8);
                CmdWriter.SetCommand(PICARegister.GPUREG_PRIMITIVE_CONFIG, (uint)SM.PrimitiveMode << 8, 8);

                CmdWriter.WriteEnd();

                WriteCmdsBuff(Writer, CmdWriter.GetBuffer(), Index * 3 + 2);
            }

            foreach (GFSubMesh SM in SubMeshes)
            {
                FNV = new GFNV1();

                FNV.Hash(SM.Name);

                Writer.Write(FNV.HashCode);
                Writer.Write(GetPaddedLen4(SM.Name.Length));
                Writer.WritePaddedString(SM.Name, GetPaddedLen4(SM.Name.Length));

                Writer.Write(SM.BoneIndicesCount);

                byte[] BoneIndices = new byte[0x1f];

                SM.BoneIndices.CopyTo(BoneIndices, 0);

                Writer.Write(BoneIndices);

                int VerticesCount = 0;

                if (SM.VertexStride != 0)
                {
                    VerticesCount = SM.RawBuffer.Length / SM.VertexStride;
                }

                int VtxBuffLen = SM.RawBuffer.Length;
                int IdxBuffLen = SM.Indices.Length * (SM.IsIdx8Bits ? 1 : 2);

                Writer.Write(VerticesCount);
                Writer.Write(SM.Indices.Length);
                Writer.Write(GetPaddedLen16(VtxBuffLen));
                Writer.Write(GetPaddedLen16(IdxBuffLen));
            }

            foreach (GFSubMesh SM in SubMeshes)
            {
                long Position = Writer.BaseStream.Position;

                Writer.Write(SM.RawBuffer);

                int VertexBufferPaddingLength = GetPaddedLen16(SM.RawBuffer.Length) - SM.RawBuffer.Length;
                Writer.Write(new byte[VertexBufferPaddingLength]);

                /*while (((Writer.BaseStream.Position - Position) & 3) != 0)
                 * {
                 *  Writer.Write((byte)0);
                 * }*/

                Position = Writer.BaseStream.Position;

                foreach (ushort Idx in SM.Indices)
                {
                    if (SM.IsIdx8Bits)
                    {
                        Writer.Write((byte)Idx);
                    }
                    else
                    {
                        Writer.Write(Idx);
                    }
                }

                /*while (((Writer.BaseStream.Position - Position) & 0xf) != 0)
                 * {
                 *  Writer.Write((byte)0);
                 * }*/
                int IndexBufferLength        = SM.Indices.Length * (SM.IsIdx8Bits ? 1 : 2);
                int IndexBufferPaddingLength = GetPaddedLen16(IndexBufferLength) - IndexBufferLength;
                Writer.Write(new byte[IndexBufferPaddingLength]);
            }

            Writer.Align(0x10, 0);

            Writer.Write(0ul);
            Writer.Write(0ul);

            long EndPosition = Writer.BaseStream.Position;

            Writer.BaseStream.Seek(StartPosition + 8, SeekOrigin.Begin);

            Writer.Write((uint)(EndPosition - StartPosition - 0x10));

            Writer.BaseStream.Seek(EndPosition, SeekOrigin.Begin);
        }