Exemple #1
0
 /// <summary>
 /// Writes the buffer vertex to a stream
 /// </summary>
 /// <param name="writer">Output stream</param>
 public void Write(EndianWriter writer)
 {
     Position.Write(writer, IOType.Float);
     Normal.Write(writer, IOType.Float);
     writer.WriteUInt16(Index);
     writer.WriteUInt16((ushort)(Weight * ushort.MaxValue));
 }
Exemple #2
0
        /// <summary>
        /// Writes the buffer mesh to a stream
        /// </summary>
        /// <param name="writer">Output stream</param>
        public uint Write(EndianWriter writer, uint imageBase)
        {
            uint vtxAddr = 0;

            if (Vertices != null)
            {
                vtxAddr = writer.Position + imageBase;
                foreach (BufferVertex vtx in Vertices)
                {
                    vtx.Write(writer);
                }
            }

            uint cornerAddr = 0;

            if (Corners != null)
            {
                cornerAddr = writer.Position + imageBase;
                foreach (BufferCorner c in Corners)
                {
                    c.Write(writer);
                }
            }

            uint triangleAddr = 0;

            if (TriangleList != null)
            {
                triangleAddr = writer.Position + imageBase;
                foreach (uint t in TriangleList)
                {
                    writer.WriteUInt32(t);
                }
            }

            uint address = writer.Position + imageBase;

            writer.WriteUInt16((ushort)(Vertices == null ? 0 : Vertices.Length));
            writer.WriteUInt16((ushort)(ContinueWeight ? 1u : 0u));
            writer.WriteUInt32((uint)(Corners == null ? 0 : Corners.Length));
            writer.WriteUInt32((uint)(TriangleList == null ? 0 : TriangleList.Length));
            if (Material == null)
            {
                writer.Write(new byte[32]);
            }
            else
            {
                Material.Write(writer);
            }
            writer.WriteUInt32(vtxAddr);
            writer.WriteUInt32(cornerAddr);
            writer.WriteUInt32(triangleAddr);

            return(address);
        }
Exemple #3
0
 internal static void DefaultWrite(this IPoly poly, EndianWriter writer)
 {
     foreach (ushort i in poly.Indices)
     {
         writer.WriteUInt16(i);
     }
 }
Exemple #4
0
            /// <summary>
            /// Writes the strip to a byte stream
            /// </summary>
            /// <param name="writer">Output stream</param>
            /// <param name="userAttribs">Amount of user attributes</param>
            /// <param name="hasUV">Whether the polygons carry uv data</param>
            /// <param name="HDUV">Whether the uv data repeats at 1024, not 256</param>
            /// <param name="hasNormal">Whether the polygons carry normal data</param>
            /// <param name="hasColor">Whether the polygons carry color data</param>
            public void Write(EndianWriter writer, byte userAttribs, bool hasUV, bool HDUV, bool hasNormal, bool hasColor)
            {
                short length = (short)Math.Min(Corners.Length, short.MaxValue);

                writer.WriteInt16(Reversed ? (short)-length : length);

                bool  flag1      = userAttribs > 0;
                bool  flag2      = userAttribs > 1;
                bool  flag3      = userAttribs > 2;
                float multiplier = HDUV ? 1024 : 256;

                for (int i = 0; i < length; i++)
                {
                    Corner c = Corners[i];
                    writer.WriteUInt16(c.Index);
                    if (hasUV)
                    {
                        (c.Texcoord * multiplier).Write(writer, IOType.Short);
                    }
                    if (hasNormal)
                    {
                        c.Normal.Write(writer, IOType.Float);
                    }
                    else if (hasColor)
                    {
                        c.Color.Write(writer, IOType.ARGB8_16);
                    }


                    if (flag1 && i > 1)
                    {
                        writer.WriteUInt16(c.UserFlag1);
                        if (flag2)
                        {
                            writer.WriteUInt16(c.UserFlag2);
                            if (flag3)
                            {
                                writer.WriteUInt16(c.UserFlag3);
                            }
                        }
                    }
                }
            }
