From 6042e8261366ec705a0825736c302fcb4e2eb08f Mon Sep 17 00:00:00 2001 From: Matthew Stanley <1379tech@gmail.com> Date: Sun, 9 Aug 2026 16:49:43 -0700 Subject: [PATCH] fix(cdrom): restore the "disc could not be mounted" check PR #110 dropped cdrom_init() is deliberately non-fatal -- BIOS-only targets run with an empty drive on purpose -- so when a disc IS requested and nothing mounts, the game boots into an empty drive and renders nothing. That is the "black screen on a .cue that works as a .bin" symptom. The earlier validate_disc_for_launch() pass cannot catch it: identify_disc() reads the data-track FILE directly, so a cue whose sheet the mounting reader rejects still earns a green "Disc verified" badge and the player is left staring at black with no explanation. Master reports the actual failure and names the likely cause; PR #110 dropped the check while keeping every part it depends on -- cdrom_has_disc() in cdrom.h, resolve_disc_path()/DiscPathResolution in disc_path.h, and launcher_warning() -- so only the call site and the disc_path.h include were missing. Block restored verbatim from origin/master. Verified no false positive: Tomba boots past cdrom_init into gameplay with a good disc (PSX_NO_LAUNCHER=1, reaches the in-game window). The negative case (a cue that verifies but will not mount) was not synthesised. Co-Authored-By: Claude Opus 5 (1M context) --- runtime/src/main.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/runtime/src/main.cpp b/runtime/src/main.cpp index 7fca8ca5..5efd5c0a 100644 --- a/runtime/src/main.cpp +++ b/runtime/src/main.cpp @@ -71,6 +71,7 @@ extern "C" void psx_event_step_conservative_env_init(void); #include "mod_runtime.h" #include "crc32.h" #include "disc_identity.h" +#include "disc_path.h" #include "iso_reader.h" /* text-image guard: extract the boot EXE from the disc */ #include "psx_keybinds.h" /* configurable keyboard->DualShock keybinds (keybinds.ini) */ @@ -10737,6 +10738,29 @@ session_reboot: std::fprintf(stdout, "psxrecomp: SPU float-shadow enabled (verified-enhancement)\n"); spu_init(); cdrom_init(disc_path_str.empty() ? NULL : disc_path_str.c_str()); + + /* A disc was requested but nothing mounted. cdrom_init() is non-fatal here + * (BIOS-only targets run with an empty drive on purpose), so without this + * check the game would boot into an empty drive and render NOTHING -- the + * "black screen on a .cue that works as a .bin" symptom. The earlier + * validate_disc_for_launch() pass cannot catch it: identify_disc() reads + * the data track FILE directly, so a cue whose sheet the mounting reader + * rejects still shows a green "Disc verified" badge. Report the actual + * failure instead of leaving the player staring at black. */ + if (!disc_path_str.empty() && !cdrom_has_disc()) { + const PSXRecompV4::DiscPathResolution r = + PSXRecompV4::resolve_disc_path(disc_path_str); + std::string detail = + "The disc image was found and verified, but the CD-ROM drive could " + "not mount it, so the game would boot with an empty drive.\n\n" + "Selected:\n" + disc_path_str; + if (r.mount != r.picked) detail += "\nMounted as:\n" + r.mount.string(); + if (!r.note.empty()) detail += "\n\n" + r.note; + detail += "\n\nIf this is a .cue, check that every FILE line it names " + "exists next to it; selecting the .bin directly also works."; + launcher_warning("Disc Could Not Be Mounted", detail); + return 1; + } for (const auto& route : warm_cd_routes) { cdrom_register_warm_route(route.arm_lba, route.lbas.data(), (int)route.lbas.size(),