예제 #1
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;
            bw.WriteUInt32((uint)Version);
            bw.BigEndian = Version == CCMVer.DemonsSouls;

            bw.ReserveInt32("FileSize");
            bw.WriteInt16(FullWidth);
            bw.WriteInt16(TexWidth);
            bw.WriteInt16(TexHeight);

            if (Version == CCMVer.DemonsSouls || Version == CCMVer.DarkSouls1)
            {
                bw.WriteInt16(Unk0E);
                bw.ReserveInt16("CodeGroupCount");
                bw.WriteInt16((short)Glyphs.Count);
            }
            else if (Version == CCMVer.DarkSouls2)
            {
                bw.ReserveInt16("TexRegionCount");
                bw.WriteInt16((short)Glyphs.Count);
                bw.WriteInt16(0);
            }

            bw.WriteInt32(0x20);
            bw.ReserveInt32("GlyphOffset");
            bw.WriteByte(Unk1C);
            bw.WriteByte(Unk1D);
            bw.WriteByte(TexCount);
            bw.WriteByte(0);

            var codes = new List <int>(Glyphs.Keys);

            codes.Sort();
            if (Version == CCMVer.DemonsSouls || Version == CCMVer.DarkSouls1)
            {
                var codeGroups = new List <CodeGroup>();
                for (int i = 0; i < Glyphs.Count;)
                {
                    int startCode  = codes[i];
                    int glyphIndex = i;
                    for (i++; i < Glyphs.Count && codes[i] == codes[i - 1] + 1; i++)
                    {
                        ;
                    }
                    int endCode = codes[i - 1];
                    codeGroups.Add(new CodeGroup(startCode, endCode, glyphIndex));
                }

                bw.FillInt16("CodeGroupCount", (short)codeGroups.Count);
                foreach (CodeGroup group in codeGroups)
                {
                    group.Write(bw);
                }

                bw.FillInt32("GlyphOffset", (int)bw.Position);
                foreach (int code in codes)
                {
                    Glyph glyph = Glyphs[code];
                    bw.WriteVector2(glyph.UV1);
                    bw.WriteVector2(glyph.UV2);
                    bw.WriteInt16(glyph.PreSpace);
                    bw.WriteInt16(glyph.Width);
                    bw.WriteInt16(glyph.Advance);
                    bw.WriteInt16(glyph.TexIndex);
                }
            }
            else if (Version == CCMVer.DarkSouls2)
            {
                var texRegionsByCode = new Dictionary <int, TexRegion>(Glyphs.Count);
                var texRegions       = new HashSet <TexRegion>();
                foreach (int code in codes)
                {
                    Glyph glyph  = Glyphs[code];
                    short x1     = (short)Math.Round(glyph.UV1.X * TexWidth);
                    short y1     = (short)Math.Round(glyph.UV1.Y * TexHeight);
                    short x2     = (short)Math.Round(glyph.UV2.X * TexWidth);
                    short y2     = (short)Math.Round(glyph.UV2.Y * TexHeight);
                    var   region = new TexRegion(x1, y1, x2, y2);
                    texRegionsByCode[code] = region;
                    texRegions.Add(region);
                }

                bw.FillInt16("TexRegionCount", (short)texRegions.Count);
                var texRegionOffsets = new Dictionary <TexRegion, int>(texRegions.Count);
                foreach (TexRegion region in texRegions)
                {
                    texRegionOffsets[region] = (int)bw.Position;
                    region.Write(bw);
                }

                bw.FillInt32("GlyphOffset", (int)bw.Position);
                foreach (int code in codes)
                {
                    Glyph glyph = Glyphs[code];
                    bw.WriteInt32(code);
                    bw.WriteInt32(texRegionOffsets[texRegionsByCode[code]]);
                    bw.WriteInt16(glyph.TexIndex);
                    bw.WriteInt16(glyph.PreSpace);
                    bw.WriteInt16(glyph.Width);
                    bw.WriteInt16(glyph.Advance);
                    bw.WriteInt32(0);
                    bw.WriteInt32(0);
                }
            }

            bw.FillInt32("FileSize", (int)bw.Position);
        }
