Skip to content

Commit 152ebf3

Browse files
committed
nscsi/cd.cpp: Fixed no-disc status for Apple CD drive and implemented eject command. [R. Belmont]
- Dragging a CD into the Trash on MacOS now properly unloads it.
1 parent 574e71a commit 152ebf3

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

src/devices/bus/nscsi/cd.cpp

+38-9
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ nscsi_cdrom_device::nscsi_cdrom_device(const machine_config &mconfig, device_typ
8383
: nscsi_full_device(mconfig, type, tag, owner, clock)
8484
, image(*this, "image")
8585
, cdda(*this, "cdda")
86+
, m_removal_prevented(false)
8687
, bytes_per_block(bytes_per_sector)
8788
, lba(0)
8889
, cur_sector(0)
@@ -549,6 +550,7 @@ void nscsi_cdrom_device::scsi_command()
549550
case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
550551
// TODO: support eject prevention
551552
LOG("command %s MEDIUM REMOVAL\n", (scsi_cmdbuf[4] & 0x1) ? "PREVENT" : "ALLOW");
553+
m_removal_prevented = BIT(scsi_cmdbuf[4], 0);
552554
scsi_status_complete(SS_GOOD);
553555
break;
554556

@@ -883,11 +885,21 @@ void nscsi_cdrom_apple_device::device_start()
883885
}
884886

885887
/*
886-
The Apple II SCSI Card firmware demands that ASC on a failing TEST_UNIT_READY be either 0x28 or 0xb0.
887-
0x28 is MEDIA_CHANGED, 0xb0 is vendor-specific. If the drive returns the normal 0x3A for disc-not-present,
888+
The Apple II SCSI Card firmware demands that ASC on a failing TEST_UNIT_READY be either 0x28 or 0xB0.
889+
0x28 is MEDIA_CHANGED, 0xB0 is vendor-specific. If the drive returns the normal 0x3A for disc-not-present,
888890
the firmware assumes the drive is broken and retries the TEST_UNIT_READY for 60 seconds before giving up
889891
and booting the machine.
892+
893+
MacOS will see the normal 0x3A disc-not-present and simply disbelieve it and hammer on the drive while
894+
asking the user to format it because it's unreadable. 0xB0 makes it behave as expected.
890895
*/
896+
897+
void nscsi_cdrom_apple_device::return_no_cd()
898+
{
899+
sense(false, SK_NOT_READY, 0xb0);
900+
scsi_status_complete(SS_CHECK_CONDITION);
901+
}
902+
891903
void nscsi_cdrom_apple_device::scsi_command()
892904
{
893905
if (scsi_cmdbuf[0] != 8 && scsi_cmdbuf[0] != 0x28 && scsi_cmdbuf[0] != 0 && scsi_cmdbuf[0] != 0x03)
@@ -908,8 +920,7 @@ void nscsi_cdrom_apple_device::scsi_command()
908920
}
909921
else
910922
{
911-
sense(false, SK_NOT_READY, 0xb0);
912-
scsi_status_complete(SS_CHECK_CONDITION);
923+
return_no_cd();
913924
}
914925
break;
915926

@@ -1312,15 +1323,33 @@ void nscsi_cdrom_apple_device::scsi_command()
13121323
case APPLE_AUDIO_CONTROL:
13131324
LOG("command APPLE AUDIO CONTROL, size %d\n", scsi_cmdbuf[8]);
13141325

1315-
scsi_data_out(3, scsi_cmdbuf[8]);
1316-
scsi_status_complete(SS_GOOD);
1326+
if (image->exists())
1327+
{
1328+
scsi_data_out(3, scsi_cmdbuf[8]);
1329+
scsi_status_complete(SS_GOOD);
1330+
}
1331+
else
1332+
{
1333+
return_no_cd();
1334+
}
13171335
break;
13181336

13191337
case APPLE_EJECT:
13201338
LOG("command APPLE EJECT\n");
1321-
cdda->stop_audio();
1322-
m_stopped = true;
1323-
scsi_status_complete(SS_GOOD);
1339+
if (!m_removal_prevented)
1340+
{
1341+
cdda->stop_audio();
1342+
m_stopped = true;
1343+
image->unload();
1344+
sense(false, SK_NOT_READY, SK_ASC_MEDIUM_NOT_PRESENT);
1345+
scsi_status_complete(SS_GOOD);
1346+
}
1347+
else
1348+
{
1349+
LOG("Eject not allowed by PREVENT_ALLOW_MEDIA_REMOVAL\n");
1350+
sense(false, SK_ILLEGAL_REQUEST, 0x80); // "Prevent bit is set"
1351+
scsi_status_complete(SS_CHECK_CONDITION);
1352+
}
13241353
break;
13251354

13261355
case SC_READ_6:

src/devices/bus/nscsi/cd.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ class nscsi_cdrom_device : public nscsi_full_device
4343
virtual uint8_t scsi_get_data(int id, int pos) override;
4444
virtual void scsi_put_data(int buf, int offset, uint8_t data) override;
4545

46-
void return_no_cd();
46+
virtual void return_no_cd();
4747
static int to_msf(int frame);
4848

49+
bool m_removal_prevented;
50+
4951
private:
5052
static constexpr uint32_t bytes_per_sector = 2048;
5153

@@ -133,6 +135,7 @@ class nscsi_cdrom_apple_device : public nscsi_cdrom_device
133135
virtual void scsi_command() override;
134136
virtual bool scsi_command_done(uint8_t command, uint8_t length) override;
135137
virtual void scsi_put_data(int buf, int offset, uint8_t data) override;
138+
virtual void return_no_cd() override;
136139

137140
private:
138141
bool m_stopped;

0 commit comments

Comments
 (0)