Exemple #5
0
        /// <summary>
        /// Updates any changes made to the object data.
        /// </summary>
        /// <param name="reader">
        /// The EndianWriter to write to.
        /// It should point to the same stream that was used to load the object data, as seeking will be done automatically.
        /// </param>
        public virtual void Update(EndianWriter writer)
        {
            // Strength info
            long chunkStartOffset = _entry.ObjectAddress + (long)TableOffset.ObjectPool;

            writer.SeekTo(chunkStartOffset + StrengthInfoOffset);
            _healthInfo.WriteTo(writer);

            // BSP Zone
            writer.SeekTo(chunkStartOffset + 0x18);
            writer.WriteUInt16(_zone);

            // Position1
            writer.SeekTo(chunkStartOffset + PositionOffset1);
            writer.WriteFloat(_positionMain.X);
            writer.WriteFloat(_positionMain.Y);
            writer.WriteFloat(_positionMain.Z);

            // Calculate extra position vectors
            Vector3 position2 = Vector3.Add(_position2Delta, _positionMain);
            Vector3 position3 = Vector3.Add(_position3Delta, _positionMain);
            Vector3 position4 = Vector3.Add(_position4Delta, _positionMain);

            // Position2
            writer.SeekTo(chunkStartOffset + PositionOffset2);
            writer.WriteFloat(position2.X);
            writer.WriteFloat(position2.Y);
            writer.WriteFloat(position2.Z);

            // Position3
            writer.SeekTo(chunkStartOffset + PositionOffset3);
            writer.WriteFloat(position3.X);
            writer.WriteFloat(position3.Y);
            writer.WriteFloat(position3.Z);

            // Position4
            writer.SeekTo(chunkStartOffset + PositionOffset4);
            writer.WriteFloat(position4.X);
            writer.WriteFloat(position4.Y);
            writer.WriteFloat(position4.Z);
        }
Exemple #6
0
 /// <summary>
 /// Write the chunk to a stream
 /// </summary>
 /// <param name="writer">Output stream</param>
 public virtual void Write(EndianWriter writer)
 {
     writer.WriteUInt16((ushort)((byte)Type | (ushort)(Attributes << 8)));
 }
Exemple #7
0
 /// <summary>
 /// Writes the buffer corner to a stream
 /// </summary>
 /// <param name="writer">Output stream</param>
 public void Write(EndianWriter writer)
 {
     writer.WriteUInt16(VertexIndex);
     Color.Write(writer, IOType.ARGB8_32);
     Texcoord.Write(writer, IOType.Float);
 }
