示例#1
0
        protected override void Write(BinaryWriterEx bw)
        {
            bw.WriteASCII("TAE ");

            bw.BigEndian = BigEndian;

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

            if (Format == TAEFormat.DS1)
            {
                bw.VarintLong = false;
                bw.WriteByte(0);
            }
            else
            {
                bw.VarintLong = true;
                bw.WriteByte(0xFF);
            }

            if (Format == TAEFormat.DS1)
            {
                bw.WriteInt32(0x1000B);
            }
            else if (Format == TAEFormat.DS3 || Format == TAEFormat.SOTFS)
            {
                bw.WriteInt32(0x1000C);
            }
            else if (Format == TAEFormat.SDT)
            {
                bw.WriteInt32(0x1000D);
            }

            bw.ReserveInt32("FileSize");
            bw.WriteVarint(0x40);
            bw.WriteVarint(1);
            bw.WriteVarint(0x50);
            bw.WriteVarint(Format == TAEFormat.DS1 ? 0x70 : 0x80);

            if (Format == TAEFormat.DS1)
            {
                bw.WriteInt16(2);
                bw.WriteInt16(1);
            }
            else
            {
                bw.WriteVarint(EventBank);
            }

            bw.WriteVarint(0);

            //DeS also
            if (Format == TAEFormat.DS1)
            {
                bw.WriteInt64(0);
                bw.WriteInt64(0);
                bw.WriteInt64(0);
            }

            bw.WriteBytes(Flags);

            if (Format == TAEFormat.SOTFS)
            {
                bw.WriteByte(0);
                bw.WriteByte(1);
            }
            else
            {
                bw.WriteByte(1);
                bw.WriteByte(0);
            }

            for (int i = 0; i < 6; i++)
            {
                bw.WriteByte(0);
            }

            bw.WriteInt32(ID);
            bw.WriteInt32(Animations.Count);
            bw.ReserveVarint("AnimsOffset");
            bw.ReserveVarint("AnimGroupsOffset");
            bw.WriteVarint(Format == TAEFormat.DS1 ? 0x90 : 0xA0);
            bw.WriteVarint(Animations.Count);
            bw.ReserveVarint("FirstAnimOffset");
            if (Format == TAEFormat.DS1)
            {
                bw.WriteInt32(0);
            }
            bw.WriteVarint(1);
            bw.WriteVarint(Format == TAEFormat.DS1 ? 0x80 : 0x90);
            if (Format == TAEFormat.DS1)
            {
                bw.WriteInt64(0);
            }
            bw.WriteInt32(ID);
            bw.WriteInt32(ID);
            bw.WriteVarint(0x50);
            bw.WriteInt64(0);
            bw.WriteVarint(Format == TAEFormat.DS1 ? 0x98 : 0xB0);
            bw.ReserveVarint("SkeletonName");
            bw.ReserveVarint("SibName");

            if (Format != TAEFormat.SOTFS)
            {
                bw.WriteVarint(0);
                bw.WriteVarint(0);
            }

            bw.FillVarint("SkeletonName", bw.Position);
            if (!string.IsNullOrEmpty(SkeletonName))
            {
                bw.WriteUTF16(SkeletonName, true);
                if (Format != TAEFormat.DS1)
                {
                    bw.Pad(0x10);
                }
            }

            bw.FillVarint("SibName", bw.Position);
            if (!string.IsNullOrEmpty(SibName))
            {
                bw.WriteUTF16(SibName, true);
                if (Format != TAEFormat.DS1)
                {
                    bw.Pad(0x10);
                }
            }

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

            var animOffsets = new List <long>(Animations.Count);

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

            bw.FillVarint("AnimGroupsOffset", bw.Position);
            bw.ReserveVarint("AnimGroupsCount");
            bw.ReserveVarint("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.WriteVarint(animOffsets[firstIndex]);
                groupCount++;
            }
            bw.FillVarint("AnimGroupsCount", groupCount);

            if (groupCount == 0)
            {
                bw.FillVarint("AnimGroupsOffset", 0);
            }
            else
            {
                bw.FillVarint("AnimGroupsOffset", groupStart);
            }

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

            for (int i = 0; i < Animations.Count; i++)
            {
                Animation anim = Animations[i];
                anim.WriteAnimFile(bw, i, Format);
                Dictionary <float, long> timeOffsets = anim.WriteTimes(bw, i, Format);
                List <long> eventHeaderOffsets       = anim.WriteEventHeaders(bw, i, timeOffsets);
                anim.WriteEventData(bw, i, Format);
                anim.WriteEventGroupHeaders(bw, i, Format);
                anim.WriteEventGroupData(bw, i, eventHeaderOffsets, Format);
            }

            bw.FillInt32("FileSize", (int)bw.Position);
        }
 public static void ReserveFXR1Varint(this BinaryWriterEx bw, string name)
 {
     bw.ReserveInt32(name);
     bw.WriteFXR1Garbage();
 }
        protected override void Write(BinaryWriterEx bw)
        {
            bw.WriteASCII("FXR\0");
            bw.WriteInt16((short)0);
            bw.WriteUInt16((ushort)this.Version);
            bw.WriteInt32(1);
            bw.WriteInt32(this.Id);
            bw.ReserveInt32("Section1Offset");
            bw.WriteInt32(1);
            bw.ReserveInt32("Section2Offset");
            bw.WriteInt32(this.RootStateMachine.States.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 (this.Version == Fxr3.FxrVersion.Sekiro)
            {
                bw.ReserveInt32("Section12Offset");
                bw.WriteInt32(this.Section12S.Count);
                bw.ReserveInt32("Section13Offset");
                bw.WriteInt32(this.Section13S.Count);
                bw.ReserveInt32("Section14Offset");
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
            }
            bw.FillInt32("Section1Offset", (int)bw.Position);
            this.RootStateMachine.Write(bw);
            bw.Pad(16);
            bw.FillInt32("Section2Offset", (int)bw.Position);
            this.RootStateMachine.WriteSection2S(bw);
            bw.Pad(16);
            bw.FillInt32("Section3Offset", (int)bw.Position);
            List <Fxr3.FfxState>      states    = this.RootStateMachine.States;
            List <Fxr3.FfxTransition> section3S = new List <Fxr3.FfxTransition>();

            for (int index = 0; index < states.Count; ++index)
            {
                states[index].WriteSection3S(bw, index, section3S);
            }
            bw.FillInt32("Section3Count", section3S.Count);
            bw.Pad(16);
            bw.FillInt32("Section4Offset", (int)bw.Position);
            List <Fxr3.FfxEffectCallA> section4S = new List <Fxr3.FfxEffectCallA>();

            this.RootEffectCall.Write(bw, section4S);
            this.RootEffectCall.WriteSection4S(bw, section4S);
            bw.FillInt32("Section4Count", section4S.Count);
            bw.Pad(16);
            bw.FillInt32("Section5Offset", (int)bw.Position);
            int section5Count = 0;

            for (int index = 0; index < section4S.Count; ++index)
            {
                section4S[index].WriteSection5S(bw, index, ref section5Count);
            }
            bw.FillInt32("Section5Count", section5Count);
            bw.Pad(16);
            bw.FillInt32("Section6Offset", (int)bw.Position);
            section5Count = 0;
            List <Fxr3.FfxActionCall> section6S = new List <Fxr3.FfxActionCall>();

            for (int index = 0; index < section4S.Count; ++index)
            {
                section4S[index].WriteSection6S(bw, index, ref section5Count, section6S);
            }
            bw.FillInt32("Section6Count", section6S.Count);
            bw.Pad(16);
            bw.FillInt32("Section7Offset", (int)bw.Position);
            List <Fxr3.FfxProperty> section7S = new List <Fxr3.FfxProperty>();

            for (int index = 0; index < section6S.Count; ++index)
            {
                section6S[index].WriteSection7S(bw, index, section7S);
            }
            bw.FillInt32("Section7Count", section7S.Count);
            bw.Pad(16);
            bw.FillInt32("Section8Offset", (int)bw.Position);
            List <Fxr3.Section8> section8S = new List <Fxr3.Section8>();

            for (int index = 0; index < section7S.Count; ++index)
            {
                section7S[index].WriteSection8S(bw, index, section8S);
            }
            bw.FillInt32("Section8Count", section8S.Count);
            bw.Pad(16);
            bw.FillInt32("Section9Offset", (int)bw.Position);
            List <Fxr3.Section9> section9S = new List <Fxr3.Section9>();

            for (int index = 0; index < section8S.Count; ++index)
            {
                section8S[index].WriteSection9S(bw, index, section9S);
            }
            bw.FillInt32("Section9Count", section9S.Count);
            bw.Pad(16);
            bw.FillInt32("Section10Offset", (int)bw.Position);
            List <Fxr3.Section10> section10S = new List <Fxr3.Section10>();

            for (int index = 0; index < section6S.Count; ++index)
            {
                section6S[index].WriteSection10S(bw, index, section10S);
            }
            bw.FillInt32("Section10Count", section10S.Count);
            bw.Pad(16);
            bw.FillInt32("Section11Offset", (int)bw.Position);
            int section11Count = 0;

            for (int index = 0; index < section3S.Count; ++index)
            {
                section3S[index].WriteSection11S(bw, index, ref section11Count);
            }
            for (int index = 0; index < section6S.Count; ++index)
            {
                section6S[index].WriteSection11S(bw, index, ref section11Count);
            }
            for (int index = 0; index < section7S.Count; ++index)
            {
                section7S[index].WriteSection11S(bw, index, ref section11Count);
            }
            for (int index = 0; index < section8S.Count; ++index)
            {
                section8S[index].WriteSection11S(bw, index, ref section11Count);
            }
            for (int index = 0; index < section9S.Count; ++index)
            {
                section9S[index].WriteSection11S(bw, index, ref section11Count);
            }
            for (int index = 0; index < section10S.Count; ++index)
            {
                section10S[index].WriteSection11S(bw, index, ref section11Count);
            }
            bw.FillInt32("Section11Count", section11Count);
            bw.Pad(16);
            if (this.Version != Fxr3.FxrVersion.Sekiro)
            {
                return;
            }
            bw.FillInt32("Section12Offset", (int)bw.Position);
            bw.WriteInt32s((IList <int>) this.Section12S);
            bw.Pad(16);
            bw.FillInt32("Section13Offset", (int)bw.Position);
            bw.WriteInt32s((IList <int>) this.Section13S);
            bw.Pad(16);
            bw.FillInt32("Section14Offset", (int)bw.Position);
        }
示例#4
0
        public void WriteWithContext(BinaryWriterEx bw, EzSembleContext context)
        {
            bw.WriteASCII(ESDMagicByFormat[FormatType]);
            bw.BigEndian = (FormatType == ESDFormatType.BigEndian32Bit || FormatType == ESDFormatType.BigEndian64Bit);

            context.IsBigEndian = bw.BigEndian;

            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(Unk6C);
            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(context, 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];
                    cond.MetaRefID = conditionOffsets[cond] = bw.Position - dataStart;
                    cond.WriteHeader(context, 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(context, bw, LongFormat, groupID, stateID, dataStart, commands);
                }
                for (int i = 0; i < conditions[groupID].Count; i++)
                {
                    conditions[groupID][i].WriteCommandCalls(context, 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(context, 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(context, bw, LongFormat, groupID, i, dataStart);
                }
            }
            for (int i = 0; i < commands.Count; i++)
            {
                commands[i].WriteBytecode(context, 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);
            }

            LastSavedHash = bw.GetMD5HashOfStream();

            Metadata = ESDMetadata.Generate(this);
        }