예제 #2
0
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            bw.WriteASCII(LongFormat ? "fsSL" : "fSSL");
            bw.WriteInt32(1);
            bw.WriteInt32(DarkSoulsCount);
            bw.WriteInt32(DarkSoulsCount);
            bw.WriteInt32(0x54);
            bw.ReserveInt32("DataSize");
            bw.WriteInt32(6);
            bw.WriteInt32(LongFormat ? 0x48 : 0x2C);
            bw.WriteInt32(1);
            bw.WriteInt32(LongFormat ? 0x20 : 0x10);
            bw.WriteInt32(StateGroups.Count);
            int stateSize = LongFormat ? 0x48 : 0x24;

            bw.WriteInt32(stateSize);
            bw.WriteInt32(StateGroups.Values.Sum(sg => sg.Count + (sg.Count == 1 ? 0 : 1)));
            bw.WriteInt32(LongFormat ? 0x38 : 0x1C);
            bw.ReserveInt32("ConditionCount");
            bw.WriteInt32(LongFormat ? 0x18 : 0x10);
            bw.ReserveInt32("CommandCallCount");
            bw.WriteInt32(LongFormat ? 0x10 : 0x8);
            bw.ReserveInt32("CommandArgCount");
            bw.ReserveInt32("ConditionOffsetsOffset");
            bw.ReserveInt32("ConditionOffsetsCount");
            bw.ReserveInt32("NameBlockOffset");
            bw.WriteInt32(Name == null ? 0 : Name.Length + 1);
            bw.ReserveInt32("UnkOffset1");
            bw.WriteInt32(0);
            bw.ReserveInt32("UnkOffset2");
            bw.WriteInt32(0);

            long dataStart = bw.Position;

            bw.WriteInt32(1);
            bw.WriteInt32(Unk70);
            bw.WriteInt32(Unk74);
            bw.WriteInt32(Unk78);
            bw.WriteInt32(Unk7C);
            if (LongFormat)
            {
                bw.WriteInt32(0);
            }

            ReserveVarint(bw, LongFormat, "StateGroupsOffset");
            WriteVarint(bw, LongFormat, StateGroups.Count);
            ReserveVarint(bw, LongFormat, "NameOffset");
            WriteVarint(bw, LongFormat, Name == null ? 0 : Name.Length + 1);
            long unkNull = DarkSoulsCount == 1 ? 0 : -1;

            WriteVarint(bw, LongFormat, unkNull);
            WriteVarint(bw, LongFormat, unkNull);

            // Collect and sort all the IDs so everything is definitely in the same order everywhere
            List <long> stateGroupIDs = StateGroups.Keys.ToList();

            stateGroupIDs.Sort();
            var stateIDs = new Dictionary <long, List <long> >();

            foreach (long groupID in stateGroupIDs)
            {
                stateIDs[groupID] = StateGroups[groupID].Keys.ToList();
                stateIDs[groupID].Sort();
            }

            if (StateGroups.Count == 0)
            {
                FillVarint(bw, LongFormat, "StateGroupsOffset", -1);
            }
            else
            {
                FillVarint(bw, LongFormat, "StateGroupsOffset", bw.Position - dataStart);
                foreach (long groupID in stateGroupIDs)
                {
                    WriteVarint(bw, LongFormat, groupID);
                    ReserveVarint(bw, LongFormat, $"StateGroup{groupID}:StatesOffset1");
                    WriteVarint(bw, LongFormat, StateGroups[groupID].Count);
                    ReserveVarint(bw, LongFormat, $"StateGroup{groupID}:StatesOffset2");
                }
            }

            var stateOffsets      = new Dictionary <long, Dictionary <long, long> >();
            var weirdStateOffsets = new List <long[]>();

            foreach (long groupID in stateGroupIDs)
            {
                stateOffsets[groupID] = new Dictionary <long, long>();
                FillVarint(bw, LongFormat, $"StateGroup{groupID}:StatesOffset1", bw.Position - dataStart);
                FillVarint(bw, LongFormat, $"StateGroup{groupID}:StatesOffset2", bw.Position - dataStart);
                long firstStateOffset = bw.Position;
                foreach (long stateID in stateIDs[groupID])
                {
                    stateOffsets[groupID][stateID] = bw.Position - dataStart;
                    StateGroups[groupID][stateID].WriteHeader(bw, LongFormat, groupID, stateID);
                }
                if (StateGroups[groupID].Count > 1)
                {
                    weirdStateOffsets.Add(new long[] { firstStateOffset, bw.Position });
                    bw.Position += stateSize;
                }
            }

            // Make a list of every unique condition
            var conditions = new Dictionary <long, List <Condition> >();

            foreach (long groupID in stateGroupIDs)
            {
                conditions[groupID] = new List <Condition>();
                void addCondition(Condition cond)
                {
                    if (!conditions[groupID].Any(c => ReferenceEquals(cond, c)))
                    {
                        conditions[groupID].Add(cond);
                        foreach (Condition subCond in cond.Subconditions)
                        {
                            addCondition(subCond);
                        }
                    }
                }

                foreach (State state in StateGroups[groupID].Values)
                {
                    foreach (Condition cond in state.Conditions)
                    {
                        addCondition(cond);
                    }
                }
            }
            bw.FillInt32("ConditionCount", conditions.Values.Sum(group => group.Count));

            // Yes, I do in fact want this to be keyed by reference
            var conditionOffsets = new Dictionary <Condition, long>();

            foreach (long groupID in stateGroupIDs)
            {
                for (int i = 0; i < conditions[groupID].Count; i++)
                {
                    Condition cond = conditions[groupID][i];
                    conditionOffsets[cond] = bw.Position - dataStart;
                    cond.WriteHeader(bw, LongFormat, groupID, i, stateOffsets[groupID]);
                }
            }

            var commands = new List <CommandCall>();

            foreach (long groupID in stateGroupIDs)
            {
                foreach (long stateID in stateIDs[groupID])
                {
                    StateGroups[groupID][stateID].WriteCommandCalls(bw, LongFormat, groupID, stateID, dataStart, commands);
                }
                for (int i = 0; i < conditions[groupID].Count; i++)
                {
                    conditions[groupID][i].WriteCommandCalls(bw, LongFormat, groupID, i, dataStart, commands);
                }
            }
            bw.FillInt32("CommandCallCount", commands.Count);
            bw.FillInt32("CommandArgCount", commands.Sum(command => command.Arguments.Count));

            for (int i = 0; i < commands.Count; i++)
            {
                commands[i].WriteArgs(bw, LongFormat, i, dataStart);
            }

            bw.FillInt32("ConditionOffsetsOffset", (int)(bw.Position - dataStart));
            int conditionOffsetsCount = 0;

            foreach (long groupID in stateGroupIDs)
            {
                foreach (long stateID in stateIDs[groupID])
                {
                    conditionOffsetsCount += StateGroups[groupID][stateID].WriteConditionOffsets(bw, LongFormat, groupID, stateID, dataStart, conditionOffsets);
                }
                for (int i = 0; i < conditions[groupID].Count; i++)
                {
                    conditionOffsetsCount += conditions[groupID][i].WriteConditionOffsets(bw, LongFormat, groupID, i, dataStart, conditionOffsets);
                }
            }
            bw.FillInt32("ConditionOffsetsCount", conditionOffsetsCount);

            foreach (long groupID in stateGroupIDs)
            {
                for (int i = 0; i < conditions[groupID].Count; i++)
                {
                    conditions[groupID][i].WriteEvaluator(bw, LongFormat, groupID, i, dataStart);
                }
            }
            for (int i = 0; i < commands.Count; i++)
            {
                commands[i].WriteBytecode(bw, LongFormat, i, dataStart);
            }

            bw.FillInt32("NameBlockOffset", (int)(bw.Position - dataStart));
            if (Name == null)
            {
                FillVarint(bw, LongFormat, "NameOffset", -1);
            }
            else
            {
                bw.Pad(2);
                FillVarint(bw, LongFormat, "NameOffset", bw.Position - dataStart);
                bw.WriteUTF16(Name, true);
            }
            bw.FillInt32("UnkOffset1", (int)(bw.Position - dataStart));
            bw.FillInt32("UnkOffset2", (int)(bw.Position - dataStart));
            bw.FillInt32("DataSize", (int)(bw.Position - dataStart));

            if (DarkSoulsCount == 1)
            {
                bw.Pad(4);
            }
            else if (DarkSoulsCount == 2)
            {
                bw.Pad(0x10);
            }

            foreach (long[] offsets in weirdStateOffsets)
            {
                bw.Position = offsets[0];
                byte[] bytes = new byte[stateSize];
                bw.Stream.Read(bytes, 0, stateSize);
                bw.Position = offsets[1];
                bw.WriteBytes(bytes);
            }
        }
