package re3lib; import java.io.File; import java.io.IOException; import generic.jar.ResourceFile; import ghidra.app.decompiler.DecompInterface; import ghidra.app.script.GhidraScript; import ghidra.program.flatapi.FlatProgramAPI; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Program; public class RecompileConfig { private static final String RECOMPILE_PREFIX = "game_re"; // Version control project root public final String rootDir; // The output directory for the recompiled game public final String outputDir; public final String typeBlacklistPath; public final String categoryPathBlacklistPath; public final String functionBlacklistPath; // The static memory block public final Address staticMemoryBlockStart; public final Address staticMemoryBlockEnd; // The automatically decompiled files public final File dirDecompAuto; // The manually decompiled files (will not be overwritten by the auto // decompiler) public final File dirDecompFix; // The automatically generated files get written here in case a gh_fix entry // exists // usable for referencing the modified function against the auto-decompiled one public final File dirDecompRef; // The path for generated function stubs, for yet-to-be-compiled functions // Usefully for testing a part of the recompiled code without linker errors public final File dirDecompStub; // The CMake timestamp file, automatically touched sometimes to trigger a // reconfigure // mostly when adding new files to the project public final File cmakeTimestampFile; public final Program currentProgram; public final DecompileCache decompCache; public final GhidraScript script; public static RecompileConfig INSTANCE; public RecompileConfig(GhidraScript script) { staticMemoryBlockStart = script.getCurrentProgram().getAddressFactory().getAddress("00597000"); staticMemoryBlockEnd = script.getCurrentProgram().getAddressFactory().getAddress("00843fff"); this.script = script; rootDir = new File(script.getSourceFile().getAbsolutePath()).getParentFile().getParentFile().toString(); outputDir = new File(rootDir, RECOMPILE_PREFIX).toString(); script.println("Output path: " + outputDir); typeBlacklistPath = new File(outputDir, "type_blacklist.txt").toString(); categoryPathBlacklistPath = new File(outputDir, "type_path_blacklist.txt").toString(); functionBlacklistPath = new File(outputDir, "function_blacklist.txt").toString(); dirDecompAuto = new File(outputDir, "gh_auto"); dirDecompFix = new File(outputDir, "gh_fix"); dirDecompRef = new File(outputDir, "gh_ref"); dirDecompStub = new File(outputDir, "gh_stub"); cmakeTimestampFile = new File(outputDir, "gh_cmake_timestamp"); currentProgram = script.getCurrentProgram(); DecompInterface decomp = new DecompInterface(); decomp.openProgram(currentProgram); decompCache = new DecompileCache(decomp, script.getMonitor()); } public void createDirectories() { dirDecompAuto.mkdirs(); dirDecompFix.mkdirs(); dirDecompRef.mkdirs(); dirDecompStub.mkdirs(); } public void touchCMakeTimestamp() { try { if (!cmakeTimestampFile.exists()) { cmakeTimestampFile.createNewFile(); } cmakeTimestampFile.setLastModified(System.currentTimeMillis()); } catch (IOException e) { } } }