On this page

Every per-scene page at /scenes/<slug>/ on this site now carries a captured-on-PS1 hero image at the top, a per-page Open Graph override pointing at it, and a figcaption underneath that names the gag and any engineering retro the scene happens to belong to. All sixty-three.

That number is not interesting on its own. The interesting thing is that nobody planned the structure of the figcaptions or the cross-link clusters they made. They came out of writing one scene’s hero at a time, in the order DuckStation had captured them, and noticing what wanted a link.

What the rollout actually was

Per scene, mechanically:

  1. Pick a representative frame from the v0.8.4-ps1 chapter-select grind’s capture dump (DuckStation writes 961×720 PNGs into ~/.var/app/.../duckstation/screenshots/ whenever you take a screenshot, and the grind took a named one for almost every scene).
  2. Promote it to site/assets/img/<slug>-ps1-<short>.png.
  3. Add image: / image_alt: / image_width: / image_height: to the page’s frontmatter so the head template flips the per-page OG override on.
  4. Add a <figure class="scene-hero"> block above the body with a figcaption that says what the gag is in one or two sentences.

That four-step pattern was set in 1adac73b5 when FISHING 2 got the first per-scene hero. The next sixty-two ships followed it.

Frame selection rules of thumb

The frame-selection step seemed obvious until it wasn’t. A few patterns kept repeating:

  • Compose-the-whole-joke. Pick the frame where both halves of the gag are visible at the same time. VISITOR 1’s hero shows the speedboat zipping past and Johnny standing at the front of the island looking the wrong way — same frame. ACTIVITY 11 has the bird perched in the palm leaves with the stolen clothes and a clothes-less Johnny standing in the water — same frame. If the joke is “X happens to Y,” the picture should have both.
  • Antagonist-in-frame beats Johnny-alone. FISHING 4 had two captures: Johnny holding a fishing rod, and a frame with Johnny + a shark fin and a fishing line stretching across the open water. The fin frame won. VISITOR 5 had three captures; the one where the biplane is in-frame won. At OG-thumbnail size the antagonist makes the gag legible; without it, the frame just looks like Johnny standing on an island.
  • Title-naming beat over generic-looking-around. JOHNNY 2’s two captures were a “thinking of home” thought-bubble and an “SOS-note” thought-bubble. The page title is “puts an SOS note inside” — so the SOS bubble won.

None of these rules were written down before the rollout started. They got noticed around the fifth or sixth ship and applied retroactively where a previous frame still looked OK with hindsight.

Every figcaption is short. Most of them have one or two outbound links. The links accumulated into clusters that nobody planned.

Variant pairs are the simplest case. Two scenes are obvious gag-twins varying one axis:

Story-arc pairs and sagas were more interesting because they walked across families. JOHNNY 2 (recycle a found bottle, write SOS) → JOHNNY 5 (write SOS in a fresh bottle, send) → JOHNNY 4 (one of his bottles eventually washes back). Three scenes, mutually cross-linked. Then SUZY 1 (Suzy back home receives a Johnny letter) ↔ JOHNNY 3 (Johnny writes a letter to Suzy). And then the longest arc in the game: WALKSTUF 2 (raft-build) → STAND 10 (admire raft) → MARY 5 (pack the raft, sail off) → SUZY 2 (drift in to the home beach). Add the SOS bottles in transit and that’s an eight-scene mutually-linked cluster: walkstuf2 + mary5 + johnny2 + johnny5 + johnny4 + suzy1 + suzy2 + stand10. None of this was visible from the per-scene markdown bodies on their own — it only crystallized once the figcaptions started linking.

Theme clusters appeared in single ADS families:

  • The coconut quartet in VISITOR. VISITOR 4 loses one (rolls off into the ocean), VISITOR 5 weaponizes one (throws at a plane, brings it down), VISITOR 6 shake-crack-eats one, VISITOR 7 just-crack-eats one. Same prop, four different fates.
  • The shark thread crosses families. FISHING 4 drags Johnny like a water-skier; FISHING 5 eats him whole; MISCGAG 2 scares him out of his bath.
  • The hard cluster. /about/ names it: foreground-only multi-view scenes (MISCGAG 1, MISCGAG 2, STAND 1, the wide LILLIPUTIAN arrival) that all needed the generic normal / far-left / far-right host stitch before their packs replayed cleanly.

