"""Generate LeafGreen 1.0 address metadata from matching pret ELF builds.""" import subprocess,bisect,re,sys,hashlib from pathlib import Path B=0x8000000 def symbols(path): out=[]; obj='' for line in subprocess.check_output(['arm-none-eabi-readelf','-sW',str(path)],text=True).splitlines(): p=line.split() if len(p)<8 or not p[0][:-1].isdigit():continue _,v,size,typ,bind,vis,ndx,name=p[:8] if typ=='FILE':obj=name;continue a=int(v,16) if typ not in ('SECTION','FILE') and not name.startswith(('$','.')) and B<=a 1 else ROOT.parent / "pokefirered") for filename, expected in { "pokefirered": "41cb23d8dccc8ebd7c649cd8fbb58eeace6e2fdc", "pokeleafgreen": "574fa542ffebb14be69902d1d36f1ec0a4afd71e", }.items(): digest = hashlib.sha1((pret / (filename + ".gba")).read_bytes()).hexdigest() if digest != expected: raise SystemExit(f"{filename} is not the matching USA 1.0 build") a = symbols(pret / "pokefirered.elf") b = symbols(pret / "pokeleafgreen.elf") bd = {name: (addr, size) for addr, name, size in b} starts = [row[0] for row in a] aliases = {"sFlames_Pal": "sLeaves_Pal", "sFlames_Gfx": "sLeaves_Gfx", "sBlankFlames_Gfx": "sStreak_Gfx"} # Only literal ROM addresses; comments, strings, masks and sizes are excluded. files = [ROOT / "src/import/gba/versions.lua", ROOT / "src/import/gba/versions_text.lua"] files += [ROOT / ("src/import/gba/" + f + ".lua") for f in ( "tileset_anim_pack", "battle_chrome_extract", "pokedex_chrome_extract", "seagallop_extract", "door_anim_extract", "text_chrome_extract", "help_extract", "quest_log_extract", "object_interactions_extract", "weather_extract")] values = set() for path in files: for line in path.read_text().splitlines(): line = re.sub(r'"[^"\n]*"|\'[^\'\n]*\'', "", line.split("--")[0]) for literal in re.findall(r"0x[0-9A-Fa-f]+", line): v = int(literal, 16) if 0x10000 <= v < 0x1000000 or B < v < B + 0x1000000: values.add(v) lines = ["-- Generated by tools/gen_leafgreen_profile.py from matching pret ELF symbols.", "-- Addresses only; no ROM content. Local symbols are qualified by object file.", "return {"] for value in sorted(values): addr = value + B if value < B else value start, key, size = a[bisect.bisect_right(starts, addr) - 1] target = (key[0], aliases.get(key[1], key[1])) if target not in bd: raise SystemExit(f"Unmapped {value:#x}: {key}") offset = addr - start mapped = bd[target][0] + offset - (B if value < B else 0) lines.append(f" [0x{value:X}] = 0x{mapped:X}, -- {key[0]}:{target[1]} + {offset}") lines.append("}") out = ROOT / "src/import/gba/editions/leafgreen_1_0.lua" out.parent.mkdir(parents=True, exist_ok=True) out.write_text("\n".join(lines) + "\n") print(f"Wrote {len(values)} address mappings to {out}")