117 lines
6.5 KiB
Markdown
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?"
|