# VGA/SVGA Video Programming--CRT Controller Registers
Pure VGA/SVGA hardware programming (registers, identification, and other low-level stuff.)
Author: Joshua Neal
Keywords: VGA SVGA hardware video programming

Home Back

Hardware Level VGA and SVGA Video Programming Information Page
CRT Controller Registers

The CRT Controller (CRTC) Registers are accessed via a pair of registers, the CRTC Address Register and the CRTC Data Register. See the Accessing the VGA Registers section for more details. The Address Register is located at port 3x4h and the Data Register is located at port 3x5h. The value of the x in 3x4h and 3x5h is dependent on the state of the Input/Output Address Select field, which allows these registers to be mapped at 3B4h-3B5h or 3D4h-3D5h. Note that when the CRTC Registers Protect Enable field is set to 1, writing to register indexes 00h-07h is prevented, with the exception of the Line Compare field of the Overflow Register.

- Index 00h -- Horizontal Total Register
- Index 01h -- End Horizontal Display Register
- Index 02h -- Start Horizontal Blanking Register
- Index 03h -- End Horizontal Blanking Register
- Index 04h -- Start Horizontal Retrace Register
- Index 05h -- End Horizontal Retrace Register
- Index 06h -- Vertical Total Register
- Index 07h -- Overflow Register
- Index 08h -- Preset Row Scan Register
- Index 09h -- Maximum Scan Line Register
- Index 0Ah -- Cursor Start Register
- Index 0Bh -- Cursor End Register
- Index 0Ch -- Start Address High Register
- Index 0Dh -- Start Address Low Register
- Index 0Eh -- Cursor Location High Register
- Index 0Fh -- Cursor Location Low Register
- Index 10h -- Vertical Retrace Start Register
- Index 11h -- Vertical Retrace End Register
- Index 12h -- Vertical Display End Register
- Index 13h -- Offset Register
- Index 14h -- Underline Location Register
- Index 15h -- Start Vertical Blanking Register
- Index 16h -- End Vertical Blanking
- Index 17h -- CRTC Mode Control Register
- Index 18h -- Line Compare Register

