Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
cc39a66
Add Jaguar CD support: CUE/BIN disc image loading, BIOS boot, and But…
claude Apr 16, 2026
34484d4
Add CHD disc image format support via vendored libchdr
claude Apr 16, 2026
ceaf122
Fix rebase conflicts, add private test ROM directory
JoeMatt Apr 16, 2026
6a8faef
Add CD EEPROM to SRAM buffer and save states
JoeMatt Apr 16, 2026
caffca4
Fix CD boot sequencing: open disc image before JaguarInit()
JoeMatt Apr 16, 2026
30dc34f
Add external CD BIOS loading, fix boot vector setup
JoeMatt Apr 16, 2026
b8398f3
Fix CD BIOS loading: treat as cartridge at $800000, not boot ROM
JoeMatt Apr 16, 2026
b2f2ff3
Get Jaguar CD BIOS through auth and into CD Player UI
JoeMatt Apr 18, 2026
bb913ea
Add CD-debug instrumentation: post-auth poll/service dumps
JoeMatt Apr 18, 2026
aadcb0a
Add CD emulation docs and update CLAUDE.md
JoeMatt Apr 19, 2026
dc30d96
Remove vendored libchdr, add HLE CD BIOS to build
JoeMatt Apr 19, 2026
76bb7fa
Overhaul CD subsystem: CUE/BIN parser, auth bypass, boot flow
JoeMatt Apr 19, 2026
902a048
Add HLE CD BIOS and CD boot test harness
JoeMatt Apr 19, 2026
c333c66
don’t randomize ram
JoeMatt Apr 19, 2026
ddfe000
docs: add Atari Jaguar 1999 hardware reference set as Markdown
JoeMatt Apr 20, 2026
4f34b62
cd bios calling convention docs
JoeMatt Apr 20, 2026
993ed70
fix cd bios calling doc
JoeMatt Apr 20, 2026
af938b7
m680000 quirk fixes
JoeMatt Apr 20, 2026
edf7158
test scripts
JoeMatt Apr 20, 2026
c8f35cc
file jaguarLoadedRAMStart addition
JoeMatt Apr 20, 2026
dd0ae11
reset fixes
JoeMatt Apr 20, 2026
582b2b8
Add tests and test helpers
JoeMatt Apr 20, 2026
063a2c4
Route all logging through libretro log interface for UI-toggleable ve…
JoeMatt Apr 21, 2026
590a62e
HLE CD boot: multi-phase sentinel scan + pass Highlander
JoeMatt Apr 21, 2026
d0522f8
HLE CD: signal completion via DSP RAM [\$F1B4C8] = \$FFFFFFFF
JoeMatt Apr 21, 2026
31203bc
test/cd_hle_boot: dump 68K registers on stuck-PC failures
JoeMatt Apr 21, 2026
841d2d6
HLE CD_read: honour D0 bit 31 (re-seek only) + mirror data into cart …
JoeMatt Apr 21, 2026
9c953b7
HLE CD_read: stream continuation for repeated identical CD_reads
JoeMatt Apr 21, 2026
bf94d17
test: add real-BIOS CD boot smoke harness (test_cd_bios_boot)
JoeMatt Apr 21, 2026
f3b1554
fix: real-BIOS CD boot — trampoline, buffer, static reset
JoeMatt Apr 21, 2026
fe363e1
CD boot improvements, BIOS strategy refactor, and expanded test suite
JoeMatt Apr 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Core options defined in `libretro_core_options.h` control blitter mode, BIOS usa

### Jaguar CD Emulation

CD support is implemented across `src/cdrom.c` (BUTCH chip / FIFO / DSA commands), `src/cdintf.c` (disc image loading: CUE/BIN, CHD, CDI), and hooks in `src/jaguar.c` (BIOS auth bypass, boot stub injection).
CD support is implemented across `src/cdrom.c` (BUTCH chip / FIFO / DSA commands), `src/cdintf.c` (disc image loading: CUE/BIN, ISO, CDI), and hooks in `src/jaguar.c` (BIOS auth bypass, boot stub injection).

Key docs:
- `docs/butch-registers.md` — full BUTCH register map ($DFFF00-$DFFF2F) with bit definitions
Expand Down
106 changes: 99 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ ifeq ($(platform), unix)
# Platform affix = classic_<ISA>_<µARCH>
# Help at https://modmyclassic.com/comp

# (armv7 a7, hard point, neon based) ###
# NESC, SNESC, C64 mini
# (armv7 a7, hard point, neon based) ###
# NESC, SNESC, C64 mini
else ifeq ($(platform), classic_armv7_a7)
TARGET := $(TARGET_NAME)_libretro.so
fpic := -fPIC
Expand All @@ -88,13 +88,20 @@ else ifeq ($(platform), classic_armv7_a7)
LDFLAGS += -static-libgcc -static-libstdc++
endif
endif
#######################################
#######################################

