Sunday, May 8, 2016

IBM's CGA Hardware Explained

The IBM Color/Graphics Card has been widely seen as a poor attempt at a video adapter.  Released with the IBM PC back in 1981, it was not particularly impressive by the standards of its day. Limited colors and no sprites did not make it very attractive for games.  However, when you look at the hardware and what it could do, it becomes more impressive.  Even though the card is a full length card, it was built from off the shelf logic chips, memory and video controller.  Looking at the hardware also helps one understand the limitations of the device.

The BIOS Modes

Mode 00h - 40x25 B&W
Mode 01h - 40x25 Color
Mode 02h - 80x25 B&W
Mode 03h - 80x25 Color
Mode 04h - 320x200 Color
Mode 05h - 320x200 B&W
Mode 06h - 640x200 B&W

On an RGBI monitor, the identical Color/B&W modes have no distinction except in Modes 04 and 05.  On a color composite monitor or TV set, color modes enable the color burst and b&w modes disable the color burst.  The IBM PC defaults to the 40x25 or 80x25 B&W modes depending on how you set a dipswitch.  Text, especially 80-column text, is much more difficult to read on a composite color display.

The CGA card has 16KB of RAM.  A full screen of 40-column text required 2KB of memory, allowing for 8 separate pages.  A full screen of 80 column memory required 4KB of memory, allowing for 4 separate pages.  Graphics modes took up all the 16KB of memory.  In order to really put the CGA card to work, one has to go deeper and look beyond the BIOS and what could be done by accessing its registers directly.

Hardware Registers

03D4 - MC6845 Address
03D5 - MC6845 Data
(Described below)

03D8 - Color Select Register
Bit 0 - Selects Blue Color of Border (Text Modes), Background and Border (320x200 Graphics) or Foreground (640x200 Graphics), 0 = No Color, 1 = Color
Bit 1 - Selects Green Color of Border (Text Modes), Background and Border (320x200 Graphics) or Foreground (640x200 Graphics), 0 = No Color, 1 = Color
Bit 2 - Selects Red Color of Border (Text Modes), Background and Border (320x200 Graphics) or Foreground (640x200 Graphics), 0 = No Color, 1 = Color
Bit 3 - Selects Intensified Color of Border (Text Modes), Background and Border (320x200 Graphics) or Foreground (640x200 Graphics), 0 = No Color, 1 = Color
Bit 4 - Graphics Mode 0 = Non-intensified Color Set Available, 1 =  Intensified Color Sets Available
Bit 5 - Graphics Mode 0 = Color Set 1, 1 =  Color Set 2

03D9 - Mode Control Register
Bit 0 - 0 = Selects 40x25 Text Mode, 1 =  Selects 80x25 Text Mode
Bit 1 - 0 = Selects Text Mode, 1 = Selects Graphics Mode
Bit 2 - 0 = Selects Color on Composite Display, 1 = Selects B&W on Composite Display
Bit 3 - 0 = Disable Video Signal, 1 = Enable Video Signal
Bit 4 - 0 = Selects 320x200 Graphics, 1 = Selects 640x200 Graphics
Bit 5 - 0 = Blinking Enabled, Character Cell can Select from 8 Background Colors, 0 = Blinking Disabled, Character Cell can Select from 16 Background Colors

03DA - Status Register
Bit 0 - Display Active, 0 = Display Active, 1 = Display Inactive
Bit 1 - Light Pen Trigger, 0 = Trigger Active, 1 = Trigger Inactive
Bit 2 - Light Pen Switch, 0 = Switch On, 1 = Switch Off
Bit 3 - Vertical Retrace Active 0 = No, 1 = Yes

03DB - Clear Light Pen Latch
03DC - Set Light Pen Latch
(Any access to these registers activates the function of these registers)

A light pen is connected to a six-pin header on the CGA card.  A light pen consists of a photo sensor and a switch.  The idea is that when you touch the pen to the screen and pushed the button, the system will know where you touched the screen and react to the input in some way.  The way this works in hardware is as follows :

1.  Clear then Set the Light Pen Latch, this allows the MC6845 to obtain the position of the light pen.
2.  Poll Bits 1 and 2 of 03DA, if both are 0, then that means that the light pen was pointed at some portion of the screen
3.  Find out which memory address the pen pointed to by reading R16 & R17 of the MC6845.
4.  Repeat

Light pens can work in all text and graphics modes, but the precision may not be what you would like.

RGBI Colors

The CGA can display 16 colors on a TTL or "Direct Drive" RGBI monitor.  However, it can only display all of them at one time in text modes.

0000 Black
0001 Blue
0010 Green
0011 Cyan
0100 Red
0101 Magenta
0110 Brown (sometimes Dark Yellow)
0111 White (also called Light Gray)
1000 Gray (also called Dark Gray)
1001 Light Blue
1010 Light Green
1011 Light Cyan
1100 Light Red
1101 Light Magenta
1110 Yellow
1111 High Intensity White (also called Bright White or simply White)

Resolutions and Palettes

The BIOS can select between three color sets in 320x200 resolution modes :

