summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Angelo Salese <angelosa@users.noreply.github.com>2010-10-25 01:29:55 +0000
committer Angelo Salese <angelosa@users.noreply.github.com>2010-10-25 01:29:55 +0000
commit8648f4a482a2864ec9c1c027c1fc14f2d4e9d1de (patch)
tree406841159d008c1ad73f96ffee710403fd822429
parent1eb4b235852394d37ad1ddbd88d2de09e479b91a (diff)
Latest megadriv source
-rw-r--r--src/mame/drivers/megadriv.c240
1 files changed, 187 insertions, 53 deletions
diff --git a/src/mame/drivers/megadriv.c b/src/mame/drivers/megadriv.c
index ebb0e5f253a..b06cff7fb2b 100644
--- a/src/mame/drivers/megadriv.c
+++ b/src/mame/drivers/megadriv.c
@@ -345,6 +345,8 @@ static cpu_device *_segacd_68k_cpu;
static emu_timer *segacd_gfx_conversion_timer;
static emu_timer *segacd_dmna_ret_timer;
static emu_timer *segacd_irq3_timer;
+static emu_timer *segacd_hock_timer;
+static UINT8 hock_cmd;
static int segacd_wordram_mapped = 0;
static TIMER_CALLBACK( segacd_irq3_timer_callback );
@@ -397,6 +399,7 @@ static struct
{
UINT8 buffer[5];
UINT8 ctrl;
+ UINT8 scd_status; // SCSI status?
}segacd_cdd;
#ifdef MESS
static struct
@@ -404,6 +407,8 @@ static struct
UINT32 current_frame;
UINT32 end_frame;
UINT32 last_frame;
+ UINT8 first_track;
+ UINT8 last_track;
cdrom_file *cd;
const cdrom_toc* toc;
@@ -4994,6 +4999,39 @@ INLINE UINT8 get_stampmap_32x32_16x16_tile_info_pixel(running_machine* machine,
}
+static TIMER_CALLBACK( segacd_hock_callback )
+{
+ int i,cdd_crc;
+
+ if(hock_cmd)
+ {
+// segacd_cdd.ctrl &= ~4; // clear HOCK flag
+
+ segacd_cdd_rx[0] = (segacd_cdd.buffer[0] & 0xf0) >> 4;
+ segacd_cdd_rx[1] = (segacd_cdd.buffer[0] & 0x0f) >> 0;
+ segacd_cdd_rx[2] = (segacd_cdd.buffer[1] & 0xf0) >> 4;
+ segacd_cdd_rx[3] = (segacd_cdd.buffer[1] & 0x0f) >> 0;
+ segacd_cdd_rx[4] = (segacd_cdd.buffer[2] & 0xf0) >> 4;
+ segacd_cdd_rx[5] = (segacd_cdd.buffer[2] & 0x0f) >> 0;
+ segacd_cdd_rx[6] = (segacd_cdd.buffer[3] & 0xf0) >> 4;
+ segacd_cdd_rx[7] = (segacd_cdd.buffer[3] & 0x0f) >> 0;
+ segacd_cdd_rx[8] = (segacd_cdd.buffer[4] & 0x0f) >> 0;
+
+ /* Do checksum calculation of the above registers */
+ cdd_crc = 0;
+ for(i=0;i<9;i++)
+ cdd_crc += segacd_cdd_rx[i];
+
+ segacd_cdd_rx[9] = ((cdd_crc & 0xf) ^ 0xf);
+
+ if(segacd_irq_mask & 0x10)
+ cputag_set_input_line(machine, "segacd_68k", 4, HOLD_LINE);
+
+ hock_cmd = 0;
+ }
+
+ timer_adjust_oneshot(segacd_hock_timer, ATTOTIME_IN_HZ(75), 0);
+}
/* main CPU map set up in INIT */
@@ -5036,6 +5074,8 @@ void segacd_init_main_cpu( running_machine* machine )
segacd_dmna_ret_timer = timer_alloc(machine, segacd_dmna_ret_timer_callback, 0);
timer_adjust_oneshot(segacd_gfx_conversion_timer, attotime_never, 0);
+ segacd_hock_timer = timer_alloc(machine, segacd_hock_callback, 0);
+ timer_adjust_oneshot(segacd_hock_timer, attotime_never, 0);
segacd_irq3_timer = timer_alloc(machine, segacd_irq3_timer_callback, 0);
timer_adjust_oneshot(segacd_irq3_timer, attotime_never, 0);
@@ -5108,6 +5148,8 @@ static MACHINE_RESET( segacd )
segacd.end_frame = segacd.last_frame;
}
}
+
+ segacd_cdd.scd_status = 0x00; // initial state
}
#endif
@@ -5118,6 +5160,8 @@ static MACHINE_RESET( segacd )
segacd_ram_mode_old = 0;
timer_adjust_oneshot(segacd_dmna_ret_timer, attotime_zero, 0);
+ timer_adjust_oneshot(segacd_hock_timer, attotime_zero, 0);
+ hock_cmd = 0;
}
@@ -5255,32 +5299,8 @@ static WRITE16_HANDLER( segacd_sub_dataram_part2_w )
}
}
-static TIMER_CALLBACK( execute_hock_irq )
-{
- int i,cdd_crc;
-
- segacd_cdd.ctrl &= ~4; // clear HOCK flag
-
- segacd_cdd_rx[0] = (segacd_cdd.buffer[0] & 0xf0) >> 4;
- segacd_cdd_rx[1] = (segacd_cdd.buffer[0] & 0x0f) >> 0;
- segacd_cdd_rx[2] = (segacd_cdd.buffer[1] & 0xf0) >> 4;
- segacd_cdd_rx[3] = (segacd_cdd.buffer[1] & 0x0f) >> 0;
- segacd_cdd_rx[4] = (segacd_cdd.buffer[2] & 0xf0) >> 4;
- segacd_cdd_rx[5] = (segacd_cdd.buffer[2] & 0x0f) >> 0;
- segacd_cdd_rx[6] = (segacd_cdd.buffer[3] & 0xf0) >> 4;
- segacd_cdd_rx[7] = (segacd_cdd.buffer[3] & 0x0f) >> 0;
- segacd_cdd_rx[8] = (segacd_cdd.buffer[4] & 0x0f) >> 0;
-
- /* Do checksum calculation of the above registers */
- cdd_crc = 0;
- for(i=0;i<9;i++)
- cdd_crc += segacd_cdd_rx[i];
-
- segacd_cdd_rx[9] = ((cdd_crc & 0xf) ^ 0xf);
-
- cputag_set_input_line(machine, "segacd_68k", 4, HOLD_LINE);
-}
+#if 0
static void cdd_hock_irq(running_machine *machine,UINT8 dir)
{
if((segacd_cdd.ctrl & 4 || dir) && segacd_irq_mask & 0x10) // export status, check if bit 2 (HOst ClocK) and irq is enabled
@@ -5289,6 +5309,7 @@ static void cdd_hock_irq(running_machine *machine,UINT8 dir)
timer_set(machine, ATTOTIME_IN_HZ(75), NULL,0, execute_hock_irq); // 1 / 75th of a second
}
}
+#endif
static READ16_HANDLER( segacd_irq_mask_r )
{
@@ -5299,8 +5320,7 @@ static WRITE16_HANDLER( segacd_irq_mask_w )
{
segacd_irq_mask = data & 0x7e;
- cdd_hock_irq(space->machine,0);
- // check here other pending IRQs
+ // TODO: check here pending IRQs
}
static READ16_HANDLER( segacd_cdd_ctrl_r )
@@ -5312,7 +5332,12 @@ static WRITE16_HANDLER( segacd_cdd_ctrl_w )
{
segacd_cdd.ctrl = data;
- cdd_hock_irq(space->machine,0);
+ hock_cmd = (data & 4) >> 2;
+
+ if(data & 4) // enable Hock timer
+ timer_adjust_oneshot(segacd_hock_timer, ATTOTIME_IN_HZ(75), 0);
+ else
+ timer_adjust_oneshot(segacd_hock_timer, attotime_never, 0);
}
/* 68k <- CDD communication comms are 4-bit wide */
@@ -5326,7 +5351,7 @@ static const char *const segacd_cdd_cmd[] =
"Status",
"Stop All",
"Get TOC Info",
- "Read",
+ "Play",
"Seek",
"Pause/Stop",
"Resume",
@@ -5365,13 +5390,13 @@ static const char *const segacd_cdd_get_toc_cmd[] =
static void segacd_cdd_get_status(running_machine *machine)
{
- segacd_cdd.buffer[0] = 0;
- segacd_cdd.buffer[1] = 0;
- segacd_cdd.buffer[2] = 0;
- segacd_cdd.buffer[3] = 0;
- segacd_cdd.buffer[4] = 0;
+ //segacd_cdd.buffer[0] = 0;
+ //segacd_cdd.buffer[1] = 0;
+ //segacd_cdd.buffer[2] = 0;
+ //segacd_cdd.buffer[3] = 0;
+ //segacd_cdd.buffer[4] = 0;
- cdd_hock_irq(machine,1);
+ hock_cmd = 1;
}
static void segacd_cdd_stop_all(running_machine *machine)
@@ -5384,43 +5409,83 @@ static void segacd_cdd_stop_all(running_machine *machine)
segacd_cdd.buffer[3] = 0;
segacd_cdd.buffer[4] = 0;
- cdd_hock_irq(machine,1);
+ hock_cmd = 1;
}
static void segacd_cdd_get_toc_info(running_machine *machine)
{
- segacd_cdd.buffer[0] = (segacd_cdd_tx[3] & 0xf) | (segacd_cdd.buffer[0] & 0xf0);
+ segacd_cdd.buffer[0] = (segacd_cdd_tx[3] & 0xf) | (segacd_cdd.scd_status & 0xf0); // TODO: remove me
#if LOG_CDD
- printf("CDD: TOC command %s issued\n",segacd_cdd_get_toc_cmd[segacd_cdd_tx[3] & 0xf]);
+ if(segacd_cdd_tx[3] >= 6)
+ printf("CDD: TOC command %s issued\n",segacd_cdd_get_toc_cmd[segacd_cdd_tx[3] & 0xf]);
#endif
+ // TODO: check if tray is open
+
if ( ! segacd.cd ) // no cd is present
{
- segacd_cdd.buffer[0] = (0) | (segacd_cdd.buffer[0] & 0xf0);
+ segacd_cdd.scd_status = 0x00;
+ segacd_cdd.buffer[0] = (0) | (segacd_cdd.scd_status & 0xf0);
segacd_cdd.buffer[1] = 0;
segacd_cdd.buffer[2] = 0;
segacd_cdd.buffer[3] = 0;
segacd_cdd.buffer[4] = 0;
- cdd_hock_irq(machine,1);
+ hock_cmd = 1;
return;
}
else
{
switch(segacd_cdd_tx[3] & 0xf)
{
+ case 0x0: //Get Current Position
+ {
+ UINT32 msf;
+
+ segacd_cdd.scd_status = 0x40; //TODO: check this
+
+ msf = lba_to_msf( segacd.current_frame );
+ segacd_cdd.buffer[0] = (0x0 & 0xf) | (segacd_cdd.scd_status & 0xf0);
+ segacd_cdd.buffer[1] = dec_2_bcd( msf >> 16 ) & 0xff;
+ segacd_cdd.buffer[2] = dec_2_bcd( msf >> 8 ) & 0xff;
+ segacd_cdd.buffer[3] = dec_2_bcd( msf >> 0 ) & 0xff;
+ segacd_cdd.buffer[4] = 0;
+
+ hock_cmd = 1;
+ return;
+ }
+ case 0x1: //Get Elapsed Time of Current Track
+ {
+ UINT32 msf;
+ UINT32 end_frame_track;
+
+ segacd_cdd.scd_status = 0x40; //TODO: check this
+
+ end_frame_track = segacd.toc->tracks[ cdrom_get_track(segacd.cd, segacd.current_frame) + 1 ].physframeofs; // correct?
+
+ msf = lba_to_msf( end_frame_track - segacd.current_frame );
+
+ segacd_cdd.buffer[0] = (0x1 & 0xf) | (segacd_cdd.scd_status & 0xf0);
+ segacd_cdd.buffer[1] = dec_2_bcd( msf >> 16 ) & 0xff;
+ segacd_cdd.buffer[2] = dec_2_bcd( msf >> 8 ) & 0xff;
+ segacd_cdd.buffer[3] = dec_2_bcd( msf >> 0 ) & 0xff;
+ segacd_cdd.buffer[4] = 0;
+
+ hock_cmd = 1;
+ return;
+ }
case 0x2: //Get Current Track
{
segacd_cdd.buffer[0] = (0x2 & 0xf) | (segacd_cdd.buffer[0] & 0xf0);
- segacd_cdd.buffer[0] = 1; // current track number, TODO
- segacd_cdd.buffer[1] = 0;
+ segacd_cdd.buffer[1] = cdrom_get_track(segacd.cd, segacd.current_frame);
segacd_cdd.buffer[2] = 0;
segacd_cdd.buffer[3] = 0;
segacd_cdd.buffer[4] = 0;
- cdd_hock_irq(machine,1);
+
+ hock_cmd = 1;
return;
}
case 0x3: //Get Total Length (in MSF)
@@ -5429,38 +5494,105 @@ static void segacd_cdd_get_toc_info(running_machine *machine)
frame = segacd.toc->tracks[segacd.toc->numtrks-1].physframeofs;
frame += segacd.toc->tracks[segacd.toc->numtrks-1].frames;
+ frame += 150; // 2 seconds of pre-gap
msf = lba_to_msf( frame );
- segacd_cdd.buffer[0] = (0x3 & 0xf) | (segacd_cdd.buffer[0] & 0xf0);
+ segacd_cdd.buffer[0] = (0x3 & 0xf) | (segacd_cdd.scd_status & 0xf0);
segacd_cdd.buffer[1] = ((msf >> 16) & 0xff);
segacd_cdd.buffer[2] = ((msf >> 8) & 0xff);
segacd_cdd.buffer[3] = ((msf >> 0) & 0xff);
segacd_cdd.buffer[4] = 0;
- cdd_hock_irq(machine,1);
+ printf("%02x %02x %02x %02x %02x\n",segacd_cdd.buffer[0],segacd_cdd.buffer[1],segacd_cdd.buffer[2],segacd_cdd.buffer[3],segacd_cdd.buffer[4]);
+
+ hock_cmd = 1;
return;
}
- case 0x4: //Get First and Last Track Number
+ case 0x4: //Get First and Last Track Number
{
- segacd_cdd.buffer[0] = (0x4 & 0xf) | (segacd_cdd.buffer[0] & 0xf0);
- segacd_cdd.buffer[1] = dec_2_bcd(1);
- segacd_cdd.buffer[2] = dec_2_bcd(segacd.toc->numtrks);
+ segacd_cdd.scd_status = 0x40;
+ segacd_cdd.buffer[0] = (0x4 & 0xf) | (segacd_cdd.scd_status & 0xf0);
+ segacd.first_track = dec_2_bcd(1);
+ segacd.last_track = dec_2_bcd(segacd.toc->numtrks - 1);
+ segacd_cdd.buffer[1] = segacd.first_track;
+ segacd_cdd.buffer[2] = segacd.last_track;
segacd_cdd.buffer[3] = 0;
segacd_cdd.buffer[4] = 0;
- cdd_hock_irq(machine,1);
+ printf("%02x %02x %02x %02x %02x\n",segacd_cdd.buffer[0],segacd_cdd.buffer[1],segacd_cdd.buffer[2],segacd_cdd.buffer[3],segacd_cdd.buffer[4]);
+
+ hock_cmd = 1;
+ return;
+ }
+ case 0x5: //Get Track Addresses
+ {
+ UINT8 track_num;
+ UINT32 start_frame,frame,msf;
+
+ track_num = ((segacd_cdd_tx[4] & 0xf) * 10) | (segacd_cdd_tx[5] & 0x0f);
+
+ if(track_num > segacd.last_track)
+ track_num = segacd.last_track;
+ if(track_num < segacd.first_track)
+ track_num = segacd.first_track;
+ start_frame = segacd.toc->tracks[ bcd_2_dec( track_num - 1 ) ].physframeofs;
+ //end_frame = segacd.toc->tracks[ bcd_2_dec( track_num ) ].physframeofs;
+ frame = start_frame;
+ msf = lba_to_msf( frame );
+
+ segacd_cdd.buffer[0] = (0x5 & 0xf) | (segacd_cdd.scd_status & 0xf0);
+ segacd_cdd.buffer[1] = ((msf >> 16) & 0xff);
+ segacd_cdd.buffer[2] = ((msf >> 8) & 0xff);
+ segacd_cdd.buffer[3] = ((msf >> 0) & 0xff);
+ segacd_cdd.buffer[4] = (track_num % 10) | (( segacd.toc->tracks[track_num-1].trktype == CD_TRACK_AUDIO ) ? 0x80 : 0x00);
+
+ printf("%02x %02x %02x %02x %02x\n",segacd_cdd.buffer[0],segacd_cdd.buffer[1],segacd_cdd.buffer[2],segacd_cdd.buffer[3],segacd_cdd.buffer[4]);
+
+ hock_cmd = 1;
+ return;
}
- return;
//default: logerror("CDD: unhandled TOC command %s issued\n",segacd_cdd_get_toc_cmd[segacd_cdd_tx[3] & 0xf]);
}
}
- cdd_hock_irq(machine,1);
+ hock_cmd = 1;
}
#endif
+static void segacd_cdd_seek(running_machine *machine)
+{
+ UINT8 m,s,f;
+ UINT8 track_num;
+ UINT32 frame;
+
+ // TODO: check if tray is open or CD isn't there and throw an error if so
+
+ segacd_cdd.scd_status = 0x20; //READY flag
+
+ m = ((segacd_cdd_tx[2] & 0xf) * 10) | (segacd_cdd_tx[3] & 0x0f);
+ s = ((segacd_cdd_tx[4] & 0xf) * 10) | (segacd_cdd_tx[5] & 0x0f);
+ f = ((segacd_cdd_tx[6] & 0xf) * 10) | (segacd_cdd_tx[7] & 0x0f);
+
+ frame = (m << 16) | (s << 8) | (f);
+
+ track_num = cdrom_get_track(segacd.cd, frame);
+ segacd.current_frame = frame;
+// printf("%02x %02x %02x %02x\n",m,s,f,track_num);
+
+ segacd_cdd.ctrl &= 0xfeff;
+ segacd_cdd.ctrl |= (( segacd.toc->tracks[track_num-1].trktype == CD_TRACK_AUDIO ) ? 0x000 : 0x100);
+
+ segacd_cdd.buffer[0] = segacd_cdd.scd_status & 0x20; // set READY
+ segacd_cdd.buffer[1] = 0;
+ segacd_cdd.buffer[2] = 0;
+ segacd_cdd.buffer[3] = 0;
+ segacd_cdd.buffer[4] = 0;
+
+ hock_cmd = 1;
+}
+
static WRITE8_HANDLER( segacd_cdd_tx_w )
{
//printf("CDD Communication write %02x -> [%02x]\n",data,offset);
@@ -5470,7 +5602,7 @@ static WRITE8_HANDLER( segacd_cdd_tx_w )
if(offset == 9) //execute the command when crc is sent (TODO: I wonder if we need to check if crc is valid. Plus obviously this shouldn't be instant)
{
#if LOG_CDD
- if(segacd_cdd_tx[0] != 0)
+ if(segacd_cdd_tx[0] != 0 && segacd_cdd_tx[0] != 2)
printf("CDD: command %s issued\n",segacd_cdd_cmd[segacd_cdd_tx[0] & 0xf]);
#endif
@@ -5479,6 +5611,8 @@ static WRITE8_HANDLER( segacd_cdd_tx_w )
case 0x0: segacd_cdd_get_status(space->machine); break;
case 0x1: segacd_cdd_stop_all(space->machine); break;
case 0x2: segacd_cdd_get_toc_info(space->machine); break;
+ //case 0x3: segacd_cdd_play(space->machine); break;
+ case 0x4: segacd_cdd_seek(space->machine); break;
//default: logerror("CDD: unhandled command %s issued\n",segacd_cdd_cmd[segacd_cdd_tx[0] & 0xf]);
}
}