The C64 used a fatter double-width font because the video quality of early VIC-IIs wasn't very good. Therefore they had to make the C64's font fatter than the VIC-20's. However, this fatter font look quite nice and there's an easy way of replicating something similar on the VIC-20.
Rather than loading in a whole new font we can double the width of the existing font stored in ROM to create a new fatter font in RAM, which we can then point to.
Standard Character Definitions
Each character definition is stored in ROM and for this demonstration we'll base our new fatter font on the uppercase characters stored from location 32768 ($8000). Because this example is for an unexpanded VIC-20 we'll only use the first 64 characters.
The Vic uses 8x8 fonts as default and each character definition is stored as a series of 8 bytes with each byte representing a row of the definition.
Fat Double-width Character Definition
To create the double-width font we get the value of each line of the original font, double it and then OR it with the original value. This has the effect of doubling each pixel's width in the character definition.
This looks like the following where
a equals the original value of the row in the character definition and
b is the new value.
b := a or (a*2)
All we need to do then is go through each row of each character definition and store the results in RAM. Once we have stored them in RAM, we use location 36869 ($9005) to set the character map address to our location in RAM.
A Short Program to Create a Fat Font
The following program will use the first 64 characters of the uppercase character set to create a double-width font. Because we're only altering the first 64 characters it means that the reverse characters aren't defined as usual so the cursor won't blink properly nor will the characters above 63 be defined properly.
First we'll create a little routine in assembly language to create the double-width font in RAM from location 7168 ($1C00). This location is being used because we are creating a custom character set with 64 entries and 7680 (Start of screen memory) - 512 (8*64 characters) = 7168.
ldy #$00 loop lda $8000,y ; Get row of character from ROM asl ; Double the value for the row ora $8000,y sta $1C00,y ; Store row of character in RAM lda $8100,y ; Get row of character from ROM asl ; Double the value for the row ora $8100,y sta $1D00,y ; Store row of character in RAM iny bne loop rts
Thanks to C.S. Bruce for his suggestions to make this more succinct.
Next we assemble the routine to machine code using location $02A1-$02BA to store it in.
02A1: A0 00 B9 00 80 02A6: 0A 19 00 80 99 02AB: 00 1C B9 00 81 02B0: 0A 19 00 81 99 02B5: 00 1D C8 D0 E9 02BA: 60
Finally we create a short program to load the machine code routine into memory, execute it and point to the new character map.
10 poke 52,28:poke 56,28:clr 20 for i=673to698:read a:poke i,a:next i 30 sys 673 40 poke 36869,255 50 data 160,0,185,0,128,10,25,0,128,153 60 data 0,28,185,0,129,10,25,0,129,153 70 data 0,29,200,208,233,96
It is worth highlighting a few points in the code:
- Location 51/52 points to the bottom of BASIC active strings and hence the top of available free space. On an unexpanded system it defaults to: 7680 ($1E00), by poking 28 ($1C) into 52 this lowers it to 7168 ($1C00).
- Location 55/56 points to the end of BASIC memory. On an unexpanded system it defaults to: 7680 ($1E00), by poking 28 ($1C) into 56 this lowers it to 7168 ($1C00).
- The command
clr, clears program variables and registers the bottom of BASIC active strings and end of BASIC memory.
- Location 673 ($02A1) is the location we assembled the machine code to. There is an area of memory from 673-767 ($02A1-$02FF) which is used for user indirect vectors or other storage and hence is a good location to put our machine code routine.
- Location 36869 ($9005) controls the location of the character set. We set it to 255 as this sets the location to 7168 ($1C00), just below the screen map at 7680 ($1E00). To see more about setting the character map location look at: Mapping the Vic, p.129-133.
Video Demonstrating Fat Font
The double-width fat font can be seen in the following video.