Пример #1
0
            internal void Write(BinaryWriterEx bw)
            {
                long start = bw.Position;

                bw.ReserveInt64("NameOffset");
                bw.WriteUInt32((uint)Type);
                bw.WriteInt32(ID);
                bw.WriteInt32(modelIndex);
                bw.WriteInt32(0);
                bw.ReserveInt64("PlaceholderOffset");
                bw.WriteVector3(Position);
                bw.WriteVector3(Rotation);
                bw.WriteVector3(Scale);

                bw.WriteUInt32(DrawGroup1);
                bw.WriteUInt32(DrawGroup2);
                bw.WriteUInt32(DrawGroup3);
                bw.WriteUInt32(DrawGroup4);
                bw.WriteUInt32(DispGroup1);
                bw.WriteUInt32(DispGroup2);
                bw.WriteUInt32(DispGroup3);
                bw.WriteUInt32(DispGroup4);

                bw.WriteInt32(UnkF01);
                bw.WriteInt32(UnkF02);
                bw.WriteInt32(UnkF03);
                bw.WriteInt32(UnkF04);
                bw.WriteInt32(UnkF05);
                bw.WriteInt32(UnkF06);
                bw.WriteInt32(UnkF07);
                bw.WriteInt32(UnkF08);
                bw.WriteInt32(UnkF09);
                bw.WriteInt32(UnkF10);
                bw.WriteInt32(UnkF11);
                bw.WriteInt32(UnkF12);
                bw.WriteInt32(UnkF13);
                bw.WriteInt32(UnkF14);
                bw.WriteInt32(UnkF15);
                bw.WriteInt32(UnkF16);
                bw.WriteInt32(UnkF17);
                bw.WriteInt32(UnkF18);
                bw.WriteInt32(0);

                bw.ReserveInt64("BaseDataOffset");
                bw.ReserveInt64("TypeDataOffset");
                bw.ReserveInt64("UnkOffset1");
                bw.ReserveInt64("UnkOffset2");

                bw.FillInt64("NameOffset", bw.Position - start);
                bw.WriteUTF16(Name, true);
                if (Placeholder == null)
                {
                    bw.FillInt64("PlaceholderOffset", 0);
                }
                else
                {
                    bw.FillInt64("PlaceholderOffset", bw.Position - start);
                    bw.WriteUTF16(Placeholder, true);
                }
                bw.Pad(8);

                bw.FillInt64("BaseDataOffset", bw.Position - start);
                bw.WriteInt32(EventEntityID);

                bw.WriteSByte(LightID);
                bw.WriteSByte(FogID);
                bw.WriteSByte(ScatterID);
                bw.WriteSByte(LensFlareID);

                bw.WriteInt32(0);

                bw.WriteSByte(LanternID);
                bw.WriteSByte(LodParamID);
                bw.WriteSByte(UnkB0E);
                bw.WriteBoolean(IsShadowDest);

                bw.WriteBoolean(IsShadowOnly);
                bw.WriteBoolean(DrawByReflectCam);
                bw.WriteBoolean(DrawOnlyReflectCam);
                bw.WriteBoolean(UseDepthBiasFloat);

                bw.WriteBoolean(DisablePointLightEffect);
                bw.WriteByte(UnkB15);
                bw.WriteByte(UnkB16);
                bw.WriteByte(UnkB17);

                bw.WriteInt32(UnkB18);
                bw.WriteInt32(UnkB1C);
                bw.WriteInt32(UnkB20);
                bw.WriteInt32(UnkB24);
                bw.WriteInt32(UnkB28);
                bw.WriteInt32(-1);
                bw.WriteInt32(UnkB30);
                bw.WriteInt32(UnkB34);
                bw.WriteInt32(UnkB38);
                bw.WriteInt32(0);

                bw.FillInt64("TypeDataOffset", bw.Position - start);
                if (UnkOffset1Delta == 0)
                {
                    bw.FillInt64("UnkOffset1", 0);
                }
                else
                {
                    bw.FillInt64("UnkOffset1", bw.Position - start + UnkOffset1Delta);
                }

                if (UnkOffset2Delta == 0)
                {
                    bw.FillInt64("UnkOffset2", 0);
                }
                else
                {
                    bw.FillInt64("UnkOffset2", bw.Position - start + UnkOffset2Delta);
                }

                WriteSpecific(bw);
            }
