diff options
Diffstat (limited to 'src/mame/machine/carpolo.c')
-rw-r--r-- | src/mame/machine/carpolo.c | 585 |
1 files changed, 585 insertions, 0 deletions
diff --git a/src/mame/machine/carpolo.c b/src/mame/machine/carpolo.c new file mode 100644 index 00000000000..6ebadeacd3e --- /dev/null +++ b/src/mame/machine/carpolo.c @@ -0,0 +1,585 @@ +/*************************************************************************** + + Exidy Car Polo hardware + + driver by Zsolt Vasvari + +****************************************************************************/ + +#include "driver.h" +#include "cpu/m6502/m6502.h" +#include "machine/6821pia.h" +#include "machine/7474.h" +#include "machine/74148.h" +#include "machine/74153.h" +#include "includes/carpolo.h" + + +/************************************* + * + * Interrupt system + * + *************************************/ + +/* the interrupt system consists of a 74148 priority encoder + with the following interrupt priorites. A lower number + indicates a lower priority (coins handled first): + + 7 - player 1 coin + 6 - player 2 coin + 5 - player 3 coin + 4 - player 4 coin + 3 - ball/screen object collision + 2 - car/car collision + 1 - car/goal collision + 0 - timer (bit 4=0, bit 6=0) + 0 - car/ball collision (bit 4=0, bit 6=1) + 0 - car/border (bit 4=1, bit 6=1) + + After the interrupt is serviced, the code clears the + priority encoder's appropriate line by pulling it HI. This + can trigger another interrupt immediately if there were + lower priority lines LO. + + The four coin inputs are latched via 7474 flip-flop's. */ + +#define COIN1_PRIORITY_LINE 7 +#define COIN2_PRIORITY_LINE 6 +#define COIN3_PRIORITY_LINE 5 +#define COIN4_PRIORITY_LINE 4 +#define BALL_SCREEN_PRIORITY_LINE 3 +#define CAR_CAR_PRIORITY_LINE 2 +#define CAR_GOAL_PRIORITY_LINE 1 +#define PRI0_PRIORTITY_LINE 0 + +/* priority 0 controls three different things */ +#define TIMER_EXTRA_BITS 0x00 +#define CAR_BALL_EXTRA_BITS 0x40 +#define CAR_BORDER_EXTRA_BITS 0x50 + + +#define TTL74148_3S 0 + +#define TTL74153_1K 0 + +#define TTL7474_2S_1 0 +#define TTL7474_2S_2 1 +#define TTL7474_2U_1 2 +#define TTL7474_2U_2 3 +#define TTL7474_1F_1 4 +#define TTL7474_1F_2 5 +#define TTL7474_1D_1 6 +#define TTL7474_1D_2 7 +#define TTL7474_1C_1 8 +#define TTL7474_1C_2 9 +#define TTL7474_1A_1 10 +#define TTL7474_1A_2 11 + + +static UINT8 ball_screen_collision_cause; +static UINT8 car_ball_collision_x; +static UINT8 car_ball_collision_y; +static UINT8 car_car_collision_cause; +static UINT8 car_goal_collision_cause; +static UINT8 car_ball_collision_cause; +static UINT8 car_border_collision_cause; +static UINT8 priority_0_extension; +static UINT8 last_wheel_value[4]; + + +static void TTL74148_3S_cb(void) +{ + cpunum_set_input_line(0, M6502_IRQ_LINE, TTL74148_output_valid_r(TTL74148_3S) ? CLEAR_LINE : ASSERT_LINE); +} + + +/* the outputs of the flip-flops are connected to the priority encoder */ +static void TTL7474_2S_1_cb(void) +{ + TTL74148_input_line_w(TTL74148_3S, COIN1_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2S_1)); + TTL74148_update(TTL74148_3S); +} + +static void TTL7474_2S_2_cb(void) +{ + TTL74148_input_line_w(TTL74148_3S, COIN2_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2S_2)); + TTL74148_update(TTL74148_3S); +} + +static void TTL7474_2U_1_cb(void) +{ + TTL74148_input_line_w(TTL74148_3S, COIN3_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2U_1)); + TTL74148_update(TTL74148_3S); +} + +static void TTL7474_2U_2_cb(void) +{ + TTL74148_input_line_w(TTL74148_3S, COIN4_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2U_2)); + TTL74148_update(TTL74148_3S); +} + + +void carpolo_generate_ball_screen_interrupt(UINT8 cause) +{ + ball_screen_collision_cause = cause; + + TTL74148_input_line_w(TTL74148_3S, BALL_SCREEN_PRIORITY_LINE, 0); + TTL74148_update(TTL74148_3S); +} + +void carpolo_generate_car_car_interrupt(int car1, int car2) +{ + car_car_collision_cause = ~((1 << (3 - car1)) | (1 << (3 - car2))); + + TTL74148_input_line_w(TTL74148_3S, CAR_CAR_PRIORITY_LINE, 0); + TTL74148_update(TTL74148_3S); +} + +void carpolo_generate_car_goal_interrupt(int car, int right_goal) +{ + car_goal_collision_cause = car | (right_goal ? 0x08 : 0x00); + + TTL74148_input_line_w(TTL74148_3S, CAR_GOAL_PRIORITY_LINE, 0); + TTL74148_update(TTL74148_3S); +} + +void carpolo_generate_car_ball_interrupt(int car, int car_x, int car_y) +{ + car_ball_collision_cause = car; + car_ball_collision_x = car_x; + car_ball_collision_y = car_y; + + priority_0_extension = CAR_BALL_EXTRA_BITS; + + TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 0); + TTL74148_update(TTL74148_3S); +} + +void carpolo_generate_car_border_interrupt(int car, int horizontal_border) +{ + car_border_collision_cause = car | (horizontal_border ? 0x04 : 0x00); + + priority_0_extension = CAR_BORDER_EXTRA_BITS; + + TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 0); + TTL74148_update(TTL74148_3S); +} + + +READ8_HANDLER( carpolo_ball_screen_collision_cause_r ) +{ + /* bit 0 - 0=ball collided with border + bit 1 - 0=ball collided with goal + bit 2 - 0=ball collided with score area + bit 3 - which goal/score collided (0=left, 1=right) */ + return ball_screen_collision_cause; +} + +READ8_HANDLER( carpolo_car_ball_collision_x_r ) +{ + /* the x coordinate of the colliding pixel */ + return car_ball_collision_x; +} + +READ8_HANDLER( carpolo_car_ball_collision_y_r ) +{ + /* the y coordinate of the colliding pixel */ + return car_ball_collision_y; +} + +READ8_HANDLER( carpolo_car_car_collision_cause_r ) +{ + /* bit 0 - car 4 collided + bit 1 - car 3 collided + bit 2 - car 2 collided + bit 3 - car 1 collided */ + return car_car_collision_cause; +} + +READ8_HANDLER( carpolo_car_goal_collision_cause_r ) +{ + /* bit 0-1 - which car collided + bit 2 - horizontal timing bit 1TEC4 (not accessed) + bit 3 - which goal collided (0=left, 1=right) */ + return car_goal_collision_cause; +} + +READ8_HANDLER( carpolo_car_ball_collision_cause_r ) +{ + /* bit 0-1 - which car collided + bit 2-3 - unconnected */ + return car_ball_collision_cause; +} + +READ8_HANDLER( carpolo_car_border_collision_cause_r ) +{ + /* bit 0-1 - which car collided + bit 2 - 0=vertical border, 1=horizontal border */ + return car_border_collision_cause; +} + + +READ8_HANDLER( carpolo_interrupt_cause_r ) +{ + /* the output of the 148 goes to bits 1-3 (which is priority ^ 7) */ + return (TTL74148_output_r(TTL74148_3S) << 1) | priority_0_extension; +} + + +INTERRUPT_GEN( carpolo_timer_interrupt ) +{ + UINT8 port_value; + int player; + + + /* cause the timer interrupt */ + TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 0); + priority_0_extension = TIMER_EXTRA_BITS; + + TTL74148_update(TTL74148_3S); + + + /* check the coins here as well - they drive the clock of the flip-flops */ + port_value = readinputport(0); + + TTL7474_clock_w(TTL7474_2S_1, port_value & 0x01); + TTL7474_clock_w(TTL7474_2S_2, port_value & 0x02); + TTL7474_clock_w(TTL7474_2U_1, port_value & 0x04); + TTL7474_clock_w(TTL7474_2U_2, port_value & 0x08); + + TTL7474_update(TTL7474_2S_1); + TTL7474_update(TTL7474_2S_2); + TTL7474_update(TTL7474_2U_1); + TTL7474_update(TTL7474_2U_2); + + + /* read the steering controls */ + for (player = 0; player < 4; player++) + { + int movement_flip_flop = TTL7474_1F_1 + (2 * player); + int dir_flip_flop = movement_flip_flop + 1; + + + port_value = readinputport(2 + player); + + if (port_value != last_wheel_value[player]) + { + /* set the movement direction */ + TTL7474_d_w(dir_flip_flop, ((port_value - last_wheel_value[player]) & 0x80) ? 1 : 0); + + last_wheel_value[player] = port_value; + } + + /* as the wheel moves, both flip-flops are clocked */ + TTL7474_clock_w(movement_flip_flop, port_value & 0x01); + TTL7474_clock_w(dir_flip_flop, port_value & 0x01); + + TTL7474_update(movement_flip_flop); + TTL7474_update(dir_flip_flop); + } + + + + /* finally read the accelerator pedals */ + port_value = readinputport(6); + + for (player = 0; player < 4; player++) + { + /* one line indicates if the pedal is pressed and the other + how much, resulting in only two different possible levels */ + if (port_value & 0x01) + { + TTL74153_input_line_w(TTL74153_1K, 0, player, 1); + TTL74153_input_line_w(TTL74153_1K, 1, player, 0); + } + else if (port_value & 0x02) + { + TTL74153_input_line_w(TTL74153_1K, 0, player, 1); + TTL74153_input_line_w(TTL74153_1K, 1, player, 1); + } + else + { + TTL74153_input_line_w(TTL74153_1K, 0, player, 0); + /* the other line is irrelevant */ + } + + port_value >>= 2; + } + + TTL74153_update(TTL74153_1K); +} + + +static WRITE8_HANDLER( coin1_interrupt_clear_w ) +{ + TTL7474_clear_w(TTL7474_2S_1, data); + TTL7474_update(TTL7474_2S_1); +} + +static WRITE8_HANDLER( coin2_interrupt_clear_w ) +{ + TTL7474_clear_w(TTL7474_2S_2, data); + TTL7474_update(TTL7474_2S_2); +} + +static WRITE8_HANDLER( coin3_interrupt_clear_w ) +{ + TTL7474_clear_w(TTL7474_2U_1, data); + TTL7474_update(TTL7474_2U_1); +} + +static WRITE8_HANDLER( coin4_interrupt_clear_w ) +{ + TTL7474_clear_w(TTL7474_2U_2, data); + TTL7474_update(TTL7474_2U_2); +} + +WRITE8_HANDLER( carpolo_ball_screen_interrupt_clear_w ) +{ + TTL74148_input_line_w(TTL74148_3S, BALL_SCREEN_PRIORITY_LINE, 1); + TTL74148_update(TTL74148_3S); +} + +WRITE8_HANDLER( carpolo_car_car_interrupt_clear_w ) +{ + TTL74148_input_line_w(TTL74148_3S, CAR_CAR_PRIORITY_LINE, 1); + TTL74148_update(TTL74148_3S); +} + +WRITE8_HANDLER( carpolo_car_goal_interrupt_clear_w ) +{ + TTL74148_input_line_w(TTL74148_3S, CAR_GOAL_PRIORITY_LINE, 1); + TTL74148_update(TTL74148_3S); +} + +WRITE8_HANDLER( carpolo_car_ball_interrupt_clear_w ) +{ + TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 1); + TTL74148_update(TTL74148_3S); +} + +WRITE8_HANDLER( carpolo_car_border_interrupt_clear_w ) +{ + TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 1); + TTL74148_update(TTL74148_3S); +} + +WRITE8_HANDLER( carpolo_timer_interrupt_clear_w ) +{ + TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 1); + TTL74148_update(TTL74148_3S); +} + + +/************************************* + * + * Input port handling + * + *************************************/ + +static WRITE8_HANDLER( pia_0_port_a_w ) +{ + /* bit 0 - Coin counter + bit 1 - Player 4 crash sound + bit 2 - Player 3 crash sound + bit 3 - Clear steering wheel logic + bit 4 - Player 2 crash sound + bit 5 - Score pulse sound + bit 6 - Player 1 crash sound + bit 7 - Ball hit pulse sound */ + + coin_counter_w(0, data & 0x01); + + + TTL7474_clear_w(TTL7474_1F_1, data & 0x08); + TTL7474_clear_w(TTL7474_1D_1, data & 0x08); + TTL7474_clear_w(TTL7474_1C_1, data & 0x08); + TTL7474_clear_w(TTL7474_1A_1, data & 0x08); + + TTL7474_update(TTL7474_1F_1); + TTL7474_update(TTL7474_1D_1); + TTL7474_update(TTL7474_1C_1); + TTL7474_update(TTL7474_1A_1); +} + + +static WRITE8_HANDLER( pia_0_port_b_w ) +{ + /* bit 0 - Strobe speed bits sound + bit 1 - Speed bit 0 sound + bit 2 - Speed bit 1 sound + bit 3 - Speed bit 2 sound + bit 6 - Select pedal 0 + bit 7 - Select pdeal 1 */ + + TTL74153_a_w(TTL74153_1K, data & 0x40); + TTL74153_b_w(TTL74153_1K, data & 0x80); + + TTL74153_update(TTL74153_1K); +} + +static READ8_HANDLER( pia_0_port_b_r ) +{ + /* bit 4 - Pedal bit 0 + bit 5 - Pedal bit 1 */ + + return (TTL74153_output_r(TTL74153_1K, 0) << 5) | + (TTL74153_output_r(TTL74153_1K, 1) << 4); +} + + +static READ8_HANDLER( pia_1_port_a_r ) +{ + UINT8 ret; + + /* bit 0 - Player 4 steering input (left or right) + bit 1 - Player 3 steering input (left or right) + bit 2 - Player 2 steering input (left or right) + bit 3 - Player 1 steering input (left or right) + bit 4 - Player 4 forward/reverse input + bit 5 - Player 3 forward/reverse input + bit 6 - Player 2 forward/reverse input + bit 7 - Player 1 forward/reverse input */ + + ret = (TTL7474_output_r(TTL7474_1A_2) ? 0x01 : 0x00) | + (TTL7474_output_r(TTL7474_1C_2) ? 0x02 : 0x00) | + (TTL7474_output_r(TTL7474_1D_2) ? 0x04 : 0x00) | + (TTL7474_output_r(TTL7474_1F_2) ? 0x08 : 0x00) | + (readinputport(7) & 0xf0); + + return ret; +} + + +static READ8_HANDLER( pia_1_port_b_r ) +{ + UINT8 ret; + + /* bit 4 - Player 4 steering input (wheel moving or stopped) + bit 5 - Player 3 steering input (wheel moving or stopped) + bit 6 - Player 2 steering input (wheel moving or stopped) + bit 7 - Player 1 steering input (wheel moving or stopped) */ + + ret = (TTL7474_output_r(TTL7474_1A_1) ? 0x10 : 0x00) | + (TTL7474_output_r(TTL7474_1C_1) ? 0x20 : 0x00) | + (TTL7474_output_r(TTL7474_1D_1) ? 0x40 : 0x00) | + (TTL7474_output_r(TTL7474_1F_1) ? 0x80 : 0x00); + + return ret; +} + + +static const pia6821_interface pia_0_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ 0, pia_0_port_b_r, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ pia_0_port_a_w, pia_0_port_b_w, coin1_interrupt_clear_w, coin2_interrupt_clear_w, + /*irqs : A/B */ 0, 0 +}; + +static const pia6821_interface pia_1_intf = +{ + /*inputs : A/B,CA/B1,CA/B2 */ pia_1_port_a_r, pia_1_port_b_r, 0, 0, 0, 0, + /*outputs: A/B,CA/B2 */ 0, 0, coin3_interrupt_clear_w, coin4_interrupt_clear_w, + /*irqs : A/B */ 0, 0 +}; + +static struct TTL74148_interface TTL74148_3S_intf = +{ + TTL74148_3S_cb +}; + +static struct TTL7474_interface TTL7474_2S_1_intf = +{ + TTL7474_2S_1_cb +}; + +static struct TTL7474_interface TTL7474_2S_2_intf = +{ + TTL7474_2S_2_cb +}; + +static struct TTL7474_interface TTL7474_2U_1_intf = +{ + TTL7474_2U_1_cb +}; + +static struct TTL7474_interface TTL7474_2U_2_intf = +{ + TTL7474_2U_2_cb +}; + + +MACHINE_START( carpolo ) +{ + /* set up the PIA's */ + pia_config(0, &pia_0_intf); + pia_config(1, &pia_1_intf); +} + +MACHINE_RESET( carpolo ) +{ + /* set up the priority encoder */ + TTL74148_config(TTL74148_3S, &TTL74148_3S_intf); + TTL74148_enable_input_w(TTL74148_3S, 0); /* always enabled */ + + + /* set up the coin handling flip-flops */ + TTL7474_config(TTL7474_2S_1, &TTL7474_2S_1_intf); + TTL7474_config(TTL7474_2S_2, &TTL7474_2S_2_intf); + TTL7474_config(TTL7474_2U_1, &TTL7474_2U_1_intf); + TTL7474_config(TTL7474_2U_2, &TTL7474_2U_2_intf); + + TTL7474_d_w (TTL7474_2S_1, 1); + TTL7474_preset_w(TTL7474_2S_1, 1); + + TTL7474_d_w (TTL7474_2S_2, 1); + TTL7474_preset_w(TTL7474_2S_2, 1); + + TTL7474_d_w (TTL7474_2U_1, 1); + TTL7474_preset_w(TTL7474_2U_1, 1); + + TTL7474_d_w (TTL7474_2U_2, 1); + TTL7474_preset_w(TTL7474_2U_2, 1); + + + /* set up the steering handling flip-flops */ + TTL7474_config(TTL7474_1F_1, 0); + TTL7474_config(TTL7474_1F_2, 0); + TTL7474_config(TTL7474_1D_1, 0); + TTL7474_config(TTL7474_1D_2, 0); + TTL7474_config(TTL7474_1C_1, 0); + TTL7474_config(TTL7474_1C_2, 0); + TTL7474_config(TTL7474_1A_1, 0); + TTL7474_config(TTL7474_1A_2, 0); + + TTL7474_d_w (TTL7474_1F_1, 1); + TTL7474_preset_w(TTL7474_1F_1, 1); + + TTL7474_clear_w (TTL7474_1F_2, 1); + TTL7474_preset_w(TTL7474_1F_2, 1); + + TTL7474_d_w (TTL7474_1D_1, 1); + TTL7474_preset_w(TTL7474_1D_1, 1); + + TTL7474_clear_w (TTL7474_1D_2, 1); + TTL7474_preset_w(TTL7474_1D_2, 1); + + TTL7474_d_w (TTL7474_1C_1, 1); + TTL7474_preset_w(TTL7474_1C_1, 1); + + TTL7474_clear_w (TTL7474_1C_2, 1); + TTL7474_preset_w(TTL7474_1C_2, 1); + + TTL7474_d_w (TTL7474_1A_1, 1); + TTL7474_preset_w(TTL7474_1A_1, 1); + + TTL7474_clear_w (TTL7474_1A_2, 1); + TTL7474_preset_w(TTL7474_1A_2, 1); + + + /* set up the pedal handling chips */ + TTL74153_config(TTL74153_1K, 0); + + TTL74153_enable_w(TTL74153_1K, 0, 0); + TTL74153_enable_w(TTL74153_1K, 1, 0); +} |