Added digitalker support to scorpion driver. [Olivier Galibert]

This commit is contained in:
Aaron Giles 2009-01-14 06:07:26 +00:00
parent 45ba56b76f
commit 62bddb4fe6
7 changed files with 752 additions and 25 deletions

2
.gitattributes vendored
View File

@ -765,6 +765,8 @@ src/emu/sound/custom.c svneol=native#text/plain
src/emu/sound/custom.h svneol=native#text/plain
src/emu/sound/dac.c svneol=native#text/plain
src/emu/sound/dac.h svneol=native#text/plain
src/emu/sound/digitalk.c svneol=native#text/plain
src/emu/sound/digitalk.h svneol=native#text/plain
src/emu/sound/disc_dev.c svneol=native#text/plain
src/emu/sound/disc_flt.c svneol=native#text/plain
src/emu/sound/disc_inp.c svneol=native#text/plain

708
src/emu/sound/digitalk.c Normal file
View File

@ -0,0 +1,708 @@
#include <math.h>
#include "sndintrf.h"
#include "streams.h"
#include "digitalk.h"
/*
National Semiconductor's Digitalker, also known as MM54104.
This is a sample decompression chip where the codec is very
specialized for speech.
- Driver history
The history of this driver is a little strange. The real
reverse-engineering work has been done by Kevin Horton
(single-stepping the chip and everything) with assistance by Lord
Nightmare who had done the work (with help from Mr. Horton) on the tsi
s14001a, a predecessor of the digitalker. Mr. Horton was not
interested in publishing his findings, but provided full-rate
resynthesized samples for the game scorpion. This driver is the
result of analyzing these samples.
- The Chip
Pinout from chipdir, added there by Agustin Yado. Added rompwr.
Package is DIP40. Standard osc is 4MHz, maximum is 5Mhz.
+--()--+
osc in | 1 40| vdd
osc out | 2 39| speech out
cs | 3 38| adr 13
wr | 4 37| adr 12
rompwr | 5 36| adr 11
intr | 6 35| adr 10
cms | 7 34| adr 9
d0 | 8 33| adr 8
d1 | 9 32| adr 7
d2 |10 31| adr 6
d3 |11 30| adr 5
d4 |12 29| adr 4
d5 |13 28| adr 3
d6 |14 27| adr 2
d7 |15 26| adr 1
rdata 0 |16 25| adr 0
rdata 1 |17 24| rdata 7
rdata 2 |18 23| rdata 6
rdata 3 |19 22| rdata 5
vss |20 21| rdata 4
+------+
Pin functions, excerpt from
http://www.ski.org/Rehab/sktf/vol06no1Winter1985.html, slightly modified
"Smith-Kettlewell Technical File, Vol 6, No 1, winter 1985"
On the controller chip, pin 40 is VCC, while pin 20 is ground. VCC
for this chip is between 7 and 11 VDC, and pin 40 is bypassed to
pin 20 by 0.1uF. Maximum current is listed at 45mA.
Pin 3 is called "Chip Select Not," and can be taken high to "open"
the input address and control lines. This is used in cases where
the Digitalker is connected to a computer bus, and the address
lines need to be floated while the bus is doing something else. In
other words, taking pin 3 high makes the Digitalker turn a deaf
ear to all of its inputs.
Pin 4 is "Write Not," and, as mentioned before, is brought low to
load an address into the controller, then brought high again to
start speech. In other words, this is the pin by which you
"trigger" the Digitalker.
Pin 5 is "Not ROM-Power Enable," an output which can be used to
control the power to the ROM's. This is used in cases of battery
supply where current drain is important; the ROM's will have their
power controlled by the controller.
Pin 6 is the "Interrupt Output," (equivalent to the "Busy Line" of
the old TSI Speech Board); this line goes low when an address is
loaded into the chip, then goes high again when speech is
finished. This signal can be used to control the driver circuitry
(or other controlling device), in which case it tells the driver
to "Hold the phone!" while the speech is running. Pin 7 is called
"CMS," and its state controls the action of the "Write Not"
line. With pin 7 low, the operation of pin 4 is as described. If
pin 7 is brought high, raising pin 4 high after loading an address
serves only to reset the interrupt and does not start speech. This
facility is probably intended for use where the interrupt line
really controls the hardware interrupt of a computer, and where
the program taking care of the interrupt may not have another word
to say every time the Digitalker is finished. I have found no
particular use for pin 7, and I simply ground it for normal
operation.
Pins 8 through 15 are the eight input address lines, with pin 8
being the most significant BIT and pin 15 being least
significant. These address lines are "active high." They should
never be left open. They are TTL-compatible; this means that logic
low is ground and logic high is plus 5VDC. (Actually, being MOS
inputs, you can take them as high as the VCC on the controller,
but a 5V supply is required for the ROM's anyhow -- it's there if
you want to use 5V.)
Pins 16 through 24 are the eight data lines which bring data from
the ROMs to the controller, with pin 16 being called "ROM Data
1," and pin 24 being "ROM Data 8."
Pins 25 through 38 are the fourteen address lines which select
location in the ROM's to be read by the controller. Pin 25 is
"Address 0," pin 38 is "Address 13."
- Codec
The codec stems from the standard model for voiced speech generation:
a stream of impulses at the pitch frequency followed by an
articulation filter. Both of those are considered slowly varying.
pitch filter voiced sound
|||||||||| * /\/\ = ~~~~
The first compression effect is by forcing the filter to be
zero-phase. That makes the periods perfectly symmetrical around the
pitch pulse. The voiced speech is as a result extracted as a number
of symmetric periods, centered on the pitch pulses.
Following that, two quantizations are done. First, the pitch
frequency is quantized to one of 32 values (see pitch_vals), going
from ~80 to 200Hz. Then the volume is selected among 8 possible
values in an exponential scale, and the amplitudes are quantized as a
4-bit signed value. The period is time-warped to make it exactly 128
samples long.
The next step of the compression is to select which harnomics will be
kept. The choices are to keep only the even ones or only the odd
ones. Dropping half the harmonics allow to encode the period in only
32 samples, using the fact that a period, for a zero-phase-at-center,
half-harmonics signal, looks like:
even harmonics: /\/\ odd harmonics: _/\_
Where / = block of 32 samples
\ = same block reversed
_ = 32 zeroes
So we're left with 32 4-bit samples to encode, which is done using a
2-bit adpcm. The adaptative part is done by using a fixed 16-deltas
table indexed by the current and the previous encoded value.
Added to all that is the possibility of repeating such a period while
increasing or decreasing the pitch frequency.
For non-voiced speech or non-speech an alternative mode is available
where an equivalent period cutting, frequency and amplitude
quantization is done, but the whole 128 samples are adpcm-encoded.
Finally, silent zones are compressed specifically by storing their
lenghts.
Decoding is simpler. The 128-samples waveform is decoded using the
adpcm data and mirroring/zeroing as needed in the voiced case. The
pitch is taken into account by modulating a 1MHz (clock/4) signal at
the pitch frequency multiplied by 128. pitch_vals in is practice this
modulation interval, hence its 128us base unit to compute the pitch
period.
- Rom organization
The rom starts with a vector of 16-bits little endian values which are
the adresses of the segments table for the samples. The segments data
is a vector of 24-bits little-endian values organized as such:
adr+2 adr+1 adr
MMAAAAAA AAAAAAAA ERRRSSSS
M: Segment base waveforms compression mode (0-3)
A: Segment base waveforms data address (0-16383)
R: Repeat count (1-8)
S: Number of waveforms (1-16)
E: Last segment of the sample (flag)
Decoding stops after having decoded a segment with the E bit set. A
final 8.192ms silence is systematically added.
A == 0 means silence. Duration is 5.12ms*(R+1)*(S+1), or in other
terms a full decode of all-zero waveforms at maximal pitch frequency
(pitch code 31).
A != 0 means sound. The sound data starts at that offset. The
encoding method is selected with M:
0: odd-harmonics voiced mode
2: even-harmonics voiced mode
3: unvoiced/non-speech mode
Mode 1 is not supported because it is not present in the available
samples, hence unknown.
Voiced mode (9 bytes/waveform):
VVVPPPPP AAAAAAAAx8 - First waveform
VVVDCCCC AAAAAAAAx8 - Following waveforms
V: Volume (first index in pcm_levels)
P: Pitch index
A: adpcm data
D: Pitch index change direction (0=increase, 1=decrease)
C: Pitch index maximum change
The waveforms are encoded with a 2-bit adpcm, lowest pair of bits
first. Deltas are a size-16 vector, indexed with the previous adpcm
value in bits 0&1 and the current in bits 2&3. Voiced speech modes
use table delta1 and initial "previous" value 2.
Each waveform is repeated R times at volume V. First waveform has
fixed pitch P. Subsequent waveforms change the pitch index by 1 every
repeat (including the first) up to a change of C. D indicates whether
it's an increment or a decrement.
Unvoiced mode (33 bytes/waveform):
VVVPPPPP AAAAAAAAx32 - All waveforms
V: Volume (first index in pcm_levels)
P: Pitch index
A: adpcm data
Adpcm encoding is identical but using delta2 table and an initial
value of 1. Every waveform is played consecutively and the adpcm
previous value or dac level is not reset between waveforms. The
complete set of waveforms is repeated R times.
*/
typedef struct {
const UINT8 *rom;
const device_config *device;
sound_stream *stream;
// Port/lines state
UINT8 data, cs, cms, wr, intr;
// Current decoding state
UINT16 bpos, apos;
UINT8 mode, cur_segment, cur_repeat, segments, repeats;
UINT8 prev_pitch, pitch, pitch_pos;
UINT8 stop_after, cur_dac, cur_bits;
// Zero-range size
UINT32 zero_count; // 0 for done
// Waveform and current index in it
UINT8 dac_index; // 128 for done
INT16 dac[128];
} digitalker;
// Quantized intensity values, first index is the volume, second the
// intensity (positive half only, real value goes -8..7)
static const short pcm_levels[8][8] = {
{ 473, 945, 1418, 1890, 2363, 2835, 3308, 3781 },
{ 655, 1310, 1966, 2621, 3276, 3931, 4586, 5242 },
{ 925, 1851, 2776, 3702, 4627, 5553, 6478, 7404 },
{ 1249, 2498, 3747, 4996, 6245, 7494, 8743, 9992 },
{ 1638, 3276, 4914, 6552, 8190, 9828, 11466, 13104 },
{ 2252, 4504, 6757, 9009, 11261, 13514, 15766, 18018 },
{ 2989, 5979, 8968, 11957, 14947, 17936, 20925, 23915 },
{ 4095, 8190, 12285, 16380, 20475, 24570, 28665, 32760 },
};
static const int delta1[16] = { -4, -4, -1, -1, -2, -2, 0, 0, 0, 0, 2, 2, 1, 1, 4, 4 };
static const int delta2[16] = { 0, -1, -2, -3, 1, 0, -1, -2, 2, 1, 0, -1, 3, 2, 1, 0 };
// Frequency quantizations, values are in units of 128us.
static const int pitch_vals[32] = {
97, 95, 92, 89, 87, 84, 82, 80, 77, 75, 73, 71, 69, 67, 65, 63,
61, 60, 58, 56, 55, 53, 52, 50, 49, 48, 46, 45, 43, 42, 41, 40
};
static void digitalker_write(digitalker *dg, UINT8 *adr, UINT8 vol, INT8 dac)
{
INT16 v;
dac &= 15;
if(dac >= 9)
v = -pcm_levels[vol][15-dac];
else if(dac)
v = pcm_levels[vol][dac-1];
else
v = 0;
dg->dac[(*adr)++] = v;
}
static UINT8 digitalker_pitch_next(UINT8 val, UINT8 prev, int step)
{
int delta, nv;
delta = val & 0xf;
if(delta > step + 1)
delta = step + 1;
if(val & 0x10)
delta = -delta;
nv = prev + delta;
if(nv < 0)
nv = 0;
else if(nv > 31)
nv = 31;
return nv;
}
static void digitalker_set_intr(digitalker *dg, UINT8 intr)
{
dg->intr = intr;
}
static void digitalker_start_command(digitalker *dg, UINT8 cmd)
{
dg->bpos = ((dg->rom[cmd*2] << 8) | dg->rom[cmd*2+1]) & 0x3fff;
dg->cur_segment = dg->segments = dg->cur_repeat = dg->repeats = 0;
dg->dac_index = 128;
dg->zero_count = 0;
digitalker_set_intr(dg, 0);
}
static void digitalker_step_mode_0(digitalker *dg)
{
INT8 dac = 0;
int i, k, l;
UINT8 wpos = 0;
UINT8 h = dg->rom[dg->apos];
UINT16 bits = 0x80;
UINT8 vol = h >> 5;
UINT8 pitch_id = dg->cur_segment ? digitalker_pitch_next(h, dg->prev_pitch, dg->cur_repeat) : h & 0x1f;
dg->pitch = pitch_vals[pitch_id];
for(i=0; i<32; i++)
dg->dac[wpos++] = 0;
for(k=1; k != 9; k++) {
bits |= dg->rom[dg->apos+k] << 8;
for(l=0; l<4; l++) {
dac += delta1[(bits >> (6+2*l)) & 15];
digitalker_write(dg, &wpos, vol, dac);
}
bits >>= 8;
}
digitalker_write(dg, &wpos, vol, dac);
for(k=7; k >= 0; k--) {
bits = (bits << 8) | (k ? dg->rom[dg->apos+k] : 0x80);
for(l=3; l>=0; l--) {
dac -= delta1[(bits >> (6+2*l)) & 15];
digitalker_write(dg, &wpos, vol, dac);
}
}
for(i=0; i<31; i++)
dg->dac[wpos++] = 0;
dg->cur_repeat++;
if(dg->cur_repeat == dg->repeats) {
dg->apos += 9;
dg->prev_pitch = pitch_id;
dg->cur_repeat = 0;
dg->cur_segment++;
}
}
static void digitalker_step_mode_1(digitalker *dg)
{
logerror("Digitalker mode 1 unsupported");
dg->zero_count = 1;
dg->cur_segment = dg->segments;
}
static void digitalker_step_mode_2(digitalker *dg)
{
INT8 dac = 0;
int k, l;
UINT8 wpos=0;
UINT8 h = dg->rom[dg->apos];
UINT16 bits = 0x80;
UINT8 vol = h >> 5;
UINT8 pitch_id = dg->cur_segment ? digitalker_pitch_next(h, dg->prev_pitch, dg->cur_repeat) : h & 0x1f;
dg->pitch = pitch_vals[pitch_id];
for(k=1; k != 9; k++) {
bits |= dg->rom[dg->apos+k] << 8;
for(l=0; l<4; l++) {
dac += delta1[(bits >> (6+2*l)) & 15];
digitalker_write(dg, &wpos, vol, dac);
}
bits >>= 8;
}
digitalker_write(dg, &wpos, vol, dac);
for(k=7; k >= 0; k--) {
bits = (bits << 8) | (k ? dg->rom[dg->apos+k] : 0x80);
for(l=3; l>=0; l--) {
dac -= delta1[(bits >> (6+2*l)) & 15];
digitalker_write(dg, &wpos, vol, dac);
}
}
digitalker_write(dg, &wpos, vol, dac);
for(k=1; k != 9; k++) {
bits |= dg->rom[dg->apos+k] << 8;
for(l=0; l<4; l++) {
dac += delta1[(bits >> (6+2*l)) & 15];
digitalker_write(dg, &wpos, vol, dac);
}
bits >>= 8;
}
digitalker_write(dg, &wpos, vol, dac);
for(k=7; k >= 0; k--) {
bits = (bits << 8) | (k ? dg->rom[dg->apos+k] : 0x80);
for(l=3; l>=0; l--) {
dac -= delta1[(bits >> (6+2*l)) & 15];
digitalker_write(dg, &wpos, vol, dac);
}
}
dg->cur_repeat++;
if(dg->cur_repeat == dg->repeats) {
dg->apos += 9;
dg->prev_pitch = pitch_id;
dg->cur_repeat = 0;
dg->cur_segment++;
}
}
static void digitalker_step_mode_3(digitalker *dg)
{
UINT8 h = dg->rom[dg->apos];
UINT8 vol = h >> 5;
UINT16 bits;
UINT8 dac, apos, wpos;
int k, l;
dg->pitch = pitch_vals[h & 0x1f];
if(dg->cur_segment == 0 && dg->cur_repeat == 0) {
dg->cur_bits = 0x40;
dg->cur_dac = 0;
}
bits = dg->cur_bits;
dac = 0;
apos = dg->apos + 1 + 32*dg->cur_segment;
wpos = 0;
for(k=0; k != 32; k++) {
bits |= dg->rom[apos++] << 8;
for(l=0; l<4; l++) {
dac += delta2[(bits >> (6+2*l)) & 15];
digitalker_write(dg, &wpos, vol, dac);
}
bits >>= 8;
}
dg->cur_bits = bits;
dg->cur_dac = dac;
dg->cur_segment++;
if(dg->cur_segment == dg->segments) {
dg->cur_segment = 0;
dg->cur_repeat++;
}
}
static void digitalker_step(digitalker *dg)
{
if(dg->cur_segment == dg->segments || dg->cur_repeat == dg->repeats) {
if(dg->stop_after == 0 && dg->bpos == 0xffff)
return;
if(dg->stop_after == 0) {
UINT8 v1 = dg->rom[dg->bpos++];
UINT8 v2 = dg->rom[dg->bpos++];
UINT8 v3 = dg->rom[dg->bpos++];
dg->apos = v2 | ((v3 << 8) & 0x3f00);
dg->segments = (v1 & 15) + 1;
dg->repeats = ((v1 >> 4) & 7) + 1;
dg->mode = (v3 >> 6) & 3;
dg->stop_after = (v1 & 0x80) != 0;
dg->cur_segment = 0;
dg->cur_repeat = 0;
if(!dg->apos) {
dg->zero_count = 40*128*dg->segments*dg->repeats;
dg->segments = 0;
dg->repeats = 0;
return;
}
} else if(dg->stop_after == 1) {
dg->bpos = 0xffff;
dg->zero_count = 81920;
dg->stop_after = 2;
dg->cur_segment = 0;
dg->cur_repeat = 0;
dg->segments = 0;
dg->repeats = 0;
} else {
dg->stop_after = 0;
digitalker_set_intr(dg, 1);
}
}
switch(dg->mode) {
case 0: digitalker_step_mode_0(dg); break;
case 1: digitalker_step_mode_1(dg); break;
case 2: digitalker_step_mode_2(dg); break;
case 3: digitalker_step_mode_3(dg); break;
}
if(!dg->zero_count)
dg->dac_index = 0;
}
static STREAM_UPDATE(digitalker_update)
{
digitalker *dg = param;
stream_sample_t *sout = outputs[0];
int cpos = 0;
while(cpos != samples) {
if(dg->zero_count == 0 && dg->dac_index == 128)
digitalker_step(dg);
if(dg->zero_count) {
int n = samples - cpos;
int i;
if(n > dg->zero_count)
n = dg->zero_count;
for(i=0; i != n; i++)
sout[cpos++] = 0;
dg->zero_count -= n;
} else if(dg->dac_index != 128) {
while(cpos != samples && dg->dac_index != 128) {
short v = dg->dac[dg->dac_index];
int pp = dg->pitch_pos;
while(cpos != samples && pp != dg->pitch) {
sout[cpos++] = v;
pp++;
}
if(pp == dg->pitch) {
pp = 0;
dg->dac_index++;
}
dg->pitch_pos = pp;
}
} else {
while(cpos != samples)
sout[cpos++] = 0;
}
}
}
static void digitalker_data_w(digitalker *dg, UINT8 data)
{
dg->data = data;
}
static void digitalker_cs_w(digitalker *dg, int line)
{
UINT8 cs = line == ASSERT_LINE ? 1 : 0;
if(cs == dg->cs)
return;
dg->cs = cs;
if(cs)
return;
if(!dg->wr) {
if(dg->cms)
digitalker_set_intr(dg, 1);
else
digitalker_start_command(dg, dg->data);
}
}
static void digitalker_cms_w(digitalker *dg, int line)
{
dg->cms = line == ASSERT_LINE ? 1 : 0;
}
static void digitalker_wr_w(digitalker *dg, int line)
{
UINT8 wr = line == ASSERT_LINE ? 1 : 0;
if(wr == dg->wr)
return;
dg->wr = wr;
if(wr || dg->cs)
return;
if(dg->cms)
digitalker_set_intr(dg, 1);
else
digitalker_start_command(dg, dg->data);
}
static int digitalker_intr_r(digitalker *dg)
{
return dg->intr ? ASSERT_LINE : CLEAR_LINE;
}
static void digitalker_register_for_save(digitalker *dg)
{
state_save_register_device_item(dg->device, 0, dg->data);
state_save_register_device_item(dg->device, 0, dg->cs);
state_save_register_device_item(dg->device, 0, dg->cms);
state_save_register_device_item(dg->device, 0, dg->wr);
state_save_register_device_item(dg->device, 0, dg->intr);
state_save_register_device_item(dg->device, 0, dg->bpos);
state_save_register_device_item(dg->device, 0, dg->apos);
state_save_register_device_item(dg->device, 0, dg->mode);
state_save_register_device_item(dg->device, 0, dg->cur_segment);
state_save_register_device_item(dg->device, 0, dg->cur_repeat);
state_save_register_device_item(dg->device, 0, dg->segments);
state_save_register_device_item(dg->device, 0, dg->repeats);
state_save_register_device_item(dg->device, 0, dg->prev_pitch);
state_save_register_device_item(dg->device, 0, dg->pitch);
state_save_register_device_item(dg->device, 0, dg->pitch_pos);
state_save_register_device_item(dg->device, 0, dg->stop_after);
state_save_register_device_item(dg->device, 0, dg->cur_dac);
state_save_register_device_item(dg->device, 0, dg->cur_bits);
state_save_register_device_item(dg->device, 0, dg->zero_count);
state_save_register_device_item(dg->device, 0, dg->dac_index);
state_save_register_device_item_array(dg->device, 0, dg->dac);
}
static SND_START(digitalker)
{
digitalker *dg = auto_malloc(sizeof(*dg));
memset(dg, 0, sizeof(*dg));
dg->device = device;
dg->rom = memory_region(device->machine, device->tag);
dg->stream = stream_create(device, 0, 1, clock/4, dg, digitalker_update);
dg->dac_index = 128;
dg->data = 0xff;
dg->cs = dg->cms = dg->wr = 1;
dg->bpos = 0xffff;
digitalker_set_intr(dg, 1);
digitalker_register_for_save(dg);
return dg;
}
static SND_SET_INFO(digitalker)
{
/* no parameters to set */
}
SND_GET_INFO(digitalker)
{
switch(state) {
case SNDINFO_PTR_SET_INFO: info->set_info = SND_SET_INFO_NAME(digitalker); break;
case SNDINFO_PTR_START: info->start = SND_START_NAME(digitalker); break;
case SNDINFO_PTR_STOP: break;
case SNDINFO_PTR_RESET: break;
case SNDINFO_STR_NAME: strcpy(info->s, "Digitalker"); break;
case SNDINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor"); break;
case SNDINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break;
case SNDINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
case SNDINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Olivier Galibert"); break;
}
}
void digitalker_0_cs_w(int line)
{
digitalker *dg = sndti_token(SOUND_DIGITALKER, 0);
digitalker_cs_w(dg, line);
}
void digitalker_0_cms_w(int line)
{
digitalker *dg = sndti_token(SOUND_DIGITALKER, 0);
digitalker_cms_w(dg, line);
}
void digitalker_0_wr_w(int line)
{
digitalker *dg = sndti_token(SOUND_DIGITALKER, 0);
digitalker_wr_w(dg, line);
}
int digitalker_0_intr_r(void)
{
digitalker *dg = sndti_token(SOUND_DIGITALKER, 0);
return digitalker_intr_r(dg);
}
WRITE8_HANDLER(digitalker_0_data_w)
{
digitalker *dg = sndti_token(SOUND_DIGITALKER, 0);
digitalker_data_w(dg, data);
}