Пример #2
0
            internal override void Write(BinaryWriterEx bw)
            {
                long start = bw.Position;

                bw.ReserveInt64("NameOffset");
                bw.WriteUInt32((uint)Type);
                bw.WriteInt32(ID);
                bw.WriteUInt32((uint)Shape.Type);
                bw.WriteVector3(Position);
                bw.WriteVector3(Rotation);
                bw.WriteInt32(Unk2C);
                bw.ReserveInt64("BaseDataOffset1");
                bw.ReserveInt64("BaseDataOffset2");
                bw.WriteInt32(-1);
                bw.WriteInt32(MapStudioLayer);
                bw.ReserveInt64("ShapeDataOffset");
                bw.ReserveInt64("BaseDataOffset3");
                bw.ReserveInt64("TypeDataOffset");

                bw.FillInt64("NameOffset", bw.Position - start);
                bw.WriteUTF16(Name, true);
                bw.Pad(4);

                bw.FillInt64("BaseDataOffset1", bw.Position - start);
                bw.WriteInt16((short)UnkA.Length);
                bw.WriteInt16s(UnkA);
                bw.Pad(4);

                bw.FillInt64("BaseDataOffset2", bw.Position - start);
                bw.WriteInt16((short)UnkB.Length);
                bw.WriteInt16s(UnkB);
                bw.Pad(8);

                if (Shape.HasShapeData)
                {
                    bw.FillInt64("ShapeDataOffset", bw.Position - start);
                    Shape.WriteShapeData(bw);
                }
                else
                {
                    bw.FillInt64("ShapeDataOffset", 0);
                }

                bw.FillInt64("BaseDataOffset3", bw.Position - start);
                bw.WriteInt32(UnkC00);
                bw.WriteInt32(UnkC04);

                if (HasTypeData)
                {
                    if (Type == RegionType.Region23 || Type == RegionType.PartsGroup || Type == RegionType.AutoDrawGroup)
                    {
                        bw.Pad(8);
                    }

                    bw.FillInt64("TypeDataOffset", bw.Position - start);
                    WriteTypeData(bw);
                }
                else
                {
                    bw.FillInt64("TypeDataOffset", 0);
                }
                bw.Pad(8);
            }
Пример #3
0
        private static void CompressDCXEDGE(byte[] data, BinaryWriterEx bw)
        {
            int chunkCount = data.Length / 0x10000;

            if (data.Length % 0x10000 > 0)
            {
                chunkCount++;
            }

            bw.WriteASCII("DCX\0");
            bw.WriteInt32(0x10000);
            bw.WriteInt32(0x18);
            bw.WriteInt32(0x24);
            bw.WriteInt32(0x24);
            bw.WriteInt32(0x50 + chunkCount * 0x10);

            bw.WriteASCII("DCS\0");
            bw.WriteInt32(data.Length);
            bw.ReserveInt32("CompressedSize");

            bw.WriteASCII("DCP\0");
            bw.WriteASCII("EDGE");
            bw.WriteInt32(0x20);
            bw.WriteInt32(0x9000000);
            bw.WriteInt32(0x10000);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0x00100100);

            long dcaStart = bw.Position;

            bw.WriteASCII("DCA\0");
            bw.ReserveInt32("DCASize");
            long egdtStart = bw.Position;

            bw.WriteASCII("EgdT");
            bw.WriteInt32(0x00010100);
            bw.WriteInt32(0x24);
            bw.WriteInt32(0x10);
            bw.WriteInt32(0x10000);
            bw.WriteInt32(data.Length % 0x10000);
            bw.ReserveInt32("EGDTSize");
            bw.WriteInt32(chunkCount);
            bw.WriteInt32(0x100000);

            for (int i = 0; i < chunkCount; i++)
            {
                bw.WriteInt32(0);
                bw.ReserveInt32($"ChunkOffset{i}");
                bw.ReserveInt32($"ChunkSize{i}");
                bw.ReserveInt32($"ChunkCompressed{i}");
            }

            bw.FillInt32("DCASize", (int)(bw.Position - dcaStart));
            bw.FillInt32("EGDTSize", (int)(bw.Position - egdtStart));

            int compressedSize = 0;

            for (int i = 0; i < chunkCount; i++)
            {
                int chunkSize = 0x10000;
                if (i == chunkCount - 1)
                {
                    chunkSize = data.Length % 0x10000;
                }

                byte[] chunk;
                using (MemoryStream cmpStream = new MemoryStream())
                    using (MemoryStream dcmpStream = new MemoryStream(data, i * 0x10000, chunkSize))
                    {
                        DeflateStream dfltStream = new DeflateStream(cmpStream, CompressionMode.Compress);
                        dcmpStream.CopyTo(dfltStream);
                        dfltStream.Close();
                        chunk = cmpStream.ToArray();
                    }

                if (chunk.Length < chunkSize)
                {
                    bw.FillInt32($"ChunkCompressed{i}", 1);
                }
                else
                {
                    bw.FillInt32($"ChunkCompressed{i}", 0);
                    chunk = data;
                }

                compressedSize += chunk.Length;
                bw.FillInt32($"ChunkOffset{i}", (int)bw.Position);
                bw.FillInt32($"ChunkSize{i}", chunk.Length);
                bw.WriteBytes(chunk);
                bw.Pad(0x10);
            }

            bw.FillInt32("CompressedSize", compressedSize);
        }
