Catalogue of the repository's developer, CI, and packaging scripts. Kept current
the same way docs/README.md is: when you add, move, or remove
a script under scripts/, update its row here in the same commit.
The Invoked by column tells you whether a script is load-bearing or a one-off:
CI / Makefile / pre-commit scripts are wired into the project and must keep
working; manual scripts are run by hand (usually documented in docs/); spike
scripts are one-shot investigations kept as reproducible evidence for a plan doc,
not maintained tooling.
| Script | What it does | Invoked by |
|---|
| ci/clang-format-select.sh | Single source of truth for the pinned clang-format major version (CLANG_FORMAT_MAJOR). Sourced, not executed. | the three format scripts + pre-commit |
| ci/check-format.sh | Verify tracked C/C++ files already match the clang-format policy; non-zero on drift. | CI (format.yml), make format-check |
| ci/check-docs-links.sh | Verify doc references resolve: markdown links and #anchors via lychee, plus docs/<name>.md paths named by bare path in source comments, tests and CMake (invisible to a link checker). --external checks URLs. lychee's settings live in lychee.toml, shared with local runs. | CI (docs-links.yml), make docs-links |
| ci/check-docs-symbols.py | Verify a doc's claim about where code lives: for `Foo()` in [FILE] the symbol must be defined there, and the report names the file it is actually in. Paths resolving is not the same as the prose being right. | CI (docs-links.yml), make docs-symbols |
| ci/apply-format.sh | Apply the clang-format policy to tracked C/C++ files (respects .clang-format-ignore). | manual, pre-commit fix step |
| ci/filter-format-files.py | Filter a NUL-delimited git file list through .clang-format-ignore (one shared exclusion list). | the format shell scripts |
| ci/run-clang-tidy.sh | Run clang-tidy for memory-safety / UB checks over the project's own sources (needs compile_commands.json). | manual (see .clang-tidy) |
| Script | What it does | Invoked by |
|---|
| dev/build-and-run.sh | Build and run lba2cc from any working directory; resolves repo root and game data. | make run |
| dev/repo_root.sh | Print the absolute repository root (directory with the top-level CMakeLists.txt). | Makefile |
| dev/check-tooling.sh | Probe the external tools the repo expects, tier by tier; non-zero only when the clone cannot build. Reads every version floor from the file that pins it. | make check-tooling, TOOLING.md |
| dev/build-android.sh | Build the engine for Android (arm64-v8a default, armeabi-v7a via --abi). | manual (ANDROID.md) |
| dev/build-sdl3-android.sh | Cross-build SDL3 for Android and install it to a known prefix (prerequisite for build-android.sh). | manual (ANDROID.md) |
| dev/check-16k-align.sh | Verify an Android APK is safe on 16 KB memory-page devices (segment alignment + uncompressed .so). | CI (android), ANDROID.md |
Clients and sweeps for the --listen command socket, which needs a
-DLBA2_CONTROL_SERVER=ON build; see
CONTROL.md. The sweeps import
lba2ctl and are restart-tolerant where they need to be, because walking many cubes in
one process faults and a sweep that stops at the first fault covers almost nothing.
| Script | What it does | Invoked by |
|---|
| dev/lba2ctl.py | Speak the line protocol: a REPL for looking around, a Control class for scripting a probe loop. Its docstring carries the traps that cost the most to rediscover. | manual, and imported by the sweeps below |
| dev/probe_bench.py | Measure one probe over the socket against the process-per-probe it replaces. | manual |
| dev/probe_zones.py | Parse zonelist into structured zones, including which cube gates wait on a door collision. Imported by the two sweeps below. | manual |
| dev/probe_gate_scan.py | Sweep every cube for transition gates that are enabled, separating ones switched off from ones waiting on a door collision: zonelist reports the two identically and they want opposite fixes. | manual |
| dev/probe_cube_overlap.py | Sweep every cube for camera zones overlapping in all three axes, where list order alone decides which shot wins. | manual |
| dev/probe_input_matrix.py | A/B whether injected input moves the hero, across several saves. | manual |
Local wrappers that build a release binary and then delegate to the matching
packaging/ bundler, so the local artifact layout can't drift from CI's.
| Script | What it does | Invoked by |
|---|
| dev/build-linux-tarball.sh | Dry-run the Linux static-binary tarball: build, then call bundle-linux-tarball.sh. | manual |
| dev/build-macos-release.sh | Dry-run the macOS DMG: build (host arch by default), then call bundle-macos.sh. | manual |
| dev/build-windows-release.sh | Dry-run the Windows ZIP: build (MSYS2 native or Linux cross), then call bundle-windows.sh. | manual |
| dev/verify-release.sh | Post-release smoke test: download the published Linux artifacts, run each in a clean container, and check the version, AppImage self-update channel and AppStream metainfo they carry. | manual (RELEASING.md) |
One bundler per platform; the CI release workflows are glue around them. The
*-readme.txt.in files are the user-facing README templates the bundlers expand
into each artifact.
| Script | What it does | Invoked by |
|---|
| dev/regen_projrec_baselines.sh | Regenerate projrec baseline hashes for the save corpus and attract-mode demo (tagged by render width). | manual (CONTROL.md) |
| dev/run-savegame-corpus.sh | Build and run the savegame corpus harness from any working directory. | make (savegame corpus target) |
| save_probe.py | Offline probe of .lba save headers, LZSS bodies, fixed-offset fields, and a 32-vs-64 ABI forward-simulator. | run-savegame-corpus.sh, SAVEGAME.md |
| save_probe_lz_selftest.py | Golden ExpandLZ vectors mirroring tests/SYSTEM/test_lz.cpp. | make save-probe-lz-selftest |
| dev/dist_check.sh | Sweep every retail distribution: one row per install, five assertions, non-zero exit if any fails. Needs real installs, so local only. | manual (TESTING.md) |
| dev/png_hash.py | Plain pixel hash of a PNG capture, which is enough because --fixed-dt makes UI captures exactly reproducible. | dist_check.sh, the control-harness UI tests |
Decoders and inspectors for the Adeline on-disk formats. Mostly one-off tools kept
for reproducibility; cited from the format and effects docs.
Read-only investigations backing LBA1_PORT_PLAN.md; each
confirms one axis of hosting LBA1 content on this engine.
| Script | What it does | Invoked by |
|---|
| dev/lba1_body_probe.py | Transcode an LBA1 body to the lba2cc body format. | spike (LBA1_PORT_PLAN §6) |
| dev/lba1_body_render.py | Render a decoded LBA1 body to PNG with a stdlib software rasteriser. | spike (LBA1_PORT_PLAN §6) |
| dev/lba1_script_remap.py | Remap LBA1 Life-script opcodes onto the LBA2 VM; flag-width divergence report. | spike (LBA1_PORT_PLAN §6) |
| dev/lba1_bkg_repack.py | Re-index LBA1's three background HQRs into LBA2's single merged container. | spike (LBA1_PORT_PLAN §6.5) |
| dev/lba1_voc_probe.py | Confirm LBA1 VOC audio plays through lba2cc's existing sample path. | spike (LBA1_PORT_PLAN §6.6) |
| Script | What it does | Invoked by |
|---|
| git-hooks/pre-commit | Opt-in clang-format check on staged C/C++ files. Enable with git config core.hooksPath scripts/git-hooks. | git (opt-in) |
The test and packaging drivers that these scripts feed into, or that stand
alongside them, live next to the code they exercise: