trunk/src/mame/drivers/carpolo.c
| r250160 | r250161 | |
| 1 | | // license:BSD-3-Clause |
| 2 | | // copyright-holders:Zsolt Vasvari |
| 3 | | /*************************************************************************** |
| 4 | | |
| 5 | | Exidy Car Polo hardware |
| 6 | | |
| 7 | | driver by Zsolt Vasvari |
| 8 | | |
| 9 | | Games supported: |
| 10 | | * Car Polo |
| 11 | | |
| 12 | | Known issues: |
| 13 | | * sound |
| 14 | | |
| 15 | | Original Bugs: |
| 16 | | * if you insert a coin too fast (before the GAME OVER sign appears), |
| 17 | | the cars will chase *away* from the ball |
| 18 | | |
| 19 | | ****************************************************************************/ |
| 20 | | |
| 21 | | #include "emu.h" |
| 22 | | #include "cpu/m6502/m6502.h" |
| 23 | | #include "machine/74153.h" |
| 24 | | #include "machine/6821pia.h" |
| 25 | | #include "includes/carpolo.h" |
| 26 | | |
| 27 | | |
| 28 | | |
| 29 | | /************************************* |
| 30 | | * |
| 31 | | * Main CPU memory handlers |
| 32 | | * |
| 33 | | *************************************/ |
| 34 | | |
| 35 | | static ADDRESS_MAP_START( main_map, AS_PROGRAM, 8, carpolo_state ) |
| 36 | | AM_RANGE(0x0000, 0x01ff) AM_RAM |
| 37 | | AM_RANGE(0x3000, 0x30ff) AM_WRITEONLY AM_SHARE("alpharam") |
| 38 | | AM_RANGE(0x4000, 0x400f) AM_WRITEONLY AM_SHARE("spriteram") |
| 39 | | AM_RANGE(0x5400, 0x5403) AM_DEVREADWRITE("pia0", pia6821_device, read, write) |
| 40 | | AM_RANGE(0x5800, 0x5803) AM_DEVREADWRITE("pia1", pia6821_device, read, write) |
| 41 | | AM_RANGE(0xa000, 0xa000) AM_READ(carpolo_ball_screen_collision_cause_r) |
| 42 | | AM_RANGE(0xa001, 0xa001) AM_READ(carpolo_car_ball_collision_x_r) |
| 43 | | AM_RANGE(0xa002, 0xa002) AM_READ(carpolo_car_ball_collision_y_r) |
| 44 | | AM_RANGE(0xa003, 0xa003) AM_READ(carpolo_car_car_collision_cause_r) |
| 45 | | AM_RANGE(0xa004, 0xa004) AM_READ(carpolo_car_border_collision_cause_r) |
| 46 | | AM_RANGE(0xa005, 0xa005) AM_READ(carpolo_car_ball_collision_cause_r) |
| 47 | | AM_RANGE(0xa006, 0xa006) AM_READ(carpolo_car_goal_collision_cause_r) |
| 48 | | AM_RANGE(0xa007, 0xa007) AM_READ_PORT("IN1") |
| 49 | | AM_RANGE(0xb000, 0xb000) AM_WRITE(carpolo_ball_screen_interrupt_clear_w) |
| 50 | | AM_RANGE(0xb001, 0xb001) AM_WRITE(carpolo_timer_interrupt_clear_w) |
| 51 | | AM_RANGE(0xb003, 0xb003) AM_WRITE(carpolo_car_car_interrupt_clear_w) |
| 52 | | AM_RANGE(0xb004, 0xb004) AM_WRITE(carpolo_car_border_interrupt_clear_w) |
| 53 | | AM_RANGE(0xb005, 0xb005) AM_WRITE(carpolo_car_ball_interrupt_clear_w) |
| 54 | | AM_RANGE(0xb006, 0xb006) AM_WRITE(carpolo_car_goal_interrupt_clear_w) |
| 55 | | AM_RANGE(0xc000, 0xc000) AM_READ(carpolo_interrupt_cause_r) |
| 56 | | AM_RANGE(0xf000, 0xffff) AM_ROM |
| 57 | | ADDRESS_MAP_END |
| 58 | | |
| 59 | | |
| 60 | | |
| 61 | | /************************************* |
| 62 | | * |
| 63 | | * Port definitions |
| 64 | | * |
| 65 | | *************************************/ |
| 66 | | |
| 67 | | static INPUT_PORTS_START( carpolo ) |
| 68 | | PORT_START("IN0") /* IN0 */ |
| 69 | | PORT_BIT (0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) |
| 70 | | PORT_BIT (0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) |
| 71 | | PORT_BIT (0x04, IP_ACTIVE_HIGH, IPT_COIN3 ) |
| 72 | | PORT_BIT (0x08, IP_ACTIVE_HIGH, IPT_COIN4 ) |
| 73 | | PORT_BIT (0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| 74 | | |
| 75 | | /* the value read from here is used directly, |
| 76 | | the result is calculated by 60/value */ |
| 77 | | PORT_START("IN1") /* IN1 */ |
| 78 | | PORT_BIT (0x03, IP_ACTIVE_HIGH, IPT_UNUSED ) /* the lowest 2 bits of the counter */ |
| 79 | | PORT_DIPNAME( 0xfc, 0x3c, "Game Sec/Real Sec" ) |
| 80 | | PORT_DIPSETTING( 0x00, "0.23 (Longest)" ) |
| 81 | | PORT_DIPSETTING( 0xfc, "0.24" ) |
| 82 | | PORT_DIPSETTING( 0xf8, "0.24" ) |
| 83 | | PORT_DIPSETTING( 0xf4, "0.25" ) |
| 84 | | PORT_DIPSETTING( 0xf0, "0.25" ) |
| 85 | | PORT_DIPSETTING( 0xec, "0.25" ) |
| 86 | | PORT_DIPSETTING( 0xe8, "0.26" ) |
| 87 | | PORT_DIPSETTING( 0xe4, "0.26" ) |
| 88 | | PORT_DIPSETTING( 0xe0, "0.27" ) |
| 89 | | PORT_DIPSETTING( 0xdc, "0.27" ) |
| 90 | | PORT_DIPSETTING( 0xd8, "0.28" ) |
| 91 | | PORT_DIPSETTING( 0xd4, "0.28" ) |
| 92 | | PORT_DIPSETTING( 0xd0, "0.29" ) |
| 93 | | PORT_DIPSETTING( 0xcc, "0.29" ) |
| 94 | | PORT_DIPSETTING( 0xc8, "0.30" ) |
| 95 | | PORT_DIPSETTING( 0xc4, "0.31" ) |
| 96 | | PORT_DIPSETTING( 0xc0, "0.31" ) |
| 97 | | PORT_DIPSETTING( 0xbc, "0.32" ) |
| 98 | | PORT_DIPSETTING( 0xb8, "0.33" ) |
| 99 | | PORT_DIPSETTING( 0xb4, "0.33" ) |
| 100 | | PORT_DIPSETTING( 0xb0, "0.34" ) |
| 101 | | PORT_DIPSETTING( 0xac, "0.35" ) |
| 102 | | PORT_DIPSETTING( 0xa8, "0.36" ) |
| 103 | | PORT_DIPSETTING( 0xa4, "0.37" ) |
| 104 | | PORT_DIPSETTING( 0xa0, "0.38" ) |
| 105 | | PORT_DIPSETTING( 0x9c, "0.38" ) |
| 106 | | PORT_DIPSETTING( 0x98, "0.39" ) |
| 107 | | PORT_DIPSETTING( 0x94, "0.41" ) |
| 108 | | PORT_DIPSETTING( 0x90, "0.42" ) |
| 109 | | PORT_DIPSETTING( 0x8c, "0.44" ) |
| 110 | | PORT_DIPSETTING( 0x84, "0.46" ) |
| 111 | | PORT_DIPSETTING( 0x80, "0.47" ) |
| 112 | | PORT_DIPSETTING( 0x7c, "0.48" ) |
| 113 | | PORT_DIPSETTING( 0x78, "0.50" ) |
| 114 | | PORT_DIPSETTING( 0x74, "0.52" ) |
| 115 | | PORT_DIPSETTING( 0x70, "0.54" ) |
| 116 | | PORT_DIPSETTING( 0x6c, "0.56" ) |
| 117 | | PORT_DIPSETTING( 0x68, "0.58" ) |
| 118 | | PORT_DIPSETTING( 0x64, "0.60" ) |
| 119 | | PORT_DIPSETTING( 0x60, "0.63" ) |
| 120 | | PORT_DIPSETTING( 0x5c, "0.65" ) |
| 121 | | PORT_DIPSETTING( 0x58, "0.68" ) |
| 122 | | PORT_DIPSETTING( 0x54, "0.71" ) |
| 123 | | PORT_DIPSETTING( 0x50, "0.75" ) |
| 124 | | PORT_DIPSETTING( 0x4c, "0.79" ) |
| 125 | | PORT_DIPSETTING( 0x48, "0.83" ) |
| 126 | | PORT_DIPSETTING( 0x44, "0.88" ) |
| 127 | | PORT_DIPSETTING( 0x40, "0.94" ) |
| 128 | | PORT_DIPSETTING( 0x3c, "1.00" ) |
| 129 | | PORT_DIPSETTING( 0x38, "1.07" ) |
| 130 | | PORT_DIPSETTING( 0x34, "1.15" ) |
| 131 | | PORT_DIPSETTING( 0x30, "1.25" ) |
| 132 | | PORT_DIPSETTING( 0x2c, "1.36" ) |
| 133 | | PORT_DIPSETTING( 0x28, "1.50" ) |
| 134 | | PORT_DIPSETTING( 0x24, "1.67" ) |
| 135 | | PORT_DIPSETTING( 0x20, "1.88" ) |
| 136 | | PORT_DIPSETTING( 0x1c, "2.14" ) |
| 137 | | PORT_DIPSETTING( 0x18, "2.50" ) |
| 138 | | PORT_DIPSETTING( 0x14, "3.00" ) |
| 139 | | PORT_DIPSETTING( 0x10, "3.75" ) |
| 140 | | PORT_DIPSETTING( 0x0c, "5.00" ) |
| 141 | | PORT_DIPSETTING( 0x08, "7.50" ) |
| 142 | | PORT_DIPSETTING( 0x04, "15.00 (Shortest)" ) |
| 143 | | |
| 144 | | PORT_START("DIAL0") /* IN2 */ |
| 145 | | PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_REVERSE PORT_PLAYER(1) |
| 146 | | |
| 147 | | PORT_START("DIAL1") /* IN3 */ |
| 148 | | PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_REVERSE PORT_PLAYER(2) |
| 149 | | |
| 150 | | PORT_START("DIAL2") /* IN4 */ |
| 151 | | PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_REVERSE PORT_PLAYER(3) |
| 152 | | |
| 153 | | PORT_START("DIAL3") /* IN5 */ |
| 154 | | PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_REVERSE PORT_PLAYER(4) |
| 155 | | |
| 156 | | PORT_START("PEDALS") /* IN6 - accelerator pedals */ |
| 157 | | PORT_BIT (0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(1) |
| 158 | | PORT_BIT (0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(1) |
| 159 | | PORT_BIT (0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2) |
| 160 | | PORT_BIT (0x08, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2) |
| 161 | | PORT_BIT (0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(3) |
| 162 | | PORT_BIT (0x20, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(3) |
| 163 | | PORT_BIT (0x40, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(4) |
| 164 | | PORT_BIT (0x80, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(4) |
| 165 | | |
| 166 | | PORT_START("IN2") /* IN7 - forward/reverse */ |
| 167 | | PORT_BIT (0x0f, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| 168 | | PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(4) |
| 169 | | PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3) |
| 170 | | PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) |
| 171 | | PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) |
| 172 | | INPUT_PORTS_END |
| 173 | | |
| 174 | | |
| 175 | | |
| 176 | | /************************************* |
| 177 | | * |
| 178 | | * Graphics definitions |
| 179 | | * |
| 180 | | *************************************/ |
| 181 | | |
| 182 | | static const gfx_layout spritelayout = |
| 183 | | { |
| 184 | | 16,16, |
| 185 | | RGN_FRAC(1,4), |
| 186 | | 1, |
| 187 | | { 0 }, |
| 188 | | { STEP4(3*0x100*8+4,1), |
| 189 | | STEP4(2*0x100*8+4,1), |
| 190 | | STEP4(1*0x100*8+4,1), |
| 191 | | STEP4(0*0x100*8+4,1) }, |
| 192 | | { STEP16(0,8) }, |
| 193 | | 16*8 |
| 194 | | }; |
| 195 | | |
| 196 | | static const gfx_layout goallayout = |
| 197 | | { |
| 198 | | 8,32, |
| 199 | | 1, |
| 200 | | 4, |
| 201 | | { 4, 5, 6, 7 }, |
| 202 | | { STEP8(0,8) }, |
| 203 | | { STEP8(192*8,8*8), |
| 204 | | STEP16( 0*8,8*8), |
| 205 | | STEP8(128*8,8*8) }, |
| 206 | | 0 |
| 207 | | }; |
| 208 | | |
| 209 | | static const gfx_layout alphalayout = |
| 210 | | { |
| 211 | | 8,8, |
| 212 | | RGN_FRAC(1,1), |
| 213 | | 1, |
| 214 | | { 0 }, |
| 215 | | { STEP8(0,1) }, |
| 216 | | { STEP8(0,8) }, |
| 217 | | 8*8 |
| 218 | | }; |
| 219 | | |
| 220 | | static GFXDECODE_START( carpolo ) |
| 221 | | GFXDECODE_ENTRY( "gfx1", 0, spritelayout, 0, 12 ) |
| 222 | | GFXDECODE_ENTRY( "gfx2", 0, goallayout, 12*2, 2 ) |
| 223 | | GFXDECODE_ENTRY( "gfx3", 0, alphalayout, 12*2+2*16, 4 ) |
| 224 | | GFXDECODE_END |
| 225 | | |
| 226 | | /************************************* |
| 227 | | * |
| 228 | | * Machine driver |
| 229 | | * |
| 230 | | *************************************/ |
| 231 | | |
| 232 | | static MACHINE_CONFIG_START( carpolo, carpolo_state ) |
| 233 | | |
| 234 | | /* basic machine hardware */ |
| 235 | | MCFG_CPU_ADD("maincpu", M6502, XTAL_11_289MHz/12) /* 940.75 kHz */ |
| 236 | | MCFG_CPU_PROGRAM_MAP(main_map) |
| 237 | | MCFG_CPU_VBLANK_INT_DRIVER("screen", carpolo_state, carpolo_timer_interrupt) /* this not strictly VBLANK, |
| 238 | | but it's supposed to happen 60 |
| 239 | | times a sec, so it's a good place */ |
| 240 | | |
| 241 | | MCFG_DEVICE_ADD("pia0", PIA6821, 0) |
| 242 | | MCFG_PIA_READPB_HANDLER(READ8(carpolo_state, pia_0_port_b_r)) |
| 243 | | MCFG_PIA_WRITEPA_HANDLER(WRITE8(carpolo_state, pia_0_port_a_w)) |
| 244 | | MCFG_PIA_WRITEPB_HANDLER(WRITE8(carpolo_state, pia_0_port_b_w)) |
| 245 | | MCFG_PIA_CA2_HANDLER(WRITELINE(carpolo_state, coin1_interrupt_clear_w)) |
| 246 | | MCFG_PIA_CB2_HANDLER(WRITELINE(carpolo_state,coin2_interrupt_clear_w)) |
| 247 | | |
| 248 | | MCFG_DEVICE_ADD("pia1", PIA6821, 0) |
| 249 | | MCFG_PIA_READPA_HANDLER(READ8(carpolo_state, pia_1_port_a_r)) |
| 250 | | MCFG_PIA_READPB_HANDLER(READ8(carpolo_state, pia_1_port_b_r)) |
| 251 | | MCFG_PIA_CA2_HANDLER(WRITELINE(carpolo_state, coin3_interrupt_clear_w)) |
| 252 | | MCFG_PIA_CB2_HANDLER(WRITELINE(carpolo_state, coin4_interrupt_clear_w)) |
| 253 | | |
| 254 | | MCFG_DEVICE_ADD("7474_2s_1", TTL7474, 0) |
| 255 | | MCFG_7474_COMP_OUTPUT_CB(WRITELINE(carpolo_state, carpolo_7474_2s_1_q_cb)) |
| 256 | | |
| 257 | | MCFG_DEVICE_ADD("7474_2s_2", TTL7474, 0) |
| 258 | | MCFG_7474_COMP_OUTPUT_CB(WRITELINE(carpolo_state, carpolo_7474_2s_2_q_cb)) |
| 259 | | |
| 260 | | MCFG_DEVICE_ADD("7474_2u_1", TTL7474, 0) |
| 261 | | MCFG_7474_COMP_OUTPUT_CB(WRITELINE(carpolo_state, carpolo_7474_2u_1_q_cb)) |
| 262 | | |
| 263 | | MCFG_DEVICE_ADD("7474_2u_2", TTL7474, 0) |
| 264 | | MCFG_7474_COMP_OUTPUT_CB(WRITELINE(carpolo_state, carpolo_7474_2u_2_q_cb)) |
| 265 | | |
| 266 | | MCFG_DEVICE_ADD("7474_1f_1", TTL7474, 0) |
| 267 | | MCFG_DEVICE_ADD("7474_1f_2", TTL7474, 0) |
| 268 | | MCFG_DEVICE_ADD("7474_1d_1", TTL7474, 0) |
| 269 | | MCFG_DEVICE_ADD("7474_1d_2", TTL7474, 0) |
| 270 | | MCFG_DEVICE_ADD("7474_1c_1", TTL7474, 0) |
| 271 | | MCFG_DEVICE_ADD("7474_1c_2", TTL7474, 0) |
| 272 | | MCFG_DEVICE_ADD("7474_1a_1", TTL7474, 0) |
| 273 | | MCFG_DEVICE_ADD("7474_1a_2", TTL7474, 0) |
| 274 | | |
| 275 | | MCFG_DEVICE_ADD("74148_3s", TTL74148, 0) |
| 276 | | MCFG_74148_OUTPUT_CB(carpolo_state, ttl74148_3s_cb) |
| 277 | | |
| 278 | | MCFG_DEVICE_ADD("74153_1k", TTL74153, 0) |
| 279 | | |
| 280 | | /* video hardware */ |
| 281 | | MCFG_SCREEN_ADD("screen", RASTER) |
| 282 | | MCFG_SCREEN_REFRESH_RATE(60) |
| 283 | | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */) |
| 284 | | MCFG_SCREEN_SIZE(256, 256) |
| 285 | | MCFG_SCREEN_VISIBLE_AREA(0, 239, 0, 255) |
| 286 | | MCFG_SCREEN_UPDATE_DRIVER(carpolo_state, screen_update_carpolo) |
| 287 | | MCFG_SCREEN_VBLANK_DRIVER(carpolo_state, screen_eof_carpolo) |
| 288 | | MCFG_SCREEN_PALETTE("palette") |
| 289 | | |
| 290 | | MCFG_GFXDECODE_ADD("gfxdecode", "palette", carpolo) |
| 291 | | MCFG_PALETTE_ADD("palette", 12*2+2*16+4*2) |
| 292 | | MCFG_PALETTE_INIT_OWNER(carpolo_state,carpolo) |
| 293 | | |
| 294 | | MACHINE_CONFIG_END |
| 295 | | |
| 296 | | |
| 297 | | |
| 298 | | /************************************* |
| 299 | | * |
| 300 | | * ROM definitions |
| 301 | | * |
| 302 | | *************************************/ |
| 303 | | |
| 304 | | ROM_START( carpolo ) |
| 305 | | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 306 | | ROM_LOAD( "4000.6c", 0xf000, 0x0200, CRC(9d2e75a5) SHA1(c249d0b31de452738516f04a7bc3fb472d54f79d) ) |
| 307 | | ROM_LOAD( "4001.6d", 0xf200, 0x0200, CRC(69fb3768) SHA1(5fcc0807e560de0d73f8bab6943f3cad5ee324c9) ) |
| 308 | | ROM_LOAD( "4002.6h", 0xf400, 0x0200, CRC(5db179c7) SHA1(83615cdc1e3d8930cbdafbd0d327e1d6611faefd) ) |
| 309 | | ROM_LOAD( "4003.6k", 0xf600, 0x0200, CRC(0f992f09) SHA1(dfb8d96b94850166a1b5332f200ae9ceeffc1ce6) ) |
| 310 | | ROM_LOAD( "4004.6e", 0xf800, 0x0200, CRC(be731610) SHA1(70b035f75dd6eace94b4d7a8a344f136b8af743d) ) |
| 311 | | ROM_LOAD( "4005.6f", 0xfa00, 0x0200, CRC(7332f84f) SHA1(be548329918c4ac512fd6027d6bcd16d20c9dd98) ) |
| 312 | | ROM_LOAD( "4006.6l", 0xfc00, 0x0200, CRC(8479c350) SHA1(391c737947498aad4d478639cbbc72181d680fce) ) |
| 313 | | ROM_LOAD( "4007a.6n", 0xfe00, 0x0200, CRC(c6a619de) SHA1(c1b650a0126791fa733f89d9e9bdeeb605486a2c) ) |
| 314 | | |
| 315 | | ROM_REGION( 0x0400, "gfx1", 0 ) /* sprites */ |
| 316 | | ROM_LOAD( "1024.10w", 0x0000, 0x0100, CRC(eedacc7e) SHA1(d89628f013039ca387cafe22180de71e1553cffc) ) |
| 317 | | ROM_LOAD( "1023.10v", 0x0100, 0x0100, CRC(45df6c74) SHA1(a986b62b4c263c5d217bae0d51e74197f5288180) ) |
| 318 | | ROM_LOAD( "1022.10u", 0x0200, 0x0100, CRC(00868768) SHA1(2388e428db300a1e0005cccb9165ec604518033d) ) |
| 319 | | ROM_LOAD( "1021.10t", 0x0300, 0x0100, CRC(a508af9c) SHA1(219ba776d8cccf6726519aff17e37f2a6a85d0d1) ) |
| 320 | | |
| 321 | | ROM_REGION( 0x0100, "gfx2", 0 ) /* goal */ |
| 322 | | ROM_LOAD( "1020.6v", 0x0000, 0x0100, CRC(5e89fbcd) SHA1(6be171168924cd8aa94ff5e1994faecb6f303bd9) ) |
| 323 | | |
| 324 | | ROM_REGION( 0x0200, "gfx3", 0 ) /* alpha */ |
| 325 | | ROM_LOAD( "2513.4l", 0x0000, 0x0200, BAD_DUMP CRC(f80d8889) SHA1(ca573543dcce1221459d5693c476cef14bfac4f4) ) /* MIA - stolen from Night Driver */ |
| 326 | | |
| 327 | | ROM_REGION( 0x0060, "proms", 0 ) |
| 328 | | ROM_LOAD( "328.5u", 0x0000, 0x0020, CRC(f295e0fc) SHA1(974a0481e0c6d5c0b6f0129653d8ed87880916e0) ) /* color PROM */ |
| 329 | | ROM_LOAD( "325.6t", 0x0020, 0x0020, CRC(b8b44022) SHA1(29fe6159c8d239c322296cef68ad59bcf290f246) ) /* horizontal timing */ |
| 330 | | ROM_LOAD( "326.6w", 0x0040, 0x0020, CRC(628ae3d1) SHA1(e6d43d2b5e8ec4b8c1adf6f29c2c9a43ab67ff50) ) /* vertical timing */ |
| 331 | | |
| 332 | | ROM_REGION( 0x0020, "user1", 0 ) |
| 333 | | ROM_LOAD( "327.10s", 0x0000, 0x0020, CRC(e047d24d) SHA1(2ea7afc8d97c906295bf2af929e0515f6c34137f) ) /* sprite image map */ |
| 334 | | ROM_END |
| 335 | | |
| 336 | | |
| 337 | | |
| 338 | | /************************************* |
| 339 | | * |
| 340 | | * Game drivers |
| 341 | | * |
| 342 | | *************************************/ |
| 343 | | |
| 344 | | DRIVER_INIT_MEMBER(carpolo_state,carpolo) |
| 345 | | { |
| 346 | | size_t i, len; |
| 347 | | UINT8 *ROM; |
| 348 | | |
| 349 | | |
| 350 | | /* invert gfx PROM since the bits are active LO */ |
| 351 | | ROM = memregion("gfx2")->base(); |
| 352 | | len = memregion("gfx2")->bytes(); |
| 353 | | for (i = 0;i < len; i++) |
| 354 | | ROM[i] ^= 0x0f; |
| 355 | | } |
| 356 | | |
| 357 | | GAME( 1977, carpolo, 0, carpolo, carpolo, carpolo_state, carpolo, ROT0, "Exidy", "Car Polo", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND ) |
trunk/src/mame/drivers/carpolo.cpp
| r0 | r250161 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:Zsolt Vasvari |
| 3 | /*************************************************************************** |
| 4 | |
| 5 | Exidy Car Polo hardware |
| 6 | |
| 7 | driver by Zsolt Vasvari |
| 8 | |
| 9 | Games supported: |
| 10 | * Car Polo |
| 11 | |
| 12 | Known issues: |
| 13 | * sound |
| 14 | |
| 15 | Original Bugs: |
| 16 | * if you insert a coin too fast (before the GAME OVER sign appears), |
| 17 | the cars will chase *away* from the ball |
| 18 | |
| 19 | ****************************************************************************/ |
| 20 | |
| 21 | #include "emu.h" |
| 22 | #include "cpu/m6502/m6502.h" |
| 23 | #include "machine/74153.h" |
| 24 | #include "machine/6821pia.h" |
| 25 | #include "includes/carpolo.h" |
| 26 | |
| 27 | |
| 28 | |
| 29 | /************************************* |
| 30 | * |
| 31 | * Main CPU memory handlers |
| 32 | * |
| 33 | *************************************/ |
| 34 | |
| 35 | static ADDRESS_MAP_START( main_map, AS_PROGRAM, 8, carpolo_state ) |
| 36 | AM_RANGE(0x0000, 0x01ff) AM_RAM |
| 37 | AM_RANGE(0x3000, 0x30ff) AM_WRITEONLY AM_SHARE("alpharam") |
| 38 | AM_RANGE(0x4000, 0x400f) AM_WRITEONLY AM_SHARE("spriteram") |
| 39 | AM_RANGE(0x5400, 0x5403) AM_DEVREADWRITE("pia0", pia6821_device, read, write) |
| 40 | AM_RANGE(0x5800, 0x5803) AM_DEVREADWRITE("pia1", pia6821_device, read, write) |
| 41 | AM_RANGE(0xa000, 0xa000) AM_READ(carpolo_ball_screen_collision_cause_r) |
| 42 | AM_RANGE(0xa001, 0xa001) AM_READ(carpolo_car_ball_collision_x_r) |
| 43 | AM_RANGE(0xa002, 0xa002) AM_READ(carpolo_car_ball_collision_y_r) |
| 44 | AM_RANGE(0xa003, 0xa003) AM_READ(carpolo_car_car_collision_cause_r) |
| 45 | AM_RANGE(0xa004, 0xa004) AM_READ(carpolo_car_border_collision_cause_r) |
| 46 | AM_RANGE(0xa005, 0xa005) AM_READ(carpolo_car_ball_collision_cause_r) |
| 47 | AM_RANGE(0xa006, 0xa006) AM_READ(carpolo_car_goal_collision_cause_r) |
| 48 | AM_RANGE(0xa007, 0xa007) AM_READ_PORT("IN1") |
| 49 | AM_RANGE(0xb000, 0xb000) AM_WRITE(carpolo_ball_screen_interrupt_clear_w) |
| 50 | AM_RANGE(0xb001, 0xb001) AM_WRITE(carpolo_timer_interrupt_clear_w) |
| 51 | AM_RANGE(0xb003, 0xb003) AM_WRITE(carpolo_car_car_interrupt_clear_w) |
| 52 | AM_RANGE(0xb004, 0xb004) AM_WRITE(carpolo_car_border_interrupt_clear_w) |
| 53 | AM_RANGE(0xb005, 0xb005) AM_WRITE(carpolo_car_ball_interrupt_clear_w) |
| 54 | AM_RANGE(0xb006, 0xb006) AM_WRITE(carpolo_car_goal_interrupt_clear_w) |
| 55 | AM_RANGE(0xc000, 0xc000) AM_READ(carpolo_interrupt_cause_r) |
| 56 | AM_RANGE(0xf000, 0xffff) AM_ROM |
| 57 | ADDRESS_MAP_END |
| 58 | |
| 59 | |
| 60 | |
| 61 | /************************************* |
| 62 | * |
| 63 | * Port definitions |
| 64 | * |
| 65 | *************************************/ |
| 66 | |
| 67 | static INPUT_PORTS_START( carpolo ) |
| 68 | PORT_START("IN0") /* IN0 */ |
| 69 | PORT_BIT (0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) |
| 70 | PORT_BIT (0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) |
| 71 | PORT_BIT (0x04, IP_ACTIVE_HIGH, IPT_COIN3 ) |
| 72 | PORT_BIT (0x08, IP_ACTIVE_HIGH, IPT_COIN4 ) |
| 73 | PORT_BIT (0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| 74 | |
| 75 | /* the value read from here is used directly, |
| 76 | the result is calculated by 60/value */ |
| 77 | PORT_START("IN1") /* IN1 */ |
| 78 | PORT_BIT (0x03, IP_ACTIVE_HIGH, IPT_UNUSED ) /* the lowest 2 bits of the counter */ |
| 79 | PORT_DIPNAME( 0xfc, 0x3c, "Game Sec/Real Sec" ) |
| 80 | PORT_DIPSETTING( 0x00, "0.23 (Longest)" ) |
| 81 | PORT_DIPSETTING( 0xfc, "0.24" ) |
| 82 | PORT_DIPSETTING( 0xf8, "0.24" ) |
| 83 | PORT_DIPSETTING( 0xf4, "0.25" ) |
| 84 | PORT_DIPSETTING( 0xf0, "0.25" ) |
| 85 | PORT_DIPSETTING( 0xec, "0.25" ) |
| 86 | PORT_DIPSETTING( 0xe8, "0.26" ) |
| 87 | PORT_DIPSETTING( 0xe4, "0.26" ) |
| 88 | PORT_DIPSETTING( 0xe0, "0.27" ) |
| 89 | PORT_DIPSETTING( 0xdc, "0.27" ) |
| 90 | PORT_DIPSETTING( 0xd8, "0.28" ) |
| 91 | PORT_DIPSETTING( 0xd4, "0.28" ) |
| 92 | PORT_DIPSETTING( 0xd0, "0.29" ) |
| 93 | PORT_DIPSETTING( 0xcc, "0.29" ) |
| 94 | PORT_DIPSETTING( 0xc8, "0.30" ) |
| 95 | PORT_DIPSETTING( 0xc4, "0.31" ) |
| 96 | PORT_DIPSETTING( 0xc0, "0.31" ) |
| 97 | PORT_DIPSETTING( 0xbc, "0.32" ) |
| 98 | PORT_DIPSETTING( 0xb8, "0.33" ) |
| 99 | PORT_DIPSETTING( 0xb4, "0.33" ) |
| 100 | PORT_DIPSETTING( 0xb0, "0.34" ) |
| 101 | PORT_DIPSETTING( 0xac, "0.35" ) |
| 102 | PORT_DIPSETTING( 0xa8, "0.36" ) |
| 103 | PORT_DIPSETTING( 0xa4, "0.37" ) |
| 104 | PORT_DIPSETTING( 0xa0, "0.38" ) |
| 105 | PORT_DIPSETTING( 0x9c, "0.38" ) |
| 106 | PORT_DIPSETTING( 0x98, "0.39" ) |
| 107 | PORT_DIPSETTING( 0x94, "0.41" ) |
| 108 | PORT_DIPSETTING( 0x90, "0.42" ) |
| 109 | PORT_DIPSETTING( 0x8c, "0.44" ) |
| 110 | PORT_DIPSETTING( 0x84, "0.46" ) |
| 111 | PORT_DIPSETTING( 0x80, "0.47" ) |
| 112 | PORT_DIPSETTING( 0x7c, "0.48" ) |
| 113 | PORT_DIPSETTING( 0x78, "0.50" ) |
| 114 | PORT_DIPSETTING( 0x74, "0.52" ) |
| 115 | PORT_DIPSETTING( 0x70, "0.54" ) |
| 116 | PORT_DIPSETTING( 0x6c, "0.56" ) |
| 117 | PORT_DIPSETTING( 0x68, "0.58" ) |
| 118 | PORT_DIPSETTING( 0x64, "0.60" ) |
| 119 | PORT_DIPSETTING( 0x60, "0.63" ) |
| 120 | PORT_DIPSETTING( 0x5c, "0.65" ) |
| 121 | PORT_DIPSETTING( 0x58, "0.68" ) |
| 122 | PORT_DIPSETTING( 0x54, "0.71" ) |
| 123 | PORT_DIPSETTING( 0x50, "0.75" ) |
| 124 | PORT_DIPSETTING( 0x4c, "0.79" ) |
| 125 | PORT_DIPSETTING( 0x48, "0.83" ) |
| 126 | PORT_DIPSETTING( 0x44, "0.88" ) |
| 127 | PORT_DIPSETTING( 0x40, "0.94" ) |
| 128 | PORT_DIPSETTING( 0x3c, "1.00" ) |
| 129 | PORT_DIPSETTING( 0x38, "1.07" ) |
| 130 | PORT_DIPSETTING( 0x34, "1.15" ) |
| 131 | PORT_DIPSETTING( 0x30, "1.25" ) |
| 132 | PORT_DIPSETTING( 0x2c, "1.36" ) |
| 133 | PORT_DIPSETTING( 0x28, "1.50" ) |
| 134 | PORT_DIPSETTING( 0x24, "1.67" ) |
| 135 | PORT_DIPSETTING( 0x20, "1.88" ) |
| 136 | PORT_DIPSETTING( 0x1c, "2.14" ) |
| 137 | PORT_DIPSETTING( 0x18, "2.50" ) |
| 138 | PORT_DIPSETTING( 0x14, "3.00" ) |
| 139 | PORT_DIPSETTING( 0x10, "3.75" ) |
| 140 | PORT_DIPSETTING( 0x0c, "5.00" ) |
| 141 | PORT_DIPSETTING( 0x08, "7.50" ) |
| 142 | PORT_DIPSETTING( 0x04, "15.00 (Shortest)" ) |
| 143 | |
| 144 | PORT_START("DIAL0") /* IN2 */ |
| 145 | PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_REVERSE PORT_PLAYER(1) |
| 146 | |
| 147 | PORT_START("DIAL1") /* IN3 */ |
| 148 | PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_REVERSE PORT_PLAYER(2) |
| 149 | |
| 150 | PORT_START("DIAL2") /* IN4 */ |
| 151 | PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_REVERSE PORT_PLAYER(3) |
| 152 | |
| 153 | PORT_START("DIAL3") /* IN5 */ |
| 154 | PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_REVERSE PORT_PLAYER(4) |
| 155 | |
| 156 | PORT_START("PEDALS") /* IN6 - accelerator pedals */ |
| 157 | PORT_BIT (0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(1) |
| 158 | PORT_BIT (0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(1) |
| 159 | PORT_BIT (0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2) |
| 160 | PORT_BIT (0x08, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2) |
| 161 | PORT_BIT (0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(3) |
| 162 | PORT_BIT (0x20, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(3) |
| 163 | PORT_BIT (0x40, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(4) |
| 164 | PORT_BIT (0x80, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(4) |
| 165 | |
| 166 | PORT_START("IN2") /* IN7 - forward/reverse */ |
| 167 | PORT_BIT (0x0f, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| 168 | PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(4) |
| 169 | PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3) |
| 170 | PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) |
| 171 | PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) |
| 172 | INPUT_PORTS_END |
| 173 | |
| 174 | |
| 175 | |
| 176 | /************************************* |
| 177 | * |
| 178 | * Graphics definitions |
| 179 | * |
| 180 | *************************************/ |
| 181 | |
| 182 | static const gfx_layout spritelayout = |
| 183 | { |
| 184 | 16,16, |
| 185 | RGN_FRAC(1,4), |
| 186 | 1, |
| 187 | { 0 }, |
| 188 | { STEP4(3*0x100*8+4,1), |
| 189 | STEP4(2*0x100*8+4,1), |
| 190 | STEP4(1*0x100*8+4,1), |
| 191 | STEP4(0*0x100*8+4,1) }, |
| 192 | { STEP16(0,8) }, |
| 193 | 16*8 |
| 194 | }; |
| 195 | |
| 196 | static const gfx_layout goallayout = |
| 197 | { |
| 198 | 8,32, |
| 199 | 1, |
| 200 | 4, |
| 201 | { 4, 5, 6, 7 }, |
| 202 | { STEP8(0,8) }, |
| 203 | { STEP8(192*8,8*8), |
| 204 | STEP16( 0*8,8*8), |
| 205 | STEP8(128*8,8*8) }, |
| 206 | 0 |
| 207 | }; |
| 208 | |
| 209 | static const gfx_layout alphalayout = |
| 210 | { |
| 211 | 8,8, |
| 212 | RGN_FRAC(1,1), |
| 213 | 1, |
| 214 | { 0 }, |
| 215 | { STEP8(0,1) }, |
| 216 | { STEP8(0,8) }, |
| 217 | 8*8 |
| 218 | }; |
| 219 | |
| 220 | static GFXDECODE_START( carpolo ) |
| 221 | GFXDECODE_ENTRY( "gfx1", 0, spritelayout, 0, 12 ) |
| 222 | GFXDECODE_ENTRY( "gfx2", 0, goallayout, 12*2, 2 ) |
| 223 | GFXDECODE_ENTRY( "gfx3", 0, alphalayout, 12*2+2*16, 4 ) |
| 224 | GFXDECODE_END |
| 225 | |
| 226 | /************************************* |
| 227 | * |
| 228 | * Machine driver |
| 229 | * |
| 230 | *************************************/ |
| 231 | |
| 232 | static MACHINE_CONFIG_START( carpolo, carpolo_state ) |
| 233 | |
| 234 | /* basic machine hardware */ |
| 235 | MCFG_CPU_ADD("maincpu", M6502, XTAL_11_289MHz/12) /* 940.75 kHz */ |
| 236 | MCFG_CPU_PROGRAM_MAP(main_map) |
| 237 | MCFG_CPU_VBLANK_INT_DRIVER("screen", carpolo_state, carpolo_timer_interrupt) /* this not strictly VBLANK, |
| 238 | but it's supposed to happen 60 |
| 239 | times a sec, so it's a good place */ |
| 240 | |
| 241 | MCFG_DEVICE_ADD("pia0", PIA6821, 0) |
| 242 | MCFG_PIA_READPB_HANDLER(READ8(carpolo_state, pia_0_port_b_r)) |
| 243 | MCFG_PIA_WRITEPA_HANDLER(WRITE8(carpolo_state, pia_0_port_a_w)) |
| 244 | MCFG_PIA_WRITEPB_HANDLER(WRITE8(carpolo_state, pia_0_port_b_w)) |
| 245 | MCFG_PIA_CA2_HANDLER(WRITELINE(carpolo_state, coin1_interrupt_clear_w)) |
| 246 | MCFG_PIA_CB2_HANDLER(WRITELINE(carpolo_state,coin2_interrupt_clear_w)) |
| 247 | |
| 248 | MCFG_DEVICE_ADD("pia1", PIA6821, 0) |
| 249 | MCFG_PIA_READPA_HANDLER(READ8(carpolo_state, pia_1_port_a_r)) |
| 250 | MCFG_PIA_READPB_HANDLER(READ8(carpolo_state, pia_1_port_b_r)) |
| 251 | MCFG_PIA_CA2_HANDLER(WRITELINE(carpolo_state, coin3_interrupt_clear_w)) |
| 252 | MCFG_PIA_CB2_HANDLER(WRITELINE(carpolo_state, coin4_interrupt_clear_w)) |
| 253 | |
| 254 | MCFG_DEVICE_ADD("7474_2s_1", TTL7474, 0) |
| 255 | MCFG_7474_COMP_OUTPUT_CB(WRITELINE(carpolo_state, carpolo_7474_2s_1_q_cb)) |
| 256 | |
| 257 | MCFG_DEVICE_ADD("7474_2s_2", TTL7474, 0) |
| 258 | MCFG_7474_COMP_OUTPUT_CB(WRITELINE(carpolo_state, carpolo_7474_2s_2_q_cb)) |
| 259 | |
| 260 | MCFG_DEVICE_ADD("7474_2u_1", TTL7474, 0) |
| 261 | MCFG_7474_COMP_OUTPUT_CB(WRITELINE(carpolo_state, carpolo_7474_2u_1_q_cb)) |
| 262 | |
| 263 | MCFG_DEVICE_ADD("7474_2u_2", TTL7474, 0) |
| 264 | MCFG_7474_COMP_OUTPUT_CB(WRITELINE(carpolo_state, carpolo_7474_2u_2_q_cb)) |
| 265 | |
| 266 | MCFG_DEVICE_ADD("7474_1f_1", TTL7474, 0) |
| 267 | MCFG_DEVICE_ADD("7474_1f_2", TTL7474, 0) |
| 268 | MCFG_DEVICE_ADD("7474_1d_1", TTL7474, 0) |
| 269 | MCFG_DEVICE_ADD("7474_1d_2", TTL7474, 0) |
| 270 | MCFG_DEVICE_ADD("7474_1c_1", TTL7474, 0) |
| 271 | MCFG_DEVICE_ADD("7474_1c_2", TTL7474, 0) |
| 272 | MCFG_DEVICE_ADD("7474_1a_1", TTL7474, 0) |
| 273 | MCFG_DEVICE_ADD("7474_1a_2", TTL7474, 0) |
| 274 | |
| 275 | MCFG_DEVICE_ADD("74148_3s", TTL74148, 0) |
| 276 | MCFG_74148_OUTPUT_CB(carpolo_state, ttl74148_3s_cb) |
| 277 | |
| 278 | MCFG_DEVICE_ADD("74153_1k", TTL74153, 0) |
| 279 | |
| 280 | /* video hardware */ |
| 281 | MCFG_SCREEN_ADD("screen", RASTER) |
| 282 | MCFG_SCREEN_REFRESH_RATE(60) |
| 283 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */) |
| 284 | MCFG_SCREEN_SIZE(256, 256) |
| 285 | MCFG_SCREEN_VISIBLE_AREA(0, 239, 0, 255) |
| 286 | MCFG_SCREEN_UPDATE_DRIVER(carpolo_state, screen_update_carpolo) |
| 287 | MCFG_SCREEN_VBLANK_DRIVER(carpolo_state, screen_eof_carpolo) |
| 288 | MCFG_SCREEN_PALETTE("palette") |
| 289 | |
| 290 | MCFG_GFXDECODE_ADD("gfxdecode", "palette", carpolo) |
| 291 | MCFG_PALETTE_ADD("palette", 12*2+2*16+4*2) |
| 292 | MCFG_PALETTE_INIT_OWNER(carpolo_state,carpolo) |
| 293 | |
| 294 | MACHINE_CONFIG_END |
| 295 | |
| 296 | |
| 297 | |
| 298 | /************************************* |
| 299 | * |
| 300 | * ROM definitions |
| 301 | * |
| 302 | *************************************/ |
| 303 | |
| 304 | ROM_START( carpolo ) |
| 305 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 306 | ROM_LOAD( "4000.6c", 0xf000, 0x0200, CRC(9d2e75a5) SHA1(c249d0b31de452738516f04a7bc3fb472d54f79d) ) |
| 307 | ROM_LOAD( "4001.6d", 0xf200, 0x0200, CRC(69fb3768) SHA1(5fcc0807e560de0d73f8bab6943f3cad5ee324c9) ) |
| 308 | ROM_LOAD( "4002.6h", 0xf400, 0x0200, CRC(5db179c7) SHA1(83615cdc1e3d8930cbdafbd0d327e1d6611faefd) ) |
| 309 | ROM_LOAD( "4003.6k", 0xf600, 0x0200, CRC(0f992f09) SHA1(dfb8d96b94850166a1b5332f200ae9ceeffc1ce6) ) |
| 310 | ROM_LOAD( "4004.6e", 0xf800, 0x0200, CRC(be731610) SHA1(70b035f75dd6eace94b4d7a8a344f136b8af743d) ) |
| 311 | ROM_LOAD( "4005.6f", 0xfa00, 0x0200, CRC(7332f84f) SHA1(be548329918c4ac512fd6027d6bcd16d20c9dd98) ) |
| 312 | ROM_LOAD( "4006.6l", 0xfc00, 0x0200, CRC(8479c350) SHA1(391c737947498aad4d478639cbbc72181d680fce) ) |
| 313 | ROM_LOAD( "4007a.6n", 0xfe00, 0x0200, CRC(c6a619de) SHA1(c1b650a0126791fa733f89d9e9bdeeb605486a2c) ) |
| 314 | |
| 315 | ROM_REGION( 0x0400, "gfx1", 0 ) /* sprites */ |
| 316 | ROM_LOAD( "1024.10w", 0x0000, 0x0100, CRC(eedacc7e) SHA1(d89628f013039ca387cafe22180de71e1553cffc) ) |
| 317 | ROM_LOAD( "1023.10v", 0x0100, 0x0100, CRC(45df6c74) SHA1(a986b62b4c263c5d217bae0d51e74197f5288180) ) |
| 318 | ROM_LOAD( "1022.10u", 0x0200, 0x0100, CRC(00868768) SHA1(2388e428db300a1e0005cccb9165ec604518033d) ) |
| 319 | ROM_LOAD( "1021.10t", 0x0300, 0x0100, CRC(a508af9c) SHA1(219ba776d8cccf6726519aff17e37f2a6a85d0d1) ) |
| 320 | |
| 321 | ROM_REGION( 0x0100, "gfx2", 0 ) /* goal */ |
| 322 | ROM_LOAD( "1020.6v", 0x0000, 0x0100, CRC(5e89fbcd) SHA1(6be171168924cd8aa94ff5e1994faecb6f303bd9) ) |
| 323 | |
| 324 | ROM_REGION( 0x0200, "gfx3", 0 ) /* alpha */ |
| 325 | ROM_LOAD( "2513.4l", 0x0000, 0x0200, BAD_DUMP CRC(f80d8889) SHA1(ca573543dcce1221459d5693c476cef14bfac4f4) ) /* MIA - stolen from Night Driver */ |
| 326 | |
| 327 | ROM_REGION( 0x0060, "proms", 0 ) |
| 328 | ROM_LOAD( "328.5u", 0x0000, 0x0020, CRC(f295e0fc) SHA1(974a0481e0c6d5c0b6f0129653d8ed87880916e0) ) /* color PROM */ |
| 329 | ROM_LOAD( "325.6t", 0x0020, 0x0020, CRC(b8b44022) SHA1(29fe6159c8d239c322296cef68ad59bcf290f246) ) /* horizontal timing */ |
| 330 | ROM_LOAD( "326.6w", 0x0040, 0x0020, CRC(628ae3d1) SHA1(e6d43d2b5e8ec4b8c1adf6f29c2c9a43ab67ff50) ) /* vertical timing */ |
| 331 | |
| 332 | ROM_REGION( 0x0020, "user1", 0 ) |
| 333 | ROM_LOAD( "327.10s", 0x0000, 0x0020, CRC(e047d24d) SHA1(2ea7afc8d97c906295bf2af929e0515f6c34137f) ) /* sprite image map */ |
| 334 | ROM_END |
| 335 | |
| 336 | |
| 337 | |
| 338 | /************************************* |
| 339 | * |
| 340 | * Game drivers |
| 341 | * |
| 342 | *************************************/ |
| 343 | |
| 344 | DRIVER_INIT_MEMBER(carpolo_state,carpolo) |
| 345 | { |
| 346 | size_t i, len; |
| 347 | UINT8 *ROM; |
| 348 | |
| 349 | |
| 350 | /* invert gfx PROM since the bits are active LO */ |
| 351 | ROM = memregion("gfx2")->base(); |
| 352 | len = memregion("gfx2")->bytes(); |
| 353 | for (i = 0;i < len; i++) |
| 354 | ROM[i] ^= 0x0f; |
| 355 | } |
| 356 | |
| 357 | GAME( 1977, carpolo, 0, carpolo, carpolo, carpolo_state, carpolo, ROT0, "Exidy", "Car Polo", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND ) |
trunk/src/mame/machine/carpolo.c
| r250160 | r250161 | |
| 1 | | // license:BSD-3-Clause |
| 2 | | // copyright-holders:Zsolt Vasvari |
| 3 | | /*************************************************************************** |
| 4 | | |
| 5 | | Exidy Car Polo hardware |
| 6 | | |
| 7 | | driver by Zsolt Vasvari |
| 8 | | |
| 9 | | ****************************************************************************/ |
| 10 | | |
| 11 | | #include "emu.h" |
| 12 | | #include "cpu/m6502/m6502.h" |
| 13 | | #include "machine/6821pia.h" |
| 14 | | #include "includes/carpolo.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 | | TTL74148_OUTPUT_CB(carpolo_state::ttl74148_3s_cb) |
| 61 | | { |
| 62 | | m_maincpu->set_input_line(M6502_IRQ_LINE, m_ttl74148_3s->output_valid_r() ? CLEAR_LINE : ASSERT_LINE); |
| 63 | | } |
| 64 | | |
| 65 | | |
| 66 | | /* the outputs of the flip-flops are connected to the priority encoder */ |
| 67 | | WRITE_LINE_MEMBER(carpolo_state::carpolo_7474_2s_1_q_cb) |
| 68 | | { |
| 69 | | m_ttl74148_3s->input_line_w(COIN1_PRIORITY_LINE, state); |
| 70 | | m_ttl74148_3s->update(); |
| 71 | | } |
| 72 | | |
| 73 | | WRITE_LINE_MEMBER(carpolo_state::carpolo_7474_2s_2_q_cb) |
| 74 | | { |
| 75 | | m_ttl74148_3s->input_line_w(COIN2_PRIORITY_LINE, state); |
| 76 | | m_ttl74148_3s->update(); |
| 77 | | } |
| 78 | | |
| 79 | | WRITE_LINE_MEMBER(carpolo_state::carpolo_7474_2u_1_q_cb) |
| 80 | | { |
| 81 | | m_ttl74148_3s->input_line_w(COIN3_PRIORITY_LINE, state); |
| 82 | | m_ttl74148_3s->update(); |
| 83 | | } |
| 84 | | |
| 85 | | WRITE_LINE_MEMBER(carpolo_state::carpolo_7474_2u_2_q_cb) |
| 86 | | { |
| 87 | | m_ttl74148_3s->input_line_w(COIN4_PRIORITY_LINE, state); |
| 88 | | m_ttl74148_3s->update(); |
| 89 | | } |
| 90 | | |
| 91 | | |
| 92 | | void carpolo_state::carpolo_generate_ball_screen_interrupt(UINT8 cause) |
| 93 | | { |
| 94 | | m_ball_screen_collision_cause = cause; |
| 95 | | |
| 96 | | m_ttl74148_3s->input_line_w(BALL_SCREEN_PRIORITY_LINE, 0); |
| 97 | | m_ttl74148_3s->update(); |
| 98 | | } |
| 99 | | |
| 100 | | void carpolo_state::carpolo_generate_car_car_interrupt(int car1, int car2) |
| 101 | | { |
| 102 | | m_car_car_collision_cause = ~((1 << (3 - car1)) | (1 << (3 - car2))); |
| 103 | | |
| 104 | | m_ttl74148_3s->input_line_w(CAR_CAR_PRIORITY_LINE, 0); |
| 105 | | m_ttl74148_3s->update(); |
| 106 | | } |
| 107 | | |
| 108 | | void carpolo_state::carpolo_generate_car_goal_interrupt(int car, int right_goal) |
| 109 | | { |
| 110 | | m_car_goal_collision_cause = car | (right_goal ? 0x08 : 0x00); |
| 111 | | |
| 112 | | m_ttl74148_3s->input_line_w(CAR_GOAL_PRIORITY_LINE, 0); |
| 113 | | m_ttl74148_3s->update(); |
| 114 | | } |
| 115 | | |
| 116 | | void carpolo_state::carpolo_generate_car_ball_interrupt(int car, int car_x, int car_y) |
| 117 | | { |
| 118 | | m_car_ball_collision_cause = car; |
| 119 | | m_car_ball_collision_x = car_x; |
| 120 | | m_car_ball_collision_y = car_y; |
| 121 | | |
| 122 | | m_priority_0_extension = CAR_BALL_EXTRA_BITS; |
| 123 | | |
| 124 | | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 0); |
| 125 | | m_ttl74148_3s->update(); |
| 126 | | } |
| 127 | | |
| 128 | | void carpolo_state::carpolo_generate_car_border_interrupt(int car, int horizontal_border) |
| 129 | | { |
| 130 | | m_car_border_collision_cause = car | (horizontal_border ? 0x04 : 0x00); |
| 131 | | |
| 132 | | m_priority_0_extension = CAR_BORDER_EXTRA_BITS; |
| 133 | | |
| 134 | | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 0); |
| 135 | | m_ttl74148_3s->update(); |
| 136 | | } |
| 137 | | |
| 138 | | |
| 139 | | READ8_MEMBER(carpolo_state::carpolo_ball_screen_collision_cause_r) |
| 140 | | { |
| 141 | | /* bit 0 - 0=ball collided with border |
| 142 | | bit 1 - 0=ball collided with goal |
| 143 | | bit 2 - 0=ball collided with score area |
| 144 | | bit 3 - which goal/score collided (0=left, 1=right) */ |
| 145 | | return m_ball_screen_collision_cause; |
| 146 | | } |
| 147 | | |
| 148 | | READ8_MEMBER(carpolo_state::carpolo_car_ball_collision_x_r) |
| 149 | | { |
| 150 | | /* the x coordinate of the colliding pixel */ |
| 151 | | return m_car_ball_collision_x; |
| 152 | | } |
| 153 | | |
| 154 | | READ8_MEMBER(carpolo_state::carpolo_car_ball_collision_y_r) |
| 155 | | { |
| 156 | | /* the y coordinate of the colliding pixel */ |
| 157 | | return m_car_ball_collision_y; |
| 158 | | } |
| 159 | | |
| 160 | | READ8_MEMBER(carpolo_state::carpolo_car_car_collision_cause_r) |
| 161 | | { |
| 162 | | /* bit 0 - car 4 collided |
| 163 | | bit 1 - car 3 collided |
| 164 | | bit 2 - car 2 collided |
| 165 | | bit 3 - car 1 collided */ |
| 166 | | return m_car_car_collision_cause; |
| 167 | | } |
| 168 | | |
| 169 | | READ8_MEMBER(carpolo_state::carpolo_car_goal_collision_cause_r) |
| 170 | | { |
| 171 | | /* bit 0-1 - which car collided |
| 172 | | bit 2 - horizontal timing bit 1TEC4 (not accessed) |
| 173 | | bit 3 - which goal collided (0=left, 1=right) */ |
| 174 | | return m_car_goal_collision_cause; |
| 175 | | } |
| 176 | | |
| 177 | | READ8_MEMBER(carpolo_state::carpolo_car_ball_collision_cause_r) |
| 178 | | { |
| 179 | | /* bit 0-1 - which car collided |
| 180 | | bit 2-3 - unconnected */ |
| 181 | | return m_car_ball_collision_cause; |
| 182 | | } |
| 183 | | |
| 184 | | READ8_MEMBER(carpolo_state::carpolo_car_border_collision_cause_r) |
| 185 | | { |
| 186 | | /* bit 0-1 - which car collided |
| 187 | | bit 2 - 0=vertical border, 1=horizontal border */ |
| 188 | | return m_car_border_collision_cause; |
| 189 | | } |
| 190 | | |
| 191 | | |
| 192 | | READ8_MEMBER(carpolo_state::carpolo_interrupt_cause_r) |
| 193 | | { |
| 194 | | /* the output of the 148 goes to bits 1-3 (which is priority ^ 7) */ |
| 195 | | return (m_ttl74148_3s->output_r() << 1) | m_priority_0_extension; |
| 196 | | } |
| 197 | | |
| 198 | | |
| 199 | | INTERRUPT_GEN_MEMBER(carpolo_state::carpolo_timer_interrupt) |
| 200 | | { |
| 201 | | UINT8 port_value; |
| 202 | | int player; |
| 203 | | |
| 204 | | |
| 205 | | /* cause the timer interrupt */ |
| 206 | | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 0); |
| 207 | | m_priority_0_extension = TIMER_EXTRA_BITS; |
| 208 | | |
| 209 | | m_ttl74148_3s->update(); |
| 210 | | |
| 211 | | |
| 212 | | /* check the coins here as well - they drive the clock of the flip-flops */ |
| 213 | | port_value = ioport("IN0")->read(); |
| 214 | | |
| 215 | | m_ttl7474_2s_1->clock_w((port_value & 0x01) >> 0); |
| 216 | | m_ttl7474_2s_2->clock_w((port_value & 0x02) >> 1); |
| 217 | | m_ttl7474_2u_1->clock_w((port_value & 0x04) >> 2); |
| 218 | | m_ttl7474_2u_2->clock_w((port_value & 0x08) >> 3); |
| 219 | | |
| 220 | | /* read the steering controls */ |
| 221 | | for (player = 0; player < 4; player++) |
| 222 | | { |
| 223 | | static const char *const portnames[] = { "DIAL0", "DIAL1", "DIAL2", "DIAL3" }; |
| 224 | | ttl7474_device *movement_flip_flop; |
| 225 | | ttl7474_device *dir_flip_flop; |
| 226 | | |
| 227 | | switch (player) |
| 228 | | { |
| 229 | | default: |
| 230 | | case 0: movement_flip_flop = m_ttl7474_1f_1; dir_flip_flop = m_ttl7474_1f_2; break; |
| 231 | | case 1: movement_flip_flop = m_ttl7474_1d_1; dir_flip_flop = m_ttl7474_1d_2; break; |
| 232 | | case 2: movement_flip_flop = m_ttl7474_1c_1; dir_flip_flop = m_ttl7474_1c_2; break; |
| 233 | | case 3: movement_flip_flop = m_ttl7474_1a_1; dir_flip_flop = m_ttl7474_1a_2; break; |
| 234 | | } |
| 235 | | |
| 236 | | port_value = ioport(portnames[player])->read(); |
| 237 | | |
| 238 | | if (port_value != m_last_wheel_value[player]) |
| 239 | | { |
| 240 | | /* set the movement direction */ |
| 241 | | dir_flip_flop->d_w(((port_value - m_last_wheel_value[player]) & 0x80) ? 1 : 0); |
| 242 | | |
| 243 | | m_last_wheel_value[player] = port_value; |
| 244 | | } |
| 245 | | |
| 246 | | /* as the wheel moves, both flip-flops are clocked */ |
| 247 | | movement_flip_flop->clock_w(port_value & 0x01); |
| 248 | | dir_flip_flop->clock_w( port_value & 0x01); |
| 249 | | } |
| 250 | | |
| 251 | | |
| 252 | | |
| 253 | | /* finally read the accelerator pedals */ |
| 254 | | port_value = ioport("PEDALS")->read(); |
| 255 | | |
| 256 | | for (player = 0; player < 4; player++) |
| 257 | | { |
| 258 | | /* one line indicates if the pedal is pressed and the other |
| 259 | | how much, resulting in only two different possible levels */ |
| 260 | | if (port_value & 0x01) |
| 261 | | { |
| 262 | | m_ttl74153_1k->input_line_w(0, player, 1); |
| 263 | | m_ttl74153_1k->input_line_w(1, player, 0); |
| 264 | | } |
| 265 | | else if (port_value & 0x02) |
| 266 | | { |
| 267 | | m_ttl74153_1k->input_line_w(0, player, 1); |
| 268 | | m_ttl74153_1k->input_line_w(1, player, 1); |
| 269 | | } |
| 270 | | else |
| 271 | | { |
| 272 | | m_ttl74153_1k->input_line_w(0, player, 0); |
| 273 | | /* the other line is irrelevant */ |
| 274 | | } |
| 275 | | |
| 276 | | port_value >>= 2; |
| 277 | | } |
| 278 | | |
| 279 | | m_ttl74153_1k->update(); |
| 280 | | } |
| 281 | | |
| 282 | | // FIXME: Remove trampolines |
| 283 | | |
| 284 | | WRITE_LINE_MEMBER(carpolo_state::coin1_interrupt_clear_w) |
| 285 | | { |
| 286 | | m_ttl7474_2s_1->clear_w(state); |
| 287 | | } |
| 288 | | |
| 289 | | WRITE_LINE_MEMBER(carpolo_state::coin2_interrupt_clear_w) |
| 290 | | { |
| 291 | | m_ttl7474_2s_2->clear_w(state); |
| 292 | | } |
| 293 | | |
| 294 | | WRITE_LINE_MEMBER(carpolo_state::coin3_interrupt_clear_w) |
| 295 | | { |
| 296 | | m_ttl7474_2u_1->clear_w(state); |
| 297 | | } |
| 298 | | |
| 299 | | WRITE_LINE_MEMBER(carpolo_state::coin4_interrupt_clear_w) |
| 300 | | { |
| 301 | | m_ttl7474_2u_2->clear_w(state); |
| 302 | | } |
| 303 | | |
| 304 | | WRITE8_MEMBER(carpolo_state::carpolo_ball_screen_interrupt_clear_w) |
| 305 | | { |
| 306 | | m_ttl74148_3s->input_line_w(BALL_SCREEN_PRIORITY_LINE, 1); |
| 307 | | m_ttl74148_3s->update(); |
| 308 | | } |
| 309 | | |
| 310 | | WRITE8_MEMBER(carpolo_state::carpolo_car_car_interrupt_clear_w) |
| 311 | | { |
| 312 | | m_ttl74148_3s->input_line_w(CAR_CAR_PRIORITY_LINE, 1); |
| 313 | | m_ttl74148_3s->update(); |
| 314 | | } |
| 315 | | |
| 316 | | WRITE8_MEMBER(carpolo_state::carpolo_car_goal_interrupt_clear_w) |
| 317 | | { |
| 318 | | m_ttl74148_3s->input_line_w(CAR_GOAL_PRIORITY_LINE, 1); |
| 319 | | m_ttl74148_3s->update(); |
| 320 | | } |
| 321 | | |
| 322 | | WRITE8_MEMBER(carpolo_state::carpolo_car_ball_interrupt_clear_w) |
| 323 | | { |
| 324 | | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 1); |
| 325 | | m_ttl74148_3s->update(); |
| 326 | | } |
| 327 | | |
| 328 | | WRITE8_MEMBER(carpolo_state::carpolo_car_border_interrupt_clear_w) |
| 329 | | { |
| 330 | | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 1); |
| 331 | | m_ttl74148_3s->update(); |
| 332 | | } |
| 333 | | |
| 334 | | WRITE8_MEMBER(carpolo_state::carpolo_timer_interrupt_clear_w) |
| 335 | | { |
| 336 | | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 1); |
| 337 | | m_ttl74148_3s->update(); |
| 338 | | } |
| 339 | | |
| 340 | | |
| 341 | | /************************************* |
| 342 | | * |
| 343 | | * Input port handling |
| 344 | | * |
| 345 | | *************************************/ |
| 346 | | |
| 347 | | WRITE8_MEMBER(carpolo_state::pia_0_port_a_w) |
| 348 | | { |
| 349 | | /* bit 0 - Coin counter |
| 350 | | bit 1 - Player 4 crash sound |
| 351 | | bit 2 - Player 3 crash sound |
| 352 | | bit 3 - Clear steering wheel logic |
| 353 | | bit 4 - Player 2 crash sound |
| 354 | | bit 5 - Score pulse sound |
| 355 | | bit 6 - Player 1 crash sound |
| 356 | | bit 7 - Ball hit pulse sound */ |
| 357 | | |
| 358 | | coin_counter_w(machine(), 0, data & 0x01); |
| 359 | | |
| 360 | | |
| 361 | | m_ttl7474_1f_1->clear_w((data & 0x08) >> 3); |
| 362 | | m_ttl7474_1d_1->clear_w((data & 0x08) >> 3); |
| 363 | | m_ttl7474_1c_1->clear_w((data & 0x08) >> 3); |
| 364 | | m_ttl7474_1a_1->clear_w((data & 0x08) >> 3); |
| 365 | | } |
| 366 | | |
| 367 | | |
| 368 | | WRITE8_MEMBER(carpolo_state::pia_0_port_b_w) |
| 369 | | { |
| 370 | | /* bit 0 - Strobe speed bits sound |
| 371 | | bit 1 - Speed bit 0 sound |
| 372 | | bit 2 - Speed bit 1 sound |
| 373 | | bit 3 - Speed bit 2 sound |
| 374 | | bit 6 - Select pedal 0 |
| 375 | | bit 7 - Select pdeal 1 */ |
| 376 | | |
| 377 | | m_ttl74153_1k->a_w(data & 0x40); |
| 378 | | m_ttl74153_1k->b_w(data & 0x80); |
| 379 | | |
| 380 | | m_ttl74153_1k->update(); |
| 381 | | } |
| 382 | | |
| 383 | | READ8_MEMBER(carpolo_state::pia_0_port_b_r) |
| 384 | | { |
| 385 | | /* bit 4 - Pedal bit 0 |
| 386 | | bit 5 - Pedal bit 1 */ |
| 387 | | |
| 388 | | return (m_ttl74153_1k->output_r(0) << 5) | |
| 389 | | (m_ttl74153_1k->output_r(1) << 4); |
| 390 | | } |
| 391 | | |
| 392 | | |
| 393 | | READ8_MEMBER(carpolo_state::pia_1_port_a_r) |
| 394 | | { |
| 395 | | UINT8 ret; |
| 396 | | |
| 397 | | /* bit 0 - Player 4 steering input (left or right) |
| 398 | | bit 1 - Player 3 steering input (left or right) |
| 399 | | bit 2 - Player 2 steering input (left or right) |
| 400 | | bit 3 - Player 1 steering input (left or right) |
| 401 | | bit 4 - Player 4 forward/reverse input |
| 402 | | bit 5 - Player 3 forward/reverse input |
| 403 | | bit 6 - Player 2 forward/reverse input |
| 404 | | bit 7 - Player 1 forward/reverse input */ |
| 405 | | |
| 406 | | ret = (m_ttl7474_1a_2->output_r() ? 0x01 : 0x00) | |
| 407 | | (m_ttl7474_1c_2->output_r() ? 0x02 : 0x00) | |
| 408 | | (m_ttl7474_1d_2->output_r() ? 0x04 : 0x00) | |
| 409 | | (m_ttl7474_1f_2->output_r() ? 0x08 : 0x00) | |
| 410 | | (ioport("IN2")->read() & 0xf0); |
| 411 | | |
| 412 | | return ret; |
| 413 | | } |
| 414 | | |
| 415 | | |
| 416 | | READ8_MEMBER(carpolo_state::pia_1_port_b_r) |
| 417 | | { |
| 418 | | UINT8 ret; |
| 419 | | |
| 420 | | /* bit 4 - Player 4 steering input (wheel moving or stopped) |
| 421 | | bit 5 - Player 3 steering input (wheel moving or stopped) |
| 422 | | bit 6 - Player 2 steering input (wheel moving or stopped) |
| 423 | | bit 7 - Player 1 steering input (wheel moving or stopped) */ |
| 424 | | |
| 425 | | ret = (m_ttl7474_1a_1->output_r() ? 0x10 : 0x00) | |
| 426 | | (m_ttl7474_1c_1->output_r() ? 0x20 : 0x00) | |
| 427 | | (m_ttl7474_1d_1->output_r() ? 0x40 : 0x00) | |
| 428 | | (m_ttl7474_1f_1->output_r() ? 0x80 : 0x00); |
| 429 | | |
| 430 | | return ret; |
| 431 | | } |
| 432 | | |
| 433 | | void carpolo_state::machine_start() |
| 434 | | { |
| 435 | | save_item(NAME(m_ball_screen_collision_cause)); |
| 436 | | save_item(NAME(m_car_ball_collision_x)); |
| 437 | | save_item(NAME(m_car_ball_collision_y)); |
| 438 | | save_item(NAME(m_car_car_collision_cause)); |
| 439 | | save_item(NAME(m_car_goal_collision_cause)); |
| 440 | | save_item(NAME(m_car_ball_collision_cause)); |
| 441 | | save_item(NAME(m_car_border_collision_cause)); |
| 442 | | save_item(NAME(m_priority_0_extension)); |
| 443 | | save_item(NAME(m_last_wheel_value)); |
| 444 | | } |
| 445 | | |
| 446 | | void carpolo_state::machine_reset() |
| 447 | | { |
| 448 | | /* set up the priority encoder */ |
| 449 | | m_ttl74148_3s->enable_input_w(0); /* always enabled */ |
| 450 | | |
| 451 | | /* set up the coin handling flip-flops */ |
| 452 | | m_ttl7474_2s_1->d_w (1); |
| 453 | | m_ttl7474_2s_1->preset_w(1); |
| 454 | | |
| 455 | | m_ttl7474_2s_2->d_w (1); |
| 456 | | m_ttl7474_2s_2->preset_w(1); |
| 457 | | |
| 458 | | m_ttl7474_2u_1->d_w (1); |
| 459 | | m_ttl7474_2u_1->preset_w(1); |
| 460 | | |
| 461 | | m_ttl7474_2u_2->d_w (1); |
| 462 | | m_ttl7474_2u_2->preset_w(1); |
| 463 | | |
| 464 | | |
| 465 | | /* set up the steering handling flip-flops */ |
| 466 | | m_ttl7474_1f_1->d_w (1); |
| 467 | | m_ttl7474_1f_1->preset_w(1); |
| 468 | | |
| 469 | | m_ttl7474_1f_2->clear_w (1); |
| 470 | | m_ttl7474_1f_2->preset_w(1); |
| 471 | | |
| 472 | | m_ttl7474_1d_1->d_w (1); |
| 473 | | m_ttl7474_1d_1->preset_w(1); |
| 474 | | |
| 475 | | m_ttl7474_1d_2->clear_w (1); |
| 476 | | m_ttl7474_1d_2->preset_w(1); |
| 477 | | |
| 478 | | m_ttl7474_1c_1->d_w (1); |
| 479 | | m_ttl7474_1c_1->preset_w(1); |
| 480 | | |
| 481 | | m_ttl7474_1c_2->clear_w (1); |
| 482 | | m_ttl7474_1c_2->preset_w(1); |
| 483 | | |
| 484 | | m_ttl7474_1a_1->d_w (1); |
| 485 | | m_ttl7474_1a_1->preset_w(1); |
| 486 | | |
| 487 | | m_ttl7474_1a_2->clear_w (1); |
| 488 | | m_ttl7474_1a_2->preset_w(1); |
| 489 | | |
| 490 | | |
| 491 | | /* set up the pedal handling chips */ |
| 492 | | m_ttl74153_1k->enable_w(0, 0); |
| 493 | | m_ttl74153_1k->enable_w(1, 0); |
| 494 | | } |
trunk/src/mame/machine/carpolo.cpp
| r0 | r250161 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:Zsolt Vasvari |
| 3 | /*************************************************************************** |
| 4 | |
| 5 | Exidy Car Polo hardware |
| 6 | |
| 7 | driver by Zsolt Vasvari |
| 8 | |
| 9 | ****************************************************************************/ |
| 10 | |
| 11 | #include "emu.h" |
| 12 | #include "cpu/m6502/m6502.h" |
| 13 | #include "machine/6821pia.h" |
| 14 | #include "includes/carpolo.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 | TTL74148_OUTPUT_CB(carpolo_state::ttl74148_3s_cb) |
| 61 | { |
| 62 | m_maincpu->set_input_line(M6502_IRQ_LINE, m_ttl74148_3s->output_valid_r() ? CLEAR_LINE : ASSERT_LINE); |
| 63 | } |
| 64 | |
| 65 | |
| 66 | /* the outputs of the flip-flops are connected to the priority encoder */ |
| 67 | WRITE_LINE_MEMBER(carpolo_state::carpolo_7474_2s_1_q_cb) |
| 68 | { |
| 69 | m_ttl74148_3s->input_line_w(COIN1_PRIORITY_LINE, state); |
| 70 | m_ttl74148_3s->update(); |
| 71 | } |
| 72 | |
| 73 | WRITE_LINE_MEMBER(carpolo_state::carpolo_7474_2s_2_q_cb) |
| 74 | { |
| 75 | m_ttl74148_3s->input_line_w(COIN2_PRIORITY_LINE, state); |
| 76 | m_ttl74148_3s->update(); |
| 77 | } |
| 78 | |
| 79 | WRITE_LINE_MEMBER(carpolo_state::carpolo_7474_2u_1_q_cb) |
| 80 | { |
| 81 | m_ttl74148_3s->input_line_w(COIN3_PRIORITY_LINE, state); |
| 82 | m_ttl74148_3s->update(); |
| 83 | } |
| 84 | |
| 85 | WRITE_LINE_MEMBER(carpolo_state::carpolo_7474_2u_2_q_cb) |
| 86 | { |
| 87 | m_ttl74148_3s->input_line_w(COIN4_PRIORITY_LINE, state); |
| 88 | m_ttl74148_3s->update(); |
| 89 | } |
| 90 | |
| 91 | |
| 92 | void carpolo_state::carpolo_generate_ball_screen_interrupt(UINT8 cause) |
| 93 | { |
| 94 | m_ball_screen_collision_cause = cause; |
| 95 | |
| 96 | m_ttl74148_3s->input_line_w(BALL_SCREEN_PRIORITY_LINE, 0); |
| 97 | m_ttl74148_3s->update(); |
| 98 | } |
| 99 | |
| 100 | void carpolo_state::carpolo_generate_car_car_interrupt(int car1, int car2) |
| 101 | { |
| 102 | m_car_car_collision_cause = ~((1 << (3 - car1)) | (1 << (3 - car2))); |
| 103 | |
| 104 | m_ttl74148_3s->input_line_w(CAR_CAR_PRIORITY_LINE, 0); |
| 105 | m_ttl74148_3s->update(); |
| 106 | } |
| 107 | |
| 108 | void carpolo_state::carpolo_generate_car_goal_interrupt(int car, int right_goal) |
| 109 | { |
| 110 | m_car_goal_collision_cause = car | (right_goal ? 0x08 : 0x00); |
| 111 | |
| 112 | m_ttl74148_3s->input_line_w(CAR_GOAL_PRIORITY_LINE, 0); |
| 113 | m_ttl74148_3s->update(); |
| 114 | } |
| 115 | |
| 116 | void carpolo_state::carpolo_generate_car_ball_interrupt(int car, int car_x, int car_y) |
| 117 | { |
| 118 | m_car_ball_collision_cause = car; |
| 119 | m_car_ball_collision_x = car_x; |
| 120 | m_car_ball_collision_y = car_y; |
| 121 | |
| 122 | m_priority_0_extension = CAR_BALL_EXTRA_BITS; |
| 123 | |
| 124 | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 0); |
| 125 | m_ttl74148_3s->update(); |
| 126 | } |
| 127 | |
| 128 | void carpolo_state::carpolo_generate_car_border_interrupt(int car, int horizontal_border) |
| 129 | { |
| 130 | m_car_border_collision_cause = car | (horizontal_border ? 0x04 : 0x00); |
| 131 | |
| 132 | m_priority_0_extension = CAR_BORDER_EXTRA_BITS; |
| 133 | |
| 134 | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 0); |
| 135 | m_ttl74148_3s->update(); |
| 136 | } |
| 137 | |
| 138 | |
| 139 | READ8_MEMBER(carpolo_state::carpolo_ball_screen_collision_cause_r) |
| 140 | { |
| 141 | /* bit 0 - 0=ball collided with border |
| 142 | bit 1 - 0=ball collided with goal |
| 143 | bit 2 - 0=ball collided with score area |
| 144 | bit 3 - which goal/score collided (0=left, 1=right) */ |
| 145 | return m_ball_screen_collision_cause; |
| 146 | } |
| 147 | |
| 148 | READ8_MEMBER(carpolo_state::carpolo_car_ball_collision_x_r) |
| 149 | { |
| 150 | /* the x coordinate of the colliding pixel */ |
| 151 | return m_car_ball_collision_x; |
| 152 | } |
| 153 | |
| 154 | READ8_MEMBER(carpolo_state::carpolo_car_ball_collision_y_r) |
| 155 | { |
| 156 | /* the y coordinate of the colliding pixel */ |
| 157 | return m_car_ball_collision_y; |
| 158 | } |
| 159 | |
| 160 | READ8_MEMBER(carpolo_state::carpolo_car_car_collision_cause_r) |
| 161 | { |
| 162 | /* bit 0 - car 4 collided |
| 163 | bit 1 - car 3 collided |
| 164 | bit 2 - car 2 collided |
| 165 | bit 3 - car 1 collided */ |
| 166 | return m_car_car_collision_cause; |
| 167 | } |
| 168 | |
| 169 | READ8_MEMBER(carpolo_state::carpolo_car_goal_collision_cause_r) |
| 170 | { |
| 171 | /* bit 0-1 - which car collided |
| 172 | bit 2 - horizontal timing bit 1TEC4 (not accessed) |
| 173 | bit 3 - which goal collided (0=left, 1=right) */ |
| 174 | return m_car_goal_collision_cause; |
| 175 | } |
| 176 | |
| 177 | READ8_MEMBER(carpolo_state::carpolo_car_ball_collision_cause_r) |
| 178 | { |
| 179 | /* bit 0-1 - which car collided |
| 180 | bit 2-3 - unconnected */ |
| 181 | return m_car_ball_collision_cause; |
| 182 | } |
| 183 | |
| 184 | READ8_MEMBER(carpolo_state::carpolo_car_border_collision_cause_r) |
| 185 | { |
| 186 | /* bit 0-1 - which car collided |
| 187 | bit 2 - 0=vertical border, 1=horizontal border */ |
| 188 | return m_car_border_collision_cause; |
| 189 | } |
| 190 | |
| 191 | |
| 192 | READ8_MEMBER(carpolo_state::carpolo_interrupt_cause_r) |
| 193 | { |
| 194 | /* the output of the 148 goes to bits 1-3 (which is priority ^ 7) */ |
| 195 | return (m_ttl74148_3s->output_r() << 1) | m_priority_0_extension; |
| 196 | } |
| 197 | |
| 198 | |
| 199 | INTERRUPT_GEN_MEMBER(carpolo_state::carpolo_timer_interrupt) |
| 200 | { |
| 201 | UINT8 port_value; |
| 202 | int player; |
| 203 | |
| 204 | |
| 205 | /* cause the timer interrupt */ |
| 206 | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 0); |
| 207 | m_priority_0_extension = TIMER_EXTRA_BITS; |
| 208 | |
| 209 | m_ttl74148_3s->update(); |
| 210 | |
| 211 | |
| 212 | /* check the coins here as well - they drive the clock of the flip-flops */ |
| 213 | port_value = ioport("IN0")->read(); |
| 214 | |
| 215 | m_ttl7474_2s_1->clock_w((port_value & 0x01) >> 0); |
| 216 | m_ttl7474_2s_2->clock_w((port_value & 0x02) >> 1); |
| 217 | m_ttl7474_2u_1->clock_w((port_value & 0x04) >> 2); |
| 218 | m_ttl7474_2u_2->clock_w((port_value & 0x08) >> 3); |
| 219 | |
| 220 | /* read the steering controls */ |
| 221 | for (player = 0; player < 4; player++) |
| 222 | { |
| 223 | static const char *const portnames[] = { "DIAL0", "DIAL1", "DIAL2", "DIAL3" }; |
| 224 | ttl7474_device *movement_flip_flop; |
| 225 | ttl7474_device *dir_flip_flop; |
| 226 | |
| 227 | switch (player) |
| 228 | { |
| 229 | default: |
| 230 | case 0: movement_flip_flop = m_ttl7474_1f_1; dir_flip_flop = m_ttl7474_1f_2; break; |
| 231 | case 1: movement_flip_flop = m_ttl7474_1d_1; dir_flip_flop = m_ttl7474_1d_2; break; |
| 232 | case 2: movement_flip_flop = m_ttl7474_1c_1; dir_flip_flop = m_ttl7474_1c_2; break; |
| 233 | case 3: movement_flip_flop = m_ttl7474_1a_1; dir_flip_flop = m_ttl7474_1a_2; break; |
| 234 | } |
| 235 | |
| 236 | port_value = ioport(portnames[player])->read(); |
| 237 | |
| 238 | if (port_value != m_last_wheel_value[player]) |
| 239 | { |
| 240 | /* set the movement direction */ |
| 241 | dir_flip_flop->d_w(((port_value - m_last_wheel_value[player]) & 0x80) ? 1 : 0); |
| 242 | |
| 243 | m_last_wheel_value[player] = port_value; |
| 244 | } |
| 245 | |
| 246 | /* as the wheel moves, both flip-flops are clocked */ |
| 247 | movement_flip_flop->clock_w(port_value & 0x01); |
| 248 | dir_flip_flop->clock_w( port_value & 0x01); |
| 249 | } |
| 250 | |
| 251 | |
| 252 | |
| 253 | /* finally read the accelerator pedals */ |
| 254 | port_value = ioport("PEDALS")->read(); |
| 255 | |
| 256 | for (player = 0; player < 4; player++) |
| 257 | { |
| 258 | /* one line indicates if the pedal is pressed and the other |
| 259 | how much, resulting in only two different possible levels */ |
| 260 | if (port_value & 0x01) |
| 261 | { |
| 262 | m_ttl74153_1k->input_line_w(0, player, 1); |
| 263 | m_ttl74153_1k->input_line_w(1, player, 0); |
| 264 | } |
| 265 | else if (port_value & 0x02) |
| 266 | { |
| 267 | m_ttl74153_1k->input_line_w(0, player, 1); |
| 268 | m_ttl74153_1k->input_line_w(1, player, 1); |
| 269 | } |
| 270 | else |
| 271 | { |
| 272 | m_ttl74153_1k->input_line_w(0, player, 0); |
| 273 | /* the other line is irrelevant */ |
| 274 | } |
| 275 | |
| 276 | port_value >>= 2; |
| 277 | } |
| 278 | |
| 279 | m_ttl74153_1k->update(); |
| 280 | } |
| 281 | |
| 282 | // FIXME: Remove trampolines |
| 283 | |
| 284 | WRITE_LINE_MEMBER(carpolo_state::coin1_interrupt_clear_w) |
| 285 | { |
| 286 | m_ttl7474_2s_1->clear_w(state); |
| 287 | } |
| 288 | |
| 289 | WRITE_LINE_MEMBER(carpolo_state::coin2_interrupt_clear_w) |
| 290 | { |
| 291 | m_ttl7474_2s_2->clear_w(state); |
| 292 | } |
| 293 | |
| 294 | WRITE_LINE_MEMBER(carpolo_state::coin3_interrupt_clear_w) |
| 295 | { |
| 296 | m_ttl7474_2u_1->clear_w(state); |
| 297 | } |
| 298 | |
| 299 | WRITE_LINE_MEMBER(carpolo_state::coin4_interrupt_clear_w) |
| 300 | { |
| 301 | m_ttl7474_2u_2->clear_w(state); |
| 302 | } |
| 303 | |
| 304 | WRITE8_MEMBER(carpolo_state::carpolo_ball_screen_interrupt_clear_w) |
| 305 | { |
| 306 | m_ttl74148_3s->input_line_w(BALL_SCREEN_PRIORITY_LINE, 1); |
| 307 | m_ttl74148_3s->update(); |
| 308 | } |
| 309 | |
| 310 | WRITE8_MEMBER(carpolo_state::carpolo_car_car_interrupt_clear_w) |
| 311 | { |
| 312 | m_ttl74148_3s->input_line_w(CAR_CAR_PRIORITY_LINE, 1); |
| 313 | m_ttl74148_3s->update(); |
| 314 | } |
| 315 | |
| 316 | WRITE8_MEMBER(carpolo_state::carpolo_car_goal_interrupt_clear_w) |
| 317 | { |
| 318 | m_ttl74148_3s->input_line_w(CAR_GOAL_PRIORITY_LINE, 1); |
| 319 | m_ttl74148_3s->update(); |
| 320 | } |
| 321 | |
| 322 | WRITE8_MEMBER(carpolo_state::carpolo_car_ball_interrupt_clear_w) |
| 323 | { |
| 324 | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 1); |
| 325 | m_ttl74148_3s->update(); |
| 326 | } |
| 327 | |
| 328 | WRITE8_MEMBER(carpolo_state::carpolo_car_border_interrupt_clear_w) |
| 329 | { |
| 330 | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 1); |
| 331 | m_ttl74148_3s->update(); |
| 332 | } |
| 333 | |
| 334 | WRITE8_MEMBER(carpolo_state::carpolo_timer_interrupt_clear_w) |
| 335 | { |
| 336 | m_ttl74148_3s->input_line_w(PRI0_PRIORTITY_LINE, 1); |
| 337 | m_ttl74148_3s->update(); |
| 338 | } |
| 339 | |
| 340 | |
| 341 | /************************************* |
| 342 | * |
| 343 | * Input port handling |
| 344 | * |
| 345 | *************************************/ |
| 346 | |
| 347 | WRITE8_MEMBER(carpolo_state::pia_0_port_a_w) |
| 348 | { |
| 349 | /* bit 0 - Coin counter |
| 350 | bit 1 - Player 4 crash sound |
| 351 | bit 2 - Player 3 crash sound |
| 352 | bit 3 - Clear steering wheel logic |
| 353 | bit 4 - Player 2 crash sound |
| 354 | bit 5 - Score pulse sound |
| 355 | bit 6 - Player 1 crash sound |
| 356 | bit 7 - Ball hit pulse sound */ |
| 357 | |
| 358 | coin_counter_w(machine(), 0, data & 0x01); |
| 359 | |
| 360 | |
| 361 | m_ttl7474_1f_1->clear_w((data & 0x08) >> 3); |
| 362 | m_ttl7474_1d_1->clear_w((data & 0x08) >> 3); |
| 363 | m_ttl7474_1c_1->clear_w((data & 0x08) >> 3); |
| 364 | m_ttl7474_1a_1->clear_w((data & 0x08) >> 3); |
| 365 | } |
| 366 | |
| 367 | |
| 368 | WRITE8_MEMBER(carpolo_state::pia_0_port_b_w) |
| 369 | { |
| 370 | /* bit 0 - Strobe speed bits sound |
| 371 | bit 1 - Speed bit 0 sound |
| 372 | bit 2 - Speed bit 1 sound |
| 373 | bit 3 - Speed bit 2 sound |
| 374 | bit 6 - Select pedal 0 |
| 375 | bit 7 - Select pdeal 1 */ |
| 376 | |
| 377 | m_ttl74153_1k->a_w(data & 0x40); |
| 378 | m_ttl74153_1k->b_w(data & 0x80); |
| 379 | |
| 380 | m_ttl74153_1k->update(); |
| 381 | } |
| 382 | |
| 383 | READ8_MEMBER(carpolo_state::pia_0_port_b_r) |
| 384 | { |
| 385 | /* bit 4 - Pedal bit 0 |
| 386 | bit 5 - Pedal bit 1 */ |
| 387 | |
| 388 | return (m_ttl74153_1k->output_r(0) << 5) | |
| 389 | (m_ttl74153_1k->output_r(1) << 4); |
| 390 | } |
| 391 | |
| 392 | |
| 393 | READ8_MEMBER(carpolo_state::pia_1_port_a_r) |
| 394 | { |
| 395 | UINT8 ret; |
| 396 | |
| 397 | /* bit 0 - Player 4 steering input (left or right) |
| 398 | bit 1 - Player 3 steering input (left or right) |
| 399 | bit 2 - Player 2 steering input (left or right) |
| 400 | bit 3 - Player 1 steering input (left or right) |
| 401 | bit 4 - Player 4 forward/reverse input |
| 402 | bit 5 - Player 3 forward/reverse input |
| 403 | bit 6 - Player 2 forward/reverse input |
| 404 | bit 7 - Player 1 forward/reverse input */ |
| 405 | |
| 406 | ret = (m_ttl7474_1a_2->output_r() ? 0x01 : 0x00) | |
| 407 | (m_ttl7474_1c_2->output_r() ? 0x02 : 0x00) | |
| 408 | (m_ttl7474_1d_2->output_r() ? 0x04 : 0x00) | |
| 409 | (m_ttl7474_1f_2->output_r() ? 0x08 : 0x00) | |
| 410 | (ioport("IN2")->read() & 0xf0); |
| 411 | |
| 412 | return ret; |
| 413 | } |
| 414 | |
| 415 | |
| 416 | READ8_MEMBER(carpolo_state::pia_1_port_b_r) |
| 417 | { |
| 418 | UINT8 ret; |
| 419 | |
| 420 | /* bit 4 - Player 4 steering input (wheel moving or stopped) |
| 421 | bit 5 - Player 3 steering input (wheel moving or stopped) |
| 422 | bit 6 - Player 2 steering input (wheel moving or stopped) |
| 423 | bit 7 - Player 1 steering input (wheel moving or stopped) */ |
| 424 | |
| 425 | ret = (m_ttl7474_1a_1->output_r() ? 0x10 : 0x00) | |
| 426 | (m_ttl7474_1c_1->output_r() ? 0x20 : 0x00) | |
| 427 | (m_ttl7474_1d_1->output_r() ? 0x40 : 0x00) | |
| 428 | (m_ttl7474_1f_1->output_r() ? 0x80 : 0x00); |
| 429 | |
| 430 | return ret; |
| 431 | } |
| 432 | |
| 433 | void carpolo_state::machine_start() |
| 434 | { |
| 435 | save_item(NAME(m_ball_screen_collision_cause)); |
| 436 | save_item(NAME(m_car_ball_collision_x)); |
| 437 | save_item(NAME(m_car_ball_collision_y)); |
| 438 | save_item(NAME(m_car_car_collision_cause)); |
| 439 | save_item(NAME(m_car_goal_collision_cause)); |
| 440 | save_item(NAME(m_car_ball_collision_cause)); |
| 441 | save_item(NAME(m_car_border_collision_cause)); |
| 442 | save_item(NAME(m_priority_0_extension)); |
| 443 | save_item(NAME(m_last_wheel_value)); |
| 444 | } |
| 445 | |
| 446 | void carpolo_state::machine_reset() |
| 447 | { |
| 448 | /* set up the priority encoder */ |
| 449 | m_ttl74148_3s->enable_input_w(0); /* always enabled */ |
| 450 | |
| 451 | /* set up the coin handling flip-flops */ |
| 452 | m_ttl7474_2s_1->d_w (1); |
| 453 | m_ttl7474_2s_1->preset_w(1); |
| 454 | |
| 455 | m_ttl7474_2s_2->d_w (1); |
| 456 | m_ttl7474_2s_2->preset_w(1); |
| 457 | |
| 458 | m_ttl7474_2u_1->d_w (1); |
| 459 | m_ttl7474_2u_1->preset_w(1); |
| 460 | |
| 461 | m_ttl7474_2u_2->d_w (1); |
| 462 | m_ttl7474_2u_2->preset_w(1); |
| 463 | |
| 464 | |
| 465 | /* set up the steering handling flip-flops */ |
| 466 | m_ttl7474_1f_1->d_w (1); |
| 467 | m_ttl7474_1f_1->preset_w(1); |
| 468 | |
| 469 | m_ttl7474_1f_2->clear_w (1); |
| 470 | m_ttl7474_1f_2->preset_w(1); |
| 471 | |
| 472 | m_ttl7474_1d_1->d_w (1); |
| 473 | m_ttl7474_1d_1->preset_w(1); |
| 474 | |
| 475 | m_ttl7474_1d_2->clear_w (1); |
| 476 | m_ttl7474_1d_2->preset_w(1); |
| 477 | |
| 478 | m_ttl7474_1c_1->d_w (1); |
| 479 | m_ttl7474_1c_1->preset_w(1); |
| 480 | |
| 481 | m_ttl7474_1c_2->clear_w (1); |
| 482 | m_ttl7474_1c_2->preset_w(1); |
| 483 | |
| 484 | m_ttl7474_1a_1->d_w (1); |
| 485 | m_ttl7474_1a_1->preset_w(1); |
| 486 | |
| 487 | m_ttl7474_1a_2->clear_w (1); |
| 488 | m_ttl7474_1a_2->preset_w(1); |
| 489 | |
| 490 | |
| 491 | /* set up the pedal handling chips */ |
| 492 | m_ttl74153_1k->enable_w(0, 0); |
| 493 | m_ttl74153_1k->enable_w(1, 0); |
| 494 | } |
trunk/src/mame/video/carpolo.c
| r250160 | r250161 | |
| 1 | | // license:BSD-3-Clause |
| 2 | | // copyright-holders:Zsolt Vasvari |
| 3 | | /*************************************************************************** |
| 4 | | |
| 5 | | Exidy Car Polo hardware |
| 6 | | |
| 7 | | driver by Zsolt Vasvari |
| 8 | | |
| 9 | | ****************************************************************************/ |
| 10 | | |
| 11 | | #include "emu.h" |
| 12 | | #include "includes/carpolo.h" |
| 13 | | |
| 14 | | |
| 15 | | /* the screen elements' priorties determine their color */ |
| 16 | | #define CHARSET_COLOR_BASE (0x00) |
| 17 | | #define BACKGROUND_PEN ((0x00 << 1) + 1) |
| 18 | | #define FIELD_PEN ((0x01 << 1) + 1) |
| 19 | | #define CAR1_COLOR (0x02) |
| 20 | | #define LINE_PEN ((0x03 << 1) + 1) |
| 21 | | #define CAR4_COLOR (0x04) |
| 22 | | #define CAR3_COLOR (0x05) |
| 23 | | #define CAR2_COLOR (0x06) |
| 24 | | #define BALL_COLOR (0x07) |
| 25 | | #define NET_COLOR (0x08) |
| 26 | | #define LEFT_GOAL_COLOR (0x09) |
| 27 | | #define LEFT_GOAL_PEN (0x18 + 0x08) |
| 28 | | #define LEFT_SCORE_PEN (0x18 + 0x06) |
| 29 | | #define RIGHT_GOAL_COLOR (0x0a) |
| 30 | | #define RIGHT_GOAL_PEN (0x18 + 0x18) |
| 31 | | #define RIGHT_SCORE_PEN (0x18 + 0x16) |
| 32 | | #define SPECIAL_CHAR_COLOR (0x0b) |
| 33 | | #define ALPHA_COLOR_BASE (0x0c) /* 0x0c - 0x0f */ |
| 34 | | |
| 35 | | #define SPRITE_WIDTH (16) |
| 36 | | #define SPRITE_HEIGHT (16) |
| 37 | | #define GOAL_WIDTH (16) |
| 38 | | #define GOAL_HEIGHT (64) |
| 39 | | |
| 40 | | #define LEFT_GOAL_X ((2 * 16) - 8) |
| 41 | | #define RIGHT_GOAL_X ((13 * 16) - 8) |
| 42 | | #define GOAL_Y (7 * 16) |
| 43 | | |
| 44 | | #define TOP_BORDER (16) |
| 45 | | #define BOTTOM_BORDER (255) |
| 46 | | #define LEFT_BORDER (0) |
| 47 | | #define RIGHT_BORDER (239) |
| 48 | | |
| 49 | | |
| 50 | | |
| 51 | | |
| 52 | | /*************************************************************************** |
| 53 | | * |
| 54 | | * Palette generation |
| 55 | | * |
| 56 | | * The palette PROM is connected to the RGB output this way. |
| 57 | | * |
| 58 | | * bit 0 -- 220 ohm resistor -- BLUE (probably an error on schematics) |
| 59 | | * -- 470 ohm resistor -- BLUE (probably an error on schematics) |
| 60 | | * -- 220 ohm resistor -- GREEN |
| 61 | | * -- 470 ohm resistor -- GREEN |
| 62 | | * -- 1 kohm resistor -- GREEN |
| 63 | | * -- 220 ohm resistor -- RED |
| 64 | | * -- 470 ohm resistor -- RED |
| 65 | | * bit 7 -- 1 kohm resistor -- RED |
| 66 | | * |
| 67 | | **************************************************************************/ |
| 68 | | |
| 69 | | PALETTE_INIT_MEMBER(carpolo_state, carpolo) |
| 70 | | { |
| 71 | | const UINT8 *color_prom = memregion("proms")->base(); |
| 72 | | int i; |
| 73 | | |
| 74 | | /* thanks to Jarek Burczynski for analyzing the circuit */ |
| 75 | | /* static const float MAX_VOLTAGE = 6.9620f; */ |
| 76 | | static const float MIN_VOLTAGE = 1.7434f; |
| 77 | | static const float MAX_VOLTAGE = 5.5266f; |
| 78 | | |
| 79 | | static const float r_voltage[] = |
| 80 | | { |
| 81 | | 1.7434f, 2.1693f, 2.5823f, 3.0585f, 3.4811f, 4.0707f, 4.7415f, 5.4251f |
| 82 | | }; |
| 83 | | |
| 84 | | static const float g_voltage[] = |
| 85 | | { |
| 86 | | 1.7434f, 2.1693f, 2.5823f, 3.0585f, 3.4811f, 4.0707f, 4.7415f, 5.4251f |
| 87 | | /* 4.7871f, 5.0613f, 5.3079f, 5.6114f, 5.7940f, 6.1608f, 6.5436f, 6.9620f */ |
| 88 | | }; |
| 89 | | |
| 90 | | static const float b_voltage[] = |
| 91 | | { |
| 92 | | 1.9176f, 2.8757f, 3.9825f, 5.5266f |
| 93 | | }; |
| 94 | | |
| 95 | | |
| 96 | | for (i = 0; i < palette.entries(); i++) |
| 97 | | { |
| 98 | | UINT8 pen, r, g, b; |
| 99 | | |
| 100 | | if (i < 0x18) |
| 101 | | /* sprites */ |
| 102 | | pen = ((i - 0x00) & 0x01) ? CHARSET_COLOR_BASE + ((i - 0x00) >> 1) : 0; |
| 103 | | |
| 104 | | else if (i < 0x38) |
| 105 | | /* the bits in the goal gfx PROM are hooked up as follows (all active LO): |
| 106 | | D3 - goal post |
| 107 | | D2 - scoring area |
| 108 | | D1 - net |
| 109 | | D0 - n/c |
| 110 | | I am only filling in the colors actually used. */ |
| 111 | | switch (i - 0x18) |
| 112 | | { |
| 113 | | case (0x00 | (0x07 ^ 0x0f)): pen = LEFT_GOAL_COLOR; break; |
| 114 | | case (0x00 | (0x0d ^ 0x0f)): pen = NET_COLOR; break; |
| 115 | | case (0x00 | (0x09 ^ 0x0f)): pen = NET_COLOR; break; /* score */ |
| 116 | | case (0x10 | (0x07 ^ 0x0f)): pen = RIGHT_GOAL_COLOR; break; |
| 117 | | case (0x10 | (0x0d ^ 0x0f)): pen = NET_COLOR; break; |
| 118 | | case (0x10 | (0x09 ^ 0x0f)): pen = NET_COLOR; break; /* score */ |
| 119 | | default: pen = 0; break; |
| 120 | | } |
| 121 | | |
| 122 | | else |
| 123 | | /* alpha layer */ |
| 124 | | pen = ((i - 0x38) & 0x01) ? ALPHA_COLOR_BASE + ((i - 0x38) >> 1) : 0; |
| 125 | | |
| 126 | | /* red component */ |
| 127 | | r = ((r_voltage[(color_prom[pen] >> 5) & 0x07] - MIN_VOLTAGE) / (MAX_VOLTAGE - MIN_VOLTAGE)) * 255.0f; |
| 128 | | |
| 129 | | /* green component */ |
| 130 | | g = ((g_voltage[(color_prom[pen] >> 2) & 0x07] - MIN_VOLTAGE) / (MAX_VOLTAGE - MIN_VOLTAGE)) * 255.0f; |
| 131 | | |
| 132 | | /* blue component */ |
| 133 | | b = ((b_voltage[(color_prom[pen] >> 0) & 0x03] - MIN_VOLTAGE) / (MAX_VOLTAGE - MIN_VOLTAGE)) * 255.0f; |
| 134 | | |
| 135 | | palette.set_pen_color(i, rgb_t(r, g, b)); |
| 136 | | } |
| 137 | | } |
| 138 | | |
| 139 | | |
| 140 | | /************************************* |
| 141 | | * |
| 142 | | * Video system start |
| 143 | | * |
| 144 | | *************************************/ |
| 145 | | |
| 146 | | void carpolo_state::video_start() |
| 147 | | { |
| 148 | | m_sprite_sprite_collision_bitmap1 = auto_bitmap_ind16_alloc(machine(), SPRITE_WIDTH*2, SPRITE_HEIGHT*2); |
| 149 | | m_sprite_sprite_collision_bitmap2 = auto_bitmap_ind16_alloc(machine(), SPRITE_WIDTH*2, SPRITE_HEIGHT*2); |
| 150 | | |
| 151 | | m_sprite_goal_collision_bitmap1 = auto_bitmap_ind16_alloc(machine(), SPRITE_WIDTH+GOAL_WIDTH, SPRITE_HEIGHT+GOAL_HEIGHT); |
| 152 | | m_sprite_goal_collision_bitmap2 = auto_bitmap_ind16_alloc(machine(), SPRITE_WIDTH+GOAL_WIDTH, SPRITE_HEIGHT+GOAL_HEIGHT); |
| 153 | | |
| 154 | | m_sprite_border_collision_bitmap = auto_bitmap_ind16_alloc(machine(), SPRITE_WIDTH, SPRITE_HEIGHT); |
| 155 | | |
| 156 | | save_item(NAME(*m_sprite_sprite_collision_bitmap1)); |
| 157 | | save_item(NAME(*m_sprite_sprite_collision_bitmap2)); |
| 158 | | save_item(NAME(*m_sprite_goal_collision_bitmap1)); |
| 159 | | save_item(NAME(*m_sprite_goal_collision_bitmap2)); |
| 160 | | save_item(NAME(*m_sprite_border_collision_bitmap)); |
| 161 | | } |
| 162 | | |
| 163 | | |
| 164 | | /************************************* |
| 165 | | * |
| 166 | | * Core video refresh |
| 167 | | * |
| 168 | | *************************************/ |
| 169 | | |
| 170 | | void carpolo_state::draw_alpha_line(bitmap_ind16 &bitmap, const rectangle &cliprect, |
| 171 | | int alpha_line, int video_line) |
| 172 | | { |
| 173 | | for (int x = 0; x < 32; x++) |
| 174 | | { |
| 175 | | UINT8 code, col; |
| 176 | | |
| 177 | | code = m_alpharam[alpha_line * 32 + x] >> 2; |
| 178 | | col = m_alpharam[alpha_line * 32 + x] & 0x03; |
| 179 | | |
| 180 | | m_gfxdecode->gfx(2)->transpen(bitmap,cliprect, |
| 181 | | code,col, |
| 182 | | 0,0, |
| 183 | | x*8,video_line*8,0); |
| 184 | | } |
| 185 | | } |
| 186 | | |
| 187 | | |
| 188 | | void carpolo_state::remap_sprite_code(int bank, int code, int *remapped_code, int *flipy) |
| 189 | | { |
| 190 | | UINT8* PROM = memregion("user1")->base(); |
| 191 | | |
| 192 | | code = (bank << 4) | code; |
| 193 | | *remapped_code = PROM[code] & 0x0f; |
| 194 | | *flipy = (PROM[code] & 0x10) >> 4; |
| 195 | | } |
| 196 | | |
| 197 | | |
| 198 | | void carpolo_state::draw_sprite(bitmap_ind16 &bitmap, const rectangle &cliprect, |
| 199 | | UINT8 x, UINT8 y, int bank, int code, int col) |
| 200 | | { |
| 201 | | int remapped_code, flipy; |
| 202 | | |
| 203 | | remap_sprite_code(bank, code, &remapped_code, &flipy); |
| 204 | | |
| 205 | | x = 240 - x; |
| 206 | | y = 240 - y; |
| 207 | | |
| 208 | | m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, |
| 209 | | remapped_code, col, |
| 210 | | 0, flipy, |
| 211 | | x, y,0); |
| 212 | | |
| 213 | | /* draw with wrap around */ |
| 214 | | m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, |
| 215 | | remapped_code, col, |
| 216 | | 0, flipy, |
| 217 | | (INT16)x - 256, y,0); |
| 218 | | } |
| 219 | | |
| 220 | | |
| 221 | | UINT32 carpolo_state::screen_update_carpolo(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 222 | | { |
| 223 | | /* draw the playfield elements in the correct priority order */ |
| 224 | | |
| 225 | | /* score area - position determined by bit 4 of the vertical timing PROM */ |
| 226 | | bitmap.plot_box(0,0,RIGHT_BORDER+1,TOP_BORDER,BACKGROUND_PEN); |
| 227 | | |
| 228 | | /* field */ |
| 229 | | bitmap.plot_box(0,TOP_BORDER,RIGHT_BORDER+1,BOTTOM_BORDER-TOP_BORDER+1,FIELD_PEN); |
| 230 | | |
| 231 | | /* car 1 */ |
| 232 | | draw_sprite(bitmap, cliprect, |
| 233 | | m_spriteram[0x00], m_spriteram[0x01], |
| 234 | | 0, m_spriteram[0x0c] & 0x0f, CAR1_COLOR); |
| 235 | | |
| 236 | | /* border - position determined by bit 4 and 7 of the vertical timing PROM */ |
| 237 | | bitmap.plot_box(0,TOP_BORDER, RIGHT_BORDER+1,1,LINE_PEN); |
| 238 | | bitmap.plot_box(0,BOTTOM_BORDER,RIGHT_BORDER+1,1,LINE_PEN); |
| 239 | | bitmap.plot_box(LEFT_BORDER,TOP_BORDER, 1,BOTTOM_BORDER-TOP_BORDER+1,LINE_PEN); |
| 240 | | bitmap.plot_box(RIGHT_BORDER,TOP_BORDER,1,BOTTOM_BORDER-TOP_BORDER+1,LINE_PEN); |
| 241 | | |
| 242 | | /* car 4 */ |
| 243 | | draw_sprite(bitmap, cliprect, |
| 244 | | m_spriteram[0x06], m_spriteram[0x07], |
| 245 | | 0, m_spriteram[0x0d] >> 4, CAR4_COLOR); |
| 246 | | |
| 247 | | /* car 3 */ |
| 248 | | draw_sprite(bitmap, cliprect, |
| 249 | | m_spriteram[0x04], m_spriteram[0x05], |
| 250 | | 0, m_spriteram[0x0d] & 0x0f, CAR3_COLOR); |
| 251 | | |
| 252 | | /* car 2 */ |
| 253 | | draw_sprite(bitmap, cliprect, |
| 254 | | m_spriteram[0x02], m_spriteram[0x03], |
| 255 | | 0, m_spriteram[0x0c] >> 4, CAR2_COLOR); |
| 256 | | |
| 257 | | /* ball */ |
| 258 | | draw_sprite(bitmap, cliprect, |
| 259 | | m_spriteram[0x08], m_spriteram[0x09], |
| 260 | | 1, m_spriteram[0x0e] & 0x0f, BALL_COLOR); |
| 261 | | |
| 262 | | /* left goal - position determined by bit 6 of the |
| 263 | | horizontal and vertical timing PROMs */ |
| 264 | | m_gfxdecode->gfx(1)->zoom_transpen(bitmap,cliprect, |
| 265 | | 0,0, |
| 266 | | 0,0, |
| 267 | | LEFT_GOAL_X,GOAL_Y, |
| 268 | | 0x20000,0x20000,0); |
| 269 | | |
| 270 | | /* right goal */ |
| 271 | | m_gfxdecode->gfx(1)->zoom_transpen(bitmap,cliprect, |
| 272 | | 0,1, |
| 273 | | 1,0, |
| 274 | | RIGHT_GOAL_X,GOAL_Y, |
| 275 | | 0x20000,0x20000,0); |
| 276 | | |
| 277 | | /* special char - bit 0 of 0x0f enables it, |
| 278 | | bit 1 marked as WIDE, but never appears to be set */ |
| 279 | | if (m_spriteram[0x0f] & 0x02) |
| 280 | | popmessage("WIDE!\n"); |
| 281 | | |
| 282 | | if (m_spriteram[0x0f] & 0x01) |
| 283 | | draw_sprite(bitmap, cliprect, |
| 284 | | m_spriteram[0x0a], m_spriteram[0x0b], |
| 285 | | 1, m_spriteram[0x0e] >> 4, SPECIAL_CHAR_COLOR); |
| 286 | | |
| 287 | | |
| 288 | | /* draw the alpha layer */ |
| 289 | | |
| 290 | | /* there are only 8 lines of text repeated 4 times |
| 291 | | and bit 3 of the vertical timing PROM controls in |
| 292 | | which quadrant the line will actually appear */ |
| 293 | | |
| 294 | | draw_alpha_line(bitmap, cliprect, 0, (0*4+0)*2 ); |
| 295 | | draw_alpha_line(bitmap, cliprect, 1, (0*4+0)*2+1); |
| 296 | | draw_alpha_line(bitmap, cliprect, 2, (3*4+1)*2 ); |
| 297 | | draw_alpha_line(bitmap, cliprect, 3, (3*4+1)*2+1); |
| 298 | | draw_alpha_line(bitmap, cliprect, 4, (1*4+2)*2 ); |
| 299 | | draw_alpha_line(bitmap, cliprect, 5, (1*4+2)*2+1); |
| 300 | | draw_alpha_line(bitmap, cliprect, 6, (0*4+3)*2 ); |
| 301 | | draw_alpha_line(bitmap, cliprect, 7, (0*4+3)*2+1); |
| 302 | | |
| 303 | | return 0; |
| 304 | | } |
| 305 | | |
| 306 | | |
| 307 | | /************************************* |
| 308 | | * |
| 309 | | * End of frame callback |
| 310 | | * |
| 311 | | *************************************/ |
| 312 | | |
| 313 | | void carpolo_state::normalize_coordinates(int *x1, int *y1, int *x2, int *y2) |
| 314 | | { |
| 315 | | if (*x1 < *x2) |
| 316 | | { |
| 317 | | *x2 = *x2 - *x1; |
| 318 | | *x1 = 0; |
| 319 | | } |
| 320 | | else |
| 321 | | { |
| 322 | | *x1 = *x1 - *x2; |
| 323 | | *x2 = 0; |
| 324 | | } |
| 325 | | |
| 326 | | if (*y1 < *y2) |
| 327 | | { |
| 328 | | *y2 = *y2 - *y1; |
| 329 | | *y1 = 0; |
| 330 | | } |
| 331 | | else |
| 332 | | { |
| 333 | | *y1 = *y1 - *y2; |
| 334 | | *y2 = 0; |
| 335 | | } |
| 336 | | } |
| 337 | | |
| 338 | | |
| 339 | | int carpolo_state::check_sprite_sprite_collision(int x1, int y1, int code1, int flipy1, |
| 340 | | int x2, int y2, int code2, int flipy2, |
| 341 | | int *col_x, int *col_y) |
| 342 | | { |
| 343 | | int collided = 0; |
| 344 | | |
| 345 | | x1 = 240 - x1; |
| 346 | | y1 = 240 - y1; |
| 347 | | x2 = 240 - x2; |
| 348 | | y2 = 240 - y2; |
| 349 | | |
| 350 | | /* check if the two sprites are even within collision range */ |
| 351 | | if ((abs(x1 - x2) < SPRITE_WIDTH) && (abs(y1 - y2) < SPRITE_HEIGHT)) |
| 352 | | { |
| 353 | | int x,y; |
| 354 | | |
| 355 | | normalize_coordinates(&x1, &y1, &x2, &y2); |
| 356 | | |
| 357 | | m_sprite_sprite_collision_bitmap1->fill(0); |
| 358 | | m_sprite_sprite_collision_bitmap2->fill(0); |
| 359 | | |
| 360 | | m_gfxdecode->gfx(0)->opaque(*m_sprite_sprite_collision_bitmap1,m_sprite_sprite_collision_bitmap1->cliprect(), |
| 361 | | code1,0, |
| 362 | | 0,flipy1, |
| 363 | | x1,y1); |
| 364 | | |
| 365 | | m_gfxdecode->gfx(0)->opaque(*m_sprite_sprite_collision_bitmap2,m_sprite_sprite_collision_bitmap2->cliprect(), |
| 366 | | code2,0, |
| 367 | | 0,flipy2, |
| 368 | | x2,y2); |
| 369 | | |
| 370 | | for (x = x1; x < x1 + SPRITE_WIDTH; x++) |
| 371 | | for (y = y1; y < y1 + SPRITE_HEIGHT; y++) |
| 372 | | if ((m_sprite_sprite_collision_bitmap1->pix16(y, x) == 1) && |
| 373 | | (m_sprite_sprite_collision_bitmap2->pix16(y, x) == 1)) |
| 374 | | { |
| 375 | | *col_x = (x1 + x) & 0x0f; |
| 376 | | *col_y = (y1 + y) & 0x0f; |
| 377 | | |
| 378 | | collided = 1; |
| 379 | | |
| 380 | | break; |
| 381 | | } |
| 382 | | } |
| 383 | | |
| 384 | | return collided; |
| 385 | | } |
| 386 | | |
| 387 | | |
| 388 | | /* returns 1 for collision with goal post, |
| 389 | | 2 for collision with scoring area */ |
| 390 | | int carpolo_state::check_sprite_left_goal_collision(int x1, int y1, int code1, int flipy1, int goalpost_only) |
| 391 | | { |
| 392 | | int collided = 0; |
| 393 | | |
| 394 | | x1 = 240 - x1; |
| 395 | | y1 = 240 - y1; |
| 396 | | |
| 397 | | /* check if the sprite is even within the range of the goal */ |
| 398 | | if (((y1 + 16) > GOAL_Y) && (y1 < (GOAL_Y + GOAL_HEIGHT)) && |
| 399 | | ((x1 + 16) > LEFT_GOAL_X) && (x1 < (LEFT_GOAL_X + GOAL_WIDTH))) |
| 400 | | { |
| 401 | | int x,y; |
| 402 | | int x2,y2; |
| 403 | | |
| 404 | | |
| 405 | | x2 = LEFT_GOAL_X; |
| 406 | | y2 = GOAL_Y; |
| 407 | | |
| 408 | | normalize_coordinates(&x1, &y1, &x2, &y2); |
| 409 | | |
| 410 | | m_sprite_goal_collision_bitmap1->fill(0); |
| 411 | | m_sprite_goal_collision_bitmap2->fill(0); |
| 412 | | |
| 413 | | m_gfxdecode->gfx(0)->opaque(*m_sprite_goal_collision_bitmap1,m_sprite_goal_collision_bitmap1->cliprect(), |
| 414 | | code1,0, |
| 415 | | 0,flipy1, |
| 416 | | x1,y1); |
| 417 | | |
| 418 | | m_gfxdecode->gfx(1)->zoom_transpen(*m_sprite_goal_collision_bitmap2,m_sprite_goal_collision_bitmap2->cliprect(), |
| 419 | | 0,0, |
| 420 | | 0,0, |
| 421 | | x2,y2, |
| 422 | | 0x20000,0x20000,0); |
| 423 | | |
| 424 | | for (x = x1; x < x1 + SPRITE_WIDTH; x++) |
| 425 | | for (y = y1; y < y1 + SPRITE_HEIGHT; y++) |
| 426 | | if (m_sprite_goal_collision_bitmap1->pix16(y, x) == 1) |
| 427 | | { |
| 428 | | pen_t pix = m_sprite_goal_collision_bitmap2->pix16(y, x); |
| 429 | | |
| 430 | | if (pix == LEFT_GOAL_PEN) |
| 431 | | { |
| 432 | | collided = 1; |
| 433 | | break; |
| 434 | | } |
| 435 | | |
| 436 | | if (!goalpost_only && (pix == LEFT_SCORE_PEN)) |
| 437 | | { |
| 438 | | collided = 2; |
| 439 | | break; |
| 440 | | } |
| 441 | | } |
| 442 | | } |
| 443 | | |
| 444 | | return collided; |
| 445 | | } |
| 446 | | |
| 447 | | |
| 448 | | int carpolo_state::check_sprite_right_goal_collision(int x1, int y1, int code1, int flipy1, int goalpost_only) |
| 449 | | { |
| 450 | | int collided = 0; |
| 451 | | |
| 452 | | x1 = 240 - x1; |
| 453 | | y1 = 240 - y1; |
| 454 | | |
| 455 | | /* check if the sprite is even within the range of the goal */ |
| 456 | | if (((y1 + 16) > GOAL_Y) && (y1 < (GOAL_Y + GOAL_HEIGHT)) && |
| 457 | | ((x1 + 16) > RIGHT_GOAL_X) && (x1 < (RIGHT_GOAL_X + GOAL_WIDTH))) |
| 458 | | { |
| 459 | | int x,y; |
| 460 | | int x2,y2; |
| 461 | | |
| 462 | | x2 = RIGHT_GOAL_X; |
| 463 | | y2 = GOAL_Y; |
| 464 | | |
| 465 | | normalize_coordinates(&x1, &y1, &x2, &y2); |
| 466 | | |
| 467 | | m_sprite_goal_collision_bitmap1->fill(0); |
| 468 | | m_sprite_goal_collision_bitmap2->fill(0); |
| 469 | | |
| 470 | | m_gfxdecode->gfx(0)->opaque(*m_sprite_goal_collision_bitmap1,m_sprite_goal_collision_bitmap1->cliprect(), |
| 471 | | code1,0, |
| 472 | | 0,flipy1, |
| 473 | | x1,y1); |
| 474 | | |
| 475 | | m_gfxdecode->gfx(1)->zoom_transpen(*m_sprite_goal_collision_bitmap2,m_sprite_goal_collision_bitmap2->cliprect(), |
| 476 | | 0,1, |
| 477 | | 1,0, |
| 478 | | x2,y2, |
| 479 | | 0x20000,0x20000,0); |
| 480 | | |
| 481 | | for (x = x1; x < x1 + SPRITE_WIDTH; x++) |
| 482 | | for (y = y1; y < y1 + SPRITE_HEIGHT; y++) |
| 483 | | if (m_sprite_goal_collision_bitmap1->pix16(y, x) == 1) |
| 484 | | { |
| 485 | | pen_t pix = m_sprite_goal_collision_bitmap2->pix16(y, x); |
| 486 | | |
| 487 | | if (pix == RIGHT_GOAL_PEN) |
| 488 | | { |
| 489 | | collided = 1; |
| 490 | | break; |
| 491 | | } |
| 492 | | |
| 493 | | if (!goalpost_only && (pix == RIGHT_SCORE_PEN)) |
| 494 | | { |
| 495 | | collided = 2; |
| 496 | | break; |
| 497 | | } |
| 498 | | } |
| 499 | | } |
| 500 | | |
| 501 | | return collided; |
| 502 | | } |
| 503 | | |
| 504 | | |
| 505 | | /* returns 1 for collision with vertical border, |
| 506 | | 2 for collision with horizontal border */ |
| 507 | | int carpolo_state::check_sprite_border_collision(UINT8 x1, UINT8 y1, int code1, int flipy1) |
| 508 | | { |
| 509 | | UINT8 x,y; |
| 510 | | int collided = 0; |
| 511 | | |
| 512 | | x1 = 240 - x1; |
| 513 | | y1 = 240 - y1; |
| 514 | | |
| 515 | | m_gfxdecode->gfx(0)->opaque(*m_sprite_border_collision_bitmap,m_sprite_border_collision_bitmap->cliprect(), |
| 516 | | code1,0, |
| 517 | | 0,flipy1, |
| 518 | | 0,0); |
| 519 | | |
| 520 | | for (x = 0; x < SPRITE_WIDTH; x++) |
| 521 | | for (y = 0; y < SPRITE_HEIGHT; y++) |
| 522 | | if (m_sprite_border_collision_bitmap->pix16(y, x) == 1) |
| 523 | | { |
| 524 | | if (((UINT8)(x1 + x) == LEFT_BORDER) || |
| 525 | | ((UINT8)(x1 + x) == RIGHT_BORDER)) |
| 526 | | { |
| 527 | | collided = 1; |
| 528 | | break; |
| 529 | | } |
| 530 | | |
| 531 | | if (((UINT8)(y1 + y) == TOP_BORDER) || |
| 532 | | ((UINT8)(y1 + y) == BOTTOM_BORDER)) |
| 533 | | { |
| 534 | | collided = 2; |
| 535 | | break; |
| 536 | | } |
| 537 | | } |
| 538 | | |
| 539 | | return collided; |
| 540 | | } |
| 541 | | |
| 542 | | |
| 543 | | void carpolo_state::screen_eof_carpolo(screen_device &screen, bool state) |
| 544 | | { |
| 545 | | // rising edge |
| 546 | | if (state) |
| 547 | | { |
| 548 | | int col_x, col_y; |
| 549 | | int car1_x, car2_x, car3_x, car4_x, ball_x; |
| 550 | | int car1_y, car2_y, car3_y, car4_y, ball_y; |
| 551 | | int car1_code, car2_code, car3_code, car4_code, ball_code; |
| 552 | | int car1_flipy, car2_flipy, car3_flipy, car4_flipy, ball_flipy; |
| 553 | | |
| 554 | | |
| 555 | | /* check car-car collision first */ |
| 556 | | |
| 557 | | car1_x = m_spriteram[0x00]; |
| 558 | | car1_y = m_spriteram[0x01]; |
| 559 | | remap_sprite_code(0, m_spriteram[0x0c] & 0x0f, &car1_code, &car1_flipy); |
| 560 | | |
| 561 | | car2_x = m_spriteram[0x02]; |
| 562 | | car2_y = m_spriteram[0x03]; |
| 563 | | remap_sprite_code(0, m_spriteram[0x0c] >> 4, &car2_code, &car2_flipy); |
| 564 | | |
| 565 | | car3_x = m_spriteram[0x04]; |
| 566 | | car3_y = m_spriteram[0x05]; |
| 567 | | remap_sprite_code(0, m_spriteram[0x0d] & 0x0f, &car3_code, &car3_flipy); |
| 568 | | |
| 569 | | car4_x = m_spriteram[0x06]; |
| 570 | | car4_y = m_spriteram[0x07]; |
| 571 | | remap_sprite_code(0, m_spriteram[0x0d] >> 4, &car4_code, &car4_flipy); |
| 572 | | |
| 573 | | ball_x = m_spriteram[0x08]; |
| 574 | | ball_y = m_spriteram[0x09]; |
| 575 | | remap_sprite_code(1, m_spriteram[0x0e] & 0x0f, &ball_code, &ball_flipy); |
| 576 | | |
| 577 | | |
| 578 | | /* cars 1 and 2 */ |
| 579 | | if (check_sprite_sprite_collision(car1_x, car1_y, car1_code, car1_flipy, |
| 580 | | car2_x, car2_y, car2_code, car2_flipy, |
| 581 | | &col_x, &col_y)) |
| 582 | | carpolo_generate_car_car_interrupt(0, 1); |
| 583 | | |
| 584 | | /* cars 1 and 3 */ |
| 585 | | else if (check_sprite_sprite_collision(car1_x, car1_y, car1_code, car1_flipy, |
| 586 | | car3_x, car3_y, car3_code, car3_flipy, |
| 587 | | &col_x, &col_y)) |
| 588 | | carpolo_generate_car_car_interrupt(0, 2); |
| 589 | | |
| 590 | | /* cars 1 and 4 */ |
| 591 | | else if (check_sprite_sprite_collision(car1_x, car1_y, car1_code, car1_flipy, |
| 592 | | car4_x, car4_y, car4_code, car4_flipy, |
| 593 | | &col_x, &col_y)) |
| 594 | | carpolo_generate_car_car_interrupt(0, 3); |
| 595 | | |
| 596 | | /* cars 2 and 3 */ |
| 597 | | else if (check_sprite_sprite_collision(car2_x, car2_y, car2_code, car2_flipy, |
| 598 | | car3_x, car3_y, car3_code, car3_flipy, |
| 599 | | &col_x, &col_y)) |
| 600 | | carpolo_generate_car_car_interrupt(1, 2); |
| 601 | | |
| 602 | | /* cars 2 and 4 */ |
| 603 | | else if (check_sprite_sprite_collision(car2_x, car2_y, car2_code, car2_flipy, |
| 604 | | car4_x, car4_y, car4_code, car4_flipy, |
| 605 | | &col_x, &col_y)) |
| 606 | | carpolo_generate_car_car_interrupt(1, 3); |
| 607 | | |
| 608 | | /* cars 3 and 4 */ |
| 609 | | else if (check_sprite_sprite_collision(car3_x, car3_y, car3_code, car3_flipy, |
| 610 | | car4_x, car4_y, car4_code, car4_flipy, |
| 611 | | &col_x, &col_y)) |
| 612 | | carpolo_generate_car_car_interrupt(2, 3); |
| 613 | | |
| 614 | | |
| 615 | | |
| 616 | | /* check car-ball collision */ |
| 617 | | if (check_sprite_sprite_collision(car1_x, car1_y, car1_code, car1_flipy, |
| 618 | | ball_x, ball_y, ball_code, ball_flipy, |
| 619 | | &col_x, &col_y)) |
| 620 | | carpolo_generate_car_ball_interrupt(0, col_x, col_y); |
| 621 | | |
| 622 | | else if (check_sprite_sprite_collision(car2_x, car2_y, car2_code, car2_flipy, |
| 623 | | ball_x, ball_y, ball_code, ball_flipy, |
| 624 | | &col_x, &col_y)) |
| 625 | | carpolo_generate_car_ball_interrupt(1, col_x, col_y); |
| 626 | | |
| 627 | | else if (check_sprite_sprite_collision(car3_x, car3_y, car3_code, car3_flipy, |
| 628 | | ball_x, ball_y, ball_code, ball_flipy, |
| 629 | | &col_x, &col_y)) |
| 630 | | carpolo_generate_car_ball_interrupt(2, col_x, col_y); |
| 631 | | |
| 632 | | else if (check_sprite_sprite_collision(car4_x, car4_y, car4_code, car4_flipy, |
| 633 | | ball_x, ball_y, ball_code, ball_flipy, |
| 634 | | &col_x, &col_y)) |
| 635 | | carpolo_generate_car_ball_interrupt(3, col_x, col_y); |
| 636 | | |
| 637 | | |
| 638 | | /* check car-goal collision */ |
| 639 | | if (check_sprite_left_goal_collision(car1_x, car1_y, car1_code, car1_flipy, 1)) |
| 640 | | carpolo_generate_car_goal_interrupt(0, 0); |
| 641 | | |
| 642 | | else if (check_sprite_right_goal_collision(car1_x, car1_y, car1_code, car1_flipy, 1)) |
| 643 | | carpolo_generate_car_goal_interrupt(0, 1); |
| 644 | | |
| 645 | | else if (check_sprite_left_goal_collision(car2_x, car2_y, car2_code, car2_flipy, 1)) |
| 646 | | carpolo_generate_car_goal_interrupt(1, 0); |
| 647 | | |
| 648 | | else if (check_sprite_right_goal_collision(car2_x, car2_y, car2_code, car2_flipy, 1)) |
| 649 | | carpolo_generate_car_goal_interrupt(1, 1); |
| 650 | | |
| 651 | | else if (check_sprite_left_goal_collision(car3_x, car3_y, car3_code, car3_flipy, 1)) |
| 652 | | carpolo_generate_car_goal_interrupt(2, 0); |
| 653 | | |
| 654 | | else if (check_sprite_right_goal_collision(car3_x, car3_y, car3_code, car3_flipy, 1)) |
| 655 | | carpolo_generate_car_goal_interrupt(2, 1); |
| 656 | | |
| 657 | | else if (check_sprite_left_goal_collision(car4_x, car4_y, car4_code, car4_flipy, 1)) |
| 658 | | carpolo_generate_car_goal_interrupt(3, 0); |
| 659 | | |
| 660 | | else if (check_sprite_right_goal_collision(car4_x, car4_y, car4_code, car4_flipy, 1)) |
| 661 | | carpolo_generate_car_goal_interrupt(3, 1); |
| 662 | | |
| 663 | | |
| 664 | | /* check ball collision with static screen elements */ |
| 665 | | { |
| 666 | | int col; |
| 667 | | |
| 668 | | col = check_sprite_left_goal_collision(ball_x, ball_y, ball_code, ball_flipy, 0); |
| 669 | | |
| 670 | | if (col == 1) carpolo_generate_ball_screen_interrupt(0x05); |
| 671 | | if (col == 2) carpolo_generate_ball_screen_interrupt(0x03); |
| 672 | | |
| 673 | | |
| 674 | | col = check_sprite_right_goal_collision(ball_x, ball_y, ball_code, ball_flipy, 0); |
| 675 | | |
| 676 | | if (col == 1) carpolo_generate_ball_screen_interrupt(0x05 | 0x08); |
| 677 | | if (col == 2) carpolo_generate_ball_screen_interrupt(0x03 | 0x08); |
| 678 | | |
| 679 | | |
| 680 | | if (check_sprite_border_collision(ball_x, ball_y, ball_code, ball_flipy)) |
| 681 | | carpolo_generate_ball_screen_interrupt(0x06); |
| 682 | | } |
| 683 | | |
| 684 | | |
| 685 | | /* check car-border collision */ |
| 686 | | { |
| 687 | | int col; |
| 688 | | |
| 689 | | col = check_sprite_border_collision(car1_x, car1_y, car1_code, car1_flipy); |
| 690 | | |
| 691 | | if (col) |
| 692 | | carpolo_generate_car_border_interrupt(0, (col == 2)); |
| 693 | | else |
| 694 | | { |
| 695 | | col = check_sprite_border_collision(car2_x, car2_y, car2_code, car2_flipy); |
| 696 | | |
| 697 | | if (col) |
| 698 | | carpolo_generate_car_border_interrupt(1, (col == 2)); |
| 699 | | else |
| 700 | | { |
| 701 | | col = check_sprite_border_collision(car3_x, car3_y, car3_code, car3_flipy); |
| 702 | | |
| 703 | | if (col) |
| 704 | | carpolo_generate_car_border_interrupt(2, (col == 2)); |
| 705 | | else |
| 706 | | { |
| 707 | | col = check_sprite_border_collision(car4_x, car4_y, car4_code, car4_flipy); |
| 708 | | |
| 709 | | if (col) |
| 710 | | carpolo_generate_car_border_interrupt(3, (col == 2)); |
| 711 | | } |
| 712 | | } |
| 713 | | } |
| 714 | | } |
| 715 | | } |
| 716 | | } |
trunk/src/mame/video/carpolo.cpp
| r0 | r250161 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:Zsolt Vasvari |
| 3 | /*************************************************************************** |
| 4 | |
| 5 | Exidy Car Polo hardware |
| 6 | |
| 7 | driver by Zsolt Vasvari |
| 8 | |
| 9 | ****************************************************************************/ |
| 10 | |
| 11 | #include "emu.h" |
| 12 | #include "includes/carpolo.h" |
| 13 | |
| 14 | |
| 15 | /* the screen elements' priorties determine their color */ |
| 16 | #define CHARSET_COLOR_BASE (0x00) |
| 17 | #define BACKGROUND_PEN ((0x00 << 1) + 1) |
| 18 | #define FIELD_PEN ((0x01 << 1) + 1) |
| 19 | #define CAR1_COLOR (0x02) |
| 20 | #define LINE_PEN ((0x03 << 1) + 1) |
| 21 | #define CAR4_COLOR (0x04) |
| 22 | #define CAR3_COLOR (0x05) |
| 23 | #define CAR2_COLOR (0x06) |
| 24 | #define BALL_COLOR (0x07) |
| 25 | #define NET_COLOR (0x08) |
| 26 | #define LEFT_GOAL_COLOR (0x09) |
| 27 | #define LEFT_GOAL_PEN (0x18 + 0x08) |
| 28 | #define LEFT_SCORE_PEN (0x18 + 0x06) |
| 29 | #define RIGHT_GOAL_COLOR (0x0a) |
| 30 | #define RIGHT_GOAL_PEN (0x18 + 0x18) |
| 31 | #define RIGHT_SCORE_PEN (0x18 + 0x16) |
| 32 | #define SPECIAL_CHAR_COLOR (0x0b) |
| 33 | #define ALPHA_COLOR_BASE (0x0c) /* 0x0c - 0x0f */ |
| 34 | |
| 35 | #define SPRITE_WIDTH (16) |
| 36 | #define SPRITE_HEIGHT (16) |
| 37 | #define GOAL_WIDTH (16) |
| 38 | #define GOAL_HEIGHT (64) |
| 39 | |
| 40 | #define LEFT_GOAL_X ((2 * 16) - 8) |
| 41 | #define RIGHT_GOAL_X ((13 * 16) - 8) |
| 42 | #define GOAL_Y (7 * 16) |
| 43 | |
| 44 | #define TOP_BORDER (16) |
| 45 | #define BOTTOM_BORDER (255) |
| 46 | #define LEFT_BORDER (0) |
| 47 | #define RIGHT_BORDER (239) |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | /*************************************************************************** |
| 53 | * |
| 54 | * Palette generation |
| 55 | * |
| 56 | * The palette PROM is connected to the RGB output this way. |
| 57 | * |
| 58 | * bit 0 -- 220 ohm resistor -- BLUE (probably an error on schematics) |
| 59 | * -- 470 ohm resistor -- BLUE (probably an error on schematics) |
| 60 | * -- 220 ohm resistor -- GREEN |
| 61 | * -- 470 ohm resistor -- GREEN |
| 62 | * -- 1 kohm resistor -- GREEN |
| 63 | * -- 220 ohm resistor -- RED |
| 64 | * -- 470 ohm resistor -- RED |
| 65 | * bit 7 -- 1 kohm resistor -- RED |
| 66 | * |
| 67 | **************************************************************************/ |
| 68 | |
| 69 | PALETTE_INIT_MEMBER(carpolo_state, carpolo) |
| 70 | { |
| 71 | const UINT8 *color_prom = memregion("proms")->base(); |
| 72 | int i; |
| 73 | |
| 74 | /* thanks to Jarek Burczynski for analyzing the circuit */ |
| 75 | /* static const float MAX_VOLTAGE = 6.9620f; */ |
| 76 | static const float MIN_VOLTAGE = 1.7434f; |
| 77 | static const float MAX_VOLTAGE = 5.5266f; |
| 78 | |
| 79 | static const float r_voltage[] = |
| 80 | { |
| 81 | 1.7434f, 2.1693f, 2.5823f, 3.0585f, 3.4811f, 4.0707f, 4.7415f, 5.4251f |
| 82 | }; |
| 83 | |
| 84 | static const float g_voltage[] = |
| 85 | { |
| 86 | 1.7434f, 2.1693f, 2.5823f, 3.0585f, 3.4811f, 4.0707f, 4.7415f, 5.4251f |
| 87 | /* 4.7871f, 5.0613f, 5.3079f, 5.6114f, 5.7940f, 6.1608f, 6.5436f, 6.9620f */ |
| 88 | }; |
| 89 | |
| 90 | static const float b_voltage[] = |
| 91 | { |
| 92 | 1.9176f, 2.8757f, 3.9825f, 5.5266f |
| 93 | }; |
| 94 | |
| 95 | |
| 96 | for (i = 0; i < palette.entries(); i++) |
| 97 | { |
| 98 | UINT8 pen, r, g, b; |
| 99 | |
| 100 | if (i < 0x18) |
| 101 | /* sprites */ |
| 102 | pen = ((i - 0x00) & 0x01) ? CHARSET_COLOR_BASE + ((i - 0x00) >> 1) : 0; |
| 103 | |
| 104 | else if (i < 0x38) |
| 105 | /* the bits in the goal gfx PROM are hooked up as follows (all active LO): |
| 106 | D3 - goal post |
| 107 | D2 - scoring area |
| 108 | D1 - net |
| 109 | D0 - n/c |
| 110 | I am only filling in the colors actually used. */ |
| 111 | switch (i - 0x18) |
| 112 | { |
| 113 | case (0x00 | (0x07 ^ 0x0f)): pen = LEFT_GOAL_COLOR; break; |
| 114 | case (0x00 | (0x0d ^ 0x0f)): pen = NET_COLOR; break; |
| 115 | case (0x00 | (0x09 ^ 0x0f)): pen = NET_COLOR; break; /* score */ |
| 116 | case (0x10 | (0x07 ^ 0x0f)): pen = RIGHT_GOAL_COLOR; break; |
| 117 | case (0x10 | (0x0d ^ 0x0f)): pen = NET_COLOR; break; |
| 118 | case (0x10 | (0x09 ^ 0x0f)): pen = NET_COLOR; break; /* score */ |
| 119 | default: pen = 0; break; |
| 120 | } |
| 121 | |
| 122 | else |
| 123 | /* alpha layer */ |
| 124 | pen = ((i - 0x38) & 0x01) ? ALPHA_COLOR_BASE + ((i - 0x38) >> 1) : 0; |
| 125 | |
| 126 | /* red component */ |
| 127 | r = ((r_voltage[(color_prom[pen] >> 5) & 0x07] - MIN_VOLTAGE) / (MAX_VOLTAGE - MIN_VOLTAGE)) * 255.0f; |
| 128 | |
| 129 | /* green component */ |
| 130 | g = ((g_voltage[(color_prom[pen] >> 2) & 0x07] - MIN_VOLTAGE) / (MAX_VOLTAGE - MIN_VOLTAGE)) * 255.0f; |
| 131 | |
| 132 | /* blue component */ |
| 133 | b = ((b_voltage[(color_prom[pen] >> 0) & 0x03] - MIN_VOLTAGE) / (MAX_VOLTAGE - MIN_VOLTAGE)) * 255.0f; |
| 134 | |
| 135 | palette.set_pen_color(i, rgb_t(r, g, b)); |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | |
| 140 | /************************************* |
| 141 | * |
| 142 | * Video system start |
| 143 | * |
| 144 | *************************************/ |
| 145 | |
| 146 | void carpolo_state::video_start() |
| 147 | { |
| 148 | m_sprite_sprite_collision_bitmap1 = auto_bitmap_ind16_alloc(machine(), SPRITE_WIDTH*2, SPRITE_HEIGHT*2); |
| 149 | m_sprite_sprite_collision_bitmap2 = auto_bitmap_ind16_alloc(machine(), SPRITE_WIDTH*2, SPRITE_HEIGHT*2); |
| 150 | |
| 151 | m_sprite_goal_collision_bitmap1 = auto_bitmap_ind16_alloc(machine(), SPRITE_WIDTH+GOAL_WIDTH, SPRITE_HEIGHT+GOAL_HEIGHT); |
| 152 | m_sprite_goal_collision_bitmap2 = auto_bitmap_ind16_alloc(machine(), SPRITE_WIDTH+GOAL_WIDTH, SPRITE_HEIGHT+GOAL_HEIGHT); |
| 153 | |
| 154 | m_sprite_border_collision_bitmap = auto_bitmap_ind16_alloc(machine(), SPRITE_WIDTH, SPRITE_HEIGHT); |
| 155 | |
| 156 | save_item(NAME(*m_sprite_sprite_collision_bitmap1)); |
| 157 | save_item(NAME(*m_sprite_sprite_collision_bitmap2)); |
| 158 | save_item(NAME(*m_sprite_goal_collision_bitmap1)); |
| 159 | save_item(NAME(*m_sprite_goal_collision_bitmap2)); |
| 160 | save_item(NAME(*m_sprite_border_collision_bitmap)); |
| 161 | } |
| 162 | |
| 163 | |
| 164 | /************************************* |
| 165 | * |
| 166 | * Core video refresh |
| 167 | * |
| 168 | *************************************/ |
| 169 | |
| 170 | void carpolo_state::draw_alpha_line(bitmap_ind16 &bitmap, const rectangle &cliprect, |
| 171 | int alpha_line, int video_line) |
| 172 | { |
| 173 | for (int x = 0; x < 32; x++) |
| 174 | { |
| 175 | UINT8 code, col; |
| 176 | |
| 177 | code = m_alpharam[alpha_line * 32 + x] >> 2; |
| 178 | col = m_alpharam[alpha_line * 32 + x] & 0x03; |
| 179 | |
| 180 | m_gfxdecode->gfx(2)->transpen(bitmap,cliprect, |
| 181 | code,col, |
| 182 | 0,0, |
| 183 | x*8,video_line*8,0); |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | |
| 188 | void carpolo_state::remap_sprite_code(int bank, int code, int *remapped_code, int *flipy) |
| 189 | { |
| 190 | UINT8* PROM = memregion("user1")->base(); |
| 191 | |
| 192 | code = (bank << 4) | code; |
| 193 | *remapped_code = PROM[code] & 0x0f; |
| 194 | *flipy = (PROM[code] & 0x10) >> 4; |
| 195 | } |
| 196 | |
| 197 | |
| 198 | void carpolo_state::draw_sprite(bitmap_ind16 &bitmap, const rectangle &cliprect, |
| 199 | UINT8 x, UINT8 y, int bank, int code, int col) |
| 200 | { |
| 201 | int remapped_code, flipy; |
| 202 | |
| 203 | remap_sprite_code(bank, code, &remapped_code, &flipy); |
| 204 | |
| 205 | x = 240 - x; |
| 206 | y = 240 - y; |
| 207 | |
| 208 | m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, |
| 209 | remapped_code, col, |
| 210 | 0, flipy, |
| 211 | x, y,0); |
| 212 | |
| 213 | /* draw with wrap around */ |
| 214 | m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, |
| 215 | remapped_code, col, |
| 216 | 0, flipy, |
| 217 | (INT16)x - 256, y,0); |
| 218 | } |
| 219 | |
| 220 | |
| 221 | UINT32 carpolo_state::screen_update_carpolo(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 222 | { |
| 223 | /* draw the playfield elements in the correct priority order */ |
| 224 | |
| 225 | /* score area - position determined by bit 4 of the vertical timing PROM */ |
| 226 | bitmap.plot_box(0,0,RIGHT_BORDER+1,TOP_BORDER,BACKGROUND_PEN); |
| 227 | |
| 228 | /* field */ |
| 229 | bitmap.plot_box(0,TOP_BORDER,RIGHT_BORDER+1,BOTTOM_BORDER-TOP_BORDER+1,FIELD_PEN); |
| 230 | |
| 231 | /* car 1 */ |
| 232 | draw_sprite(bitmap, cliprect, |
| 233 | m_spriteram[0x00], m_spriteram[0x01], |
| 234 | 0, m_spriteram[0x0c] & 0x0f, CAR1_COLOR); |
| 235 | |
| 236 | /* border - position determined by bit 4 and 7 of the vertical timing PROM */ |
| 237 | bitmap.plot_box(0,TOP_BORDER, RIGHT_BORDER+1,1,LINE_PEN); |
| 238 | bitmap.plot_box(0,BOTTOM_BORDER,RIGHT_BORDER+1,1,LINE_PEN); |
| 239 | bitmap.plot_box(LEFT_BORDER,TOP_BORDER, 1,BOTTOM_BORDER-TOP_BORDER+1,LINE_PEN); |
| 240 | bitmap.plot_box(RIGHT_BORDER,TOP_BORDER,1,BOTTOM_BORDER-TOP_BORDER+1,LINE_PEN); |
| 241 | |
| 242 | /* car 4 */ |
| 243 | draw_sprite(bitmap, cliprect, |
| 244 | m_spriteram[0x06], m_spriteram[0x07], |
| 245 | 0, m_spriteram[0x0d] >> 4, CAR4_COLOR); |
| 246 | |
| 247 | /* car 3 */ |
| 248 | draw_sprite(bitmap, cliprect, |
| 249 | m_spriteram[0x04], m_spriteram[0x05], |
| 250 | 0, m_spriteram[0x0d] & 0x0f, CAR3_COLOR); |
| 251 | |
| 252 | /* car 2 */ |
| 253 | draw_sprite(bitmap, cliprect, |
| 254 | m_spriteram[0x02], m_spriteram[0x03], |
| 255 | 0, m_spriteram[0x0c] >> 4, CAR2_COLOR); |
| 256 | |
| 257 | /* ball */ |
| 258 | draw_sprite(bitmap, cliprect, |
| 259 | m_spriteram[0x08], m_spriteram[0x09], |
| 260 | 1, m_spriteram[0x0e] & 0x0f, BALL_COLOR); |
| 261 | |
| 262 | /* left goal - position determined by bit 6 of the |
| 263 | horizontal and vertical timing PROMs */ |
| 264 | m_gfxdecode->gfx(1)->zoom_transpen(bitmap,cliprect, |
| 265 | 0,0, |
| 266 | 0,0, |
| 267 | LEFT_GOAL_X,GOAL_Y, |
| 268 | 0x20000,0x20000,0); |
| 269 | |
| 270 | /* right goal */ |
| 271 | m_gfxdecode->gfx(1)->zoom_transpen(bitmap,cliprect, |
| 272 | 0,1, |
| 273 | 1,0, |
| 274 | RIGHT_GOAL_X,GOAL_Y, |
| 275 | 0x20000,0x20000,0); |
| 276 | |
| 277 | /* special char - bit 0 of 0x0f enables it, |
| 278 | bit 1 marked as WIDE, but never appears to be set */ |
| 279 | if (m_spriteram[0x0f] & 0x02) |
| 280 | popmessage("WIDE!\n"); |
| 281 | |
| 282 | if (m_spriteram[0x0f] & 0x01) |
| 283 | draw_sprite(bitmap, cliprect, |
| 284 | m_spriteram[0x0a], m_spriteram[0x0b], |
| 285 | 1, m_spriteram[0x0e] >> 4, SPECIAL_CHAR_COLOR); |
| 286 | |
| 287 | |
| 288 | /* draw the alpha layer */ |
| 289 | |
| 290 | /* there are only 8 lines of text repeated 4 times |
| 291 | and bit 3 of the vertical timing PROM controls in |
| 292 | which quadrant the line will actually appear */ |
| 293 | |
| 294 | draw_alpha_line(bitmap, cliprect, 0, (0*4+0)*2 ); |
| 295 | draw_alpha_line(bitmap, cliprect, 1, (0*4+0)*2+1); |
| 296 | draw_alpha_line(bitmap, cliprect, 2, (3*4+1)*2 ); |
| 297 | draw_alpha_line(bitmap, cliprect, 3, (3*4+1)*2+1); |
| 298 | draw_alpha_line(bitmap, cliprect, 4, (1*4+2)*2 ); |
| 299 | draw_alpha_line(bitmap, cliprect, 5, (1*4+2)*2+1); |
| 300 | draw_alpha_line(bitmap, cliprect, 6, (0*4+3)*2 ); |
| 301 | draw_alpha_line(bitmap, cliprect, 7, (0*4+3)*2+1); |
| 302 | |
| 303 | return 0; |
| 304 | } |
| 305 | |
| 306 | |
| 307 | /************************************* |
| 308 | * |
| 309 | * End of frame callback |
| 310 | * |
| 311 | *************************************/ |
| 312 | |
| 313 | void carpolo_state::normalize_coordinates(int *x1, int *y1, int *x2, int *y2) |
| 314 | { |
| 315 | if (*x1 < *x2) |
| 316 | { |
| 317 | *x2 = *x2 - *x1; |
| 318 | *x1 = 0; |
| 319 | } |
| 320 | else |
| 321 | { |
| 322 | *x1 = *x1 - *x2; |
| 323 | *x2 = 0; |
| 324 | } |
| 325 | |
| 326 | if (*y1 < *y2) |
| 327 | { |
| 328 | *y2 = *y2 - *y1; |
| 329 | *y1 = 0; |
| 330 | } |
| 331 | else |
| 332 | { |
| 333 | *y1 = *y1 - *y2; |
| 334 | *y2 = 0; |
| 335 | } |
| 336 | } |
| 337 | |
| 338 | |
| 339 | int carpolo_state::check_sprite_sprite_collision(int x1, int y1, int code1, int flipy1, |
| 340 | int x2, int y2, int code2, int flipy2, |
| 341 | int *col_x, int *col_y) |
| 342 | { |
| 343 | int collided = 0; |
| 344 | |
| 345 | x1 = 240 - x1; |
| 346 | y1 = 240 - y1; |
| 347 | x2 = 240 - x2; |
| 348 | y2 = 240 - y2; |
| 349 | |
| 350 | /* check if the two sprites are even within collision range */ |
| 351 | if ((abs(x1 - x2) < SPRITE_WIDTH) && (abs(y1 - y2) < SPRITE_HEIGHT)) |
| 352 | { |
| 353 | int x,y; |
| 354 | |
| 355 | normalize_coordinates(&x1, &y1, &x2, &y2); |
| 356 | |
| 357 | m_sprite_sprite_collision_bitmap1->fill(0); |
| 358 | m_sprite_sprite_collision_bitmap2->fill(0); |
| 359 | |
| 360 | m_gfxdecode->gfx(0)->opaque(*m_sprite_sprite_collision_bitmap1,m_sprite_sprite_collision_bitmap1->cliprect(), |
| 361 | code1,0, |
| 362 | 0,flipy1, |
| 363 | x1,y1); |
| 364 | |
| 365 | m_gfxdecode->gfx(0)->opaque(*m_sprite_sprite_collision_bitmap2,m_sprite_sprite_collision_bitmap2->cliprect(), |
| 366 | code2,0, |
| 367 | 0,flipy2, |
| 368 | x2,y2); |
| 369 | |
| 370 | for (x = x1; x < x1 + SPRITE_WIDTH; x++) |
| 371 | for (y = y1; y < y1 + SPRITE_HEIGHT; y++) |
| 372 | if ((m_sprite_sprite_collision_bitmap1->pix16(y, x) == 1) && |
| 373 | (m_sprite_sprite_collision_bitmap2->pix16(y, x) == 1)) |
| 374 | { |
| 375 | *col_x = (x1 + x) & 0x0f; |
| 376 | *col_y = (y1 + y) & 0x0f; |
| 377 | |
| 378 | collided = 1; |
| 379 | |
| 380 | break; |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | return collided; |
| 385 | } |
| 386 | |
| 387 | |
| 388 | /* returns 1 for collision with goal post, |
| 389 | 2 for collision with scoring area */ |
| 390 | int carpolo_state::check_sprite_left_goal_collision(int x1, int y1, int code1, int flipy1, int goalpost_only) |
| 391 | { |
| 392 | int collided = 0; |
| 393 | |
| 394 | x1 = 240 - x1; |
| 395 | y1 = 240 - y1; |
| 396 | |
| 397 | /* check if the sprite is even within the range of the goal */ |
| 398 | if (((y1 + 16) > GOAL_Y) && (y1 < (GOAL_Y + GOAL_HEIGHT)) && |
| 399 | ((x1 + 16) > LEFT_GOAL_X) && (x1 < (LEFT_GOAL_X + GOAL_WIDTH))) |
| 400 | { |
| 401 | int x,y; |
| 402 | int x2,y2; |
| 403 | |
| 404 | |
| 405 | x2 = LEFT_GOAL_X; |
| 406 | y2 = GOAL_Y; |
| 407 | |
| 408 | normalize_coordinates(&x1, &y1, &x2, &y2); |
| 409 | |
| 410 | m_sprite_goal_collision_bitmap1->fill(0); |
| 411 | m_sprite_goal_collision_bitmap2->fill(0); |
| 412 | |
| 413 | m_gfxdecode->gfx(0)->opaque(*m_sprite_goal_collision_bitmap1,m_sprite_goal_collision_bitmap1->cliprect(), |
| 414 | code1,0, |
| 415 | 0,flipy1, |
| 416 | x1,y1); |
| 417 | |
| 418 | m_gfxdecode->gfx(1)->zoom_transpen(*m_sprite_goal_collision_bitmap2,m_sprite_goal_collision_bitmap2->cliprect(), |
| 419 | 0,0, |
| 420 | 0,0, |
| 421 | x2,y2, |
| 422 | 0x20000,0x20000,0); |
| 423 | |
| 424 | for (x = x1; x < x1 + SPRITE_WIDTH; x++) |
| 425 | for (y = y1; y < y1 + SPRITE_HEIGHT; y++) |
| 426 | if (m_sprite_goal_collision_bitmap1->pix16(y, x) == 1) |
| 427 | { |
| 428 | pen_t pix = m_sprite_goal_collision_bitmap2->pix16(y, x); |
| 429 | |
| 430 | if (pix == LEFT_GOAL_PEN) |
| 431 | { |
| 432 | collided = 1; |
| 433 | break; |
| 434 | } |
| 435 | |
| 436 | if (!goalpost_only && (pix == LEFT_SCORE_PEN)) |
| 437 | { |
| 438 | collided = 2; |
| 439 | break; |
| 440 | } |
| 441 | } |
| 442 | } |
| 443 | |
| 444 | return collided; |
| 445 | } |
| 446 | |
| 447 | |
| 448 | int carpolo_state::check_sprite_right_goal_collision(int x1, int y1, int code1, int flipy1, int goalpost_only) |
| 449 | { |
| 450 | int collided = 0; |
| 451 | |
| 452 | x1 = 240 - x1; |
| 453 | y1 = 240 - y1; |
| 454 | |
| 455 | /* check if the sprite is even within the range of the goal */ |
| 456 | if (((y1 + 16) > GOAL_Y) && (y1 < (GOAL_Y + GOAL_HEIGHT)) && |
| 457 | ((x1 + 16) > RIGHT_GOAL_X) && (x1 < (RIGHT_GOAL_X + GOAL_WIDTH))) |
| 458 | { |
| 459 | int x,y; |
| 460 | int x2,y2; |
| 461 | |
| 462 | x2 = RIGHT_GOAL_X; |
| 463 | y2 = GOAL_Y; |
| 464 | |
| 465 | normalize_coordinates(&x1, &y1, &x2, &y2); |
| 466 | |
| 467 | m_sprite_goal_collision_bitmap1->fill(0); |
| 468 | m_sprite_goal_collision_bitmap2->fill(0); |
| 469 | |
| 470 | m_gfxdecode->gfx(0)->opaque(*m_sprite_goal_collision_bitmap1,m_sprite_goal_collision_bitmap1->cliprect(), |
| 471 | code1,0, |
| 472 | 0,flipy1, |
| 473 | x1,y1); |
| 474 | |
| 475 | m_gfxdecode->gfx(1)->zoom_transpen(*m_sprite_goal_collision_bitmap2,m_sprite_goal_collision_bitmap2->cliprect(), |
| 476 | 0,1, |
| 477 | 1,0, |
| 478 | x2,y2, |
| 479 | 0x20000,0x20000,0); |
| 480 | |
| 481 | for (x = x1; x < x1 + SPRITE_WIDTH; x++) |
| 482 | for (y = y1; y < y1 + SPRITE_HEIGHT; y++) |
| 483 | if (m_sprite_goal_collision_bitmap1->pix16(y, x) == 1) |
| 484 | { |
| 485 | pen_t pix = m_sprite_goal_collision_bitmap2->pix16(y, x); |
| 486 | |
| 487 | if (pix == RIGHT_GOAL_PEN) |
| 488 | { |
| 489 | collided = 1; |
| 490 | break; |
| 491 | } |
| 492 | |
| 493 | if (!goalpost_only && (pix == RIGHT_SCORE_PEN)) |
| 494 | { |
| 495 | collided = 2; |
| 496 | break; |
| 497 | } |
| 498 | } |
| 499 | } |
| 500 | |
| 501 | return collided; |
| 502 | } |
| 503 | |
| 504 | |
| 505 | /* returns 1 for collision with vertical border, |
| 506 | 2 for collision with horizontal border */ |
| 507 | int carpolo_state::check_sprite_border_collision(UINT8 x1, UINT8 y1, int code1, int flipy1) |
| 508 | { |
| 509 | UINT8 x,y; |
| 510 | int collided = 0; |
| 511 | |
| 512 | x1 = 240 - x1; |
| 513 | y1 = 240 - y1; |
| 514 | |
| 515 | m_gfxdecode->gfx(0)->opaque(*m_sprite_border_collision_bitmap,m_sprite_border_collision_bitmap->cliprect(), |
| 516 | code1,0, |
| 517 | 0,flipy1, |
| 518 | 0,0); |
| 519 | |
| 520 | for (x = 0; x < SPRITE_WIDTH; x++) |
| 521 | for (y = 0; y < SPRITE_HEIGHT; y++) |
| 522 | if (m_sprite_border_collision_bitmap->pix16(y, x) == 1) |
| 523 | { |
| 524 | if (((UINT8)(x1 + x) == LEFT_BORDER) || |
| 525 | ((UINT8)(x1 + x) == RIGHT_BORDER)) |
| 526 | { |
| 527 | collided = 1; |
| 528 | break; |
| 529 | } |
| 530 | |
| 531 | if (((UINT8)(y1 + y) == TOP_BORDER) || |
| 532 | ((UINT8)(y1 + y) == BOTTOM_BORDER)) |
| 533 | { |
| 534 | collided = 2; |
| 535 | break; |
| 536 | } |
| 537 | } |
| 538 | |
| 539 | return collided; |
| 540 | } |
| 541 | |
| 542 | |
| 543 | void carpolo_state::screen_eof_carpolo(screen_device &screen, bool state) |
| 544 | { |
| 545 | // rising edge |
| 546 | if (state) |
| 547 | { |
| 548 | int col_x, col_y; |
| 549 | int car1_x, car2_x, car3_x, car4_x, ball_x; |
| 550 | int car1_y, car2_y, car3_y, car4_y, ball_y; |
| 551 | int car1_code, car2_code, car3_code, car4_code, ball_code; |
| 552 | int car1_flipy, car2_flipy, car3_flipy, car4_flipy, ball_flipy; |
| 553 | |
| 554 | |
| 555 | /* check car-car collision first */ |
| 556 | |
| 557 | car1_x = m_spriteram[0x00]; |
| 558 | car1_y = m_spriteram[0x01]; |
| 559 | remap_sprite_code(0, m_spriteram[0x0c] & 0x0f, &car1_code, &car1_flipy); |
| 560 | |
| 561 | car2_x = m_spriteram[0x02]; |
| 562 | car2_y = m_spriteram[0x03]; |
| 563 | remap_sprite_code(0, m_spriteram[0x0c] >> 4, &car2_code, &car2_flipy); |
| 564 | |
| 565 | car3_x = m_spriteram[0x04]; |
| 566 | car3_y = m_spriteram[0x05]; |
| 567 | remap_sprite_code(0, m_spriteram[0x0d] & 0x0f, &car3_code, &car3_flipy); |
| 568 | |
| 569 | car4_x = m_spriteram[0x06]; |
| 570 | car4_y = m_spriteram[0x07]; |
| 571 | remap_sprite_code(0, m_spriteram[0x0d] >> 4, &car4_code, &car4_flipy); |
| 572 | |
| 573 | ball_x = m_spriteram[0x08]; |
| 574 | ball_y = m_spriteram[0x09]; |
| 575 | remap_sprite_code(1, m_spriteram[0x0e] & 0x0f, &ball_code, &ball_flipy); |
| 576 | |
| 577 | |
| 578 | /* cars 1 and 2 */ |
| 579 | if (check_sprite_sprite_collision(car1_x, car1_y, car1_code, car1_flipy, |
| 580 | car2_x, car2_y, car2_code, car2_flipy, |
| 581 | &col_x, &col_y)) |
| 582 | carpolo_generate_car_car_interrupt(0, 1); |
| 583 | |
| 584 | /* cars 1 and 3 */ |
| 585 | else if (check_sprite_sprite_collision(car1_x, car1_y, car1_code, car1_flipy, |
| 586 | car3_x, car3_y, car3_code, car3_flipy, |
| 587 | &col_x, &col_y)) |
| 588 | carpolo_generate_car_car_interrupt(0, 2); |
| 589 | |
| 590 | /* cars 1 and 4 */ |
| 591 | else if (check_sprite_sprite_collision(car1_x, car1_y, car1_code, car1_flipy, |
| 592 | car4_x, car4_y, car4_code, car4_flipy, |
| 593 | &col_x, &col_y)) |
| 594 | carpolo_generate_car_car_interrupt(0, 3); |
| 595 | |
| 596 | /* cars 2 and 3 */ |
| 597 | else if (check_sprite_sprite_collision(car2_x, car2_y, car2_code, car2_flipy, |
| 598 | car3_x, car3_y, car3_code, car3_flipy, |
| 599 | &col_x, &col_y)) |
| 600 | carpolo_generate_car_car_interrupt(1, 2); |
| 601 | |
| 602 | /* cars 2 and 4 */ |
| 603 | else if (check_sprite_sprite_collision(car2_x, car2_y, car2_code, car2_flipy, |
| 604 | car4_x, car4_y, car4_code, car4_flipy, |
| 605 | &col_x, &col_y)) |
| 606 | carpolo_generate_car_car_interrupt(1, 3); |
| 607 | |
| 608 | /* cars 3 and 4 */ |
| 609 | else if (check_sprite_sprite_collision(car3_x, car3_y, car3_code, car3_flipy, |
| 610 | car4_x, car4_y, car4_code, car4_flipy, |
| 611 | &col_x, &col_y)) |
| 612 | carpolo_generate_car_car_interrupt(2, 3); |
| 613 | |
| 614 | |
| 615 | |
| 616 | /* check car-ball collision */ |
| 617 | if (check_sprite_sprite_collision(car1_x, car1_y, car1_code, car1_flipy, |
| 618 | ball_x, ball_y, ball_code, ball_flipy, |
| 619 | &col_x, &col_y)) |
| 620 | carpolo_generate_car_ball_interrupt(0, col_x, col_y); |
| 621 | |
| 622 | else if (check_sprite_sprite_collision(car2_x, car2_y, car2_code, car2_flipy, |
| 623 | ball_x, ball_y, ball_code, ball_flipy, |
| 624 | &col_x, &col_y)) |
| 625 | carpolo_generate_car_ball_interrupt(1, col_x, col_y); |
| 626 | |
| 627 | else if (check_sprite_sprite_collision(car3_x, car3_y, car3_code, car3_flipy, |
| 628 | ball_x, ball_y, ball_code, ball_flipy, |
| 629 | &col_x, &col_y)) |
| 630 | carpolo_generate_car_ball_interrupt(2, col_x, col_y); |
| 631 | |
| 632 | else if (check_sprite_sprite_collision(car4_x, car4_y, car4_code, car4_flipy, |
| 633 | ball_x, ball_y, ball_code, ball_flipy, |
| 634 | &col_x, &col_y)) |
| 635 | carpolo_generate_car_ball_interrupt(3, col_x, col_y); |
| 636 | |
| 637 | |
| 638 | /* check car-goal collision */ |
| 639 | if (check_sprite_left_goal_collision(car1_x, car1_y, car1_code, car1_flipy, 1)) |
| 640 | carpolo_generate_car_goal_interrupt(0, 0); |
| 641 | |
| 642 | else if (check_sprite_right_goal_collision(car1_x, car1_y, car1_code, car1_flipy, 1)) |
| 643 | carpolo_generate_car_goal_interrupt(0, 1); |
| 644 | |
| 645 | else if (check_sprite_left_goal_collision(car2_x, car2_y, car2_code, car2_flipy, 1)) |
| 646 | carpolo_generate_car_goal_interrupt(1, 0); |
| 647 | |
| 648 | else if (check_sprite_right_goal_collision(car2_x, car2_y, car2_code, car2_flipy, 1)) |
| 649 | carpolo_generate_car_goal_interrupt(1, 1); |
| 650 | |
| 651 | else if (check_sprite_left_goal_collision(car3_x, car3_y, car3_code, car3_flipy, 1)) |
| 652 | carpolo_generate_car_goal_interrupt(2, 0); |
| 653 | |
| 654 | else if (check_sprite_right_goal_collision(car3_x, car3_y, car3_code, car3_flipy, 1)) |
| 655 | carpolo_generate_car_goal_interrupt(2, 1); |
| 656 | |
| 657 | else if (check_sprite_left_goal_collision(car4_x, car4_y, car4_code, car4_flipy, 1)) |
| 658 | carpolo_generate_car_goal_interrupt(3, 0); |
| 659 | |
| 660 | else if (check_sprite_right_goal_collision(car4_x, car4_y, car4_code, car4_flipy, 1)) |
| 661 | carpolo_generate_car_goal_interrupt(3, 1); |
| 662 | |
| 663 | |
| 664 | /* check ball collision with static screen elements */ |
| 665 | { |
| 666 | int col; |
| 667 | |
| 668 | col = check_sprite_left_goal_collision(ball_x, ball_y, ball_code, ball_flipy, 0); |
| 669 | |
| 670 | if (col == 1) carpolo_generate_ball_screen_interrupt(0x05); |
| 671 | if (col == 2) carpolo_generate_ball_screen_interrupt(0x03); |
| 672 | |
| 673 | |
| 674 | col = check_sprite_right_goal_collision(ball_x, ball_y, ball_code, ball_flipy, 0); |
| 675 | |
| 676 | if (col == 1) carpolo_generate_ball_screen_interrupt(0x05 | 0x08); |
| 677 | if (col == 2) carpolo_generate_ball_screen_interrupt(0x03 | 0x08); |
| 678 | |
| 679 | |
| 680 | if (check_sprite_border_collision(ball_x, ball_y, ball_code, ball_flipy)) |
| 681 | carpolo_generate_ball_screen_interrupt(0x06); |
| 682 | } |
| 683 | |
| 684 | |
| 685 | /* check car-border collision */ |
| 686 | { |
| 687 | int col; |
| 688 | |
| 689 | col = check_sprite_border_collision(car1_x, car1_y, car1_code, car1_flipy); |
| 690 | |
| 691 | if (col) |
| 692 | carpolo_generate_car_border_interrupt(0, (col == 2)); |
| 693 | else |
| 694 | { |
| 695 | col = check_sprite_border_collision(car2_x, car2_y, car2_code, car2_flipy); |
| 696 | |
| 697 | if (col) |
| 698 | carpolo_generate_car_border_interrupt(1, (col == 2)); |
| 699 | else |
| 700 | { |
| 701 | col = check_sprite_border_collision(car3_x, car3_y, car3_code, car3_flipy); |
| 702 | |
| 703 | if (col) |
| 704 | carpolo_generate_car_border_interrupt(2, (col == 2)); |
| 705 | else |
| 706 | { |
| 707 | col = check_sprite_border_collision(car4_x, car4_y, car4_code, car4_flipy); |
| 708 | |
| 709 | if (col) |
| 710 | carpolo_generate_car_border_interrupt(3, (col == 2)); |
| 711 | } |
| 712 | } |
| 713 | } |
| 714 | } |
| 715 | } |
| 716 | } |