Skip to content

Commit d9baa7e

Browse files
JoeMattclaude
andcommitted
Overhaul CD subsystem: CUE/BIN parser, auth bypass, boot flow
cdintf: rewrite CUE parser for multi-file multi-session discs, add CDI format support, boot stub extraction, auth-zone redirect for redump-style dumps that strip pregap audio. cdrom/jaguar: improve BUTCH FIFO emulation, DSA command handling, add CD auth bypass for stripped-pregap dumps, boot stub injection hooks, GPU data phase intercept for HLE path. libretro: add HLE CD boot fallback when no external BIOS ROM found. Co-Authored-By: Claude Opus 4.6 <[email protected]>
1 parent 09ae30d commit d9baa7e

8 files changed

Lines changed: 1004 additions & 421 deletions

File tree

libretro.c

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ int64_t rfread(void* buffer, size_t elem_size, size_t elem_count, RFILE* stream)
2222
#include "jagdevcdbios.h"
2323
#include "jaguar.h"
2424
#include "cdintf.h"
25+
#include "jagcd_hle.h"
2526
#include "dac.h"
2627
#include "dsp.h"
2728
#include "joystick.h"
@@ -807,7 +808,7 @@ void retro_get_system_info(struct retro_system_info *info)
807808
#endif
808809
info->library_version = "v2.1.0" GIT_VERSION;
809810
info->need_fullpath = true;
810-
info->valid_extensions = "j64|jag|cue|cdi|chd|iso";
811+
info->valid_extensions = "j64|jag|cue|cdi|iso";
811812
}
812813

813814
void retro_get_system_av_info(struct retro_system_av_info *info)
@@ -1101,7 +1102,7 @@ bool retro_load_game(const struct retro_game_info *info)
11011102
jaguar_cd_mode = false;
11021103
cd_image_path[0] = '\0';
11031104

1104-
if (info->path && (has_extension(info->path, "cue") || has_extension(info->path, "chd")))
1105+
if (info->path && (has_extension(info->path, "cue") || has_extension(info->path, "cdi")))
11051106
{
11061107
jaguar_cd_mode = true;
11071108
strncpy(cd_image_path, info->path, sizeof(cd_image_path) - 1);
@@ -1112,13 +1113,12 @@ bool retro_load_game(const struct retro_game_info *info)
11121113
vjs.useCDBIOS = true;
11131114

11141115
/* Try to load an external CD BIOS from the system directory.
1115-
* The embedded CD BIOS data is scrambled and non-functional;
1116-
* a real BIOS dump is required for CD games to boot. */
1116+
* If no external BIOS is found, we'll use HLE (High-Level
1117+
* Emulation) to boot the CD game directly. */
11171118
cd_bios_loaded_externally = false;
11181119
if (!load_external_cd_bios())
11191120
{
1120-
/* No external BIOS found -- CD games won't boot.
1121-
* We still allow loading so users see a diagnostic screen. */
1121+
fprintf(stderr, "[CD] No external BIOS found — will use HLE boot path\n");
11221122
}
11231123
}
11241124

@@ -1158,40 +1158,32 @@ bool retro_load_game(const struct retro_game_info *info)
11581158
for (i = 0; i < videoWidth * videoHeight; ++i)
11591159
videoBuffer[i] = 0xFF00FFFF;
11601160

1161-
if (jaguar_cd_mode)
1161+
if (jaguar_cd_mode && cd_bios_loaded_externally)
11621162
{
1163-
/* The CD BIOS is a "cartridge" loaded at $800000. The standard
1164-
* boot ROM at $E00000 detects it, reads the header at $800404
1165-
* (entry point $802000), and jumps there.
1166-
*
1167-
* We load directly into jagMemSpace rather than using JaguarLoadFile()
1168-
* because ParseFileType() doesn't recognize the 256KB CD BIOS format. */
1169-
const uint8_t *cdBiosData;
1163+
/* Real BIOS path: The CD BIOS is a "cartridge" loaded at $800000.
1164+
* The standard boot ROM at $E00000 detects it, reads the header at
1165+
* $800404 (entry point $802000), and jumps there. */
1166+
const uint8_t *cdBiosData = external_cd_bios;
11701167
size_t cdBiosSize = 0x40000;
11711168

1172-
if (cd_bios_loaded_externally)
1173-
cdBiosData = external_cd_bios;
1174-
else
1175-
cdBiosData = (vjs.cdBiosType == CDBIOS_DEV)
1176-
? jaguarDevCDBootROM : jaguarCDBootROM;
1177-
11781169
memcpy(jagMemSpace + 0x800000, cdBiosData, cdBiosSize);
11791170
jaguarRunAddress = GET32(jagMemSpace, 0x800404);
11801171
jaguarCartInserted = true;
11811172
jaguarROMSize = cdBiosSize;
11821173

11831174
/* The boot ROM runs a GPU-based cart authentication check that loops
11841175
* forever in emulation (the GPU security code at $F032EC never
1185-
* converges). The boot ROM checks:
1186-
* 1. bit 0 of $800408 → if set, wait for GPU to finish
1187-
* 2. GPU RAM $F03000 → if == $03D0DEAD, jump to cart entry
1188-
* We skip the GPU wait by clearing bit 0 here (survives JaguarReset
1189-
* since jagMemSpace is not randomized). The GPU magic is written
1190-
* after JaguarReset() below since GPUReset() randomizes GPU RAM. */
1176+
* converges). Skip the GPU wait by clearing bit 0. */
11911177
jagMemSpace[0x80040B] &= 0xFE;
11921178
fprintf(stderr, "[CD-TRACE] Boot ROM wait bypass applied at $80040B (value now $%02X)\n",
11931179
jagMemSpace[0x80040B]);
11941180
}
1181+
else if (jaguar_cd_mode)
1182+
{
1183+
/* HLE path: no external BIOS — JaguarCDHLEBoot() will be called
1184+
* after JaguarReset() to set up the boot stub directly. */
1185+
jaguarCartInserted = false;
1186+
}
11951187
else
11961188
{
11971189
// Standard cartridge loading (need_fullpath=true, so load from file)
@@ -1230,6 +1222,16 @@ bool retro_load_game(const struct retro_game_info *info)
12301222

12311223
JaguarReset();
12321224

1225+
/* HLE CD boot: if CD mode and no external BIOS, boot via HLE.
1226+
* Must happen after JaguarReset() since reset clears RAM/GPU state. */
1227+
if (jaguar_cd_mode && !cd_bios_loaded_externally)
1228+
{
1229+
if (!JaguarCDHLEBoot())
1230+
{
1231+
fprintf(stderr, "[CD-HLE] HLE boot failed — falling back to diagnostic screen\n");
1232+
}
1233+
}
1234+
12331235
/* The frontend will load .srm data into our save buffer (returned by
12341236
* retro_get_memory_data) after this function returns but before the
12351237
* first retro_run(). We unpack it on the first frame. */

0 commit comments

Comments
 (0)