13
src/emu/sound/digitalk.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef _DIGITALKER_H_
#define _DIGITALKER_H_
void digitalker_0_cs_w(int line);
void digitalker_0_cms_w(int line);
void digitalker_0_wr_w(int line);
int digitalker_0_intr_r(void);
WRITE8_HANDLER(digitalker_0_data_w);
SND_GET_INFO(digitalker);
#define SOUND_DIGITALKER SND_GET_INFO_NAME(digitalker)
#endif

View File

@ -335,6 +335,18 @@ endif
#-------------------------------------------------
# National Semiconductor Digitalker
#-------------------------------------------------
SOUNDDEFS += -DHAS_DIGITALKER=$(if $(filter DIGITALKER,$(SOUNDS)),1,0)
ifneq ($(filter DIGITALKER,$(SOUNDS)),)
SOUNDOBJS += $(SOUNDOBJ)/digitalk.o
endif
#-------------------------------------------------
# Nintendo custom sound chips
#-------------------------------------------------

View File

@ -232,6 +232,7 @@ TO DO :
#include "sound/ay8910.h"
#include "sound/sn76496.h"
#include "sound/dac.h"
#include "sound/digitalk.h"
#include "includes/cclimber.h"
#include "sound/discrete.h"
@ -251,7 +252,6 @@ static UINT8 zigzag_ay8910_latch;
static UINT8 kingball_speech_dip;
static UINT8 kingball_sound;
static UINT8 mshuttle_ay8910_cs;
static UINT8 scorpion_sound_data;
static UINT16 protection_state;
static UINT8 protection_result;
@ -799,29 +799,18 @@ static WRITE8_DEVICE_HANDLER( scorpion_protection_w )
}
}
static READ8_HANDLER( scorpion_sound_status_r )
static READ8_HANDLER( scorpion_digitalker_intr_r )
{
logerror("%04X:scorpion_sound_status_r()\n", cpu_get_pc(space->cpu));
return 1;
return digitalker_0_intr_r();
}
static WRITE8_HANDLER( scorpion_sound_data_w )
static WRITE8_HANDLER( scorpion_digitalker_control_w )
{
scorpion_sound_data = data;
// logerror("%04X:scorpion_sound_data_w(%02X)\n", cpu_get_pc(space->cpu), data);
digitalker_0_cs_w(data & 1 ? ASSERT_LINE : CLEAR_LINE);
digitalker_0_cms_w(data & 2 ? ASSERT_LINE : CLEAR_LINE);
digitalker_0_wr_w(data & 4 ? ASSERT_LINE : CLEAR_LINE);
}
static WRITE8_HANDLER( scorpion_sound_control_w )
{
if (!(data & 0x04))
mame_printf_debug("Secondary sound = %02X\n", scorpion_sound_data);
// logerror("%04X:scorpion_sound_control_w(%02X)\n", cpu_get_pc(space->cpu), data);
}
static const ppi8255_interface scorpion_ppi8255_1_intf =
{
NULL, /* Port A read */
@ -1652,8 +1641,8 @@ static const ay8910_interface scorpion_ay8910_interface =
AY8910_DEFAULT_LOADS,
NULL,
NULL,
scorpion_sound_data_w,
scorpion_sound_control_w,
digitalker_0_data_w,
scorpion_digitalker_control_w,
};
static const ay8910_interface checkmaj_ay8910_interface =
@ -1666,7 +1655,6 @@ static const ay8910_interface checkmaj_ay8910_interface =
NULL
};
static const discrete_mixer_desc konami_sound_mixer_desc =
{DISC_MIXER_IS_OP_AMP,
{RES_K(5.1), RES_K(5.1), RES_K(5.1), RES_K(5.1), RES_K(5.1), RES_K(5.1)},
@ -2052,6 +2040,9 @@ static MACHINE_DRIVER_START( scorpion )
MDRV_SOUND_ADD("8910.2", AY8910, KONAMI_SOUND_CLOCK/8)
MDRV_SOUND_CONFIG(scorpion_ay8910_interface)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
MDRV_SOUND_ADD("digitalker", DIGITALKER, 4000000)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.16)
MACHINE_DRIVER_END
@ -2882,7 +2873,7 @@ static DRIVER_INIT( scorpion )
/* no background related */
// memory_install_write8_handler(space, 0x6803, 0x6803, 0, 0, SMH_NOP);
memory_install_read8_handler(cpu_get_address_space(machine->cpu[1], ADDRESS_SPACE_PROGRAM), 0x3000, 0x3000, 0, 0, scorpion_sound_status_r);
memory_install_read8_handler(cpu_get_address_space(machine->cpu[1], ADDRESS_SPACE_PROGRAM), 0x3000, 0x3000, 0, 0, scorpion_digitalker_intr_r);
/*
{
const UINT8 *rom = memory_region(machine, "speech");

View File

@ -4375,7 +4375,7 @@ ROM_START( scorpion )
ROM_LOAD( "32_f5.5f", 0x0000, 0x1000, CRC(1e5da9d6) SHA1(ca8b27e6dd40e4ca13e7e6b5f813bafca78b62f4) )
ROM_LOAD( "32_h5.5h", 0x1000, 0x1000, CRC(a57adb0a) SHA1(d97c7dc4a6c5efb59cc0148e2498156c682c6714) )
ROM_REGION( 0x3000, "speech", 0 ) /* Samples? / Speech? */
ROM_REGION( 0x3000, "digitalker", 0 ) /* Digitalker speech samples */
ROM_LOAD( "32_a3.6e", 0x0000, 0x1000, CRC(279ae6f9) SHA1(a93b1d68c9f4b6ad62fdb8816285e61bd3b4b884) )
ROM_LOAD( "32_a2.6d", 0x1000, 0x1000, CRC(90352dd4) SHA1(62c261a2f2fbd8eff31d5c72cf532d5e43d86dd3) )
ROM_LOAD( "32_a1.6c", 0x2000, 0x1000, CRC(3bf2452d) SHA1(7a163e0ef108dd40d3beab5e9805886e45be744b) )
@ -4402,7 +4402,7 @@ ROM_START( scrpiona )
ROM_LOAD( "scor_f5.bin", 0x0000, 0x1000, CRC(60180a38) SHA1(518c1267523139aa4e27860012a722b67fe25b6d) )
ROM_LOAD( "32_h5.5h", 0x1000, 0x1000, CRC(a57adb0a) SHA1(d97c7dc4a6c5efb59cc0148e2498156c682c6714) )
ROM_REGION( 0x3000, "speech", 0 ) /* Samples? / Speech? */
ROM_REGION( 0x3000, "digitalker", 0 ) /* Digitalker speech samples */
ROM_LOAD( "scor_a3.bin", 0x0000, 0x1000, CRC(04abf178) SHA1(2e7f231413d9ec461ca21840f31d1d6b8b17c4d5) )
ROM_LOAD( "scor_a2.bin", 0x1000, 0x1000, CRC(452d6354) SHA1(3d5397fddcc17b4d03b9cdc53a6439f159d1bfcc) )
ROM_LOAD( "32_a1.6c", 0x2000, 0x1000, CRC(3bf2452d) SHA1(7a163e0ef108dd40d3beab5e9805886e45be744b) )
@ -4428,7 +4428,7 @@ ROM_START( scrpionb )
ROM_LOAD( "ic72.5f", 0x0000, 0x1000, CRC(1e5da9d6) SHA1(ca8b27e6dd40e4ca13e7e6b5f813bafca78b62f4) )
ROM_LOAD( "ic73.5h", 0x1000, 0x1000, CRC(a57adb0a) SHA1(d97c7dc4a6c5efb59cc0148e2498156c682c6714) )
ROM_REGION( 0x3000, "speech", 0 ) /* Samples? / Speech? */
ROM_REGION( 0x3000, "digitalker", 0 ) /* Digitalker speech samples */
ROM_LOAD( "ic25.6e", 0x0000, 0x1000, CRC(04abf178) SHA1(2e7f231413d9ec461ca21840f31d1d6b8b17c4d5) )
ROM_LOAD( "ic24.6d", 0x1000, 0x1000, CRC(90352dd4) SHA1(62c261a2f2fbd8eff31d5c72cf532d5e43d86dd3) )
ROM_LOAD( "ic23.6c", 0x2000, 0x1000, CRC(3bf2452d) SHA1(7a163e0ef108dd40d3beab5e9805886e45be744b) )

View File

@ -303,6 +303,7 @@ SOUNDS += WAVE
#SOUNDS += SID6581
#SOUNDS += SID8580
SOUNDS += SP0256
SOUNDS += DIGITALKER
#-------------------------------------------------