Пример #4
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.WriteASCII("TAE ");
            bw.WriteByte(0);
            bw.WriteByte(0);
            bw.WriteByte(0);
            bw.WriteByte(0xFF);
            bw.WriteInt32(0x1000C);
            bw.ReserveInt32("FileSize");
            bw.WriteInt64(0x40);
            bw.WriteInt64(1);
            bw.WriteInt64(0x50);
            bw.WriteInt64(0x80);
            bw.WriteInt64(0x15);
            bw.WriteInt64(0);
            bw.WriteBytes(Flags);
            bw.WriteInt64(1);
            bw.WriteInt32(ID);
            bw.WriteInt32(Animations.Count);
            bw.ReserveInt64("AnimsOffset");
            bw.ReserveInt64("AnimGroupsOffset");
            bw.WriteInt64(0xA0);
            bw.WriteInt64(Animations.Count);
            bw.ReserveInt64("FirstAnimOffset");
            bw.WriteInt64(1);
            bw.WriteInt64(0x90);
            bw.WriteInt32(ID);
            bw.WriteInt32(ID);
            bw.WriteInt64(0x50);
            bw.WriteInt64(0);
            bw.WriteInt64(0xB0);
            bw.ReserveInt64("SkeletonName");
            bw.ReserveInt64("SibName");
            bw.WriteInt64(0);
            bw.WriteInt64(0);

            bw.FillInt64("SkeletonName", bw.Position);
            bw.WriteUTF16(SkeletonName, true);
            bw.Pad(0x10);

            bw.FillInt64("SibName", bw.Position);
            bw.WriteUTF16(SibName, true);
            bw.Pad(0x10);

            Animations.Sort((a1, a2) => a1.ID.CompareTo(a2.ID));

            bw.FillInt64("AnimsOffset", bw.Position);
            var animOffsets = new List <long>(Animations.Count);

            for (int i = 0; i < Animations.Count; i++)
            {
                animOffsets.Add(bw.Position);
                Animations[i].WriteHeader(bw, i);
            }

            bw.FillInt64("AnimGroupsOffset", bw.Position);
            bw.ReserveInt64("AnimGroupsCount");
            bw.ReserveInt64("AnimGroupsOffset");
            int  groupCount = 0;
            long groupStart = bw.Position;

            for (int i = 0; i < Animations.Count; i++)
            {
                int firstIndex = i;
                bw.WriteInt32((int)Animations[i].ID);
                while (i < Animations.Count - 1 && Animations[i + 1].ID == Animations[i].ID + 1)
                {
                    i++;
                }
                bw.WriteInt32((int)Animations[i].ID);
                bw.WriteInt64(animOffsets[firstIndex]);
                groupCount++;
            }
            bw.FillInt64("AnimGroupsCount", groupCount);
            if (groupCount == 0)
            {
                bw.FillInt64("AnimGroupsOffset", 0);
            }
            else
            {
                bw.FillInt64("AnimGroupsOffset", groupStart);
            }

            bw.FillInt64("FirstAnimOffset", bw.Position);
            for (int i = 0; i < Animations.Count; i++)
            {
                Animations[i].WriteBody(bw, i);
            }

            for (int i = 0; i < Animations.Count; i++)
            {
                Animations[i].WriteAnimFile(bw, i);

                long timeStart = bw.Position;
                Animations[i].WriteTimes(bw, i);

                var eventHeaderOffsets = Animations[i].WriteEventHeaders(bw, i, timeStart);

                Animations[i].WriteEventData(bw, i);

                Animations[i].WriteEventGroupHeaders(bw, i);

                Animations[i].WriteEventGroupData(bw, i, eventHeaderOffsets);
            }

            bw.FillInt32("FileSize", (int)bw.Position);
        }
Пример #5
0
 private static void WriteMarker(BinaryWriterEx bw, byte marker)
 {
     bw.WriteByte(marker);
     bw.Pad(4);
 }
Пример #6
0
            internal void Write(BinaryWriterEx bw, List <File> files)
            {
                bw.BigEndian = BigEndian;
                bw.WriteASCII("BHF4");
                bw.WriteBoolean(Flag1);
                bw.WriteBoolean(Flag2);
                bw.WriteByte(0);
                bw.WriteByte(0);
                bw.WriteInt32(0x10000);
                bw.WriteInt32(files.Count);
                bw.WriteInt64(0x40);
                bw.WriteASCII(Timestamp);
                if (Format == 0x0C || Format == 0x30)
                {
                    bw.WriteInt64(0x18);
                }
                else if (Format == 0x2E || Format == 0x74)
                {
                    bw.WriteInt64(0x24);
                }
                else if (Format == 0x3E)
                {
                    bw.WriteInt64(0x28);
                }
                bw.WriteInt64(0);

                bw.WriteBoolean(Unicode);
                bw.WriteByte(Format);
                bw.WriteByte(Extended);
                bw.WriteByte(0);

                bw.WriteInt32(0);
                if (Extended == 4)
                {
                    bw.ReserveInt64("HashGroups");
                }
                else
                {
                    bw.WriteInt64(0);
                }

                for (int i = 0; i < files.Count; i++)
                {
                    FileHeader.Write(bw, files[i], i, Format);
                }

                for (int i = 0; i < files.Count; i++)
                {
                    File file = files[i];
                    bw.FillInt32($"FileName{i}", (int)bw.Position);
                    if (Unicode)
                    {
                        bw.WriteUTF16(file.Name, true);
                    }
                    else
                    {
                        bw.WriteShiftJIS(file.Name, true);
                    }
                }

                if (Extended == 4)
                {
                    uint groupCount = 0;
                    for (uint p = (uint)files.Count / 7; p <= 100000; p++)
                    {
                        if (Util.IsPrime(p))
                        {
                            groupCount = p;
                            break;
                        }
                    }

                    if (groupCount == 0)
                    {
                        throw new InvalidOperationException("Hash group count not determined in BXF4.");
                    }

                    var hashLists = new List <PathHash> [groupCount];
                    for (int i = 0; i < groupCount; i++)
                    {
                        hashLists[i] = new List <PathHash>();
                    }

                    for (int i = 0; i < files.Count; i++)
                    {
                        var  pathHash = new PathHash(i, files[i].Name);
                        uint group    = pathHash.Hash % groupCount;
                        hashLists[group].Add(pathHash);
                    }

                    for (int i = 0; i < groupCount; i++)
                    {
                        hashLists[i].Sort((ph1, ph2) => ph1.Hash.CompareTo(ph2.Hash));
                    }

                    var hashGroups = new List <HashGroup>();
                    var pathHashes = new List <PathHash>();

                    int count = 0;
                    foreach (List <PathHash> hashList in hashLists)
                    {
                        int index = count;
                        foreach (PathHash pathHash in hashList)
                        {
                            pathHashes.Add(pathHash);
                            count++;
                        }

                        hashGroups.Add(new HashGroup(index, count - index));
                    }

                    bw.Pad(0x8);
                    bw.FillInt64("HashGroups", bw.Position);
                    bw.ReserveInt64("PathHashes");
                    bw.WriteUInt32(groupCount);
                    bw.WriteInt32(0x00080810);

                    foreach (HashGroup hashGroup in hashGroups)
                    {
                        hashGroup.Write(bw);
                    }

                    // No padding after section 1
                    bw.FillInt64("PathHashes", bw.Position);
                    foreach (PathHash pathHash in pathHashes)
                    {
                        pathHash.Write(bw);
                    }
                }
            }
