Two new floating browsers, both fed only by static data — the disc for screens,
a savedata file for saves — following the existing Game Data / Ships pattern
(request event → worker thread → IsoLoaderMsg → draw system).
UI Screens
Pick a screen pak and one of its builds (a build = one context × language
variant; GP_PAUSE_MENU holds six) and see the screen reassembled at 1280×720
beside the element list it was derived from, so a wrong placement shows up as
a wrong picture and the row next to it says why. Per-element visibility
toggles, focused-state and loop-animation toggles, and an inspector showing
each element's sprite, parent link, kind flags, pivot and keyframe count.
Compositing decodes ~30 T8aD sprites, which is far too slow for the UI
thread, so it runs on a worker under the same generation gate the XPR path
uses — a toggle mid-decode discards the stale result rather than racing it.
The panel deliberately surfaces two things it would be easy to hide: sprites
that named a child the bundle does not hold, and builds recovered through the
.rat fallback (where elements without a record are simply absent).
Save File
Opens a savedata file (it lives in the emulator's content tree, not on the
disc, so this is a file dialog rather than a disc path). Shows the container,
the GHAD block with every field coloured by its actual confidence, the
Arsenal develop blob, the per-stage SHAB records, and the header summary.
Three things the panel states rather than glosses: the byte-identical
round-trip, which is the check the whole layout rests on; that SHAB records
are per-stage results and NOT the UI's save slots; and that the header
summary is what the Details panel reads, so a payload edit that leaves it
stale proves nothing about the field that was edited. Fields tested and
refuted (+36, +56) are shown as refuted rather than dropped.
Also gates draw_game_data_ui / draw_ships_ui at their registration site. Both
are #[cfg(not(wasm32))] but were registered unconditionally, so the wasm leg of
`just ci` failed on an undefined name. NOTE: that leg still does not build, for
a pre-existing and unrelated reason — the workspace pins tokio with features =
["full"], which pulls mio, which refuses to compile for wasm32. Fixing that
means restructuring tokio's features per target and is left alone here.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>