Files
Sylpheed/tools/re-capture/splash_boundaries.py
sim e909c7c133 chore: retire the last dead paths and names from the consolidation
Nothing here changes what a tool computes; it changes where tools look.

- tools/re-capture: 33 censuses globbed /work/sylph_extract, a path that has
  existed nowhere since /work became a clone, so they matched nothing and
  printed empty results. They now resolve the disc through a new disc.py
  from $SYLPHEED_DISC and exit loudly without it (the #44 fix, generalised).
  Nine scripts that imported siblings from the retired Reborn checkout or an
  old session scratchpad now import from their own directory. unitgroup.py
  only needs the variable when --pak is not given.
- sylpheed-xex: the loader only ever uses the XEX2 retail key. The dead
  devkit key and a doc comment claiming a devkit fallback that does not
  exist are gone; Project Sylpheed is a retail XEX2, so no XEX1 key either.
- sylpheed-viewer: real_font_rasterizes looked for /tmp/sylph_extract and so
  always skipped. It reads $SYLPHEED_DISC now, and passes against the disc.
- Comments and docs that named xenia-rs, the Reborn repository or /work/*.pe
  as places to look now name sylpheed.db, Canary's ppc_context.h and the
  flat .pe; docs/re/README.md no longer says the native Canary build does not
  run.

Historical records keep their original paths: findings that were measured
against /work/xenia-rs/sylpheed.db still say so.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 22:30:28 +02:00

71 lines
2.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""Boot-splash boundaries from a UI draw log, counted the way that survives the cap.
🔴 Do NOT read element visibility off which quads the log prints. A draw batches
several quads (`indices=24` is six) and the log dumps only the first 8 vertices —
two quads — so which elements appear is the first two IN THE BATCH, and that set
moves as elements fade. On the developer splash the three glows hold that prefix
until t=45, which makes the three wordmarks look as though they start there.
`indices / 4` is how many quads the draw actually holds, and the cap cannot touch
it. Its transitions land exactly where the declared count of elements with
alpha > 0 changes:
publisher 1 -> 2 -> 1 (wordmark joins the glow at t=15; glow ends at t=45)
developer 3 -> 6 -> 3 (three wordmarks join three glows; glows end)
so each run yields calibration points at t = 15, 45 and the splash's end.
"""
import os, sys, collections
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from quads_per_frame import quads
def batch_runs(path, lo=0, hi=400):
per = {}
for (f, ind, got, exp, x, y, w, h, a) in quads(path, lo, hi):
if exp >= 1:
per[f] = max(per.get(f, 0), exp if exp >= 2 else 1)
runs = []
cur = None
for f in sorted(per):
n = per[f]
if cur and cur[2] == n and f <= cur[1] + 2:
cur[1] = f
else:
if cur: runs.append(tuple(cur))
cur = [f, f, n]
if cur: runs.append(tuple(cur))
return [r for r in runs if r[1] - r[0] >= 1]
def main():
path = sys.argv[1]
runs = batch_runs(path)
print(f"# {path}")
for a, b, n in runs:
print(f" frames {a:>4}..{b:<4} ({b-a+1:>3}) {n} quads")
# publisher = the 2-quad run; developer = the 6-quad run
pub = [r for r in runs if r[2] == 2]
dev6 = [r for r in runs if r[2] == 6]
dev3 = [r for r in runs if r[2] == 3]
if pub and dev6 and dev3:
p = pub[0]
d6 = dev6[0]
d3after = [r for r in dev3 if r[0] > d6[1]]
d3before = [r for r in dev3 if r[1] < d6[0]]
if d3after and d3before:
pub_start, pub_end = d3before[0][0], None
# publisher span: its own 2-quad run brackets t=15..45; the screen ends
# at the last frame before the developer's first 3-quad run
pub_last = d3before[0][0] - 1
pub_first = 1
dev_first = d3before[0][0]
dev_last = d3after[-1][1]
print(f"\n publisher frames {pub_first}..{pub_last} = {pub_last-pub_first+1}")
print(f" developer frames {dev_first}..{dev_last} = {dev_last-dev_first+1}")
r = (pub_last-pub_first+1)/(dev_last-dev_first+1)
print(f" ratio = {r:.4f} (declared 255/210 = {255/210:.4f}, "
f"excess {(r-255/210)/(255/210)*100:+.2f}%)")
if __name__ == "__main__":
main()