Theoretical Paper
- Computer Organization
- Data Structure
- Digital Electronics
- Object Oriented Programming
- Discrete Mathematics
- Graph Theory
- Operating Systems
- Software Engineering
- Computer Graphics
- Database Management System
- Operation Research
- Computer Networking
- Image Processing
- Internet Technologies
- Micro Processor
- E-Commerce & ERP
Practical Paper
Industrial Training
Loading Installable Fonts
Loading Installable Fonts
Several Wordprocessors and DTP softwares provide numerous fonts to work with. Though a lot has been said about font generation in graphics mode not much literature is available about font generation in text mode. For example, what do I do if I am to generate Devnagari characters in text mode? For this character generation functions are available for MCGA/EGA/VGA+ adapters. These functions are grouped under interrupt 16 function 11. Function 11 provides a number of sub-functions to set and get character generation features on the MCGA, EGA, and VGA+ adapters. Obviously, different adapters have slight differences in implementation of these sub-functions. Following is the list of these functions.
AL = | Character Generator Sub-functions | Adapters/Drivers |
0 | Load User Font |
VGA+,EGA,MCGA |
1 | Load 8x14 Font |
VGA+,EGA,MCGA |
2 | Load 8x8 Font |
VGA+,EGA,MCGA |
3 | Select Font Mode |
VGA+,EGA,MCGA |
4 | Load 8x16 Mode |
VGA+,MCGA |
10h | Load User Font After Mode Set |
VGA+,EGA,MCGA |
11h | Load 8x14 Font After Mode Set |
VGA+,EGA,MCGA |
12h | Load 8x8 Font After Mode Set |
VGA+,EGA,MCGA |
14h | Load 8x16 Font After Mode Set |
VGA+,MCGA |
20h | Set Int 1Fh Graphics Font Pointer |
VGA+,EGA,MCGA |
21h | Set Int 43h Graphics Font Pointer |
VGA+,EGA,MCGA |
22h | Load 8x14 Font into Int 43h |
VGA+,EGA,MCGA |
23h | Load 8x8 Font into Int 43h |
VGA+,EGA,MCGA |
24h | Load 8x16 Font into Int 43h |
VGA+,MCGA |
30h | Get Font Information |
VGA+,EGA,MCGA |
Although the list of sub-functions skips over some sub-function numbers, these are unused and will simply return without any action on an EGA/VGA adapter. Future adapters may assign currently unused sub-functions to new uses.
Let us now see how the ASCII character codes are converted into actual character shapes on the screen. For converting an ASCII character code into an array of pixels on the screen, a translation table or Character Generator is used. On older display adapters such as MA and CGA, the character generator is located in ROM. Newer adapters like EGA and VGA do not use a character generator ROM. Instead, in these adapters character generator data is loaded into plane 2 of the display RAM. This feature makes it easy for custom character sets to be loaded. Multiple character sets (up to 4) may reside in RAM simultaneously. Each character set can have 256 characters.
Character width is fixed at eight pixels (this is stretched to nine for monochrome text). Character height is selectable from 1 to 32 pixels. The standard character sets which are provided with the EGA are the CGA character set (8 pixels wide by 8 pixels tall), and the enhanced colour character set (8 pixels wide by 14 pixels tall.) One of these character sets is automatically loaded by the BIOS when a text operating mode is selected. If a monochrome text mode is selected, the 8 x 14 enhanced colour character set is used, but several characters in the set are replaced with characters that are optimized for the 9 pixel wide monochrome character cell. Because of its higher resolution capabilities, the VGA also includes a 9 pixel wide by 16 pixel tall character set. Custom character sets can be loaded using the BIOS video services.
Irrespective of the character height being used, characters always begin on 32 byte boundaries. For instance, the 8 pixel by 14 pixel character set requires 14 bytes per character, so 18 bytes per character go unused in the character map.
The location of character maps in memory is shown below.
Character Map A Character Map B 0000h to 001Fh - Char.0 2000 to 201Fh - Char.0 0020h to 003Fh - Char.1 2020h to 203Fh - Char.1 0041h to 005Fh - Char.2 2040h to 205Fh - Char.2 .... .... ..... .... .... .... .... .... 1FE0h to 1FFFh - Char.255 3FE0h to 3FFFh - Char.255 Character Map C Character Map D 4000h to 401Fh - Char.0 6000h to 601Fh - Char.0 5FE0h to 5FFFh - Char.255 7FE0h to 7FFFh - Char.255 For VGA only: Character Map E Character Map F 8000h to 801Fh - Char.0 A000h to A01Fh - Char.0 9FE0h to 9FFFH - Char.255 BFE0h to BFFFh - Char.255 Character Map G Character Map H C000h to C01Fh - Char.0 E000h to E01Fh - Char.0 DFE0h to DFFFh - Char.255 FFE0h to FFFFh - Char.255Internal to the adapter are a number of 32x256 font pages. Each 32-byte font block in a font page describes the bits to use for each text character. In most cases only a portion of the 32 bytes make up the complete character. For example, the EGA's standard 8x14 font is made up of 14 bytes. The character "T" appears as:
Byte |
Bits 76543210 |
0 |
00000000 |
1 |
01111110 |
2 |
01111110 |
3 |
01011010 |
4 |
00011000 |
5 |
00011000 |
6 |
00011000 |
7 |
00011000 |
8 |
00011000 |
9 |
00011000 |
10 |
00111100 |
11 |
00000000 |
12 |
00000000 |
13 |
00000000 |
While loading a user font, we need to supply only the number of bytes per character that make up the character cell. For an 8x14 font, the user font table will have 14x256 bytes. All font characters for text modes are stored in the red plane, plane number 2, in the high-resolution graphics memory area. The following program puts this theory into a program to generate the relevant devanagari characters when you hit A, B, C, D from the keyboard.
#pragma inline
#include "dos.h"
main( )
{
unsigned seg, off ;
unsigned char far ( tbl[56] ) =
{
/* bitmap for Devanagari equivalent of A */
0x00, 0x00, 0xFF, 0x92, 0x0A, 0x0A, 0x12,
0x7E, 0x12, 0x0A, 0x0A, 0x92, 0x62, 0x00,
/* bitmap for Devanagari equivalent of B */
0x00, 0x00, 0xFF, 0x02, 0x3A, 0x66, 0x92,
0x8A, 0x46, 0x3A, 0x02, 0x02, 0x02, 0x00,
/* bitmap for Devanagari equivalent of C */
0x00, 0x00, 0xFF, 0x08, 0x28, 0x5A, 0x89,
0x99, 0x69, 0x0D, 0x0A, 0x08, 0x08, 0x00,
/* bitmap for Devanagari equivalent of D */
0x00, 0x00, 0xFF, 0x04, 0x3C, 0x44, 0x40,
0x3C, 0x02, 0x42, 0x22, 0x1C, 0x00, 0x00,
} ;
seg = FP_SEG ( tbl ) ;
off = FP_OFF ( tbl ) ;
_AH = 0x11 ; /* service number */
_AL = 0 ; /* subfunction number */
_BH = 14 ; /* bytes per character */
_BL = 0 ; /* character set number */
_CX = 4 ; /* number of characters defined by table */
_DX = 'A' ; /* first character in the table */
/* store segment:offset of font table in ES:BP */
_ES = seg ;
asm push bp
asm mov bp, off
geninterrupt ( 0x10 ) ;
_DX = 'a' ;
geninterrupt ( 0x10 ) ;
asm pop bp
}
To begin with, we have stored the bitmaps of equivalent Devanagari characters in the array tbl[ ]. Since each character is assumed to be of size 8x14 and there are four characters to be loaded the size of the array is kept as 56 bytes. To accommodate more characters you may add their bitmaps and increase the array size correspondingly. Next interrupt 10h, function 10h, sub-function 0h is called to load these bitmaps in character generator RAM. The same service is called once again to ensure that the Devanagari characters appear even for smallcase equivalents of A to D. Remember to compile the program using the TCC compiler by giving the command:
C>TCC -Emasm.exe ' filename'
The MA and CGA adapters permitted the usage of only 1 character set of 256 characters generated by the ROM character generator. As against this, in EGA and VGA at a time two character sets may be active, giving them the capability to display up to 512 different characters on the screen simultaneously. Suppose we are to write a program to demonstrate how two sets of characters can be used. Out of the two 256 character sets we can load only one set through our program, whereas the default character set can be used as the other set. When two character sets are active, the text attribute bit 3 selects which character set will be used when you type a key. Before we can use bit 3 for this purpose the normal foreground intensity function of text attribute bit 3 should be disabled. This is done by loading the second eight palette registers to equal the first eight palette registers. For this interrupt 10h, function 10h, sub-function 2h can be used. Once this is done, we have to set the Character Generator Select Register to a value 4 to select characters sets 0 and 1. This enables the bit 3 in attribute byte to select either first or second set of 256 characters. This is achieved by calling interrupt 10h, function 11h, sub-function 3h. Next we can use calls to writestring( ) function to show how the two different character sets can be used. Here is the program which implements all these details.
#pragma inline
#include "dos.h"
char far *scr = 0xB8000000 ;
main( )
{
unsigned seg, off ;
unsigned char far *equip = 0x410 ;
unsigned char d_col[ ] = { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0 } ;
unsigned char far ( tbl[56] ) =
{
/* bitmap for Devanagari equivalent of A */
0x00, 0x00, 0xFF, 0x92, 0x0A, 0x0A, 0x12,
0x7E, 0x12, 0x0A, 0x0A, 0x92, 0x62, 0x00,
/* bitmap for Devanagari equivalent of B */
0x00, 0x00, 0xFF, 0x02, 0x3A, 0x66, 0x92,
0x8A, 0x46, 0x3A, 0x02, 0x02, 0x02, 0x00,
/* bitmap for Devanagari equivalent of C */
0x00, 0x00, 0xFF, 0x08, 0x28, 0x5A, 0x89,
0x99, 0x69, 0x0D, 0x0A, 0x08, 0x08, 0x00,
/* bitmap for Devanagari equivalent of D */
0x00, 0x00, 0xFF, 0x04, 0x3C, 0x44, 0x40,
0x3C, 0x02, 0x42, 0x22, 0x1C, 0x00, 0x00,
} ;
clrscr( ) ;
seg = FP_SEG ( tbl ) ;
off = FP_OFF ( tbl ) ;
_AH = 0x11 ; /* service number */
_AL = 0 ; /* subfunction number */
_BH = 14 ;/* bytes per character */
_BL = 1 ; /* character set number */
_CX = 4 ; /* number of characters defined by table */
_DX = 'A' ; /* first character in the table */
/* store segment:offset of font table in ES:BP */
_ES = seg ;
asm push bp
asm mov bp, off
geninterrupt ( 0x10 ) ;
_DX = 'a' ;
geninterrupt ( 0x10 ) ;
asm pop bp
/* reload upper 8 palette registers */
_AH = 0x10 ;
_AL = 2 ;
/* load segment:offset of colour palette in ES:DX */
_ES = _DS ;
_DX = d_col ;
geninterrupt ( 0x10 ) ;
/* select active character sets */
_AH = 0x11 ;
_AL = 3 ;
_BL = 4 ; /* block specifier ( attb. bit 3=0 - set 0, attb. bit 3=1 - set 1 ) */
geninterrupt ( 0x10 ) ;
writestring ( "ABCDEFG", 0, 0, 7 ) ; /* use set 0 */
writestring ( "ABCDEFG", 1, 0, 15 ) ; /* use set 1 */
}
writechar ( char ch, int r, int c, int attb )
{
* ( scr + r * 160 + c * 2 ) = ch ;
* ( scr + r * 160 + c * 2 + 1 ) = attb ;
}
writestring ( char *str, int r, int c, int attb )
{
while ( *str )
writechar ( *str++, r, c++, attb ) ;
}