nxu/unihex2uf2

109 lines
2.9 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import re
import sys
line_re = re.compile(r'^([0-9A-Fa-f]{4}):((?:[0-9A-Fa-f]{32}){1,2})$')
def parse(line):
m = line_re.match(line)
if not m:
raise Exception('could not parse line: %r' % line)
n = int(m.group(1), 16)
data = m.group(2)
return (n, data)
blank_line = ' '.join(['00'] * 16)
def split16(data):
return ' '.join([data[i:i+2] for i in range(0, 32, 2)])
def split(data):
if len(data) == 32:
return (split16(data),)
elif len(data) == 64:
return (split16(data[0:32]), split16(data[32:64]))
else:
raise Exception('invalid data length: %d' % len(data))
def run(path, start):
limit = start + 256
widths = [8] * 256
lines = []
def emit(n, line1, line2):
lines.append(('( %04x ) ' % n) + line1)
lines.append(' ' + line2)
with open(path, 'r') as f:
seeking = start
for line in f:
n, data = parse(line.lower())
if n < seeking:
continue
if n > seeking:
for i in range(seeking, min(limit, seeking)):
emit(i, blank_line, blank_line)
if n >= limit:
break
tpl = split(data)
if len(tpl) == 1:
emit(n, tpl[0], blank_line)
widths[n - start] = 8
else:
emit(n, tpl[0], tpl[1])
widths[n - start] = 16
seeking = n + 1
for i in range(seeking, limit):
emit(i, blank_line, blank_line)
print('( unifont: %04x to %04x )' % (start, limit - 1))
print('')
print('( widths )')
for i in range(16):
j = i * 16
width_line = ' '.join([('%02x' % widths[k]) for k in range(j, j + 16)])
print(('( %04x ) ' % j) + width_line)
print('')
print('( font data, 2x2 tiles )')
for line in lines:
print(line)
def usage(message=None):
if message:
print('ERROR: %s' % message)
print('')
print('USAGE: %s PATH START' % sys.argv[0])
print('')
print(' PATH is a hex file, e.g. /usr/share/unifont/unifont.hex')
print(' START is a code point in hex, e.g. 0, 3c0, 7f00, etc.')
print('')
print(' each .uf2 file contains 256 characters, so the output')
print(' will contains widths and data for all characters from')
print(' START to START+255 (inclusive).')
print('')
sys.exit(1)
def main():
args = sys.argv[1:]
if len(args) != 2:
return usage()
path, start = args
if not os.path.exists(path):
return usage('could not read .hex file: %s' % path)
try:
n = int(start, 16)
except:
return usage('could not parse start character: %s' % start)
if n < 0:
return usage('start must be >= 0: %s' % start)
if n > 65280:
return usage('start must be <= ff00: %s' % start)
run(path, n)
if __name__ == "__main__":
main()