diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..65e3ba2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +test/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a50e8f8 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +#! /usr/bin/env make -f + +py = g35pe2_ml_patch.py +src = $(filter-out $(wildcard test/*-E2.g1a),$(wildcard test/*.g1a)) +out = $(src:.g1a=-E2.g1a) + +test: $(out) + +test/%-E2.g1a: test/%.g1a $(py) + @echo -e "\n\e[33;1mPatching $<...\x1b[0m" + @ python $(py) $< $@ + +# Always redo all the tests +.PHONY: test diff --git a/g35pe2_ml_patch.py b/g35pe2_ml_patch.py index d681a06..2dbe341 100755 --- a/g35pe2_ml_patch.py +++ b/g35pe2_ml_patch.py @@ -104,29 +104,39 @@ class Transform: self.insn = [(make_pattern(p), make_pattern(repl)) for p, repl in patterns] +def match_transform_recursive(insn, vars, offsets, data, start, end): + if not insn: + return (vars, offsets) + + p, repl = insn[0] + n = len(p.nibbles) // 2 + insn = insn[1:] + + # Try all matching offsets + for offset in range(start, end, 2): + d = data[offset:offset+n] + v = match_pattern(p, d, vars) + if v != False: + o = offsets + [offset] + v2, o2 = match_transform_recursive(insn, v, o, data, start, end) + if v2 != False: + # TODO: Yield here to explore all options + return (v2, o2) + + return (False, []) + + def match_transform(tr, base_vars, data, start, end): """Matches all instructions from in between and , returning either (False, []) or a pair (, [...]) - indicating where instructions matched and with what variables.""" + indicating where instructions matched and with what variables. Only the + first solution found to the unification problem is returned.""" start, end = align(start, end, 2) vars = base_vars.copy() offsets = [] - for p, repl in tr.insn: - n = len(p.nibbles) // 2 - - for offset in range(start, end, 2): - d = data[offset:offset+n] - v = match_pattern(p, d, vars) - if v != False: - offsets.append(offset) - vars = v - break - else: - return (False, []) - - return (vars, offsets) + return match_transform_recursive(tr.insn, vars, offsets, data, start, end) def apply_transform(tr, vars, offsets, data): """Apply replacements from on in-place, using the and