示例#1
0
            internal CompiledState(EzSembleContext context, State s)
            {
                try
                {
                    EntryCommands = EzSembler.AssembleCommandScript(context, s.EntryScript);
                }
                catch (Exception ex)
                {
                    context.Debug_StateSaveError(ex, "Failed to compile state entry script.");
                }

                try
                {
                    ExitCommands = EzSembler.AssembleCommandScript(context, s.ExitScript);
                }
                catch (Exception ex)
                {
                    context.Debug_StateSaveError(ex, "Failed to compile state exit script.");
                }

                try
                {
                    WhileCommands = EzSembler.AssembleCommandScript(context, s.WhileScript);
                }
                catch (Exception ex)
                {
                    context.Debug_StateSaveError(ex, "Failed to compile state while script.");
                }
            }
示例#2
0
 public static ESD ReadWithContext(string path, EzSembleContext context)
 {
     using (FileStream stream = File.OpenRead(path))
     {
         BinaryReaderEx br   = new BinaryReaderEx(false, stream);
         ESD            file = new ESD();
         br = SFUtil.GetDecompressedBR(br, out file.Compression);
         file.ReadWithContext(br, context);
         return(file);
     }
 }
示例#3
0
        byte[] WriteESD(ESDL esd)
        {
            EzSembleContext context = EzSembleContext.LoadFromXml(docPath);

            // ESD esd = new ESD();
            using (MemoryStream stream = new MemoryStream())
            {
                esd.WriteWithContext(new BinaryWriterEx(false, stream), context);
                return(stream.ToArray());
            }
        }
示例#4
0
        private EzSembleContext LoadContext(ESDOptions.CmdType type)
        {
            if (contexts.TryGetValue(type, out EzSembleContext context))
            {
                return(context);
            }
            string docPath = $@"dist\ESDScriptingDocumentation_{type}.xml";

            context = contexts[type] = EzSembleContext.LoadFromXml(docPath);
            return(context);
        }
示例#5
0
        private ESDL ReadESD(byte[] data, string path, int check = -1)
        {
            if (check > 1)
            {
                int esdId = int.Parse(path.Substring(1));
                if (esdId != check)
                {
                    return(null);
                }
            }
            EzSembleContext context = EzSembleContext.LoadFromXml(docPath);
            ESDL            esd     = new ESDL();

            esd.ReadWithContext(new BinaryReaderEx(false, data), context);
            return(esd);
        }
示例#6
0
        /// <summary>
        /// Writes this ESD file to the specified path, saving its metadata to "&lt;ESDFileName&gt;.meta".
        /// </summary>
        public void WriteWithMetadata(string path, bool isBinaryMetadata, EzSembleContext context)
        {
            using (MemoryStream corruptPreventStream = new MemoryStream())
            {
                BinaryWriterEx bw = new BinaryWriterEx(false, corruptPreventStream);
                WriteWithContext(bw, context);

                corruptPreventStream.Position = 0;

                using (FileStream actualFileStream = File.Create(path))
                {
                    corruptPreventStream.CopyTo(actualFileStream);
                }

                bw.Finish();
            }

            SaveMetadataFile(path + ".meta", isBinaryMetadata);
        }
示例#7
0
 internal CompiledCondition(EzSembleContext context, Condition c)
 {
     PassCommands = EzSembler.AssembleCommandScript(context, c.PassScript);
     Evaluator    = EzSembler.AssembleExpression(context, c.Evaluator);
 }
示例#8
0
 internal CompiledState(EzSembleContext context, State s)
 {
     EntryCommands = EzSembler.AssembleCommandScript(context, s.EntryScript);
     ExitCommands  = EzSembler.AssembleCommandScript(context, s.ExitScript);
     WhileCommands = EzSembler.AssembleCommandScript(context, s.WhileScript);
 }
示例#9
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);
        }