Engineering-quirk lineages showed up too. Three STAND scenes (10, 11, 12) all had the same host pipeline quirk — STAND.ADS:N exits after only two frames, the no-stitch export collapses to a 92-byte empty pack. The previously-committed packs played cleanly on PS1, so they were signed off as-is. Paid pragmatism, called out by name. Three more STAND scenes (5, 6, 7, 8) all share the no-stitch fast-path lineage with the runtime FG2 wave-tick fix STAND 8 introduced.

Engineering retros that didn’t justify a doc

A repeated discovery during the rollout was that a figcaption is a useful surface for naming a concrete engineering detail that doesn’t justify writing a whole doc but should be on the record somewhere. A reader looking at the STAND 5 hero learns:

Engineering footnote: STAND 5 is what surfaced the “no-stitch fast path fades Johnny’s legs” bug — pure base-diff treated frame-0 static pixels as background and dropped them. The exporter fast path now keeps a single-position foreground-only overlay while still skipping far-left / far-right stitch captures for simple STAND scenes.

That sentence didn’t exist anywhere on the site before the hero shipped. It would not, on its own, have justified a /docs/ reference page or a devlog post — but it is a useful piece of the project’s why. A reader on STAND 8 finds the static-ocean bug retro the same way; on VISITOR 7, the dedupe-too-short-strike-rows fix; on WALKSTUF 1, the v0.8.3 compact-FGP3/v4 restore-minus-current pack pass and its before/after VBlank numbers.

The one scene the chapter-select grind missed

Sixty-two of sixty-three. The capture dump from the v0.8.4 grind covered every scene except JOHNNY 3. The dump was named, frame-by-frame, and johnny3 was simply absent — the sweep had moved past it without taking a screenshot.

Closing the rollout required generating a fresh capture. The same headless harness machinery that runs /help/menu/ and powered the Scene Explorer screenshot replacement on this site’s homepage handled it: write a one-shot BOOTMODE.TXT (fgpilot johnny3 night/raft-stage 4 island-pos -64 54 pad-script), write a one-shot PADSCRIPT.TXT taking four shots across one full ~3.5s scene loop, rebuild the EXE + CD image, run ./scripts/run-regtest.sh, grep JCPADSHOT markers out of the TTY log, pick the captured frame that best showed the gag, restore the originals.

The frame that won was the romantic thought-bubble — Johnny standing on the island writing the letter, picturing himself with Suzy back home embracing on a beach. Two of the four candidate frames showed only Johnny + the letter; one showed only the bubble at a too-early moment. The winning frame had both. Compose-the-whole-joke held up.

Final shape

Sixty-three of sixty-three. Ten ADS families closed. Every per-scene page now carries a unique OG card. The cross-link cluster taxonomy that emerged was not designed up front; it accreted because every figcaption has to ask “what does this scene most want to link to right now?” and small consistent answers stack up.

If there’s a generalizable thing here, it’s that figcaptions are an under-rated documentation surface. They are constrained — short, page-local, attached to a picture — and the constraint is what makes them useful. A writer can fit one engineering-retro sentence and one gag-arc cross-link in a figcaption without making it feel padded. Sixty-three of those, taken together, build a connectivity graph that no individual essay had to draw on its own.

The full list of per-scene pages with their heroes is at /scenes/. The matching commit history is on the project’s main branch — every scene’s hero is one focused commit, mergeable and revertable on its own.

  • Scene ledger — where every hero now sits, linked from a per-scene page with figcaption + per-page OG override.
  • Lab: the chapter-select grind — the v0.8.4-ps1 loop that captured 62 of the 63 hero frames on hardware in one named pass. The rollout described here was the consume-side of that producer.
  • Lab: the 63-scene grind — the earlier validation grind that made every scene heroable in the first place. Hero rollout is the post-validation polish pass; this is the pre-rollout signoff pass.
  • Lab: the site itself, as a small program — the per-page OG override machinery (image / image_alt / image_width / image_height frontmatter routed through _includes/head.html) that makes each scene page’s social card carry its hero instead of the site default.
  • Captions — the paired post-validation reconciliation surface: the chapter-select grind’s hardware capture loop is where caption-mismaps were surfaced, fixed in the per-scene index.md titles + bodies, and documented in the corrections section.