re_match: byte-match functions with the game's compiler (Visual C++ 2003)

Runs R:/Workspace/Tools/re/match71.py for up to 50 addresses from main or
an agent's worktree; configured by matcher/match_flags in [reverse].
This commit is contained in:
KeelrLeek committed 2026-10-05 13:10:01 -05:00
1 parent 584fabeb74
commit c7e678eacb
5 files changed
+78 -3

No files matched your search

+29
View File
@@ -452,3 +452,32 @@ class Debugger:
pass
self.proc.terminate()
self.proc = None
def match_functions(config, targets, decomp=None, flags=None):
"""Compile functions with the game's compiler (Visual C++ 2003) and compare them with the original bytes.
targets: addresses ("0x4ADC70, 0x412F70"); decomp: the checkout or worktree whose src/ holds them."""
import subprocess
import sys
import tempfile
config = config or {}
matcher = config.get("matcher")
if not matcher:
raise HarborError("this project has no matcher in its [reverse] table")
wanted = [t.strip() for t in re.split(r"[,\s]+", str(targets)) if t.strip()]
if not wanted or len(wanted) > 50:
raise HarborError("give 1 to 50 addresses")
with tempfile.TemporaryDirectory(dir=config.get("debugger_temp")) as tmp:
out = Path(tmp) / "match.json"
command = [sys.executable, "-B", str(matcher), "--all", "--only", ",".join(wanted), "--json", str(out),
"--flags", flags or config.get("match_flags", "-TC -O2")]
if decomp:
command += ["--decomp", str(decomp)]
result = subprocess.run(command, capture_output=True, text=True, encoding="utf-8", errors="replace",
timeout=600, creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0))
if not out.exists():
raise HarborError("the matcher failed: " + (result.stdout + result.stderr).strip()[-800:])
rows = json.loads(out.read_text(encoding="utf-8"))
errors = [line for line in result.stdout.splitlines() if "compile errors" in line]
return {"results": rows, "summary": result.stdout.strip().splitlines()[0] if result.stdout.strip() else "",
**({"compile": errors[0]} if errors else {})}