Files

1147 lines
90 KiB
Markdown

# CD boot matrix
Generated by `test/tools/cd_boot_matrix.sh` -- the regression gate for CD-boot
work. Every subsequent CD-boot fix must move rows forward through the stage
taxonomy below, never backward. Do not hand-edit this table; re-run the script
and commit its output instead. `test/tools/matrix_diff.py OLD.md NEW.md` enforces
the never-backward rule against the previous tag's copy (checklist:
`docs/release-process.md`).
## How to re-run
```bash
bash test/tools/cd_boot_matrix.sh
```
Requires `test/roms/private/` populated with the CUE/CDI/ISO images and the real
Jaguar CD BIOS (`Jaguar CD BIOS.rom` in this repo's corpus; see
`test/test_cd_bios_boot.c`'s header comment for the full accepted-filename list).
In a git-worktree checkout that does not share untracked files with the main
checkout: `ln -s /path/to/main-checkout/test/roms/private test/roms/private`.
Core must be built `make TEST_EXPORTS=1` (a plain `make` strips the dlsym export
set the harnesses need -- the script auto-rebuilds if it detects this).
Env knobs: `CD_MATRIX_FRAMES` (default 3000), `CD_MATRIX_TIMEOUT` (default 120s
per title x mode), `CD_MATRIX_ROMS_ROOT` (default `test/roms/private`),
`CD_MATRIX_OUT` (output path, default `docs/cd-boot-matrix.md`),
`CD_MATRIX_LOGDIR` (raw per-run logs, default a fresh `mktemp -d`; pass a
fixed dir to keep logs across chunked invocations), and
`CD_MATRIX_MAX_RUNS` (max NEW runs per invocation, default 0 = unlimited).
Rows append incrementally with a resume guard: already-recorded title x mode
combos are skipped, so an interrupted sweep resumes where it left off. For
long sweeps (or agent sessions with per-command time limits), run chunked:
```bash
# ~3 runs x <=120s wall each per invocation; repeat until every line
# reports "already recorded, skipping":
CD_MATRIX_MAX_RUNS=3 CD_MATRIX_LOGDIR=/tmp/cdmx_logs bash test/tools/cd_boot_matrix.sh
```
To force a re-run of specific rows, delete those table lines from the output
file first -- the resume guard re-runs only missing title x mode combos.
## Legend
**Stage** (finest level the harness evidence supports; `?` = insufficient
evidence to classify further, never fabricated):
| Stage | Meaning |
|---|---|
| `LOAD_FAIL` | `retro_load_game()` returned false, or the harness child crashed (segfault) before producing a usable PC trace |
| `BIOS_INTRO` | Real CD BIOS executing (boot ROM cube animation, BIOS main loop/error handler, or CD-read poll code) -- has not yet handed off to the boot stub or game |
| `BOOT_STUB` | PC parked in the injected boot-stub ISR/poll-loop/data region (`$080000`-`$08FFFF`) |
| `GAME_CODE` | PC in game-owned RAM outside the BIOS/boot-stub bands (HLE: any stable multi-PC run, since HLE synthesizes past BIOS/boot-stub by design) |
| `MENU` / `IN_GAME` | Not distinguished by any current harness -- see "Headless framebuffer caveat" in CLAUDE.md. Reported as `GAME_CODE` with a note. |
| `HARNESS_HANG` | Killed at the wall-clock timeout; the harness process itself did not exit |
| `? (pc_escape)` | Final 68K PC outside every valid execute window (RAM <`$200000`, boot ROM `$E00000`-`$E1FFFF`, cart/CD BIOS `$800000`-`$8FFFFF`) -- a crash, not a reached stage |
| `? (BIOS service band ...)` | Final PC in `$0`-`$3FFF` (BIOS TOC / CD_read service code, used both by the BIOS during boot and by games after handoff). Two variants, distinct evidence strength: "PC-SET showed no game-band entries" = the visited-PC dump was checked and contains no `$090000`-`$1FFFFF` addresses (checked negative); "PC-SET suppressed, unique_pcs>32" = the harness never emitted the dump, so the game-band check could not run (undetermined) |
Score `N/1` follows the harness's own PASS/FAIL heuristic (PC stays in
RAM/BIOS/cart range, not self-looping, not thrashing among <=4 distinct PCs,
RAM has non-trivial non-zero payload) -- see `test/cd_assertions.h`. It is
informational, not the stage classification: a title can score FAIL yet still
classify as GAME_CODE (e.g. stuck in its own hardware-poll wait loop after
booting), or score PASS while stuck in a still-early BIOS/boot-stub band.
## Baseline notes -- 2026-07-13, branch feature/jaguar-cd-support @ cbd2518
Dated observations for this baseline run (3000 frames/title/mode, 120 s
wall-clock cap). Notes sections are snapshots -- a regenerated table gets a
fresh dated section; do not retrofit old ones.
- **Stage distribution (21 rows):** HLE -- 9 GAME_CODE (of which 3 score 0/1:
Baldies, Iron Soldier 2, and Baldies' final PC `$1FFFDE` is top-of-RAM/stack,
i.e. GAME_CODE only in the "68K executing game-owned RAM" sense), 1 LOAD_FAIL
(baldies.cdi segfault). BIOS -- 4 BIOS_INTRO, 1 BOOT_STUB (Primal Rage,
`final_pc=$0803AC` = documented boot-stub poll loop), 1 GAME_CODE
(BrainDead 13 -- the disambiguating game-band PCs `$124342 $124346 $12434C`
are quoted in the row's own evidence column), 2 `? (BIOS service band)`
(Highlander: PC-SET checked, no game-band entries; Iron Soldier 2: PC-SET
suppressed at unique_pcs=34, so the game-band check never ran --
undetermined, not a checked negative), 1 `? (pc_escape)`
(Battle Morph, `final_pc=$8FBFB758`), 1 HARNESS_HANG (Baldies, video_stall
watchdog fired at frame 745, GPU wedged at `$F03060`), 1 LOAD_FAIL
(baldies.cdi), plus the ISO documentation row (BIOS_INTRO,
`final_pc=$194D12` = CD BIOS poll loop; `.iso` support has since been
removed entirely (load refused with an explanatory error) — historical
note only; it was a permanent,
documented limitation -- no session-2 layout).
- **No title reaches a verified MENU or IN_GAME headlessly.** Every
GAME_CODE row still trips `video_stall` or sits in a tight wait loop.
MENU/IN_GAME verification requires RetroArch (headless framebuffer caveat).
- **BIOS-mode error-loop signature:** `final_pc=$0059B0` with `unique_pcs=6`
and `seeks=0` (seen in shorter runs / Task 2) is the BIOS "no boot" spin.
At 3000 frames several titles progress past it: Dragon's Lair and Space Ace
show real disc activity (`seeks=1`, `dsaIRQs` in the millions, `cdPlaying=1`)
yet remain in BIOS code bands -- boot progresses but never completes.
- **Task 2 aggregate parity:** harness scores here are per-title at 3000
frames and are NOT comparable 1:1 to the 300/900-frame Task 2 sweeps
(test_cd_hle_boot 6/9, test_cd_bios_boot 7/9); longer runs legitimately
change PASS/FAIL for titles that wedge late (e.g. Battle Morph HLE passes
at 3000 frames, unique_pcs=126). The stage column, not the score, is the
regression gate.
- **baldies.cdi segfaults the core in both modes** (CDI parser crash, known
since the corpus was assembled -- see `test/cd_assertions.h`
`cd_ext_enabled()` rationale). Fixing the CDI loader is its own work item;
the row exists so the fix has a baseline to move.
- **Last-DSA-command column** from the original plan sketch is intentionally
absent: per-title DSA tracing is Task 4 instrumentation. The `[CD-DIAG]`
counters (`seeks`, `dsaIRQs`, `fifoReads`) in the raw logs carry the
equivalent evidence for now.
## Results
| Title | Mode | Score | Stage | Watchdog | PC evidence |
|---|---|---|---|---|---|
| Baldies (USA) (Rev 1).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=20409B unique_pcs=39 final_pc=$05FE8A <!-- build:67acceb9dc39 --> |
| Baldies (USA) (Rev 1).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=20303B unique_pcs=65 final_pc=$05FE88 <!-- build:67acceb9dc39 --> |
| Battle Morph (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Battle Morph (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=26709B unique_pcs=47 final_pc=$007794 <!-- build:67acceb9dc39 --> |
| Battle Morph (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Battle Morph (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=28474B unique_pcs=69 final_pc=$022052 <!-- build:67acceb9dc39 --> |
| BrainDead 13 (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=17926B unique_pcs=51 final_pc=$004FD0 <!-- build:67acceb9dc39 --> |
| BrainDead 13 (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=19577B unique_pcs=62 final_pc=$004FD2 <!-- build:67acceb9dc39 --> |
| Dragon's Lair (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=18477B unique_pcs=74 final_pc=$00967A <!-- build:67acceb9dc39 --> |
| Dragon's Lair (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=20802B unique_pcs=79 final_pc=$004C10 <!-- build:67acceb9dc39 --> |
| Highlander - The Last of the MacLeods (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=21068B unique_pcs=52 final_pc=$009222 <!-- build:67acceb9dc39 --> |
| Highlander - The Last of the MacLeods (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=16336B unique_pcs=69 final_pc=$0088DA <!-- build:67acceb9dc39 --> |
| Hover Strike - Unconquered Lands (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Hover Strike - Unconquered Lands (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=6150B unique_pcs=48 final_pc=$05DAA4 <!-- build:67acceb9dc39 --> |
| Hover Strike - Unconquered Lands (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Hover Strike - Unconquered Lands (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=15762B unique_pcs=74 final_pc=$05DAA6 <!-- build:67acceb9dc39 --> |
| Iron Soldier 2 (USA) (Songbird).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29325B unique_pcs=23 final_pc=$00B542 <!-- build:67acceb9dc39 --> |
| Iron Soldier 2 (USA) (Songbird).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29752B unique_pcs=41 final_pc=$00B542 <!-- build:67acceb9dc39 --> |
| Primal Rage (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=28237B unique_pcs=97 final_pc=$00457A <!-- build:67acceb9dc39 --> |
| Primal Rage (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=25774B unique_pcs=75 final_pc=$01AFCE <!-- build:67acceb9dc39 --> |
| Space Ace (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Space Ace (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=19041B unique_pcs=60 final_pc=$004D4E <!-- build:67acceb9dc39 --> |
| Space Ace (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Space Ace (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=20881B unique_pcs=78 final_pc=$00B87A <!-- build:67acceb9dc39 --> |
| baldies.cdi | hle | 1/1 | GAME_CODE | (none) | [PASS] baldies.cdi : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=20409B unique_pcs=39 final_pc=$05FE8A <!-- build:67acceb9dc39 --> |
| baldies.cdi | bios | 1/1 | GAME_CODE | (none) | [PASS] baldies.cdi : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=20303B unique_pcs=65 final_pc=$05FE88 <!-- build:67acceb9dc39 --> |
| Myst (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Myst (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=10988B unique_pcs=256+ final_pc=$0103FA <!-- build:67acceb9dc39 --> |
| Myst (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Myst (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=8123B unique_pcs=256+ final_pc=$00EF82 <!-- build:67acceb9dc39 --> |
| Baldies (USA) (Rev 1).chd | hle | 1/1 | GAME_CODE | (none) | [PASS] Baldies (USA) (Rev 1).chd : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=20409B unique_pcs=39 final_pc=$05FE8A <!-- build:67acceb9dc39 --> |
| Baldies (USA) (Rev 1).chd | bios | 1/1 | GAME_CODE | (none) | [PASS] Baldies (USA) (Rev 1).chd : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=20303B unique_pcs=65 final_pc=$05FE88 <!-- build:67acceb9dc39 --> |
| Myst (USA).chd | hle | 1/1 | GAME_CODE | (none) | [PASS] Myst (USA).chd : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=10988B unique_pcs=256+ final_pc=$0103FA <!-- build:67acceb9dc39 --> |
| Myst (USA).chd | bios | 1/1 | GAME_CODE | (none) | [PASS] Myst (USA).chd : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=8123B unique_pcs=256+ final_pc=$00EF82 <!-- build:67acceb9dc39 --> |
| Frog Feast (USA) (Unl).chd | hle | 1/1 | GAME_CODE | (none) | [PASS] Frog Feast (USA) (Unl).chd : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=7027B unique_pcs=119 final_pc=$006E92 <!-- build:67acceb9dc39 --> |
| Frog Feast (USA) (Unl).chd | bios | 1/1 | GAME_CODE | (none) | [PASS] Frog Feast (USA) (Unl).chd : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=9667B unique_pcs=131 final_pc=$006E92 <!-- build:67acceb9dc39 --> |
Raw per-run logs are not committed; re-run the script to regenerate.
### Regenerated on ab77d16 -- 2026-10-07 (v3.7.1 release gate)
Swept with the v3.7.0 tag (`274fa74`) and `libretro/develop` (`ab77d16`) built
side by side from pristine trees (`CD_MATRIX_TIMEOUT=500`, 3000 frames, the
host heavily loaded). **The two builds agree on all 28 rows**: every row is
`1/1 GAME_CODE`, no watchdog line, and `final_pc` / `unique_pcs` match for every
row where the harness prints them. No CD regression since v3.7.0.
Against the rows this table carried before (`4cbb1d56cff7`, the 2026-10-02
sweep), the only change is that the five bios rows that read `0/1` now read
`1/1` with no `cd_seek_wedge` line: `Baldies (USA) (Rev 1)` `.cue` / `.chd` /
`.cdi` and `Myst (USA)` `.cue` / `.chd`. The v3.7.0 tag already reads that way,
so it predates every PR merged since and v3.7.1 adds nothing here. The bios
rows of Battle Morph, BrainDead 13, Highlander and Primal Rage, which carried a
`cd_seek_wedge` line in the old table, no longer do either (same reason).
`ram_payload` and `unique_pcs` moved slightly on a few rows (for example Frog
Feast `unique_pcs` 122 -> 119, Hover Strike hle `ram_payload` 13546B -> 6150B)
between the old table and v3.7.0; they are identical between v3.7.0 and
`ab77d16`.
### Regenerated on 2f913d8 -- 2026-10-02 (#735)
The first full sweep since 2026-08-13. Against those rows, two titles improved
and four regressed. Everything else is unchanged at the stage and verdict level.
- **Improved.** `Frog Feast (USA) (Unl).chd`: hle LOAD_FAIL -> GAME_CODE PASS,
bios BIOS_INTRO -> GAME_CODE PASS.
- **Regressed, all in bios mode, PASS -> FAIL at the same stage.** Baldies
`.cue` / `.chd` / `.cdi` and `Myst (USA).cue`. In each the 68K is parked
waiting for an interrupt that does not come (`not_loop=0`). These are #752
(Baldies: STOP at `$05F4EA`, GPU completion IRQ starved) and #756 (Myst:
68K sleeps on STOP, GPU IRQ serviced early). #757 claims #756 and should
move these rows.
Wall-clock caps were raised for this sweep (`CD_MATRIX_TIMEOUT=400`) because
the host was heavily loaded. The frame budget is unchanged (3000).
### Myst CHD joined the sweep -- 2026-10-01
`Myst (USA).chd` now has rows (issue #774, after #755 fixed virtual-pregap
handling in `ParseCHD`). It is the corpus's only CHD with virtual pregaps:
tracks 3-10 carry 148-149-frame `VAUDIO` pregaps, which is exactly the case
#755 fixed. Its rows match the `Myst (USA).cue` rows field for field when
both are measured on the same build (`ram_payload`, `unique_pcs`, `final_pc`,
and in bios mode the same `cd_seek_wedge` frame, seek and drain counts), so
the CHD reader returns the same data the CUE/BIN path does.
Conversion matters. Homebrew/distro `chdman` (0.289 here) does not write CHSE
session tags, and the core refuses such a CHD at load (`LOAD_FAIL`). Convert
with `tools/jagcd/jagcd-to-chd` and the pinned `chdman` from the
`jagcd-tools-*.zip` release asset. It exits 2 on this disc, which means
"virtual pregaps present": a warning, not a failure.
These two rows are stamped with a newer cache id than the rest of the table.
The 2026-08-13 rows are stale (#735). On the current build the Myst CUE rows
also read `not_loop=0`, and bios reads `[FAIL]`. That is identical on v3.6.1
(`f9a3c89`), so it predates #750 and #755. Whether it is a regression or Myst
idling on a static screen at frame 3000 is for #735 to decide.
### Myst joined the sweep -- 2026-07-30
`Myst (USA).cue` was missing from this script's `CUE_TITLES` array even though
`cd_discover_discs()` has always found it in the corpus -- the matrix simply
never asked for it. It now has rows: **`GAME_CODE 1/1` in both hle and bios**,
matching the independent evidence already on record (`cd_wedge_probe` runs
clean in both modes; `cd_visual_verify` gives avg RMS 2548 bios / 2698 hle,
both in envelope).
Two things worth recording, because neither matches the assumption that
prompted the addition:
- **The `$004000`-`$007FFF` band gate is not what makes Myst pass.** Myst's
boot executable does load at `$005000`-`$01D380` (`src/cd/jagcd_bios.c:45`),
inside the shared band, so it looked like a fourth title the pre-5a83d3d
unconditional rule would have mislabelled `BIOS_INTRO`. It is not: at 3000
frames the sampled PC is already well past that code -- `final_pc=$00CA64`
(hle), `$00F1A4` (bios), both outside the band. Sampling Myst much earlier
would be needed to land in it.
- **The bios row's `cd_seek_wedge` line was a false positive** (fixed in
#741): Myst goes CD-idle for ~6s during the intro movie's all-black pause,
with the transfer finished (BUTCH bit 0 cleared). The watchdog no longer
counts that window. The hle row shows the same window as `video_stall`.
Neither is a failure.
Adding a title also exposed a latent bug in this script, fixed in the same
commit: new rows were appended to EOF instead of into the results table. On a
fresh generation the table is the last thing in the file so it made no
difference, but on a resume against this doc -- which carries several hundred
lines of prose notes after the table -- a new title's rows landed outside the
block `find_row_lineno` scans. The guard could never see them, so the title
re-ran on every invocation and appended another duplicate each time. Only
adding a title to `CUE_TITLES` can trigger it, which is why it survived this
long.
### `baldies.cdi` must be regenerated with `cue2cdi`, not taken from the ROM set
Recorded because it cost a full sweep to work out, and the next person to
rebuild the corpus will hit it again.
The corpus's `baldies.cdi` is **not** the `baldies.cdi` that ships with the
ROM set. It is generated from the CUE/BIN by `test/tools/cue2cdi`, which emits
the layout `src/cd/cdintf.c :: ParseCDI` walks natively. When
`test/roms/private` was rebuilt from a separate archive during this work the
ROM-set download was substituted, and both rows went backward -- `hle`
`GAME_CODE` -> `LOAD_FAIL`, `bios` `GAME_CODE` -> `BIOS_INTRO`. The two images
differ in size (61.7 MB generated vs 62.4 MB downloaded) and place track 2 at
different offsets (`$AB0270` vs `$B06490`); at the download's offset the
boot-stub reader finds zeros, logs `[CD-BOOTSTUB] Boot stub extraction
failed`, and the HLE load is refused.
Regenerating restores both rows exactly -- evidence strings identical to the
previous sweep, down to `ram_payload=18235B unique_pcs=29 final_pc=$05FE82`
(hle) and the whole of the bios row's `cd_seek_wedge` line:
```bash
./test/tools/cue2cdi \
"$ROMS/Baldies (USA) (Rev 1)/Baldies (USA) (Rev 1)/Baldies (USA) (Rev 1).cue" \
"$ROMS/baldies.cdi" --verify
```
This is **not** evidence that the downloaded image is bad. It is a legitimate
DiscJuggler image that our `ParseCDI` boot-stub path cannot read -- a real gap,
independent of every row in this table, and not tracked anywhere yet.
## Re-run notes -- 2026-07-29, branch fix/cd-fmv-bios-handoff @ 17375c3
Full re-sweep (3000 frames, `CD_MATRIX_TIMEOUT=400`, chunked via
`CD_MATRIX_MAX_RUNS`) after correcting the `$004000`-`$007FFF` stage rule
in `classify_stage()`. **Three rows moved forward, zero backward** -- and
no emulator code changed, because there was no emulator defect:
- **BrainDead 13 bios**: `BIOS_INTRO` -> **GAME_CODE** (`final_pc=$004FCA`)
- **Dragon's Lair bios**: `BIOS_INTRO` -> **GAME_CODE** (`final_pc=$004C12`)
- **Primal Rage bios**: `BIOS_INTRO` -> **GAME_CODE** (`final_pc=$0044CC`)
Every other row is unchanged in stage and score (all 20 rows 1/1
GAME_CODE in both modes). The at-risk bios rows the taxonomy change could
have disturbed -- Baldies, Battle Morph, Highlander, Hover Strike, Iron
Soldier 2, Space Ace -- all still report `GAME_CODE 1/1`. `final_pc` and
`unique_pcs` vary run to run inside `GAME_CODE` (the harness samples a
live game); that is not a stage move.
### Why these three rows were never stuck
`docs/cd-known-issues.md` item 1 recorded these as a real "FMV titles do
not hand off from the real BIOS" defect, with three ranked timing
candidates in `docs/cd-bizhawk-comparison.md`. It was none of them: the
band rule was wrong, and the rows were false negatives.
Method (the comparison doc's own prescribed first step -- disassemble the
loop instead of correlating against it). `cd_wedge_probe --arm N
--freeze-frames 0` forces a full state dump at a chosen frame, and the
snapshot was disassembled at each reported PC:
| Title | PC | What the code is | Polled address | Written by |
|---|---|---|---|---|
| Dragon's Lair | `$004C0A`-`$004C12` | `move.l $562E,d0 / cmp.l d0,d2 / bgt` | `$562E` | GPU PIT ISR (`$F0308A`), 30 Hz |
| BrainDead 13 | `$004FCA`-`$004FD2` | byte-identical code, `$72DA` instead | `$72DA` | GPU PIT ISR, 24 Hz |
| Primal Rage | `$004436`-`$0044EE` | joypad scan: writes `$817F/$81BF/$81DF/$81EF` to `$F14000`, de-interleaves via tables at `$44F0/$4510/$4530` | -- (not a poll loop) | -- |
Dragon's Lair and BrainDead 13 are both ReadySoft titles and share one
FMV player, linked at different addresses -- the instruction stream at
`$004BF0` and `$004FB0` is byte-for-byte identical. The loop waits for
the movie's presentation clock to reach the next frame's timestamp. That
clock is a 48-bit fixed-point accumulator (`$562E`.w integer :
`$5630`.l fraction) that the GPU's PIT ISR advances by a per-title
increment; it was **measured still advancing** across snapshots at frames
1200/1800/2400/2900 (DL: `$8E` -> `$1BA` -> `$2E6` -> `$3DF`, exactly
30.0/s; BD13: `$CD` -> `$1BD` -> `$2AC` -> `$374`, 24.0/s). Sampling
landed mid-wait for the next 1/30 s tick. Primal Rage was not even in a
loop -- its PC ring is a straight-line sweep through its input scanner.
Confirmed with `cd_visual_verify` in bios mode (screenshots read, not
just counted): Dragon's Lair plays its attract FMV (79.5% non-black,
avg RMS 1230); BrainDead 13 plays its castle-and-moon intro (68.1%,
RMS 2651); Primal Rage runs its full attract cycle -- "WHO WILL RULE THE
NEW URTH?", then DEMO gameplay with two dinosaurs fighting, then back to
the "JAGUAR VERSION 1.2" title screen (93.3%, RMS 980). Primal Rage
needed 6000 frames to show the cycle: its zero-motion windows
(3060-3359, 5280-5519) are black scene transitions, the same benign
pattern already documented for Myst, not a freeze.
The decisive datum needs no visuals at all: **Dragon's Lair's hle and
bios rows now both report `final_pc=$004C12`, and BrainDead 13's both
report `$004FCA`** -- the same instruction in the same player. Only the
bios path applied the band rule, so the same code was labelled
`GAME_CODE` in one mode and `BIOS_INTRO` in the other. Space Ace vs
Dragon's Lair (the control pair the comparison doc built its ranking on)
was likewise never "works vs stuck": Space Ace's copy of the same
ReadySoft player is linked at `$00B87A`, outside the band.
## Re-run notes -- 2026-07-27, branch feature/jaguar-cd-support @ 73438ba
Full re-sweep (3000 frames, CD_MATRIX_TIMEOUT=300) after four CD fixes.
**Five rows moved forward, zero backward:**
- **Battle Morph bios**: `? (pc_escape)` -> GAME_CODE 1/1 -- 8c9356b
(HLE stream status-struct base latched per CD_read; stops the
mid-stream ISR-setup shred of the game's uploaded GPU worker).
- **Iron Soldier 2 hle**: 0/1 -> 1/1 GAME_CODE -- 73438ba (game-installed
CD drivers own the transfer; HLE hooks step aside when their $4E75
stubs are overwritten) on top of bf4b7e8 (G_CTRL SINGLE_STEP honored,
which fixed the deeper match-load wedge in bios mode).
- **Baldies hle**: 0/1 -> 1/1 GAME_CODE -- 73438ba (FIFO interlock +
32-byte-batch progress cadence).
- **baldies.cdi hle + bios**: LOAD_FAIL (segv) -> GAME_CODE 1/1 both --
6fc874c/c5707c8 (canonical packed DiscJuggler track-block layout in
ParseCDI + single-file session-2 boot-stub extraction). NOTE: the
on-disk baldies.cdi asset was regenerated with the fixed cue2cdi
(9c82be1); files written by the pre-9c82be1 writer use a mirrored,
non-canonical layout and are invalid -- reconvert any old .cdi.
Final PCs now match the .cue rows exactly in both modes (CDI parity).
One transient during the sweep: Battle Morph bios first classified
HARNESS_HANG at the default 120s wall-clock while other heavy test
sweeps shared the host; re-run at CD_MATRIX_TIMEOUT=300 passes. Prefer
the longer timeout when the host is loaded.
## Re-run notes -- 2026-07-13, Task 6A fix (BUTCH -> GPU IRQ1 routing)
Five bios rows deleted + re-run after the Mechanism-A fix (3000 frames,
same knobs); all other rows are the earlier baseline.
- **Targets** -- Primal Rage / Highlander / Iron Soldier 2 (bios): the
FIFO-never-fills deadlock is gone. Primal Rage's watchdog line now shows
`gpu_pc=$00F03010` (executing the CD ISR; was foreground poll $F03060),
and a `VJ_CD_TRACE=1` run shows a live FIFO_FILL/FIFO_DRAIN stream with
the block counter advancing (116618 -> 118131 in 1500 frames; dsaIRQs
556791 -> 1, i2sEn=1). Highlander now records `fifo_drains=54` (was 0).
Stage labels have not advanced yet (Primal Rage still BOOT_STUB even at
a 12000-frame probe, 9.7M FIFO reads): the boot stub's sentinel scan
never matches despite real word-swapped sector data flowing -- that is
a separate downstream mechanism (data content/positioning), not the
Mechanism-A gate.
- **Controls** -- BrainDead 13 (bios) and Dragon's Lair (bios): stage,
score, and PC evidence identical to baseline (Dragon's Lair row is
byte-identical; BrainDead differs only in which watchdog signature got
logged first -- `cd_seek_wedge` vs `video_stall`, both fire at the same
frame, and its stalled gpu_pc moved $F03270 -> $F03276 within the same
GPU poll band; its game-band PC set `$124342 $124346 $12434C` is
unchanged). No regression.
- **HLE rows re-validated post-reroute** (BUTCHExec ticks for all
`bootConfig.isCDGame` modes, so the IRQ0->IRQ1 change is live in HLE
too): Primal Rage (hle), Iron Soldier 2 (hle), BrainDead 13 (hle)
deleted + re-run -- all three unchanged vs baseline (Primal Rage and
IS2 rows byte-identical; BrainDead identical stage/score/final_pc,
the re-run row merely adds the informational PC-SET game-band list).
No spurious $F03010 dispatches surfaced in HLE mode.
- **Provenance:** the reroute functionally reverts commit `3279b30`
("CD: fix BUTCH->GPU IRQ line - route to GPU IRQ0 (EXT1), not IRQ1
(DSP)", 2026-04-29), whose "$F03000 = EXT1" premise was unverified and
which self-declared "no behaviour change without the BUTCHExec
scheduler tick". The original IRQ1 routing it removed was correct.
## Re-run notes -- 2026-07-14, Task 6D fix ($2C00 TOC track-indexed layout)
Rewrote the $2C00 TOC injector (both `src/cd/jagcd_bios.c` and the HLE path's
`HLEPopulateTOC` in `src/cd/jagcd_hle.c`) to the authoritative track-indexed
layout produced by the real CD BIOS's own $2C00 TOC builder (disasm ROM
`$808BE8`: entry for track N at `$2C00 + N*8`, `byte[0]=track#`,
`byte[1..3]=start MSF`, `byte[4]=0-based session`). The old standalone
zero-longword marker slot terminated Baldies' `$4E18` scan early (deliberate
ILLEGAL) and left every `byte[4]` zero so the session-key match was
impossible; both defects fixed. The derivation is captured by the RED/GREEN contract test
`test/test_cd_toc_contract.c`.
Boot-mode determination: **outcome (c)** — `$2C00` is PRNG garbage at injection
time (the BIOS TOC builder never runs under the auth-bypass boot), so the
injected table must be correct itself.
**Writer provenance (reconciling prior project notes):** `$808BE8` is a
**68K routine in the BIOS ROM** — every quoted instruction is 68K
(`movem.l`/`lea`/`dbra`) and it polls BUTCH DSA responses directly at
`$DFFF0A` — not the DSP code the prior notes said the BIOS copies to
`$F1B000` to query the drive via BUTCH `$14xx` TOC requests. The two are
most plausibly different stages of one pipeline (DSP handles drive-level
transport; this 68K routine consumes the `$60`-`$64` DSA response words and
builds `$2C00`), but this disasm does not confirm the DSP stage either way —
the earlier "the DSP writes $2C00" belief was at minimum imprecise about
which processor does the writing. The layout's real validation anchors are
(1) the two independently disassembled game boot-stub scanners, which read
exactly this track-indexed format, and (2) the reviewer-reproduced GREEN on
the real Baldies disc. Note also that track-indexed and the old sequential
placement coincide byte-for-byte when track numbering is contiguous from 1
(as on real discs) — the load-bearing fixes are the removed zero-longword
marker slot and the byte[4] session stamp, not the indexing scheme itself.
**Contract-test scope:** `test_cd_toc_contract`'s Primal Rage MSF assertion
compares the injected table against `CDIntfGetTrackInfo()` — the injector's
own data source — so it proves copy fidelity into the scanner-visible
layout, NOT seek-target/LBA correctness (an H1-class pregap/offset bug would
still pass it); Primal Rage's marker-then-NEXT-entry path is likewise not
yet exercised end-to-end in-game (title blocked downstream of the TOC scan).
- **Target that moved -- Baldies (bios):** `HARNESS_HANG` (frame-437 ILLEGAL
halt; the boot stub's TOC scan returned -1) -> **`[PASS]` final_pc=$003610**,
now in the BIOS CD-read poll band with the CD stream live (seeks=1, i2sEn=1,
fifoReads=2.1M) -- the same downstream wall as Highlander/IS2. The ILLEGAL
halt is cleared.
- **Targets unchanged (different blockers) -- Primal Rage / Battle Morph
(bios):** Primal Rage still BOOT_STUB $0803AC (its blocker is the downstream
sentinel scan per Task 6A, not the TOC; the TOC is now faithfully
track-indexed and its `$0803E2` scanner lands on the correct track). Battle
Morph still pc-escapes at frame 437 ($8CA88044) -- **the Task 6B UNCONFIRMED
"derailment <-> TOC" link is now evidence-negative**: fixing the TOC did not
change it; its derailment is a distinct, still-uncharacterized mechanism.
- **HLE rows (targets -- HLE injector also fixed):** Primal Rage (hle)
`[PASS]` final_pc=$00419E and Iron Soldier 2 (hle) final_pc=$007416
uniq=3 -- both byte-identical to baseline (their blockers are not the TOC
scan; no regression).
- **Controls -- BrainDead 13 / Dragon's Lair / Highlander (bios):**
byte-identical to baseline (final_pc $00361E with game-band $124342/46/4C;
$0060D8; $003610 respectively). No regression.
- `make TEST_EXPORTS=1 test` exit 0 (56103/56103); c89-lint clean on both
touched src files. New run-gated harness `test/test_cd_toc_contract.c`
(needs `VJ_TOC_DISC`).
## Diagnosis (Task 5) -- 2026-07-13, branch feature/jaguar-cd-support @ 5827940
Trace-based root-cause analysis of the BIOS-mode boot failures, using the
Task 4 instrumentation (`VJ_CD_TRACE=1`, `test/test_cd_bios_boot` /
`test_cd_hle_boot`, 1500 frames). Every classification below cites trace
lines, `[CD-DIAG]` counters, register values, or disassembly. Temporary
per-register counters (`[T5-DIAG]`) were added to `src/cd/cdrom.c` for the
run, cited here, and reverted -- they are NOT in the tree. Two distinct
mechanisms account for all four failure classes.
### Mechanism A -- I2S FIFO never enabled after seek (FIFO-wait deadlock)
> **RESOLVED (Task 6A, 2026-07-13).** Attribution is now CONFIRMED: our
> emulation asserted the wrong GPU IRQ line. `BUTCHExec` raised GPU IRQ0
> (CPU-sourced, vector $F03000) but the CD BIOS installs its CD-data ISR
> at **$F03010 = the GPU IRQ 1 vector** (DSP/JERRY source, JTRM vector =
> int# x 16), enables only G_FLAGS INT_ENA1 ($20), acks via INT_CLR1 and
> re-arms the JERRY external latch (J_INT=$0101) in its epilogue --
> BUTCH's eint enters through JERRY (butch.v line 83). With only
> INT_ENA1 set, our IRQ0 latch was permanently masked: instrumented run
> showed **zero GPU interrupt dispatches ever** (enable-bail x 2.4M,
> latch=$01 vs enable=$02), zero GPU BUTCH reads, zero I2CNTRL writes.
> The ISR's bit-2 setter (`BSET #2` at ISR +$4A on the BUTCH-bit-13
> branch) simply never ran. Fix: `GPUSetIRQLine(GPUIRQ_DSP, ...)` in
> `BUTCHExec`. Post-fix: dsaIRQs 556791 -> 1 (response consumed on first
> dispatch), i2sEn=1, FIFO fill/drain engine live (111k cycles / 1500
> frames). Remaining blocker for these titles is downstream (boot-stub
> sentinel scan never matches despite real word-swapped sector data
> flowing -- a data-content/positioning mechanism, tracked separately).
Affects: **Primal Rage (bios)** [class 1, BOOT_STUB $0803AC] and
**Highlander (bios)** [class 3]; **Iron Soldier 2 (bios)** [class 3] shares
the same deadlock with a partially-unresolved chain (see IS2 caveat below).
Verdict is split in two, at different confidence levels:
- **The deadlock itself -- CONFIRMED (airtight):** I2CNTRL bit 2
(`i2s_fifo_enabled`) is never set by any processor after the seek, so
`BUTCHExec`'s bit-2 FIFO-fill gate never opens, `FIFO_FILL` never fires,
and the guest polls forever.
- **Attribution (whose fault) -- UNCONFIRMED:** whether the guest *never
intends* to set bit 2 on this path, or a guest GPU CD-ISR is *supposed*
to set it but our GPU/IRQ emulation stalls it before it gets there, is
not resolved by this evidence (see below).
The DSA/seek handshake completes correctly. Primal Rage ring tail:
```
#7 DSA_TX $1244 #8 SEEK_START $1244 block=116618 #9 SEEK_DONE $0100 block=116618
[CD-DIAG] butchExec=786000 globalDisabled=229109 seeks=1 fifoIRQs=0 dsaIRQs=556791 fifoReads=2 cdPlaying=1 fifoReady=0 i2sEn=0
```
`SEEK_DONE` fires 100 ticks after `SEEK_START` (== `SEEK_DELAY_TICKS`), the
`$0100` "Found" response is queued -- the seek is NOT the problem. But **no
`FIFO_FILL` event ever appears** and `i2sEn=0`.
Root cause, confirmed by temporary per-register counters:
```
Primal Rage [T5-DIAG] dsDataReads=3 (afterSeek=0) i2cntrlWrites=6 (afterSeek=0) lastI2cWrite=$0001@PC$00365E i2cReg=$00000001
Highlander [T5-DIAG] dsDataReads=3 (afterSeek=0) i2cntrlWrites=6 (afterSeek=0) lastI2cWrite=$0001@PC$00365E i2cReg=$00000001
Iron Sold 2 [T5-DIAG] dsDataReads=8 (afterSeek=4) i2cntrlReads=5804936 i2cntrlWrites=10 (afterSeek=4) lastI2cWrite=$0011@PC$00365E i2cReg=$00100011
```
- The CD BIOS CD-read routine (PC `$00365E`) writes **I2CNTRL = $0001**
(bit 0 = `i2s_drive`, per `test/mister_ground_truth.h` butch.v map). It
**never sets bit 2 (`i2s_fifo_enabled`, mask $04)** -- for Iron Soldier 2
the last write is `$0011` (bits 0+4; bit 4 is the read-only FIFO-not-empty
*status* line, not the enable). `i2cReg` (live register bytes) confirms
bit 2 clear in every case.
- `src/cd/cdrom.c` `BUTCHExec()` gates FIFO fill on I2CNTRL bit 2
(`cdRam[I2CNTRL+3] & 0x04`, lines ~595 and ~622). With bit 2 never set,
the delayed-fill countdown perpetually re-arms (`fifoFillDelay = 1; //
Retry next tick`) and `fifoDataReady` never becomes true. FIFO never
fills; the guest polls forever (Primal Rage's boot stub at `$0803AC`;
Highlander/IS2 in the BIOS CD_read poll band `$003610`-`$0036BE`, which
longword-reads `$00DFFF00` = BUTCH status).
**Iron Soldier 2 caveat (confirmed root, scoped-UNCONFIRMED chain):** the
shared confirmed fact -- I2CNTRL bit 2 never set, `i2sEn=0`, `fifoReady=0` --
holds for IS2. But IS2's *exact* deadlock chain is not identical to Primal
Rage's: IS2 reads DS_DATA 4 times after the seek (`dsDataReads afterSeek=4`),
and the DS_DATA `$0100`-pop branch (`cdrom.c` ~763-773) sets
`fifoDataReady=true` *unconditionally* (independent of bit 2). Yet IS2 still
ends `fifoReady=0` with 5.8M FIFO_DATA reads and `fifo_drains=0`. Whether IS2
pops `$0100` at all and, if so, what re-clears `fifoDataReady` before a drain
completes is **not fully resolved** (would need a one-run `fifoDataReady`-
transition trace). So IS2 = same confirmed deadlock (bit 2 never set), with
its FIFO drain/refill interaction left UNCONFIRMED; the Primal Rage /
Highlander deadlock chain below is the airtight one.
**What the write counters do and do not prove.** The `[T5-DIAG]` counters
lived in the common `CDROMWriteWord`/`CDROMWriteByte` handlers -- the single
choke point every processor's CD-range writes funnel through
(`src/core/jaguar.c:480,623` for the 68K path, `:447,592` for the
`who`-tagged GPU/DSP/DMA path) -- so "no bit-2 write" holds for **all**
processors, and no write was mis-decoded or dropped (the values that were
written, $0001/$0011, are stored correctly; `i2cReg` reflects them). But
that only proves **no processor executed a bit-2 write**, NOT that the guest
never intended one. The CD-data path is architecturally driven by a guest
GPU CD-ISR that the CD BIOS uploads into GPU RAM -- `src/core/jaguar.c:762`
asserts GPU IRQ0 precisely "to drive the CD-data ISR". The trace signature
here -- 556k GPU IRQ0 assertions, GPU running (`gpu_run=1`, PC circling
`$F03060`-`$F03080` in GPU RAM), yet `dsDataReads afterSeek=0` and zero
post-seek I2CNTRL writes -- is equally consistent with **that guest ISR
firing but never completing its DSA-consume -> I2CNTRL handshake**, i.e.
the "our GPU/IRQ emulation breaks the path" branch. Attribution between
"guest never issues" and "guest ISR stalls under our GPU/IRQ emulation" is
therefore **UNCONFIRMED**.
Related confirmed symptom (cause vs effect unresolved, same ambiguity):
`dsDataReads afterSeek=0` for Primal Rage/Highlander means the `$0100` seek
response is **never consumed** via DS_DATA. `dsaResponseReady` stays latched
true, so `BUTCHExec` re-asserts GPU IRQ0 on every interrupt-enabled halfline
(`dsaIRQs=556791`) -- the DSCNTRL-read latch-clear at `cdrom.c:743` is on a
path that never runs here. If the guest GPU ISR is supposed to consume the
response and set bit 2, this un-consumed response and the IRQ storm are the
*same* stall observed from the DSA side, not a separate fault.
**Task 6 pointers (hardware-correctness is Task 6's call), three candidates
to resolve against JTRM/MiSTer butch.v -- in this order:**
1. **Determine whether the CD BIOS's uploaded GPU IRQ0 CD-ISR is expected to
consume the DSA response and set I2CNTRL bit 2 -- and if so, why our GPU
execution of it stalls** (disassemble the GPU-RAM ISR the BIOS uploads;
check its progress against the GPU PC band `$F03060`-`$F03080` observed
wedged). This MUST be resolved first: if the ISR is being blocked by a
GPU/IRQ emulation bug, any change to the FIFO gate would mask it.
2. Check MiSTer butch.v FIFO-fill logic: does hardware fill depend on bit 2
(`i2s_fifo_enabled`), bit 0 (`i2s_drive`), or seek-complete alone?
3. Only then decide whether the `cdrom.c` bit-2 gate is itself wrong. Do NOT
trust the cdrom.c comments claiming "the GPU ISR re-enables I2CNTRL
bit 2" as established fact -- the trace shows no such write occurs today,
but whether it *should* occur is exactly candidate 1.
### Mechanism B -- unpopulated 68K exception vectors in CD-BIOS mode
Affects: **Battle Morph (bios)** [class 2, pc_escape $8FBFB758] and
**Baldies (bios)** [class 4, reclassified from video_stall/HARNESS_HANG].
**CONFIRMED escape mechanism; exact exception trigger UNCONFIRMED.**
Both titles pc-escape at **exactly frame 437** from the same `prev_pc`, with
**no CD activity whatsoever** beforehand:
```
Battle Morph [PC-OOB] first oob at frame 437 PC=$8CA88044 [OOB-FROZEN] prev_pc=$8020A2 -> oob_pc=$8CA88044
Baldies [PC-OOB] first oob at frame 437 PC=$A7E08FA0 [OOB-FROZEN] prev_pc=$8020A2 -> oob_pc=$A7E08FA0
both [CD-DIAG] ... seeks=0 ... dsaIRQs=0 ... cdPlaying=0 i2sEn=0
```
- **`seeks=0`, `dsaIRQs=0`, `cdPlaying=0`**: the crash happens *before any
seek or CD read*. This **rejects the wrong-LBA / $2C00-TOC / 149-sector
pregap-MSF hypothesis** for these titles -- the MSF->LBA path never runs.
- The harness `[OOB-PREVBYTES $8020A2]` label is misleading: with
`prev_pc >= 0x200000` the dump offset falls back to 0
(`test/test_cd_bios_boot.c:231`), so those 32 bytes are actually **main
RAM $000000-$00001F -- the 68K exception vector table**:
`00 00 00 00 | 00 E0 00 08 | C6 E5 74 7A | 65 2A 09 AF | A7 E0 8F A0 ...`
= SSP=$0, reset=$00E00008 (valid), then bus-error/address-error/
illegal-instruction vectors = PRNG garbage. Vector $10 (illegal
instruction) = **$A7E08FA0**, which is exactly Baldies' escape target.
- Confirmed in code: in CD-BIOS mode `vjs.useJaguarBIOS = true`
(`libretro.c:1070`, `bootConfig.showBootROM`). `src/core/jaguar.c:831`
then copies only the first **8 bytes** (SSP + reset PC) from the boot ROM
into RAM, and the HLE exception-vector-stub block
(`src/core/jaguar.c:857-881`, which fills vectors 2-255 with RTE stubs) is
**gated on `!vjs.useJaguarBIOS`** and therefore skipped. The auth-bypass +
boot-stub-injection boot flow never runs the real BIOS code that would
populate them either. Result: any exception/interrupt after boot vectors
through PRNG garbage and the 68K pc-escapes.
Baldies' target `$A7E08FA0` is a direct hit on the dumped illegal-instruction
vector (RAM offset $10) -- the smoking gun. Battle Morph's `$8CA88044` does
NOT appear in the 32-byte RAM[0..31] dump, so it would sit in an un-dumped
higher vector slot (vectors 8-255, RAM $20-$3FF); Battle Morph is therefore
confirmed by the *shared code gate + identical crash signature*, not by a
located slot. Both titles inject large boot stubs (Battle Morph `$65290` @
`$004400`, Baldies `$4000` @ `$004000`) and take their fatal exception at
**exactly frame 437** (an identical deterministic onset across two unrelated
games -- consistent with a common BIOS/timing-driven trigger rather than
game data, though the trigger itself is not isolated here). An unexplained
detail worth flagging: both games escape from the *same* `prev_pc` under the
*same* deterministic PRNG-seeded vector table, yet land on *different*
targets (`$8CA88044` vs `$A7E08FA0`) -- i.e. they take different vector
slots (or RAM at those slots had already been overwritten differently by the
two boot stubs), which the 32-byte dump cannot distinguish.
#### Task 6B update — premise OVERTURNED by instruction-level disasm; this is a MASK, real cause is the $2C00 TOC
The Task-6 REQUIREMENT (disasm before trusting RTE stubs) was carried out.
It **rejects** the "populate vectors" fix for these two titles. Essentials:
- `prev_pc=$8020A2` is a **red herring**: the harness samples PC once per
frame (`test_cd_bios_boot.c:198,255`), so it only means "the 68K was in
this BIOS ROM→RAM copy loop (`cmpa.l a2,a0 / bcs.b`, cannot fault) at the
end of frame 436" — it is not instruction-adjacent to the fault.
- The **actual first fault** (logged from `cpuextra.c::Exception`, since
reverted) is a *synchronous CPU trap the loaded boot stub executes on its
own error path*, not an async interrupt:
```
Baldies: Exception nr=4 currpc=$004D54 op=$4AFC (68000 ILLEGAL) -> vec4 =$A7E08FA0 garbage
Battle Morph: Exception nr=10 currpc=$0507E2 op=$AFDE (Line-A word) -> vec10=$8CA71E78 garbage
```
- **Baldies**: coherent stub code `moveq #1,d0; jsr $4E18; tst.l d0; bpl
$004D56; move.w #$C000,$F00058; ILLEGAL`. `$4E18` is a TOC scanner
(`movea.l #$2C08,a0; movem.l (a0)+,d2-d3; tst.l d2; beq → moveq #-1,d0`).
Our injected TOC (`src/cd/jagcd_bios.c:96-121`) puts the session marker as
an 8-byte slot with **first longword = 0 at `$2C08`**, so the scanner's
first `tst.l d2` sees 0 and returns error (-1) → the stub deliberately traps
via ILLEGAL. **Root cause = the `$2C00` TOC format is incompatible with the
boot stub's scanner** (see `project_cd_toc_format.md`), NOT the vectors.
- **Battle Morph**: `currpc=$0507E2` is inside a **data region** (`7838 7834
7838 7834 …` run) — PC has derailed into data and executes it until hitting
the Line-A word. Uncharacterized derailment (PC-in-data proven; the
derailing jump not traced), likely downstream of the same loaded-data/TOC
path.
- **Anomaly resolved**: different vectors (4 vs 10) *and* once-per-frame
sampling landing mid-runaway. Vec 4 = `$A7E08FA0` re-faults on itself
(`$8888` = illegal) so Baldies' sampled PC == the raw vector; Battle Morph's
vec-10 target `$8CA71E78` differs from its sampled `$8CA88044` (which is
absent from the entire pristine 2 MB PRNG image) because its runaway
wandered before the frame-boundary sample.
**Verdict: populating vectors MASKS.** The existing HLE stub sets vector 4 =
plain `RTE`; the 68000 stacks PC *at* the illegal instruction, so `RTE`
returns to `$004D54` and re-executes ILLEGAL forever — Baldies would turn
`pc_escape` into a **wedge** while a "vectors populated" test goes GREEN
(PR#170 pattern). The same holds for Battle Morph's Line-A trap (vector 10
also stacks the faulting PC on a 68000, so plain `RTE` re-executes `$AFDE` =
wedge), and for the `jagcd_hle.c:934-949` "skip-2" ILLEGAL-handler variant
(`ADDQ.L #2,(2,SP); RTE`): skipping past the deliberate halt lets the stub
continue with `d0=-1` and garbage TOC state — an equally effective mask.
The real fix is the `$2C00` TOC layout (a different mechanism, needs the
authoritative MiSTer format) — tracked separately, **not under 6B**. Task 6B
outcome: **BLOCKED with artifacts**, no `src/` change.
**TOC defect spec for the fix task** (what the disasm establishes; resolve
the open points against MiSTer/BIOS-DSP ground truth, not guesswork):
1. **Defect (1) — marker slot terminates the scan.** The injector writes the
session-2 marker as an 8-byte slot whose first longword is 0 at `$2C08`
(marker byte `01` at `+4`); Baldies' `$4E18` scanner reads entries from
`$2C08` and treats a zero first longword as end-of-table → instant
`d0=-1`.
2. **Defect (2) — no entry carries the byte[4] key.** Even past the marker,
the scanner matches via `rol.l #8,d3; cmp.b d0,d3` — i.e. it compares the
search key against **entry byte[4]** (first byte of the second longword).
`jagcd_bios.c` writes only bytes [0..3] = `[track][min][sec][frm]` and
leaves [4..7] zero, so the key match can never succeed for any entry.
**A fix that only un-zeroes the marker still returns `d0=-1`.**
3. **Format-model question to resolve:** per-entry session/type byte at
offset [4] (structurally closer to what `$4E18` expects — it counts
*occurrences* of the key byte, consistent with "Nth entry of session S")
vs the current standalone-marker-slot design. Decide from MiSTer ground
truth, not by making one scanner happy.
4. **Two-scanner requirement:** any TOC layout must satisfy BOTH Baldies'
`$4E18` occurrence-counting scan AND Primal Rage's `$0803E2`
marker-then-NEXT-entry scan (`project_cd_toc_format.md`). The found-path
payload — which MSF fields the stub consumes from the matched entry
(`$4E48: ror.l #8,d3; bsr $4E54` onward) — is still unknown;
MiSTer/BIOS-DSP ground truth required before writing bytes.
5. **Frame-437 determinism, crisply:** the shared CD BIOS reaches the
`$050176` boot-stub injection hook at ~frame 437 in both titles; each
injected stub then faults within its first frame of execution. The
constant is a property of the deterministic BIOS boot sequence, not a
timer/interrupt.
### HLE-mode wrong-LBA spot check -- Iron Soldier 2 (hle)
**Wrong-LBA hypothesis REJECTED; failure is a repeated-read continuation
loop.** IS2 hle scores 0/1 with `not_thrash=0`. The `HLE_READ` sequence:
```
CD_read: D1='D8A' MSF=50:00:01 LBA=224851 dest=$00CB00 size=$14FE -> sentinel match at LBA 224857
CD_read: (identical) LBA=224851 ... -> repeated read -- resuming from LBA 224860 ... sentinel NOT found
CD_read: (identical) LBA=224851 ... -> repeated read -- resuming from LBA 224863 ... sentinel NOT found
... (+3 LBA per identical call, indefinitely: 224866, 224869, 224872, ...)
```
- MSF 50:00:01 -> LBA `((50*60+0)*75 + 1) - 150 = 224851`. Disc layout
(`[CD-LAYOUT]`) puts track 12 (session 2 boot/data) at startLBA 224391,
len 764 (ends 225155); **224851 is validly inside track 12** -- the LBA
and MSF->LBA math are correct.
- The game re-issues a byte-identical `CD_read` (same MSF/LBA/dest/size),
but the `jagcd_hle.c` "repeated read" heuristic advances the resume LBA by
+3 each call and reports "sentinel NOT found", so the game never receives
the data it expects and retries forever. The bug is the HLE
repeated-read/continuation logic, **not** MSF->LBA mapping.
#### Task 6C fix -- delete the continuation heuristic (CD_read is idempotent)
**Contract.** `CD_read` (`$303C`) is a discrete, self-contained read: `D0`
(packed MSF) fully specifies the source position, `A0`/`A1` the destination
range, `D1` the sync marker to lock onto in the I2S stream after the seek. A
re-issued byte-identical call re-seeks to the SAME position and reproduces the
SAME data. There is no per-call "continuation" pointer. This holds under both
readings of the real service (stateless-idempotent, or a BIOS that streams
internally): a repeat with an identical MSF is a *restart from the same
position* either way. The only reading in which the removed heuristic is
correct -- a BIOS that ignores the passed MSF and advances an internal pointer
-- is self-contradictory (why pass an MSF at all) and unsupported.
**Where the heuristic came from.** It was a tuned guess, not a disassembled
contract: the writeback `hle_next_lba = scanLBA + s` (post-transfer LBA) plus
the `hle_have_last` "repeated read -- resuming from LBA" block, extended by
commit `4844f6b` into the raw-fallback and counter-ID paths. The `+3/call`
IS2 saw is just `s` = ceil(0x14FE / 2352) = 3 sectors per transfer. The
comment admitted it "mimics the I2S stream that real hardware would still be
feeding" -- a fabricated streaming model layered on a stateless service.
**LBA trace, IS2 (hle), before vs after** (`VJ_CD_TRACE`/HLE_LOG, identical
`D0=$00320001 D1=$4438410B dest=$00CB00 size=$14FE` every call):
```
BEFORE (heuristic): AFTER (idempotent):
call 1: sync block @ LBA 224857 off 278 -> call 1: sync block @ LBA 224857 off 278
call 2: resume 224860, sentinel NOT found call 2: sync block @ LBA 224857 off 278
call 3: resume 224863, sentinel NOT found call 3: sync block @ LBA 224857 off 278
call N: resume 224857+3N, raw garbage call N: sync block @ LBA 224857 off 278
-> dest $00CB00 corrupted on every repeat -> dest $00CB00 stable (correct) every repeat
```
**RED/GREEN.** `test/test_cd_hle_idempotent.c` runs IS2 (hle) and counts how
many times the destination region `$00CB00..$00DFFF` changes content after it
is first populated. RED (heuristic present): 27 changes over 300 frames.
GREEN (heuristic removed): 0 changes. Golden-free, deterministic, game-agnostic.
**Matrix (current HEAD, before vs after the fix, matched frame budgets --
the older rows in the table below predate the HEAD~1 TOC-writer rewrite and
are stale for Baldies hle):**
| Row | Mode | Frames | BEFORE (heuristic) | AFTER (fix) |
|---|---|---|---|---|
| Iron Soldier 2 | hle | 3000 | FAIL not_thrash=0 unique=3 $007416 | FAIL not_thrash=0 unique=3 $007416 |
| Baldies | hle | 3000 | FAIL unique=3 $05FE0C | FAIL unique=3 $05FE0C |
| Primal Rage | hle | 3000 | PASS unique=14 $00419E | PASS unique=14 $00419E |
| BrainDead 13 | hle | 3000 | PASS unique=6 $1243BC | PASS unique=6 $1243BC |
| Dragon's Lair | hle | 3000 | PASS $005412 | PASS unique=60 $005412 |
| Primal Rage | bios | 300 | PASS/BIOS_INTRO $0059B0 | PASS/BIOS_INTRO $0059B0 |
| Baldies | bios | 300 | PASS/BIOS_INTRO $0059B0 | PASS/BIOS_INTRO $0059B0 |
All controls unchanged. bios rows are structurally unaffected -- the heuristic
lives only on the HLE path (`cd_boot_strategy_hle`).
**Honest outcome (necessary, not sufficient).** The fix provably stops the
corruption -- IS2's first read stays correct and idempotent on every repeat --
but IS2 (hle) does NOT boot past the loop: its harness verdict is unchanged
(`not_thrash=0`, 3 game-code PCs `$007416/$006F78/$006B74`, `final_pc=$007416`).
CD_poll reports completion (A0 reaches the GPU data pointer), so the residual
loop is downstream **game logic** re-issuing the read -- a separate defect from
the continuation heuristic (candidate: the game validates loaded state / awaits
a subsequent read that isn't modelled). Not re-tuned to force a boot.
Baldies (hle) does not issue repeated-identical reads at HEAD, so it neither
regressed nor advanced -- the "Baldies shares the heuristic" hypothesis is
**not** supported by the trace.
### Summary
| Class | Title(s) | Verdict | Mechanism |
|---|---|---|---|
| 1 | Primal Rage (bios) | deadlock FIXED (Task 6A) -- attribution was our IRQ0-vs-IRQ1 routing | Mechanism A resolved: BUTCH interrupt now lands on GPU IRQ1 ($F03010) where the BIOS CD-ISR lives; FIFO fills/drains live. Next blocker: boot-stub sentinel scan (separate mechanism) |
| 3 | Highlander (bios) | deadlock FIXED (Task 6A) | Same fix as class 1; fifo_drains now non-zero (was 0). Downstream progress blocked same as class 1 |
| 3 | Iron Soldier 2 (bios) | deadlock FIXED (Task 6A) / drain-chain caveat moot | Same fix; the previously-unresolved drain/refill oddity was a symptom of the never-dispatched ISR |
| 2 | Battle Morph (bios) | CONFIRMED escape / UNCONFIRMED trigger | Unpopulated 68K exception vectors in CD-BIOS mode -> exception vectors through garbage (Mechanism B); pre-CD-read, wrong-LBA rejected |
| 4 | Baldies (bios) | CONFIRMED | Same as class 2 (Mechanism B); reclassified from video_stall/HANG. video_stall is downstream of the frame-437 escape |
| -- | Iron Soldier 2 (hle) | wrong-LBA REJECTED | LBAs correct; repeated-read continuation loop in jagcd_hle.c |
## Re-run notes -- 2026-07-14, Task 8 fix (GPU delay-slot IRQ dispatch clobber)
Seven rows deleted + re-run after `fix(gpu): don't clobber IRQ dispatch
raised in a branch delay slot` (3000 frames, same knobs). Root cause and
byte-level evidence in `docs/cd-diagnosis/braindead13-second-wedge-diagnosis.md`:
the CD streaming ISR epilogue (`JUMP T,(Rret)` with an IMASK-clearing
G_FLAGS store in the delay slot) had its interrupt dispatch overwritten by
`gpu_opcode_jump/jr` applying the branch target after the delay slot ran --
IMASK stayed set forever and the CD ISR never fired again. This was the
post-first-load wedge: cd_seek_wedge / video_stall with G_FLAGS.IMASK stuck
and the GPU spinning in a foreground mailbox loop ($F03168 Primal Rage 2nd
engine, $F0327x BrainDead / Dragon's Lair / Space Ace class). Contract test:
`test/test_cd_second_transfer` (VJ_FIFO_DISC-gated).
- **BrainDead 13 (bios)** -- ADVANCED. Was: video_stall frame=739,
final_pc=$00361E, dsp_run=0 (the user-confirmed on-device logo wedge).
Now: logo load completes, the game issues a SECOND ~1 MB FMV streaming
read and completes it (38,915 fifo drains, IMASK clear), dsp now running,
final_pc=$00B2FA (new game-code band), unique_pcs 23->43, payload 25 kB.
The remaining video_stall is the game's frame-kick wait (headless-fb
class).
- **Primal Rage (bios)** -- ADVANCED to the HLE oracle's state. Was:
cd_seek_wedge, drains frozen 12,857 mid-scan, gpu wedged $F03168. Now:
transfer #2 runs to completion (drains 17,996; the engine's ISR signals
done by clearing BUTCH bit 0), gpu waits at $F031F6 with IMASK clear --
byte-for-byte the same wait state as the Primal Rage (hle) control row,
payload 6790B vs hle 6679B. The row logged `cd_seek_wedge` at the time:
drains legitimately stop after transfer completion (BUTCH bit 0 off), which
the watchdog could not then distinguish from a freeze. Fixed in #741 -- the
watchdog now requires BUTCH's master + FIFO interrupts to still be armed
and I2CNTRL FIFO data enabled.
- **Highlander (bios)** -- ADVANCED. Was: cd_seek_wedge with drains frozen
at 54 right after the first fills (same clobber, first ISR invocations).
Now: no seek wedge, gpu active at $F031C2, dsp running, final_pc=$0036BE
(CD service band, PC-SET suppressed at unique_pcs=38).
- **Dragon's Lair (bios)** (control, but itself an IMASK-wedge-class title:
its old stall had gpu_pc=$F0327A) -- moved FORWARD: BIOS_INTRO $0060D8 ->
CD service band $0036B8, unique_pcs 38->51, payload 23.4->27.2 kB,
stall deferred 840->1008.
- **Iron Soldier 2 (bios)** -- byte-identical row (its blocker is a
different, earlier mechanism; unaffected as expected).
- **Controls Primal Rage (hle), Iron Soldier 2 (hle)** -- byte-identical.
| Baldies (USA) (Rev 1).cue | bios | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=865 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03270 gpu_run=1 dsp_pc=$00F1B086 dsp_run=1 | [PASS] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=11957B unique_pcs=38 final_pc=$060106 |
| BrainDead 13 (USA).cue | bios | 0/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=957 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03270 gpu_run=1 dsp_pc=$00F1B084 dsp_run=1 | [FAIL] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=24918B unique_pcs=43 final_pc=$00B2FA |
| Dragon's Lair (USA).cue | bios | 1/1 | ? (BIOS service band $0-$3FFF; PC-SET suppressed, unique_pcs>32 -- game handoff undetermined) | [CRASH-DETECT] video_stall frame=1008 fb_hash=$4DE01878 unchanged for 300 frames gpu_pc=$00F03270 gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=27155B unique_pcs=51 final_pc=$0036B8 |
| Highlander - The Last of the MacLeods (USA).cue | bios | 1/1 | ? (BIOS service band $0-$3FFF; PC-SET suppressed, unique_pcs>32 -- game handoff undetermined) | [CRASH-DETECT] video_stall frame=920 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F031C2 gpu_run=1 dsp_pc=$00F1B07E dsp_run=1 | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=2726B unique_pcs=38 final_pc=$0036BE |
| Iron Soldier 2 (USA) (Songbird).cue | hle | 0/1 | GAME_CODE | (none) | [FAIL] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=0 ram_payload=474B unique_pcs=3 final_pc=$007416 |
| Iron Soldier 2 (USA) (Songbird).cue | bios | 1/1 | ? (BIOS service band $0-$3FFF; PC-SET showed no game-band entries) | [CRASH-DETECT] video_stall frame=760 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B04A dsp_run=1 | [PASS] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=584B unique_pcs=31 final_pc=$0036B8 |
| Primal Rage (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=530 fb_hash=$BFFF6779 unchanged for 300 frames gpu_pc=$00F031F6 gpu_run=1 dsp_pc=$00F1B0AE dsp_run=1 | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=6679B unique_pcs=14 final_pc=$00419E |
| Primal Rage (USA).cue | bios | 1/1 | ? (BIOS service band $0-$3FFF; PC-SET suppressed, unique_pcs>32 -- game handoff undetermined) | [CRASH-DETECT] cd_seek_wedge frame=958 seek_starts=2 seek_dones=2 fifo_drains=17996 unchanged for 300 frames gpu_pc=$00F031F6 gpu_run=1 dsp_pc=$00F1B0B0 dsp_run=1 | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=6790B unique_pcs=45 final_pc=$0036B8 |
## Re-run notes -- 2026-07-15, lost-wakeup fix (event-scheduled GPU CPUINT)
Full-table re-run (all 21 rows deleted + regenerated, 3000 frames, 120 s cap)
after the 68K/GPU lost-wakeup fix: GPU-raised CPUINT (G_CTRL bit 1, who==GPU,
68K not already stopped) is now delivered through the event scheduler at
(slice budget + GPU cycles consumed) usec instead of synchronously, so the
one-shot wakeup can no longer be consumed before the 68K executes the `stop`
of a command/stop/wait handshake. Raw logs: /tmp/cdmx_postfix.
- **BrainDead 13 (bios) -- THE TARGET -- ADVANCED.** Was: score 0/1,
final_pc=$00B2FA (the documented lost-wakeup deadlock loop), not_loop=0,
video_stall frame=957. Now: score 1/1, not_loop=1, unique_pcs 43->59,
ram_payload 24918->25309B, no video_stall; final_pc=$0036B8 is the BIOS
CD-read service band, i.e. the game is alive and streaming. A PC-band
sampler (3000 frames) confirms game-band execution from frame 438 and
`test/test_cd_lost_wakeup` (new, in `make test`) passes with a worst
halted-no-IRQ window of 1 frame (was: permanent).
- **Stage-column caveat for the three GAME_CODE -> `?` moves** (Baldies bios,
BrainDead 13 bios, and BIOS_INTRO -> `?` for Hover Strike / Space Ace bios):
the stage classifies the FINAL-frame PC only. Post-fix these titles spend
most frame boundaries inside the BIOS CD-read service band ($0-$3FFF)
because more interrupts flow and more disc I/O happens. Direct PC-band
sampling over all 3000 frames shows Baldies (bios) in game-band code for
522/3000 samples (first at frame 566) -- GAME_CODE is still reached; the
`?` is a sampling artifact, not a regression. Counter evidence agrees:
Baldies fifoIRQs 45895 with fifoReads 14.7M; Space Ace (bios) advanced from
seeks=1 to seeks=7 / drains=173466.
- **No row moved backward** on score or on evidence-verified stage; baldies.cdi
LOAD_FAIL and Battle Morph (bios) pc_escape are unchanged pre-existing
backlog items (see handoff doc section 5).
## Re-run notes -- 2026-07-15 (2), GPU internal-RAM LOADB/LOADW fix
Full-table re-run after fix(gpu) f13892b (internal byte/word loads perform a
32-bit read). All 21 rows IDENTICAL in score and stage to the previous run --
expected: the fix corrects decoded pixel VALUES (Cinepak FMV), which the
boot-stage taxonomy cannot observe. Visual confirmation is in
docs/cd-diagnosis/fmv-corruption-diagnosis.md (BrainDead 13 / Dragon's Lair
FMV now render pixel-perfect via cd_visual_verify screenshots).
Raw logs: /tmp/cdmx_loadb.
## Re-run notes -- 2026-07-15, I2CNTRL status-bit fix (f74ce09)
Full 21-row re-run after masking the read-only FIFO-not-empty status bit
(b4) on I2CNTRL writes. The pre-fix baseline had six bios rows wedged at
final_pc $36B2-$36C2 -- all the SAME BIOS end-of-transfer FIFO flush loop
("read FIFO_DATA; btst #4,I2CNTRL; bne", BIOS service code resident at
$3600) spinning on the stuck status bit. Post-fix:
- Baldies bios: "? BIOS service band" + cd_seek_wedge -> **1/1 GAME_CODE, no watchdog**
- Highlander bios: "? BIOS service band" + video_stall -> **1/1 GAME_CODE**
- Iron Soldier 2 bios: "? BIOS service band" -> **1/1 GAME_CODE**
- BrainDead 13 / Primal Rage bios: "? BIOS service band" -> BIOS_INTRO (final-frame
sampling label shift within the known artifact class; scores unchanged 1/1)
- Dragon's Lair bios: still "?" at the 3000-frame horizon, but now streams five
further transfer cycles (seeks 2 -> 10) and reaches its in-game CD error
handler (~frame 2760) -- next diagnosis target
- Everything else: unchanged
| Title | Mode | Score | Stage | Watchdog | PC evidence |
| Baldies (USA) (Rev 1).cue | hle | 0/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=302 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B088 dsp_run=1 | [FAIL] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=0 not_thrash=0 ram_payload=11731B unique_pcs=3 final_pc=$05FE0C |
| Baldies (USA) (Rev 1).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=22046B unique_pcs=52 final_pc=$05FE8A |
| Battle Morph (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=1359 fb_hash=$114AB567 unchanged for 300 frames gpu_pc=$00F031D8 gpu_run=0 dsp_pc=$00F1B57E dsp_run=1 | [PASS] Battle Morph (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=22157B unique_pcs=126 final_pc=$0046DC |
| Battle Morph (USA).cue | bios | 0/1 | ? (pc_escape) | (none) | [FAIL] Battle Morph (USA).cue : pc_in_ram=0 not_loop=1 not_thrash=1 ram_payload=32704B unique_pcs=256+ final_pc=$8FBFB758 |
| BrainDead 13 (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=1531B unique_pcs=6 final_pc=$1243BC; PC-SET game-band: $12438A $1243BC $12438C $12562C $1243BA |
| BrainDead 13 (USA).cue | bios | 1/1 | BIOS_INTRO | [CRASH-DETECT] cd_seek_wedge frame=1267 seek_starts=2 seek_dones=2 fifo_drains=38915 unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B084 dsp_run=1 | [PASS] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=27241B unique_pcs=61 final_pc=$004FD0 |
| Dragon's Lair (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=412 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14268B unique_pcs=60 final_pc=$005412 |
| Dragon's Lair (USA).cue | bios | 1/1 | ? (BIOS service band $0-$3FFF; PC-SET suppressed, unique_pcs>32 -- game handoff undetermined) | [CRASH-DETECT] video_stall frame=1007 fb_hash=$8BF6E404 unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B084 dsp_run=1 | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=28779B unique_pcs=82 final_pc=$00392A |
| Highlander - The Last of the MacLeods (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] dsp_pc_escape frame=128 pc=$FFFFCE03 (valid: $0-$E3FFFF or $F1B000-$F1CFFF) | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14552B unique_pcs=5 final_pc=$008D66 |
| Highlander - The Last of the MacLeods (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14922B unique_pcs=64 final_pc=$0088D8 |
| Hover Strike - Unconquered Lands (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Hover Strike - Unconquered Lands (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=15997B unique_pcs=19 final_pc=$065B36 |
| Hover Strike - Unconquered Lands (USA).cue | bios | 1/1 | ? (BIOS service band $0-$3FFF; PC-SET suppressed, unique_pcs>32 -- game handoff undetermined) | [CRASH-DETECT] video_stall frame=737 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03010 gpu_run=1 dsp_pc=$00F1B086 dsp_run=1 | [PASS] Hover Strike - Unconquered Lands (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=23447B unique_pcs=66 final_pc=$003544 |
| Iron Soldier 2 (USA) (Songbird).cue | hle | 0/1 | GAME_CODE | (none) | [FAIL] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=0 ram_payload=474B unique_pcs=3 final_pc=$007416 |
| Iron Soldier 2 (USA) (Songbird).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=19233B unique_pcs=68 final_pc=$00B66E |
| Primal Rage (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=530 fb_hash=$BFFF6779 unchanged for 300 frames gpu_pc=$00F031F6 gpu_run=1 dsp_pc=$00F1B0AE dsp_run=1 | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=6679B unique_pcs=14 final_pc=$00419E |
| Primal Rage (USA).cue | bios | 1/1 | BIOS_INTRO | [CRASH-DETECT] cd_seek_wedge frame=958 seek_starts=2 seek_dones=2 fifo_drains=17996 unchanged for 300 frames gpu_pc=$00F031F8 gpu_run=1 dsp_pc=$00F1B0AE dsp_run=1 | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=25933B unique_pcs=82 final_pc=$0044BC |
| Space Ace (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=529 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F0327A gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] Space Ace (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14565B unique_pcs=68 final_pc=$0055CC |
| Space Ace (USA).cue | bios | 1/1 | ? (BIOS service band $0-$3FFF; PC-SET suppressed, unique_pcs>32 -- game handoff undetermined) | [CRASH-DETECT] cd_seek_wedge frame=2496 seek_starts=7 seek_dones=7 fifo_drains=173466 unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] Space Ace (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29025B unique_pcs=63 final_pc=$00392A |
| baldies.cdi | hle | 0/1 | LOAD_FAIL (harness crash) | (none) | [CRASH] baldies.cdi : child died with signal 11 (Segmentation fault: 11) |
| baldies.cdi | bios | 0/1 | LOAD_FAIL (harness crash) | (none) | [CRASH] baldies.cdi : child died with signal 11 (Segmentation fault: 11) |
## Re-run notes -- 2026-07-15, FIFO transfer-rate fix (real 2x drive speed)
Full 21-row re-run after pacing FIFO refills at the hardware rate
(352,800 B/s; error-diffused 2.85-tick period) instead of the fixed 5-tick
~201 KB/s. The ReadySoft schedule-watchdog class (Dragon's Lair / Space Ace
"error reading CD" + looping-FMV retry) is fixed -- both titles stream FMV
continuously through 4200-frame visual runs with no watchdogs. Matrix
deltas vs the I2CNTRL-fix run:
- Hover Strike bios: "? BIOS service band" -> **1/1 GAME_CODE**
- Space Ace bios: "? BIOS service band" -> **1/1 GAME_CODE**
- Dragon's Lair bios: "?" -> BIOS_INTRO (final-frame sampling label; visual
run confirms continuous in-game FMV)
- Space Ace hle recorded HARNESS_HANG under heavy machine load (concurrent
visual runs); direct re-run exits normally with the known pre-existing
HLE stall (video_stall + silent audio, same as Dragon's Lair hle)
- Everything else unchanged
| Title | Mode | Score | Stage | Watchdog | PC evidence |
| Baldies (USA) (Rev 1).cue | hle | 0/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=302 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B088 dsp_run=1 | [FAIL] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=0 not_thrash=0 ram_payload=11731B unique_pcs=3 final_pc=$05FE0C |
| Baldies (USA) (Rev 1).cue | bios | 1/1 | GAME_CODE | [CRASH-DETECT] cd_seek_wedge frame=990 seek_starts=2 seek_dones=2 fifo_drains=45895 unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B086 dsp_run=1 | [PASS] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=21698B unique_pcs=58 final_pc=$05FE8A |
| Battle Morph (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=1359 fb_hash=$114AB567 unchanged for 300 frames gpu_pc=$00F031D8 gpu_run=0 dsp_pc=$00F1B57E dsp_run=1 | [PASS] Battle Morph (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=22157B unique_pcs=126 final_pc=$0046DC |
| Battle Morph (USA).cue | bios | 0/1 | ? (pc_escape) | (none) | [FAIL] Battle Morph (USA).cue : pc_in_ram=0 not_loop=1 not_thrash=1 ram_payload=32704B unique_pcs=256+ final_pc=$8FBFB758 |
| BrainDead 13 (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=1531B unique_pcs=6 final_pc=$1243BC; PC-SET game-band: $12438A $1243BC $12438C $12562C $1243BA |
| BrainDead 13 (USA).cue | bios | 1/1 | BIOS_INTRO | [CRASH-DETECT] cd_seek_wedge frame=1107 seek_starts=2 seek_dones=2 fifo_drains=38915 unchanged for 300 frames gpu_pc=$00F03270 gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=27663B unique_pcs=65 final_pc=$004FD0 |
| Dragon's Lair (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=412 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14268B unique_pcs=60 final_pc=$005412 |
| Dragon's Lair (USA).cue | bios | 1/1 | BIOS_INTRO | (none) | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29338B unique_pcs=65 final_pc=$004C10 |
| Highlander - The Last of the MacLeods (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] dsp_pc_escape frame=128 pc=$FFFFCE03 (valid: $0-$E3FFFF or $F1B000-$F1CFFF) | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14552B unique_pcs=5 final_pc=$008D66 |
| Highlander - The Last of the MacLeods (USA).cue | bios | 1/1 | GAME_CODE | [CRASH-DETECT] cd_seek_wedge frame=1743 seek_starts=4 seek_dones=4 fifo_drains=92617 unchanged for 300 frames gpu_pc=$00F031C2 gpu_run=1 dsp_pc=$00F1B07C dsp_run=1 | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=17876B unique_pcs=62 final_pc=$0088D8 |
| Hover Strike - Unconquered Lands (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Hover Strike - Unconquered Lands (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=15997B unique_pcs=19 final_pc=$065B36 |
| Hover Strike - Unconquered Lands (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Hover Strike - Unconquered Lands (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=17157B unique_pcs=71 final_pc=$05DA9E |
| Iron Soldier 2 (USA) (Songbird).cue | hle | 0/1 | GAME_CODE | (none) | [FAIL] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=0 ram_payload=474B unique_pcs=3 final_pc=$007416 |
| Iron Soldier 2 (USA) (Songbird).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29870B unique_pcs=39 final_pc=$00B542 |
| Primal Rage (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=530 fb_hash=$BFFF6779 unchanged for 300 frames gpu_pc=$00F031F6 gpu_run=1 dsp_pc=$00F1B0AE dsp_run=1 | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=6679B unique_pcs=14 final_pc=$00419E |
| Primal Rage (USA).cue | bios | 1/1 | BIOS_INTRO | [CRASH-DETECT] cd_seek_wedge frame=884 seek_starts=2 seek_dones=2 fifo_drains=17996 unchanged for 300 frames gpu_pc=$00F031F6 gpu_run=1 dsp_pc=$00F1B0AE dsp_run=1 | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=25894B unique_pcs=78 final_pc=$0044D0 |
| Space Ace (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Space Ace (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29417B unique_pcs=75 final_pc=$00B87A |
| baldies.cdi | hle | 0/1 | LOAD_FAIL (harness crash) | (none) | [CRASH] baldies.cdi : child died with signal 11 (Segmentation fault: 11) |
| baldies.cdi | bios | 0/1 | LOAD_FAIL (harness crash) | (none) | [CRASH] baldies.cdi : child died with signal 11 (Segmentation fault: 11) |
## Re-run notes -- 2026-07-16, SCLK synchronous-SSI-IRQ fix (b63fb7d)
Full 21-row re-run (fresh table, 3000 frames, 120 s cap) at b63fb7d
(`fix(jerry): SCLK write no longer fires the SSI interrupt synchronously`):
writing SCLK ($F1A150) no longer invokes JERRYI2SCallback() inside the
programming store; the first SSI interrupt is deferred one full I2S frame
period (JERRYRescheduleI2S), so a DSP audio module re-uploaded mid-boot
(park DSP -> upload -> D_PC -> DSPGO) finishes its register init before its
I2S handler can fire with the OLD module's registers still live. That stale
dispatch was the mechanism behind the recurring `dsp_pc_escape $FFFFCE03` /
video_stall class (the handler mixed a CD sample through stale r13 over its
own code at $F1B07C). Note this table also folds in the five CD fixes landed
since the previous (FIFO transfer-rate) table was generated (c336839,
0f22fac, 746cf4a, 0e30eed, 874330f) -- their combined matrix-visible delta
is nil outside the rows called out below.
- **Highlander (hle) -- THE TARGET -- dsp_pc_escape GONE.** Was:
`[CRASH-DETECT] dsp_pc_escape frame=128 pc=$FFFFCE03`, unique_pcs=5,
final_pc=$008D66. Now: no crash-detect signature at all, unique_pcs=10
(PC-SET all game-band: $00412C $005876 $008BBC ...), final_pc=$008BBC,
seeks=7, i2sEn=1, fifoIRQs=178636 -- the DSP survives the module
re-upload and the CD stream keeps flowing.
- **Space Ace (hle)** -- the previous table's HARNESS_HANG (recorded under
heavy machine load, already annotated there as a flake) recovered to the
known 1/1 GAME_CODE state (video_stall f529, final_pc=$0055CC,
unique_pcs=68), matching that section's direct re-run.
- **All other 19 rows byte-identical** to the previous table, including
the two rows this re-run targeted for confirmation: Dragon's Lair (bios)
(BIOS_INTRO, no watchdog, final_pc=$004C10) and Highlander (bios)
(GAME_CODE, final_pc=$0088D8).
- **Visual/audio confirmation** (cd_visual_verify, 3000 frames, bios mode,
this exact build) -- the boot-stage taxonomy cannot see "renders with
audio", so recorded here: Dragon's Lair streams FMV continuously through
frame 2999 (motion in every 60-frame window, avg change up to 25%, 79.5%
non-black), audio RMS 1234, zero crash-detect signatures. Highlander
renders ~98% non-black with sustained motion, audio RMS 1526.
- **Remaining open bug -- Highlander (bios) cd_seek_wedge.** The signature
fires at frame 1743 (seek_starts=4 seek_dones=4, fifo_drains frozen at
92617) and AGAIN at frame 2704 (seeks 6/6, drains 149967); the visual run
shows rendering, motion, and audio continue across both, and the run ends
with seeks=13, cdPlaying=1, i2sEn=1. Disc activity resumes after each
signature, so this is an intermittent drain stall (or a watchdog
false-positive during paused-drive gaps, same class as the Primal Rage
post-transfer note in the Task 8 section) rather than a terminal wedge --
next diagnosis target.
| Title | Mode | Score | Stage | Watchdog | PC evidence |
|---|---|---|---|---|---|
| Baldies (USA) (Rev 1).cue | hle | 0/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=302 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B088 dsp_run=1 | [FAIL] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=0 not_thrash=0 ram_payload=11731B unique_pcs=3 final_pc=$05FE0C |
| Baldies (USA) (Rev 1).cue | bios | 1/1 | GAME_CODE | [CRASH-DETECT] cd_seek_wedge frame=990 seek_starts=2 seek_dones=2 fifo_drains=45895 unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B086 dsp_run=1 | [PASS] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=21698B unique_pcs=58 final_pc=$05FE8A |
| Battle Morph (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=1359 fb_hash=$114AB567 unchanged for 300 frames gpu_pc=$00F031D8 gpu_run=0 dsp_pc=$00F1B57E dsp_run=1 | [PASS] Battle Morph (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=22157B unique_pcs=126 final_pc=$0046DC |
| Battle Morph (USA).cue | bios | 0/1 | ? (pc_escape) | (none) | [FAIL] Battle Morph (USA).cue : pc_in_ram=0 not_loop=1 not_thrash=1 ram_payload=32704B unique_pcs=256+ final_pc=$8FBFB758 |
| BrainDead 13 (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=1531B unique_pcs=6 final_pc=$1243BC; PC-SET game-band: $12438A $1243BC $12438C $12562C $1243BA |
| BrainDead 13 (USA).cue | bios | 1/1 | BIOS_INTRO | [CRASH-DETECT] cd_seek_wedge frame=1107 seek_starts=2 seek_dones=2 fifo_drains=38915 unchanged for 300 frames gpu_pc=$00F03270 gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=27663B unique_pcs=65 final_pc=$004FD0 |
| Dragon's Lair (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=412 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14268B unique_pcs=60 final_pc=$005412 |
| Dragon's Lair (USA).cue | bios | 1/1 | BIOS_INTRO | (none) | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29338B unique_pcs=65 final_pc=$004C10 |
| Highlander - The Last of the MacLeods (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14691B unique_pcs=10 final_pc=$008BBC |
| Highlander - The Last of the MacLeods (USA).cue | bios | 1/1 | GAME_CODE | [CRASH-DETECT] cd_seek_wedge frame=1743 seek_starts=4 seek_dones=4 fifo_drains=92617 unchanged for 300 frames gpu_pc=$00F031C2 gpu_run=1 dsp_pc=$00F1B07C dsp_run=1 | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=17876B unique_pcs=62 final_pc=$0088D8 |
| Hover Strike - Unconquered Lands (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Hover Strike - Unconquered Lands (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=15997B unique_pcs=19 final_pc=$065B36 |
| Hover Strike - Unconquered Lands (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Hover Strike - Unconquered Lands (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=17157B unique_pcs=71 final_pc=$05DA9E |
| Iron Soldier 2 (USA) (Songbird).cue | hle | 0/1 | GAME_CODE | (none) | [FAIL] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=0 ram_payload=474B unique_pcs=3 final_pc=$007416 |
| Iron Soldier 2 (USA) (Songbird).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29870B unique_pcs=39 final_pc=$00B542 |
| Primal Rage (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=530 fb_hash=$BFFF6779 unchanged for 300 frames gpu_pc=$00F031F6 gpu_run=1 dsp_pc=$00F1B0AE dsp_run=1 | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=6679B unique_pcs=14 final_pc=$00419E |
| Primal Rage (USA).cue | bios | 1/1 | BIOS_INTRO | [CRASH-DETECT] cd_seek_wedge frame=884 seek_starts=2 seek_dones=2 fifo_drains=17996 unchanged for 300 frames gpu_pc=$00F031F6 gpu_run=1 dsp_pc=$00F1B0AE dsp_run=1 | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=25894B unique_pcs=78 final_pc=$0044D0 |
| Space Ace (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=529 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F0327A gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] Space Ace (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14565B unique_pcs=68 final_pc=$0055CC |
| Space Ace (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Space Ace (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29417B unique_pcs=75 final_pc=$00B87A |
| baldies.cdi | hle | 0/1 | LOAD_FAIL (harness crash) | (none) | [CRASH] baldies.cdi : child died with signal 11 (Segmentation fault: 11) |
| baldies.cdi | bios | 0/1 | LOAD_FAIL (harness crash) | (none) | [CRASH] baldies.cdi : child died with signal 11 (Segmentation fault: 11) |
Raw per-run logs are not committed; re-run the script to regenerate.
## Re-run notes -- 2026-07-16, SCLK sync-SSI-IRQ fix + SSI head split + drive-silence gate
Regenerated @ ca82c5b (fixes since the 07-15 table: b63fb7d SCLK no longer
fires the SSI interrupt synchronously; 0e30eed independent SSI read head;
874330f paused/seeking drive delivers I2S silence; 746cf4a TOC track
durations; ca82c5b matrix tooling -- bare `make test/<bin>` linked an
unexecutable dylib via the built-in rule, which is why the first 07-16
regeneration attempt produced all-`?` rows).
9 of 21 rows changed; no regressions:
- **Highlander hle**: `dsp_pc_escape $FFFFCE03` watchdog -> `(none)` --
the SCLK synchronous-IRQ fix, exactly as verified in b63fb7d.
- **Dragon's Lair bios**: `video_stall f1008` -> `(none)`, stage now
BIOS_INTRO (was `? service band`).
- **Hover Strike bios / Iron Soldier 2 bios / Space Ace bios**: watchdog
signatures cleared, stage now GAME_CODE (handoff determined -- these
previously sat in `? (BIOS service band)`).
- **Highlander bios**: `video_stall f920` -> `cd_seek_wedge f1743` --
runs much further; the remaining wedge is the known open item noted in
b63fb7d's verification.
- **Baldies bios**: stage `?` -> GAME_CODE; cd_seek_wedge remains.
- **BrainDead 13 bios / Primal Rage bios**: stage `?` -> BIOS_INTRO
reclassification; cd_seek_wedge remains at slightly different frames.
Several `PC-SET suppressed` indeterminates resolved to real stages this
run -- fewer early wedges means the harness now emits the PC-SET dump.
## Re-run notes -- 2026-07-16, streamed HLE CD_read (a1f1ac1)
HLE CD_read now streams at the double-speed drive rate (352,800 B/s)
instead of completing instantly. Instant delivery overwrote game code
that was still executing inside the destination window (Hover Strike's
LVL6 mission load: 2/2 scripted-input lockups before, 0/16 after --
the "lockup when skipping cutscenes / starting a mission" reports).
Deltas vs the previous table; no regressions:
- **Baldies hle**: 0/1 FAIL (not_thrash=0, unique_pcs=3) -> **1/1
GAME_CODE** (unique_pcs=19) -- the game's load sequencing also relied
on observing streaming progress.
- Battle Morph hle / Primal Rage hle: PASS as before, richer PC sets
(126->147 / 14->21 unique).
- Everything else identical.
| Title | Mode | Score | Stage | Watchdog | PC evidence |
|---|---|---|---|---|---|
| Baldies (USA) (Rev 1).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=369 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03270 gpu_run=1 dsp_pc=$00F1B088 dsp_run=1 | [PASS] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=11739B unique_pcs=19 final_pc=$05FE0C |
| Baldies (USA) (Rev 1).cue | bios | 1/1 | GAME_CODE | [CRASH-DETECT] cd_seek_wedge frame=990 seek_starts=2 seek_dones=2 fifo_drains=45895 unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B086 dsp_run=1 | [PASS] Baldies (USA) (Rev 1).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=21698B unique_pcs=58 final_pc=$05FE8A |
| Battle Morph (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=302 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F030C8 gpu_run=1 dsp_pc=$00F1C072 dsp_run=1 | [PASS] Battle Morph (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=22157B unique_pcs=147 final_pc=$0046DC |
| Battle Morph (USA).cue | bios | 0/1 | ? (pc_escape) | (none) | [FAIL] Battle Morph (USA).cue : pc_in_ram=0 not_loop=1 not_thrash=1 ram_payload=32704B unique_pcs=256+ final_pc=$8FBFB758 |
| BrainDead 13 (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=1531B unique_pcs=10 final_pc=$12438A; PC-SET game-band: $124342 $12438A $1243BC $12438C $1257E8 $124396 $12434C $1243BA $125902 |
| BrainDead 13 (USA).cue | bios | 1/1 | BIOS_INTRO | [CRASH-DETECT] cd_seek_wedge frame=1107 seek_starts=2 seek_dones=2 fifo_drains=38915 unchanged for 300 frames gpu_pc=$00F03270 gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] BrainDead 13 (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=27663B unique_pcs=65 final_pc=$004FD0 |
| Dragon's Lair (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=412 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F03276 gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14268B unique_pcs=60 final_pc=$005412 |
| Dragon's Lair (USA).cue | bios | 1/1 | BIOS_INTRO | (none) | [PASS] Dragon's Lair (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29338B unique_pcs=65 final_pc=$004C10 |
| Highlander - The Last of the MacLeods (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14691B unique_pcs=20 final_pc=$00826E |
| Highlander - The Last of the MacLeods (USA).cue | bios | 1/1 | GAME_CODE | [CRASH-DETECT] cd_seek_wedge frame=1743 seek_starts=4 seek_dones=4 fifo_drains=92617 unchanged for 300 frames gpu_pc=$00F031C2 gpu_run=1 dsp_pc=$00F1B07C dsp_run=1 | [PASS] Highlander - The Last of the MacLeods (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=17876B unique_pcs=62 final_pc=$0088D8 |
| Hover Strike - Unconquered Lands (USA).cue | hle | 1/1 | GAME_CODE | (none) | [PASS] Hover Strike - Unconquered Lands (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=7254B unique_pcs=52 final_pc=$065B36 |
| Hover Strike - Unconquered Lands (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Hover Strike - Unconquered Lands (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=17157B unique_pcs=71 final_pc=$05DA9E |
| Iron Soldier 2 (USA) (Songbird).cue | hle | 0/1 | GAME_CODE | (none) | [FAIL] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=0 ram_payload=474B unique_pcs=3 final_pc=$007416 |
| Iron Soldier 2 (USA) (Songbird).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Iron Soldier 2 (USA) (Songbird).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29870B unique_pcs=39 final_pc=$00B542 |
| Primal Rage (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=620 fb_hash=$BFFF6779 unchanged for 300 frames gpu_pc=$00F031F6 gpu_run=1 dsp_pc=$00F1B0AC dsp_run=1 | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=0 not_thrash=1 ram_payload=6679B unique_pcs=21 final_pc=$00419E |
| Primal Rage (USA).cue | bios | 1/1 | BIOS_INTRO | [CRASH-DETECT] cd_seek_wedge frame=884 seek_starts=2 seek_dones=2 fifo_drains=17996 unchanged for 300 frames gpu_pc=$00F031F6 gpu_run=1 dsp_pc=$00F1B0AE dsp_run=1 | [PASS] Primal Rage (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=25894B unique_pcs=78 final_pc=$0044D0 |
| Space Ace (USA).cue | hle | 1/1 | GAME_CODE | [CRASH-DETECT] video_stall frame=529 fb_hash=$292A41FD unchanged for 300 frames gpu_pc=$00F0327A gpu_run=1 dsp_pc=$00F1B082 dsp_run=1 | [PASS] Space Ace (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=14565B unique_pcs=68 final_pc=$0055CC |
| Space Ace (USA).cue | bios | 1/1 | GAME_CODE | (none) | [PASS] Space Ace (USA).cue : pc_in_ram=1 not_loop=1 not_thrash=1 ram_payload=29417B unique_pcs=75 final_pc=$00B87A |
| baldies.cdi | hle | 0/1 | LOAD_FAIL (harness crash) | (none) | [CRASH] baldies.cdi : child died with signal 11 (Segmentation fault: 11) |
| baldies.cdi | bios | 0/1 | LOAD_FAIL (harness crash) | (none) | [CRASH] baldies.cdi : child died with signal 11 (Segmentation fault: 11) |
Raw per-run logs are not committed; re-run the script to regenerate.
Raw per-run logs: /Users/jmattiello/vj-remote/validation/release-3.10.0-final-b5e40090/cd (not committed; re-run to regenerate).