
                         Programming the VGA Registers
                      by Boone (boone@ucsd.edu), March '94

   The IBM PC has long been slammed by owners of other computers which come 
with superior graphics capabilities built right into hardware.  The PC is a 
strange beast to program in general, and when it comes to graphics the 
programmer doesn't get much help from the video hardware.  However, there are 
quite a few neat tricks you can do using the VGA registers, as I'm sure you're 
aware.  The trick is knowing just which registers to use and how to use them to 
achieve the desired results.  In particular, precise timing is necessary to 
avoid screen flicker and/or "snow".  The registers on your video card are 
necessary for just about any communication with the VGA besides basic 
reading/writing of pixels.  Some of the registers are standard, which are the 
ones we will be discussing here.  Most SVGA chipsets have their own special 
functions associated with different registers for things such as bank 
switching, which is part of what makes trying to write SVGA programs so 
difficult.  The registers are also used to set the various attributes of each 
video mode: horizontal and vertical resolution, color depth, refresh rate, 
chain-4 mode, and so on.  Luckily, BIOS handles all this for us and since we 
only need to set the video mode once at program start-up and once at exit, you 
should need to mess with these particular functions too much, unless you are 
using a special mode, such as mode X.  (See the mode X section for more info on 
all this.)  If you want to experiment with the video mode registers, ftp 
yourself a file called TWEAK*.* (my version is TWEAK10.ZIP).  For now we'll 
just assume the video mode has already been set to whatever mode you wish.
   One of the most common techniques used by game programmers is fade in/out.  
A clean fade is simple but very effective.  Suprisingly, even big-budget games 
like Ultima VII often have a lot of screen noise during their fades.  With a 
little effort you can easily write your own noise-free fade routines.  There's 
nothing like giving a professional first impression on your intro screen, since 
the fade-in is likely to be the very first thing they see of your program.
   BIOS is much to slow for this timing-critical opperation, so we'll have to 
get down and dirty with our VGA card.  Fading is a fairly simple process.  As 
you should know, the VGA palette consists of 256 colors with 3 attributes for 
each color: red, green and blue.  Every cycle of the fade, we have to go 
through all 768 attributes and if it is larger than 0 subtract one.  We'll use 
regsiters 3C8h and 3C9h for palette opperations.  The operation for sending a 
palette to the card is straight-forward: send a 0 to port 3C8h and then your 
768 byte buffer to port 3C9h.  This is good enough for setting the palette at 
the start of your program, but of course it has to go in a loop for the fade, 
since you'll have to do this 256 times, subtracting one from each non-zero 
member of the buffer.  The pseudo-code looks something like this:

   constant PALSIZE = 256*3;
   unsigned character buffer[PALSIZE];
   boolean done;
   counter i,j;

      for j = 255 to 0
       {
         for i = 0 to PALSIZE-1
            if buffer[i] > 0
               buffer[i] = buffer[i] - 1;

         output 0 to port 3C8h;
         for i = 0 to PALSIZE-1
            output buffer[i] to port 3C9h;
       }

   Easy enough, right?  If you convert this to the language of your choice it 
should run fine.  (Make sure you have the buffer pre-loaded with the correct 
palette, however, or you will get very strange results...)  But you'll notice 
the "snow" mentioned earlier.  Depending on your video card, this could mean 
that you see no noise at all to fuzz covering your entire screen.  Even if it 
look fine on your system, however, we want to make sure it will be smooth on 
*all* setups it could potentially be run on.  For that we're going to have to 
ask the video card when it's safe to send the palette buffer to the card, and 
for that we'll need the retrace register.
   Putting aside palette concerns for a moment, I'll briefly cover the retrace 
on your video card.  (See the next section of this article for a more in-depth 
discussion of this.)  Bascially the vertical retrace is a short time in which 
the screen is not being updated (from video memory to your monitor) and you can 
safely do writes to your video memory or palette without worrying about getting 
snow, flicker, tearing, or other unwanted side-effects.  This is a pretty quick 
period (retrace occurs 60 to 70 times a second) so you can't do too much at 
once.
   Returning to our fade: we want to update the palette during the vertical 
retrace.  The value we want is bit 3 of register 3DAh.  While that bit is zero 
we're safe to write.  The best practice in this case is to wait for the bit to 
change to one (screen is being traced) and then the instant it changes to 0, 
blast all our new video info to the card.  It won't be necessary in this case 
since all we are doing is fading the palette and then waiting for the next 
retrace, but if you're doing animation or playing music at the same time 
you'll want to include this extra bit of code as a safety net.  Otherwise you 
might detect the 0 in the refresh bit at the very last instant of the retrace 
and end up writing while the screen is being traced.  The pseudo-code now goes 
like this:

      for j = 255 to 0
       {
         for i = 0 to PALSIZE-1
            if buffer[i] > 0
               buffer[i] = buffer[i] - 1;

         while bit 3 of port 3DAh is 0
            no opperation;
         while bit 3 of port 3DAh is 1
            no opperation;

         output 0 to port 3C8h;
         for i = 0 to PALSIZE-1
            output buffer[i] to port 3C9h;
       }

   That's it!  All that's left is for you to implement it in your favorite 
language.  However, I can hear the cries right now: "Code!  Give us some real 
assembly code we can use!"  I'm reluctant to provided it as this is the exact 
sort of thing that is easy to cut and paste into your program without knowing 
how it works.  However, I'll give you the unoptimized main loop in 80x86 
assembly as this may be clearer to you that my explanation or pseudo-code.  Two 
things to remember about this code: it is optimized enough to be smooth on any 
video card (or any that I've seen, anyway) assuming that the fade is the _only_ 
thing going on.  There's some other things you may want to change if you plan 
to say, play music during this process.  Secondly, you'll need to have the 
current palette loaded into the buffer beforehand.  You could read it from the 
VGA card using either registers or BIOS, but this is both slow and (in my 
oppinion) sloppy coding.  You should *never* ask the video card about anything 
(excluding retrace) that you could keep track of yourself.  In the case of the 
palette, you probably already loaded it from disk anyway, or if you are using 
the default palette <cough, gag, choke> just read the values once and store 
them in your executable or in a resource file.

     palbuf   DB                  768 DUP (?)
     fadecnt  DW                  040h

; At this point, you should:
;  1) have the video mode set
;  2) have palbuf loaded with the current palette
;  3) have something on the screen to fade!

fadeloop:

     xor      al,al               ; used for comparisons and port 3D8h
     mov      cx,768              ; loop counter
     mov      si,offset palbuf    ; save palette buffer in si

decloop:
     mov      dl,[si]              ; put next pal reg in dx
     cmp      al,dl                ; is it 0?
     je       next                 ; nope...
     dec      dl                   ; yes, so subtract one
     mov      [si],dl              ; put it back into palette buffer

next:
     dec      cx                   ; decrement counter
     inc      si                   ; increment our buffer
     cmp      cx,0
     jne      decloop              ; not done yet, so loop around

     mov      cx,768              ; reset for palette output
     sub      si,768              ; reset palbuf pointer
     mov      dx,03c8h
     out      dx,al               ; inform VGA of palette change
     inc      dx                  ; DX = 3C8h + 1 = 3C9h

     mov      ch,02h              ; do outter loop 2 times
     mov      dx,03dah            ; prepare refresh register
     mov      bx,03c9h            ; prepare palette reg (for quick loading)

     cli                          ; disable interrupts!

outloop:
     mov      cl,80h              ; do inner loop 128 times

     in       al,dx               ; wait for current retrace to end
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 