• Please review our updated Terms and Rules here

ASCII / BIOS Character Graphics

neilobremski

Experienced Member
Joined
Oct 9, 2016
Messages
55
Location
Seattle, USA
Even back on the original IBM PC you could get read-only access to the glyph pixel data for the standard ASCII character set, extended ASCII, and control characters with codes less than 32 (0x20) [SUP][1][/SUP].

Each character glyph is 8 bytes where every byte represents a row and every bit represents a column. The horizontal bits start in the most significant bit, so the font pixel for column 0, row 0 is bit 7 in byte 0 which follows the style for monochrome graphics modes.

The font tables themselves are split in two. The first 128 characters (0 - 127) contain a couple dozen special DOS glyphs followed by standard ASCII; you'll find them starting at the specific memory address 0xF000:FA6E. For the second half of the character data there is some indirection: the vector table entry 0x1F contains a pointer to the actual memory address of the data.

Below is a C function I wrote for the original Magenta's Maze which returns a far pointer to the character of choice:

Code:
/* returns start address of bios character glyph (each one is 8 bytes) */
unsigned char far *bioschar(unsigned char c)
{
	/* INT 0x1F refers to a block of memory for codes 128+ */
	static unsigned long far *vector1f = (unsigned long far*)(0x1f * 4);

	/* F000:FA6E contains first 127 ASCII characters */
	unsigned char far *p = (unsigned char far*)0xF000FA6E;

	if (252 == c) { /* patch for ^3 superscript */
		static unsigned char superscript3[8] = {
			0x70, 0x08, 0x30, 0x08, 0x70, 0x00, 0x00, 0x00 };
		return (unsigned char far *)superscript3;
	}

	/* upper ASCII (128 - 255) retrieved with INT 1F vector */
	if (c > 127) {
		p = (unsigned char far*)(*vector1f);
		c -= 128;
	}

	return p + (((int)c) << 3);
}

Now that I'm writing a version in assembler I had to create something similar there. Below is one I wrote over a month ago and it shows!

Code:
a 370
; ----------------------------------------------------------------------------
; BIOSCHAR ()							:BIOSCHAR
;
; AL = character
;
; modifies DS:SI!
;
CMP	AL, FC	; 370
JNZ	037A	; 372
MOV	SI, 03B0; 374
RET		; 377
NOP		; 378
NOP		; 379
CMP	AL, 80	; 37A
JAE	0392	; 37C
XOR	AH, AH	; 37E
SHL	AX, 1	; 380
SHL	AX, 1	; 382
SHL	AX, 1	; 384
MOV	SI, FA6E; 386
ADD	SI, AX	; 389
MOV	DX, F000; 38B
MOV	DS, DX	; 38E
RET		; 390
NOP		; 391
XOR	AH, AH	; 392
SUB	AL, 80	; 394
SHL	AX, 1	; 396
SHL	AX, 1	; 398
SHL	AX, 1	; 39A
MOV	DX, 0000; 39C
MOV	DS, DX	; 39F
MOV SI, [007C]	; 3A1
ADD	SI, AX	; 3A5
MOV DX, [007E]	; 3A7
MOV	DS, DX	; 3AB
RET		; 3AD
NOP		; 3AE
NOP		; 3AF

e 3b0 70 08 30 08 70 00 00 00

Footnotes:

[SUP][1][/SUP]. https://en.wikipedia.org/wiki/Code_page_437 . I'd like to add that although the symbols and their dimensions are the same across all IBM compatibles, their representations are not. This makes the textures a bit of a surprise in Magenta's Maze because they depend on the underlying machine.
 
Back
Top