private bool TryDecompileScript(FlowScript flowScript, out CompilationUnit compilationUnit)
        {
            // Evaluate script
            if (!TryEvaluateScript(flowScript, out var evaluationResult))
            {
                LogError("Failed to evaluate script");
                compilationUnit = null;
                return(false);
            }

            if (!TryDecompileScriptInternal(evaluationResult, out compilationUnit))
            {
                LogError("Failed to decompile script");
                compilationUnit = null;
                return(false);
            }

            return(true);
        }
        public bool TryDecompile(FlowScript flowScript, string filepath)
        {
            mFilePath = Path.GetFullPath(filepath);
            LogInfo($"FlowScript output path set to {mFilePath}");

            if (MessageScriptFilePath == null)
            {
                MessageScriptFilePath = Path.ChangeExtension(mFilePath, "msg");
            }

            LogInfo($"MessageScript output path set to {MessageScriptFilePath}");

            if (flowScript.MessageScript != null)
            {
                // Disambiguate message script dialog names so that the decompilation won't fail
                DisambiguateMessageScriptDialogNames(flowScript.MessageScript);

                if (DecompileMessageScript)
                {
                    // Decompile embedded message script
                    LogInfo("Writing decompiled MessageScript to file");
                    using (var messageScriptDecompiler = new MessageScriptDecompiler(new FileTextWriter(MessageScriptFilePath)))
                    {
                        messageScriptDecompiler.Library = Library;
                        messageScriptDecompiler.Decompile(flowScript.MessageScript);
                    }
                }
            }

            // Decompile to decompilation unit
            if (!TryDecompile(flowScript, out var compilationUnit))
            {
                return(false);
            }

            // Write out the decompilation unit
            LogInfo("Writing decompiled FlowScript to file");
            var writer = new CompilationUnitWriter();

            writer.Write(compilationUnit, filepath);

            return(true);
        }
예제 #3
0
        FlowScript CheckInstance()
        {
            if (flowScript == currentInstance)
            {
                return(currentInstance);
            }

            FlowScript instance = null;

            if (!instances.TryGetValue(flowScript, out instance))
            {
                instance = Graph.Clone <FlowScript>(flowScript);
                instances[flowScript] = instance;
            }

            instance.agent      = graphAgent;
            instance.blackboard = graphBlackboard;
            flowScript          = instance;
            return(instance);
        }
예제 #4
0
        private static bool TryDoFlowScriptDecompilation()
        {
            // Load binary file
            Logger.Info("Loading binary FlowScript file...");
            FlowScript flowScript = null;
            var        encoding   = MessageScriptEncoding;
            var        format     = GetFlowScriptFormatVersion();

            if (!TryPerformAction("Failed to load flow script from file", () => flowScript = FlowScript.FromFile(InputFilePath, encoding, format)))
            {
                return(false);
            }

            Logger.Info("Decompiling FlowScript...");

            var decompiler = new FlowScriptDecompiler();

            decompiler.SumBits = FlowScriptSumBits;
            decompiler.AddListener(Listener);

            if (LibraryName != null)
            {
                var library = LibraryLookup.GetLibrary(LibraryName);

                if (library == null)
                {
                    Logger.Error("Invalid library name specified");
                    return(false);
                }

                decompiler.Library = library;
            }

            if (!decompiler.TryDecompile(flowScript, OutputFilePath))
            {
                Logger.Error("Failed to decompile FlowScript");
                return(false);
            }

            return(true);
        }
        protected override Status OnExecute(Component agent, IBlackboard blackboard)
        {
            if (flowScript == null)
            {
                return(Status.Failure);
            }

            if (status == Status.Resting)
            {
                currentInstance = CheckInstance();
                status          = Status.Running;
                currentInstance.StartGraph(agent, blackboard, false, OnFlowScriptFinished);
            }

            if (status == Status.Running)
            {
                currentInstance.UpdateGraph();
            }

            return(status);
        }