Пример #7
0
        /// <summary>
        /// Writes BND4 data to a BinaryWriterEx.
        /// </summary>
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = BigEndian;

            bw.WriteASCII("BND4");
            bw.WriteBoolean(Flag1);
            bw.WriteBoolean(Flag2);
            bw.WriteByte(0);
            bw.WriteByte(0);

            bw.WriteInt32(0x10000);
            bw.WriteInt32(Files.Count);
            bw.WriteInt64(0x40);
            bw.WriteFixStr(Timestamp, 8);
            bw.WriteInt64(Binder.FileHeaderSize(Format));
            bw.ReserveInt64("DataStart");

            bw.WriteBoolean(Unicode);
            bw.WriteByte((byte)Format);
            bw.WriteByte(Extended);
            bw.WriteByte(0);

            bw.WriteInt32(0);
            if (Extended == 4)
            {
                bw.ReserveInt64("HashGroups");
            }
            else
            {
                bw.WriteInt64(0);
            }

            for (int i = 0; i < Files.Count; i++)
            {
                WriteFile(Files[i], bw, i, Format);
            }

            if (Binder.HasName(Format))
            {
                for (int i = 0; i < Files.Count; i++)
                {
                    BinderFile file = Files[i];
                    bw.FillUInt32($"FileName{i}", (uint)bw.Position);
                    if (Unicode)
                    {
                        bw.WriteUTF16(file.Name, true);
                    }
                    else
                    {
                        bw.WriteShiftJIS(file.Name, true);
                    }
                }
            }

            if (Extended == 4)
            {
                uint groupCount = 0;
                for (uint p = (uint)Files.Count / 7; p <= 100000; p++)
                {
                    if (SFUtil.IsPrime(p))
                    {
                        groupCount = p;
                        break;
                    }
                }

                if (groupCount == 0)
                {
                    throw new InvalidOperationException("Hash group count not determined in BND4.");
                }

                var hashLists = new List <PathHash> [groupCount];
                for (int i = 0; i < groupCount; i++)
                {
                    hashLists[i] = new List <PathHash>();
                }

                for (int i = 0; i < Files.Count; i++)
                {
                    var  pathHash = new PathHash(i, Files[i].Name);
                    uint group    = pathHash.Hash % groupCount;
                    hashLists[group].Add(pathHash);
                }

                for (int i = 0; i < groupCount; i++)
                {
                    hashLists[i].Sort((ph1, ph2) => ph1.Hash.CompareTo(ph2.Hash));
                }

                var hashGroups = new List <HashGroup>();
                var pathHashes = new List <PathHash>();

                int count = 0;
                foreach (List <PathHash> hashList in hashLists)
                {
                    int index = count;
                    foreach (PathHash pathHash in hashList)
                    {
                        pathHashes.Add(pathHash);
                        count++;
                    }

                    hashGroups.Add(new HashGroup(index, count - index));
                }

                bw.Pad(0x8);
                bw.FillInt64("HashGroups", bw.Position);
                bw.ReserveInt64("PathHashes");
                bw.WriteUInt32(groupCount);
                bw.WriteInt32(0x00080810);

                foreach (HashGroup hashGroup in hashGroups)
                {
                    hashGroup.Write(bw);
                }

                // No padding after section 1
                bw.FillInt64("PathHashes", bw.Position);
                foreach (PathHash pathHash in pathHashes)
                {
                    pathHash.Write(bw);
                }
            }

            bw.FillInt64("DataStart", bw.Position);
            for (int i = 0; i < Files.Count; i++)
            {
                BinderFile file = Files[i];
                if (file.Bytes.LongLength > 0)
                {
                    bw.Pad(0x10);
                }

                bw.FillUInt32($"FileData{i}", (uint)bw.Position);

                int compressedSize = file.Bytes.Length;

                if (Binder.IsCompressed(file.Flags))
                {
                    if (Format == Binder.Format.x2E)
                    {
                        byte[] bytes = DCX.Compress(file.Bytes, DCX.Type.DemonsSoulsEDGE);
                        bw.WriteBytes(bytes);
                        compressedSize = bytes.Length;
                    }
                    else
                    {
                        compressedSize = SFUtil.WriteZlib(bw, 0x9C, file.Bytes);
                    }
                }
                else
                {
                    bw.WriteBytes(file.Bytes);
                }

                bw.FillInt64($"CompressedSize{i}", compressedSize);
            }
        }
