Repository navigation
Debugging Tips
This page is the practical catalogue of runtime environment variables, build modes and tooling. For new-game bring-up patterns see Adding a New Game.
All flags are opt-in (defaults are quiet). Combine freely.
| Var | What it does |
|---|---|
PS1_HLE_TRACE=1 |
Logs every psyq_dispatch call to stderr: function name, first three argument registers (a0/a1/a2), and the return address (RA). Output volume can be high — pipe to a file and post-process with tools/trace_replay.py. |
PS1_INDIRECT_TRACE=1 |
Logs every CALL_INDIRECT / JUMP_INDIRECT dispatch with the target address. Catches dispatch tables that route to address 0 (silently dropped). |
PS1_INDIRECT_TRACE_RA=0x80123456 |
Filter PS1_INDIRECT_TRACE output to indirect dispatches whose return address matches. Useful when the global trace is too noisy. |
PS1_BIOS_DEBUG=1 |
Verbose A0/B0/C0 syscall logging. |
PS1_DRAIN_TRACE=N |
Log every N-th call to Bios::drainPendingCallbacks with the per-call delta. A high call rate with delta=0 means the game thread is spinning, not deadlocked. |
Typical first-day-of-bring-up combo:
PS1_HLE_TRACE=1 PS1_HLE_PERMISSIVE=1 SDL_AUDIODRIVER=dummy \
./build/ps1Runtime/ps1Runtime --config configs/<game>.toml \
2> /tmp/<game>_trace.log
tools/trace_replay.py /tmp/<game>_trace.log --tail 20| Var | What it does |
|---|---|
PS1_HLE_PERMISSIVE=1 |
When a PsyQ function is identified by hash but has no native HLE implementation registered, log [PSYQ] WARN: function 'X' missing HLE — NOP once per name and continue, instead of abort(). |
These are temporary bypasses that let the game proceed past a known blocker. None of them are correct — they buy time while a permanent fix lands.
| Var | Title | Effect | Permanent fix |
|---|---|---|---|
PS1_SKIP_31BF8=1 |
Crash Bandicoot 1 | NOPs func_80031BF8 (display-mode setup) to avoid the unpopulated hash-table walk at 0x8005C530. |
Roadmap Phase 2 — port the NS chunk subsystem. |
| Var | What it does |
|---|---|
SDL_AUDIODRIVER=dummy |
Skip real audio backend (no PulseAudio / ALSA / CoreAudio dependency). Essential for CI and MCP runs. |
The full pipeline builds and 557/557 tests pass without any game files. This is the CI baseline.
cmake -B build -DCMAKE_BUILD_TYPE=Release \
-DPS1RECOMP_USE_STUB=ON \
-DPS1RECOMP_BUILD_TESTS=ON
cmake --build build -j$(nproc)
ctest --test-dir build --output-on-failurecmake -B build-asan -DPS1RECOMP_ASAN=ON -DCMAKE_BUILD_TYPE=Debug
cmake --build build-asan -j$(nproc)
./build-asan/ps1Runtime/ps1Runtime --config configs/<game>.tomlRuns are slower but catch:
- Use-after-free across shutdown destructors (the Crash UAF in
Bios::~Bios()was caught this way). - Signed-integer-overflow UB in emitted
ADD/ADDU/SUB/SUBU/ADDI/ADDIU(now fixed by emitting throughuint32_t). - Misaligned 4-byte loads (e.g.
iso9660.cppreadinguint32_tfrom a byte buffer that is not 4-aligned — open).
cmake -B build -DPS1RECOMP_BUILD_INTERFACE=ON
cmake --build build -j$(nproc)
./build/ps1Interface/ps1InterfaceThe studio exposes an ImGui explorer of functions, an inspector for changing the per-function recompilation strategy, and a config-editor pane.
Runs the game for N seconds and emits a JSON report with frame rate, VRAM pixel analysis, GPU command log and CD-ROM callback counts.
python3 tools/run_and_report.py --duration 15 --output /tmp/report.jsonTails or summarises a PS1_HLE_TRACE log into a per-function call count and
the last N call sites.
Pixel-diffs a captured frame against a reference VRAM PPM. Reference for Crash
is captured via PCSX-Redux — see
audit_notes/crash/HOW_TO_CAPTURE_TITLE_REF.md
in the working tree.
tools/smoke_test.py --config configs/crash.toml \
--ref audit_notes/crash/title_ref.ppmThe repository ships an MCP (Model Context Protocol) server at
tools/ps1_mcp_server.py. When run, exposes typed tools for the project:
| Tool | Purpose |
|---|---|
mcp__ps1-recomp__build |
cmake --build build |
mcp__ps1-recomp__run_game |
Runs the game and captures JSON metrics |
mcp__ps1-recomp__run_tests |
ctest |
mcp__ps1-recomp__decompile_function |
View C body of a function by address |
mcp__ps1-recomp__find_callers / find_callees
|
Call graph queries |
mcp__ps1-recomp__get_vram_image |
Capture current VRAM state |
mcp__ps1-recomp__search_functions / search_code
|
Code search |
mcp__ps1-recomp__read_log |
Read /tmp/*.log
|
Configure via .mcp.json at the repo root.
Ghidra scripts under tools/ghidra/ export function boundaries to CSV and
launch a GhidraMCP bridge for AI-assisted analysis:
tools/ghidra/start_ghidra_mcp.sh # MCP bridge on port 8080Install the ghidra_psx_ldr plugin first — it adds the PSX loader with GTE
and PsyQ awareness. See Reference-Projects-Misc for
notes on what ghidra_psx_ldr ships.
progress/*.log in the working tree contains historical trace captures for
Crash bring-up sessions:
2026-05-15_crash_indirect_trace.log2026-05-15_crash_trace_70calls.log2026-05-16_crash_asan_use_after_free.log2026-05-16_crash_first_frames_loop.log2026-05-16_crash_hash_walk_isolated.log
These are session-private (gitignored) but the patterns they document are generic and worth reading if you are doing similar diagnostic work.
ps1-recomp • Licensed under GPL v3 • Current release: v0.1.0-alpha