129 lines
7.1 KiB
Markdown
129 lines
7.1 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](34-04.html) [Table of Contents](index.html) [Next](35-01.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
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?”
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](34-04.html) [Table of Contents](index.html) [Next](35-01.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|