void matsucd_read_next_block( void ) { cd.xfer_offset = 0; if ( cd.num_blocks ) { cd.lba++; cd.num_blocks--; if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type())) { logerror( "MATSUCD - Warning: Read error on CD!\n" ); } } }
bool mcd_isa_device::read_sector(bool first) { if((m_irq & IRQ_DATACOMP) && !first) m_isa->irq5_w(ASSERT_LINE); if(!m_readcount) { m_isa->drq5_w(CLEAR_LINE); m_data = false; return false; } uint32_t lba = msf_to_lba(m_readmsf); cdrom_read_data(m_cdrom_handle, lba - 150, m_buf, m_mode & 0x40 ? CD_TRACK_MODE1_RAW : CD_TRACK_MODE1); if(m_mode & 0x40) { //correct the header m_buf[12] = dec_2_bcd((m_readmsf >> 16) & 0xff); m_buf[13] = dec_2_bcd((m_readmsf >> 8) & 0xff); }
io_status *mess_cdrom_driver::read_sectors(const unsigned int startsec, const unsigned int numsec, unsigned char *buf) { const cdrom_toc *toc = cdrom_get_toc(m_cd); UINT32 track = cdrom_get_track(m_cd, startsec); UINT32 secsize = toc->tracks[track].datasize; #ifdef debug_mess_driver printf("mess: read %d sectors from %d (secsize %d)\n",numsec,startsec,secsize); #endif if (1) // && ((int)startsec<num_sectors)) { // fin->seek((INT64)startsec*(INT64)bin_sector_size); // io_status *ios=fin->async_read(buf,numsec*bin_sector_size); // if (! ios) for (int i = 0; i < numsec; i++) { // printf("[%d/%d] Reading to pf_buffer %p at offset %d, size %d\n", i, numsec, &buf[secsize*i], secsize*i, secsize); cdrom_read_data(m_cd, startsec+i, &buf[secsize*i], CD_TRACK_RAW_DONTCARE); } return NULL; // return ios; } else { printf("mess: read sector out of range (%d, max=%d)\n", startsec, num_sectors); memset(buf,0xff,numsec*bin_sector_size); return NULL; } }
void cdda_device::get_audio_data(stream_sample_t *bufL, stream_sample_t *bufR, uint32_t samples_wanted) { int i; int16_t *audio_cache = (int16_t *) m_audio_cache.get(); while (samples_wanted > 0) { /* if no file, audio not playing, audio paused, or out of disc data, just zero fill */ if (!m_disc || !m_audio_playing || m_audio_pause || (!m_audio_length && !m_audio_samples)) { if( m_disc && m_audio_playing && !m_audio_pause && !m_audio_length ) { m_audio_playing = false; m_audio_ended_normally = true; } memset(bufL, 0, sizeof(stream_sample_t)*samples_wanted); memset(bufR, 0, sizeof(stream_sample_t)*samples_wanted); return; } int samples = samples_wanted; if (samples > m_audio_samples) { samples = m_audio_samples; } for (i = 0; i < samples; i++) { /* CD-DA data on the disc is big-endian */ *bufL++ = (int16_t) big_endianize_int16( audio_cache[ m_audio_bptr ] ); m_audio_bptr++; *bufR++ = (int16_t) big_endianize_int16( audio_cache[ m_audio_bptr ] ); m_audio_bptr++; } samples_wanted -= samples; m_audio_samples -= samples; if (m_audio_samples == 0) { int sectors = m_audio_length; if (sectors > MAX_SECTORS) { sectors = MAX_SECTORS; } for (i = 0; i < sectors; i++) { cdrom_read_data(m_disc, m_audio_lba, &m_audio_cache[CD_MAX_SECTOR_DATA*i], CD_TRACK_AUDIO); m_audio_lba++; } m_audio_samples = (CD_MAX_SECTOR_DATA*sectors)/4; m_audio_length -= sectors; /* reset feedout ptr */ m_audio_bptr = 0; } } }
static void get_audio_data(cdda_info *info, stream_sample_t *bufL, stream_sample_t *bufR, UINT32 samples_wanted) { int i, sectoread, remaining; INT16 *audio_cache = (INT16 *) info->audio_cache; /* if no file, audio not playing, audio paused, or out of disc data, just zero fill */ if (!info->disc || !info->audio_playing || info->audio_pause || (!info->audio_length && !info->audio_samples)) { if( info->disc && info->audio_playing && !info->audio_pause && !info->audio_length ) { info->audio_playing = FALSE; info->audio_ended_normally = TRUE; } memset(bufL, 0, sizeof(stream_sample_t)*samples_wanted); memset(bufR, 0, sizeof(stream_sample_t)*samples_wanted); return; } /* if we've got enough samples, just feed 'em out */ if (samples_wanted <= info->audio_samples) { for (i = 0; i < samples_wanted; i++) { *bufL++ = audio_cache[ info->audio_bptr++ ]; *bufR++ = audio_cache[ info->audio_bptr++ ]; } info->audio_samples -= samples_wanted; return; } /* we don't have enough, so first feed what we've got */ for (i = 0; i < info->audio_samples; i++) { *bufL++ = audio_cache[ info->audio_bptr++ ]; *bufR++ = audio_cache[ info->audio_bptr++ ]; } /* remember how much left for later */ remaining = samples_wanted - info->audio_samples; /* reset the buffer and get what we can from the disc */ info->audio_samples = 0; if (info->audio_length >= MAX_SECTORS) { sectoread = MAX_SECTORS; } else { sectoread = info->audio_length; } for (i = 0; i < sectoread; i++) { cdrom_read_data(info->disc, info->audio_lba, &info->audio_cache[CD_MAX_SECTOR_DATA*i], CD_TRACK_AUDIO); info->audio_lba++; } info->audio_samples = (CD_MAX_SECTOR_DATA*sectoread)/4; info->audio_length -= sectoread; /* CD-DA data on the disc is big-endian, flip if we're not */ if (ENDIANNESS_NATIVE == ENDIANNESS_LITTLE) { for( i = 0; i < info->audio_samples * 2; i++ ) { audio_cache[ i ] = BIG_ENDIANIZE_INT16( audio_cache[ i ] ); } } /* reset feedout ptr */ info->audio_bptr = 0; /* we've got data, feed it out by calling ourselves recursively */ get_audio_data(info, bufL, bufR, remaining); }
void matsucd_command_w( running_machine &machine, UINT8 data ) { UINT8 cmd; /* make sure we're enabled */ if ( cd.enabled == 0 ) return; /* make sure /CMD is asserted */ if ( cd.cmd_signal == 0 ) return; if ( cd.cdda_set == 0 ) { // 2009-10, FP: for some reason, cdda_from_cdrom was not returning the correct // CDDA device. Hence, as a temp workaround, I added the cdda to the struct // and its tag is configured in matsucd_init if ( cd.cdrom ) cdda_set_cdrom( cd.cdda, cd.cdrom); cd.cdda_set = 1; } cd.input[cd.input_pos++] = data; cmd = cd.input[0]; switch( cmd ) { case 0x01: /* seek */ { if ( cd.input_pos < 7 ) return; /* stop CDDA audio if necessary */ matsucd_cdda_stop(machine); cd.motor = 1; memset( cd.output, 0, 6 ); matsucd_complete_cmd( machine, 0 ); } break; case 0x02: /* read sectors */ { if ( cd.input_pos < 7 ) return; /* stop CDDA audio if necessary */ matsucd_cdda_stop(machine); /* LBA */ cd.lba = cd.input[1]; cd.lba <<= 8; cd.lba |= cd.input[2]; cd.lba <<= 8; cd.lba |= cd.input[3]; /* Number of blocks */ cd.num_blocks = cd.input[4]; cd.num_blocks <<= 8; cd.num_blocks |= cd.input[5]; /* Reset transfer count */ cd.xfer_offset = 0; /* go ahead and cache the first block */ if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type())) { logerror( "MATSUCD - Warning: Read error on CD!\n" ); matsucd_command_error( machine ); return; } cd.motor = 1; memset( cd.output, 0, 6 ); matsucd_complete_cmd( machine, 0 ); } break; case 0x04: /* motor on */ { if ( cd.input_pos < 7 ) return; cd.motor = 1; memset( cd.output, 0, 6 ); matsucd_complete_cmd( machine, 0 ); } break; case 0x05: /* motor off */ { if ( cd.input_pos < 7 ) return; /* stop CDDA audio if necessary */ matsucd_cdda_stop(machine); cd.motor = 0; memset( cd.output, 0, 6 ); matsucd_complete_cmd( machine, 0 ); } break; case 0x09: /* play audio cd, LBA mode */ { UINT32 lba, numblocks; if ( cd.input_pos < 7 ) return; lba = cd.input[1]; lba <<= 8; lba |= cd.input[2]; lba <<= 8; lba |= cd.input[3]; numblocks = cd.input[4]; numblocks <<= 8; numblocks |= cd.input[5]; numblocks <<= 8; numblocks |= cd.input[6]; matsucd_cdda_play( machine, lba, numblocks ); cd.motor = 1; memset( cd.output, 0, 6 ); matsucd_complete_cmd( machine, 0 ); } break; case 0x0a: /* play audio cd, MSF mode */ { UINT32 start, end, lba_start, lba_end; if ( cd.input_pos < 7 ) return; start = cd.input[1]; start <<= 8; start |= cd.input[2]; start <<= 8; start |= cd.input[3]; end = cd.input[4]; end <<= 8; end |= cd.input[5]; end <<= 8; end |= cd.input[6]; lba_start = MSF2LBA( start ); lba_end = MSF2LBA( end ); if ( end == 0xffffff ) { lba_end = cdrom_get_track_start(cd.cdrom,cdrom_get_last_track(cd.cdrom)-1); lba_end += cdrom_get_toc(cd.cdrom)->tracks[cdrom_get_last_track(cd.cdrom)-1].frames; } if ( lba_end <= lba_start ) { matsucd_cdda_stop(machine); } else { matsucd_cdda_play( machine, lba_start, lba_end - lba_start ); cd.motor = 1; } memset( cd.output, 0, 6 ); matsucd_complete_cmd( machine, 0 ); } break; case 0x0b: /* play audio track and index */ { UINT8 track_start = cd.input[1]; UINT8 index_start = cd.input[2]; UINT8 track_end = cd.input[3]; UINT8 index_end = cd.input[4]; UINT32 lba_start, lba_end; /* TODO: Add index support once the CDDA engine supports it */ (void)index_start; (void)index_end; /* sanitize values */ if ( track_start == 0 ) track_start++; if ( track_end == 0 ) track_end++; if ( track_end > cdrom_get_last_track(cd.cdrom) ) track_end = cdrom_get_last_track(cd.cdrom); /* find the start and stop positions */ lba_start = cdrom_get_track_start(cd.cdrom,track_start-1); lba_end = cdrom_get_track_start(cd.cdrom,track_end-1); lba_end += cdrom_get_toc(cd.cdrom)->tracks[track_end-1].frames; if ( lba_end <= lba_start ) { matsucd_cdda_stop(machine); } else { matsucd_cdda_play( machine, lba_start, lba_end - lba_start ); cd.motor = 1; } memset( cd.output, 0, 6 ); matsucd_complete_cmd( machine, 0 ); } break; case 0x81: /* status read */ { UINT8 newstatus = cd.status; newstatus &= MATSU_STATUS_SUCCESS | MATSU_STATUS_ERROR | MATSU_STATUS_PLAYING; newstatus |= MATSU_STATUS_READY; if (cd.cdrom) { newstatus |= MATSU_STATUS_MEDIA; } if (cd.motor) newstatus |= MATSU_STATUS_MOTOR; cd.output[0] = newstatus; matsucd_set_status( machine, newstatus ); matsucd_complete_cmd( machine, 1 ); } break; case 0x82: /* error read */ { if ( cd.input_pos < 7 ) return; memset( cd.output, 0, 6 ); matsucd_complete_cmd( machine, 6 ); } break; case 0x84: /* set mode */ { if ( cd.input_pos < 7 ) return; cd.sector_size = cd.input[2]; cd.sector_size <<= 8; cd.sector_size |= cd.input[3]; memset( cd.output, 0, 6 ); matsucd_complete_cmd( machine, 0 ); } break; case 0x87: /* read SUBQ */ { int msfmode; UINT32 lba; UINT8 track; if ( cd.input_pos < 7 ) return; msfmode = (cd.input[1] & 0x02) ? 1 : 0; memset( cd.output, 0, 13 ); cd.output[0] = matsucd_cdda_getstatus( machine, &lba ); if ( lba > 0 ) { UINT32 disk_pos; UINT32 track_pos; track = cdrom_get_track(cd.cdrom, lba); cd.output[1] = cdrom_get_adr_control(cd.cdrom, track); cd.output[2] = track+1; cd.output[3] = 0; /* index */ disk_pos = lba; if ( msfmode ) disk_pos = LBA2MSF(disk_pos); cd.output[4] = (disk_pos >> 24) & 0xff; cd.output[5] = (disk_pos >> 16) & 0xff; cd.output[6] = (disk_pos >> 8) & 0xff; cd.output[7] = (disk_pos) & 0xff; track_pos = lba - cdrom_get_track_start(cd.cdrom, track); if ( msfmode ) track_pos = LBA2MSF(track_pos); cd.output[8] = (track_pos >> 24) & 0xff; cd.output[9] = (track_pos >> 16) & 0xff; cd.output[10] = (track_pos >> 8) & 0xff; cd.output[11] = (track_pos) & 0xff; /* TODO: UPC flag at offset 12 */ cd.output[12] = 0; } matsucd_complete_cmd( machine, 13 ); } break; case 0x89: /* read disk info */ { UINT32 end; if ( cd.input_pos < 7 ) return; memset( cd.output, 0, 5 ); cd.output[0] = cdrom_get_last_track(cd.cdrom) ? 1 : 0; cd.output[1] = cdrom_get_last_track(cd.cdrom); end = cdrom_get_track_start(cd.cdrom,cd.output[1]-1); end += cdrom_get_toc(cd.cdrom)->tracks[cd.output[1]-1].frames; end = LBA2MSF(end); cd.output[2] = (end >> 16) & 0xff; cd.output[3] = (end >> 8) & 0xff; cd.output[4] = (end) & 0xff; matsucd_complete_cmd( machine, 5 ); } break; case 0x8a: /* read toc */ { UINT8 track; int msfmode; UINT32 track_start; if ( cd.input_pos < 7 ) return; /* stop CDDA audio if necessary */ matsucd_cdda_stop(machine); track = cd.input[2]; msfmode = (cd.input[1] & 0x02) ? 1 : 0; if ( cd.cdrom == NULL ) { logerror( "MATSUCD - Warning: Reading TOC without a CD!\n" ); matsucd_command_error( machine ); return; } if ( track > cdrom_get_last_track(cd.cdrom) ) { logerror( "MATSUCD - Warning: Reading invalid track entry from TOC!\n" ); matsucd_command_error( machine ); return; } memset( cd.output, 0, 7 ); track_start = cdrom_get_track_start(cd.cdrom, track > 0 ? (track-1) : track ); if ( msfmode ) track_start = LBA2MSF( track_start ); cd.output[1] = cdrom_get_adr_control(cd.cdrom, track > 0 ? (track-1) : track); cd.output[2] = track; cd.output[3] = (track == 0 ) ? cdrom_get_last_track(cd.cdrom) : 0; cd.output[4] = (track_start >> 24) & 0xff; cd.output[5] = (track_start >> 16) & 0xff; cd.output[6] = (track_start >> 8) & 0xff; cd.output[7] = (track_start) & 0xff; cd.motor = 1; matsucd_complete_cmd( machine, 8 ); } break; case 0x8b: /* pause audio */ { if ( cd.input_pos < 7 ) return; matsucd_cdda_pause( machine, (cd.input[1] == 0) ? 1 : 0 ); memset( cd.output, 0, 7 ); matsucd_complete_cmd( machine, 0 ); } break; case 0xa3: /* front panel */ { if ( cd.input_pos < 7 ) return; /* TODO: ??? */ memset( cd.output, 0, 7 ); matsucd_complete_cmd( machine, 0 ); } break; default: logerror( "MATSUCD: Unknown/inimplemented command %08x\n", cmd ); break; }