Commit be21c000 authored by Ada Gottensträter's avatar Ada Gottensträter

propplay: move help screen to file, fix some bugs

parent bcfb2240
......@@ -3,7 +3,7 @@ mkdir -p sdbins/PROPPLAY
cd source
bstc -c help.spin
python screen.py help.dat help.scr
python compress.py --length 5 --lookback 10 --binary help.scr help.exc
cp help.scr "../sdbins/propplay/HELP.SCR"
bstc -c -o "../sdbins/propplay/sid" SIDcog_asm.spin
mv "../sdbins/propplay/sid.dat" "../sdbins/propplay/SID.COG"
......
import time
import sys
import array
def prefix(s1, s2):
""" Return the length of the common prefix of s1 and s2 """
sz = len(s2)
for i in range(sz):
if s1[i % len(s1)] != s2[i]:
return i
return sz
class Bitstream(object):
def __init__(self):
self.b = []
def append(self, sz, v):
assert 0 <= v
assert v < (1 << sz)
for i in range(sz):
self.b.append(1 & (v >> (sz - 1 - i)))
def toarray(self):
bb = [0] * int((len(self.b) + 7) / 8)
for i,b in enumerate(self.b):
if b:
bb[int(i / 8)] |= (1 << (i & 7));
return array.array('B', bb)
class Codec(object):
def __init__(self, b_off, b_len):
self.b_off = b_off
self.b_len = b_len
self.history = 2 ** b_off
refsize = (1 + self.b_off + self.b_len) # bits needed for a backreference
if refsize < 9:
self.M = 1
elif refsize < 18:
self.M = 2
else:
self.M = 3
# print "M", self.M
# e.g. M 2, b_len 4, so: 0->2, 15->17
self.maxlen = self.M + (2**self.b_len) - 1
def compress(self, blk):
lempel = {}
sched = []
pos = 0
while pos < len(blk):
k = blk[pos:pos+self.M]
older = (pos - self.history - 1)
candidates = [p for p in lempel.get(k, []) if (older < p)]
(bestlen, bestpos) = max([(0, 0)] + [(prefix(blk[p:pos], blk[pos:]), p) for p in candidates])
if k in lempel:
lempel[k].add(pos)
else:
lempel[k] = set([pos])
bestlen = min(bestlen, self.maxlen)
if bestlen >= self.M:
sched.append((bestpos - pos, bestlen))
pos += bestlen
else:
sched.append(chr(blk[pos]))
pos += 1
return sched
def toarray(self, blk):
bs = Bitstream()
bs.append(4, self.b_off)
bs.append(4, self.b_len)
bs.append(2, self.M)
sched = self.compress(blk)
bs.append(16, len(sched))
for c in sched:
if len(c) != 1:
(offset, l) = c
bs.append(1, 1)
bs.append(self.b_off, -offset - 1)
bs.append(self.b_len, l - self.M)
else:
bs.append(1, 0)
bs.append(8, ord(c))
return bs.toarray()
def to_cfile(self, hh, blk, name):
print >>hh, "static PROGMEM prog_uchar %s[] = {" % name
bb = self.toarray(blk)
for i in range(0, len(bb), 16):
if (i & 0xff) == 0:
print >>hh
for c in bb[i:i+16]:
print >>hh, "0x%02x, " % c,
print >>hh
print >>hh, "};"
def decompress(self, sched):
s = ""
for c in sched:
if len(c) == 1:
s += c
else:
(offset, l) = c
for i in range(l):
s += s[offset]
return s
def main():
from optparse import OptionParser
parser = OptionParser("%prog [ --lookback O ] [ --length L ] --name NAME inputfile outputfile")
parser.add_option("--lookback", type=int, default=8, dest="O", help="lookback field size in bits")
parser.add_option("--length", type=int, default=3, dest="L", help="length field size in bits")
parser.add_option("--name", type=str, default="data", dest="NAME", help="name for generated C array")
parser.add_option("--binary", action="store_true", default=False, dest="binary", help="write a binary file (default is to write a C++ header file)")
options, args = parser.parse_args()
if len(args) != 2:
parser.error("must specify input and output files");
print (options.O)
print (options.L)
print (options.NAME)
print (args)
(inputfile, outputfile) = args
cc = Codec(b_off = options.O, b_len = options.L)
uncompressed = open(inputfile, "rb").read()
if options.binary:
compressed = cc.toarray(uncompressed)
open(outputfile, "wb").write(compressed.tostring())
else:
outfile = open(outputfile, "w")
cc.to_cfile(outfile, uncompressed, options.NAME)
if __name__ == "__main__":
main()
Binary files a/utils/propplay_tv/source/decompress.spin and /dev/null differ
......@@ -9,11 +9,15 @@ def main():
infile = open(infilen, "rb")
outfile = open(outfilen, "wb")
byte = infile.read(1)
while len(byte):
outfile.write(byte)
outfile.write(b'\x9e')
byte = infile.read(1)
color = infile.read(1)
while len(color):
scr = infile.read(960)
if len(scr) != 960:
raise Exception('Screen too short')
for i in range(0,960):
outfile.write(scr[i:i+1])
outfile.write(color)
color = infile.read(1)
outfile.close()
infile.close()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment