ks26+@andrew.cmu.edu (Kenneth Sykes) (02/03/89)
VGA programming
---------------
A. Palette programming
The VGA has two palettes: the EGA palette and the VGA palette. The VGA
palette is a 256 entry table of r,g,b values. the r,g,b values range
from 0 to 63, giving 18-bit color. Each of the r,g,b values are stored
in a byte, so an r,g,b triple is 3 bytes and the palette is 768 bytes
long.
The EGA palette is a 16 entry palette, where each entry is a byte
ranging from 0 to 63. The byte is organized as follows:
7 6 5 4 3 2 1 0
x x r' g' b' r g b
r' is the MSB (Most significant bit) and r is the LSB. Similarly for g
and b. On a VGA, the low order 6 bits are used as an index into the
VGA palette. For instance bright red is 00100100b which corresponds to
entry 36 in the VGA palette.
Use the following BIOS calls to set the EGA palette (all call INT 10h):
to set an individual entry:
AX = 1000h BL = palette index (0-15) BH = value
to set overscan register (background):
AX = 1001h BH = value
to set palette all registers and overscan:
AX = 1002h ES:DX = pointer to 17 byte table
(0-15 are palette, 16 is overscan)
Note: the associated read commands are the same except add 7 to AL.
For instance, to read overscan: AX = 1008h (value returned
in BH).
Use the following BIOS calls to set the VGA palette (all call INT 10h):
to set an individual entry:
AX = 1010h BX = index DH = red CH = green CL = blue
to set a block of registers:
AX = 1012h ES:DX = pointer to table (r,g,b,r,g,b,...)
BX = starting index CX = length of table (#entries NOT #bytes)
Note: the associated read commands are the same except add 5 to AL.
The overscan color is defined to be entry 0 in the VGA
palette.
One other useful function is conversion to Gray Scale:
AX = 101Bh BX = starting index CX = # colors to convert
For each palette entry, a weighted sum of the components is
computed and the result is placed back into the palette. If r,g,b
are components of a given palette entry, then this function does
the following:
i = 0.3 * r + 0.59 * g + 0.11 * b;
r = g = b = i;
Note: this function does NOT preserve the original value.
B. Video Memory organization
The 320x200x256 color mode is a 64000 byte array starting at A000:0.
Each pixel can range from 0 to 255 and corresponds to an index into the
VGA palette [To answer someone's question concerning gray scales: If
you need gray scales, you can stuff the first 64 palette entries with
gray scale values (palette[i].r = i, etc.) and then treat the pixels
as gray scale values from 0 to 63.]. That's all there is to it - one
byte per pixel. It's much easier to program than the EGA.
(Use AX = 0013h to get this mode)
The 16 color modes are organized the same as the EGA, and are register
compatible with the EGA. There are 4 bit planes, and a mask register
(among other things). The bit plane is accessable starting at A000:0.
The following is a C example for setting pixels:
don't worry about this unless you have version 3
|
/* EGADEMO.C -- Compile with Microsoft C Version 3 with /Ze parameter
to enable "far" keyword. Programmed by Charles Petzold. */
#include <dos.h>
#define MAXROWS 350
#define MAXCOLS 640
#define COLBYTES MAXCOLS/8
#define GRAFOUT(index,value) { outp(0x3CE,index) ; outp(0x3CF,value) ; }
#define SWAP(a,b,temp) { temp = a ; a = b ; b = temp ; }
main() {
setvideomode(0x12) ;
randomrect(0) ; /* Draw colored rectangles */
setvideomode(0x12) ;
randomrect(0x18) ; /* Rectangles with XORing */
setvideomode(3) ;
}
setvideomode(mode) /* Sets video mode */
int mode ;
{
union REGS regs ;
regs.x.ax = mode ;
int86(0x10, ®s, ®s) ;
}
randomrect(fnct) /* Draws 100 rectangles */
int fnct ;
{
unsigned int i, r1, c1, r2, c2, temp ;
GRAFOUT(3, fnct) ; /* Function Register */
for (i = 0 ; i < 100 ; i++) {
r1 = rand() % MAXROWS ; r2 = rand() % MAXROWS ;
c1 = rand() % MAXCOLS ; c2 = rand() % MAXCOLS ;
if (r1 > r2) SWAP (r1, r2, temp) ;
if (c1 > c2) SWAP (c1, c2, temp) ;
rect(r1, c1, r2, c2, rand()%16);
}
}
rect(r1, c1, r2, c2, color) /* r1 <= r2 and c1 <= c2 */
unsigned int r1, c1, r2, c2, color ;
{
char far *addr = (char far *) (0xA0000000L + COLBYTES*r1 + (c1>>3)) ;
int numrows = r2 - r1 ; /* Number of rows */
int numcols = (c2 >> 3) - (c1 >> 3) - 1 ; /* Number of columns */
char lmask = 0xFF >> (c1 & 7) ; /* Mask for left */
char rmask = ~(0xFF >> (c2 & 7)) ; /* Mask for right */
register row, col ;
if (numcols < 0) { /* Adjustment for small rows */
lmask &= rmask ;
rmask = numcols = 0 ;
}
GRAFOUT(0, color) ; /* Set/Reset Register */
GRAFOUT(1, 0x0F) ; /* Enable Set/Reset Register */
for (row = 0 ; row < numrows ; row++) {
GRAFOUT(8, lmask) ; /* Bit Mask Register */
*(addr++) &= 1 ; /* Left side */
GRAFOUT(8, 0xFF) ;
for (col = 0 ; col < numcols ; col++)
*(addr++) &= 1 ; /* Middle part */
GRAFOUT(8, rmask) ;
*(addr++) &= 1 ; /* Right side */
addr += COLBYTES - 2 - numcols ; /* Next row */
}
GRAFOUT(0, 0) ; /* Set/Reset to normal */
GRAFOUT(1, 0) ; /* S/R Enable to normal */
GRAFOUT(8, 0xFF) ; /* Bit mask to normal */
}
This should have everything needed to get started.
E-mail me if there are any questions.
--Ken Sykesmartin@csd4.csd.uwm.edu (Martin A Miller) (10/12/90)
Greetings, Well, I think I've exhausted all the "direct" approaches to solving my problem, so I'll try the "brute force" method. I recently found a couple of no-frills GIF viewers on the "grape" archive site in the file "gifsrc.arc". They were written by Jim Griebel and for my EGA needs I was able to hack one of them a bit to write a plain ASCII file with the actual numerical values for each pixel (0=black, 1=blue,..., 15=white) of the GIF. These programs are written in Turbo Pascal 4.0. The programs work for EGA only, so of course, now I have been asked to do the same thing with VGA. Not having any background in programming VGA graphics, I have found out that VGA is quite a different animal...(than EGA). I've sent msgs to "grape" asking for info; they don't have any..I've got Richard Wilton's book "Programmer's Guide to PC & PS/2 Video Systems" and I can't make heads or tails out it.. The purpose of this post, then, is twofold: Jim Griebel, if you're reading this, please contact me, or if anyone has any info on VGA programming ie., which registers take what values, etc.. please email. thank you.. -mm Martin A. Miller Programmer/Consultant Social Science Research Facility University of Wisconsin-Milwaukee Phone: (414) 229-5314 Internet: martin@csd4.csd.uwm.edu Bitnet : martin%csd4.csd.uwm.edu@INTERBIT UUCP : uunet!martin@csd4.csd.uwm.edu