#!/usr/bin/python2
# This decodes fonts from the original binary and outputs binary stream for
# displaying with printline_decoder.
# usage: python fontdecode.py program.bin H e l l o ' ' 0xb5 0xb6 0xb7 0xb8 | python printline_decoder.py
from sys import argv

def extract_glyphs(rawdata):
	charsize = 24
	fontstart = 0x6800

	glyphs = []
	for i in range(0x100):
		byteoffset = i * charsize
		pos = fontstart + byteoffset
		glyphs.append(rawdata[pos:pos + charsize])
	return glyphs

def wordstr(x):
	return ("%016d" % int(bin(x)[len("0b"):]))

def bytes2words(buf):
	ret = []
	for lo, hi in zip(buf[::2], buf[1::2]):
		ret.append(lo | (hi << 8))
	return ret

def build_charbits(glyphs, char):
	#try:
	#	ch = int(char, 0) # decimal value or 0xhex
	#except ValueError:
	#	ch = ord(char) # a simple character
	ch = ord(char)

	bytebuf = map(ord, glyphs[ch])
	words = bytes2words(bytebuf)
	strwords = map(wordstr, words)
	import pprint, sys; pprint.pprint(strwords, sys.stderr) # debug log
	revstr = lambda s: s[::-1]
	low12bits = lambda w: w[4:]
	low11bits = lambda w: w[5:]
	# 2 first words are some magic
	# upper bits also contain something
	top = "".join(map(lambda x: x, map(low12bits, strwords[2:7])))
	bot = "".join(map(revstr, map(low11bits, strwords[7:12])))
	return (top, bot)

def pad_printline(toprow, botrow):
	segments = 4
	segcolumns = 24
	toprows = 12
	botrows = 11

	topbits = segments * segcolumns * toprows
	botbits = segments * segcolumns * botrows

	tops = toprow + "0" * (topbits - len(toprow))
	bots = botrow + "0" * (botbits - len(botrow))

	return "\n".join(tops[::-1] + bots)

def main():
	rawdata = open(argv[1], "rb").read()
	glyphs = extract_glyphs(rawdata)
	chars = argv[2:]
	if chars[0] == "line":
		startoff = int(chars[1])
		charsperline = 19
		chars = map(chr, range(charsperline*startoff, min(255, charsperline*startoff + charsperline)))
	tops, bots = map("".join, zip(*[build_charbits(glyphs, x) for x in chars]))
	print pad_printline(tops, bots)

if __name__ == "__main__":
	main()