예제 #3
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            bw.WriteByte(0);
            bw.WriteByte(0);
            bw.WriteByte((byte)(Long ? 2 : 1));
            bw.WriteByte(0);

            bw.ReserveInt32("FileSize");
            bw.WriteInt32(1);
            bw.ReserveInt32("GroupCount");
            bw.WriteInt32(Entries.Count);

            if (Long)
            {
                bw.WriteInt32(0xFF);
            }

            if (Long)
            {
                bw.ReserveInt64("StringOffsets");
            }
            else
            {
                bw.ReserveInt32("StringOffsets");
            }

            bw.WriteInt32(0);
            bw.WriteInt32(0);

            int groupCount = 0;

            Entries.Sort((e1, e2) => e1.ID.CompareTo(e2.ID));
            for (int i = 0; i < Entries.Count; i++)
            {
                bw.WriteInt32(i);
                bw.WriteInt32(Entries[i].ID);
                while (i < Entries.Count - 1 && Entries[i + 1].ID == Entries[i].ID + 1)
                {
                    i++;
                }
                bw.WriteInt32(Entries[i].ID);

                if (Long)
                {
                    bw.WriteInt32(0);
                }

                groupCount++;
            }
            bw.FillInt32("GroupCount", groupCount);

            if (Long)
            {
                bw.FillInt64("StringOffsets", bw.Position);
            }
            else
            {
                bw.FillInt32("StringOffsets", (int)bw.Position);
            }

            for (int i = 0; i < Entries.Count; i++)
            {
                if (Long)
                {
                    bw.ReserveInt64($"StringOffset{i}");
                }
                else
                {
                    bw.ReserveInt32($"StringOffset{i}");
                }
            }

            for (int i = 0; i < Entries.Count; i++)
            {
                string text = Entries[i].Text;

                if (Long)
                {
                    bw.FillInt64($"StringOffset{i}", text == null ? 0 : bw.Position);
                }
                else
                {
                    bw.FillInt64($"StringOffset{i}", text == null ? 0 : (int)bw.Position);
                }

                if (text != null)
                {
                    bw.WriteUTF16(Entries[i].Text, true);
                }
            }

            bw.FillInt32("FileSize", (int)bw.Position);
        }
예제 #4
0
        internal override void Write(BinaryWriterEx bw)
        {
            if (layout == null)
            {
                throw new InvalidOperationException("Params cannot be written without a layout.");
            }

            Rows.Sort((r1, r2) => r1.ID.CompareTo(r2.ID));

            bw.BigEndian = false;

            bw.ReserveInt32("NameOffset");
            bw.WriteInt16(0);
            bw.WriteInt16(Unk1);
            bw.WriteInt16(Unk2);
            bw.WriteUInt16((ushort)Rows.Count);

            if (FixStrID)
            {
                bw.WriteFixStr(ID, 0x20);
            }
            else
            {
                bw.WriteInt32(0);
                bw.ReserveInt32("IDOffset");
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
            }

            bw.WriteByte(0);
            bw.WriteByte(Unk3);
            bw.WriteByte(Unk4);
            bw.WriteByte(0);

            bw.ReserveInt64("DataStart");
            bw.WriteInt32(0);
            bw.WriteInt32(0);

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

            bw.FillInt64("DataStart", bw.Position);

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteCells(bw, i, layout);
            }

            bw.FillInt32("NameOffset", (int)bw.Position);
            if (FixStrID)
            {
                if (Unk4 == 6)
                {
                    bw.WriteShiftJIS(Name, true);
                }
                else if (Unk4 == 7)
                {
                    bw.WriteUTF16(Name, true);
                }
            }
            else
            {
                bw.WriteShiftJIS(Name, true);
                bw.FillInt32("IDOffset", (int)bw.Position);
                bw.WriteASCII(ID, true);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteName(bw, i, Unk4);
            }
        }
예제 #5
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.WriteASCII("TAE ");
            bw.WriteByte(0);
            bw.WriteByte(0);
            bw.WriteByte(0);
            bw.WriteByte(0xFF);
            bw.WriteInt32(0x1000D);
            bw.ReserveInt32("FileSize");
            bw.WriteInt64(0x40);
            bw.WriteInt64(1);
            bw.WriteInt64(0x50);
            bw.WriteInt64(0x80);
            bw.WriteInt64(Unk30);
            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);
        }
예제 #6
0
        /// <summary>
        /// Writes FLVER data to a BinaryWriterEx.
        /// </summary>
        protected 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.Length < 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 (FLVER.Dummy dummy in Dummies)
            {
                dummy.Write(bw, Header.Version);
            }

            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.Length);
                }
                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.Unicode, 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);
            }
        }
예제 #7
0
            internal void Write(BinaryWriterEx bw, NGPVersion version)
            {
                long start = bw.Position;

                bw.WriteInt32(Unk00);
                bw.ReserveInt32("MeshLength");
                bw.WriteInt32(Unk08);
                if (version == NGPVersion.Scholar)
                {
                    bw.WriteInt32(0);
                }
                bw.WriteVector3(BoundingBoxMin);
                bw.WriteVector3(BoundingBoxMax);
                bw.WriteInt32(Vertices.Count);
                bw.WriteInt16((short)Faces.Count);
                bw.WriteInt16((short)Struct4s.Count);
                bw.WriteInt16(Unk30);
                bw.WriteInt16(Unk32);
                bw.WriteByte(1);
                bw.WriteByte(0);
                bw.WriteByte(0);
                bw.WriteByte(0);
                if (version == NGPVersion.Scholar)
                {
                    bw.WriteInt64(0);
                }
                bw.ReserveVarint("VerticesOffset");
                bw.ReserveVarint("Struct2sOffset");
                bw.ReserveVarint("FacesOffset");
                bw.ReserveVarint("Struct4sOffset");
                bw.ReserveVarint("Struct5sOffset");
                bw.ReserveVarint("Struct6sOffset");

                bw.FillVarint("VerticesOffset", bw.Position);
                foreach (Vector3 vertex in Vertices)
                {
                    bw.WriteVector3(vertex);
                }
                bw.Pad(bw.VarintSize);

                bw.FillVarint("Struct2sOffset", bw.Position);
                foreach (int struct2 in Struct2s)
                {
                    bw.WriteInt32(struct2);
                }
                bw.Pad(bw.VarintSize);

                bw.FillVarint("FacesOffset", bw.Position);
                foreach (Face face in Faces)
                {
                    face.Write(bw);
                }
                bw.Pad(bw.VarintSize);

                bw.FillVarint("Struct4sOffset", bw.Position);
                foreach (Struct4 struct4 in Struct4s)
                {
                    struct4.Write(bw);
                }
                bw.Pad(bw.VarintSize);

                bw.FillVarint("Struct5sOffset", bw.Position);
                short index = 0;

                Struct5Root.Write(bw, ref index);
                bw.Pad(bw.VarintSize);

                bw.FillVarint("Struct6sOffset", bw.Position);
                index = 0;
                int faceIndexIndex = 0;

                Struct5Root.WriteFaceIndices(bw, ref index, ref faceIndexIndex);
                bw.Pad(bw.VarintSize);

                bw.FillInt32("MeshLength", (int)(bw.Position - start));
            }
