From 62bb579153259d8fc278ce9d274f98827a3d734d Mon Sep 17 00:00:00 2001 From: d6 Date: Mon, 14 Nov 2022 18:02:15 -0500 Subject: [PATCH] parse colors out of rom --- uxnmeta | 64 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/uxnmeta b/uxnmeta index 3241256..c666015 100755 --- a/uxnmeta +++ b/uxnmeta @@ -17,10 +17,14 @@ def parsestr(data, start): end = start + data[start:].find(b'\0') return end + 1, data[start:end].decode('ascii') +# emit 24-bit integer (big endian) +def emit24(n): + return bytes([(n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]) + # convert 64x64 icn to bmp # since we are always dealing with a 1-bit 64x64 # image we can just hardcode the BMP header data -def tobmp(icn): +def tobmp(icn, light, dark): bmp = b"BM" # 0: bitmap file bmp += b"\x20\x10\x00\x00" # 2: file size: 4128 (32 + 4096) bmp += b"\x00\x00" # 6: reserved: 0 @@ -31,8 +35,8 @@ def tobmp(icn): bmp += b"\x40\x00" # 20: height in pixels: 64 bmp += b"\x01\x00" # 22: color planes: 1 bmp += b"\x01\x00" # 24: bits per pixel: 1 - bmp += b"\xff\xff\xff" # 26: color 0 - bmp += b"\x00\x00\x00" # 29: color 1 + bmp += emit24(light) # 26: color 0 + bmp += emit24(dark) # 29: color 1 # 32: start of pixel data # ICN is composed of a grid of 8x8 tiles. for BMP we need @@ -48,13 +52,26 @@ def tobmp(icn): return bmp # read the icon from the given binary data and address -def parseicon(path, data, pos0): +def parseicon(path, data, pos0, light, dark): if len(data[pos0:]) < 512: print('needed 512 bytes, only had %d' % len(data[pos0:])) icn = data[pos0:pos0+512] - bmp = tobmp(icn) + bmp = tobmp(icn, light, dark) return bmp +# try to parse LIT2 x y .System/[rgb] DEO2 +# returns (shift, tint) +# shift 16=red, 8=green, 0=blue +def parsecolor(data, pos0): + a,b,c,d,e,f = data[pos0:pos0+6] + if a == 0xa0 and d == 0x80 and f == 0x37: + tint = b * 256 + c + # we only care about 'b' i.e. the first two colors + if e == 0x08: return (16, tint) + if e == 0x0a: return (8, tint) + if e == 0x0c: return (0, tint) + return None + # parse the metadata from the given binary data and address def parsemeta(path, data, pos0): a,b,c,d = data[pos0:pos0+4] @@ -66,15 +83,11 @@ def parsemeta(path, data, pos0): pos4, author = parsestr(data, pos3) if pos4 != endaddr: print('%s: data ended by %04x but expected %04x' % (path, pos4, endaddr)) - bmp = parseicon(path, data, iconaddr) - return {'name': name, 'version': version, 'desc': desc, 'author': author, 'icon': bmp} + meta = {'name': name, 'version': version, 'desc': desc, 'author': author, 'icon': iconaddr} + return meta # parse metadata from the given uxn rom -def parse(path): - f = open(path, 'rb') - data = f.read() - f.close() - +def parse(path, data): if len(data) < 6: print("%s: file too small (%d bytes)" % (path, len(data))) exit(1) @@ -93,11 +106,34 @@ def main(): exit(1) path = argv[1] - meta = parse(path) + f = open(path, 'rb') + data = f.read() + f.close() + + meta = parse(path, data) + + i = 6 + colors = [0, 0, 0, 0] + while True: + res = parsecolor(data, i) + i += 6 + if res is None: + break + shift, tint = res + colors[0] |= ((((tint >> 12) & 0xf) * 0x11) << shift) + colors[1] |= ((((tint >> 8) & 0xf) * 0x11) << shift) + colors[2] |= ((((tint >> 4) & 0xf) * 0x11) << shift) + colors[3] |= ((((tint >> 0) & 0xf) * 0x11) << shift) + + if colors == [0, 0, 0, 0]: + dark, light = 0x000000, 0xffffff + else: + dark, light = colors[0], colors[1] iconpath = path + '.bmp' + bmp = parseicon(path, data, meta['icon'], light, dark) with open(iconpath, 'wb') as f: - f.write(meta['icon']) + f.write(bmp) print('%s:' % path) print(' Name: %s' % meta['name'])