Added a readyq callback to the TMS5220 interface. This is needed to solve MT #3832. In zaccaria games, the intq and readyq are connected to pia 6821 lines ca2 and cb1 which are edge driven. Just reading readyq would miss to detect a state change if between reads readyq went 0-1-0. Updated zaccaria.c and looping.c. Fixes MT #3832. [Couriersud]

This commit is contained in:
Couriersud 2010-05-24 12:13:13 +00:00
parent 4093adacbc
commit 37f35e51c1
4 changed files with 40 additions and 24 deletions

View File

@ -238,6 +238,7 @@ struct _tms5220_state
/* callbacks */ /* callbacks */
devcb_resolved_write_line irq_func; devcb_resolved_write_line irq_func;
devcb_resolved_write_line readyq_func;
/* these contain data that describes the 128-bit data FIFO */ /* these contain data that describes the 128-bit data FIFO */
UINT8 fifo[FIFO_SIZE]; UINT8 fifo[FIFO_SIZE];
@ -254,6 +255,7 @@ struct _tms5220_state
UINT8 buffer_low; /* If 1, FIFO has less than 8 bytes in it */ UINT8 buffer_low; /* If 1, FIFO has less than 8 bytes in it */
UINT8 buffer_empty; /* If 1, FIFO is empty */ UINT8 buffer_empty; /* If 1, FIFO is empty */
UINT8 irq_pin; /* state of the IRQ pin (output) */ UINT8 irq_pin; /* state of the IRQ pin (output) */
UINT8 ready_pin; /* state of the READY pin (output) */
/* these contain data describing the current and previous voice frames */ /* these contain data describing the current and previous voice frames */
#define OLD_FRAME_SILENCE_FLAG (tms->old_frame_energy_idx == 0) // 1 if E=0, 0 otherwise. #define OLD_FRAME_SILENCE_FLAG (tms->old_frame_energy_idx == 0) // 1 if E=0, 0 otherwise.
@ -362,6 +364,7 @@ static void update_status_and_ints(tms5220_state *tms);
static void set_interrupt_state(tms5220_state *tms, int state); static void set_interrupt_state(tms5220_state *tms, int state);
static INT32 lattice_filter(tms5220_state *tms); static INT32 lattice_filter(tms5220_state *tms);
static INT16 clip_analog(INT16 clip); static INT16 clip_analog(INT16 clip);
static void update_ready_state(tms5220_state *tms);
static STREAM_UPDATE( tms5220_update ); static STREAM_UPDATE( tms5220_update );
void tms5220_set_variant(tms5220_state *tms, int variant) void tms5220_set_variant(tms5220_state *tms, int variant)
@ -400,6 +403,7 @@ static void register_for_save_states(tms5220_state *tms)
state_save_register_device_item(tms->device, 0, tms->buffer_low); state_save_register_device_item(tms->device, 0, tms->buffer_low);
state_save_register_device_item(tms->device, 0, tms->buffer_empty); state_save_register_device_item(tms->device, 0, tms->buffer_empty);
state_save_register_device_item(tms->device, 0, tms->irq_pin); state_save_register_device_item(tms->device, 0, tms->irq_pin);
state_save_register_device_item(tms->device, 0, tms->ready_pin);
state_save_register_device_item(tms->device, 0, tms->old_frame_energy_idx); state_save_register_device_item(tms->device, 0, tms->old_frame_energy_idx);
state_save_register_device_item(tms->device, 0, tms->old_frame_pitch_idx); state_save_register_device_item(tms->device, 0, tms->old_frame_pitch_idx);
@ -560,6 +564,9 @@ static void tms5220_data_write(tms5220_state *tms, int data)
static void update_status_and_ints(tms5220_state *tms) static void update_status_and_ints(tms5220_state *tms)
{ {
/* update flags and set ints if needed */ /* update flags and set ints if needed */
update_ready_state(tms);
/* BL is set if neither byte 9 nor 8 of the fifo are in use; this /* BL is set if neither byte 9 nor 8 of the fifo are in use; this
translates to having fifo_count (which ranges from 0 bytes in use to 16 translates to having fifo_count (which ranges from 0 bytes in use to 16
bytes used) being less than or equal to 8. Victory/Victorba depends on this. */ bytes used) being less than or equal to 8. Victory/Victorba depends on this. */
@ -1378,6 +1385,23 @@ static void set_interrupt_state(tms5220_state *tms, int state)
tms->irq_pin = state; tms->irq_pin = state;
} }
/**********************************************************************************************
update_ready_state -- update the ready line
***********************************************************************************************/
static void update_ready_state(tms5220_state *tms)
{
int state = tms5220_ready_read(tms);
#ifdef DEBUG_PIN_READS
logerror("ready pin set to state %d\n", state);
#endif
if (tms->readyq_func.write && state != tms->ready_pin)
devcb_call_write_line(&tms->readyq_func, !state);
tms->ready_pin = state;
}
/********************************************************************************************** /**********************************************************************************************
@ -1399,8 +1423,9 @@ static DEVICE_START( tms5220 )
assert_always(tms != NULL, "Error creating TMS5220 chip"); assert_always(tms != NULL, "Error creating TMS5220 chip");
/* resolve irq line */ /* resolve irq and readyq line */
devcb_resolve_write_line(&tms->irq_func, &tms->intf->irq_func, device); devcb_resolve_write_line(&tms->irq_func, &tms->intf->irq_func, device);
devcb_resolve_write_line(&tms->readyq_func, &tms->intf->readyq_func, device);
/* initialize a stream */ /* initialize a stream */
tms->stream = stream_create(device, 0, 1, device->clock / 80, tms, tms5220_update); tms->stream = stream_create(device, 0, 1, device->clock / 80, tms, tms5220_update);
@ -1459,8 +1484,9 @@ static DEVICE_RESET( tms5220 )
/* initialize the chip state */ /* initialize the chip state */
/* Note that we do not actually clear IRQ on start-up : IRQ is even raised if tms->buffer_empty or tms->buffer_low are 0 */ /* Note that we do not actually clear IRQ on start-up : IRQ is even raised if tms->buffer_empty or tms->buffer_low are 0 */
tms->speaking_now = tms->speak_external = tms->talk_status = tms->irq_pin = 0; tms->speaking_now = tms->speak_external = tms->talk_status = tms->irq_pin = tms->ready_pin = 0;
set_interrupt_state(tms, 0); set_interrupt_state(tms, 0);
update_ready_state(tms);
tms->buffer_empty = tms->buffer_low = 1; tms->buffer_empty = tms->buffer_low = 1;
tms->RDB_flag = FALSE; tms->RDB_flag = FALSE;
@ -1524,6 +1550,7 @@ static TIMER_CALLBACK( io_ready_cb )
} }
} }
tms->io_ready = param; tms->io_ready = param;
update_ready_state(tms);
} }
WRITE_LINE_DEVICE_HANDLER( tms5220_rsq_w ) WRITE_LINE_DEVICE_HANDLER( tms5220_rsq_w )
@ -1571,8 +1598,8 @@ WRITE_LINE_DEVICE_HANDLER( tms5220_rsq_w )
/* 100 nsec from data sheet, through 3 asynchronous gates on patent */ /* 100 nsec from data sheet, through 3 asynchronous gates on patent */
//timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock), tms, 0, io_ready_cb); // /READY goes inactive immediately, within one clock... for that matter, what do we even need a timer for then? //timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock), tms, 0, io_ready_cb); // /READY goes inactive immediately, within one clock... for that matter, what do we even need a timer for then?
tms->io_ready = 0; tms->io_ready = 0;
/* 25 usec (16 clocks) in datasheet, but zaccaria games glitch or fail to talk if that value is used. The zaccaria glitching may be buggy game code or may be a bug with the MAME 6821 PIA code which interfaces with the tms5200, particularly its handling of updates of the CA1 and CA2 lines? */ update_ready_state(tms);
//timer_set(tms->device->machine, ATTOTIME_IN_USEC(100), tms, 1, io_ready_cb); /* 25 usec (16 clocks) in datasheet */
timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock/16), tms, 1, io_ready_cb); // this should take around 10-16 (closer to ~11?) cycles to complete timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock/16), tms, 1, io_ready_cb); // this should take around 10-16 (closer to ~11?) cycles to complete
} }
} }
@ -1620,6 +1647,7 @@ WRITE_LINE_DEVICE_HANDLER( tms5220_wsq_w )
/* 100 nsec from data sheet, through 3 asynchronous gates on patent */ /* 100 nsec from data sheet, through 3 asynchronous gates on patent */
//timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock), tms, 0, io_ready_cb); // /READY goes inactive immediately, within one clock... for that matter, what do we even need a timer for then? //timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock), tms, 0, io_ready_cb); // /READY goes inactive immediately, within one clock... for that matter, what do we even need a timer for then?
tms->io_ready = 0; tms->io_ready = 0;
update_ready_state(tms);
timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock/16), tms, 1, io_ready_cb); // this should take around 10-16 (closer to ~15) cycles to complete for fifo writes, TODO: but actually depends on what command is written if in command mode timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock/16), tms, 1, io_ready_cb); // this should take around 10-16 (closer to ~15) cycles to complete for fifo writes, TODO: but actually depends on what command is written if in command mode
} }
} }

