Skip to content

Update from feature/jaguar-cd-support#10

Draft
github-actions[bot] wants to merge 29 commits into
masterfrom
feature/jaguar-cd-support
Draft

Update from feature/jaguar-cd-support#10
github-actions[bot] wants to merge 29 commits into
masterfrom
feature/jaguar-cd-support

Conversation

@github-actions
Copy link
Copy Markdown

This is an automated pull request to update from branch feature/jaguar-cd-support

@github-actions
Copy link
Copy Markdown
Author

github-actions Bot commented Apr 29, 2026

Regression: macos-arm64

Regression Test Results

ROM Status Details Diff
jagniccc 🆕 NEW no baseline -
yarc 🆕 NEW no baseline -
jagniccc (determinism) ✅ PASS identical across runs -
yarc (determinism) ✅ PASS identical across runs -
jagniccc (frameskip) ✅ PASS skip=0 matches skip=3 -
yarc (frameskip) ✅ PASS skip=0 matches skip=3 -
jagniccc (save state) ✅ PASS round-trip matches -
yarc (save state) ✅ PASS round-trip matches -
jagniccc (rewind) ✅ PASS rewind matches -
yarc (rewind) ✅ PASS rewind matches -

Platform: Darwin arm64

Updated by CI at 2026-05-08T00:58:05.647Z

@github-actions
Copy link
Copy Markdown
Author

github-actions Bot commented Apr 29, 2026

Regression: linux-x64

Regression Test Results

ROM Status Details Diff
jagniccc 🆕 NEW no baseline -
yarc 🆕 NEW no baseline -
jagniccc (determinism) ✅ PASS identical across runs -
yarc (determinism) ✅ PASS identical across runs -
jagniccc (frameskip) ✅ PASS skip=0 matches skip=3 -
yarc (frameskip) ✅ PASS skip=0 matches skip=3 -
jagniccc (save state) ✅ PASS round-trip matches -
yarc (save state) ✅ PASS round-trip matches -
jagniccc (rewind) ✅ PASS rewind matches -
yarc (rewind) ✅ PASS rewind matches -

Platform: Linux x86_64

Updated by CI at 2026-05-08T00:58:05.499Z

@github-actions
Copy link
Copy Markdown
Author

github-actions Bot commented Apr 29, 2026

Regression: linux-arm64

Regression Test Results

ROM Status Details Diff
jagniccc 🆕 NEW no baseline -
yarc 🆕 NEW no baseline -
jagniccc (determinism) ✅ PASS identical across runs -
yarc (determinism) ✅ PASS identical across runs -
jagniccc (frameskip) ✅ PASS skip=0 matches skip=3 -
yarc (frameskip) ✅ PASS skip=0 matches skip=3 -
jagniccc (save state) ✅ PASS round-trip matches -
yarc (save state) ✅ PASS round-trip matches -
jagniccc (rewind) ✅ PASS rewind matches -
yarc (rewind) ✅ PASS rewind matches -

Platform: Linux aarch64

Updated by CI at 2026-05-08T00:58:07.688Z

