This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Syplheed-Reborn/tools/re-capture/fast_title_probe.py
Sylpheed RE agent e9924ff9e8 re: build the fast probe -- and it refutes the diagnosis that motivated it
Last iteration I blamed four failed runs on the probe sampling every
~41 s, slower than the title screen lasts, and withdrew three earlier
conclusions on that basis. Building the fix tested the claim and killed
it.

The speedup is real and control-verified. One long-lived ffmpeg x11grab
stream, raw RGB, glyph counted in numpy -- no per-sample process startup,
no PNG encode, no convert -crop:

  wrapper `screenshot`            3.98 s per sample (emulator running)
  import -window root -> PPM      1.20 s
  long-lived x11grab stream       0.29 s          13.7x

The counter is byte-identical to is_title.py: 753 on the committed title
capture, 327 on the main menu.

Pointed at a running game it says the opposite of what I expected:

  332 frames in  85.3 s = 3.89 fps; max glyph 0
  1674 frames in 420.0 s = 3.99 fps; max glyph 0

1674 consecutive samples over seven unbroken minutes, four per second,
zero green-(A) pixels. Sampling rate was a real defect that happened not
to be the cause.

So "neither locale reaches the interactive title without a pad press" --
withdrawn last iteration for want of evidence -- is reinstated, now as a
dense measurement, with its reach stated: a MID-RUN window only, silent
about the boot title.

Leading hypothesis, unconfirmed: the PRESS (A) plate appears only in the
boot title window and the attract loop's title carries none, which is
exactly what title_states_capture.sh was written to test. The experiment
is to start the fast probe from t=0 rather than attach to a run already
in progress.

METHOD: fixing the instrument is how you test the explanation that blamed
it -- a plausible mechanism is a hypothesis, and the fix is its
experiment, not its proof.
2026-08-29 01:34:40 +00:00

35 lines
1.4 KiB
Python
Executable File

"""Fast title probe: one long-lived x11grab stream, ~3.5 fps, glyph count per frame.
Replaces the two-`screenshot` polling loop, which costs ~4-11 s per grab while
xenia runs and so samples every ~41 s -- slower than the title screen lasts.
Counter is byte-identical to is_title.py (controlled: 753 on the committed title
capture, 327 on the main menu).
"""
import subprocess, sys, time
import numpy as np
W,H = 1280,720
LIMIT = float(sys.argv[1]) if len(sys.argv)>1 else 120
NEED = int(sys.argv[2]) if len(sys.argv)>2 else 400
p = subprocess.Popen(["ffmpeg","-loglevel","error","-f","x11grab","-draw_mouse","0",
"-video_size",f"{W}x{H}","-i",":98","-r","4","-f","rawvideo","-pix_fmt","rgb24","-"],
stdout=subprocess.PIPE, bufsize=W*H*3*2)
n=W*H*3; t0=time.time(); frames=0; best=0; hits=0
while time.time()-t0 < LIMIT:
buf=p.stdout.read(n)
if len(buf)<n: break
a=np.frombuffer(buf,np.uint8).reshape(H,W,3).astype(int)
r,g,b=a[:,:,0],a[:,:,1],a[:,:,2]
c=int(((g>130)&(g-r>45)&(g-b>45)).sum())
frames+=1
if c>best:
best=c
if c>=NEED:
from PIL import Image
Image.fromarray(a.astype(np.uint8)).save("/sylph-home/re/shots/fast-title.png")
if c>=NEED:
hits+=1
if hits==1: print(f"TITLE at t={time.time()-t0:.1f}s glyph={c} (frame {frames})", flush=True)
p.kill()
dt=time.time()-t0
print(f"{frames} frames in {dt:.1f}s = {frames/dt:.2f} fps; max glyph {best}; hits {hits}")