6.8 KiB
| title | author | date | isbn | publisher | category | chapter | pages |
|---|---|---|---|---|---|---|---|
| Michael Abrash's Graphics Programming Black Book, Special Edition | Michael Abrash | 1997-07-01 | 1576101746 | The Coriolis Group | Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development | 23 | 427-430 |
At the Core
A little background is necessary before we're ready to examine Listing 23.1. The VGA is built around four functional blocks, named the CRT Controller (CRTC), the Sequence Controller (SC), the Attribute Controller (AC), and the Graphics Controller (GC). The single-chip VGA could have been designed to treat the registers for all the blocks as one large set, addressed at one pair of I/O ports, but in the EGA, each of these blocks was a separate chip, and the legacy of EGA compatibility is why each of these blocks has a separate set of registers and is addressed at different I/O ports in the VGA.
Each of these blocks has a sizable complement of registers. It is not particularly important that you understand why a given block has a given register; all the registers together make up the programming interface, and it is the entire interface that is of interest to the VGA programmer. However, the means by which most VGA registers are addressed makes it necessary for you to remember which registers are in which blocks.
Most VGA registers are addressed as internally indexed registers. The internal address of the register is written to a given block's Index register, and then the data for that register is written to the block's Data register. For example, GC register 8, the Bit Mask register, is set to 0FFH by writing 8 to port 3CEH, the GC Index register, and then writing 0FFH to port 3CFH, the GC Data register. Internal indexing makes it possible to address the 9 GC registers through only two ports, and allows the entire VGA programming interface to be squeezed into fewer than a dozen ports. The downside is that two I/O operations are required to access most VGA registers.
The ports used to control the VGA are shown in Table 23.1. The CRTC, SC,
and GC Data registers are located at the addresses of their respective
Index registers plus one. However, the AC Index and Data registers are
located at the same address, 3C0H. The function of this port toggles on
every OUT to 3C0H, and resets to Index mode (in which the Index
register is programmed by the next OUT to 3C0H) on every read from
the Input Status 1 register (3DAH when the VGA is in a color mode,
| Register | Address |
|---|---|
| AC Index/Data register | 3C0H (write with toggle) |
| AC Index register | 3C0H (read) |
| AC Data register | 3C1H (read) |
| Miscellaneous Output register | 3C2H (write) |
| 3CCH (read) | |
| Input Status 0 register | 3C2H (read) |
| SC Index register | 3C4H (read/write) |
| SC Data register | 3C5H (read/write) |
| GC Index register | 3CEH (read/write) |
| GC Data register | 3CFH (read/write) |
| CRTC Index register | 3B4H/3D4H (read/write) |
| CRTC Data register | 3B5H/3D5H (read/write) |
| Input Status 1 register/AC Index/Data reset | 3 BAH/3DAH (read) |
| Feature Control | 3BAH/3DAH (write) |
| 3CAH (read) |
Table: Table 1.1 The Ports through which the VGA is controlled.
3BAH in monochrome modes). Note that all CRTC registers are addressed at either 3DXH or 3BXH, the former in color modes and the latter in monochrome modes. This provides compatibility with the register addressing of the now-vanished Color/Graphics Adapter and Monochrome Display Adapter.
The method used in the VGA BIOS to set registers is to point DX to the
desired Index register, load AL with the index, perform a byte OUT,
increment DX to point to the Data register (except in the case of the
AC, where DX remains the same), load AL with the desired data, and
perform a byte OUT. A handy shortcut is to point DX to the desired
Index register, load AL with the index, load AH with the data, and
perform a word OUT. Since the high byte of the OUT value goes to
port DX+1, this is equivalent to the first method but is faster.
However, this technique does not work for programming the AC Index and
Data registers; both AC registers are addressed at 3C0H, so two separate
byte OUTs must be used to program the AC. (Actually, word OUTs
to the AC do work in the EGA, but not in the VGA, so they shouldn't be
used.) As mentioned above, you must be sure which mode—Index or Data—the
AC is in before you do an OUT to 3C0H; you can read the Input Status
1 register at any time to force the AC to Index mode.
How safe is the word-OUT method of addressing VGA registers? I have,
in the past, run into adapter/computer combinations that had trouble
with word OUTs; however, all such problems I am aware of have been
fixed. Moreover, a great deal of graphics software now uses word
OUTs, so any computer or VGA that doesn't properly support word
OUTs could scarcely be considered a clone at all.
A speed tip: The setting of each chip's Index register remains the same until it is reprogrammed. This means that in cases where you are setting the same internal register repeatedly, you can set the Index register to point to that internal register once, then write to the Data register multiple times. For example, the Bit Mask register (GC register 8) is often set repeatedly inside a loop when drawing lines. The standard code for this is:
MOV DX,03CEH ;point to GC Index register MOV AL,8 ;internal index of Bit Mask register OUT DX,AX ;AH contains Bit Mask register settingAlternatively, the GC Index register could initially be set to point to the Bit Mask register with
MOV DX,03CEH ;point to GC Index register MOV AL,8 ;internal index of Bit Mask register OUT DX,AL ;set GC Index register INC DX ;point to GC Data register>and then the Bit Mask register could be set repeatedly with the byte-size
OUTinstructionOUT DX,AL ;AL contains Bit Mask register settingwhich is generally faster (and never slower) than a word-sized
OUT, and which does not require AH to be set, freeing up a register. Of course, this method only works if the GC Index register remains unchanged throughout the loop.
