"""Fresh genuine pre-outcome native start; no synthetic action/RNG/result fields.
The graphics/menu update changes cold-start timing. A matched real start isolates
shot-plan mechanics while independent ordinary cold-boot runs stay recorded.
State restoration always includes its exact capture-time SRAM pair.
"""
from pathlib import Path
import hashlib,json,struct,subprocess,os

def capture(reference,observer,here,out,initial,on,current_observed):
 h=Path(here);p=Path(out);p.mkdir(parents=True,exist_ok=False);reference=Path(reference);sha=lambda f:hashlib.sha256(Path(f).read_bytes()).hexdigest()
 assert sha(reference)=='6e66c0afe2496eb3f6a688c29888ca62b17aee0b0f51efec96d11dce5e842b31','exact pre-graphics R7 flow reference required'
 b=bytearray(reference.read_bytes());assert b[0x2d9000:0x2d9000+len(observer)]==b'\xff'*len(observer);b[0x2d9000:0x2d9000+len(observer)]=observer
 for at,old,new in[(0xe116,'6600000c08380000c2fa','4ef9002d90004e714e71'),(0xc314,'31eb0052bed8','4ef9002d9200'),(0x1538a,'4ef9002efc00','4ef9002d9400')]:
  assert b[at:at+len(bytes.fromhex(old))]==bytes.fromhex(old);b[at:at+len(bytes.fromhex(new))]=bytes.fromhex(new)
 observed=p/'reference-observed.bin';observed.write_bytes(b);(p/'battery.srm').write_bytes(initial);(p/'spec.json').write_text(json.dumps(dict(on=on,end=30000)));(p/'commands.txt').write_text('1500 press 1 Start 5\n1900 press 1 Start 5\n2501 exit\n')
 source=(h/'testcases/shot_plan_flow_hook.py').read_text();source+='''
_capture_original_tick=test_tick
def test_tick(f):
 if f==2500:
  n=core.retro_serialize_size();b=C.create_string_buffer(n);assert core.retro_serialize(b,n);raw=b.raw
  assert raw.startswith(b'GENPLUS-GX 1.7.6')
  assert rw(0xc6da)==rw(0xca3e)==0 and rw(0xef84)==rw(0xef86)==0,('matched start must precede goals/shots/catches',f)
  assert rw(0xf810)==s['on'] and rw(0xf07a)==1 and rw(0xc468)>0 and rw(0xc466)==0
  (p/'native-start.state').write_bytes(raw);(p/'native-start.srm').write_bytes(bytes(sram)[:65536])
  (p/'native-start.json').write_text(json.dumps(dict(frame=f,pc=struct.unpack_from('<I',raw,144468)[0],clock=rw(0xc468),score=[0,0],no_shot_or_catch=True,option=rw(0xf810))))
  raise SystemExit(0)
 _capture_original_tick(f)
''';(p/'capture-hook.py').write_text('import struct\n'+source);env={k:v for k,v in os.environ.items()if not k.startswith('GPGX_')};env.update(GPGX_DEV='513',GPGX_SRM=str(p/'battery.srm'),GPGX_HOOK=str(p/'capture-hook.py'))
 with(p/'log').open('w')as log:subprocess.run(['python3',str(h/'test_core.py'),str(observed),str(p/'commands.txt'),str(p)],env=env,stdout=log,stderr=log,check=True,timeout=100)
 state=p/'native-start.state';paired=p/'native-start.srm';context=json.loads((p/'native-start.json').read_text());pc=context['pc'];current=Path(current_observed).read_bytes();assert b[pc:pc+8]==current[pc:pc+8],'captured native PC is not byte-compatible'
 metadata=dict(reference_ROM_sha256=sha(reference),reference_observed_sha256=sha(observed),observer_sha256=hashlib.sha256(observer).hexdigest(),state_sha256=sha(state),paired_SRAM_sha256=sha(paired),context=context,scope='Genuine R7 cold-boot native state before any goal/shot/catch; same ABI-qualified passive observer as the actual trials. Full state+SRAM restoration, no individual outcome or RNG field edits.')
 (p/'provenance.json').write_text(json.dumps(metadata,indent=2)+'\n')
 hook=p/'matched-hook.py';hook.write_text('import os\n'+(h/'testcases/shot_plan_flow_hook.py').read_text()+'''
_matched_original_tick=test_tick
def test_tick(f):
 if f==2500:
  raw=Path(os.environ['COMMON_PAIRED_SRAM']).read_bytes();assert len(raw)<=len(sram)
  for i,v in enumerate(raw):sram[i]=v
 _matched_original_tick(f)
''')
 return dict(state=state,paired=paired,hook=hook,reference_observed=observed,provenance=metadata)