Пример #8
0
        /// <summary>
        /// Writes FLVER data to a BinaryWriterEx.
        /// </summary>
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = Header.BigEndian;
            bw.WriteASCII("FLVER\0");
            bw.WriteASCII(Header.BigEndian ? "B\0" : "L\0");
            bw.WriteInt32(Header.Version);

            bw.ReserveInt32("DataOffset");
            bw.ReserveInt32("DataSize");
            bw.WriteInt32(Dummies.Count);
            bw.WriteInt32(Materials.Count);
            bw.WriteInt32(Bones.Count);
            bw.WriteInt32(Meshes.Count);
            bw.WriteInt32(Meshes.Sum(m => m.VertexBuffers.Count));
            bw.WriteVector3(Header.BoundingBoxMin);
            bw.WriteVector3(Header.BoundingBoxMax);

            int trueFaceCount  = 0;
            int totalFaceCount = 0;

            foreach (Mesh mesh in Meshes)
            {
                bool allowPrimitiveRestarts = mesh.Vertices.Count < ushort.MaxValue;
                foreach (FaceSet faceSet in mesh.FaceSets)
                {
                    faceSet.AddFaceCounts(allowPrimitiveRestarts, ref trueFaceCount, ref totalFaceCount);
                }
            }
            bw.WriteInt32(trueFaceCount);
            bw.WriteInt32(totalFaceCount);

            byte vertexIndicesSize = 0;

            if (Header.Version < 0x20013)
            {
                vertexIndicesSize = 16;
                foreach (Mesh mesh in Meshes)
                {
                    foreach (FaceSet fs in mesh.FaceSets)
                    {
                        vertexIndicesSize = (byte)Math.Max(vertexIndicesSize, fs.GetVertexIndexSize());
                    }
                }
            }

            bw.WriteByte(vertexIndicesSize);
            bw.WriteBoolean(Header.Unicode);
            bw.WriteBoolean(Header.Unk4A);
            bw.WriteByte(0);

            bw.WriteInt32(Header.Unk4C);

            bw.WriteInt32(Meshes.Sum(m => m.FaceSets.Count));
            bw.WriteInt32(BufferLayouts.Count);
            bw.WriteInt32(Materials.Sum(m => m.Textures.Count));

            bw.WriteByte(Header.Unk5C);
            bw.WriteByte(Header.Unk5D);
            bw.WriteByte(0);
            bw.WriteByte(0);

            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(Header.Unk68);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);

            foreach (Dummy dummy in Dummies)
            {
                dummy.Write(bw, Header);
            }

            for (int i = 0; i < Materials.Count; i++)
            {
                Materials[i].Write(bw, i);
            }

            for (int i = 0; i < Bones.Count; i++)
            {
                Bones[i].Write(bw, i);
            }

            for (int i = 0; i < Meshes.Count; i++)
            {
                Meshes[i].Write(bw, i);
            }

            int faceSetIndex = 0;

            foreach (Mesh mesh in Meshes)
            {
                for (int i = 0; i < mesh.FaceSets.Count; i++)
                {
                    int indexSize = vertexIndicesSize;
                    if (indexSize == 0)
                    {
                        indexSize = mesh.FaceSets[i].GetVertexIndexSize();
                    }

                    mesh.FaceSets[i].Write(bw, Header, indexSize, faceSetIndex + i);
                }
                faceSetIndex += mesh.FaceSets.Count;
            }

            int vertexBufferIndex = 0;

            foreach (Mesh mesh in Meshes)
            {
                for (int i = 0; i < mesh.VertexBuffers.Count; i++)
                {
                    mesh.VertexBuffers[i].Write(bw, Header, vertexBufferIndex + i, i, BufferLayouts, mesh.Vertices.Count);
                }
                vertexBufferIndex += mesh.VertexBuffers.Count;
            }

            for (int i = 0; i < BufferLayouts.Count; i++)
            {
                BufferLayouts[i].Write(bw, i);
            }

            int textureIndex = 0;

            for (int i = 0; i < Materials.Count; i++)
            {
                Materials[i].WriteTextures(bw, i, textureIndex);
                textureIndex += Materials[i].Textures.Count;
            }

            if (Header.Version >= 0x2001A)
            {
                SekiroUnk.Write(bw);
            }

            bw.Pad(0x10);
            for (int i = 0; i < BufferLayouts.Count; i++)
            {
                BufferLayouts[i].WriteMembers(bw, i);
            }

            bw.Pad(0x10);
            for (int i = 0; i < Meshes.Count; i++)
            {
                Meshes[i].WriteBoundingBox(bw, i, Header);
            }

            bw.Pad(0x10);
            int boneIndicesStart = (int)bw.Position;

            for (int i = 0; i < Meshes.Count; i++)
            {
                Meshes[i].WriteBoneIndices(bw, i, boneIndicesStart);
            }

            bw.Pad(0x10);
            faceSetIndex = 0;
            for (int i = 0; i < Meshes.Count; i++)
            {
                bw.FillInt32($"MeshFaceSetIndices{i}", (int)bw.Position);
                for (int j = 0; j < Meshes[i].FaceSets.Count; j++)
                {
                    bw.WriteInt32(faceSetIndex + j);
                }
                faceSetIndex += Meshes[i].FaceSets.Count;
            }

            bw.Pad(0x10);
            vertexBufferIndex = 0;
            for (int i = 0; i < Meshes.Count; i++)
            {
                bw.FillInt32($"MeshVertexBufferIndices{i}", (int)bw.Position);
                for (int j = 0; j < Meshes[i].VertexBuffers.Count; j++)
                {
                    bw.WriteInt32(vertexBufferIndex + j);
                }
                vertexBufferIndex += Meshes[i].VertexBuffers.Count;
            }

            bw.Pad(0x10);
            var gxOffsets = new List <int>();

            foreach (GXList gxList in GXLists)
            {
                gxOffsets.Add((int)bw.Position);
                gxList.Write(bw, Header);
            }
            for (int i = 0; i < Materials.Count; i++)
            {
                Materials[i].FillGXOffset(bw, i, gxOffsets);
            }

            bw.Pad(0x10);
            textureIndex = 0;
            for (int i = 0; i < Materials.Count; i++)
            {
                Material material = Materials[i];
                material.WriteStrings(bw, Header, i);

                for (int j = 0; j < material.Textures.Count; j++)
                {
                    material.Textures[j].WriteStrings(bw, Header, textureIndex + j);
                }
                textureIndex += material.Textures.Count;
            }

            bw.Pad(0x10);
            for (int i = 0; i < Bones.Count; i++)
            {
                Bones[i].WriteStrings(bw, Header, i);
            }

            int alignment = Header.Version <= 0x2000E ? 0x20 : 0x10;

            bw.Pad(alignment);
            if (Header.Version == 0x2000F || Header.Version == 0x20010)
            {
                bw.Pad(0x20);
            }

            int dataStart = (int)bw.Position;

            bw.FillInt32("DataOffset", dataStart);

            faceSetIndex      = 0;
            vertexBufferIndex = 0;
            for (int i = 0; i < Meshes.Count; i++)
            {
                Mesh mesh = Meshes[i];
                for (int j = 0; j < mesh.FaceSets.Count; j++)
                {
                    int indexSize = vertexIndicesSize;
                    if (indexSize == 0)
                    {
                        indexSize = mesh.FaceSets[j].GetVertexIndexSize();
                    }

                    bw.Pad(alignment);
                    mesh.FaceSets[j].WriteVertices(bw, indexSize, faceSetIndex + j, dataStart);
                }
                faceSetIndex += mesh.FaceSets.Count;

                foreach (FLVER.Vertex vertex in mesh.Vertices)
                {
                    vertex.PrepareWrite();
                }

                for (int j = 0; j < mesh.VertexBuffers.Count; j++)
                {
                    bw.Pad(alignment);
                    mesh.VertexBuffers[j].WriteBuffer(bw, vertexBufferIndex + j, BufferLayouts, mesh.Vertices, dataStart, Header);
                }

                foreach (FLVER.Vertex vertex in mesh.Vertices)
                {
                    vertex.FinishWrite();
                }

                vertexBufferIndex += mesh.VertexBuffers.Count;
            }

            bw.Pad(alignment);
            bw.FillInt32("DataSize", (int)bw.Position - dataStart);
            if (Header.Version == 0x2000F || Header.Version == 0x20010)
            {
                bw.Pad(0x20);
            }
        }
