trunk/src/emu/video/pc_vga.c
| r19847 | r19848 | |
| 26 | 26 | per-game issues: |
| 27 | 27 | - The Incredible Machine: fix partial updates |
| 28 | 28 | - MAME 0.01: fix 92 Hz refresh rate bug (uses VESA register?). |
| 29 | | - Alien Breed, Bio Menace: jerky H scrolling (uses VGA/EGA mode with pel shift) |
| 30 | 29 | - Virtual Pool: ET4k unrecognized; |
| 31 | 30 | - California Chase (calchase): various gfx bugs, CPU related? |
| 31 | - Jazz Jackrabbit: status bar is very jerky, but main screen scrolling is fine? |
| 32 | - Catacombs: weird resolution (untested) |
| 32 | 33 | |
| 33 | 34 | ROM declarations: |
| 34 | 35 | |
| r19847 | r19848 | |
| 193 | 194 | { |
| 194 | 195 | } |
| 195 | 196 | |
| 197 | |
| 198 | /* VBLANK callback, start address definitely updates AT vblank, not before. */ |
| 199 | TIMER_CALLBACK_MEMBER(vga_device::vblank_timer_cb) |
| 200 | { |
| 201 | vga.crtc.start_addr = vga.crtc.start_addr_latch; |
| 202 | m_vblank_timer->adjust( machine().primary_screen->time_until_pos(vga.crtc.vert_blank_start) ); |
| 203 | } |
| 204 | |
| 196 | 205 | void vga_device::device_start() |
| 197 | 206 | { |
| 198 | 207 | memset(&vga, 0, sizeof(vga)); |
| r19847 | r19848 | |
| 212 | 221 | vga.svga_intf.crtc_regcount = 0x19; |
| 213 | 222 | |
| 214 | 223 | vga.memory = auto_alloc_array_clear(machine(), UINT8, vga.svga_intf.vram_size); |
| 224 | |
| 225 | m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vga_device::vblank_timer_cb),this)); |
| 215 | 226 | } |
| 216 | 227 | |
| 217 | 228 | void svga_device::device_start() |
| r19847 | r19848 | |
| 370 | 381 | int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); |
| 371 | 382 | UINT32 *bitmapline; |
| 372 | 383 | pen_t pen; |
| 384 | int pel_shift = (vga.attribute.pel_shift); |
| 373 | 385 | |
| 386 | // popmessage("%08x %02x",EGA_START_ADDRESS,pel_shift); |
| 387 | |
| 374 | 388 | /**/ |
| 375 | 389 | for (addr=EGA_START_ADDRESS, pos=0, line=0; line<LINES; |
| 376 | 390 | line += height, addr += EGA_LINE_LENGTH) |
| r19847 | r19848 | |
| 379 | 393 | { |
| 380 | 394 | bitmapline = &bitmap.pix32(line + yi); |
| 381 | 395 | |
| 382 | | for (pos=addr, c=0, column=0; column<EGA_COLUMNS; column++, c+=8, pos=(pos+1)&0xffff) |
| 396 | for (pos=addr, c=0, column=0; column<EGA_COLUMNS+1; column++, c+=8, pos=(pos+1)&0xffff) |
| 383 | 397 | { |
| 384 | 398 | int data[4]; |
| 385 | 399 | |
| r19847 | r19848 | |
| 391 | 405 | for (i = 7; i >= 0; i--) |
| 392 | 406 | { |
| 393 | 407 | pen = vga.pens[(data[0]&1) | (data[1]&2) | (data[2]&4) | (data[3]&8)]; |
| 394 | | if(!machine().primary_screen->visible_area().contains(c+i, line + yi)) |
| 395 | | continue; |
| 396 | | bitmapline[c+i] = pen; |
| 397 | 408 | |
| 398 | 409 | data[0]>>=1; |
| 399 | 410 | data[1]>>=1; |
| 400 | 411 | data[2]>>=1; |
| 401 | 412 | data[3]>>=1; |
| 413 | |
| 414 | if(!machine().primary_screen->visible_area().contains(c+i-pel_shift, line + yi)) |
| 415 | continue; |
| 416 | bitmapline[c+i-pel_shift] = pen; |
| 402 | 417 | } |
| 403 | 418 | } |
| 404 | 419 | } |
| r19847 | r19848 | |
| 414 | 429 | int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); |
| 415 | 430 | int yi; |
| 416 | 431 | int xi; |
| 417 | | int pel_shift = 0;//vga.attribute.pel_shift; /* TODO: timing bug with this */ |
| 432 | int pel_shift = (vga.attribute.pel_shift & 6); |
| 418 | 433 | |
| 419 | 434 | /* line compare is screen sensitive */ |
| 420 | 435 | mask_comp = 0x3ff; //| (LINES & 0x300); |
| 421 | 436 | |
| 437 | // popmessage("%02x %02x",vga.attribute.pel_shift,vga.sequencer.data[4] & 0x08); |
| 438 | |
| 422 | 439 | curr_addr = 0; |
| 423 | 440 | if(!(vga.sequencer.data[4] & 0x08)) |
| 424 | 441 | { |
| r19847 | r19848 | |
| 431 | 448 | if((line + yi) == (vga.crtc.line_compare & mask_comp)) |
| 432 | 449 | curr_addr = 0; |
| 433 | 450 | bitmapline = &bitmap.pix32(line + yi); |
| 434 | | for (pos=curr_addr, c=0, column=0; column<VGA_COLUMNS; column++, c+=8, pos++) |
| 451 | for (pos=curr_addr, c=0, column=0; column<VGA_COLUMNS+1; column++, c+=8, pos++) |
| 435 | 452 | { |
| 436 | 453 | if(pos > 0x80000/4) |
| 437 | 454 | return; |
| 438 | 455 | |
| 439 | 456 | for(xi=0;xi<8;xi++) |
| 440 | 457 | { |
| 441 | | if(!machine().primary_screen->visible_area().contains(c+xi-pel_shift, line + yi)) |
| 458 | if(!machine().primary_screen->visible_area().contains(c+xi-(pel_shift), line + yi)) |
| 442 | 459 | continue; |
| 443 | | bitmapline[c+xi-pel_shift] = machine().pens[vga.memory[(pos & 0xffff)+((xi >> 1)*0x10000)]]; |
| 460 | bitmapline[c+xi-(pel_shift)] = machine().pens[vga.memory[(pos & 0xffff)+((xi >> 1)*0x10000)]]; |
| 444 | 461 | } |
| 445 | 462 | } |
| 446 | 463 | } |
| r19847 | r19848 | |
| 458 | 475 | curr_addr = 0; |
| 459 | 476 | bitmapline = &bitmap.pix32(line + yi); |
| 460 | 477 | //addr %= 0x80000; |
| 461 | | for (pos=curr_addr, c=0, column=0; column<VGA_COLUMNS; column++, c+=0x10, pos+=0x8) |
| 478 | for (pos=curr_addr, c=0, column=0; column<VGA_COLUMNS+1; column++, c+=0x10, pos+=0x8) |
| 462 | 479 | { |
| 463 | 480 | if(pos + 0x08 > 0x80000) |
| 464 | 481 | return; |
| 465 | 482 | |
| 466 | 483 | for(xi=0;xi<0x10;xi++) |
| 467 | 484 | { |
| 468 | | if(!machine().primary_screen->visible_area().contains(c+xi-pel_shift, line + yi)) |
| 485 | if(!machine().primary_screen->visible_area().contains(c+xi-(pel_shift), line + yi)) |
| 469 | 486 | continue; |
| 470 | 487 | bitmapline[c+xi-pel_shift] = machine().pens[vga.memory[(pos+(xi >> 1)) & 0xffff]]; |
| 471 | 488 | } |
| r19847 | r19848 | |
| 939 | 956 | |
| 940 | 957 | return 0; |
| 941 | 958 | } |
| 959 | |
| 942 | 960 | UINT32 svga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 943 | 961 | { |
| 944 | 962 | UINT8 cur_mode = pc_vga_choosevideomode(); |
| 963 | |
| 945 | 964 | switch(cur_mode) |
| 946 | 965 | { |
| 947 | 966 | case SCREEN_OFF: bitmap.fill (get_black_pen(machine()), cliprect);break; |
| r19847 | r19848 | |
| 1158 | 1177 | break; |
| 1159 | 1178 | case 0x0c: |
| 1160 | 1179 | case 0x0d: |
| 1161 | | res = (vga.crtc.start_addr >> ((index & 1) ^ 1)*8) & 0xff; |
| 1180 | res = (vga.crtc.start_addr_latch >> ((index & 1) ^ 1)*8) & 0xff; |
| 1162 | 1181 | break; |
| 1163 | 1182 | case 0x0e: |
| 1164 | 1183 | case 0x0f: |
| r19847 | r19848 | |
| 1231 | 1250 | |
| 1232 | 1251 | machine().primary_screen->configure((hblank_period), (vblank_period), visarea, refresh ); |
| 1233 | 1252 | // popmessage("%d %d\n",vga.crtc.horz_total * 8,vga.crtc.vert_total); |
| 1253 | |
| 1254 | m_vblank_timer->adjust( machine().primary_screen->time_until_pos(vga.crtc.vert_blank_start) ); |
| 1234 | 1255 | } |
| 1235 | 1256 | |
| 1236 | 1257 | void vga_device::recompute_params() |
| r19847 | r19848 | |
| 1333 | 1354 | break; |
| 1334 | 1355 | case 0x0c: |
| 1335 | 1356 | case 0x0d: |
| 1336 | | vga.crtc.start_addr &= ~(0xff << (((index & 1)^1) * 8)); |
| 1337 | | vga.crtc.start_addr |= (data << (((index & 1)^1) * 8)); |
| 1357 | vga.crtc.start_addr_latch &= ~(0xff << (((index & 1)^1) * 8)); |
| 1358 | vga.crtc.start_addr_latch |= (data << (((index & 1)^1) * 8)); |
| 1338 | 1359 | break; |
| 1339 | 1360 | case 0x0e: |
| 1340 | 1361 | case 0x0f: |
| r19847 | r19848 | |
| 2045 | 2066 | MCFG_SCREEN_UPDATE_DEVICE("vga", trident_vga_device, screen_update) |
| 2046 | 2067 | |
| 2047 | 2068 | MCFG_PALETTE_LENGTH(0x100) |
| 2048 | | |
| 2049 | 2069 | MCFG_DEVICE_ADD("vga", TRIDENT_VGA, 0) |
| 2050 | 2070 | MACHINE_CONFIG_END |
| 2051 | 2071 | |
| r19847 | r19848 | |
| 2055 | 2075 | MCFG_SCREEN_UPDATE_DEVICE("vga", cirrus_vga_device, screen_update) |
| 2056 | 2076 | |
| 2057 | 2077 | MCFG_PALETTE_LENGTH(0x100) |
| 2058 | | |
| 2059 | 2078 | MCFG_DEVICE_ADD("vga", CIRRUS_VGA, 0) |
| 2060 | 2079 | MACHINE_CONFIG_END |
| 2061 | 2080 | |
| r19847 | r19848 | |
| 2660 | 2679 | res = s3.cursor_pattern_y; |
| 2661 | 2680 | break; |
| 2662 | 2681 | case 0x51: |
| 2663 | | res = (vga.crtc.start_addr & 0x0c0000) >> 18; |
| 2682 | res = (vga.crtc.start_addr_latch & 0x0c0000) >> 18; |
| 2664 | 2683 | break; |
| 2665 | 2684 | case 0x55: |
| 2666 | 2685 | res = s3.extended_dac_ctrl; |
| r19847 | r19848 | |
| 2669 | 2688 | res = s3.ext_misc_ctrl_2; |
| 2670 | 2689 | break; |
| 2671 | 2690 | case 0x69: |
| 2672 | | res = vga.crtc.start_addr >> 16; |
| 2691 | res = vga.crtc.start_addr_latch >> 16; |
| 2673 | 2692 | break; |
| 2674 | 2693 | case 0x6a: |
| 2675 | 2694 | res = svga.bank_r & 0x7f; |
| r19847 | r19848 | |
| 2781 | 2800 | { |
| 2782 | 2801 | case 0x31: // CR31 Memory Configuration Register |
| 2783 | 2802 | s3.memory_config = data; |
| 2784 | | vga.crtc.start_addr &= ~0x30000; |
| 2785 | | vga.crtc.start_addr |= ((data & 0x30) << 12); |
| 2803 | vga.crtc.start_addr_latch &= ~0x30000; |
| 2804 | vga.crtc.start_addr_latch |= ((data & 0x30) << 12); |
| 2786 | 2805 | //popmessage("%02x",data); |
| 2787 | 2806 | s3_define_video_mode(); |
| 2788 | 2807 | break; |
| r19847 | r19848 | |
| 2930 | 2949 | s3.cursor_pattern_y = data; |
| 2931 | 2950 | break; |
| 2932 | 2951 | case 0x51: |
| 2933 | | vga.crtc.start_addr &= ~0xc0000; |
| 2934 | | vga.crtc.start_addr |= ((data & 0x3) << 18); |
| 2952 | vga.crtc.start_addr_latch &= ~0xc0000; |
| 2953 | vga.crtc.start_addr_latch |= ((data & 0x3) << 18); |
| 2935 | 2954 | svga.bank_w = (svga.bank_w & 0xcf) | ((data & 0x0c) << 2); |
| 2936 | 2955 | svga.bank_r = svga.bank_r; |
| 2937 | 2956 | s3_define_video_mode(); |
| r19847 | r19848 | |
| 3022 | 3041 | //printf("%02x X\n",data); |
| 3023 | 3042 | break; |
| 3024 | 3043 | case 0x69: |
| 3025 | | vga.crtc.start_addr &= ~0x1f0000; |
| 3026 | | vga.crtc.start_addr |= ((data & 0x1f) << 16); |
| 3044 | vga.crtc.start_addr_latch &= ~0x1f0000; |
| 3045 | vga.crtc.start_addr_latch |= ((data & 0x1f) << 16); |
| 3027 | 3046 | s3_define_video_mode(); |
| 3028 | 3047 | break; |
| 3029 | 3048 | case 0x6a: |
| r19847 | r19848 | |
| 4996 | 5015 | switch(ati.ext_reg_select) |
| 4997 | 5016 | { |
| 4998 | 5017 | case 0x23: |
| 4999 | | vga.crtc.start_addr = (vga.crtc.start_addr & 0xfffdffff) | ((data & 0x10) << 13); |
| 5018 | vga.crtc.start_addr_latch = (vga.crtc.start_addr_latch & 0xfffdffff) | ((data & 0x10) << 13); |
| 5000 | 5019 | vga.crtc.cursor_addr = (vga.crtc.cursor_addr & 0xfffdffff) | ((data & 0x08) << 14); |
| 5001 | 5020 | logerror("ATI: ATI23 write %02x\n",data); |
| 5002 | 5021 | break; |
| r19847 | r19848 | |
| 5010 | 5029 | logerror("ATI: ATI2D (extensions) write %02x\n",data); |
| 5011 | 5030 | break; |
| 5012 | 5031 | case 0x30: |
| 5013 | | vga.crtc.start_addr = (vga.crtc.start_addr & 0xfffeffff) | ((data & 0x40) << 10); |
| 5032 | vga.crtc.start_addr_latch = (vga.crtc.start_addr_latch & 0xfffeffff) | ((data & 0x40) << 10); |
| 5014 | 5033 | vga.crtc.cursor_addr = (vga.crtc.cursor_addr & 0xfffeffff) | ((data & 0x04) << 14); |
| 5015 | 5034 | logerror("ATI: ATI30 write %02x\n",data); |
| 5016 | 5035 | break; |