src/mess/drivers/a7000.c
| r8783 | r8784 | |
| 5 | 5 | preliminary driver by Angelo Salese, |
| 6 | 6 | based on work by Tomasz Slanina and Tom Walker |
| 7 | 7 | |
| 8 | | |
| 8 | ??? |
| 9 | 9 | bp (0382827C) (second trigger) |
| 10 | 10 | do R13 = SR13 |
| 11 | 11 | |
| r8783 | r8784 | |
| 21 | 21 | * |
| 22 | 22 | */ |
| 23 | 23 | |
| 24 | static UINT8 vidc20_pal_index; |
| 25 | static UINT16 vidc20_horz_reg[0x10],vidc20_vert_reg[0x10]; |
| 26 | static UINT8 vidc20_bpp_mode; |
| 27 | |
| 24 | 28 | static const char *const vidc20_regnames[] = |
| 25 | 29 | { |
| 26 | 30 | "Video Palette", // 0 |
| r8783 | r8784 | |
| 41 | 45 | "Data Control" // F |
| 42 | 46 | }; |
| 43 | 47 | |
| 48 | static const char *const vidc20_horz_regnames[] = |
| 49 | { |
| 50 | "Horizontal Cycle", // 0x80 HCR |
| 51 | "Horizontal Sync Width", // 0x81 HSWR |
| 52 | "Horizontal Border Start", // 0x82 HBSR |
| 53 | "Horizontal Display Start", // 0x83 HDSR |
| 54 | "Horizontal Display End", // 0x84 HDER |
| 55 | "Horizontal Border End", // 0x85 HBER |
| 56 | "Horizontal Cursor Start", // 0x86 HCSR |
| 57 | "Horizontal Interlace", // 0x87 HIR |
| 58 | "Horizontal Counter TEST", // 0x88 |
| 59 | "Horizontal <UNDEFINED>", // 0x89 |
| 60 | "Horizontal <UNDEFINED>", // 0x8a |
| 61 | "Horizontal <UNDEFINED>", // 0x8b |
| 62 | "Horizontal All TEST", // 0x8c |
| 63 | "Horizontal <UNDEFINED>", // 0x8d |
| 64 | "Horizontal <UNDEFINED>", // 0x8e |
| 65 | "Horizontal <UNDEFINED>" // 0x8f |
| 66 | }; |
| 44 | 67 | |
| 68 | #define HCR 0 |
| 69 | #define HSWR 1 |
| 70 | #define HBSR 2 |
| 71 | #define HDSR 3 |
| 72 | #define HDER 4 |
| 73 | #define HBER 5 |
| 74 | #define HCSR 6 |
| 75 | #define HIR 7 |
| 76 | |
| 77 | static const char *const vidc20_vert_regnames[] = |
| 78 | { |
| 79 | "Vertical Cycle", // 0x90 VCR |
| 80 | "Vertical Sync Width", // 0x91 VSWR |
| 81 | "Vertical Border Start", // 0x92 VBSR |
| 82 | "Vertical Display Start", // 0x93 VDSR |
| 83 | "Vertical Display End", // 0x94 VDER |
| 84 | "Vertical Border End", // 0x95 VBER |
| 85 | "Vertical Cursor Start", // 0x96 VCSR |
| 86 | "Vertical Cursor End", // 0x97 VCER |
| 87 | "Vertical Counter TEST", // 0x98 |
| 88 | "Horizontal <UNDEFINED>", // 0x99 |
| 89 | "Vertical Counter Increment TEST", // 0x9a |
| 90 | "Horizontal <UNDEFINED>", // 0x9b |
| 91 | "Vertical All TEST", // 0x9c |
| 92 | "Horizontal <UNDEFINED>", // 0x9d |
| 93 | "Horizontal <UNDEFINED>", // 0x9e |
| 94 | "Horizontal <UNDEFINED>" // 0x9f |
| 95 | }; |
| 96 | |
| 97 | #define VCR 0 |
| 98 | #define VSWR 1 |
| 99 | #define VBSR 2 |
| 100 | #define VDSR 3 |
| 101 | #define VDER 4 |
| 102 | #define VBER 5 |
| 103 | #define VCSR 6 |
| 104 | #define VCER 7 |
| 105 | |
| 106 | static void vidc20_dynamic_screen_change(running_machine *machine) |
| 107 | { |
| 108 | /* sanity checks - first pass */ |
| 109 | /* |
| 110 | total cycles + border start/end |
| 111 | */ |
| 112 | if(vidc20_horz_reg[HCR] && vidc20_horz_reg[HBSR] && vidc20_horz_reg[HBER] && |
| 113 | vidc20_vert_reg[VCR] && vidc20_vert_reg[VBSR] && vidc20_vert_reg[VBER]) |
| 114 | { |
| 115 | /* sanity checks - second pass */ |
| 116 | /* |
| 117 | total cycles > border end > border start |
| 118 | */ |
| 119 | if((vidc20_horz_reg[HCR] > vidc20_horz_reg[HBER]) && |
| 120 | (vidc20_horz_reg[HBER] > vidc20_horz_reg[HBSR]) && |
| 121 | (vidc20_vert_reg[VCR] > vidc20_vert_reg[VBER]) && |
| 122 | (vidc20_vert_reg[VBER] > vidc20_vert_reg[VBSR])) |
| 123 | { |
| 124 | /* finally ready to change the resolution */ |
| 125 | int hblank_period,vblank_period; |
| 126 | rectangle visarea = machine->primary_screen->visible_area(); |
| 127 | hblank_period = (vidc20_horz_reg[HCR] & 0x3ffc); |
| 128 | vblank_period = (vidc20_vert_reg[VCR] & 0x3fff); |
| 129 | /* note that we use the border registers as the visible area */ |
| 130 | visarea.min_x = (vidc20_horz_reg[HBSR] & 0x3ffe); |
| 131 | visarea.max_x = (vidc20_horz_reg[HBER] & 0x3ffe)-1; |
| 132 | visarea.min_y = (vidc20_vert_reg[VBSR] & 0x1fff); |
| 133 | visarea.max_y = (vidc20_vert_reg[VBER] & 0x1fff)-1; |
| 134 | |
| 135 | machine->primary_screen->configure(hblank_period, vblank_period, visarea, machine->primary_screen->frame_period().attoseconds ); |
| 136 | logerror("VIDC20: successfully changed the screen to:\n Display Size = %d x %d\n Border Size %d x %d\n Cycle Period %d x %d\n", |
| 137 | (vidc20_horz_reg[HDER]-vidc20_horz_reg[HDSR]),(vidc20_vert_reg[VDER]-vidc20_vert_reg[VDSR]), |
| 138 | (vidc20_horz_reg[HBER]-vidc20_horz_reg[HBSR]),(vidc20_vert_reg[VBER]-vidc20_vert_reg[VBSR]), |
| 139 | hblank_period,vblank_period); |
| 140 | } |
| 141 | } |
| 142 | } |
| 143 | |
| 45 | 144 | static WRITE32_HANDLER( a7000_vidc20_w ) |
| 46 | 145 | { |
| 47 | 146 | int reg = data >> 28; |
| 48 | | int val = data & 0xffffff; |
| 49 | 147 | |
| 50 | 148 | switch(reg) |
| 51 | 149 | { |
| 150 | case 0: // Video Palette |
| 151 | { |
| 152 | int r,g,b; |
| 153 | |
| 154 | r = (data & 0x0000ff) >> 0; |
| 155 | g = (data & 0x00ff00) >> 8; |
| 156 | b = (data & 0xff0000) >> 16; |
| 157 | |
| 158 | palette_set_color_rgb(space->machine,vidc20_pal_index & 0xff,r,g,b); |
| 159 | |
| 160 | /* auto-increment & wrap-around */ |
| 161 | vidc20_pal_index++; |
| 162 | vidc20_pal_index &= 0xff; |
| 163 | } |
| 164 | break; |
| 165 | case 1: // Video Palette Address |
| 166 | { |
| 167 | // according to RPCEmu, these mustn't be set |
| 168 | if (data & 0x0fffff00) |
| 169 | return; |
| 170 | |
| 171 | vidc20_pal_index = data & 0xff; |
| 172 | } |
| 173 | break; |
| 174 | |
| 52 | 175 | case 4: // Border Color |
| 53 | 176 | { |
| 54 | 177 | int r,g,b; |
| 55 | 178 | |
| 56 | | r = (val & 0x0000ff) >> 0; |
| 57 | | g = (val & 0x00ff00) >> 8; |
| 58 | | b = (val & 0xff0000) >> 16; |
| 179 | r = (data & 0x0000ff) >> 0; |
| 180 | g = (data & 0x00ff00) >> 8; |
| 181 | b = (data & 0xff0000) >> 16; |
| 59 | 182 | |
| 60 | 183 | palette_set_color_rgb(space->machine,0x100,r,g,b); |
| 61 | 184 | } |
| 62 | 185 | break; |
| 63 | | default: logerror("VIDC20: %s Register write = %08x\n",vidc20_regnames[reg],val); |
| 186 | case 5: // Cursor Palette Logical Colour n |
| 187 | case 6: |
| 188 | case 7: |
| 189 | { |
| 190 | int r,g,b; |
| 191 | int cursor_index = 0x100 + reg - 4; // 0x101,0x102 and 0x103 (plus 0x100 of above, 2bpp) |
| 192 | |
| 193 | r = (data & 0x0000ff) >> 0; |
| 194 | g = (data & 0x00ff00) >> 8; |
| 195 | b = (data & 0xff0000) >> 16; |
| 196 | |
| 197 | palette_set_color_rgb(space->machine,cursor_index,r,g,b); |
| 198 | } |
| 199 | break; |
| 200 | case 8: // Horizontal |
| 201 | { |
| 202 | int horz_reg; |
| 203 | |
| 204 | horz_reg = (data >> 24) & 0xf; |
| 205 | vidc20_horz_reg[horz_reg] = data & 0x3fff; |
| 206 | if(horz_reg == 0 || horz_reg == 2 || horz_reg == 5) |
| 207 | vidc20_dynamic_screen_change(space->machine); |
| 208 | |
| 209 | // logerror("VIDC20: %s Register write = %08x (%d)\n",vidc20_horz_regnames[horz_reg],val,val); |
| 210 | } |
| 211 | break; |
| 212 | case 9: // Vertical |
| 213 | { |
| 214 | int vert_reg; |
| 215 | |
| 216 | vert_reg = (data >> 24) & 0xf; |
| 217 | vidc20_vert_reg[vert_reg] = data & 0x1fff; |
| 218 | if(vert_reg == 0 || vert_reg == 2 || vert_reg == 5) |
| 219 | vidc20_dynamic_screen_change(space->machine); |
| 220 | |
| 221 | // logerror("VIDC20: %s Register write = %08x (%d)\n",vidc20_vert_regnames[vert_reg],val,val); |
| 222 | |
| 223 | } |
| 224 | break; |
| 225 | case 0x0e: // Control |
| 226 | { |
| 227 | vidc20_bpp_mode = (data & 0xe0) >> 5; |
| 228 | } |
| 229 | break; |
| 230 | default: logerror("VIDC20: %s Register write = %08x\n",vidc20_regnames[reg],data & 0xfffffff); |
| 64 | 231 | } |
| 65 | 232 | } |
| 66 | 233 | |
| r8783 | r8784 | |
| 70 | 237 | |
| 71 | 238 | static VIDEO_UPDATE( a7000 ) |
| 72 | 239 | { |
| 240 | int x_size,y_size,x_start,y_start; |
| 241 | int x,y,xi; |
| 242 | UINT32 count; |
| 243 | static UINT8 *vram = memory_region(screen->machine, "vram"); |
| 244 | |
| 73 | 245 | bitmap_fill(bitmap, cliprect, screen->machine->pens[0x100]); |
| 74 | 246 | |
| 247 | count = 0; |
| 248 | x_size = (vidc20_horz_reg[HDER]-vidc20_horz_reg[HDSR]); |
| 249 | y_size = (vidc20_vert_reg[VDER]-vidc20_vert_reg[VDSR]); |
| 250 | x_start = vidc20_horz_reg[HDSR]; |
| 251 | y_start = vidc20_vert_reg[VDSR]; |
| 252 | |
| 253 | /* check if display is enabled */ |
| 254 | if(x_size <= 0 || y_size <= 0) |
| 255 | return 0; |
| 256 | |
| 257 | // popmessage("%d",vidc20_bpp_mode); |
| 258 | |
| 259 | switch(vidc20_bpp_mode) |
| 260 | { |
| 261 | case 0: /* 1 bpp */ |
| 262 | { |
| 263 | for(y=0;y<y_size;y++) |
| 264 | { |
| 265 | for(x=0;x<x_size;x+=8) |
| 266 | { |
| 267 | for(xi=0;xi<8;xi++) |
| 268 | *BITMAP_ADDR16(bitmap, y+y_start, x+xi+x_start) = (vram[count]>>(7-xi))&1; |
| 269 | |
| 270 | count++; |
| 271 | } |
| 272 | } |
| 273 | } |
| 274 | break; |
| 275 | case 3: /* 8 bpp */ |
| 276 | { |
| 277 | for(y=0;y<y_size;y++) |
| 278 | { |
| 279 | for(x=0;x<x_size;x++) |
| 280 | { |
| 281 | *BITMAP_ADDR16(bitmap, y+y_start, x+x_start) = (vram[count])&0xff; |
| 282 | |
| 283 | count++; |
| 284 | } |
| 285 | } |
| 286 | } |
| 287 | break; |
| 288 | } |
| 289 | |
| 75 | 290 | return 0; |
| 76 | 291 | } |
| 77 | 292 | |
| r8783 | r8784 | |
| 230 | 445 | #define IOMD_ID0 0x094/4 |
| 231 | 446 | #define IOMD_ID1 0x098/4 |
| 232 | 447 | |
| 448 | #define IOMD_VIDCUR 0x1d0/4 |
| 449 | #define IOMD_VIDEND 0x1d4/4 |
| 450 | #define IOMD_VIDSTART 0x1d8/4 |
| 451 | #define IOMD_VIDINIT 0x1dc/4 |
| 452 | #define IOMD_VIDCR 0x1e0/4 |
| 453 | |
| 233 | 454 | static UINT16 timer_in[2],timer_out[2]; |
| 234 | 455 | static int timer_counter[2]; |
| 235 | 456 | static emu_timer *IOMD_timer[2]; |
| r8783 | r8784 | |
| 237 | 458 | static UINT8 IOMD_IO_ctrl,IOMD_keyb_ctrl; |
| 238 | 459 | |
| 239 | 460 | static UINT16 io_id; |
| 461 | static UINT8 viddma_status; |
| 462 | static UINT32 viddma_addr_start,viddma_addr_end; |
| 240 | 463 | |
| 241 | 464 | static void fire_iomd_timer(int timer, int timer_count) |
| 242 | 465 | { |
| r8783 | r8784 | |
| 268 | 491 | */ |
| 269 | 492 | } |
| 270 | 493 | |
| 494 | static void viddma_transfer_start(const address_space *space) |
| 495 | { |
| 496 | UINT32 src = viddma_addr_start; |
| 497 | UINT32 dst = 0; |
| 498 | UINT32 size = viddma_addr_end; |
| 499 | UINT32 dma_index; |
| 500 | UINT8 *vram = memory_region(space->machine, "vram"); |
| 501 | |
| 502 | /* TODO: this should actually be a qword transfer */ |
| 503 | for(dma_index = 0;dma_index < size;dma_index++) |
| 504 | { |
| 505 | vram[dst] = memory_read_byte(space, src); |
| 506 | |
| 507 | src++; |
| 508 | dst++; |
| 509 | } |
| 510 | } |
| 511 | |
| 271 | 512 | static READ32_HANDLER( a7000_iomd_r ) |
| 272 | 513 | { |
| 273 | | if(offset != IOMD_KBDCR) |
| 274 | | logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); |
| 514 | // if(offset != IOMD_KBDCR) |
| 515 | // logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); |
| 275 | 516 | |
| 276 | 517 | |
| 277 | 518 | switch(offset) |
| r8783 | r8784 | |
| 303 | 544 | |
| 304 | 545 | case IOMD_ID0: return io_id & 0xff; // IOMD ID low |
| 305 | 546 | case IOMD_ID1: return (io_id >> 8) & 0xff; // IOMD ID high |
| 306 | | // default: logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); break; |
| 547 | |
| 548 | case IOMD_VIDEND: return (viddma_addr_end & 0x00fffff8); //bits 31:24 undefined |
| 549 | case IOMD_VIDSTART: return (viddma_addr_start & 0x1ffffff8); //bits 31, 30, 29 undefined |
| 550 | case IOMD_VIDCR: return (viddma_status & 0xa0) | 0x50; //bit 6 = DRAM mode, bit 4 = QWORD transfer |
| 551 | |
| 552 | default: logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); break; |
| 307 | 553 | } |
| 308 | 554 | |
| 309 | 555 | return 0; |
| r8783 | r8784 | |
| 311 | 557 | |
| 312 | 558 | static WRITE32_HANDLER( a7000_iomd_w ) |
| 313 | 559 | { |
| 314 | | logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data); |
| 560 | // logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data); |
| 315 | 561 | |
| 316 | 562 | switch(offset) |
| 317 | 563 | { |
| r8783 | r8784 | |
| 345 | 591 | } |
| 346 | 592 | break; |
| 347 | 593 | |
| 348 | | //default: logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data); |
| 594 | case IOMD_VIDEND: viddma_addr_end = data & 0x00fffff8; //bits 31:24 unused |
| 595 | case IOMD_VIDSTART: viddma_addr_start = data & 0x1ffffff8; //bits 31, 30, 29 unused |
| 596 | case IOMD_VIDCR: |
| 597 | viddma_status = data & 0xa0; if(data & 0x20) { viddma_transfer_start(space); } |
| 598 | break; |
| 599 | |
| 600 | |
| 601 | default: logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data); |
| 349 | 602 | } |
| 350 | 603 | } |
| 351 | 604 | |
| 352 | 605 | static ADDRESS_MAP_START( a7000_mem, ADDRESS_SPACE_PROGRAM, 32) |
| 353 | | AM_RANGE(0x00000000, 0x007fffff) AM_MIRROR(0x00800000) AM_ROM AM_REGION("user1", 0x0) |
| 606 | AM_RANGE(0x00000000, 0x003fffff) AM_MIRROR(0x00800000) AM_ROM AM_REGION("user1", 0x0) |
| 354 | 607 | // AM_RANGE(0x01000000, 0x01ffffff) AM_NOP //expansion ROM |
| 355 | 608 | // AM_RANGE(0x02000000, 0x02ffffff) AM_RAM //VRAM |
| 356 | 609 | // I/O 03000000 - 033fffff |
| 357 | | AM_RANGE(0x03000000, 0x030001ff) AM_MIRROR(0x00200000) AM_READWRITE(a7000_iomd_r,a7000_iomd_w) //IOMD Registers |
| 358 | 610 | // AM_RANGE(0x03010000, 0x03011fff) //Super IO |
| 359 | 611 | // AM_RANGE(0x03012000, 0x03029fff) //FDC |
| 360 | 612 | // AM_RANGE(0x0302b000, 0x0302bfff) //Network podule |
| 361 | 613 | // AM_RANGE(0x03040000, 0x0304ffff) //podule space 0,1,2,3 |
| 362 | 614 | // AM_RANGE(0x03070000, 0x0307ffff) //podule space 4,5,6,7 |
| 615 | AM_RANGE(0x03200000, 0x032001ff) AM_READWRITE(a7000_iomd_r,a7000_iomd_w) //IOMD Registers //mirrored at 0x03000000-0x1ff? |
| 363 | 616 | // AM_RANGE(0x03310000, 0x03310003) //Mouse Buttons |
| 617 | |
| 364 | 618 | AM_RANGE(0x03400000, 0x037fffff) AM_WRITE(a7000_vidc20_w) |
| 365 | 619 | // AM_RANGE(0x08000000, 0x08ffffff) AM_MIRROR(0x07000000) //EASI space |
| 366 | 620 | AM_RANGE(0x10000000, 0x13ffffff) AM_RAM //SIMM 0 bank 0 |
| r8783 | r8784 | |
| 421 | 675 | MDRV_SCREEN_REFRESH_RATE(60) |
| 422 | 676 | MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ |
| 423 | 677 | MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) |
| 424 | | MDRV_SCREEN_SIZE(640, 480) |
| 425 | | MDRV_SCREEN_VISIBLE_AREA(0, 640-1, 0, 480-1) |
| 678 | MDRV_SCREEN_SIZE(1900, 1080) //max available size |
| 679 | MDRV_SCREEN_VISIBLE_AREA(0, 1900-1, 0, 1080-1) |
| 426 | 680 | MDRV_PALETTE_LENGTH(0x200) |
| 427 | 681 | // MDRV_PALETTE_INIT(black_and_white) |
| 428 | 682 | |
| r8783 | r8784 | |
| 443 | 697 | ROM_LOAD( "rom2.bin", 0x100000, 0x100000, CRC(4ae4fd8b) SHA1(1b30d5905d5364dfa48bad69257b0ef8190e9bf6) ) |
| 444 | 698 | ROM_LOAD( "rom3.bin", 0x200000, 0x100000, CRC(3108fb2b) SHA1(865b01583f3fb5f4ed5e9201676db327cdeb40b3) ) |
| 445 | 699 | ROM_LOAD( "rom4.bin", 0x300000, 0x100000, CRC(55a51980) SHA1(a7191727edd5babf679ebbdea6585833a1fb34e6) ) |
| 700 | |
| 701 | ROM_REGION( 0x800000, "vram", ROMREGION_ERASE00 ) |
| 446 | 702 | ROM_END |
| 447 | 703 | |
| 448 | 704 | ROM_START(a7000p) |
| 449 | 705 | ROM_REGION( 0x800000, "user1", ROMREGION_ERASEFF ) |
| 450 | 706 | ROM_LOAD( "riscos-3.71.rom", 0x000000, 0x400000, CRC(211cf888) SHA1(c5fe0645e48894fb4b245abeefdc9a65d659af59)) |
| 707 | |
| 708 | ROM_REGION( 0x800000, "vram", ROMREGION_ERASE00 ) |
| 451 | 709 | ROM_END |
| 452 | 710 | |
| 453 | 711 | /*************************************************************************** |