Exemple #8
0
        private void WriteChunks(SerializingContainer2 sc)
        {
            EndianWriter writer = sc.ms.Writer;

            if (EmbeddedFiles.Count > 0)
            {
                writer.WriteUInt32(didx);
                writer.WriteInt32(EmbeddedFiles.Count * 12);
                var dataChunk = new MemoryStream();
                foreach ((uint id, byte[] bytes) in EmbeddedFiles)
                {
                    dataChunk.WriteZeros((int)(dataChunk.Position.Align(16) - dataChunk.Position)); //files must be 16-byte aligned in the data chunk
                    writer.WriteUInt32(id);                                                         //writing to DIDX
                    writer.WriteInt32((int)dataChunk.Position);                                     //Writing to DIDX
                    writer.WriteInt32(bytes.Length);                                                //Writing to DIDX
                    dataChunk.WriteFromBuffer(bytes);                                               //Writing to DATA
                }

                writer.WriteUInt32(data);
                writer.WriteInt32((int)dataChunk.Length);
                writer.WriteFromBuffer(dataChunk.ToArray());
            }

            if (sc.Game == MEGame.ME2 && ME2STMGFallback != null)
            {
                writer.WriteUInt32(stmg);
                writer.WriteInt32(ME2STMGFallback.Length);
                writer.WriteFromBuffer(ME2STMGFallback);
            }

            if (sc.Game == MEGame.ME3 && InitStateManagement != null)
            {
                writer.WriteUInt32(stmg);
                var lenPos = sc.ms.Position;
                writer.WriteUInt32(0);
                writer.WriteFloat(InitStateManagement.VolumeThreshold);
                writer.WriteUInt16(InitStateManagement.MaxVoiceInstances);
                writer.WriteInt32(InitStateManagement.StateGroups.Count);
                foreach ((uint _, WwiseStateManagement.StateGroup stateGroup) in InitStateManagement.StateGroups)
                {
                    writer.WriteUInt32(stateGroup.ID);
                    writer.WriteUInt32(stateGroup.DefaultTransitionTime);
                    writer.WriteInt32(stateGroup.CustomTransitionTimes.Count);
                    foreach (var transTime in stateGroup.CustomTransitionTimes)
                    {
                        writer.WriteUInt32(transTime.FromStateID);
                        writer.WriteUInt32(transTime.ToStateID);
                        writer.WriteUInt32(transTime.TransitionTime);
                    }
                }
                writer.WriteInt32(InitStateManagement.SwitchGroups.Count);
                foreach ((uint _, WwiseStateManagement.SwitchGroup switchGroup) in InitStateManagement.SwitchGroups)
                {
                    writer.WriteUInt32(switchGroup.ID);
                    writer.WriteUInt32(switchGroup.GameParamID);
                    writer.WriteInt32(switchGroup.Points.Count);
                    foreach (var point in switchGroup.Points)
                    {
                        writer.WriteFloat(point.GameParamValue);
                        writer.WriteUInt32(point.SwitchID);
                        writer.WriteUInt32(point.CurveShape);
                    }
                }
                writer.WriteInt32(InitStateManagement.GameParameterDefaultValues.Count);
                foreach ((uint id, float defaultValue) in InitStateManagement.GameParameterDefaultValues)
                {
                    writer.WriteUInt32(id);
                    writer.WriteFloat(defaultValue);
                }
                var endPos = sc.ms.Position;
                sc.ms.JumpTo(lenPos);
                writer.WriteInt32((int)(endPos - lenPos - 4));
                sc.ms.JumpTo(endPos);
            }

            if (HIRCObjects.Count > 0)
            {
                writer.WriteUInt32(hirc);
                var lengthPos = sc.ms.Position;
                writer.WriteUInt32(0);
                writer.WriteInt32(HIRCObjects.Count);
                foreach ((uint _, HIRCObject h) in HIRCObjects)
                {
                    writer.WriteFromBuffer(h.ToBytes(sc.Game));
                }

                var endPos = sc.ms.Position;
                sc.ms.JumpTo(lengthPos);
                writer.WriteInt32((int)(endPos - lengthPos - 4));
                sc.ms.JumpTo(endPos);
            }

            if (ReferencedBanks.Count > 0)
            {
                writer.WriteUInt32(stid);
                var lengthPos = sc.ms.Position;
                writer.WriteUInt32(0);
                writer.WriteUInt32(1);
                writer.WriteInt32(ReferencedBanks.Count);
                foreach ((uint id, string name) in ReferencedBanks)
                {
                    writer.WriteUInt32(id);
                    writer.WriteByte((byte)name.Length);
                    writer.WriteStringASCII(name);
                }

                var endPos = sc.ms.Position;
                sc.ms.JumpTo(lengthPos);
                writer.WriteInt32((int)(endPos - lengthPos - 4));
                sc.ms.JumpTo(endPos);
            }

            if (FXPR_Chunk != null)
            {
                writer.WriteUInt32(fxpr);
                writer.WriteInt32(FXPR_Chunk.Length);
                writer.WriteFromBuffer(FXPR_Chunk);
            }

            if (ENVS_Chunk != null)
            {
                writer.WriteUInt32(envs);
                writer.WriteInt32(ENVS_Chunk.Length);
                writer.WriteFromBuffer(ENVS_Chunk);
            }
        }