예제 #8
0
            internal void Write(BinaryWriterEx bw, PARAMDEF def, int index)
            {
                if (def.FormatVersion >= 202)
                {
                    bw.ReserveInt64($"DisplayNameOffset{index}");
                }
                else if (def.Unicode)
                {
                    bw.WriteFixStrW(DisplayName, 0x40, (byte)(def.FormatVersion >= 104 ? 0x00 : 0x20));
                }
                else
                {
                    bw.WriteFixStr(DisplayName, 0x40, (byte)(def.FormatVersion >= 104 ? 0x00 : 0x20));
                }

                byte padding = (byte)(def.FormatVersion >= 200 ? 0x00 : 0x20);

                bw.WriteFixStr(DisplayType.ToString(), 8, padding);
                bw.WriteFixStr(DisplayFormat, 8, padding);
                bw.WriteSingle(Default);
                bw.WriteSingle(Minimum);
                bw.WriteSingle(Maximum);
                bw.WriteSingle(Increment);
                bw.WriteInt32((int)EditFlags);
                bw.WriteInt32(ParamUtil.GetValueSize(DisplayType) * (ParamUtil.IsArrayType(DisplayType) ? ArrayLength : 1));

                if (def.FormatVersion >= 200)
                {
                    bw.ReserveInt64($"DescriptionOffset{index}");
                }
                else
                {
                    bw.ReserveInt32($"DescriptionOffset{index}");
                }

                if (def.FormatVersion >= 202)
                {
                    bw.ReserveInt64($"InternalTypeOffset{index}");
                }
                else
                {
                    bw.WriteFixStr(InternalType, 0x20, padding);
                }

                if (def.FormatVersion >= 202)
                {
                    bw.ReserveInt64($"InternalNameOffset{index}");
                }
                else if (def.FormatVersion >= 102)
                {
                    bw.WriteFixStr(MakeInternalName(), 0x20, padding);
                }

                if (def.FormatVersion >= 104)
                {
                    bw.WriteInt32(SortID);
                }

                if (def.FormatVersion >= 200)
                {
                    bw.WriteInt32(0);
                    bw.ReserveInt64($"UnkB8Offset{index}");
                    bw.ReserveInt64($"UnkC0Offset{index}");
                    bw.ReserveInt64($"UnkC8Offset{index}");
                }
            }
예제 #9
0
 internal void WriteHeaderOffset(BinaryWriterEx bw, int groupIndex)
 {
     bw.ReserveInt32($"GroupHeaderOffset{groupIndex}");
 }
예제 #10
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            bw.WriteUTF16("filt");
            bw.WriteInt32(3);
            bw.WriteInt32(0);
            bw.WriteInt32(Groups.Count);
            bw.WriteInt32(Unk1);
            bw.WriteInt32(0x50);

            bw.ReserveInt32("GroupHeadersOffset");
            bw.ReserveInt32("ParamHeaderOffsetsOffset");
            bw.ReserveInt32("ParamHeadersOffset");
            bw.ReserveInt32("ValuesOffset");
            bw.ReserveInt32("UnkOffset1");
            bw.ReserveInt32("UnkOffset2");

            bw.WriteInt32(Unk3s.Count);
            bw.ReserveInt32("UnkOffset3");
            bw.ReserveInt32("Unk3ValuesOffset");
            bw.WriteInt32(0);

            bw.ReserveInt32("CommentOffsetsOffsetsOffset");
            bw.ReserveInt32("CommentOffsetsOffset");
            bw.ReserveInt32("CommentsOffset");

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

            int groupHeadersOffset = (int)bw.Position;

            bw.FillInt32("GroupHeadersOffset", groupHeadersOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteHeader(bw, i, groupHeadersOffset);
            }

            int paramHeaderOffsetsOffset = (int)bw.Position;

            bw.FillInt32("ParamHeaderOffsetsOffset", paramHeaderOffsetsOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteParamHeaderOffsets(bw, i, paramHeaderOffsetsOffset);
            }

            int paramHeadersOffset = (int)bw.Position;

            bw.FillInt32("ParamHeadersOffset", paramHeadersOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteParamHeaders(bw, i, paramHeadersOffset);
            }

            int valuesOffset = (int)bw.Position;

            bw.FillInt32("ValuesOffset", valuesOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteValues(bw, i, valuesOffset);
            }

            int unkOffset1 = (int)bw.Position;

            bw.FillInt32("UnkOffset1", (int)bw.Position);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteUnk1(bw, i, unkOffset1);
            }

            bw.FillInt32("UnkOffset2", (int)bw.Position);
            bw.WriteBytes(UnkBlock2);

            bw.FillInt32("UnkOffset3", (int)bw.Position);
            for (int i = 0; i < Unk3s.Count; i++)
            {
                Unk3s[i].WriteHeader(bw, i);
            }

            int unk3ValuesOffset = (int)bw.Position;

            bw.FillInt32("Unk3ValuesOffset", unk3ValuesOffset);
            for (int i = 0; i < Unk3s.Count; i++)
            {
                Unk3s[i].WriteValues(bw, i, unk3ValuesOffset);
            }

            bw.FillInt32("CommentOffsetsOffsetsOffset", (int)bw.Position);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteCommentOffsetsOffset(bw, i);
            }

            int commentOffsetsOffset = (int)bw.Position;

            bw.FillInt32("CommentOffsetsOffset", commentOffsetsOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteCommentOffsets(bw, i, commentOffsetsOffset);
            }

            int commentsOffset = (int)bw.Position;

            bw.FillInt32("CommentsOffset", commentsOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteComments(bw, i, commentsOffset);
            }
        }
