mirror of
https://github.com/holub/mame
synced 2025-05-25 23:35:26 +03:00
Formalized the Votrax SC-01 device. Implemented the full set of
digital logic from the patent, including the timing circuit, transition circuit, glottal generator, and noise source. Some unknowns still exist with regards to clocking, due to contradictory statements in the patent, but as it stands now, all parameters are fetched and processed, phonemes are requested, and in theory all that remains is for someone with analog sound experience to simulate the filters on the output. For now, you just get the raw glottal pulse mixed with the noise signal based on the vocal and fricative amplitudes, which is enough to show progress, but hardly a pleasing result just yet. [Aaron Giles, Lord Nightmare, Olivier Galibert] Converted gottlieb r1 and r2 sound boards into full-on devices, using the recently-added mixer interface. All sound outputs are redirected to the new sound device itself, and then the consuming driver can route the new sound device's outputs as appropriate. The Votrax chip has been hooked up properly, with a crude guess at the variable clocking. Current Votrax emulation is turned off, but it can be enabled by changing USE_FAKE_VOTRAX to 0 in gottlieb.h. [Aaron Giles]
This commit is contained in:
parent
9cf92e7be0
commit
e2e32aac85
@ -2,8 +2,7 @@
|
||||
|
||||
votrax.c
|
||||
|
||||
Hacked up votrax simulator that maps to samples, until a real one
|
||||
is written.
|
||||
Simple VOTRAX SC-01 simulator based on sample fragments.
|
||||
|
||||
****************************************************************************
|
||||
|
||||
@ -43,23 +42,75 @@
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
// note that according to the patent timing circuit, p1/p2 and phi1/phi2
|
||||
// run 4x faster than all references in the patent text
|
||||
const UINT32 P_CLOCK_BIT = 5; // 5 according to timing diagram
|
||||
const UINT32 PHI_CLOCK_BIT = 3; // 3 according to timing diagram
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
const device_type VOTRAX = &device_creator<votrax_device>;
|
||||
const device_type VOTRAX_SC01 = &device_creator<votrax_sc01_device>;
|
||||
|
||||
const char *const votrax_device::s_phoneme_table[64] =
|
||||
// ROM definition for the Votrax phoneme ROM
|
||||
ROM_START( votrax_sc01 )
|
||||
ROM_REGION( 0x200, "phoneme", 0 )
|
||||
ROM_LOAD( "sc01.bin", 0x0000, 0x200, CRC(0353dd6c) SHA1(00e8e497b96a10bd9f4d7e559433c3c209b0d3a8) )
|
||||
ROM_END
|
||||
|
||||
// textual phoneme names for debugging
|
||||
const char *const votrax_sc01_device::s_phoneme_table[64] =
|
||||
{
|
||||
"EH3", "EH2", "EH1", " "/*PA0*/"DT", "A1", "A2", "ZH",
|
||||
"EH3", "EH2", "EH1", "PA0", "DT", "A1", "A2", "ZH",
|
||||
"AH2", "I3", "I2", "I1", "M", "N", "B", "V",
|
||||
"CH", "SH", "Z", "AW1", "NG", "AH1", "OO1", "OO",
|
||||
"L", "K", "J", "H", "G", "F", "D", "S",
|
||||
"A", "AY", "Y1", "UH3", "AH", "P", "O", "I",
|
||||
"U", "Y", "T", "R", "E", "W", "AE", "AE1",
|
||||
"AW2", "UH2", "UH1", "UH", "O2", "O1", "IU", "U1",
|
||||
"THV", "TH", "ER", "EH", "E1", "AW", " "/*PA1*/, "."/*STOP*/
|
||||
"THV", "TH", "ER", "EH", "E1", "AW", "PA1", "STOP"
|
||||
};
|
||||
|
||||
const UINT16 votrax_sc01_device::s_phoneme_duration[64] =
|
||||
{
|
||||
59, 71, 121, 47, 47, 71, 103, 90,
|
||||
71, 55, 80, 121, 103, 80, 71, 71,
|
||||
71, 121, 71, 146, 121, 146, 103, 185,
|
||||
103, 80, 47, 71, 71, 103, 55, 90,
|
||||
185, 65, 80, 47, 250, 103, 185, 185,
|
||||
185, 103, 71, 90, 185, 80, 185, 103,
|
||||
90, 71, 103, 185, 80, 121, 59, 90,
|
||||
80, 71, 146, 185, 121, 253, 185, 47
|
||||
};
|
||||
|
||||
// this waveform is derived from measuring fig. 10 in the patent
|
||||
// it is only an approximation
|
||||
const double votrax_sc01_device::s_glottal_wave[16] =
|
||||
{
|
||||
0,
|
||||
16.0/22.0,
|
||||
-22.0/22.0,
|
||||
-17.0/22.0,
|
||||
-15.0/22.0,
|
||||
-10.0/22.0,
|
||||
-7.0/22.0,
|
||||
-4.0/22.0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
@ -69,11 +120,14 @@ const char *const votrax_device::s_phoneme_table[64] =
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// votrax_device - constructor
|
||||
// votrax_sc01_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
votrax_device::votrax_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: samples_device(mconfig, VOTRAX, "VOTRAX SC-01", tag, owner, clock)
|
||||
votrax_sc01_device::votrax_sc01_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, VOTRAX_SC01, "Votrax SC-01", "votrax", tag, owner, clock),
|
||||
device_sound_interface(mconfig, *this),
|
||||
m_stream(NULL),
|
||||
m_phoneme_timer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -83,10 +137,10 @@ votrax_device::votrax_device(const machine_config &mconfig, const char *tag, dev
|
||||
// to set the interface
|
||||
//-------------------------------------------------
|
||||
|
||||
void votrax_device::static_set_interface(device_t &device, const votrax_interface &interface)
|
||||
void votrax_sc01_device::static_set_interface(device_t &device, const votrax_sc01_interface &interface)
|
||||
{
|
||||
votrax_device &samples = downcast<votrax_device &>(device);
|
||||
static_cast<votrax_interface &>(samples) = interface;
|
||||
votrax_sc01_device &votrax = downcast<votrax_sc01_device &>(device);
|
||||
static_cast<votrax_sc01_interface &>(votrax) = interface;
|
||||
}
|
||||
|
||||
|
||||
@ -99,42 +153,598 @@ void votrax_device::static_set_interface(device_t &device, const votrax_interfac
|
||||
// write - handle a write to the control register
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE8_MEMBER( votrax_device::write )
|
||||
WRITE8_MEMBER( votrax_sc01_device::write )
|
||||
{
|
||||
// append to the current string
|
||||
m_current.cat(s_phoneme_table[data & 0x3f]);
|
||||
// flush out anything currently processing
|
||||
m_stream->update();
|
||||
|
||||
// look for a match in our sample table
|
||||
for (int index = 0; m_votrax_map[index].phoneme != NULL; index++)
|
||||
if (m_current.find(m_votrax_map[index].phoneme) != -1)
|
||||
{
|
||||
// if we found it, play the corresponding sample and flush the buffer
|
||||
start(0, index);
|
||||
m_current.replace(m_votrax_map[index].phoneme, "");
|
||||
m_current.trimspace();
|
||||
if (m_current.len() > 0)
|
||||
mame_printf_warning("Votrax missed partial match: %s\n", m_current.cstr());
|
||||
m_current.reset();
|
||||
return;
|
||||
}
|
||||
// only 6 bits matter
|
||||
m_phoneme = data & 0x3f;
|
||||
mame_printf_debug("%s: STROBE %s\n", machine().time().as_string(3), s_phoneme_table[m_phoneme]);
|
||||
|
||||
// the STROBE signal resets the phoneme counter
|
||||
m_counter_84 = 0xf;
|
||||
|
||||
// not in the schematics, but necessary to fully reset the request latch
|
||||
m_latch_92 = 0;
|
||||
|
||||
// if we got a stop and didn't find a match, print it
|
||||
if ((data & 0x3f) == 0x3f)
|
||||
{
|
||||
mame_printf_warning("Votrax missed match: %s\n", m_current.cstr());
|
||||
m_current.reset();
|
||||
}
|
||||
// clear the request signal
|
||||
m_request_func(m_request_state = m_internal_request = CLEAR_LINE);
|
||||
m_phoneme_timer->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// status - read the status line
|
||||
// inflection_w - handle a write to the
|
||||
// inflection bits
|
||||
//-------------------------------------------------
|
||||
|
||||
READ_LINE_MEMBER( votrax_device::status )
|
||||
WRITE8_MEMBER( votrax_sc01_device::inflection_w )
|
||||
{
|
||||
// is this correct, or is it really a ready line and should be inverted?
|
||||
return (m_current.len() > 0 || playing(0)) ? ASSERT_LINE : CLEAR_LINE;
|
||||
// only 2 bits matter
|
||||
data &= 3;
|
||||
if (m_inflection == data)
|
||||
return;
|
||||
|
||||
// append an inflection marker
|
||||
m_stream->update();
|
||||
m_inflection = data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CORE LOGIC
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// update_subphoneme_clock_period - re-compute the
|
||||
// period of the sub-phoneme clock, as a multiple
|
||||
// of the master clock
|
||||
//-------------------------------------------------
|
||||
|
||||
void votrax_sc01_device::update_subphoneme_clock_period()
|
||||
{
|
||||
assert(m_latch_80 < 128);
|
||||
|
||||
/*
|
||||
The sub-phoneme timing circuit is based off the switching capacitor
|
||||
technique described in the Votrax patent. Replacing the capacitor
|
||||
ladder with [Rx] representing the effective resistance, the circuit
|
||||
becomes essentially a pair of op-amps:
|
||||
|
||||
VM
|
||||
| i1
|
||||
[R1]
|
||||
| Vc
|
||||
+----------------------+
|
||||
| +---|C1|---+ |
|
||||
[R2] | | | |\
|
||||
|Vb i2 | |\ | +--++\
|
||||
+--[Rx]--+----+-\ | | >
|
||||
| | >--+-----+-/
|
||||
[R3] +----++/ Vc |/
|
||||
|i3 | |/
|
||||
+--------+ Va
|
||||
|
|
||||
[R4]
|
||||
|
|
||||
0
|
||||
|
||||
We have two op-amps, the left used as a standard amplifier, the right
|
||||
one as a comparator. The circuit triggers when the two inputs of the
|
||||
right op-amp are equal.
|
||||
|
||||
The left part of the circuit (before C1) is simply a current injector.
|
||||
It's all made of resistors, there's no modulated input, so everything
|
||||
is going to be constant. If you don't know about op-amps used as
|
||||
amplifiers, you just need to know that it forces its two inputs to
|
||||
have the same voltage while not sending or providing any current
|
||||
through there (only though its output in fact).
|
||||
|
||||
In the schema, the injected current is i2. Basic equations apply:
|
||||
Va = R4.i3
|
||||
Vb = Va + R3.i3
|
||||
Vb = Va + Rx.i2
|
||||
Vc = Vb + R2.i1
|
||||
VM = Vc + R1.i1
|
||||
i1 = i2 + i3
|
||||
|
||||
And the tipping happens when the voltage on the right of C1 reaches
|
||||
Vc, so:
|
||||
Vc = Va + i2.T/C1
|
||||
|
||||
(i2 being a constant, the integration is kinda easy)
|
||||
|
||||
Some maths later:
|
||||
R3.i3 = Rx.i2 -> i3 = Rx/R3.i2
|
||||
i1 = (1+Rx/R3).i2
|
||||
Va + (Rx + R2 + R2.Rx/R3).i2 = Va + T/C1.i2
|
||||
T = C1*(Rx*(1+R2/R3) + R2)
|
||||
|
||||
Which isn't, interestingly though not surprisingly, dependant on Vm,
|
||||
R1 or R4. And you have to round it to the next multiple of
|
||||
0.2ms+0.1ms due to the clocking on p2 and its offset to p1 (charging
|
||||
only happens on p1 active), and add one p1/p2 cycle (0.2ms) for the
|
||||
discharge.
|
||||
|
||||
So now you have your base clock, which you have to multiply by 16 to
|
||||
get the phoneme length.
|
||||
|
||||
r2 = 9e3
|
||||
r3 = 1e3
|
||||
c1 = 1000e-12
|
||||
rx = 1/(5KHz * cx)
|
||||
*/
|
||||
|
||||
// determine total capacitance
|
||||
double cx = 0;
|
||||
if ((m_latch_80 & 0x01) != 0) cx += 5e-12;
|
||||
if ((m_latch_80 & 0x02) != 0) cx += 11e-12;
|
||||
if ((m_latch_80 & 0x04) != 0) cx += 21e-12;
|
||||
if ((m_latch_80 & 0x08) != 0) cx += 43e-12;
|
||||
if ((m_latch_80 & 0x10) != 0) cx += 86e-12;
|
||||
if ((m_latch_80 & 0x20) != 0) cx += 173e-12;
|
||||
if ((m_latch_80 & 0x40) != 0) cx += 345e-12;
|
||||
|
||||
// apply the equation above to determine charging time
|
||||
// note that the 5kHz listed above for P1 is for a nominal master
|
||||
// clock frequency of 1.28MHz, meaning it is master clock / 128
|
||||
// which should be the P1 clock but appears to be a bit different
|
||||
double p1_frequency = double(m_master_clock_freq) / double(1 << (P_CLOCK_BIT + 2));
|
||||
double rx = 1.0 / (p1_frequency * cx);
|
||||
double period = 1000e-12 * (rx * (1.0 + 9e3 / 1e3) + 9e3);
|
||||
|
||||
// convert to master clock cycles and round up
|
||||
m_subphoneme_period = UINT32(ceil(period * double(m_master_clock_freq)));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sound_stream_update - handle update requests
|
||||
// for our sound stream
|
||||
//-------------------------------------------------
|
||||
|
||||
void votrax_sc01_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
// determine how many master half-clocks per sample
|
||||
int clocks_per_sample = m_master_clock_freq / stream.sample_rate();
|
||||
|
||||
// iterate over clocks (samples)
|
||||
stream_sample_t *dest = outputs[0];
|
||||
while (samples--)
|
||||
{
|
||||
// run the digital logic at the master clock rate
|
||||
double glottal_out = 0;
|
||||
double noise_out = 0;
|
||||
for (int curclock = 0; curclock < clocks_per_sample; curclock++)
|
||||
{
|
||||
//==============================================
|
||||
//
|
||||
// Timing circuit (patent figure 2a)
|
||||
//
|
||||
//==============================================
|
||||
|
||||
// update master clock
|
||||
m_master_clock ^= 1;
|
||||
|
||||
// on the falling edge of the master clock, advance the 10-bit counter at 34
|
||||
UINT8 old_latch_72 = m_latch_72;
|
||||
if (m_master_clock == 0)
|
||||
m_counter_34 = (m_counter_34 + 1) & 0x3ff;
|
||||
else
|
||||
{
|
||||
m_latch_70 = m_counter_34 & 0xf;
|
||||
m_latch_72 = ((m_counter_34 >> 4) & 7) | ((m_counter_34 >> 6) & 8);
|
||||
}
|
||||
|
||||
// derive beta 1 clock:
|
||||
// set if m_latch_70.0 == 1
|
||||
// reset if m_latch_70.0 == 0
|
||||
// UINT8 old_beta1 = m_beta1;
|
||||
m_beta1 = BIT(m_latch_70, 0);
|
||||
|
||||
// derive p2 clock:
|
||||
// set if (m_counter_34.P_CLOCK_BIT & clock) == 1
|
||||
// reset if (m_counter_34.P_CLOCK_BIT == 0)
|
||||
UINT8 old_p2 = m_p2;
|
||||
if (BIT(m_counter_34, P_CLOCK_BIT) & m_master_clock)
|
||||
m_p2 = 1;
|
||||
else if (!BIT(m_counter_34, P_CLOCK_BIT))
|
||||
m_p2 = 0;
|
||||
|
||||
// derive p1 clock:
|
||||
// set if (!m_counter_34.P_CLOCK_BIT & clock) == 1
|
||||
// reset if (m_counter_34.P_CLOCK_BIT == 1)
|
||||
// UINT8 old_p1 = m_p1;
|
||||
if (BIT(~m_counter_34, P_CLOCK_BIT) & m_master_clock)
|
||||
m_p1 = 1;
|
||||
else if (BIT(m_counter_34, P_CLOCK_BIT))
|
||||
m_p1 = 0;
|
||||
|
||||
// derive phi2 clock:
|
||||
// set if (m_counter_34.PHI_CLOCK_BIT & clock) == 1
|
||||
// reset if (m_counter_34.PHI_CLOCK_BIT == 0)
|
||||
UINT8 old_phi2 = m_phi2;
|
||||
if (BIT(m_counter_34, PHI_CLOCK_BIT) & m_master_clock)
|
||||
m_phi2 = 1;
|
||||
else if (!BIT(m_counter_34, PHI_CLOCK_BIT))
|
||||
m_phi2 = 0;
|
||||
|
||||
// derive phi1 clock:
|
||||
// set if (!m_counter_34.PHI_CLOCK_BIT & clock) == 1
|
||||
// reset if (m_counter_34.PHI_CLOCK_BIT == 1)
|
||||
UINT8 old_phi1 = m_phi1;
|
||||
if (BIT(~m_counter_34, PHI_CLOCK_BIT) & m_master_clock)
|
||||
m_phi1 = 1;
|
||||
else if (BIT(m_counter_34, PHI_CLOCK_BIT))
|
||||
m_phi1 = 0;
|
||||
|
||||
// determine rising edges of each clock of interest
|
||||
// UINT8 beta1_rising = (old_beta1 ^ m_beta1) & m_beta1;
|
||||
UINT8 p2_rising = (old_p2 ^ m_p2) & m_p2;
|
||||
// UINT8 p1_rising = (old_p1 ^ m_p1) & m_p1;
|
||||
UINT8 phi2_rising = (old_phi2 ^ m_phi2) & m_phi2;
|
||||
UINT8 phi1_rising = (old_phi1 ^ m_phi1) & m_phi1;
|
||||
UINT8 a0_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 0);
|
||||
UINT8 a2_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 2);
|
||||
UINT8 _125k_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 3);
|
||||
|
||||
// track subphoneme counter state
|
||||
if (!(m_latch_42 | m_phi1))
|
||||
m_subphoneme_count = 0;
|
||||
else
|
||||
m_subphoneme_count++;
|
||||
if (p2_rising)
|
||||
m_latch_42 = (m_subphoneme_count < m_subphoneme_period);
|
||||
|
||||
// update the state of the subphoneme clock line
|
||||
UINT8 old_clock_88 = m_clock_88;
|
||||
m_clock_88 = !m_latch_42; //!(m_latch_42 | m_phi1); -- figure 7 seems to be wrong here
|
||||
UINT8 clock_88_rising = (old_clock_88 ^ m_clock_88) & m_clock_88;
|
||||
|
||||
// the A/R line holds the counter in reset except during phoneme processing,
|
||||
// when it is clocked on the rising edge of the subphoneme timer clock
|
||||
if (m_internal_request != CLEAR_LINE)
|
||||
m_counter_84 = 0xf;
|
||||
else if (clock_88_rising)
|
||||
{
|
||||
m_counter_84 = (m_counter_84 - 1) & 0x0f;
|
||||
mame_printf_debug("counter=%d\n", m_counter_84);
|
||||
}
|
||||
|
||||
// clock the zero count latch
|
||||
if (p2_rising)
|
||||
m_latch_92 = ((m_counter_84 == 0) | (m_latch_92 << 1)) & 3;
|
||||
|
||||
// once both bits are set, the request line goes high
|
||||
if (m_latch_92 == 3)
|
||||
{
|
||||
// if the request line was previously low, reset the VD/CLD flip-flops
|
||||
if (m_internal_request == CLEAR_LINE)
|
||||
m_srff_112 = m_srff_114 = 0;
|
||||
m_internal_request = ASSERT_LINE;
|
||||
}
|
||||
|
||||
//==============================================
|
||||
//
|
||||
// Low parameter clocking (patent figure 2b)
|
||||
//
|
||||
//==============================================
|
||||
|
||||
// fetch ROM data; note that the address lines come directly from
|
||||
// counter_34 and not from the latches, which are 1 cycle delayed
|
||||
UINT8 romdata = m_rom[(m_phoneme << 3) | ((m_counter_34 >> 4) & 7)];
|
||||
|
||||
// update the ROM data; ROM format is (upper nibble/lower nibble)
|
||||
// +00 = F1 parameter / 0
|
||||
// +01 = F2 parameter / 0
|
||||
// +02 = FC parameter / 0
|
||||
// +03 = F3 parameter / CL
|
||||
// +04 = F2Q Parameter / CLD
|
||||
// +05 = VA Parameter / VD
|
||||
// +06 = FA Parameter / PAC
|
||||
// +07 = Phoneme timing (full 7 bits)
|
||||
|
||||
// latch a new value from ROM on phi2
|
||||
UINT8 a = m_latch_72 & 7;
|
||||
UINT8 romdata_swapped;
|
||||
if (phi2_rising)
|
||||
{
|
||||
switch (a)
|
||||
{
|
||||
// update CL
|
||||
case 3:
|
||||
m_srff_132 = m_srff_114 & BIT(~romdata, 3);
|
||||
break;
|
||||
|
||||
// update CLD
|
||||
case 4:
|
||||
romdata_swapped = (BIT(romdata, 0) << 3) | (BIT(romdata, 1) << 2) | (BIT(romdata, 2) << 1) | (BIT(romdata, 3) << 0);
|
||||
if (m_counter_84 != 0 && romdata_swapped == (m_counter_84 ^ 0xf))
|
||||
m_srff_114 = 1;
|
||||
break;
|
||||
|
||||
// update VD
|
||||
case 5:
|
||||
romdata_swapped = (BIT(romdata, 0) << 3) | (BIT(romdata, 1) << 2) | (BIT(romdata, 2) << 1) | (BIT(romdata, 3) << 0);
|
||||
if (m_counter_84 != 0 && romdata_swapped == (m_counter_84 ^ 0xf))
|
||||
m_srff_112 = 1;
|
||||
break;
|
||||
|
||||
// update FF == PAC & (VA | FA)
|
||||
case 6:
|
||||
m_srff_142 = BIT(romdata, 3);
|
||||
break;
|
||||
|
||||
// update PH
|
||||
case 7:
|
||||
if (m_latch_80 != (romdata & 0x7f))
|
||||
{
|
||||
m_latch_80 = romdata & 0x7f;
|
||||
mame_printf_debug("[PH=%02X]\n", m_latch_80);
|
||||
UINT32 old_period = m_subphoneme_period;
|
||||
update_subphoneme_clock_period();
|
||||
m_subphoneme_count = (m_subphoneme_count * m_subphoneme_period) / old_period;
|
||||
m_phoneme_timer->adjust(attotime::zero);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================
|
||||
//
|
||||
// Glottal circuit (patent figure 6)
|
||||
//
|
||||
//==============================================
|
||||
|
||||
// determine the TC output from the counters (note that TC requires ET)
|
||||
UINT8 counter_222_tc = (m_counter_222 == 0xf);
|
||||
UINT8 counter_220_tc = (m_counter_220 == 0xf && counter_222_tc);
|
||||
UINT8 counter_224_tc = (m_counter_224 == 0xf && counter_222_tc);
|
||||
|
||||
// clock glottal counter 224 on rising edge of a0
|
||||
if (a0_rising)
|
||||
{
|
||||
// counter 224 is only enabled if TC of counter 222 is 1
|
||||
if (counter_222_tc)
|
||||
{
|
||||
// if counter 220's TC is 1, do a load instead of a count
|
||||
if (counter_220_tc)
|
||||
m_counter_224 = (m_inflection << 1) | ((~m_f1 & 0x8) >> 3);
|
||||
else
|
||||
m_counter_224 = (m_counter_224 + 1) & 0xf;
|
||||
}
|
||||
}
|
||||
|
||||
// clock remaining glottal counters (220, 222, 236) on rising edge of phi2
|
||||
if (phi2_rising)
|
||||
{
|
||||
// counter 220 is only enabled if TC of counter 222 is 1
|
||||
if (counter_222_tc)
|
||||
{
|
||||
// if counter 220's TC is 1, do a load instead of a count
|
||||
if (counter_220_tc)
|
||||
m_counter_220 = (m_inflection << 1) | ((~m_f1 & 0x8) >> 3);
|
||||
else
|
||||
m_counter_220 = (m_counter_220 + 1) & 0xf;
|
||||
}
|
||||
|
||||
// counter 222 is always enabled
|
||||
if (1)
|
||||
{
|
||||
// if counter 220's TC is 1, do a load instead of a count
|
||||
if (counter_220_tc)
|
||||
m_counter_222 = (~m_f1 & 0x7) << 1;
|
||||
else
|
||||
m_counter_222 = (m_counter_222 + 1) & 0xf;
|
||||
}
|
||||
|
||||
// counter 236 is always enabled
|
||||
if (1)
|
||||
{
|
||||
m_counter_236 = (m_counter_236 + 1) & 0xf;
|
||||
|
||||
// rising edge of Q1 from counter 236 clocks counter 234
|
||||
if ((m_counter_236 & 0x3) == 0x2)
|
||||
{
|
||||
// counter 234 is only enabled if it has not reached terminal
|
||||
if (m_counter_234 != 0xf)
|
||||
m_counter_234 = (m_counter_234 + 1) & 0xf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update FGATE state
|
||||
if (counter_220_tc)
|
||||
m_fgate = 0;
|
||||
if (counter_224_tc)
|
||||
m_fgate = 1;
|
||||
|
||||
// apply asynchronous clear to counters 234/236
|
||||
if (counter_220_tc && m_phi1)
|
||||
m_counter_236 = m_counter_234 = 0;
|
||||
|
||||
// derive glottal circuit output signals
|
||||
UINT8 old_glottal_sync = m_glottal_sync;
|
||||
m_glottal_sync = (m_counter_234 == 0);
|
||||
glottal_out = s_glottal_wave[m_counter_234];
|
||||
|
||||
//==============================================
|
||||
//
|
||||
// Transition circuit (patent figure 3a/3b)
|
||||
//
|
||||
//==============================================
|
||||
|
||||
// divide 1.25k clock by 2 (lower-left of 46)
|
||||
UINT8 old_0625_clock = m_0625_clock;
|
||||
if (_125k_rising)
|
||||
m_0625_clock = !m_0625_clock;
|
||||
UINT8 _0625_rising = (old_0625_clock ^ m_0625_clock) & m_0625_clock;
|
||||
|
||||
// update counter above
|
||||
if (_0625_rising)
|
||||
{
|
||||
if (m_counter_46 == 0xf)
|
||||
m_counter_46 = 0xd;
|
||||
else
|
||||
m_counter_46 = (m_counter_46 + 1) & 0xf;
|
||||
}
|
||||
|
||||
// and then the latch to the right
|
||||
if (a2_rising)
|
||||
m_latch_46 = (BIT(m_counter_46, 1) << 0) |
|
||||
(BIT(m_latch_46, 0) << 1) |
|
||||
(m_0625_clock << 2) |
|
||||
(BIT(m_latch_46, 2) << 3);
|
||||
|
||||
// determine the read/write signal
|
||||
UINT8 ram_write = 0;
|
||||
switch (a)
|
||||
{
|
||||
// write if not FF and low 2 bits of latch
|
||||
// FF is the S/R flip-flop at 142 ANDed with !(/FA & /VA)
|
||||
case 0: case 1: case 2: case 3: case 4:
|
||||
if (!(m_srff_142 && ((m_fa | m_va) & 0xf0) != 0) && (m_latch_46 & 0x3) == 0x3)
|
||||
ram_write = 1;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if ((m_latch_46 & 0xc) == 0xc && m_srff_112)
|
||||
ram_write = 1;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if ((m_latch_46 & 0xc) == 0xc && m_srff_114)
|
||||
ram_write = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// gate on the phi2 clock (OR gate @ 172)
|
||||
ram_write &= m_phi2;
|
||||
|
||||
// write the transitioned values to RAM if requested
|
||||
// (note we consolidate the serial addition and clocking steps here)
|
||||
if (ram_write)
|
||||
{
|
||||
UINT8 old = (m_latch_168 << 4) | m_latch_170;
|
||||
m_ram[a] = old - (old >> 3) + ((romdata & 0xf0) >> 3);
|
||||
}
|
||||
|
||||
// latch some parameter values on rising edge of phi2
|
||||
if (phi2_rising)
|
||||
{
|
||||
switch (a)
|
||||
{
|
||||
case 2:
|
||||
m_fc = m_latch_168;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
m_va = m_latch_168;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
m_fa = m_latch_168;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// latch remaining parameter values on rising edge of (phi2 & glottal sync)
|
||||
UINT8 old_phi2_glottal = (old_phi2 & old_glottal_sync);
|
||||
UINT8 new_phi2_glottal = m_phi2 & m_glottal_sync;
|
||||
if ((old_phi2_glottal ^ new_phi2_glottal) & new_phi2_glottal)
|
||||
switch (a)
|
||||
{
|
||||
case 0:
|
||||
m_f1 = m_latch_168;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_f2 = (m_latch_168 << 1) | (m_latch_170 >> 3);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_f3 = m_latch_168;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_f2q = m_latch_168;
|
||||
break;
|
||||
}
|
||||
|
||||
// latch value from RAM on rising edge of phi1
|
||||
if (phi1_rising)
|
||||
{
|
||||
m_latch_168 = m_ram[a] >> 4;
|
||||
m_latch_170 = m_ram[a] & 0xf;
|
||||
}
|
||||
|
||||
//==============================================
|
||||
//
|
||||
// Noise generator circuit (patent figure 8)
|
||||
//
|
||||
//==============================================
|
||||
|
||||
// nose is clocked by the NOR of /FA and P1
|
||||
UINT8 old_noise_clock = m_noise_clock;
|
||||
m_noise_clock = !((m_fa == 0) | m_p1);
|
||||
UINT8 noise_clock_rising = (old_noise_clock ^ m_noise_clock) & m_noise_clock;
|
||||
UINT8 noise_clock_falling = (old_noise_clock ^ m_noise_clock) & old_noise_clock;
|
||||
|
||||
// falling edge clocks the shift register
|
||||
if (noise_clock_falling)
|
||||
{
|
||||
// shift register 252 is actually 4 shift registers (2 4-bit, 2 5-bit)
|
||||
// d1 and d3 are the 4-bit registers, d2 and d4 are the 5-bit registers
|
||||
// XOR'ed input goes into d4, which shifts in to d2, then d3, then d1
|
||||
// thus the full 18-bit value is effectively
|
||||
//
|
||||
// d4 = (m_shift_252 >> 0) & 0x1f;
|
||||
// d2 = (m_shift_252 >> 5) & 0x1f;
|
||||
// d3 = (m_shift_252 >> 10) & 0xf;
|
||||
// d1 = (m_shift_252 >> 14) & 0xf;
|
||||
//
|
||||
// input at the low end is ((d1+4 ^ d2+5) ^ (d4+4 ^ d4+5)) ^ !(counter2 | counter3)
|
||||
// output is tapped at d3+4
|
||||
|
||||
UINT32 old_shift = m_shift_252;
|
||||
m_shift_252 <<= 1;
|
||||
m_shift_252 |= ((BIT(old_shift, 17) ^ BIT(old_shift, 9)) ^ (BIT(old_shift, 3) ^ BIT(old_shift, 4))) ^
|
||||
((m_counter_250 & 0xc) == 0);
|
||||
}
|
||||
|
||||
// rising edge clocks the counter
|
||||
if (noise_clock_rising)
|
||||
{
|
||||
// counter is reset to 1 if terminal, otherwise it increments
|
||||
if (m_counter_250 == 0xf)
|
||||
m_counter_250 = 0x1;
|
||||
else
|
||||
m_counter_250 = (m_counter_250 + 1) & 0xf;
|
||||
}
|
||||
|
||||
// compute final noise out signal
|
||||
UINT8 noise_out_digital = !(BIT(m_shift_252, 13) & (m_fgate | (m_va == 0)));
|
||||
noise_out = noise_out_digital ? (double(m_fa) / 15.0f) : 0;
|
||||
}
|
||||
|
||||
// amplify the glottal pulse by the VA and cheesily mix in the noise just to
|
||||
// help see what's going on
|
||||
double current = 0.5 * glottal_out * (double(m_va) / 15.0f) + 0.5 * noise_out;
|
||||
|
||||
// TODO: apply high pass noise shaping to noise_out (see figure 8)
|
||||
|
||||
// TODO: apply resonsant filters based on m_f1, m_f2, m_f2q and
|
||||
// inject noise based on m_fc (see figure 9)
|
||||
|
||||
// TODO: apply final filter f3 and inject inverse of noise based on ~m_fc (see figure 5)
|
||||
|
||||
// TODO: apply closure circuit (undocumented)
|
||||
|
||||
// output the current result
|
||||
*dest++ = INT16(current * 32767.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -143,21 +753,233 @@ READ_LINE_MEMBER( votrax_device::status )
|
||||
// DEVICE INTERFACE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// rom_region - return a pointer to the device's
|
||||
// internal ROM region
|
||||
//-------------------------------------------------
|
||||
|
||||
const rom_entry *votrax_sc01_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME( votrax_sc01 );
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - handle device startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void votrax_device::device_start()
|
||||
void votrax_sc01_device::device_start()
|
||||
{
|
||||
// build up a samples list
|
||||
for (const votrax_map *curmap = m_votrax_map; curmap->phoneme != NULL; curmap++)
|
||||
m_sample_list.append((curmap->samplename != NULL) ? curmap->samplename : "");
|
||||
// initialize internal state
|
||||
m_master_clock_freq = clock();
|
||||
m_stream = stream_alloc(0, 1, m_master_clock_freq / 16);
|
||||
m_phoneme_timer = timer_alloc();
|
||||
m_rom = subregion("phoneme")->base();
|
||||
|
||||
// reset inputs
|
||||
m_inflection = 0;
|
||||
m_phoneme = 0x3f;
|
||||
|
||||
// reset outputs
|
||||
m_request_func.resolve(m_request_cb, *this);
|
||||
m_request_state = ASSERT_LINE;
|
||||
m_internal_request = ASSERT_LINE;
|
||||
|
||||
// save inputs
|
||||
save_item(NAME(m_inflection));
|
||||
save_item(NAME(m_phoneme));
|
||||
|
||||
// save outputs
|
||||
save_item(NAME(m_request_state));
|
||||
save_item(NAME(m_internal_request));
|
||||
|
||||
// save timing circuit
|
||||
save_item(NAME(m_master_clock_freq));
|
||||
save_item(NAME(m_master_clock));
|
||||
save_item(NAME(m_counter_34));
|
||||
save_item(NAME(m_latch_70));
|
||||
save_item(NAME(m_latch_72));
|
||||
save_item(NAME(m_beta1));
|
||||
save_item(NAME(m_p2));
|
||||
save_item(NAME(m_p1));
|
||||
save_item(NAME(m_phi2));
|
||||
save_item(NAME(m_phi1));
|
||||
save_item(NAME(m_subphoneme_period));
|
||||
save_item(NAME(m_subphoneme_count));
|
||||
save_item(NAME(m_clock_88));
|
||||
save_item(NAME(m_latch_42));
|
||||
save_item(NAME(m_counter_84));
|
||||
save_item(NAME(m_latch_92));
|
||||
|
||||
// save low parameter clocking
|
||||
save_item(NAME(m_srff_132));
|
||||
save_item(NAME(m_srff_114));
|
||||
save_item(NAME(m_srff_112));
|
||||
save_item(NAME(m_srff_142));
|
||||
save_item(NAME(m_latch_80));
|
||||
|
||||
// save glottal circuit
|
||||
save_item(NAME(m_counter_220));
|
||||
save_item(NAME(m_counter_222));
|
||||
save_item(NAME(m_counter_224));
|
||||
save_item(NAME(m_counter_234));
|
||||
save_item(NAME(m_counter_236));
|
||||
save_item(NAME(m_fgate));
|
||||
save_item(NAME(m_glottal_sync));
|
||||
|
||||
// create the samples interface
|
||||
m_channels = 1;
|
||||
m_names = m_sample_list;
|
||||
m_start = NULL;
|
||||
|
||||
// let the samples device do the rest
|
||||
samples_device::device_start();
|
||||
// save transition circuit
|
||||
save_item(NAME(m_0625_clock));
|
||||
save_item(NAME(m_counter_46));
|
||||
save_item(NAME(m_latch_46));
|
||||
save_item(NAME(m_ram));
|
||||
save_item(NAME(m_latch_168));
|
||||
save_item(NAME(m_latch_170));
|
||||
save_item(NAME(m_f1));
|
||||
save_item(NAME(m_f2));
|
||||
save_item(NAME(m_fc));
|
||||
save_item(NAME(m_f3));
|
||||
save_item(NAME(m_f2q));
|
||||
save_item(NAME(m_va));
|
||||
save_item(NAME(m_fa));
|
||||
|
||||
// save noise generator circuit
|
||||
save_item(NAME(m_noise_clock));
|
||||
save_item(NAME(m_shift_252));
|
||||
save_item(NAME(m_counter_250));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - handle device reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void votrax_sc01_device::device_reset()
|
||||
{
|
||||
// set the initial state
|
||||
m_stream->update();
|
||||
|
||||
// reset inputs
|
||||
m_phoneme = 0x3f;
|
||||
m_request_func(m_internal_request = m_request_state = ASSERT_LINE);
|
||||
|
||||
// reset timing circuit
|
||||
m_master_clock = 0;
|
||||
m_counter_34 = 0;
|
||||
m_latch_70 = 0;
|
||||
m_latch_72 = 0;
|
||||
m_beta1 = 0;
|
||||
m_p2 = 0;
|
||||
m_p1 = 0;
|
||||
m_phi2 = 0;
|
||||
m_phi1 = 0;
|
||||
m_subphoneme_period = 1000;
|
||||
m_subphoneme_count = 0;
|
||||
m_clock_88 = 0;
|
||||
m_latch_42 = 0;
|
||||
m_counter_84 = 0;
|
||||
m_latch_92 = 0;
|
||||
|
||||
// reset low parameter clocking
|
||||
m_srff_132 = 0;
|
||||
m_srff_114 = 0;
|
||||
m_srff_112 = 0;
|
||||
m_srff_142 = 0;
|
||||
m_latch_80 = 50;
|
||||
update_subphoneme_clock_period();
|
||||
|
||||
// reset glottal circuit
|
||||
m_counter_220 = 0;
|
||||
m_counter_222 = 0;
|
||||
m_counter_224 = 0;
|
||||
m_counter_234 = 0;
|
||||
m_counter_236 = 0;
|
||||
m_fgate = 0;
|
||||
m_glottal_sync = 0;
|
||||
|
||||
// reset transition circuit
|
||||
m_0625_clock = 0;
|
||||
m_counter_46 = 0;
|
||||
m_latch_46 = 0;
|
||||
memset(m_ram, 0, sizeof(m_ram));
|
||||
m_latch_168 = 0;
|
||||
m_latch_170 = 0;
|
||||
m_f1 = 0;
|
||||
m_f2 = 0;
|
||||
m_fc = 0;
|
||||
m_f3 = 0;
|
||||
m_f2q = 0;
|
||||
m_va = 0;
|
||||
m_fa = 0;
|
||||
|
||||
// reset noise circuit
|
||||
m_noise_clock = 0;
|
||||
m_shift_252 = 0;
|
||||
m_counter_250 = 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_clock_changed - handle dynamic clock
|
||||
// changes by altering our output frequency
|
||||
//-------------------------------------------------
|
||||
|
||||
void votrax_sc01_device::device_clock_changed()
|
||||
{
|
||||
// compute new frequency of the master clock, and update if changed
|
||||
UINT32 newfreq = clock();
|
||||
if (newfreq != m_master_clock_freq)
|
||||
{
|
||||
// if we have a stream
|
||||
if (m_stream != NULL)
|
||||
{
|
||||
m_stream->update();
|
||||
m_stream->set_sample_rate(newfreq / 16);
|
||||
}
|
||||
|
||||
// determine how many clock ticks remained on the phoneme timer
|
||||
UINT64 remaining = m_phoneme_timer->remaining().as_ticks(m_master_clock_freq);
|
||||
|
||||
// recompute the master clock
|
||||
m_master_clock_freq = newfreq;
|
||||
|
||||
// adjust the phoneme timer to the same number of ticks based on the new frequency
|
||||
if (remaining > 0)
|
||||
m_phoneme_timer->adjust(attotime::from_ticks(remaining, newfreq));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_timer - handle device timer
|
||||
//-------------------------------------------------
|
||||
|
||||
void votrax_sc01_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
// force a stream update
|
||||
m_stream->update();
|
||||
|
||||
// if we're requesting more data, no need for timing
|
||||
if (m_request_state == ASSERT_LINE)
|
||||
return;
|
||||
|
||||
// if we're supposed to have fired, do it now
|
||||
if (m_internal_request == ASSERT_LINE)
|
||||
{
|
||||
mame_printf_debug("%s: REQUEST\n", timer.machine().time().as_string(3));
|
||||
m_request_func(m_request_state = ASSERT_LINE);
|
||||
return;
|
||||
}
|
||||
|
||||
// account for the rest of this subphoneme clock
|
||||
UINT32 clocks_until_request = 0;
|
||||
if (m_counter_84 != 0)
|
||||
{
|
||||
if (m_subphoneme_count < m_subphoneme_period)
|
||||
clocks_until_request += m_subphoneme_period - m_subphoneme_count;
|
||||
clocks_until_request += m_subphoneme_period * (m_counter_84 - 1);
|
||||
}
|
||||
|
||||
// plus 1/2
|
||||
clocks_until_request = MAX(clocks_until_request, (1 << P_CLOCK_BIT) / 2);
|
||||
timer.adjust(attotime::from_ticks(clocks_until_request, m_master_clock_freq));
|
||||
}
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
votrax.h
|
||||
|
||||
Hacked up votrax simulator that maps to samples, until a real one
|
||||
is written.
|
||||
Simple VOTRAX SC-01 simulator based on sample fragments.
|
||||
|
||||
****************************************************************************
|
||||
|
||||
@ -50,56 +49,129 @@
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_VOTRAX_ADD(_tag, _clock, _interface) \
|
||||
MCFG_DEVICE_ADD(_tag, VOTRAX, 0) \
|
||||
votrax_device::static_set_interface(*device, _interface);
|
||||
|
||||
#define MCFG_VOTRAX_SC01_ADD(_tag, _clock, _interface) \
|
||||
MCFG_DEVICE_ADD(_tag, VOTRAX_SC01, _clock) \
|
||||
votrax_sc01_device::static_set_interface(*device, _interface); \
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> votrax_interface sample
|
||||
// ======================> votrax_sc01_interface
|
||||
|
||||
struct votrax_map
|
||||
struct votrax_sc01_interface
|
||||
{
|
||||
const char *phoneme;
|
||||
const char *samplename;
|
||||
};
|
||||
|
||||
struct votrax_interface
|
||||
{
|
||||
votrax_map const *m_votrax_map; // array of map entries
|
||||
devcb_write_line m_request_cb; // callback for request
|
||||
};
|
||||
|
||||
|
||||
// ======================> votrax_device
|
||||
// ======================> votrax_sc01_device
|
||||
|
||||
class votrax_device : public samples_device,
|
||||
public votrax_interface
|
||||
class votrax_sc01_device : public device_t,
|
||||
public device_sound_interface,
|
||||
public votrax_sc01_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
votrax_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
votrax_sc01_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// static configuration helpers
|
||||
static void static_set_interface(device_t &device, const votrax_interface &interface);
|
||||
static void static_set_interface(device_t &device, const votrax_sc01_interface &interface);
|
||||
|
||||
// writers
|
||||
DECLARE_WRITE8_MEMBER( write );
|
||||
DECLARE_READ_LINE_MEMBER( status );
|
||||
DECLARE_WRITE8_MEMBER( inflection_w );
|
||||
DECLARE_READ_LINE_MEMBER( request ) { return m_request_state; }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
const rom_entry *device_rom_region() const;
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual void device_clock_changed();
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
// device_sound_interface overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
|
||||
private:
|
||||
// internal state
|
||||
astring m_current;
|
||||
dynamic_array<const char *> m_sample_list;
|
||||
// internal helpers
|
||||
void update_subphoneme_clock_period();
|
||||
|
||||
// internal state
|
||||
sound_stream * m_stream; // output stream
|
||||
emu_timer * m_phoneme_timer; // phoneme timer
|
||||
const UINT8 * m_rom; // pointer to our ROM
|
||||
|
||||
// inputs
|
||||
UINT8 m_inflection; // 2-bit inflection value
|
||||
UINT8 m_phoneme; // 6-bit phoneme value
|
||||
|
||||
// outputs
|
||||
devcb_resolved_write_line m_request_func; // request callback
|
||||
UINT8 m_request_state; // request as seen to the outside world
|
||||
UINT8 m_internal_request; // request managed by stream timing
|
||||
|
||||
// timing circuit
|
||||
UINT32 m_master_clock_freq; // frequency of the master clock
|
||||
UINT8 m_master_clock; // master clock
|
||||
UINT16 m_counter_34; // ripple counter @ 34
|
||||
UINT8 m_latch_70; // 4-bit latch @ 70
|
||||
UINT8 m_latch_72; // 4-bit latch @ 72
|
||||
UINT8 m_beta1; // beta1 clock state
|
||||
UINT8 m_p2; // P2 clock state
|
||||
UINT8 m_p1; // P1 clock state
|
||||
UINT8 m_phi2; // phi2 clock state
|
||||
UINT8 m_phi1; // phi1 clock state
|
||||
UINT32 m_subphoneme_period; // period of the subphoneme timer
|
||||
UINT32 m_subphoneme_count; // number of ticks executed already
|
||||
UINT8 m_clock_88; // subphoneme clock output @ 88
|
||||
UINT8 m_latch_42; // D flip-flop @ 42
|
||||
UINT8 m_counter_84; // 4-bit phoneme counter @ 84
|
||||
UINT8 m_latch_92; // 2-bit latch @ 92
|
||||
|
||||
// low parameter clocking
|
||||
UINT8 m_srff_132; // S/R flip-flop @ 132
|
||||
UINT8 m_srff_114; // S/R flip-flop @ 114
|
||||
UINT8 m_srff_112; // S/R flip-flop @ 112
|
||||
UINT8 m_srff_142; // S/R flip-flop @ 142
|
||||
UINT8 m_latch_80; // phoneme timing latch @ 80
|
||||
|
||||
// glottal circuit
|
||||
UINT8 m_counter_220; // 4-bit counter @ 220
|
||||
UINT8 m_counter_222; // 4-bit counter @ 222
|
||||
UINT8 m_counter_224; // 4-bit counter @ 224
|
||||
UINT8 m_counter_234; // 4-bit counter @ 234
|
||||
UINT8 m_counter_236; // 4-bit counter @ 236
|
||||
UINT8 m_fgate; // FGATE signal
|
||||
UINT8 m_glottal_sync; // Glottal Sync signal
|
||||
|
||||
// transition circuit
|
||||
UINT8 m_0625_clock; // state of 0.625kHz clock
|
||||
UINT8 m_counter_46; // 4-bit counter in block @ 46
|
||||
UINT8 m_latch_46; // 4-bit latch in block @ 46
|
||||
UINT8 m_ram[8]; // RAM to hold parameters
|
||||
UINT8 m_latch_168; // 4-bit latch @ 168
|
||||
UINT8 m_latch_170; // 4-bit latch @ 170
|
||||
UINT8 m_f1; // latched 4-bit F1 value
|
||||
UINT8 m_f2; // latched 5-bit F2 value
|
||||
UINT8 m_fc; // latched 4-bit FC value
|
||||
UINT8 m_f3; // latched 4-bit F3 value
|
||||
UINT8 m_f2q; // latched 4-bit F2Q value
|
||||
UINT8 m_va; // latched 4-bit VA value
|
||||
UINT8 m_fa; // latched 4-bit FA value
|
||||
|
||||
// noise generator circuit
|
||||
UINT8 m_noise_clock; // clock input to noise generator
|
||||
UINT32 m_shift_252; // shift register @ 252
|
||||
UINT8 m_counter_250; // 4-bit counter @ 250
|
||||
|
||||
// static tables
|
||||
static const char *const s_phoneme_table[64];
|
||||
static const UINT16 s_phoneme_duration[64];
|
||||
static const double s_glottal_wave[16];
|
||||
};
|
||||
|
||||
|
||||
@ -109,7 +181,7 @@ private:
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
extern const device_type VOTRAX;
|
||||
extern const device_type VOTRAX_SC01;
|
||||
|
||||
|
||||
#endif /* __VOTRAX_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -194,7 +194,6 @@ VBlank duration: 1/VSYNC * (16/256) = 1017.6 us
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/i86/i86.h"
|
||||
#include "machine/6532riot.h"
|
||||
#include "sound/ay8910.h"
|
||||
#include "sound/dac.h"
|
||||
@ -693,6 +692,15 @@ static INTERRUPT_GEN( gottlieb_interrupt )
|
||||
* Main CPU memory handlers
|
||||
*
|
||||
*************************************/
|
||||
|
||||
static WRITE8_HANDLER( gottlieb_sh_w )
|
||||
{
|
||||
gottlieb_state *state = space->machine().driver_data<gottlieb_state>();
|
||||
if (state->m_r1_sound != NULL)
|
||||
state->m_r1_sound->write(*space, offset, data);
|
||||
if (state->m_r2_sound != NULL)
|
||||
state->m_r2_sound->write(*space, offset, data);
|
||||
}
|
||||
|
||||
static ADDRESS_MAP_START( reactor_map, AS_PROGRAM, 8 )
|
||||
ADDRESS_MAP_GLOBAL_MASK(0xffff)
|
||||
@ -791,8 +799,6 @@ static INPUT_PORTS_START( reactor )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_COIN2 )
|
||||
PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
|
||||
PORT_INCLUDE(gottlieb1_sound)
|
||||
|
||||
PORT_START("TRACKX") /* trackball H */
|
||||
PORT_BIT( 0xff, 0, IPT_TRACKBALL_X ) PORT_SENSITIVITY(15) PORT_KEYDELTA(20)
|
||||
|
||||
@ -848,8 +854,6 @@ static INPUT_PORTS_START( qbert )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY PORT_COCKTAIL
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL
|
||||
|
||||
PORT_INCLUDE(gottlieb1_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -904,8 +908,6 @@ static INPUT_PORTS_START( insector )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_COCKTAIL
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL
|
||||
|
||||
PORT_INCLUDE(gottlieb1_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -957,8 +959,6 @@ static INPUT_PORTS_START( tylz )
|
||||
PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
|
||||
PORT_INCLUDE(gottlieb1_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1014,8 +1014,6 @@ static INPUT_PORTS_START( argusg )
|
||||
|
||||
PORT_START("TRACKY")
|
||||
PORT_BIT( 0xff, 0, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(15) PORT_KEYDELTA(20)
|
||||
|
||||
PORT_INCLUDE(gottlieb1_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1069,8 +1067,6 @@ static INPUT_PORTS_START( mplanets )
|
||||
|
||||
PORT_START("TRACKY")
|
||||
PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(5) PORT_KEYDELTA(10) PORT_CODE_DEC(KEYCODE_Z) PORT_CODE_INC(KEYCODE_X)
|
||||
|
||||
PORT_INCLUDE(gottlieb1_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1124,8 +1120,6 @@ static INPUT_PORTS_START( krull )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_8WAY
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_8WAY
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_8WAY
|
||||
|
||||
PORT_INCLUDE(gottlieb1_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1170,8 +1164,6 @@ static INPUT_PORTS_START( kngtmare )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2 )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_START1 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_START2 )
|
||||
|
||||
PORT_INCLUDE(gottlieb1_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1232,8 +1224,6 @@ static INPUT_PORTS_START( qbertqub )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
|
||||
PORT_INCLUDE(gottlieb1_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1293,8 +1283,6 @@ static INPUT_PORTS_START( curvebal )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Bunt") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
|
||||
PORT_INCLUDE(gottlieb1_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1349,8 +1337,6 @@ static INPUT_PORTS_START( screwloo )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Start 1P") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
|
||||
PORT_INCLUDE(gottlieb2_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1405,8 +1391,6 @@ static INPUT_PORTS_START( mach3 )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
|
||||
PORT_INCLUDE(gottlieb2_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START( cobram3 )
|
||||
@ -1460,8 +1444,6 @@ static INPUT_PORTS_START( cobram3 )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
|
||||
PORT_INCLUDE(gottlieb2_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1507,8 +1489,6 @@ static INPUT_PORTS_START( usvsthem )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2 )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON3 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
|
||||
PORT_INCLUDE(gottlieb2_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1575,8 +1555,6 @@ static INPUT_PORTS_START( 3stooges )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
|
||||
|
||||
PORT_INCLUDE(gottlieb2_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1628,8 +1606,6 @@ static INPUT_PORTS_START( vidvince )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
|
||||
|
||||
PORT_INCLUDE(gottlieb2_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1682,8 +1658,6 @@ static INPUT_PORTS_START( wizwarz )
|
||||
|
||||
PORT_START("TRACKY")
|
||||
PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(15) PORT_KEYDELTA(15) PORT_CODE_DEC(KEYCODE_Z) PORT_CODE_INC(KEYCODE_X)
|
||||
|
||||
PORT_INCLUDE(gottlieb2_sound)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -1737,103 +1711,6 @@ GFXDECODE_END
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Sound interfaces
|
||||
*
|
||||
*************************************/
|
||||
|
||||
static const char *const reactor_sample_names[] =
|
||||
{
|
||||
"*reactor",
|
||||
"fx_53", /* "8 left" */
|
||||
"fx_54", /* "16 left" */
|
||||
"fx_55", /* "24 left" */
|
||||
"fx_56", /* "32 left" */
|
||||
"fx_57", /* "40 left" */
|
||||
"fx_58", /* "warning, core unstable" */
|
||||
"fx_59", /* "bonus" */
|
||||
"fx_31", /* "chamber activated" */
|
||||
"fx_39a", /* "2000" */
|
||||
"fx_39b", /* "5000" */
|
||||
"fx_39c", /* "10000" */
|
||||
"fx_39d", /* "15000" */
|
||||
"fx_39e", /* "20000" */
|
||||
"fx_39f", /* "25000" */
|
||||
"fx_39g", /* "30000" */
|
||||
"fx_39h", /* "35000" */
|
||||
"fx_39i", /* "40000" */
|
||||
"fx_39j", /* "45000" */
|
||||
"fx_39k", /* "50000" */
|
||||
"fx_39l", /* "55000" */
|
||||
0 /* end of array */
|
||||
};
|
||||
|
||||
static const char *const qbert_sample_names[] =
|
||||
{
|
||||
"*qbert",
|
||||
"fx_17a", /* random speech, voice clock 255 */
|
||||
"fx_17b", /* random speech, voice clock 255 */
|
||||
"fx_17c", /* random speech, voice clock 255 */
|
||||
"fx_17d", /* random speech, voice clock 255 */
|
||||
"fx_17e", /* random speech, voice clock 255 */
|
||||
"fx_17f", /* random speech, voice clock 255 */
|
||||
"fx_17g", /* random speech, voice clock 255 */
|
||||
"fx_17h", /* random speech, voice clock 255 */
|
||||
"fx_18a", /* random speech, voice clock 176 */
|
||||
"fx_18b", /* random speech, voice clock 176 */
|
||||
"fx_18c", /* random speech, voice clock 176 */
|
||||
"fx_18d", /* random speech, voice clock 176 */
|
||||
"fx_18e", /* random speech, voice clock 176 */
|
||||
"fx_18f", /* random speech, voice clock 176 */
|
||||
"fx_18g", /* random speech, voice clock 176 */
|
||||
"fx_18h", /* random speech, voice clock 176 */
|
||||
"fx_19a", /* random speech, voice clock 128 */
|
||||
"fx_19b", /* random speech, voice clock 128 */
|
||||
"fx_19c", /* random speech, voice clock 128 */
|
||||
"fx_19d", /* random speech, voice clock 128 */
|
||||
"fx_19e", /* random speech, voice clock 128 */
|
||||
"fx_19f", /* random speech, voice clock 128 */
|
||||
"fx_19g", /* random speech, voice clock 128 */
|
||||
"fx_19h", /* random speech, voice clock 128 */
|
||||
"fx_20a", /* random speech, voice clock 96 */
|
||||
"fx_20b", /* random speech, voice clock 96 */
|
||||
"fx_20c", /* random speech, voice clock 96 */
|
||||
"fx_20d", /* random speech, voice clock 96 */
|
||||
"fx_20e", /* random speech, voice clock 96 */
|
||||
"fx_20f", /* random speech, voice clock 96 */
|
||||
"fx_20g", /* random speech, voice clock 96 */
|
||||
"fx_20h", /* random speech, voice clock 96 */
|
||||
"fx_21a", /* random speech, voice clock 62 */
|
||||
"fx_21b", /* random speech, voice clock 62 */
|
||||
"fx_21c", /* random speech, voice clock 62 */
|
||||
"fx_21d", /* random speech, voice clock 62 */
|
||||
"fx_21e", /* random speech, voice clock 62 */
|
||||
"fx_21f", /* random speech, voice clock 62 */
|
||||
"fx_21g", /* random speech, voice clock 62 */
|
||||
"fx_21h", /* random speech, voice clock 62 */
|
||||
"fx_22", /* EH2 with decreasing voice clock */
|
||||
"fx_23", /* O1 with varying voice clock */
|
||||
"fx_28",
|
||||
"fx_36",
|
||||
"knocker",
|
||||
0 /* end of array */
|
||||
};
|
||||
|
||||
static const samples_interface qbert_samples_interface =
|
||||
{
|
||||
1, /* one channel */
|
||||
qbert_sample_names
|
||||
};
|
||||
|
||||
static const samples_interface reactor_samples_interface =
|
||||
{
|
||||
1, /* one channel */
|
||||
reactor_sample_names
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Core machine drivers
|
||||
@ -1862,23 +1739,32 @@ static MACHINE_CONFIG_START( gottlieb_core, gottlieb_state )
|
||||
|
||||
MCFG_VIDEO_START(gottlieb)
|
||||
|
||||
/* sound hardware */
|
||||
// basic speaker configuration
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( gottlieb1, gottlieb_core )
|
||||
MCFG_FRAGMENT_ADD(gottlieb_soundrev1)
|
||||
MCFG_GOTTLIEB_SOUND_R1_ADD("r1sound")
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( gottlieb1_votrax, gottlieb_core )
|
||||
MCFG_GOTTLIEB_SOUND_R1_ADD_VOTRAX("r1sound")
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( gottlieb2, gottlieb_core )
|
||||
MCFG_FRAGMENT_ADD(gottlieb_soundrev2)
|
||||
MCFG_GOTTLIEB_SOUND_R2_ADD("r2sound")
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( g2laser, gottlieb_core )
|
||||
MCFG_FRAGMENT_ADD(gottlieb_soundrev2)
|
||||
MCFG_GOTTLIEB_SOUND_R2_ADD("r2sound")
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
|
||||
|
||||
MCFG_LASERDISC_PR8210_ADD("laserdisc")
|
||||
MCFG_LASERDISC_AUDIO(laserdisc_audio_delegate(FUNC(laserdisc_audio_process), device))
|
||||
@ -1892,12 +1778,15 @@ static MACHINE_CONFIG_DERIVED( g2laser, gottlieb_core )
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Specific machine drivers
|
||||
*
|
||||
*************************************/
|
||||
|
||||
#if USE_FAKE_VOTRAX
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( reactor, gottlieb1 )
|
||||
|
||||
/* basic machine hardware */
|
||||
@ -1905,20 +1794,31 @@ static MACHINE_CONFIG_DERIVED( reactor, gottlieb1 )
|
||||
MCFG_CPU_PROGRAM_MAP(reactor_map)
|
||||
|
||||
MCFG_DEVICE_REMOVE("nvram")
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_SAMPLES_ADD("samples", reactor_samples_interface)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
|
||||
MCFG_FRAGMENT_ADD(reactor_samples)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( qbert, gottlieb1 )
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SAMPLES_ADD("samples", qbert_samples_interface)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
|
||||
MCFG_FRAGMENT_ADD(qbert_samples)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
#else
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( reactor, gottlieb1_votrax )
|
||||
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_MODIFY("maincpu")
|
||||
MCFG_CPU_PROGRAM_MAP(reactor_map)
|
||||
|
||||
MCFG_DEVICE_REMOVE("nvram")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( qbert, gottlieb1_votrax )
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( screwloo, gottlieb2 )
|
||||
|
||||
@ -1926,7 +1826,8 @@ static MACHINE_CONFIG_DERIVED( screwloo, gottlieb2 )
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( cobram3, gottlieb_core )
|
||||
MCFG_FRAGMENT_ADD(gottlieb_cobram3_soundrev2)
|
||||
MCFG_GOTTLIEB_SOUND_R2_ADD_COBRAM3("r2sound")
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
|
||||
|
||||
MCFG_LASERDISC_PR8210_ADD("laserdisc")
|
||||
MCFG_LASERDISC_AUDIO(laserdisc_audio_delegate(FUNC(laserdisc_audio_process), device))
|
||||
@ -1939,9 +1840,9 @@ static MACHINE_CONFIG_DERIVED( cobram3, gottlieb_core )
|
||||
MCFG_LASERDISC_SCREEN_ADD_NTSC("screen", "laserdisc")
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_SOUND_MODIFY("dac1")
|
||||
MCFG_SOUND_MODIFY("r2sound:dac")
|
||||
MCFG_SOUND_ROUTES_RESET()
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, DEVICE_SELF_OWNER, 1.00)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
@ -1962,7 +1863,7 @@ ROM_START( reactor )
|
||||
ROM_LOAD( "rom1", 0xe000, 0x1000, CRC(944e1ddf) SHA1(6b487f1cb405e2ba9345190e8ab6022c790882c1) )
|
||||
ROM_LOAD( "rom0", 0xf000, 0x1000, CRC(55930aed) SHA1(37ed60386935741e8cc0b8750bfcdf6f54c1bf9e) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "snd1", 0x7000, 0x800, CRC(d958a0fd) SHA1(3c383076c68a929f96d844e89b09f3075f331906) )
|
||||
ROM_LOAD( "snd2", 0x7800, 0x800, CRC(5dc86942) SHA1(a449fcfb25521a0e7523184518b5204dac56e5f8) )
|
||||
|
||||
@ -1983,7 +1884,7 @@ ROM_START( qbert )
|
||||
ROM_LOAD( "qb-rom1.bin", 0xc000, 0x2000, CRC(55635447) SHA1(ca6acdef1c9e06b33efe1f0a2df2dfb03723cfbe) )
|
||||
ROM_LOAD( "qb-rom0.bin", 0xe000, 0x2000, CRC(8e318641) SHA1(7f8f66d1e6a7905e93cce07fc92e8801370b7194) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "qb-snd1.bin", 0x7000, 0x800, CRC(15787c07) SHA1(8b7d03fbf2ebaa71b3a7e2f636a0d1bb9b796e43) )
|
||||
ROM_LOAD( "qb-snd2.bin", 0x7800, 0x800, CRC(58437508) SHA1(09d8053e7e99679b602dcda230d64db7fe6cb7f5) )
|
||||
|
||||
@ -2004,7 +1905,7 @@ ROM_START( qberta )
|
||||
ROM_LOAD( "qrom_1.bin", 0xc000, 0x2000, CRC(19d924e3) SHA1(af55ecb5b650e7b069d8be67eb9a9d0f3e69e3f1) )
|
||||
ROM_LOAD( "qrom_0.bin", 0xe000, 0x2000, CRC(2e7fad1b) SHA1(5c1feafe00c21ddddde67ab0093e847a5fc9ec2d) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "qb-snd1.bin", 0x7000, 0x800, CRC(15787c07) SHA1(8b7d03fbf2ebaa71b3a7e2f636a0d1bb9b796e43) )
|
||||
ROM_LOAD( "qb-snd2.bin", 0x7800, 0x800, CRC(58437508) SHA1(09d8053e7e99679b602dcda230d64db7fe6cb7f5) )
|
||||
|
||||
@ -2025,7 +1926,7 @@ ROM_START( qbertj )
|
||||
ROM_LOAD( "qbj-rom1.bin", 0xc000, 0x2000, CRC(c61216e7) SHA1(e727b85dddc2963e33af6c02b675243f6fbe2710) )
|
||||
ROM_LOAD( "qbj-rom0.bin", 0xe000, 0x2000, CRC(69679d5c) SHA1(996d45517d0c01a1952fead05dbe201dbb7dca35) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "qb-snd1.bin", 0x7000, 0x800, CRC(15787c07) SHA1(8b7d03fbf2ebaa71b3a7e2f636a0d1bb9b796e43) )
|
||||
ROM_LOAD( "qb-snd2.bin", 0x7800, 0x800, CRC(58437508) SHA1(09d8053e7e99679b602dcda230d64db7fe6cb7f5) )
|
||||
|
||||
@ -2046,7 +1947,7 @@ ROM_START( myqbert )
|
||||
ROM_LOAD( "mqb-rom1.bin", 0xc000, 0x2000, CRC(11f0a4e4) SHA1(a805e51c40042fae209ace277abd9b35a990905b) )
|
||||
ROM_LOAD( "mqb-rom0.bin", 0xe000, 0x2000, CRC(12a90cb2) SHA1(a33203aea79fe43d1233a16e3fdddaceac6e4a20) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "mqb-snd1.bin", 0x7000, 0x800, CRC(495ffcd2) SHA1(b2c16fffbd6af1c17fdb1a99844819e6ee0550ee) )
|
||||
ROM_LOAD( "mqb-snd2.bin", 0x7800, 0x800, CRC(9bbaa945) SHA1(13791b69cd6f426ad77a7d0537b10012feb0bc87) )
|
||||
|
||||
@ -2067,7 +1968,7 @@ ROM_START( qberttst )
|
||||
ROM_LOAD( "qbtst1.bin", 0xc000, 0x2000, CRC(e97fdd78) SHA1(98dd07043a72273240c593650aa9947199347870) )
|
||||
ROM_LOAD( "qbtst0.bin", 0xe000, 0x2000, CRC(94c9f588) SHA1(f586bcd8e6762614bed634a007508abea071754c) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "qb-snd1.bin", 0x7000, 0x800, CRC(15787c07) SHA1(8b7d03fbf2ebaa71b3a7e2f636a0d1bb9b796e43) )
|
||||
ROM_LOAD( "qb-snd2.bin", 0x7800, 0x800, CRC(58437508) SHA1(09d8053e7e99679b602dcda230d64db7fe6cb7f5) )
|
||||
|
||||
@ -2089,7 +1990,7 @@ ROM_START( qbtrktst )
|
||||
ROM_LOAD( "qb-rom1.bin", 0xc000, 0x2000, CRC(55635447) SHA1(ca6acdef1c9e06b33efe1f0a2df2dfb03723cfbe) )
|
||||
ROM_LOAD( "gv103_t-ball-test_rom0_2764.c11c12", 0xe000, 0x2000, CRC(5d390cd2) SHA1(9031926a6f6179e340b67c3a7949062b4a75e3cf) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "qb-snd1.bin", 0x7000, 0x800, CRC(15787c07) SHA1(8b7d03fbf2ebaa71b3a7e2f636a0d1bb9b796e43) )
|
||||
ROM_LOAD( "qb-snd2.bin", 0x7800, 0x800, CRC(58437508) SHA1(09d8053e7e99679b602dcda230d64db7fe6cb7f5) )
|
||||
|
||||
@ -2112,7 +2013,7 @@ ROM_START( insector )
|
||||
ROM_LOAD( "rom1", 0xc000, 0x2000, CRC(706962af) SHA1(e40b567fdf6a3f7c6485808b4db45cea322c7724) )
|
||||
ROM_LOAD( "rom0", 0xe000, 0x2000, CRC(31cee24b) SHA1(3d21f5d530cc022f9633ad487e13a664848dd3e6) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "gv106s.bin", 0x7000, 0x1000, CRC(25bcc8bc) SHA1(adf401901f1479a5bffaed85135669b1133334b4) )
|
||||
|
||||
ROM_REGION( 0x2000, "bgtiles", 0 )
|
||||
@ -2134,7 +2035,7 @@ ROM_START( tylz )
|
||||
ROM_LOAD( "tylz.r4", 0xc000, 0x2000, CRC(657c3d2e) SHA1(9908a2dd5109e632dff38b8b4b56160615355200) )
|
||||
ROM_LOAD( "tylz.n4", 0xe000, 0x2000, CRC(b2a15510) SHA1(15db4d1a2fb70d8111940246cd7a8ae06403cac5) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "tylz.f2", 0x7000, 0x1000, CRC(ebcedba9) SHA1(94aee8e32bdc80bbc5dc1423ca97597bdb9d808c) )
|
||||
|
||||
ROM_REGION( 0x2000, "bgtiles", 0 )
|
||||
@ -2159,7 +2060,7 @@ ROM_START( argusg )
|
||||
ROM_LOAD( "arg_rom1_2764.c12c13", 0xc000, 0x2000, CRC(733d3d44) SHA1(03c11e89ed6906c0383dc19c0db2d21ebe69b128) )
|
||||
ROM_LOAD( "arg_rom0_2764.c11c12", 0xe000, 0x2000, CRC(e1906355) SHA1(4735370ff0dfe381358dfa41d82fab455ec3c016) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "arg_snd1_2716.u5", 0x7000, 0x800, CRC(3a6cf455) SHA1(0c701aa4d956947a101212b494b030cd2df5a2d6) )
|
||||
ROM_LOAD( "arg_snd2_2716.u6", 0x7800, 0x800, CRC(ddf32040) SHA1(61ae22faa013b29a5fbd9520073f172a98ca38ec) )
|
||||
|
||||
@ -2184,7 +2085,7 @@ ROM_START( mplanets )
|
||||
|
||||
/* note from f205v: my original Gottlieb PCB only sports one 2732 sound EPROM labeled "snd.3h"
|
||||
It contains the two joint roms you can find herefollowing, therefore the sound is identical */
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "snd1", 0x7000, 0x0800, CRC(453193a1) SHA1(317ec81f71661eaa92624c0304a52b635dcd5613) )
|
||||
ROM_LOAD( "snd2", 0x7800, 0x0800, CRC(f5ffc98f) SHA1(516e895df94942fc51f1b51eb9316d4296df82e7) )
|
||||
|
||||
@ -2207,7 +2108,7 @@ ROM_START( mplanetsuk )
|
||||
ROM_LOAD( "mpt_rom1.bin", 0xc000, 0x2000, CRC(94d67b87) SHA1(2cbf09f0ba3b6769de90d8f61913fec3010553e2) )
|
||||
ROM_LOAD( "mpt_rom0.bin", 0xe000, 0x2000, CRC(a9e30ad2) SHA1(39d830dda92ab5a6dbb44943be92bca0464e64e0) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "mpt_snd1.bin", 0x7000, 0x800, CRC(453193a1) SHA1(317ec81f71661eaa92624c0304a52b635dcd5613) )
|
||||
ROM_LOAD( "mpt_snd2.bin", 0x7800, 0x800, CRC(f5ffc98f) SHA1(516e895df94942fc51f1b51eb9316d4296df82e7) )
|
||||
|
||||
@ -2233,7 +2134,7 @@ ROM_START( krull )
|
||||
ROM_LOAD( "rom1.bin", 0xc000, 0x2000, CRC(1ad956a3) SHA1(f5b74b196fe1bd9ab48336e0051cbf29c650cfc1) )
|
||||
ROM_LOAD( "rom0.bin", 0xe000, 0x2000, CRC(a466afae) SHA1(d691cbb46e8c3b71f9b1688d7fcef36df82aa854) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "snd1.bin", 0x6000, 0x1000, CRC(dd2b30b4) SHA1(f01cb64932493bf69d4fc75a7fa809ff6f6e4263) )
|
||||
ROM_LOAD( "snd2.bin", 0x7000, 0x1000, CRC(8cab901b) SHA1(b886532828efc8cf442e2ee4ebbfe37acd489f62) )
|
||||
|
||||
@ -2255,7 +2156,7 @@ ROM_START( kngtmare )
|
||||
ROM_LOAD( "gv112_rom1_2764.c12c13", 0xc000, 0x2000, CRC(5b340640) SHA1(8ccad017d5b9b748327baf22ff51d30ee96cb25e) )
|
||||
ROM_LOAD( "gv112_rom0_2764.c11c12", 0xe000, 0x2000, CRC(620dc629) SHA1(0d94b7c50ef499eb9bb3f4986a8d29547181f7ea) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "gv112_snd", 0x7000, 0x1000, NO_DUMP )
|
||||
|
||||
ROM_REGION( 0x2000, "bgtiles", 0 )
|
||||
@ -2276,7 +2177,7 @@ ROM_START( sqbert )
|
||||
ROM_LOAD( "qb-rom1.bin", 0xc000, 0x2000, CRC(eaf3076c) SHA1(749a87b3c40ba0a2ecd2ca962786e066daf63e30) )
|
||||
ROM_LOAD( "qb-rom0.bin", 0xe000, 0x2000, CRC(61260a7e) SHA1(e2028a453aa34aaffa2c465f64a963504315df3c) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "qb-snd1.bin", 0x7000, 0x800, CRC(15787c07) SHA1(8b7d03fbf2ebaa71b3a7e2f636a0d1bb9b796e43) )
|
||||
ROM_LOAD( "qb-snd2.bin", 0x7800, 0x800, CRC(58437508) SHA1(09d8053e7e99679b602dcda230d64db7fe6cb7f5) )
|
||||
|
||||
@ -2299,7 +2200,7 @@ ROM_START( qbertqub )
|
||||
ROM_LOAD( "qq-rom1.bin", 0xc000, 0x2000, CRC(63e6c43d) SHA1(9435eb06dc069e5bf1c439f0c772fef3183745b0) )
|
||||
ROM_LOAD( "qq-rom0.bin", 0xe000, 0x2000, CRC(8ddbe438) SHA1(31112d711af5d4039491e99a0be0c088b3272482) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "qq-snd1.bin", 0x7000, 0x800, CRC(e704b450) SHA1(d509f54658e9f0264b9ab865a6f36e5423a28904) )
|
||||
ROM_LOAD( "qq-snd2.bin", 0x7800, 0x800, CRC(c6a98bf8) SHA1(cc5b5bb5966f5d79226f1f665a3f9fc934f4ef7f) )
|
||||
|
||||
@ -2322,7 +2223,7 @@ ROM_START( curvebal )
|
||||
ROM_LOAD( "cb-rom-1.chp", 0xc000, 0x2000, CRC(eb1e08bd) SHA1(f558664df12e4e15ef2779a0bdf99538f8c43ca3) )
|
||||
ROM_LOAD( "cb-rom-0.chp", 0xe000, 0x2000, CRC(401fc7e3) SHA1(86ca53cb6f1d88d5a95baa9524c6b42a1f7fc9c2) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r1sound:audiocpu", 0 )
|
||||
ROM_LOAD( "yrom.sbd", 0x6000, 0x1000, CRC(4c313d9b) SHA1(c61a8c827f4b199fdfb6ffc0bc6cca396c73625e) )
|
||||
ROM_LOAD( "drom.sbd", 0x7000, 0x1000, CRC(cecece88) SHA1(4c6639f6f89f80b04b6ffbb5004ea2121e71f504) )
|
||||
|
||||
@ -2346,10 +2247,10 @@ ROM_START( screwloo )
|
||||
ROM_LOAD( "rom1", 0xc000, 0x2000, CRC(571b65ca) SHA1(75077f4fab296b3802271fa77af588003570cde6) )
|
||||
ROM_LOAD( "rom0", 0xe000, 0x2000, CRC(6447fe54) SHA1(6391c841cafd35dd315d9fac99ed5d8304018747) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:audiocpu", 0 )
|
||||
ROM_LOAD( "drom1", 0xc000, 0x2000, CRC(ae965ade) SHA1(84a690cba8990fe6406b7cfbd6ea643a48446567) )
|
||||
|
||||
ROM_REGION( 0x10000, "speech", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:speechcpu", 0 )
|
||||
ROM_LOAD( "yrom1", 0xe000, 0x2000, CRC(3719b0b5) SHA1(4f215ca2f15956374c4cd9484b6798f1c4d60fc7) )
|
||||
|
||||
ROM_REGION( 0x2000, "bgtiles", 0 )
|
||||
@ -2372,10 +2273,10 @@ ROM_START( mach3 )
|
||||
ROM_LOAD( "m3rom1.bin", 0xc000, 0x2000, CRC(3b0ba80b) SHA1(bc7e961311b40f05f2998f10f0a68f2e515c8e66) )
|
||||
ROM_LOAD( "m3rom0.bin", 0xe000, 0x2000, CRC(70c12bf4) SHA1(c26127b6e2a16791b3be8abac93be6af4f30fb3b) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:audiocpu", 0 )
|
||||
ROM_LOAD( "m3drom1.bin", 0xd000, 0x1000, CRC(a6e29212) SHA1(a73aafc2efa99e9ae0aecbb6075a10f7178ac938) )
|
||||
|
||||
ROM_REGION( 0x10000, "speech", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:speechcpu", 0 )
|
||||
ROM_LOAD( "m3yrom1.bin", 0xf000, 0x1000, CRC(eddf8872) SHA1(29ed0d1828639849bab826b3e2ab4eefac45fd85) )
|
||||
|
||||
ROM_REGION( 0x2000, "bgtiles", 0 )
|
||||
@ -2400,10 +2301,10 @@ ROM_START( cobram3 )
|
||||
ROM_LOAD( "bh01", 0xc000, 0x2000, CRC(7d86ab08) SHA1(26b7eb089ca3fe3f8b1531316ce8f95e33b380e5) )
|
||||
ROM_LOAD( "bh00", 0xe000, 0x2000, CRC(c19ad038) SHA1(4d20ae70d8ad1eaa61cb91d7a0cff6932fce30d2) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:audiocpu", 0 )
|
||||
ROM_LOAD( "m3drom1.bin", 0xd000, 0x1000, CRC(a6e29212) SHA1(a73aafc2efa99e9ae0aecbb6075a10f7178ac938) )
|
||||
|
||||
ROM_REGION( 0x10000, "speech", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:speechcpu", 0 )
|
||||
ROM_LOAD( "bh04", 0xe000, 0x2000, CRC(c3f61bc9) SHA1(d02374e6e29238def0cfb01c96c78b206f24d77e) )
|
||||
|
||||
ROM_REGION( 0x2000, "bgtiles", 0 )
|
||||
@ -2429,10 +2330,10 @@ ROM_START( usvsthem )
|
||||
ROM_LOAD( "usvs.rm1", 0xc000, 0x2000, CRC(697bc989) SHA1(ebfc0868f949e5aba1efb8fbce06f795888d8e00) )
|
||||
ROM_LOAD( "usvs.rm0", 0xe000, 0x2000, CRC(30cf6bd9) SHA1(527ad3b96ea4a77f6d6f8a89a9215da490292297) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:audiocpu", 0 )
|
||||
ROM_LOAD( "usvsdrom.1", 0xc000, 0x2000, CRC(c0b5cab0) SHA1(b18e8fd9837bb52d6b3d86f2b652f6573c7cd3b3) )
|
||||
|
||||
ROM_REGION( 0x10000, "speech", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:speechcpu", 0 )
|
||||
ROM_LOAD( "usvsyrom.1", 0xe000, 0x2000, CRC(c3d245ca) SHA1(d281b139ae6c58e855b2914a24ca4bc5f8800681) )
|
||||
|
||||
ROM_REGION( 0x2000, "bgtiles", 0 )
|
||||
@ -2459,10 +2360,10 @@ ROM_START( 3stooges )
|
||||
ROM_LOAD( "gv113rom.1", 0xc000, 0x2000, CRC(34ab051e) SHA1(df416aaf34d6bbbdd79ae633842355a292ed935d) )
|
||||
ROM_LOAD( "gv113rom.0", 0xe000, 0x2000, CRC(ab124329) SHA1(de1bc721eea74426035eec10a389f77b435aa9b9) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:audiocpu", 0 )
|
||||
ROM_LOAD( "drom1", 0xc000, 0x2000, CRC(87a9fa10) SHA1(9c07837dce1384d6b51b716aa8ceeb5bc247a911) )
|
||||
|
||||
ROM_REGION( 0x10000, "speech", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:speechcpu", 0 )
|
||||
ROM_LOAD( "yrom2", 0xc000, 0x2000, CRC(90f9c940) SHA1(646dacc902cf235948ac9c064c92390e2764370b) )
|
||||
ROM_LOAD( "yrom1", 0xe000, 0x2000, CRC(55f8ab30) SHA1(a6b6318f12fd4a1fab61b82cde33759da615d5b2) )
|
||||
|
||||
@ -2486,10 +2387,10 @@ ROM_START( vidvince )
|
||||
ROM_LOAD( "gv132_rom1_2764.c12c13", 0xc000, 0x2000, CRC(a5bf40b7) SHA1(a5a193173fa7b764706bf8d3eaaaf18c6812e436) )
|
||||
ROM_LOAD( "gv132_rom0_2764.c11c12", 0xe000, 0x2000, CRC(2c02b598) SHA1(0c214f6625d6ef88bf89d96776683e15cf4a85c4) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:audiocpu", 0 )
|
||||
ROM_LOAD( "gv132_drom_snd_2764.k2", 0xc000, 0x2000, CRC(18d9d72f) SHA1(985007f49885621eb96e86dc51812983bd113550) )
|
||||
|
||||
ROM_REGION( 0x10000, "speech", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:speechcpu", 0 )
|
||||
ROM_LOAD( "gv132_yrom2_snd_2764.k3", 0xc000, 0x2000, CRC(ff59f618) SHA1(c8b2cb1ab3b69f94dd6be87da8bdfc85c6ed8707) )
|
||||
ROM_LOAD( "gv132_yrom1_snd_2764.n3", 0xe000, 0x2000, CRC(befa4b97) SHA1(424b40844629631a3f31cc12c61ac7000b5f3eb9) )
|
||||
|
||||
@ -2513,10 +2414,10 @@ ROM_START( wizwarz )
|
||||
ROM_LOAD( "gv110_rom1_2764.c12c13", 0xc000, 0x2000, CRC(358895b5) SHA1(38a4a27849ab491a6e3dd3415fe684d1c71c392d) )
|
||||
ROM_LOAD( "gv110_rom0_2764.c11c12", 0xe000, 0x2000, CRC(f7157e17) SHA1(1b155602557ad173d74d4d5cf953b206b262987b) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:audiocpu", 0 )
|
||||
ROM_LOAD( "gv110_drom1_snd_2732.k2",0xd000, 0x1000, CRC(05ca79da) SHA1(f9e9b0de02d618aeb73f7218a49b41d7b94c24a4) )
|
||||
|
||||
ROM_REGION( 0x10000, "speech", 0 )
|
||||
ROM_REGION( 0x10000, "r2sound:speechcpu", 0 )
|
||||
ROM_LOAD( "gv110_yrom1_snd_2732.n3",0xf000, 0x1000, CRC(1e3de643) SHA1(7717547c6c5b1ff178595c67f19265dc59130d90) )
|
||||
|
||||
ROM_REGION( 0x2000, "bgtiles", 0 )
|
||||
@ -2583,23 +2484,23 @@ static DRIVER_INIT( vidvince )
|
||||
*************************************/
|
||||
|
||||
/* games using rev 1 sound board */
|
||||
GAME( 1982, reactor, 0, reactor, reactor, ramtiles, ROT0, "Gottlieb", "Reactor", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, qbert, 0, qbert, qbert, romtiles, ROT270, "Gottlieb", "Q*bert (US set 1)", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, qberta, qbert, qbert, qbert, romtiles, ROT270, "Gottlieb", "Q*bert (US set 2)", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, qbertj, qbert, qbert, qbert, romtiles, ROT270, "Gottlieb (Konami license)", "Q*bert (Japan)", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, myqbert, qbert, qbert, qbert, romtiles, ROT270, "Gottlieb", "Mello Yello Q*bert", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, qberttst, qbert, qbert, qbert, romtiles, ROT270, "Gottlieb", "Q*bert (early test version)", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, qbtrktst, qbert, qbert, qbert, romtiles, ROT270, "Gottlieb", "Q*bert Board Input Test Rom", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, insector, 0, gottlieb1, insector, romtiles, ROT0, "Gottlieb", "Insector (prototype)", 0 )
|
||||
GAME( 1982, tylz, 0, qbert, tylz, romtiles, ROT0, "Mylstar", "Tylz (prototype)", GAME_IMPERFECT_SOUND ) // modified sound hw?
|
||||
GAME( 1984, argusg, 0, gottlieb1, argusg, ramtiles, ROT0, "Gottlieb", "Argus (Gottlieb, prototype)" , 0) // aka Guardian / Protector?
|
||||
GAME( 1983, mplanets, 0, gottlieb1, mplanets, romtiles, ROT270, "Gottlieb", "Mad Planets", 0 )
|
||||
GAME( 1983, mplanetsuk,mplanets, gottlieb1, mplanets, romtiles, ROT270, "Gottlieb (Taitel license)", "Mad Planets (UK)", 0 )
|
||||
GAME( 1983, krull, 0, gottlieb1, krull, ramtiles, ROT270, "Gottlieb", "Krull", 0 )
|
||||
GAME( 1983, kngtmare, 0, gottlieb1, kngtmare, romtiles, ROT0, "Gottlieb", "Knightmare (prototype)", GAME_NO_SOUND )
|
||||
GAME( 1983, sqbert, 0, qbert, qbert, romtiles, ROT270, "Mylstar", "Faster, Harder, More Challenging Q*bert (prototype)", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1983, qbertqub, 0, qbert, qbertqub, romtiles, ROT270, "Mylstar", "Q*bert's Qubes", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1984, curvebal, 0, gottlieb1, curvebal, romtiles, ROT270, "Mylstar", "Curve Ball", 0 )
|
||||
GAME( 1982, reactor, 0, reactor, reactor, ramtiles, ROT0, "Gottlieb", "Reactor", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, qbert, 0, qbert, qbert, romtiles, ROT270, "Gottlieb", "Q*bert (US set 1)", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, qberta, qbert, qbert, qbert, romtiles, ROT270, "Gottlieb", "Q*bert (US set 2)", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, qbertj, qbert, qbert, qbert, romtiles, ROT270, "Gottlieb (Konami license)", "Q*bert (Japan)", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, myqbert, qbert, qbert, qbert, romtiles, ROT270, "Gottlieb", "Mello Yello Q*bert", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, qberttst, qbert, qbert, qbert, romtiles, ROT270, "Gottlieb", "Q*bert (early test version)", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, qbtrktst, qbert, qbert, qbert, romtiles, ROT270, "Gottlieb", "Q*bert Board Input Test Rom", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1982, insector, 0, gottlieb1, insector, romtiles, ROT0, "Gottlieb", "Insector (prototype)", 0 )
|
||||
GAME( 1982, tylz, 0, gottlieb1_votrax, tylz, romtiles, ROT0, "Mylstar", "Tylz (prototype)", GAME_IMPERFECT_SOUND ) // modified sound hw?
|
||||
GAME( 1984, argusg, 0, gottlieb1, argusg, ramtiles, ROT0, "Gottlieb", "Argus (Gottlieb, prototype)" , 0) // aka Guardian / Protector?
|
||||
GAME( 1983, mplanets, 0, gottlieb1, mplanets, romtiles, ROT270, "Gottlieb", "Mad Planets", 0 )
|
||||
GAME( 1983, mplanetsuk,mplanets, gottlieb1, mplanets, romtiles, ROT270, "Gottlieb (Taitel license)", "Mad Planets (UK)", 0 )
|
||||
GAME( 1983, krull, 0, gottlieb1, krull, ramtiles, ROT270, "Gottlieb", "Krull", 0 )
|
||||
GAME( 1983, kngtmare, 0, gottlieb1, kngtmare, romtiles, ROT0, "Gottlieb", "Knightmare (prototype)", GAME_NO_SOUND )
|
||||
GAME( 1983, sqbert, 0, qbert, qbert, romtiles, ROT270, "Mylstar", "Faster, Harder, More Challenging Q*bert (prototype)", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1983, qbertqub, 0, qbert, qbertqub, romtiles, ROT270, "Mylstar", "Q*bert's Qubes", GAME_IMPERFECT_SOUND )
|
||||
GAME( 1984, curvebal, 0, gottlieb1, curvebal, romtiles, ROT270, "Mylstar", "Curve Ball", 0 )
|
||||
|
||||
/* games using rev 2 sound board */
|
||||
GAME( 1983, screwloo, 0, screwloo, screwloo, screwloo, ROT0, "Mylstar", "Screw Loose (prototype)", 0 )
|
||||
|
@ -4,41 +4,220 @@
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "cpu/i86/i86.h"
|
||||
#include "cpu/m6502/m6502.h"
|
||||
#include "machine/6532riot.h"
|
||||
#include "sound/dac.h"
|
||||
#include "sound/ay8910.h"
|
||||
#include "sound/sp0250.h"
|
||||
#include "sound/samples.h"
|
||||
#include "sound/votrax.h"
|
||||
#include "machine/ldpr8210.h"
|
||||
|
||||
|
||||
// set to 0 to enable Votrax device and disable samples
|
||||
#define USE_FAKE_VOTRAX (1)
|
||||
|
||||
|
||||
#define GOTTLIEB_VIDEO_HCOUNT 318
|
||||
#define GOTTLIEB_VIDEO_HBLANK 256
|
||||
#define GOTTLIEB_VIDEO_VCOUNT 256
|
||||
#define GOTTLIEB_VIDEO_VBLANK 240
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
extern const device_type GOTTLIEB_SOUND_REV1;
|
||||
extern const device_type GOTTLIEB_SOUND_REV1_WITH_VOTRAX;
|
||||
extern const device_type GOTTLIEB_SOUND_REV2;
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_GOTTLIEB_SOUND_R1_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, GOTTLIEB_SOUND_REV1, 0) \
|
||||
|
||||
#define MCFG_GOTTLIEB_SOUND_R1_ADD_VOTRAX(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, GOTTLIEB_SOUND_REV1_WITH_VOTRAX, 0) \
|
||||
|
||||
|
||||
#define MCFG_GOTTLIEB_SOUND_R2_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, GOTTLIEB_SOUND_REV2, 0) \
|
||||
|
||||
#define MCFG_GOTTLIEB_SOUND_R2_ADD_COBRAM3(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, GOTTLIEB_SOUND_REV2, 0) \
|
||||
gottlieb_sound_r2_device::static_enable_cobram3_mods(*device); \
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> gottlieb_sound_r1_device
|
||||
|
||||
// rev 1 sound board, with unpopulated VOTRAX
|
||||
class gottlieb_sound_r1_device : public device_t,
|
||||
public device_mixer_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
gottlieb_sound_r1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
gottlieb_sound_r1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock, bool populate_votrax);
|
||||
|
||||
// read/write
|
||||
DECLARE_WRITE8_MEMBER( write );
|
||||
|
||||
// internal communications
|
||||
DECLARE_WRITE_LINE_MEMBER( snd_interrupt );
|
||||
DECLARE_WRITE8_MEMBER( r6532_portb_w );
|
||||
DECLARE_WRITE8_MEMBER( votrax_data_w );
|
||||
DECLARE_WRITE8_MEMBER( speech_clock_dac_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( votrax_request );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual machine_config_constructor device_mconfig_additions() const;
|
||||
virtual ioport_constructor device_input_ports() const;
|
||||
virtual void device_start();
|
||||
|
||||
private:
|
||||
// devices
|
||||
required_device<m6502_device> m_audiocpu;
|
||||
required_device<riot6532_device> m_riot;
|
||||
required_device<dac_device> m_dac;
|
||||
optional_device<votrax_sc01_device> m_votrax;
|
||||
|
||||
// internal state
|
||||
bool m_populate_votrax;
|
||||
UINT8 m_last_speech_clock;
|
||||
|
||||
#if USE_FAKE_VOTRAX
|
||||
protected:
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
private:
|
||||
void fake_votrax_data_w(UINT8 data);
|
||||
void trigger_sample(UINT8 data);
|
||||
optional_device<samples_device> m_samples;
|
||||
UINT8 m_score_sample;
|
||||
UINT8 m_random_offset;
|
||||
UINT8 m_votrax_queue[100];
|
||||
UINT8 m_votrax_queuepos;
|
||||
#endif
|
||||
};
|
||||
|
||||
// fully populated rev 1 sound board
|
||||
class gottlieb_sound_r1_with_votrax_device : public gottlieb_sound_r1_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
gottlieb_sound_r1_with_votrax_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual machine_config_constructor device_mconfig_additions() const;
|
||||
virtual ioport_constructor device_input_ports() const;
|
||||
};
|
||||
|
||||
|
||||
// ======================> gottlieb_sound_r2_device
|
||||
|
||||
// fully populated rev 2 sound board
|
||||
class gottlieb_sound_r2_device : public device_t,
|
||||
public device_mixer_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
gottlieb_sound_r2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// static configuration helpers
|
||||
static void static_enable_cobram3_mods(device_t &device);
|
||||
|
||||
// read/write
|
||||
DECLARE_WRITE8_MEMBER( write );
|
||||
|
||||
// internal communications
|
||||
DECLARE_READ8_MEMBER( speech_data_r );
|
||||
DECLARE_READ8_MEMBER( audio_data_r );
|
||||
DECLARE_WRITE8_MEMBER( signal_audio_nmi_w );
|
||||
DECLARE_WRITE8_MEMBER( nmi_rate_w );
|
||||
CUSTOM_INPUT_MEMBER( speech_drq_custom_r );
|
||||
DECLARE_WRITE8_MEMBER( dac_w );
|
||||
DECLARE_WRITE8_MEMBER( speech_control_w );
|
||||
DECLARE_WRITE8_MEMBER( sp0250_latch_w );
|
||||
DECLARE_WRITE8_MEMBER( psg_latch_w );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual machine_config_constructor device_mconfig_additions() const;
|
||||
virtual ioport_constructor device_input_ports() const;
|
||||
virtual void device_start();
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
private:
|
||||
// internal helpers
|
||||
void nmi_timer_adjust();
|
||||
void nmi_state_update();
|
||||
|
||||
// timer IDs
|
||||
enum
|
||||
{
|
||||
TID_NMI_GENERATE,
|
||||
TID_NMI_CLEAR,
|
||||
TID_SOUND_LATCH_WRITE
|
||||
};
|
||||
|
||||
// devices
|
||||
required_device<m6502_device> m_audiocpu;
|
||||
required_device<m6502_device> m_speechcpu;
|
||||
required_device<dac_device> m_dac;
|
||||
required_device<ay8913_device> m_ay1;
|
||||
required_device<ay8913_device> m_ay2;
|
||||
optional_device<sp0250_device> m_sp0250;
|
||||
|
||||
// internal state
|
||||
bool m_cobram3_mod;
|
||||
emu_timer * m_nmi_timer;
|
||||
UINT8 m_nmi_rate;
|
||||
UINT8 m_nmi_state;
|
||||
UINT8 m_audiocpu_latch;
|
||||
UINT8 m_speechcpu_latch;
|
||||
UINT8 m_speech_control;
|
||||
UINT8 m_last_command;
|
||||
UINT8 m_dac_data[2];
|
||||
UINT8 m_psg_latch;
|
||||
UINT8 m_psg_data_latch;
|
||||
UINT8 m_sp0250_latch;
|
||||
};
|
||||
|
||||
|
||||
// ======================> gottlieb_state
|
||||
|
||||
// shared driver state
|
||||
class gottlieb_state : public driver_device
|
||||
{
|
||||
public:
|
||||
gottlieb_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_laserdisc(*this, "laserdisc") { }
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_laserdisc(*this, "laserdisc"),
|
||||
m_r1_sound(*this, "r1sound"),
|
||||
m_r2_sound(*this, "r2sound") { }
|
||||
|
||||
// devices
|
||||
required_device<i8088_device> m_maincpu;
|
||||
optional_device<pioneer_pr8210_device> m_laserdisc;
|
||||
optional_device<gottlieb_sound_r1_device> m_r1_sound;
|
||||
optional_device<gottlieb_sound_r2_device> m_r2_sound;
|
||||
|
||||
UINT8 *m_videoram;
|
||||
UINT8 m_votrax_queue[100];
|
||||
UINT8 m_votrax_queuepos;
|
||||
emu_timer *m_nmi_timer;
|
||||
UINT8 m_nmi_rate;
|
||||
UINT8 m_nmi_state;
|
||||
UINT8 m_speech_control;
|
||||
UINT8 m_last_command;
|
||||
UINT8 *m_dac_data;
|
||||
UINT8 *m_psg_latch;
|
||||
UINT8 m_psg_data_latch;
|
||||
UINT8 *m_sp0250_latch;
|
||||
int m_score_sample;
|
||||
int m_random_offset;
|
||||
int m_last;
|
||||
UINT8 m_joystick_select;
|
||||
UINT8 m_track[2];
|
||||
optional_device<pioneer_pr8210_device> m_laserdisc;
|
||||
emu_timer *m_laserdisc_bit_timer;
|
||||
emu_timer *m_laserdisc_philips_timer;
|
||||
UINT8 m_laserdisc_select;
|
||||
@ -64,18 +243,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/*----------- defined in audio/gottlieb.c -----------*/
|
||||
|
||||
WRITE8_HANDLER( gottlieb_sh_w );
|
||||
|
||||
MACHINE_CONFIG_EXTERN( gottlieb_soundrev1 );
|
||||
MACHINE_CONFIG_EXTERN( gottlieb_soundrev2 );
|
||||
MACHINE_CONFIG_EXTERN( gottlieb_cobram3_soundrev2 );
|
||||
|
||||
INPUT_PORTS_EXTERN( gottlieb1_sound );
|
||||
INPUT_PORTS_EXTERN( gottlieb2_sound );
|
||||
|
||||
|
||||
/*----------- defined in video/gottlieb.c -----------*/
|
||||
|
||||
extern WRITE8_HANDLER( gottlieb_videoram_w );
|
||||
@ -87,3 +254,8 @@ extern WRITE8_HANDLER( gottlieb_paletteram_w );
|
||||
VIDEO_START( gottlieb );
|
||||
VIDEO_START( screwloo );
|
||||
SCREEN_UPDATE_RGB32( gottlieb );
|
||||
|
||||
#if USE_FAKE_VOTRAX
|
||||
MACHINE_CONFIG_EXTERN( reactor_samples );
|
||||
MACHINE_CONFIG_EXTERN( qbert_samples );
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user