Exemple #9
0
        public override uint Write(EndianWriter writer, uint imageBase, bool DX, Dictionary <string, uint> labels)
        {
            VertexSet[] sets         = VertexData.Values.ToArray();
            uint[]      vtxAddresses = new uint[VertexData.Count];
            for (int i = 0; i < sets.Length; i++)
            {
                VertexSet vtxSet = sets[i];
                vtxAddresses[i] = writer.Position + imageBase;
                IOType outputType = vtxSet.DataType.ToStructType();

                switch (vtxSet.Attribute)
                {
                case VertexAttribute.Position:
                case VertexAttribute.Normal:
                    foreach (Vector3 vec in vtxSet.Vector3Data)
                    {
                        vec.Write(writer, outputType);
                    }
                    break;

                case VertexAttribute.Color0:
                case VertexAttribute.Color1:
                    foreach (Color col in vtxSet.ColorData)
                    {
                        col.Write(writer, outputType);
                    }
                    break;

                case VertexAttribute.Tex0:
                case VertexAttribute.Tex1:
                case VertexAttribute.Tex2:
                case VertexAttribute.Tex3:
                case VertexAttribute.Tex4:
                case VertexAttribute.Tex5:
                case VertexAttribute.Tex6:
                case VertexAttribute.Tex7:
                    foreach (Vector2 uv in vtxSet.UVData)
                    {
                        (uv * 256).Write(writer, outputType);
                    }
                    break;

                case VertexAttribute.PositionMatrixId:
                case VertexAttribute.Null:
                default:
                    throw new FormatException($"Vertex set had an invalid or unavailable type: {vtxSet.Attribute}");
                }
            }

            uint vtxAddr = writer.Position + imageBase;

            // writing vertex attributes
            for (int i = 0; i < sets.Length; i++)
            {
                VertexSet vtxSet = sets[i];

                writer.Write(new byte[] { (byte)vtxSet.Attribute, (byte)vtxSet.StructSize });
                writer.WriteUInt16((ushort)vtxSet.DataLength);

                uint structure = (uint)vtxSet.StructType;
                structure |= (uint)((byte)vtxSet.DataType << 4);
                writer.WriteUInt32(structure);

                writer.WriteUInt32(vtxAddresses[i]);
                writer.WriteUInt32((uint)(vtxSet.DataLength * vtxSet.StructSize));
            }

            // empty vtx attribute
            byte[] nullVtx = new byte[16];
            nullVtx[0] = 0xFF;
            writer.Write(nullVtx);

            // writing geometry data
            uint[] WriteMeshData(Mesh[] meshes)
            {
                uint[]          result       = new uint[meshes.Length * 4];
                IndexAttributes indexAttribs = IndexAttributes.HasPosition;

                for (int i = 0, ri = 0; i < meshes.Length; i++, ri += 4)
                {
                    Mesh m = meshes[i];

                    IndexAttributes?t = m.IndexAttributes;
                    if (t.HasValue)
                    {
                        indexAttribs = t.Value;
                    }

                    // writing parameters
                    result[ri]     = writer.Position + imageBase;
                    result[ri + 1] = (uint)m.Parameters.Length;
                    foreach (IParameter p in m.Parameters)
                    {
                        p.Write(writer);
                    }

                    // writing polygons
                    uint addr = writer.Position;
                    foreach (Poly p in m.Polys)
                    {
                        p.Write(writer, indexAttribs);
                    }
                    result[ri + 2] = addr + imageBase;
                    result[ri + 3] = writer.Position - addr;
                }
                return(result);
            }

            uint[] opaqueMeshStructs      = WriteMeshData(OpaqueMeshes);
            uint[] transparentMeshStructs = WriteMeshData(TransparentMeshes);

            // writing geometry properties
            uint opaqueAddress = writer.Position + imageBase;

            foreach (uint i in opaqueMeshStructs)
            {
                writer.Write(i);
            }

            uint transparentAddress = writer.Position + imageBase;

            foreach (uint i in transparentMeshStructs)
            {
                writer.Write(i);
            }

            uint address = writer.Position + imageBase;

            labels.AddLabel(Name, address);

            writer.WriteUInt32(vtxAddr);
            writer.WriteUInt32(0);
            writer.WriteUInt32(opaqueAddress);
            writer.WriteUInt32(transparentAddress);
            writer.WriteUInt16((ushort)OpaqueMeshes.Length);
            writer.WriteUInt16((ushort)TransparentMeshes.Length);
            MeshBounds.Write(writer);
            return(address);
        }
