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 Sykes
martin@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