trunk/src/mame/drivers/cops.c
r32689 | r32690 | |
8 | 8 | Bad Boys by Inner Circle, so there is muscial accompaniment to areas |
9 | 9 | where the laserdisc audio is muted. |
10 | 10 | |
| 11 | NOTES: To boot up Revelations, turn the refill key (R) and press button A. |
11 | 12 | TODO: There are probably more ROMs for Revelations, the disc contains |
12 | 13 | full data for a picture based memory game called 'Vision Quest'. |
| 14 | |
| 15 | TODO: There are probably more ROMs for Revelations, the disc contains |
| 16 | full data for a picture based memory game called 'Vision Quest'. |
13 | 17 | |
14 | 18 | LaserMax memory map needs sorting out, Cops uses a subset of what's |
15 | 19 | actually available |
r32689 | r32690 | |
28 | 32 | |
29 | 33 | #include "cops.lh" |
30 | 34 | |
31 | | #define LOG_CDROM 1 |
| 35 | #define LOG_CDROM 0 |
32 | 36 | #define LOG_DACIA 0 |
33 | 37 | |
| 38 | #define CMP_REGISTER 0 |
| 39 | #define AUX_REGISTER 1 |
| 40 | |
34 | 41 | #define MAIN_CLOCK XTAL_4MHz |
35 | 42 | |
36 | 43 | class cops_state : public driver_device |
r32689 | r32690 | |
65 | 72 | DECLARE_WRITE_LINE_MEMBER(via1_irq); |
66 | 73 | DECLARE_WRITE_LINE_MEMBER(via2_irq); |
67 | 74 | void dacia_receive(UINT8 data); |
| 75 | void update_dacia_irq(); |
68 | 76 | DECLARE_WRITE8_MEMBER(dacia_w); |
69 | 77 | DECLARE_READ8_MEMBER(dacia_r); |
70 | 78 | DECLARE_WRITE8_MEMBER(via1_b_w); |
r32689 | r32690 | |
78 | 86 | UINT8 m_lcd_addr_l, m_lcd_addr_h; |
79 | 87 | UINT8 m_lcd_data_l, m_lcd_data_h; |
80 | 88 | |
| 89 | UINT8 m_dacia_irq1_reg; |
| 90 | UINT8 m_dacia_rts1; |
| 91 | UINT8 m_dacia_dtr1; |
| 92 | UINT8 m_parity_1; |
| 93 | UINT8 m_parity_mode_1; |
| 94 | UINT8 m_bpc_1; |
| 95 | int m_dacia_ic_div_1; |
| 96 | UINT8 m_dacia_echo1; |
| 97 | UINT8 m_dacia_stp_1; |
| 98 | UINT8 m_dacia_reg1; |
| 99 | UINT8 m_dacia_fe1; |
| 100 | UINT8 m_dacia_cmp1; |
| 101 | UINT8 m_dacia_cmpval1; |
| 102 | |
| 103 | UINT8 m_dacia_cts; |
| 104 | UINT8 m_dacia_dcd; |
| 105 | UINT8 m_dacia_trans; |
| 106 | |
81 | 107 | UINT8 m_dacia_receiver_data; |
82 | 108 | UINT8 m_dacia_receiver_full; |
83 | 109 | |
r32689 | r32690 | |
106 | 132 | LD_INPUT_TEXT_GET_SET_WINDOW |
107 | 133 | } m_ld_input_state; |
108 | 134 | |
| 135 | UINT8 generate_isr(); |
109 | 136 | void laserdisc_w(UINT8 data); |
110 | 137 | void laserdisc_response_w(UINT8 data); |
111 | 138 | DECLARE_PALETTE_INIT( cops ); |
112 | 139 | }; |
113 | 140 | |
| 141 | const int timer_divide_select[16] = |
| 142 | { |
| 143 | 73728, |
| 144 | 33538, |
| 145 | 27408, |
| 146 | 24576, |
| 147 | 12288, |
| 148 | 6144, |
| 149 | 3072, |
| 150 | 2048, |
| 151 | 1536, |
| 152 | 1024, |
| 153 | 768, |
| 154 | 512, |
| 155 | 384, |
| 156 | 192, |
| 157 | 96, |
| 158 | 16 |
| 159 | }; |
| 160 | |
114 | 161 | void cops_state::video_start() |
115 | 162 | { |
116 | 163 | } |
r32689 | r32690 | |
155 | 202 | |
156 | 203 | TIMER_CALLBACK_MEMBER(cops_state::ld_timer_callback) |
157 | 204 | { |
| 205 | m_dacia_receiver_full = 1; |
| 206 | |
158 | 207 | if ( m_ld_command_current_byte < m_ld_command_total_bytes ) |
159 | 208 | { |
160 | 209 | dacia_receive(m_ld_command_to_send[m_ld_command_current_byte]); |
r32689 | r32690 | |
309 | 358 | * |
310 | 359 | *************************************/ |
311 | 360 | |
| 361 | void cops_state::update_dacia_irq() |
| 362 | { |
| 363 | UINT8 isr = generate_isr(); |
| 364 | //remove bits |
| 365 | isr &= ~m_dacia_irq1_reg; |
| 366 | m_maincpu->set_input_line(INPUT_LINE_NMI, isr? ASSERT_LINE:CLEAR_LINE); |
| 367 | } |
| 368 | |
312 | 369 | void cops_state::dacia_receive(UINT8 data) |
313 | 370 | { |
314 | | m_dacia_receiver_data = data; |
315 | | m_dacia_receiver_full = 1; |
316 | | m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); |
| 371 | if (m_dacia_cmp1) |
| 372 | { |
| 373 | if (m_dacia_cmpval1 == data) |
| 374 | { |
| 375 | m_dacia_receiver_data = data; |
| 376 | m_dacia_receiver_full = 1; |
| 377 | update_dacia_irq(); |
| 378 | m_dacia_cmp1 =0; |
| 379 | m_dacia_cts =1; |
| 380 | m_dacia_trans =1; |
| 381 | } |
| 382 | } |
| 383 | else |
| 384 | { |
| 385 | m_dacia_receiver_data = data; |
| 386 | m_dacia_receiver_full = 1; |
| 387 | update_dacia_irq(); |
| 388 | m_dacia_cts =1; |
| 389 | m_dacia_trans =1; |
| 390 | } |
317 | 391 | } |
318 | 392 | |
| 393 | UINT8 cops_state::generate_isr() |
| 394 | { |
| 395 | UINT8 isr =0; |
| 396 | |
| 397 | isr |= m_dacia_receiver_full; |
| 398 | isr |= (m_dacia_cmp1 << 1); |
| 399 | isr |= (m_dacia_trans <<4); |
| 400 | |
| 401 | if (isr) |
| 402 | { |
| 403 | isr |= 0x40; |
| 404 | } |
| 405 | return isr; |
| 406 | } |
319 | 407 | |
320 | 408 | READ8_MEMBER(cops_state::dacia_r) |
321 | 409 | { |
322 | 410 | switch(offset & 0x07) |
323 | 411 | { |
324 | 412 | case 0: /* ISR1: Interrupt Status Register */ |
325 | | return 0x40 | m_dacia_receiver_full; /* Bit 6: Transmit Data Register Empty (TDRE) */ |
| 413 | { |
| 414 | UINT8 isr = generate_isr(); |
| 415 | m_dacia_trans =0; |
| 416 | m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); |
| 417 | return isr; |
| 418 | } |
| 419 | |
| 420 | case 1: /* CSR1: Control Status Register */ |
| 421 | { |
| 422 | UINT8 csr =0; |
| 423 | csr |= m_dacia_rts1; |
| 424 | csr |= (m_dacia_dtr1 << 1); |
| 425 | csr |= (m_dacia_cts <<4); |
| 426 | csr |= (m_dacia_fe1 <<7); |
| 427 | if (LOG_DACIA) logerror("CSR1 %02x\n",csr); |
| 428 | return csr; |
| 429 | } |
| 430 | |
326 | 431 | case 3: /* RDR1: Receive data register */ |
327 | 432 | m_dacia_receiver_full = 0; |
| 433 | m_dacia_fe1=0; |
| 434 | if (LOG_DACIA) logerror("RDR1 %02x\n",m_dacia_receiver_data); |
328 | 435 | return m_dacia_receiver_data; |
329 | 436 | default: |
330 | 437 | if (LOG_DACIA) logerror("%s:dacia_r(%02x)\n", machine().describe_context(), offset); |
r32689 | r32690 | |
336 | 443 | { |
337 | 444 | switch(offset & 0x07) |
338 | 445 | { |
| 446 | case 0: /* IRQ enable Register 1 */ |
| 447 | { |
| 448 | m_dacia_irq1_reg &= ~0x80; |
| 449 | |
| 450 | if (data & 0x80) //enable bits |
| 451 | { |
| 452 | m_dacia_irq1_reg |= (data & 0x7f); |
| 453 | } |
| 454 | else // disable bits |
| 455 | { |
| 456 | m_dacia_irq1_reg &= ~(data & 0x7f); |
| 457 | } |
| 458 | if (LOG_DACIA) logerror("DACIA IRQ 1 Register: %02x\n", m_dacia_irq1_reg); |
| 459 | update_dacia_irq(); |
| 460 | break; |
| 461 | } |
| 462 | |
| 463 | case 1: /* Control / Format Register 1 */ |
| 464 | { |
| 465 | if (data & 0x80) //Format Register |
| 466 | { |
| 467 | m_dacia_rts1 = (data & 0x01); |
| 468 | m_dacia_dtr1 = (data & 0x02 ? 1:0); |
| 469 | m_parity_1 = (data & 0x04); |
| 470 | m_parity_mode_1 = ((data & 0x18) >> 3); |
| 471 | m_bpc_1 = ((data & 0x60) >> 5) +5; |
| 472 | if (LOG_DACIA) logerror("DACIA Format Register: %02x\n", data); |
| 473 | } |
| 474 | else // Control register |
| 475 | { |
| 476 | m_dacia_ic_div_1 = timer_divide_select[data & 0x15]; |
| 477 | m_dacia_echo1 = (data & 0x10); |
| 478 | m_dacia_stp_1 = (data & 0x20 ? 2:1); |
| 479 | if (data & 0x40) |
| 480 | { |
| 481 | m_dacia_reg1 = AUX_REGISTER; |
| 482 | } |
| 483 | else |
| 484 | { |
| 485 | m_dacia_reg1 = CMP_REGISTER; |
| 486 | } |
| 487 | if (LOG_DACIA) logerror("DACIA TIME %02d\n", XTAL_3_6864MHz / m_dacia_ic_div_1); |
| 488 | |
| 489 | m_ld_timer->adjust(attotime::from_hz(XTAL_3_6864MHz / m_dacia_ic_div_1), 0, attotime::from_hz(XTAL_3_6864MHz / m_dacia_ic_div_1)); |
| 490 | |
| 491 | if (LOG_DACIA) logerror("DACIA Ctrl Register: %02x\n", data); |
| 492 | |
| 493 | } |
| 494 | break; |
| 495 | } |
| 496 | case 2: /* Compare / Aux Ctrl Register 1 */ |
| 497 | { |
| 498 | if (m_dacia_reg1 == CMP_REGISTER) |
| 499 | { |
| 500 | m_dacia_cmp1 =1; |
| 501 | m_dacia_cmpval1=data; |
| 502 | if (LOG_DACIA) logerror("DACIA Compare mode: %02x \n", data); |
| 503 | // update_dacia_irq(); |
| 504 | } |
| 505 | else |
| 506 | { |
| 507 | if (LOG_DACIA) logerror("DACIA Aux ctrl: %02x \n", data); |
| 508 | } |
| 509 | } |
339 | 510 | case 3: /* Transmit Data Register 1 */ |
340 | | //logerror("DACIA Transmit: %02x %c\n", data, (char)data); |
| 511 | if (LOG_DACIA) logerror("DACIA Transmit: %02x %c\n", data, (char)data); |
341 | 512 | laserdisc_w(data); |
342 | 513 | break; |
343 | 514 | default: |
r32689 | r32690 | |
589 | 760 | PORT_BIT( 0xff, 0x80, IPT_PADDLE ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) |
590 | 761 | INPUT_PORTS_END |
591 | 762 | |
| 763 | static INPUT_PORTS_START( revlatns ) |
| 764 | PORT_START("SW0") |
| 765 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A") |
| 766 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("C") |
| 767 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("COLLECT") |
| 768 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN5 ) |
| 769 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_IMPULSE(1) |
| 770 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN6 ) |
| 771 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("Continue") |
| 772 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B") |
| 773 | |
| 774 | PORT_START("SW1") |
| 775 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Refill Key") PORT_CODE(KEYCODE_R) PORT_TOGGLE |
| 776 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_INTERLOCK) PORT_NAME("Cashbox Door") PORT_CODE(KEYCODE_Q) PORT_TOGGLE |
| 777 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("20P LEVEL") PORT_CODE(KEYCODE_Q) |
| 778 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 779 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 780 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 781 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("*") |
| 782 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("100P LEVEL") PORT_CODE(KEYCODE_W) |
| 783 | |
| 784 | PORT_START("SW2") |
| 785 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_NAME("50p") |
| 786 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_NAME("20p") |
| 787 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN3 ) PORT_NAME("10p") |
| 788 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN4 ) PORT_NAME("100p") |
| 789 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SPECIAL ) |
| 790 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SPECIAL ) |
| 791 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) |
| 792 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SPECIAL ) |
| 793 | |
| 794 | INPUT_PORTS_END |
| 795 | |
592 | 796 | void cops_state::machine_start() |
593 | 797 | { |
594 | 798 | m_ld_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cops_state::ld_timer_callback),this)); |
| 799 | m_dacia_ic_div_1 = timer_divide_select[0]; |
| 800 | |
595 | 801 | m_ld_timer->adjust(attotime::from_hz(167*5), 0, attotime::from_hz(167*5)); |
596 | 802 | } |
597 | 803 | |
r32689 | r32690 | |
601 | 807 | m_lcd_addr_l = m_lcd_addr_h = 0; |
602 | 808 | m_lcd_data_l = m_lcd_data_h = 0; |
603 | 809 | |
604 | | m_dacia_receiver_full = 0; |
| 810 | m_dacia_cts = 0; |
| 811 | m_dacia_dcd = 0; |
| 812 | |
| 813 | m_dacia_irq1_reg = 0x80; |
| 814 | m_dacia_rts1 = 1; |
| 815 | m_dacia_dtr1 = 1; |
| 816 | m_dacia_fe1 = 1; |
| 817 | m_dacia_receiver_full = 1; |
605 | 818 | m_ld_input_state = LD_INPUT_GET_COMMAND; |
606 | 819 | m_ld_command_current_byte = m_ld_command_total_bytes = 0; |
607 | 820 | m_ld_frame_index = 0; |
r32689 | r32690 | |
698 | 911 | ROM_END |
699 | 912 | |
700 | 913 | |
701 | | GAMEL( 1994, cops, 0, cops, cops, cops_state, cops, ROT0, "Atari Games", "Cops (USA)", GAME_NOT_WORKING | GAME_NO_SOUND, layout_cops ) |
702 | | GAMEL( 1994, copsuk, cops,cops, cops, cops_state, cops, ROT0, "Nova Productions / Deith Leisure","Cops (UK)", GAME_NOT_WORKING | GAME_NO_SOUND, layout_cops ) |
703 | | GAMEL( 1994, revlatns, 0, cops, cops, cops_state, cops, ROT0, "Nova Productions", "Revelations", GAME_NOT_WORKING | GAME_NO_SOUND, layout_cops ) |
| 914 | GAMEL( 1994, cops, 0, cops, cops, cops_state, cops, ROT0, "Atari Games", "Cops (USA)", GAME_NOT_WORKING | GAME_NO_SOUND, layout_cops ) |
| 915 | GAMEL( 1994, copsuk, cops,cops, cops, cops_state, cops, ROT0, "Nova Productions / Deith Leisure","Cops (UK)", GAME_NOT_WORKING | GAME_NO_SOUND, layout_cops ) |
| 916 | GAMEL( 1994, revlatns, 0, cops, revlatns, cops_state, cops, ROT0, "Nova Productions", "Revelations", GAME_NOT_WORKING | GAME_NO_SOUND, layout_cops ) |