#!/usr/bin/env python3
"""Probe native main-menu font selection through complete real-controller circles.

The private JSR wrapper tail-jumps11B92, retaining its original inline-data return
address and complete register/SR contract. No instrumentation is published in ROMs.
"""
from pathlib import Path
import argparse, os, subprocess, json, shutil, struct
ap=argparse.ArgumentParser(description=__doc__)
ap.add_argument('rom',type=Path);ap.add_argument('output',type=Path)
ap.add_argument('--baseline',type=Path);ap.add_argument('--seed',type=Path,required=True)
ap.add_argument('--empty-save',type=Path,action='append',default=[])
ap.add_argument('--three-playoffs',type=Path)
a=ap.parse_args();here=Path(__file__).resolve().parent;out=a.output.resolve();out.mkdir(parents=True,exist_ok=True)
source=out/'font_probe.s';source.write_text('''    .text
    .globl _start
_start:
    move.w %sr,-(%sp)
    movem.l %d0-%d1,-(%sp)
    addq.w #1,0xFFFFF080
    btst #3,0xFFFFC2F8
    bne.s good
    addq.w #1,0xFFFFF082
    move.w %d7,%d0
    lsr.w #1,%d0
    moveq #1,%d1
    lsl.w %d0,%d1
    or.w %d1,0xFFFFF084
good:
    movem.l (%sp)+,%d0-%d1
    move.w (%sp)+,%sr
    jmp 0x11B92
''')
subprocess.run([str(here.parent/'m68kasm.sh'),str(source),'2FEA00',str(out/'font_probe.bin')],check=True,stdout=subprocess.DEVNULL)
code=(out/'font_probe.bin').read_bytes();reports=[]
for label,rom in [('current',a.rom)]+([('baseline',a.baseline)] if a.baseline else []):
 d=bytearray(rom.read_bytes());assert d[0xf7b66:0xf7b6c]==bytes.fromhex('4eb900011b92')
 assert d[0x2fea00:0x2fea00+len(code)]==bytes([255])*len(code)
 d[0x2fea00:0x2fea00+len(code)]=code;d[0xf7b66:0xf7b6c]=bytes.fromhex('4eb9002fea00')
 private=out/(label+'-probe.bin');private.write_bytes(d);case=out/label
 cmd=['python3',str(here/'verify_season_navigation.py'),str(private),str(case),'--seed',str(a.seed.resolve())]
 for save in a.empty_save:cmd+=['--empty-save',str(save.resolve())]
 if a.three_playoffs:cmd+=['--three-playoffs',str(a.three_playoffs.resolve())]
 with (out/(label+'.log')).open('w') as log:r=subprocess.run(cmd,env=dict(os.environ,SEASON_FONT_PROBE='1'),stdout=log,stderr=log)
 metrics=[json.loads(p.read_text()) for p in case.glob('*/font-metrics.json')]
 assert metrics,'no native font samples'
 if label=='current':assert r.returncode==0 and all(m['wrong_font']==0 for m in metrics),(label,r.returncode,metrics)
 else:assert r.returncode!=0 and any(m['wrong_font']>0 for m in metrics),'preceding ROM did not reproduce font bug'
 reports.append(dict(version=label,cases=len(metrics),native_text_calls=sum(m['total'] for m in metrics),wrong_font_calls=sum(m['wrong_font'] for m in metrics),expected_failure=label=='baseline'))
(out/'results.json').write_text(json.dumps(reports,indent=2)+'\n');print(json.dumps(reports,indent=2));print('PASS native main-menu font selection and baseline reproduction')