JoeMatt and others added 11 commits May 6, 2026 20:37
Bumps the actions-minor-patch group with 1 update: [cirrus-actions/rebase](https://github.com/cirrus-actions/rebase).


Updates `cirrus-actions/rebase` from 1.4 to 1.8
- [Release notes](https://github.com/cirrus-actions/rebase/releases)
- [Commits](cirrus-actions/rebase@1.4...1.8)

---
updated-dependencies:
- dependency-name: cirrus-actions/rebase
  dependency-version: '1.8'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v4...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/labeler](https://github.com/actions/labeler) from 5 to 6.
- [Release notes](https://github.com/actions/labeler/releases)
- [Commits](actions/labeler@v5...v6)

---
updated-dependencies:
- dependency-name: actions/labeler
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5 to 6.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@v5...v6)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
…ns/develop/codecov/codecov-action-6

ci: Bump codecov/codecov-action from 5 to 6
…ns/develop/actions/cache-5

ci: Bump actions/cache from 4 to 5
…ns/develop/actions/labeler-6

ci: Bump actions/labeler from 5 to 6
…ns/develop/actions/upload-artifact-7

ci: Bump actions/upload-artifact from 4 to 7
…ns/develop/actions-minor-patch-4f0f6e5aaa

ci: Bump cirrus-actions/rebase from 1.4 to 1.8 in the actions-minor-patch group
@JoeMatt JoeMatt force-pushed the feature/jaguar-cd-support branch from 806f321 to 77b0675 Compare May 7, 2026 02:19
JoeMatt and others added 15 commits May 6, 2026 23:44
Signed-off-by: Joseph Mattiello <git@joemattiello.com>
PR libretro#170 (closed without merge) shipped a test_audio_clipping pass on
Iron Soldier 2 that read "0 saturated samples / RMS=521" — which is
silence, not fixed audio.  The clipping test couldn't tell those
apart: it only flags loud-broken output (saturation density, run
length, sustained loud RMS), so a "fix" that drops RMS to zero
sailed through.

test_audio_presence is the missing counterpart.  It runs N frames,
captures the post-onset window, and asserts:

- first_audio_frame is reached (some |s| > 32 seen)
- window RMS lies in [floor, ceiling] -- per-ROM tunables via CLI
- longest run of near-zero stereo frames < max_zero_run_pct of window

Wired into `make test` against Iron Soldier 1 (boots straight to a
music-on title, develop measures RMS ~1175).  Floor 200 catches the
silencing-regression class, ceiling 25000 catches the loud-broken
class.  Same skip-if-missing pattern as the rest of the audio tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PR libretro#170 lesson: a clipping-only test missed the silencing regression
where Iron Soldier 2 went from 17% saturated → RMS=521 (silent).
Document `test_audio_clipping` + `test_audio_presence` as a pair, and
add a "Audio / DSP work — required tests" section that spells out
the required runs before declaring an audio change done.  Also pin
the rule into the sub-agent guidelines so worktree agents don't ship
the same masked-failure pattern.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Brings in the CUE/BIN parser, BUTCH emulation, HLE/cart/bios boot
strategies, and BootConfig settings glue from
claude/add-jaguar-cd-support-hOzev (PR libretro#109), repointed to the new
src/cd and src/core layout. The build now links the CD subsystem
but no path activates it -- bootConfig.strategy is NULL and
JaguarCDHLEActive() returns false. libretro.c CD detection and
src/core/jaguar.c CD reset are deferred to Tier 2.

C89 fixes applied to satisfy scripts/c89-lint.sh: hoisted for-loop
counters (HLEHandleCDRead phase loop, HLEPopulateCartBuffer, ATRI
sync block, cdrom.c HLETransferTick), moved mid-block decls to block
tops in cdrom.c (BUTCHExec, NM93C14 opcode/addr decode, seek-redirect
discTotal) and cdintf.c (CDIntfGetTrackInfo MSF locals), pulled
HLEHandleCDRead's sentinelIsAscii/fallback*/phase_starts/wasRedirected
to the function header, and converted designated initializers in
cd_boot_strategy_{hle,cart,bios} to positional.

VJSettings layout: kept hardwareTypeNTSC/useJaguarBIOS/useFastBlitter
as the leading three fields so test/test_hle_bios.c (which redeclares
the struct with just those three) still resolves them via dlsym at
matching offsets.

external_cd_bios[] / cd_bios_loaded_externally are emitted as weak
fallback definitions in src/cd/jagcd_bios.c; libretro.c will provide
the real definitions in Tier 2 and override them.

JaguarInstallCDAuthBypass() is forward-declared in cdintf.c; it is
defined in jagcd_bios.c so cdintf can arm the BNE-NOP patch when the
BIOS reads into an inter-session gap.

Files imported:
- src/cd/cdintf.{c,h}    -- CUE/BIN parser
- src/cd/cdrom.{c,h}     -- BUTCH emulation
- src/cd/jagcd_{bios,cart,hle}.c, jagcd_{boot,hle}.h  -- strategies
- src/core/settings.{c,h} -- BootConfig + ResolveBootConfig
- Makefile.common        -- register the new objects

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Detects .cue/.cdi/.iso content in retro_load_game, scans the system
directory for a CD BIOS image, opens the disc image via CDIntfOpenImage,
calls ResolveBootConfig to pick the boot strategy, and dispatches via
bootConfig.strategy->boot(info). Adds virtualjaguar_cd_bios_type and
virtualjaguar_cd_boot_mode core options. Extends the EEPROM save buffer
to include the CD EEPROM (cdrom_eeprom_ram[64]).

The Tier 1 weak symbols for external_cd_bios[] and
cd_bios_loaded_externally are now overridden by strong libretro.c
definitions. Cart-only flow is unchanged when no CD content is loaded.

Also propagates JaguarLoadFile failures out of cart_boot (so the
'unknown headerless BIN rejected' contract still holds) and folds the
post-reset reload of RAM-loaded executables (ABS/COFF/JAGSERVER) into
the cart strategy. Exposes cdrom_eeprom_ram so the save buffer can pack
both EEPROMs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wires the M68KInstructionHook to dispatch JaguarCDHLEHook and the active
CDBootStrategy's instruction_hook, and invokes the strategy's reset()
from JaguarReset so HLE/BIOS per-run state (auth-bypass flag, boot-stub
flag, HLE active flag) clears alongside the rest of the machine.

The cart strategy keeps its existing path: cart_instruction_hook and
cart_reset are no-ops, so non-CD content is unaffected.  CD HLE/BIOS
strategies (already imported by Tier 1) now actually fire.

Tier 1+2 already exposed everything else this needs:
  - jagcd_hle.c defines JaguarCDHLEHook + cd_boot_strategy_hle
  - jagcd_bios.c defines bios_instruction_hook + JaguarInstallCDAuthBypass
  - jagcd_cart.c defines the cart no-op strategy
  - cdrom.c handles BUTCH FIFO drain via HLETransferTick (no GPU-side
    intercept needed; libretro#109's gpu.c HLE path was an alternate route)
  - jerry.c already routes BUTCH I2S into the DAC (Tier 1 imported)
  - libretro.c populates bootConfig.strategy via ResolveBootConfig

Hunks from libretro#109 not ported, with reasoning:
  - src/m68000/m68kinterface.c MULL/DIVL: their version is buggier
    (truncates 64-bit overflow detection, mishandles unsigned q sign,
    drops Dh != Dl guard).  Our existing code is correct; keep ours.
  - src/tom/gpu.c +263 lines: 95% diagnostic tracing (gpuStartCount,
    GPU_TRACE, gpu_isr_phase, gpu_ram_8 dumps).  The functional CD
    intercept (JaguarCDHLEGPUDataPhase) is reachable from cdrom.c's
    HLE path; the GPU-side intercept is an alternate route we don't
    need.  Skipping to preserve our IRQ priority/dispatch (Test 9d).
  - src/tom/tom.c: their tom.c has no CD-specific changes vs ours;
    the diff was rename + cosmetic.
  - src/jerry/eeprom.{c,h}: cdrom_eeprom_ram[] already lives in
    cdrom.c with libretro.c handling save/restore.  No header tweak
    needed.
  - src/core/file.c: ours has more code (raw-binary homebrew load
    address inference); their version is older.  Keep ours.
  - src/core/log.h: identical content (just inline vs INLINE; ours
    is more portable for MSVC).

No test changes (Tier 4) and no libretro.c changes (Tier 2 already
did those).  test_hle_bios stays at 211/211, make test 0 failures.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Brings in libretro#109's test infrastructure for the CD subsystem. Per the
Tier 5 triage report, redundant general-hardware suites were dropped;
overlapping cherry-picks deferred to a follow-up.

Imported and wired into make test (84 new passing asserts):
  test/test_butch_cd.c, test_bios_config.c, test_boot_config.c,
  test_audio_dac.c

Built but not auto-run (private-ROM gated; surface real per-game
boot regressions when discs are present):
  test/test_cd_boot.c, test_cd_hle_boot.c, test_cd_bios_boot.c,
  test_blitter.c

Framework + helpers + tooling: test_framework.h, cd_assertions.h,
mister_ground_truth.h, dump_pc.c, heap_search.c, headless.py, and
test/tools/{analyze_cd_roms,bios_disasm,disasm_gpu_isr}.py.

Dropped (redundant with our coverage in test_hle_bios, test_dsp_ops,
test_gpu_ops, test_m68k_ops, test_blitter_simd):
  test_dsp_instructions, test_gpu_controlflow, test_gpu_instructions,
  test_m68k_instructions, test_timers, test_irq, test_gpu_ctrl,
  test_video_modes, test_memory_map, test_gpu_irq.

Cherry-picks deferred to a follow-up:
  resolution-derivation cases from test_video_modes ->test_hle_bios,
  gpu_ctrl_bus_hog_readback / gpu_flags_int_enable_all_five from
  test_gpu_ctrl -> test_hle_bios, BUTCH cases from test_irq ->
  test_butch_cd, line_buffer cases from test_memory_map ->
  test_hle_bios.

All imports pass scripts/c89-lint.sh (decls hoisted). test_hle_bios
unchanged at 211; full suite OK: 0 test(s) failed.
…-ID shortcut

Two bugs in jagcd_hle.c CD_read:

1. The "sentinel NOT found — read raw" fallback hard-coded scanLBA = lba
   (the original requested seek), which silently undid the
   streaming-continuation logic that advances startLBA past previously
   transferred sectors on repeated calls. Result: a game polling the same
   CD_read got the same 1 MB on loop forever. Now uses startLBA so
   continuation works on the fallback path too.

2. When D1's top 16 bits are zero (e.g. Space Ace passes D1=$00000001
   as a transfer ID, not a sync pattern), the sentinel scan finds
   millions of false-positive `\0\0\0\x01` matches across the disc but
   never accepts a real sync block — then falls back to "read raw"
   anyway, after burning 4 M log lines and several seconds of CPU per
   call. Now short-circuits the scan when D1 is clearly a counter and
   streams raw from startLBA directly.

Space Ace's HLE_LOG output drops from ~4.3 M lines to ~43 K (100x).
Primal Rage's behaviour unchanged (it uses real ASCII sentinels —
DDL9/DDL5 — which find proper sync blocks). Full HLE sweep still
5/9 pass; full make test green.

The user-visible "screen goes black" failure on Space Ace is upstream
of these fixes — the game now gets fresh sectors per call but quickly
runs past end-of-disc into zero-fill. Tracking that as part of a
broader CD-subsystem audit now that the CPU/GPU/DSP/IRQ baseline is
solid.
load_external_cd_bios() previously only matched the .j64 variants of
the World retail and developer CD BIOS plus the lowercase
jaguarcd_bios variants. Real-world libretro frontends ship the BIOS
under names like "Jaguar CD BIOS.rom" or with the libretro [BIOS] tag
in .rom/.bin form. Add those filenames so the BIOS is picked up
without renaming.
cdrom.c:593 was asserting GPUIRQ_DSP (=1, vector $F03010) but the CD
BIOS installs its CD-data ISR at GPU IRQ0 ($F03000) - the EXT1/CPU
line. The mismatch meant any BUTCH-triggered IRQ landed on the DSP
vector with no handler. Fix to GPUIRQ_CPU.

Identified by the CD-IRQ-chain audit (no behaviour change without
the BUTCHExec scheduler tick - see follow-up commit).
BUTCHExec was fully written but never called from anywhere in the
live engine, so BUTCH never asserted IRQs to the GPU on any path.
The HLE shortcuts (jagcd_hle.c sentinel scan, cdrom.c:335
HLETransferTick) compensated by bypassing BUTCH entirely.

Tick BUTCHExec once per halfline when bootConfig.isCDGame is true.
Halfline cadence (~32 us) is much coarser than real BUTCH I2S timing
but matches our existing event-queue resolution; the FIFO-fill state
machine progresses one transition per call.

Real-BIOS path can now fire its CD ISR. The HLE shortcuts remain
load-bearing because of the documented PTRPOS divergence
(cdrom.c:319-333) - that fix is separate.

Adds test_butch_gpu_irq_line_mapping to test_hle_bios.c pinning the
GPUSetIRQLine(line, ASSERT) -> gpu_control bit (6+line) mapping for
both lines BUTCH could plausibly target, regression-locking the
GPUIRQ_CPU vs GPUIRQ_DSP fix from the previous commit.
… dual-delivery

Two destructive paths surfaced when Path A wired BUTCHExec into the
scheduler:

1. The "after N seeks without HLE progress, fall back to native FIFO
   IRQ" mechanism (HLE_FALLBACK_THRESHOLD) was harmless when BUTCH
   was dormant but actively destructive once BUTCHExec ticks: the
   fallback unleashed FIFO IRQs which run the BIOS GPU ISR's
   fifo_read path, which writes to the wrong RAM address (PTRPOS
   divergence, cdrom.c:319-333). Pin hleActive = (strategy==bios)
   permanently. HLETransferTick remains the canonical CD-data path
   for both strategies until the GPU-side PTRPOS bug is fixed.

2. The dual JERRY-EXT1 delivery — JERRYSetPendingIRQ() AND
   m68k_set_irq(2) — fired the 68K IRQ2 vector during transfers when
   the CD BIOS hadn't yet installed its EXT1 trampoline (Hover
   Strike, Primal Rage stack-corruption to PC=$22xxxxxx). The CD
   BIOS clears BUTCH bit 0 before issuing CD_read so the 68K side is
   dormant during transfers; the GPU side (BUTCH -> JERRY EXT1
   latch -> GPU IRQ0) is the path that matters. Drop the m68k_set_irq
   call but keep the JERRYSetPendingIRQ pending bit so JINTCTRL reads
   continue to see the latched source.

Sweep deltas vs pre-Path-A baseline (which passed 7/9 via fake
HLETransferTick path):
  BIOS: 6/9 actually executing the BIOS code path (was 5/9 with
        Path-A regression, was 7/9 fake before Path A).
  HLE:  5/9 (unchanged).
  Hover Strike: recovered to PASS.
  Primal Rage:  still fails but the wedge moved deeper into the BIOS
                path (227 unique PCs, 16 KB RAM payload before the
                $220DC09E garbage-PC). Tracking separately.
Adds per-disc visibility into actual CD subsystem activity. Previously
the harness only sampled 68K PC, which can't distinguish "BIOS wedged
in CD spin-loop" from "BIOS booted game code." Now the per-disc line
includes GPU PC, GPU IRQ0 (CD ISR) count, GPU IRQ3 (OP IRQ) count,
BUTCH diag counters (butchExec/fifoIRQs/dsaIRQs/fifoReads/seeks/
globalDisabled), and HLE transfer bytes.

Implementation:
- Adds gpu_irq0_count and gpu_irq3_count globals to gpu.c, declared
  in gpu.h. Incremented in GPUSetIRQLine on ASSERT_LINE; reset in
  GPUReset alongside other GPU state. Pure observability — no
  behavioural side effects.
- Adds CDROMDiagGetCounters() accessor to cdrom.c/cdrom.h that
  exposes the existing static diag_* counters and hleTransferBytes
  to harnesses. Avoids dropping `static` on the whole set.
- cd_assertions.h: new cd_diag_snapshot struct + cd_diag_capture()
  helper that reads the accessor via dlsym (alongside gpu_irq0_count,
  gpu_irq3_count, GPUGetPC). Both HLE and BIOS harnesses capture the
  snapshot before unload and emit a [DIAG] line per disc.

C89/GNU89 clean (declarations at top of block).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Removed 6 patches in jagcd_bios.c (4 RAM stomps, BNE-NOP auth-bypass + helper, DSP completion-flag stomp), TryReadAuthRedirect in cdintf.c, and HLETransferTick + support machinery in cdrom.c.

HLE 5/9 unchanged. BIOS 6/9 -> 7/9 (Primal Rage flips PASS, was wedging at gpu_pc=$22002200). make test green.
The CD BIOS GPU CD ISR reads DSCNTRL after handling a DSARX response
and the inline comment in the embedded BIOS listing (cdrom.c:1643)
documents this read as 'Clears DSA pending interrupt'. Real BUTCH
hardware acks the DSA pending latch on a CPU/GPU read of DSCNTRL.

Without this, dsaResponseReady stays sticky after the first seek and
BUTCHExec re-asserts GPU IRQ0 every halfline indefinitely (Primal Rage
trace shows 2.9 M GPU IRQ0 firings across 6 K frames, all DSARX, while
the game's poll-loop at \$0050E2 waits for game state that never
advances because the GPU is permanently re-entering its DSARX handler).

The fix doesn't (yet) flip Primal Rage from harness wedge to harness
PASS — the GPU still parks at gpu_pc=\$F03060 long enough for the user-
visible boot to reach the publisher logo and stall there. That's a
separate bug; this commit is the correct hardware semantics regardless.
JoeMatt added 3 commits May 7, 2026 20:53
Audited HLE-side hacks the same way as a96556b did the BIOS side.

REMOVE: single-match sentinel fallback (unreachable once multi-phase
scan + raw-from-startLBA fallback are both present).

REMOVE: per-CD_read $800000 cart-space mirror. HLEPopulateCartBuffer
already covers BrainDead 13's cart-scan at boot; the per-read mirror
was just redundant write traffic.

REMOVE: 10 jump-table no-op intercepts (CD_I2S_ENABLE, CD_SPIN_UP,
CD_STOP_DRIVE, CD_SET_VOL_*, CD_PAUSE, CD_UNPAUSE, CD_FIFO_DISABLE,
CD_HW_RESET, CD_SET_DAC_MODE). HLEInstallJumpTable pre-fills these
slots with RTS so falling through is a clean no-op naturally.

CHANGE: defer CD_poll completion by one tick. Some boot stubs depend
on observing not-done at least once before done (BrainDead 13's HLE
poll loop misses an init step otherwise). Return A0=0 the first time
we see hle_read_pending and clear it; subsequent polls return the
GPU data area pointer as before.

Sweep: HLE 5/9 -> 6/9 (BrainDead 13 PASS). BIOS 7/9 unchanged.
Combined coverage: 8/9 boot via at least one strategy. make test green.

Kept (still load-bearing): counter-ID shortcut (perf), multi-phase
sentinel scan (Highlander), sentinel scan as a whole (Highlander +
Primal Rage), ATRI sync block writeback (boot-stub PC diversity for
BrainDead 13/Baldies), streaming continuation (Iron Soldier 2's
repeated-CD_read pattern).
- Add CDROM*/BUTCH*/GetRamPtr/bootConfig/cd_boot_strategy_*/
  ResolveBootConfig to the test export lists (link-test.T,
  exports-test.list) so test/test_butch_cd, test/test_bios_config,
  and test/test_boot_config can dlsym the CD subsystem.
- Make retro_get_memory_size(SAVE_RAM) return EEPROM_SAVE_SIZE
  (128 bytes) for cart-only loads and (EEPROM_SAVE_SIZE +
  CD_EEPROM_SAVE_SIZE) (256 bytes) only when jaguar_cd_mode is
  active.  Keeps cart save format byte-compatible with develop and
  un-breaks test/test_eeprom_lifecycle:first_load_sram_available.
The unconditional JaguarReset() after retro_load_game's strategy->boot()
call was wiping out HLE CD state: it re-randomized RAM (clobbering the
boot stub injected at $004000+), reset TOM/JERRY/GPU/DSP/CDROM, and
called the strategy reset hook a second time, undoing the entire HLE
setup the cd_boot_hle path had just performed.  Symptom: every CD HLE
disc booted to the injected entry PC, then the 68K immediately wandered
into garbage and saturated the test harness's 256-PC unique-PC ceiling
(test_cd_hle_boot regressed 6/9 -> 0/9).

Cart and CD strategies already perform their own JaguarReset() at the
right point in their boot sequence, so the only path that genuinely
needs the extra reset+reload is the RAM-loaded executable case
(.abs/.cof/JagServer) where the load buffer must be re-applied after
RAM is randomized.  Move the JaguarReset() inside the RAM-loaded
branch and drop the unconditional one.

After fix: test_cd_hle_boot 6/9 (matches pre-rebase tip 806f321);
test_cd_bios_boot stays 7/9; make test exits 0.
@JoeMatt JoeMatt force-pushed the feature/jaguar-cd-support branch from afb04f6 to 31a6629 Compare May 8, 2026 00:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant