D174 - The screen said nothing about what it was doing, and the first fix for that made the probe worse
Three faults, found by watching PS5PCEM sit on one page and asking why.
The page cycling stopped, and the reason was in our own reports
obs_screen_present paced its detail pages with a single
sceKernelUsleep(3000000) - three seconds. On PS5PCEM the
screen froze on whatever page was up.
The evidence was already recorded here: 050-time/usleep
sleeps 2 ms and passes on PS5PCEM, while
120-measure/sleep-fidelity, which asks for longer, is
excluded there as known to end the process. We were asking for
1500× the duration known to work.
Pages now wait by repeating the 2 ms sleep. Same total time where
either works; keeps advancing where only the short one does.
This is presence-versus-behaviour inside our own display
loop - the guard above it tests that
sceKernelUsleep exists, which says nothing about
whether it returns.
"Is it stuck or finished?" was unanswerable from the screen
REPORT COMPLETE appeared on page 0 only, so a detail
page said nothing about whether the suite had ended. Someone looking at
page seven of fifteen could not distinguish a completed run cycling its
results from a run stopped dead - and when a page sits unchanged, the
honest reading is the second.
Every page now carries
SUITE COMPLETE - IDLE, CYCLING RESULTS, and the header
carries RUNNING <id> while a check is in flight.
These pages are only ever drawn after the suite ends, so the word is a
constant in the code - which is exactly why it is worth printing. The
reader does not know what the code knows.
And the in-flight indicator, done wrong first
The first version redrew the screen inside
obs_screen_attempt, so the name was on screen
during the call. obs_screen_redraw ends in
obs_display_flip, so that added a full present per check -
515 of them - and shadPS4 began dying in
120-measure, three checks it had never crashed on
before.
A probe that perturbs what it measures is worse than one that reports less. The id is recorded without redrawing; the screen is redrawn at every section boundary anyway, so a hang is narrowed to its section rather than its exact check. That is the trade, and it is the right way round.
Waiting for the end record instead of the budget
run-emulator.sh only stopped on its timeout, because a
module that draws its report never exits - it cycles pages for as long
as it is alive. So every successful run cost its whole budget: shadPS4
finishes the suite in about a minute and was being given two hundred
seconds, multiplied by every sweep round.
The report says when it is done. The screenshot path had watched for
OBS|end for a long time for exactly this reason; it simply
was not applied to the run.
And it had never worked there either. Both used
grep -q "^OBS|end", anchored - but records arrive
embedded in a loader's own log lines, which is why the
extraction at the bottom of the same script uses an unanchored
grep -o 'OBS|.*'. The anchored form matched nothing, so the
screenshot always landed late and the wait always ran full term.
Unanchored, a shadPS4 run went from 3m32s to 51s,
finishing on the end record after five seconds. A run that ends on the
record is reported as not timed out however long it took to get
there - reporting otherwise would make sweep.sh exclude a
check that finished.