Horizontal Total Register (Index 00h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Horizontal Total

- Horizontal Total
This field is used to specify the number of character clocks per scan line. This field, along with the dot rate selected, controls the horizontal refresh rate of the VGA by specifying the amount of time one scan line takes. This field is not programmed with the actual number of character clocks, however. Due to timing factors of the VGA hardware (which, for compatibility purposes has been emulated by VGA compatible chipsets), the actual horizontal total is 5 character clocks more than the value stored in this field, thus one needs to subtract 5 from the actual horizontal total value desired before programming it into this register.

End Horizontal Display Register (Index 01h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
End Horizontal Display

- End Horizontal Display
This field is used to control the point that the sequencer stops outputting pixel values from display memory, and sequences the pixel value specified by the Overscan Palette Index field for the remainder of the scan line. The overscan begins the character clock after the the value programmed into this field. This register should be programmed with the number of character clocks in the active display - 1. Note that the active display may be affected by the Display Enable Skew field.

Start Horizontal Blanking Register (Index 02h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Start Horizontal Blanking

- Start Horizontal Blanking
This field is used to specify the character clock at which the horizontal blanking period begins. During the horizontal blanking period, the VGA hardware forces the DAC into a blanking state, where all of the intensities output are at minimum value, no matter what color information the attribute controller is sending to the DAC. This field works in conjunction with the End Horizontal Blanking field to specify the horizontal blanking period. Note that the horizontal blanking can be programmed to appear anywhere within the scan line, as well as being programmed to a value greater than the Horizontal Total field preventing the horizontal blanking from occurring at all.

End Horizontal Blanking Register (Index 03h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
EVRA | Display Enable Skew | End Horizontal Blanking

- EVRA -- Enable Vertical Retrace Access
This field was used in the IBM EGA to provide access to the light pen input values as the light pen registers were mapped over CRTC indexes 10h-11h. The VGA lacks capability for light pen input, thus this field is normally forced to 1 (although always writing it as 1 might be a good idea for compatibility) , which in the EGA would enable access to the vertical retrace fields instead of the light pen fields.
- Display Enable Skew
This field affects the timings of the display enable circuitry in the VGA. The value of this field is the number of character clocks that the display enable "signal" is delayed. In all the VGA/SVGA chipsets I've tested, including a PS/2 VGA this field is always programmed to 0. Programming it to non-zero values results in the overscan being displayed over the number of characters programmed into this field at the beginning of the scan line, as well as the end of the active display being shifted the number of characters programmed into this field. The characters that extend past the normal end of the active display can be garbled in certain circumstances that is dependent on the particular VGA implementation. According to documentation from IBM, "This skew control is needed to provide sufficient time for the CRT controller to read a character and attribute code from the video buffer, to gain access to the character generator, and go through the Horizontal PEL Panning register in the attribute controller. Each access requires the 'display enable' signal to be skewed one character clock so that the video output is synchronized with the horizontal and vertical retrace signals." as well as "Note: Character skew is not adjustable on the Type 2 video and the bits are ignored; however, programs should set these bits for the appropriate skew to maintain compatibility." This may be required for some early IBM VGA implementations or may be simply an unused "feature" carried over along with its register description from the IBM EGA implementations that require the use of this field.
- End Horizontal Blanking
This contains bits 4-0 of the End Horizontal Blanking field which specifies the end of the horizontal blanking period. Bit 5 is located After the period has begun as specified by the Start Horizontal Blanking field, the 6-bit value of this field is compared against the lower 6 bits of the character clock. When a match occurs, the horizontal blanking signal is disabled. This provides from 1 to 64 character clocks although some implementations may match in the character clock specified by the Start Horizontal Blanking field, in which case the range is 0 to 63. Note that if blanking extends past the end of the scan line, it will end on the first match of this field on the next scan line.

Start Horizontal Retrace Register (Index 04h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Start Horizontal Retrace

- Start Horizontal Retrace
This field specifies the character clock at which the VGA begins sending the horizontal synchronization pulse to the display which signals the monitor to retrace back to the left side of the screen. The end of this pulse is controlled by the End Horizontal Retrace field. This pulse may appear anywhere in the scan line, as well as set to a position beyond the Horizontal Total field which effectively disables the horizontal synchronization pulse.

End Horizontal Retrace Register (Index 05h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
EHB5 | Horiz. Retrace Skew | End Horizontal Retrace

- EHB5 -- End Horizontal Blanking (bit 5)
This contains bit 5 of the End Horizontal Blanking field. See the End Horizontal Blanking Register for details.
- Horiz. Retrace Skew -- Horizontal Retrace Skew
This field delays the start of the horizontal retrace period by the number of character clocks equal to the value of this field. From observation, this field is programmed to 0, with the exception of the 40 column text modes where this field is set to 1. The VGA hardware simply acts as if this value is added to the Start Horizontal Retrace field. According to IBM documentation, "For certain modes, the 'horizontal retrace' signal takes up the entire blanking interval. Some internal timings are generated by the falling edge of the 'horizontal retrace' signal. To ensure that the signals are latched properly, the 'retrace' signal is started before the end of the 'display enable' signal and then skewed several character clock times to provide the proper screen centering." This does not appear to be the case, leading me to believe this is yet another holdout from the IBM EGA implementations that do require the use of this field.
- End Horizontal Retrace
This field specifies the end of the horizontal retrace period, which begins at the character clock specified in the Start Horizontal Retrace field. The horizontal retrace signal is enabled until the lower 5 bits of the character counter match the 5 bits of this field. This provides for a horizontal retrace period from 1 to 32 character clocks. Note that some implementations may match immediately instead of 32 clocks away, making the effective range 0 to 31 character clocks.

Vertical Total Register (Index 06h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Vertical Total

Vertical Total
This contains the lower 8 bits of the Vertical Total field. Bits 9-8 of this field are located in the Overflow Register. This field determines the number of scanlines in the active display and thus the length of each vertical retrace. This field contains the value of the scanline counter at the beginning of the last scanline in the vertical period.

Overflow Register (Index 07h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
VRS9 | VDE9 | VT9 | LC8 | SVB8 | VRS8 | VDE8 | VT8

- VRS9 -- Vertical Retrace Start (bit 9)
Specifies bit 9 of the Vertical Retrace Start field. See the Vertical Retrace Start Register for details.
- VDE9 -- Vertical Display End (bit9)
Specifies bit 9 of the Vertical Display End field. See the Vertical Display End Register for details.
- VT9 -- Vertical Total (bit 9)
Specifies bit 9 of the Vertical Total field. See the Vertical Total Register for details.
- LC8 -- Line Compare (bit 8)
Specifies bit 8 of the Line Compare field. See the Line Compare Register for details.
- SVB8 -- Start Vertical Blanking (bit 8)
Specifies bit 8 of the Start Vertical Blanking field. See the Start Vertical Blanking Register for details.
- VRS8 -- Vertical Retrace Start (bit 8)
Specifies bit 8 of the Vertical Retrace Start field. See the Vertical Retrace Start Register for details.
- VDE8 -- Vertical Display End (bit 8)
Specifies bit 8 of the Vertical Display End field. See the Vertical Display End Register for details.
- VT8 -- Vertical Total (bit 8)
Specifies bit 8 of the Vertical Total field. See the Vertical Total Register for details.

Preset Row Scan Register (Index 08h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
| Byte Panning | Preset Row Scan

- Byte Panning
The value of this field is added to the Start Address Register when calculating the display memory address for the upper left hand pixel or character of the screen. This allows for a maximum shift of 15, 31, or 35 pixels without having to reprogram the Start Address Register.
- Preset Row Scan
This field is used when using text mode or any mode with a non-zero Maximum Scan Line field to provide for more precise vertical scrolling than the Start Address Register provides. The value of this field specifies how many scan lines to scroll the display upwards. Valid values range from 0 to the value of the Maximum Scan Line field. Invalid values may cause undesired effects and seem to be dependent upon the particular VGA implementation.

Maximum Scan Line Register (Index 09h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
SD | LC9 | SVB9 | Maximum Scan Line

SD -- Scan Doubling
"When this bit is set to 1, 200-scan-line video data is converted to 400-scan-line output. To do this, the clock in the row scan counter is divided by 2, which allows the 200-line modes to be displayed as 400 lines on the display (this is called double scanning; each line is displayed twice). When this bit is set to 0, the clock to the row scan counter is equal to the horizontal scan rate."
- LC9 -- Line Compare (bit 9)
Specifies bit 9 of the Line Compare field. See the Line Compare Register for details.
- SVB9 -- Start Vertical Blanking (bit 9)
Specifies bit 9 of the Start Vertical Blanking field. See the Start Vertical Blanking Register for details.
- Maximum Scan Line
In text modes, this field is programmed with the character height - 1 (scan line numbers are zero based.) In graphics modes, a non-zero value in this field will cause each scan line to be repeated by the value of this field + 1.

Cursor Start Register (Index 0Ah)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
|  | CD | Cursor Scan Line Start

- CD -- Cursor Disable
This field controls whether or not the text-mode cursor is displayed. Values are:

- 0 -- Cursor Enabled
- 1 -- Cursor Disabled

- Cursor Scan Line Start
This field controls the appearance of the text-mode cursor by specifying the scan line location within a character cell at which the cursor should begin, with the top-most scan line in a character cell being 0 and the bottom being with the value of the Maximum Scan Line field.

Cursor End Register (Index 0Bh)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
| Cursor Skew | Cursor Scan Line End

- CSK -- Cursor Skew
This field was necessary in the EGA to synchronize the cursor with internal timing. In the VGA it basically is added to the cursor location. In some cases when this value is non-zero and the cursor is near the left or right edge of the screen, the cursor will not appear at all, or a second cursor above and to the left of the actual one may appear. This behavior may not be the same on all VGA compatible adapter cards.
- Cursor Scan Line End
This field controls the appearance of the text-mode cursor by specifying the scan line location within a character cell at which the cursor should end, with the top-most scan line in a character cell being 0 and the bottom being with the value of the Maximum Scan Line field. If this field is less than the Cursor Scan Line Start field, the cursor is not drawn. Some graphics adapters, such as the IBM EGA display a split-block cursor instead.

Start Address High Register (Index 0Ch)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Start Address High

- Start Address High
This contains specifies bits 15-8 of the Start Address field. See the Start Address Low Register for details.

Start Address Low Register (Index 0Dh)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Start Address Low

- Start Address Low
This contains the bits 7-0 of the Start Address field. The upper 8 bits are specified by the Start Address High Register. The Start Address field specifies the display memory address of the upper left pixel or character of the screen. Because the standard VGA has a maximum of 256K of memory, and memory is accessed 32 bits at a time, this 16-bit field is sufficient to allow the screen to start at any memory address. Normally this field is programmed to 0h, except when using virtual resolutions, paging, and/or split-screen operation. Note that the VGA display will wrap around in display memory if the starting address is too high. (This may or may not be desirable, depending on your intentions.)

Cursor Location High Register (Index 0Eh)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Cursor Location High

- Cursor Location High
This field specifies bits 15-8 of the Cursor Location field. See the Cursor Location Low Register for details.

Cursor Location Low Register (Index 0Fh)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Cursor Location Low

- Cursor Location Low
This field specifies bits 7-0 of the Cursor Location field. When the VGA hardware is displaying text mode and the text-mode cursor is enabled, the hardware compares the address of the character currently being displayed with sum of value of this field and the sum of the Cursor Skew field. If the values equal then the scan lines in that character specified by the Cursor Scan Line Start field and the Cursor Scan Line End field are replaced with the foreground color.

Vertical Retrace Start Register (Index 10h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Vertical Retrace Start

- Vertical Retrace Start
This field specifies bits 7-0 of the Vertical Retrace Start field. Bits 9-8 are located in the Overflow Register. This field controls the start of the vertical retrace pulse which signals the display to move up to the beginning of the active display. This field contains the value of the vertical scanline counter at the beginning of the first scanline where the vertical retrace signal is asserted.

Vertical Retrace End Register (Index 11h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Protect | Bandwidth |  |  | Vertical Retrace End

- Protect -- CRTC Registers Protect Enable
This field is used to protect the video timing registers from being changed by programs written for earlier graphics chipsets that attempt to program these registers with values unsuitable for VGA timings. When this field is set to 1, the CRTC register indexes 00h-07h ignore write access, with the exception of bit 4 of the Overflow Register, which holds bit 8 of the Line Compare field.
- Bandwidth -- Memory Refresh Bandwidth
Nearly all video chipsets include a few registers that control memory, bus, or other timings not directly related to the output of the video card. Most VGA/SVGA implementations ignore the value of this field; however, in the least, IBM VGA adapters do utilize it and thus for compatibility with these chipsets this field should be programmed. This register is used in the IBM VGA hardware to control the number of DRAM refresh cycles per scan line. The three refresh cycles per scanline is appropriate for the IBM VGA horizontal frequency of approximately 31.5 kHz. For horizontal frequencies greater than this, this setting will work as the DRAM will be refreshed more often. However, refreshing not often enough for the DRAM can cause memory loss. Thus at some point slower than 31.5 kHz the five refresh cycle setting should be used. At which particular point this should occur, would require better knowledge of the IBM VGA's schematics than I have available. According to IBM documentation, "Selecting five refresh cycles allows use of the VGA chip with 15.75 kHz displays." which isn't really enough to go by unless the mode you are defining has a 15.75 kHz horizontal frequency.
- Vertical Retrace End
This field determines the end of the vertical retrace pulse, and thus its length. This field contains the lower four bits of the vertical scanline counter at the beginning of the scanline immediately after the last scanline where the vertical retrace signal is asserted.

Vertical Display End Register (Index 12h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Vertical Display End

- Vertical Display End
This contains the bits 7-0 of the Vertical Display End field. Bits 9-8 are located in the Overflow Register. The field contains the value of the vertical scanline counter at the beggining of the scanline immediately after the last scanline of active display.

Offset Register (Index 13h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Offset

- Offset
This field specifies the address difference between consecutive scan lines or two lines of characters. Beginning with the second scan line, the starting scan line is increased by twice the value of this register multiplied by the current memory address size (byte = 1, word = 2, double-word = 4) each line. For text modes the following equation is used:
Offset = Width / ( MemoryAddressSize * 2 )
and in graphics mode, the following equation is used:
Offset = Width / ( PixelsPerAddress * MemoryAddressSize * 2 )
where Width is the width in pixels of the screen. This register can be modified to provide for a virtual resolution, in which case Width is the width is the width in pixels of the virtual screen. PixelsPerAddress is the number of pixels stored in one display memory address, and MemoryAddressSize is the current memory addressing size.

Underline Location Register (Index 14h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
| DW | DIV4 | Underline Location

DW - Double-Word Addressing
"When this bit is set to 1, memory addresses are doubleword addresses. See the description of the word/byte mode bit (bit 6) in the CRT Mode Control Register"
DIV4 - Divide Memory Address Clock by 4
"When this bit is set to 1, the memory-address counter is clocked with the character clock divided by 4, which is used when doubleword addresses are used."
Underline Location
"These bits specify the horizontal scan line of a character row on which an underline occurs. The value programmed is the scan line desired minus 1."

Start Vertical Blanking Register (Index 15h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Start Vertical Blanking

- Start Vertical Blanking
This contains bits 7-0 of the Start Vertical Blanking field. Bit 8 of this field is located in the Overflow Register, and bit 9 is located in the Maximum Scan Line Register. This field determines when the vertical blanking period begins, and contains the value of the vertical scanline counter at the beginning of the first vertical scanline of blanking.

End Vertical Blanking Register (Index 16h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
| End Vertical Blanking

- End Vertical Blanking
This field determines when the vertical blanking period ends, and contains the value of the vertical scanline counter at the beginning of the vertical scanline immediately after the last scanline of blanking.

CRTC Mode Control Register (Index 17h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
SE | Word/Byte | AW |  | DIV2 | SLDIV | MAP14 | MAP13

SE -- Sync Enable
"When set to 0, this bit disables the horizontal and vertical retrace signals and forces them to an inactive level. When set to 1, this bit enables the horizontal and vertical retrace signals. This bit does not reset any other registers or signal outputs."
Word/Byte -- Word/Byte Mode Select
"When this bit is set to 0, the word mode is selected. The word mode shifts the memory-address counter bits to the left by one bit; the most-significant bit of the counter appears on the least-significant bit of the memory address outputs. The doubleword bit in the Underline Location register (0x14) also controls the addressing. When the doubleword bit is 0, the word/byte bit selects the mode. When the doubleword bit is set to 1, the addressing is shifted by two bits. When set to 1, bit 6 selects the byte address mode."
AW -- Address Wrap Select
"This bit selects the memory-address bit, bit MA 13 or MA 15, that appears on the output pin MA 0, in the word address mode. If the VGA is not in the word address mode, bit 0 from the address counter appears on the output pin, MA 0. When set to 1, this bit selects MA 15. In odd/even mode, this bit should be set to 1 because 256KB of video memory is installed on the system board. (Bit MA 13 is selected in applications where only 64KB is present. This function maintains compatibility with the IBM Color/Graphics Monitor Adapter.)"
DIV2 -- Divide Memory Address clock by 2
"When this bit is set to 0, the address counter uses the character clock. When this bit is set to 1, the address counter uses the character clock input divided by 2. This bit is used to create either a byte or word refresh address for the display buffer."
SLDIV -- Divide Scan Line clock by 2
"This bit selects the clock that controls the vertical timing counter. The clocking is either the horizontal retrace clock or horizontal retrace clock divided by 2. When this bit is set to 1. the horizontal retrace clock is divided by 2. Dividing the clock effectively doubles the vertical resolution of the CRT controller. The vertical counter has a maximum resolution of 1024 scan lines because the vertical total value is 10-bits wide. If the vertical counter is clocked with the horizontal retrace divided by 2, the vertical resolution is doubled to 2048 scan lines."
MAP14 -- Map Display Address 14
"This bit selects the source of bit 14 of the output multiplexer. When this bit is set to 0, bit 1 of the row scan counter is the source. When this bit is set to 1, the bit 14 of the address counter is the source."
MAP13 -- Map Display Address 13
"This bit selects the source of bit 13 of the output multiplexer. When this bit is set to 0, bit 0 of the row scan counter is the source, and when this bit is set to 1, bit 13 of the address counter is the source. The CRT controller used on the IBM Color/Graphics Adapter was capable of using 128 horizontal scan-line addresses. For the VGA to obtain 640-by-200 graphics resolution, the CRT controller is programmed for 100 horizontal scan lines with two scan-line addresses per character row. Row scan address bit 0 becomes the most-significant address bit to the display buffer. Successive scan lines of the display image are displaced in 8KB of memory. This bit allows compatibility with the graphics modes of earlier adapters."

Line Compare Register (Index 18h)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
Line Compare Register

- Line Compare Register
This field specifies bits 7-0 of the Line Compare field. Bit 9 of this field is located in the Maximum Scan Line Register, and bit 8 of this field is located in the Overflow Register. The Line Compare field specifies the scan line at which a horizontal division can occur, providing for split-screen operation. If no horizontal division is required, this field should be set to 3FFh. When the scan line counter reaches the value in the Line Compare field, the current scan line address is reset to 0 and the Preset Row Scan is presumed to be 0. If the Pixel Panning Mode field is set to 1 then the Pixel Shift Count and Byte Panning fields are reset to 0 for the remainder of the display cycle.

Notice: All trademarks used or referred to on this page are the property of their respective owners.
All pages are Copyright © 1997, 1998, J. D. Neal, except where noted. Permission for utilization and distribution
is subject to the terms of the FreeVGA Project Copyright License.