This page is a vocabulary anchor for the rest of /docs/. The project’s prose is dense by choice — FntFlush, dirty-rect bookkeeping, SPI tx_len, the FISHING 1 bar show up without scaffolding because the voice is “write the way an expert writes.” This page lets a new reader land at the start of a paragraph rather than google a phrase.

Grouped by area, not alphabetical — most readers come in via one section of the codebase, not by spelling. Cross-references inside definitions stay terse on purpose.

Pipeline

ADS
Sierra's Animation Description Script file — the higher-level sequencer that picks scenes, drives Johnny's mood and posture, and routes between scene-tag indices. The original game's `ACTIVITY.ADS`, `BUILDING.ADS`, etc. are still the source of truth for which 63 scenes ship; the PS1 runtime never interprets them at runtime.
TTM
Sierra's Tagged Text Machine bytecode — the lower-level animation primitives an `ADS` scene tag dispatches into. Each TTM script is a sequence of opcodes (load resource, draw rect, blit, sleep N ticks, play sample, etc.). The host build runs the real TTM interpreter to capture every visible draw; the PS1 build replays the captured stream.
FG2 pack
The per-scene foreground binary the PS1 loads off the disc. One fg2.high and one fg2.low per scene (high-tide and low-tide variants). Carries its own palette, frame-timing table, base-frame full-render, and per-frame diff spans. The whole runtime trick of this port is that the PS1 replays packs instead of running TTM. Most scenes have moved to the denser FGP3 successor format internally while keeping the .FG2 filename.
Host build
The desktop-side Linux build, forked from jno6809/jc_reborn. Runs the original Sierra bytecode against the original Sierra data files (RESOURCE.MAP, RESOURCE.001) under a capture mode that records every draw and every PLAY_SAMPLE into FG2 packs. Required to develop new scenes; not needed to play the released disc.
Capture (mode)
Host-build environment-variable knob that turns on FG2 export for a single scene's story-flag permutation. Two captures per scene: high tide + low tide. The capture must produce a deterministic replay, which is why the host respects an explicit RNG seed in capture mode.
Replay
What the PS1 build does. Loads an FG2 pack from the disc, plays back every frame's diffs against its own background and overlay layers, fires sound events at the recorded ticks. The PS1 never interprets a Sierra opcode at runtime.
fgpilot
Internal codename for the PS1 scene-playback runtime — the replay engine implemented in src/foreground_pilot.c. The name comes from when the foreground-only host capture was a pilot experiment that didn't yet work; the directory was named fgpilot/ and it stuck. As a BOOTMODE.TXT token, fgpilot <slug> forces a specific scene (e.g. fgpilot mary4) instead of letting the screensaver loop pick at random; fgpilot freeplay boots straight into Freeplay. The public-facing name is gradually moving to "PS1 scene playback" in operator docs; the internal codename in source stays.
Scene Explorer (chapter-select)
The pause-menu sub-screen that lists every FG2 pack on the disc and lets the player jump straight to one. Each grid slot shows a thumbnail (a 320×240 RGB555 SCR loaded from SCR\SX<abbrev><tag>.SCR) plus a display name; cursoring over a slot streams its thumbnail into the framebuffer and selecting it boots the scene through fgpilot. The runtime header is src/scene_explorer_data.h (regenerated from docs/ps1/scene-status.md + per-scene index.md titles); the loader is grLoadSceneExplorerThumbnail in src/graphics_ps1.c. The "chapter-select" name comes from PS1-era game UX and gets used informally; "Scene Explorer" is the in-game label. The v0.8.4-ps1 grind shipped a custom on-PS1-captured thumbnail for every one of the 63 scenes — see /lab/chapter-select-grind/ for the loop story.
Freeplay
The direct-control runtime mode added in v0.5.0-ps1. Johnny walks the island under D-pad / left-analog input instead of being replayed from a captured FG2 pack. Architecturally this is the first PS1 mode that's live C code rather than diff-spans-from-disc: every frame reads the controller, updates a small state machine, restores the island background from clean rects, draws Johnny and any active prop, and presents — all in src/scene_freeplay.c, sharing the per-frame draw kernel src/walk_render.c with story-loop walks. The pause-menu Freeplay Options sub-screen exposes debug catalogs (Gags, Visitors, Controls, Clear) selected from in-game without rebuilding. R1 + D-pad shortcuts apply day/night, tide, raft, and holiday changes immediately. Reachable two ways: from the pause menu's Freeplay ON toggle, or as the fgpilot freeplay BOOTMODE.TXT token. Full reference at /docs/freeplay/.
Story-loop walks
The runtime path that moves Johnny between scenes instead of teleporting him. Fires after the screensaver-loop scene picker has chosen the next scene and before that scene's FG2 pack plays. Uses Sierra's pre-baked walk_data.h route table from the original engine; the PS1-side modules are src/walk_pilot.c (state) and src/walk_render.c (per-frame draw, also reused by Freeplay direct-control walks). Shipped in v0.4.20-ps1; v0.7.2 added a backdrop-key guard, v0.8.0 a clean-rect retry path, v0.8.1 wave-band/split-rect pressure accounting. Full reference at /docs/walks/.
Frog clock
The animated loading-transition card that appears between scene swaps and during freeplay teardown/rebuild. Sierra's original engine had a static "MEANWHILE…" frame (MEANWHIL.BMP + a single hand sprite); the PS1 port shipped it static at first and then in v0.6.x turned it into a 36-VBlank animation with hour and minute hands positioned from the original MEANWHIL.TTM script. Plays during walk-skipping cycles too — see the scene-set-and-frog-clock devlog for the sequence-reset story.
Scene picker
The runtime dispatcher that decides which scene plays next. Three policies (Random / Sequential / Original Sierra), selectable from the pause menu's Scene Set sub-screen. The Original Sierra policy is a state machine that runs sequences of intermediate scenes followed by a FINAL, filters candidates by FINAL / FIRST / LOWTIDE_OK / VARPOS_OK / dayNo, forbids same-tag-twice-in-a-row, and retries up to 8 times when a candidate has no valid walk-in spot. Sits between the screensaver-loop scheduler and the story-loop walk driver: it picks, then walks Johnny to the next scene's start spot, then plays the FG2 pack. Source at src/scene_picker.c; design notes at docs/ps1/scene-picker-design.md.
The FISHING 1 bar
The project's internal acceptance bar for "scene validated." Pixel-perfect visuals against the host-captured reference, plus SFX cues that land on the same engine ticks, signed off by human visual + audible review across every variant flag that applies to the scene (night palette, low-tide shoreline, holiday overlay, raft-stage progression). Named because FISHING 1 was the first scene to clear it.
Regtest harness
Headless DuckStation with a scripted-input file (controller frame log) that boots a build, walks a known route, captures screenshots at marker frames, and pixel-diffs against stored reference shots. Source of truth for "does this still build and boot." The release bar (visual signoff) is a separate, stricter pass on top.
Story flags
The handful of mood / posture / tide bytes the original engine carries between scenes. A scene's exact behavior depends on them — a fishing scene plays differently if Johnny had just woken up vs. just eaten dinner. The host build replays scenes in order to establish state before capturing; the PS1 build doesn't carry runtime state because its packs already encode the right variant.
Seed
RNG seed used by the host to make a capture deterministic, so two runs of the same scene produce byte-identical packs. Override surface in the pause menu (Pause → System → Set RNG Seed) lets the runtime force the same path the host captured under, which is occasionally useful in regtest debugging.
BOOTMODE.TXT
A small text file the runtime reads at boot to override default state for a deterministic run. Carries one or more tokens — night 1, lowtide 1, holiday N, raft-stage N, fgpilot <slug>, seed N, fgpilot freeplay, pad-script, pad-script-log, etc. — that fix variant flags and entry points the screensaver loop would otherwise pick at random. The capture pipeline writes one before each host run; the regtest harness writes one before each headless DuckStation pass; the menu help auto-builder writes one before each pad-script run. End users never see it; release discs ship without it and let the screensaver pick its own state. The full token surface and worked examples are at /docs/regtest/; /docs/scripted-input/ covers the pad-script token specifically.
PADSCRIPT.TXT
The build-time deterministic-input script at config/ps1/PADSCRIPT.TXT, embedded into the EXE by scripts/build-ps1.sh. The runtime only executes it when BOOTMODE.TXT carries the pad-script or pad-script-log token, so the file is dormant for normal release builds. Four commands — wait, tap/press, hold, shot/screenshot/mark — drive a button vocabulary that covers the full pad (D-pad, START / SELECT, the four face buttons, L1R2; combine masks with + or ,). Durations are frames unless suffixed with s (60 Hz). Used by the pause-menu screenshot harness and pad-driven regtest routes; empty for everything else. Full grammar at /docs/scripted-input/.
TTY
The PS1's serial debug output channel — historically a hardware UART, in this project a printf()-backed log line surface that DuckStation exposes to host stdout / a per-run tty.log file. The runtime's structured diagnostic records all flow through TTY: JCPERF / JCPERF2 at scene-end, JCSPI / JCPAD for controller-input diagnostics, JCPADSHOT for screenshot markers, plus ad-hoc printf() debug. The regtest harness + build farm consume those records by grepping tty.log with no parser — flat key=value lines on purpose. TTY was effectively disabled for most of 2026-Q1 because per-frame printf was destabilizing scene timing (the telemetry overlay was the only diagnostic surface during that window); restored 2026-04-25 with a gated, bounded-output printf path. Per-frame use is still discouraged in timing-bearing code.
JCPADSHOT
The screenshot-marker TTY line emitted by PADSCRIPT.TXT's shot / screenshot / mark commands. Format: JCPADSHOT label=<name> frame=<n> tick=<n>. The headless harness greps these out of tty.log and copies the first captured PNG at or after each marker frame into the published asset path; that's how the auto-built menu help guide knows which captured frame matches which sub-screen. Disambiguation: JCPADSHOT is a marker, not a diagnostic dump — distinct from JCPAD (the pad-layer cooked-event diagnostic) despite the prefix collision.
Telemetry overlay
The five-panel on-screen debug overlay drawn down the left edge of the frame, gated by grPs1TelemetryEnabled in src/graphics_ps1.c with row writes scattered through the ADS interpreter (src/ads.c) and helpers like grPs1SetLastBmpTelemetry. Built when text I/O was unsafe — for most of 2026-Q1 the project ran with TTY printf disabled (per-frame text logging was breaking timing and growing logs unboundedly), so the overlay was the diagnostic surface. The five panels: Drop/Load Diagnostics (top-left, y=2), Pilot Pack Diagnostics (upper-left, y=30), ADS Runtime Diagnostics (mid-left, y=90), Memory/Resource Pressure (mid-left, y=174), Story Transition Diagnostics (bottom-left, y=222). Off by default in release builds; the headless regtest harness runs scripts/decode-ps1-bars.py against captured frames to extract per-frame state from the overlay into telemetry.json — the visual channel doubles as a structured-data channel. Even after TTY printf was re-stabilised on 2026-04-25, the overlay remained the right tool for per-frame state because it can't perturb timing the way text I/O does. Permanent reference at docs/PS1_LEFT_DEBUG_PANEL.md.