Mode 04 Color Set 1
0010 Green
0100 Red
0110 Brown

Mode 04 Color Set 2
0011 Cyan
0101 Magenta
0111 White

Mode 05 Color Set
0011 Cyan
0100 Red
0111 White

The BIOS cannot turn on the intensity bit, you must write to 03D8.  Mode 05h was never documented by IBM as giving different colors on an RGBI display.  You cannot change the Color Set in Mode 05h, but you can set the intensity.  So when you add intensity, you get :

Mode 04 Color Set 1
1010 Light Green
1100 Light Red
1110 Yellow

Mode 04 Color Set 2
1011 Light Cyan
1101 Light Magenta
1111 High Intensity White

Mode 05 Color Set
0011 Light Cyan
0100 Light Red
0111 High Intensity White

Given the nibble values, you can see that the difference between Color Set 1 and Color Set 2 is the activation of the Blue bit.  In Mode 05h, it appears that the Blue bit is always activated except for the middle color, where it is never activated.  The pattern suggests that bit 2, when set to 1, from 03D9 is ANDed with the Green bit from the Color Set and put in the Blue bit, essentially giving the proper nibble pattern shown above.  

In the 640x200 graphics Mode 06, only two colors were available.  The BIOS gave a default foreground color of High Intensity White.  The background and border colors in this mode are always black and cannot be changed with a standard CGA card.  The foreground color can be changed to any of the 16 colors in the CGA palette, but this could not be done by the BIOS.

The Motorola MC6845

The CGA is at heart a text-based display adapter.  It uses the MC6845 Cathode Ray Tube Controller (CRTC) for setting up the display and most display timings. This chip is also used in the text-only Monochrome Display and Printer Adapter.  The chip acts in terms of scanlines and character cells, so how did IBM manage to coax medium and high resolution resolution graphics modes?  How did programmers coax low resolution full color modes?

This chip has eighteen internal registers, and the register you wish to access is loaded by writing the Address Register number to 03D4.  The data to be written to that Address Register is written to 03D5.

Here are the registers and their default IBM PC BIOS values :

Address Reg Reg # Unit Read/Write Reg Name Reg Size 40x25 Alpha 80x25 Alpha Graphics
00 R0 Char Write Hor. Total 8 38 71 38
01 R1 Char Write Hor. Disp. 8 28 50 28
02 R2 Char Write Hor. Sync Pos. 8 2D 5A 2D
03 R3 Char Write Hor. Sync Width 4 0A 0A 0A
04 R4 Char Row Write Vert. Total 7 1F 1F 7F
05 R5 Scan Line Write Vert. Total Adj. 5 06 06 06
06 R6 Char Row Write Vert. Disp. 7 19 19 64
07 R7 Char Row Write Vert. Sync Pos. 7 1C 1C 70
08 R8
Write Interlace Mode 2 02 02 02
09 R9 Scan Line Write Max Scan Line Addr. 5 07 07 01
0A R10 Scan Line Write Cursor Start 7 (5) 06 06 06
0B R11 Scan Line Write Cursor End 5 07 07 07
0C R12
Write Start Add. (H) 6 00 00 00
0D R13
Write Start Add. (L) 8 00 00 00
0E R14
Read/Write Cursor Add. (H) 6 XX XX XX
0F R15
Read/Write Cursor Add. (L) 8 XX XX XX
10 R16
Read Light Pen (H) 6 XX XX XX
11 R17
Read Light Pen (L) 8 XX XX XX

The text character cell in all CGA modes is 8 pixels by 8 scanlines.  This gives an effective resolution of 320x200 for the 40x25 text mode and 640x200 for the 80x25 text mode.

From the numbers given in the table, we can make calculations.  

From R0 and R1, we know how many horizontal characters are displayed.  

R1 - The total number for the 40x25 mode, 38h/56 characters + 1 character if you include the border.  

R2 - Of those, the displayed number is 28h, or 40 characters.  This works similarly for the 80x25 text mode.

R3 and R4 deal with Horizontal Sync.  Horizontal Sync starts at Character 45 or 90 and the Width of the Sync lasts for 10 Characters.  When some games allow you to adjust your display by shifting the image to the left or right, they are almost certainly writing to R3 and R4.  

Next we go to the vertical timings

R4 and R5 deal with the total characters displayed vertically.  We have 1Fh/31 + 1 characters displayed by R4.  Given an 8x8 text box, this gives us 256 scanlines.  The total number of scanlines in an NTSC display in a progressive scan mode is 262, so R5 gives us the extra 6 scanlines.  

From R6 we always get 19h/25 rows of text characters.

R7 gives us the time for the vertical sync signal, and it starts at character 1Ch/28.

For Graphics Modes, things are a little different by the vertical.  Here we have a vertical displayed total R6 of 64h/100 "character rows" and a vertical total R4 of 7F + 1 or 128 "character rows".  Here is where the famous CGA interlaced memory model comes into place.  The graphics modes have 200 lines, so they are programmed as two 100 line pages by the 6845's perspective.  Each line is separated by 8KB of memory in an interleaved format.  

