paul@78 | 1 | #!/usr/bin/env python |
paul@78 | 2 | |
paul@78 | 3 | """ |
paul@78 | 4 | Convert simple font bitmaps to GNU assembler data. |
paul@78 | 5 | |
paul@78 | 6 | Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk> |
paul@78 | 7 | |
paul@78 | 8 | This program is free software; you can redistribute it and/or modify it under |
paul@78 | 9 | the terms of the GNU General Public License as published by the Free Software |
paul@78 | 10 | Foundation; either version 3 of the License, or (at your option) any later |
paul@78 | 11 | version. |
paul@78 | 12 | |
paul@78 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY |
paul@78 | 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
paul@78 | 15 | PARTICULAR PURPOSE. See the GNU General Public License for more details. |
paul@78 | 16 | |
paul@78 | 17 | You should have received a copy of the GNU General Public License along |
paul@78 | 18 | with this program. If not, see <http://www.gnu.org/licenses/>. |
paul@78 | 19 | """ |
paul@78 | 20 | |
paul@78 | 21 | import sys |
paul@78 | 22 | |
paul@78 | 23 | class MissingRow(Exception): |
paul@78 | 24 | |
paul@78 | 25 | "Indicate a missing row in a character definition." |
paul@78 | 26 | |
paul@78 | 27 | def __init__(self, lineno): |
paul@78 | 28 | self.lineno = lineno |
paul@78 | 29 | |
paul@78 | 30 | def __repr__(self): |
paul@78 | 31 | return "MissingRow(%r)" % self.lineno |
paul@78 | 32 | |
paul@78 | 33 | |
paul@78 | 34 | |
paul@78 | 35 | def get_character_row(f, lineno=0): |
paul@78 | 36 | |
paul@78 | 37 | "Return a row of characters from 'f', employing 'lineno' for reference." |
paul@78 | 38 | |
paul@78 | 39 | line = f.readline().strip() |
paul@78 | 40 | rows = [] |
paul@78 | 41 | |
paul@78 | 42 | while line: |
paul@78 | 43 | row = line.split() |
paul@78 | 44 | if rows and len(row) != len(rows[-1]): |
paul@78 | 45 | raise MissingRow, lineno |
paul@78 | 46 | |
paul@78 | 47 | rows.append(row) |
paul@78 | 48 | lineno += 1 |
paul@78 | 49 | line = f.readline().strip() |
paul@78 | 50 | |
paul@78 | 51 | chars = [] |
paul@78 | 52 | |
paul@78 | 53 | if rows: |
paul@78 | 54 | for i in range(0, len(rows[0])): |
paul@78 | 55 | char = [] |
paul@78 | 56 | for row in rows: |
paul@78 | 57 | char.append(row[i]) |
paul@78 | 58 | chars.append(char) |
paul@78 | 59 | |
paul@78 | 60 | return chars |
paul@78 | 61 | |
paul@78 | 62 | |
paul@78 | 63 | |
paul@78 | 64 | def convert(infile, outfile, base=33): |
paul@78 | 65 | |
paul@78 | 66 | "Convert textual data in 'infile' to assembler data in 'outfile'." |
paul@78 | 67 | |
paul@78 | 68 | f_in = open(infile) |
paul@78 | 69 | f_out = open(outfile, "w") |
paul@78 | 70 | try: |
paul@78 | 71 | print >>f_out, """\ |
paul@78 | 72 | .globl fontchars |
paul@78 | 73 | .globl fonttable |
paul@78 | 74 | .globl fontbase |
paul@78 | 75 | .globl fontlimit |
paul@78 | 76 | |
paul@78 | 77 | .section .flash, "a" |
paul@78 | 78 | |
paul@135 | 79 | fontchars:""" |
paul@78 | 80 | |
paul@78 | 81 | lineno = 1 |
paul@78 | 82 | offset = 0 |
paul@78 | 83 | offsets = [] |
paul@78 | 84 | point = base |
paul@78 | 85 | |
paul@78 | 86 | # Get each row of characters. |
paul@78 | 87 | |
paul@78 | 88 | chars = get_character_row(f_in, lineno) |
paul@78 | 89 | |
paul@78 | 90 | while chars: |
paul@78 | 91 | lineno += len(chars[0]) + 1 |
paul@78 | 92 | |
paul@78 | 93 | # Write each character definition. |
paul@78 | 94 | |
paul@78 | 95 | for point, char in enumerate(chars, point): |
paul@78 | 96 | offsets.append(offset) |
paul@78 | 97 | offset += write_character(f_out, point, char) |
paul@78 | 98 | |
paul@78 | 99 | point += 1 |
paul@78 | 100 | |
paul@78 | 101 | # Get the next row. |
paul@78 | 102 | |
paul@78 | 103 | chars = get_character_row(f_in, lineno) |
paul@78 | 104 | |
paul@78 | 105 | # Write the limit of characters. |
paul@78 | 106 | |
paul@78 | 107 | print >>f_out, """\ |
paul@135 | 108 | fontbase: |
paul@135 | 109 | .word %d |
paul@135 | 110 | |
paul@78 | 111 | fontlimit: |
paul@135 | 112 | .word %d""" % (base, point) |
paul@78 | 113 | |
paul@78 | 114 | # Write the offset table. |
paul@78 | 115 | |
paul@78 | 116 | print >>f_out, """\ |
paul@78 | 117 | fonttable:""" |
paul@78 | 118 | |
paul@78 | 119 | for offset in offsets: |
paul@78 | 120 | print >>f_out, ".word %d" % offset |
paul@78 | 121 | |
paul@78 | 122 | finally: |
paul@78 | 123 | f_in.close() |
paul@78 | 124 | f_out.close() |
paul@78 | 125 | |
paul@78 | 126 | |
paul@78 | 127 | |
paul@78 | 128 | def write_character(f, point, char): |
paul@78 | 129 | |
paul@78 | 130 | "Write to 'f' for the given 'point' the indicated 'char' definition." |
paul@78 | 131 | |
paul@78 | 132 | # Write a comment and pixel width information. |
paul@78 | 133 | |
paul@78 | 134 | print >>f, """\ |
paul@78 | 135 | /* %d */ |
paul@78 | 136 | .byte %d /* width in pixels */ |
paul@78 | 137 | .byte %d /* height in pixels */ |
paul@78 | 138 | """ % (point, len(char[0]), len(char)) |
paul@78 | 139 | |
paul@78 | 140 | # Write the pixel rows to a sequence of bytes. |
paul@78 | 141 | |
paul@78 | 142 | for row in char: |
paul@78 | 143 | print >>f, ".byte 0b%s" % row.replace("-", "0").replace("#", "1") |
paul@78 | 144 | |
paul@78 | 145 | print >>f |
paul@78 | 146 | |
paul@78 | 147 | # Return the size of the definition as the number of rows plus the width |
paul@78 | 148 | # and height bytes. |
paul@78 | 149 | |
paul@78 | 150 | return len(char) + 2 |
paul@78 | 151 | |
paul@78 | 152 | |
paul@78 | 153 | |
paul@78 | 154 | # Main program. |
paul@78 | 155 | |
paul@78 | 156 | if __name__ == "__main__": |
paul@78 | 157 | |
paul@78 | 158 | # Obtain filenames. |
paul@78 | 159 | |
paul@78 | 160 | try: |
paul@78 | 161 | infile, outfile = sys.argv[1:3] |
paul@78 | 162 | except ValueError: |
paul@78 | 163 | print >>sys.stderr, """\ |
paul@78 | 164 | Usage: %s <input filename> <output filename> |
paul@78 | 165 | """ |
paul@78 | 166 | sys.exit(1) |
paul@78 | 167 | |
paul@78 | 168 | # Perform the conversion. |
paul@78 | 169 | |
paul@78 | 170 | try: |
paul@78 | 171 | convert(infile, outfile) |
paul@78 | 172 | except MissingRow, exc: |
paul@78 | 173 | print >>sys.stderr, """\ |
paul@78 | 174 | Missing character information at line %d in file %s. |
paul@78 | 175 | """ % (exc.lineno, infile) |
paul@78 | 176 | |
paul@78 | 177 | # vim: tabstop=4 expandtab shiftwidth=4 |