From eefe5912b6dc04d435bb9ddf36d049e5feccff6e Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Mon, 8 May 2023 19:05:12 +0200 Subject: [PATCH] ata/gdrom.cpp: overhaul (#11140) - ata/gdrom.cpp: Fix READ_TOC command, improve logging, add redbook playback & repeat, add basic CD status; - ata/gdrom.cpp: fix loopchk Maker/Model identify ATA command 0104; - ata/gdrom.h: flip is_ready() to true, fixes several hangs (cfr. hash/dc.xml) - sound/aica.cpp: fix EXTS[1] routing; - sega/dccons.cpp: fix dcfish gdrom region hookup regression; --- hash/dc.xml | 211 +++++++---- src/devices/bus/ata/gdrom.cpp | 684 +++++++++++++++++++++++++--------- src/devices/bus/ata/gdrom.h | 17 +- src/devices/sound/aica.cpp | 9 +- src/mame/sega/dccons.cpp | 25 +- src/mame/sega/dccons_m.cpp | 4 + 6 files changed, 681 insertions(+), 269 deletions(-) diff --git a/hash/dc.xml b/hash/dc.xml index 5366c50c791..8d76cc6030d 100644 --- a/hash/dc.xml +++ b/hash/dc.xml @@ -740,7 +740,8 @@ Black screen [GDROM] 2002 Sega @@ -1141,7 +1142,7 @@ Punts to BIOS at start of loading [GDROM] 2004 Pionesoft @@ -1222,7 +1223,7 @@ Punts to BIOS at start of loading [GDROM] 2001 NEC Interchannel @@ -1891,7 +1892,7 @@ Punts to BIOS at start of loading [GDROM] 2001 NEC Interchannel @@ -1914,7 +1915,8 @@ No [redbook] audio 2005 Pionesoft @@ -1982,7 +1984,8 @@ Punts to BIOS at start of loading [GDROM] 2000 Sega @@ -2229,7 +2232,7 @@ Optional [BBA] support 2004 Alchemist @@ -2417,7 +2420,9 @@ Punts to BIOS at start of loading [GDROM] 1999 ESP @@ -2440,7 +2445,7 @@ Punts to BIOS at start of loading [GDROM], locks up 2000 Visco @@ -3165,7 +3170,7 @@ Black screen [GDROM] 2002 Fujicom @@ -3238,7 +3243,8 @@ Punts to BIOS at start of loading [GDROM] 2001 Bimboosoft @@ -3343,7 +3349,8 @@ No [redbook] audio 2003 G.rev @@ -3769,7 +3776,7 @@ Built on Windows CE, requires [MMU] support 2003 Princess Soft @@ -3793,7 +3800,8 @@ Black screen [GDROM] 2001 NEC Interchannel @@ -3915,11 +3923,12 @@ Punts to BIOS at start of loading [GDROM] 2001 NEC Interchannel + @@ -4136,7 +4145,7 @@ Hangs on ADX logo with [drc] 2002 Abel @@ -4171,7 +4180,7 @@ Punts to BIOS at start of loading [GDROM] 2000 Sega @@ -4469,7 +4478,7 @@ Crashes after ADX logo with [drc] 2004 Milestone Inc. @@ -4487,7 +4496,7 @@ Punts to BIOS at start of loading [GDROM], locks up 2004 Milestone Inc. @@ -4512,7 +4521,7 @@ Punts to BIOS at start of loading [GDROM], locks up 2004 Milestone Inc. @@ -4777,7 +4786,7 @@ Built on Windows CE, requires [MMU] support 2003 Alchemist @@ -4801,7 +4810,7 @@ Punts to BIOS at start of loading [GDROM], locks up 2003 Alchemist @@ -5393,7 +5402,7 @@ Overly stretched [PVR] output (displays top right of actual screen, SCALER_CTL) 2001 AquaPlus @@ -5464,7 +5473,8 @@ Punts to BIOS at start of loading [GDROM] 2001 Sega @@ -5625,7 +5635,7 @@ Punts to BIOS at start of loading [GDROM] 2001 Sega @@ -5650,7 +5660,7 @@ Crashes at "Produced by Sega" 2001 Hackberry @@ -5852,7 +5862,8 @@ Punts to BIOS at start of loading [GDROM], locks up 2001 Media Factory @@ -6064,7 +6075,8 @@ Hangs at "Produced by Sega", [GDROM] keeps reading LBA=$afbe with REQ_ERROR 13h 2001 Princess Soft @@ -7384,7 +7396,7 @@ Black screen [GDROM] Hudson @@ -8145,7 +8157,7 @@ Hardlocks MAME if left idle on title screen with [drc] 2002 G.rev @@ -8348,7 +8360,7 @@ Punts to BIOS at start of loading [GDROM] 1999 Softbank @@ -8381,7 +8393,7 @@ No [redbook] audio 1999 Softbank @@ -8476,7 +8488,7 @@ No [redbook] audio 2000 Softbank @@ -8500,7 +8512,7 @@ No [redbook] audio 2000 Softbank @@ -8524,7 +8536,12 @@ No [redbook] audio 2000 Softbank @@ -8560,7 +8577,13 @@ No [redbook] audio 2000 Softbank @@ -8585,7 +8608,7 @@ No [redbook] audio 2000 Softbank @@ -8610,7 +8633,8 @@ No [redbook] audio 2001 Softbank @@ -8635,7 +8659,7 @@ No [redbook] audio 2001 Softbank @@ -8660,7 +8684,7 @@ No [redbook] audio 2001 Softbank @@ -11707,7 +11731,7 @@ Doesn't detect key repeat properly in main menu (inputs get stuck), [Maple] timi 2001 Capcom @@ -11730,7 +11754,7 @@ Punts to BIOS at start of loading [GDROM] 2001 Capcom @@ -11753,7 +11777,7 @@ Punts to BIOS at start of loading [GDROM] 2001 Capcom @@ -11817,7 +11841,7 @@ Punts to BIOS at start of loading [GDROM] 2002 NEC Interchannel @@ -12030,7 +12054,7 @@ Hardlocks MAME after event "how to play" with [drc] 2001 NetVillage @@ -12328,7 +12352,7 @@ Punts to BIOS at start of loading [GDROM] 2001 Abel @@ -12648,7 +12672,8 @@ Punts to BIOS at start of loading [GDROM] 1999 Video System @@ -13085,7 +13110,8 @@ Gameplay requires [PVR] user tile clip 2001 SNK @@ -13401,7 +13427,10 @@ Punts to BIOS at start of loading [GDROM], locks up 2001 Spike @@ -13431,7 +13460,8 @@ No [redbook] audio 2002 Broccoli @@ -13485,7 +13515,8 @@ Hangs at "Produced by Sega", [GDROM] reads LBA=$afd8 and $afdc (same as culdcept 2002 Broccoli @@ -13594,7 +13625,7 @@ Hangs at "Produced by Sega", [GDROM] reads LBA=$afd8 and $afdc (same as culdcept @@ -15229,7 +15260,7 @@ Hangs on FMV with [drc] 2001 Softmax @@ -15664,8 +15695,8 @@ Punts to BIOS at start of loading [GDROM] 2000 Sammy @@ -15752,7 +15783,7 @@ No [redbook] audio 2000 Sammy @@ -16029,7 +16060,7 @@ Optional [BBA] support Sega @@ -16191,7 +16222,8 @@ Built on Windows CE, requires [MMU] support 2001 NEC Interchannel @@ -16337,7 +16369,7 @@ Punts to BIOS at start of loading [GDROM] 2000 Capcom @@ -16569,7 +16601,8 @@ Built on Windows CE, requires [MMU] support 2001 Starfish-SD @@ -17009,7 +17042,7 @@ FMV draws [PVR] black pixels instead of transparent color 2002 ESP @@ -17175,7 +17208,7 @@ Punts to BIOS at start of loading [GDROM], locks up 1998 Imagineer @@ -17209,7 +17242,7 @@ No [redbook] audio 1998 Imagineer @@ -17331,7 +17364,7 @@ No [redbook] audio 2001 Datam Polystar @@ -17547,7 +17580,7 @@ Crashes on FMV with [drc] 2004 Symbio Planning @@ -17600,7 +17633,7 @@ Punts to BIOS at start of loading [GDROM] Visit @@ -17625,6 +17658,10 @@ No [redbook] audio Jeremy McGrath Supercross 2000 (USA) 2000 Acclaim Entertainment + @@ -17736,7 +17773,8 @@ No [redbook] audio 2000 Bimboosoft @@ -18488,7 +18526,9 @@ Built on Windows CE, requires [MMU] support 2007 Milestone Inc. @@ -18514,7 +18554,8 @@ Punts to BIOS at start of loading [GDROM], locks up 2004 Rain Software @@ -18671,7 +18712,7 @@ No [redbook] audio 2002 Alchemist @@ -18923,7 +18964,8 @@ Built on Windows CE, requires [MMU] support 2001 Success @@ -18948,7 +18990,8 @@ Punts to BIOS at start of loading [GDROM] 2002 Success @@ -19229,6 +19272,10 @@ Hangs after (skipped) FMV, keeps stuck at 0% on loading Legacy of Kain: Soul Reaver (USA) 2000 Eidos Interactive + @@ -19840,6 +19887,10 @@ Hangs after (skipped) FMV, keeps stuck at 0% on loading Maken X (USA) 1999 Sega + @@ -20808,7 +20859,7 @@ Built on Windows CE, requires [MMU] support 2002 FOG @@ -20831,7 +20882,7 @@ Punts to BIOS at start of loading [GDROM] 2002 FOG @@ -20874,7 +20925,8 @@ Punts to BIOS at start of loading [GDROM] 2002 NEC Interchannel @@ -21054,7 +21106,7 @@ Punts to BIOS at start of loading [GDROM] Ubisoft @@ -21502,7 +21554,7 @@ Built on Windows CE, requires [MMU] support 2000 Sega @@ -21584,6 +21636,9 @@ Crashes at "Produced by Sega", PC=C010094 Mr. Driller (USA) 2000 Namco + @@ -23939,7 +23994,7 @@ cfr. https://github.com/mamedev/mame/issues/9106 for more info. Sega diff --git a/src/devices/bus/ata/gdrom.cpp b/src/devices/bus/ata/gdrom.cpp index 135cbcb66b4..a362bf5cb18 100644 --- a/src/devices/bus/ata/gdrom.cpp +++ b/src/devices/bus/ata/gdrom.cpp @@ -8,18 +8,25 @@ #include "emu.h" #include "gdrom.h" +#include "coreutil.h" + +#include #define LOG_WARN (1U << 1) #define LOG_CMD (1U << 2) -#define LOG_XFER (1U << 3) +#define LOG_CMD_RAW (1U << 3) // bare command IDs (temp until all commands are in) +#define LOG_XFER (1U << 4) +#define LOG_TOC (1U << 5) // TOC frame offsets -#define VERBOSE (LOG_WARN | LOG_CMD) +#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_CMD | LOG_TOC) //#define LOG_OUTPUT_STREAM std::cout #include "logmacro.h" #define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) #define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__) +#define LOGCMDRAW(...) LOGMASKED(LOG_CMD_RAW, __VA_ARGS__) #define LOGXFER(...) LOGMASKED(LOG_XFER, __VA_ARGS__) +#define LOGTOC(...) LOGMASKED(LOG_TOC, __VA_ARGS__) #define GDROM_BUSY_STATE 0x00 #define GDROM_PAUSE_STATE 0x01 @@ -32,6 +39,8 @@ #define GDROM_RETRY_STATE 0x08 #define GDROM_ERROR_STATE 0x09 +// CD status readback/subchannel Q +#define LIVE_REQ_STAT 0 /* Officially not documented security-related packet commands: @@ -161,6 +170,8 @@ void gdrom_device::device_reset() GDROM_Cmd11_Reply[i] = GDROM_Def_Cmd11_Reply[i]; atapi_cdrom_device::device_reset(); + + m_cdda->set_cdrom(m_image); } // scsicd_exec_command @@ -169,29 +180,201 @@ void gdrom_device::device_reset() void gdrom_device::ExecCommand() { + LOGCMDRAW("%02x\n", command[0]); switch ( command[0] ) { - case 0x11: // REQ_MODE + case 0x00: + // TEST_UNIT + // TODO: verify if t10mmc use is enough + // loopchk returns OK in Packet cmnd (0201) + t10mmc::ExecCommand(); + break; + + case 0x10: + { + transferOffset = command[2]; + u8 allocation_length = SCSILengthFromUINT8( &command[ 4 ] ); + // any game that enables [redbook] + LOGCMD("REQ_STAT 10h offset %02x length %02x\n", transferOffset, allocation_length); + + if (transferOffset || allocation_length != 0xa) + throw emu_fatalerror("GDROM: REQ_STAT with unsupported offset %02x length %02x", transferOffset, allocation_length); + m_phase = SCSI_PHASE_DATAIN; m_status_code = SCSI_STATUS_CODE_GOOD; - LOGCMD("REQ_MODE %02x %02x %02x %02x %02x %02x\n", - command[0], command[1], - command[2], command[3], - command[4], command[5] - ); + m_transfer_length = allocation_length; + break; + } + + case 0x11: + LOGCMD("REQ_MODE 11h %02x %02x\n", command[2], command[4]); + m_phase = SCSI_PHASE_DATAIN; + m_status_code = SCSI_STATUS_CODE_GOOD; + // if (SCSILengthFromUINT8( &command[ 4 ] ) < 32) return -1; transferOffset = command[2]; m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] ); + if (transferOffset & 1) + throw emu_fatalerror("GDROM: REQ_MODE with odd offset %02x %02x", transferOffset, m_transfer_length); break; case 0x12: // SET_MODE + LOGCMD("SET_MODE 12h %02x %02x\n", command[2], command[4]); + m_phase = SCSI_PHASE_DATAOUT; m_status_code = SCSI_STATUS_CODE_GOOD; //transferOffset = command[2]; m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] ); - LOGCMD("SET_MODE %02x %02x\n", command[2], command[4]); + if (command[2]) + throw emu_fatalerror("GDROM: SET_MODE with offset %02x %02x", transferOffset, m_transfer_length); + + if (m_transfer_length > 0xa) + { + LOGWARN("SET_MODE attempt to write on read only regs %02x\n", command[4]); + m_transfer_length = 0xa; + } break; + case 0x14: + { + if (!m_image->exists()) + { + m_phase = SCSI_PHASE_STATUS; + m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION; + m_transfer_length = 0; + break; + } + + // TODO: it's supposed to write a single and a double density TOC request + //if (command[1]) + // throw emu_fatalerror("Double density unsupported"); + u16 allocation_length = SCSILengthFromUINT16( &command[ 3 ] ); + LOGCMD("READ_TOC 14h %02x %02x %d\n", + command[1], command[2], allocation_length + ); + + if (allocation_length != 408) + throw emu_fatalerror("TOC with allocation length != 408 (%d)", allocation_length); + + if (m_cdda != nullptr) + { + m_cdda->stop_audio(); + m_sector_number = (m_sector_number & 0xf0) | GDROM_STANDBY_STATE; + } + + m_phase = SCSI_PHASE_DATAIN; + m_status_code = SCSI_STATUS_CODE_GOOD; + m_transfer_length = allocation_length; + break; + } + + // accessed for audio CDs + // TODO: needed for Mil CD support + case 0x15: + { + m_phase = SCSI_PHASE_DATAIN; + m_status_code = SCSI_STATUS_CODE_GOOD; + m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] ); + LOGCMD("REQ_SES 15h %02x %02x\n", command[2], m_transfer_length); + break; + } + + case 0x20: // CD_PLAY + { + if (!m_image->exists()) + { + m_phase = SCSI_PHASE_STATUS; + m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION; + m_transfer_length = 0; + break; + } + + const u32 start_offs = (command[2]<<16 | command[3]<<8 | command[4]); + const u32 end_offs = (command[8]<<16 | command[9]<<8 | command[10]); + //(command[8] % 75) + ((command[7] * 75) % (60*75)) + (command[6] * (75*60)) - m_lba; + + const u8 play_mode = command[1] & 7; + + auto trk = m_image->get_track(start_offs); + const u8 repeat = command[6] & 0xf; + LOGCMD("CD_PLAY 20h track %d FAD %d blocks %d type %02x repeat %01x\n" + , trk + 1 + , start_offs + , end_offs - start_offs + , play_mode + , repeat + ); + + if (play_mode == 7 && m_audio_sense == SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_PAUSED) + { + m_cdda->pause_audio(0); + m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS; + LOGCMD("\tPlayback resume\n"); + m_sector_number = (m_sector_number & 0xf0) | GDROM_PLAY_STATE; + } + else if (m_image->get_track_type(trk) == cdrom_file::CD_TRACK_AUDIO && end_offs > start_offs) + { + // TODO: check end > start assertion + m_cd_status.cdda_fad = start_offs - 150; + m_cd_status.cdda_blocks = (end_offs - start_offs); + + m_cdda->start_audio(m_cd_status.cdda_fad, m_cd_status.cdda_blocks); + m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS; + m_cd_status.repeat_current = 0; + m_cd_status.repeat_count = repeat; + m_sector_number = (m_sector_number & 0xf0) | GDROM_PLAY_STATE; + + LOGCMD("\tPlayback started\n"); + } + else + { + LOGWARN("track is NOT audio!\n"); + set_sense(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_SENSE_ASC_ASCQ_ILLEGAL_MODE_FOR_THIS_TRACK); + // TODO: unconfirmed state + m_sector_number = (m_sector_number & 0xf0) | GDROM_ERROR_STATE; + return; + } + + m_phase = SCSI_PHASE_STATUS; + m_status_code = SCSI_STATUS_CODE_GOOD; + m_transfer_length = 0; + break; + } + + case 0x21: + { + if (!m_image->exists()) + { + m_phase = SCSI_PHASE_STATUS; + m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION; + m_transfer_length = 0; + break; + } + + const u32 start_seek = (command[2]<<16 | command[3]<<8 | command[4]); + const u8 seek_mode = command[1] & 0xf; + LOGCMD("CD_SEEK 21h FAD %d type %02x\n", start_seek + 150, seek_mode); + switch(seek_mode) + { + // TODO: implement SEEK & standby + // 1 FAD seek + // 2 MSF seek + // 3 stop audio, go to Home FAD + case 4: + // 4 pause audio + LOGCMD("\tPlayback paused\n"); + m_cdda->pause_audio(1); + m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_PAUSED; + m_sector_number = (m_sector_number & 0xf0) | GDROM_PAUSE_STATE; + break; + } + + m_phase = SCSI_PHASE_STATUS; + m_status_code = SCSI_STATUS_CODE_GOOD; + m_transfer_length = 0; + break; + } + case 0x30: // CD_READ if (command[1] & 1) { @@ -204,9 +387,11 @@ void gdrom_device::ExecCommand() m_blocks = command[8]<<16 | command[9]<<8 | command[10]; read_type = (command[1] >> 1) & 7; - data_select = (command[1]>>4) & 0xf; + data_select = (command[1] >> 4) & 0xf; + //m_status |= IDE_STATUS_DSC; - if (read_type != 2) // mode 1 + // TODO: any other value is a non-Mode 1 attempt basically + if (read_type != 0 && read_type != 2) { throw emu_fatalerror("GDROM: Unhandled read_type %d", read_type); } @@ -217,7 +402,7 @@ void gdrom_device::ExecCommand() } // LBA 45000 is start of double density GD-ROM - LOGCMD("CD_READ %02x %02x\n", command[2], command[4]); + LOGCMD("CD_READ 30h %02x %02x\n", command[2], command[4]); LOGCMD(" LBA %d (%x) for %d blocks (%d bytes, read type %d, data select %d)\n", m_lba + 150, m_lba, m_blocks, m_blocks * m_sector_bytes, read_type, data_select @@ -236,6 +421,8 @@ void gdrom_device::ExecCommand() if (m_cdda != nullptr) { m_cdda->stop_audio(); + m_audio_sense = SCSI_SENSE_ASC_ASCQ_NO_SENSE; + m_sector_number = (m_sector_number & 0xf0) | GDROM_STANDBY_STATE; } m_phase = SCSI_PHASE_DATAIN; @@ -244,54 +431,32 @@ void gdrom_device::ExecCommand() } break; - // READ TOC (GD-ROM ver.) - case 0x14: + case 0x40: { - if (!m_image->exists()) - { - m_phase = SCSI_PHASE_STATUS; - m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION; - m_transfer_length = 0; - break; - } + m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] ); + //LOGCMD("CD_SCD 40h %02x %d\n", command[1] & 0xf, m_transfer_length); - // TODO: is this correct? - int start_trk = command[2]; - int end_trk = m_image->get_last_track(); - int length; - int allocation_length = SCSILengthFromUINT16( &command[ 3 ] ); - - if( start_trk == 0 ) + switch(command[1] & 0xf) { - start_trk = 1; + case 0x00: + m_phase = SCSI_PHASE_DATAIN; + m_status_code = SCSI_STATUS_CODE_GOOD; + m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] ); + break; + case 0x01: + m_phase = SCSI_PHASE_DATAIN; + m_status_code = SCSI_STATUS_CODE_GOOD; + m_transfer_length = 0xe; + break; + default: + LOGWARN("command 0x40: unhandled subchannel request\n"); + break; } - if( start_trk == 0xaa ) - { - end_trk = start_trk; - } - - length = 4 + ( 8 * ( ( end_trk - start_trk ) + 1 ) ); - if( length > allocation_length ) - { - length = allocation_length; - } - else if( length < 4 ) - { - length = 4; - } - - if (m_cdda != nullptr) - { - m_cdda->stop_audio(); - } - - m_phase = SCSI_PHASE_DATAIN; - m_status_code = SCSI_STATUS_CODE_GOOD; - m_transfer_length = length; break; } - case 0x70: // security check, return no data, always followed by cmd 0x71, command[1] parameter can be 0x1f or 0x9f + // security check, return no data, always followed by cmd 0x71, command[1] parameter can be 0x1f or 0x9f + case 0x70: m_phase = SCSI_PHASE_STATUS; m_status_code = SCSI_STATUS_CODE_GOOD; m_transfer_length = 0; @@ -303,22 +468,16 @@ void gdrom_device::ExecCommand() m_transfer_length = sizeof(GDROM_Cmd71_Reply); break; - case 0x40: - if(command[1] & 0xf) - { - m_phase = SCSI_PHASE_DATAIN; - m_status_code = SCSI_STATUS_CODE_GOOD; - m_transfer_length = 0xe; - } - else - { - LOGWARN("command 0x40: unhandled subchannel request\n"); - } - break; + // case 0x22: CD_SCAN + // case 0x31: CD_READ2 + // case 0x13: REQ_ERROR + // case 0x16: CD_OPEN [Tray] + + // case 0x08: ??? loopchk uses it in one of the Packet cmnd tests + // (check for unsupported command?) default: - t10mmc::ExecCommand(); - break; + throw emu_fatalerror("GDROM: unhandled command %02x", command[0]); } } @@ -333,14 +492,152 @@ void gdrom_device::ReadData( uint8_t *data, int dataLength ) switch ( command[0] ) { + case 0x10: // REQ_STAT + { + data[0] = m_sector_number & 0xf; // CD status + data[1] = (m_sector_number & 0xf0) | (m_cd_status.repeat_current & 0xf); + auto fad = m_cdda->get_audio_lba(); + auto trk = m_image->get_track(fad); + data[2] = m_image->get_adr_control(trk - 1); + data[3] = trk; + // TODO: index + data[4] = 1; + // FAD, in binary format + data[5] = (fad >> 16) & 0xff; + data[6] = (fad >> 8) & 0xff; + data[7] = fad & 0xff; + // Max Read Error Retry Times + data[8] = 0; + // + data[9] = 0; + if (LIVE_REQ_STAT) + { + popmessage("REQ_STAT STATUS %02x track %d index %d adr %02x fad %06d" + , m_sector_number + , data[3] + , data[4] + , data[2] + , fad + ); + } + break; + } + case 0x11: // REQ_MODE - LOGCMD("REQ_MODE dataLength %d\n", dataLength); + //LOGCMD("REQ_MODE dataLength %d\n", dataLength); memcpy(data, &GDROM_Cmd11_Reply[transferOffset], (dataLength >= 32-transferOffset) ? 32-transferOffset : dataLength); + // TODO: reading this while playing a redbook likely hardwires CD speed to 75 Hz + //data[1] = 0x01; break; + case 0x13: // REQ_ERROR + // cfr. Appendix I for possible error types + data[0] = 0xf0; // fixed? + data[1] = 0; + data[2] = 6; // Sense Key + data[3] = 0; + // 4-7 "specific command details" (?) or FAD + data[4] = 0; + data[5] = 0; + data[6] = 0; + data[7] = 0; + data[8] = 0x29; // ASC + data[9] = 0; // ASCQ + break; + + case 0x14: // READ TOC (GD-ROM ver.) + /* + Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out. + That makes sense in terms of how real-world CDs are referred to, but + our internal routines for tracks use "0" as track 1. That probably + should be fixed... + */ + LOGCMD("READ_TOC format %d time %d\n", + command[2] & 0xf, (command[1] >> 1) & 1 + ); + switch (command[2] & 0x0f) + { + case 0: // normal + { + int start_trk = 1; + int end_trk = m_image->get_last_track(); + int len = 408; + //int in_len; + int dptr = 0; + uint32_t tstart; + + // Non-standard, doesn't want in_len readback + //dptr = 0; + //data[dptr++] = (len>>8) & 0xff; + //data[dptr++] = (len & 0xff); + + // pre-fill with 0xffs, audio CD player counts number of tracks by checking the + // first EOF it encounters (and don't care about the 396-407 dataset below) + memset(data, 0xff, len); + dptr = 0; + LOGTOC("TOC: Start track %d end track %d\n", start_trk, end_trk); + for (i = start_trk; i <= end_trk; i++) + { + u8 adr = m_image->get_adr_control(i - 1) | 1; + data[dptr++] = adr; + + tstart = m_image->get_track_start(i - 1) + 150; + //if ((command[1]&2)>>1) + // tstart = cdrom_file::lba_to_msf(tstart); + data[dptr++] = (tstart>>16) & 0xff; + data[dptr++] = (tstart>>8) & 0xff; + data[dptr++] = (tstart & 0xff); + LOGTOC("\t%d: FAD %d %02x\n", i, tstart, adr); + } + + dptr = 396; + data[dptr++] = m_image->get_adr_control(0) | 1; + data[dptr++] = start_trk; + data[dptr++] = 0; + data[dptr++] = 0; + data[dptr++] = m_image->get_adr_control(end_trk) | 1; + data[dptr++] = end_trk; + data[dptr++] = 0; + data[dptr++] = 0; + const u32 tend = m_image->get_track_start(0xaa) + 150; + //if ((command[1]&2)>>1) + // tstart = cdrom_file::lba_to_msf(tstart); + data[dptr++] = m_image->get_adr_control(0xaa) | 1; + data[dptr++] = (tend>>16) & 0xff; + data[dptr++] = (tend>>8) & 0xff; + data[dptr++] = (tend & 0xff); + LOGTOC("\t0xaa: FAD %d\n", tstart); + break; + } + default: + LOGWARN("Unhandled READ_TOC format %d\n", command[2]&0xf); + break; + } + break; + + case 0x15: + { + // REQ_SES + data[0] = m_sector_number & 0xf; // CD status, stripped by type? + data[1] = 0; // , zeroed + data[2] = 1; // number of sessions + + const u8 session_num = command[2] & 0xff; + u32 fad; + if (session_num == 0) + fad = m_image->get_track_start(0xaa) + 150; + else + fad = m_image->get_track_start(0) + 150; + LOGTOC("SESSION %d: %06d\n", session_num, fad); + data[3] = (fad >> 16) & 0xff; + data[4] = (fad >> 8) & 0xff; + data[5] = fad & 0xff; + break; + } + case 0x30: // CD_READ - LOGCMD("CD_READ read %x dataLength,\n", dataLength); - if (m_image->exists() && m_blocks) + LOGXFER("CD_READ read %x dataLength,\n", dataLength); + if ((m_image->exists()) && (m_blocks)) { while (dataLength > 0) { @@ -370,82 +667,71 @@ void gdrom_device::ReadData( uint8_t *data, int dataLength ) } break; - case 0x14: // READ TOC (GD-ROM ver.) - /* - Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out. - That makes sense in terms of how real-world CDs are referred to, but - our internal routines for tracks use "0" as track 1. That probably - should be fixed... - */ - LOGCMD("READ TOC format = %d time=%d\n", - command[2] & 0xf, (command[1] >> 1) & 1 - ); + case 0x40: // Get Subchannel status switch (command[2] & 0x0f) { - case 0: // normal + case 0: // Subcode P-W { - int start_trk; - int end_trk; - int len; - int in_len; - int dptr; - uint32_t tstart; - - start_trk = command[2]; - if( start_trk == 0 ) + data[0] = 0; // Reserved + data[1] = m_audio_sense; + data[2] = 0; + data[3] = m_transfer_length; // header size + auto fad = m_cdda->get_audio_lba(); + if (!m_image->read_subcode( fad, &data[4 + m_transfer_length])) { - start_trk = 1; - } + // attempt to provide Q channel + // TODO: audio CD player definitely reads here but never updates GFXs? + u8 subqbuf[12]{}; + const u32 msf_abs = cdrom_file::lba_to_msf_alt( fad ); + const auto trk = m_image->get_track( fad ); + const u32 msf_rel = cdrom_file::lba_to_msf_alt( fad - m_image->get_track_start( trk ) ); - end_trk = m_image->get_last_track(); - len = (end_trk * 8) + 2; + subqbuf[0] = 0x01 | ((m_image->get_track_type(m_image->get_track(trk + 1)) == cdrom_file::CD_TRACK_AUDIO) ? 0x00 : 0x40); + subqbuf[1] = dec_2_bcd(trk + 1); + subqbuf[2] = 1; + subqbuf[3] = dec_2_bcd((msf_rel >> 16) & 0xff); + subqbuf[4] = dec_2_bcd((msf_rel >> 8) & 0xff); + subqbuf[5] = dec_2_bcd((msf_rel >> 0) & 0xff); + subqbuf[6] = 0; + subqbuf[7] = dec_2_bcd((msf_abs >> 16) & 0xff); + subqbuf[8] = dec_2_bcd((msf_abs >> 8) & 0xff); + subqbuf[9] = dec_2_bcd((msf_abs >> 0) & 0xff); + subqbuf[10] = 0xff; //machine().rand(); // CRC + subqbuf[11] = 0xff; //machine().rand(); - // the returned TOC DATA LENGTH must be the full amount, - // regardless of how much we're able to pass back due to in_len - dptr = 0; - data[dptr++] = (len>>8) & 0xff; - data[dptr++] = (len & 0xff); - data[dptr++] = 1; - data[dptr++] = end_trk; - - if( start_trk == 0xaa ) - { - end_trk = 0xaa; - } - - in_len = command[3]<<8 | command[4]; - - for (i = start_trk; i <= end_trk; i++) - { - int cdrom_track = i; - if( cdrom_track != 0xaa ) + if (LIVE_REQ_STAT) { - cdrom_track--; + popmessage("Qchan STATUS %02x TRACK %d ABS %02x:%02x:%02x REL %02x:%02x:%02x" + , subqbuf[0] + , subqbuf[1] + , subqbuf[7], subqbuf[8], subqbuf[9] + , subqbuf[3], subqbuf[4], subqbuf[5] + ); } - if( dptr >= in_len ) - { - break; - } - - data[dptr++] = 0; - data[dptr++] = m_image->get_adr_control(cdrom_track); - data[dptr++] = i; - data[dptr++] = 0; - - tstart = m_image->get_track_start(cdrom_track); - if ((command[1]&2)>>1) - tstart = cdrom_file::lba_to_msf(tstart); - data[dptr++] = (tstart>>24) & 0xff; - data[dptr++] = (tstart>>16) & 0xff; - data[dptr++] = (tstart>>8) & 0xff; - data[dptr++] = (tstart & 0xff); + for (int i = 0; i < m_transfer_length - 4; i++) + data[i + 4] = BIT(subqbuf[i >> 3], 7 - (i & 7)) ? 0x40 : 0x00; } break; } - default: - LOGWARN("Unhandled READ TOC format %d\n", command[2]&0xf); + case 1: // Subcode Q + // TODO: unread by audio CD player (?) + LOGWARN("CD_SCD: unhandled Subcode Q path\n"); + data[0] = 0; // Reserved + data[1] = m_audio_sense; + data[2] = 0; + data[3] = m_transfer_length; // header size + data[4] = 0; // ADR + data[5] = 1; // Track Number + data[6] = 1; // index #1 + data[7] = 0; // ? + data[8] = 0; // ? + data[9] = 0; // elapsed FAD + data[0xa] = 0; // , zeroed + data[0xb] = 0; // FAD >> 16 + data[0xc] = 0; // FAD >> 8 + data[0xd] = 0x96; // FAD >> 0 break; } break; @@ -457,23 +743,6 @@ void gdrom_device::ReadData( uint8_t *data, int dataLength ) data[10] = 0x1f; // needed by dimm board firmware break; - case 0x40: // Get Subchannel status - data[0] = 0; // Reserved - data[1] = 0x15; // Audio Playback status (todo) - data[2] = 0; - data[3] = 0x0e; // header size - data[4] = 0; // ? - data[5] = 1; // Track Number - data[6] = 1; // gap #1 - data[7] = 0; // ? - data[8] = 0; // ? - data[9] = 0; // ? - data[0xa] = 0; // ? - data[0xb] = 0; // FAD >> 16 - data[0xc] = 0; // FAD >> 8 - data[0xd] = 0x96; // FAD >> 0 - break; - default: t10mmc::ReadData( data, dataLength ); break; @@ -490,6 +759,22 @@ void gdrom_device::WriteData( uint8_t *data, int dataLength ) { case 0x12: // SET_MODE memcpy(&GDROM_Cmd11_Reply[transferOffset], data, (dataLength >= 32-transferOffset) ? 32-transferOffset : dataLength); + if (data[2] != 0 && data[2] != 7) + throw emu_fatalerror("GDROM: Unsupported CD speed setting %02x\n", data[2]); + // ---- -000 Max speed (x12) + // ---- -xxx [x1 (75 Hz), x2, x4, x6, x8, x10, x12] + LOGCMD("\tCD speed: %02x\n", data[2]); + // Standby Time: + // - 0 = no standby + // any other value = number of seconds for pause -> standby transition + LOGCMD("\tStandby Time: %02x%02x\n", data[4], data[5]); + + LOGCMD("\tRead Continous: %s\n", BIT(data[6], 5) ? "enable" : "disable"); + LOGCMD("\tECC: %s\n", BIT(data[6], 4) ? "enable" : "disable"); + LOGCMD("\tRead Retry: %s\n", BIT(data[6], 3) ? "enable" : "disable"); + LOGCMD("\tForm 2 Read Retry: %s\n", BIT(data[6], 0) ? "enable" : "disable"); + + LOGCMD("\tRead Retry Times %d\n", data[9]); break; default: @@ -519,31 +804,33 @@ void gdrom_device::device_start() m_identify_buffer[0] = 0x8600; // ATAPI device, cmd set 6 compliant, DRQ within 3 ms of PACKET command - m_identify_buffer[23] = ('S' << 8) | 'E'; - m_identify_buffer[24] = (' ' << 8) | ' '; - m_identify_buffer[25] = (' ' << 8) | ' '; - m_identify_buffer[26] = (' ' << 8) | ' '; + // non-standard identify returns + // TODO: should be centralized in command 11h + // loopchk: identify device Maker test (0104) PC=c04694a + // Was 23 + int dptr = 8; + m_identify_buffer[dptr++] = 'S' | ('E' << 8); + m_identify_buffer[dptr++] = ' ' | (' ' << 8); + m_identify_buffer[dptr++] = ' ' | (' ' << 8); + m_identify_buffer[dptr++] = ' ' | (' ' << 8); - m_identify_buffer[27] = ('C' << 8) | 'D'; - m_identify_buffer[28] = ('-' << 8) | 'R'; - m_identify_buffer[29] = ('O' << 8) | 'M'; - m_identify_buffer[30] = (' ' << 8) | 'D'; - m_identify_buffer[31] = ('R' << 8) | 'I'; - m_identify_buffer[32] = ('V' << 8) | 'E'; - m_identify_buffer[33] = (' ' << 8) | ' '; - m_identify_buffer[34] = (' ' << 8) | ' '; - m_identify_buffer[35] = ('6' << 8) | '.'; - m_identify_buffer[36] = ('4' << 8) | '2'; - m_identify_buffer[37] = (' ' << 8) | ' '; - m_identify_buffer[38] = (' ' << 8) | ' '; - m_identify_buffer[39] = (' ' << 8) | ' '; - m_identify_buffer[40] = (' ' << 8) | ' '; - m_identify_buffer[41] = (' ' << 8) | ' '; - m_identify_buffer[42] = (' ' << 8) | ' '; - m_identify_buffer[43] = (' ' << 8) | ' '; - m_identify_buffer[44] = (' ' << 8) | ' '; - m_identify_buffer[45] = (' ' << 8) | ' '; - m_identify_buffer[46] = (' ' << 8) | ' '; + // loopchk: identify device Model test (0104) PC=c046acc + // Was 27 + dptr = 16; + m_identify_buffer[dptr++] = 'C' | ('D' << 8); + m_identify_buffer[dptr++] = '-' | ('R' << 8); + m_identify_buffer[dptr++] = 'O' | ('M' << 8); + m_identify_buffer[dptr++] = ' ' | ('D' << 8); + m_identify_buffer[dptr++] = 'R' | ('I' << 8); + m_identify_buffer[dptr++] = 'V' | ('E' << 8); + m_identify_buffer[dptr++] = ' ' | (' ' << 8); + m_identify_buffer[dptr++] = ' ' | (' ' << 8); + // TODO: versioning is unchecked by loopchk + m_identify_buffer[dptr++] = '6' | ('.' << 8); + m_identify_buffer[dptr++] = '4' | ('2' << 8); + // FIXME: doc mentions a "System Date" readback + for (; dptr < 47; dptr ++) + m_identify_buffer[dptr] = ' ' | (' ' << 8); m_identify_buffer[49] = 0x0400; // IORDY may be disabled @@ -555,14 +842,57 @@ void gdrom_device::process_buffer() { atapi_hle_device::process_buffer(); // HACK: find out when this should be updated - m_sector_number = 0x80 | GDROM_PAUSE_STATE; + // TODO: upper byte is CD type detection + // 0000 CD-DA + // 0001 CD-ROM + // 0010 CD-ROM XA / CD Extra + // 0011 CD-I + // 1000 GD-ROM + const u8 cd_type = m_image->is_gd() ? 0x80 : 0x00; + m_sector_number = cd_type | (m_image->exists() ? m_sector_number & 0xf : GDROM_NODISC_STATE); } void gdrom_device::signature() { atapi_hle_device::signature(); + const u8 cd_type = m_image->is_gd() ? 0x80 : 0x00; + // naomi dimm board firmware needs the upper nibble to be 8 at the beginning - if (m_image->is_gd()) - m_sector_number = 0x81; + m_sector_number = cd_type | (m_image->exists() ? m_sector_number & 0xf : GDROM_NODISC_STATE); +} + +//bool gdrom_device::set_features() +//{ + // TODO: DSC, likely tested by Check-GD programs +// m_status |= IDE_STATUS_DSC; +// return atapi_cdrom_device::set_features(); +//} + +WRITE_LINE_MEMBER(gdrom_device::cdda_end_mark_cb) +{ + if (state != ASSERT_LINE) + return; + + m_cd_status.repeat_current ++; + m_cd_status.repeat_current &= 0xf; + LOG("end marker %d %d\n", m_cd_status.repeat_current, m_cd_status.repeat_count); + + // repeat_count = 0xf: infinite, not unlike Saturn CD Block + // - ggx sound test track #20 (opening) is a good testing scenario. + // - audio cd player don't care about this: + // it manually handle repeat modes depending on GD state alone. + if (m_cd_status.repeat_current > m_cd_status.repeat_count) + { + m_cdda->pause_audio(1); + m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_SUCCESSFULLY_COMPLETED; + LOG("\tCompleted\n"); + m_sector_number = (m_sector_number & 0xf0) | GDROM_PAUSE_STATE; + } + else + { + m_cdda->start_audio(m_cd_status.cdda_fad, m_cd_status.cdda_blocks); + LOG("\tRestart playback\n"); + m_sector_number = (m_sector_number & 0xf0) | GDROM_PLAY_STATE; + } } diff --git a/src/devices/bus/ata/gdrom.h b/src/devices/bus/ata/gdrom.h index 829186dec62..7467d1dff20 100644 --- a/src/devices/bus/ata/gdrom.h +++ b/src/devices/bus/ata/gdrom.h @@ -23,6 +23,7 @@ public: virtual void ExecCommand() override; virtual void WriteData( uint8_t *data, int dataLength ) override; virtual void ReadData( uint8_t *data, int dataLength ) override; + DECLARE_WRITE_LINE_MEMBER(cdda_end_mark_cb); protected: virtual void process_buffer() override; @@ -31,12 +32,26 @@ protected: // device-level overrides virtual void device_start() override; virtual void device_reset() override; +// virtual bool set_features() override; + // TODO: how GDROM determines ready flag? + // cfr. dc.xml [GDROM READY] for a list of SW that wants this on. + virtual bool is_ready() override { return true; } private: - uint8_t GDROM_Cmd11_Reply[32]; + uint8_t GDROM_Cmd11_Reply[32]{}; uint32_t read_type = 0; // for command 0x30 only uint32_t data_select = 0; // for command 0x30 only uint32_t transferOffset = 0; + + struct cd_status + { + u8 repeat_count = 0; + u8 repeat_current = 0; + u32 cdda_fad = 0; + u32 cdda_blocks = 0; + }; + + cd_status m_cd_status; }; DECLARE_DEVICE_TYPE(ATAPI_GDROM, gdrom_device) diff --git a/src/devices/sound/aica.cpp b/src/devices/sound/aica.cpp index a746f80eae0..9be26af8b8d 100644 --- a/src/devices/sound/aica.cpp +++ b/src/devices/sound/aica.cpp @@ -91,8 +91,8 @@ static constexpr s32 clip18(int x) { return std::clamp(x, -131072, 131071); } #define DISDL(slot) ((slot->udata.data[0x24 / 2] >> 0x8) & 0x000F) #define DIPAN(slot) (MONO() ? 0 : ((slot->udata.data[0x24 / 2] >> 0x0) & 0x001F)) -#define EFSDL(slot) ((m_EFSPAN[slot * 4] >> 8) & 0x000f) -#define EFPAN(slot) (MONO() ? 0 : ((m_EFSPAN[slot * 4] >> 0) & 0x001f)) +#define EFSDL(slot) ((m_EFSPAN[slot] >> 8) & 0x000f) +#define EFPAN(slot) (MONO() ? 0 : ((m_EFSPAN[slot] >> 0) & 0x001f)) //Unimplemented #define Q(slot) ((slot->udata.data[0x28 / 2] >> 0x0) & 0x001F) // (0.75 × register value - 3) @@ -874,7 +874,7 @@ void aica_device::w16(u32 addr,u16 val) if (addr <= 0x2044) { // printf("%x to EFSxx slot %d (addr %x)\n", val, (addr - 0x2000)/4, addr & 0x7f); - m_EFSPAN[addr & 0x7f] = val; + m_EFSPAN[(addr & 0x7f) >> 2] = val; } } else if (addr < 0x3000) @@ -976,7 +976,7 @@ u16 aica_device::r16(u32 addr) { if (addr <= 0x2044) { - v = m_EFSPAN[addr & 0x7f]; + v = m_EFSPAN[(addr & 0x7f) >> 2]; } else if (addr < 0x2800) { @@ -1300,6 +1300,7 @@ void aica_device::DoMasterSamples(std::vector const &inputs, w } bufl.put_int(s, smpl * m_LPANTABLE[MVOL() << 0xd], 32768 << SHIFT); + // TODO: diverges with SCSP, also wut? bufr.put_int(s, smpr * m_LPANTABLE[MVOL() << 0xd], 32768 << SHIFT); } } diff --git a/src/mame/sega/dccons.cpp b/src/mame/sega/dccons.cpp index 9cc26768325..2191f09d22a 100644 --- a/src/mame/sega/dccons.cpp +++ b/src/mame/sega/dccons.cpp @@ -19,7 +19,6 @@ 25925600 (PAL 480 @ 50.00), 13462800 (PAL 240 @ 50.00) TODO: - - RTC error always pops up at start-up, no flash plus bug with ticks (needs rewrite) - cfr. naomi.cpp header for general DC notes; - https://github.com/flyinghead/flycast/blob/master/docs/Notable%20game%20bugs.md For a comprehensive list of issues to be verified; @@ -27,15 +26,22 @@ - G1 i/f for GD-ROM needs to be converted in device class and hunted for unsupported features; - VMU; - Modem; + - regtest dc.xml against region setting, find the bad chance that a SW item + managed to brick a dcjp and turning into PAL. Notable symptoms: + - crzytaxi2j will start with 50Hz/60Hz screen selector; + - jojobaj will run in PAL mode; + + Notes: + - RTC error pops up at start-up. (btanb) + System saves to flash the AICA RTC timestamp and prompt user to change the clock in + case that drifts out significantly during boot. + Solution is to insert the actual host PC timestamp and have MAME nvram_save on, + that will lift the RTC prompt at next boot. Old TODO (to be rechecked and moved in XML notes): - Inputs doesn't work most of the time; - Candy Stripe: fills the log with "ATAPI_FEATURES_FLAG_OVL not supported", black screen - - Carrier: Jaleco logo uses YUV, but y size is halved? - Close To: Hangs at FMV - - F355 Challenge: black screen after Sega logo; - - Gundam - Side Story 0079: currently hangs at Bandai logo (regression) - - Idol Janshi wo Tsukucchaou: pixel aspect is way wrong (stretched and offsetted horizontally) - Power Stone: hangs at Capcom logo; - Sega GT: no cursor on main menu; - Tetris 4D: hangs at BPS FMV (bp 0C0B0C4E) @@ -368,8 +374,9 @@ INPUT_PORTS_END void dc_cons_state::gdrom_config(device_t *device) { cdda_device *cdda = device->subdevice("cdda"); - cdda->add_route(0, "^^aica", 0.4); - cdda->add_route(1, "^^aica", 0.4); + cdda->audio_end_cb().set(*device, FUNC(gdrom_device::cdda_end_mark_cb)); + cdda->add_route(0, "^^aica", 1.0); + cdda->add_route(1, "^^aica", 1.0); } void dc_cons_state::dc_base(machine_config &config) @@ -659,9 +666,9 @@ ROM_START( dcfish ) ROM_REGION64_LE(0x040000, "dcflash", ROMREGION_ERASEFF) ROM_LOAD( "fish_flash.bin", 0x020000, 0x020000, CRC(f7f36b7b) SHA1(f49d18de85c519c16d5447ca8ae39b62d1b8e483) ) // VA1 NTSC-JP - DISK_REGION( "ata:0:gdrom" ) + DISK_REGION( "ata:0:gdrom:image" ) DISK_IMAGE_READONLY( "fish_life_amazon", 0, SHA1(2cbba727b219bbbeddf551d0f3e80c5f8ecbe21f) ) // HDR-0094 ROM_END /* YEAR NAME PARENT MACHINE INPUT CLASS INIT ROT COMPANY FULLNAME */ -GAME( 2000, dcfish, 0, dc_fish, dcfish,dc_cons_state, init_dc, ROT0, "Sega", "Fish Life Amazon Playful Edition (Japan)", MACHINE_NOT_WORKING ) +GAME( 2000, dcfish, 0, dc_fish, dcfish,dc_cons_state, init_dc, ROT0, "Sega", "Fish Life Amazon Playful Edition (Japan)", MACHINE_NOT_WORKING ) // requires SH-4 touch screen, crashes on attract mode with DRC diff --git a/src/mame/sega/dccons_m.cpp b/src/mame/sega/dccons_m.cpp index 419e7383351..c085f6a4320 100644 --- a/src/mame/sega/dccons_m.cpp +++ b/src/mame/sega/dccons_m.cpp @@ -105,6 +105,10 @@ TIMER_CALLBACK_MEMBER(dc_cons_state::atapi_xfer_end ) atapi_xferbase += 2048; } + // TODO: understand when this should go off + // (would otherwise cause REQ ERRORs in gdrom_device with current hookup) + m_ata->write_dmack(0); + // set the next transfer, or a transfer end event. atapi_timer->adjust(attotime::from_usec(ATAPI_SINGLE_XFER_TIME), atapi_xferlen); }