Vintage PC pages
Home -> Vintage PCs -> Sigma Designs Color 400

Sigma Designs Color 400

The Color 400 is a graphics card that was designed to compete with the EGA. It provides the features of a CGA card, with the addition of three new video modes: 80×30 text, 80×50 text and 640×400 graphics in 16 colours.

Table of contents


The card seems to have gone through various iterations of hardware design. Pictures of early versions show a full-length ISA card, while Total Hardware 99 shows a more compact half-length design.

Sigma Designs Color 400 version 2.52L

According to TH99, the address ranges used by the card can be configured with DIP switches. However the BIOS in mine is hardcoded to use one specific set of addresses, so that's what I will use in the remainder of this document.

Along with the DIP switches, the card is equipped with two ROMs (one for the text-mode font, one for the BIOS), a 9-pin video connector, and a Berg connector for a light pen.

The card has two 8k ROM chips; one contains 8×8 and 8×16 fonts for text modes, while the other contains 6k of BIOS code and an 8×16 font for the 640×400 graphics mode.

Text-mode font ROMGraphics-mode font in BIOS
Text-mode fonts Graphics-mode font


Where a normal CGA would have its I/O ports in the 3D0-3DF range, the Color 400 uses the 2D0-2DF range. I/O accesses to 3D0-3DF can trigger a non-maskable interrupt; this is handled by the card's BIOS and translated to accesses in the 2D0-2DF range.

I/O ports are:

2D0: CRTC register select.
2D1: CRTC register value.
     The above may be replicated in the 2D2-2D7 range, but the card BIOS 
     does not access these addresses.

     The X values used by the CRTC are half of what you would expect from a
     normal CGA. So the 40-column text mode has a width of 20, and 80-column
     modes have a width of 40. This means that the CRTC 'cursor address' 
     registers only give the cursor position to the nearest word; bit 7 of
     port 2D9 gives the lowest bit of its address.

2D8: Mode register. The values written to this for various video modes are:
	Text      40× 25: 0xA8  1010 1000
	Text      80× 25: 0xB9  1011 1001
	Graphics 320×200: 0x0F  0000 1111
	Graphics 640×200: 0x1F  0001 1111
	Graphics 640×400: 0x7F  0111 1111
	Text      80× 50: 0x79  0111 1001
	Text      80× 30: 0xB9  1011 1001

2D9: Control register.
	Bit 7: Cursor position, low bit
	Bit 6: Unknown
	Bit 5: NMI on writes to ports 03D0h-03DFh
	Bit 3: Normally 1, set to 0 to clear lightpen latch
	Bit 2: Normally 1, set to 0 to set lightpen latch
	Bit 1:  
	Bit 0: Controls what port 2DE does.
			0 => Select plane
			1 => Write to palette

	(The card BIOS seems to have an alternative mode where bits 2/3 
	 are normally 0 and are set to 1 to set/clear the latch)

2DA: Status. On read:
	Bits 7-5: NMI mask / cursor position as set by last write to 2D9.
	Bit 4: Vertical retrace
	Bit 2: Light pen switch, active low
	Bit 1: Light pen trigger, active low
	Bit 0: Horizontal retrace?

     On startup, the BIOS does 100 reads of this port. If bit 1 is zero in
     all of them, it disables the NMI functionality and only emulates CGA at
     the BIOS level.

2DB: On read: Byte written to CRTC that triggered NMI.
     The BIOS writes a random value to this port after the NMI has been 
     processed, presumably to clear bit 7 of port 2DC below.     

