votrax sc01: Simulate [O. Galibert]

This commit is contained in:
Olivier Galibert 2016-12-23 00:13:25 +01:00
parent ee5d18f657
commit 2c79c1ed0d
14 changed files with 917 additions and 1949 deletions

View File

@ -2492,10 +2492,6 @@ files {
MAME_DIR .. "src/mame/drivers/astrocde.cpp", MAME_DIR .. "src/mame/drivers/astrocde.cpp",
MAME_DIR .. "src/mame/includes/astrocde.h", MAME_DIR .. "src/mame/includes/astrocde.h",
MAME_DIR .. "src/mame/video/astrocde.cpp", MAME_DIR .. "src/mame/video/astrocde.cpp",
MAME_DIR .. "src/mame/audio/gorf.cpp",
MAME_DIR .. "src/mame/audio/gorf.h",
MAME_DIR .. "src/mame/audio/wow.cpp",
MAME_DIR .. "src/mame/audio/wow.h",
MAME_DIR .. "src/mame/drivers/atlantis.cpp", MAME_DIR .. "src/mame/drivers/atlantis.cpp",
MAME_DIR .. "src/mame/drivers/balsente.cpp", MAME_DIR .. "src/mame/drivers/balsente.cpp",
MAME_DIR .. "src/mame/includes/balsente.h", MAME_DIR .. "src/mame/includes/balsente.h",

View File

@ -1141,8 +1141,6 @@ files {
MAME_DIR .. "src/mame/video/jagblit.h", MAME_DIR .. "src/mame/video/jagblit.h",
MAME_DIR .. "src/mame/video/jagblit.hxx", MAME_DIR .. "src/mame/video/jagblit.hxx",
MAME_DIR .. "src/mame/video/jagobj.hxx", MAME_DIR .. "src/mame/video/jagobj.hxx",
MAME_DIR .. "src/mame/audio/gorf.cpp",
MAME_DIR .. "src/mame/audio/wow.cpp",
MAME_DIR .. "src/mame/drivers/astrocde.cpp", MAME_DIR .. "src/mame/drivers/astrocde.cpp",
MAME_DIR .. "src/mame/includes/astrocde.h", MAME_DIR .. "src/mame/includes/astrocde.h",
MAME_DIR .. "src/mame/video/astrocde.cpp", MAME_DIR .. "src/mame/video/astrocde.cpp",

View File

@ -139,8 +139,6 @@ files{
MAME_DIR .. "src/mame/audio/williams.cpp", MAME_DIR .. "src/mame/audio/williams.cpp",
MAME_DIR .. "src/mame/audio/williams.h", MAME_DIR .. "src/mame/audio/williams.h",
MAME_DIR .. "src/mame/video/williams.cpp", MAME_DIR .. "src/mame/video/williams.cpp",
MAME_DIR .. "src/mame/audio/gorf.cpp",
MAME_DIR .. "src/mame/audio/wow.cpp",
MAME_DIR .. "src/mame/drivers/gaelco.cpp", MAME_DIR .. "src/mame/drivers/gaelco.cpp",
MAME_DIR .. "src/mame/includes/gaelco.h", MAME_DIR .. "src/mame/includes/gaelco.h",
MAME_DIR .. "src/mame/video/gaelco.cpp", MAME_DIR .. "src/mame/video/gaelco.cpp",

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +1,22 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Aaron Giles // copyright-holders:Olivier Galibert
/*************************************************************************** /***************************************************************************
votrax.h votrax.h
Simple VOTRAX SC-01 simulator based on sample fragments. Votrax SC01A simulation
***************************************************************************/ ***************************************************************************/
#pragma once #pragma once
#ifndef __VOTRAX_H__ #ifndef VOTRAX_H
#define __VOTRAX_H__ #define VOTRAX_H
#include "sound/samples.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_VOTRAX_SC01_REQUEST_CB(_devcb) \ #define MCFG_VOTRAX_SC01_REQUEST_CB(_devcb) \
devcb = &votrax_sc01_device::set_request_callback(*device, DEVCB_##_devcb); devcb = &downcast<votrax_sc01_device *>(device)->set_ar_callback(DEVCB_##_devcb);
#include <assert.h>
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> votrax_sc01_device
class votrax_sc01_device : public device_t, class votrax_sc01_device : public device_t,
public device_sound_interface public device_sound_interface
@ -37,12 +25,11 @@ public:
// construction/destruction // construction/destruction
votrax_sc01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); votrax_sc01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
template<class _Object> static devcb_base &set_request_callback(device_t &device, _Object object) { return downcast<votrax_sc01_device &>(device).m_request_cb.set_callback(object); } template<class _Object> devcb_base &set_ar_callback(_Object object) { return m_ar_cb.set_callback(object); }
// writers DECLARE_WRITE8_MEMBER(write);
DECLARE_WRITE8_MEMBER( write ); DECLARE_WRITE8_MEMBER(inflection_w);
DECLARE_WRITE8_MEMBER( inflection_w ); DECLARE_READ_LINE_MEMBER(request) { m_stream->update(); return m_ar_state; }
DECLARE_READ_LINE_MEMBER( request ) { m_stream->update(); return m_request_state; }
protected: protected:
// device-level overrides // device-level overrides
@ -56,99 +43,146 @@ protected:
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override; virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
private: private:
// internal helpers // Possible timer parameters
void update_subphoneme_clock_period(); enum {
static double bits_to_caps(uint32_t value, int caps_count, const double *caps_values); T_COMMIT_PHONE,
static void shift_hist(double val, double *hist_array, int hist_size); T_END_OF_PHONE
static void filter_s_to_z(const double *k, double fs, double *a, double *b); };
static double apply_filter(const double *x, const double *y, const double *a, const double *b);
// internal state static const char *const s_phone_table[64];
sound_stream * m_stream; // output stream static const double s_glottal_wave[9];
emu_timer * m_phoneme_timer; // phoneme timer
const uint8_t * m_rom; // pointer to our ROM
// inputs sound_stream *m_stream; // Output stream
uint8_t m_inflection; // 2-bit inflection value emu_timer *m_timer; // General timer
uint8_t m_phoneme; // 6-bit phoneme value required_memory_region m_rom; // Internal ROM
u32 m_mainclock; // Current main clock
double m_sclock; // Stream sample clock (40KHz, main/18)
double m_cclock; // 20KHz capacitor switching clock (main/36)
u32 m_sample_count; // Sample counter, to cadence chip updates
// outputs // Inputs
devcb_write_line m_request_cb; // callback for request u8 m_inflection; // 2-bit inflection value
uint8_t m_request_state; // request as seen to the outside world u8 m_phone; // 6-bit phone value
uint8_t m_internal_request; // request managed by stream timing
// timing circuit // Outputs
uint32_t m_master_clock_freq; // frequency of the master clock devcb_write_line m_ar_cb; // Callback for ar
uint8_t m_master_clock; // master clock bool m_ar_state; // Current ar state
uint16_t m_counter_34; // ripple counter @ 34
uint8_t m_latch_70; // 4-bit latch @ 70
uint8_t m_latch_72; // 4-bit latch @ 72
uint8_t m_beta1; // beta1 clock state
uint8_t m_p2; // P2 clock state
uint8_t m_p1; // P1 clock state
uint8_t m_phi2; // phi2 clock state
uint8_t m_phi1; // phi1 clock state
uint8_t m_phi2_20; // alternate phi2 clock state (20kHz)
uint8_t m_phi1_20; // alternate phi1 clock state (20kHz)
uint32_t m_subphoneme_period; // period of the subphoneme timer
uint32_t m_subphoneme_count; // number of ticks executed already
uint8_t m_clock_88; // subphoneme clock output @ 88
uint8_t m_latch_42; // D flip-flop @ 42
uint8_t m_counter_84; // 4-bit phoneme counter @ 84
uint8_t m_latch_92; // 2-bit latch @ 92
// low parameter clocking // "Unpacked" current rom values
bool m_srff_132; // S/R flip-flop @ 132 u8 m_rom_duration; // Duration in 5KHz units (main/144) of one tick, 16 ticks per phone, 7 bits
bool m_srff_114; // S/R flip-flop @ 114 u8 m_rom_vd, m_rom_cld; // Duration in ticks of the "voice" and "closure" delays, 4 bits
bool m_srff_112; // S/R flip-flop @ 112 u8 m_rom_fa, m_rom_fc, m_rom_va; // Analog parameters, noise volume, noise freq cutoff and voice volume, 4 bits each
bool m_srff_142; // S/R flip-flop @ 142 u8 m_rom_f1, m_rom_f2, m_rom_f2q, m_rom_f3; // Analog parameters, formant frequencies and Q, 4 bits each
uint8_t m_latch_80; // phoneme timing latch @ 80 bool m_rom_closure; // Closure bit, true = silence at cld
bool m_rom_pause; // Pause bit
// glottal circuit // Current interpolated values (8 bits each)
uint8_t m_counter_220; // 4-bit counter @ 220 u8 m_cur_fa, m_cur_fc, m_cur_va;
uint8_t m_counter_222; // 4-bit counter @ 222 u8 m_cur_f1, m_cur_f2, m_cur_f2q, m_cur_f3;
uint8_t m_counter_224; // 4-bit counter @ 224
uint8_t m_counter_234; // 4-bit counter @ 234
uint8_t m_counter_236; // 4-bit counter @ 236
uint8_t m_fgate; // FGATE signal
uint8_t m_glottal_sync; // Glottal Sync signal
// transition circuit // Current committed values
uint8_t m_0625_clock; // state of 0.625kHz clock u8 m_filt_fa, m_filt_fc, m_filt_va; // Analog parameters, noise volume, noise freq cutoff and voice volume, 4 bits each
uint8_t m_counter_46; // 4-bit counter in block @ 46 u8 m_filt_f1, m_filt_f2, m_filt_f2q, m_filt_f3; // Analog parameters, formant frequencies/Q on 4 bits except f2 on 5 bits
uint8_t m_latch_46; // 4-bit latch in block @ 46
uint8_t m_ram[8]; // RAM to hold parameters
uint8_t m_latch_168; // 4-bit latch @ 168
uint8_t m_latch_170; // 4-bit latch @ 170
uint8_t m_f1; // latched 4-bit F1 value
uint8_t m_f2; // latched 5-bit F2 value
uint8_t m_fc; // latched 4-bit FC value
uint8_t m_f3; // latched 4-bit F3 value
uint8_t m_f2q; // latched 4-bit F2Q value
uint8_t m_va; // latched 4-bit VA value
uint8_t m_fa; // latched 4-bit FA value
// noise generator circuit // Internal counters
uint8_t m_noise_clock; // clock input to noise generator u16 m_phonetick; // 9-bits phone tick duration counter
uint32_t m_shift_252; // shift register @ 252 u8 m_ticks; // 5-bits tick counter
uint8_t m_counter_250; // 4-bit counter @ 250 u8 m_pitch; // 7-bits pitch counter
u8 m_closure; // 5-bits glottal closure counter
u8 m_update_counter; // 6-bits counter for the 625Hz (main/1152) and 208Hz (main/3456) update timing generators
// stages outputs history // Internal state
double m_ni_hist[4]; bool m_cur_closure; // Current internal closure state
double m_no_hist[4]; u16 m_noise; // 15-bit noise shift register
double m_va_hist[4]; bool m_cur_noise; // Current noise output
double m_s1_hist[4];
double m_s2g_hist[4];
double m_s2ni_hist[4];
double m_s2n_hist[4];
double m_s2_hist[4];
double m_s3_hist[4];
double m_s4i_hist[4];
double m_s4_hist[4];
// static tables // Filter coefficients and level histories
static const char *const s_phoneme_table[64]; double m_voice_1[4];
static const double s_glottal_wave[16]; double m_voice_2[4];
double m_voice_3[4];
double m_noise_1[3];
double m_noise_2[3];
double m_noise_3[2];
double m_noise_4[2];
double m_vn_1[4];
double m_vn_2[4];
double m_vn_3[4];
double m_vn_4[4];
double m_vn_5[2];
double m_vn_6[2];
double m_f1_a[4], m_f1_b[4]; // F1 filtering
double m_f2v_a[4], m_f2v_b[4]; // F2 voice filtering
double m_f2n_a[2], m_f2n_b[2]; // F2 noise filtering
double m_f3_a[4], m_f3_b[4]; // F3 filtering
double m_f4_a[4], m_f4_b[4]; // F4 filtering
double m_fx_a[1], m_fx_b[2]; // Final filtering
double m_fn_a[3], m_fn_b[3]; // Noise shaping
// Compute a total capacitor value based on which bits are currently active
static double bits_to_caps(u32 value, std::initializer_list<double> caps_values) {
double total = 0;
for(double d : caps_values) {
if(value & 1)
total += d;
value >>= 1;
}
return total;
}
// Shift a history of values by one and insert the new value at the front
template<u32 N> static void shift_hist(double val, double (&hist_array)[N]) {
for(u32 i=N-1; i>0; i--)
hist_array[i] = hist_array[i-1];
hist_array[0] = val;
}
// Apply a filter and compute the result. 'a' is applied to x (inputs) and 'b' to y (outputs)
template<u32 Nx, u32 Ny, u32 Na, u32 Nb> static double apply_filter(const double (&x)[Nx], const double (&y)[Ny], const double (&a)[Na], const double (&b)[Nb]) {
static_assert(Nx >= Na);
static_assert(Ny >= Nb);
double total = 0;
for(u32 i=0; i<Na; i++)
total += x[i] * a[i];
for(u32 i=1; i<Nb; i++)
total -= y[i-1] * b[i];
return total / b[0];
}
void build_standard_filter(double *a, double *b,
double c1t, // Unswitched cap, input, top
double c1b, // Switched cap, input, bottom
double c2t, // Unswitched cap, over first amp-op, top
double c2b, // Switched cap, over first amp-op, bottom
double c3, // Cap between the two op-amps
double c4); // Cap over second op-amp
void build_noise_shaper_filter(double *a, double *b,
double c1, // Cap over first amp-op
double c2t, // Unswitched cap between amp-ops, input, top
double c2b, // Switched cap between amp-ops, input, bottom
double c3, // Cap over second amp-op
double c4); // Switched cap after second amp-op
void build_lowpass_filter(double *a, double *b,
double c1t, // Unswitched cap, over amp-op, top
double c1b); // Switched cap, over amp-op, bottom
void build_injection_filter(double *a, double *b,
double c1b, // Switched cap, input, bottom
double c2t, // Unswitched cap, over first amp-op, top
double c2b, // Switched cap, over first amp-op, bottom
double c3, // Cap between the two op-amps
double c4); // Cap over second op-amp
static void interpolate(u8 &reg, u8 target); // Do one interpolation step
void chip_update(); // Global update called at 20KHz (main/36)
void filters_commit(bool force); // Commit the currently computed interpolation values to the filters
void phone_commit(); // Commit the current phone id
stream_sample_t analog_calc(); // Compute one more sample
}; };
@ -160,5 +194,4 @@ private:
// device type definition // device type definition
extern const device_type VOTRAX_SC01; extern const device_type VOTRAX_SC01;
#endif /* VOTRAX_H */
#endif /* __VOTRAX_H__ */

View File

@ -1,190 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Mike Coates
/**************************************************************************
Gorf/Votrax SC-01 Emulator
Mike@Dissfulfils.co.uk
Modified to match phonemes to words
Ajudd@quantime.co.uk
**************************************************************************
gorf_sh_w - Write data to votrax port
gorf_sh_status - Return busy status (-1 = busy)
gorf_port_2_r - Returns status of voice port
gorf_sh_ update- Null
**************************************************************************/
#include "emu.h"
#include "cpu/z80/z80.h"
#include "includes/astrocde.h"
#include "audio/gorf.h"
/****************************************************************************
* 64 Phonemes - currently 1 sample per phoneme, will be combined sometime!
****************************************************************************/
static const char *const PhonemeTable[65] =
{
"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",
nullptr
};
static const char *const GorfWordTable[] =
{
"A2AYY1","A2E1","UH1GEH1I3N","AE1EH2M","AEM",
"AE1EH3ND","UH1NAH2I1YLA2SHUH2N","AH2NUHTHER","AH1NUHTHVRR",
"AH1R","UHR","UH1VEH1EH3NNDJER","BAEEH3D","BAEEH1D","BE",
"BEH3EH1N","buht","BUH1DTTEH2NN","KUHDEH2T",
"KAE1NUH1T","KAE1EH3PTI3N",
"KRAH2UH3NI3KUH3O2LZ","KO1UH3I3E1N","KO1UH3I3E1NS",
"KERNAH2L","KAH1NCHEHSNEHS","DE1FEH1NDER",
"DE1STRO1I1Y","DE1STRO1I1Y1D",
"DU1UM","DRAW1S","EHMPAH2I3YR","EHND",
"EH1NEH1MY","EH1SKA1E1P","FLEHGSHIP",
"FOR","GUH1LAEKTI1K",
"DJEH2NERUH3L","GDTO1O1RRFF","GDTO1RFYA2N","GDTO1RFE1EH2N","GDTO1RFYA2NS",
"HAH1HAH1HAH1HAH1","hahaher.wav","HUHRDER",
"HAE1EH3V","HI1TI1NG","AH1I1Y", "AH1I1Y1","I1MPAH1SI1BL",
"IN*","INSERT","I1S","LI1V","LAWNG","MEE1T","MUU1V",
"MAH2I1Y","MAH2I3Y","NIR","NEHKST","NUH3AH2YS","NO",
"NAH1O1U1W","PA1","PLA1AYER","PRE1PAE1ER","PRI1SI3NEH3RS",
"PRUH2MOTEH3D","POO1IUSH","RO1U1BAH1T","RO1U1BAH1TS",
"RO1U1BAH1UH3TS","SEK", "SHIP","SHAH1UH3T","SUHM","SPA2I3YS","PA0",
"SERVAH2I1Y1VUH3L","TAK","THVUH","THVUH1",
"THUH","TAH1EH3YM","TU","TIUU1",
"UH2NBE1AYTUH3BUH3L",
"WORAYY1EH3R","WORAYY1EH3RS","WI1L",
"Y1I3U1","YIUU1U1","YI1U1U1","Y1IUU1U1","Y1I1U1U1","YOR","YU1O1RSEH1LF","s.wav",
"FO1R","FO2R","WIL","GDTO1RVYA2N",
"KO1UH3I3AYNN",
"UH1TAEEH3K","BAH2I3Y1T","KAH1NKER","DYVAH1U1ER","DUHST","GAE1LUH1KSY","GAH1EH3T",
"PAH1I1R","TRAH2I1Y","SU1PRE1N","AWL","HA2AYL",
"EH1MPAH1I1R",
nullptr
};
#define num_samples (sizeof(GorfWordTable)/sizeof(char *))
const char *const gorf_sample_names[] =
{
"*gorf","a","a","again","am","am","and","anhilatn",
"another","another","are","are",
"avenger","bad","bad","be",
"been","but","button","cadet",
"cannot","captain","chronicl","coin","coins","colonel",
"consciou","defender","destroy","destroyd",
"doom","draws","empire","end",
"enemy","escape","flagship","for","galactic",
"general","gorf","gorphian","gorphian","gorphins",
"hahahahu","hahaher","harder","have",
"hitting","i","i","impossib","in","insert",
"is","live","long","meet","move",
"my","my",
"near","next","nice","no",
"now","pause","player","prepare","prisonrs",
"promoted","push","robot","robots","robots",
"seek","ship","shot","some","space","spause",
"survival","take","the","the","the","time",
"to","to","unbeatab",
"warrior","warriors","will",
"you","you","you","you","your","your","yourself",
"s","for","for","will","gorph",
// Missing Samples
"coin", "attack","bite","conquer","devour","dust",
"galaxy","got","power","try","supreme","all",
"hail","emperor",
nullptr
};
READ8_MEMBER( astrocde_state::gorf_speech_r )
{
uint8_t data = offset >> 8;
#if USE_FAKE_VOTRAX
int Phoneme, Intonation;
int i = 0;
offset &= 0xff;
m_totalword_ptr = m_totalword;
Phoneme = data & 0x3F;
Intonation = data >> 6;
logerror("Date : %d Speech : %s at intonation %d\n",Phoneme, PhonemeTable[Phoneme],Intonation);
if(Phoneme==63) {
m_samples->stop(0);
if (strlen(m_totalword)>2) logerror("Clearing sample %s\n",m_totalword);
m_totalword[0] = 0; /* Clear the total word stack */
return data;
}
/* Phoneme to word translation */
if (*(m_totalword) == 0) {
strcpy(m_totalword,PhonemeTable[Phoneme]); /* Copy over the first phoneme */
if (m_plural != 0) {
logerror("found a possible plural at %d\n",m_plural-1);
if (!strcmp("S",m_totalword)) { /* Plural check */
m_samples->start(0, num_samples-2); /* play the sample at position of word */
m_samples->set_frequency(0, 11025); /* play at correct rate */
m_totalword[0] = 0; /* Clear the total word stack */
m_oldword[0] = 0; /* Clear the total word stack */
return data;
} else {
m_plural=0;
}
}
} else
strcat(m_totalword,PhonemeTable[Phoneme]); /* Copy over the first phoneme */
logerror("Total word = %s\n",m_totalword);
for (i=0; GorfWordTable[i]; i++) {
if (!strcmp(GorfWordTable[i],m_totalword)) { /* Scan the word (sample) table for the complete word */
if ((!strcmp("GDTO1RFYA2N",m_totalword)) || (!strcmp("RO1U1BAH1T",m_totalword)) || (!strcmp("KO1UH3I3E1N",m_totalword)) || (!strcmp("WORAYY1EH3R",m_totalword)) || (!strcmp("IN",m_totalword)) ) { /* May be m_plural */
m_plural=i+1;
strcpy(m_oldword,m_totalword);
logerror("Storing sample position %d and copying string %s\n",m_plural,m_oldword);
} else {
m_plural=0;
}
m_samples->start(0, i); /* play the sample at position of word */
m_samples->set_frequency(0, 11025); /* play at correct rate */
logerror("Playing sample %d",i);
m_totalword[0] = 0; /* Clear the total word stack */
return data;
}
}
#else
m_votrax->inflection_w(space, 0, data >> 6);
m_votrax->write(space, 0, data);
#endif
/* Note : We should really also use volume in this as well as frequency */
return data; /* Return nicely */
}
CUSTOM_INPUT_MEMBER( astrocde_state::gorf_speech_status_r )
{
#if USE_FAKE_VOTRAX
return !m_samples->playing(0);
#else
return m_votrax->request();
#endif
}

View File

@ -1,4 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Mike Coates
extern const char *const gorf_sample_names[];

View File

@ -30,225 +30,6 @@ extern const device_type GOTTLIEB_SOUND_REV1_WITH_VOTRAX = &device_creator<gottl
extern const device_type GOTTLIEB_SOUND_REV2 = &device_creator<gottlieb_sound_r2_device>; extern const device_type GOTTLIEB_SOUND_REV2 = &device_creator<gottlieb_sound_r2_device>;
//**************************************************************************
// OLD CRAPPY SAMPLE PLAYER
//**************************************************************************
#if USE_FAKE_VOTRAX
void gottlieb_sound_r1_device::trigger_sample(uint8_t data)
{
/* Reactor samples */
if (strcmp(machine().system().name, "reactor") == 0)
{
switch (data)
{
case 55:
case 56:
case 57:
case 59:
m_samples->start(0, data - 53);
break;
case 31:
m_score_sample = 7;
break;
case 39:
m_score_sample++;
if (m_score_sample < 20)
m_samples->start(0, m_score_sample);
break;
}
}
/* Q*Bert samples */
else
{
switch (data)
{
case 17:
case 18:
case 19:
case 20:
case 21:
m_samples->start(0, (data - 17) * 8 + m_random_offset);
m_random_offset = (m_random_offset + 1) & 7;
break;
case 22:
m_samples->start(0,40);
break;
case 23:
m_samples->start(0,41);
break;
}
}
}
void gottlieb_sound_r1_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
m_audiocpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
}
void gottlieb_sound_r1_device::fake_votrax_data_w(uint8_t data)
{
static const char *const PhonemeTable[0x40] =
{
"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"
};
data ^= 0xff;
logerror("Votrax: intonation %d, phoneme %02x %s\n",data >> 6,data & 0x3f,PhonemeTable[data & 0x3f]);
m_votrax_queue[m_votrax_queuepos++] = data;
if ((data & 0x3f) == 0x3f)
{
if (m_votrax_queuepos > 1)
{
int last = -1;
int i;
char phonemes[200];
phonemes[0] = 0;
for (i = 0;i < m_votrax_queuepos-1;i++)
{
static const char *const inf[4] = { "[0]", "[1]", "[2]", "[3]" };
int phoneme = m_votrax_queue[i] & 0x3f;
int inflection = m_votrax_queue[i] >> 6;
if (inflection != last) strcat(phonemes, inf[inflection]);
last = inflection;
if (phoneme == 0x03 || phoneme == 0x3e) strcat(phonemes," ");
else strcat(phonemes,PhonemeTable[phoneme]);
}
osd_printf_debug("Votrax played '%s'\n", phonemes);
if (strcmp(phonemes, "[0] HEH3LOOW AH1EH3I3YMTERI2NDAHN") == 0) /* Q-Bert & Tylz - Hello, I am turned on */
m_samples->start(0, 42);
else if (strcmp(phonemes, "[0]BAH1EH1Y") == 0) /* Q-Bert - Bye, bye */
m_samples->start(0, 43);
else if (strcmp(phonemes, "[0]A2YHT LEH2FTTH") == 0) /* Reactor - Eight left */
m_samples->start(0, 0);
else if (strcmp(phonemes, "[0]SI3KS DTYN LEH2FTTH") == 0) /* Reactor - Sixteen left */
m_samples->start(0, 1);
else if (strcmp(phonemes, "[0]WO2RNYNG KO2R UH1NSDTABUH1L") == 0) /* Reactor - Warning core unstable */
m_samples->start(0, 5);
else if (strcmp(phonemes, "[0]CHAMBERR AE1EH2KTI1VA1I3DTEH1DT ") == 0) /* Reactor - Chamber activated */
m_samples->start(0, 7);
}
m_votrax_queuepos = 0;
}
/* generate a NMI after a while to make the CPU continue to send data */
timer_set(attotime::from_usec(50));
}
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" */
nullptr /* 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",
nullptr /* end of array */
};
MACHINE_CONFIG_FRAGMENT( reactor_samples )
MCFG_SOUND_ADD("samples", SAMPLES, 0)
MCFG_SAMPLES_CHANNELS(1)
MCFG_SAMPLES_NAMES(reactor_sample_names)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.0)
MACHINE_CONFIG_END
MACHINE_CONFIG_FRAGMENT( qbert_samples )
MCFG_SOUND_ADD("samples", SAMPLES, 0)
MCFG_SAMPLES_CHANNELS(1)
MCFG_SAMPLES_NAMES(qbert_sample_names)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.0)
MACHINE_CONFIG_END
#endif
//************************************************************************** //**************************************************************************
// REV 0 SOUND BOARD: 6502 + 6530 + DAC // REV 0 SOUND BOARD: 6502 + 6530 + DAC
//************************************************************************** //**************************************************************************
@ -390,12 +171,6 @@ gottlieb_sound_r1_device::gottlieb_sound_r1_device(const machine_config &mconfig
m_votrax(*this, "votrax"), m_votrax(*this, "votrax"),
//m_populate_votrax(false), //m_populate_votrax(false),
m_last_speech_clock(0) m_last_speech_clock(0)
#if USE_FAKE_VOTRAX
, m_samples(*this, ":samples"),
m_score_sample(0),
m_random_offset(0),
m_votrax_queuepos(0)
#endif
{ {
} }
@ -407,12 +182,6 @@ gottlieb_sound_r1_device::gottlieb_sound_r1_device(const machine_config &mconfig
m_votrax(*this, "votrax"), m_votrax(*this, "votrax"),
//m_populate_votrax(populate_votrax), //m_populate_votrax(populate_votrax),
m_last_speech_clock(0) m_last_speech_clock(0)
#if USE_FAKE_VOTRAX
, m_samples(*this, ":samples"),
m_score_sample(0),
m_random_offset(0),
m_votrax_queuepos(0)
#endif
{ {
} }
@ -427,11 +196,6 @@ WRITE8_MEMBER( gottlieb_sound_r1_device::write )
uint8_t pa7 = (data & 0x0f) != 0xf; uint8_t pa7 = (data & 0x0f) != 0xf;
uint8_t pa0_5 = ~data & 0x3f; uint8_t pa0_5 = ~data & 0x3f;
m_riot->porta_in_set(pa0_5 | (pa7 << 7), 0xbf); m_riot->porta_in_set(pa0_5 | (pa7 << 7), 0xbf);
#if USE_FAKE_VOTRAX
if (pa7 && m_samples != nullptr)
trigger_sample(pa0_5);
#endif
} }
@ -469,10 +233,6 @@ WRITE8_MEMBER( gottlieb_sound_r1_device::votrax_data_w )
m_votrax->inflection_w(space, offset, data >> 6); m_votrax->inflection_w(space, offset, data >> 6);
m_votrax->write(space, offset, ~data & 0x3f); m_votrax->write(space, offset, ~data & 0x3f);
} }
#if USE_FAKE_VOTRAX
fake_votrax_data_w(data);
#endif
} }

