
|
 |
|
Zen of Graphics Programming, 2nd Edition
by Michael Abrash
Coriolis, The Coriolis Group
ISBN: 1883577896 Pub Date: 04/01/96
|
Clearly, what we want is to set the new start address, then wait for the start of the vertical sync pulse, at which point we can be sure the page has flipped. However, we cant just set the start address and wait, because we might have the extreme misfortune to set one of the start address registers before the start of vertical sync and the other after, resulting in mismatched halves of the start address and a nasty jump of the displayed image for one frame.
One possible solution to this problem is to pick a second page start address that has a 0 value for the lower byte, so only the Start Address High register ever needs to be set, but in the sample program in Listing 1.1 Ive gone for generality and always set both bytes. To avoid mismatched start address bytes, the sample program waits for pixel data to be displayed, as indicated by the Display Enable status; this tells us were somewhere in the displayed portion of the frame, far enough away from vertical sync so we can be sure the new start address will get used at the next vertical sync. Once the Display Enable status is observed, the program sets the new start address, waits for vertical sync to happen, sets the new pel panning state, and then continues drawing. Dont worry about the details right now; page flipping will come up again, at considerably greater length, in later chapters.
As an interesting side note, be aware that if you run DOS software under a multitasking environment such as Windows NT, timeslicing delays can make mismatched start address bytes or mismatched start address and pel panning settings much more likely, for the graphics code can be interrupted at any time. This is also possible, although much less likely, under non-multitasking environments such as DOS, because strategically placed interrupts can cause the same sorts of problems there. For maximum safety, you should disable interrupts around the key portions of your page-flipping code, although here we run into the problem that if interrupts are disabled from the time we start looking for Display Enable until we set the Pel Panning register, they will be off for far too long, and keyboard, mouse, and network events will potentially be lost. Also, disabling interrupts wont help in true multitasking environments, which never let a program hog the entire CPU. This is one reason that pel panning, although indubitably flashy, isnt widely used and should be reserved for only those cases where its absolutely necessary.
Waiting for the sync pulse has the side effect of causing program execution to synchronize to the VGAs frame rate of 60 or 70 frames per second, depending on the display mode. This synchronization has the useful consequence of causing the program to execute at the same speed on any CPU that can draw fast enough to complete the drawing in a single frame; the program just idles for the rest of each frame that it finishes before the VGA is finished displaying the previous frame.
An important point illustrated by the sample program is that while the VGAs display memory is far larger and more versatile than is the case with earlier adapters, it is nonetheless a limited resource and must be used judiciously. The sample program uses VGA memory to store two 672×384 virtual pages, leaving only 1024 bytes free to store images. In this case, the only images needed are a colored ball and a blank block with which to erase it, so there is no problem, but many applications require dozens or hundreds of images. The tradeoffs between virtual page size, page flipping, and image storage must always be kept in mind when designing programs for the VGA.
To see the program run in 640x200 16-color mode, comment out the EQU line for MEDRES_VIDEO_MODE .
The Hazards of VGA Clones
Earlier, I said that any VGA that doesnt support the features and functionality covered in this book cant properly be called VGA compatible. I also noted that there are some exceptions, however, and weve just come to the most prominent one. You see, all VGAs really are compatible with the IBM VGAs functionality when it comes to drawing pixels into display memory; all the write modes and read modes and set/reset capabilities and everything else involved with manipulating display memory really does work in the same way on all VGAs and VGA clones. That compatibility isnt as airtight when it comes to scanning pixels out of display memory and onto the screen in certain infrequently-used ways, however.
The areas of incompatibility of which Im aware are illustrated by the sample program, and may in fact have caused you to see some glitches when you ran Listing 1.1. The problem, which arises only on certain VGAs, is that some settings of the Row Offset register cause some pixels to be dropped or displaced to the wrong place on the screen; often, this happens only in conjunction with certain start address settings. (In my experience, only VRAM (Video RAM)-based VGAs exhibit this problem, no doubt due to the way that pixel data is fetched from VRAM in large blocks.) Panning and large virtual bitmaps can be made to work reliably, by careful selection of virtual bitmap sizes and start addresses, but its difficult; thats one of the reasons that most commercial software does not use these features, although a number of games do. The upshot is that if youre going to use oversized virtual bitmaps and pan around them, you should take great care to test your software on a wide variety of VRAM- and DRAM-based VGAs.
Just the Beginning
That pretty well covers the important points of the sample VGA program in Listing 1.1. There are many VGA features we didnt even touch on, but the object was to give you a feel for the variety of features available on the VGA, to convey the flexibility and complexity of the VGAs resources, and in general to give you an initial sense of what VGA programming is like. Starting with the next chapter, well begin to explore the VGA systematically, on a more detailed basis.
|