2DC: On read: Bit 7 set if video adapter raised NMI.
	      Bits 00-0F give the I/O port that triggered the NMI (less 
     The NMI handler writes to 2DCh at the end of the NMI handler, presumably
     to reset the NMI signal from the card to the motherboard.

2DD: Memory paging. The memory from 0xC1800 to 0xC1FFF can be either:
	* ROM: The 128 character 8×16 font for use in graphics modes
	* RAM: Use by the video BIOS to hold its settings.

	Reading port 2DD switches to ROM. Bit 7 of the value read gives the
	previous paging state: bit 7 set if ROM was paged, clear if RAM was

	Writing port 2DD switches to RAM.

2DE: Depending on value written to port 02D9 bits 0-1, can be palette
	or plane select.

	If palette: High 4 bits = register. Low 4 bits = IRGB, active low
                    (so 0Fh is black, 0Eh is blue, ... 00h is white). 
	If plane select: Write value, 0-3.

3DA: A CGA-compatible status can be read from this port. This behaviour can
     be disabled by a jumper on the card.

The BIOS does not appear to attempt to emulate the CGA 'blink' / 'bright background' toggle, so I don't know if the card supports this function.


The video RAM is arranged as four 32k planes at 0B8000h. In text modes, plane 0 contains the characters and attributes in their usual layout. The way the graphics modes work is slightly more complex.

320×200 mode

This is notionally a 4-colour mode. In fact it's a 16-colour mode, drawing its data from planes 2 and 3:

	Bits 76543210
Plane 2      ABCDEFGH
Plane 3      JKLMNPQR

There are four pixels.
Colour for pixel 0 is KBJA. 
Colour for pixel 1 is MDLC.
Colour for pixel 2 is PFNE.
Colour for pixel 3 is RHQG.

When selecting the mode, the BIOS writes all ones to plane 3, and sends memory accesses to plane 2. The palette registers are programmed so that the pixel patterns map to CGA-compatible colours as they should.

640×200 mode

On a CGA, this is a monochrome mode. On the Sigma 400, it's actually a 16-colour mode; each pixel draws its colour from all four planes (bit 0 from plane 0, bit 1 from plane 1 etc.)

When the BIOS selects this mode, it clears all four planes and sends memory accesses to plane 2. Set pixels will therefore display in colour 4, so the palette is programmed to make colour 4 the foreground colour.

A program aware of the Sigma 400 can use this mode as a 16-colour mode by programming a suitable palette and accessing the plane select register.

640×400 mode

The memory layout of this mode is identical to the "AT&T" mode found on some CGA cards, or in Hercules monochrome mode:

The arrangements for memory planes are identical to the 640×200 mode. By default the BIOS selects plane 1 (green) so that set pixels display in green on black. As with the 640×200 mode, full colour support is possible by programming a suitable palette and using the plane select register; this is what the Windows 1.03 drivers SIGMA4.DRV and SIGMA8.DRV do.


The card BIOS supports the following interrupts:


This checks to see whether the NMI was triggered by a write to ports 03D0-03DF; if so, it performs the appropriate translation to the card's actual video hardware.

INT 8 (timer)

This is hooked if the processor is 286 or higher. If so, it will poll the I/O channel check bit (port 61h bit 6 on ISA systems, port 62h bit 6 on PC/XT type systems) and if it's set simulate an NMI.

INT 9 (keyboard)

This resets bit 5 of port 02D9h (so the card will not trigger a NMI), calls the original INT 9 handler, and restores port 02D9h to its original value.

INT 10h (video)

The card's video BIOS provides INT 10h functions 00h-13h; some are implemented by passing the call on to the motherboard's CGA BIOS. Functions worth noting are:

INT 10h/AH=0 (set mode)

Three additional modes are supported: 40h (80×30 text), 41h (80×50 text) and 42h (640×400 graphics).

INT 10h/AH=10h (palette functions)

Subfunctions supported are 0 (set single palette register) and 2 (set all palette registers). There is no support for setting the border colour.

If the last byte of the BIOS is less than 2Fh (the same check that relates to differences in how the lightpen hardware responds to commands) then attempts to change colour 0 will be ignored.

INT 10h/AH=8Fh (installation check)

This returns:

AX = BIOS version. AH=major version, AL=minor. For example 0234h for version 2.52.
BX = video RAM segment (0B800h)
CX = video ROM segment | 80h (so 0C080h for me)
DX = I/O port base (02D0h)

INT 1Fh (graphics table):

This is expanded. Where a normal CGA BIOS would expect 1k of data for a 128-character 8×8 font, the Sigma 400 expects 3k of data: 128 8×8 characters, followed by the same characters at 8×16 resolution.

BIOS parameter table

At C000:000C is a pointer to a 5-word table:

	DW	offset mode_setups	;Table of setup data for each mode
	DW	offset mode_palettes	;Table of palette data for each mode
	DW	offset int10_funcs	;Table of INT 10h handlers
	DW	offset int9		;Address of INT 9 handler
	DW	0

The tables are:

	DW	offset setup_text40	;Mode 0
	DW	offset setup_text40	;Mode 1
	DW	offset setup_text80	;Mode 2
	DW	offset setup_text80	;Mode 3
	DW	offset setup_gfx320	;Mode 4
	DW	offset setup_gfx320	;Mode 5
	DW	offset setup_gfx640	;Mode 6
	DW	offset setup_text80	;Mode 7
	DW	offset setup_mode40	;Mode 0x40
	DW	offset setup_mode41	;Mode 0x41
	DW	offset setup_mode42	;Mode 0x42

	DW	offset palette_mode0
	DW	offset palette_mode1

Each mode setup table is 32 bytes long:

	DB	53,40,45,4,27,12,25,26,0,15,12,15,0,0,0,0	;CRTC registers
	DB	0B9h	;0x10	Mode register 2D8
	DB	0Ch	;0x11	Control register 2D9
	DB	020h	;0x12	Character for clear screen
	DB	7	;0x13	Attribute for clear screen
	DB	3	;0x14	BIOS mode
	DW	50h	;0x15	Columns
	DW	1000h	;0x17	Buffer size
	DB	7	;0x19	Cursor end
	DB	6	;0x1A	Cursor start
	DW	03D4h	;0x1B	I/O port
	DB	29h	;0x1D	CGA mode register
	DB	30h	;0x1E	CGA colour select register
	DB	0	;0x1F	Not used

For text modes the palette table is 64 bytes, containing four sets of identical palette register values.

For 4-colour CGA mode the palette table is 128 bytes, corresponding to the possible values of the CGA mode control and colour select registers:


The Windows 1.03 driver pack (V1DSK.ZIP / V1DSK2.ZIP at includes two drivers for this card: 8-colour and 4-colour. The latter is, as far as I know, the only 4-colour driver for any version of Windows 1.x:

Screenshot of Windows 1.03 in four colours

There is another driver pack at which contains the Windows drivers, plus drivers for Lotus 1-2-3 and GEM 1.x / 2.x and an image viewer.

For GEM 3.x / ViewMAX, the latest FreeGEM driver pack (version 3.14.12) contains three suitable drivers:

John Elliott 16 October 2018