Skip to content

Debugging

Jason edited this page Sep 17, 2026 · 2 revisions

Debugging

Maintained docs in the repository are authoritative; this page is a summary. Last reviewed 2026-09-16.

Use a bounded, evidence-first loop. Reproduce the symptom with the smallest reproducible input, identify the earliest divergence, and fix the owning layer rather than adding a route-specific latch or forced success.

A practical loop

  1. Reproduce deterministically with the smallest supported route or synthetic test.
  2. Determine whether the first divergence is in guest state, translation, HLE/runtime, renderer, audio/media, or host integration.
  3. Inspect generated source only as an output of the generator and input manifest; never hand-edit generated translation units.
  4. Compare the production path against a source-owned synthetic fixture (fixtures/production_smoke/) or reference interpreter case.
  5. Validate output pointers, lengths, return values, and failure paths before looking at high-level symptoms.
  6. Add a focused regression test that fails before the fix and passes after it.
  7. Re-run focused gates, then aggregate verification and publication checks.

Useful diagnostics

The maintained debugging guide documents categories and profiles. Useful diagnostic switches:

$env:SR_DEBUG = "0x03"          # bitmask: 0x01 memory + 0x02 HLE
$env:SR_DISPATCH_FATAL = "1"    # fail closed on dispatch misses

SR_DEBUG categories (src/rt/debug.h): 0x01 MEM, 0x02 HLE, 0x04 SCHED, 0x08 GE, 0x10 INPUT, 0x20 FS, 0x40 VIDEO, 0x80 MISC.

Use nk_manager.ps1 runtime profiles where possible:

  • -Profile Performance: redirects stdout/stderr to null device for pure execution testing.
  • -Profile Benchmark: enables 1 Hz telemetry and writes logs/perf.csv.
  • -GuestProfile: enables generated-PC call/block profiling.

Preflight diagnostics:

.\nk.ps1 Doctor -Scope build

Many legacy Boolean SR_ switches are enabled by presence: setting a literal "0" may still enable them, so unset/remove the variable to disable it. Keep logging bounded; SR_DEBUG=0xFF is useful for brief diagnoses but can overwhelm disk I/O.

Watchdog firings (SR_WATCHDOG_EXIT) detect a lack of newly presented frames (NO-NEW-FLIP), not necessarily a process hang. Legitimate static scenes (e.g., input modals) stop presenting; classify with WATCHDOG_DISPLAY counters and thread wait dumps.

Common problem families

  • Dispatch miss or unknown NID: Run with SR_DISPATCH_FATAL=1. Classify the missing operation and implement real behavior or fail closed. Do not return zero to fake success.
  • Black screen or stale frame: Distinguish guest framebuffer writes, display latch/VBLANK delivery, GE command processing, VRAM coherency, and host presentation.
  • Audio silence or stutter: Separate PSP API queues, logical stream position, ring-buffer wrapping, decoder output, scheduler timing, and host SDL3 device routing.
  • Crash after pointer access: Preflight complete readable/writable guest spans and checked size arithmetic before forming bulk host pointers.
  • Generated code differs: Check generator revision and title manifest, regenerate cleanly, and inspect the first differing function block.

Keep private title traces, captures, saves, and local paths out of public reports. Use Verification and Testing to interpret results.

Nakagawa Recomp

Architecture

Development

Project

Research site

Clone this wiki locally