Пример #9
0
            internal void Write(BinaryWriterEx bw)
            {
                bw.WriteInt32(0);
                bw.WriteInt32(Unk04);
                bw.WriteInt32(4);
                bw.WriteInt32(4);
                WriteMarker(bw, 0xA3);
                bw.WriteShiftJISLengthPrefixed(Name, 0xA3);
                bw.WriteShiftJISLengthPrefixed(Type.ToString().ToLower(), 0x04);
                bw.WriteInt32(1);
                bw.WriteInt32(0);
                bw.ReserveInt32("ValueSize");
                int valueStart = (int)bw.Position;

                if (Type == ParamType.Bool)
                {
                    bw.WriteByte(0);
                }
                else if (Type == ParamType.Int || Type == ParamType.Int2)
                {
                    bw.WriteByte(1);
                }
                else if (Type == ParamType.Float || Type == ParamType.Float2 || Type == ParamType.Float3 || Type == ParamType.Float4)
                {
                    bw.WriteByte(2);
                }
                bw.WriteByte(0x10);
                bw.WriteByte(0);
                bw.WriteByte(0);

                bw.WriteInt32(1);
                if (Type == ParamType.Bool)
                {
                    WriteMarker(bw, 0xC0);
                }
                else if (Type == ParamType.Int || Type == ParamType.Int2)
                {
                    WriteMarker(bw, 0xC5);
                }
                else if (Type == ParamType.Float || Type == ParamType.Float2 || Type == ParamType.Float3 || Type == ParamType.Float4)
                {
                    WriteMarker(bw, 0xCA);
                }

                if (Type == ParamType.Bool || Type == ParamType.Float || Type == ParamType.Int)
                {
                    bw.WriteInt32(1);
                }
                else if (Type == ParamType.Float2 || Type == ParamType.Int2)
                {
                    bw.WriteInt32(2);
                }
                else if (Type == ParamType.Float3)
                {
                    bw.WriteInt32(3);
                }
                else if (Type == ParamType.Float4)
                {
                    bw.WriteInt32(4);
                }

                if (Type == ParamType.Int)
                {
                    bw.WriteInt32((int)Value);
                }
                else if (Type == ParamType.Int2)
                {
                    bw.WriteInt32s((int[])Value);
                }
                else if (Type == ParamType.Bool)
                {
                    bw.WriteBoolean((bool)Value);
                }
                else if (Type == ParamType.Float)
                {
                    bw.WriteSingle((float)Value);
                }
                else if (Type == ParamType.Float2)
                {
                    bw.WriteSingles((float[])Value);
                }
                else if (Type == ParamType.Float3)
                {
                    bw.WriteSingles((float[])Value);
                }
                else if (Type == ParamType.Float4)
                {
                    bw.WriteSingles((float[])Value);
                }

                bw.FillInt32("ValueSize", (int)bw.Position - valueStart);
                bw.WriteByte(4);
                bw.Pad(4);
                bw.WriteInt32(0);
            }