Graphics

CLUT-indexed sprite
The PS1 GPU's native texture format: 4-bit (16-color) or 8-bit (256-color) indices into a Color Lookup Table. The replay engine ships sprites in 4-bit indexed form (indexedPixels) with a per-pack palette LUT. The 4-pixel-unrolled inner blit loop and opaque-sprite fast path live in graphics_ps1.c.
RGB555
The PS1 GPU's 16-bit direct-color pixel format: 5 bits each for red / green / blue plus 1 bit for semi-transparency (sometimes called STP). The PS1 actually packs the channels as STP|B5|G5|R5 in memory (so technically BGR-1555 — blue in the low bits, red in the high bits, STP in the topmost), but the project's prose uses the more common RGB555 name for the format itself; the byte order matters in writes to VRAM via LoadImage. Used for true-color textures, full-screen backgrounds, and the framebuffer itself. Scene Explorer thumbnails are 320×240 RGB555 .SCR files loaded straight from the disc; FG2 packs ship sprites in 4-bit CLUT-indexed form instead because that's ~4× tighter in VRAM. The format is the native cell of every other graphics term in this section.
Backdrop
The persistent island + ocean composite that lives behind every scene. Two layers: the static island bitmap (palms, beach, sky, sometimes holiday emblem) plus the live ocean band that animates regardless of foreground state. The runtime never redraws the full backdrop from scratch except on full scene swaps or pause-menu Clear; instead, dirty-rect bookkeeping restores just the spans Johnny + props dirtied last frame. The backdrop-key guard (v0.7.2-ps1) prevents story-loop walks from running against a stale backdrop after a tide / night / holiday / raft-stage state change in the next scene's load.
SPRT (and the GPU primitive family)
A fixed-shape PS1 GPU primitive struct from PSn00bSDK's psxgpu.h: a rectangular textured sprite (position, size, UV, CLUT, color tint). The runtime allocates one per textured rect it wants drawn, fills the fields, and links it into the ordering table via addPrim — the GPU consumes the table on the next DrawOTag. Used heavily on this project for caption glyph rendering (one SPRT per glyph against a shared font atlas), pause-menu chrome, and any rectangular sprite the foreground replay can't ship as a baked diff. Part of a family that also includes POLY_F4 / POLY_FT4 (flat-shaded or textured quads), TILE (solid-color rect, no texture lookup), and LINE_F2 (line primitives); SPRT is the workhorse because most of what this port draws is rectangular and textured.
Dirty-rect bookkeeping
Tracking which screen rectangles changed this frame so only those get redrawn from the background, instead of redrawing the whole framebuffer. The PS1 replay engine's dirty-rect path reduces per-frame data movement by 80–95%. Without it, the SPU and the GPU compete for memory bandwidth and audio glitches.
FntFlush
PSn00bSDK's BIOS-text print-and-flush routine. Empirically broken in this scene-runtime context — does not honor draw ordering reliably and corrupts captioned frames. The project's caption renderer therefore stamps glyphs through the regular sprite path, never through FntFlush. "Do not regress to FntFlush" is a load-bearing rule.
Ordering table (OT)
The PS1 GPU's display list. Primitives are queued into the OT in z-order; the GPU processes the table front-to-back per frame. The replay engine assembles its OT inline as it iterates the FG2 pack's frame diffs.
VRAM
1 MB of dedicated GPU memory on the PS1, holding both the framebuffer and all sprite textures + CLUTs. Doubly tight: 24-bit framebuffer at 320×240 alone is ~225 KB, and every loaded sprite atlas + palette eats from the rest. Why packs ship pre-mangled sprites and why the runtime preloads palettes once at boot.
Multi-view stitch
For wide scenes that exceed one screen of action (e.g., LILLIPUTIAN arrival sweeping in from far-left), the host capture takes three sightlines — normal / far-left / far-right — and stitches their foreground deltas into one merged pack. MISCGAG 1, MISCGAG 2, STAND 1 all needed this before they replayed cleanly.
No-stitch fast path
The host capture's shortcut for scenes that don't need multi-view stitch — typically simple STAND idles and short ACTIVITY beats where Johnny stays in one place. Skips the far-left / far-right sightline captures, exports a single-position foreground-only overlay against the base background, and produces a smaller pack faster. Surfaced one notable bug at STAND 5 ("no-stitch fast path fades Johnny's legs" — pure base-diff treated frame-0 static pixels as background and dropped them); the fix was to keep the single-position foreground overlay while still skipping the wide-sightline captures. Lineage: STAND 5 / 6 / 7 / 8 all share this fast path; STAND 8 additionally added the per-frame FG2 wave tick that fixed the static-ocean bug. Three other STAND scenes (STAND 10, 11, 12) hit the no-stitch path and produced 92-byte effectively-empty packs — the previously-committed packs played cleanly on PS1 so they were signed off as-is, called out by name. Used by FG2 exporter scripts/export-scene-foreground-pilot.sh.
Static-ocean bug (STAND wave tick)
STAND 8 surfaced this in v0.7.x: a STAND scene exported through the no-stitch fast path would hold a frozen ocean because the foreground-only pack carried no per-frame wave updates, and the runtime's wave layer normally only retouches when the foreground asks. The fix was to add a synthetic per-frame wave tick to the FG2 stream so the runtime keeps animating the ocean even when nothing else moves. Inherited by every later STAND scene that takes the fast path.
Residual cleanup contract
The rule that the foreground replay must restore every dirty-rect span back to the background bitmap before next frame, with no left-over pixels. When a scene's pack misses a few pixels, the project ships a small patch-<scene>-foreground.py that keys foreground-only contamination against the full-host composite.

