mirror of
https://github.com/holub/mame
synced 2025-05-26 07:41:28 +03:00
Fix race condition involving tms52xx status register which broke victory/victorba self test.
Updated debug routines a bit, and improved the non-NORMALMODE a bit. [Lord Nightmare]
This commit is contained in:
parent
cd4aef0bd5
commit
26e06630b5
@ -187,11 +187,15 @@ device), PES Speech adapter (serial port connection)
|
|||||||
|
|
||||||
/* *****debugging defines***** */
|
/* *****debugging defines***** */
|
||||||
#undef VERBOSE
|
#undef VERBOSE
|
||||||
// above is general, somewhat obsolete
|
// above is general, somewhat obsolete, catch all for debugs which don't fit elsewhere
|
||||||
#undef DEBUG_FIFO
|
#undef DEBUG_FIFO
|
||||||
// above debugs fifo stuff: writes, reads and flag updates
|
// above debugs fifo stuff: writes, reads and flag updates
|
||||||
#undef DEBUG_PARSE_FRAME_DUMP
|
#undef DEBUG_PARSE_FRAME_DUMP
|
||||||
// above dumps each speech frame as a binary index listing
|
// above dumps each frame to stderr: be sure to select one of the options below if you define it!
|
||||||
|
#undef DEBUG_PARSE_FRAME_DUMP_BIN
|
||||||
|
// dumps each speech frame as binary
|
||||||
|
#undef DEBUG_PARSE_FRAME_DUMP_HEX
|
||||||
|
// dumps each speech frame as hex
|
||||||
#undef DEBUG_FRAME_ERRORS
|
#undef DEBUG_FRAME_ERRORS
|
||||||
// above dumps info if a frame ran out of data
|
// above dumps info if a frame ran out of data
|
||||||
#undef DEBUG_COMMAND_DUMP
|
#undef DEBUG_COMMAND_DUMP
|
||||||
@ -435,12 +439,35 @@ static void register_for_save_states(tms5220_state *tms)
|
|||||||
|
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
||||||
#ifdef DEBUG_PARSE_FRAME_DUMP
|
#ifdef DEBUG_PARSE_FRAME_DUMP_BIN
|
||||||
static void printbits(long data, int num)
|
static void printbits(long data, int num)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i=(num-1); i>=0; i--)
|
for (i=(num-1); i>=0; i--)
|
||||||
fprintf(stderr,"%0d", (int)(data>>i)&1);
|
fprintf(stderr,"%0ld", (data>>i)&1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUG_PARSE_FRAME_DUMP_HEX
|
||||||
|
static void printbits(long data, int num)
|
||||||
|
{
|
||||||
|
switch((num-1)&0xFC)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
fprintf(stderr,"%0lx", data);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
fprintf(stderr,"%02lx", data);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
fprintf(stderr,"%03lx", data);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
fprintf(stderr,"%03lx", data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"%04lx", data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -460,22 +487,33 @@ static void tms5220_data_write(tms5220_state *tms, int data)
|
|||||||
tms->fifo[tms->fifo_tail] = data;
|
tms->fifo[tms->fifo_tail] = data;
|
||||||
tms->fifo_tail = (tms->fifo_tail + 1) % FIFO_SIZE;
|
tms->fifo_tail = (tms->fifo_tail + 1) % FIFO_SIZE;
|
||||||
tms->fifo_count++;
|
tms->fifo_count++;
|
||||||
|
|
||||||
/* if we were speaking, then we're no longer empty */
|
|
||||||
if (tms->speak_external)
|
|
||||||
tms->buffer_empty = 0;
|
|
||||||
#ifdef DEBUG_FIFO
|
#ifdef DEBUG_FIFO
|
||||||
logerror("data_write: Added byte to FIFO (current count=%2d)\n", tms->fifo_count);
|
logerror("data_write: Added byte to FIFO (current count=%2d)\n", tms->fifo_count);
|
||||||
|
#endif
|
||||||
|
update_status_and_ints(tms);
|
||||||
|
if ((tms->talk_status == 0) && (tms->buffer_low == 0)) // we just unset buffer low with that last write, and talk status *was* zero...
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
#ifdef DEBUG_FIFO
|
||||||
|
logerror("data_write triggered talk status to go active!\n");
|
||||||
|
#endif
|
||||||
|
/* ...then we now have enough bytes to start talking; clear out the new frame parameters (it will become old frame just before the first call to parse_frame() ) */
|
||||||
|
tms->new_frame_energy = 0;
|
||||||
|
tms->new_frame_pitch = 0;
|
||||||
|
for (i = 0; i < tms->coeff->num_k; i++)
|
||||||
|
tms->new_frame_k[i] = 0;
|
||||||
|
tms->talk_status = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_FIFO
|
||||||
logerror("data_write: Ran out of room in the FIFO!\n");
|
logerror("data_write: Ran out of room in the tms52xx FIFO! this should never happen!\n");
|
||||||
// at this point, /READY should remain HIGH/inactive until the fifo has at least one byte open in it.
|
// at this point, /READY should remain HIGH/inactive until the fifo has at least one byte open in it.
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
update_status_and_ints(tms);
|
|
||||||
}
|
}
|
||||||
else //(! tms->speak_external)
|
else //(! tms->speak_external)
|
||||||
/* R Nabet : we parse commands at once. It is necessary for such commands as read. */
|
/* R Nabet : we parse commands at once. It is necessary for such commands as read. */
|
||||||
@ -703,20 +741,9 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
|
|||||||
|
|
||||||
/* if speak external is set, but talk status is not (yet) set,
|
/* if speak external is set, but talk status is not (yet) set,
|
||||||
wait for buffer low to clear */
|
wait for buffer low to clear */
|
||||||
if (!tms->talk_status && tms->speak_external)
|
if (!tms->talk_status && tms->speak_external && tms->buffer_low == 1)
|
||||||
{
|
|
||||||
if (tms->buffer_low == 1)
|
|
||||||
goto empty;
|
goto empty;
|
||||||
|
|
||||||
/* we now have enough bytes; clear out the new frame parameters (it will become old frame just before the first call to parse_frame() ) */
|
|
||||||
tms->new_frame_energy = 0;
|
|
||||||
tms->new_frame_pitch = 0;
|
|
||||||
for (i = 0; i < tms->coeff->num_k; i++)
|
|
||||||
tms->new_frame_k[i] = 0;
|
|
||||||
|
|
||||||
tms->talk_status = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* loop until the buffer is full or we've stopped speaking */
|
/* loop until the buffer is full or we've stopped speaking */
|
||||||
while ((size > 0) && tms->talk_status)
|
while ((size > 0) && tms->talk_status)
|
||||||
{
|
{
|
||||||
@ -888,10 +915,17 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
|
|||||||
if (OLD_FRAME_UNVOICED_FLAG == 1)
|
if (OLD_FRAME_UNVOICED_FLAG == 1)
|
||||||
{
|
{
|
||||||
/* generate unvoiced samples here */
|
/* generate unvoiced samples here */
|
||||||
|
#ifdef NORMALMODE
|
||||||
if (tms->RNG & 1)
|
if (tms->RNG & 1)
|
||||||
tms->excitation_data = -0x40; /* according to the patent it is (either + or -) half of the maximum value in the chirp table, so +-64 */
|
tms->excitation_data = -0x40; /* according to the patent it is (either + or -) half of the maximum value in the chirp table, so +-64 */
|
||||||
else
|
else
|
||||||
tms->excitation_data = 0x40;
|
tms->excitation_data = 0x40;
|
||||||
|
#else
|
||||||
|
if (tms->RNG & 1)
|
||||||
|
tms->excitation_data = ~0x7F;
|
||||||
|
else
|
||||||
|
tms->excitation_data = 0x80;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -910,7 +944,7 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
|
|||||||
tms->excitation_data = tms->coeff->chirptable[tms->pitch_count]<<CHIRPROM_LEFTSHIFT;
|
tms->excitation_data = tms->coeff->chirptable[tms->pitch_count]<<CHIRPROM_LEFTSHIFT;
|
||||||
#else
|
#else
|
||||||
if (tms->pitch_count > 40)
|
if (tms->pitch_count > 40)
|
||||||
tms->excitation_data = -128; // tms->coeff->chirptable[51];
|
tms->excitation_data = ~0x7F; // tms->coeff->chirptable[51];
|
||||||
else /*tms->pitch_count <= 40*/
|
else /*tms->pitch_count <= 40*/
|
||||||
tms->excitation_data = tms->coeff->chirptable[tms->pitch_count];
|
tms->excitation_data = tms->coeff->chirptable[tms->pitch_count];
|
||||||
//tms->excitation_data = tms->pitch_count - 64;
|
//tms->excitation_data = tms->pitch_count - 64;
|
||||||
@ -1262,7 +1296,7 @@ static void parse_frame(tms5220_state *tms)
|
|||||||
#endif
|
#endif
|
||||||
tms->new_frame_k[i] = tms->coeff->ktable[i][x];
|
tms->new_frame_k[i] = tms->coeff->ktable[i][x];
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_FRAME_INFO
|
#ifdef VERBOSE
|
||||||
if (tms->speak_external)
|
if (tms->speak_external)
|
||||||
logerror("Parsed a frame successfully in FIFO - %d bits remaining\n", bits);
|
logerror("Parsed a frame successfully in FIFO - %d bits remaining\n", bits);
|
||||||
else
|
else
|
||||||
@ -1489,12 +1523,13 @@ WRITE_LINE_DEVICE_HANDLER( tms5220_rsq_w )
|
|||||||
#ifdef DEBUG_RS_WS
|
#ifdef DEBUG_RS_WS
|
||||||
logerror("Schedule write ready\n");
|
logerror("Schedule write ready\n");
|
||||||
#endif
|
#endif
|
||||||
tms->io_ready = 1;
|
//tms->io_ready = 1;
|
||||||
/* 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); // goes immediately, within one clock
|
//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 in datasheet, but zaccaria won't work */
|
/* 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? */
|
||||||
timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock/11), tms, 1, io_ready_cb); // this should take around 10-16 (closer to ~11) cycles to complete
|
//timer_set(tms->device->machine, ATTOTIME_IN_USEC(100), tms, 1, io_ready_cb);
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1537,10 +1572,11 @@ WRITE_LINE_DEVICE_HANDLER( tms5220_wsq_w )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
///* high to low - schedule ready cycle*/
|
///* high to low - schedule ready cycle*/
|
||||||
tms->io_ready = 1;
|
//tms->io_ready = 1;
|
||||||
timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock), tms, 0, io_ready_cb); // goes immediately, within one clock
|
/* 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?
|
||||||
tms->io_ready = 0;
|
tms->io_ready = 0;
|
||||||
timer_set(tms->device->machine, ATTOTIME_IN_HZ(device->clock/15), tms, 1, io_ready_cb); // this should take around 10-16 (closer to ~15) 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 ~15) cycles to complete
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user