trunk/src/mess/drivers/psx.c
| r20301 | r20302 | |
| 16 | 16 | #include "debugger.h" |
| 17 | 17 | #include "zlib.h" |
| 18 | 18 | #include "machine/psxcd.h" |
| 19 | | #include "machine/psxcard.h" |
| 20 | 19 | #include "machine/psxcport.h" |
| 21 | 20 | |
| 22 | 21 | class psx1_state : public driver_device |
| r20301 | r20302 | |
| 507 | 506 | { |
| 508 | 507 | } |
| 509 | 508 | |
| 510 | | static INPUT_PORTS_START( psx ) |
| 511 | | PORT_START("IN0") |
| 512 | | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) |
| 513 | | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) |
| 514 | | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) |
| 515 | | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) |
| 516 | | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) |
| 517 | | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_PLAYER(1) |
| 518 | | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_PLAYER(1) |
| 519 | | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SELECT ) PORT_PLAYER(1) |
| 520 | | |
| 521 | | PORT_START("IN1") |
| 522 | | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 Square") |
| 523 | | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 Cross") |
| 524 | | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 Circle") |
| 525 | | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("P1 Triangle") |
| 526 | | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("P1 R1") |
| 527 | | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("P1 L1") |
| 528 | | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("P1 R2") |
| 529 | | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(1) PORT_NAME("P1 L2") |
| 530 | | |
| 531 | | PORT_START("IN2") |
| 532 | | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) |
| 533 | | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) |
| 534 | | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) |
| 535 | | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) |
| 536 | | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) |
| 537 | | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_PLAYER(2) |
| 538 | | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_PLAYER(2) |
| 539 | | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SELECT ) PORT_PLAYER(2) |
| 540 | | |
| 541 | | PORT_START("IN3") |
| 542 | | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 Square") |
| 543 | | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 Cross") |
| 544 | | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 Circle") |
| 545 | | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("P2 Triangle") |
| 546 | | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("P2 R1") |
| 547 | | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("P2 L1") |
| 548 | | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("P2 R2") |
| 549 | | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(2) PORT_NAME("P2 L2") |
| 550 | | INPUT_PORTS_END |
| 551 | | |
| 552 | 509 | struct cdrom_interface psx_cdrom = |
| 553 | 510 | { |
| 554 | 511 | "psx_cdrom", |
| r20301 | r20302 | |
| 561 | 518 | MCFG_CPU_PROGRAM_MAP( psx_map ) |
| 562 | 519 | |
| 563 | 520 | MCFG_DEVICE_ADD("maincpu:sio0:controllers", PSXCONTROLLERPORTS, 0) |
| 521 | MCFG_PSX_CTRL_PORT_ADD("port1", psx_controllers, "digital_pad", NULL) |
| 522 | MCFG_PSX_CTRL_PORT_ADD("port2", psx_controllers, "digital_pad", NULL) |
| 564 | 523 | |
| 565 | 524 | /* video hardware */ |
| 566 | 525 | MCFG_PSXGPU_ADD( "maincpu", "gpu", CXD8561Q, 0x100000, XTAL_53_693175MHz ) |
| r20301 | r20302 | |
| 581 | 540 | MCFG_PSXCD_IRQ_HANDLER(DEVWRITELINE("maincpu:irq", psxirq_device, intin2)) |
| 582 | 541 | MCFG_PSX_DMA_CHANNEL_READ( "maincpu", 3, psx_dma_read_delegate( FUNC( cd_dma_read ), (psxcd_device *) device ) ) |
| 583 | 542 | MCFG_PSX_DMA_CHANNEL_WRITE( "maincpu", 3, psx_dma_write_delegate( FUNC( cd_dma_write ), (psxcd_device *) device ) ) |
| 584 | | |
| 585 | | MCFG_PSXCARD_ADD("card1") |
| 586 | | MCFG_PSXCARD_ADD("card2") |
| 587 | 543 | MACHINE_CONFIG_END |
| 588 | 544 | |
| 589 | 545 | static MACHINE_CONFIG_START( psxpal, psx1_state ) |
| r20301 | r20302 | |
| 591 | 547 | MCFG_CPU_ADD( "maincpu", CXD8530AQ, XTAL_67_7376MHz ) |
| 592 | 548 | MCFG_CPU_PROGRAM_MAP( psx_map) |
| 593 | 549 | |
| 550 | MCFG_DEVICE_ADD("maincpu:sio0:controllers", PSXCONTROLLERPORTS, 0) |
| 551 | MCFG_PSX_CTRL_PORT_ADD("port1", psx_controllers, "digital_pad", NULL) |
| 552 | MCFG_PSX_CTRL_PORT_ADD("port2", psx_controllers, "digital_pad", NULL) |
| 553 | |
| 594 | 554 | /* video hardware */ |
| 595 | 555 | /* TODO: visible area and refresh rate */ |
| 596 | 556 | MCFG_PSXGPU_ADD( "maincpu", "gpu", CXD8561Q, 0x100000, XTAL_53_693175MHz ) |
| r20301 | r20302 | |
| 611 | 571 | MCFG_PSXCD_IRQ_HANDLER(DEVWRITELINE("maincpu:irq", psxirq_device, intin2)) |
| 612 | 572 | MCFG_PSX_DMA_CHANNEL_READ( "maincpu", 3, psx_dma_read_delegate( FUNC( cd_dma_read ), (psxcd_device *) device ) ) |
| 613 | 573 | MCFG_PSX_DMA_CHANNEL_WRITE( "maincpu", 3, psx_dma_write_delegate( FUNC( cd_dma_write ), (psxcd_device *) device ) ) |
| 614 | | |
| 615 | | MCFG_PSXCARD_ADD("card1") |
| 616 | | MCFG_PSXCARD_ADD("card2") |
| 617 | 574 | MACHINE_CONFIG_END |
| 618 | 575 | |
| 619 | 576 | ROM_START( psj ) |
| r20301 | r20302 | |
| 738 | 695 | */ |
| 739 | 696 | |
| 740 | 697 | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ |
| 741 | | CONS( 1994, psj, 0, 0, psxntsc, psx, psx1_state, psx, "Sony Computer Entertainment Inc", "Sony PlayStation (Japan)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) |
| 742 | | CONS( 1995, pse, psj, 0, psxpal, psx, psx1_state, psx, "Sony Computer Entertainment Inc", "Sony PlayStation (Europe)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) |
| 743 | | CONS( 1995, psu, psj, 0, psxntsc, psx, psx1_state, psx, "Sony Computer Entertainment Inc", "Sony PlayStation (USA)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) |
| 744 | | CONS( 1995, psa, psj, 0, psxntsc, psx, psx1_state, psx, "Sony Computer Entertainment Inc", "Sony PlayStation (Asia-Pacific)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) |
| 698 | CONS( 1994, psj, 0, 0, psxntsc, 0, psx1_state, psx, "Sony Computer Entertainment Inc", "Sony PlayStation (Japan)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) |
| 699 | CONS( 1995, pse, psj, 0, psxpal, 0, psx1_state, psx, "Sony Computer Entertainment Inc", "Sony PlayStation (Europe)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) |
| 700 | CONS( 1995, psu, psj, 0, psxntsc, 0, psx1_state, psx, "Sony Computer Entertainment Inc", "Sony PlayStation (USA)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) |
| 701 | CONS( 1995, psa, psj, 0, psxntsc, 0, psx1_state, psx, "Sony Computer Entertainment Inc", "Sony PlayStation (Asia-Pacific)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) |
trunk/src/mess/machine/psxanalog.c
| r0 | r20302 | |
| 1 | #include "machine/psxanalog.h" |
| 2 | |
| 3 | const device_type PSX_ANALOG_CONTROLLER = &device_creator<psx_analog_controller_device>; |
| 4 | |
| 5 | psx_analog_controller_device::psx_analog_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 6 | device_t(mconfig, PSX_ANALOG_CONTROLLER, "Playstation Analog Controller", tag, owner, clock), |
| 7 | device_psx_controller_interface(mconfig, *this) |
| 8 | { |
| 9 | } |
| 10 | |
| 11 | void psx_analog_controller_device::device_reset() |
| 12 | { |
| 13 | m_confmode = false; |
| 14 | m_analogmode = false; |
| 15 | m_analoglock = false; |
| 16 | |
| 17 | m_cmd = 0; |
| 18 | } |
| 19 | |
| 20 | UINT8 psx_analog_controller_device::pad_data(int count, bool analog) |
| 21 | { |
| 22 | UINT8 data; |
| 23 | switch(count) |
| 24 | { |
| 25 | case 2: |
| 26 | data = ioport("PSXPAD0")->read(); |
| 27 | if(!analog) |
| 28 | data |= 6; |
| 29 | break; |
| 30 | case 3: |
| 31 | data = ioport("PSXPAD1")->read(); |
| 32 | break; |
| 33 | case 4: |
| 34 | data = ioport("PSXRSTICKX")->read(); |
| 35 | break; |
| 36 | case 5: |
| 37 | data = ioport("PSXRSTICKY")->read(); |
| 38 | break; |
| 39 | case 6: |
| 40 | data = ioport("PSXLSTICKX")->read(); |
| 41 | break; |
| 42 | case 7: |
| 43 | data = ioport("PSXLSTICKY")->read(); |
| 44 | break; |
| 45 | } |
| 46 | return data; |
| 47 | } |
| 48 | |
| 49 | bool psx_analog_controller_device::get_pad(int count, UINT8 *odata, UINT8 idata) |
| 50 | { |
| 51 | if(m_confmode) |
| 52 | { |
| 53 | switch(count) |
| 54 | { |
| 55 | case 0: |
| 56 | m_temp = 0; |
| 57 | *odata = 0xf3; |
| 58 | break; |
| 59 | case 1: |
| 60 | m_cmd = idata; |
| 61 | if((m_cmd & 0xf0) != 0x40) |
| 62 | return false; |
| 63 | *odata = 0x5a; |
| 64 | break; |
| 65 | default: |
| 66 | switch(m_cmd) |
| 67 | { |
| 68 | default: // 40,41,48,49,4a,4b,4f -- all unknown |
| 69 | *odata = 0x00; |
| 70 | break; |
| 71 | case CONFIG_MODE: // 43 |
| 72 | if(count == 3) |
| 73 | m_temp = idata; |
| 74 | /* no break */ |
| 75 | case QUERY_PAD_STATE: // 42 |
| 76 | *odata = pad_data(count, true); |
| 77 | break; |
| 78 | case 0x44: // set mode and lock ? |
| 79 | switch(count) |
| 80 | { |
| 81 | case 3: |
| 82 | m_analogmode = idata ? true : false; // only 0x01 ? |
| 83 | break; |
| 84 | case 4: |
| 85 | m_analoglock = idata ? true : false; // only 0x03 ? |
| 86 | break; |
| 87 | } |
| 88 | *odata = 0x00; |
| 89 | break; |
| 90 | case 0x45: // get mode ? |
| 91 | { |
| 92 | const UINT8 val[] = { 1, 2, 0, 2, 1, 0 }; |
| 93 | if(count == 4) |
| 94 | *odata = m_analogmode; |
| 95 | else |
| 96 | *odata = val[count-2]; |
| 97 | break; |
| 98 | } |
| 99 | case 0x46: // query act (vibrate) ? |
| 100 | { |
| 101 | const UINT8 val[2][6] = {{ 0, 0, 1, 2, 0, 10 }, |
| 102 | { 0, 0, 1, 1, 1, 14 }}; |
| 103 | *odata = val[m_temp][count-2]; |
| 104 | if(count == 3) |
| 105 | m_temp = idata ? 1 : 0; |
| 106 | break; |
| 107 | } |
| 108 | case 0x47: // query comb (combination?) ? |
| 109 | { |
| 110 | const UINT8 val[] = { 0, 0, 2, 0, 1, 0 }; |
| 111 | *odata = val[count-2]; |
| 112 | break; |
| 113 | } |
| 114 | case 0x4c: // query mode ? |
| 115 | switch(count) |
| 116 | { |
| 117 | case 3: |
| 118 | m_temp = idata; |
| 119 | /* no break */ |
| 120 | default: |
| 121 | *odata = 0x00; |
| 122 | break; |
| 123 | case 5: |
| 124 | *odata = m_analogmode ? 0x07 : 0x04; // ? |
| 125 | break; |
| 126 | } |
| 127 | break; |
| 128 | case 0x4d: // set act (vibrate) ? |
| 129 | *odata = 0xff; |
| 130 | break; |
| 131 | } |
| 132 | break; |
| 133 | case 8: |
| 134 | if(m_cmd == CONFIG_MODE) |
| 135 | m_confmode = m_temp; |
| 136 | return false; |
| 137 | } |
| 138 | } |
| 139 | else if(m_analogmode) |
| 140 | { |
| 141 | switch(count) |
| 142 | { |
| 143 | case 0: |
| 144 | *odata = 0x73; |
| 145 | break; |
| 146 | case 1: |
| 147 | m_cmd = idata; |
| 148 | if((m_cmd & 0xfe) != QUERY_PAD_STATE) |
| 149 | return false; |
| 150 | *odata = 0x5a; |
| 151 | break; |
| 152 | case 3: |
| 153 | if(m_cmd == CONFIG_MODE) |
| 154 | m_temp = idata; |
| 155 | /* no break */ |
| 156 | default: |
| 157 | *odata = pad_data(count, true); |
| 158 | break; |
| 159 | case 8: |
| 160 | if(m_cmd == CONFIG_MODE) |
| 161 | m_confmode = m_temp; |
| 162 | return false; |
| 163 | } |
| 164 | } |
| 165 | else |
| 166 | { |
| 167 | switch(count) |
| 168 | { |
| 169 | case 0: |
| 170 | *odata = 0x41; |
| 171 | break; |
| 172 | case 1: |
| 173 | m_cmd = idata; |
| 174 | if((m_cmd & 0xfe) != QUERY_PAD_STATE) |
| 175 | return false; |
| 176 | *odata = 0x5a; |
| 177 | break; |
| 178 | case 3: |
| 179 | if(m_cmd == CONFIG_MODE) |
| 180 | m_temp = idata; |
| 181 | /* no break */ |
| 182 | default: |
| 183 | *odata = pad_data(count, false); |
| 184 | break; |
| 185 | case 4: |
| 186 | if(m_cmd == CONFIG_MODE) |
| 187 | m_confmode = m_temp; |
| 188 | return false; |
| 189 | } |
| 190 | } |
| 191 | return true; |
| 192 | } |
| 193 | |
| 194 | static INPUT_PORTS_START( psx_analog_controller ) |
| 195 | PORT_START("PSXPAD0") |
| 196 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) |
| 197 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) |
| 198 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) |
| 199 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) |
| 200 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START ) |
| 201 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON9 ) PORT_NAME("R3") |
| 202 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON10 ) PORT_NAME("L3") |
| 203 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SELECT ) |
| 204 | |
| 205 | PORT_START("PSXPAD1") |
| 206 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Square") |
| 207 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Cross") |
| 208 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Circle") |
| 209 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Triangle") |
| 210 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("R1") |
| 211 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("L1") |
| 212 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("R2") |
| 213 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("L2") |
| 214 | |
| 215 | PORT_START("PSXRSTICKX") |
| 216 | PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_NAME("Right Analog X") PORT_SENSITIVITY(100) |
| 217 | |
| 218 | PORT_START("PSXRSTICKY") |
| 219 | PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_NAME("Right Analog Y") PORT_SENSITIVITY(100) |
| 220 | |
| 221 | PORT_START("PSXLSTICKX") |
| 222 | PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Z ) PORT_NAME("Left Analog X") PORT_SENSITIVITY(100) |
| 223 | |
| 224 | PORT_START("PSXLSTICKY") |
| 225 | PORT_BIT( 0xff, 0x80, IPT_PADDLE ) PORT_NAME("Left Analog Y") PORT_SENSITIVITY(100) |
| 226 | |
| 227 | PORT_START("PSXMISC") |
| 228 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("Analog") PORT_CHANGED_MEMBER(DEVICE_SELF, psx_analog_controller_device, change_mode, 0) |
| 229 | INPUT_PORTS_END |
| 230 | |
| 231 | ioport_constructor psx_analog_controller_device::device_input_ports() const |
| 232 | { |
| 233 | return INPUT_PORTS_NAME(psx_analog_controller); |
| 234 | } |
| 235 | |
| 236 | INPUT_CHANGED_MEMBER(psx_analog_controller_device::change_mode) |
| 237 | { |
| 238 | if(!m_analoglock) |
| 239 | m_analogmode = ioport("PSXPAD1")->read(); |
| 240 | } |
trunk/src/mess/machine/psxcport.c
| r20301 | r20302 | |
| 1 | 1 | /* PAD emulation */ |
| 2 | 2 | |
| 3 | | #include "psxcport.h" |
| 4 | | #include "machine/psxcard.h" |
| 3 | #include "machine/psxcport.h" |
| 4 | #include "machine/psxanalog.h" |
| 5 | 5 | |
| 6 | | #define PAD_STATE_IDLE ( 0 ) |
| 7 | | #define PAD_STATE_LISTEN ( 1 ) |
| 8 | | #define PAD_STATE_ACTIVE ( 2 ) |
| 9 | | #define PAD_STATE_READ ( 3 ) |
| 10 | | #define PAD_STATE_UNLISTEN ( 4 ) |
| 11 | | #define PAD_STATE_MEMCARD ( 5 ) |
| 6 | const device_type PSX_CONTROLLER_PORT = &device_creator<psx_controller_port_device>; |
| 12 | 7 | |
| 13 | | #define PAD_TYPE_STANDARD ( 4 ) |
| 14 | | #define PAD_BYTES_STANDARD ( 2 ) |
| 8 | psx_controller_port_device::psx_controller_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 9 | device_t(mconfig, PSX_CONTROLLER_PORT, "Playstation Controller Port", tag, owner, clock), |
| 10 | device_slot_interface(mconfig, *this), |
| 11 | m_card(*this, "card") |
| 12 | { |
| 13 | } |
| 15 | 14 | |
| 16 | | #define PAD_CMD_START ( 0x01 ) |
| 17 | | #define PAD_CMD_READ ( 0x42 ) /* B */ |
| 15 | void psx_controller_port_device::device_config_complete() |
| 16 | { |
| 17 | m_dev = dynamic_cast<device_psx_controller_interface *>(get_card_device()); |
| 18 | } |
| 18 | 19 | |
| 19 | | #define PAD_DATA_OK ( 0x5a ) /* Z */ |
| 20 | | #define PAD_DATA_IDLE ( 0xff ) |
| 20 | static MACHINE_CONFIG_FRAGMENT( psx_memory_card ) |
| 21 | MCFG_PSXCARD_ADD("card") |
| 22 | MACHINE_CONFIG_END |
| 21 | 23 | |
| 24 | machine_config_constructor psx_controller_port_device::device_mconfig_additions() const |
| 25 | { |
| 26 | return MACHINE_CONFIG_NAME( psx_memory_card ); |
| 27 | } |
| 28 | |
| 22 | 29 | const device_type PSXCONTROLLERPORTS = &device_creator<psxcontrollerports_device>; |
| 23 | 30 | |
| 24 | 31 | psxcontrollerports_device::psxcontrollerports_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 25 | | psxsiodev_device(mconfig, PSXCONTROLLERPORTS, "PSXCONTROLLERPORTS", tag, owner, clock) |
| 32 | psxsiodev_device(mconfig, PSXCONTROLLERPORTS, "PSXCONTROLLERPORTS", tag, owner, clock) |
| 26 | 33 | { |
| 27 | 34 | } |
| 28 | 35 | |
| 29 | 36 | void psxcontrollerports_device::device_start() |
| 30 | 37 | { |
| 38 | m_port0 = machine().device<psx_controller_port_device>("port1"); |
| 39 | m_port1 = machine().device<psx_controller_port_device>("port2"); |
| 40 | m_port0->setup_ack_cb(psx_controller_port_device::void_cb(FUNC(psxcontrollerports_device::ack), this)); |
| 41 | m_port1->setup_ack_cb(psx_controller_port_device::void_cb(FUNC(psxcontrollerports_device::ack), this)); |
| 31 | 42 | psxsiodev_device::device_start(); |
| 43 | } |
| 32 | 44 | |
| 33 | | m_ack_timer = timer_alloc( 0 ); |
| 45 | SLOT_INTERFACE_START(psx_controllers) |
| 46 | SLOT_INTERFACE("digital_pad", PSX_STANDARD_CONTROLLER) |
| 47 | SLOT_INTERFACE("analog_pad", PSX_ANALOG_CONTROLLER) |
| 48 | SLOT_INTERFACE_END |
| 49 | |
| 50 | void psxcontrollerports_device::data_in( int data, int mask ) |
| 51 | { |
| 52 | m_port0->sel_w((data & PSX_SIO_OUT_DTR)?1:0); |
| 53 | m_port0->tx_w((data & PSX_SIO_OUT_DATA)?1:0); |
| 54 | m_port0->clock_w((data & PSX_SIO_OUT_CLOCK)?1:0); // clock must be last |
| 55 | |
| 56 | m_port1->tx_w((data & PSX_SIO_OUT_DATA)?1:0); |
| 57 | m_port1->sel_w((data & PSX_SIO_OUT_DTR)?0:1); // not dtr |
| 58 | m_port1->clock_w((data & PSX_SIO_OUT_CLOCK)?1:0); |
| 59 | |
| 60 | data_out(((m_port0->rx_r() && m_port1->rx_r()) * PSX_SIO_IN_DATA), PSX_SIO_IN_DATA); |
| 34 | 61 | } |
| 35 | 62 | |
| 36 | | void psxcontrollerports_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr) |
| 63 | void psxcontrollerports_device::ack() |
| 37 | 64 | { |
| 38 | | int n_port = param; |
| 39 | | pad_t *pad = &m_pad[ n_port ]; |
| 65 | data_out((!(m_port0->ack_r() && m_port1->ack_r()) * PSX_SIO_IN_DSR), PSX_SIO_IN_DSR); |
| 66 | } |
| 40 | 67 | |
| 41 | | if( pad->n_state != PAD_STATE_IDLE ) |
| 42 | | { |
| 43 | | data_out( pad->b_ack * PSX_SIO_IN_DSR, PSX_SIO_IN_DSR ); |
| 68 | device_psx_controller_interface::device_psx_controller_interface(const machine_config &mconfig, device_t &device) : |
| 69 | device_slot_card_interface(mconfig, device) |
| 70 | { |
| 71 | } |
| 44 | 72 | |
| 45 | | if( !pad->b_ack ) |
| 46 | | { |
| 47 | | pad->b_ack = 1; |
| 48 | | m_ack_timer->adjust( attotime::from_usec( 2 ), n_port ); |
| 49 | | } |
| 50 | | } |
| 73 | device_psx_controller_interface::~device_psx_controller_interface() |
| 74 | { |
| 51 | 75 | } |
| 52 | 76 | |
| 53 | | void psxcontrollerports_device::psx_pad( int n_port, int n_data ) |
| 77 | void device_psx_controller_interface::interface_pre_reset() |
| 54 | 78 | { |
| 55 | | pad_t *pad = &m_pad[ n_port ]; |
| 56 | | int b_sel; |
| 57 | | int b_clock; |
| 58 | | int b_data; |
| 59 | | int b_ack; |
| 60 | | int b_ready; |
| 61 | | static const char *const portnames[] = { ":IN0", ":IN1", ":IN2", ":IN3" }; |
| 62 | | psxcard_device *psxcard = NULL; |
| 79 | m_bit = 0; |
| 80 | m_count = 0; |
| 81 | m_idata = 0; |
| 82 | m_memcard = false; |
| 63 | 83 | |
| 64 | | if (n_port == 0) |
| 65 | | { |
| 66 | | psxcard = machine().device<psxcard_device>(":card1"); |
| 67 | | } |
| 68 | | else |
| 69 | | { |
| 70 | | psxcard = machine().device<psxcard_device>(":card2"); |
| 71 | | } |
| 84 | m_clock = true; |
| 85 | m_sel = true; |
| 86 | m_rx = true; |
| 87 | m_ack = true; |
| 88 | m_owner->ack(); |
| 89 | } |
| 72 | 90 | |
| 73 | | b_sel = ( n_data & PSX_SIO_OUT_DTR ) / PSX_SIO_OUT_DTR; |
| 74 | | b_clock = ( n_data & PSX_SIO_OUT_CLOCK ) / PSX_SIO_OUT_CLOCK; |
| 75 | | b_data = ( n_data & PSX_SIO_OUT_DATA ) / PSX_SIO_OUT_DATA; |
| 76 | | b_ready = 0; |
| 77 | | b_ack = 0; |
| 91 | void device_psx_controller_interface::interface_pre_start() |
| 92 | { |
| 93 | m_owner = dynamic_cast<psx_controller_port_device *>(device().owner()); |
| 94 | m_ack_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_psx_controller_interface::ack_timer), this)); |
| 95 | } |
| 78 | 96 | |
| 79 | | if( b_sel ) |
| 97 | void device_psx_controller_interface::ack_timer(void *ptr, int param) |
| 98 | { |
| 99 | m_ack = param; |
| 100 | m_owner->ack(); |
| 101 | |
| 102 | if(!param) |
| 103 | m_ack_timer->adjust(attotime::from_usec(2), 1); |
| 104 | } |
| 105 | |
| 106 | void device_psx_controller_interface::do_pad() |
| 107 | { |
| 108 | if(!m_bit) |
| 80 | 109 | { |
| 81 | | pad->n_state = PAD_STATE_IDLE; |
| 110 | if(!m_count) |
| 111 | m_odata = 0xff; |
| 112 | m_idata = 0; |
| 82 | 113 | } |
| 83 | 114 | |
| 84 | | switch( pad->n_state ) |
| 115 | m_rx = (m_odata & (1 << m_bit)) ? true : false; |
| 116 | m_idata |= (m_owner->tx_r()?1:0) << m_bit; |
| 117 | m_bit = (m_bit + 1) % 8; |
| 118 | |
| 119 | if(!m_bit) |
| 85 | 120 | { |
| 86 | | case PAD_STATE_LISTEN: |
| 87 | | case PAD_STATE_ACTIVE: |
| 88 | | case PAD_STATE_READ: |
| 89 | | case PAD_STATE_MEMCARD: |
| 90 | | if( pad->b_lastclock && !b_clock ) |
| 121 | if((!m_count) && (m_idata & 0x80)) |
| 91 | 122 | { |
| 92 | | data_out( ( pad->n_shiftout & 1 ) * PSX_SIO_IN_DATA, PSX_SIO_IN_DATA ); |
| 93 | | pad->n_shiftout >>= 1; |
| 123 | m_memcard = true; |
| 124 | return; |
| 94 | 125 | } |
| 95 | | if( !pad->b_lastclock && b_clock ) |
| 96 | | { |
| 97 | | pad->n_shiftin >>= 1; |
| 98 | | pad->n_shiftin |= b_data << 7; |
| 99 | | pad->n_bits++; |
| 100 | 126 | |
| 101 | | if( pad->n_bits == 8 ) |
| 102 | | { |
| 103 | | pad->n_bits = 0; |
| 104 | | b_ready = 1; |
| 105 | | } |
| 106 | | } |
| 107 | | break; |
| 127 | if(get_pad(m_count++, &m_odata, m_idata)) |
| 128 | m_ack_timer->adjust(attotime::from_usec(10), 0); |
| 129 | else |
| 130 | m_count = 0; |
| 108 | 131 | } |
| 132 | } |
| 109 | 133 | |
| 110 | | pad->b_lastclock = b_clock; |
| 134 | void device_psx_controller_interface::sel_w(bool state) { |
| 135 | if(state && !m_sel) |
| 136 | interface_pre_reset(); // don't reset the controller, just the interface |
| 137 | m_sel = state; |
| 138 | } |
| 111 | 139 | |
| 112 | | switch( pad->n_state ) |
| 113 | | { |
| 114 | | case PAD_STATE_IDLE: |
| 115 | | if( !b_sel ) |
| 116 | | { |
| 117 | | pad->n_state = PAD_STATE_LISTEN; |
| 118 | | pad->n_shiftout = PAD_DATA_IDLE; |
| 119 | | pad->n_bits = 0; |
| 120 | | } |
| 121 | | break; |
| 122 | | case PAD_STATE_LISTEN: |
| 123 | | if( b_ready ) |
| 124 | | { |
| 125 | | if( pad->n_shiftin == PAD_CMD_START ) |
| 126 | | { |
| 127 | | pad->n_state = PAD_STATE_ACTIVE; |
| 128 | | pad->n_shiftout = ( PAD_TYPE_STANDARD << 4 ) | ( PAD_BYTES_STANDARD >> 1 ); |
| 129 | | b_ack = 1; |
| 130 | | } |
| 131 | | else if( psxcard->transfer(pad->n_shiftin, &pad->n_shiftout) ) |
| 132 | | { |
| 133 | | pad->n_state = PAD_STATE_MEMCARD; |
| 134 | | b_ack = 1; |
| 135 | | } |
| 136 | | else |
| 137 | | { |
| 138 | | pad->n_state = PAD_STATE_UNLISTEN; |
| 139 | | } |
| 140 | | } |
| 141 | | break; |
| 142 | | case PAD_STATE_MEMCARD: |
| 143 | | if( b_ready ) |
| 144 | | { |
| 145 | | if( psxcard->transfer(pad->n_shiftin, &pad->n_shiftout) ) |
| 146 | | { |
| 147 | | b_ack = 1; |
| 148 | | } |
| 149 | | else |
| 150 | | { |
| 151 | | b_ack = 0; |
| 152 | | pad->n_state = PAD_STATE_IDLE; |
| 153 | | } |
| 154 | | } |
| 155 | | break; |
| 156 | | case PAD_STATE_ACTIVE: |
| 157 | | if( b_ready ) |
| 158 | | { |
| 159 | | if( pad->n_shiftin == PAD_CMD_READ ) |
| 160 | | { |
| 161 | | pad->n_state = PAD_STATE_READ; |
| 162 | | pad->n_shiftout = PAD_DATA_OK; |
| 163 | | pad->n_byte = 0; |
| 164 | | b_ack = 1; |
| 165 | | } |
| 166 | | else |
| 167 | | { |
| 168 | | pad->n_state = PAD_STATE_UNLISTEN; |
| 169 | | } |
| 170 | | } |
| 171 | | break; |
| 172 | | case PAD_STATE_READ: |
| 173 | | if( b_ready ) |
| 174 | | { |
| 175 | | if( pad->n_byte < PAD_BYTES_STANDARD ) |
| 176 | | { |
| 177 | | pad->n_shiftout = ioport(portnames[pad->n_byte + ( n_port * PAD_BYTES_STANDARD )])->read(); |
| 178 | | pad->n_byte++; |
| 179 | | b_ack = 1; |
| 180 | | } |
| 181 | | else |
| 182 | | { |
| 183 | | pad->n_state = PAD_STATE_LISTEN; |
| 184 | | } |
| 185 | | } |
| 186 | | break; |
| 187 | | } |
| 140 | const device_type PSX_STANDARD_CONTROLLER = &device_creator<psx_standard_controller_device>; |
| 188 | 141 | |
| 189 | | if( b_ack ) |
| 142 | psx_standard_controller_device::psx_standard_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 143 | device_t(mconfig, PSX_STANDARD_CONTROLLER, "Playstation Standard Controller", tag, owner, clock), |
| 144 | device_psx_controller_interface(mconfig, *this) |
| 145 | { |
| 146 | } |
| 147 | |
| 148 | bool psx_standard_controller_device::get_pad(int count, UINT8 *odata, UINT8 idata) |
| 149 | { |
| 150 | switch(count) |
| 190 | 151 | { |
| 191 | | pad->b_ack = 0; |
| 192 | | m_ack_timer->adjust( attotime::from_usec( 10 ), n_port ); |
| 152 | case 0: |
| 153 | *odata = 0x41; |
| 154 | break; |
| 155 | case 1: |
| 156 | if(idata != QUERY_PAD_STATE) |
| 157 | return false; |
| 158 | *odata = 0x5a; |
| 159 | break; |
| 160 | case 2: |
| 161 | *odata = ioport("PSXPAD0")->read(); |
| 162 | break; |
| 163 | case 3: |
| 164 | *odata = ioport("PSXPAD1")->read(); |
| 165 | break; |
| 166 | case 4: |
| 167 | return false; |
| 193 | 168 | } |
| 169 | return true; |
| 194 | 170 | } |
| 195 | 171 | |
| 196 | | void psxcontrollerports_device::data_in( int data, int mask ) |
| 172 | static INPUT_PORTS_START( psx_standard_controller ) |
| 173 | PORT_START("PSXPAD0") |
| 174 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) |
| 175 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) |
| 176 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) |
| 177 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) |
| 178 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START ) |
| 179 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 180 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 181 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SELECT ) |
| 182 | |
| 183 | PORT_START("PSXPAD1") |
| 184 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Square") |
| 185 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Cross") |
| 186 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Circle") |
| 187 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Triangle") |
| 188 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("R1") |
| 189 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("L1") |
| 190 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("R2") |
| 191 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("L2") |
| 192 | INPUT_PORTS_END |
| 193 | |
| 194 | ioport_constructor psx_standard_controller_device::device_input_ports() const |
| 197 | 195 | { |
| 198 | | /* todo: raise data & ack when nothing is driving it low */ |
| 199 | | psx_pad( 0, data ); |
| 200 | | psx_pad( 1, data ^ PSX_SIO_OUT_DTR ); |
| 196 | return INPUT_PORTS_NAME(psx_standard_controller); |
| 201 | 197 | } |
trunk/src/mess/machine/psxcport.h
| r20301 | r20302 | |
| 4 | 4 | #define __PSXCPORT_H__ |
| 5 | 5 | |
| 6 | 6 | #include "cpu/psx/siodev.h" |
| 7 | #include "machine/psxcard.h" |
| 7 | 8 | |
| 9 | #define MCFG_PSX_CTRL_PORT_ADD(_tag, _slot_intf, _def_slot, _def_inp) \ |
| 10 | MCFG_DEVICE_ADD(_tag, PSX_CONTROLLER_PORT, 0) \ |
| 11 | MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _def_inp, false) |
| 12 | |
| 13 | SLOT_INTERFACE_EXTERN(psx_controllers); |
| 14 | |
| 8 | 15 | extern const device_type PSXCONTROLLERPORTS; |
| 16 | extern const device_type PSX_CONTROLLER_PORT; |
| 17 | extern const device_type PSX_STANDARD_CONTROLLER; |
| 9 | 18 | |
| 10 | | struct pad_t |
| 19 | class psx_controller_port_device; |
| 20 | |
| 21 | class device_psx_controller_interface : public device_slot_card_interface |
| 11 | 22 | { |
| 12 | | UINT8 n_shiftin; |
| 13 | | UINT8 n_shiftout; |
| 14 | | int n_bits; |
| 15 | | int n_state; |
| 16 | | int n_byte; |
| 17 | | int b_lastclock; |
| 18 | | int b_ack; |
| 23 | public: |
| 24 | device_psx_controller_interface(const machine_config &mconfig, device_t &device); |
| 25 | virtual ~device_psx_controller_interface(); |
| 26 | |
| 27 | void clock_w(bool state) { if(m_clock && !m_sel && !state && !m_memcard) do_pad(); m_clock = state; } |
| 28 | void sel_w(bool state); |
| 29 | |
| 30 | bool rx_r() { return m_rx; } |
| 31 | bool ack_r() { return m_ack; } |
| 32 | |
| 33 | protected: |
| 34 | virtual void interface_pre_reset(); |
| 35 | virtual void interface_pre_start(); |
| 36 | |
| 37 | enum |
| 38 | { |
| 39 | QUERY_PAD_STATE = 0x42, |
| 40 | CONFIG_MODE = 0x43, |
| 41 | }; |
| 42 | |
| 43 | private: |
| 44 | virtual bool get_pad(int count, UINT8 *odata, UINT8 idata) = 0; |
| 45 | virtual void do_pad(); |
| 46 | void ack_timer(void *ptr, int param); |
| 47 | |
| 48 | UINT8 m_odata; |
| 49 | UINT8 m_idata; |
| 50 | int m_bit; |
| 51 | int m_count; |
| 52 | bool m_memcard; |
| 53 | |
| 54 | bool m_clock; |
| 55 | bool m_sel; |
| 56 | bool m_ack; |
| 57 | bool m_rx; |
| 58 | |
| 59 | emu_timer *m_ack_timer; |
| 60 | psx_controller_port_device *m_owner; |
| 19 | 61 | }; |
| 20 | 62 | |
| 63 | class psx_standard_controller_device : public device_t, |
| 64 | public device_psx_controller_interface |
| 65 | { |
| 66 | public: |
| 67 | psx_standard_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 68 | |
| 69 | virtual ioport_constructor device_input_ports() const; |
| 70 | |
| 71 | protected: |
| 72 | virtual void device_start() { } |
| 73 | virtual void device_config_complete() { m_shortname = "psx_standard_controller"; } |
| 74 | private: |
| 75 | virtual bool get_pad(int count, UINT8 *odata, UINT8 idata); |
| 76 | }; |
| 77 | |
| 21 | 78 | class psxcontrollerports_device : public psxsiodev_device |
| 22 | 79 | { |
| 23 | 80 | public: |
| 24 | 81 | psxcontrollerports_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 82 | void ack(); |
| 25 | 83 | |
| 26 | 84 | protected: |
| 27 | 85 | void device_start(); |
| 28 | | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
| 29 | 86 | |
| 30 | 87 | private: |
| 31 | | void psx_pad( int n_port, int n_data ); |
| 32 | | virtual void data_in( int data, int mask ); |
| 88 | virtual void data_in(int data, int mask); |
| 33 | 89 | |
| 34 | | pad_t m_pad[ 2 ]; |
| 35 | | emu_timer *m_ack_timer; |
| 90 | psx_controller_port_device *m_port0; |
| 91 | psx_controller_port_device *m_port1; |
| 36 | 92 | }; |
| 37 | 93 | |
| 94 | class psx_controller_port_device : public device_t, |
| 95 | public device_slot_interface |
| 96 | { |
| 97 | public: |
| 98 | psx_controller_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 99 | virtual machine_config_constructor device_mconfig_additions() const; |
| 100 | |
| 101 | typedef delegate<void ()> void_cb; |
| 102 | void ack() { if(!ack_cb.isnull()) ack_cb(); } |
| 103 | void setup_ack_cb(void_cb cb) { ack_cb = cb; } |
| 104 | |
| 105 | DECLARE_WRITE_LINE_MEMBER(tx_w) { m_tx = state; } |
| 106 | DECLARE_WRITE_LINE_MEMBER(sel_w) { if(m_dev) m_dev->sel_w(state); m_card->sel_w(state); } |
| 107 | DECLARE_WRITE_LINE_MEMBER(clock_w) { if(m_dev) m_dev->clock_w(state); m_card->clock_w(state); } |
| 108 | |
| 109 | DECLARE_READ_LINE_MEMBER(rx_r) { return (m_dev?m_dev->rx_r():true) && m_card->rx_r(); } |
| 110 | DECLARE_READ_LINE_MEMBER(ack_r) { return (m_dev?m_dev->ack_r():true) && m_card->ack_r(); } |
| 111 | DECLARE_READ_LINE_MEMBER(tx_r) { return m_tx; } |
| 112 | |
| 113 | protected: |
| 114 | virtual void device_start() {} |
| 115 | virtual void device_reset() { m_tx = true; } |
| 116 | virtual void device_config_complete(); |
| 117 | |
| 118 | private: |
| 119 | void_cb ack_cb; |
| 120 | bool m_tx; |
| 121 | |
| 122 | device_psx_controller_interface *m_dev; |
| 123 | required_device<psxcard_device> m_card; |
| 124 | }; |
| 38 | 125 | #endif |