예제 #11
0
            internal void Write(BinaryWriterEx bw, List <CustomData> allCustomData, List <long> customDataValueOffsets)
            {
                bw.WriteFixStrW(Name, 0x40, 0x00);
                bw.WriteUInt32((uint)Type);
                bw.WriteInt32(Type == DataType.Color ? 3 : 0);

                int length = -1;

                if (Type == DataType.String)
                {
                    length = SFEncoding.UTF16.GetByteCount((string)Value + '\0');
                    if (length % 0x10 != 0)
                    {
                        length += 0x10 - length % 0x10;
                    }
                }
                else if (Type == DataType.Custom)
                {
                    length = ((byte[])Value).Length;
                    if (length % 4 != 0)
                    {
                        throw new InvalidDataException($"Unexpected custom data custom length: {length}");
                    }
                }
                else if (Type == DataType.Color)
                {
                    length = 4;
                }

                long valueOffset = bw.Position;

                switch (Type)
                {
                case DataType.Bool: bw.WriteBoolean((bool)Value); break;

                case DataType.SByte: bw.WriteSByte((sbyte)Value); break;

                case DataType.Byte: bw.WriteByte((byte)Value); break;

                case DataType.Short: bw.WriteInt16((short)Value); break;

                case DataType.Int: bw.WriteInt32((int)Value); break;

                case DataType.UInt: bw.WriteUInt32((uint)Value); break;

                case DataType.Float: bw.WriteSingle((float)Value); break;

                case DataType.String:
                case DataType.Custom:
                case DataType.Color: bw.WriteInt32(length); break;

                default: throw new NotImplementedException($"Unimplemented custom data type: {Type}");
                }

                if (Type == DataType.Bool || Type == DataType.SByte || Type == DataType.Byte)
                {
                    bw.WriteByte(0);
                    bw.WriteInt16(0);
                }
                else if (Type == DataType.Short)
                {
                    bw.WriteInt16(0);
                }

                // This is probably wrong for the 64-bit format
                bw.WriteInt32(0);
                bw.ReserveInt32($"SequencesOffset[{allCustomData.Count}]");
                bw.WriteInt32(Sequences.Count);
                bw.WriteInt32(0);
                bw.WriteInt32(0);

                if (Type == DataType.String)
                {
                    bw.WriteFixStrW((string)Value, length, 0x00);
                }
                else if (Type == DataType.Custom)
                {
                    bw.WriteBytes((byte[])Value);
                }
                else if (Type == DataType.Color)
                {
                    var color = (Color)Value;
                    valueOffset = bw.Position;
                    bw.WriteByte(color.R);
                    bw.WriteByte(color.G);
                    bw.WriteByte(color.B);
                    bw.WriteByte(0);
                }

                allCustomData.Add(this);
                customDataValueOffsets.Add(valueOffset);
            }
예제 #12
0
 internal void WriteHeader(BinaryWriterEx bw, int index)
 {
     bw.WriteInt32(ID);
     bw.WriteInt32(Values.Count);
     bw.ReserveInt32($"Unk3ValuesOffset{index}");
 }
예제 #13
0
 internal void WriteCommentOffsetsOffset(BinaryWriterEx bw, int index)
 {
     bw.ReserveInt32($"CommentOffsetsOffset{index}");
 }
예제 #14
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            if (Game == GPGame.DarkSouls2)
            {
                bw.WriteASCII("filt");
            }
            else
            {
                bw.WriteUTF16("filt");
            }
            bw.WriteUInt32((uint)Game);
            bw.WriteByte(0);
            bw.WriteBoolean(Unk0D);
            bw.WriteInt16(0);
            bw.WriteInt32(Groups.Count);
            bw.WriteInt32(Unk14);
            bw.ReserveInt32("HeaderSize");

            bw.ReserveInt32("GroupHeadersOffset");
            bw.ReserveInt32("ParamHeaderOffsetsOffset");
            bw.ReserveInt32("ParamHeadersOffset");
            bw.ReserveInt32("ValuesOffset");
            bw.ReserveInt32("ValueIDsOffset");
            bw.ReserveInt32("UnkOffset2");

            bw.WriteInt32(Unk3s.Count);
            bw.ReserveInt32("UnkOffset3");
            bw.ReserveInt32("Unk3ValuesOffset");
            bw.WriteInt32(0);

            if (Game == GPGame.DarkSouls3 || Game == GPGame.Sekiro)
            {
                bw.ReserveInt32("CommentOffsetsOffsetsOffset");
                bw.ReserveInt32("CommentOffsetsOffset");
                bw.ReserveInt32("CommentsOffset");
            }

            if (Game == GPGame.Sekiro)
            {
                bw.WriteSingle(Unk50);
            }

            bw.FillInt32("HeaderSize", (int)bw.Position);

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

            int groupHeadersOffset = (int)bw.Position;

            bw.FillInt32("GroupHeadersOffset", groupHeadersOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteHeader(bw, Game, i, groupHeadersOffset);
            }

            int paramHeaderOffsetsOffset = (int)bw.Position;

            bw.FillInt32("ParamHeaderOffsetsOffset", paramHeaderOffsetsOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteParamHeaderOffsets(bw, i, paramHeaderOffsetsOffset);
            }

            int paramHeadersOffset = (int)bw.Position;

            bw.FillInt32("ParamHeadersOffset", paramHeadersOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteParamHeaders(bw, Game, i, paramHeadersOffset);
            }

            int valuesOffset = (int)bw.Position;

            bw.FillInt32("ValuesOffset", valuesOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteValues(bw, i, valuesOffset);
            }

            int valueIDsOffset = (int)bw.Position;

            bw.FillInt32("ValueIDsOffset", (int)bw.Position);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteValueIDs(bw, Game, i, valueIDsOffset);
            }

            bw.FillInt32("UnkOffset2", (int)bw.Position);
            bw.WriteBytes(UnkBlock2);

            bw.FillInt32("UnkOffset3", (int)bw.Position);
            for (int i = 0; i < Unk3s.Count; i++)
            {
                Unk3s[i].WriteHeader(bw, Game, i);
            }

            int unk3ValuesOffset = (int)bw.Position;

            bw.FillInt32("Unk3ValuesOffset", unk3ValuesOffset);
            for (int i = 0; i < Unk3s.Count; i++)
            {
                Unk3s[i].WriteValues(bw, Game, i, unk3ValuesOffset);
            }

            if (Game == GPGame.DarkSouls3 || Game == GPGame.Sekiro)
            {
                bw.FillInt32("CommentOffsetsOffsetsOffset", (int)bw.Position);
                for (int i = 0; i < Groups.Count; i++)
                {
                    Groups[i].WriteCommentOffsetsOffset(bw, i);
                }

                int commentOffsetsOffset = (int)bw.Position;
                bw.FillInt32("CommentOffsetsOffset", commentOffsetsOffset);
                for (int i = 0; i < Groups.Count; i++)
                {
                    Groups[i].WriteCommentOffsets(bw, i, commentOffsetsOffset);
                }

                int commentsOffset = (int)bw.Position;
                bw.FillInt32("CommentsOffset", commentsOffset);
                for (int i = 0; i < Groups.Count; i++)
                {
                    Groups[i].WriteComments(bw, i, commentsOffset);
                }
            }
        }
