Vintage PC pages
Home -> Vintage PCs -> Hercules InColor notes

Hercules InColor Card: Notes

The InColor Card was Hercules Graphics' attempt to compete with the EGA; like the EGA, it outputs a 16-colour 720×350 display to an EGA monitor. The difference is that unlike the EGA, it's backwards compatible with programs written for the original Hercules Graphics Card and Hercules Graphics Card Plus, rather than those written for the CGA and MDA.

It is not to be confused with the Hercules Color Card, a CGA clone designed to be installed alongside a monochrome (or InColor) Hercules card.

Hardware requirements

The InColor is an 8-bit ISA card containing the display controller and a printer port. When present in a computer, it requires the following system resources:

The hardware

Output is from a DE9 socket. The pinout of this socket is:

  1. Ground
  2. Secondary red
  3. Primary red
  4. Primary green
  5. Primary blue
  6. Secondary green
  7. Secondary blue
  8. Horizontal sync
  9. -Vertical sync

The font rom is marked AMI C15994 FONTROM (the same ROM is used on the Hercules Graphics Card Plus). As on the original IBM MDA, this is a 9264 rather than a 2764, so it can't be read in a standard EPROM programmer. The memory layout isn't the same as on the MDA, so you can't swap the chip with one from an MDA and expect it to make sense. Both ROMs are divided into four 2k blocks; on the MDA, the font is in blocks 0 and 1, but here it is in blocks 1 and 3.

The card uses the 14-pixel font in the ROM:

[14-pixel Hercules Plus font]

The ROM also contains two 8-pixel fonts (in blocks 0 and 2) which do not appear to be used.

[8-pixel Hercules Plus fonts]

Memory Map

On power-up, the InColor card behaves like an MDA, producing an 80×25 text screen in white on black. Each character is 9 pixels wide and 14 high, giving a 720×350 pixel resolution. Although the characters are 9 pixels wide, the bitmaps in the ROM (or the RAM) only cover the first 8. For characters 0C0h-0DFh, the ninth pixel column is a duplicate of the eighth; for others, it's blank.

In text mode, the usual MDA-esque scheme is used, with two bytes of RAM for each character. The first byte is the character code, and the second gives the attribute.

On startup, the character attribute scheme behaves like an MDA:

with eight exceptions:

The card can also use a CGA-like attribute scheme, in which bits 3-0 give the foreground colour, 6-4 the background colour, and bit 7 is set to blink. If blinking is disabled, bits 7-4 give the background colour.

Blink enabled
MDA-like attributesCGA-like attributes
Blink disabled
MDA-like attributesCGA-like attributes

Register I/O

03B4h: CRTC address register.

Write a CRTC register number (0 to 1Ch) to this port to select the CRTC register that will appear at port 03B5h. Registers 0-11h are standard 6845 registers and are described on the 6845 datasheet.

Registers 14h-1Ch are used to control the InColor card's additional features, and are described below.

On the MDA, the CRTC address and data register are partially decoded, so that any even-numbered address between 03B0h and 03B7h will get you the CRTC address register, and any odd-numbered address gets you the data register. I don't know whether this holds for the InColor card.

This is a write-only register.

03B5h: CRTC register read/write.

This gives access to the selected CRTC data register. Most CRTC registers are write only; some are read/write or read-only.

03B8h: Mode Control Register

This is a write-only register. The following bits are used:

Bit 7: Graphics page to display

If bit 7 is 1, the graphics page at 0B8000h is displayed. Otherwise, the page at 0B0000h is displayed.

Bit 5: 1 to enable blinking, 0 to disable it.

If bit 5 is 1, characters with attribute bit 7 set will blink. If not, they will have high intensity background.

Bit 3: 1 to enable video output, 0 to disable it.

If bit 3 is 0, screen output will not be shown. The usual use of this is if you're reprogramming the CRTC registers; disable video output beforehand and re-enable it after.

Bit 1: 1 for graphics mode, 0 for text.

When the card is switched between text and graphics modes, the 6845 must be reprogrammed with suitable parameters for the new mode.

03B9h: Set light pen flip-flop

Any write to this port sets the flip-flop.

03BAh: Status Register

This is a read-only register.

03BBh: Reset light pen flip-flop

Any write to this port resets the flip-flop.

03BFh: Graphics mode enable

This is a write-only register.

Additional CRTC registers

The additional CRTC registers are:

Register 14h: xMode

This is a write-only register, initialised to 0 on reset. The following bits are used:

Bit 0: 0 to use ROM font, 1 to use RAM font.

If the RAM font is selected, character bitmaps are read from 0B4000h. Each bitmap holds 16 bytes per character; the top 14 (normally) are drawn.

Bit 1: 0 for 80-column mode, 1 for 90-column mode.

If this bit is changed, the first four CRTC registers need to be reprogrammed. For 80-column mode, they should be set to 61 50 52 0F, and for 90-column mode they should be set to 6D 5A 5C 0F.

In 90-column mode characters are 8 bits wide, and so there is no special treatment of characters 0C0h-0DFh.

Bit 2: 0 for 4k RAMfont, 1 for 48k RAMfont

In 48k RAMfont mode, the low 4 bits of the attribute byte become a font selector, 0-11 (Values 12-15 are treated as 4-7). This selects the font used for drawing: font 0 is at B4000h, font 1 is at B5000h and so on.

Register 15h: Underline

This is a write-only register, initialised to 0Dh on reset. It only applies in 48k RAMfont mode; it sets the position and colour of the underline for underlined characters. Bits 3-0 give the row (0-15); bits 7-4 give the colour. Colour 0 behaves as colour 7. Note that drawing a character in 'inverse' mode also inverts the underline.

Register 16h: Strikethrough

This is a write-only register, initialised to 0Dh on reset. It behaves as underline, for characters with the 'strikethrough' attribute. If underline and strikethrough are both set to be drawn on the same line, and a character has both attributes, the strikethrough colour will be used.

Register 17h: Exception

This is a write-only register, initialised to 20h on reset.

Bit 5: 0 for CGA attributes, 1 for MDA attributes

This controls which attribute system is used.

Bit 4: 0 to disable palette, 1 to enable palette

If this bit is 0, all 16-bit colours will be treated as CGA-style IRGB values. If it is 1, the colour will be treated as the index into a 16-byte lookup table which will provide the actual 6-bit colour value.

Bits 3-0: Cursor colour

If the colour is 0, then the cursor will be drawn in either colour 7 or 15, depending on bit 3 of the attribute of its current cell.

Register 18h: Plane mask

This is a write-only register, initialised to 0Fh on reset.

Bits 7-4: Plane protect

Sets which planes are written by a write operation. A 0 bit means the corresponding plane can be written; a 1 bit means it cannot.

Note that in text modes, these values are ignored for the bottom 16k of RAM; all four planes are always written.

Bits 3-0: Visible planes

Sets which planes are visible.

Register 19h: Read/write control register

This is a write-only register, initialised to 40h on reset.

Bit 6: Mask polarity

This modifies the way bytes are read from memory. If this bit is set, the byte returned will have 0 bits where the colour read matches the background colour, and 1 bits where it does not. If the bit is clear, matching pixels will be returned as 1, and non-matching as 0.

Bits 5-4: Write mode

The write modes behave as follows:

Bit 5Bit 4Bit written=0Bit written=1
00Background colourForeground colour
01Last value latchedForeground colour
10Background colourLast value latched
11~Last value latchedLast value latched

This will be explained more fully in the Memory Access section below.

Bits 3-0: Don't care

This also modifies the way bytes are read; if a 'don't care' bit is set, that plane will not be checked when a comparison is made against the background colour. Thus if all four 'don't care' bits are set, all pixels will be assumed to match the background colour.

Register 1Ah: Read/write colour register

This is a write-only register, initialised to 0Fh on reset. Bits 4-7 give the background colour for read/write operations; bits 0-3 give the foreground colour.

Register 1Bh: Latch protect register

This is a write-only register, initialised to 0 on reset. It modifies read operations; when a memory read is performed, four latches are loaded with the contents of the four planes at that address. If a bit is set in this register, the corresponding bit of the latches is unaffected by the read.

Register 1Ch: Palette register

This is used to load the palette. First it should be read, to reset the palette counter to zero. Then 16 bytes should be written, giving the colour mapping for each ink. Bits 5-3 of each byte give secondary RGB, bits 2-0 give primary RGB.

Memory Access

The InColor card has 256k of memory, arranged in four planes of 64k each. This means, pretty much, that behind every address there are four bytes. At power-on, this system is transparent; a memory write will set all four bytes to the same value, and a memory read will return the last value written. But for colour graphics or colour RAMfont access, the data path needs to be described in full.

In text mode, memory access to addresses below 0B4000h bypasses most of the plane mechanism; writes always update all four planes to the same value, and reads return the last value written. For addresses above 0B4000h, or for all addresses in graphics mode, the plane system applies.

Memory reads

