summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/carpolo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/carpolo.c')
-rw-r--r--src/mame/machine/carpolo.c585
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);
+}