The lost art of making custom terminal fonts ============================================ I've been playing with my old terminals quite a bit, a wyse-325 and a honeywell terminal - the wyse terminal has a way to emulate a vt-220 among a few other terminals, and I noticed it supports loading custom fonts. Now, That's kind of neat, because you could combine multiple custom font characters into a graphical image. Wooo, GFX on an old text terminal! sign me up! It took a bit of research to figure out how to do this. I combined my notes below along with a little script that should help if you want to try this on your terminal. Say you wanted to have an O, or a circle, or whatever. First draw the character in a 8x12 grid and split the grid in a top and bottom half. Then, for each half, add up the columns into a value, treating each column as a series of bits top to bottom: --------------------- 1| | | |X| | | | | Calculate values by reading 2| | |X| |X| | | | bits top to bottom. 4| |X| | | |X| | | For every pixel denoted with X, 8| |X| | | |X| | | you will be adding up 16|X| | | | | |X| | the value in the first 32|X| | | | | |X| | column to get the total) --+-+-+-+-+-+-+-+-+-- 48,12,2,1,2,12,48,0 <- top half total --------------------- 1| |X| | | |X| | | 2| |X| | | |X| | | 4| | |X| |x| | | | 8| | | |x| | | | | 16| | | | | | | | | 32| | | | | | | | | --------------------- 0,3,4,8,4,3,0,0 <- bottom half total Now add 63 to each number (0x3f hex): Top half: 111, 75, 65, 64, 65, 75, 111, 63 Bottom half: 63, 66, 67, 71, 67, 66, 63, 63 Or converted to hex: Top half: 6f, 4B, 41, 40, 41, 4b, 6f, 3f Bottom half: 3f, 42, 43, 47, 43, 42, 3f, 3f Or converted to ascii: Top half: oKA@AKo? Bottom half: ?BCGCB?? Note that we didn't put any pixels in the rightmost column. This is because that column is kind of special. Any pixel you put there, gets doubled-up to the right, meaning, the terminal will automatically provide a sort of 'bridge' between this character and the next character at any place there is a pixel in the rightmost column. This is so characters can look like they are 'connected', for instance if you wanted to draw a solid, uninterrupted line. Next, we pick a font bank, a place in the bank, and a name for that character etc,... and we can form our magic string to load and activate the new character. For the vt300 and vt220 and probably some other compatible terminals, this seems to be DCS followed by the font bank, and a whole bunch of other params, ending with an ST char. I wrote a little bash script which I'll share below that automates and explains the whole process. The script will load a smiley-face character into the "!" character, so, if you execute this on a vt300/vt220/(/others) terminal, you will now see a smiley face where there would normally be an exclamation point. # Font definition (calculated from grid, TSL=top, BSL=bottom) TSL="{AX@@XA\x3f" BSL="BCHIIHC\x3f" # Destination font bank ( 0 or 1 ) FB="1" # Position in which the first character of the font set is to be # loaded (0-95) BP="1" # What part of the font bank should be erased: # 0,2 = entire font set ; 1 = only loaded characters ER="1" # Cell size # 0 = 7x10 # 2 = 5x10 # 3 = 6x10 # 4 = 7x10 # 5 = 5x10 # 6 = 5x10 # 7 = 7x10 # 8..15 = 8x10 CW="8" # Font size # 0,1 = 80 cols, 26 lines # 2 = 132 cols # 11,12,21,22 = 80 cols, 44 lines FS="0" # Character type (0,1=text | 2 = graphics) TG="2" # Max. cell height (0..5 = 12 px or 10 | 6..12 = 6..12 px) CH="12" # Size of the character set (0 = 94, 1 = 96) SS="1" # Name of the charset, should be unique, 0-2 chars + one final. # first 2 chars should be 0x20 - 0x2f ; final is 0x30-0x7e CN=" @" # Escapes ESC="\x1b" DCS="${ESC}P" ST="${ESC}\\" # TSL and BSL combined into one font definition. FONTDEF="${TSL}/${BSL}" # All configuration parameters. CONFIG="${FB};${BP};${ER};${CW};${RW};${IG};${CH};${SS}" # This loads the font echo -e -n "${DCS}${CONFIG}{${CN}${FONTDEF};${ST}" # This activates the font. echo -e -n "${ESC}(${CN}" # Print our smiley face. echo "!" # If you want to restore back the original font bank afterwards, # uncomment below. echo -e -n "${ESC}(B"