mirror of
https://github.com/holub/mame
synced 2025-05-12 00:58:53 +03:00

Hand-checked the most popular English word misspellings and made the appropriate changes. Nearly all of the changes made were in commented areas. (no whatsnew)
767 lines
16 KiB
C
767 lines
16 KiB
C
/***************************************************************************
|
|
|
|
Matsushita/Panasonic CDR521/522 type CDROM drive emulation
|
|
|
|
Notes:
|
|
This version implements the drive found in Amiga CDTV. There are
|
|
different drives supporting this command-set (look in the sbpcd driver
|
|
in Linux for examples). Most drives support the exact same command
|
|
structure, but the command numbers differ. Eventually this driver
|
|
can be expanded with support for the other drives as needed.
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
#include "emu.h"
|
|
#include "imagedev/chd_cd.h"
|
|
#include "sound/cdda.h"
|
|
#include "machine/matsucd.h"
|
|
|
|
|
|
#define MATSU_STATUS_READY ( 1 << 0 ) /* driver ready */
|
|
#define MATSU_STATUS_DOORLOCKED ( 1 << 1 ) /* door locked */
|
|
#define MATSU_STATUS_PLAYING ( 1 << 2 ) /* drive playing */
|
|
#define MATSU_STATUS_SUCCESS ( 1 << 3 ) /* last command was successful */
|
|
#define MATSU_STATUS_ERROR ( 1 << 4 ) /* last command failed */
|
|
#define MATSU_STATUS_MOTOR ( 1 << 5 ) /* spinning */
|
|
#define MATSU_STATUS_MEDIA ( 1 << 6 ) /* media present (in caddy or tray) */
|
|
#define MATSU_STATUS_DOORCLOSED ( 1 << 7 ) /* tray status */
|
|
|
|
typedef struct
|
|
{
|
|
UINT8 enabled; /* /ENABLE - Unit enabled */
|
|
UINT8 cmd_signal; /* /CMD - Command mode */
|
|
UINT8 stch_signal; /* /STCH - Status Changed */
|
|
UINT8 sten_signal; /* /STEN - Status Enabled */
|
|
UINT8 scor_signal; /* /STEN - Subcode Ready */
|
|
UINT8 input[16];
|
|
UINT8 input_pos;
|
|
UINT8 output[16];
|
|
UINT8 output_pos;
|
|
UINT8 output_len;
|
|
UINT8 status;
|
|
UINT8 motor;
|
|
UINT16 sector_size;
|
|
UINT32 lba;
|
|
UINT16 num_blocks;
|
|
UINT16 xfer_offset;
|
|
UINT8 sector_buffer[CD_MAX_SECTOR_DATA];
|
|
UINT8 cdda_set;
|
|
void (*sten_cb)( running_machine &machine, int level ); /* Status enabled callback */
|
|
void (*stch_cb)( running_machine &machine, int level ); /* Status changed callback */
|
|
void (*scor_cb)( running_machine &machine, int level ); /* Subcode ready callback */
|
|
cdrom_file *cdrom;
|
|
device_t *cdda;
|
|
emu_timer *frame_timer;
|
|
} matsucd;
|
|
|
|
static matsucd cd;
|
|
|
|
#define MSF2LBA(msf) (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff))
|
|
#define LBA2MSF(lba) (((lba / (75 * 60)) << 16) | (((lba / 75) % 60) << 8) | (lba % 75))
|
|
|
|
static TIMER_CALLBACK(matsu_subcode_proc);
|
|
|
|
void matsucd_init( cdrom_image_device *cdrom_device, const char *cdda_tag )
|
|
{
|
|
memset(&cd, 0, sizeof( matsucd ) );
|
|
|
|
cd.cdrom = cdrom_device->get_cdrom_file();
|
|
cd.cdda = cdrom_device->machine().device(cdda_tag);
|
|
|
|
cd.frame_timer = cdrom_device->machine().scheduler().timer_alloc(FUNC(matsu_subcode_proc));
|
|
|
|
cd.stch_signal = 1;
|
|
}
|
|
|
|
void matsucd_set_status_enabled_callback( void (*sten_cb)( running_machine &machine, int level ) )
|
|
{
|
|
/* add the callback for status enabled signal */
|
|
cd.sten_cb = sten_cb;
|
|
}
|
|
|
|
void matsucd_set_status_changed_callback( void (*stch_cb)( running_machine &machine, int level ) )
|
|
{
|
|
/* add the callback for status changed signal */
|
|
cd.stch_cb = stch_cb;
|
|
}
|
|
|
|
void matsucd_set_subcode_ready_callback( void (*scor_cb)( running_machine &machine, int level ) )
|
|
{
|
|
/* add the callback for subcode ready signal */
|
|
cd.scor_cb = scor_cb;
|
|
}
|
|
|
|
static int matsucd_getsector_type( void )
|
|
{
|
|
switch( cd.sector_size )
|
|
{
|
|
case 2048: return CD_TRACK_MODE1;
|
|
case 2324: return CD_TRACK_MODE2_FORM2;
|
|
case 2336: return CD_TRACK_MODE2;
|
|
case 2352: return CD_TRACK_MODE2_RAW;
|
|
|
|
default: logerror( "MATSUCD: Sector size %d unsupported!\n", cd.sector_size ); break;
|
|
}
|
|
|
|
return CD_TRACK_RAW_DONTCARE;
|
|
}
|
|
|
|
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" );
|
|
}
|
|
}
|
|
}
|
|
|
|
int matsucd_get_next_byte( UINT8 *data )
|
|
{
|
|
/* no more data to read on this sector */
|
|
if ( cd.xfer_offset >= cd.sector_size )
|
|
return -1;
|
|
|
|
if ( data )
|
|
*data = cd.sector_buffer[cd.xfer_offset++];
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void matsucd_cdda_stop( running_machine &machine )
|
|
{
|
|
device_t *cdda = cdda_from_cdrom(machine, cd.cdrom);
|
|
|
|
if (cdda != NULL)
|
|
{
|
|
cdda_stop_audio(cdda);
|
|
cd.frame_timer->reset( );
|
|
}
|
|
}
|
|
|
|
static void matsucd_cdda_play( running_machine &machine, UINT32 lba, UINT32 num_blocks )
|
|
{
|
|
device_t *cdda = cdda_from_cdrom(machine, cd.cdrom);
|
|
if (cdda != NULL)
|
|
{
|
|
cdda_start_audio(cdda, lba, num_blocks);
|
|
cd.frame_timer->adjust(attotime::from_hz( 75 ));
|
|
}
|
|
}
|
|
|
|
static void matsucd_cdda_pause( running_machine &machine, int pause )
|
|
{
|
|
device_t *cdda = cdda_from_cdrom(machine, cd.cdrom);
|
|
if (cdda != NULL)
|
|
{
|
|
cdda_pause_audio(cdda, pause);
|
|
|
|
if ( pause )
|
|
{
|
|
cd.frame_timer->reset( );
|
|
}
|
|
else
|
|
{
|
|
cd.frame_timer->adjust(attotime::from_hz( 75 ));
|
|
}
|
|
}
|
|
}
|
|
|
|
static UINT8 matsucd_cdda_getstatus( running_machine &machine, UINT32 *lba )
|
|
{
|
|
device_t *cdda = cdda_from_cdrom(machine, cd.cdrom);
|
|
|
|
if ( lba ) *lba = 0;
|
|
|
|
if (cdda != NULL)
|
|
{
|
|
if (cdda_audio_active(cdda))
|
|
{
|
|
if ( lba ) *lba = cdda_get_audio_lba(cdda);
|
|
|
|
if (cdda_audio_paused(cdda))
|
|
{
|
|
return 0x12; /* audio paused */
|
|
}
|
|
else
|
|
{
|
|
return 0x11; /* audio in progress */
|
|
}
|
|
}
|
|
else if (cdda_audio_ended(cdda))
|
|
{
|
|
return 0x13; /* audio ended */
|
|
}
|
|
}
|
|
|
|
return 0x15; /* no audio status */
|
|
}
|
|
|
|
void matsucd_enable_w( int level )
|
|
{
|
|
cd.enabled = ( level ) ? 0 : 1;
|
|
}
|
|
|
|
void matsucd_cmd_w( int level )
|
|
{
|
|
cd.cmd_signal = ( level ) ? 0 : 1;
|
|
}
|
|
|
|
int matsucd_stch_r( void )
|
|
{
|
|
return cd.stch_signal ? 0 : 1;
|
|
}
|
|
|
|
int matsucd_sten_r( void )
|
|
{
|
|
return cd.sten_signal ? 0 : 1;
|
|
}
|
|
|
|
int matsucd_scor_r( void )
|
|
{
|
|
return cd.scor_signal ? 0 : 1;
|
|
}
|
|
|
|
static void update_status_enable( running_machine &machine, int level )
|
|
{
|
|
cd.sten_signal = level;
|
|
|
|
if ( cd.sten_cb )
|
|
{
|
|
(*cd.sten_cb)(machine, cd.sten_signal);
|
|
}
|
|
}
|
|
|
|
static void update_status_changed( running_machine &machine, int level )
|
|
{
|
|
cd.stch_signal = level;
|
|
|
|
if ( cd.stch_cb )
|
|
{
|
|
(*cd.stch_cb)(machine, cd.stch_signal);
|
|
}
|
|
}
|
|
|
|
static void update_subcode_ready( running_machine &machine, int level )
|
|
{
|
|
cd.scor_signal = level;
|
|
|
|
if ( cd.scor_cb )
|
|
{
|
|
(*cd.scor_cb)(machine, cd.scor_signal);
|
|
}
|
|
}
|
|
|
|
static TIMER_CALLBACK(matsucd_set_status_end)
|
|
{
|
|
update_status_changed( machine, 1 );
|
|
}
|
|
|
|
static void matsucd_set_status( running_machine &machine, UINT8 status )
|
|
{
|
|
if ( status != cd.status )
|
|
{
|
|
cd.status = status;
|
|
|
|
if ( cd.stch_signal != 0 )
|
|
{
|
|
update_status_changed( machine, 0 );
|
|
machine.scheduler().timer_set(attotime::from_msec(1), FUNC(matsucd_set_status_end));
|
|
}
|
|
}
|
|
}
|
|
|
|
static TIMER_CALLBACK(matsu_subcode_proc)
|
|
{
|
|
device_t *cdda = cdda_from_cdrom(machine, cd.cdrom);
|
|
|
|
(void)param;
|
|
|
|
if (cdda != NULL)
|
|
{
|
|
UINT8 s = matsucd_cdda_getstatus(machine, NULL);
|
|
UINT8 newstatus = cd.status;
|
|
|
|
if ( s == 0x11 || s == 0x12 )
|
|
{
|
|
if ( s == 0x11 )
|
|
{
|
|
update_subcode_ready( machine, 1 );
|
|
update_subcode_ready( machine, 0 );
|
|
}
|
|
|
|
newstatus |= MATSU_STATUS_PLAYING;
|
|
|
|
cd.frame_timer->adjust(attotime::from_hz( 75 ));
|
|
}
|
|
else
|
|
{
|
|
newstatus &= ~MATSU_STATUS_PLAYING;
|
|
}
|
|
|
|
matsucd_set_status( machine, newstatus );
|
|
}
|
|
}
|
|
|
|
static void matsucd_command_error( running_machine &machine )
|
|
{
|
|
UINT8 newstatus = cd.status;
|
|
|
|
newstatus &= ~MATSU_STATUS_SUCCESS;
|
|
newstatus |= MATSU_STATUS_ERROR;
|
|
|
|
matsucd_set_status( machine, newstatus );
|
|
}
|
|
|
|
static void matsucd_complete_cmd( running_machine &machine, UINT8 len )
|
|
{
|
|
UINT8 newstatus = cd.status;
|
|
|
|
cd.input_pos = 0;
|
|
cd.output_pos = 0;
|
|
cd.output_len = len;
|
|
|
|
newstatus &= ~MATSU_STATUS_ERROR;
|
|
newstatus |= MATSU_STATUS_SUCCESS;
|
|
|
|
matsucd_set_status( machine, newstatus );
|
|
|
|
update_status_enable( machine, 1 );
|
|
update_status_enable( machine, 0 );
|
|
}
|
|
|
|
UINT8 matsucd_response_r( running_machine &machine )
|
|
{
|
|
UINT8 v = cd.output[cd.output_pos++];
|
|
|
|
if ( cd.output_pos < cd.output_len )
|
|
{
|
|
update_status_enable( machine, 1 );
|
|
update_status_enable( machine, 0 );
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|