src/mess/drivers/vcs80.c
| r5151 | r5152 | |
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | |
| 3 | | VCS-80 |
| 3 | VCS-80 |
| 4 | 4 | |
| 5 | | 12/05/2009 Skeleton driver. |
| 5 | 12/05/2009 Skeleton driver. |
| 6 | 6 | |
| 7 | http://hc-ddr.hucki.net/entwicklungssysteme.htm#VCS_80_von_Eckhard_Schiller |
| 8 | |
| 7 | 9 | ****************************************************************************/ |
| 8 | 10 | |
| 9 | 11 | #include "driver.h" |
| 12 | #include "includes/vcs80.h" |
| 10 | 13 | #include "cpu/z80/z80.h" |
| 14 | #include "cpu/z80/z80daisy.h" |
| 15 | #include "machine/z80pio.h" |
| 16 | #include "vcs80.lh" |
| 11 | 17 | |
| 12 | | static ADDRESS_MAP_START(vcs80_mem, ADDRESS_SPACE_PROGRAM, 8) |
| 13 | | ADDRESS_MAP_UNMAP_HIGH |
| 14 | | AM_RANGE( 0x0000, 0x01ff ) AM_ROM |
| 15 | | AM_RANGE( 0x0200, 0xffff ) AM_RAM |
| 18 | /* Read/Write Handlers */ |
| 19 | |
| 20 | static READ8_DEVICE_HANDLER( vcs80_z80pio_r ) |
| 21 | { |
| 22 | switch (offset) |
| 23 | { |
| 24 | case 0: return z80pio_c_r(device, 1); |
| 25 | case 1: return z80pio_c_r(device, 0); |
| 26 | case 2: return z80pio_d_r(device, 1); |
| 27 | case 3: return z80pio_d_r(device, 0); |
| 28 | } |
| 29 | |
| 30 | return 0; |
| 31 | } |
| 32 | |
| 33 | static WRITE8_DEVICE_HANDLER( vcs80_z80pio_w ) |
| 34 | { |
| 35 | switch (offset) |
| 36 | { |
| 37 | case 0: z80pio_c_w(device, 1, data); break; |
| 38 | case 1: z80pio_c_w(device, 0, data); break; |
| 39 | case 2: z80pio_d_w(device, 1, data); break; |
| 40 | case 3: z80pio_d_w(device, 0, data); break; |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | /* Memory Maps */ |
| 45 | |
| 46 | static ADDRESS_MAP_START( vcs80_mem, ADDRESS_SPACE_PROGRAM, 8 ) |
| 47 | AM_RANGE(0x0000, 0x01ff) AM_ROM |
| 48 | AM_RANGE(0x0400, 0x07ff) AM_RAM |
| 16 | 49 | ADDRESS_MAP_END |
| 17 | 50 | |
| 18 | | static ADDRESS_MAP_START( vcs80_io , ADDRESS_SPACE_IO, 8) |
| 19 | | ADDRESS_MAP_UNMAP_HIGH |
| 51 | static ADDRESS_MAP_START( vcs80_io, ADDRESS_SPACE_IO, 8 ) |
| 52 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 53 | AM_RANGE(0x04, 0x07) AM_DEVREADWRITE(Z80PIO_TAG, vcs80_z80pio_r, vcs80_z80pio_w) |
| 20 | 54 | ADDRESS_MAP_END |
| 21 | 55 | |
| 22 | | /* Input ports */ |
| 56 | /* Input Ports */ |
| 57 | |
| 23 | 58 | static INPUT_PORTS_START( vcs80 ) |
| 59 | PORT_START("ROW0") |
| 60 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') |
| 61 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') |
| 62 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') |
| 63 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') |
| 64 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') |
| 65 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') |
| 66 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') |
| 67 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') |
| 68 | |
| 69 | PORT_START("ROW1") |
| 70 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') |
| 71 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') |
| 72 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') |
| 73 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B') |
| 74 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') |
| 75 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') |
| 76 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E') |
| 77 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F') |
| 78 | |
| 79 | PORT_START("ROW2") |
| 80 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("A+") PORT_CODE(KEYCODE_F1) |
| 81 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("A-") PORT_CODE(KEYCODE_F2) |
| 82 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("MA") PORT_CODE(KEYCODE_F3) |
| 83 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RE") PORT_CODE(KEYCODE_F4) |
| 84 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("GO") PORT_CODE(KEYCODE_F5) |
| 85 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("TR") PORT_CODE(KEYCODE_F6) |
| 86 | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ST") PORT_CODE(KEYCODE_F7) |
| 87 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PE") PORT_CODE(KEYCODE_F8) |
| 24 | 88 | INPUT_PORTS_END |
| 25 | 89 | |
| 90 | /* Keyboard HACK */ |
| 26 | 91 | |
| 27 | | static MACHINE_RESET(vcs80) |
| 92 | static TIMER_DEVICE_CALLBACK( vcs80_keyboard_tick ) |
| 28 | 93 | { |
| 94 | vcs80_state *state = timer->machine->driver_data; |
| 95 | |
| 96 | UINT8 data = 0xf7; |
| 97 | |
| 98 | if (!BIT(input_port_read(timer->machine, "ROW0"), state->keylatch)) data &= ~0x10; |
| 99 | if (!BIT(input_port_read(timer->machine, "ROW1"), state->keylatch)) data &= ~0x20; |
| 100 | if (!BIT(input_port_read(timer->machine, "ROW2"), state->keylatch)) data &= ~0x40; |
| 101 | |
| 102 | z80pio_p_w(state->z80pio, 0, data); |
| 103 | |
| 104 | z80pio_p_w(state->z80pio, 1, 0x80); |
| 105 | z80pio_p_w(state->z80pio, 1, 0x00); |
| 29 | 106 | } |
| 30 | 107 | |
| 31 | | static VIDEO_START( vcs80 ) |
| 108 | /* Z80-PIO Interface */ |
| 109 | |
| 110 | static READ8_DEVICE_HANDLER( pio_port_a_r ) |
| 32 | 111 | { |
| 112 | /* |
| 113 | |
| 114 | bit description |
| 115 | |
| 116 | 0 keyboard and led latch bit 0 |
| 117 | 1 keyboard and led latch bit 1 |
| 118 | 2 keyboard and led latch bit 2 |
| 119 | 3 GND |
| 120 | 4 keyboard row input 0 |
| 121 | 5 keyboard row input 1 |
| 122 | 6 keyboard row input 2 |
| 123 | 7 demultiplexer clock output |
| 124 | |
| 125 | */ |
| 126 | |
| 127 | vcs80_state *state = device->machine->driver_data; |
| 128 | |
| 129 | UINT8 data = 0xf7; |
| 130 | |
| 131 | if (!BIT(input_port_read(device->machine, "ROW0"), state->keylatch)) data &= ~0x10; |
| 132 | if (!BIT(input_port_read(device->machine, "ROW1"), state->keylatch)) data &= ~0x20; |
| 133 | if (!BIT(input_port_read(device->machine, "ROW2"), state->keylatch)) data &= ~0x40; |
| 134 | |
| 135 | return data; |
| 33 | 136 | } |
| 34 | 137 | |
| 35 | | static VIDEO_UPDATE( vcs80 ) |
| 138 | static WRITE8_DEVICE_HANDLER( pio_port_a_w ) |
| 36 | 139 | { |
| 37 | | return 0; |
| 140 | /* |
| 141 | |
| 142 | bit description |
| 143 | |
| 144 | 0 keyboard and led latch bit 0 |
| 145 | 1 keyboard and led latch bit 1 |
| 146 | 2 keyboard and led latch bit 2 |
| 147 | 3 GND |
| 148 | 4 keyboard row input 0 |
| 149 | 5 keyboard row input 1 |
| 150 | 6 keyboard row input 2 |
| 151 | 7 demultiplexer clock output |
| 152 | |
| 153 | */ |
| 154 | |
| 155 | vcs80_state *state = device->machine->driver_data; |
| 156 | |
| 157 | state->keylatch = data & 0x07; |
| 38 | 158 | } |
| 39 | 159 | |
| 160 | static WRITE8_DEVICE_HANDLER( pio_port_b_w ) |
| 161 | { |
| 162 | /* |
| 163 | |
| 164 | bit description |
| 165 | |
| 166 | 0 VQD30 segment A |
| 167 | 1 VQD30 segment B |
| 168 | 2 VQD30 segment C |
| 169 | 3 VQD30 segment D |
| 170 | 4 VQD30 segment E |
| 171 | 5 VQD30 segment F |
| 172 | 6 VQD30 segment G |
| 173 | 7 PIO B/_A |
| 174 | |
| 175 | */ |
| 176 | |
| 177 | vcs80_state *state = device->machine->driver_data; |
| 178 | |
| 179 | int digit = state->keylatch; |
| 180 | |
| 181 | /* skip middle digit */ |
| 182 | if (digit > 3) digit++; |
| 183 | |
| 184 | output_set_digit_value(digit, data & 0x7f); |
| 185 | } |
| 186 | |
| 187 | static const z80pio_interface pio_intf = |
| 188 | { |
| 189 | DEVCB_CPU_INPUT_LINE(Z80_TAG, INPUT_LINE_IRQ0), /* callback when change interrupt status */ |
| 190 | DEVCB_HANDLER(pio_port_a_r), /* port A read callback */ |
| 191 | DEVCB_NULL, /* port B read callback */ |
| 192 | DEVCB_HANDLER(pio_port_a_w), /* port A write callback */ |
| 193 | DEVCB_HANDLER(pio_port_b_w), /* port B write callback */ |
| 194 | DEVCB_NULL, /* portA ready active callback */ |
| 195 | DEVCB_NULL /* portB ready active callback */ |
| 196 | }; |
| 197 | |
| 198 | /* Z80 Daisy Chain */ |
| 199 | |
| 200 | static const z80_daisy_chain vcs80_daisy_chain[] = |
| 201 | { |
| 202 | { Z80PIO_TAG }, |
| 203 | { NULL } |
| 204 | }; |
| 205 | |
| 206 | /* Machine Initialization */ |
| 207 | |
| 208 | static MACHINE_START(vcs80) |
| 209 | { |
| 210 | vcs80_state *state = machine->driver_data; |
| 211 | |
| 212 | /* find devices */ |
| 213 | state->z80pio = devtag_get_device(machine, Z80PIO_TAG); |
| 214 | |
| 215 | /* register for state saving */ |
| 216 | state_save_register_global(machine, state->keylatch); |
| 217 | } |
| 218 | |
| 219 | /* Machine Driver */ |
| 220 | |
| 40 | 221 | static MACHINE_DRIVER_START( vcs80 ) |
| 41 | | /* basic machine hardware */ |
| 42 | | MDRV_CPU_ADD("maincpu",Z80, XTAL_4MHz) |
| 222 | MDRV_DRIVER_DATA(vcs80_state) |
| 223 | |
| 224 | /* basic machine hardware */ |
| 225 | MDRV_CPU_ADD(Z80_TAG, Z80, XTAL_5MHz/2) /* U880D */ |
| 43 | 226 | MDRV_CPU_PROGRAM_MAP(vcs80_mem) |
| 44 | 227 | MDRV_CPU_IO_MAP(vcs80_io) |
| 228 | MDRV_CPU_CONFIG(vcs80_daisy_chain) |
| 45 | 229 | |
| 46 | | MDRV_MACHINE_RESET(vcs80) |
| 230 | MDRV_MACHINE_START(vcs80) |
| 47 | 231 | |
| 232 | /* keyboard HACK */ |
| 233 | MDRV_TIMER_ADD_PERIODIC("keyboard", vcs80_keyboard_tick, HZ(1000)) |
| 234 | |
| 48 | 235 | /* video hardware */ |
| 49 | | MDRV_SCREEN_ADD("screen", RASTER) |
| 50 | | MDRV_SCREEN_REFRESH_RATE(50) |
| 51 | | MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ |
| 52 | | MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) |
| 53 | | MDRV_SCREEN_SIZE(640, 480) |
| 54 | | MDRV_SCREEN_VISIBLE_AREA(0, 640-1, 0, 480-1) |
| 55 | | MDRV_PALETTE_LENGTH(2) |
| 56 | | MDRV_PALETTE_INIT(black_and_white) |
| 236 | MDRV_DEFAULT_LAYOUT( layout_vcs80 ) |
| 57 | 237 | |
| 58 | | MDRV_VIDEO_START(vcs80) |
| 59 | | MDRV_VIDEO_UPDATE(vcs80) |
| 238 | /* devices */ |
| 239 | MDRV_Z80PIO_ADD(Z80PIO_TAG, pio_intf) |
| 60 | 240 | MACHINE_DRIVER_END |
| 61 | 241 | |
| 62 | | static SYSTEM_CONFIG_START(vcs80) |
| 63 | | SYSTEM_CONFIG_END |
| 242 | /* ROMs */ |
| 64 | 243 | |
| 65 | | /* ROM definition */ |
| 66 | 244 | ROM_START( vcs80 ) |
| 67 | | ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF ) |
| 68 | | ROM_LOAD( "monitor.rom", 0x0000, 0x0200, CRC(44aff4e9) SHA1(3472e5a9357eaba3ed6de65dee2b1c6b29349dd2)) |
| 69 | | |
| 245 | ROM_REGION( 0x10000, Z80_TAG, 0 ) |
| 246 | ROM_LOAD( "monitor.rom", 0x0000, 0x0200, CRC(44aff4e9) SHA1(3472e5a9357eaba3ed6de65dee2b1c6b29349dd2) ) |
| 70 | 247 | ROM_END |
| 71 | 248 | |
| 72 | | /* Driver */ |
| 249 | /* System Configuration */ |
| 73 | 250 | |
| 74 | | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT CONFIG COMPANY FULLNAME FLAGS */ |
| 75 | | COMP( ????, vcs80, 0, 0, vcs80, vcs80, 0, vcs80, "Eckhard Schiller", "VCS-80", GAME_NOT_WORKING) |
| 251 | static SYSTEM_CONFIG_START(vcs80) |
| 252 | CONFIG_RAM_DEFAULT( 1 * 1024 ) |
| 253 | SYSTEM_CONFIG_END |
| 76 | 254 | |
| 255 | /* System Drivers */ |
| 256 | |
| 257 | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT CONFIG COMPANY FULLNAME FLAGS */ |
| 258 | COMP( 1983, vcs80, 0, 0, vcs80, vcs80, 0, vcs80, "Eckhard Schiller", "VCS-80", GAME_NOT_WORKING) |