예제 #6
0
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine($"Missing filename");
                return;
            }

            MessageScript msg      = null;
            var           filePath = args[0];

            if (filePath.EndsWith("bf", StringComparison.InvariantCultureIgnoreCase))
            {
                msg = FlowScript.FromFile(filePath).MessageScript;
            }
            else if (filePath.EndsWith("bmd"))
            {
                msg = MessageScript.FromFile(args[0]);
            }
            else if (filePath.EndsWith("msg"))
            {
                var msgCompiler = new MessageScriptCompiler(AtlusScriptLibrary.MessageScriptLanguage.FormatVersion.Version1);
                msg = msgCompiler.Compile(File.OpenText(filePath));
            }
            else
            {
                Console.WriteLine("Can't detect input type (unknown extension)");
                return;
            }

            using (var writer = File.CreateText($"{Path.GetFileNameWithoutExtension( args[ 0 ] )}_ids.txt"))
            {
                for (var i = 0; i < msg.Dialogs.Count; i++)
                {
                    var dialog = msg.Dialogs[i];
                    writer.WriteLine($"{i}\t\t{dialog.Name}");
                }
            }
        }
예제 #7
0
 private static IEnumerable <(FlowScript, string)> FindFlowScripts(string file, Archive archive = null, string archiveFilePath = null)
 {
     if (file.EndsWith("bf", StringComparison.InvariantCultureIgnoreCase))
     {
         if (archive == null)
         {
             yield return(FlowScript.FromFile(file, sEncoding), file);
         }
         else
         {
             yield return(FlowScript.FromStream(archive.OpenFile(file), sEncoding), Path.Combine(archiveFilePath, file));
         }
     }
     else if (archive == null ? Archive.TryOpenArchive(File.OpenRead(file), out var subArchive) : Archive.TryOpenArchive(archive.OpenFile(file), out subArchive))
     {
         foreach (string entry in subArchive)
         {
             foreach (var script in FindFlowScripts(entry, subArchive, archive == null ? file : Path.Combine(archiveFilePath, file)))
             {
                 yield return(script);
             }
         }
     }
 }
예제 #8
0
 bool IsInstance(FlowScript fs)
 {
     return(instances.Values.Contains(fs));
 }
