1 /***************************************************************************
2
3 Exidy Car Polo hardware
4
5 driver by Zsolt Vasvari
6
7 ****************************************************************************/
8
9 #include "driver.h"
10 #include "cpu/m6502/m6502.h"
11 #include "machine/6821pia.h"
12 #include "machine/7474.h"
13 #include "machine/74148.h"
14 #include "machine/74153.h"
15
16
17 /*************************************
18 *
19 * Interrupt system
20 *
21 *************************************/
22
23 /* the interrupt system consists of a 74148 priority encoder
24 with the following interrupt priorites. A lower number
25 indicates a lower priority (coins handled first):
26
27 7 - player 1 coin
28 6 - player 2 coin
29 5 - player 3 coin
30 4 - player 4 coin
31 3 - ball/screen object collision
32 2 - car/car collision
33 1 - car/goal collision
34 0 - timer (bit 4=0, bit 6=0)
35 0 - car/ball collision (bit 4=0, bit 6=1)
36 0 - car/border (bit 4=1, bit 6=1)
37
38 After the interrupt is serviced, the code clears the
39 priority encoder's appropriate line by pulling it HI. This
40 can trigger another interrupt immediately if there were
41 lower priority lines LO.
42
43 The four coin inputs are latched via 7474 flip-flop's. */
44
45 #define COIN1_PRIORITY_LINE 7
46 #define COIN2_PRIORITY_LINE 6
47 #define COIN3_PRIORITY_LINE 5
48 #define COIN4_PRIORITY_LINE 4
49 #define BALL_SCREEN_PRIORITY_LINE 3
50 #define CAR_CAR_PRIORITY_LINE 2
51 #define CAR_GOAL_PRIORITY_LINE 1
52 #define PRI0_PRIORTITY_LINE 0
53
54 /* priority 0 controls three different things */
55 #define TIMER_EXTRA_BITS 0x00
56 #define CAR_BALL_EXTRA_BITS 0x40
57 #define CAR_BORDER_EXTRA_BITS 0x50
58
59
60 #define TTL74148_3S 0
61
62 #define TTL74153_1K 0
63
64 #define TTL7474_2S_1 0
65 #define TTL7474_2S_2 1
66 #define TTL7474_2U_1 2
67 #define TTL7474_2U_2 3
68 #define TTL7474_1F_1 4
69 #define TTL7474_1F_2 5
70 #define TTL7474_1D_1 6
71 #define TTL7474_1D_2 7
72 #define TTL7474_1C_1 8
73 #define TTL7474_1C_2 9
74 #define TTL7474_1A_1 10
75 #define TTL7474_1A_2 11
76
77
78 static data8_t ball_screen_collision_cause;
79 static data8_t car_ball_collision_x;
80 static data8_t car_ball_collision_y;
81 static data8_t car_car_collision_cause;
82 static data8_t car_goal_collision_cause;
83 static data8_t car_ball_collision_cause;
84 static data8_t car_border_collision_cause;
85 static data8_t priority_0_extension;
86 static data8_t last_wheel_value[4];
87
88
TTL74148_3S_cb(void)89 static void TTL74148_3S_cb(void)
90 {
91 cpu_set_irq_line(0, M6502_IRQ_LINE, TTL74148_output_valid_r(TTL74148_3S) ? CLEAR_LINE : ASSERT_LINE);
92 }
93
94
95 /* the outputs of the flip-flops are connected to the priority encoder */
TTL7474_2S_1_cb(void)96 static void TTL7474_2S_1_cb(void)
97 {
98 TTL74148_input_line_w(TTL74148_3S, COIN1_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2S_1));
99 TTL74148_update(TTL74148_3S);
100 }
101
TTL7474_2S_2_cb(void)102 static void TTL7474_2S_2_cb(void)
103 {
104 TTL74148_input_line_w(TTL74148_3S, COIN2_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2S_2));
105 TTL74148_update(TTL74148_3S);
106 }
107
TTL7474_2U_1_cb(void)108 static void TTL7474_2U_1_cb(void)
109 {
110 TTL74148_input_line_w(TTL74148_3S, COIN3_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2U_1));
111 TTL74148_update(TTL74148_3S);
112 }
113
TTL7474_2U_2_cb(void)114 static void TTL7474_2U_2_cb(void)
115 {
116 TTL74148_input_line_w(TTL74148_3S, COIN4_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2U_2));
117 TTL74148_update(TTL74148_3S);
118 }
119
120
carpolo_generate_ball_screen_interrupt(data8_t cause)121 void carpolo_generate_ball_screen_interrupt(data8_t cause)
122 {
123 ball_screen_collision_cause = cause;
124
125 TTL74148_input_line_w(TTL74148_3S, BALL_SCREEN_PRIORITY_LINE, 0);
126 TTL74148_update(TTL74148_3S);
127 }
128
carpolo_generate_car_car_interrupt(int car1,int car2)129 void carpolo_generate_car_car_interrupt(int car1, int car2)
130 {
131 car_car_collision_cause = ~((1 << (3 - car1)) | (1 << (3 - car2)));
132
133 TTL74148_input_line_w(TTL74148_3S, CAR_CAR_PRIORITY_LINE, 0);
134 TTL74148_update(TTL74148_3S);
135 }
136
carpolo_generate_car_goal_interrupt(int car,int right_goal)137 void carpolo_generate_car_goal_interrupt(int car, int right_goal)
138 {
139 car_goal_collision_cause = car | (right_goal ? 0x08 : 0x00);
140
141 TTL74148_input_line_w(TTL74148_3S, CAR_GOAL_PRIORITY_LINE, 0);
142 TTL74148_update(TTL74148_3S);
143 }
144
carpolo_generate_car_ball_interrupt(int car,int car_x,int car_y)145 void carpolo_generate_car_ball_interrupt(int car, int car_x, int car_y)
146 {
147 car_ball_collision_cause = car;
148 car_ball_collision_x = car_x;
149 car_ball_collision_y = car_y;
150
151 priority_0_extension = CAR_BALL_EXTRA_BITS;
152
153 TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 0);
154 TTL74148_update(TTL74148_3S);
155 }
156
carpolo_generate_car_border_interrupt(int car,int horizontal_border)157 void carpolo_generate_car_border_interrupt(int car, int horizontal_border)
158 {
159 car_border_collision_cause = car | (horizontal_border ? 0x04 : 0x00);
160
161 priority_0_extension = CAR_BORDER_EXTRA_BITS;
162
163 TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 0);
164 TTL74148_update(TTL74148_3S);
165 }
166
167
READ_HANDLER(carpolo_ball_screen_collision_cause_r)168 READ_HANDLER( carpolo_ball_screen_collision_cause_r )
169 {
170 /* bit 0 - 0=ball collided with border
171 bit 1 - 0=ball collided with goal
172 bit 2 - 0=ball collided with score area
173 bit 3 - which goal/score collided (0=left, 1=right) */
174 return ball_screen_collision_cause;
175 }
176
READ_HANDLER(carpolo_car_ball_collision_x_r)177 READ_HANDLER( carpolo_car_ball_collision_x_r )
178 {
179 /* the x coordinate of the colliding pixel */
180 return car_ball_collision_x;
181 }
182
READ_HANDLER(carpolo_car_ball_collision_y_r)183 READ_HANDLER( carpolo_car_ball_collision_y_r )
184 {
185 /* the y coordinate of the colliding pixel */
186 return car_ball_collision_y;
187 }
188
READ_HANDLER(carpolo_car_car_collision_cause_r)189 READ_HANDLER( carpolo_car_car_collision_cause_r )
190 {
191 /* bit 0 - car 4 collided
192 bit 1 - car 3 collided
193 bit 2 - car 2 collided
194 bit 3 - car 1 collided */
195 return car_car_collision_cause;
196 }
197
READ_HANDLER(carpolo_car_goal_collision_cause_r)198 READ_HANDLER( carpolo_car_goal_collision_cause_r )
199 {
200 /* bit 0-1 - which car collided
201 bit 2 - horizontal timing bit 1TEC4 (not accessed)
202 bit 3 - which goal collided (0=left, 1=right) */
203 return car_goal_collision_cause;
204 }
205
READ_HANDLER(carpolo_car_ball_collision_cause_r)206 READ_HANDLER( carpolo_car_ball_collision_cause_r )
207 {
208 /* bit 0-1 - which car collided
209 bit 2-3 - unconnected */
210 return car_ball_collision_cause;
211 }
212
READ_HANDLER(carpolo_car_border_collision_cause_r)213 READ_HANDLER( carpolo_car_border_collision_cause_r )
214 {
215 /* bit 0-1 - which car collided
216 bit 2 - 0=vertical border, 1=horizontal border */
217 return car_border_collision_cause;
218 }
219
220
READ_HANDLER(carpolo_interrupt_cause_r)221 READ_HANDLER( carpolo_interrupt_cause_r )
222 {
223 /* the output of the 148 goes to bits 1-3 (which is priority ^ 7) */
224 return (TTL74148_output_r(TTL74148_3S) << 1) | priority_0_extension;
225 }
226
227
INTERRUPT_GEN(carpolo_timer_interrupt)228 INTERRUPT_GEN( carpolo_timer_interrupt )
229 {
230 data8_t port_value;
231 int player;
232
233
234 /* cause the timer interrupt */
235 TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 0);
236 priority_0_extension = TIMER_EXTRA_BITS;
237
238 TTL74148_update(TTL74148_3S);
239
240
241 /* check the coins here as well - they drive the clock of the flip-flops */
242 port_value = readinputport(0);
243
244 TTL7474_clock_w(TTL7474_2S_1, port_value & 0x01);
245 TTL7474_clock_w(TTL7474_2S_2, port_value & 0x02);
246 TTL7474_clock_w(TTL7474_2U_1, port_value & 0x04);
247 TTL7474_clock_w(TTL7474_2U_2, port_value & 0x08);
248
249 TTL7474_update(TTL7474_2S_1);
250 TTL7474_update(TTL7474_2S_2);
251 TTL7474_update(TTL7474_2U_1);
252 TTL7474_update(TTL7474_2U_2);
253
254
255 /* read the steering controls */
256 for (player = 0; player < 4; player++)
257 {
258 int movement_flip_flop = TTL7474_1F_1 + (2 * player);
259 int dir_flip_flop = movement_flip_flop + 1;
260
261
262 port_value = readinputport(2 + player);
263
264 if (port_value != last_wheel_value[player])
265 {
266 /* set the movement direction */
267 TTL7474_d_w(dir_flip_flop, ((port_value - last_wheel_value[player]) & 0x80) ? 1 : 0);
268
269 last_wheel_value[player] = port_value;
270 }
271
272 /* as the wheel moves, both flip-flops are clocked */
273 TTL7474_clock_w(movement_flip_flop, port_value & 0x01);
274 TTL7474_clock_w(dir_flip_flop, port_value & 0x01);
275
276 TTL7474_update(movement_flip_flop);
277 TTL7474_update(dir_flip_flop);
278 }
279
280
281
282 /* finally read the accelerator pedals */
283 port_value = readinputport(6);
284
285 for (player = 0; player < 4; player++)
286 {
287 /* one line indicates if the pedal is pressed and the other
288 how much, resulting in only two different possible levels */
289 if (port_value & 0x01)
290 {
291 TTL74153_input_line_w(TTL74153_1K, 0, player, 1);
292 TTL74153_input_line_w(TTL74153_1K, 1, player, 0);
293 }
294 else if (port_value & 0x02)
295 {
296 TTL74153_input_line_w(TTL74153_1K, 0, player, 1);
297 TTL74153_input_line_w(TTL74153_1K, 1, player, 1);
298 }
299 else
300 {
301 TTL74153_input_line_w(TTL74153_1K, 0, player, 0);
302 /* the other line is irrelevant */
303 }
304
305 port_value >>= 2;
306 }
307
308 TTL74153_update(TTL74153_1K);
309 }
310
311
WRITE_HANDLER(coin1_interrupt_clear_w)312 static WRITE_HANDLER( coin1_interrupt_clear_w )
313 {
314 TTL7474_clear_w(TTL7474_2S_1, data);
315 TTL7474_update(TTL7474_2S_1);
316 }
317
WRITE_HANDLER(coin2_interrupt_clear_w)318 static WRITE_HANDLER( coin2_interrupt_clear_w )
319 {
320 TTL7474_clear_w(TTL7474_2S_2, data);
321 TTL7474_update(TTL7474_2S_2);
322 }
323
WRITE_HANDLER(coin3_interrupt_clear_w)324 static WRITE_HANDLER( coin3_interrupt_clear_w )
325 {
326 TTL7474_clear_w(TTL7474_2U_1, data);
327 TTL7474_update(TTL7474_2U_1);
328 }
329
WRITE_HANDLER(coin4_interrupt_clear_w)330 static WRITE_HANDLER( coin4_interrupt_clear_w )
331 {
332 TTL7474_clear_w(TTL7474_2U_2, data);
333 TTL7474_update(TTL7474_2U_2);
334 }
335
WRITE_HANDLER(carpolo_ball_screen_interrupt_clear_w)336 WRITE_HANDLER( carpolo_ball_screen_interrupt_clear_w )
337 {
338 TTL74148_input_line_w(TTL74148_3S, BALL_SCREEN_PRIORITY_LINE, 1);
339 TTL74148_update(TTL74148_3S);
340 }
341
WRITE_HANDLER(carpolo_car_car_interrupt_clear_w)342 WRITE_HANDLER( carpolo_car_car_interrupt_clear_w )
343 {
344 TTL74148_input_line_w(TTL74148_3S, CAR_CAR_PRIORITY_LINE, 1);
345 TTL74148_update(TTL74148_3S);
346 }
347
WRITE_HANDLER(carpolo_car_goal_interrupt_clear_w)348 WRITE_HANDLER( carpolo_car_goal_interrupt_clear_w )
349 {
350 TTL74148_input_line_w(TTL74148_3S, CAR_GOAL_PRIORITY_LINE, 1);
351 TTL74148_update(TTL74148_3S);
352 }
353
WRITE_HANDLER(carpolo_car_ball_interrupt_clear_w)354 WRITE_HANDLER( carpolo_car_ball_interrupt_clear_w )
355 {
356 TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 1);
357 TTL74148_update(TTL74148_3S);
358 }
359
WRITE_HANDLER(carpolo_car_border_interrupt_clear_w)360 WRITE_HANDLER( carpolo_car_border_interrupt_clear_w )
361 {
362 TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 1);
363 TTL74148_update(TTL74148_3S);
364 }
365
WRITE_HANDLER(carpolo_timer_interrupt_clear_w)366 WRITE_HANDLER( carpolo_timer_interrupt_clear_w )
367 {
368 TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 1);
369 TTL74148_update(TTL74148_3S);
370 }
371
372
373 /*************************************
374 *
375 * Input port handling
376 *
377 *************************************/
378
WRITE_HANDLER(pia_0_port_a_w)379 static WRITE_HANDLER( pia_0_port_a_w )
380 {
381 /* bit 0 - Coin counter
382 bit 1 - Player 4 crash sound
383 bit 2 - Player 3 crash sound
384 bit 3 - Clear steering wheel logic
385 bit 4 - Player 2 crash sound
386 bit 5 - Score pulse sound
387 bit 6 - Player 1 crash sound
388 bit 7 - Ball hit pulse sound */
389
390 coin_counter_w(0, data & 0x01);
391
392
393 TTL7474_clear_w(TTL7474_1F_1, data & 0x08);
394 TTL7474_clear_w(TTL7474_1D_1, data & 0x08);
395 TTL7474_clear_w(TTL7474_1C_1, data & 0x08);
396 TTL7474_clear_w(TTL7474_1A_1, data & 0x08);
397
398 TTL7474_update(TTL7474_1F_1);
399 TTL7474_update(TTL7474_1D_1);
400 TTL7474_update(TTL7474_1C_1);
401 TTL7474_update(TTL7474_1A_1);
402 }
403
404
WRITE_HANDLER(pia_0_port_b_w)405 static WRITE_HANDLER( pia_0_port_b_w )
406 {
407 /* bit 0 - Strobe speed bits sound
408 bit 1 - Speed bit 0 sound
409 bit 2 - Speed bit 1 sound
410 bit 3 - Speed bit 2 sound
411 bit 6 - Select pedal 0
412 bit 7 - Select pdeal 1 */
413
414 TTL74153_a_w(TTL74153_1K, data & 0x40);
415 TTL74153_b_w(TTL74153_1K, data & 0x80);
416
417 TTL74153_update(TTL74153_1K);
418 }
419
READ_HANDLER(pia_0_port_b_r)420 static READ_HANDLER( pia_0_port_b_r )
421 {
422 /* bit 4 - Pedal bit 0
423 bit 5 - Pedal bit 1 */
424
425 return (TTL74153_output_r(TTL74153_1K, 0) << 5) |
426 (TTL74153_output_r(TTL74153_1K, 1) << 4);
427 }
428
429
READ_HANDLER(pia_1_port_a_r)430 static READ_HANDLER( pia_1_port_a_r )
431 {
432 data8_t ret;
433
434 /* bit 0 - Player 4 steering input (left or right)
435 bit 1 - Player 3 steering input (left or right)
436 bit 2 - Player 2 steering input (left or right)
437 bit 3 - Player 1 steering input (left or right)
438 bit 4 - Player 4 forward/reverse input
439 bit 5 - Player 3 forward/reverse input
440 bit 6 - Player 2 forward/reverse input
441 bit 7 - Player 1 forward/reverse input */
442
443 ret = (TTL7474_output_r(TTL7474_1A_2) ? 0x01 : 0x00) |
444 (TTL7474_output_r(TTL7474_1C_2) ? 0x02 : 0x00) |
445 (TTL7474_output_r(TTL7474_1D_2) ? 0x04 : 0x00) |
446 (TTL7474_output_r(TTL7474_1F_2) ? 0x08 : 0x00) |
447 (readinputport(7) & 0xf0);
448
449 return ret;
450 }
451
452
READ_HANDLER(pia_1_port_b_r)453 static READ_HANDLER( pia_1_port_b_r )
454 {
455 data8_t ret;
456
457 /* bit 4 - Player 4 steering input (wheel moving or stopped)
458 bit 5 - Player 3 steering input (wheel moving or stopped)
459 bit 6 - Player 2 steering input (wheel moving or stopped)
460 bit 7 - Player 1 steering input (wheel moving or stopped) */
461
462 ret = (TTL7474_output_r(TTL7474_1A_1) ? 0x10 : 0x00) |
463 (TTL7474_output_r(TTL7474_1C_1) ? 0x20 : 0x00) |
464 (TTL7474_output_r(TTL7474_1D_1) ? 0x40 : 0x00) |
465 (TTL7474_output_r(TTL7474_1F_1) ? 0x80 : 0x00);
466
467 return ret;
468 }
469
470
471 static struct pia6821_interface pia_0_intf =
472 {
473 /*inputs : A/B,CA/B1,CA/B2 */ 0, pia_0_port_b_r, 0, 0, 0, 0,
474 /*outputs: A/B,CA/B2 */ pia_0_port_a_w, pia_0_port_b_w, coin1_interrupt_clear_w, coin2_interrupt_clear_w,
475 /*irqs : A/B */ 0, 0
476 };
477
478 static struct pia6821_interface pia_1_intf =
479 {
480 /*inputs : A/B,CA/B1,CA/B2 */ pia_1_port_a_r, pia_1_port_b_r, 0, 0, 0, 0,
481 /*outputs: A/B,CA/B2 */ 0, 0, coin3_interrupt_clear_w, coin4_interrupt_clear_w,
482 /*irqs : A/B */ 0, 0
483 };
484
485 static struct TTL74148_interface TTL74148_3S_intf =
486 {
487 TTL74148_3S_cb
488 };
489
490 static struct TTL7474_interface TTL7474_2S_1_intf =
491 {
492 TTL7474_2S_1_cb
493 };
494
495 static struct TTL7474_interface TTL7474_2S_2_intf =
496 {
497 TTL7474_2S_2_cb
498 };
499
500 static struct TTL7474_interface TTL7474_2U_1_intf =
501 {
502 TTL7474_2U_1_cb
503 };
504
505 static struct TTL7474_interface TTL7474_2U_2_intf =
506 {
507 TTL7474_2U_2_cb
508 };
509
510
MACHINE_INIT(carpolo)511 MACHINE_INIT( carpolo )
512 {
513 /* set up the priority encoder */
514 TTL74148_config(TTL74148_3S, &TTL74148_3S_intf);
515 TTL74148_enable_input_w(TTL74148_3S, 0); /* always enabled */
516
517
518 /* set up the coin handling flip-flops */
519 TTL7474_config(TTL7474_2S_1, &TTL7474_2S_1_intf);
520 TTL7474_config(TTL7474_2S_2, &TTL7474_2S_2_intf);
521 TTL7474_config(TTL7474_2U_1, &TTL7474_2U_1_intf);
522 TTL7474_config(TTL7474_2U_2, &TTL7474_2U_2_intf);
523
524 TTL7474_d_w (TTL7474_2S_1, 1);
525 TTL7474_preset_w(TTL7474_2S_1, 1);
526
527 TTL7474_d_w (TTL7474_2S_2, 1);
528 TTL7474_preset_w(TTL7474_2S_2, 1);
529
530 TTL7474_d_w (TTL7474_2U_1, 1);
531 TTL7474_preset_w(TTL7474_2U_1, 1);
532
533 TTL7474_d_w (TTL7474_2U_2, 1);
534 TTL7474_preset_w(TTL7474_2U_2, 1);
535
536
537 /* set up the steering handling flip-flops */
538 TTL7474_config(TTL7474_1F_1, 0);
539 TTL7474_config(TTL7474_1F_2, 0);
540 TTL7474_config(TTL7474_1D_1, 0);
541 TTL7474_config(TTL7474_1D_2, 0);
542 TTL7474_config(TTL7474_1C_1, 0);
543 TTL7474_config(TTL7474_1C_2, 0);
544 TTL7474_config(TTL7474_1A_1, 0);
545 TTL7474_config(TTL7474_1A_2, 0);
546
547 TTL7474_d_w (TTL7474_1F_1, 1);
548 TTL7474_preset_w(TTL7474_1F_1, 1);
549
550 TTL7474_clear_w (TTL7474_1F_2, 1);
551 TTL7474_preset_w(TTL7474_1F_2, 1);
552
553 TTL7474_d_w (TTL7474_1D_1, 1);
554 TTL7474_preset_w(TTL7474_1D_1, 1);
555
556 TTL7474_clear_w (TTL7474_1D_2, 1);
557 TTL7474_preset_w(TTL7474_1D_2, 1);
558
559 TTL7474_d_w (TTL7474_1C_1, 1);
560 TTL7474_preset_w(TTL7474_1C_1, 1);
561
562 TTL7474_clear_w (TTL7474_1C_2, 1);
563 TTL7474_preset_w(TTL7474_1C_2, 1);
564
565 TTL7474_d_w (TTL7474_1A_1, 1);
566 TTL7474_preset_w(TTL7474_1A_1, 1);
567
568 TTL7474_clear_w (TTL7474_1A_2, 1);
569 TTL7474_preset_w(TTL7474_1A_2, 1);
570
571
572 /* set up the pedal handling chips */
573 TTL74153_config(TTL74153_1K, 0);
574
575 TTL74153_enable_w(TTL74153_1K, 0, 0);
576 TTL74153_enable_w(TTL74153_1K, 1, 0);
577
578
579 /* set up the PIA's */
580 pia_config(0, PIA_STANDARD_ORDERING, &pia_0_intf);
581 pia_config(1, PIA_STANDARD_ORDERING, &pia_1_intf);
582 }
583