Previous Table of Contents Next

VGA and EGA Split-Screen Operation Don’t Mix

You must set the IS_VGA equate at the start of Listing 30.1 correctly for the adapter the code will run on in order for the program to perform properly. This equate determines how the upper bits of the split screen start scan line are set by SetSplitScreenRow. If IS_VGA is 0 (specifying an EGA target), then bit 8 of the split screen start scan line is set by programming the entire Overflow register to 1FH; this is hard-wired for the 350-scan-line modes of the EGA. If IS_VGA is 1 (specifying a VGA target), then bits 8 and 9 of the split screen start scan line are set by reading the registers they reside in, changing only the split-screen-related bits, and writing the modified settings back to their respective registers.

The VGA version of Listing 30.1 won’t work on an EGA, because EGA registers aren’t readable. The EGA version of Listing 30.1 won’t work on a VGA, both because VGA monitors require different vertical settings than EGA monitors and because the EGA version doesn’t set bit 9 of the split screen start scan line. In short, there is no way that I know of to support both VGA and EGA split screens with common code; separate drivers are required. This is one of the reasons that split screens are so rarely used in PC programming.

By the way, Listing 30.1 operates in mode 10H because that’s the highest-resolution mode the VGA and EGA share. That’s not the only mode the split screen works in, however. In fact, it works in all modes, as we’ll see later.

Setting the Split-Screen-Related Registers

Setting the split-screen-related registers is not as simple a matter as merely outputting the right values to the right registers; timing is also important. The split screen start scan line value is checked against the number of each scan line as that scan line is displayed, which means that the split screen start scan line potentially takes effect the moment it is set. In other words, if the screen is displaying scan line 15 and you set the split screen start to 16, that change will be picked up immediately and the split screen will start after the next scan line. This is markedly different from changes to the start address, which take effect only at the start of the next frame.

The instantly-effective nature of the split screen is a bit of a problem, not because the changed screen appears as soon as the new split screen start scan line is set—that seems to me to be an advantage—but because the changed screen can appear before the new split screen start scan line is set.

Remember, the split screen start scan line is spread out over two or three registers. What if the incompletely-changed value matches the current scan line after you’ve set one register but before you’ve set the rest? For one frame, you’ll see the split screen in a wrong place—possibly a very wrong place—resulting in jumping and flicker.

The solution is simple: Set the split screen start scan line at a time when it can’t possibly match the currently displayed scan line. The easy way to do that is to set it when there isn’t any currently displayed scan line—during vertical non-display time. One safe time that’s easy to find is the start of the vertical sync pulse, which is typically pretty near the middle of vertical non-display time, and that’s the approach I’ve followed in Listing 30.1. I’ve also disabled interrupts during the period when the split screen registers are being set. This isn’t absolutely necessary, but if it’s not done, there’s the possibility that an interrupt will occur between register sets and delay the later register sets until display time, again causing flicker.

One interesting effect of setting the split screen registers at the start of vertical sync is that it has the effect of synchronizing the program to the display adapter’s frame rate. No matter how fast the computer running Listing 30.1 may be, the split screen will move at a maximum rate of once per frame. This is handy for regulating execution speed over a wide variety of hardware performance ranges; however, be aware that the VGA supports 70 Hz frame rates in all non-480-scan-line modes, while the VGA in 480-scan-line-modes and the EGA in all color modes support 60 Hz frame rates.

The Problem with the EGA Split Screen

I mentioned earlier that the EGA’s split screen is a little buggy. How? you may well ask, particularly given that Listing 30.1 illustrates that the EGA split screen seems pretty functional.

The bug is this: The first scan line of the EGA split screen—the scan line starting at offset zero in display memory—is displayed not once but twice. In other words, the first line of split screen display memory, and only the first line, is replicated one unnecessary time, pushing all the other lines down by one.

That’s not a fatal bug, of course. In fact, if the first few scan lines are identical, it’s not even noticeable. The EGA’s split-screen bug can produce visible distortion given certain patterns, however, so you should try to make the top few lines identical (if possible) when designing split-screen images that might be displayed on EGAs, and you should in any case check how your split-screens look on both VGAs and EGAs.

I have an important caution here: Don’t count on the EGA’s split-screen bug; that is, don’t rely on the first scan line being doubled when you design your split screens. IBM designed and made the original EGA, but a lot of companies cloned it, and there’s no guarantee that all EGA clones copy the bug. It is a certainty, at least, that the VGA didn’t copy it.

There’s another respect in which the EGA is inferior to the VGA when it comes to the split screen, and that’s in the area of panning when the split screen is on. This isn’t a bug—it’s just one of the many areas in which the VGA’s designers learned from the shortcomings of the EGA and went the EGA one better.

Previous Table of Contents Next

Graphics Programming Black Book © 2001 Michael Abrash