trunk/src/mess/machine/nes.c
| r23716 | r23717 | |
| 48 | 48 | m_in_1.shift = 0; |
| 49 | 49 | |
| 50 | 50 | m_maincpu->reset(); |
| 51 | |
| 52 | memset(m_pad_latch, 0, sizeof(m_pad_latch)); |
| 53 | memset(m_zapper_latch, 0, sizeof(m_zapper_latch)); |
| 54 | m_paddle_latch = 0; |
| 55 | m_paddle_btn_latch = 0; |
| 51 | 56 | } |
| 52 | 57 | |
| 53 | 58 | static void nes_state_register( running_machine &machine ) |
| r23716 | r23717 | |
| 71 | 76 | |
| 72 | 77 | if (state->m_disk_expansion) |
| 73 | 78 | state->save_pointer(NAME(state->m_vram), 0x800); |
| 79 | |
| 80 | state->save_item(NAME(state->m_pad_latch)); |
| 81 | state->save_item(NAME(state->m_zapper_latch)); |
| 82 | state->save_item(NAME(state->m_paddle_latch)); |
| 83 | state->save_item(NAME(state->m_paddle_btn_latch)); |
| 74 | 84 | } |
| 75 | 85 | |
| 76 | 86 | |
| r23716 | r23717 | |
| 104 | 114 | m_io_ctrlsel = ioport("CTRLSEL"); |
| 105 | 115 | m_io_exp = ioport("EXP"); |
| 106 | 116 | m_io_paddle = ioport("PADDLE"); |
| 117 | m_io_paddle_btn = ioport("PADDLE_BUTTON"); |
| 107 | 118 | m_io_cc_left = ioport("CC_LEFT"); |
| 108 | 119 | m_io_cc_right = ioport("CC_RIGHT"); |
| 109 | 120 | m_io_zapper1_t = ioport("ZAPPER1_T"); |
| r23716 | r23717 | |
| 200 | 211 | READ8_MEMBER(nes_state::nes_in0_r) |
| 201 | 212 | { |
| 202 | 213 | int cfg = m_io_ctrlsel->read(); |
| 203 | | /* Some games expect bit 6 to be set because the last entry on the data bus shows up */ |
| 204 | | /* in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. */ |
| 205 | | UINT8 ret = 0x40; |
| 206 | | ret |= ((m_in_0.i0 >> m_in_0.shift) & 0x01); |
| 207 | 214 | |
| 208 | | /* zapper */ |
| 215 | // Some games expect bit 6 to be set because the last entry on the data bus shows up |
| 216 | // in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. |
| 217 | UINT8 ret = 0x40; |
| 218 | ret |= (m_pad_latch[0] & 0x01); |
| 219 | |
| 220 | // shift |
| 221 | m_pad_latch[0] >>= 1; |
| 222 | |
| 223 | // zapper |
| 209 | 224 | if ((cfg & 0x000f) == 0x0002) |
| 210 | 225 | { |
| 211 | | int x = m_in_0.i1; /* read Zapper x-position */ |
| 212 | | int y = m_in_0.i2; /* read Zapper y-position */ |
| 226 | int x = m_zapper_latch[0][1]; // x-position |
| 227 | int y = m_zapper_latch[0][2]; // y-position |
| 213 | 228 | UINT32 pix, color_base; |
| 214 | 229 | |
| 215 | | /* get the pixel at the gun position */ |
| 230 | // get the pixel at the gun position |
| 216 | 231 | pix = m_ppu->get_pixel(x, y); |
| 217 | 232 | |
| 218 | | /* get the color base from the ppu */ |
| 233 | // get the color base from the ppu |
| 219 | 234 | color_base = m_ppu->get_colorbase(); |
| 220 | 235 | |
| 221 | | /* look at the screen and see if the cursor is over a bright pixel */ |
| 236 | // check if the cursor is over a bright pixel |
| 222 | 237 | if ((pix == color_base + 0x20) || (pix == color_base + 0x30) || |
| 223 | 238 | (pix == color_base + 0x33) || (pix == color_base + 0x34)) |
| 224 | | { |
| 225 | | ret &= ~0x08; /* sprite hit */ |
| 226 | | } |
| 239 | ret &= ~0x08; // sprite hit |
| 227 | 240 | else |
| 228 | | ret |= 0x08; /* no sprite hit */ |
| 241 | ret |= 0x08; // no sprite hit |
| 229 | 242 | |
| 230 | | /* If button 1 is pressed, indicate the light gun trigger is pressed */ |
| 231 | | ret |= ((m_in_0.i0 & 0x01) << 4); |
| 243 | // light gun trigger |
| 244 | ret |= (m_zapper_latch[0][0] << 4); |
| 232 | 245 | } |
| 233 | 246 | |
| 234 | 247 | if (LOG_JOY) |
| 235 | 248 | logerror("joy 0 read, val: %02x, pc: %04x, bits read: %d, chan0: %08x\n", ret, space.device().safe_pc(), m_in_0.shift, m_in_0.i0); |
| 236 | 249 | |
| 237 | | m_in_0.shift++; |
| 238 | | |
| 239 | 250 | return ret; |
| 240 | 251 | } |
| 241 | 252 | |
| 242 | 253 | READ8_MEMBER(nes_state::nes_in1_r) |
| 243 | 254 | { |
| 244 | 255 | int cfg = m_io_ctrlsel->read(); |
| 245 | | /* Some games expect bit 6 to be set because the last entry on the data bus shows up */ |
| 246 | | /* in the unused upper 3 bits, so typically a read from $4017 leaves 0x40 there. */ |
| 256 | |
| 257 | // Some games expect bit 6 to be set because the last entry on the data bus shows up |
| 258 | // in the unused upper 3 bits, so typically a read from $4017 leaves 0x40 there. |
| 247 | 259 | UINT8 ret = 0x40; |
| 248 | | ret |= ((m_in_1.i0 >> m_in_1.shift) & 0x01); |
| 260 | ret |= (m_pad_latch[1] & 0x01); |
| 249 | 261 | |
| 250 | | /* zapper */ |
| 262 | // shift |
| 263 | m_pad_latch[1] >>= 1; |
| 264 | |
| 265 | // zapper |
| 251 | 266 | if ((cfg & 0x00f0) == 0x0020) |
| 252 | 267 | { |
| 253 | | int x = m_in_1.i1; /* read Zapper x-position */ |
| 254 | | int y = m_in_1.i2; /* read Zapper y-position */ |
| 268 | int x = m_zapper_latch[1][1]; // x-position |
| 269 | int y = m_zapper_latch[1][2]; // y-position |
| 255 | 270 | UINT32 pix, color_base; |
| 256 | 271 | |
| 257 | | /* get the pixel at the gun position */ |
| 272 | // get the pixel at the gun position |
| 258 | 273 | pix = m_ppu->get_pixel(x, y); |
| 259 | 274 | |
| 260 | | /* get the color base from the ppu */ |
| 275 | // get the color base from the ppu |
| 261 | 276 | color_base = m_ppu->get_colorbase(); |
| 262 | 277 | |
| 263 | | /* look at the screen and see if the cursor is over a bright pixel */ |
| 278 | // check if the cursor is over a bright pixel |
| 264 | 279 | if ((pix == color_base + 0x20) || (pix == color_base + 0x30) || |
| 265 | 280 | (pix == color_base + 0x33) || (pix == color_base + 0x34)) |
| 266 | | { |
| 267 | | ret &= ~0x08; /* sprite hit */ |
| 268 | | } |
| 281 | ret &= ~0x08; // sprite hit |
| 269 | 282 | else |
| 270 | | ret |= 0x08; /* no sprite hit */ |
| 283 | ret |= 0x08; // no sprite hit |
| 271 | 284 | |
| 272 | | /* If button 1 is pressed, indicate the light gun trigger is pressed */ |
| 273 | | ret |= ((m_in_1.i0 & 0x01) << 4); |
| 285 | // light gun trigger |
| 286 | ret |= (m_zapper_latch[1][0] << 4); |
| 274 | 287 | } |
| 275 | 288 | |
| 276 | | /* arkanoid dial */ |
| 289 | // arkanoid paddle |
| 277 | 290 | if ((cfg & 0x00f0) == 0x0040) |
| 278 | 291 | { |
| 279 | | /* Handle data line 2's serial output */ |
| 280 | | ret |= ((m_in_1.i2 >> m_in_1.shift) & 0x01) << 3; |
| 281 | | |
| 282 | | /* Handle data line 3's serial output - bits are reversed */ |
| 283 | | /* NPW 27-Nov-2007 - there is no third subscript! commenting out */ |
| 284 | | /* ret |= ((m_in_1[3] >> m_in_1.shift) & 0x01) << 4; */ |
| 285 | | /* ret |= ((m_in_1[3] << m_in_1.shift) & 0x80) >> 3; */ |
| 292 | ret |= (m_paddle_btn_latch << 3); // button |
| 293 | ret |= ((m_paddle_latch & 0x80) >> 3); // paddle data |
| 294 | m_paddle_latch <<= 1; |
| 295 | m_paddle_latch &= 0xff; |
| 286 | 296 | } |
| 287 | 297 | |
| 288 | 298 | if (LOG_JOY) |
| 289 | 299 | logerror("joy 1 read, val: %02x, pc: %04x, bits read: %d, chan0: %08x\n", ret, space.device().safe_pc(), m_in_1.shift, m_in_1.i0); |
| 290 | 300 | |
| 291 | | m_in_1.shift++; |
| 292 | | |
| 293 | 301 | return ret; |
| 294 | 302 | } |
| 295 | 303 | |
| r23716 | r23717 | |
| 297 | 305 | { |
| 298 | 306 | int cfg = m_io_ctrlsel->read(); |
| 299 | 307 | |
| 300 | | /* Check if lightgun has been chosen as input: if so, enable crosshair */ |
| 308 | // Check if lightgun has been chosen as input: if so, enable crosshair |
| 301 | 309 | timer_set(attotime::zero, TIMER_ZAPPER_TICK); |
| 302 | 310 | |
| 303 | | // check 'standard' inputs |
| 304 | 311 | if (data & 0x01) |
| 305 | 312 | return; |
| 313 | |
| 314 | // Toggling bit 0 high then low resets controllers |
| 315 | m_pad_latch[0] = 0; |
| 316 | m_pad_latch[1] = 0; |
| 317 | m_zapper_latch[0][0] = 0; |
| 318 | m_zapper_latch[0][1] = 0; |
| 319 | m_zapper_latch[0][2] = 0; |
| 320 | m_zapper_latch[1][0] = 0; |
| 321 | m_zapper_latch[1][1] = 0; |
| 322 | m_zapper_latch[1][2] = 0; |
| 323 | m_paddle_latch = 0; |
| 306 | 324 | |
| 307 | | if (LOG_JOY) |
| 308 | | logerror("joy 0 bits read: %d\n", m_in_0.shift); |
| 309 | | |
| 310 | | /* Toggling bit 0 high then low resets both controllers */ |
| 311 | | m_in_0.shift = 0; |
| 312 | | m_in_1.shift = 0; |
| 313 | | m_in_0.i0 = 0; |
| 314 | | m_in_0.i1 = 0; |
| 315 | | m_in_0.i2 = 0; |
| 316 | | m_in_1.i0 = 0; |
| 317 | | m_in_1.i1 = 0; |
| 318 | | m_in_1.i2 = 0; |
| 319 | | m_in_2.i0 = 0; |
| 320 | | m_in_2.i1 = 0; |
| 321 | | m_in_2.i2 = 0; |
| 322 | | m_in_3.i0 = 0; |
| 323 | | m_in_3.i1 = 0; |
| 324 | | m_in_3.i2 = 0; |
| 325 | | |
| 326 | 325 | // P1 inputs |
| 327 | 326 | switch (cfg & 0x000f) |
| 328 | 327 | { |
| 329 | | case 0x01: /* gamepad */ |
| 330 | | m_in_0.i0 = m_io_pad[0]->read(); |
| 328 | case 0x01: // pad 1 |
| 329 | m_pad_latch[0] = m_io_pad[0]->read(); |
| 331 | 330 | break; |
| 332 | 331 | |
| 333 | | case 0x02: /* zapper 1 */ |
| 334 | | m_in_0.i0 = m_io_zapper1_t->read(); |
| 335 | | m_in_0.i1 = m_io_zapper1_x->read(); |
| 336 | | m_in_0.i2 = m_io_zapper1_y->read(); |
| 332 | case 0x02: // zapper (secondary) |
| 333 | m_zapper_latch[0][0] = m_io_zapper1_t->read(); |
| 334 | m_zapper_latch[0][1] = m_io_zapper1_x->read(); |
| 335 | m_zapper_latch[0][2] = m_io_zapper1_y->read(); |
| 337 | 336 | break; |
| 338 | 337 | } |
| 339 | 338 | |
| 340 | 339 | // P2 inputs |
| 341 | 340 | switch ((cfg & 0x00f0) >> 4) |
| 342 | 341 | { |
| 343 | | case 0x01: /* gamepad */ |
| 344 | | m_in_1.i0 = m_io_pad[1]->read(); |
| 342 | case 0x01: // pad 2 |
| 343 | m_pad_latch[1] = m_io_pad[1]->read(); |
| 345 | 344 | break; |
| 346 | 345 | |
| 347 | | case 0x02: /* zapper 2 */ |
| 348 | | m_in_1.i0 = m_io_zapper2_t->read(); |
| 349 | | m_in_1.i1 = m_io_zapper2_x->read(); |
| 350 | | m_in_1.i2 = m_io_zapper2_y->read(); |
| 346 | case 0x02: // zapper (primary) - most games expect pad in port1 & zapper in port2 |
| 347 | m_zapper_latch[1][0] = m_io_zapper2_t->read(); |
| 348 | m_zapper_latch[1][1] = m_io_zapper2_x->read(); |
| 349 | m_zapper_latch[1][2] = m_io_zapper2_y->read(); |
| 351 | 350 | break; |
| 352 | 351 | |
| 353 | | case 0x04: /* arkanoid paddle */ |
| 354 | | m_in_1.i0 = (UINT8) ((UINT8) m_io_paddle->read() + (UINT8)0x52) ^ 0xff; |
| 352 | case 0x04: // arkanoid paddle |
| 353 | m_paddle_btn_latch = m_io_paddle_btn->read(); |
| 354 | m_paddle_latch = (UINT8) (m_io_paddle->read() ^ 0xff); |
| 355 | 355 | break; |
| 356 | 356 | } |
| 357 | 357 | |
| 358 | 358 | // P3 inputs |
| 359 | 359 | if ((cfg & 0x0f00)) |
| 360 | | m_in_2.i0 = m_io_pad[2]->read(); |
| 360 | m_pad_latch[0] |= ((m_io_pad[2]->read() << 8) | (0x08 << 16)); // pad 3 + signature |
| 361 | 361 | |
| 362 | 362 | // P4 inputs |
| 363 | | if ((cfg & 0x0f00)) |
| 364 | | m_in_3.i0 = m_io_pad[3]->read(); |
| 365 | | |
| 366 | | if (cfg & 0x0f00) |
| 367 | | m_in_0.i0 |= (m_in_2.i0 << 8) | (0x08 << 16); |
| 368 | | |
| 369 | | if (cfg & 0xf000) |
| 370 | | m_in_1.i0 |= (m_in_3.i0 << 8) | (0x04 << 16); |
| 371 | | |
| 363 | if ((cfg & 0xf000)) |
| 364 | m_pad_latch[1] |= ((m_io_pad[3]->read() << 8) | (0x04 << 16)); // pad 4 + signature |
| 372 | 365 | } |
| 373 | 366 | |
| 374 | 367 | |
trunk/src/mess/drivers/nes.c
| r23716 | r23717 | |
| 110 | 110 | PORT_START("ZAPPER1_Y") /* P1 zapper */ |
| 111 | 111 | PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002) |
| 112 | 112 | PORT_START("ZAPPER1_T") /* P1 zapper trigger */ |
| 113 | | PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P1 Lightgun Trigger") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002) |
| 113 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P1 Lightgun Trigger") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002) |
| 114 | 114 | INPUT_PORTS_END |
| 115 | 115 | |
| 116 | 116 | static INPUT_PORTS_START( nes_zapper2 ) |
| r23716 | r23717 | |
| 119 | 119 | PORT_START("ZAPPER2_Y") /* P2 zapper */ |
| 120 | 120 | PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020) |
| 121 | 121 | PORT_START("ZAPPER2_T") /* P2 zapper trigger */ |
| 122 | | PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P2 Lightgun Trigger") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020) |
| 122 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P2 Lightgun Trigger") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020) |
| 123 | 123 | INPUT_PORTS_END |
| 124 | 124 | |
| 125 | 125 | static INPUT_PORTS_START( nes_paddle ) |
| 126 | 126 | PORT_START("PADDLE") /* Arkanoid paddle */ |
| 127 | | PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(3) PORT_MINMAX(0x62,0xf2) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0040) |
| 127 | PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(25) PORT_CENTERDELTA(0) PORT_MINMAX(0x62,0xf2) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0040) |
| 128 | PORT_START("PADDLE_BUTTON") /* Arkanoid paddle button */ |
| 129 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Paddle button") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0040) |
| 128 | 130 | INPUT_PORTS_END |
| 129 | 131 | |
| 130 | 132 | static INPUT_PORTS_START( nes ) |