diff --git a/src/emu/machine/t10mmc.c b/src/emu/machine/t10mmc.c index 3ed535873d6..a5dcdb74d57 100644 --- a/src/emu/machine/t10mmc.c +++ b/src/emu/machine/t10mmc.c @@ -17,7 +17,7 @@ void t10mmc::t10_start(device_t &device) device.save_item(NAME(last_lba)); device.save_item(NAME(num_subblocks)); device.save_item(NAME(cur_subblock)); - device.save_item(NAME(play_err_flag)); + device.save_item(NAME(m_audio_sense)); } void t10mmc::t10_reset() @@ -36,10 +36,20 @@ void t10mmc::t10_reset() m_sector_bytes = 2048; num_subblocks = 1; cur_subblock = 0; - play_err_flag = 0; + m_audio_sense = 0; } // scsicd_exec_command + +void t10mmc::abort_audio() +{ + if (m_cdda->audio_active()) + { + m_cdda->stop_audio(); + m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_STOPPED_DUE_TO_ERROR; + } +} + // // Execute a SCSI command. @@ -47,15 +57,26 @@ void t10mmc::ExecCommand() { int trk; + // keep updating the sense data while playing audio. + if (command[0] == SCSI_CMD_REQUEST_SENSE && m_audio_sense != SCSI_SENSE_ASC_ASCQ_NO_SENSE && m_sense_key == SCSI_SENSE_KEY_NO_SENSE && m_sense_asc == 0 && m_sense_ascq == 0) + { + if (m_audio_sense == SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS && !m_cdda->audio_active()) + { + m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_SUCCESSFULLY_COMPLETED; + } + + set_sense(SCSI_SENSE_KEY_NO_SENSE, (sense_asc_ascq_t) m_audio_sense); + + if (m_audio_sense != SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS) + { + m_audio_sense = SCSI_SENSE_ASC_ASCQ_NO_SENSE; + } + } + switch ( command[0] ) { - case 0x03: // REQUEST SENSE - m_phase = SCSI_PHASE_DATAIN; - m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] ); - break; - case 0x12: // INQUIRY - logerror("T10MMC: REQUEST SENSE\n"); + logerror("T10MMC: INQUIRY\n"); m_phase = SCSI_PHASE_DATAIN; m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] ); break; @@ -72,7 +93,7 @@ void t10mmc::ExecCommand() break; case 0x1b: // START STOP UNIT - m_cdda->stop_audio(); + abort_audio(); m_phase = SCSI_PHASE_STATUS; m_transfer_length = 0; break; @@ -104,7 +125,7 @@ void t10mmc::ExecCommand() cur_subblock = 0; } - m_cdda->stop_audio(); + abort_audio(); m_phase = SCSI_PHASE_DATAIN; m_transfer_length = blocks * m_sector_bytes; @@ -142,7 +163,7 @@ void t10mmc::ExecCommand() length = 4; } - m_cdda->stop_audio(); + abort_audio(); m_phase = SCSI_PHASE_DATAIN; m_transfer_length = length; @@ -168,13 +189,13 @@ void t10mmc::ExecCommand() if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO) { - play_err_flag = 0; m_cdda->start_audio(lba, blocks); + m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS; } else { logerror("T10MMC: track is NOT audio!\n"); - play_err_flag = 1; + set_sense(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_SENSE_ASC_ASCQ_ILLEGAL_MODE_FOR_THIS_TRACK); } m_phase = SCSI_PHASE_STATUS; @@ -184,6 +205,7 @@ void t10mmc::ExecCommand() case 0x48: // PLAY AUDIO TRACK/INDEX // be careful: tracks here are zero-based, but the SCSI command // uses the real CD track number which is 1-based! + logerror("T10MMC: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], blocks); lba = cdrom_get_track_start(cdrom, command[4]-1); blocks = cdrom_get_track_start(cdrom, command[7]-1) - lba; if (command[4] > command[7]) @@ -196,12 +218,19 @@ void t10mmc::ExecCommand() blocks = cdrom_get_track_start(cdrom, command[4]) - lba; } - if (blocks && cdrom) + trk = cdrom_get_track(cdrom, lba); + + if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO) { m_cdda->start_audio(lba, blocks); + m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS; + } + else + { + logerror("T10MMC: track is NOT audio!\n"); + set_sense(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_SENSE_ASC_ASCQ_ILLEGAL_MODE_FOR_THIS_TRACK); } - logerror("T10MMC: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], blocks); m_phase = SCSI_PHASE_STATUS; m_transfer_length = 0; break; @@ -218,10 +247,7 @@ void t10mmc::ExecCommand() break; case 0x4e: // STOP - if (cdrom) - { - m_cdda->stop_audio(); - } + abort_audio(); logerror("T10MMC: STOP_PLAY_SCAN\n"); m_phase = SCSI_PHASE_STATUS; @@ -259,14 +285,15 @@ void t10mmc::ExecCommand() if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO) { - play_err_flag = 0; m_cdda->start_audio(lba, blocks); + m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS; } else { logerror("T10MMC: track is NOT audio!\n"); - play_err_flag = 1; + set_sense(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_SENSE_ASC_ASCQ_ILLEGAL_MODE_FOR_THIS_TRACK); } + m_phase = SCSI_PHASE_STATUS; m_transfer_length = 0; break; @@ -287,7 +314,7 @@ void t10mmc::ExecCommand() cur_subblock = 0; } - m_cdda->stop_audio(); + abort_audio(); m_phase = SCSI_PHASE_DATAIN; m_transfer_length = blocks * m_sector_bytes; @@ -317,27 +344,6 @@ void t10mmc::ReadData( UINT8 *data, int dataLength ) switch ( command[0] ) { - case 0x03: // REQUEST SENSE - logerror("T10MMC: Reading REQUEST SENSE data\n"); - - memset( data, 0, dataLength ); - - data[0] = 0x71; // deferred error - - if (m_cdda->audio_active()) - { - data[12] = 0x00; - data[13] = 0x11; // AUDIO PLAY OPERATION IN PROGRESS - } - else if (play_err_flag) - { - play_err_flag = 0; - data[12] = 0x64; // ILLEGAL MODE FOR THIS TRACK - data[13] = 0x00; - } - // (else 00/00 means no error to report) - break; - case 0x12: // INQUIRY memset( data, 0, dataLength ); data[0] = 0x05; // device is present, device is CD/DVD (MMC-3) @@ -404,8 +410,6 @@ void t10mmc::ReadData( UINT8 *data, int dataLength ) { case 1: // return current position { - int msf; - if (!cdrom) { return; @@ -413,8 +417,6 @@ void t10mmc::ReadData( UINT8 *data, int dataLength ) logerror("T10MMC: READ SUB-CHANNEL Time = %x, SUBQ = %x\n", command[1], command[2]); - msf = command[1] & 0x2; - int audio_active = m_cdda->audio_active(); if (audio_active) { @@ -452,6 +454,7 @@ void t10mmc::ReadData( UINT8 *data, int dataLength ) last_phys_frame = last_lba; + int msf = command[1] & 0x2; if (msf) { int m,s,f; diff --git a/src/emu/machine/t10mmc.h b/src/emu/machine/t10mmc.h index 255ac9c3404..ae11b332071 100644 --- a/src/emu/machine/t10mmc.h +++ b/src/emu/machine/t10mmc.h @@ -24,6 +24,8 @@ protected: virtual void t10_start(device_t &device); virtual void t10_reset(); + void abort_audio(); + cdrom_image_device *m_image; cdda_device *m_cdda; cdrom_file *cdrom; @@ -33,7 +35,7 @@ protected: UINT32 last_lba; UINT32 num_subblocks; UINT32 cur_subblock; - UINT32 play_err_flag; + int m_audio_sense; }; #endif diff --git a/src/emu/machine/t10sbc.c b/src/emu/machine/t10sbc.c index 70040bb3554..e9c89a80386 100644 --- a/src/emu/machine/t10sbc.c +++ b/src/emu/machine/t10sbc.c @@ -34,11 +34,6 @@ void t10sbc::ExecCommand() { switch ( command[0] ) { - case 0x03: // REQUEST SENSE - m_phase = SCSI_PHASE_DATAIN; - m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] ); - break; - case 0x04: // FORMAT UNIT m_phase = SCSI_PHASE_STATUS; m_transfer_length = 0; @@ -123,8 +118,6 @@ void t10sbc::ExecCommand() void t10sbc::ReadData( UINT8 *data, int dataLength ) { - int i; - // if we're a drive without a disk, return all zeroes if (!disk) { @@ -134,14 +127,6 @@ void t10sbc::ReadData( UINT8 *data, int dataLength ) switch ( command[0] ) { - case 0x03: // REQUEST SENSE - data[0] = 0x80; // valid sense - for (i = 1; i < 12; i++) - { - data[i] = 0; - } - break; - case 0x12: // INQUIRY memset( data, 0, dataLength ); data[0] = 0x00; // device is direct-access (e.g. hard disk) diff --git a/src/emu/machine/t10spc.c b/src/emu/machine/t10spc.c index 1ffdc4ea8b7..8e6b18fd9a9 100644 --- a/src/emu/machine/t10spc.c +++ b/src/emu/machine/t10spc.c @@ -1,18 +1,32 @@ #include "t10spc.h" -#define SCSI_SENSE_SIZE 4 - void t10spc::t10_start(device_t &device) { device.save_item(NAME(command)); device.save_item(NAME(commandLength)); - device.save_item(NAME(m_phase)); device.save_item(NAME(m_transfer_length)); + device.save_item(NAME(m_phase)); + device.save_item(NAME(m_sense_key)); + device.save_item(NAME(m_sense_asc)); + device.save_item(NAME(m_sense_ascq)); + device.save_item(NAME(m_sense_information)); } void t10spc::t10_reset() { m_phase = SCSI_PHASE_BUS_FREE; + m_sense_key = 0; + m_sense_asc = 0; + m_sense_ascq = 0; + m_sense_information = 0; +} + +void t10spc::set_sense(sense_key_t key, sense_asc_ascq_t asc_ascq) +{ + m_sense_key = key; + m_sense_asc = (asc_ascq >> 8) & 0xff; + m_sense_ascq = asc_ascq & 0xff; + m_sense_information = 0; } void t10spc::ExecCommand() @@ -30,8 +44,19 @@ void t10spc::ExecCommand() break; case SCSI_CMD_REQUEST_SENSE: - m_phase = SCSI_PHASE_DATAOUT; - m_transfer_length = SCSI_SENSE_SIZE; + m_phase = SCSI_PHASE_DATAIN; + if (command[4] == 0) + { + m_transfer_length = 4; + } + else if (command[4] > 18) + { + m_transfer_length = 18; + } + else + { + m_transfer_length = command[ 4 ]; + } break; case SCSI_CMD_SEND_DIAGNOSTIC: @@ -51,11 +76,38 @@ void t10spc::ReadData( UINT8 *data, int dataLength ) switch( command[ 0 ] ) { case SCSI_CMD_REQUEST_SENSE: - data[ 0 ] = SCSI_SENSE_NO_SENSE; - data[ 1 ] = 0x00; - data[ 2 ] = 0x00; - data[ 3 ] = 0x00; + if (command[4] == 0) + { + data[0] = m_sense_asc & 0x7f; + data[1] = (m_sense_information >> 16) & 0x1f; + data[2] = (m_sense_information >> 8) & 0xff; + data[3] = (m_sense_information >> 0) & 0xff; + } + else + { + data[0] = 0x70; + data[1] = 0; + data[2] = m_sense_key & 0xf; + data[3] = (m_sense_information >> 24) & 0xff; + data[4] = (m_sense_information >> 16) & 0xff; + data[5] = (m_sense_information >> 8) & 0xff; + data[6] = (m_sense_information >> 0) & 0xff; + data[7] = 10; + data[8] = 0; + data[9] = 0; + data[10] = 0; + data[11] = 0; + data[12] = m_sense_asc; + data[13] = m_sense_ascq; + data[14] = 0; + data[15] = 0; + data[16] = 0; + data[17] = 0; + } + + set_sense(SCSI_SENSE_KEY_NO_SENSE, SCSI_SENSE_ASC_ASCQ_NO_SENSE); break; + default: logerror( "SCSIDEV unknown read %02x\n", command[ 0 ] ); break; diff --git a/src/emu/machine/t10spc.h b/src/emu/machine/t10spc.h index c56f203ef28..34d301b72fc 100644 --- a/src/emu/machine/t10spc.h +++ b/src/emu/machine/t10spc.h @@ -29,10 +29,32 @@ protected: int SCSILengthFromUINT8( UINT8 *length ) { if( *length == 0 ) { return 256; } return *length; } int SCSILengthFromUINT16( UINT8 *length ) { return ( *(length) << 8 ) | *(length + 1 ); } + enum sense_key_t + { + SCSI_SENSE_KEY_NO_SENSE = 0, + SCSI_SENSE_KEY_ILLEGAL_REQUEST = 5 + }; + + enum sense_asc_ascq_t + { + SCSI_SENSE_ASC_ASCQ_NO_SENSE = 0x0, + SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS = 0x0011, + SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_PAUSED = 0x0012, + SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_SUCCESSFULLY_COMPLETED = 0x0013, + SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_STOPPED_DUE_TO_ERROR = 0x0014, + SCSI_SENSE_ASC_ASCQ_ILLEGAL_MODE_FOR_THIS_TRACK = 0x6400 + }; + + void set_sense(sense_key_t key, sense_asc_ascq_t asc_ascq); + UINT8 command[ 32 ]; int commandLength; int m_transfer_length; int m_phase; + UINT8 m_sense_key; + UINT8 m_sense_asc; + UINT8 m_sense_ascq; + UINT32 m_sense_information; int m_sector_bytes; device_t *m_device; }; @@ -52,28 +74,4 @@ protected: #define SCSI_CMD_MODE_SELECT ( 0x15 ) #define SCSI_CMD_SEND_DIAGNOSTIC ( 0x1d ) -#define SCSI_SENSE_ADDR_VALID 0x80 -#define SCSI_SENSE_NO_SENSE 0x00 -#define SCSI_SENSE_NO_INDEX 0x01 -#define SCSI_SENSE_SEEK_NOT_COMP 0x02 -#define SCSI_SENSE_WRITE_FAULT 0x03 -#define SCSI_SENSE_DRIVE_NOT_READY 0x04 -#define SCSI_SENSE_NO_TRACK0 0x06 -#define SCSI_SENSE_ID_CRC_ERROR 0x10 -#define SCSI_SENSE_UNCORRECTABLE 0x11 -#define SCSI_SENSE_ADDRESS_NF 0x12 -#define SCSI_SENSE_RECORD_NOT_FOUND 0x14 -#define SCSI_SENSE_SEEK_ERROR 0x15 -#define SCSI_SENSE_DATA_CHECK_RETRY 0x18 -#define SCSI_SENSE_ECC_VERIFY 0x19 -#define SCSI_SENSE_INTERLEAVE_ERROR 0x1A -#define SCSI_SENSE_UNFORMATTED 0x1C -#define SCSI_SENSE_ILLEGAL_COMMAND 0x20 -#define SCSI_SENSE_ILLEGAL_ADDRESS 0x21 -#define SCSI_SENSE_VOLUME_OVERFLOW 0x23 -#define SCSI_SENSE_BAD_ARGUMENT 0x24 -#define SCSI_SENSE_INVALID_LUN 0x25 -#define SCSI_SENSE_CART_CHANGED 0x28 -#define SCSI_SENSE_ERROR_OVERFLOW 0x2C - #endif