123 lines
7.4 KiB
Markdown
123 lines
7.4 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](45-03.html) [Table of Contents](index.html) [Next](45-05.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
One point I’d like to make is that although the system-memory buffer in
|
||
Listing 45.1 has exactly the same dimensions as the screen bitmap,
|
||
that’s not a requirement, and there are some good reasons not to make
|
||
the two the same size. For example, if the system buffer is bigger than
|
||
the area displayed on the screen, it’s possible to pan the visible area
|
||
around the system buffer. Or, alternatively, the system buffer can be
|
||
just the size of a desired window, representing a window into a larger,
|
||
virtual buffer. We could then draw the desired portion of the virtual
|
||
bitmap into the system-memory buffer, then copy the buffer to the
|
||
screen, and the effect will be of having panned the window to the new
|
||
location.
|
||
|
||
------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
 *Another argument in favor of a small viewing window is that it restricts the amount of display memory actually drawn to. Restricting the display memory used for animation reduces the total number of display-memory accesses, which in turn boosts overall performance; it also improves the performance and appearance of panning, in which the whole window has to be redrawn or copied.*
|
||
------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
If you keep a close watch, you’ll notice that many high-performance
|
||
animation games similarly restrict their full-featured animation area to
|
||
a relatively small region. Often, it’s hard to tell that this is the
|
||
case, because the animation region is surrounded by flashy digitized
|
||
graphics and by items such as scoreboards and status screens, but look
|
||
closely and see if the animation region in your favorite game isn’t
|
||
smaller than you thought.
|
||
|
||
### Hi-Res VGA Page Flipping {#Heading8}
|
||
|
||
On a standard VGA, hi-res mode is mode 12H, which offers 640x480
|
||
resolution with 16 colors. That’s a nice mode, with plenty of pixels,
|
||
and square ones at that, but it lacks one thing—page flipping. The
|
||
problem is that the mode 12H bitmap is 150 K in size, and the standard
|
||
VGA has only 256 K total, too little memory for two of those monster
|
||
mode 12H pages. With only one page, flipping is obviously out of the
|
||
question, and without page flipping, top-flight, hi-res animation can’t
|
||
be implemented. The standard fallback is to use the EGA’s hi-res mode,
|
||
mode 10H (640x350, 16 colors) for page flipping, but this mode is less
|
||
than ideal for a couple of reasons: It offers sharply lower vertical
|
||
resolution, and it’s lousy for handling scaled-up CGA graphics, because
|
||
the vertical resolution is a fractional multiple—1.75 times, to be
|
||
exact—of that of the CGA. CGA resolution may not seem important these
|
||
days, but many images were originally created for the CGA, as were many
|
||
graphics packages and games, and it’s at least convenient to be able to
|
||
handle CGA graphics easily. Then, too, 640x350 is also a poor multiple
|
||
of the 200 scan lines of the popular 320x200 256-color mode 13H of the
|
||
VGA.
|
||
|
||
There are a couple of interesting, if imperfect, solutions to the
|
||
problem of hi-res page flipping. One is to use the split screen to
|
||
enable page flipping only in the top two-thirds of the screen; see the
|
||
previous chapter for details, and for details on the mechanics of page
|
||
flipping generally. This doesn’t address the CGA problem, but it does
|
||
yield square pixels and a full 640x480 screen resolution, although not
|
||
all those pixels are flippable and thus animatable.
|
||
|
||
A second solution is to program the screen to a 640x400 mode. Such a
|
||
mode uses almost every byte of display memory (64,000 bytes, actually;
|
||
you could add another few lines, if you really wanted to), and thereby
|
||
provides the highest resolution possible on the VGA for a fully
|
||
page-flipped display. It maps well to CGA and mode 13H resolutions,
|
||
being either identical or double in both dimensions. As an added
|
||
benefit, it offers an easy-on-the-eyes 70-Hz frame rate, as opposed to
|
||
the 60 Hz that is the best that mode 12H can offer, due to the design of
|
||
standard VGA monitors. Best of all, perhaps, is that 640x400 16-color
|
||
mode is easy to set up.
|
||
|
||
The key to 640x400 mode is understanding that on a VGA, mode 10H
|
||
(640x350) is, at heart, a 400-scan-line mode. What I mean by that is
|
||
that in mode 10H, the Vertical Total register, which controls the total
|
||
number of scan lines, both displayed and nondisplayed, is set to 447,
|
||
exactly the same as in the VGA’s text modes, which do in fact support
|
||
400 scan lines. A properly sized and centered display is achieved in
|
||
mode 10H by setting the polarity of the sync pulses to tell the monitor
|
||
to scan vertically at a faster rate (to make fewer lines fill the
|
||
screen), by starting the overscan after 350 lines, and by setting the
|
||
vertical sync and blanking pulses appropriately for the faster vertical
|
||
scanning rate. Changing those settings is all that’s required to turn
|
||
mode 10H into a 640x400 mode, and that’s easy to do, as illustrated by
|
||
Listing 45.2, which provides mode set code for 640x400 mode.
|
||
|
||
**LISTING 45.2 L45-2.C**
|
||
|
||
/* Mode set routine for VGA 640x400 16-color mode. Tested with
|
||
Borland C++ in C compilation mode. */
|
||
|
||
#include <dos.h>
|
||
|
||
void Set640x400()
|
||
{
|
||
union REGS regset;
|
||
|
||
/* First, set to standard 640x350 mode (mode 10h) */
|
||
regset.x.ax = 0x0010;
|
||
int86(0x10, ®set, ®set);
|
||
|
||
/* Modify the sync polarity bits (bits 7 & 6) of the
|
||
Miscellaneous Output register (readable at 0x3CC, writable at
|
||
0x3C2) to select the 400-scan-line vertical scanning rate */
|
||
outp(0x3C2, ((inp(0x3CC) & 0x3F) | 0x40));
|
||
|
||
/* Now, tweak the registers needed to convert the vertical
|
||
timings from 350 to 400 scan lines */
|
||
outpw(0x3D4, 0x9C10); /* adjust the Vertical Sync Start register
|
||
for 400 scan lines */
|
||
outpw(0x3D4, 0x8E11); /* adjust the Vertical Sync End register
|
||
for 400 scan lines */
|
||
outpw(0x3D4, 0x8F12); /* adjust the Vertical Display End
|
||
register for 400 scan lines */
|
||
outpw(0x3D4, 0x9615); /* adjust the Vertical Blank Start
|
||
register for 400 scan lines */
|
||
outpw(0x3D4, 0xB916); /* adjust the Vertical Blank End register
|
||
for 400 scan lines */
|
||
}
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](45-03.html) [Table of Contents](index.html) [Next](45-05.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|