Exemple #10
0
        public override uint Write(EndianWriter writer, uint imageBase, bool DX, Dictionary <string, uint> labels)
        {
            // writing positions
            uint posAddress;

            if (labels.ContainsKey(PositionName))
            {
                posAddress = labels[PositionName];
            }
            else
            {
                posAddress = writer.Position + imageBase;
                labels.AddLabel(PositionName, posAddress);
                foreach (Vector3 p in Positions)
                {
                    p.Write(writer, IOType.Float);
                }
            }

            // writing normals
            uint nrmAddress = 0;

            if (Normals != null)
            {
                if (labels.ContainsKey(NormalName))
                {
                    nrmAddress = labels[NormalName];
                }
                else
                {
                    nrmAddress = writer.Position + imageBase;
                    labels.AddLabel(NormalName, nrmAddress);
                    foreach (Vector3 p in Normals)
                    {
                        p.Write(writer, IOType.Float);
                    }
                }
            }

            // writing meshsets
            uint meshAddress;

            if (labels.ContainsKey(MeshName))
            {
                meshAddress = labels[MeshName];
            }
            else
            {
                // writing meshset data
                foreach (Mesh m in Meshes)
                {
                    m.WriteData(writer, imageBase, labels);
                }

                meshAddress = writer.Position + imageBase;
                labels.AddLabel(MeshName, meshAddress);
                foreach (Mesh m in Meshes)
                {
                    m.WriteMeshset(writer, DX, labels);
                }
            }

            // writing materials
            uint materialAddress;

            if (labels.ContainsKey(MaterialName))
            {
                materialAddress = labels[MaterialName];
            }
            else
            {
                materialAddress = writer.Position + imageBase;
                labels.AddLabel(MaterialName, materialAddress);
                foreach (Material m in Materials)
                {
                    m.Write(writer);
                }
            }

            // writing the attach

            uint outAddress = writer.Position + imageBase;

            labels.AddLabel(Name, outAddress);

            writer.WriteUInt32(posAddress);
            writer.WriteUInt32(nrmAddress);
            writer.WriteUInt32((uint)Positions.Length);
            writer.WriteUInt32(meshAddress);
            writer.WriteUInt32(materialAddress);
            writer.WriteUInt16((ushort)Meshes.Length);
            writer.WriteUInt16((ushort)Materials.Length);
            MeshBounds.Write(writer);
            if (DX)
            {
                writer.WriteUInt32(0);
            }

            return(outAddress);
        }