View File

@ -15,11 +15,6 @@
#include "sound/votrax.h" #include "sound/votrax.h"
// set to 0 to enable Votrax device and disable samples
#define USE_FAKE_VOTRAX (1)
//************************************************************************** //**************************************************************************
// GLOBAL VARIABLES // GLOBAL VARIABLES
//************************************************************************** //**************************************************************************
@ -108,19 +103,6 @@ private:
// internal state // internal state
//bool m_populate_votrax; //bool m_populate_votrax;
uint8_t m_last_speech_clock; uint8_t m_last_speech_clock;
#if USE_FAKE_VOTRAX
protected:
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
void fake_votrax_data_w(uint8_t data);
void trigger_sample(uint8_t data);
optional_device<samples_device> m_samples;
uint8_t m_score_sample;
uint8_t m_random_offset;
uint8_t m_votrax_queue[100];
uint8_t m_votrax_queuepos;
#endif
}; };
// fully populated rev 1 sound board // fully populated rev 1 sound board
@ -203,10 +185,3 @@ private:
uint8_t m_sp0250_latch; uint8_t m_sp0250_latch;
}; };
/*----------- defined in audio/gottlieb.c -----------*/
#if USE_FAKE_VOTRAX
MACHINE_CONFIG_EXTERN( reactor_samples );
MACHINE_CONFIG_EXTERN( qbert_samples );
#endif

