abrash-black-book/23-06.md
2013-12-30 20:26:41 +11:00

106 lines
9.2 KiB
Markdown

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
23.1 I've 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 we're 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. Don't worry about the details right now; page flipping will
come up again, at considerably greater length, in later chapters.
------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
![](images/i.jpg) *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 won't help in true multitasking environments, which never let a program hog the entire CPU. This is one reason that pel panning, although indubitably flashy, isn't widely used and should be reserved for only those cases where it's absolutely necessary.*
------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Waiting for the sync pulse has the side effect of causing program
execution to synchronize to the VGA's 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
VGA's 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
672x384 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 {#Heading10}
Earlier, I said that any VGA that doesn't support the features and
functionality covered in this book can't properly be called VGA
compatible. I also noted that there are some exceptions, however, and
we've just come to the most prominent one. You see, all VGAs really
*are* compatible with the IBM VGA's 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 isn't 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 I'm aware are illustrated by the
sample program, and may in fact have caused you to see some glitches
when you ran Listing 23.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
it's difficult; that's one of the reasons that most commercial software
does not use these features, although a number of games do. The upshot
is that if you're 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 {#Heading11}
That pretty well covers the important points of the sample VGA program
in Listing 23.1. There are many VGA features we didn't 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
VGA's resources, and in general to give you an initial sense of what VGA
programming is like. Starting with the next chapter, we'll begin to
explore the VGA systematically, on a more detailed basis.
### The Macro Assembler {#Heading12}
The code in this book is written in both C and assembly. I think C is a
good development environment, but I believe that often the best code
(although not necessarily the easiest to write or the most reliable) is
written in assembly. This is especially true of graphics code for the
x86 family, given segments, the string instructions, and the asymmetric
and limited register set, and for real-time programming of a complex
board like the VGA, there's really no other choice for the lowest-level
code.
Before I'm deluged with protests from C devotees, let me add that the
majority of my productive work is done in C; no programmer is immune to
the laws of time, and C is simply a more time-efficient environment in
which to develop, particularly when working in a programming team. In
this book, however, we're after the *sine qua non* of PC
graphics—performance—and we can't get there from here without a fair
amount of assembly language.
Now that we know what the VGA looks like in broad strokes and have a
sense of what VGA programming is like, we can start looking at specific
areas in depth. In the next chapter, we'll take a look at the hardware
assistance the VGA provides the CPU during display memory access. There
are four latches and four ALUs in those chips, along with some useful
masks and comparators, and it's that hardware that's the difference
between sluggish performance and making the VGA get up and dance.