When the CPU reads a byte from memory, the four bytes at that location are read into the four memory latches. If bits are set in the Latch Protect register (CRTC register 1Bh), the corresponding bits in the latches are unaffected by the read. This still applies in text mode when everything else is being bypassed, so it's not a good idea to leave a value in the Latch Protect register when switching to text mode.

For the eight pixels in the latches, the colour of each pixel is compared to the background colour (bits 7-4 of CRTC register 1Ah). If a Don't Care bit is set in the Read/Write control register (bits 3-0 of CRTC register 19h) then the corresponding plane will be assumed to match. For example:

	Register 19h = 44h	Bit 2 is set, so plane 2 will be ignored
	Register 1Ah = 1Fh	Bits 7-4: Background is blue

	The byte to read has eight pixels: black, blue, green, cyan, red, 
					       magenta, yellow, white.
	Values loaded into the latches: 
		01010101b	blue plane
		00110011b	green plane
		00001111b	red plane
		00000000b	intensity plane

	The comparison will then match pixels with the pattern 0?01b, which
	in this case means bits 6 and 2 of the latches.

		01000100b

	And because bit 6 of register 19h is set, the CPU will read the
	inverse value: 10111011b.

Memory writes

When the CPU writes a byte, it generates bytes for the four planes based on the value written and (depending on the write mode) the contents of the four latches.

Write mode 0

In this mode, a zero bit writes the background colour (CRTC register 1Ah, bits 7-4) and a one bit writes the foreground colour (register 1Ah, bits 3-0). For example:

	Register 18h = 2Fh	Bit 5 set, so plane 1 will not be written
	Register 19h = 40h	Bits 5-4: Write mode is 0
	Register 1Ah = 1Fh	Bits 7-4: Background is blue
				Bits 3-0: Foreground is white

	If the byte written is 00010000b, the four values to write to the 
	planes will be
		11111111b	Blue plane
		00010000b	Green plane
		00010000b	Red plane
		00010000b	Intensity plane
	
	but because bit 5 of register 18h is set, the green plane will not
	be touched.

Write mode 1

In this mode, a zero bit writes the last value read into the latches, and a one bit writes the foreground colour (register 1Ah, bits 3-0). For example:

	Contents of the latches:
		01010101b	blue plane
		00110011b	green plane
		00001111b	red plane
		00000000b	intensity plane

	Register 18h = 0Fh	Bits 7-4 are 0, so all planes will be written
	Register 19h = 50h	Bits 5-4: Write mode is 1
	Register 1Ah = 1Fh	Bits 7-4: Background is blue
				Bits 3-0: Foreground is white

	If the byte written is 00110000b, the four values written to the 
	planes will be
		01110101b	blue plane
		00110011b	green plane
		00111111b	red plane
		00110000b	intensity plane

	ie, two pixels in the byte will become white.

Write mode 2

In this mode, a zero bit writes the background colour (register 1Ah, bits 7-4), and a one bit writes the last value read into the latches. Using the same example as before:

	Contents of the latches:
		01010101b	blue plane
		00110011b	green plane
		00001111b	red plane
		00000000b	intensity plane

	Register 18h = 0Fh	Bits 7-4 are 0, so all planes will be written
	Register 19h = 60h	Bits 5-4: Write mode is 2
	Register 1Ah = 1Fh	Bits 7-4: Background is blue
				Bits 3-0: Foreground is white

	If the byte written is 00110000b, the four values written to the 
	planes will be
		11011111b	blue plane
		00110000b	green plane
		00000000b	red plane
		00000000b	intensity plane

	ie, all but two pixels in the byte will become blue.

Write mode 3

In this mode, a zero bit inverts the last colour read into the latches, and a one bit writes the last value read. Using the same example:

	Contents of the latches:
		01010101b	blue plane
		00110011b	green plane
		00001111b	red plane
		00000000b	intensity plane

	Register 18h = 0Fh	Bits 7-4 are 0, so all planes will be written
	Register 19h = 70h	Bits 5-4: Write mode is 3
	Register 1Ah = 1Fh	Bits 7-4: Background is blue
				Bits 3-0: Foreground is white


	If the byte written is 00110000b, the four values written to the 
	planes will be


	ie, all but two pixels in the byte will be inverted.
		10011010b	blue plane
		11111100b	green plane
		11000000b	red plane
		11001111b	intensity plane

Character Attributes

Character attributes are a complicated subject on the InColor, for a number of reasons:

Normal mode

This is reasonably straightforward:

