#!/usr/bin/env python3
"""Capture original 120 Hz timer callback and live two-tick pacing.
The timer callback and ratio/pacing routines execute unchanged. The harness
advances the interrupt explicitly, and calls the busy-wait consumer only when
its observed countdown gate is satisfied.
"""
import json,random,struct
from pathlib import Path
from native_reference import NativeReference,ROOT
def run(output):
 n=NativeReference();rng=random.Random(0x63e3c);records=[];rows=[]
 for trial in range(32):
  maximum=120;nominal=12;alternate=[6,12,24,120][trial%4]
  fast=[0,1,0xfffffff8,0xfffffffd][trial%4];slow=[0,1,0xfffffffc,0xffffffff][trial%4]
  n.put(0xbba40,'4h',120,12,maximum,maximum);n.put(0xbdbd0,'5h',256,256,nominal,alternate,nominal);n.put(0x981c4,'2I',slow,fast)
  rec=bytearray(struct.pack('<3h2I',maximum,nominal,alternate,fast,slow));steps=[]
  for step in range(120):
   elapsed=[0,1,2,3,4,8,12,21,22,120,255][step%11] if step<33 else rng.randrange(26)
   for _ in range(elapsed):n.call(0x63e3c)
   ready=n.get(0xbba46,'h')[0]<=maximum-2
   if ready:n.call(0x63f40)
   values=[n.get(0xbba46,'h')[0],n.get(0xbdbd8,'h')[0],*n.get(0xbdbd0,'2h'),*n.get(0x981c8,'I'),*n.get(0x981c4,'I')]
   rec+=struct.pack('<HB4h2I',elapsed,ready,*values)
   steps.append(dict(ticks=elapsed,ready=ready,state=values))
  records.append(rec);rows.append(dict(maximum=maximum,nominal=nominal,alternate=alternate,fast=fast,slow=slow,steps=steps))
 output.write_bytes(b'ESPACE01'+struct.pack('<II',len(rows),120)+b''.join(records))
 (ROOT/'work/research/interface/frame-pacing.json').write_text(json.dumps(dict(scope=__doc__,state=['countdown','elapsed','ratio','alternate_ratio','120Hz','60Hz'],traces=rows),separators=(',',':'))+'\n')
 print(len(rows)*120,'original timer/pacing states, including zero/one tick waits, stalls and clock wrap')
if __name__=='__main__':
 import argparse
 p=argparse.ArgumentParser();p.add_argument('--output',type=Path,required=True);run(p.parse_args().output)