예제 #15
0
            internal void WriteHeader(BinaryWriterEx bw, int index, TPFPlatform platform, byte flag2)
            {
                if (platform == TPFPlatform.PC)
                {
                    DDS dds = new DDS(Bytes);
                    if (dds.dwCaps2.HasFlag(DDS.DDSCAPS2.CUBEMAP))
                    {
                        Type = TexType.Cubemap;
                    }
                    else if (dds.dwCaps2.HasFlag(DDS.DDSCAPS2.VOLUME))
                    {
                        Type = TexType.Volume;
                    }
                    else
                    {
                        Type = TexType.Texture;
                    }
                    Mipmaps = (byte)dds.dwMipMapCount;
                }

                bw.ReserveUInt32($"FileData{index}");
                bw.ReserveInt32($"FileSize{index}");

                bw.WriteByte(Format);
                bw.WriteByte((byte)Type);
                bw.WriteByte(Mipmaps);
                bw.WriteByte(Flags1);

                if (platform != TPFPlatform.PC)
                {
                    bw.WriteInt16(Header.Width);
                    bw.WriteInt16(Header.Height);

                    if (platform == TPFPlatform.Xbox360)
                    {
                        bw.WriteInt32(0);
                    }
                    else if (platform == TPFPlatform.PS3)
                    {
                        bw.WriteInt32(Header.Unk1);
                        if (flag2 != 0)
                        {
                            bw.WriteInt32(Header.Unk2);
                        }
                    }
                    else if (platform == TPFPlatform.PS4 || platform == TPFPlatform.Xbone)
                    {
                        bw.WriteInt32(Header.TextureCount);
                        bw.WriteInt32(Header.Unk2);
                    }
                }

                bw.ReserveUInt32($"FileName{index}");
                bw.WriteInt32(FloatStruct == null ? 0 : 1);

                if (platform == TPFPlatform.PS4 || platform == TPFPlatform.Xbone)
                {
                    bw.WriteInt32(Header.DXGIFormat);
                }

                if (FloatStruct != null)
                {
                    FloatStruct.Write(bw);
                }
            }
예제 #16
0
 internal void WriteParamHeaderOffset(BinaryWriterEx bw, int groupIndex, int paramIndex)
 {
     bw.ReserveInt32($"ParamHeaderOffset{groupIndex}:{paramIndex}");
 }
예제 #17
0
 internal void Write(BinaryWriterEx bw, int index)
 {
     bw.WriteInt32(Count);
     bw.ReserveInt32($"FileHeadersOffset{index}");
 }
예제 #18
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            bw.WriteASCII("filt");
            bw.WriteInt32(2);
            bw.WriteInt32(0);
            bw.WriteInt32(Groups.Count);
            bw.WriteInt32(Unk1);
            bw.WriteInt32(0x40);

            bw.ReserveInt32("GroupHeadersOffset");
            bw.ReserveInt32("ParamHeaderOffsetsOffset");
            bw.ReserveInt32("ParamHeadersOffset");
            bw.ReserveInt32("ValuesOffset");
            bw.ReserveInt32("UnkBlock1Offset");
            bw.ReserveInt32("UnkBlock2Offset");

            bw.WriteInt32(Unk2);
            bw.ReserveInt32("UnkBlock3Offset");
            bw.ReserveInt32("UnkBlock4Offset");
            bw.WriteInt32(0);

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

            int groupHeadersOffset = (int)bw.Position;

            bw.FillInt32("GroupHeadersOffset", groupHeadersOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteHeader(bw, i, groupHeadersOffset);
            }

            int paramHeaderOffsetsOffset = (int)bw.Position;

            bw.FillInt32("ParamHeaderOffsetsOffset", paramHeaderOffsetsOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteParamHeaderOffsets(bw, i, paramHeaderOffsetsOffset);
            }

            int paramHeadersOffset = (int)bw.Position;

            bw.FillInt32("ParamHeadersOffset", paramHeadersOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteParamHeaders(bw, i, paramHeadersOffset);
            }

            int valuesOffset = (int)bw.Position;

            bw.FillInt32("ValuesOffset", valuesOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteValues(bw, i, valuesOffset);
            }

            bw.FillInt32("UnkBlock1Offset", (int)bw.Position);
            bw.WriteBytes(UnkBlock1);

            bw.FillInt32("UnkBlock2Offset", (int)bw.Position);
            bw.WriteBytes(UnkBlock2);

            bw.FillInt32("UnkBlock3Offset", (int)bw.Position);
            bw.WriteBytes(UnkBlock3);

            bw.FillInt32("UnkBlock4Offset", (int)bw.Position);
            bw.WriteBytes(UnkBlock4);
        }
예제 #19
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);
            }
        }
