Files
BFM-decomp/tools/interleave_check.py
T
Drew T c513e1fbbd feat(phase-32): T1a (2) — resident: func_800D128C (243 ins) BANKED byte-identical 8e17e02f via the raw splice + a 5-piece carve; three instrument fixes (§498)
- BANK: the stored S71 closeness-0 draft spliced into src/resident/resident_jr_800D128C.c; jtbl_carve --func
  carved jtbl_80113FB8 (119 entries, 1 pad word trimmed) + jtbl_80114198 into [0x451c0, .rodata,
  resident_jr_800D128C] + [0x453c4, data, tail3]; JTBL_PADS 0,4; make extract + make build BINARY=resident -j8
  rc 0, sha 8e17e02ff8954d07c979449198f7e1645046b353 == check (R53). pads_audit ok/ok; interleave_check
  ALIGNED n=5; verbatim_check --strict 5==5. Resident stubs 2 -> 1 (func_800D06E8 remains).
- WHY THE GATE SAID DIFF (parallel_gate banked 0/DIFF on an rtu_match MATCH): jtbl_carve.set_overlays_var
  regenerated resident_JTBL_INTERLEAVE from the carve set and DROPPED the resident's `--pre hdr.rodata.o`
  (§8f leading-rodata sandwich); make extract refused (ld_interleave: hdr.rodata.o would be parked with
  .text), the build linked the STALE script (249,252 differing bytes from file offset 0x4), and
  harvest_verify._jtbl_prep_one never read the post-carve extract's exit code (R49/R61).
- FIXES (R35/R40/R57): jtbl_carve._merge_pre carries an existing --pre forward (idempotent; overlays
  unchanged, 4-shape unit control); harvest_verify refuses loudly on a failed post-carve extract and
  restores the snapshot (CARVE refusal, NOT a draft verdict); interleave_check's anchor accepts a leading
  --pre (was a false DRIFT n=0 on the resident; control ov_SC02_017 ALIGNED n=44 unchanged).
- cookbook §498 (+ the stale-asm-after-a-failed-extract sequencing law); SETUP rows for all three
2026-09-04 23:28:59 -06:00

29 lines
1.8 KiB
Python

#!/usr/bin/env python3
"""tools/interleave_check.py <overlay> — the `_JTBL_INTERLEAVE` order in config/overlays.mk must equal the yaml's
subseg sequence (tailN data / .rodata carves / trailing) position by position; any blanket restore of either
file silently breaks that (P31 S62: ov_SC03_015, ov_SC02_005 — extract rot + unwinnable pad searches). Prints
ALIGNED or the first mismatching positions. Zero-token; run after any overlays.mk or splat yaml restore."""
import re,sys
ov=sys.argv[1]
fix='--fix' in sys.argv[2:]
mk=open('config/overlays.mk').read()
# P32 T1a (cookbook §498): a binary may carry `--pre <obj>` BEFORE `--order` (the resident's §8f leading-rodata
# sandwich, `--pre hdr.rodata.o`); the old anchor `:= --order` read such a line as n=0 and reported a false DRIFT.
m=re.search(r'^%s_JTBL_INTERLEAVE := (?:--pre \S+ )?--order (\S+)'%ov,mk,re.M)
order=m.group(1).split(',') if m else []
y=open('config/splat.%s.yaml'%ov).read()
yseq=[]
for a,k,n in re.findall(r'^\s*- \[0x([0-9a-fA-F]+), (\.rodata|data|bin|c), (\S+?)\]',y,re.M):
if k=='data' and n.startswith('tail'): yseq.append(n+'.data.o')
elif k=='.rodata': yseq.append(n+'.o')
elif k=='bin' and n=='trailing': yseq.append('trailing.o')
print('%s order n=%d yaml n=%d %s'%(ov,len(order),len(yseq),'ALIGNED' if order==yseq else 'DRIFT'))
if fix and order!=yseq and m:
# --fix: the yaml is what `make extract` splits, so the order is REGENERATED from it (never edited by hand)
new=m.group(0).replace(m.group(1),','.join(yseq))
mk2=mk.replace(m.group(0),new,1); open('config/overlays.mk','w').write(mk2)
print(' FIXED: order rewritten from the yaml (%d pieces)'%len(yseq))
for i in range(max(len(order),len(yseq))):
o=order[i] if i<len(order) else '-'; yy=yseq[i] if i<len(yseq) else '-'
if o!=yy: print(' !! %-36s | %s'%(o,yy))