View File

@ -11,7 +11,8 @@
typedef struct _tms5220_interface tms5220_interface; typedef struct _tms5220_interface tms5220_interface;
struct _tms5220_interface struct _tms5220_interface
{ {
devcb_write_line irq_func; /* IRQ callback function */ devcb_write_line irq_func; /* IRQ callback function, active low, i.e. state=0 */
devcb_write_line readyq_func; /* Ready callback function, active low, i.e. state=0 */
int (*read)(running_device *device, int count); /* speech ROM read callback */ int (*read)(running_device *device, int count); /* speech ROM read callback */
void (*load_address)(running_device *device, int data); /* speech ROM load address callback */ void (*load_address)(running_device *device, int data); /* speech ROM load address callback */

View File

@ -580,7 +580,8 @@ GFXDECODE_END
static const tms5220_interface tms5220_config = static const tms5220_interface tms5220_config =
{ {
DEVCB_LINE(looping_spcint) DEVCB_LINE(looping_spcint), // IRQ
DEVCB_NULL // READYQ
}; };
static const ay8910_interface ay8910_config = static const ay8910_interface ay8910_config =

View File

@ -161,15 +161,6 @@ static WRITE8_DEVICE_HANDLER( zaccaria_port0b_w )
last_port0b = data; last_port0b = data;
} }
static INTERRUPT_GEN( zaccaria_cb1_toggle )
{
running_device *pia0 = devtag_get_device(device->machine, "pia0");
static int toggle;
pia6821_cb1_w(pia0,0, toggle & 1);
toggle ^= 1;
}
static WRITE8_DEVICE_HANDLER( zaccaria_port1b_w ) static WRITE8_DEVICE_HANDLER( zaccaria_port1b_w )
{ {
running_device *tms = devtag_get_device(device->machine, "tms"); running_device *tms = devtag_get_device(device->machine, "tms");
@ -186,11 +177,6 @@ static WRITE8_DEVICE_HANDLER( zaccaria_port1b_w )
set_led_status(device->machine, 0,~data & 0x10); set_led_status(device->machine, 0,~data & 0x10);
} }
static READ_LINE_DEVICE_HANDLER( zaccaria_ca2_r )
{
return tms5220_readyq_r(device);
}
static const pia6821_interface pia_0_intf = static const pia6821_interface pia_0_intf =
{ {
@ -214,8 +200,8 @@ static const pia6821_interface pia_1_intf =
DEVCB_DEVICE_HANDLER("tms", tms5220_status_r), /* port A in */ DEVCB_DEVICE_HANDLER("tms", tms5220_status_r), /* port A in */
DEVCB_NULL, /* port B in */ DEVCB_NULL, /* port B in */
DEVCB_NULL, /* line CA1 in */ DEVCB_NULL, /* line CA1 in */
DEVCB_NULL, /* line CB1 in */ DEVCB_NULL, //DEVCB_DEVICE_LINE("tms", tms5220_intq_r), /* line CB1 in */
DEVCB_DEVICE_LINE("tms", zaccaria_ca2_r), /* line CA2 in */ DEVCB_NULL, //DEVCB_DEVICE_LINE("tms", tms5220_readyq_r), /* line CA2 in */
DEVCB_NULL, /* line CB2 in */ DEVCB_NULL, /* line CB2 in */
DEVCB_DEVICE_HANDLER("tms", tms5220_data_w), /* port A out */ DEVCB_DEVICE_HANDLER("tms", tms5220_data_w), /* port A out */
DEVCB_HANDLER(zaccaria_port1b_w), /* port B out */ DEVCB_HANDLER(zaccaria_port1b_w), /* port B out */
@ -541,7 +527,8 @@ static const ay8910_interface ay8910_config =
static const tms5220_interface tms5220_config = static const tms5220_interface tms5220_config =
{ {
DEVCB_DEVICE_HANDLER("pia1", pia6821_cb1_w) /* IRQ handler */ DEVCB_DEVICE_HANDLER("pia1", pia6821_cb1_w), /* IRQ handler */
DEVCB_DEVICE_HANDLER("pia1", pia6821_ca2_w) /* READYQ handler */
}; };
@ -556,7 +543,6 @@ static MACHINE_DRIVER_START( zaccaria )
MDRV_CPU_ADD("audiocpu", M6802,XTAL_3_579545MHz) /* verified on pcb */ MDRV_CPU_ADD("audiocpu", M6802,XTAL_3_579545MHz) /* verified on pcb */
MDRV_CPU_PROGRAM_MAP(sound_map_1) MDRV_CPU_PROGRAM_MAP(sound_map_1)
MDRV_CPU_PERIODIC_INT(zaccaria_cb1_toggle,(double)3580000/4096)
MDRV_QUANTUM_TIME(HZ(1000000)) MDRV_QUANTUM_TIME(HZ(1000000))
MDRV_CPU_ADD("audio2", M6802,XTAL_3_579545MHz) /* verified on pcb */ MDRV_CPU_ADD("audio2", M6802,XTAL_3_579545MHz) /* verified on pcb */