View File

@ -1,183 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Mike Coates
/**************************************************************************
WOW/Votrax SC-01 Emulator
Mike@Dissfulfils.co.uk
Modified to match phonemes to words
Ajudd@quantime.co.uk
**************************************************************************
wow_sh_start - Start emulation, load samples from Votrax subdirectory
wow_sh_w - Write data to votrax port
wow_sh_status - Return busy status (-1 = busy)
wow_port_2_r - Returns status of voice port
wow_sh_ update- Null
**************************************************************************/
#include "emu.h"
#include "cpu/z80/z80.h"
#include "includes/astrocde.h"
#include "audio/wow.h"
/****************************************************************************
* 64 Phonemes - currently 1 sample per phoneme, will be combined sometime!
****************************************************************************/
static const char *const PhonemeTable[65] =
{
"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",
nullptr
};
/* Missing samples : ready, from, one, bite, youl, explode, if, myself, back,
cant, do, wait, worlings, very, babies, breath, fire, beat, rest,
then, never, worlock, escape, door, try, any, harder, only, meet, with,
doom, pop,
Problems with YOU and YOU'LL and YOU'DD */
static const char *const wowWordTable[] =
{
"AH1I3Y1", "UH1GA1EH1N", "AHAH2", "AE1EH3M", "AE1EH3ND",
"anew.wav", "AH1NUHTHER", "AE1NY", "anyone.wav", "appear.wav", "AH1UH3R", "UHR", "BABYY1S", "BAE1EH3K",
"BE1T", "become.wav", "BEHST", "BEH1TER", "BUH3AH2YT", "bones.wav", "BRE1YTH", "but.wav", "can.wav", "KAE1EH3NT",
"chance.wav", "CHEHST", "KO1O2I3Y1N", "dance.wav", "DE1STRO1UH3I3AY",
"DE1VEH1LUH3PT", "DIUU", "DONT", "DUUM", "DOO1R", "draw.wav", "DUHNJEH1N", "DUHNJEH1NZ",
"each.wav", "eaten.wav", "EHSPA0KA2I3Y1P", "EHKPA0SPLOU1D", "fear.wav", "FAH1I3YND", "FAH1I3Y1ND", "FAH1EH3AYR", "FOR", "FRUHMM",
"garwor.wav", "GEHT", "GEH1T", "GEHEH3T", "GEHTING", "good.wav", "HAH1HAH1HAH1HAH1", "HAH1RDER",
"hasnt.wav", "have.wav", "HEH1I3VE1WA1I3Y1TS", "HAI1Y1", "HOP",
"HUHNGRY", "HUHNGGRY", "HERRY", "AH1EH3I3Y", "AH1UH3I3Y", "IF", "I1F", "AH1I3YM", "AH1EH3I3YL", "AH1I3Y1L", "IN1",
"INSERT", "invisibl.wav", "IT", "lie.wav", "MAE1EH3DJI1KUH1L",
"MAE1EH3DJI1KUH1L", "MEE1", "MEE1T", "months.wav",
"MAH1EH3I3Y", "MAH2AH2EH3I3Y", "MAH1I1Y", "MAH1I3Y1", "MAH1I3Y", "MAH1I3YSEHLF", "near.wav", "NEH1VER",
"NAH1UH3U1", "UHV", "AWF", "WUHN", "O1NLY", "UHVEHN", "PA1", "PEHTS", "PAH1WERFUH1L", "PAH1P",
"radar.wav", "REHDY",
"REHST", "say.wav", "SAH1I3AYEHNS", "SE1Y", "PA0", "start.wav", "THVAYAY", "THVUH", "THVUH1", "THUH1", "THVEH1N",
"THVRU", "thurwor.wav", "time.wav", "TU1", "TUU1", "TIUU1", "TREH1ZHERT", "TRAH1EH3I3Y", "VEHEH3RY", "WA2AYYT",
"WOO1R", "WORYER", "watch.wav", "WE1Y", "WEHLKUHM",
"WERR", "WAH1EH3I3L", "WIL", "WITH", "WIZERD", "wont.wav",
"WO1O2R", "WO1ERLD", "WORLINGS", "WORLUHK",
"YI3U", "Y1IUU", "YIUUI", "Y1IUU1U1", "YI3U1", "Y1IUUL", "YIUU1L", "Y1IUUD", "YO2O2R",nullptr
};
#define num_samples (sizeof(wowWordTable)/sizeof(char *))
const char *const wow_sample_names[] =
{
"*wow",
"a", "again", "ahh", "am", "and",
"anew", "another", "any", "anyone", "appear", "are", "are", "babies", "back",
"beat", "become", "best", "better", "bite", "bones", "breath", "but", "can", "cant",
"chance", "chest", "coin", "dance", "destroy",
"develop", "do", "dont", "doom", "door", "draw", "dungeon", "dungeons",
"each", "eaten", "escape", "explode", "fear", "find", "find", "fire", "for", "from",
"garwor", "get", "get", "get", "getting", "good", "hahahaha", "harder",
"hasnt", "have", "heavyw", "hey", "hope",
"hungry", "hungry", "hurry", "i", "i", "if", "if", "im", "i1", "ill", "in",
"insert", "invisibl", "it", "lie", "magic",
"magical", "me", "meet", "months",
"my", "my", "my", "my", "my", "myself", "near", "never",
"now", "of", "off", "one", "only", "oven", "pause", "pets", "powerful", "pop",
"radar", "ready",
"rest", "say", "science", "see", "spause", "start", "the", "the", "the", "the", "then",
"through", "thurwor", "time", "to", "to", "to", "treasure", "try", "very", "wait",
"war", "warrior", "watch", "we", "welcome",
"were", "while", "will", "with", "wizard", "wont",
"wor", "world", "worlings", "worlock",
"you", "you", "you", "you", "you", "youl", "youl", "youd", "your",nullptr
};
READ8_MEMBER( astrocde_state::wow_speech_r )
{
uint8_t data = offset >> 8;
#if USE_FAKE_VOTRAX
int Phoneme/*, Intonation*/;
int i = 0;
offset &= 0xff;
m_totalword_ptr = m_totalword;
Phoneme = data & 0x3F;
//Intonation = data >> 6;
//logerror("Data : %d Speech : %s at intonation %d\n",Phoneme, PhonemeTable[Phoneme],Intonation);
if(Phoneme==63) {
m_samples->stop(0);
//logerror("Clearing sample %s\n",m_totalword);
m_totalword[0] = 0; /* Clear the total word stack */
return data;
}
if (Phoneme==3) /* We know PA0 is never part of a word */
m_totalword[0] = 0; /* Clear the total word stack */
/* Phoneme to word translation */
if (*(m_totalword) == 0) {
strcpy(m_totalword,PhonemeTable[Phoneme]); /* Copy over the first phoneme */
if (m_plural != 0) {
//logerror("found a possible plural at %d\n",m_plural-1);
if (!strcmp("S",m_totalword)) { /* Plural check */
m_samples->start(0, num_samples-2); /* play the sample at position of word */
m_samples->set_frequency(0, 11025); /* play at correct rate */
m_totalword[0] = 0; /* Clear the total word stack */
m_oldword[0] = 0; /* Clear the total word stack */
return data;
} else {
m_plural=0;
}
}
} else
strcat(m_totalword,PhonemeTable[Phoneme]); /* Copy over the first phoneme */
//logerror("Total word = %s\n",m_totalword);
for (i=0; wowWordTable[i]; i++) {
if (!strcmp(wowWordTable[i],m_totalword)) { /* Scan the word (sample) table for the complete word */
/* WOW has Dungeon */
if ((!strcmp("GDTO1RFYA2N",m_totalword)) || (!strcmp("RO1U1BAH1T",m_totalword)) || (!strcmp("KO1UH3I3E1N",m_totalword))) { /* May be plural */
m_plural=i+1;
strcpy(m_oldword,m_totalword);
//logerror("Storing sample position %d and copying string %s\n",m_plural,m_oldword);
} else {
m_plural=0;
}
m_samples->start(0, i); /* play the sample at position of word */
m_samples->set_frequency(0, 11025); /* play at correct rate */
//logerror("Playing sample %d\n",i);
m_totalword[0] = 0; /* Clear the total word stack */
return data;
}
}
#else
m_votrax->inflection_w(space, 0, data >> 6);
m_votrax->write(space, 0, data);
#endif
/* Note : We should really also use volume in this as well as frequency */
return data; /* Return nicely */
}
CUSTOM_INPUT_MEMBER( astrocde_state::wow_speech_status_r )
{
#if USE_FAKE_VOTRAX
return !m_samples->playing(0);
#else
return m_votrax->request();
#endif
}

