Guidance for Claude Code working in this repository.
Virtual Jaguar libretro core — Atari Jaguar emulator on the libretro API. C, GPLv3. Upstream: http://shamusworld.gotdns.org/git/virtualjaguar.
GitFlow: branch new work off develop (the integration branch); master is release-only (tagged commits, hotfix merges, release-branch merges). PRs targeting master get auto-warned by .github/workflows/warn-pr-base.yml — retarget to develop unless the source branch is hotfix/* or release/*. Full flow in docs/release-process.md.
make -j$(getconf _NPROCESSORS_ONLN) # Build (auto-detects platform)
make -j$(getconf _NPROCESSORS_ONLN) DEBUG=1 # Debug (-O0 -g)
make clean
make platform=ios-arm64 # Cross-compile targetOutput: virtualjaguar_libretro.{dylib,so,dll}. CI: make -j4 on Ubuntu (GCC) and macOS (Clang) plus test/regression_test.sh screenshots.
The libretro buildbot uses MSVC on Windows. CI has a c89-lint job. Run bash scripts/c89-lint.sh src/YOURFILE.c before pushing.
- No mid-block declarations. All vars at top of block, before any statement. Most common violation.
//comments allowed (GNU89), but prefer/* */for new code.- No C99: no
for (int i…), no compound literals, no designated initializers, no VLAs. - Exempt (see
scripts/c89-lint.sh::skip_file):src/m68000/cpu*.candsrc/m68000/read*.c(UAE 68K),src/bios/jag*bios*.candsrc/bios/jagstub*bios.c(bin2c hex tables),src/tom/blitter_simd_{sse2,neon}.c(platform intrinsics),test/tools/test_rcheevos_e2e.c(rcheevos-dependent),test/tools/flicker_detect.c(diagnostic).
Four processors, unified memory map, big-endian. GET16/GET32/SET16/SET32 macros byte-swap on LE hosts. Address-range map is documented in src/core/vjag_memory.c (header comment); the dispatch logic lives in src/core/jaguar.c. RAM 0x000000 (2 MB), cart 0x800000, TOM regs 0xF00000, JERRY regs 0xF10000.
- 68000 (13.3 MHz,
src/m68000/) — main CPU. UAE-derived.cpuemu.cis machine-generated, ~1.8 MB — never read whole; grep first, thenReadwith offset/limit only on matched ranges. - GPU (26.6 MHz RISC,
src/tom/gpu.c) — graphics coprocessor. - DSP (
src/jerry/dsp.c) — same ISA as GPU; audio. - Object Processor (
src/tom/op.c) — sprite/bitmap rendering. - TOM (
src/tom/tom.c) — video, GPU, OP, Blitter (src/tom/blitter.c). - JERRY (
src/jerry/jerry.c) — audio DAC, DSP, timers, EEPROM.
Frame loop is event-driven (not cycle-accurate): JaguarExecuteNew() in src/core/jaguar.c runs 68K to next event, then GPU, then fires callbacks (half-line render, timers).
libretro.c (top-level) implements the API. Video XRGB8888 dynamic res (320×240 NTSC / 320×256 PAL). Audio 48 kHz 16-bit stereo. Core options in libretro_core_options.h (blitter mode, BIOS, NTSC/PAL, DSP, input).
src/core/— orchestration, memory map, events, settings, files, cheatssrc/tom/— video, GPU, OP, blitter (+ SIMD)src/jerry/— audio, DSP, DAC, EEPROM, input, wavetablesrc/cd/— Jaguar CD: BUTCH/FIFO/DSA incdrom.c, image loading (CUE/BIN, CHD, CDI) incdintf.c; BIOS auth bypass + boot stub insrc/core/jaguar.csrc/bios/— embedded BIOS / boot stubssrc/m68000/— UAE 68K (machine-generated; treat as opaque)libretro-common/— shared utility libtest/tools/— test harnesses;test/roms/private/— commercial ROMs/BIOSes (gitignored)
Makefile covers 30+ targets, auto-detected via uname or platform=. Makefile.common lists sources. Flags: -D__LIBRETRO__, -DMSB_FIRST for big-endian.
Local-only RetroAchievements validation — no RA account/API/server. test/tools/test_rcheevos_e2e.sh downloads pinned RCHEEVOS_REF and verifies rc_libretro mapping (RC_CONSOLE_ATARI_JAGUAR) matches host RAM.
Key harnesses:
test/regression_test.sh— screenshot regression vstest/baselines/via miniretro (built from source on first run;MINIRETRO_BINenv to skip the build)test/tools/test_memory_map.c— assertsSET_MEMORY_MAPS,SET_SUPPORT_ACHIEVEMENTS=true, descriptor layouttest/tools/test_blitter_compare— fast vs accurate blitter difftest/test_dsp_mac40.c— DSP 40-bit MAC accumulator (dsp_acc40.h)test/test_cd_boot.c— dlsym harness for 68K regs/RAMtest/sram_test.sh— SRAM round-trip
make benchmark runs test/tools/test_benchmark headlessly against a fixed ROM (default test/roms/yarc.j64, 600 frames) and prints FPS / ms-per-frame. Use as a same-host commit-to-commit delta — don't compare across machines. Full guide: docs/profiling.md covers Instruments / perf / flame graphs and the SIMD A/B knob.
The miniretro harness used by test/regression_test.sh doesn't expose the same composited framebuffer that RetroArch reads. Symptom: jag_240p_test_suite main menu shows ~1k non-black pixels via miniretro vs tens of thousands via RetroArch. Treat that as a headless read-path / presentation bug (OP+blitter output vs what the host reads), not a 240p timing or __muldi3 performance bug. Verify against RetroArch before treating a regression as real.
- Blitter not fully cycle-accurate (some games need fast mode).
- No bus contention modeling.
- VC register behavior not fully accurate.