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); } }