channel6¶
Screenshots¶




The fourth image is synthetic. preview_in_game.py draws the frame beneath the
UI from flat shapes, not a captured game, and renders the blob onto full
transparency before compositing the two. It shows the operation the GS
performs on a skipped clear. It is not a photograph of this UI over a running
game.
What it demonstrates¶
channel6 bakes a games screen (a six-cover grid, a detail column, three
actions) and a probe screen (eight labelled conformance cells) into one
blob, sharing every texture, atlas and font table between them. The two
screens are reached with ps2ui_screen_set, not composited: the browser and
the probe never share a frame.
| mechanism | where |
|---|---|
One project file compiles two screens against one shared stylesheet; only probe.html sets focusWrap: true |
ps2ui.json |
focusable/autofocus sets initial focus per screen; games dead-ends at its grid edges, probe wraps |
games.html, probe.html |
data-slot with data-slot-capacity for 13 games-screen slots and 2 probe-screen slots |
games.html, probe.html |
data-keep protects the CLIP cell's out-of-clip scissor instrument from the bake-time dead-geometry trim |
probe.html, channel6.css |
A second ps2ui build --mode ntsc16x9 -o build/ui-16x9.uib of the same project bakes the widescreen blob; there is no variants key |
build.sh |
preview_in_game.py renders the blob on full transparency and composites it over a synthetic driving-game frame |
preview_in_game.py |
check.py re-reads the baked blob and asserts the focus graph, slot capacities, vanish-row colours and the swizzle tile's region order |
check.py |
The project file sets no mode, canvas, strict or vramBudget, so every
one of those takes the baker's default. Read the full key table on
the project file. The 16:9
blob is a second build of the same ps2ui.json with flags, which is why the
project file carries no variants block.
Build and check¶
Run the example's own script from the repository root:
The script bakes the 4:3 project, bakes it again for 16:9, renders the probe
screen's own preview and montage, composites the browser over a synthetic
game frame, refreshes the four committed screenshots, then runs check.py
against the fresh blob. Its last lines:
ok 46 - both are the same size (24x24), so only position distinguishes them
ok 47 - and clears the clip edge by 15px, so an ordinary layout edit cannot walk it back inside
1..47
PASS: 47 checks, 0 failure(s)
channel6 browser: ./examples/channel6/build/ui.uib
The screenshots the run just wrote match the ones already committed:
Validate either blob directly with ps2ui-check:
$ ps2ui-check examples/channel6/build/ui.uib
...
1..75
# examples/channel6/build/ui.uib: 640x448 at 4:3, 2 screen(s), 1242 commands, 25 textures, 15 slots
PASS: 75 checks, 0 error(s), 1 warning(s)
tools/check-blobs.sh runs both channel6 blobs with a declared exemption,
because the probe screen's CLIP cell parks one instrument quad outside its
own scissor on purpose and a validator reading the file cannot tell that from
waste:
examples/channel6/build/ui.uib|examples/channel6/build/ui-16x9.uib)
echo "--allow-dead 1 --strict" ;;
Under that flag the same run shows zero warnings:
$ sh tools/check-blobs.sh examples/channel6/build/ui.uib examples/channel6/build/ui-16x9.uib
...
PASS: 75 checks, 0 error(s), 0 warning(s)
...
PASS: 75 checks, 0 error(s), 0 warning(s)
check-blobs: 2 blob(s) validated
CI runs this example across three separate steps: "Channel-6 browser end to
end" runs ./examples/channel6/build.sh and nothing else
(ci.yml); "Committed screenshots
match the renderer" re-runs the git diff --exit-code above alongside
memcard's and opl-env's screenshot directories
(ci.yml); "Validate every blob
against the runtime's assumptions" runs tools/check-blobs.sh by name
against both channel6 blobs plus the other two examples'
(ci.yml).
Numbers from the blob¶
Taken from the ps2ui-check trailer and arena note above, the ps2ui-bake
texture and VRAM lines from the same build.sh run, and the two blobs' file
sizes. The 16:9 blob repeats every count and the arena figure; only its
canvas aspect and screen names differ.
| field | value |
|---|---|
| canvas | 640x448 at 4:3 (ui.uib); 640x448 at 16:9 (ui-16x9.uib) |
| screens | 2 |
| commands | 1242 |
| textures | 25 |
| CLUTs | 9 |
| slots | 15 |
| fonts | 4 |
| kern pairs | 570 |
| dead commands trimmed at bake | 20 |
| dead commands remaining, declared | 1 of 1 (--allow-dead 1) |
| arena, EE | 10624 bytes |
| arena, 64-bit host | 10824 bytes |
| VRAM used | 368 KiB of 736 KiB budget (50%) |
blob size, ui.uib |
252,624 bytes |
blob size, ui-16x9.uib |
252,640 bytes |
The arena figure is blob-specific: only a bake or a check run in this session
proves what this project needs. See
the arena note for why the EE and host
figures differ. The 20 trimmed commands are the tail of nowrap runs the GS
could never see; the one remaining dead command is the CLIP cell's own
data-keep instrument, declared through --allow-dead 1 rather than fixed.
Source tour¶
- ps2ui.json - the whole project: two screens, one of them wrapping, one shared stylesheet, three preview paths.
- ui/games.html - the browser: six focusable cover tiles, a detail column of five slots and three actions.
- ui/probe.html - the conformance
grid: eight labelled cells, each keyed to one bring-up step, including the
data-keepscissor pair. - ui/channel6.css - the shared
stylesheet, including the comment on why
data-keepexists and what it guards against. - check.py - the blob-level contract: the focus graph, the vanish rows for bring-up steps 4 and 5, and the swizzle tile's authored region order for step 3.
- preview_in_game.py - the synthetic composite: a driving-game frame drawn from flat shapes, never a captured photograph.
Start from this¶
Copy the two-screen project shape with one screen's focusWrap set and the
other left at the default, the data-slot pattern for runtime-editable text,
and the second ps2ui build --mode invocation for a widescreen bake of the
same project. Replace the six covers and eight probe cells with your own
screens, and keep the probe screen itself: it stays useful long after your
markup has replaced the browser, and its cells are what
first boot compares a console
frame against.
channel6 uses none of the following, so add them only if the new project needs them:
- Composited overlay screens, covered in
screens and overlays.
gamesandprobeare both top-level and reached withps2ui_screen_set; neither is drawn over the other. - More than one theme, covered in theming. opl-env uses two.
- Streamed textures instead of baked ones, covered in streaming art. Every cover here is palettized and baked in place; opl-env streams its covers instead.
- Repeated rows from one template, covered in lists. channel6 writes six tiles and eight cells out by hand, the same choice memcard makes.
After the blob passes ps2ui-check, the first-boot checklist runs the ten steps this example's probe screen was built to answer.