- // FUNCTION: / GLOBAL: / LIBRARY: annotations in source name symbols, so decompiling never needs edits to the shared symbols.txt - check follows compiler-generated EH handlers into .text$x and verifies string literals / float constants by content - link rebuilds eqgame.exe from compiled objects with relocations resolved through the map and checks the SHA1 (currently identical) - Ghidra pseudo-C export script; docs/ROADMAP.md for the full-relink plan - /GS confirmed; 0x401022-0x4013e1 (13 functions, spell casting particle points) match byte-for-byte Co-Authored-By: Claude Opus 5.5 <[email protected]>
29 lines
1.3 KiB
Java
29 lines
1.3 KiB
Java
// Writes Ghidra's pseudo-C for every function to <outdir>/<addr>.c (a starting point for decompiling).
|
|
// Usage: analyzeHeadless <proj> <name> -import eqgame.exe -postScript ExportDecomp.java <outdir>
|
|
import ghidra.app.decompiler.*;
|
|
import ghidra.app.script.GhidraScript;
|
|
import ghidra.program.model.listing.*;
|
|
import java.io.*;
|
|
|
|
public class ExportDecomp extends GhidraScript {
|
|
@Override
|
|
public void run() throws Exception {
|
|
File dir = new File(getScriptArgs()[0]);
|
|
dir.mkdirs();
|
|
DecompInterface di = new DecompInterface();
|
|
di.openProgram(currentProgram);
|
|
int n = 0;
|
|
for (Function f : currentProgram.getFunctionManager().getFunctions(true)) {
|
|
if (monitor.isCancelled()) break;
|
|
if (f.isExternal() || f.isThunk()) continue;
|
|
File out = new File(dir, String.format("%08x.c", f.getEntryPoint().getOffset()));
|
|
if (out.exists()) continue;
|
|
DecompileResults r = di.decompileFunction(f, 60, monitor);
|
|
String c = r.decompileCompleted() ? r.getDecompiledFunction().getC() : "// decompile failed: " + r.getErrorMessage() + "\n";
|
|
try (PrintWriter w = new PrintWriter(new FileWriter(out))) { w.print(c); }
|
|
if (++n % 500 == 0) println("decompiled " + n);
|
|
}
|
|
di.dispose();
|
|
}
|
|
}
|