Amiga 8x8 font convertor

The Speccy's spritely young offspring. Discuss everything from FPGA to ZX
Post Reply
User avatar
Manic Miner
Posts: 279
Joined: Thu Feb 08, 2018 1:01 pm

Amiga 8x8 font convertor

Post by MonkZy »

I am working on a project that requires a full ANSI character set. The ZX Spectrums have an ASCII compliant character set which contains the glyphs for character codes 32 through to 126. Only the glyph for character 96 is changed, swapping a left slanted apostrophe with the UK pound sign. An extra glyph is added for character 127 (usually the delete control code) where a copyright symbol is placed on the Spectrum. Later computers used an extended character set which I will refer to as ANSI. ANSI sets include extra glyphs between character codes 160 and 255. These characters are not defined in the Spectrum ROM. An easy way to grab a full ANSI font is to convert a font from the Amiga computer.

The converter is written in nextBASIC and requires at least nextOS 2.08 to run. It works fine on CSpect but at the time of writing only version V2.19.4.4 will run NextOS 2.08


The program asks for a filename for the font, this can include the path. Amiga fonts are organized as a .font file and a similarly named folder containing numerically named files for each height of the font. The file needed is the '8' from this folder. If no file named 8 exists the font is not suitable. The .font file is not needed for the convertor. The font is checked to see if it is 8x8, any other sized fonts will not work. The font is checked to see if it has characters for at least codes 32-126. The font is then read from the file and loaded into memory as two standard font structures, one for 32-127 and another for 160-255. Chars 128-159 are reserved for control codes so not used.

The file that is created is not a standard spectrum character set, as I said the pound sign will be incorrect and the copyright symbol will be missing. The file is also twice as long. A standard file could be made with little trouble and often the Amiga font will contain a pound sign and a copyright sign in the extended characters. These could be moved prior to saving with a for-next loop. I did not need this functionality so I have not added it. I did not want to replace the sexy Spectrum font, I just needed a full ANSI compliant font. I may recreate the converter as an esxDOS dot command which will include this functionality. I release this just in case someone may be interested.

A zip with the .bas file and a small selection of PD fonts (not topaz/8) can be found here :

More fonts can be found on Aminet or in the FONTS: drive on your Amiga! Look for fonts with an 8 point file. Not all will work as many are not truly monospaced, my script fails on proportional fonts. Some 8 point fonts are less than 8 points wide, these currently will not work.

The Code :

Code: Select all

10 REM Amiga 8x8 font converter
20 REM By MonkZy 2024

30 REG 7,3: CLEAR 49999

60 CLOSE #4
70 LAYER 1,2: CLS

80 PRINT "Amiga 8x8 Monospaced Font Convertor v1.0"
90 PRINT "By MonkZy "; CHR$ 127;"2024"; CHR$ 13

100 INPUT "Font file path :";f$: PRINT

110 OPEN #4,f$
120 PROC getUwordBE(78,2) TO y
130 PROC getUwordBE(82,2) TO x
140 PROC getByte(90) TO lo
150 PROC getByte(91) TO hi
160 PROC getUwordBE(92,4) TO fs
170 PROC getUwordBE(96,2) TO m
180 PROC getUwordBE(98,4) TO ls

200 PRINT "ySize : ";y; TAB 18;"loChar : ";lo
210 PRINT "xSize : ";x; TAB 18;"hiChar : ";hi
220 PRINT "modulo : ";m
240 IF x<>8 OR y<>8 THEN PRINT "The font must be 8 x 8 pixels!!": PRINT : STOP
250 IF lo>32 THEN PRINT "The font must start at space (32)!!": PRINT : STOP
260 IF hi<126 THEN PRINT "The hiChar must be at least 126 for an ASCII set!!": PRINT : STOP
270 IF hi<255 THEN PRINT "This font is not a complete ANSI font (32-255)"; CHR$ 13;"Some glyphs may be blank or corrupted !!": PRINT 

280 cs=50000:cpos=50000:cc=0:offset=0

310 FOR a=lo TO hi
315 IF a=128 THEN cpos+=768: offset=128
320 IF (a>127 AND a<160) OR a<32 THEN ls+=4:cc=0: NEXT a
330 IF cc=0 THEN PRINT a; TAB 3;":";: PROC setChars(cpos)
340 PROC getUwordBE(ls,2) TO p
350 PROC getUwordBE(ls+2,2) TO l
360 IF l<>8 THEN PRINT : PRINT "This font is not monospaced!!": PRINT : STOP
370 gb=fs
380 FOR z=0 TO 7
390 PROC getByte(gb+(p/8)) TO byte
470 POKE cs+z,byte
480 gb+=m
490 NEXT z

500 PRINT CHR$ 2; CHR$ (a-offset);
510 IF cc=31 THEN PROC setChars(15616): PRINT ":";a: cc=0: GO TO 600

520 cc+=1

600 ls+=4:cs+=8
610 NEXT a
620 CLOSE #4

630 IF cc>0 THEN PROC setChars(15616): PRINT ":";a

700 cpos=50000 
710 PRINT cpos;" : ";
720 PROC setChars(cpos)
730 PRINT "the quick brown cat jumped over the lazy dog"
740 cpos+=768
750 PROC setChars(15616)
760 PRINT cpos;" : ";
850 PROC setChars(cpos)
860 PRINT "the quick brown cat jumped over the lazy dog"
870 PROC setChars(15616)
880 PRINT CHR$ 13;"Input a filename for the full char set, '.bin' will be added."; CHR$ 13;"Leave blank to skip save"; CHR$ 13
890 INPUT "Filename :";z$
900 IF z$<>"" THEN SAVE z$+".bin" CODE 50000,1536
910 PRINT CHR$ 13; CHR$ 13; z$;".bin has been created!"; CHR$ 13
920 STOP

1000 DEFPROC getUwordBE(pos,bytes)
1010   GO TO #4,pos+32
1020   LOCAL %b: LOCAL c
1030   LOCAL d=256^(bytes-1): LOCAL value
1040   FOR %b=1 TO bytes
1050   NEXT #4 TO c
1060   value+=d*c
1070   d=d/256
1080   NEXT %b
1090 ENDPROC =value
1100 DEFPROC getByte(pos)
1110   GO TO #4,pos+32
1120   LOCAL b
1130   NEXT #4 TO b
1140   LOCAL value=b
1150 ENDPROC =value

1200 DEFPROC setChars(loc)
1210   LOCAL chars=loc-256
1220   LOCAL hib=INT(chars/256)
1230   LOCAL lob=chars-(hib*256)
1240   POKE 23606,lob
1250   POKE 23607,hib
1260   PRINT CHR$ 2;
[edit] This script was adapted from a more complete Java script written by Andrew Graham. Although I have no Java skills, the script exposed the file structure allowing me to write the BASIC. Andrews script is more advanced as it can decode proportional fonts which requires treating the file as a bit stream, fortunately an 8 wide monospaced font the char data is all aligned with bytes....simples!
Post Reply