示例#10
0
        public void ReadWithContext(BinaryReaderEx br, EzSembleContext context)
        {
            LastSavedHash = br.GetMD5HashOfStream();

            string magic = br.AssertASCII("fSSL", "fsSL", "FSSL", "FsSL");

            FormatType = ESDFormatByMagic[magic];

            br.BigEndian = (FormatType == ESDFormatType.BigEndian32Bit || FormatType == ESDFormatType.BigEndian64Bit);

            context.IsBigEndian = br.BigEndian;

            br.AssertInt32(1);
            DarkSoulsCount = br.AssertInt32(1, 2, 3);
            br.AssertInt32(DarkSoulsCount);
            br.AssertInt32(0x54);
            int dataSize = br.ReadInt32();

            br.AssertInt32(6);
            br.AssertInt32(LongFormat ? 0x48 : 0x2C);
            br.AssertInt32(1);
            int stateGroupSize  = br.AssertInt32(LongFormat ? 0x20 : 0x10);
            int stateGroupCount = br.ReadInt32();
            int stateSize       = br.AssertInt32(LongFormat ? 0x48 : 0x24);
            int stateCount      = br.ReadInt32();

            br.AssertInt32(LongFormat ? 0x38 : 0x1C);
            int conditionCount = br.ReadInt32();

            br.AssertInt32(LongFormat ? 0x18 : 0x10);
            int commandCallCount = br.ReadInt32();

            br.AssertInt32(LongFormat ? 0x10 : 0x8);
            int commandArgCount        = br.ReadInt32();
            int conditionOffsetsOffset = br.ReadInt32();
            int conditionOffsetsCount  = br.ReadInt32();
            int nameBlockOffset        = br.ReadInt32();
            int nameLength             = br.ReadInt32();
            int unkOffset1             = br.ReadInt32();

            br.AssertInt32(0);
            int unkOffset2 = br.ReadInt32();

            br.AssertInt32(0);

            long dataStart = br.Position;

            Unk6C = br.AssertInt32(1, 0);
            Unk70 = br.ReadInt32();
            Unk74 = br.ReadInt32();
            Unk78 = br.ReadInt32();
            Unk7C = br.ReadInt32();
            if (LongFormat)
            {
                br.AssertInt32(0);
            }

            long stateGroupsOffset = ReadVarint(br, LongFormat);

            AssertVarint(br, LongFormat, stateGroupCount);
            long nameOffset = ReadVarint(br, LongFormat);

            AssertVarint(br, LongFormat, nameLength);
            long unkNull = DarkSoulsCount == 1 ? 0 : -1;

            AssertVarint(br, LongFormat, unkNull);
            AssertVarint(br, LongFormat, unkNull);

            if (nameLength > 0)
            {
                Name = br.GetUTF16(dataStart + nameOffset);
            }
            else
            {
                Name = null;
            }

            var stateGroupOffsets = new Dictionary <long, long[]>(stateGroupCount);

            for (int i = 0; i < stateGroupCount; i++)
            {
                long   id           = ReadVarint(br, LongFormat);
                long[] stateOffsets = ReadStateGroup(br, LongFormat, dataStart, stateSize);
                if (stateGroupOffsets.ContainsKey(id))
                {
                    throw new FormatException("Duplicate state group ID.");
                }
                stateGroupOffsets[id] = stateOffsets;
            }

            var states = new Dictionary <long, State>(stateCount);

            for (int i = 0; i < stateCount; i++)
            {
                states[br.Position - dataStart] = new State(context, br, LongFormat, dataStart);
            }

            var conditions = new Dictionary <long, Condition>(conditionCount);

            for (int i = 0; i < conditionCount; i++)
            {
                conditions[br.Position - dataStart] = new Condition(context, br, LongFormat, dataStart);
            }

            foreach (State state in states.Values)
            {
                state.GetConditions(conditions);
            }

            StateGroups = new Dictionary <long, Dictionary <long, State> >(stateGroupCount);
            var groupedStateOffsets = new Dictionary <long, Dictionary <long, long> >();

            foreach (long stateGroupID in stateGroupOffsets.Keys)
            {
                long[] stateOffsets = stateGroupOffsets[stateGroupID];
                Dictionary <long, State> stateGroup = TakeStates(stateSize, stateOffsets, states, out Dictionary <long, long> stateIDs);
                StateGroups[stateGroupID]         = stateGroup;
                groupedStateOffsets[stateGroupID] = stateIDs;

                foreach (State state in stateGroup.Values)
                {
                    foreach (Condition condition in state.Conditions)
                    {
                        condition.GetStateAndConditions(stateIDs, conditions);
                    }
                }
            }

            if (states.Count > 0)
            {
                throw new FormatException("Orphaned states found.");
            }

            foreach (var s in conditions)
            {
                s.Value.MetaRefID = s.Key;
                s.Value.Name      = $"Condition[{s.Key:X8}]";
            }

            foreach (var g in StateGroups.Keys)
            {
                foreach (var s in StateGroups[g])
                {
                    s.Value.Name = $"State{g}-{s.Value.ID}";
                }
            }

            StateGroupNames.Clear();
            foreach (var g in StateGroups)
            {
                StateGroupNames.Add(g.Key, $"StateGroup{g.Key}");
            }
        }
示例#11
0
        /// <summary>
        /// Loads an ESD file from the specified path, loading the metadata along with it if applicable "&lt;ESDFileName&gt;.meta".
        /// If no metadata exists, generates default metadata.
        /// If metadata does not exist, an exception is thrown if <paramref name="assertMetadataExists"/> is true,
        /// and default metadata is generated if it is false.
        /// </summary>
        public static ESD ReadWithMetadata(string path, bool isBinaryMetadata, bool assertMetadataExists, EzSembleContext context)
        {
            var esd = ESD.ReadWithContext(path, context);

            if (System.IO.File.Exists(path + ".meta"))
            {
                esd.LoadAndApplyMetadataFile(path + ".meta", isBinaryMetadata);
            }
            else if (assertMetadataExists)
            {
                throw new Exception($"Metadata file did not exist and {nameof(assertMetadataExists)} was true.");
            }

            return(esd);
        }