From 9169cc84a29cd92c9252bee883a430d3e62d93c6 Mon Sep 17 00:00:00 2001 From: Jonathan Campbell Date: Thu, 29 Feb 2024 14:08:06 -0800 Subject: [PATCH] IDE: If the user mounts the empty CD-ROM drive "image", then always return "Medium Not Present" for Test Unit Ready and any attempt to read --- src/dos/cdrom.cpp | 2 +- src/dos/cdrom.h | 12 ++++++++++++ src/dos/cdrom_image.cpp | 1 + src/dos/dos_mscdex.cpp | 19 ++++++++++++------- src/hardware/ide.cpp | 36 ++++++++++++++++++++++++++++++------ 5 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/dos/cdrom.cpp b/src/dos/cdrom.cpp index 77c3016da56..3e0dbd49495 100644 --- a/src/dos/cdrom.cpp +++ b/src/dos/cdrom.cpp @@ -262,7 +262,7 @@ bool CDROM_Interface_Fake :: GetAudioStatus(bool& playing, bool& pause) { } bool CDROM_Interface_Fake :: GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) { - mediaPresent = true; + mediaPresent = !isEmpty; mediaChanged = false; trayOpen = false; return true; diff --git a/src/dos/cdrom.h b/src/dos/cdrom.h index 0c1effe9b38..8c615041da3 100644 --- a/src/dos/cdrom.h +++ b/src/dos/cdrom.h @@ -96,6 +96,12 @@ extern int CDROM_GetMountType(const char* path, int forceCD); class CDROM_Interface { public: + enum INTERFACE_TYPE { + ID_BASE=0, + ID_FAKE, + ID_IMAGE + }; + // CDROM_Interface (void); virtual ~CDROM_Interface (void) {}; @@ -143,6 +149,8 @@ class CDROM_Interface //! \brief TODO? virtual void InitNewMedia (void) {}; + + INTERFACE_TYPE class_id = ID_BASE; }; //! \brief CD-ROM interface to SDL 1.x CD-ROM support @@ -206,6 +214,10 @@ class CDROM_Interface_Fake : public CDROM_Interface bool ReadSectorsHost (void* buffer, bool raw, unsigned long sector, unsigned long num); bool LoadUnloadMedia (bool /*unload*/) { return true; }; + + CDROM_Interface_Fake() { class_id = ID_FAKE; } + + bool isEmpty = false; }; //! \brief Image CD-ROM interface diff --git a/src/dos/cdrom_image.cpp b/src/dos/cdrom_image.cpp index c06186325da..fad36448927 100644 --- a/src/dos/cdrom_image.cpp +++ b/src/dos/cdrom_image.cpp @@ -470,6 +470,7 @@ CDROM_Interface_Image::imagePlayer CDROM_Interface_Image::player; CDROM_Interface_Image::CDROM_Interface_Image(uint8_t subUnit) :subUnit(subUnit) { + class_id = ID_IMAGE; images[subUnit] = this; if (refCount == 0) { if (player.channel == NULL) { diff --git a/src/dos/dos_mscdex.cpp b/src/dos/dos_mscdex.cpp index 13ca9e771ca..8bfb20af1e8 100644 --- a/src/dos/dos_mscdex.cpp +++ b/src/dos/dos_mscdex.cpp @@ -300,13 +300,18 @@ int CMscdex::AddDrive(uint16_t _drive, char* physicalPath, uint8_t& subUnit) cdrom[numDrives] = new CDROM_Interface_Image((uint8_t)numDrives); break; case 0x02: // fake cdrom interface (directories) - cdrom[numDrives] = new CDROM_Interface_Fake; - if (!strcmp(physicalPath,"empty")) { - } - else { - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting directory as cdrom: %s",physicalPath); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: You won't have full MSCDEX support !"); - result = 5; + { + CDROM_Interface_Fake *fake = new CDROM_Interface_Fake; + cdrom[numDrives] = fake; + assert(fake->class_id == CDROM_Interface::INTERFACE_TYPE::ID_FAKE); + if (!strcmp(physicalPath,"empty")) { + fake->isEmpty = true; + } + else { + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting directory as cdrom: %s",physicalPath); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: You won't have full MSCDEX support !"); + result = 5; + } } break; default : // weird result diff --git a/src/hardware/ide.cpp b/src/hardware/ide.cpp index 28f724bad7a..d70f47efa71 100644 --- a/src/hardware/ide.cpp +++ b/src/hardware/ide.cpp @@ -464,6 +464,16 @@ bool IDEATAPICDROMDevice::common_spinup_response(bool trigger,bool wait) { } } + /* if the CD-ROM drive has mounted the empty drive, then ALWAYS return Medium Not Present */ + CDROM_Interface *cdrom = getMSCDEXDrive(); + if (cdrom) { + if (cdrom->class_id == CDROM_Interface::INTERFACE_TYPE::ID_FAKE) { + set_sense(/*SK=*/0x02,/*ASC=*/0x3A); /* Medium Not Present */ +// LOG_MSG("ATAPI: Medium Not Ready"); + return false; + } + } + switch (loading_mode) { case LOAD_NO_DISC: case LOAD_INSERT_CD: @@ -1183,9 +1193,16 @@ void IDEATAPICDROMDevice::on_atapi_busy_time() { status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE; } else { - LOG_MSG("ATAPI: Failed to read %lu sectors at %lu\n", - (unsigned long)TransferLength,(unsigned long)LBA); - set_sense(/*SK=*/0x03,/*ASC=*/0x11); /* Medium Error: Unrecovered Read Error */ + if (cdrom->class_id == CDROM_Interface::INTERFACE_TYPE::ID_FAKE) { + set_sense(/*SK=*/0x02,/*ASC=*/0x3A); /* Not Ready: Medium Not Present */ + LOG_MSG("ATAPI: Rejecting read %lu sectors at %lu as Medium Not Present\n", + (unsigned long)TransferLength,(unsigned long)LBA); + } + else { + set_sense(/*SK=*/0x03,/*ASC=*/0x11); /* Medium Error: Unrecovered Read Error */ + LOG_MSG("ATAPI: Failed to read %lu sectors at %lu\n", + (unsigned long)TransferLength,(unsigned long)LBA); + } feature = 0xF4; /* abort sense=0xF */ count = 0x03; /* no more transfer */ sector_total = 0;/*nothing to transfer */ @@ -1257,9 +1274,16 @@ void IDEATAPICDROMDevice::on_atapi_busy_time() { status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE; } else { - LOG_MSG("ATAPI: Failed to read %lu sectors at %lu\n", - (unsigned long)TransferLength,(unsigned long)LBA); - set_sense(/*SK=*/0x03,/*ASC=*/0x11); /* Medium Error: Unrecovered Read Error */ + if (cdrom->class_id == CDROM_Interface::INTERFACE_TYPE::ID_FAKE) { + set_sense(/*SK=*/0x02,/*ASC=*/0x3A); /* Not Ready: Medium Not Present */ + LOG_MSG("ATAPI: Rejecting read %lu sectors at %lu as Medium Not Present\n", + (unsigned long)TransferLength,(unsigned long)LBA); + } + else { + set_sense(/*SK=*/0x03,/*ASC=*/0x11); /* Medium Error: Unrecovered Read Error */ + LOG_MSG("ATAPI: Failed to read %lu sectors at %lu\n", + (unsigned long)TransferLength,(unsigned long)LBA); + } feature = 0xF4; /* abort sense=0xF */ count = 0x03; /* no more transfer */ sector_total = 0;/*nothing to transfer */