Previous Table of Contents Next

The interesting aspects of Listing 31.1 are three. First, the Set320×400Mode subroutine selects 320×400 256-color mode. This is accomplished by performing a mode 13H mode set followed by then putting the VGA into standard planar byte mode. Set320×400Mode 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 320×400 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 320×400 256-color mode stack up as regards performance? As it turns out, the programming model of 320×400 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 320×400 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, 320×400 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 320×400 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 320×400 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, 320×400 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 320×400 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 320×400 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.

Previous Table of Contents Next

Graphics Programming Black Book © 2001 Michael Abrash