# OSX
else ifeq ($(platform), osx)
TARGET := $(TARGET_NAME)_libretro.dylib
fpic := -fPIC
SHARED := -dynamiclib
CFLAGS += -Ofast
CXXFLAGS += $(CFLAGS)
ifneq ($(arch),intel)
ifneq ($(arch),ppc)
HAVE_NEON = 1
endif
endif
ifeq ($(arch),ppc)
FLAGS += -DMSB_FIRST
OLD_GCC = 1
Expand Down Expand Up @@ -123,6 +130,10 @@ else ifneq (,$(findstring ios,$(platform)))
fpic := -fPIC
SHARED := -dynamiclib
MINVERSION :=
CFLAGS += -Ofast
CXXFLAGS += $(CFLAGS)
HAVE_NEON = 1

ifeq ($(IOSSDK),)
IOSSDK := $(shell xcodebuild -version -sdk iphoneos Path)
endif
Expand Down Expand Up @@ -582,7 +593,7 @@ CXXFLAGS += $(FLAGS)
CFLAGS += $(FLAGS)

OBJOUT = -o
LINKOUT = -o
LINKOUT = -o

ifneq (,$(findstring msvc,$(platform)))
OBJOUT = -Fo
Expand Down Expand Up @@ -616,9 +627,90 @@ endif
clean:
rm -f $(TARGET) $(OBJECTS)

.PHONY: clean
# --- Unit tests ---
# Build tests against the dylib via dlsym.
# Run: make test (builds core + tests, then runs all test suites)

TEST_CC ?= $(CC)
TEST_CFLAGS = -O0 -g -Wno-incompatible-pointer-types
TEST_LDFLAGS = -ldl
TEST_BINS = test/test_gpu_instructions test/test_dsp_instructions test/test_m68k_instructions test/test_irq test/test_hle_bios test/test_cd_hle_boot test/test_cd_bios_boot test/test_blitter_simd

test/test_gpu_instructions: test/test_gpu_instructions.c test/test_framework.h $(TARGET)
$(TEST_CC) $(TEST_CFLAGS) -o $@ $< $(TEST_LDFLAGS)

test/test_dsp_instructions: test/test_dsp_instructions.c test/test_framework.h $(TARGET)
$(TEST_CC) $(TEST_CFLAGS) -o $@ $< $(TEST_LDFLAGS)

test/test_m68k_instructions: test/test_m68k_instructions.c test/test_framework.h $(TARGET)
$(TEST_CC) $(TEST_CFLAGS) -o $@ $< $(TEST_LDFLAGS)

test/test_irq: test/test_irq.c test/test_framework.h $(TARGET)
$(TEST_CC) $(TEST_CFLAGS) -o $@ $< $(TEST_LDFLAGS)

test/test_hle_bios: test/test_hle_bios.c test/test_framework.h $(TARGET)
$(TEST_CC) $(TEST_CFLAGS) -o $@ $< $(TEST_LDFLAGS)

test/test_cd_hle_boot: test/test_cd_hle_boot.c test/test_framework.h test/cd_assertions.h $(TARGET)
$(TEST_CC) $(TEST_CFLAGS) -o $@ $< $(TEST_LDFLAGS)

test/test_cd_bios_boot: test/test_cd_bios_boot.c test/test_framework.h test/cd_assertions.h $(TARGET)
$(TEST_CC) $(TEST_CFLAGS) -o $@ $< $(TEST_LDFLAGS)

BLITTER_SIMD_TEST_FLAGS :=
ifeq ($(BLITTER_SIMD_SRC),$(CORE_DIR)/src/blitter_simd_sse2.c)
ifneq (,$(filter i686 i386 x86 win32,$(ARCH) $(platform)))
BLITTER_SIMD_TEST_FLAGS += -msse2
endif
endif

test/test_blitter_simd: test/test_blitter_simd.c src/blitter_simd.h $(BLITTER_SIMD_SRC) $(TARGET)
$(TEST_CC) -O2 $(BLITTER_SIMD_TEST_FLAGS) -I src -o $@ test/test_blitter_simd.c $(BLITTER_SIMD_SRC)

test-build: $(TEST_BINS)

test: test-build
@echo ""; echo "=== Running unit tests ===" ; echo ""
@fail=0; \
for t in test/test_gpu_instructions test/test_dsp_instructions test/test_m68k_instructions test/test_irq test/test_hle_bios test/test_blitter_simd; do \
if [ -x "$$t" ]; then \
DYLD_LIBRARY_PATH=. LD_LIBRARY_PATH=. "$$t" > /tmp/vj_test_out.txt 2>&1; \
rc=$$?; \
grep -E 'PASS|FAIL|SKIP|===|---|Results:' /tmp/vj_test_out.txt; \
if [ $$rc -ne 0 ]; then fail=1; fi; \
fi; \
done; \
exit $$fail