Exemple #11
0
        /// <summary>
        /// Writes the landtable to a stream
        /// </summary>
        /// <param name="writer">Output stream</param>
        /// <param name="imageBase">Image base for all addresses</param>
        /// <param name="labels">C struct labels</param>
        /// <returns></returns>
        public uint Write(EndianWriter writer, uint imageBase, Dictionary <string, uint> labels)
        {
            // sort the landentries
            HashSet <Attach> attaches = new();

            ushort visCount = 0;

            if (Format > LandtableFormat.SADX && Format != LandtableFormat.Buffer)
            {
                List <LandEntry> visual = new();
                List <LandEntry> basic  = new();

                foreach (LandEntry le in Geometry)
                {
                    if (le.Attach.Format == AttachFormat.BASIC)
                    {
                        basic.Add(le);
                    }
                    else
                    {
                        visual.Add(le);
                    }
                    attaches.Add(le.Attach);
                }

                Geometry.Clear();
                Geometry.AddRange(visual);
                Geometry.AddRange(basic);
                visCount = (ushort)visual.Count;
            }
            else
            {
                foreach (LandEntry le in Geometry)
                {
                    attaches.Add(le.Attach);
                }
            }

            foreach (LandEntryMotion lem in GeometryAnimations)
            {
                NJObject[] models = lem.Model.GetObjects();
                foreach (NJObject mdl in models)
                {
                    if (mdl.Attach != null)
                    {
                        attaches.Add(mdl.Attach);
                    }
                }
            }

            // writing all attaches
            if (Format == LandtableFormat.Buffer)
            {
                foreach (var atc in attaches)
                {
                    atc.WriteBuffer(writer, imageBase, labels);
                }
            }
            else
            {
                foreach (var atc in attaches)
                {
                    atc.Write(writer, imageBase, false, labels);
                }
            }

            var t = labels.GroupBy(x => x.Value).Where(x => x.Count() > 1).ToList();

            // write the landentry models
            foreach (LandEntry le in Geometry)
            {
                le.WriteModel(writer, imageBase, labels);
            }

            // write the landentry motion models
            foreach (LandEntryMotion lem in GeometryAnimations)
            {
                lem.Model.Write(writer, imageBase, labels);
            }

            Dictionary <Action, uint> actionAddresses = new();

            // write the landentry motion animations
            foreach (LandEntryMotion lem in GeometryAnimations)
            {
                actionAddresses.Add(lem.MotionAction, lem.MotionAction.Write(writer, imageBase, Format == LandtableFormat.SADX, Format == LandtableFormat.Buffer, labels));
            }

            // writing the geometry list
            uint geomAddr = 0;

            if (Geometry.Count > 0)
            {
                if (labels.ContainsKey(GeoName))
                {
                    geomAddr = labels[GeoName];
                }
                else
                {
                    geomAddr = writer.Position + imageBase;
                    labels.AddLabel(GeoName, geomAddr);
                    foreach (LandEntry le in Geometry)
                    {
                        le.Write(writer, Format, labels);
                    }
                }
            }

            // writing the animation list
            uint animAddr = 0;

            if (GeometryAnimations.Count > 0)
            {
                if (labels.ContainsKey(GeoAnimName))
                {
                    animAddr = labels[GeoAnimName];
                }
                else
                {
                    animAddr = writer.Position + imageBase;
                    labels.AddLabel(GeoAnimName, animAddr);
                    foreach (LandEntryMotion lem in GeometryAnimations)
                    {
                        lem.Write(writer, actionAddresses, labels);
                    }
                }
            }

            // write the texture name
            uint texNameAddr = 0;

            if (TextureFileName != null)
            {
                texNameAddr = writer.Position + imageBase;
                writer.Write(Encoding.ASCII.GetBytes(TextureFileName));
                writer.Write(new byte[1]);
            }

            // write the landtable struct itself
            uint address = writer.Position + imageBase;

            writer.WriteUInt16((ushort)Geometry.Count);
            if (Format < LandtableFormat.SA2) // sa1 + sadx
            {
                writer.WriteUInt16((ushort)GeometryAnimations.Count);
                writer.WriteUInt32((uint)Attributes);
                writer.WriteSingle(DrawDistance);
                writer.WriteUInt32(geomAddr);
                writer.WriteUInt32(animAddr);
                writer.WriteUInt32(texNameAddr);
                writer.WriteUInt32(TexListPtr);
                writer.WriteUInt64(0); // two unused pointers
            }
            else // sa2 + sa2b
            {
                writer.WriteUInt16(visCount);
                writer.WriteUInt64(0); // todo: figure out what these do
                writer.WriteSingle(DrawDistance);
                writer.WriteUInt32(geomAddr);
                writer.WriteUInt32(animAddr);
                writer.WriteUInt32(texNameAddr);
                writer.WriteUInt32(TexListPtr);
            }

            labels.AddLabel(Name, address);
            return(address);
        }
Exemple #12
0
 public void Write(EndianWriter writer)
 {
     writer.WriteUInt16((ushort)((Indices.Length & 0x7FFF) | (Reversed ? 0x8000 : 0)));
     this.DefaultWrite(writer);
 }