October 21, 2012

Using FONTX font files


DOS/V diskette

Nowadays the font files in FONTX2 format is often used in hobby electronics projects. This page describes about the background of FONTX and how to use the FONTX files for your projects.

DOS/V - FONTX - Electronics Projects

What is DOS/V?

DOS/V system

In early '90s, "IBM DOS J4.0/V" called DOS/V was released. The DOS/V consists of PC DOS and additional device drivers to handle Japanese characters (Kanji). It could display Kanji on the display of IBM AT or compatibles without any add-on board. Right image shows the system diagram of DOS/V. The "V" added end of the product name denotes VGA and it means "IBM Japanese DOS version 4.0 for VGA".

The display driver ($DISP.SYS) extends the video BIOS (INT 10h) and it processes the character output request by application program. The character is drawn on the graphic screen instead of character screen, therefore it can display arbitrary fonts including Kanji. This enabled _a few_ English applications to handle Japanese without any modification. The reason of only a few applications is that the most of DOS applications bypass the video BIOS and write characters into the VRAM directly. The display driver also supports virtual VRAM to minimize cost of development and porting the applications, however, supporting the Japanese was not easy because of handling of double byte character that not exist in alphabet bloc.

The font driver ($FONT.SYS) manages the Kanji font. It loads the font files to the memory on start up and it works as a font server via system BIOS (INT 15h). The font data amounted to 200K bytes is placed on EMB memory, so that it does not consume conventional momory but the DOS/V requires 80286 or higher.

DOS/V and FONTX

At that time, NEC PC-9800 series PCs that supports hardware Kanji character screen was occupying the business PC market in Japan. The new entry of DOS/V architecture into the mature architecture as Japanese business PC was a big topic. Some magazines related to DOS/V started to issue, and DOS/V drivers with new functions were released by hackers in succession.

As for the display drivers, it supported some type of display sub-systems in addition to the regular VGA. Most of them supported SVGA and the graphics accelerator for wide character screen with fast drawing. Some drivers supported CGA for pocket PCs. IBM also followed these implementations and released add-on drivers as "DOS/V EXTENSION" package. With it, the mean of "V" has been redefined from VGA to Variable. Also I was developping some display drivers as one of the DOS/V freaks :-)

As for the font drivers, there were some expansions, reload font and change it on the fly, selectable font buffer memory other than EMB, such as EMS memory, conventional memory and hardware specific bank memory, to enable support of XT based pocket PCs. The number of font drivers released was not many as display drivers. The FONTX was a set of font driver and font converter tools released first and gets the major font driver as freeware. As the result, all DOS/V font files that has been released as freeware are in FONTX format.

FONTX coming back from death's door

A few years later, the time went to Windows age and MS-DOS age with DOS/V archtecture has closed. The number of software resources and DOS/V fonts have been passed into oblivion. However, after middle of '00s, the use of 32-bit microcontrollers and graphic display modules have spread even to hobby electronics projects. With this trend, FONTX files came to be used to output Kanji characters into the graphic LCD module. The FONTX is a bitmap font format suitable for such use because the file format is opened and many free font files are found on the internet. Therfore the FONTX became to be noticed again. But in only electronics projects as a minor world.

How to use FONTX files

FONTX format

The FONTX file is, unlike BDF file, in binary form shown below. There are two type of font file, single byte code font and double byte code font. The font type is identified by code flag. The single byte code font file has 256 font images. The double byte font uses valid code range table to store only some thousands of Shift_JIS code fonts out of 65536. The font image is stored in order of listed in the code range table.

Single byte code FONTX file
OffsetSizeDescription
06File signature("FONTX2")
68Font name
141Font width WF(dot)
151Font height HF(dot)
161Code flag (0:ANK)
17*1Font image
(*1:Font size * 256)
Double byte code FONTX file
OffsetSizeDescription
06File signature("FONTX2")
68Font name
141Font width WF (dots)
151Font height HF (dots)
161Code flag (1:Shift JIS)
171Number of code blocks NB
182Block 1 startCode block table
(little endian)
202Block 1 end
14+4*NB2Block NB start
16+4*NB2Block NB end
18+4*NB*2Font image
(*2:Font size * total number of codes)

The image shown below is the font image stored on the file. The font face is in left-justified if the font width is not equal to multiple of 8.

Font example

The font size becomes (WF + 7) / 8 * HF [bytes]. The offset where the top of font image data from top of the file are:

To edit the FONTX file, a font editor supports the FONTX format is required. However the FONTX editor for Windows had not been developped because the FONTX was already not needed in Windows age, so that I built a simple FONTX editor.

Sample code

This is an example to get the font image in the FONTX file stored on the memory. The two arguments specifies pointer to the FONTX data and character code. If the code is not found in the font data, it returns a NULL.

const uint8_t* get_font (   /* Returns pointer to the font image (NULL:invalid code) */
    const uint8_t* font,    /* Pointer to the FONTX file on the memory */
    uint16_t code           /* Character code */
)
{
    unsigned int nc, bc, sb, eb;
    uint32_t fsz;
    const uint8_t *cblk;


    fsz = (font[14] + 7) / 8 * font[15];  /* Get font size */

    if (font[16] == 0) {  /* Single byte code font */
        if (code < 0x100) return &font[17 + code * fsz];
    } else {              /* Double byte code font */
        cblk = &font[18]; nc = 0;  /* Code block table */
        bc = font[17];
        while (bc--) {
            sb = cblk[0] + cblk[1] * 0x100;  /* Get range of the code block */
            eb = cblk[2] + cblk[3] * 0x100;
            if (code >= sb && code <= eb) {  /* Check if in the code block */
                nc += code - sb;             /* Number of codes from top of the block */
                return &font[18 + 4 * font[17] + nc * fsz];
            }
            nc += eb - sb + 1;     /* Number of codes in the previous blocks */
            cblk += 4;             /* Next code block */
        }
    }

    return 0;   /* Invalid code */
}