# CD HLE boot smoke suite — separated from `test` because it intentionally
# carries a known-failing TDD baseline. CI / pre-commit should call `test`
# (which stays green); developers iterating on CD HLE call `test-cd-hle-boot`
# directly and diff against test/cd_hle_boot_baseline.log.
test-cd-hle-boot: test/test_cd_hle_boot
@echo ""; echo "=== CD HLE boot smoke (TDD baseline; not part of strict test) ==="
@DYLD_LIBRARY_PATH=. LD_LIBRARY_PATH=. test/test_cd_hle_boot \
> test/cd_hle_boot_baseline.log 2>&1; \
rc=$$?; \
grep -aE '\[(RUN|PASS|FAIL|CRASH|FOCUS-SKIP|SKIP|PC-)\]|Discovered|---' test/cd_hle_boot_baseline.log; \
echo ""; echo "(full log: test/cd_hle_boot_baseline.log; rc=$$rc)"; \
exit 0

# Same shape as test-cd-hle-boot but exercises the real Atari Jaguar CD BIOS.
# Requires the BIOS file to live under VJ_TEST_CD_ROOT (default test/roms/private).
test-cd-bios-boot: test/test_cd_bios_boot
@echo ""; echo "=== CD real-BIOS boot smoke (TDD baseline; not part of strict test) ==="
@DYLD_LIBRARY_PATH=. LD_LIBRARY_PATH=. test/test_cd_bios_boot \
> test/cd_bios_boot_baseline.log 2>&1; \
rc=$$?; \
grep -aE '\[(RUN|PASS|FAIL|CRASH|FOCUS-SKIP|SKIP|PC-)\]|Discovered|---' test/cd_bios_boot_baseline.log; \
echo ""; echo "(full log: test/cd_bios_boot_baseline.log; rc=$$rc)"; \
exit 0

clean-test:
rm -f $(TEST_BINS) $(addsuffix .dSYM,$(TEST_BINS))

.PHONY: clean test test-build clean-test test-cd-hle-boot test-cd-bios-boot
endif

print-%:
@echo '$*=$($*)'

5 changes: 4 additions & 1 deletion Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ SOURCES_C := \
$(CORE_DIR)/src/mmu.c \
$(CORE_DIR)/src/vjag_memory.c \
$(CORE_DIR)/src/universalhdr.c \
$(CORE_DIR)/src/wavetable.c
$(CORE_DIR)/src/wavetable.c \
$(CORE_DIR)/src/jagcd_hle.c \
$(CORE_DIR)/src/jagcd_bios.c \
$(CORE_DIR)/src/jagcd_cart.c

# SIMD-accelerated blitter operations: select arch-specific implementation.
# BLITTER_SIMD may be set explicitly to one of: scalar, sse2, neon.
Expand Down
46 changes: 46 additions & 0 deletions docs/atari-jaguar-1999/.convert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
"""Convert every PDF in this directory to a sibling .md via pymupdf4llm."""
from __future__ import annotations

import os
import sys
import time
from concurrent.futures import ProcessPoolExecutor, as_completed
from pathlib import Path

import pymupdf4llm

HERE = Path(__file__).resolve().parent


def convert(pdf: Path) -> tuple[Path, int, float]:
t0 = time.time()
md = pymupdf4llm.to_markdown(str(pdf), show_progress=False)
out = pdf.with_suffix(".md")
out.write_text(md, encoding="utf-8")
return out, len(md), time.time() - t0


def main() -> int:
pdfs = sorted(p for p in HERE.glob("*.pdf"))
if not pdfs:
print("no PDFs found", file=sys.stderr)
return 1

workers = min(os.cpu_count() or 4, 8)
print(f">> converting {len(pdfs)} PDFs with {workers} workers", flush=True)

with ProcessPoolExecutor(max_workers=workers) as ex:
futs = {ex.submit(convert, p): p for p in pdfs}
for f in as_completed(futs):
src = futs[f]
try:
out, size, dt = f.result()
print(f" [{dt:5.1f}s] {src.name} -> {out.name} ({size:,} chars)", flush=True)
except Exception as exc:
print(f" !! {src.name}: {type(exc).__name__}: {exc}", flush=True)
return 0


if __name__ == "__main__":
sys.exit(main())
8 changes: 8 additions & 0 deletions docs/atari-jaguar-1999/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.venv/
__pycache__/
*.pyc

# Source PDFs (~73 MB) are not checked in — they live in cubanismo/jaguar-sdk
# and hillsoftware.com. Run `./fetch-pdfs.sh` to re-download locally if you
# need them, then `./.venv/bin/python .convert.py` to regenerate the .md files.
*.pdf
Loading
Loading