diff options
Diffstat (limited to 'src/mame/machine/qix.c')
-rw-r--r-- | src/mame/machine/qix.c | 605 |
1 files changed, 605 insertions, 0 deletions
diff --git a/src/mame/machine/qix.c b/src/mame/machine/qix.c new file mode 100644 index 00000000000..aa1e93ff630 --- /dev/null +++ b/src/mame/machine/qix.c @@ -0,0 +1,605 @@ +/*************************************************************************** + + Taito Qix hardware + + driver by John Butler, Ed Mueller, Aaron Giles + +***************************************************************************/ + +#include "driver.h" +#include "qix.h" +#include "machine/6821pia.h" +#include "cpu/m6800/m6800.h" +#include "cpu/m6805/m6805.h" +#include "cpu/m6809/m6809.h" +#include "sound/sn76496.h" + + +/* Globals */ +UINT8 *qix_68705_port_out; +UINT8 *qix_68705_ddr; + + +/* Local variables */ +static UINT8 qix_68705_port_in[3]; +static UINT8 qix_coinctrl; + + +/* Prototypes */ +static READ8_HANDLER( qixmcu_coin_r ); +static WRITE8_HANDLER( qixmcu_coinctrl_w ); +static WRITE8_HANDLER( qixmcu_coin_w ); + +static WRITE8_HANDLER( sync_pia_4_porta_w ); + +static WRITE8_HANDLER( pia_5_warning_w ); + +static WRITE8_HANDLER( qix_inv_flag_w ); + +static WRITE8_HANDLER( qix_coinctl_w ); +static WRITE8_HANDLER( slither_coinctl_w ); + +static void qix_pia_sint(int state); +static void qix_pia_dint(int state); + +static WRITE8_HANDLER( slither_76489_0_w ); +static WRITE8_HANDLER( slither_76489_1_w ); + +static READ8_HANDLER( slither_trak_lr_r ); +static READ8_HANDLER( slither_trak_ud_r ); + + + +/*************************************************************************** + + Qix has 6 PIAs on board: + + From the ROM I/O schematic: + + PIA 0 = U11: (mapped to $9400 on the data CPU) + port A = external input (input_port_0) + port B = external input (input_port_1) (coin) + + PIA 1 = U20: (mapped to $9800/$9900 on the data CPU) + port A = external input (input_port_2) + port B = external input (input_port_3) + + PIA 2 = U30: (mapped to $9c00 on the data CPU) + port A = external input (input_port_4) + port B = external output (coin control) + + + From the data/sound processor schematic: + + PIA 3 = U20: (mapped to $9000 on the data CPU) + port A = data CPU to sound CPU communication + port B = stereo volume control, 2 4-bit values + CA1 = interrupt signal from sound CPU + CA2 = interrupt signal to sound CPU + CB1 = VS input signal (vertical sync) + CB2 = INV output signal (cocktail flip) + IRQA = /DINT1 signal + IRQB = /DINT1 signal + + PIA 4 = U8: (mapped to $4000 on the sound CPU) + port A = sound CPU to data CPU communication + port B = DAC value (port B) + CA1 = interrupt signal from data CPU + CA2 = interrupt signal to data CPU + IRQA = /SINT1 signal + IRQB = /SINT1 signal + + PIA 5 = U7: (never actually used, mapped to $2000 on the sound CPU) + port A = unused + port B = sound CPU to TMS5220 communication + CA1 = interrupt signal from TMS5220 + CA2 = write signal to TMS5220 + CB1 = ready signal from TMS5220 + CB2 = read signal to TMS5220 + IRQA = /SINT2 signal + IRQB = /SINT2 signal + +***************************************************************************/ + +static const pia6821_interface qix_pia_0_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, input_port_1_r, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ 0, 0, 0, 0, + /*irqs : A/B */ 0, 0 +}; + +static const pia6821_interface qix_pia_1_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, input_port_3_r, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ 0, 0, 0, 0, + /*irqs : A/B */ 0, 0 +}; + +static const pia6821_interface qix_pia_2_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ input_port_4_r, 0, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ 0, qix_coinctl_w, 0, 0, + /*irqs : A/B */ 0, 0 +}; + +static const pia6821_interface qix_pia_3_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ sync_pia_4_porta_w, qix_vol_w, pia_4_ca1_w, qix_inv_flag_w, + /*irqs : A/B */ qix_pia_dint, qix_pia_dint +}; + +static const pia6821_interface qix_pia_4_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ pia_3_porta_w, qix_dac_w, pia_3_ca1_w, 0, + /*irqs : A/B */ qix_pia_sint, qix_pia_sint +}; + +static const pia6821_interface qix_pia_5_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ pia_5_warning_w, pia_5_warning_w, pia_5_warning_w, pia_5_warning_w, + /*irqs : A/B */ 0, 0 +}; + + +static WRITE8_HANDLER( pia_5_warning_w ) +{ + popmessage("PIA 5 write!!"); +} + + +/*************************************************************************** + + Games with an MCU need to handle coins differently, and provide + communication with the MCU + +***************************************************************************/ + +static const pia6821_interface qixmcu_pia_0_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, qixmcu_coin_r, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ 0, qixmcu_coin_w, 0, 0, + /*irqs : A/B */ 0, 0 +}; + +static const pia6821_interface qixmcu_pia_2_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ input_port_4_r, 0, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ 0, qixmcu_coinctrl_w, 0, 0, + /*irqs : A/B */ 0, 0 +}; + + + +/*************************************************************************** + + Slither uses 2 SN76489's for sound instead of the 6802+DAC; these + are accessed via the PIAs. + +***************************************************************************/ + +static const pia6821_interface slither_pia_1_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ slither_trak_lr_r, 0, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ 0, slither_76489_0_w, 0, 0, + /*irqs : A/B */ 0, 0 +}; + +static const pia6821_interface slither_pia_2_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ slither_trak_ud_r, 0, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ 0, slither_76489_1_w, 0, 0, + /*irqs : A/B */ 0, 0 +}; + +static const pia6821_interface slither_pia_3_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ 0, slither_coinctl_w, 0, qix_inv_flag_w, + /*irqs : A/B */ qix_pia_dint, qix_pia_dint +}; + + + +/************************************* + * + * Machine initialization + * + *************************************/ + +MACHINE_START( qix ) +{ + /* configure the PIAs */ + pia_config(0, &qix_pia_0_intf); + pia_config(1, &qix_pia_1_intf); + pia_config(2, &qix_pia_2_intf); + pia_config(3, &qix_pia_3_intf); + pia_config(4, &qix_pia_4_intf); + pia_config(5, &qix_pia_5_intf); +} + +MACHINE_RESET( qix ) +{ + /* reset the PIAs */ + pia_reset(); + + /* reset the coin counter register */ + qix_coinctrl = 0x00; +} + + +MACHINE_START( qixmcu ) +{ + /* configure the PIAs */ + pia_config(0, &qixmcu_pia_0_intf); + pia_config(1, &qix_pia_1_intf); + pia_config(2, &qixmcu_pia_2_intf); + pia_config(3, &qix_pia_3_intf); + pia_config(4, &qix_pia_4_intf); + pia_config(5, &qix_pia_5_intf); + + /* set up save states */ + state_save_register_global_array(qix_68705_port_in); + state_save_register_global(qix_coinctrl); +} + +MACHINE_START( slither ) +{ + /* configure the PIAs */ + pia_config(0, &qix_pia_0_intf); + pia_config(1, &slither_pia_1_intf); + pia_config(2, &slither_pia_2_intf); + pia_config(3, &slither_pia_3_intf); +} + + + +/************************************* + * + * VSYNC interrupt handling + * + *************************************/ + +static TIMER_CALLBACK( vblank_stop ) +{ + pia_3_cb1_w(0, 0); +} + + +INTERRUPT_GEN( qix_vblank_start ) +{ + pia_3_cb1_w(0, 1); + timer_set(video_screen_get_time_until_pos(0, 0, 0), 0, vblank_stop); +} + + + +/************************************* + * + * Zoo Keeper bankswitching + * + *************************************/ + +WRITE8_HANDLER( zoo_bankswitch_w ) +{ + memory_set_bank(1, (data >> 2) & 1); + /* not necessary, but technically correct */ + qix_palettebank_w(offset,data); +} + + + +/************************************* + * + * Data CPU FIRQ generation/ack + * + *************************************/ + +WRITE8_HANDLER( qix_data_firq_w ) +{ + cpunum_set_input_line(0, M6809_FIRQ_LINE, ASSERT_LINE); +} + + +WRITE8_HANDLER( qix_data_firq_ack_w ) +{ + cpunum_set_input_line(0, M6809_FIRQ_LINE, CLEAR_LINE); +} + + +READ8_HANDLER( qix_data_firq_r ) +{ + cpunum_set_input_line(0, M6809_FIRQ_LINE, ASSERT_LINE); + return 0xff; +} + + +READ8_HANDLER( qix_data_firq_ack_r ) +{ + cpunum_set_input_line(0, M6809_FIRQ_LINE, CLEAR_LINE); + return 0xff; +} + + + +/************************************* + * + * Video CPU FIRQ generation/ack + * + *************************************/ + +WRITE8_HANDLER( qix_video_firq_w ) +{ + cpunum_set_input_line(1, M6809_FIRQ_LINE, ASSERT_LINE); +} + + +WRITE8_HANDLER( qix_video_firq_ack_w ) +{ + cpunum_set_input_line(1, M6809_FIRQ_LINE, CLEAR_LINE); +} + + +READ8_HANDLER( qix_video_firq_r ) +{ + cpunum_set_input_line(1, M6809_FIRQ_LINE, ASSERT_LINE); + return 0xff; +} + + +READ8_HANDLER( qix_video_firq_ack_r ) +{ + cpunum_set_input_line(1, M6809_FIRQ_LINE, CLEAR_LINE); + return 0xff; +} + + + +/************************************* + * + * Sound PIA interfaces + * + *************************************/ + +static TIMER_CALLBACK( deferred_pia_4_porta_w ) +{ + pia_4_porta_w(0, param); +} + + +static WRITE8_HANDLER( sync_pia_4_porta_w ) +{ + /* we need to synchronize this so the sound CPU doesn't drop anything important */ + timer_call_after_resynch(data, deferred_pia_4_porta_w); +} + + + +/************************************* + * + * IRQ generation + * + *************************************/ + +static void qix_pia_dint(int state) +{ + /* DINT is connected to the data CPU's IRQ line */ + cpunum_set_input_line(0, M6809_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE); +} + + +static void qix_pia_sint(int state) +{ + /* SINT is connected to the sound CPU's IRQ line */ + cpunum_set_input_line(2, M6802_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE); +} + + + +/************************************* + * + * 68705 Communication + * + *************************************/ + +READ8_HANDLER( qixmcu_coin_r ) +{ + logerror("6809:qixmcu_coin_r = %02X\n", qix_68705_port_out[0]); + return qix_68705_port_out[0]; +} + + +static WRITE8_HANDLER( qixmcu_coin_w ) +{ + logerror("6809:qixmcu_coin_w = %02X\n", data); + /* this is a callback called by pia_0_w(), so I don't need to synchronize */ + /* the CPUs - they have already been synchronized by qix_pia_0_w() */ + qix_68705_port_in[0] = data; +} + + +static WRITE8_HANDLER( qixmcu_coinctrl_w ) +{ + if (!(data & 0x04)) + { + cpunum_set_input_line(3, M68705_IRQ_LINE, ASSERT_LINE); + /* temporarily boost the interleave to sync things up */ + /* note: I'm using 50 because 30 is not enough for space dungeon at game over */ + cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(50)); + } + else + cpunum_set_input_line(3, M68705_IRQ_LINE, CLEAR_LINE); + + /* this is a callback called by pia_0_w(), so I don't need to synchronize */ + /* the CPUs - they have already been synchronized by qix_pia_0_w() */ + qix_coinctrl = data; + logerror("6809:qixmcu_coinctrl_w = %02X\n", data); +} + + + +/************************************* + * + * 68705 Port Inputs + * + *************************************/ + +READ8_HANDLER( qix_68705_portA_r ) +{ + UINT8 ddr = qix_68705_ddr[0]; + UINT8 out = qix_68705_port_out[0]; + UINT8 in = qix_68705_port_in[0]; + logerror("68705:portA_r = %02X (%02X)\n", (out & ddr) | (in & ~ddr), in); + return (out & ddr) | (in & ~ddr); +} + + +READ8_HANDLER( qix_68705_portB_r ) +{ + UINT8 ddr = qix_68705_ddr[1]; + UINT8 out = qix_68705_port_out[1]; + UINT8 in = (readinputport(1) & 0x0f) | ((readinputport(1) & 0x80) >> 3); + return (out & ddr) | (in & ~ddr); +} + + +READ8_HANDLER( qix_68705_portC_r ) +{ + UINT8 ddr = qix_68705_ddr[2]; + UINT8 out = qix_68705_port_out[2]; + UINT8 in = (qix_coinctrl & 0x08) | ((readinputport(1) & 0x70) >> 4); + return (out & ddr) | (in & ~ddr); +} + + + +/************************************* + * + * 68705 Port Outputs + * + *************************************/ + +WRITE8_HANDLER( qix_68705_portA_w ) +{ + logerror("68705:portA_w = %02X\n", data); + qix_68705_port_out[0] = data; +} + + +WRITE8_HANDLER( qix_68705_portB_w ) +{ + qix_68705_port_out[1] = data; + coin_lockout_w(0, (~data >> 6) & 1); + coin_counter_w(0, (data >> 7) & 1); +} + + +WRITE8_HANDLER( qix_68705_portC_w ) +{ + qix_68705_port_out[2] = data; +} + + + +/************************************* + * + * Data CPU PIA 0 synchronization + * + *************************************/ + +static TIMER_CALLBACK( pia_0_w_callback ) +{ + pia_0_w(param >> 8, param & 0xff); +} + + +WRITE8_HANDLER( qix_pia_0_w ) +{ + /* make all the CPUs synchronize, and only AFTER that write the command to the PIA */ + /* otherwise the 68705 will miss commands */ + timer_call_after_resynch(data | (offset << 8), pia_0_w_callback); +} + + + +/************************************* + * + * Cocktail flip + * + *************************************/ + +static WRITE8_HANDLER( qix_inv_flag_w ) +{ + qix_cocktail_flip = data; +} + + + +/************************************* + * + * Coin I/O for games without coin CPU + * + *************************************/ + +static WRITE8_HANDLER( qix_coinctl_w ) +{ + coin_lockout_w(0, (~data >> 2) & 1); + coin_counter_w(0, (data >> 1) & 1); +} + + +static WRITE8_HANDLER( slither_coinctl_w ) +{ + coin_lockout_w(0, (~data >> 6) & 1); + coin_counter_w(0, (data >> 5) & 1); +} + + + +/************************************* + * + * Slither SN76489 I/O + * + *************************************/ + +static WRITE8_HANDLER( slither_76489_0_w ) +{ + /* write to the sound chip */ + SN76496_0_w(0, data); + + /* clock the ready line going back into CB1 */ + pia_1_cb1_w(0, 0); + pia_1_cb1_w(0, 1); +} + + +static WRITE8_HANDLER( slither_76489_1_w ) +{ + /* write to the sound chip */ + SN76496_1_w(0, data); + + /* clock the ready line going back into CB1 */ + pia_2_cb1_w(0, 0); + pia_2_cb1_w(0, 1); +} + + + +/************************************* + * + * Slither trackball I/O + * + *************************************/ + +static READ8_HANDLER( slither_trak_lr_r ) +{ + return readinputport(qix_cocktail_flip ? 6 : 4); +} + + +static READ8_HANDLER( slither_trak_ud_r ) +{ + return readinputport(qix_cocktail_flip ? 5 : 3); +} |