5.7 KiB
| title | author | date | isbn | publisher | category | chapter | pages |
|---|---|---|---|---|---|---|---|
| Michael Abrash's Graphics Programming Black Book, Special Edition | Michael Abrash | 1997-07-01 | 1576101746 | The Coriolis Group | Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development | 31 | 599-600 |
The interesting aspects of Listing 31.1 are three. First, the
Set320x400Mode subroutine selects 320x400 256-color mode. This is
accomplished by performing a mode 13H mode set followed by then putting
the VGA into standard planar byte mode. Set320x400Mode zeros display
memory as well. It's necessary to clear display memory even after a mode
13H mode set because the mode 13H mode set clears only the 64K of
display memory that can be accessed in that mode, leaving 192K of
display memory untouched.
The second interesting aspect of Listing 31.1 is the WritePixel
subroutine, which draws a colored pixel at any x,y addressable
location on the screen. Although it may not be obvious because I've
optimized the code a little, the process of drawing a pixel is
remarkably simple. First, the pixel's display memory address is
calculated as
address=(y * (SCREEN_WIDTH / 4)) + (x / 4)
which might be more recognizable as:
address=((y * SCREEN_WIDTH) + x) / 4
(There are 4 pixels at each display memory address in 320x400 mode, hence the division by 4.) Then the pixel's plane is calculated as
plane=x and 3
which is equivalent to:
plane=x modulo 4
The pixel's color is then written to the addressed byte in the addressed plane. That's all there is to it!
The third item of interest in Listing 31.1 is the ReadPixel
subroutine. ReadPixel is virtually identical to WritePixel, save
that in ReadPixel the Read Map register is programmed with a plane
number, while WritePixel uses a plane mask to set the Map Mask
register. Of course, that difference merely reflects a fundamental
difference in the operation of the two registers. (If that's Greek to
you, refer back to Chapters 23-30 for a refresher on VGA programming.)
ReadPixel isn't used in Listing 31.1, but I've included it because,
as I said above, the read and write pixel functions together can support
a whole host of more complex graphics functions.
How does 320x400 256-color mode stack up as regards performance? As it turns out, the programming model of 320x400 mode is actually pretty good for pixel drawing, pretty much on a par with the model of mode 13H. When you run Listing 31.1, you'll no doubt notice that the lines are drawn quite rapidly. (In fact, the drawing could be considerably faster still with a dedicated line-drawing subroutine, which would avoid the multiplication associated with each pixel in Listing 31.1.)
In 320x400 mode, the calculation of the memory address is not significantly slower than in mode 13H, and the calculation and selection of the target plane is quickly accomplished. As with mode 13H, 320x400 mode benefits tremendously from the byte-per-pixel organization of 256-color mode, which eliminates the need for the time-consuming pixel-masking of the 16-color modes. Most important, byte-per-pixel modes never require read-modify-write operations (which can be extremely slow due to display memory wait states) in order to clip and draw pixels. To draw a pixel, you just store its color in display memory—what could be simpler?
More sophisticated operations than pixel drawing are less easy to
accomplish in 320x400 mode, but with a little ingenuity it is possible
to implement a reasonably efficient version of just about any useful
graphics function. A fast line draw for 320x400 256-color mode would be
simple (although not as fast as would be possible in mode 13H). Fast
image copies could be implemented by copying one-quarter of the image to
one plane, one-quarter to the next plane, and so on for all four planes,
thereby eliminating the OUT per pixel that sequential processing
requires. If you're really into performance, you could store your images
with all the bytes for plane 0 grouped together, followed by all the
bytes for plane 1, and so on. That would allow a single REP MOVS
instruction to copy all the bytes for a given plane, with just four
REP MOVS instructions copying the whole image. In a number of cases,
in fact, 320x400 256-color mode can actually be much faster than mode
13H, because the VGA's hardware can be used to draw four or even eight
pixels with a single access; I'll return to the topic of
high-performance programming in 256-color modes other than mode 13H
("non-chain 4" modes) in Chapter 47.
It's all a bit complicated, but as I say, you should be able to design
an adequately fast—and often very fast—version for 320x400 mode of
whatever graphics function you need. If you're not all that concerned
with speed, WritePixel and ReadPixel should meet your needs.
Two 256-Color Pages
Listing 31.2 demonstrates the two pages of 320x400 256-color mode by drawing slanting color bars in page 0, then drawing color bars slanting the other way in page 1 and flipping to page 1 on the next key press. (Note that page 1 is accessed starting at offset 8000H in display memory, and is—unsurprisingly—displayed by setting the start address to 8000H.) Finally, Listing 31.2 draws vertical color bars in page 0 and flips back to page 0 when another key is pressed.
The color bar routines don't use the WritePixel subroutine from
Listing 31.1; they go straight to display memory instead for improved
speed. As I mentioned above, better speed yet could be achieved by a
color-bar algorithm that draws all the pixels in plane 0, then all the
pixels in plane 1, and so on, thereby avoiding the overhead of
constantly reprogramming the Map Mask register.