MDA attributesCGA attributes
Blink onBit 7=Blink
Bit 3=If set, foreground=15 else foreground=7
Bits 2-0=1 to underline
00, 08, 80, 88 solid background colour
70, 78, F0, F8 swap foreground and background
Bit 7=Blink
Bits 6-4=Background
Bits 3-0=Foreground
Blink offBit 7=If set, background=8 else background=0
Bit 3=If set, foreground=15 else foreground=0
Bits 2-0=1 to underline
00, 08, 80, 88 blank
70, 78, F0, F8 swap foreground and background
Bits 7-4=Background
Bits 3-0=Foreground

4k RAMfont mode

Now the fun begins. If, when loading the character set, you write the same value into all four planes, this mode behaves just like the normal text mode. But if you don't, the colour of a pixel is determined like this:

For example, drawing a byte which contains 8 colours:

	Foreground = 2 (green). 
	Background = 1 (blue).
	First byte of character definition is
						fg	bg
		01010101b  blue plane		 0	 1
		00110011b  green plane		 1	 0
		00001111b  red plane		 0	 0
		00000000b  intensity plane	 0	 0

	Colours drawn:

		10101010b  blue plane
		00110011b  green plane
		00000000b  red plane
		00000000b  intensity plane
		
	ie, some pixels will be black, some blue, some green and some cyan.

48k RAMfont mode

In this mode, the semantics of the attribute byte change considerably. The low 4 bits are always a font number; the high 4 bits behave thus:

MDA attributesCGA attributes
Blink onBit 7=Bright (background = 8)
Bit 6=Blink
Bit 5=Strikethrough
Bit 4=Underline
Bits 7-4 = ~Foreground colour
Blink offBit 7=Boldface
Bit 6=Inverse (background = 15)
Bit 5=Strikethrough
Bit 4=Underline

Character drawing differs in the three cases:

MDA attributes, blink on

MDA attributes, blink off

CGA attributes

So, for example, using the same character definition as before:

					
	01010101b  blue plane
	00110011b  green plane	
	00001111b  red plane	
	00000000b  intensity plane

	With attribute=0, all colours are drawn as in the memory:

	MDA, blink on	MDA, blink off	CGA
	01010101b  	01010101b	01010101b	blue plane
	00110011b	00110011b	00110011b	green plane
	00001111b  	00001111b	00001111b	red plane
	00000000b 	00000000b 	00000000b	intensity plane
	
	With attribute=12 (1100b):

	MDA, blink on	MDA, blink off	CGA
	01010101b  	10101010b	01010101b	blue plane
	00110011b	11001100b	00110011b	green plane
	00001111b  	11110000b	00000000b	red plane
	11111111b 	11111111b 	00000000b	intensity plane

	high intensity	inverted	only blue,green,cyan drawn

Different fonts in each plane

The reason for treating the fonts as colour bitmaps is that the card can then support 48 fonts rather than 12. The program would load four sets of fonts, one into each plane, and output all its text in colour 1, 2, 4 or 8 on a black background. The palette could be used to make the four colours all map to the same RGB values, so the fonts would not differ in appearance.

Recommended CRTC values

Hercules graphics cards do not include any form of BIOS extension, and the standard IBM BIOS treats them as an MDA. Consequently, to switch between text and graphics modes (or 80- and 90- column modes), the CRT controller has to be reprogrammed manually. These values should be set at the same time as the text/graphics bit in the Mode Control register, or the 80/90 column bit in the xMode register.

In the tables below, all values are in hexadecimal.

Register80-column text90-coluumn textGraphics
00 Horizontal total616D35
01 Horizontal displayed505A2D
02 Horizontal blanking525C2E
03 Sync width0F0F07
04 Vertical total19195B
05 Vertical adjust060602
06 Vertical displayed191957
07 Vertical sync position191957
08 Interlace and skew020202
09 Max raster0D0D03
0A Cursor start0B0B00
0B Cursor end0C0C00

The manual also provides timing values for different character heights, allowing (for example) a 43-line display with 8-pixel characters. In this situation, a suitable font of the correct height should be loaded into RAM.

RegisterCharacter height
45678 9101112 13141516
04 Vertical total5C4A3D34 2D2824201D1B 191716
05 Vertical adjust02000406 020100070A06 060A02
06 Vertical displayed58463A32 2B26231F1D1A 191715
07 Vertical sync position59463B 332C2723201D 1B191716

The printer port

According to the manual, the printer port can be disabled (if it conflicts with another piece of hardware) by removing the chip marked HCT LP112 adjacent to the port.

The printer port behaves like the one on an MDA:


John Elliott 5 August 2012