Reference · vocabulary
Glossary
The specific technical terms the rest of the docs use without scaffolding. Written in the project's own voice.
~23 min read · 5809 words
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.highand onefg2.lowper 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.FG2filename. - 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 everyPLAY_SAMPLEinto 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 namedfgpilot/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 freeplayboots 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 issrc/scene_explorer_data.h(regenerated fromdocs/ps1/scene-status.md+ per-sceneindex.mdtitles); the loader isgrLoadSceneExplorerThumbnailinsrc/graphics_ps1.c. The "chapter-select" name comes from PS1-era game UX and gets used informally; "Scene Explorer" is the in-game label. Thev0.8.4-ps1grind 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 insrc/scene_freeplay.c, sharing the per-frame draw kernelsrc/walk_render.cwith 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'sFreeplay ONtoggle, or as thefgpilot freeplayBOOTMODE.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.hroute table from the original engine; the PS1-side modules aresrc/walk_pilot.c(state) andsrc/walk_render.c(per-frame draw, also reused by Freeplay direct-control walks). Shipped inv0.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 inv0.6.xturned it into a 36-VBlank animation with hour and minute hands positioned from the originalMEANWHIL.TTMscript. 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 atsrc/scene_picker.c; design notes atdocs/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 1was the first scene to clear it. - Regtest harness
- Headless DuckStation with a
scripted-inputfile (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 thepad-scripttoken specifically. - PADSCRIPT.TXT
- The build-time deterministic-input script at
config/ps1/PADSCRIPT.TXT, embedded into the EXE byscripts/build-ps1.sh. The runtime only executes it when BOOTMODE.TXT carries thepad-scriptorpad-script-logtoken, 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,L1–R2; combine masks with+or,). Durations are frames unless suffixed withs(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-runtty.logfile. 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-hocprintf()debug. The regtest harness + build farm consume those records by greppingtty.logwith no parser — flatkey=valuelines on purpose. TTY was effectively disabled for most of 2026-Q1 because per-frameprintfwas 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/markcommands. Format:JCPADSHOT label=<name> frame=<n> tick=<n>. The headless harness greps these out oftty.logand 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:JCPADSHOTis 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
grPs1TelemetryEnabledinsrc/graphics_ps1.cwith row writes scattered through the ADS interpreter (src/ads.c) and helpers likegrPs1SetLastBmpTelemetry. Built when text I/O was unsafe — for most of 2026-Q1 the project ran with TTYprintfdisabled (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 runsscripts/decode-ps1-bars.pyagainst captured frames to extract per-frame state from the overlay intotelemetry.json— the visual channel doubles as a structured-data channel. Even after TTYprintfwas 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 ingraphics_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|R5in 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 viaLoadImage. Used for true-color textures, full-screen backgrounds, and the framebuffer itself. Scene Explorer thumbnails are 320×240 RGB555.SCRfiles 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 viaaddPrim— the GPU consumes the table on the nextDrawOTag. Used heavily on this project for caption glyph rendering (oneSPRTper 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 includesPOLY_F4/POLY_FT4(flat-shaded or textured quads),TILE(solid-color rect, no texture lookup), andLINE_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 1all 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/8all share this fast path;STAND 8additionally 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 exporterscripts/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.pythat 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
.VAGfiles 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.pyand was extensively debugged during thev0.3.6-ps1milestone (commit355227fa). - 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.cfires 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-discOCEAN.VAGis a 20-second seamless loop, downsampled to 11.025 kHz mono and encoded to Sony VAG ADPCM byscripts/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.0shipped with PSn00bSDK 0.24 — the little-endianmipsel-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-gccvia 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 producesjcreborn.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.
JCSPIdumps 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.JCPADdumps the pad layer above SPI (cooked button events, hold tracking, repeat suppression). Both fire from the gatedprintf()path restored in 2026-04-25, are off by default, and are ignored by the headless regtest + build farm consumers (which only parseJCPERF). Distinct fromJCPADSHOT, the screenshot-marker line emitted by the scripted-input harness'sshotcommand. - 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 insrc/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.exeis 208 KiB (104 sectors) atv0.8.12-ps1, produced bymips-mipsel-none-elf-gccthrough the PSn00bSDK linker and bundled onto the disc by mkpsxiso perconfig/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
.binbinary track plus a.cuecuesheet 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_vbis the vblanks a scene should take at native rate (computed from the host capture's frame count).loop_vbis 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 at100.0%speed and0.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 at99.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/JCPERF2TTY 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 a12000-frame matrix budget rather than the default7200. - JCPERF / JCPERF2
- The structured TTY printf records the runtime emits at scene-end.
JCPERFis the original line: vblank totals,target_vb/loop_vb,over_target,blocking_vb,alloc_fail.JCPERF2is the v0.8.0-era extension: stream-window, prefetch-hits, read-group, plus the clean-rect pressure split (wave-band, upper, lower) added inv0.8.1. Both are flatkey=valuesequences on a single line so the headless DuckStation runner can grep them out oftty.logwith 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.logpins 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 (onlyJCPERFdrives the perf matrix). - JCBOOT
- The TTY printf prefix the runtime uses for boot-related log lines. As of
v0.8.7-ps1the runtime emits a single earlyJCBOOTline 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:JCBOOTsays what was asked to play;JCPERF2says what actually played. The headless perf iterator now derives the expected scene from eachfgpilot <slug>boot string and rejects any run whereJCBOOT's scene disagrees withJCPERF2's — catching the "measured the wrong scene" silent-pass failure mode the deterministic-boot release closed. - over_target
- The percentage by which
loop_vbexceededtarget_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 at0.0%so fast scenes do not offset slow-scene debt. The matrix-wide public aggregate atv0.8.12-ps1is+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/.
0is 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.0was a clean-rect allocation failure under post-walk memory pressure, andv0.8.1extends 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-ps1stability 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/; thev0.8.1-ps1stability 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.xmlbundles 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.pypostprocess that earlier filled the missing pixels at runtime. - Canary scene
- FISHING 1's high-tide run. Gets re-measured on every release. Its
loop_vbvstarget_vbis 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-ps1release shipped specifically because a soak surfaced aMARY 4random-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 fitsMARY 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 butcaptionSceneMap[]insrc/ps1_captions.cstill 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.