#!/usr/bin/env python3
from __future__ import annotations
import argparse, csv, zipfile
from pathlib import Path

ORDER=[
 's00_locked_idle','s01_after_read_capacity_locked','s02_after_mode_sense_pre','s03_after_read_dvd_structure_c0',
 's04_after_mode_select_challenge1','s05_after_mode_sense_challenge1','s06_after_mode_select_challenge2',
 's07_after_mode_sense_challenge2','s08_after_mode_select_partition1','s09_after_final_mode_sense','s11_after_final_read_capacity']
ADDS=[0x8003E7BA,0x8003E7BC,0x8003E7DC,0x8003E7FC,0x8003E804,0x8003E80C]

def hx(b: bytes) -> str: return b.hex(' ').upper()
def get_bytes(source, name):
    if isinstance(source, zipfile.ZipFile): return source.read(name)
    return Path(name).read_bytes()

def main():
    ap=argparse.ArgumentParser()
    ap.add_argument('capture', help='instrumented capture folder or zip')
    ap.add_argument('--out', default='gdr8050l_high_block_timeline.csv')
    ns=ap.parse_args()
    p=Path(ns.capture)
    rows=[]
    if p.suffix.lower()=='.zip':
        z=zipfile.ZipFile(p)
        names=z.namelist()
        def read(n): return z.read(n)
    else:
        z=None
        names=[str(x) for x in p.rglob('*_80038000_64k.bin')]
        def read(n): return Path(n).read_bytes()
    for step in ORDER:
        cand=[n for n in names if step in n and n.endswith('_80038000_64k.bin')]
        if not cand: continue
        data=read(cand[0])
        def sl(addr,ln): return data[addr-0x80038000:addr-0x80038000+ln]
        e7=sl(0x8003E7BA,8)
        state='unlocked/high-layout' if e7[:6]==bytes.fromhex('01 01 00 06 06 00') else 'locked/pre'
        rows.append({
            'snapshot':step,'state':state,
            'e7ba_e7c1':hx(e7),'e7ba':f'{e7[0]:02X}','e7bb':f'{e7[1]:02X}','e7bc_e7bf':hx(e7[2:6]),
            'e7dc_e7df':hx(sl(0x8003E7DC,4)),'e7fc_e80b':hx(sl(0x8003E7FC,16)),
            'e804_e80f':hx(sl(0x8003E804,12)),
        })
    with open(ns.out,'w',newline='') as f:
        fields=['snapshot','state','e7ba_e7c1','e7ba','e7bb','e7bc_e7bf','e7dc_e7df','e7fc_e80b','e804_e80f']
        w=csv.DictWriter(f,fields); w.writeheader(); w.writerows(rows)
    print(f'[OK] wrote {ns.out} rows={len(rows)}')
if __name__=='__main__': main()
