trunk/src/mess/drivers/ti99_4x.c
| r26101 | r26102 | |
| 54 | 54 | #include "machine/ti99/joyport.h" |
| 55 | 55 | #include "machine/ti99/peribox.h" |
| 56 | 56 | |
| 57 | | #include "drivlgcy.h" |
| 58 | | |
| 59 | 57 | #define LOG logerror |
| 60 | 58 | #define VERBOSE 1 |
| 61 | 59 | |
| r26101 | r26102 | |
| 67 | 65 | public: |
| 68 | 66 | ti99_4x_state(const machine_config &mconfig, device_type type, const char *tag) |
| 69 | 67 | : driver_device(mconfig, type, tag), |
| 68 | m_cpu(*this, "maincpu"), |
| 69 | m_tms9901(*this, TMS9901_TAG), |
| 70 | m_gromport(*this, GROMPORT_TAG), |
| 71 | m_peribox(*this, PERIBOX_TAG), |
| 72 | m_joyport(*this, JOYPORT_TAG), |
| 73 | m_datamux(*this, DATAMUX_TAG), |
| 74 | m_video(*this, VIDEO_SYSTEM_TAG), |
| 70 | 75 | m_cassette1(*this, "cassette"), |
| 71 | | m_cassette2(*this, "cassette2") { } |
| 76 | m_cassette2(*this, "cassette2") |
| 77 | { } |
| 72 | 78 | |
| 73 | | // CRU (Communication Register Unit) handling |
| 74 | | DECLARE_READ8_MEMBER(cruread); |
| 75 | | DECLARE_WRITE8_MEMBER(cruwrite); |
| 76 | | DECLARE_WRITE8_MEMBER(external_operation); |
| 79 | // Machine management |
| 80 | DECLARE_MACHINE_START(ti99_4); |
| 81 | DECLARE_MACHINE_START(ti99_4a); |
| 82 | DECLARE_MACHINE_START(ti99_4qi); |
| 83 | DECLARE_MACHINE_RESET(ti99_4); |
| 84 | DECLARE_MACHINE_RESET(ti99_4a); |
| 77 | 85 | |
| 78 | | // Forwarding interrupts to the CPU or CRU |
| 86 | // Processor connections with the main board |
| 87 | DECLARE_READ8_MEMBER( cruread ); |
| 88 | DECLARE_READ8_MEMBER( interrupt_level ); |
| 89 | DECLARE_WRITE8_MEMBER( cruwrite ); |
| 90 | DECLARE_WRITE8_MEMBER( external_operation ); |
| 91 | DECLARE_WRITE_LINE_MEMBER( clock_out ); |
| 92 | DECLARE_WRITE_LINE_MEMBER( dbin_line ); |
| 93 | |
| 94 | // Connections from outside towards the CPU (callbacks) |
| 79 | 95 | DECLARE_WRITE_LINE_MEMBER( console_ready ); |
| 80 | 96 | DECLARE_WRITE_LINE_MEMBER( console_ready_dmux ); |
| 81 | 97 | DECLARE_WRITE_LINE_MEMBER( console_reset ); |
| 82 | 98 | |
| 99 | // Connections with the system interface chip 9901 |
| 83 | 100 | DECLARE_WRITE_LINE_MEMBER( set_tms9901_INT2 ); |
| 84 | 101 | DECLARE_WRITE_LINE_MEMBER( set_tms9901_INT12 ); |
| 85 | 102 | DECLARE_WRITE_LINE_MEMBER( set_tms9901_INT2_from_v9938); |
| 86 | 103 | DECLARE_WRITE_LINE_MEMBER( extint ); |
| 87 | 104 | DECLARE_WRITE_LINE_MEMBER( notconnected ); |
| 88 | 105 | |
| 89 | | DECLARE_READ8_MEMBER( interrupt_level ); |
| 90 | | DECLARE_READ_LINE_MEMBER( ready_connect ); |
| 91 | | DECLARE_WRITE_LINE_MEMBER( clock_out ); |
| 92 | | DECLARE_WRITE_LINE_MEMBER( dbin_line ); |
| 93 | | |
| 94 | | DECLARE_INPUT_CHANGED_MEMBER( load_interrupt ); |
| 95 | | TIMER_DEVICE_CALLBACK_MEMBER(ti99_4ev_hblank_interrupt); |
| 96 | | |
| 97 | | // Some values to keep |
| 98 | | tms9900_device* m_cpu; |
| 99 | | tms9901_device* m_tms9901; |
| 100 | | gromport_device* m_gromport; |
| 101 | | peribox_device* m_peribox; |
| 102 | | joyport_device* m_joyport; |
| 103 | | ti99_datamux_device* m_datamux; |
| 104 | | ti_video_device* m_video; |
| 105 | | |
| 106 | | int m_ready_line, m_ready_line_dmux; |
| 107 | | |
| 108 | | int m_firstjoy; // First joystick. 6 for TI-99/4A, 5 for TI-99/4 |
| 109 | | |
| 110 | 106 | // Connections with the system interface TMS9901 |
| 111 | 107 | DECLARE_READ8_MEMBER(read_by_9901); |
| 112 | 108 | DECLARE_WRITE_LINE_MEMBER(keyC0); |
| r26101 | r26102 | |
| 119 | 115 | DECLARE_WRITE_LINE_MEMBER(handset_ack); |
| 120 | 116 | DECLARE_WRITE_LINE_MEMBER(cs2_motor); |
| 121 | 117 | DECLARE_WRITE_LINE_MEMBER(alphaW); |
| 122 | | DECLARE_MACHINE_START(ti99_4); |
| 123 | | DECLARE_MACHINE_START(ti99_4a); |
| 124 | | DECLARE_MACHINE_START(ti99_4qi); |
| 125 | | DECLARE_MACHINE_RESET(ti99_4); |
| 126 | | DECLARE_MACHINE_RESET(ti99_4a); |
| 118 | |
| 119 | // Interrupt triggers |
| 120 | DECLARE_INPUT_CHANGED_MEMBER( load_interrupt ); |
| 121 | TIMER_DEVICE_CALLBACK_MEMBER(ti99_4ev_hblank_interrupt); |
| 122 | |
| 127 | 123 | private: |
| 128 | 124 | void set_keyboard_column(int number, int data); |
| 129 | 125 | int m_keyboard_column; |
| 130 | 126 | int m_check_alphalock; |
| 131 | | bool m_qi_version; |
| 132 | 127 | |
| 133 | 128 | int m_ready_prev; // for debugging purposes only |
| 129 | |
| 130 | // Latches the ready line from different sources |
| 131 | int m_ready_line, m_ready_line_dmux; |
| 132 | |
| 133 | // Console type |
| 134 | int m_console; |
| 135 | |
| 136 | // Connected devices |
| 137 | required_device<tms9900_device> m_cpu; |
| 138 | required_device<tms9901_device> m_tms9901; |
| 139 | required_device<gromport_device> m_gromport; |
| 140 | required_device<peribox_device> m_peribox; |
| 141 | required_device<joyport_device> m_joyport; |
| 142 | required_device<ti99_datamux_device> m_datamux; |
| 143 | required_device<ti_video_device> m_video; |
| 134 | 144 | required_device<cassette_image_device> m_cassette1; |
| 135 | 145 | required_device<cassette_image_device> m_cassette2; |
| 136 | 146 | }; |
| 137 | 147 | |
| 138 | 148 | /* |
| 149 | Console models. |
| 150 | */ |
| 151 | enum |
| 152 | { |
| 153 | MODEL_4, |
| 154 | MODEL_4A, |
| 155 | MODEL_4QI |
| 156 | }; |
| 157 | |
| 158 | /* |
| 139 | 159 | Memory map. |
| 140 | 160 | Most of the work is done in the datamux (see datamux.c). We only keep ROM |
| 141 | 161 | and the small 256 byte PAD RAM here because they are directly connected |
| r26101 | r26102 | |
| 362 | 382 | // Also, we translate the bit addresses to base addresses |
| 363 | 383 | |
| 364 | 384 | // The QI version does not propagate the CRU signals to the cartridge slot |
| 365 | | if (!m_qi_version) m_gromport->crureadz(space, offset<<4, &value); |
| 385 | if (m_console != MODEL_4QI) m_gromport->crureadz(space, offset<<4, &value); |
| 366 | 386 | m_peribox->crureadz(space, offset<<4, &value); |
| 367 | 387 | |
| 368 | 388 | return value; |
| r26101 | r26102 | |
| 372 | 392 | { |
| 373 | 393 | if (VERBOSE>6) LOG("ti99_4x: write access to CRU address %04x\n", offset << 1); |
| 374 | 394 | // The QI version does not propagate the CRU signals to the cartridge slot |
| 375 | | if (!m_qi_version) m_gromport->cruwrite(space, offset<<1, data); |
| 395 | if (m_console != MODEL_4QI) m_gromport->cruwrite(space, offset<<1, data); |
| 376 | 396 | m_peribox->cruwrite(space, offset<<1, data); |
| 377 | 397 | } |
| 378 | 398 | |
| r26101 | r26102 | |
| 430 | 450 | // |
| 431 | 451 | // |K|K|K|K|K|I2|I1|C| |
| 432 | 452 | // |
| 433 | | if (m_keyboard_column >= m_firstjoy) // joy 1, 2, handset |
| 453 | if (m_keyboard_column >= (m_console==MODEL_4? 5:6)) // joy 1, 2, handset |
| 434 | 454 | { |
| 435 | 455 | answer = m_joyport->read_port(); |
| 436 | 456 | // The hardware bug of the TI-99/4A: you have to release the |
| r26101 | r26102 | |
| 441 | 461 | // the line enough to make the TMS9901 sense the low level. |
| 442 | 462 | // A reported, feasible fix was to cut the line and insert a diode |
| 443 | 463 | // below the Alphalock key. |
| 444 | | if ((ioport("ALPHABUG")!=0) && m_firstjoy==6) answer |= ioport("ALPHA")->read(); |
| 464 | if ((ioport("ALPHABUG")!=0) && (m_console!=MODEL_4)) answer |= ioport("ALPHA")->read(); |
| 445 | 465 | } |
| 446 | 466 | else |
| 447 | 467 | { |
| r26101 | r26102 | |
| 457 | 477 | |
| 458 | 478 | case TMS9901_INT8_INT15: |
| 459 | 479 | // |1|1|1|1|0|K|K|K| |
| 460 | | if (m_keyboard_column >= m_firstjoy) answer = 0x07; |
| 480 | if (m_keyboard_column >= (m_console==MODEL_4? 5:6)) answer = 0x07; |
| 461 | 481 | else answer = ((ioport(column[m_keyboard_column])->read())>>5) & 0x07; |
| 462 | 482 | answer |= 0xf0; |
| 463 | 483 | break; |
| r26101 | r26102 | |
| 505 | 525 | else |
| 506 | 526 | m_keyboard_column &= ~ (1 << number); |
| 507 | 527 | |
| 508 | | if (m_keyboard_column >= m_firstjoy) |
| 528 | if (m_keyboard_column >= (m_console==MODEL_4? 5:6)) |
| 509 | 529 | { |
| 510 | | m_joyport->write_port(m_keyboard_column - m_firstjoy + 1); |
| 530 | m_joyport->write_port(m_keyboard_column - (m_console==MODEL_4? 5:6) + 1); |
| 511 | 531 | } |
| 512 | 532 | |
| 513 | 533 | // TI-99/4: joystick 1 = column 5 |
| r26101 | r26102 | |
| 870 | 890 | |
| 871 | 891 | MACHINE_START_MEMBER(ti99_4x_state,ti99_4) |
| 872 | 892 | { |
| 873 | | m_cpu = static_cast<tms9900_device*>(machine().device("maincpu")); |
| 874 | | m_tms9901 = static_cast<tms9901_device*>(machine().device(TMS9901_TAG)); |
| 875 | | |
| 876 | | m_gromport = static_cast<gromport_device*>(machine().device(GROMPORT_TAG)); |
| 877 | | |
| 878 | | m_peribox = static_cast<peribox_device*>(machine().device(PERIBOX_TAG)); |
| 879 | | m_datamux = static_cast<ti99_datamux_device*>(machine().device(DATAMUX_TAG)); |
| 880 | | |
| 881 | | m_joyport = static_cast<joyport_device*>(machine().device(JOYPORT_TAG)); |
| 882 | | |
| 883 | | m_video = static_cast<ti_video_device*>(machine().device(VIDEO_SYSTEM_TAG)); |
| 884 | | |
| 885 | 893 | m_peribox->senila(CLEAR_LINE); |
| 886 | 894 | m_peribox->senilb(CLEAR_LINE); |
| 887 | | m_firstjoy = 5; |
| 888 | | |
| 889 | 895 | m_ready_line = m_ready_line_dmux = ASSERT_LINE; |
| 890 | 896 | |
| 891 | | m_qi_version = false; |
| 897 | m_console = MODEL_4; |
| 892 | 898 | } |
| 893 | 899 | |
| 894 | 900 | MACHINE_RESET_MEMBER(ti99_4x_state,ti99_4) |
| r26101 | r26102 | |
| 989 | 995 | |
| 990 | 996 | MACHINE_START_MEMBER(ti99_4x_state,ti99_4a) |
| 991 | 997 | { |
| 992 | | m_cpu = static_cast<tms9900_device*>(machine().device("maincpu")); |
| 993 | | m_tms9901 = static_cast<tms9901_device*>(machine().device(TMS9901_TAG)); |
| 994 | | |
| 995 | | m_gromport = static_cast<gromport_device*>(machine().device(GROMPORT_TAG)); |
| 996 | | m_peribox = static_cast<peribox_device*>(machine().device(PERIBOX_TAG)); |
| 997 | | |
| 998 | | m_datamux = static_cast<ti99_datamux_device*>(machine().device(DATAMUX_TAG)); |
| 999 | | m_joyport = static_cast<joyport_device*>(machine().device(JOYPORT_TAG)); |
| 1000 | | m_video = static_cast<ti_video_device*>(machine().device(VIDEO_SYSTEM_TAG)); |
| 1001 | | m_firstjoy = 6; |
| 1002 | | |
| 1003 | 998 | m_peribox->senila(CLEAR_LINE); |
| 1004 | 999 | m_peribox->senilb(CLEAR_LINE); |
| 1005 | 1000 | m_ready_line = m_ready_line_dmux = ASSERT_LINE; |
| 1006 | | |
| 1007 | | m_qi_version = false; |
| 1001 | m_console = MODEL_4A; |
| 1008 | 1002 | } |
| 1009 | 1003 | |
| 1010 | 1004 | MACHINE_RESET_MEMBER(ti99_4x_state,ti99_4a) |
| r26101 | r26102 | |
| 1108 | 1102 | |
| 1109 | 1103 | MACHINE_START_MEMBER(ti99_4x_state, ti99_4qi) |
| 1110 | 1104 | { |
| 1111 | | m_cpu = static_cast<tms9900_device*>(machine().device("maincpu")); |
| 1112 | | m_tms9901 = static_cast<tms9901_device*>(machine().device(TMS9901_TAG)); |
| 1113 | | |
| 1114 | | m_gromport = static_cast<gromport_device*>(machine().device(GROMPORT_TAG)); |
| 1115 | | m_peribox = static_cast<peribox_device*>(machine().device(PERIBOX_TAG)); |
| 1116 | | |
| 1117 | | m_datamux = static_cast<ti99_datamux_device*>(machine().device(DATAMUX_TAG)); |
| 1118 | | m_joyport = static_cast<joyport_device*>(machine().device(JOYPORT_TAG)); |
| 1119 | | m_video = static_cast<ti_video_device*>(machine().device(VIDEO_SYSTEM_TAG)); |
| 1120 | | m_firstjoy = 6; |
| 1121 | | |
| 1122 | 1105 | m_peribox->senila(CLEAR_LINE); |
| 1123 | 1106 | m_peribox->senilb(CLEAR_LINE); |
| 1124 | 1107 | m_ready_line = m_ready_line_dmux = ASSERT_LINE; |
| 1125 | | |
| 1126 | | m_qi_version = true; |
| 1108 | m_console = MODEL_4QI; |
| 1127 | 1109 | } |
| 1128 | 1110 | |
| 1129 | 1111 | static MACHINE_CONFIG_START( ti99_4qi_60hz, ti99_4x_state ) |