titles.json no longer takes a name: a run is labelled with the package's
own param.json title name. discover() checks the param.json titleId with
the same pattern as the catalog keys, since it names the work directory
that prepare() empties.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
ScreenTester5 presented twice in 60 s, just before the run ended, and
was reported as rendering with no frame kept. A run that never presents
enough for a frame to be dumped is now stalled.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Windows placed past the desktop edge could not be looked at. They now
keep their position and go to the bottom of the z-order without focus
when created or shown, so the run stays out of the way and the window
can be brought forward from the taskbar. A window is sent back once, so
it stays in front after the user raises it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A crashing title brings Windows Error Reporting into the job, and its
exit code of 0 hid the crash: the exit code now comes only from
processes whose image is inside the title's folder. Relinker FAIL lines
count as errors, and the catalog titles that need
--trap-sdk-syscall-stubs have it in titles.json. Each title is prepared
in <out>/work/<ID>, the same path on every run, so a firewall prompt
appears once per title; its relink.log is copied into the run's folder.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Report the last process's exit code after LoadExec on Windows, keep the batch when one package cannot be prepared, write summary.json after each title, default --out to build/title-runs, skip non-object summary lines, drop inherited shader cache variables.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
An APS5_AB run interleaves phases A and B, and every periodic report
covers the time since the previous report of its kind, so its numbers
need sorting before A and B can be compared. tools/ab_split.py reads
the [ab] lines and counts a [present], [gputime], [draw] pipelined or
[syncwait] report for a phase only when its whole span lies inside the
phase after its settled line. It prints presents per 10 s and frame
time per phase, GPU busy and idle time per frame, GPU time per present
(also per --program key and --class), committer, drain and hook-wait
times, the A and B means, and each B phase against the mean of its
neighbouring A phases, which cancels a linear drift.
AI-assisted: yes
Two runs of the same scene drift apart by more than many effects worth
measuring. APS5_AB=<seconds>:<switch>[+...] alternates phase A (switches
as the environment sets them) and phase B (the listed switches toggled)
at flip packets, under the GPU mutex after the draw pipeline drained,
and prints "[ab] phase A|B <k> begins/settled at present <n> (t <s> s)".
APS5_AB_START (a flip count, or <n>s) delays the first phase and
APS5_AB_SETTLE (default 2 s) marks when a phase's reports are clean.
Switches live in a registry (RuntimeSwitches) of relaxed atomics that
start as the environment sets them; APS5_NO_BARRIER_BATCH is the first,
since every elision it gates is decided per barrier. Any other name
fails the first flip. Without APS5_AB nothing changes.
AI-assisted: yes
Save r12 in the entry walk so TraceImport_nid_no_patch is called with an aligned stack, record only executable Mach-O segments in the module map, and make the test hook check the alignment.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Walk each macOS function import before the guest entry and pass it through TraceImport_nid_no_patch, as Linux and Windows already do. An x86-64 libc build records the call and prints it on SIGABRT.
A traced run that ends without a crash or an abort never reports which
imports it called. With APS5_TRACE_CALLS_FILE set, the first traced import
starts a thread that rewrites that file every 10 seconds with every import
called so far, most called first.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Linux entry stub now passes each traced import through libc.prx's
TraceImport_nid_no_patch before it calls the guest entry, and stores the
returned thunk in the import's slot. The same imports are traced as on
Windows: functions bound through a PLT slot or a GOT slot, without an
addend, and not weak. TraceImport_nid_no_patch is bound eagerly through
an added GLOB_DAT relocation, so a libc.prx without it fails at load.
Each slot's page is made writable with mprotect first, so slots inside a
PT_GNU_RELRO range can be replaced.
--trace-imports now requires libc.prx among the libraries on Linux too,
and is refused with --macos.
APS5_VIDEOOUT_TELEMETRY_DIR=<directory> appends one JSON object per line to <directory>/videoout.jsonl: a contract line for the run (commit and pid), a pad line whenever the published pad state changes in its buttons, sticks, L2 or R2, a present line after the first present and every 30 after that with the count and rate the window title shows, and a drops line with the number of lines the writer discarded, reported every ten seconds while it grows and once at a normal exit. A bounded queue of 4096 lines and one writer thread batch the file, so neither the present nor the input path waits for it; a pad change that the full queue refused stays pending for a later publish, and the frame count moves from UpdateTitle's function-static to DisplayWindow so the input path can name the present it belongs to.
Without the variable no file is opened and no thread is started: a present or an input update costs one call that checks a guard variable and returns null.