102 lines
7.4 KiB
Markdown
102 lines
7.4 KiB
Markdown
#### VGA and EGA Split-Screen Operation Don't Mix {#Heading5}
|
|
|
|
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 {#Heading6}
|
|
|
|
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 {#Heading7}
|
|
|
|
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.
|