Пример #1
0
        public int DisassembleOneInstructionForListFile(int address)
        {
            int instructionAddress = address;

            var         instructionInfo = Decompiler.Peek(ainFile.Code, address);
            Instruction instruction     = instructionInfo.instruction;
            int         word1           = instructionInfo.word1;
            int         word2           = instructionInfo.word2;
            int         word3           = instructionInfo.word3;
            int         totalArguments  = instructionInfo.totalArguments;

            address = instructionInfo.nextAddress;

            StringBuilder sb = new StringBuilder();

            sb.Append(instructionAddress.ToString("X8") + ":");
            if (instruction > Instruction.A_REVERSE && instruction.GetNumberOfWords() == 0 && !InstructionInformation.instructionsWithZeroArguments.Contains(instruction))
            {
                sb.Append("*");
            }
            if (options.DisassembleDisplayBytes == false)
            {
                PadToColumn(sb, 11);
                sb.Append(((int)instruction).ToString("X4"));
                if (totalArguments >= 1)
                {
                    sb.Append(word1.ToString("X8"));
                }
                if (totalArguments >= 2)
                {
                    sb.Append(word2.ToString("X8"));
                }
                if (totalArguments >= 3)
                {
                    sb.Append(word3.ToString("X8"));
                }
                sb.Append(" ");
                PadToColumn(sb, 33);
                sb.Append(instruction.ToString());
                if (totalArguments >= 1)
                {
                    sb.Append(" 0x");
                    sb.Append(word1.ToString("X"));
                }
                if (totalArguments >= 2)
                {
                    sb.Append(" 0x");
                    sb.Append(word2.ToString("X"));
                }
                if (totalArguments >= 3)
                {
                    sb.Append(" 0x");
                    sb.Append(word3.ToString("X"));
                }
            }
            else
            {
                PadToColumn(sb, 11);
                AppendHexBytes(sb, (ushort)instruction);
                sb.Append(" ");
                if (totalArguments >= 1)
                {
                    AppendHexBytes(sb, word1);
                    sb.Append(" ");
                }
                if (totalArguments >= 2)
                {
                    AppendHexBytes(sb, word2);
                    sb.Append(" ");
                }
                if (totalArguments >= 3)
                {
                    AppendHexBytes(sb, word3);
                    sb.Append(" ");
                }
                PadToColumn(sb, 58);
                sb.Append(instruction.ToString());
            }

            InstructionInfo nextIntruction = new InstructionInfo();

            if (address < ainFile.Code.Length)
            {
                nextIntruction = Decompiler.Peek(ainFile.Code, address);
            }
            int nextValue = -1;

            if (nextIntruction.instruction == Instruction.PUSH)
            {
                nextValue = nextIntruction.word1;
            }

            switch (instruction)
            {
            case Instruction.S_PUSH:
            {
                PadToColumn(sb, 60);
                sb.Append("; \"" + displayer.GetString(word1) + "\"");
            }
            break;

            case Instruction.PUSHGLOBALPAGE:
                if (nextValue != -1)
                {
                    PadToColumn(sb, 60);
                    sb.Append("; " + displayer.GetGlobalVariableDeclaration(nextValue));
                }
                break;

            case Instruction.PUSHLOCALPAGE:
                if (nextValue != -1)
                {
                    PadToColumn(sb, 60);
                    sb.Append("; " + displayer.GetLocalVariableDeclaration(nextValue));
                }
                break;

            case Instruction.PUSHSTRUCTPAGE:
                if (nextValue != -1)
                {
                    PadToColumn(sb, 60);
                    sb.Append("; " + displayer.GetLocalStructMemberDeclaration(nextValue));
                }
                break;

            case Instruction.SH_GLOBALREF:
                PadToColumn(sb, 60);
                sb.Append("; " + displayer.GetGlobalVariableDeclaration(word1));
                break;

            case Instruction.SH_LOCALASSIGN:
            case Instruction.SH_LOCALDEC:
            case Instruction.SH_LOCALREF:
                PadToColumn(sb, 60);
                sb.Append("; " + displayer.GetLocalVariableDeclaration(word1));
                break;

            case Instruction.SH_STRUCTREF:
                PadToColumn(sb, 60);
                sb.Append("; " + displayer.GetLocalStructMemberDeclaration(word1));
                break;

            case Instruction.EOF:
                PadToColumn(sb, 60);
                sb.Append("; End of File \"" + displayer.GetFileName(word1) + "\"");
                break;

            case Instruction.FUNC:
                PadToColumn(sb, 60);
                sb.Append("; " + displayer.GetFunctionDeclaration(word1));
                displayer.currentFuncNumber = word1;
                break;

            case Instruction.CALLFUNC:
                PadToColumn(sb, 60);
                sb.Append("; " + displayer.GetFunctionDeclaration(word1));
                break;

            case Instruction.CALLSYS:
                PadToColumn(sb, 60);
                sb.Append("; " + displayer.GetSystemCallDeclaration(word1));
                break;

            case Instruction.CALLHLL:
                PadToColumn(sb, 60);
                sb.Append("; " + displayer.GetHllDeclaration(word1, word2));
                break;

            case Instruction.CALLMETHOD:
                PadToColumn(sb, 60);
                sb.Append("; " + displayer.GetFunctionDeclaration(word1));
                break;

            case Instruction.ENDFUNC:
                PadToColumn(sb, 60);
                sb.Append("; End of Function " + displayer.GetFunctionDeclaration(word1));
                break;

            case Instruction.MSG:
                PadToColumn(sb, 60);
                sb.Append("; '" + ainFile.Messages[word1] + "'");
                break;
            }

            tw.WriteLine(sb.ToString());
            return(address);
        }
        internal void ExportFiles(string destinationPath)
        {
            ainFile.FindFunctionTypes();
            stopwatch.Start();

            var encoding   = Extensions.BinaryEncoding;
            var enumerator = new FunctionEnumerator(this.ainFile);
            var results    = enumerator.GetFilesAndFunctions();
            HashSet <Struct> UnvisitedStructs = new HashSet <Struct>(ainFile.Structs);
            HashSet <int>    VisitedFunctions = new HashSet <int>();
            int functionsVisited = 0;
            int totalFunctions   = ainFile.Functions.Count;

            codeDisplayOptions.DisplayDefaultValuesForMethods = false;
            var displayer = new ExpressionDisplayer(ainFile, codeDisplayOptions);

            StringBuilder mainIncludeFile = new StringBuilder();

            mainIncludeFile.AppendLine("Source = {");
            mainIncludeFile.AppendLine("\t\"constants.jaf\",");
            mainIncludeFile.AppendLine("\t\"classes.jaf\",");
            mainIncludeFile.AppendLine("\t\"globals.jaf\",");

            this.SeenFilenames.Add("classes.jaf");
            this.SeenFilenames.Add("globals.jaf");
            this.SeenFilenames.Add("constants.jaf");
            this.SeenFilenames.Add("HLL\\hll.inc");

            if (ainFile.Libraries.Count > 0)
            {
                mainIncludeFile.AppendLine("\t\"HLL\\hll.inc\",");
            }

            foreach (var fileNode in results)
            {
                string fileName = fileNode.name.Replace("\r", "\\r").Replace("\n", "\\n");  //fix filenames that went through bad tools
                if (fileNode.children.Count > 0)
                {
                    using (FileStream fs = CreateFileUnique(ref fileName, destinationPath))
                    {
                        mainIncludeFile.AppendLine("\t\"" + fileName + "\",");

                        using (var streamWriter = new StreamWriter(fs, encoding))
                        {
                            foreach (var functionNode in fileNode.children)
                            {
                                if (backgroundWorker != null)
                                {
                                    if (backgroundWorker.CancellationPending == true)
                                    {
                                        //abort
                                        return;
                                    }
                                }

                                int functionNumber = functionNode.id;
                                var function       = ainFile.GetFunction(functionNumber);

                                if (function.ToString().Contains("SP_SET_CG_REAL"))
                                {
                                    Console.WriteLine("SP_SET_CG_REAL");
                                }

                                if (!VisitedFunctions.Contains(functionNumber))
                                {
                                    VisitedFunctions.Add(functionNumber);
                                    if (this.backgroundWorker != null && stopwatch.ElapsedTime >= 250)
                                    {
                                        stopwatch.Start();
                                        backgroundWorker.ReportProgress(100 * functionsVisited / totalFunctions,
                                                                        "Function " + functionNumber.ToString() + " of " + totalFunctions.ToString() +
                                                                        ", currently decompiling" + Environment.NewLine + function.Name);
                                    }

                                    if (function.Name == "0" || function.Name.EndsWith("@2"))
                                    {
                                        //exclude global array initializer and struct array initializer functions
                                    }
                                    else
                                    {
                                        //var structInfo = function.GetClass();
                                        //if (structInfo != null)
                                        //{
                                        //    if (UnvisitedStructs.Contains(structInfo))
                                        //    {
                                        //        UnvisitedStructs.Remove(structInfo);
                                        //        string classDeclaration = displayer.GetClassDeclaration(structInfo);
                                        //        streamWriter.Write(classDeclaration);
                                        //    }
                                        //}
                                        if (Debugger.IsAttached)
                                        {
                                            //no exception handling when debugging - we want to see the exceptions
                                            try
                                            {
                                                var    expression = decompiler.DecompileFunction(function);
                                                string text       = displayer.PrintExpression2(expression, true);
                                                streamWriter.WriteLine(text);
                                            }
                                            finally
                                            {
                                            }
                                        }
                                        else
                                        {
                                            try
                                            {
                                                var    expression = decompiler.DecompileFunction(function);
                                                string text       = displayer.PrintExpression2(expression, true);
                                                streamWriter.WriteLine(text);
                                            }
                                            catch (Exception ex)
                                            {
                                                string errorMessage = "Function " + functionNode.name + " failed to decompile.";
                                                RaiseError(errorMessage, ex);
                                            }
                                            finally
                                            {
                                            }
                                        }
                                    }
                                    functionsVisited++;
                                }
                            }
                            streamWriter.Flush();
                            streamWriter.Close();
                        }
                    }
                }
            }
            mainIncludeFile.AppendLine("}");

            if (UnvisitedStructs.Count > 0)
            {
                var remainingStructs = UnvisitedStructs.OrderByIndex().ToArray();

                if (this.backgroundWorker != null)
                {
                    backgroundWorker.ReportProgress(100, "Generating class declarations...");
                }
                using (var fs = CreateFile("classes.jaf", destinationPath))
                {
                    using (var sw = new StreamWriter(fs, encoding))
                    {
                        foreach (var structInfo in remainingStructs)
                        {
                            string classDeclaration = displayer.GetClassDeclaration(structInfo);
                            sw.Write(classDeclaration);
                            sw.WriteLine();
                        }

                        foreach (var funcType in ainFile.FunctionTypes)
                        {
                            string funcTypeDeclaration = displayer.GetFunctypeDeclaration(funcType);
                            sw.WriteLine(funcTypeDeclaration);
                        }

                        foreach (var delg in ainFile.Delegates)
                        {
                            string delegateDeclaration = displayer.GetDelegateDeclaration(delg);
                            sw.WriteLine(delegateDeclaration);
                        }
                        sw.Flush();
                        sw.Close();
                    }
                }
            }

            Dictionary <Global, Expression> globalInitializers = GetGlobalInitializers();

            if (this.backgroundWorker != null)
            {
                backgroundWorker.ReportProgress(100, "Listing global variables...");
            }

            using (var fs = CreateFile("globals.jaf", destinationPath))
            {
                string lastGlobalGroupName = null;
                using (var sw = new MyIndentedTextWriter(new StreamWriter(fs, encoding)))
                {
                    Dictionary <int, GlobalInitialValue> initialValues = new Dictionary <int, GlobalInitialValue>();
                    foreach (var globalInitialValue in ainFile.GlobalInitialValues)
                    {
                        initialValues[globalInitialValue.GlobalIndex] = globalInitialValue;
                    }


                    foreach (var global in ainFile.Globals)
                    {
                        if (global.DataType != DataType.Void)
                        {
                            string globalGroupName = global.GroupName;
                            if (globalGroupName != lastGlobalGroupName)
                            {
                                if (lastGlobalGroupName != null)
                                {
                                    sw.Indent--;
                                    sw.WriteLine("}");
                                }
                                if (globalGroupName != null)
                                {
                                    sw.WriteLine("globalgroup " + globalGroupName);
                                    sw.WriteLine("{");
                                    sw.Indent++;
                                }
                            }
                            lastGlobalGroupName = globalGroupName;

                            sw.Write(global.GetDataTypeName());
                            sw.Write(" ");
                            sw.Write(global.Name);

                            if (global.DataType.IsArray())
                            {
                                if (globalInitializers.ContainsKey(global))
                                {
                                    var expr = globalInitializers[global];

                                    foreach (var e in expr.Args)
                                    {
                                        if (e.ExpressionType == Instruction.PUSH)
                                        {
                                            sw.Write("[" + e.Value.ToString() + "]");
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (initialValues.ContainsKey(global.Index))
                                {
                                    sw.Write(" = ");
                                    var initialValue = initialValues[global.Index];
                                    sw.Write(initialValue.GetValueQuoted());
                                }
                            }
                            sw.WriteLine(";");
                        }
                    }
                    if (lastGlobalGroupName != null)
                    {
                        sw.Indent--;
                        sw.WriteLine("}");
                    }
                    sw.Flush();
                    sw.Close();
                }
            }

            using (var fs = CreateFile("constants.jaf", destinationPath))
            {
                using (StreamWriter sw = new StreamWriter(fs, encoding))
                {
                    sw.WriteLine("const int true = 1;");
                    sw.WriteLine("const int false = 0;");
                    sw.WriteLine();
                    if (ainFile.MetadataFile != null)
                    {
                        foreach (var pair in ainFile.MetadataFile.EnumerationTypes)
                        {
                            var enumerationType = pair.Value;
                            sw.WriteLine("//" + enumerationType.Name);
                            foreach (var pair2 in enumerationType)
                            {
                                sw.WriteLine("const int " + pair2.Value + " = " + pair2.Key.ToString() + ";");
                            }
                            sw.WriteLine();
                        }
                    }

                    sw.Flush();
                    fs.Flush();
                    sw.Close();
                    fs.Close();
                }
            }

            if (this.backgroundWorker != null)
            {
                backgroundWorker.ReportProgress(100, "Creating project file...");
            }

            if (ainFile.Libraries.Count > 0)
            {
                StringBuilder libraryIncludeFile = new StringBuilder();
                libraryIncludeFile.AppendLine("SystemSource = {");

                string hllDirectory = Path.Combine(destinationPath, "HLL");
                foreach (var library in ainFile.Libraries)
                {
                    string hllFileName = library.LibraryName + ".hll";

                    using (var fs = CreateFileUnique(ref hllFileName, hllDirectory))
                    {
                        libraryIncludeFile.AppendLine("\t\"" + hllFileName + "\",\t\"" + library.LibraryName + "\",");
                        using (var sw = new StreamWriter(fs, encoding))
                        {
                            foreach (var func in library.Functions)
                            {
                                string declaration = func.GetDeclaration() + ";";
                                sw.WriteLine(declaration);
                            }
                            sw.Flush();
                            sw.Close();
                        }
                    }
                }
                libraryIncludeFile.AppendLine("}");
                string includeFileContents = libraryIncludeFile.ToString();

                using (var fs = CreateFile("hll.inc", hllDirectory))
                {
                    using (var sw = new StreamWriter(fs, encoding))
                    {
                        sw.Write(includeFileContents);
                    }
                }
            }

            File.WriteAllText(Path.Combine(destinationPath, "main.inc"), mainIncludeFile.ToString(), encoding);

            //build a PJE file
            {
                StringBuilder pje = new StringBuilder();
                pje.AppendLine("// Project Environment File");
                pje.AppendLine("ProjectName = \"" + Path.GetFileNameWithoutExtension(this.ainFile.OriginalFilename) + "\"");
                pje.AppendLine();
                pje.AppendLine("CodeName = \"" + Path.GetFileNameWithoutExtension(this.ainFile.OriginalFilename) + ".ain\"");
                pje.AppendLine();
                pje.AppendLine("#define _AINVERSION " + ainFile.Version.ToString());
                pje.AppendLine("#define _KEYCODE 0x" + ainFile.KeyCode.ToString("X8"));
                pje.AppendLine("#define _ISAI2FILE " + (ainFile.IsAi2File ? "true" : "false"));
                if (ainFile.Version >= 6)
                {
                    pje.AppendLine("#define _USESMSG1 " + (ainFile.UsesMsg1 ? "true" : "false"));
                }
                pje.AppendLine("#define _TARGETVM " + ainFile.TargetVMVersion.ToString());
                pje.AppendLine();
                pje.AppendLine("GameVersion = " + ainFile.GameVersion.ToString());
                pje.AppendLine();
                pje.AppendLine("// Settings for each directory");
                pje.AppendLine("SourceDir = \".\"");
                pje.AppendLine("HLLDir = \"HLL\"");
                pje.AppendLine("ObjDir = \"OBJ\"");
                pje.AppendLine("OutputDir = \"Run\"");
                pje.AppendLine();
                pje.AppendLine("Source = {");
                pje.AppendLine("    \"main.inc\",");
                pje.AppendLine("}");

                string pjeFileName = Path.Combine(destinationPath, Path.GetFileNameWithoutExtension(this.ainFile.OriginalFilename) + ".pje");

                File.WriteAllText(pjeFileName, pje.ToString(), encoding);
            }
        }