Audio

VAG
Sony's compressed audio format on the PS1, used by the SPU. Roughly 4-bit ADPCM with predictor coefficients per 16-sample block. All 23 SFX preload into SPU RAM at boot from .VAG files on the disc.
ADPCM
Adaptive Differential Pulse Code Modulation. The compression scheme inside VAG: each sample is stored as a 4-bit delta predicted from the previous samples. The encoder lives in scripts/wav2vag.py and was extensively debugged during the v0.3.6-ps1 milestone (commit 355227fa).
SPU
The PS1's Sound Processing Unit: 24 hardware voices, 512 KB of dedicated SPU RAM, hardware sample-rate conversion and looping. Per-voice volumes, pitch, ADSR envelopes, and reverb send all controlled by writing memory-mapped registers.
PLAY_SAMPLE
The TTM opcode (0xC051) that triggers a sound effect. Captured into the FG2 pack as a per-frame sound-event table; foreground_pilot.c fires them with a 3-frame key-on delay so SPU register writes land before the PS1 expects audio.
Voice slot
One of the SPU's 24 hardware-managed voices. The runtime uses 8 voices in round-robin for scene SFX, plus one dedicated voice for the optional ocean-ambience loop (toggle: Pause → Accessibility → Ocean).
Ocean ambience
Optional looping background track that shipped in v0.6.0-ps1. Lives on a dedicated voice slot separate from the 8-voice scene-SFX round-robin so ducking the gag SFX never affects the ambient loop. The on-disc OCEAN.VAG is a 20-second seamless loop, downsampled to 11.025 kHz mono and encoded to Sony VAG ADPCM by scripts/wav2vag.py; the source recording is BigSoundBank sound 0266 ("Sea: Waves"), released CC0 (full attribution at /credits/). The SPU's hardware sample-loop reads as unbroken because the seam is hidden by an equal-power crossfade with the recording's natural continuation. Toggle path: Pause → Accessibility → Ocean; the choice persists to the memcard save block alongside the rest of the user-preference state.

