Skip to content

Commit 181b1b3

Browse files
JoeMattclaude
andcommitted
Add CD-debug instrumentation: post-auth poll/service dumps
Adds one-shot JaguarDumpMemWindow hooks in JaguarExecuteNew() for the game CD-event poll function ($081220), its flag area ($0008B398), and the BIOS service routines the game calls into ($00196446 DSP serial comms, $00194D18 CD-data processing). Also traces writes to the $0008B398 game flag. These dumps decoded the post-auth blocker: the BIOS service at $194D18 expects $001AE034 (data-present) and $001AE032 (bytes-remaining) to be non-zero, kicked by ($001AE00C & 0x2000). Our $0505FA stuff value of $20010001 lacks bit 13, so the kick path never triggers. Also adds .iso to libretro core's valid_extensions and headless.py docs. Co-Authored-By: Claude Opus 4.7 <[email protected]>
1 parent e6e696c commit 181b1b3

3 files changed

Lines changed: 53 additions & 3 deletions

File tree

libretro.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ void retro_get_system_info(struct retro_system_info *info)
807807
#endif
808808
info->library_version = "v2.1.0" GIT_VERSION;
809809
info->need_fullpath = true;
810-
info->valid_extensions = "j64|jag|cue|cdi|chd";
810+
info->valid_extensions = "j64|jag|cue|cdi|chd|iso";
811811
}
812812

813813
void retro_get_system_av_info(struct retro_system_av_info *info)

src/jaguar.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,43 @@ void M68KInstructionHook(void)
426426
JaguarWriteWord(0x001A6800, 0x0001, UNKNOWN);
427427
}
428428

429+
/* One-shot dump of the game's main poll function context once we
430+
* see the game executing at $081220. Helps decode the outer caller. */
431+
if (m68kPC == 0x081220)
432+
{
433+
static bool dumpedGamePoll = false;
434+
if (!dumpedGamePoll)
435+
{
436+
dumpedGamePoll = true;
437+
fprintf(stderr, "[CD-DUMP] Game poll function context @ $081220:\n");
438+
JaguarDumpMemWindow(0x081200, 0x20, 0x80);
439+
fprintf(stderr, "[CD-DUMP] Game CD-event flag area @ $0008B380:\n");
440+
JaguarDumpMemWindow(0x0008B380, 0x00, 0x40);
441+
}
442+
}
443+
444+
/* One-shot dump of the BIOS service routines the game calls into. */
445+
if (m68kPC == 0x196446)
446+
{
447+
static bool dumped196446 = false;
448+
if (!dumped196446)
449+
{
450+
dumped196446 = true;
451+
fprintf(stderr, "[CD-DUMP] BIOS service @ $00196446:\n");
452+
JaguarDumpMemWindow(0x196446, 0x10, 0x100);
453+
}
454+
}
455+
if (m68kPC == 0x194D18)
456+
{
457+
static bool dumped194D18 = false;
458+
if (!dumped194D18)
459+
{
460+
dumped194D18 = true;
461+
fprintf(stderr, "[CD-DUMP] BIOS service @ $00194D18:\n");
462+
JaguarDumpMemWindow(0x194D18, 0x40, 0x100);
463+
}
464+
}
465+
429466
}
430467
}
431468

@@ -782,6 +819,19 @@ void JaguarWriteWord(uint32_t offset, uint16_t data, uint32_t who)
782819
ramOff, data, GPUGetPC(), who);
783820
}
784821
}
822+
/* Track writes to the game's CD-event flag at $0008B398.
823+
* Game's poll function at $081220 returns RTS unless either
824+
* BUTCH bit13 (DSARX) or this longword is non-zero. We never
825+
* deliver BUTCH IRQs (game uses polling), so this flag is the
826+
* only path that wakes the game's main loop. */
827+
if (vjs.useCDBIOS && (ramOff == 0x08B398 || ramOff == 0x08B39A))
828+
{
829+
static uint32_t b398Count = 0;
830+
if (++b398Count <= 20)
831+
fprintf(stderr, "[CD-FLAG] $%06X = $%04X who=%u 68K_PC=$%06X GPU_PC=$%06X\n",
832+
ramOff, data, who,
833+
m68k_get_reg(NULL, M68K_REG_PC), GPUGetPC());
834+
}
785835
jaguarMainRAM[(offset+0) & 0x1FFFFF] = data >> 8;
786836
jaguarMainRAM[(offset+1) & 0x1FFFFF] = data & 0xFF;
787837
return;

test/headless.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
1616
Usage:
1717
source .venv-libretropy/bin/activate
18-
python test/headless.py <content.cue|.j64|.cdi> [--frames N] [--cd-bios retail|dev]
18+
python test/headless.py <content.cue|.j64|.cdi|.iso> [--frames N] [--cd-bios retail|dev]
1919
2020
The core is auto-detected from the repo root. The system_dir defaults to
2121
test/roms/private/ (where BIOSes are kept). Adjust via --system-dir.
@@ -46,7 +46,7 @@ def detect_core() -> Path:
4646

4747
def parse_args() -> argparse.Namespace:
4848
p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
49-
p.add_argument("content", help="Path to game content (.cue, .j64, .cdi, etc.)")
49+
p.add_argument("content", help="Path to game content (.cue, .j64, .cdi, .iso, etc.)")
5050
p.add_argument("--frames", type=int, default=600, help="Frames to run (default: 600)")
5151
p.add_argument("--cd-bios", choices=["retail", "dev"], default="retail",
5252
help="CD BIOS variant (default: retail)")

0 commit comments

Comments
 (0)