src/mess/drivers/coupe.c
| r2175 | r2176 | |
| 70 | 70 | #define COUPE_XTAL_X2 XTAL_4_433619MHz |
| 71 | 71 | |
| 72 | 72 | |
| 73 | | static unsigned char getSamKey1(unsigned char hi); |
| 74 | | static unsigned char getSamKey2(unsigned char hi); |
| 75 | 73 | |
| 74 | /************************************* |
| 75 | * |
| 76 | * I/O port handling |
| 77 | * |
| 78 | *************************************/ |
| 76 | 79 | |
| 77 | | static READ8_HANDLER( coupe_port_r ) |
| 80 | static READ8_HANDLER( coupe_disk_r ) |
| 78 | 81 | { |
| 79 | | if (offset==SSND_ADDR) /* Sound address request */ |
| 80 | | return SOUND_ADDR; |
| 82 | /* drive and side is encoded into bit 5 and 3 */ |
| 83 | wd17xx_set_drive((offset >> 4) & 1); |
| 84 | wd17xx_set_side((offset >> 2) & 1); |
| 81 | 85 | |
| 82 | | if (offset==HPEN_PORT) |
| 86 | /* bit 1 and 2 select the controller register */ |
| 87 | switch (offset & 0x03) |
| 83 | 88 | { |
| 89 | case 0: return wd17xx_status_r(machine, 0); |
| 90 | case 1: return wd17xx_track_r(machine, 0); |
| 91 | case 2: return wd17xx_sector_r(machine, 0); |
| 92 | case 3: return wd17xx_data_r(machine, 0); |
| 93 | } |
| 94 | |
| 95 | return 0xff; |
| 96 | } |
| 97 | |
| 98 | |
| 99 | static WRITE8_HANDLER( coupe_disk_w ) |
| 100 | { |
| 101 | /* drive and side is encoded into bit 5 and 3 */ |
| 102 | wd17xx_set_drive((offset >> 4) & 1); |
| 103 | wd17xx_set_side((offset >> 2) & 1); |
| 104 | |
| 105 | /* bit 1 and 2 select the controller register */ |
| 106 | switch (offset & 0x03) |
| 107 | { |
| 108 | case 0: wd17xx_command_w(machine, 0, data); break; |
| 109 | case 1: wd17xx_track_w(machine, 0, data); break; |
| 110 | case 2: wd17xx_sector_w(machine, 0, data); break; |
| 111 | case 3: wd17xx_data_w(machine, 0, data); break; |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | |
| 116 | static READ8_HANDLER( coupe_pen_r ) |
| 117 | { |
| 118 | UINT8 data; |
| 119 | |
| 120 | if (offset & 0x100) |
| 121 | { |
| 84 | 122 | /* return either the current line or 192 for the vblank area */ |
| 85 | 123 | int line = video_screen_get_vpos(machine->primary_screen); |
| 86 | | return video_screen_get_vblank(machine->primary_screen) ? 192 : line; |
| 124 | data = video_screen_get_vblank(machine->primary_screen) ? 192 : line; |
| 87 | 125 | } |
| 88 | | |
| 89 | | switch (offset & 0xFF) |
| 126 | else |
| 90 | 127 | { |
| 91 | | case DSK1_PORT+0: /* This covers the total range of ports for 1 floppy controller */ |
| 92 | | case DSK1_PORT+4: |
| 93 | | wd17xx_set_side((offset >> 2) & 1); |
| 94 | | return wd17xx_status_r(machine, 0); |
| 95 | | case DSK1_PORT+1: |
| 96 | | case DSK1_PORT+5: |
| 97 | | wd17xx_set_side((offset >> 2) & 1); |
| 98 | | return wd17xx_track_r(machine, 0); |
| 99 | | case DSK1_PORT+2: |
| 100 | | case DSK1_PORT+6: |
| 101 | | wd17xx_set_side((offset >> 2) & 1); |
| 102 | | return wd17xx_sector_r(machine, 0); |
| 103 | | case DSK1_PORT+3: |
| 104 | | case DSK1_PORT+7: |
| 105 | | wd17xx_set_side((offset >> 2) & 1); |
| 106 | | return wd17xx_data_r(machine, 0); |
| 107 | | case LPEN_PORT: |
| 108 | | return video_screen_get_hpos(machine->primary_screen) & 0xfc; |
| 109 | | case STAT_PORT: |
| 110 | | return ((getSamKey2((offset >> 8)&0xFF))&0xE0) | STAT; |
| 111 | | case LMPR_PORT: |
| 112 | | return LMPR; |
| 113 | | case HMPR_PORT: |
| 114 | | return HMPR; |
| 115 | | case VMPR_PORT: |
| 116 | | return VMPR; |
| 117 | | case KEYB_PORT: |
| 118 | | return (getSamKey1((offset >> 8)&0xFF)&0x1F) | 0xE0; |
| 119 | | case SSND_DATA: |
| 120 | | return SOUND_REG[SOUND_ADDR]; |
| 121 | | default: |
| 122 | | logerror("Read Unsupported Port: %04x\n", offset); |
| 123 | | break; |
| 128 | /* horizontal position is encoded into bits 3 to 8 */ |
| 129 | data = video_screen_get_hpos(machine->primary_screen) & 0xfc; |
| 124 | 130 | } |
| 131 | |
| 132 | return data; |
| 133 | } |
| 125 | 134 | |
| 126 | | return 0x0ff; |
| 135 | |
| 136 | static WRITE8_HANDLER( coupe_clut_w ) |
| 137 | { |
| 138 | CLUT[(offset >> 8) & 0x0f] = data & 0x7f; |
| 127 | 139 | } |
| 128 | 140 | |
| 129 | 141 | |
| 130 | | static WRITE8_HANDLER( coupe_port_w ) |
| 142 | static READ8_HANDLER( coupe_status_r ) |
| 131 | 143 | { |
| 132 | | if (offset==SSND_ADDR) // Set sound address |
| 144 | UINT8 data = 0xe0; |
| 145 | UINT8 row = ~(offset >> 8); |
| 146 | |
| 147 | if (row & 0x80) data &= readinputport(7) & 0xe0; |
| 148 | if (row & 0x40) data &= readinputport(6) & 0xe0; |
| 149 | if (row & 0x20) data &= readinputport(5) & 0xe0; |
| 150 | if (row & 0x10) data &= readinputport(4) & 0xe0; |
| 151 | if (row & 0x08) data &= readinputport(3) & 0xe0; |
| 152 | if (row & 0x04) data &= readinputport(2) & 0xe0; |
| 153 | if (row & 0x02) data &= readinputport(1) & 0xe0; |
| 154 | if (row & 0x01) data &= readinputport(0) & 0xe0; |
| 155 | |
| 156 | return data | STAT; |
| 157 | } |
| 158 | |
| 159 | |
| 160 | static WRITE8_HANDLER( coupe_line_int_w ) |
| 161 | { |
| 162 | LINE_INT = data; |
| 163 | } |
| 164 | |
| 165 | |
| 166 | static READ8_HANDLER( coupe_lmpr_r ) |
| 167 | { |
| 168 | return LMPR; |
| 169 | } |
| 170 | |
| 171 | |
| 172 | static WRITE8_HANDLER( coupe_lmpr_w ) |
| 173 | { |
| 174 | LMPR = data; |
| 175 | coupe_update_memory(); |
| 176 | } |
| 177 | |
| 178 | |
| 179 | static READ8_HANDLER( coupe_hmpr_r ) |
| 180 | { |
| 181 | return HMPR; |
| 182 | } |
| 183 | |
| 184 | |
| 185 | static WRITE8_HANDLER( coupe_hmpr_w ) |
| 186 | { |
| 187 | HMPR = data; |
| 188 | coupe_update_memory(); |
| 189 | } |
| 190 | |
| 191 | |
| 192 | static READ8_HANDLER( coupe_vmpr_r ) |
| 193 | { |
| 194 | return VMPR; |
| 195 | } |
| 196 | |
| 197 | |
| 198 | static WRITE8_HANDLER( coupe_vmpr_w ) |
| 199 | { |
| 200 | VMPR = data; |
| 201 | coupe_update_memory(); |
| 202 | } |
| 203 | |
| 204 | |
| 205 | static READ8_HANDLER( coupe_midi_r ) |
| 206 | { |
| 207 | logerror("Read from midi port\n"); |
| 208 | return 0xff; |
| 209 | } |
| 210 | |
| 211 | |
| 212 | static WRITE8_HANDLER( coupe_midi_w ) |
| 213 | { |
| 214 | logerror("Write to midi port: 0x%02x\n", data); |
| 215 | } |
| 216 | |
| 217 | |
| 218 | static READ8_HANDLER( coupe_keyboard_r ) |
| 219 | { |
| 220 | UINT8 data = 0xff; |
| 221 | UINT8 row = ~(offset >> 8); |
| 222 | |
| 223 | if (row == 0) |
| 133 | 224 | { |
| 134 | | SOUND_ADDR=data&0x1F; // 32 registers max |
| 135 | | saa1099_control_port_0_w(machine, 0, SOUND_ADDR); |
| 136 | | return; |
| 225 | data &= readinputport(8) & 0x1f; |
| 137 | 226 | } |
| 227 | else |
| 228 | { |
| 229 | if (row & 0x80) data &= readinputport(7) & 0x1f; |
| 230 | if (row & 0x40) data &= readinputport(6) & 0x1f; |
| 231 | if (row & 0x20) data &= readinputport(5) & 0x1f; |
| 232 | if (row & 0x10) data &= readinputport(4) & 0x1f; |
| 233 | if (row & 0x08) data &= readinputport(3) & 0x1f; |
| 234 | if (row & 0x04) data &= readinputport(2) & 0x1f; |
| 235 | if (row & 0x02) data &= readinputport(1) & 0x1f; |
| 236 | if (row & 0x01) data &= readinputport(0) & 0x1f; |
| 237 | } |
| 138 | 238 | |
| 139 | | switch (offset & 0xFF) |
| 239 | return data | 0xe0; |
| 240 | } |
| 241 | |
| 242 | |
| 243 | static WRITE8_HANDLER( coupe_border_w ) |
| 244 | { |
| 245 | /* DAC output state */ |
| 246 | speaker_level_w(0,(data >> 4) & 0x01); |
| 247 | } |
| 248 | |
| 249 | |
| 250 | static READ8_HANDLER( coupe_attributes_r ) |
| 251 | { |
| 252 | if (video_screen_get_vblank(machine->primary_screen)) |
| 140 | 253 | { |
| 141 | | case DSK1_PORT+0: // This covers the total range of ports for 1 floppy controller |
| 142 | | case DSK1_PORT+4: |
| 143 | | wd17xx_set_side((offset >> 2) & 1); |
| 144 | | wd17xx_command_w(machine, 0, data); |
| 145 | | break; |
| 146 | | case DSK1_PORT+1: |
| 147 | | case DSK1_PORT+5: |
| 148 | | /* Track byte requested on address line */ |
| 149 | | wd17xx_set_side((offset >> 2) & 1); |
| 150 | | wd17xx_track_w(machine, 0, data); |
| 151 | | break; |
| 152 | | case DSK1_PORT+2: |
| 153 | | case DSK1_PORT+6: |
| 154 | | /* Sector byte requested on address line */ |
| 155 | | wd17xx_set_side((offset >> 2) & 1); |
| 156 | | wd17xx_sector_w(machine, 0, data); |
| 157 | | break; |
| 158 | | case DSK1_PORT+3: |
| 159 | | case DSK1_PORT+7: |
| 160 | | /* Data byte requested on address line */ |
| 161 | | wd17xx_set_side((offset >> 2) & 1); |
| 162 | | wd17xx_data_w(machine, 0, data); |
| 163 | | break; |
| 164 | | case CLUT_PORT: |
| 165 | | CLUT[(offset >> 8)&0x0F]=data&0x7F; // set CLUT data |
| 166 | | break; |
| 167 | | case LINE_PORT: |
| 168 | | LINE_INT=data; // Line to generate interrupt on |
| 169 | | break; |
| 170 | | case LMPR_PORT: |
| 171 | | LMPR=data; |
| 172 | | coupe_update_memory(); |
| 173 | | break; |
| 174 | | case HMPR_PORT: |
| 175 | | HMPR=data; |
| 176 | | coupe_update_memory(); |
| 177 | | break; |
| 178 | | case VMPR_PORT: |
| 179 | | VMPR=data; |
| 180 | | coupe_update_memory(); |
| 181 | | break; |
| 182 | | case BORD_PORT: |
| 183 | | /* DAC output state */ |
| 184 | | speaker_level_w(0,(data>>4) & 0x01); |
| 185 | | break; |
| 186 | | case SSND_DATA: |
| 187 | | saa1099_write_port_0_w(machine, 0, data); |
| 188 | | SOUND_REG[SOUND_ADDR] = data; |
| 189 | | break; |
| 190 | | default: |
| 191 | | logerror("Write Unsupported Port: %04x,%02x\n", offset,data); |
| 192 | | break; |
| 254 | /* Border areas return 0xff */ |
| 255 | return 0xff; |
| 193 | 256 | } |
| 257 | else |
| 258 | { |
| 259 | /* TODO: This actually needs to return various attributes |
| 260 | * of the currently displayed screen data */ |
| 261 | return 0x00; |
| 262 | } |
| 194 | 263 | } |
| 195 | 264 | |
| 196 | 265 | |
| 266 | static WRITE8_HANDLER( coupe_sound_w ) |
| 267 | { |
| 268 | if (offset & 0x100) |
| 269 | saa1099_control_port_0_w(machine, 0, data); |
| 270 | else |
| 271 | saa1099_write_port_0_w(machine, 0, data); |
| 272 | } |
| 197 | 273 | |
| 274 | |
| 275 | |
| 198 | 276 | /************************************* |
| 199 | 277 | * |
| 200 | 278 | * Address maps |
| r2175 | r2176 | |
| 208 | 286 | AM_RANGE(0xc000, 0xffff) AM_RAMBANK(4) |
| 209 | 287 | ADDRESS_MAP_END |
| 210 | 288 | |
| 289 | |
| 211 | 290 | static ADDRESS_MAP_START( coupe_io, ADDRESS_SPACE_IO, 8 ) |
| 212 | | AM_RANGE(0x0000, 0x0ffff) AM_READWRITE(coupe_port_r, coupe_port_w) |
| 291 | AM_RANGE(0xe0, 0xe7) AM_MIRROR(0xff10) AM_MASK(0xffff) AM_READWRITE(coupe_disk_r, coupe_disk_w) |
| 292 | AM_RANGE(0xf8, 0xf8) AM_MIRROR(0xff00) AM_MASK(0xffff) AM_READWRITE(coupe_pen_r, coupe_clut_w) |
| 293 | AM_RANGE(0xf9, 0xf9) AM_MIRROR(0xff00) AM_MASK(0xffff) AM_READWRITE(coupe_status_r, coupe_line_int_w) |
| 294 | AM_RANGE(0xfa, 0xfa) AM_MIRROR(0xff00) AM_MASK(0xffff) AM_READWRITE(coupe_lmpr_r, coupe_lmpr_w) |
| 295 | AM_RANGE(0xfb, 0xfb) AM_MIRROR(0xff00) AM_MASK(0xffff) AM_READWRITE(coupe_hmpr_r, coupe_hmpr_w) |
| 296 | AM_RANGE(0xfc, 0xfc) AM_MIRROR(0xff00) AM_MASK(0xffff) AM_READWRITE(coupe_vmpr_r, coupe_vmpr_w) |
| 297 | AM_RANGE(0xfd, 0xfd) AM_MIRROR(0xff00) AM_MASK(0xffff) AM_READWRITE(coupe_midi_r, coupe_midi_w) |
| 298 | AM_RANGE(0xfe, 0xfe) AM_MIRROR(0xff00) AM_MASK(0xffff) AM_READWRITE(coupe_keyboard_r, coupe_border_w) |
| 299 | AM_RANGE(0xff, 0xff) AM_MIRROR(0xff00) AM_MASK(0xffff) AM_READWRITE(coupe_attributes_r, coupe_sound_w) |
| 213 | 300 | ADDRESS_MAP_END |
| 214 | 301 | |
| 215 | 302 | |
| r2175 | r2176 | |
| 251 | 338 | |
| 252 | 339 | /************************************* |
| 253 | 340 | * |
| 254 | | * Inputs |
| 341 | * Input ports |
| 255 | 342 | * |
| 256 | 343 | *************************************/ |
| 257 | 344 | |
| 258 | | static unsigned char getSamKey1(unsigned char hi) |
| 259 | | { |
| 260 | | unsigned char result; |
| 261 | | |
| 262 | | hi=~hi; |
| 263 | | result=0xFF; |
| 264 | | |
| 265 | | if (hi==0x00) |
| 266 | | result &=readinputport(8) & 0x1F; |
| 267 | | else |
| 268 | | { |
| 269 | | if (hi&0x80) result &= readinputport(7) & 0x1F; |
| 270 | | if (hi&0x40) result &= readinputport(6) & 0x1F; |
| 271 | | if (hi&0x20) result &= readinputport(5) & 0x1F; |
| 272 | | if (hi&0x10) result &= readinputport(4) & 0x1F; |
| 273 | | if (hi&0x08) result &= readinputport(3) & 0x1F; |
| 274 | | if (hi&0x04) result &= readinputport(2) & 0x1F; |
| 275 | | if (hi&0x02) result &= readinputport(1) & 0x1F; |
| 276 | | if (hi&0x01) result &= readinputport(0) & 0x1F; |
| 277 | | } |
| 278 | | |
| 279 | | return result; |
| 280 | | } |
| 281 | | |
| 282 | | |
| 283 | | static unsigned char getSamKey2(unsigned char hi) |
| 284 | | { |
| 285 | | unsigned char result; |
| 286 | | |
| 287 | | hi=~hi; |
| 288 | | result=0xFF; |
| 289 | | |
| 290 | | if (hi==0x00) |
| 291 | | { |
| 292 | | /* does not map to any keys? */ |
| 293 | | } |
| 294 | | else |
| 295 | | { |
| 296 | | if (hi&0x80) result &= readinputport(7) & 0xE0; |
| 297 | | if (hi&0x40) result &= readinputport(6) & 0xE0; |
| 298 | | if (hi&0x20) result &= readinputport(5) & 0xE0; |
| 299 | | if (hi&0x10) result &= readinputport(4) & 0xE0; |
| 300 | | if (hi&0x08) result &= readinputport(3) & 0xE0; |
| 301 | | if (hi&0x04) result &= readinputport(2) & 0xE0; |
| 302 | | if (hi&0x02) result &= readinputport(1) & 0xE0; |
| 303 | | if (hi&0x01) result &= readinputport(0) & 0xE0; |
| 304 | | } |
| 305 | | |
| 306 | | return result; |
| 307 | | } |
| 308 | | |
| 309 | | |
| 310 | 345 | static INPUT_PORTS_START( coupe ) |
| 311 | 346 | PORT_START // FE 0 |
| 312 | 347 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT) |
| r2175 | r2176 | |
| 458 | 493 | MDRV_CPU_PROGRAM_MAP(coupe_mem, 0) |
| 459 | 494 | MDRV_CPU_IO_MAP(coupe_io, 0) |
| 460 | 495 | MDRV_CPU_VBLANK_INT("main", coupe_frame_interrupt) |
| 461 | | MDRV_MACHINE_START( coupe ) |
| 462 | 496 | |
| 497 | MDRV_MACHINE_START(coupe) |
| 498 | MDRV_MACHINE_RESET(coupe) |
| 499 | |
| 463 | 500 | /* video hardware */ |
| 464 | 501 | MDRV_SCREEN_ADD("main", RASTER) |
| 465 | 502 | MDRV_SCREEN_RAW_PARAMS(COUPE_XTAL_X1/2, 768, 0, 512, 312, 0, 192) /* border area? */ |