
|
 |
|
Zen of Graphics Programming, 2nd Edition
by Michael Abrash
Coriolis, The Coriolis Group
ISBN: 1883577896 Pub Date: 04/01/96
|
By the way, if IS_VGA is set to 0 in Listing 8.2, the program will assemble in a form that will run on the EGA and only the EGA. Pel panning suppression in the split screen wont work in this version, however, because the EGA lacks the capability to support that feature. When the EGA version runs, the split screen simply jerks back and forth during both panning sessions.
Notes on Setting and Reading Registers
There are a few interesting points regarding setting and reading registers to be made about Listing 8.2. First, bit 5 of the AC Index register should be set to 1 whenever palette RAM is not being set (which is to say, all the time in your code, because palette RAM should normally be set via the BIOS). When bit 5 is 0, video data from display memory is no longer sent to palette RAM, and the screen becomes a solid colornot normally a desirable state of affairs.
Recall also that the AC Index and Data registers are both written to at I/O address 3C0H, with the toggle that determines which one is written to at any time switching state on every write to 3C0H; this toggle is reset to index mode by each read from the Input Status 0 register (3DAH in color modes, 3BAH in monochrome modes). The AC Index and Data registers can also be written to at 3C1H on the EGA, but not on the VGA, so steer clear of that practice.
On the VGA, reading AC registers is a bit different from writing to them. The AC Data register can be read from 3C0H, and the AC register currently addressed by the AC Index register can be read from 3C1H; reading does not affect the state of the AC index/data toggle. Listing 8.2 illustrates reading from and writing to the AC registers. Finally, setting the start address registers (CRTC registers 0CH and 0DH) has its complications. As with the split screen registers, the start address registers must be set together and without interruption at a time when theres no chance of a partial setting being used for a frame. However, its a little more difficult to know when that might be the case with the start address registers than it was with the split screen registers, because its not clear when the start address is used.
You see, the start address is loaded into the EGAs or VGAs internal display memory pointer once per frame. The internal pointer is then advanced, byte-by-byte and line-by-line, until the end of the frame (with a possible resetting to zero if the split screen line is reached), and is then reloaded for the next frame. Thats straightforward enough; the real question is, Exactly when is the start address loaded?
In his excellent book Programmers Guide to PC Video Systems (Microsoft Press) Richard Wilton says that the start address is loaded at the start of the vertical sync pulse. (Wilton calls it vertical retrace, which can also be taken to mean vertical non-display time, but given that hes testing the vertical sync status bit in the Input Status 0 register, I assume he means that the start address is loaded at the start of vertical sync.) Consequently, he waits until the end of the vertical sync pulse to set the start address registers, confident that the start address wont take effect until the next frame.
Im sure Richard is right when it comes to the real McCoy IBM VGA and EGA, but Im less confident that every clone out there loads the start address at the start of vertical sync.
For that very reason, I generally advise people not to use horizontal smooth panning unless they can test their software on all the makes of display adapter it might run on. Ive used Richards approach in Listings 8.1 and 8.2, and so far as Ive seen it works fine, but be aware that there are potential, albeit unproven, hazards to relying on the setting of the start address registers to occur at a specific time in the frame.
The interaction of the start address registers and the Pel Panning register is worthy of note. After waiting for the end of vertical sync to set the start address in Listing 8.2, I wait for the start of the next vertical sync to set the Pel Panning register. Thats because the start address doesnt take effect until the start of the next frame, but the pel panning setting takes effect at the start of the next line; if we set the pel panning at the same time we set the start address, wed get a whole frame with the old start address and the new pel panning settings mixed together, causing the screen to jump. As with the split screen registers, its safest to set the Pel Panning register during non-display time. For maximum reliability, wed have interrupts off from the time we set the start address registers to the time we change the pel planning setting, to make sure an interrupt doesnt come in and cause us to miss the start of a vertical sync and thus get a mismatched pel panning/start address pair for a frame, although for modularity I havent done this in Listing 8.2. (Also, doing so would require disabling interrupts for much too long a time.)
What if you wanted to pan faster? Well, you could of course just move two pixels at a time rather than one; I assure you no one will ever notice when youre panning at a rate of 10 or more times per second.
|