Files
gen1recomp/tools/gen_leafgreen_profile.py
bryanthaboi c8b64177f6 classic goia
2026-09-23 17:18:42 -04:00

62 lines
3.1 KiB
Python

"""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<B+0x1000000:
# Function symbols carry Thumb bit; anchor their actual first byte.
out.append((a&~1 if typ=='FUNC' else a, (obj if bind=='LOCAL' else '',name),int(size)))
return sorted(out)
ROOT = Path(__file__).resolve().parents[1]
pret = Path(sys.argv[1] if len(sys.argv) > 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}")