예제 #9
0
        private static bool TryDoFlowScriptCompilation()
        {
            Logger.Info("Compiling FlowScript...");

            // Get format verson
            var version = GetFlowScriptFormatVersion();

            if (version == FormatVersion.Unknown)
            {
                Logger.Error("Invalid FlowScript file format specified");
                return(false);
            }

            // Compile source
            var compiler = new FlowScriptCompiler(version);

            compiler.AddListener(Listener);
            compiler.Encoding = MessageScriptEncoding;
            compiler.EnableProcedureTracing     = FlowScriptEnableProcedureTracing;
            compiler.EnableProcedureCallTracing = FlowScriptEnableProcedureCallTracing;
            compiler.EnableFunctionCallTracing  = FlowScriptEnableFunctionCallTracing;
            compiler.EnableStackCookie          = FlowScriptEnableStackCookie;
            compiler.ProcedureHookMode          = FlowScriptEnableProcedureHook ? ProcedureHookMode.ImportedOnly : ProcedureHookMode.None;

            if (LibraryName != null)
            {
                var library = LibraryLookup.GetLibrary(LibraryName);

                if (library == null)
                {
                    Logger.Error("Invalid library name specified");
                    return(false);
                }

                compiler.Library = library;
            }

            FlowScript flowScript = null;
            var        success    = false;

            using (var file = File.Open(InputFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                try
                {
                    success = compiler.TryCompile(file, out flowScript);
                }
                catch (UnsupportedCharacterException e)
                {
                    Logger.Error($"Character '{e.Character}' not supported by encoding '{e.EncodingName}'");
                }

                if (!success)
                {
                    Logger.Error("One or more errors occured during compilation!");
                    return(false);
                }
            }

            // Write binary
            Logger.Info("Writing binary to file...");
            return(TryPerformAction("An error occured while saving the file.", () => flowScript.ToFile(OutputFilePath)));
        }
예제 #10
0
 public void FromFile_ShouldThrowInvalidDataException_InvalidFileFormatBig()
 {
     Assert.ThrowsException <InvalidDataException>(() => FlowScript.FromFile("TestResources\\dummy_big.bin", null, FormatVersion.Unknown));
 }
예제 #11
0
        public void ToBinary_ContentsShouldMatchThatOfSourceBinary_Version3BigEndian()
        {
            var binaryIn  = FlowScriptBinary.FromFile("TestResources\\Version3BigEndian.bf");
            var script    = FlowScript.FromBinary(binaryIn);
            var binaryOut = script.ToBinary();

            // Compare headers
            Assert.AreEqual(binaryIn.Header.FileType, binaryOut.Header.FileType);
            Assert.AreEqual(binaryIn.Header.Compressed, binaryOut.Header.Compressed);
            Assert.AreEqual(binaryIn.Header.UserId, binaryOut.Header.UserId);
            Assert.AreEqual(binaryIn.Header.FileSize, binaryOut.Header.FileSize);
            Assert.IsTrue(binaryIn.Header.Magic.SequenceEqual(binaryOut.Header.Magic));
            Assert.AreEqual(binaryIn.Header.Field0C, binaryOut.Header.Field0C);
            Assert.AreEqual(binaryIn.Header.SectionCount, binaryOut.Header.SectionCount);
            Assert.AreEqual(binaryIn.Header.LocalIntVariableCount, binaryOut.Header.LocalIntVariableCount);
            Assert.AreEqual(binaryIn.Header.LocalFloatVariableCount, binaryOut.Header.LocalFloatVariableCount);
            Assert.AreEqual(binaryIn.Header.Endianness, binaryOut.Header.Endianness);
            Assert.AreEqual(binaryIn.Header.Field1A, binaryOut.Header.Field1A);
            Assert.AreEqual(binaryIn.Header.Padding, binaryOut.Header.Padding);

            // Compare section headers
            for (int i = 0; i < binaryIn.SectionHeaders.Count; i++)
            {
                Assert.AreEqual(binaryIn.SectionHeaders[i].SectionType, binaryOut.SectionHeaders[i].SectionType);
                Assert.AreEqual(binaryIn.SectionHeaders[i].ElementSize, binaryOut.SectionHeaders[i].ElementSize);
                Assert.AreEqual(binaryIn.SectionHeaders[i].ElementCount, binaryOut.SectionHeaders[i].ElementCount);
                Assert.AreEqual(binaryIn.SectionHeaders[i].FirstElementAddress, binaryOut.SectionHeaders[i].FirstElementAddress);
            }

            // Compare labels
            for (int i = 0; i < binaryIn.ProcedureLabelSection.Count; i++)
            {
                Assert.AreEqual(binaryIn.ProcedureLabelSection[i].Name, binaryOut.ProcedureLabelSection[i].Name);
                Assert.AreEqual(binaryIn.ProcedureLabelSection[i].InstructionIndex, binaryOut.ProcedureLabelSection[i].InstructionIndex);
                Assert.AreEqual(binaryIn.ProcedureLabelSection[i].Reserved, binaryOut.ProcedureLabelSection[i].Reserved);
            }

            for (int i = 0; i < binaryIn.JumpLabelSection.Count; i++)
            {
                Assert.AreEqual(binaryIn.JumpLabelSection[i].Name, binaryOut.JumpLabelSection[i].Name);
                Assert.AreEqual(binaryIn.JumpLabelSection[i].InstructionIndex, binaryOut.JumpLabelSection[i].InstructionIndex);
                Assert.AreEqual(binaryIn.JumpLabelSection[i].Reserved, binaryOut.JumpLabelSection[i].Reserved);
            }

            // Compare instructions
            for (int i = 0; i < binaryIn.TextSection.Count; i++)
            {
                var inInstruction  = binaryIn.TextSection[i];
                var outInstruction = binaryOut.TextSection[i];

                Assert.AreEqual(inInstruction.Opcode, outInstruction.Opcode);

                if (inInstruction.Opcode == Opcode.PUSHI || inInstruction.Opcode == Opcode.PUSHF)
                {
                    ++i;
                    continue;
                }

                if (inInstruction.Opcode == Opcode.IF || inInstruction.Opcode == Opcode.GOTO)
                {
                    Assert.AreEqual(binaryIn.JumpLabelSection[inInstruction.OperandShort].Name, binaryOut.JumpLabelSection[outInstruction.OperandShort].Name);
                }
                else
                {
                    Assert.AreEqual(inInstruction.OperandShort, outInstruction.OperandShort);
                }
            }

            // Compare message script
            //Assert.IsTrue(binaryIn.MessageScriptSection.SequenceEqual(binaryOut.MessageScriptSection));

            // Compare strings
            Assert.IsTrue(binaryIn.StringSection.SequenceEqual(binaryOut.StringSection));
        }