mirror of
https://github.com/libretro/virtualjaguar-libretro.git
synced 2026-11-07 04:36:00 -10:00
1147 lines
90 KiB
Markdown
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).
|