src/mess/video/vdc.c
| r977 | r978 | |
| 25 | 25 | int dvssr_write; /* Set when the DVSSR register has been written to */ |
| 26 | 26 | int physical_width; /* Width of the display */ |
| 27 | 27 | int physical_height; /* Height of the display */ |
| 28 | | UINT8 vce_control; /* VCE control register */ |
| 29 | | pair vce_address; /* Current address in the palette */ |
| 30 | | pair vce_data[512]; /* Palette data */ |
| 31 | 28 | UINT16 sprite_ram[64*4]; /* Sprite RAM */ |
| 32 | 29 | int curline; /* the current scanline we're on */ |
| 33 | | int current_bitmap_line; /* the current line in the display we are on */ |
| 34 | 30 | int current_segment; /* current segment of display */ |
| 35 | 31 | int current_segment_line; /* current line inside a segment of display */ |
| 36 | 32 | int vblank_triggered; /* to indicate whether vblank has been triggered */ |
| r977 | r978 | |
| 42 | 38 | UINT8 vdc_latch; |
| 43 | 39 | pair vdc_data[32]; |
| 44 | 40 | int status; |
| 45 | | mame_bitmap *bmp; |
| 46 | 41 | int y_scroll; |
| 47 | 42 | }VDC; |
| 48 | 43 | |
| 44 | typedef struct { |
| 45 | UINT8 vce_control; /* VCE control register */ |
| 46 | pair vce_address; /* Current address in the palette */ |
| 47 | pair vce_data[512]; /* Palette data */ |
| 48 | int current_bitmap_line; /* The current line in the display we are on */ |
| 49 | mame_bitmap *bmp; |
| 50 | }VCE; |
| 51 | |
| 49 | 52 | static VDC vdc; |
| 53 | static VCE vce; |
| 50 | 54 | |
| 51 | 55 | /* Function prototypes */ |
| 52 | 56 | |
| r977 | r978 | |
| 61 | 65 | int ret = 0; |
| 62 | 66 | |
| 63 | 67 | /* Draw the last scanline */ |
| 64 | | if ( vdc.current_bitmap_line >= 14 && vdc.current_bitmap_line < 14 + 242 ) { |
| 68 | if ( vce.current_bitmap_line >= 14 && vce.current_bitmap_line < 14 + 242 ) { |
| 65 | 69 | /* We are in the active display area */ |
| 66 | 70 | if ( vdc.current_segment == STATE_VDW ) { |
| 67 | 71 | vdc.y_scroll = ( vdc.current_segment_line == 0 ) ? vdc.vdc_data[BYR].w : ( vdc.y_scroll + 1 ); |
| 68 | | pce_refresh_line( vdc.current_bitmap_line, vdc.current_segment_line ); |
| 72 | pce_refresh_line( vce.current_bitmap_line, vdc.current_segment_line ); |
| 69 | 73 | } else { |
| 70 | | draw_overscan_line( vdc.current_bitmap_line ); |
| 74 | draw_overscan_line( vce.current_bitmap_line ); |
| 71 | 75 | } |
| 72 | 76 | } else { |
| 73 | 77 | /* We are in one of the blanking areas */ |
| 74 | | draw_black_line( vdc.current_bitmap_line ); |
| 78 | draw_black_line( vce.current_bitmap_line ); |
| 75 | 79 | } |
| 76 | 80 | |
| 77 | 81 | /* bump current scanline */ |
| 78 | | vdc.current_bitmap_line = ( vdc.current_bitmap_line + 1 ) % VDC_LPF; |
| 82 | vce.current_bitmap_line = ( vce.current_bitmap_line + 1 ) % VDC_LPF; |
| 79 | 83 | vdc.curline += 1; |
| 80 | 84 | vdc.current_segment_line += 1; |
| 81 | 85 | vdc.raster_count += 1; |
| r977 | r978 | |
| 90 | 94 | } |
| 91 | 95 | } |
| 92 | 96 | |
| 93 | | if ( vdc.current_bitmap_line == 0 ) { |
| 97 | if ( vce.current_bitmap_line == 0 ) { |
| 94 | 98 | vdc.current_segment = STATE_VSW; |
| 95 | 99 | vdc.current_segment_line = 0; |
| 96 | 100 | vdc.vblank_triggered = 0; |
| r977 | r978 | |
| 188 | 192 | |
| 189 | 193 | /* clear context */ |
| 190 | 194 | memset(&vdc, 0, sizeof(vdc)); |
| 195 | memset(&vce, 0, sizeof(vce)); |
| 191 | 196 | |
| 192 | 197 | /* allocate VRAM */ |
| 193 | 198 | vdc.vram = auto_malloc(0x10000); |
| 194 | 199 | memset(vdc.vram, 0, 0x10000); |
| 195 | 200 | |
| 196 | 201 | /* create display bitmap */ |
| 197 | | vdc.bmp = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, machine->screen[0].format); |
| 202 | vce.bmp = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, machine->screen[0].format); |
| 198 | 203 | |
| 199 | 204 | vdc.inc = 1; |
| 200 | 205 | } |
| r977 | r978 | |
| 203 | 208 | VIDEO_UPDATE( pce ) |
| 204 | 209 | { |
| 205 | 210 | /* copy our rendering buffer to the display */ |
| 206 | | copybitmap (bitmap,vdc.bmp,0,0,0,0,cliprect,TRANSPARENCY_NONE,0); |
| 211 | copybitmap (bitmap,vce.bmp,0,0,0,0,cliprect,TRANSPARENCY_NONE,0); |
| 207 | 212 | return 0; |
| 208 | 213 | } |
| 209 | 214 | |
| r977 | r978 | |
| 212 | 217 | int i; |
| 213 | 218 | |
| 214 | 219 | /* our line buffer */ |
| 215 | | UINT16 *line_buffer = BITMAP_ADDR16( vdc.bmp, line, 0 ); |
| 220 | UINT16 *line_buffer = BITMAP_ADDR16( vce.bmp, line, 0 ); |
| 216 | 221 | |
| 217 | 222 | for( i=0; i< VDC_WPF; i++ ) |
| 218 | 223 | line_buffer[i] = get_black_pen( Machine ); |
| r977 | r978 | |
| 223 | 228 | int i; |
| 224 | 229 | |
| 225 | 230 | /* Are we in greyscale mode or in color mode? */ |
| 226 | | int color_base = vdc.vce_control & 0x80 ? 512 : 0; |
| 231 | int color_base = vce.vce_control & 0x80 ? 512 : 0; |
| 227 | 232 | |
| 228 | 233 | /* our line buffer */ |
| 229 | | UINT16 *line_buffer = BITMAP_ADDR16( vdc.bmp, line, 0 ); |
| 234 | UINT16 *line_buffer = BITMAP_ADDR16( vce.bmp, line, 0 ); |
| 230 | 235 | |
| 231 | 236 | for ( i = 0; i < VDC_WPF; i++ ) |
| 232 | | line_buffer[i] = Machine->pens[color_base + vdc.vce_data[0x100].w]; |
| 237 | line_buffer[i] = Machine->pens[color_base + vce.vce_data[0x100].w]; |
| 233 | 238 | |
| 234 | 239 | } |
| 235 | 240 | |
| r977 | r978 | |
| 397 | 402 | switch(offset & 7) |
| 398 | 403 | { |
| 399 | 404 | case 0x04: /* color table data (LSB) */ |
| 400 | | temp = vdc.vce_data[vdc.vce_address.w].b.l; |
| 405 | temp = vce.vce_data[vce.vce_address.w].b.l; |
| 401 | 406 | break; |
| 402 | 407 | |
| 403 | 408 | case 0x05: /* color table data (MSB) */ |
| 404 | | temp = vdc.vce_data[vdc.vce_address.w].b.h; |
| 409 | temp = vce.vce_data[vce.vce_address.w].b.h; |
| 405 | 410 | temp |= 0xFE; |
| 406 | | vdc.vce_address.w = (vdc.vce_address.w + 1) & 0x01FF; |
| 411 | vce.vce_address.w = (vce.vce_address.w + 1) & 0x01FF; |
| 407 | 412 | break; |
| 408 | 413 | } |
| 409 | 414 | return (temp); |
| r977 | r978 | |
| 415 | 420 | switch(offset & 7) |
| 416 | 421 | { |
| 417 | 422 | case 0x00: /* control reg. */ |
| 418 | | vdc.vce_control = data; |
| 423 | vce.vce_control = data; |
| 419 | 424 | break; |
| 420 | 425 | |
| 421 | 426 | case 0x02: /* color table address (LSB) */ |
| 422 | | vdc.vce_address.b.l = data; |
| 423 | | vdc.vce_address.w &= 0x1FF; |
| 427 | vce.vce_address.b.l = data; |
| 428 | vce.vce_address.w &= 0x1FF; |
| 424 | 429 | break; |
| 425 | 430 | |
| 426 | 431 | case 0x03: /* color table address (MSB) */ |
| 427 | | vdc.vce_address.b.h = data; |
| 428 | | vdc.vce_address.w &= 0x1FF; |
| 432 | vce.vce_address.b.h = data; |
| 433 | vce.vce_address.w &= 0x1FF; |
| 429 | 434 | break; |
| 430 | 435 | |
| 431 | 436 | case 0x04: /* color table data (LSB) */ |
| 432 | | vdc.vce_data[vdc.vce_address.w].b.l = data; |
| 437 | vce.vce_data[vce.vce_address.w].b.l = data; |
| 433 | 438 | break; |
| 434 | 439 | |
| 435 | 440 | case 0x05: /* color table data (MSB) */ |
| 436 | | vdc.vce_data[vdc.vce_address.w].b.h = data & 0x01; |
| 441 | vce.vce_data[vce.vce_address.w].b.h = data & 0x01; |
| 437 | 442 | |
| 438 | 443 | /* bump internal address */ |
| 439 | | vdc.vce_address.w = (vdc.vce_address.w + 1) & 0x01FF; |
| 444 | vce.vce_address.w = (vce.vce_address.w + 1) & 0x01FF; |
| 440 | 445 | break; |
| 441 | 446 | } |
| 442 | 447 | } |
| r977 | r978 | |
| 463 | 468 | int v_width = width_table[(vdc.vdc_data[MWR].w >> 4) & 3]; |
| 464 | 469 | |
| 465 | 470 | /* our line buffer */ |
| 466 | | UINT16 *line_buffer = BITMAP_ADDR16( vdc.bmp, bitmap_line, 86 ); |
| 471 | UINT16 *line_buffer = BITMAP_ADDR16( vce.bmp, bitmap_line, 86 ); |
| 467 | 472 | |
| 468 | 473 | /* pointer to the name table (Background Attribute Table) in VRAM */ |
| 469 | 474 | UINT8 *bat = &(vdc.vram[nt_row << (v_width+1)]); |
| r977 | r978 | |
| 474 | 479 | UINT8 drawn[VDC_WPF]; |
| 475 | 480 | |
| 476 | 481 | /* Are we in greyscale mode or in color mode? */ |
| 477 | | int color_base = vdc.vce_control & 0x80 ? 512 : 0; |
| 482 | int color_base = vce.vce_control & 0x80 ? 512 : 0; |
| 478 | 483 | |
| 479 | 484 | int b0, b1, b2, b3; |
| 480 | 485 | int i0, i1, i2, i3; |
| r977 | r978 | |
| 497 | 502 | |
| 498 | 503 | /* First fill line with overscan colour */ |
| 499 | 504 | for ( i = -86; i < VDC_WPF - 86; i++ ) |
| 500 | | line_buffer[i] = Machine->pens[color_base + vdc.vce_data[0x100].w]; |
| 505 | line_buffer[i] = Machine->pens[color_base + vce.vce_data[0x100].w]; |
| 501 | 506 | |
| 502 | 507 | for(i=0;i<(vdc.physical_width >> 3) + 1;i++) |
| 503 | 508 | { |
| r977 | r978 | |
| 534 | 539 | |
| 535 | 540 | if ( phys_x >= 0 && phys_x < vdc.physical_width ) { |
| 536 | 541 | drawn[ phys_x ] = c ? 1 : 0; |
| 537 | | line_buffer[ pixel ] = Machine->pens[color_base + vdc.vce_data[c].w]; |
| 542 | line_buffer[ pixel ] = Machine->pens[color_base + vce.vce_data[c].w]; |
| 538 | 543 | pixel++; |
| 539 | 544 | if ( vdc.physical_width != 512 ) { |
| 540 | 545 | if ( pixel < ( ( ( phys_x + 1 ) * 512 ) / vdc.physical_width ) ) { |
| 541 | | line_buffer[ pixel ] = Machine->pens[color_base + vdc.vce_data[c].w]; |
| 546 | line_buffer[ pixel ] = Machine->pens[color_base + vce.vce_data[c].w]; |
| 542 | 547 | pixel++; |
| 543 | 548 | } |
| 544 | 549 | } |
| r977 | r978 | |
| 591 | 596 | { |
| 592 | 597 | int i; |
| 593 | 598 | UINT8 sprites_drawn=0; |
| 594 | | UINT16 *line_buffer= BITMAP_ADDR16( vdc.bmp, bitmap_line, 86 ); |
| 599 | UINT16 *line_buffer= BITMAP_ADDR16( vce.bmp, bitmap_line, 86 ); |
| 595 | 600 | |
| 596 | 601 | /* Are we in greyscale mode or in color mode? */ |
| 597 | | int color_base = vdc.vce_control & 0x80 ? 512 : 0; |
| 602 | int color_base = vce.vce_control & 0x80 ? 512 : 0; |
| 598 | 603 | |
| 599 | 604 | /* count up: Highest priority is Sprite 0 */ |
| 600 | 605 | for(i=0; i<64; i++) |
| r977 | r978 | |
| 662 | 667 | if ( buf[x] ) { |
| 663 | 668 | if( drawn[obj_x+x] < 2 ) { |
| 664 | 669 | if(priority || drawn[obj_x+x] == 0 ) { |
| 665 | | line_buffer[pixel_x] = Machine->pens[color_base + vdc.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 670 | line_buffer[pixel_x] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 666 | 671 | if ( vdc.physical_width != 512 ) { |
| 667 | 672 | if ( pixel_x + 1 < ( ( ( obj_x + x + 1 ) * 512 ) / vdc.physical_width ) ) { |
| 668 | | line_buffer[pixel_x + 1] = Machine->pens[color_base + vdc.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 673 | line_buffer[pixel_x + 1] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 669 | 674 | } |
| 670 | 675 | } |
| 671 | 676 | } |
| r977 | r978 | |
| 702 | 707 | if ( buf[x] ) { |
| 703 | 708 | if( drawn[obj_x+x] < 2 ) { |
| 704 | 709 | if ( priority || drawn[obj_x+x] == 0 ) { |
| 705 | | line_buffer[pixel_x] = Machine->pens[color_base + vdc.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 710 | line_buffer[pixel_x] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 706 | 711 | if ( vdc.physical_width != 512 ) { |
| 707 | 712 | if ( pixel_x + 1 < ( ( ( obj_x + x + 1 ) * 512 ) / vdc.physical_width ) ) { |
| 708 | | line_buffer[pixel_x + 1] = Machine->pens[color_base + vdc.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 713 | line_buffer[pixel_x + 1] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 709 | 714 | } |
| 710 | 715 | } |
| 711 | 716 | } |
| r977 | r978 | |
| 744 | 749 | if ( buf[x] ) { |
| 745 | 750 | if( drawn[obj_x+0x10+x] < 2 ) { |
| 746 | 751 | if( priority || drawn[obj_x+0x10+x] == 0 ) { |
| 747 | | line_buffer[pixel_x] = Machine->pens[color_base + vdc.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 752 | line_buffer[pixel_x] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 748 | 753 | if ( vdc.physical_width != 512 ) { |
| 749 | 754 | if ( pixel_x + 1 < ( ( ( obj_x + x + 17 ) * 512 ) / vdc.physical_width ) ) { |
| 750 | | line_buffer[pixel_x + 1] = Machine->pens[color_base + vdc.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 755 | line_buffer[pixel_x + 1] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; |
| 751 | 756 | } |
| 752 | 757 | } |
| 753 | 758 | } |