diff options
Diffstat (limited to 'src/mame/audio/gottlieb.c')
-rw-r--r-- | src/mame/audio/gottlieb.c | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/src/mame/audio/gottlieb.c b/src/mame/audio/gottlieb.c new file mode 100644 index 00000000000..2236a5e9cf8 --- /dev/null +++ b/src/mame/audio/gottlieb.c @@ -0,0 +1,313 @@ +#include "driver.h" +#include "cpu/m6502/m6502.h" +#include "sound/samples.h" +#include "sound/dac.h" +#include "sound/ay8910.h" +#include "sound/sp0250.h" + + +WRITE8_HANDLER( gottlieb_sh_w ) +{ + static int score_sample=7; + static int random_offset=0; + data &= 0x3f; + + if ((data&0x0f) != 0xf) /* interrupt trigered by four low bits (not all 1's) */ + { + if (sndti_exists(SOUND_SAMPLES, 0)) + { + if (!strcmp(Machine->gamedrv->name,"reactor")) /* reactor */ + { + switch (data ^ 0x3f) + { + case 53: + case 54: + case 55: + case 56: + case 57: + case 58: + case 59: + sample_start(0,(data^0x3f)-53,0); + break; + case 31: + sample_start(0,7,0); + score_sample=7; + break; + case 39: + score_sample++; + if (score_sample<20) sample_start(0,score_sample,0); + break; + } + } + else /* qbert */ + { + switch (data ^ 0x3f) + { + case 17: + case 18: + case 19: + case 20: + case 21: + sample_start(0,((data^0x3f)-17)*8+random_offset,0); + random_offset= (random_offset+1)&7; + break; + case 22: + sample_start(0,40,0); + break; + case 23: + sample_start(0,41,0); + break; + case 28: + sample_start(0,42,0); + break; + case 36: + sample_start(0,43,0); + break; + } + } + } + + soundlatch_w(offset,data); + + switch (cpu_gettotalcpu()) + { + case 2: + /* Revision 1 sound board */ + cpunum_set_input_line(1,M6502_IRQ_LINE,HOLD_LINE); + break; + case 3: + case 4: + /* Revision 2 & 3 sound board */ + cpunum_set_input_line(cpu_gettotalcpu()-1,M6502_IRQ_LINE,HOLD_LINE); + cpunum_set_input_line(cpu_gettotalcpu()-2,M6502_IRQ_LINE,HOLD_LINE); + break; + } + } +} + + +#ifdef UNUSED_FUNCTION +void gottlieb_knocker(void) +{ + if (!strcmp(Machine->gamedrv->name,"reactor")) /* reactor */ + { + } + else if (sndti_exists(SOUND_SAMPLES, 0)) /* qbert */ + sample_start(0,44,0); +} +#endif + +/* callback for the timer */ +static TIMER_CALLBACK( gottlieb_nmi_generate ) +{ + cpunum_set_input_line(1,INPUT_LINE_NMI,PULSE_LINE); +} + +static const char *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", + 0 +}; + + +WRITE8_HANDLER( gottlieb_speech_w ) +{ + static int queue[100],pos; + + data ^= 255; + +logerror("Votrax: intonation %d, phoneme %02x %s\n",data >> 6,data & 0x3f,PhonemeTable[data & 0x3f]); + + queue[pos++] = data & 0x3f; + + if ((data & 0x3f) == 0x3f) + { +#if 0 + if (pos > 1) + { + int i; + char buf[200]; + + buf[0] = 0; + for (i = 0;i < pos-1;i++) + { + if (queue[i] == 0x03 || queue[i] == 0x3e) strcat(buf," "); + else strcat(buf,PhonemeTable[queue[i]]); + } + + popmessage(buf); + } +#endif + + pos = 0; + } + + /* generate a NMI after a while to make the CPU continue to send data */ + timer_set(ATTOTIME_IN_USEC(50),0,gottlieb_nmi_generate); +} + +WRITE8_HANDLER( gottlieb_speech_clock_DAC_w ) +{} + + + + /* partial decoding takes place to minimize chip count in a 6502+6532 + system, so both page 0 (direct page) and 1 (stack) access the same + 128-bytes ram, + either with the first 128 bytes of the page or the last 128 bytes */ + +UINT8 *riot_ram; + +READ8_HANDLER( riot_ram_r ) +{ + return riot_ram[offset&0x7f]; +} + +WRITE8_HANDLER( riot_ram_w ) +{ + riot_ram[offset&0x7f]=data; +} + +static UINT8 riot_regs[32]; + /* lazy handling of the 6532's I/O, and no handling of timers at all */ + +READ8_HANDLER( gottlieb_riot_r ) +{ + switch (offset&0x1f) { + case 0: /* port A */ + return soundlatch_r(offset) ^ 0xff; /* invert command */ + case 2: /* port B */ + return 0x40; /* say that PB6 is 1 (test SW1 not pressed) */ + case 5: /* interrupt register */ + return 0x40; /* say that edge detected on PA7 */ + default: + return riot_regs[offset&0x1f]; + } +} + +WRITE8_HANDLER( gottlieb_riot_w ) +{ + riot_regs[offset&0x1f]=data; +} + + + + +static UINT8 psg_latch; +static emu_timer *nmi_timer; +static int nmi_rate; +static int sp0250_drq; +static UINT8 sp0250_latch; + +static TIMER_CALLBACK( nmi_callback ); +void gottlieb_sound_init(void) +{ + nmi_timer = timer_alloc(nmi_callback); +} + +void stooges_sp0250_drq(int level) +{ + sp0250_drq = (level == ASSERT_LINE) ? 1 : 0; +} + +READ8_HANDLER( stooges_sound_input_r ) +{ + /* bits 0-3 are probably unused (future expansion) */ + + /* bits 4 & 5 are two dip switches. Unused? */ + + /* bit 6 is the test switch. When 0, the CPU plays a pulsing tone. */ + + /* bit 7 comes from the speech chip DATA REQUEST pin */ + + return 0x40 | (sp0250_drq << 7); +} + +WRITE8_HANDLER( stooges_8910_latch_w ) +{ + psg_latch = data; +} + +/* callback for the timer */ +static TIMER_CALLBACK( nmi_callback ) +{ + cpunum_set_input_line(cpu_gettotalcpu()-1, INPUT_LINE_NMI, PULSE_LINE); +} + +static WRITE8_HANDLER( common_sound_control_w ) +{ + /* Bit 0 enables and starts NMI timer */ + if (data & 0x01) + { + /* base clock is 250kHz divided by 256 */ + attotime interval = attotime_mul(ATTOTIME_IN_HZ(250000), 256 * (256-nmi_rate)); + timer_adjust(nmi_timer, interval, 0, interval); + } + else + timer_adjust(nmi_timer, attotime_never, 0, attotime_never); + + /* Bit 1 controls a LED on the sound board. I'm not emulating it */ +} + +WRITE8_HANDLER( stooges_sp0250_latch_w ) +{ + sp0250_latch = data; +} + +WRITE8_HANDLER( stooges_sound_control_w ) +{ + static int last; + + common_sound_control_w(offset, data); + + /* bit 2 goes to 8913 BDIR pin */ + if ((last & 0x04) == 0x04 && (data & 0x04) == 0x00) + { + /* bit 3 selects which of the two 8913 to enable */ + if (data & 0x08) + { + /* bit 4 goes to the 8913 BC1 pin */ + if (data & 0x10) + AY8910_control_port_0_w(0,psg_latch); + else + AY8910_write_port_0_w(0,psg_latch); + } + else + { + /* bit 4 goes to the 8913 BC1 pin */ + if (data & 0x10) + AY8910_control_port_1_w(0,psg_latch); + else + AY8910_write_port_1_w(0,psg_latch); + } + } + + /* bit 5 goes to the speech chip DIRECT DATA TEST pin */ + + /* bit 6 = speech chip DATA PRESENT pin; high then low to make the chip read data */ + if ((last & 0x40) == 0x40 && (data & 0x40) == 0x00) + { + sp0250_w(0,sp0250_latch); + } + + /* bit 7 goes to the speech chip RESET pin */ + + last = data & 0x44; +} + +WRITE8_HANDLER( gottlieb_nmi_rate_w ) +{ + nmi_rate = data; +} + +WRITE8_HANDLER( gottlieb_cause_dac_nmi_w ) +{ + cpunum_set_input_line(cpu_gettotalcpu()-2, INPUT_LINE_NMI, PULSE_LINE); +} |