From 69d4893ec6cf1fc1e2f0984137753b8cc0b77f0c Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Sun, 5 Jul 2015 11:38:30 -0700 Subject: [PATCH] More VGA tests --- modules/pcjs/lib/video.js | 20 +++-- tests/pc/vga/L33-1.ASM | 176 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 tests/pc/vga/L33-1.ASM diff --git a/modules/pcjs/lib/video.js b/modules/pcjs/lib/video.js index 38bf52cf7..71ea591db 100644 --- a/modules/pcjs/lib/video.js +++ b/modules/pcjs/lib/video.js @@ -3589,10 +3589,10 @@ Video.prototype.getCardColors = function(nBitsPerPixel) if (nBitsPerPixel == 8) { /* - * The card must be a VGA, and it's using an (8bpp) mode that bypasses the ATC, so we need - * to pull RGB data exclusively from the 256-entry DAC; each entry contains 6-bit red, green, - * and blue values packed into bits 0-5, 6-11, and 12-17, respectively, each of which we - * effectively shift left 2 bits: a crude 6-to-8-bit color conversion. + * The card must be a VGA, and it's using an (8bpp) mode that bypasses the ATC, so we need to pull + * RGB data exclusively from the 256-entry DAC; each entry contains 6-bit red, green, and blue values + * packed into bits 0-5, 6-11, and 12-17, respectively, each of which we effectively shift left 2 bits: + * a crude 6-to-8-bit color conversion. */ for (i = 0; i < 256; i++) { dw = aDAC[i] || 0; @@ -3605,12 +3605,22 @@ Video.prototype.getCardColors = function(nBitsPerPixel) } else { /* * We need to pull RGB data from the ATC; moreover, if the ATC hasn't been initialized yet, - * we go with a default EGA-compatible 16-color palette. + * we go with a default EGA-compatible 16-color palette. We'll also use the DAC if there is one + * (ie, this is actually a VGA) and it appears to be initialized (ie, the VGA BIOS has been run). */ var fDAC = (aDAC && aDAC[255]); aRegs = (card.regATCData[15] != null? card.regATCData : Video.aEGAPalDef); for (i = 0; i < 16; i++) { b = aRegs[i] & Card.ATC.PALETTE.MASK; + /* + * If the DAC is valid, we need to supplement the 6 bits of each ATC palette entry with the values + * for bits 6 and 7 from the ATC COLORSEL register (and overwrite bits 4 and 5 if ATC.MODE.COLORSEL_ALL + * is set as well). + * + * The only reason the DAC wouldn't be valid is if 1) we're trying to display an image before the machine + * and its BIOS have had a chance to initialize the DAC (because we don't preset it to anything, although + * perhaps we should), or 2) this is an EGA, which doesn't have a DAC. + */ if (fDAC) { b |= (card.regATCData[Card.ATC.COLORSEL.INDX] & (Card.ATC.COLORSEL.DAC_BIT7 | Card.ATC.COLORSEL.DAC_BIT6)) << 4; if (card.regATCData[Card.ATC.MODE.INDX] & Card.ATC.MODE.COLORSEL_ALL) { diff --git a/tests/pc/vga/L33-1.ASM b/tests/pc/vga/L33-1.ASM new file mode 100644 index 000000000..0ee5f531b --- /dev/null +++ b/tests/pc/vga/L33-1.ASM @@ -0,0 +1,176 @@ +; Program to demonstrate use of the DAC registers by selecting a +; smoothly contiguous set of 256 colors, then filling the screen +; with concentric diamonds in all 256 colors so that they blend +; into one another to form a continuum of color. +; + .model small + .stack 200h + .data + +; Table used to set all 256 DAC entries. +; +; Table format: +; Byte 0: DAC register 0 red value +; Byte 1: DAC register 0 green value +; Byte 2: DAC register 0 blue value +; Byte 3: DAC register 1 red value +; Byte 4: DAC register 1 green value +; Byte 5: DAC register 1 blue value +; : +; Byte 765: DAC register 255 red value +; Byte 766: DAC register 255 green value +; Byte 767: DAC register 255 blue value + +ColorTable label byte + +; The first 64 entries are increasingly dim pure green. +X=0 + REPT 64 + db 0,63-X,0 +X=X+1 + ENDM + +; The next 64 entries are increasingly strong pure blue. +X=0 + REPT 64 + db 0,0,X +X=X+1 + ENDM + +; The next 64 entries fade through violet to red. +X=0 + REPT 64 + db X,0,63-X +X=X+1 + ENDM + +; The last 64 entries are increasingly dim pure red. +X=0 + REPT 64 + db 63-X,0,0 +X=X+1 + ENDM + + .code +Start: + mov ax,0013h ;AH=0 selects set mode function, + ; AL=13h selects 320x200 256-color + int 10h ; mode + + ;load the DAC registers with the + ; color settings + mov ax,@data ;point ES to the default + mov es,ax ; data segment + mov dx,offset ColorTable + ;point ES:DX to the start of the + ; block of RGB three-byte values + ; to load into the DAC registers + mov ax,1012h ;AH=10h selects set color function, + ; AL=12h selects set block of DAC + ; registers subfunction + sub bx,bx ;load the block of registers + ; starting at DAC register #0 + mov cx,100h ;set all 256 registers + int 10h ;load the DAC registers + + ;now fill the screen with + ; concentric diamonds in all 256 + ; color attributes + mov ax,0a000h ;point DS to the display memory + mov ds,ax ; segment + ; + ;draw diagonal lines in the upper + ; left quarter of the screen + mov al,2 ;start with color attribute #2 + mov ah,-1 ;cycle down through the colors + mov bx,320 ;draw top to bottom (distance from + ; one line to the next) + mov dx,160 ;width of rectangle + mov si,100 ;height of rectangle + sub di,di ;start at (0,0) + mov bp,1 ;draw left to right (distance from + ; one column to the next) + call FillBlock ;draw it + ; + ;draw diagonal lines in the upper + ; right quarter of the screen + mov al,2 ;start with color attribute #2 + mov ah,-1 ;cycle down through the colors + mov bx,320 ;draw top to bottom (distance from + ; one line to the next) + mov dx,160 ;width of rectangle + mov si,100 ;height of rectangle + mov di,319 ;start at (319,0) + mov bp,-1 ;draw right to left (distance from + ; one column to the next) + call FillBlock ;draw it + + ;draw diagonal lines in the lower + ; left quarter of the screen + mov al,2 ;start with color attribute #2 + mov ah,-1 ;cycle down through the colors + mov bx,-320 ;draw bottom to top (distance from + ; one line to the next) + mov dx,160 ;width of rectangle + mov si,100 ;height of rectangle + mov di,199*320 ;start at (0,199) + mov bp,1 ;draw left to right (distance from + ; one column to the next) + call FillBlock ;draw it + ; + ;draw diagonal lines in the lower + ; right quarter of the screen + mov al,2 ;start with color attribute #2 + mov ah,-1 ;cycle down through the colors + mov bx,-320 ;draw bottom to top (distance from + ; one line to the next) + mov dx,160 ;width of rectangle + mov si,100 ;height of rectangle + mov di,199*320+319 ;start at (319,199) + mov bp,-1 ;draw right to left (distance from + ; one column to the next) + call FillBlock ;draw it + + mov ah,1 ;wait for a key + int 21h ; + + mov ax,0003h ;return to text mode + int 10h ; + + mov ah,4ch ;done--return to DOS + int 21h + +; Fills the specified rectangular area of the screen with diagonal +; lines. +; +; Input: +; AL = initial attribute with which to draw +; AH = amount by which to advance the attribute from +; one pixel to the next +; BX = distance to advance from one pixel to the next +; DX = width of rectangle to fill +; SI = height of rectangle to fill +; DS:DN = screen address of first pixel to draw +; BP = offset from the start of one column to the start of +; the next + +FillBlock: +FillHorzLoop: + push di ;preserve pointer to top of column + push ax ;preserve initial attribute + mov cx,si ;column height +FillVertLoop: + mov [di],al ;set the pixel + add di,bx ;point to the next row in the column + add al,ah ;advance the attribute + loop FillVertLoop ; + pop ax ;restore initial attribute + add al,ah ;advance to the next attribute to + ; start the next column + pop di ;retrieve pointer to top of column + add di,bp ;point to next column + dec dx ;have we done all columns? + jnz FillHorzLoop ;no, do the next column + ret ; + + end Start