src/mess/machine/psxcard.c
| r0 | r11047 | |
| 1 | /* |
| 2 | psxcard.c - Sony PlayStation memory card device |
| 3 | |
| 4 | by pSXAuthor |
| 5 | MESS conversion by R. Belmont |
| 6 | */ |
| 7 | |
| 8 | #include "emu.h" |
| 9 | #include "psxcard.h" |
| 10 | #include "includes/psx.h" |
| 11 | |
| 12 | // |
| 13 | // |
| 14 | // |
| 15 | |
| 16 | //#define debug_card |
| 17 | |
| 18 | // |
| 19 | // |
| 20 | // |
| 21 | |
| 22 | const device_type PSXCARD = psxcard_device_config::static_alloc_device_config; |
| 23 | |
| 24 | enum transfer_states |
| 25 | { |
| 26 | state_illegal=0, |
| 27 | state_command, |
| 28 | state_cmdack_1, |
| 29 | state_cmdack_2, |
| 30 | state_addr_hi, |
| 31 | state_addr_lo, |
| 32 | state_read, |
| 33 | state_write, |
| 34 | state_writeack_1, |
| 35 | state_writeack_2, |
| 36 | state_writechk |
| 37 | }; |
| 38 | |
| 39 | // |
| 40 | // |
| 41 | // |
| 42 | |
| 43 | psxcard_device_config::psxcard_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock) |
| 44 | : device_config(mconfig, static_alloc_device_config, "Sony PSX Memory Card", tag, owner, clock) |
| 45 | { |
| 46 | } |
| 47 | |
| 48 | device_config *psxcard_device_config::static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock) |
| 49 | { |
| 50 | return global_alloc(psxcard_device_config(mconfig, tag, owner, clock)); |
| 51 | } |
| 52 | |
| 53 | device_t *psxcard_device_config::alloc_device(running_machine &machine) const |
| 54 | { |
| 55 | return auto_alloc(machine, psxcard_device(machine, *this)); |
| 56 | } |
| 57 | |
| 58 | psxcard_device::psxcard_device(running_machine &_machine, const psxcard_device_config &_config) |
| 59 | : device_t(_machine, _config), |
| 60 | m_config(_config) |
| 61 | { |
| 62 | } |
| 63 | |
| 64 | void psxcard_device::device_start() |
| 65 | { |
| 66 | cache=new unsigned char [128*1024]; |
| 67 | |
| 68 | memset(cache, 0, 128*1024); |
| 69 | |
| 70 | // save state registrations |
| 71 | /* save_item(NAME(pkt)); |
| 72 | save_item(NAME(pkt_ptr)); |
| 73 | save_item(NAME(pkt_sz)); |
| 74 | save_item(NAME(pkt)); |
| 75 | save_item(NAME(cache)); |
| 76 | save_item(NAME(addr)); |
| 77 | save_item(NAME(state));*/ |
| 78 | } |
| 79 | |
| 80 | void psxcard_device::device_reset() |
| 81 | { |
| 82 | state = state_illegal; |
| 83 | addr = 0; |
| 84 | } |
| 85 | |
| 86 | // |
| 87 | // |
| 88 | // |
| 89 | |
| 90 | bool psxcard_device::transfer(UINT8 to, UINT8 *from) |
| 91 | { |
| 92 | bool ret=true; |
| 93 | |
| 94 | switch (state) |
| 95 | { |
| 96 | case state_illegal: |
| 97 | if (to == 0x81) |
| 98 | { |
| 99 | // printf("CARD: begin\n"); |
| 100 | state = state_command; |
| 101 | *from = 0x00; |
| 102 | } |
| 103 | else |
| 104 | { |
| 105 | ret = false; |
| 106 | } |
| 107 | break; |
| 108 | |
| 109 | case state_command: |
| 110 | cmd=to; |
| 111 | *from=0x00; |
| 112 | state=state_cmdack_1; |
| 113 | break; |
| 114 | |
| 115 | case state_cmdack_1: |
| 116 | //assert(to==0); |
| 117 | *from=0x5a; |
| 118 | state=state_cmdack_2; |
| 119 | break; |
| 120 | |
| 121 | case state_cmdack_2: |
| 122 | //assert(to==0); |
| 123 | *from=0x5d; |
| 124 | state=state_addr_hi; |
| 125 | break; |
| 126 | |
| 127 | case state_addr_hi: |
| 128 | addr=(to<<8); |
| 129 | // printf("addr_hi: %02x, addr = %x\n", to, addr); |
| 130 | *from=0; |
| 131 | state=state_addr_lo; |
| 132 | break; |
| 133 | |
| 134 | case state_addr_lo: |
| 135 | addr|=(to&0xff); |
| 136 | // printf("addr_lo: %02x, addr = %x, cmd = %x\n", to, addr, cmd); |
| 137 | *from=(addr>>8); |
| 138 | |
| 139 | switch (cmd) |
| 140 | { |
| 141 | case 'R': // 0x52 |
| 142 | { |
| 143 | pkt[0]=0x5c; |
| 144 | pkt[1]=0x5d; |
| 145 | pkt[2]=(addr>>8); |
| 146 | pkt[3]=(addr&0xff); |
| 147 | read_card(addr,&pkt[4]); |
| 148 | pkt[4+128]=checksum_data(&pkt[2],128+2); |
| 149 | pkt[5+128]=0x47; |
| 150 | pkt_sz=6+128; |
| 151 | pkt_ptr=0; |
| 152 | state=state_read; |
| 153 | break; |
| 154 | } |
| 155 | case 'W': // 0x57 |
| 156 | { |
| 157 | pkt[0]=addr>>8; |
| 158 | pkt[1]=addr&0xff; |
| 159 | pkt_sz=129+2; |
| 160 | pkt_ptr=2; |
| 161 | state=state_write; |
| 162 | break; |
| 163 | } |
| 164 | default: |
| 165 | state=state_illegal; |
| 166 | break; |
| 167 | } |
| 168 | break; |
| 169 | |
| 170 | case state_read: |
| 171 | //assert(to==0); |
| 172 | // printf("state_read: pkt_ptr = %d, pkt_sz = %d\n", pkt_ptr, pkt_sz); |
| 173 | *from=pkt[pkt_ptr++]; |
| 174 | if (pkt_ptr==pkt_sz) |
| 175 | { |
| 176 | #ifdef debug_card |
| 177 | printf("card: read finished\n"); |
| 178 | #endif |
| 179 | |
| 180 | state=state_illegal; |
| 181 | ret=false; |
| 182 | } |
| 183 | break; |
| 184 | |
| 185 | case state_write: |
| 186 | *from=(pkt_ptr==0)?(addr&0xff):pkt[pkt_ptr-1]; |
| 187 | pkt[pkt_ptr++]=to; |
| 188 | if (pkt_ptr==pkt_sz) |
| 189 | state=state_writeack_1; |
| 190 | break; |
| 191 | |
| 192 | case state_writeack_1: |
| 193 | *from=0x5c; |
| 194 | state=state_writeack_2; |
| 195 | break; |
| 196 | |
| 197 | case state_writeack_2: |
| 198 | *from=0x5d; |
| 199 | state=state_writechk; |
| 200 | break; |
| 201 | |
| 202 | case state_writechk: |
| 203 | { |
| 204 | unsigned char chk=checksum_data(pkt,128+2); |
| 205 | if (chk==pkt[128+2]) |
| 206 | { |
| 207 | #ifdef debug_card |
| 208 | printf("card: write ok\n"); |
| 209 | #endif |
| 210 | |
| 211 | write_card(addr,pkt+2); |
| 212 | |
| 213 | *from='G'; |
| 214 | } else |
| 215 | { |
| 216 | #ifdef debug_card |
| 217 | printf("card: write fail\n"); |
| 218 | #endif |
| 219 | |
| 220 | *from='N'; |
| 221 | } |
| 222 | state=state_illegal; |
| 223 | ret=false; |
| 224 | break; |
| 225 | } |
| 226 | |
| 227 | default: /*assert(0);*/ ret=false; break; |
| 228 | } |
| 229 | |
| 230 | #ifdef debug_card |
| 231 | // printf("card: transfer to=%02x from=%02x ret=%c\n",to,*from,ret ? 'T' : 'F'); |
| 232 | #endif |
| 233 | |
| 234 | return ret; |
| 235 | } |
| 236 | |
| 237 | void psxcard_device::read_card(const unsigned short addr, unsigned char *buf) |
| 238 | { |
| 239 | #ifdef debug_card |
| 240 | printf("card: read block %d\n",addr); |
| 241 | #endif |
| 242 | |
| 243 | if (addr<1024) |
| 244 | { |
| 245 | memcpy(buf,cache+(addr*128),128); |
| 246 | } else |
| 247 | { |
| 248 | memset(buf,0,128); |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | // |
| 253 | // |
| 254 | // |
| 255 | |
| 256 | void psxcard_device::write_card(const unsigned short addr, unsigned char *buf) |
| 257 | { |
| 258 | #ifdef debug_card |
| 259 | printf("card: write block %d\n",addr); |
| 260 | #endif |
| 261 | |
| 262 | if (addr<1024) |
| 263 | { |
| 264 | memcpy(cache+(addr*128),buf,128); |
| 265 | } |
| 266 | } |
| 267 | |
| 268 | // |
| 269 | // |
| 270 | // |
| 271 | |
| 272 | unsigned char psxcard_device::checksum_data(const unsigned char *buf, const unsigned int sz) |
| 273 | { |
| 274 | unsigned char chk=*buf++; |
| 275 | int left=sz; |
| 276 | while (--left) chk^=*buf++; |
| 277 | return chk; |
| 278 | } |
src/mess/machine/psxcard.h
| r0 | r11047 | |
| 1 | #pragma once |
| 2 | |
| 3 | #ifndef _PSXCARD_ |
| 4 | #define _PSXCARD_ |
| 5 | |
| 6 | #include "emu.h" |
| 7 | |
| 8 | #define MCFG_PSXCARD_ADD(_tag) \ |
| 9 | MCFG_DEVICE_ADD(_tag, PSXCARD, 0) |
| 10 | |
| 11 | struct psxcard_interface |
| 12 | { |
| 13 | }; |
| 14 | |
| 15 | class psxcard_device_config : public device_config, |
| 16 | public psxcard_interface |
| 17 | { |
| 18 | friend class psxcard_device; |
| 19 | |
| 20 | // construction/destruction |
| 21 | psxcard_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); |
| 22 | |
| 23 | public: |
| 24 | // allocators |
| 25 | static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); |
| 26 | virtual device_t *alloc_device(running_machine &machine) const; |
| 27 | }; |
| 28 | |
| 29 | class psxcard_device : public device_t |
| 30 | { |
| 31 | friend class psxcard_device_config; |
| 32 | |
| 33 | psxcard_device(running_machine &_machine, const psxcard_device_config &_config); |
| 34 | |
| 35 | unsigned char pkt[0x8b], pkt_ptr, pkt_sz, cmd, *cache; |
| 36 | unsigned short addr; |
| 37 | int state; |
| 38 | |
| 39 | void read_card(const unsigned short addr, unsigned char *buf); |
| 40 | void write_card(const unsigned short addr, unsigned char *buf); |
| 41 | unsigned char checksum_data(const unsigned char *buf, const unsigned int sz); |
| 42 | |
| 43 | public: |
| 44 | virtual void device_start(); |
| 45 | virtual void device_reset(); |
| 46 | |
| 47 | bool transfer(UINT8 to, UINT8 *from); |
| 48 | void mess_io(running_machine *machine, UINT8 n_data); |
| 49 | private: |
| 50 | const psxcard_device_config &m_config; |
| 51 | }; |
| 52 | |
| 53 | // device type definition |
| 54 | extern const device_type PSXCARD; |
| 55 | |
| 56 | #endif |
src/mess/drivers/psx.c
| r11046 | r11047 | |
| 3 | 3 | Sony Playstaion |
| 4 | 4 | =============== |
| 5 | 5 | Preliminary driver by smf |
| 6 | Additional development by pSXAuthor and R. Belmont |
| 6 | 7 | |
| 7 | | todo: |
| 8 | | add memcard support |
| 9 | | tidy up cd controller |
| 10 | | work out why bios scph1000 doesn't get past the first screen |
| 11 | | add cd image support |
| 12 | | |
| 13 | 8 | ***************************************************************************/ |
| 14 | 9 | |
| 15 | 10 | #include "emu.h" |
| r11046 | r11047 | |
| 21 | 16 | #include "debugger.h" |
| 22 | 17 | #include "zlib.h" |
| 23 | 18 | #include "machine/psxcd.h" |
| 19 | #include "machine/psxcard.h" |
| 24 | 20 | |
| 25 | 21 | typedef struct |
| 26 | 22 | { |
| 27 | | int n_shiftin; |
| 28 | | int n_shiftout; |
| 23 | UINT8 n_shiftin; |
| 24 | UINT8 n_shiftout; |
| 29 | 25 | int n_bits; |
| 30 | 26 | int n_state; |
| 31 | 27 | int n_byte; |
| r11046 | r11047 | |
| 480 | 476 | #define PAD_STATE_ACTIVE ( 2 ) |
| 481 | 477 | #define PAD_STATE_READ ( 3 ) |
| 482 | 478 | #define PAD_STATE_UNLISTEN ( 4 ) |
| 479 | #define PAD_STATE_MEMCARD ( 5 ) |
| 483 | 480 | |
| 484 | 481 | #define PAD_TYPE_STANDARD ( 4 ) |
| 485 | 482 | #define PAD_BYTES_STANDARD ( 2 ) |
| r11046 | r11047 | |
| 517 | 514 | int b_ack; |
| 518 | 515 | int b_ready; |
| 519 | 516 | static const char *const portnames[] = { "IN0", "IN1", "IN2", "IN3" }; |
| 517 | psxcard_device *psxcard = NULL; |
| 520 | 518 | |
| 519 | if (n_port == 0) |
| 520 | { |
| 521 | psxcard = machine.device<psxcard_device>("card1"); |
| 522 | } |
| 523 | else |
| 524 | { |
| 525 | psxcard = machine.device<psxcard_device>("card2"); |
| 526 | } |
| 527 | |
| 521 | 528 | b_sel = ( n_data & PSX_SIO_OUT_DTR ) / PSX_SIO_OUT_DTR; |
| 522 | 529 | b_clock = ( n_data & PSX_SIO_OUT_CLOCK ) / PSX_SIO_OUT_CLOCK; |
| 523 | 530 | b_data = ( n_data & PSX_SIO_OUT_DATA ) / PSX_SIO_OUT_DATA; |
| r11046 | r11047 | |
| 534 | 541 | case PAD_STATE_LISTEN: |
| 535 | 542 | case PAD_STATE_ACTIVE: |
| 536 | 543 | case PAD_STATE_READ: |
| 544 | case PAD_STATE_MEMCARD: |
| 537 | 545 | if( pad->b_lastclock && !b_clock ) |
| 538 | 546 | { |
| 539 | 547 | psx_sio_input( machine, 0, PSX_SIO_IN_DATA, ( pad->n_shiftout & 1 ) * PSX_SIO_IN_DATA ); |
| r11046 | r11047 | |
| 575 | 583 | pad->n_shiftout = ( PAD_TYPE_STANDARD << 4 ) | ( PAD_BYTES_STANDARD >> 1 ); |
| 576 | 584 | b_ack = 1; |
| 577 | 585 | } |
| 586 | else if( psxcard->transfer(pad->n_shiftin, &pad->n_shiftout) ) |
| 587 | { |
| 588 | pad->n_state = PAD_STATE_MEMCARD; |
| 589 | b_ack = 1; |
| 590 | } |
| 578 | 591 | else |
| 579 | 592 | { |
| 580 | 593 | pad->n_state = PAD_STATE_UNLISTEN; |
| 581 | 594 | } |
| 582 | 595 | } |
| 583 | 596 | break; |
| 597 | case PAD_STATE_MEMCARD: |
| 598 | if( b_ready ) |
| 599 | { |
| 600 | if( psxcard->transfer(pad->n_shiftin, &pad->n_shiftout) ) |
| 601 | { |
| 602 | b_ack = 1; |
| 603 | } |
| 604 | else |
| 605 | { |
| 606 | b_ack = 0; |
| 607 | pad->n_state = PAD_STATE_IDLE; |
| 608 | } |
| 609 | } |
| 610 | break; |
| 584 | 611 | case PAD_STATE_ACTIVE: |
| 585 | 612 | if( b_ready ) |
| 586 | 613 | { |
| r11046 | r11047 | |
| 593 | 620 | } |
| 594 | 621 | else |
| 595 | 622 | { |
| 596 | | logerror( "unknown pad command %02x\n", pad->n_shiftin ); |
| 597 | 623 | pad->n_state = PAD_STATE_UNLISTEN; |
| 598 | 624 | } |
| 599 | 625 | } |
| r11046 | r11047 | |
| 622 | 648 | } |
| 623 | 649 | } |
| 624 | 650 | |
| 625 | | static void psx_mcd( int n_port, int n_data ) |
| 626 | | { |
| 627 | | /* todo */ |
| 628 | | } |
| 629 | | |
| 630 | 651 | static void psx_sio0( running_machine &machine, int n_data ) |
| 631 | 652 | { |
| 632 | 653 | /* todo: raise data & ack when nothing is driving it low */ |
| 633 | 654 | psx_pad( machine, 0, n_data ); |
| 634 | | psx_mcd( 0, n_data ); |
| 635 | 655 | psx_pad( machine, 1, n_data ^ PSX_SIO_OUT_DTR ); |
| 636 | | psx_mcd( 1, n_data ^ PSX_SIO_OUT_DTR ); |
| 637 | 656 | } |
| 638 | 657 | |
| 639 | 658 | /* ----------------------------------------------------------------------- */ |
| r11046 | r11047 | |
| 792 | 811 | |
| 793 | 812 | MCFG_CDROM_ADD("cdrom") |
| 794 | 813 | MCFG_PSXCD_ADD("cdrom") |
| 814 | MCFG_PSXCARD_ADD("card1") |
| 815 | MCFG_PSXCARD_ADD("card2") |
| 795 | 816 | MACHINE_CONFIG_END |
| 796 | 817 | |
| 797 | 818 | static MACHINE_CONFIG_START( psxpal, psx1_state ) |
| r11046 | r11047 | |
| 827 | 848 | |
| 828 | 849 | MCFG_CDROM_ADD("cdrom") |
| 829 | 850 | MCFG_PSXCD_ADD("cdrom") |
| 851 | MCFG_PSXCARD_ADD("card1") |
| 852 | MCFG_PSXCARD_ADD("card2") |
| 830 | 853 | MACHINE_CONFIG_END |
| 831 | 854 | |
| 832 | 855 | ROM_START( psj ) |