Hardware & toolchain

MIPS
The 32-bit RISC instruction-set architecture the PS1's CPU implements — a Sony-customized R3000A clocked at 33.8688 MHz. The acronym originally stood for Microprocessor without Interlocked Pipeline Stages; in practice the name covers the whole ISA family the chip belongs to. No FPU, no SIMD, no branch predictor. The toolchain target name is mipsel-none-elf-gcc 12.3.0 shipped with PSn00bSDK 0.24 — the little-endian mipsel- prefix is correct: the PS1 runs MIPS little-endian, unlike the big-endian MIPS in many embedded targets. The single-core, single-thread, no-cache-coherency envelope is what most of the perf work on /perf/ is constrained by.
PSn00bSDK
Lameguy64's open-source PSX SDK, version 0.24 here. Replaces Sony's proprietary Psy-Q with permissively-licensed equivalents. Build pipeline: cmake + mips-mipsel-none-elf-gcc via the SDK's CMake module.
DuckStation
Connor McLaughlin et al.'s PS1 emulator. Every commit is regtested against headless DuckStation; visual + audible signoff happens against the GUI build. The project's runtime works around several DuckStation HLE quirks (SPU master-volume isn't honored, the BIOS pad path is unusable, etc.).
VBlank
The GPU's vertical blanking interrupt — fires once per refresh (NTSC: 60 Hz, PAL: 50 Hz; this project targets NTSC). The runtime's atomic time unit: every per-scene timing measurement on /perf/ is counted in vblanks (target_vb, loop_vb, blocking_vb, prefetch_overrun_vb), pack frame durations are stored as vblank counts, and the foreground-pilot cadence is a vblank-aligned scheduler. Replaces the host build's wall-clock timing — the PS1 has no reliable monotonic clock outside the GPU IRQ surface, so VBlank IS the clock. Cross-references the perf-side entries: target_vb / loop_vb, blocking_vb, prefetch_hits.
mkpsxiso
The CD-image packager. Reads config/ps1/cd_layout.xml + the compiled PS-EXE + the asset bundle and produces jcreborn.bin / jcreborn.cue.
SPI driver
The controller-poll driver in src/spi.c, derived from spicyjpeg's MPL-licensed pad-poll example. Direct SIO0 + Timer-2 IRQ at 250 Hz; the BIOS pad path (InitPAD/StartPAD) is unusable in PSn00bSDK 0.24 + DuckStation.
tx_len
The number of TX bytes the SPI poll sends before reading button bytes back. Must be 5, not 4 — DuckStation only delivers the actual button state when the full five-byte sequence comes from the TX buffer. The two-day lab essay on this is at /lab/two-day-spi-bug/.
JCSPI / JCPAD
The two TTY-record companions to JCPERF/JCPERF2. JCSPI dumps the diagnostic state of the SPI driver (poll counters, IRQ rate, last button bytes) — useful when chasing controller-poll bugs like the two-day tx_len bug. JCPAD dumps the pad layer above SPI (cooked button events, hold tracking, repeat suppression). Both fire from the gated printf() path restored in 2026-04-25, are off by default, and are ignored by the headless regtest + build farm consumers (which only parse JCPERF). Distinct from JCPADSHOT, the screenshot-marker line emitted by the scripted-input harness's shot command.
TonyHax
The softmod path used to boot homebrew on retail PS1 hardware. The project is smoke-tested on a SCPH-7501 via TonyHax. Treat any boot success as a small miracle.
Memcard
The PS1 Memory Card — 128 KB of removable battery-backed flash, addressed via SIO0 like the controller. The project persists pause-menu user choices (Scene Set pool, holiday-overlay mode, ocean ambience toggle, accessibility flags, time/date, RNG seed) into a v6-schema save block. PSn00bSDK exposes the read/write surface via McRead* / McWrite*; this project's wrapper lives in src/memcard.c + src/memcard.h. DuckStation emulates a virtual memcard per save slot; on real hardware any standard 1-block .MCR file works. Saved blocks survive across releases as long as the schema version doesn't bump.

Build & release

PS-EXE
PlayStation executable format. A small 2 KB header (load address, entry point, code size, stack base) followed by the binary code/data, padded to 2 KiB CD-ROM sectors. The project's jcreborn.exe is 208 KiB (104 sectors) at v0.8.12-ps1, produced by mips-mipsel-none-elf-gcc through the PSn00bSDK linker and bundled onto the disc by mkpsxiso per config/ps1/cd_layout.xml. The BIOS loads it from disc into main RAM at boot and jumps to the entry point.
jcreborn.bin / jcreborn.cue
The shipped CD image, a .bin binary track plus a .cue cuesheet that DuckStation (and real hardware) opens. Both files belong in the same directory. End users never need original Sierra files — the pre-baked FG2 packs are derived data, not Sierra source.
RESOURCE.MAP, RESOURCE.001
The original Sierra data files from a legal Johnny Castaway 1.0 install. Required only by the host build during development. Not shipped with this project. See /legal/ for the licensing line.
Release bar
Human visual + audible signoff against the host capture across every applicable variant. The release bar gates the version-tag commits, not the regtest harness — regtest only proves "still builds and boots."
Milestone
Tagged release line cut every ~10 newly validated scenes (v0.6.x, v0.7.x). Smaller stability releases happen between milestones for runtime fixes that don't change the validated set.

Performance

Battle card (headless-perf)
The headless-DuckStation timing matrix. One row per scene/tide variant; the live aggregate is average public over-target % and average public target-speed % across timing-bearing rows. Public reporting caps faster-than-target rows at native speed so the website never claims playback faster than intended; the raw signed values remain in the CSV for optimization analysis. The live page is at /perf/, separate from the visual signoff at /scenes/ on purpose — different bars, different cadences, different failure modes. The current matrix mean is on the home-page status pill.
target_vb / loop_vb
target_vb is the vblanks a scene should take at native rate (computed from the host capture's frame count). loop_vb is what the run actually took. Their raw ratio is the row's internal target speed %; their raw difference is over target %. Anything above zero on over-target means the row missed. The public /perf/ display caps faster-than-target rows at 100.0% speed and 0.0% over target.
target_speed
The user-facing perf column: min(100%, target_vb / loop_vb × 100%). 100% means the run hit or beat native cadence; below means it slipped. The Target Speed column on /perf/ color-codes ≥99% green, ≥95% yellow, ≥90% orange, <90% red. The matrix-wide public mean across timing-bearing rows is the home page status pill at 99.7%. See target_vb / loop_vb for the underlying raw values.
Scene-end
The runtime event marking one full FG2 pack loop completion. Triggers a JCPERF/JCPERF2 TTY dump (vblank counts, CD/compose/upload/wait counters, blocking_vb, alloc_fail) and finalizes the row's perf-matrix entry; the regtest harness uses it as the natural pivot point for state-hash capture. Long scenes can need a higher frame budget before this event appears; SUZY1 currently uses a 12000-frame matrix budget rather than the default 7200.
JCPERF / JCPERF2
The structured TTY printf records the runtime emits at scene-end. JCPERF is the original line: vblank totals, target_vb/loop_vb, over_target, blocking_vb, alloc_fail. JCPERF2 is the v0.8.0-era extension: stream-window, prefetch-hits, read-group, plus the clean-rect pressure split (wave-band, upper, lower) added in v0.8.1. Both are flat key=value sequences on a single line so the headless DuckStation runner can grep them out of tty.log with no parser; regtest + the build farm consume them to fill the /perf/ matrix and gate promotion on no-worse aggregates.
JCPAUSE
The TTY printf prefix for the pause-menu one-shot snapshot. Emitted when the user opens the pause menu — a single line capturing the runtime state at that moment (current scene, frame index, tide/night/holiday flags, freeplay state, audio voice slots). Useful for reproducing a bug report from a screenshot: the snapshot in tty.log pins exactly which configuration was on screen when the menu was opened. Like the other JC-prefixed records, gated by the bounded-output printf path restored 2026-04-25 and ignored by the headless regtest consumers (only JCPERF drives the perf matrix).
JCBOOT
The TTY printf prefix the runtime uses for boot-related log lines. As of v0.8.7-ps1 the runtime emits a single early JCBOOT line at boot-time, naming the boot source, explicit scene, seed, loop mode, tide / night / holiday / raft state, island position, and normalized boot text — before title screens, resource loads, or sound side effects run. Pair with the scene-end JCPERF / JCPERF2 lines: JCBOOT says what was asked to play; JCPERF2 says what actually played. The headless perf iterator now derives the expected scene from each fgpilot <slug> boot string and rejects any run where JCBOOT's scene disagrees with JCPERF2's — catching the "measured the wrong scene" silent-pass failure mode the deterministic-boot release closed.
over_target
The percentage by which loop_vb exceeded target_vb. The Over Target column on /perf/. Lower is better; 0% means exact target cadence; raw negative CSV values mean the run finished under the budget. Public reporting caps those faster rows at 0.0% so fast scenes do not offset slow-scene debt. The matrix-wide public aggregate at v0.8.12-ps1 is +0.3% across the 126 timing-bearing rows.
blocking_vb
The number of vblanks where the renderer was blocked waiting for the CD prefetcher to land the next pack chunk. The Blocking column on /perf/. 0 is ideal; non-zero values are usually traceable to a too-small stream-window or a wide-action scene whose pack chunk crossed a read group boundary.
prefetch_hits
The Prefetch column on /perf/ — vblanks where the CD prefetcher hit a buffer overrun and had to wait. Distinct from blocking_vb: prefetch overrun means data was ready early enough but the buffer was already full; blocking means data was late. Both move with stream-window size in opposite directions.
Clean-rect (memory pressure)
The runtime's per-scene allocation for "the bytes needed to restore the static background under the foreground." Wide-action scenes need a wide clean-rect; the long-soak BUILDING4 regression resolved in v0.8.0 was a clean-rect allocation failure under post-walk memory pressure, and v0.8.1 extends the pressure estimator to include ocean wave-band expansion plus upper/lower split rects before allocation. The "clean-memory-relief drop-prefetch" experiment in the retrospective is the related performance unlock — letting the prefetch window drop to free clean-rect bytes when the scene needs them.
Wave-band
The horizontal strip of ocean across the framebuffer that the runtime's per-frame wave animation paints into. Distinct from the static background bitmap (handled by the upper/lower split-rect clean-rect halves) because the wave layer changes every frame, not just when the foreground does — so the bytes needed to restore it have to be budgeted separately. The v0.8.1-ps1 stability fix made this explicit: the per-scene clean-rect pressure estimator now splits its allocation budget into wave-band + upper + lower components before allocation, so a wide-action scene whose wave layer competes with a foreground for the same clean-rect bytes gets caught at plan time instead of crashing at commit time. Surfaced on the /perf/ battle card in the JCPERF2 per-scene records that the post-v0.8.1 matrix consumes; full war story at /lab/v081-mary4-freeze/.
FGP3 pack format
Denser successor to the original FG2 pack format. Same per-frame foreground deltas, but with a smaller header and a residual cleanup table that replaces the runtime's "did I miss a pixel" rebuild. Most scenes' high-tide and low-tide packs are FGP3 as of v0.8.0-ps1; the win is per-frame upload bytes, the biggest bottleneck after raw playback on a 2× CD.
Prefetch window
The streaming budget the runtime uses to read pack data ahead of the playback frame. Originally global (one number across all scenes); the scene-local relief pass made it a per-scene setting backed by measurement. Smaller per-scene buffers, fewer evictions when the next scene is loading.
Drop-prefetch (clean-memory relief)
The per-scene opt-in that lets the runtime drop the prefetch window down to zero for a scene whose clean-rect allocation would otherwise fail under post-walk memory pressure. Surfaced as the single biggest perf unlock during the post-validation optimization loop: trade some streaming headroom (which a wide-action scene wasn't fully using anyway) for the clean-rect bytes the scene actually needs to render. Maintained as an exception list per scene rather than a global on/off, because most scenes don't need it and lowering prefetch globally regresses scenes that were using their streaming budget. Canonical opt-in: BUILDING 4 (lilliputian Gulliver-tie-down — wide clean-rect demand, modest streaming demand). Full retrospective at /lab/from-87-to-99-5/; the v0.8.1-ps1 stability fix later generalized the pressure estimator side of this trade for every random-position scene (see /lab/v081-mary4-freeze/).
Stream-window (stage-1)
The CD stream's first-stage read buffer. Default was 32 KB; the per-scene retune (some up, some down) reduced blocking vblanks across the matrix by about a third. The number that mattered wasn't the size — it was that the size had been one number before, and was a per-scene measurement after.
Read group (CD layout)
How cd_layout.xml bundles related scene/tide assets so the streaming code can prefetch them as a unit. Naive bundling (every scene's high+low together) backfires — the screensaver loop picks tides independently, so bundling slowed the first-tide read. Scoped read groups (e.g., ACTIVITY 9's low-tide variant on its own) are the correct shape.
Padded residual packs
FGP3 residual cleanup tables padded to cover a sprite footprint that exceeds the legacy 640px scene clip. Used for ACTIVITY 9's wide-boat scene; replaces the per-scene patch-<scene>-foreground.py postprocess that earlier filled the missing pixels at runtime.
Canary scene
FISHING 1's high-tide run. Gets re-measured on every release. Its loop_vb vs target_vb is the load-bearing reference frame for "did this matrix-wide change just regress the easiest path." If the canary moves the wrong way, the change doesn't promote.
Experiment log
The decision-record table at docs/ps1/performance-experiment-log.md. Every accepted optimization gets a row; every rejected one too — -O2, naive read-group probes, anything that ran for two days and produced the same number. The rejected rows pay for themselves the first time someone is about to re-try a no-op.
Promotion rule
An optimization promotes when (a) the canary doesn't regress, (b) every visual signoff still holds, and (c) the matrix mean improves. All three must hold; mixing them is how regressions ship.
Soak test
A long-run randomized DuckStation pass — boot, let the screensaver loop pick scenes at random for hours, watch for freezes, hangs, drift, or memory pressure that the per-scene matrix runs miss. Not part of the per-commit regtest gate; reserved for release candidates and after structural changes (walk pipeline, prefetch policy, clean-rect estimator). The v0.8.1-ps1 release shipped specifically because a soak surfaced a MARY 4 random-load freeze that the matrix-bounded headless runs never exercised.

Voice

drawCredits
The four-line in-game credits text in src/pause_menu.c. Hand-written, load-bearing, the irreducible voice anchor for everything else on this domain. "A labor of love by Hunter Davis. Hunter does not own or have a license to the Johnny Castaway character. The original creator generously allows fan ports. If you paid for this, you were cheated. Open source and free." Any prose on the site has to sit comfortably next to it. Long version: /about/voice/.
The 63-scene grind
The project's name for the work between "first scene validated" and "every scene validated." Same loop, repeated 63 times: capture, pack, route, replay, sign off. Retrospective at /lab/the-63-scene-grind/.
Dead end (named out loud)
A path that did not work, kept in the public record because dead ends are content. The devlog is verbatim — superseded plans, partial successes, week-long timing bugs preserved unedited. The blog convention is to name them with a short lampshade ("Bummer." "Lightbulb moment!") rather than rewrite history into a clean narrative.
Caption-mismap
A scene whose prose description on the site drifted from what the FG2 pack actually plays on PS1 — the captured frame and the surrounding caption / title / alt-text disagree. The FISHING 1 bar guards pixel drift, not caption drift, so a scene can be fully visually signed off while its sentence-long human-readable label still names the wrong gag. Surfaced systematically by the v0.8.4-ps1 chapter-select grind, which walked all 63 packs on hardware and reconciled scene-page metadata against what the discs play. Canonical examples: FISHING 2 ("He catches a boot" → actually a Titanic-stenciled life preserver — the boot line fits MARY 2); VISITOR 5 (audit "future blanking" → actually the unambiguous coconut-plane-hit beat); WALKSTUF 3 (audit MED label → exercise-jog laps); JOHNNY 3 / 4 (audit had them swapped — JOHNNY 3 writes the letter to Suzy, JOHNNY 4 is where the SOS returns). The post-validation runtime corrections section of /docs/captions/ lists the named mismaps still active at the runtime layer; the website prose is reconciled but captionSceneMap[] in src/ps1_captions.c still routes a few HIGH-confidence audit lines to the wrong scene tag and is open work.

See also

  • /scenes/ — the visual signoff ledger; the FISHING 1 bar in practice.
  • /perf/ — the headless-perf battle card; the column headers (over_target, blocking_vb, prefetch_hits, etc.) all have entries above.
  • /docs/ — the reference manuals these definitions support.
  • /about/method/ — the methodology essay; the host-capture / FG2 pack / PS1 replay pipeline and the gotchas hit on the way, written in narrative form using many of the terms above.
  • /lab/ — the magazine-length retrospectives where many of these terms got their first in-context introduction.
  • /about/voice/ — the editorial standard the entries above are written to. The voice that lets a definition stay terse without being curt.