Пример #10
0
        protected override void Write(BinaryWriterEx bw)
        {
            bw.WriteASCII("FXR\0");
            bw.WriteInt16(0);
            bw.WriteUInt16((ushort)Version);
            bw.WriteInt32(1);
            bw.WriteInt32(ID);
            bw.ReserveInt32("Section1Offset");
            bw.WriteInt32(1);
            bw.ReserveInt32("Section2Offset");
            bw.WriteInt32(Section1Tree.Section2s.Count);
            bw.ReserveInt32("Section3Offset");
            bw.ReserveInt32("Section3Count");
            bw.ReserveInt32("Section4Offset");
            bw.ReserveInt32("Section4Count");
            bw.ReserveInt32("Section5Offset");
            bw.ReserveInt32("Section5Count");
            bw.ReserveInt32("Section6Offset");
            bw.ReserveInt32("Section6Count");
            bw.ReserveInt32("Section7Offset");
            bw.ReserveInt32("Section7Count");
            bw.ReserveInt32("Section8Offset");
            bw.ReserveInt32("Section8Count");
            bw.ReserveInt32("Section9Offset");
            bw.ReserveInt32("Section9Count");
            bw.ReserveInt32("Section10Offset");
            bw.ReserveInt32("Section10Count");
            bw.ReserveInt32("Section11Offset");
            bw.ReserveInt32("Section11Count");
            bw.WriteInt32(1);
            bw.WriteInt32(0);

            if (Version == FXRVersion.Sekiro)
            {
                bw.ReserveInt32("Section12Offset");
                bw.WriteInt32(Section12s.Count);
                bw.ReserveInt32("Section13Offset");
                bw.WriteInt32(Section13s.Count);
                bw.ReserveInt32("Section14Offset");
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
            }

            bw.FillInt32("Section1Offset", (int)bw.Position);
            Section1Tree.Write(bw);
            bw.Pad(0x10);

            bw.FillInt32("Section2Offset", (int)bw.Position);
            Section1Tree.WriteSection2s(bw);
            bw.Pad(0x10);

            bw.FillInt32("Section3Offset", (int)bw.Position);
            List <Section2> section2s = Section1Tree.Section2s;
            var             section3s = new List <Section3>();

            for (int i = 0; i < section2s.Count; i++)
            {
                section2s[i].WriteSection3s(bw, i, section3s);
            }
            bw.FillInt32("Section3Count", section3s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section4Offset", (int)bw.Position);
            var section4s = new List <Section4>();

            Section4Tree.Write(bw, section4s);
            Section4Tree.WriteSection4s(bw, section4s);
            bw.FillInt32("Section4Count", section4s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section5Offset", (int)bw.Position);
            int section5Count = 0;

            for (int i = 0; i < section4s.Count; i++)
            {
                section4s[i].WriteSection5s(bw, i, ref section5Count);
            }
            bw.FillInt32("Section5Count", section5Count);
            bw.Pad(0x10);

            bw.FillInt32("Section6Offset", (int)bw.Position);
            section5Count = 0;
            var section6s = new List <FFXDrawEntityHost>();

            for (int i = 0; i < section4s.Count; i++)
            {
                section4s[i].WriteSection6s(bw, i, ref section5Count, section6s);
            }
            bw.FillInt32("Section6Count", section6s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section7Offset", (int)bw.Position);
            var section7s = new List <FFXProperty>();

            for (int i = 0; i < section6s.Count; i++)
            {
                section6s[i].WriteSection7s(bw, i, section7s);
            }
            bw.FillInt32("Section7Count", section7s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section8Offset", (int)bw.Position);
            var section8s = new List <Section8>();

            for (int i = 0; i < section7s.Count; i++)
            {
                section7s[i].WriteSection8s(bw, i, section8s);
            }
            bw.FillInt32("Section8Count", section8s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section9Offset", (int)bw.Position);
            var section9s = new List <Section9>();

            for (int i = 0; i < section8s.Count; i++)
            {
                section8s[i].WriteSection9s(bw, i, section9s);
            }
            bw.FillInt32("Section9Count", section9s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section10Offset", (int)bw.Position);
            var section10s = new List <Section10>();

            for (int i = 0; i < section6s.Count; i++)
            {
                section6s[i].WriteSection10s(bw, i, section10s);
            }
            bw.FillInt32("Section10Count", section10s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section11Offset", (int)bw.Position);
            int section11Count = 0;

            for (int i = 0; i < section3s.Count; i++)
            {
                section3s[i].WriteSection11s(bw, i, ref section11Count);
            }
            for (int i = 0; i < section6s.Count; i++)
            {
                section6s[i].WriteSection11s(bw, i, ref section11Count);
            }
            for (int i = 0; i < section7s.Count; i++)
            {
                section7s[i].WriteSection11s(bw, i, ref section11Count);
            }
            for (int i = 0; i < section8s.Count; i++)
            {
                section8s[i].WriteSection11s(bw, i, ref section11Count);
            }
            for (int i = 0; i < section9s.Count; i++)
            {
                section9s[i].WriteSection11s(bw, i, ref section11Count);
            }
            for (int i = 0; i < section10s.Count; i++)
            {
                section10s[i].WriteSection11s(bw, i, ref section11Count);
            }
            bw.FillInt32("Section11Count", section11Count);
            bw.Pad(0x10);

            if (Version == FXRVersion.Sekiro)
            {
                bw.FillInt32("Section12Offset", (int)bw.Position);
                bw.WriteInt32s(Section12s);
                bw.Pad(0x10);

                bw.FillInt32("Section13Offset", (int)bw.Position);
                bw.WriteInt32s(Section13s);
                bw.Pad(0x10);

                bw.FillInt32("Section14Offset", (int)bw.Position);
            }
        }
Пример #11
0
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = BigEndian;

            bw.ReserveInt32("FileSize");
            bw.WriteInt16((short)(FormatVersion >= 200 ? 0xFF : 0x30));
            bw.WriteInt16(DataVersion);
            bw.WriteInt16((short)Fields.Count);

            if (FormatVersion == 101)
            {
                bw.WriteInt16(0x8C);
            }
            else if (FormatVersion == 102)
            {
                bw.WriteInt16(0xAC);
            }
            else if (FormatVersion == 103)
            {
                bw.WriteInt16(0x6C);
            }
            else if (FormatVersion == 104)
            {
                bw.WriteInt16(0xB0);
            }
            else if (FormatVersion == 201)
            {
                bw.WriteInt16(0xD0);
            }
            else if (FormatVersion == 202)
            {
                bw.WriteInt16(0x68);
            }

            if (FormatVersion >= 202)
            {
                bw.WriteInt32(0);
                bw.ReserveInt64("ParamTypeOffset");
                bw.WriteInt64(0);
                bw.WriteInt64(0);
                bw.WriteInt32(0);
            }
            else
            {
                bw.WriteFixStr(ParamType, 0x20, (byte)(FormatVersion >= 200 ? 0x00 : 0x20));
            }

            bw.WriteSByte((sbyte)(BigEndian ? -1 : 0));
            bw.WriteBoolean(Unicode);
            bw.WriteInt16(FormatVersion);
            if (FormatVersion >= 200)
            {
                bw.WriteInt64(0x38);
            }

            for (int i = 0; i < Fields.Count; i++)
            {
                Fields[i].Write(bw, this, i);
            }

            if (FormatVersion >= 202)
            {
                bw.FillInt64("ParamTypeOffset", bw.Position);
                bw.WriteShiftJIS(ParamType, true);
            }

            long fieldStringsStart   = bw.Position;
            var  sharedStringOffsets = new Dictionary <string, long>();

            for (int i = 0; i < Fields.Count; i++)
            {
                Fields[i].WriteStrings(bw, this, i, sharedStringOffsets);
            }

            if (FormatVersion >= 104 && FormatVersion < 202)
            {
                long fieldStringsLength = bw.Position - fieldStringsStart;
                if (fieldStringsLength % 0x10 != 0)
                {
                    bw.WritePattern((int)(0x10 - fieldStringsLength % 0x10), 0x00);
                }
            }
            else
            {
                if (FormatVersion >= 202 && bw.Position % 0x10 == 0)
                {
                    bw.WritePattern(0x10, 0x00);
                }
                bw.Pad(0x10);
            }
            bw.FillInt32("FileSize", (int)bw.Position);
        }