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

117 lines
6.5 KiB
Markdown

Yet another and somewhat odder workaround is that of using only 128 DAC
locations and page flipping. (Page flipping in 256-color modes involves
using the VGA's undocumented 256-color modes; see Chapters 31, 43, and
47 for details.) In this mode of operation, you'd first display page 0,
which is drawn entirely with colors 0-127. Then you'd draw page 1 to
look just like page 0, except that colors 128-255 are used instead.
You'd load DAC locations 128-255 with the next cycle settings for the
128 colors you're using, then you'd switch to display the second page
with the new colors. Then you could modify page 0 as needed, drawing in
colors 0-127, load DAC locations 0-127 with the next color cycle
settings, and flip back to page 0.
The idea is that you modify only those DAC locations that are not used
to display any pixels on the current screen. The advantage of this is
*not*, as you might think, that you don't generate garbage on the screen
when modifying undisplayed DAC locations; in fact, you do, for a spot of
interference will show up if you set a DAC location, displayed or not,
during display time. No, you still have to wait for vertical sync and
load only during vertical blanking before loading the DAC when page
flipping with 128 colors; the advantage is that since none of the DAC
locations you're modifying is currently displayed, you can spread the
loading out over two or more vertical blanking periods—however long it
takes. If you did this without the 128-color page flipping, you might
get odd on-screen effects as some of the colors changed after one frame,
some after the next, and so on—or you might not; changing the entire DAC
in chunks over several frames is another possibility worth considering.
Yet another approach to color cycling is that of loading a bit of the
DAC during each horizontal blanking period. Combine that with counting
scan lines, and you could vastly expand the number of simultaneous
on-screen colors by cycling colors *as a frame is displayed*, so that
the color set changes from scan line to scan line down the screen.
The possibilities are endless. However, were I to be writing 256-color
software that used color cycling, I'd find out how many colors could be
cycled after the start of vertical sync on the slowest computer I
expected the software to run on, I'd lop off at least 10 percent for a
safety margin, and I'd structure my program so that no color cycling set
exceeded that size, interleaving several color cycling sets if
necessary.
That's what *I'd* do. Don't let yourself be held back by my limited
imagination, though! Color cycling may be the most complicated of all
the color control techniques, but it's also the most powerful.
### Odds and Ends {#Heading9}
In my experience, when relying on the autoincrementing feature while
loading the DAC, the Write Index register wraps back from 255 to 0, and
likewise when you load a block of registers through the BIOS. So far as
I know, this is a characteristic of the hardware, and should be
consistent; also, Richard Wilton documents this behavior for the BIOS in
the VGA bible, *Programmer's Guide to PC Video Systems, Second Edition*
(Microsoft Press), so you should be able to count on it. Not that I see
that DAC index wrapping is especially useful, but it never hurts to
understand exactly how your resources behave, and I never know when one
of you might come up with a serviceable application for any particular
quirk.
#### The DAC Mask {#Heading10}
There's one register in the DAC that I haven't mentioned yet, the DAC
Mask register at 03C6H. The operation of this register is simple but
powerful; it can mask off any or all of the 8 bits of pixel information
coming into the DAC from the VGA. Whenever a bit of the DAC Mask
register is 1, the corresponding bit of pixel information is passed
along to the DAC to be used in looking up the RGB triplet to be sent to
the screen. Whenever a bit of the DAC Mask register is 0, the
corresponding pixel bit is ignored, and a 0 is used for that bit
position in all look-ups of RGB triplets. At the extreme, a DAC Mask
setting of 0 causes all 8 bits of pixel information to be ignored, so
DAC location 0 is looked up for every pixel, and the entire screen
displays the color stored in DAC location 0. This makes setting the DAC
Mask register to 0 a quick and easy way to blank the screen.
#### Reading the DAC {#Heading11}
The DAC can be read directly, via the DAC Read Index register at 3C7H
and the DAC Data register at 3C9H, in much the same way as it can be
written directly by way of the DAC Write Index register—complete with
autoincrementing the DAC Read Index register after every three reads.
Everything I've said about writing to the DAC applies to reading from
the DAC. In fact, reading from the DAC can even cause snow, just as
loading the DAC does, so it should ideally be performed during vertical
blanking.
The DAC can also be read by way of the BIOS in either of two ways.
**INT** 10H, function 10H (AH=10H), subfunction 15H (AL=15H) reads out a
single DAC location, specified by BX; this function returns the RGB
triplet stored in the specified location with the red component in the
lower 6 bits of DH, the green component in the lower 6 bits of CH, and
the blue component in the lower 6 bits of CL.
**INT** 10H, function 10H (AH=10H), subfunction 17H (AL=17H) reads out a
block of DAC locations of length CX, starting with the location
specified by BX. ES:DX must point to the buffer in which the RGB values
from the specified block of DAC locations are to be stored. The form of
this buffer (RGB, RGB, RGB ..., with three bytes per RGB triple) is
exactly the same as that of the buffer used when calling the BIOS to
load a block of registers.
Listing 34.1 illustrates reading the DAC both through the BIOS
block-read function and directly, with the direct-read code capable of
conditionally assembling to either guard against interrupts or not and
to use **REP INSB** or not. As you can see, reading the DAC settings is
very much symmetric with setting the DAC.
#### Cycling Down {#Heading12}
And so, at long last, we come to the end of our discussion of color
control on the VGA. If it has been more complex than anyone might have
imagined, it has also been most rewarding. There's as much obscure but
very real potential in color control as there is anywhere on the VGA,
which is to say that there's a very great deal of potential indeed. Put
color cycling or color paging together with the page flipping and image
drawing techniques explored elsewhere in this book, and you'll leave the
audience gasping and wondering "How the heck did they *do* that?"