aboutsummaryrefslogtreecommitdiff
path: root/fonts/mkpsf.pl
diff options
context:
space:
mode:
Diffstat (limited to 'fonts/mkpsf.pl')
-rw-r--r--fonts/mkpsf.pl1358
1 files changed, 1358 insertions, 0 deletions
diff --git a/fonts/mkpsf.pl b/fonts/mkpsf.pl
new file mode 100644
index 0000000..8a349f1
--- /dev/null
+++ b/fonts/mkpsf.pl
@@ -0,0 +1,1358 @@
+#!/usr/bin/perl -w
+
+# Read raw font data from atari rom images, plus a few hand-drawn
+# "text bitmaps" from __DATA__.
+
+# Write 3 bitmap font "txt" files in the format txt2psf expects, then
+# runs txt2psf on them. Results in 3 fonts:
+
+# fauxtari-8.psf - 8x8 native size
+# fauxtari-16.psf - 16x16 scaled up
+# fauxtari-24.psf - 24x24 scaled up
+
+# The fiddly bits of this are getting the Unicode mappings correct.
+
+# ROM dumps are mapped to Atari address space at $C000, the regular
+# charset starts at $E000, so it's at offset $2000 (8192) in the
+# image. The XL international set is at $CC00, or offset $0C00 (3072).
+# In the Arabic ROM, the Arabic font takes the place of the standard
+# charset. All the charsets are 1K in size.
+
+# Arabic ROM, plus some info about it and a mention of the Hebrew ROM:
+# https://www.savetz.com/vintagecomputers/arabic65xe/
+
+use bytes;
+
+$fontname = "fauxtari";
+
+sub byte2line {
+ my $t = shift;
+ $t = sprintf("%08b", $t);
+ $t =~ y/0/-/;
+ $t =~ y/1/#/;
+ return $t;
+}
+
+sub scale_line {
+ my $line = shift;
+ my $scale = shift;
+ my $one = '#' x $scale;
+ my $zero = '-' x $scale;
+
+ $line =~ s/#/$one/g;
+ $line =~ s/-/$zero/g;
+ return ($line x $scale);
+}
+
+sub chr2output {
+ my $codepoint = shift;
+ my $bytes = shift;
+ my $scale = shift || 1;
+ my $unicode = "";
+
+ if(!ref $codepoint) {
+ $codepoint = [ $codepoint ];
+ }
+
+ $unicode .= sprintf("[%04x];", $_) for @$codepoint;
+
+ my $result = sprintf("%%\nUnicode: %s\nBitmap: \\\n", $unicode);
+ for(0..7) {
+ my $byte = $bytes->[$_];
+ my $line = byte2line($byte);
+ $result .= scale_line($line, $scale);
+ $result .= " \\" unless $_ == 7;
+ $result .= "\n";
+ }
+ return $result;
+}
+
+sub internal2byte {
+ my $t = shift;
+ $t =~ y/-/0/;
+ $t =~ y/#/1/;
+ return pack("B*", $t);
+}
+
+sub psf2txt_header {
+ my $charcount = shift;
+ my $scale = shift;
+ my $w = 8 * $scale;
+ my $h = 8 * $scale;
+ return <<EOF;
+%PSF2
+Version: 0
+Flags: 1
+Length: $charcount
+Width: $w
+Height: $h
+EOF
+}
+
+sub read_rom {
+ my $data;
+ my $filename = shift;
+ my $offset = shift;
+ my $charcount = shift;
+ my $len = $charcount * 8;
+ open my $fh, '<', $filename;
+ read($fh, $data, 16384);
+ close $fh;
+ return substr($data, $offset, $len);
+}
+
+# position in the map (array index) is the raw glyph number, in
+# the order we read the font data.
+# value is the Unicode codepoint. if there are multiple codepoints
+# for the glyph, make the value an array ref (see 0x1B below, the
+# Atari Escape glyph is both 0x0118 aka LATIN CAPITAL LETTER E WITH OGONEK,
+# and 0x241b aka SYMBOL FOR ESCAPE).
+sub setup_map {
+ our @map = (
+ 0x2665, # 0x00
+ 0x2523, # 0x01
+ 0x2503, # 0x02
+ 0x251b, # 0x03
+ 0x252b, # 0x04
+ 0x2513, # 0x05
+ 0x2571, # 0x06
+ 0x2572, # 0x07
+ 0x25e2, # 0x08
+ 0x2597, # 0x09
+ 0x25e3, # 0x0a
+ 0x259d, # 0x0b
+ 0x2598, # 0x0c
+ 0x2594, # 0x0d
+ 0x2581, # 0x0e
+ 0x2596, # 0x0f
+ 0x2663, # 0x10
+ 0x250f, # 0x11
+ 0x2501, # 0x12
+ 0x254b, # 0x13
+ 0x25cf, # 0x14
+ 0x2584, # 0x15
+ 0x258e, # 0x16
+ 0x2533, # 0x17
+ 0x253b, # 0x18
+ 0x258c, # 0x19
+ 0x2517, # 0x1a
+ [ 0x0118, 0x241b ], # 0x1b
+ 0x2191, # 0x1c
+ 0x2193, # 0x1d
+ 0x2190, # 0x1e
+ 0x2192, # 0x1f
+ [ 0x0020, 0xa0 ], # 0x20 (plus &nbsp;)
+ 0x0021, # 0x21
+ 0x0022, # 0x22
+ 0x0023, # 0x23
+ 0x0024, # 0x24
+ 0x0025, # 0x25
+ 0x0026, # 0x26
+ 0x0027, # 0x27
+ 0x0028, # 0x28
+ 0x0029, # 0x29
+ 0x002a, # 0x2a
+ 0x002b, # 0x2b
+ [ 0x002c, 0x00b8 ], # 0x2c (comma and cedilla)
+ [ 0x002d, 0x00ad, 0x2013, 0x2014 ], # 0x2d (plus soft hyphen, en, em)
+ 0x002e, # 0x2e
+ 0x002f, # 0x2f
+ 0x0030, # 0x30
+ 0x0031, # 0x31
+ 0x0032, # 0x32
+ 0x0033, # 0x33
+ 0x0034, # 0x34
+ 0x0035, # 0x35
+ 0x0036, # 0x36
+ 0x0037, # 0x37
+ 0x0038, # 0x38
+ 0x0039, # 0x39
+ 0x003a, # 0x3a
+ 0x003b, # 0x3b
+ 0x003c, # 0x3c
+ 0x003d, # 0x3d
+ 0x003e, # 0x3e
+ 0x003f, # 0x3f
+ 0x0040, # 0x40
+ 0x0041, # 0x41
+ 0x0042, # 0x42
+ 0x0043, # 0x43
+ 0x0044, # 0x44
+ 0x0045, # 0x45
+ 0x0046, # 0x46
+ 0x0047, # 0x47
+ 0x0048, # 0x48
+ 0x0049, # 0x49
+ 0x004a, # 0x4a
+ 0x004b, # 0x4b
+ 0x004c, # 0x4c
+ 0x004d, # 0x4d
+ 0x004e, # 0x4e
+ 0x004f, # 0x4f
+ 0x0050, # 0x50
+ 0x0051, # 0x51
+ 0x0052, # 0x52
+ 0x0053, # 0x53
+ 0x0054, # 0x54
+ 0x0055, # 0x55
+ 0x0056, # 0x56
+ 0x0057, # 0x57
+ 0x0058, # 0x58
+ 0x0059, # 0x59
+ 0x005a, # 0x5a
+ 0x005b, # 0x5b
+ 0x005c, # 0x5c
+ 0x005d, # 0x5d
+ 0x005e, # 0x5e
+ 0x005f, # 0x5f
+ 0x25c6, # 0x60
+ 0x0061, # 0x61
+ 0x0062, # 0x62
+ 0x0063, # 0x63
+ 0x0064, # 0x64
+ 0x0065, # 0x65
+ 0x0066, # 0x66
+ 0x0067, # 0x67
+ 0x0068, # 0x68
+ 0x0069, # 0x69
+ 0x006a, # 0x6a
+ 0x006b, # 0x6b
+ 0x006c, # 0x6c
+ 0x006d, # 0x6d
+ 0x006e, # 0x6e
+ 0x006f, # 0x6f
+ 0x0070, # 0x70
+ 0x0071, # 0x71
+ 0x0072, # 0x72
+ 0x0073, # 0x73
+ 0x0074, # 0x74
+ 0x0075, # 0x75
+ 0x0076, # 0x76
+ 0x0077, # 0x77
+ 0x0078, # 0x78
+ 0x0079, # 0x79
+ 0x007a, # 0x7a
+ 0x2660, # 0x7b
+ [ 0x007c, 0x0622, 0xfe81, 0xfe82 ], # 0x7c, pipe + arabic ﺁ
+ 0x21b0, # 0x7d
+ 0x25c0, # 0x7e
+ 0x25b6, # 0x7f
+
+# next, 28 "international" characters from the xl rom $cc00 area
+# á
+ 0x00e1, # 0x80
+# ù
+ 0x00f9, # 0x81
+# Ñ
+ 0x00d1, # 0x82
+# É
+ 0x00c9, # 0x83
+# ç
+ 0x00e7, # 0x84
+# ô (or is it?)
+ 0x00f4, # 0x85
+# ò
+ 0x00f2, # 0x86
+# ì
+ 0x00ec, # 0x87
+# £
+ 0x00a3, # 0x88
+# ï
+ 0x00ef, # 0x89
+# ü
+ 0x00fc, # 0x8a
+# ä
+ 0x00e4, # 0x8b
+# Ö
+ 0x00d6, # 0x8c
+# ú
+ 0x00fa, # 0x8d
+# ó
+ 0x00f3, # 0x8e
+# ö
+ 0x00f6, # 0x8f
+# Ü
+ 0x00dc, # 0x90
+# å
+ 0x00e5, # 0x91
+# û (?)
+ 0x00fb, # 0x92
+# î
+ 0x00ee, # 0x93
+# é
+ 0x00e9, # 0x94
+# è
+ 0x00e8, # 0x95
+# ñ
+ 0x00f1, # 0x96
+# ê
+ 0x00ea, # 0x97
+# ȧ
+ 0x0227, # 0x98
+# à
+ 0x00e0, # 0x99
+# ¡
+ 0x00a1, # 0x9a
+# Ä
+ 0x00c4, # 0x9b
+
+# hebrew rom is probably a 3rd-party hack, afaik never released by
+# atari, but i'm told the glyphs look good (by someone who reads hebrew),
+# so include it here.
+ 0x05d0, # 0x9c
+ 0x05d1, # 0x9d
+ 0x05d2, # 0x9e
+ 0x05d3, # 0x9f
+ 0x05d4, # 0xa0
+ 0x05d5, # 0xa1
+ 0x05d6, # 0xa2
+ 0x05d7, # 0xa3
+ 0x05d8, # 0xa4
+ 0x05d9, # 0xa5
+ 0x05da, # 0xa6
+ 0x05db, # 0xa7
+ 0x05dc, # 0xa8
+ 0x05dd, # 0xa9
+ 0x05de, # 0xaa
+ 0x05df, # 0xab
+ 0x05e0, # 0xac
+ 0x05e1, # 0xad
+ 0x05e2, # 0xae
+ 0x05e3, # 0xaf
+ 0x05e4, # 0xb0
+ 0x05e5, # 0xb1
+ 0x05e6, # 0xb2
+ 0x05e7, # 0xb3
+ 0x05e8, # 0xb4
+ 0x05e9, # 0xb5
+ 0x05ea, # 0xb6
+
+# polish rom. probably a 3rd-party hack, but there are a lot of polish
+# atari users out there.
+ 0x0179, # 0xb7
+ 0x0105, # 0xb8
+ 0x017a, # 0xb9
+ 0x0107, # 0xba
+ 0x015a, # 0xbb
+ 0x0119, # 0xbc
+# german sharp s, not polish at all:
+ 0x00df, # 0xbd
+ 0x0141, # 0xbe
+ 0x0142, # 0xbf
+ 0x0143, # 0xc0
+ 0x0144, # 0xc1
+ 0x00d3, # 0xc3
+# 0xc3 weird-looking v?
+# next glyph is e with ogonek, we already have it as esc
+ 0x015b, # 0xc4
+ 0x0106, # 0xc5
+ 0x0104, # 0xc6
+ 0x017b, # 0xc7
+ 0x017c, # 0xc8
+
+# the rest are from the arabic xe rom
+ 0x0660, # eastern arabic numeral 0
+ 0x0661, # eastern arabic numeral 1
+ 0x0662, # eastern arabic numeral 2
+ 0x0663, # eastern arabic numeral 3
+ 0x0664, # eastern arabic numeral 4
+ 0x0665, # eastern arabic numeral 5
+ 0x0666, # eastern arabic numeral 6
+ 0x0667, # eastern arabic numeral 7
+ 0x0668, # eastern arabic numeral 8
+ 0x0669, # eastern arabic numeral 9
+
+# todo: figure out the arabic letter mappings. might need someone who
+# actually reads arabic to make sense of them... what i've got is just
+# a guess.
+ [ 0x0624, 0xfe85, 0xfe86 ], # 0x3c, maybe?
+
+ [ 0x0634, 0xfeb5, 0xfeb6, 0xfeb8 ], # 0x41
+ [ 0x0648, 0xfeed, 0xfeee ], # 0x42
+ [ 0x0629, 0xfe93, 0xfe94 ], # 0x43
+ [ 0x064a, 0xfef1, 0xfef2, 0xfef4 ], # 0x44
+ [ 0x062b, 0xfe99, 0xfe9a, 0xfe9c ], # 0x45
+ [ 0x0628, 0xfe8f, 0xfe90, 0xfe92 ], # 0x46
+ [ 0x0644, 0xfedd, 0xfede, 0xfee0 ], # 0x47
+ [ 0x0621, 0xfe80 ], # 0x48
+ [ 0x0647, 0xfee9, 0xfeea, 0xfeec ], # 0x49
+ [ 0x062a, 0xfe95, 0xfe96, 0xfe98 ], # 0x4a
+ [ 0x0646, 0xfee5, 0xfee6, 0xfee8 ], # 0x4b
+ [ 0x0645, 0xfee1, 0xfee2, 0xfee4 ], # 0x4c
+ [ 0x062c, 0xfe9d, 0xfe9e, 0xfea0 ], # 0x4d
+ # xxx don't know what 0x4e is
+ [ 0x062e, 0xfea5, 0xfea6, 0xfea8 ], # 0x4f
+ [ 0x062d, 0xfea1, 0xfea2, 0xfea4 ], # 0x50
+ [ 0x0636, 0xfebd, 0xfebe, 0xfec0 ], # 0x51
+ [ 0x0642, 0xfed5, 0xfed6, 0xfed8 ], # 0x52
+ [ 0x0633, 0xfeb1, 0xfeb2, 0xfeb4 ], # 0x53
+ [ 0x0641, 0xfed1, 0xfed2, 0xfed4 ], # 0x54
+ [ 0x0639, 0xfec9, 0xfeca, 0xfecc ], # 0x55
+ [ 0x0643, 0xfed9, 0xfeda, 0xfedc ], # 0x56
+ [ 0x0635, 0xfeb9, 0xfeba, 0xfebc ], # 0x57
+ # xxx don't know what 0x58 is
+ [ 0x063a, 0xfecd, 0xfece, 0xfed0 ], # 0x59
+ [ 0x0649, 0xfeef, 0xfef0 ], # 0x5a
+ [ 0x0632, 0xfeaf, 0xfeb0 ], # 0x60
+ 0xfeb7, # 0x61
+ # xxx 0x62 isn't really both ﺩ and ﺭ but where's the atari's ﺭ at?
+ [ 0x062f, 0xfea9, 0xfeaa, 0x0631, 0xfead, 0xfeae ], # 0x62
+ [ 0x0630, 0xfeab, 0xfeac ], # 0x63
+ 0xfef3, # 0x64
+ 0xfe9b, # 0x65
+ 0xfe91, # 0x66
+ 0xfedf, # 0x67
+ [ 0x0627, 0xfe8d, 0xfe8e ], # 0x68
+ 0xfeeb, # 0x69
+ 0xfe97, # 0x6a
+ 0xfee7, # 0x6b
+ 0xfee3, # 0x6c
+ 0xfe9f, # 0x6d
+ [ 0xfef7, 0xf3f8 ], # 0x6e
+ 0xfea7, # 0x6f
+ 0xfea3, # 0x70
+ 0xfebf, # 0x71
+ 0xfed7, # 0x72
+ 0xfeb3, # 0x73
+ 0xfed3, # 0x74
+ 0xfecb, # 0x75
+ 0xfedb, # 0x76
+ 0xfebb, # 0x77
+ [ 0x0637, 0xfec1, 0xfec2, 0xfec4, 0xfec3 ], # 0x78
+ 0xfecf, # 0x79
+ [ 0x0638, 0xfec5, 0xfec6, 0xfec8, 0xfec7 ], # 0x7a
+ 0x061f, # 0x7f
+ );
+}
+
+### main()
+setup_map();
+
+@scale1 = ();
+@scale2 = ();
+@scale3 = ();
+
+$raw .= read_rom("atarixl.rom", 0x2200, 32);
+$raw .= read_rom("atarixl.rom", 0x2000, 32);
+$raw .= read_rom("atarixl.rom", 0x2100, 32);
+$raw .= read_rom("atarixl.rom", 0x2300, 32);
+$raw .= read_rom("atarixl.rom", 0xe00, 26);
+$raw .= read_rom("atarixl.rom", 0xf00, 1);
+$raw .= read_rom("atarixl.rom", 0xfd8, 1);
+
+$raw .= read_rom("xl_hebrew.rom", 0xf00, 27);
+
+$raw .= read_rom("xl_polish.rom", 0xe00, 6);
+$raw .= read_rom("xl_polish.rom", 0xe50, 5);
+$raw .= read_rom("xl_polish.rom", 0xe80, 1);
+$raw .= read_rom("xl_polish.rom", 0xe98, 1);
+$raw .= read_rom("xl_polish.rom", 0xeb0, 3);
+$raw .= read_rom("xl_polish.rom", 0xed0, 1);
+
+$raw .= read_rom("xe_arabic.rom", 0x2000+8*15, 10);
+$raw .= read_rom("xe_arabic.rom", 0x2000+8*0x3c, 1);
+$raw .= read_rom("xe_arabic.rom", 0x2000+8*0x41, 13);
+$raw .= read_rom("xe_arabic.rom", 0x2000+8*0x4f, 9);
+$raw .= read_rom("xe_arabic.rom", 0x2000+8*0x59, 2);
+$raw .= read_rom("xe_arabic.rom", 0x2000+8*0x60, 27);
+$raw .= read_rom("xe_arabic.rom", 0x2000+8*0x7f, 1);
+
+$cnt = 0;
+while($raw =~ /(.{8})/gc) {
+ my @bytes;
+ my $got = $1;
+ my $chr = $map[$cnt++];
+ die "$0: incomplete map" unless defined $chr;
+ #warn $got;
+ push @bytes, ord(substr($got, $_, 1)) for(0..7);
+ #warn $_ for @bytes;
+ push @scale1, chr2output($chr, \@bytes, 1);
+ push @scale2, chr2output($chr, \@bytes, 2);
+ push @scale3, chr2output($chr, \@bytes, 3);
+}
+
+while(<DATA>) {
+ push @scale1, $_;
+ $cnt++ if /^%/;
+ if(/^\s*[-#]/) {
+ push @scale2, scale_line($_, 2);
+ push @scale3, scale_line($_, 3);
+ } else {
+ push @scale2, $_;
+ push @scale3, $_;
+ }
+}
+
+#warn "$cnt characters\n";
+#warn "(padding to 256 characters)\n" unless $cnt >= 256;
+#warn "(padding to 512 characters)\n" unless $cnt >= 512;
+
+# 512 glyphs is the max for a PSF font. There can be more
+# *codepoints*, because the Unicode directory allows the same
+# glyph to represent multiple codepoints (e.g. space and
+# non-breaking space).
+if($cnt > 512) {
+ die "$0: too many glyphs ($cnt > 512)";
+}
+
+# The kernel refuses to load a font that isn't exactly
+# 256 or 512 glyphs, so we have to pad with junk glyphs.
+while($cnt < 512) {
+ my $fake = "%\nUnicode: [0000];\nBitmap: ";
+ push @scale1, $fake . (("-" x 8) x 8) . "\n";
+ push @scale2, $fake . (("-" x 16) x 16) . "\n";
+ push @scale3, $fake . (("-" x 24) x 24) . "\n";
+ $cnt++;
+}
+
+#warn "$cnt characters with padding\n";
+
+# What is dupglyphs.pl for?
+# PSF allows the same glyph to represent multiple codepoints (e.g.
+# space and NBSP, or hyphen/soft-hyphen/en-dash). We only get 512
+# glyphs max for a PSF, so we definitely want to use this.
+# BDF on the other hand doesn't allow this. So if the same glyph
+# data is to be used for multiple codepoints in BDF, the glyph data
+# has to be repeated for each codepoint. Bloats the font, but not
+# too much. The BDF is also what gets made into the TTF. I'm pretty
+# sure TTF supports multiple codepoints per glyph, but until I
+# learn some other way besides bitmapfont2ttf to generate the TTF,
+# it also will have dup glyph bloat. On the bright side, dupglyphs.pl
+# removes all the padding characters required by the psf font.
+sub mkfonts {
+ my $px = shift;
+ my $scaled_data = shift;
+ my $scale = shift;
+
+ open $fh, '>', "$fontname-$px.txt" or die $!;
+ print $fh psf2txt_header($cnt, $scale);
+ print $fh $_ for(@$scaled_data);
+ close $fh;
+
+ system("txt2psf $fontname-$px.txt $fontname-$px.psf");
+ system("perl dupglyphs.pl $fontname-$px.txt | perl sorttxtfont.pl | txt2psf | psf2bdf --defchar=0 --iso10646 --fontname=$fontname-$px | perl ./fixbdf.pl $px > $fontname-$px.bdf");
+}
+
+mkfonts(8, \@scale1, 1);
+mkfonts(16, \@scale2, 2);
+mkfonts(24, \@scale3, 3);
+
+exit 0;
+
+__DATA__
+%
+// dotted-box (no such glyph)
+Unicode: [0000];
+Bitmap: \
+ -------- \
+ -##-###- \
+ -#------ \
+ ------#- \
+ -#------ \
+ ------#- \
+ -###-##- \
+ --------
+%
+// backtick
+Unicode: [0060];
+Bitmap: \
+ -------- \
+ --##---- \
+ --##---- \
+ ---##--- \
+ -------- \
+ -------- \
+ -------- \
+ --------
+%
+// curlies
+Unicode: [007b];
+Bitmap: \
+ ----##-- \
+ ---##--- \
+ ---##--- \
+ --##---- \
+ ---##--- \
+ ---##--- \
+ ----##-- \
+ --------
+%
+Unicode: [007d];
+Bitmap: \
+ --##---- \
+ ---##--- \
+ ---##--- \
+ ----##-- \
+ ---##--- \
+ ---##--- \
+ --##---- \
+ --------
+%
+// tilde
+Unicode: [007e];
+Bitmap: \
+ -------- \
+ -###--## \
+ ##-##-## \
+ ##--###- \
+ -------- \
+ -------- \
+ -------- \
+ --------
+%
+// euro
+Unicode: [20ac];
+Bitmap: \
+ ---####- \
+ --##---- \
+ -#####-- \
+ --##---- \
+ -#####-- \
+ --##---- \
+ ---####- \
+ --------
+%
+// spanish left-quote
+Unicode: [00ab];
+Bitmap: \
+ -------- \
+ -------- \
+ -------- \
+ -##--##- \
+ ##--##-- \
+ -##--##- \
+ -------- \
+ --------
+%
+// spanish right-quote
+Unicode: [00bb];
+Bitmap: \
+ -------- \
+ -------- \
+ -------- \
+ ##--##-- \
+ -##--##- \
+ ##--##-- \
+ -------- \
+ --------
+%
+// spanish inverted question mark
+Unicode: [00bf];
+Bitmap: \
+ -------- \
+ ---##--- \
+ -------- \
+ ---##--- \
+ ----##-- \
+ -##--##- \
+ --####-- \
+ --------
+%
+// copyright
+Unicode: [00a9];
+Bitmap: \
+ -#####-- \
+ #-----#- \
+ #--##-#- \
+ #-#---#- \
+ #--##-#- \
+ #-----#- \
+ -#####-- \
+ --------
+%
+// registered
+Unicode: [00ae];
+Bitmap: \
+ -#####-- \
+ #-----#- \
+ #-##--#- \
+ #-#-#-#- \
+ #-##--#- \
+ #-#-#-#- \
+ -#####-- \
+ --------
+%
+// degrees
+Unicode: [00b0];[00ba];
+Bitmap: \
+ -------- \
+ ---##--- \
+ --#--#-- \
+ ---##--- \
+ -------- \
+ -------- \
+ -------- \
+ --------
+%
+// cents
+Unicode: [00a2];
+Bitmap: \
+ -------- \
+ ---##--- \
+ --#####- \
+ -##----- \
+ -##----- \
+ --#####- \
+ ---##--- \
+ --------
+%
+// "currency sign"
+// FIXME: not bold enough
+Unicode: [00a4];
+Bitmap: \
+ -------- \
+ -#----#- \
+ --####-- \
+ --#--#-- \
+ --#--#-- \
+ --####-- \
+ -#----#- \
+ --------
+%
+// yen
+Unicode: [00a5];
+Bitmap: \
+ -##--##- \
+ -##--##- \
+ ---##--- \
+ -######- \
+ ---##--- \
+ -######- \
+ ---##--- \
+ --------
+%
+// broken bar
+Unicode: [00a6];
+Bitmap: \
+ -------- \
+ ---##--- \
+ ---##--- \
+ -------- \
+ ---##--- \
+ ---##--- \
+ ---##--- \
+ --------
+%
+// section sign
+// FIXME: not bold enough
+Unicode: [00a7];
+Bitmap: \
+ ---###-- \
+ --#----- \
+ ---##--- \
+ --#--#-- \
+ ---##--- \
+ -----#-- \
+ --###--- \
+ --------
+%
+// diaresis (cha, cha, cha!)
+Unicode: [00a8];
+Bitmap: \
+ -------- \
+ -##--##- \
+ -##--##- \
+ -------- \
+ -------- \
+ -------- \
+ -------- \
+ --------
+%
+// feminine ordinal (superscript a)
+Unicode: [00aa];
+Bitmap: \
+ -------- \
+ --####-- \
+ ----###- \
+ --##-##- \
+ ---####- \
+ -------- \
+ -------- \
+ --------
+%
+// "not" sign
+Unicode: [00ac];
+Bitmap: \
+ -------- \
+ -------- \
+ -------- \
+ -######- \
+ -----##- \
+ -------- \
+ -------- \
+ --------
+%
+// macron
+Unicode: [00af];
+Bitmap: \
+ -------- \
+ -######- \
+ -------- \
+ -------- \
+ -------- \
+ -------- \
+ -------- \
+ --------
+%
+// plus-minus
+Unicode: [00b1];
+Bitmap: \
+ -------- \
+ ---##--- \
+ -######- \
+ ---##--- \
+ -------- \
+ -######- \
+ -------- \
+ --------
+%
+// superscript 2
+// FIXME: not bold enough
+Unicode: [00b2];
+Bitmap: \
+ -------- \
+ --##---- \
+ -#--#--- \
+ ---#---- \
+ --#----- \
+ -####--- \
+ -------- \
+ --------
+%
+// FIXME: not bold enough
+// superscript 3
+Unicode: [00b3];
+Bitmap: \
+ -------- \
+ --##---- \
+ -#--#--- \
+ ---#---- \
+ -#--#--- \
+ --##---- \
+ -------- \
+ --------
+%
+// acute
+Unicode: [00b4];
+Bitmap: \
+ -------- \
+ ----##-- \
+ ---##--- \
+ -------- \
+ -------- \
+ -------- \
+ -------- \
+ --------
+%
+// mu
+Unicode: [00b5];
+Bitmap: \
+ -------- \
+ -------- \
+ -##--##- \
+ -##--##- \
+ -##--##- \
+ --#####- \
+ -----##- \
+ --------
+%
+// paragraph
+Unicode: [00b6];
+Bitmap: \
+ -------- \
+ --##-##- \
+ -###-##- \
+ -###-##- \
+ --##-##- \
+ ---#-##- \
+ ---#-##- \
+ --------
+%
+// middle dot
+Unicode: [00b7];
+Bitmap: \
+ -------- \
+ -------- \
+ -------- \
+ ---##--- \
+ ---##--- \
+ -------- \
+ -------- \
+ --------
+%
+// superscript 1
+Unicode: [00b9];
+Bitmap: \
+ -------- \
+ ---##--- \
+ --###--- \
+ ---##--- \
+ --####-- \
+ -------- \
+ -------- \
+ --------
+// FIXME: MISSING fractions, 00bc/00bd/00bc, ¼ ½ ¾, hard to do in 8x8
+%
+// A with grave
+Unicode: [00c0];
+Bitmap: \
+ -------- \
+ --##---- \
+ ---##--- \
+ --####-- \
+ -##--##- \
+ -######- \
+ -##--##- \
+ --------
+%
+// A with acute
+Unicode: [00c1];
+Bitmap: \
+ -------- \
+ ----##-- \
+ ---##--- \
+ --####-- \
+ -##--##- \
+ -######- \
+ -##--##- \
+ --------
+%
+// A with circumflex
+Unicode: [00c2];
+Bitmap: \
+ --####-- \
+ -#----#- \
+ ---##--- \
+ --####-- \
+ -##--##- \
+ -######- \
+ -##--##- \
+ --------
+%
+// A with tilde
+Unicode: [00c3];
+Bitmap: \
+ --##-##- \
+ -##-##-- \
+ ---##--- \
+ --####-- \
+ -##--##- \
+ -######- \
+ -##--##- \
+ --------
+%
+// A with ring
+Unicode: [00c5];
+Bitmap: \
+ ---##--- \
+ --#--#-- \
+ ---##--- \
+ --####-- \
+ -##--##- \
+ -######- \
+ -##--##- \
+ --------
+%
+// AE ligature
+Unicode: [00c6];
+Bitmap: \
+ -------- \
+ --#####- \
+ -####--- \
+ ##-##--- \
+ #######- \
+ ##-##--- \
+ ##-####- \
+ --------
+// FIXME: this is hideous!
+%
+// C with cedilla
+Unicode: [00c7];
+Bitmap: \
+ -------- \
+ --####-- \
+ -##--##- \
+ -##----- \
+ -##--##- \
+ --####-- \
+ ---##--- \
+ --##----
+%
+// E with circumflex
+Unicode: [00ca];
+Bitmap: \
+ --####-- \
+ -#----#- \
+ -######- \
+ -##----- \
+ -#####-- \
+ -##----- \
+ -######- \
+ --------
+// FIXME: ugly!
+%
+// E with umlaut
+Unicode: [00cb];
+Bitmap: \
+ --##-##- \
+ -------- \
+ -######- \
+ -##----- \
+ -#####-- \
+ -##----- \
+ -######- \
+ --------
+%
+// I with grave
+Unicode: [00cc];
+Bitmap: \
+ --##---- \
+ ---##--- \
+ -######- \
+ ---##--- \
+ ---##--- \
+ ---##--- \
+ -######- \
+ --------
+%
+// I with acute
+Unicode: [00cd];
+Bitmap: \
+ ----##-- \
+ ---##--- \
+ -######- \
+ ---##--- \
+ ---##--- \
+ ---##--- \
+ -######- \
+ --------
+%
+// I with circumflex
+Unicode: [00ce];
+Bitmap: \
+ --####-- \
+ -#----#- \
+ -######- \
+ ---##--- \
+ ---##--- \
+ ---##--- \
+ -######- \
+ --------
+// FIXME: ugly!
+%
+// I with umlaut
+Unicode: [00cf];
+Bitmap: \
+ --##-##- \
+ -------- \
+ -######- \
+ ---##--- \
+ ---##--- \
+ ---##--- \
+ -######- \
+ --------
+%
+// capital eth
+Unicode: [00d0];
+Bitmap: \
+ -------- \
+ -####--- \
+ -##-##-- \
+ -##--##- \
+ ####-##- \
+ -##-##-- \
+ -####--- \
+ --------
+%
+// O with grave
+Unicode: [00d2];
+Bitmap: \
+ -##----- \
+ --####-- \
+ -#-#-##- \
+ -##--##- \
+ -##--##- \
+ -##--##- \
+ --####-- \
+ --------
+// FIXME: MISSING Ô Õ
+%
+// multiplication
+Unicode: [00d7];
+Bitmap: \
+ -------- \
+ -##--##- \
+ --####-- \
+ ---##--- \
+ --####-- \
+ -##--##- \
+ -------- \
+ --------
+// FIXME: MISSING Ø
+%
+// U with grave
+Unicode: [00d9];
+Bitmap: \
+ --##---- \
+ ---##--- \
+ -##--##- \
+ -##--##- \
+ -##--##- \
+ -##--##- \
+ -######- \
+ --------
+%
+// U with acute
+Unicode: [00da];
+Bitmap: \
+ ----##-- \
+ ---##--- \
+ -##--##- \
+ -##--##- \
+ -##--##- \
+ -##--##- \
+ -######- \
+ --------
+// FIXME: MISSING Û
+%
+// Y with acute
+Unicode: [00dd];
+Bitmap: \
+ ----##-- \
+ ---##--- \
+ -##--##- \
+ -##--##- \
+ --####-- \
+ ---##--- \
+ ---##--- \
+ --------
+%
+// capital thorn
+Unicode: [00de];
+Bitmap: \
+ -------- \
+ -##----- \
+ -#####-- \
+ -##--##- \
+ -#####-- \
+ -##----- \
+ -##----- \
+ --------
+%
+// a with circumflex
+Unicode: [00e2];
+Bitmap: \
+ --####-- \
+ -#----#- \
+ -------- \
+ --####-- \
+ ----###- \
+ --##-##- \
+ ---####- \
+ --------
+%
+// a with tilde
+Unicode: [00e3];
+Bitmap: \
+ --##-##- \
+ -##-##-- \
+ -------- \
+ --####-- \
+ ----###- \
+ --##-##- \
+ ---####-
+// FIXME: touches bottom
+%
+// ae ligature
+Unicode: [00e6];
+Bitmap: \
+ -------- \
+ -------- \
+ -###-##- \
+ ---##-## \
+ -######- \
+ ##-##--- \
+ -######- \
+ --------
+// FIXME: fugly
+%
+// e with umlaut
+Unicode: [00eb];
+Bitmap: \
+ -##--##- \
+ -------- \
+ --####-- \
+ -##--##- \
+ -######- \
+ -##----- \
+ --####-- \
+ --------
+%
+// i with acute
+Unicode: [00ed];
+Bitmap: \
+ ----##-- \
+ ---##--- \
+ -------- \
+ --###--- \
+ ---##--- \
+ ---##--- \
+ --####-- \
+ --------
+%
+// lowercase eth
+Unicode: [00f0];
+Bitmap: \
+ -##-#--- \
+ --##---- \
+ -#-##--- \
+ --####-- \
+ -##--##- \
+ -##--##- \
+ --####-- \
+ --------
+%
+// o with tilde
+Unicode: [00f5];
+Bitmap: \
+ --##-##- \
+ -##-##-- \
+ -------- \
+ --####-- \
+ -##--##- \
+ -##--##- \
+ --####-- \
+ --------
+%
+// division
+Unicode: [00f7];
+Bitmap: \
+ -------- \
+ ---##--- \
+ -------- \
+ -######- \
+ -------- \
+ ---##--- \
+ -------- \
+ --------
+// FIXME: MISSING ø
+%
+// y with acute
+Unicode: [00fd];
+Bitmap: \
+ ----##-- \
+ ---##--- \
+ -------- \
+ -##--##- \
+ -##--##- \
+ --#####- \
+ ----##-- \
+ -####---
+%
+// lowercase thorn
+Unicode: [00fe];
+Bitmap: \
+ -##----- \
+ -##----- \
+ -####--- \
+ -##-##-- \
+ -####--- \
+ -##----- \
+ -##----- \
+ --------
+%
+// y with umlaut
+Unicode: [00ff];
+Bitmap: \
+ -##--##- \
+ -------- \
+ -##--##- \
+ -##--##- \
+ -##--##- \
+ --#####- \
+ ----##-- \
+ -####---
+%
+// left single curly quote
+Unicode: [2018];
+Bitmap: \
+ -------- \
+ --##---- \
+ ---##--- \
+ ----##-- \
+ -------- \
+ -------- \
+ -------- \
+ --------
+%
+// right single curly quote
+Unicode: [2019];
+Bitmap: \
+ -------- \
+ ----##-- \
+ ---##--- \
+ --##---- \
+ -------- \
+ -------- \
+ -------- \
+ --------
+%
+// left double curly quote
+Unicode: [201c];
+Bitmap: \
+ -------- \
+ -##--##- \
+ -##--##- \
+ --##--## \
+ -------- \
+ -------- \
+ -------- \
+ --------
+%
+// right double curly quote
+Unicode: [201d];
+Bitmap: \
+ -------- \
+ -##--##- \
+ -##--##- \
+ ##--##-- \
+ -------- \
+ -------- \
+ -------- \
+ --------
+%
+// spanish left single quote
+Unicode: [2039];
+Bitmap: \
+ -------- \
+ -------- \
+ -------- \
+ ---##--- \
+ --##---- \
+ ---##--- \
+ -------- \
+ --------
+%
+// spanish right single quote
+Unicode: [203a];
+Bitmap: \
+ -------- \
+ -------- \
+ -------- \
+ ---##--- \
+ ----##-- \
+ ---##--- \
+ -------- \
+ --------
+%
+// replacement character for missing glyphs
+Unicode: [fffd];
+Bitmap: \
+ --####-- \
+ -##--##- \
+ -#-##-#- \
+ -###-##- \
+ -######- \
+ -###-##- \
+ --####-- \
+ --------