예제 #20
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            bw.WriteInt32(0);
            bw.ReserveInt32("FileSize");
            int fileStart = (int)bw.Position;

            bw.WriteInt32(0);
            bw.WriteInt32(3);
            WriteMarker(bw, 0x01);
            bw.WriteInt32(0);
            bw.WriteInt32(0x1C);
            bw.WriteInt32(1);
            bw.WriteInt32(2);
            WriteMarker(bw, 0xB0);
            bw.WriteInt32(4);
            bw.WriteASCII("MTD ");
            WriteMarker(bw, 0x34);
            bw.WriteInt32(0x3E8);
            WriteMarker(bw, 0x01);
            bw.WriteInt32(0);
            bw.ReserveInt32("DataSize");
            bw.WriteInt32(2);
            bw.WriteInt32(4);
            int dataStart = (int)bw.Position;

            WriteMarker(bw, 0xA3);

            bw.WriteShiftJISLengthPrefixed(ShaderPath, 0xA3);
            bw.WriteShiftJISLengthPrefixed(Description, 0x03);

            bw.WriteInt32(1);
            bw.WriteInt32(0);
            bw.ReserveInt32("ParamSize");
            bw.WriteInt32(3);
            bw.WriteInt32(4);
            WriteMarker(bw, 0xA3);
            bw.WriteInt32(0);
            int paramStart = (int)bw.Position;

            WriteMarker(bw, 0x03);

            bw.WriteInt32(Params.Count);
            foreach (Param internalEntry in Params)
            {
                internalEntry.Write(bw);
            }

            WriteMarker(bw, 0x03);

            bw.WriteInt32(Textures.Count);
            foreach (Texture externalEntry in Textures)
            {
                externalEntry.Write(bw);
            }

            WriteMarker(bw, 0x04);
            bw.WriteInt32(0);
            WriteMarker(bw, 0x04);
            bw.WriteInt32(0);
            WriteMarker(bw, 0x04);
            bw.WriteInt32(0);

            int position = (int)bw.Position;

            bw.FillInt32("FileSize", position - fileStart);
            bw.FillInt32("DataSize", position - dataStart);
            bw.FillInt32("ParamSize", position - paramStart);
        }
예제 #21
0
 internal void Write(BinaryWriterEx bw, int entryIndex, int memberIndex, List <int> offsetIndex)
 {
     offsetIndex.Add((int)bw.Position);
     bw.ReserveInt32($"MemberTextOffset{entryIndex}:{memberIndex}");
     bw.WriteInt32(Unk04);
 }
예제 #22
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);
            }
예제 #23
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));
            long dataStart = bw.Position;

            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 - dataStart));
                bw.FillInt32($"ChunkSize{i}", chunk.Length);
                bw.WriteBytes(chunk);
                bw.Pad(0x10);
            }

            bw.FillInt32("CompressedSize", compressedSize);
        }
예제 #24
0
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = BigEndian;

            bw.ReserveInt32("FileSize");
            bw.WriteInt16((short)(Version >= 201 ? 0xFF : 0x30));
            bw.WriteInt16(Unk06);
            bw.WriteInt16((short)Fields.Count);

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

            bw.WriteFixStr(ParamType, 0x20, (byte)(Version >= 201 ? 0x00 : 0x20));
            bw.WriteSByte((sbyte)(BigEndian ? -1 : 0));
            bw.WriteBoolean(Unicode);
            bw.WriteInt16(Version);
            if (Version >= 201)
            {
                bw.WriteInt64(0x38);
            }

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

            long descriptionsStart = bw.Position;

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

            if (Version >= 104)
            {
                long descriptionsLength = bw.Position - descriptionsStart;
                if (descriptionsLength % 0x10 != 0)
                {
                    bw.WritePattern((int)(0x10 - descriptionsLength % 0x10), 0x00);
                }
            }
            else
            {
                bw.Pad(0x10);
            }
            bw.FillInt32("FileSize", (int)bw.Position);
        }
예제 #25
0
        protected override void Write(BinaryWriterEx bw)
        {
            bool bigEndian = Format == Game.DarkSouls1BE;
            bool is64Bit   = Format >= Game.Bloodborne;
            bool unk06     = Format >= Game.DarkSouls3;
            bool unk07     = Format >= Game.Sekiro;
            int  version   = Format < Game.DarkSouls3 ? 0xCC : 0xCD;

            var layers = new List <uint>();

            foreach (Event evt in Events)
            {
                foreach (Instruction inst in evt.Instructions)
                {
                    if (inst.Layer.HasValue && !layers.Contains(inst.Layer.Value))
                    {
                        layers.Add(inst.Layer.Value);
                    }
                }
            }

            bw.WriteASCII("EVD\0");
            bw.WriteBoolean(bigEndian);
            bw.WriteSByte((sbyte)(is64Bit ? -1 : 0));
            bw.WriteBoolean(unk06);
            bw.WriteSByte((sbyte)(unk07 ? -1 : 0));
            bw.BigEndian  = bigEndian;
            bw.VarintLong = is64Bit;

            bw.WriteInt32(version);
            bw.ReserveInt32("FileSize");

            Offsets offsets = default;

            bw.WriteVarint(Events.Count);
            bw.ReserveVarint("EventsOffset");
            bw.WriteVarint(Events.Sum(e => e.Instructions.Count));
            bw.ReserveVarint("InstructionsOffset");
            bw.WriteVarint(0);
            bw.ReserveVarint("Offset3");
            bw.WriteVarint(layers.Count);
            bw.ReserveVarint("LayersOffset");
            bw.WriteVarint(Events.Sum(e => e.Parameters.Count));
            bw.ReserveVarint("ParametersOffset");
            bw.WriteVarint(LinkedFileOffsets.Count);
            bw.ReserveVarint("LinkedFilesOffset");
            bw.ReserveVarint("ArgumentsLength");
            bw.ReserveVarint("ArgumentsOffset");
            bw.WriteVarint(StringData.Length);
            bw.ReserveVarint("StringsOffset");
            if (!is64Bit)
            {
                bw.WriteInt32(0);
            }

            offsets.Events = bw.Position;
            bw.FillVarint("EventsOffset", bw.Position);
            for (int i = 0; i < Events.Count; i++)
            {
                Events[i].Write(bw, Format, i);
            }

            offsets.Instructions = bw.Position;
            bw.FillVarint("InstructionsOffset", bw.Position);
            for (int i = 0; i < Events.Count; i++)
            {
                Events[i].WriteInstructions(bw, Format, offsets, i);
            }

            bw.FillVarint("Offset3", bw.Position);

            offsets.Layers = bw.Position;
            bw.FillVarint("LayersOffset", bw.Position);
            var layerOffsets = new Dictionary <uint, long>(layers.Count);

            foreach (uint layer in layers)
            {
                layerOffsets[layer] = bw.Position - offsets.Layers;
                Layer.Write(bw, layer);
            }
            for (int i = 0; i < Events.Count; i++)
            {
                Event evt = Events[i];
                for (int j = 0; j < evt.Instructions.Count; j++)
                {
                    evt.Instructions[j].FillLayerOffset(bw, Format, i, j, layerOffsets);
                }
            }

            offsets.Arguments = bw.Position;
            bw.FillVarint("ArgumentsOffset", bw.Position);
            for (int i = 0; i < Events.Count; i++)
            {
                Event evt = Events[i];
                for (int j = 0; j < evt.Instructions.Count; j++)
                {
                    evt.Instructions[j].WriteArgs(bw, Format, offsets, i, j);
                }
            }
            if ((bw.Position - offsets.Arguments) % 0x10 > 0)
            {
                bw.WritePattern(0x10 - (int)(bw.Position - offsets.Arguments) % 0x10, 0x00);
            }
            bw.FillVarint("ArgumentsLength", bw.Position - offsets.Arguments);

            offsets.Parameters = bw.Position;
            bw.FillVarint("ParametersOffset", bw.Position);
            for (int i = 0; i < Events.Count; i++)
            {
                Events[i].WriteParameters(bw, Format, offsets, i);
            }

            offsets.LinkedFiles = bw.Position;
            bw.FillVarint("LinkedFilesOffset", bw.Position);
            foreach (long offset in LinkedFileOffsets)
            {
                bw.WriteVarint((int)offset);
            }

            offsets.Strings = bw.Position;
            bw.FillVarint("StringsOffset", bw.Position);
            bw.WriteBytes(StringData);

            bw.FillInt32("FileSize", (int)bw.Position);
        }
