trunk/src/mess/machine/nes.c
| r23696 | r23697 | |
| 211 | 211 | READ8_MEMBER(nes_state::nes_IN0_r) |
| 212 | 212 | { |
| 213 | 213 | int cfg = m_io_ctrlsel->read(); |
| 214 | | int ret; |
| 215 | | |
| 216 | | if ((cfg & 0x000f) >= 0x08) // for now we treat the FC keyboard separately from other inputs! |
| 214 | /* Some games expect bit 6 to be set because the last entry on the data bus shows up */ |
| 215 | /* in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. */ |
| 216 | UINT8 ret = 0x40; |
| 217 | |
| 218 | if ((cfg & 0x000f) >= 0x08) |
| 217 | 219 | { |
| 218 | 220 | // here we should have the tape input |
| 219 | | ret = 0; |
| 221 | ret |= 0; |
| 220 | 222 | } |
| 221 | | else |
| 222 | | { |
| 223 | | /* Some games expect bit 6 to be set because the last entry on the data bus shows up */ |
| 224 | | /* in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. */ |
| 225 | | ret = 0x40; |
| 226 | 223 | |
| 227 | | ret |= ((m_in_0.i0 >> m_in_0.shift) & 0x01); |
| 224 | ret |= ((m_in_0.i0 >> m_in_0.shift) & 0x01); |
| 228 | 225 | |
| 229 | | /* zapper */ |
| 230 | | if ((cfg & 0x000f) == 0x0002) |
| 231 | | { |
| 232 | | int x = m_in_0.i1; /* read Zapper x-position */ |
| 233 | | int y = m_in_0.i2; /* read Zapper y-position */ |
| 234 | | UINT32 pix, color_base; |
| 226 | /* zapper */ |
| 227 | if ((cfg & 0x000f) == 0x0002) |
| 228 | { |
| 229 | int x = m_in_0.i1; /* read Zapper x-position */ |
| 230 | int y = m_in_0.i2; /* read Zapper y-position */ |
| 231 | UINT32 pix, color_base; |
| 235 | 232 | |
| 236 | | /* get the pixel at the gun position */ |
| 237 | | pix = m_ppu->get_pixel(x, y); |
| 233 | /* get the pixel at the gun position */ |
| 234 | pix = m_ppu->get_pixel(x, y); |
| 238 | 235 | |
| 239 | | /* get the color base from the ppu */ |
| 240 | | color_base = m_ppu->get_colorbase(); |
| 236 | /* get the color base from the ppu */ |
| 237 | color_base = m_ppu->get_colorbase(); |
| 241 | 238 | |
| 242 | | /* look at the screen and see if the cursor is over a bright pixel */ |
| 243 | | if ((pix == color_base + 0x20) || (pix == color_base + 0x30) || |
| 244 | | (pix == color_base + 0x33) || (pix == color_base + 0x34)) |
| 245 | | { |
| 246 | | ret &= ~0x08; /* sprite hit */ |
| 247 | | } |
| 248 | | else |
| 249 | | ret |= 0x08; /* no sprite hit */ |
| 250 | | |
| 251 | | /* If button 1 is pressed, indicate the light gun trigger is pressed */ |
| 252 | | ret |= ((m_in_0.i0 & 0x01) << 4); |
| 239 | /* look at the screen and see if the cursor is over a bright pixel */ |
| 240 | if ((pix == color_base + 0x20) || (pix == color_base + 0x30) || |
| 241 | (pix == color_base + 0x33) || (pix == color_base + 0x34)) |
| 242 | { |
| 243 | ret &= ~0x08; /* sprite hit */ |
| 253 | 244 | } |
| 245 | else |
| 246 | ret |= 0x08; /* no sprite hit */ |
| 254 | 247 | |
| 255 | | if (LOG_JOY) |
| 256 | | 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); |
| 257 | | |
| 258 | | m_in_0.shift++; |
| 248 | /* If button 1 is pressed, indicate the light gun trigger is pressed */ |
| 249 | ret |= ((m_in_0.i0 & 0x01) << 4); |
| 259 | 250 | } |
| 260 | 251 | |
| 252 | if (LOG_JOY) |
| 253 | 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); |
| 254 | |
| 255 | m_in_0.shift++; |
| 256 | |
| 261 | 257 | return ret; |
| 262 | 258 | } |
| 263 | 259 | |
| 264 | 260 | READ8_MEMBER(nes_state::nes_IN1_r) |
| 265 | 261 | { |
| 266 | 262 | int cfg = m_io_ctrlsel->read(); |
| 267 | | int ret; |
| 268 | | |
| 263 | /* Some games expect bit 6 to be set because the last entry on the data bus shows up */ |
| 264 | /* in the unused upper 3 bits, so typically a read from $4017 leaves 0x40 there. */ |
| 265 | UINT8 ret = 0x40; |
| 266 | |
| 269 | 267 | // row of the keyboard matrix are read 4-bits at time, and gets returned as bit1->bit4 |
| 270 | 268 | if ((cfg & 0x000f) == 0x08) // for now we treat the FC keyboard separately from other inputs! |
| 271 | 269 | { |
| 272 | 270 | if (m_fck_scan < 9) |
| 273 | | ret = ~(((m_io_fckey[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e; |
| 271 | ret |= ~(((m_io_fckey[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e; |
| 274 | 272 | else |
| 275 | | ret = 0x1e; |
| 273 | ret |= 0x1e; |
| 276 | 274 | } |
| 277 | | else if ((cfg & 0x000f) == 0x09) // for now we treat the Subor keyboard separately from other inputs! |
| 275 | |
| 276 | if ((cfg & 0x000f) == 0x09) // for now we treat the Subor keyboard separately from other inputs! |
| 278 | 277 | { |
| 279 | 278 | if (m_fck_scan < 12) |
| 280 | | ret = ~(((m_io_subkey[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e; |
| 279 | ret |= ~(((m_io_subkey[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e; |
| 281 | 280 | else |
| 282 | | ret = 0x1e; |
| 281 | ret |= 0x1e; |
| 283 | 282 | } |
| 283 | |
| 284 | /* Handle data line 0's serial output */ |
| 285 | if ((cfg & 0x00f0) == 0x0070) |
| 286 | ret |= (((m_in_1.i0 >> m_in_1.shift) & 0x01) << 1); |
| 284 | 287 | else |
| 285 | | { |
| 286 | | /* Some games expect bit 6 to be set because the last entry on the data bus shows up */ |
| 287 | | /* in the unused upper 3 bits, so typically a read from $4017 leaves 0x40 there. */ |
| 288 | | ret = 0x40; |
| 288 | ret |= ((m_in_1.i0 >> m_in_1.shift) & 0x01); |
| 289 | 289 | |
| 290 | | /* Handle data line 0's serial output */ |
| 291 | | if((cfg & 0x00f0) == 0x0070) |
| 292 | | ret |= (((m_in_1.i0 >> m_in_1.shift) & 0x01) << 1); |
| 293 | | else |
| 294 | | ret |= ((m_in_1.i0 >> m_in_1.shift) & 0x01); |
| 295 | | |
| 296 | | /* zapper */ |
| 297 | | if ((cfg & 0x00f0) == 0x0030) |
| 290 | /* zapper */ |
| 291 | if ((cfg & 0x00f0) == 0x0030) |
| 292 | { |
| 293 | int x = m_in_1.i1; /* read Zapper x-position */ |
| 294 | int y = m_in_1.i2; /* read Zapper y-position */ |
| 295 | UINT32 pix, color_base; |
| 296 | |
| 297 | /* get the pixel at the gun position */ |
| 298 | pix = m_ppu->get_pixel(x, y); |
| 299 | |
| 300 | /* get the color base from the ppu */ |
| 301 | color_base = m_ppu->get_colorbase(); |
| 302 | |
| 303 | /* look at the screen and see if the cursor is over a bright pixel */ |
| 304 | if ((pix == color_base + 0x20) || (pix == color_base + 0x30) || |
| 305 | (pix == color_base + 0x33) || (pix == color_base + 0x34)) |
| 298 | 306 | { |
| 299 | | int x = m_in_1.i1; /* read Zapper x-position */ |
| 300 | | int y = m_in_1.i2; /* read Zapper y-position */ |
| 301 | | UINT32 pix, color_base; |
| 302 | | |
| 303 | | /* get the pixel at the gun position */ |
| 304 | | pix = m_ppu->get_pixel(x, y); |
| 305 | | |
| 306 | | /* get the color base from the ppu */ |
| 307 | | color_base = m_ppu->get_colorbase(); |
| 308 | | |
| 309 | | /* look at the screen and see if the cursor is over a bright pixel */ |
| 310 | | if ((pix == color_base + 0x20) || (pix == color_base + 0x30) || |
| 311 | | (pix == color_base + 0x33) || (pix == color_base + 0x34)) |
| 312 | | { |
| 313 | | ret &= ~0x08; /* sprite hit */ |
| 314 | | } |
| 315 | | else |
| 316 | | ret |= 0x08; /* no sprite hit */ |
| 317 | | |
| 318 | | /* If button 1 is pressed, indicate the light gun trigger is pressed */ |
| 319 | | ret |= ((m_in_1.i0 & 0x01) << 4); |
| 307 | ret &= ~0x08; /* sprite hit */ |
| 320 | 308 | } |
| 321 | | |
| 322 | | /* arkanoid dial */ |
| 323 | | else if ((cfg & 0x00f0) == 0x0040) |
| 324 | | { |
| 325 | | /* Handle data line 2's serial output */ |
| 326 | | ret |= ((m_in_1.i2 >> m_in_1.shift) & 0x01) << 3; |
| 327 | | |
| 328 | | /* Handle data line 3's serial output - bits are reversed */ |
| 329 | | /* NPW 27-Nov-2007 - there is no third subscript! commenting out */ |
| 330 | | /* ret |= ((m_in_1[3] >> m_in_1.shift) & 0x01) << 4; */ |
| 331 | | /* ret |= ((m_in_1[3] << m_in_1.shift) & 0x80) >> 3; */ |
| 332 | | } |
| 333 | | |
| 334 | | if (LOG_JOY) |
| 335 | | 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); |
| 336 | | |
| 337 | | m_in_1.shift++; |
| 309 | else |
| 310 | ret |= 0x08; /* no sprite hit */ |
| 311 | |
| 312 | /* If button 1 is pressed, indicate the light gun trigger is pressed */ |
| 313 | ret |= ((m_in_1.i0 & 0x01) << 4); |
| 338 | 314 | } |
| 339 | 315 | |
| 340 | | return ret; |
| 341 | | } |
| 342 | | |
| 343 | | |
| 344 | | // FIXME: this is getting messier and messier (no pun intended). inputs reading should be simplified and port_categories cleaned up |
| 345 | | // to also emulate the fact that nothing should be in Port 2 if there is a Crazy Climber pad, etc. |
| 346 | | static void nes_read_input_device( running_machine &machine, int cfg, nes_input *vals, int pad_port, int supports_zapper, int mux_data ) |
| 347 | | { |
| 348 | | nes_state *state = machine.driver_data<nes_state>(); |
| 349 | | |
| 350 | | vals->i0 = 0; |
| 351 | | vals->i1 = 0; |
| 352 | | vals->i2 = 0; |
| 353 | | |
| 354 | | switch (cfg & 0x0f) |
| 316 | /* arkanoid dial */ |
| 317 | if ((cfg & 0x00f0) == 0x0040) |
| 355 | 318 | { |
| 356 | | case 0x01: /* gamepad */ |
| 357 | | if (pad_port >= 0) |
| 358 | | vals->i0 = state->m_io_pad[pad_port]->read(); |
| 359 | | break; |
| 319 | /* Handle data line 2's serial output */ |
| 320 | ret |= ((m_in_1.i2 >> m_in_1.shift) & 0x01) << 3; |
| 360 | 321 | |
| 361 | | case 0x02: /* zapper 1 */ |
| 362 | | if (supports_zapper) |
| 363 | | { |
| 364 | | vals->i0 = state->m_io_zapper1_t->read(); |
| 365 | | vals->i1 = state->m_io_zapper1_x->read(); |
| 366 | | vals->i2 = state->m_io_zapper1_y->read(); |
| 367 | | } |
| 368 | | break; |
| 322 | /* Handle data line 3's serial output - bits are reversed */ |
| 323 | /* NPW 27-Nov-2007 - there is no third subscript! commenting out */ |
| 324 | /* ret |= ((m_in_1[3] >> m_in_1.shift) & 0x01) << 4; */ |
| 325 | /* ret |= ((m_in_1[3] << m_in_1.shift) & 0x80) >> 3; */ |
| 326 | } |
| 369 | 327 | |
| 370 | | case 0x03: /* zapper 2 */ |
| 371 | | if (supports_zapper) |
| 372 | | { |
| 373 | | vals->i0 = state->m_io_zapper2_t->read(); |
| 374 | | vals->i1 = state->m_io_zapper2_x->read(); |
| 375 | | vals->i2 = state->m_io_zapper2_y->read(); |
| 376 | | } |
| 377 | | break; |
| 328 | if (LOG_JOY) |
| 329 | 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); |
| 378 | 330 | |
| 379 | | case 0x04: /* arkanoid paddle */ |
| 380 | | if (pad_port == 1) |
| 381 | | vals->i0 = (UINT8) ((UINT8) state->m_io_paddle->read() + (UINT8)0x52) ^ 0xff; |
| 382 | | break; |
| 331 | m_in_1.shift++; |
| 383 | 332 | |
| 384 | | case 0x06: /* crazy climber controller */ |
| 385 | | if (pad_port == 0) |
| 386 | | { |
| 387 | | state->m_in_0.i0 = state->m_io_cc_left->read(); |
| 388 | | state->m_in_1.i0 = state->m_io_cc_right->read(); |
| 389 | | } |
| 390 | | break; |
| 391 | | |
| 392 | | case 0x07: /* Mahjong Panel */ |
| 393 | | if(mux_data & 0xf8) |
| 394 | | logerror("Error: Mahjong panel read with mux data %02x\n",mux_data); |
| 395 | | else |
| 396 | | vals->i0 = state->m_io_mahjong[mux_data >> 1]->read(); |
| 397 | | break; |
| 398 | | } |
| 333 | return ret; |
| 399 | 334 | } |
| 400 | 335 | |
| 401 | 336 | |
| r23696 | r23697 | |
| 444 | 379 | /* Check if lightgun has been chosen as input: if so, enable crosshair */ |
| 445 | 380 | timer_set(attotime::zero, TIMER_LIGHTGUN_TICK); |
| 446 | 381 | |
| 447 | | if ((cfg & 0x000f) >= 0x08) // for now we treat the FC keyboard separately from other inputs! |
| 382 | if ((cfg & 0x000f) >= 0x08) |
| 448 | 383 | { |
| 449 | 384 | // here we should also have the tape output |
| 450 | 385 | |
| 451 | 386 | if (BIT(data, 2)) // keyboard active |
| 452 | 387 | { |
| 453 | | int lines = ((cfg & 0x000f) == 0x04) ? 9 : 12; |
| 388 | int lines = ((cfg & 0x000f) == 0x08) ? 9 : 12; |
| 454 | 389 | UINT8 out = BIT(data, 1); // scan |
| 455 | 390 | |
| 456 | 391 | if (m_fck_mode && !out && ++m_fck_scan > lines) |
| r23696 | r23697 | |
| 462 | 397 | m_fck_scan = 0; |
| 463 | 398 | } |
| 464 | 399 | } |
| 465 | | else |
| 466 | | { |
| 467 | | if (data & 0x01) |
| 468 | | return; |
| 469 | 400 | |
| 470 | | if (LOG_JOY) |
| 471 | | logerror("joy 0 bits read: %d\n", m_in_0.shift); |
| 472 | | |
| 473 | | /* Toggling bit 0 high then low resets both controllers */ |
| 474 | | m_in_0.shift = 0; |
| 475 | | m_in_1.shift = 0; |
| 476 | | |
| 477 | | /* Read the input devices */ |
| 478 | | if ((cfg & 0x000f) != 0x06) |
| 479 | | { |
| 480 | | nes_read_input_device(machine(), cfg >> 0, &m_in_0, 0, TRUE,data & 0xfe); |
| 481 | | nes_read_input_device(machine(), cfg >> 4, &m_in_1, 1, TRUE,data & 0xfe); |
| 482 | | nes_read_input_device(machine(), cfg >> 8, &m_in_2, 2, FALSE,data & 0xfe); |
| 483 | | nes_read_input_device(machine(), cfg >> 12, &m_in_3, 3, FALSE,data & 0xfe); |
| 484 | | } |
| 485 | | else // crazy climber pad |
| 486 | | { |
| 487 | | nes_read_input_device(machine(), 0, &m_in_1, 1, TRUE,data & 0xfe); |
| 488 | | nes_read_input_device(machine(), 0, &m_in_2, 2, FALSE,data & 0xfe); |
| 489 | | nes_read_input_device(machine(), 0, &m_in_3, 3, FALSE,data & 0xfe); |
| 490 | | nes_read_input_device(machine(), cfg >> 0, &m_in_0, 0, TRUE,data & 0xfe); |
| 491 | | } |
| 492 | | |
| 493 | | if (cfg & 0x0f00) |
| 494 | | m_in_0.i0 |= (m_in_2.i0 << 8) | (0x08 << 16); |
| 495 | | |
| 496 | | if (cfg & 0xf000) |
| 497 | | m_in_1.i0 |= (m_in_3.i0 << 8) | (0x04 << 16); |
| 401 | // check 'standard' inputs |
| 402 | if (data & 0x01) |
| 403 | return; |
| 404 | |
| 405 | if (LOG_JOY) |
| 406 | logerror("joy 0 bits read: %d\n", m_in_0.shift); |
| 407 | |
| 408 | /* Toggling bit 0 high then low resets both controllers */ |
| 409 | m_in_0.shift = 0; |
| 410 | m_in_1.shift = 0; |
| 411 | m_in_0.i0 = 0; |
| 412 | m_in_0.i1 = 0; |
| 413 | m_in_0.i2 = 0; |
| 414 | m_in_1.i0 = 0; |
| 415 | m_in_1.i1 = 0; |
| 416 | m_in_1.i2 = 0; |
| 417 | m_in_2.i0 = 0; |
| 418 | m_in_2.i1 = 0; |
| 419 | m_in_2.i2 = 0; |
| 420 | m_in_3.i0 = 0; |
| 421 | m_in_3.i1 = 0; |
| 422 | m_in_3.i2 = 0; |
| 423 | |
| 424 | // P1 inputs |
| 425 | switch (cfg & 0x000f) |
| 426 | { |
| 427 | case 0x01: /* gamepad */ |
| 428 | m_in_0.i0 = m_io_pad[0]->read(); |
| 429 | break; |
| 430 | |
| 431 | case 0x02: /* zapper 1 */ |
| 432 | m_in_0.i0 = m_io_zapper1_t->read(); |
| 433 | m_in_0.i1 = m_io_zapper1_x->read(); |
| 434 | m_in_0.i2 = m_io_zapper1_y->read(); |
| 435 | break; |
| 436 | |
| 437 | case 0x06: /* crazy climber controller */ |
| 438 | m_in_0.i0 = m_io_cc_left->read(); |
| 439 | m_in_1.i0 = m_io_cc_right->read(); |
| 440 | break; |
| 498 | 441 | } |
| 442 | |
| 443 | // P2 inputs |
| 444 | switch ((cfg & 0x00f0) >> 4) |
| 445 | { |
| 446 | case 0x01: /* gamepad */ |
| 447 | m_in_1.i0 = m_io_pad[1]->read(); |
| 448 | break; |
| 449 | |
| 450 | case 0x03: /* zapper 2 */ |
| 451 | m_in_1.i0 = m_io_zapper2_t->read(); |
| 452 | m_in_1.i1 = m_io_zapper2_x->read(); |
| 453 | m_in_1.i2 = m_io_zapper2_y->read(); |
| 454 | break; |
| 455 | |
| 456 | case 0x04: /* arkanoid paddle */ |
| 457 | m_in_1.i0 = (UINT8) ((UINT8) m_io_paddle->read() + (UINT8)0x52) ^ 0xff; |
| 458 | break; |
| 459 | |
| 460 | case 0x07: /* Mahjong Panel */ |
| 461 | if (data & 0xf8) |
| 462 | logerror("Error: Mahjong panel read with mux data %02x\n", (data & 0xfe)); |
| 463 | else |
| 464 | m_in_1.i0 = m_io_mahjong[(data & 0xfe) >> 1]->read(); |
| 465 | break; |
| 466 | } |
| 467 | |
| 468 | // P3 inputs |
| 469 | if ((cfg & 0x0f00)) |
| 470 | m_in_2.i0 = m_io_pad[2]->read(); |
| 471 | |
| 472 | // P4 inputs |
| 473 | if ((cfg & 0x0f00)) |
| 474 | m_in_3.i0 = m_io_pad[3]->read(); |
| 475 | |
| 476 | if (cfg & 0x0f00) |
| 477 | m_in_0.i0 |= (m_in_2.i0 << 8) | (0x08 << 16); |
| 478 | |
| 479 | if (cfg & 0xf000) |
| 480 | m_in_1.i0 |= (m_in_3.i0 << 8) | (0x04 << 16); |
| 481 | |
| 499 | 482 | } |
| 500 | 483 | |
| 501 | 484 | |