R8, the Interlace Mode register, is never intentionally used because it does not display a proper interlaced signal with a standard monitor.  

R9 tells us how many scanlines there will be for each character row + 1, so you get 8 scanlines for text modes.  For graphics modes, this value ends up being 2.  Combined with the values at R4-R6, this gives you the interlaced memory addressing.  Using this value for the 80x25 text mode gives you an effective 160x100 mode when using the ASCII character 221 for every text box.  

R10 and R11 allows a cursor of up to 32 scanlines, and bits 5 and 6 of R10 control the blinking rate for the cursor.  

R12 through R17 are programmed in terms of memory addressing.  Each pair of registers combines into a 14-bit value.  Essentially this means the MC6845 can address 16,384 bytes of memory.   In text mode, you can obtain eight pages of 40x25 text and four pages of 80x25 text.  Graphics mode takes up all the memory. The Start Address can come in handy for hardware scrolling and double buffering.  

One thing the MC6845 does not determine fully is how many pixels there are on a line.  This is determined by the dot clock rate.  In 320x200 and 40x25 text mode (which has the equivalent resolution), a 7.16MHz dot clock is used.  

First, we divide 7,159,090Hz by 60Hz to obtain the number of pixels for each frame = 119,318.1667
Next, we divide 119,318.1667 by 262 lines to obtain the number of pixels per line = 455.4128
455 is larger than 320, so this doesn't make sense.  However, that is the total number of pixels displayed per line, including both active and border portions of the screen.  Dividing R2 by R1 gives us an active to total ratio of .70175.  Now, 455 * .70175 gives us 320 pixels (more or less).  

It follows that the 14.318MHz dot clock is used for the 80x25 text and 640x200 graphics modes.  Even though both use this dot clock, there is random flickering lines if you write to the 80x25 text mode outside vertical retrace.  This is the dreaded CGA snow.  Snow is the result of the CPU and the MC6845 accessing the memory at the same time.  The CPU must win the fight or you lose access to the data.  The MC6845 shows random lines in the character cell which is being written to during that frame.  In 40-column text and the graphics modes, the CPU writes and the MC6845 reads are properly synchronized to avoid snow, but the 80 column text mode's memory bandwidth requirements are too high.

DOS updates 80 column text in a slow and flickery fashion because it can detect a CGA card and tries to avoid snow.  IBM did not assign an IRQ to its video adapters until the PCjr. and EGA, so there is no interrupt alterting the programmer that the system has entered a retrace period where it is safe to write to the screen memory.  Instead the programmer must routinely 3DA for the appropriate time.  Polling is slower than interrupts.  Alternately, using the BIOS functions to address the screen would avoid snow, but was also slower than dealing with snow.

"Alternate Palettes"

If you bought an IBM PC with a CGA card in it when it was first made available on August 19, 1981 or for some time thereafter, you would need to find a compatible monitor from a source outside of IBM.  The monitor you purchased may only have been able to display one of these 8-color palettes :

IBM recognized in its first IBM PC Technical Reference Manual that some of the available RGB monitors could not handle the intensity signal or display a brown color.  If you use a "CGA" to VGA converter these are the colors you can expect if you do not have a proper digital RGBI to analog RGB converter circuit.

Adding Intensity is easy enough, but if you monitor does nothing else, this is the palette you will get :

Color #6 is dark yellow in this palette, but the IBM canonical color is brown.  The difference between dark yellow and brown is that the green signal is halved.  So, if Red is 1, Blue is 0 and Intensity is 0, then Green's analog component will be half as bright.

Brown is the color that will be displayed on IBM's official CGA monitor, the 5153 Color Display, and its later color monitors.  It will be the color displayed on the PCjr., Tandy 1000, EGA, MCGA and VGA adapters.


rcreif said...

Interesting! I understood that the "four" palette options were determined by fixing the B and I bits and letting the bitmap adjust the R and G bits, but I never understood why the background color was freely selectable. Now I know how the color register works.

But now I wonder: with eight bits available in the color register, why did IBM make the decision to arrange it like this? Why not, for example, have two freely selectable colors (foreground and background in 640x200 mode), and have the other two colors in 320x200 mode always be white and black?

Cyan/red/white/black is a good non-garish colorblind-friendly palette, with others optimized for contrast (blue/yellow/white/black) or a setting-appropriate theme (blue/green/white/black for ocean, red/magenta/white/black for cyberpunk, green/magenta/white/black for Apple II ports, etc.) To say nothing of just having a 16-bit color register to make all four colors freely selectable...

Great Hierophant said...

IBM used discrete logic for the CGA Registers, there are no custom chips on the board. The chips used were 74LS174s, which are 6-bit latches/flip-flops. So they simply did not have the extra 2-bits to use. With the PCjr., they used an ASIC chip that could perform all the functions of the discrete logic chips on the CGA card and more like implement palette registers for a fully-selectable 16-color palette in most of the graphics modes. Of course the way they did this was not register compatible with CGA for the most part, something Tandy fixed in its implementation.