View File

@ -1,4 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Mike Coates
extern const char *const wow_sample_names[];

View File

@ -120,9 +120,7 @@
#include "machine/z80ctc.h" #include "machine/z80ctc.h"
#include "machine/nvram.h" #include "machine/nvram.h"
#include "sound/ay8910.h" #include "sound/ay8910.h"
#include "sound/votrax.h"
#include "audio/wow.h"
#include "audio/gorf.h"
#include "gorf.lh" #include "gorf.lh"
#include "seawolf2.lh" #include "seawolf2.lh"
@ -292,7 +290,6 @@ READ8_MEMBER(astrocde_state::wow_io_r)
} }
/************************************* /*************************************
* *
* Gorf specific input/output * Gorf specific input/output
@ -313,11 +310,7 @@ READ8_MEMBER(astrocde_state::gorf_io_1_r)
case 5: m_sparkle[3] = data; break; case 5: m_sparkle[3] = data; break;
case 6: case 6:
m_astrocade_sound1->set_output_gain(0, data ? 0.0 : 1.0); m_astrocade_sound1->set_output_gain(0, data ? 0.0 : 1.0);
#if USE_FAKE_VOTRAX
m_samples->set_output_gain(0, data ? 1.0 : 0.0);
#else
m_votrax->set_output_gain(0, data ? 1.0 : 0.0); m_votrax->set_output_gain(0, data ? 1.0 : 0.0);
#endif
break; break;
case 7: osd_printf_debug("io_1:%d\n", data); break; case 7: osd_printf_debug("io_1:%d\n", data); break;
} }
@ -512,6 +505,28 @@ WRITE8_MEMBER(astrocde_state::tenpindx_lights_w)
} }
/*************************************
*
* Votrax SC01 specific input/output
*
*************************************/
READ8_MEMBER( astrocde_state::votrax_speech_r )
{
uint8_t data = offset >> 8;
m_votrax->inflection_w(space, 0, data >> 6);
m_votrax->write(space, 0, data);
/* Note : We should really also use volume in this as well as frequency */
return data; /* Return nicely */
}
CUSTOM_INPUT_MEMBER( astrocde_state::votrax_speech_status_r )
{
return m_votrax->request();
}
/************************************* /*************************************
* *
@ -879,7 +894,7 @@ static INPUT_PORTS_START( wow )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, astrocde_state, wow_speech_status_r, nullptr) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, astrocde_state, votrax_speech_status_r, nullptr)
PORT_START("P4HANDLE") PORT_START("P4HANDLE")
/* "If S1:1,2,3 are all ON or all OFF, only coin meter number 1 will count." */ /* "If S1:1,2,3 are all ON or all OFF, only coin meter number 1 will count." */
@ -949,7 +964,7 @@ static INPUT_PORTS_START( gorf )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, astrocde_state, gorf_speech_status_r, nullptr) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, astrocde_state, votrax_speech_status_r, nullptr)
PORT_START("P4HANDLE") PORT_START("P4HANDLE")
PORT_DIPNAME( 0x01, 0x01, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("S1:1") PORT_DIPNAME( 0x01, 0x01, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("S1:1")
@ -1354,13 +1369,7 @@ static MACHINE_CONFIG_DERIVED( wow, astrocade_base )
/* sound hardware */ /* sound hardware */
MCFG_SPEAKER_ADD("center", 0.0, 0.0, 1.0) MCFG_SPEAKER_ADD("center", 0.0, 0.0, 1.0)
#if USE_FAKE_VOTRAX MCFG_SOUND_ADD("votrax", VOTRAX_SC01, 720000)
MCFG_SOUND_ADD("samples", SAMPLES, 0)
MCFG_SAMPLES_CHANNELS(1)
MCFG_SAMPLES_NAMES(wow_sample_names)
#else
MCFG_VOTRAX_SC01_ADD("votrax", VOTRAX_SC01, 720000)
#endif
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "center", 0.85) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "center", 0.85)
MACHINE_CONFIG_END MACHINE_CONFIG_END
@ -1386,13 +1395,7 @@ static MACHINE_CONFIG_DERIVED( gorf, astrocade_base )
MCFG_ASTROCADE_ADD("astrocade2", ASTROCADE_CLOCK/4) MCFG_ASTROCADE_ADD("astrocade2", ASTROCADE_CLOCK/4)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lower", 1.0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lower", 1.0)
#if USE_FAKE_VOTRAX MCFG_SOUND_ADD("votrax", VOTRAX_SC01, 720000)
MCFG_SOUND_ADD("samples", SAMPLES, 0)
MCFG_SAMPLES_CHANNELS(1)
MCFG_SAMPLES_NAMES(gorf_sample_names)
#else
MCFG_VOTRAX_SC01_ADD("votrax", VOTRAX_SC01, 720000)
#endif
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "upper", 0.85) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "upper", 0.85)
MACHINE_CONFIG_END MACHINE_CONFIG_END
@ -1709,7 +1712,7 @@ DRIVER_INIT_MEMBER(astrocde_state,wow)
{ {
m_video_config = AC_SOUND_PRESENT | AC_LIGHTPEN_INTS | AC_STARS; m_video_config = AC_SOUND_PRESENT | AC_LIGHTPEN_INTS | AC_STARS;
m_maincpu->space(AS_IO).install_read_handler(0x15, 0x15, 0, 0xf000, 0x0f00, read8_delegate(FUNC(astrocde_state::wow_io_r), this)); m_maincpu->space(AS_IO).install_read_handler(0x15, 0x15, 0, 0xf000, 0x0f00, read8_delegate(FUNC(astrocde_state::wow_io_r), this));
m_maincpu->space(AS_IO).install_read_handler(0x17, 0x17, 0, 0x0000, 0xff00, read8_delegate(FUNC(astrocde_state::wow_speech_r), this)); m_maincpu->space(AS_IO).install_read_handler(0x17, 0x17, 0, 0x0000, 0xff00, read8_delegate(FUNC(astrocde_state::votrax_speech_r), this));
} }
@ -1718,7 +1721,7 @@ DRIVER_INIT_MEMBER(astrocde_state,gorf)
m_video_config = AC_SOUND_PRESENT | AC_LIGHTPEN_INTS | AC_STARS; m_video_config = AC_SOUND_PRESENT | AC_LIGHTPEN_INTS | AC_STARS;
m_maincpu->space(AS_IO).install_read_handler(0x15, 0x15, 0, 0xf000, 0x0f00, read8_delegate(FUNC(astrocde_state::gorf_io_1_r), this)); m_maincpu->space(AS_IO).install_read_handler(0x15, 0x15, 0, 0xf000, 0x0f00, read8_delegate(FUNC(astrocde_state::gorf_io_1_r), this));
m_maincpu->space(AS_IO).install_read_handler(0x16, 0x16, 0, 0xf000, 0x0f00, read8_delegate(FUNC(astrocde_state::gorf_io_2_r), this)); m_maincpu->space(AS_IO).install_read_handler(0x16, 0x16, 0, 0xf000, 0x0f00, read8_delegate(FUNC(astrocde_state::gorf_io_2_r), this));
m_maincpu->space(AS_IO).install_read_handler(0x17, 0x17, 0, 0x0000, 0xff00, read8_delegate(FUNC(astrocde_state::gorf_speech_r), this)); m_maincpu->space(AS_IO).install_read_handler(0x17, 0x17, 0, 0x0000, 0xff00, read8_delegate(FUNC(astrocde_state::votrax_speech_r), this));
} }
@ -1797,13 +1800,13 @@ GAMEL(1980, ebases, 0, ebases, ebases, astrocde_state, ebases, ROT0,
GAMEL(1980, spacezap, 0, spacezap, spacezap, astrocde_state, spacezap, ROT0, "Midway", "Space Zap", MACHINE_SUPPORTS_SAVE, layout_spacezap ) GAMEL(1980, spacezap, 0, spacezap, spacezap, astrocde_state, spacezap, ROT0, "Midway", "Space Zap", MACHINE_SUPPORTS_SAVE, layout_spacezap )
/* 91354 CPU board + 90708 game board + 91356 RAM board + 91355 pattern board + 91397 memory board */ /* 91354 CPU board + 90708 game board + 91356 RAM board + 91355 pattern board + 91397 memory board */
GAME( 1980, wow, 0, wow, wow, astrocde_state, wow, ROT0, "Dave Nutting Associates / Midway", "Wizard of Wor", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1980, wow, 0, wow, wow, astrocde_state, wow, ROT0, "Dave Nutting Associates / Midway", "Wizard of Wor", MACHINE_SUPPORTS_SAVE )
GAME( 1980, wowg, wow, wow, wowg, astrocde_state, wow, ROT0, "Dave Nutting Associates / Midway", "Wizard of Wor (with German Language ROM)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1980, wowg, wow, wow, wowg, astrocde_state, wow, ROT0, "Dave Nutting Associates / Midway", "Wizard of Wor (with German Language ROM)", MACHINE_SUPPORTS_SAVE )
/* 91354 CPU board + 90708 game board + 91356 RAM board + 91355 pattern board + 91364 ROM/RAM board */ /* 91354 CPU board + 90708 game board + 91356 RAM board + 91355 pattern board + 91364 ROM/RAM board */
GAMEL(1981, gorf, 0, gorf, gorf, astrocde_state, gorf, ROT270, "Dave Nutting Associates / Midway", "Gorf", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE, layout_gorf ) GAMEL(1981, gorf, 0, gorf, gorf, astrocde_state, gorf, ROT270, "Dave Nutting Associates / Midway", "Gorf", MACHINE_SUPPORTS_SAVE, layout_gorf )
GAMEL(1981, gorfpgm1, gorf, gorf, gorf, astrocde_state, gorf, ROT270, "Dave Nutting Associates / Midway", "Gorf (program 1)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE, layout_gorf ) GAMEL(1981, gorfpgm1, gorf, gorf, gorf, astrocde_state, gorf, ROT270, "Dave Nutting Associates / Midway", "Gorf (program 1)", MACHINE_SUPPORTS_SAVE, layout_gorf )
GAMEL(1981, gorfpgm1g,gorf, gorf, gorfpgm1g, astrocde_state,gorf, ROT270, "Dave Nutting Associates / Midway", "Gorf (program 1, with German Language ROM)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE, layout_gorf ) GAMEL(1981, gorfpgm1g,gorf, gorf, gorfpgm1g, astrocde_state,gorf, ROT270, "Dave Nutting Associates / Midway", "Gorf (program 1, with German Language ROM)", MACHINE_SUPPORTS_SAVE, layout_gorf )
/* 91354 CPU board + 90708 game board + 91356 RAM board + 91355 pattern board + 91423 memory board */ /* 91354 CPU board + 90708 game board + 91356 RAM board + 91355 pattern board + 91423 memory board */
GAME( 1981, robby, 0, robby, robby, astrocde_state, robby, ROT0, "Dave Nutting Associates / Bally Midway", "The Adventures of Robby Roto!", MACHINE_SUPPORTS_SAVE ) GAME( 1981, robby, 0, robby, robby, astrocde_state, robby, ROT0, "Dave Nutting Associates / Bally Midway", "The Adventures of Robby Roto!", MACHINE_SUPPORTS_SAVE )

View File

@ -1822,38 +1822,6 @@ MACHINE_CONFIG_END
* *
*************************************/ *************************************/
#if USE_FAKE_VOTRAX
static MACHINE_CONFIG_DERIVED( reactor, gottlieb1 )
/* basic machine hardware */
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(reactor_map)
MCFG_DEVICE_REMOVE("nvram")
/* sound hardware */
MCFG_FRAGMENT_ADD(reactor_samples)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( qbert, gottlieb1 )
/* sound hardware */
MCFG_FRAGMENT_ADD(qbert_knocker)
MCFG_FRAGMENT_ADD(qbert_samples)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( tylz, gottlieb1 )
/* sound hardware */
MCFG_FRAGMENT_ADD(qbert_samples)
MACHINE_CONFIG_END
#else
static MACHINE_CONFIG_DERIVED( gottlieb1_votrax, gottlieb_core ) static MACHINE_CONFIG_DERIVED( gottlieb1_votrax, gottlieb_core )
MCFG_SOUND_ADD("r1sound", GOTTLIEB_SOUND_REV1_WITH_VOTRAX, 0) MCFG_SOUND_ADD("r1sound", GOTTLIEB_SOUND_REV1_WITH_VOTRAX, 0)
@ -1882,9 +1850,6 @@ static MACHINE_CONFIG_DERIVED( tylz, gottlieb1_votrax )
MACHINE_CONFIG_END MACHINE_CONFIG_END
#endif
static MACHINE_CONFIG_DERIVED( screwloo, gottlieb2 ) static MACHINE_CONFIG_DERIVED( screwloo, gottlieb2 )
MCFG_VIDEO_START_OVERRIDE(gottlieb_state,screwloo) MCFG_VIDEO_START_OVERRIDE(gottlieb_state,screwloo)

View File

@ -19,8 +19,6 @@
#define AC_STARS (0x04) #define AC_STARS (0x04)
#define AC_MONITOR_BW (0x08) #define AC_MONITOR_BW (0x08)
#define USE_FAKE_VOTRAX (1)
class astrocde_state : public driver_device class astrocde_state : public driver_device
{ {
@ -195,13 +193,8 @@ public:
void init_sparklestar(); void init_sparklestar();
virtual void machine_start() override; virtual void machine_start() override;
/*----------- defined in audio/wow.c -----------*/ DECLARE_READ8_MEMBER( votrax_speech_r );
DECLARE_READ8_MEMBER( wow_speech_r ); CUSTOM_INPUT_MEMBER( votrax_speech_status_r );
CUSTOM_INPUT_MEMBER( wow_speech_status_r );
/*----------- defined in audio/gorf.c -----------*/
DECLARE_READ8_MEMBER( gorf_speech_r );
CUSTOM_INPUT_MEMBER( gorf_speech_status_r );
protected: protected:
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;