VGA Fonts

From OSDev.wiki
Revision as of 11:42, 16 February 2012 by osdev>Turdus (Created page with "== Preface == So you know how to display characters in text mode, and now you want to do it in graphics mode. It's not complicated, but definitely more complex than writing an...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Preface

So you know how to display characters in text mode, and now you want to do it in graphics mode. It's not complicated, but definitely more complex than writing and ASCII code at a specific offset in memory. You'll have to do it pixel by pixel.

But how do you know what to draw? It's stored in data matrix called bitmap fonts.

Decoding of bitmap fonts

How is a character stored in memory? It's quite simple, 0 encodes background, 1 encodes foreground color. Each byte contains one row. For letter 'A' it would be (in binary):

00000000b  byte  0
00000000b  byte  1
00000000b  byte  2
00010000b  byte  3
00111000b  byte  4
01101100b  byte  5
11000110b  byte  6
11000110b  byte  7
11111110b  byte  8
11000110b  byte  9
11000110b  byte 10
11000110b  byte 11
11000110b  byte 12
00000000b  byte 13
00000000b  byte 14
00000000b  byte 15

The full bitmap contains bitmaps for every character, thus it's 256*16 bytes, 4096 bytes long. If you want to get the bitmap for a specific character, you have to multiply the ASCII code by 16 (number of rows in a character), add the offset of your bitmap and you're ready to go.

How to get fonts?

There're several ways. You can have it in a file on your filesystem. You can hardcode it in an array. But sometimes 4k is so much that you cannot afford, and reading a file is not an option (like in a boot loader), in which case you'll have to read the one used by the card (to display text mode characters) from VGA RAM.

Store it in an array

Easiest way, but increases your code by 4k.

Store it in a file

Most modular way. You can use different fonts if you like. Downside you'll need a working filesystem implementation.

Get from VGA RAM via BIOS

It's a standard BIOS call (you can trust it's exists and bugfree). If you're still in real mode, it's quite easy to use.

		;in: es:di=4k buffer
		;out: buffer filled with font
		push			ds
		push			es
		;ask BIOS to return VGA bitmap fonts
		mov			ax, 1130h
		mov			bh, 6
		int			10h
		;copy charmap
		push			es
		pop			ds
		pop			es
		mov			si, bp
		mov			cx, 256*16/4
		repnz			movsd
		pop			ds

Get from VGA RAM directly

Maybe you're already in protected mode, so cannot access BIOS functions. In this case you can still get the bitmap by programming VGA registers:

		;in: edi=4k buffer
		;out: buffer filled with font
		;clear even/odd mode
		mov			dx, 03ceh
		mov			ax, 5
		out			dx, ax
		;map VGA memory to 0A0000h
		mov			ax, 0406h
		out			dx, ax
		;set bitplane 2
		mov			dx, 03c4h
		mov			ax, 0402h
		out			dx, ax
		;clear even/odd mode (the other way, don't ask why)
		mov			ax, 0704h
		out			dx, ax
		;copy charmap
		mov			esi, 0A0000h
		mov			cx, 256*16/4
		repnz			movsd
		;restore VGA state to normal operation
		mov			ax, 0302h
		out			dx, ax
		mov			ax, 0304h
		out			dx, ax
		mov			dx, 03ceh
		mov			ax, 1005h
		out			dx, ax
		mov			ax, 0A06h
		out			dx, ax

It worth mentioning that it has to be done _BEFORE_ you switch to VBE graphics mode, because VGA registers are usually not accessible afterwards.

Set VGA fonts

It's only make sense if you're still in text mode and want the VGA card to draw different glyphs. It's worthless in graphics mode (because characters displayed by your code there, not by the card), I only wrote this section for completeness. Modifying the font bitmaps in VGA RAM isn't hard if you read carefully what's written so far. I'll left it to you as a homework.

Set fonts via BIOS

Hint: check Ralph Brown Interrupt list Int 10/AX=1110h.

Set fonts directly

Hint: use the same code as above, but swap source and destination for "repnz movsd".