Battle Isle 2

Bitmap fonts

LIB/CHAR006.CHR, CHAR009.CHR, CHAR011.CHR, CHAR013.CHR

Four variable-width glyph banks that draw all of the game's text.

The CHAR###.CHR files are the game's bitmap fonts. Each holds up to 256 variable-width glyphs indexed by character code, stored as 8-bit palette indexes; the number in the file name is the font's line height.

A font file has two parts. The first is a 516-byte header (FontHeader): a table of 256 two-byte slots, one per character code, followed by two metrics words. The second is the glyph records (Glyph), stored one after another. A slot in the table holds the file offset where that character's glyph record starts, so the header is how you find the glyphs. Zero means the character has no glyph.

× 60–90 per font
Point at the bar to name a field; select it to jump to its chapter and row.

Cut blocks are not drawn to scale; every other block is as wide as its bytes. The stack stands for all the records of that kind, one for each non-zero slot of the offsets table; the one drawn is opened up into its fields. Dashed blocks hold the same value in every record. The file does not store how many records there are: count the non-zero slots in glyph_offsets. The game keeps the whole font in memory and finds a glyph by its character code each time it draws one.

File Layout

516 bytes3 fields● 3 ◐ 0 ○ 0values from LIB/CHAR006.CHR, CHAR009.CHR, CHAR011.CHR, CHAR013.CHR, 4 headers

Header

3 fields · 516 bytes
0x0000u16le[256]glyph_offsets ●0–10360319 distinct valuesOffset table indexed by character code: slot 65 is A, slot 97 is a.
0x0200u16lebaseline ●4 · 6 · 8 · 10Native formatted-text drawing adjusts y by the maximum baseline on the line minus this font's value.
0x0202u16leline_height ●6 · 9 · 11 · 13Font-level cell height, used as the line advance.
variable size8 fields● 7 ◐ 1 ○ 0values from LIB/CHAR006.CHR, CHAR009.CHR, CHAR011.CHR, CHAR013.CHR, 329 glyph records

Glyph

8 fields · 18 bytes
0x00u8[8]reserved_prefix ◐always 0All zero in every populated glyph of the four shipped fonts.
0x08u8transparent_index ●always 0x60The pixel value that means "draw nothing here": the typed U blitter (the routine that copies a glyph's pixels to the screen) skips every sample equal to this byte before applying the caller's colour offset.
0x09u8record_type ●always 0x550x55 (U) in all shipped glyphs; selects the byte-per-pixel planar blitter.
0x0as16lex_offset ●always 0Added to caller x before clipping and drawing.
0x0cs16ley_offset ●always 0Added to caller y before clipping and drawing.
0x0eu16lewidth ●1–1010 distinct valuesGlyph width in pixels.
0x10u16leheight ●6 · 9 · 11 · 13Glyph height in pixels.
0x12..endu8[]pixels ●Plane-interleaved indexed samples: four planes, plane p holding the columns where x % 4 == p, each scanned top to bottom.

The fonts also contain the German umlauts, at their DOS code page 437 positions: ü 0x81, ä 0x84, Ä 0x8e, ö 0x94, Ö 0x99, Ü 0x9a.

Example: the letter A in CHAR011.CHR

A is character code 65, so its slot in the header is at byte 65 x 2 = 0x82.

0x0082  10 0c         glyph_offsets[65] = 0x0c10, so the glyph for "A" starts at 0x0c10
0x0200  08 00         baseline = 8
0x0202  0b 00         line_height = 11

0x0c10  00 00 00 00 00 00 00 00   reserved_prefix
0x0c18  60                        transparent_index
0x0c19  55                        record_type ("U")
0x0c1a  00 00                     x_offset = 0
0x0c1c  00 00                     y_offset = 0
0x0c1e  09 00                     width = 9
0x0c20  0b 00                     height = 11
0x0c22  pixels, 9 x 11 = 99 bytes, in four planes:
          plane 0 (columns 0, 4, 8): 60 f0 60 60 f0 60 60 f0 60 60 60 60 60 60 60 60 f0 60 ee f0 ee f0 60 f0 f0 60 f0 60 60 60 60 60 60
          plane 1 (columns 1, 5): 60 ee 60 f0 60 f0 60 f0 60 f0 f0 f0 f0 f0 f0 60 f0 60 60 60 60 60
          plane 2 (columns 2, 6): 60 60 60 60 ee ee f0 f0 f0 f0 f0 f0 f0 f0 ee ee 60 60 60 60 60 60
          plane 3 (columns 3, 7): ee 60 f0 60 f0 60 f0 60 f0 60 f0 f0 f0 f0 60 f0 60 f0 60 60 60 60

Planes are counted per glyph, not across the file. Column x of a glyph is always in plane x % 4, counting from the glyph's own left edge, so every glyph starts again at plane 0 and its pixel bytes are self-contained. A glyph 9 columns wide has three columns in plane 0 and two in each of the others. Each plane is read top to bottom, and the planes are then interleaved on screen. The drawing also shows where the header's baseline and line_height fall: a capital sits on row 8 (the baseline), and a text line is 11 rows tall.

How the 9 x 11 glyph is stored as four planes and drawn column by columnIn the filefour planes, each read top to bottomOn screen9 x 11 pixels, columns interleavedwidth 9plane 0plane 1plane 2plane 3→x=0x=1x=2x=3x=4x=5x=6x=7x=8baseline 8line_height 11(= height 11)0x60: transparent, nothing is drawn0xee: mid shade (grey)0xf0: full ink (white)

In text form the same glyph is below: . is the transparent value 60, # is full ink f0 and o is the mid shade ee, which softens the corners of the strokes.

...o#o...
...###...
..o###o..
..##.##..
..##.##..
.#######.
o#######o
##o...o##
##.....##
.........
.........