With the introduction of the IBM-PC in 1980 two different graphic adapters were available. The Monochrome Display Adapter MDA, featuring high resolution text mode, was designed for business use, and the Color Graphics Adapter CGA for use in entertainment and at home. While the MDA only displayed text using a 8x14 font, the CGA could handle bitmapped graphics with a resolution of either 320x200x4 of 640x200x2 colors. The cost of bitmapped graphics was the ugly text mode using a 8x8 font.
The Hercules Graphics Card combined the best features of both cards. It could handle standard text mode with a 8x14 font, highlightning and underscore plus a high resolution graphics mode with a 720x348 monochrome bitmap.
Textmode
In textmode the HGC displays 25 rows with 80 columns (the standard text mode
for IBM compatibles). Each character consists of 8x14 pixels. Unlike EGA or VGA
the bitmap for each char is stored onboard in ROM, so the card can not use user
defined fonts.
The physical screen consists of 720x350 pixels. So each char covers 9x14 pixels of
physical screen space. The 8th pixel column of each char with ascii
value of 192-223 is doubled so that the graphic ascii chars
have no gaps. For all other chars the 9th column is set to black.
This trick saves much memory for the character ROM (remember memory was
horribly expensive in 1980) and makes handling more easy as each row
occupies 8 bits <=> 1 byte.
For each char on the screen one attribute byte is reserved. The attribute is the same for every graphics card (MDA-VGA), but due to the monochrome nature of the HGC only very few bit combinations are usable.
|
The background color is always black. Colors with the intensity bit set (8-15) are displayed with high intensity. All other colors are displayed using normal intensity. The 6845 can handle two more character styles:
The 6845 mirrors its internal memory onto the main memory from B000h - BFFFh. As modern VGA cards have their text mode memory from B800h-BFFFh, the BIOS sets a flag for the 6845 to prevent it from accessing above B7FFh. You can change this, but be warned that the VGA card will surely interfer with your HGC.
The textmode memory starts at B000h and occupies 80*2*25 = 4000 bytes. So you can have up to 8 different text mode pages. Unfortunately not all BIOSes support multiple pages for HGC, so you may have to program the HGC directly to access all pages. But anyway we mostly need one textmode page, as textmode normally should be fast enough for scrolling etc.
Graphics Mode
In graphics mode the HGC behaves totally different from textmode. We now have
controll over each individual pixel with a resolution of 720x348 pixel. The
last two rows can not be accessed due to internal synchronization details.
A graphics mode screen needs about 31320bytes = 32K, so the HGC can handle two graphics
mode pages. But Page 2 lies within the VGA textmode memory (B800-BFFFh) , so
it should not be used, when working with two graphics cards.
The memory layout in graphics mode is totally different from text mode. Each Page is divided into 4 Banks each using 8K.
void hgcplot(unsigned short x, unsigned short y) { unsigned char mem=(unsigned char *)0xB0000; mem[((y&3)<<13)+(y>>2)*90+(x>>3)]|=1<<(x&7); }programing the HGC using ports
WARNING: you are directly programing the video signal generator. Wrong values in the wrong registers can damage your card or monitor. So only poke around if you know what to do. Especially registers with syncing information should be handled with great care. |
The 6845 uses 7 ports to communicate with the rest of the computer. All ports are 8 bit.
3B4h | Index Register | w |
3B5h | Data Register | r/w |
3B8h | Mode Register | w |
3B9h | Light-Pen set | w |
3BAh | State Register | r |
3BBh | Light-Pen reset | w |
3BFh | Configuration Register | w |
|
|
|
Index Register 3B4h and Data Register 3B5h
18 internal registers are covered behind these two ports. Each register is
accessible by writing its index number to port 3B4h and then the desired
value to port 3B5h. These ports are mainly used to reprogram the 6845 for
generating a new video signal.
The following values are only valid for europe and countries with a
refresh frequency of 50Hz. As most monitors synchronize themselvs using the
frequency provided by the alternating current of the electricity network
I strongly assume that hercules monitors in USA run with a refreshing rate
of 60Hz. So poking the following numbers into the hercules card will interfere
with the monitor setup.
The clock tick of the HGC is 1.778MHz, which is equal to 0.5625ęs.
|
horizontal total (0) = 97
this register defines the horizontal frequency in chars. If the internal
counter of the 6845 has reached this value a HSYNC is generated leading to
a horizontal retrace. Load this register with 97 in text mode. So this leads
to 97chars*0.5625ęs=54ęs <=> 18.45Khz, the horizonzal frequency.
horizontal visible (1) = 80
this register hold the visible characters per row. This value has to be lower
than the horizontal total value. The lesser the difference between those two
values gets, the faster the horizontal retrace has to occur. Not all monitors
can handle fast retraces, resulting in damaged monitors. So leave this value
at 80 chars per row.
hsync position (2) = 82
at the character position set with this register the horizontal retrace
(hsync signal) is activated. this register has to be greater than
horizontal visible (1) and the sum of hsync position (2) and sync width (3)
has to be lower than horizonzal total (0).
If you increase this register the entire screen will be moved leftwards and
vice versa.
Set this register to 82. So one row consits of 80 printable characters, one
invisble character and 15 chars used for the horizontal retrace. the hsync
signal is therefore activated for 15chars=8.4375ęs.
sync width (3) = 15
the width (time) used for the hsync signal (as always defined in characters).
you can use values from 1-15 in this register. 0 would disable the hsync.
load this register with 15 for the standard text mode.
vertical total (4) = 25
this register defines the number of rows to process -1. remember that the
6845 has to produce a refresh rate of 50Hz. this leads to a fractional
number of rows per frame. the finetuning of the vertical retrace is covered
in the following register. Set this register to 25.
vertical finetune (5) = 6
this register sets additional raster lines to register (4).
Standard value for this register is 6. So the HGC produces 6 invisible
raster lines of the 26 defined above, before activating the VSYNC. this
leads to a perfect refresh rate of 50Hz.
vertical visible (6) = 25
the number of visible rows. Should be set to 25.
vsync position (7) = 25
the row -1 in which the vsync signal is generated. this register has to be
greater or equal to register (6). if you increase this value the screen
will move upwards and vice versa.
Standard value is 25.
interlace mode (8) = 2
the HGC can use the following interlaced modes:
max.rasterline (9) = 13
this register defines the number of rasterlines per textmode row -1.
This highest possible value is 32. Standard value is 13.
cursor start line (10) = 11
rasterline in which the cursor starts. bits 0 - 4 define the rasterline.
bit 6 | bit 5 | |
0 | 0 | no blinking |
0 | 1 | cursor off |
1 | 0 | blink with 16*period |
1 | 1 | blink with 32*period |
cursor end line (11) = 12
standard value 12. so the cursor is two rasterlines high.
start adress high (12) / low (13) = 0
a 14bit value defining the start adress of the textmode/graphics memory.
Standard value is 0. you can use this value to make efficient hardware
scrolling in text mode.
cursor adress high (14) / low (15) = 0
this 14bit value hold the cursor position inside the memory.
light-pen high (16) / low (17) = 40
the position of the light-pen as a 14bit value.
If you want to change the display mode of the HGC use the following table.
index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
text | 97 | 80 | 82 | 15 | 25 | 6 | 25 | 25 | 2 | 13 | 11 | 12 | 0 | 0 |
gfx | 53 | 45 | 46 | 7 | 91 | 2 | 87 | 87 | 2 | 3 | 0 | 0 | 0 | 0 |
Now some C source code to enable/disable the text mode on a hercules card.
#include <conio.h> #define hgc_index 0x3b4 #define hgc_data 0x3b5 #define hgc_mode 0x3b8 #define hgc_conf 0x3bf void hgcGfxOn(void) { unsigned char table[]={53,45,46,7,91,2,87,87,2,3,0,0,0,0,0,0}; outp(hgc_conf, 1); // allow graphics mode outp(hgc_mode, 2); // gfxmode on; screen off for ( int i=0; i<16; i++ ) { outp(hgc_index, i); outp(hgc_data, table[i]); } outp(hgc_mode, 2+8); // screen on; } void hgcGfxOff(void) { unsigned char table[]={97,80,82,15,25,6,25,25,2,13,11,12,0,0,0,0}; outp(hgc_mode, 32); // textmode on; blink off; screen off; for ( int i=0; i<16; i++ ) { outp(hgc_index, i); outp(hgc_data, table[i]); } outp(hgc_mode, 32+8); // screen on; }
Disabling printer on monochrome cards
I found this tip on the Hercules homepage:
24 | 13 | |
notch -> | BIOS | |
1 | 12 |
IBM 9 pin monochrome pinout
|