Previous Table of Contents Next

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 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 setting
Alternatively, 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 OUT instruction
     OUT     DX,AL    ;AL contains Bit Mask register setting
which 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.

Previous Table of Contents Next

Graphics Programming Black Book © 2001 Michael Abrash