abrash-black-book/34-01.md
2013-12-30 20:26:41 +11:00

112 lines
6.3 KiB
Markdown

Chapter 34\
Changing Colors without Writing Pixels {#Heading1}
---------------------------------------
### Special Effects through Realtime Manipulation of DAC Colors {#Heading2}
Sometimes, strange as it may seem, the harder you try, the less you
accomplish. Brute force is fine when it suffices, but it does not always
suffice, and when it does not, finesse and alternative approaches are
called for. Such is the case with rapidly cycling through colors by
repeatedly loading the VGA's Digital to Analog Converter (DAC). No
matter how much you optimize your code, you just can't reliably load the
whole DAC cleanly in a single frame, so you had best find other ways to
use the DAC to cycle colors. What's more, BIOS support for DAC loading
is so inconsistent that it's unusable for color cycling; direct loading
through the I/O ports is the only way to go. We'll see why next, as we
explore color cycling, and then finish up this chapter and this section
by cleaning up some odds and ends about VGA color.
There's a lot to be said about loading the DAC, so let's dive right in
and see where the complications lie.
### Color Cycling {#Heading3}
As we've learned in past chapters, the VGA's DAC contains 256 storage
locations, each holding one 18-bit value representing an RGB color
triplet organized as 6 bits per primary color. Each and every pixel
generated by the VGA is fed into the DAC as an 8-bit value (refer to
Chapter 33 and to Chapter A on the companion CD-ROM to see how pixels
become 8-bit values in non-256 color modes) and each 8-bit value is used
to look up one of the 256 values stored in the DAC. The looked-up value
is then converted to analog red, green, and blue signals and sent to the
monitor to form one pixel.
That's straightforward enough, and we've produced some pretty impressive
color effects by loading the DAC once and then playing with the 8-bit
path into the DAC. Now, however, we want to generate color effects by
dynamically changing the values stored in the DAC in real time, a
technique that I'll call *color cycling*. The potential of color cycling
should be obvious: Smooth motion can easily be simulated by altering the
colors in an appropriate pattern, and all sorts of changing color
effects can be produced without altering a single bit of display memory.
For example, a sunset can be made to color and darken by altering the
DAC locations containing the colors used to draw the sunset, or a river
can be made to appear to flow by cycling through the colors used to draw
the river. Another use for color cycling is in providing more realistic
displays for applications like realtime 3-D games, where the VGA's 256
simultaneous colors can be made to seem like many more by changing the
DAC settings from frame to frame to match the changing color demands of
the rendered scene. Which leaves only one question: How do we load the
DAC smoothly in realtime?
Actually, so far as I know, you can't. At least you can't load the
*entire* DAC—all 256 locations—frame after frame without producing
distressing on-screen effects on at least some computers. In non-256
color modes, it is indeed possible to load the DAC quickly enough to
cycle all displayed colors (of which there are 16 or fewer), so color
cycling could be used successfully to cycle all colors in such modes. On
the other hand, color paging (which flips among a number of color sets
stored within the DAC in all modes other than 256 color mode, as
discussed in Chapter A on the companion CD-ROM) can be used in non-256
color modes to produce many of the same effects as color cycling and is
considerably simpler and more reliable then color cycling, so color
paging is generally superior to color cycling whenever it's available.
In short, color cycling is really the method of choice for dynamic color
effects only in 256-color mode—but, regrettably, color cycling is at its
least reliable and capable in that mode, as we'll see next.
### The Heart of the Problem {#Heading4}
Here's the problem with loading the entire DAC repeatedly: The DAC
contains 256 color storage locations, each loaded via either 3 or 4
**OUT** instructions (more on that next), so at least 768 **OUT**s are
needed to load the entire DAC. That many **OUT**s take a considerable
amount of time, all the more so because **OUT**s are painfully slow on
486s and Pentiums, and because the DAC is frequently on the ISA bus
(although VLB and PCI are increasingly common), where wait states are
inserted in fast computers. In an 8 MHz AT, 768 **OUT**s alone would
take 288 microseconds, and the data loading and looping that are also
required would take in the ballpark of 1,800 microseconds more, for a
minimum of 2 milliseconds total.
As it happens, the DAC should only be loaded during vertical blanking;
that is, the time between the end of displaying the bottom border and
the start of displaying the top border, when no video information at all
is being sent to the screen by the DAC. Otherwise, small dots of snow
appear on the screen, and while an occasional dot of this sort wouldn't
be a problem, the constant DAC loading required by color cycling would
produce a veritable snowstorm on the screen. By the way, I do mean
"border," not "frame buffer"; the overscan pixels pass through the DAC
just like the pixels controlled by the frame buffer, so you can't even
load the DAC while the border color is being displayed without getting
snow.
The start of vertical blanking itself is not easy to find, but the
leading edge of the vertical sync pulse is easy to detect via bit 3 of
the Input Status 1 register at 3DAH; when bit 3 is 1, the vertical sync
pulse is active. Conveniently, the vertical sync pulse starts partway
through but not too far into vertical blanking, so it serves as a handy
way to tell when it's safe to load the DAC without producing snow on the
screen.
So we wait for the start of the vertical sync pulse, then begin to load
the DAC. There's a catch, though. On many computers—Pentiums, 486s, and
386s sometimes, 286s most of the time, and 8088s all the time—there just
isn't enough time between the start of the vertical sync pulse and the
end of vertical blanking to load all 256 DAC locations. That's the crux
of the problem with the DAC, and shortly we'll get to a tool that will
let you explore for yourself the extent of the problem on computers in
which you're interested. First, though, we must address *another* DAC
loading problem: the BIOS.