335 lines
19 KiB
HTML
335 lines
19 KiB
HTML
<HTML>
|
|
<HEAD>
|
|
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
|
<META NAME="Author" CONTENT="Joshua Neal">
|
|
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
|
|
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
|
|
<TITLE>VGA/SVGA Video Programming--Accessing the VGA Display Memory</TITLE>
|
|
</HEAD>
|
|
<BODY>
|
|
|
|
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#detect">Detecting</A>
|
|
<A HREF="#mapping">Mapping</A> <A HREF="#address">Addressing</A> <A HREF="#manip">Manipulating</A>
|
|
<A HREF="#read">Reading</A> <A HREF="#write">Writing</A> <A HREF="vga.htm#general">Back</A>
|
|
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
|
Page</B></CENTER>
|
|
|
|
<CENTER>Accessing the VGA Display Memory
|
|
<HR WIDTH="100%"></CENTER>
|
|
|
|
<UL>
|
|
<LI>
|
|
<A HREF="#intro">Introduction</A> -- gives an overview of the VGA display
|
|
memory.</LI>
|
|
|
|
<LI>
|
|
<A HREF="#detect">Detecting the Amount of Display Memory on the Adapter</A>
|
|
-- details how to determine the amount of memory present on the VGA.</LI>
|
|
|
|
<LI>
|
|
<A HREF="#mapping">Mapping of Display Memory into CPU Address Space</A>
|
|
-- details how to control the location and size of the memory aperture.</LI>
|
|
|
|
<LI>
|
|
<A HREF="#address">Host Address to Display Address Translation</A> -- detail
|
|
how the VGA hardware maps a host access to a display memory access</LI>
|
|
|
|
<LI>
|
|
<A HREF="#manip">Manipulating Display Memory</A> -- Details on reading
|
|
and writing to VGA memory</LI>
|
|
|
|
<UL>
|
|
<LI>
|
|
<A HREF="#read">Reading from Display Memory</A> -- Details the hardware
|
|
mechanisms used when reading display memory.</LI>
|
|
|
|
<LI>
|
|
<A HREF="#write">Writing to Display Memory</A> -- Details the hardware
|
|
mechanisms used when writing display memory.</LI>
|
|
</UL>
|
|
</UL>
|
|
<A NAME="intro"></A><B>Introduction</B>
|
|
<BR> The standard VGA hardware
|
|
contains up to 256K of onboard display memory. While it would seem logical
|
|
that this memory would be directly available to the processor, this is
|
|
not the case. The host CPU accesses the display memory through a window
|
|
of up to 128K located in the high memory area. (Note that many SVGA chipsets
|
|
provide an alternate method of accessing video memory directly, called
|
|
a Linear Frame Buffer.) Thus in order to be able to access display memory
|
|
you must deal with registers that control the mapping into host address
|
|
space. To further complicate things, the VGA hardware provides support
|
|
for memory models similar to that used by the monochrome, CGA, EGA, and
|
|
MCGA adapters. In addition, due to the way the VGA handles 16 color modes,
|
|
additional hardware is included that can speed access immensely. Also,
|
|
hardware is present that allows the programer to rapidly copy data from
|
|
one area of display memory to another. While it is quite complicated to
|
|
understand, learning to utilize the VGA's hardware at a low level can vastly
|
|
improve performance. Many game programmers utilize the BIOS mode 13h, simply
|
|
because it offers the simplest memory model and doesn't require having
|
|
to deal with the VGA's registers to draw pixels. However, this same decision
|
|
limits them from being able to use the infamous X modes, or higher resolution
|
|
modes.
|
|
|
|
<P><A NAME="detect"></A><B>Detecting the Amount of Display Memory on the
|
|
Adapter</B>
|
|
<BR><B> </B>Most VGA cards in
|
|
existence have 256K on board; however there is the possibility that some
|
|
VGA boards have less. To actually determine further if the card has 256K
|
|
one must actually write to display memory and read back values. If RAM
|
|
is not present in a location, then the value read back will not equal the
|
|
value written. It is wise to utilize multiple values when doing this, as
|
|
the undefined result may equal the value written. Also, the card may alias
|
|
addresses, causing say the same 64K of RAM to appear 4 times in the 256K
|
|
address space, thus it is wise to change an address and see if the change
|
|
is reflected anywhere else in display memory. In addition, the card may
|
|
buffer one location of video memory in the chipset, making it appear that
|
|
there is RAM at an address where there is none present, so you may have
|
|
to read or write to a second location to clear the buffer. Not that if
|
|
the <A HREF="seqreg.htm#04">Extended Memory</A> field is not set to 1,
|
|
the adapter appears to only have 64K onboard, thus this bit should be set
|
|
to 1 before attempting to determine the memory size.
|
|
|
|
<P><A NAME="mapping"></A><B>Mapping of Display Memory into CPU Address
|
|
Space</B>
|
|
<BR> The first element that defines
|
|
this mapping is whether or not the VGA decodes accesses from the CPU. This
|
|
is controlled by the <A HREF="extreg.htm#3CCR3C2W">RAM Enable</A> field.
|
|
If display memory decoding is disabled, then the VGA hardware ignores writes
|
|
to its address space. The address range that the VGA hardware decodes is
|
|
based upon the <A HREF="graphreg.htm#06">Memory Map Select</A> field. The
|
|
following table shows the address ranges in absolute 32-bit form decoded
|
|
for each value of this field:
|
|
<UL>
|
|
<LI>
|
|
00 -- A0000h-BFFFFh -- 128K</LI>
|
|
|
|
<LI>
|
|
01 -- A0000h-AFFFFh -- 64K</LI>
|
|
|
|
<LI>
|
|
10 -- B0000h-B7FFFh -- 32K</LI>
|
|
|
|
<LI>
|
|
11 -- B8000h-BFFFFh -- 32K</LI>
|
|
</UL>
|
|
Note -- It would seem that by setting the <A HREF="graphreg.htm#06">Memory
|
|
Map Select</A> field to 00 and then using planar memory access that you
|
|
could gain access to more than 256K of memory on an SVGA card. However,
|
|
I have found that some cards simply mirror the first 64K twice within the
|
|
128K address space. This memory map is intended for use in the Chain Odd/Even
|
|
modes, eliminating the need to use the Odd/Even Page Select field. Also
|
|
I have found that MS-DOS memory managers don't like this very much and
|
|
are likely to lock up the system if configured to use the area from B0000h-B7FFFh
|
|
for loading device drivers high.
|
|
|
|
<P><A NAME="address"></A><B>Host Address to Display Address Translation</B>
|
|
<BR> The most complicated part
|
|
of accessing display memory involves the translation between a host address
|
|
and a display memory address. Internally, the VGA has a 64K 32-bit memory
|
|
locations. These are divided into four 64K bit planes. Because the VGA
|
|
was designed for 8 and 16 bit bus systems, and due to the way the Intel
|
|
chips handle memory accesses, it is impossible for the host CPU to access
|
|
the bit planes directly, instead relying on I/O registers to make part
|
|
of the memory accessible. The most straightforward display translation
|
|
is where a host access translates directly to a display memory address.
|
|
What part of the particular 32-bit memory location is dependent on certain
|
|
registers and is discussed in more detail in Manipulating Display Memory
|
|
below. The VGA has three modes for addressing, Chain 4, Odd/Even mode,
|
|
and normal mode:
|
|
<UL>
|
|
<LI>
|
|
Chain 4: This mode is used for MCGA emulation in the 320x200 256-color
|
|
mode. The address is mapped to memory MOD 4 (shifted right 2 places.)</LI>
|
|
</UL>
|
|
<B><More to be added here.></B>
|
|
|
|
<P><A NAME="manip"></A><B>Manipulating Display Memory</B>
|
|
<BR> The VGA hardware contains
|
|
hardware that can perform bit manipulation on data and allow the host to
|
|
operate on all four display planes in a single operation. These features
|
|
are fairly straightforward, yet complicated enough that most VGA programmers
|
|
choose to ignore them. This is unfortunate, as properly utilization of
|
|
these registers is crucial to programming the VGA's 16 color modes. Also,
|
|
knowledge of this functionality can in many cases enhance performance in
|
|
other modes including text and 256 color modes. In addition to normal read
|
|
and write operations the VGA hardware provides enhanced operations such
|
|
as the ability to perform rapid comparisons, to write to multiple planes
|
|
simultaneously, and to rapidly move data from one area of display memory
|
|
to another, faster logical operations (AND/OR/XOR) as well as bit rotation
|
|
and masking.
|
|
|
|
<P><A NAME="read"></A><B>Reading from Display Memory</B>
|
|
<BR> The VGA hardware has two
|
|
read modes, selected by the <A HREF="graphreg.htm#05">Read Mode</A> field.
|
|
The first is a straightforward read of one or more consecutive bytes (depending
|
|
on whether a byte, word or dword operation is used) from one bit plane.
|
|
The value of the <A HREF="graphreg.htm#04">Read Map Select</A> field is
|
|
the page that will be read from. The second read mode returns the result
|
|
of a comparison of the display memory and the <A HREF="graphreg.htm#02">Color
|
|
Compare</A> field and masked by the <A HREF="graphreg.htm#07">Color Don't
|
|
Care</A> field. This mode which can be used to rapidly perform up to 32
|
|
pixel comparisons in one operation in the planar video modes, helpful for
|
|
the implementation of fast flood-fill routines. A read from display memory
|
|
also loads a 32 bit latch register, one byte from each plane. This latch
|
|
register, is not directly accessible from the host CPU; rather it can be
|
|
used as data for the various write operations. The latch register retains
|
|
its value until the next read and thus may be used with more than one write
|
|
operation.
|
|
<BR> The two read modes, simply called
|
|
Read Mode 0-1 based on the value of the <A HREF="graphreg.htm#05">Read
|
|
Mode</A> field are:
|
|
<UL>
|
|
<LI>
|
|
<B>Read Mode 0:</B></LI>
|
|
|
|
<BR> Read Mode 0 is used to read one
|
|
byte from a single plane of display memory. The plane read is the value
|
|
of the <A HREF="graphreg.htm#04">Read Map Select</A> field. In order to
|
|
read a single pixel's value in planar modes, four read operations must
|
|
be performed, one for each plane. If more than one bytes worth of data
|
|
is being read from the screen it is recommended that you read it a plane
|
|
at a time instead of having to perform four I/O operations to the <A HREF="graphreg.htm#04">Read
|
|
Map Select</A> field for each byte, as this will allow the use of faster
|
|
string copy instructions and reduce the number I/O operations performed.
|
|
<LI>
|
|
<B>Read Mode 1:</B></LI>
|
|
|
|
<BR> Read Mode 1 is used to perform
|
|
comparisons against a reference color, specified by the <A HREF="graphreg.htm#02">Color
|
|
Compare</A> field. If a bit is set in the <A HREF="graphreg.htm#07">Color
|
|
Don't Care</A> field then the corresponding color plane is considered for
|
|
by the comparison, otherwise it is ignored. Each bit in the returned result
|
|
represents one comparison between the reference color from the <A HREF="graphreg.htm#02">Color
|
|
Compare</A> field, with the bit being set if the comparison is true. This
|
|
mode is mainly used by flood fill algorithms that fill an area of a specific
|
|
color, as it requires 1/4 the number of reads to determine the area that
|
|
needs to be filled in addition to the additional work done by the comparison.
|
|
Also an efficient "search and replace" operation that replaces one color
|
|
with another can be performed when this mode is combined with Write Mode
|
|
3.</UL>
|
|
<A NAME="write"></A><B>Writing to Display Memory</B>
|
|
<BR> The VGA has four write modes,
|
|
selected by the <A HREF="graphreg.htm#05">Write Mode</A> field. This controls
|
|
how the write operation and host data affect the display memory. The VGA,
|
|
depending on the <A HREF="graphreg.htm#05">Write Mode</A> field performs
|
|
up to five distinct operations before the write affects display memory.
|
|
Note that not all write modes use all of pipelined stages in the write
|
|
hardware, and others use some of the pipelined stages in different ways.
|
|
<BR> The first of these allows
|
|
the VGA hardware to perform a bitwise rotation on the data written from
|
|
the host. This is accomplished via a barrel rotator that rotates the bits
|
|
to the right by the number of positions specified by the <A HREF="graphreg.htm#03">Rotate
|
|
Count</A> field. This performs the same operation as the 8086 ROR instruction,
|
|
shifting bits to the right (from bit 7 towards bit 0.) with the bit shifted
|
|
out of position 0 being "rolled" into position 7. Note that if the rotate
|
|
count field is zero then no rotation is performed.
|
|
<BR> The second uses the <A HREF="graphreg.htm#01">Enable
|
|
Set/Reset</A> and <A HREF="graphreg.htm#00">Set/Reset</A> fields. These
|
|
fields can provide an additional data source in addition to the data written
|
|
and the latched value from the last read operation performed. Normally,
|
|
data from the host is replicated four times, one for each plane. In this
|
|
stage, a 1 bit in the <A HREF="graphreg.htm#01">Enable Set/Reset</A> field
|
|
will cause the corresponding bit plane to be replaced by the bit value
|
|
in the corresponding <A HREF="graphreg.htm#00">Set/Reset</A> field location,
|
|
replicated 8 times to fill the byte, giving it either the value 00000000b
|
|
or 11111111b. If the <A HREF="graphreg.htm#01">Enable Set/Reset</A> field
|
|
for a given plane is 0 then the host data byte is used instead. Note that
|
|
in some write modes, the host data byte is used for other purposes, and
|
|
the set/reset register is always used as data, and in other modes the set/reset
|
|
mechanism is not used at all.
|
|
<BR> The third stage performs logical operations
|
|
between the host data, which has been split into four planes and is now
|
|
32-bits wide, and the latch register, which provides a second 32-bit operand.
|
|
The <A HREF="graphreg.htm#03">Logical Operation</A> field selects the operation
|
|
that this stage performs. The four possibilities are: NOP (the host data
|
|
is passed directly through, performing no operation), AND (the data is
|
|
logically ANDed with the latched data.), OR (the data is logically ORed
|
|
with the latched data), and XOR (the data is logically XORed with the latched
|
|
data.) The result of this operation is then passed on. whilst the latched
|
|
data remains unchanged, available for use in successive operations.
|
|
<BR> In the fourth stage, individual
|
|
bits may be selected from the result or copied from the latch register.
|
|
Each bit of the <A HREF="graphreg.htm#08">Bit Mask</A> field determines
|
|
whether the corresponding bits in each plane are the result of the previous
|
|
step or are copied directly from the latch register. This allows the host
|
|
CPU to modify only a single bit, by first performing a dummy read to fill
|
|
the latch register
|
|
<BR> The fifth stage allows specification
|
|
of what planes, if any a write operation affects, via the <A HREF="seqreg.htm#02">Memory
|
|
Plane Write Enable</A> field. The four bits in this field determine whether
|
|
or not the write affects the corresponding plane If the a planes bit is
|
|
1 then the data from the previous step will be written to display memory,
|
|
otherwise the display buffer location in that plane will remain unchanged.
|
|
<BR> The four write modes, of
|
|
which the current one is set by writing to the <A HREF="graphreg.htm#05">Write
|
|
Mode</A> field The four write modes, simply called write modes 0-3, based
|
|
on the value of the <A HREF="graphreg.htm#05">Write Mode</A> field are:
|
|
<UL>
|
|
<LI>
|
|
<B>Write Mode 0:</B></LI>
|
|
|
|
<BR> Write Mode 0 is the standard
|
|
and most general write mode. While the other write modes are designed to
|
|
perform a specific task, this mode can be used to perform most tasks as
|
|
all five operations are performed on the data. The data byte from the host
|
|
is first rotated as specified by the <A HREF="graphreg.htm#03">Rotate Count</A>
|
|
field, then is replicated across all four planes. Then the <A HREF="graphreg.htm#01">Enable
|
|
Set/Reset</A> field selects which planes will receive their values from
|
|
the host data and which will receive their data from that plane's <A HREF="graphreg.htm#00">Set/Reset</A>
|
|
field location. Then the operation specified by the <A HREF="graphreg.htm#03">Logical
|
|
Operation</A> field is performed on the resulting data and the data in
|
|
the read latches. The <A HREF="graphreg.htm#08">Bit Mask</A> field is then
|
|
used to select between the resulting data and data from the latch register.
|
|
Finally, the resulting data is written to the display memory planes enabled
|
|
in the <A HREF="seqreg.htm#02">Memory Plane Write Enable</A> field.
|
|
<LI>
|
|
<B>Write Mode 1:</B></LI>
|
|
|
|
<BR> Write Mode 1 is used to
|
|
transfer the data in the latches register directly to the screen, affected
|
|
only by the <A HREF="seqreg.htm#02">Memory Plane Write Enable</A> field.
|
|
This can facilitate rapid transfer of data on byte boundaries from one
|
|
area of video memory to another or filling areas of the display with a
|
|
pattern of 8 pixels. When Write Mode 0 is used with the <A HREF="graphreg.htm#08">Bit
|
|
Mask</A> field set to 00000000b the operation of the hardware is identical
|
|
to this mode, although it is entirely possible that this mode is faster
|
|
on some cards.
|
|
<LI>
|
|
<B>Write Mode 2:</B></LI>
|
|
|
|
<BR> Write Mode 2 is used to
|
|
unpack a pixel value packed into the lower 4 bits of the host data byte
|
|
into the 4 display planes. In the byte from the host, the bit representing
|
|
each plane will be replicated across all 8 bits of the corresponding planes.
|
|
Then the operation specified by the <A HREF="graphreg.htm#03">Logical Operation</A>
|
|
field is performed on the resulting data and the data in the read latches.
|
|
The <A HREF="graphreg.htm#08">Bit Mask</A> field is then used to select
|
|
between the resulting data and data from the latch register. Finally, the
|
|
resulting data is written to the display memory planes enabled in the <A HREF="seqreg.htm#02">Memory
|
|
Plane Write Enable</A> field.
|
|
<LI>
|
|
<B>Write Mode 3:</B></LI>
|
|
|
|
<BR><B> </B>Write Mode 3 is used
|
|
when the color written is fairly constant but the <A HREF="graphreg.htm#08">Bit
|
|
Mask</A> field needs to be changed frequently, such as when drawing single
|
|
color lines or text. The value of the <A HREF="graphreg.htm#00">Set/Reset</A>
|
|
field is expanded as if the <A HREF="graphreg.htm#01">Enable Set/Reset</A>
|
|
field were set to 1111b, regardless of its actual value. The host data
|
|
is first rotated as specified by the <A HREF="graphreg.htm#03">Rotate Count</A>
|
|
field, then is ANDed with the <A HREF="graphreg.htm#08">Bit Mask</A> field.
|
|
The resulting value is used where the <A HREF="graphreg.htm#08">Bit Mask</A>
|
|
field normally would be used, selecting data from either the expansion
|
|
of the <A HREF="graphreg.htm#00">Set/Reset</A> field or the latch register.
|
|
Finally, the resulting data is written to the display memory planes enabled
|
|
in the <A HREF="seqreg.htm#02">Memory Plane Write Enable</A> field.</UL>
|
|
Notice: All trademarks used or referred to on this page are the property
|
|
of their respective owners.
|
|
<BR>All pages are Copyright © 1997, 1998, J. D. Neal, except where
|
|
noted. Permission for utilization and distribution is subject to the terms
|
|
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
|
|
<BR>
|
|
<BR>
|
|
</BODY>
|
|
</HTML>
|