예제 #26
0
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = BigEndian;

            bw.WriteInt32(1);
            bw.WriteInt32(Vertices.Count);
            bw.ReserveInt32("VertexOffset");
            bw.WriteInt32(Triangles.Count);
            bw.ReserveInt32("TriangleOffset");
            bw.ReserveInt32("RootBoxOffset");
            bw.WriteInt32(0);
            bw.WriteInt32(Entities.Count);
            bw.ReserveInt32("EntityOffset");
            for (int i = 0; i < 23; i++)
            {
                bw.WriteInt32(0);
            }

            bw.FillInt32("VertexOffset", (int)bw.Position);
            foreach (Vector3 vertex in Vertices)
            {
                bw.WriteVector3(vertex);
            }

            bw.FillInt32("TriangleOffset", (int)bw.Position);
            foreach (Triangle triangle in Triangles)
            {
                triangle.Write(bw);
            }

            var boxTriangleIndexOffsets = new Queue <int>();

            void WriteBoxTriangleIndices(Box box)
            {
                if (box == null)
                {
                    return;
                }

                WriteBoxTriangleIndices(box.ChildBox1);
                WriteBoxTriangleIndices(box.ChildBox2);
                WriteBoxTriangleIndices(box.ChildBox3);
                WriteBoxTriangleIndices(box.ChildBox4);

                if (box.TriangleIndices.Count == 0)
                {
                    boxTriangleIndexOffsets.Enqueue(0);
                }
                else
                {
                    boxTriangleIndexOffsets.Enqueue((int)bw.Position);
                    bw.WriteInt32s(box.TriangleIndices);
                }
            }

            WriteBoxTriangleIndices(RootBox);

            int rootBoxOffset = RootBox.Write(bw, boxTriangleIndexOffsets);

            bw.FillInt32("RootBoxOffset", rootBoxOffset);

            var entityTriangleIndexOffsets = new List <int>();

            foreach (Entity entity in Entities)
            {
                entityTriangleIndexOffsets.Add((int)bw.Position);
                bw.WriteInt32s(entity.TriangleIndices);
            }

            bw.FillInt32("EntityOffset", (int)bw.Position);
            for (int i = 0; i < Entities.Count; i++)
            {
                Entities[i].Write(bw, entityTriangleIndexOffsets[i]);
            }
        }
예제 #27
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = BigEndian;
            bool wide = Version == FMGVersion.DarkSouls3;

            bw.WriteByte(0);
            bw.WriteBoolean(bw.BigEndian);
            bw.WriteByte((byte)Version);
            bw.WriteByte(0);

            bw.ReserveInt32("FileSize");
            bw.WriteByte(1);
            bw.WriteByte((byte)(Version == FMGVersion.DemonsSouls ? 0xFF : 0x00));
            bw.WriteByte(0);
            bw.WriteByte(0);
            bw.ReserveInt32("GroupCount");
            bw.WriteInt32(Entries.Count);

            if (wide)
            {
                bw.WriteInt32(0xFF);
            }

            if (wide)
            {
                bw.ReserveInt64("StringOffsets");
            }
            else
            {
                bw.ReserveInt32("StringOffsets");
            }

            if (wide)
            {
                bw.WriteInt64(0);
            }
            else
            {
                bw.WriteInt32(0);
            }

            int groupCount = 0;

            Entries.Sort((e1, e2) => e1.ID.CompareTo(e2.ID));
            for (int i = 0; i < Entries.Count; i++)
            {
                bw.WriteInt32(i);
                bw.WriteInt32(Entries[i].ID);
                while (i < Entries.Count - 1 && Entries[i + 1].ID == Entries[i].ID + 1)
                {
                    i++;
                }
                bw.WriteInt32(Entries[i].ID);

                if (wide)
                {
                    bw.WriteInt32(0);
                }

                groupCount++;
            }
            bw.FillInt32("GroupCount", groupCount);

            if (wide)
            {
                bw.FillInt64("StringOffsets", bw.Position);
            }
            else
            {
                bw.FillInt32("StringOffsets", (int)bw.Position);
            }

            for (int i = 0; i < Entries.Count; i++)
            {
                if (wide)
                {
                    bw.ReserveInt64($"StringOffset{i}");
                }
                else
                {
                    bw.ReserveInt32($"StringOffset{i}");
                }
            }

            for (int i = 0; i < Entries.Count; i++)
            {
                string text = Entries[i].Text;

                if (wide)
                {
                    bw.FillInt64($"StringOffset{i}", text == null ? 0 : bw.Position);
                }
                else
                {
                    bw.FillInt32($"StringOffset{i}", text == null ? 0 : (int)bw.Position);
                }

                if (text != null)
                {
                    bw.WriteUTF16(Entries[i].Text, true);
                }
            }

            bw.FillInt32("FileSize", (int)bw.Position);
        }
예제 #28
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);
        }