parse colors out of rom

This commit is contained in:
~d6 2022-11-14 18:02:15 -05:00
parent e74ef2bde2
commit 62bb579153
1 changed files with 50 additions and 14 deletions

64
uxnmeta
View File

@ -17,10 +17,14 @@ def parsestr(data, start):
end = start + data[start:].find(b'\0') end = start + data[start:].find(b'\0')
return end + 1, data[start:end].decode('ascii') 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 # convert 64x64 icn to bmp
# since we are always dealing with a 1-bit 64x64 # since we are always dealing with a 1-bit 64x64
# image we can just hardcode the BMP header data # 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"BM" # 0: bitmap file
bmp += b"\x20\x10\x00\x00" # 2: file size: 4128 (32 + 4096) bmp += b"\x20\x10\x00\x00" # 2: file size: 4128 (32 + 4096)
bmp += b"\x00\x00" # 6: reserved: 0 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"\x40\x00" # 20: height in pixels: 64
bmp += b"\x01\x00" # 22: color planes: 1 bmp += b"\x01\x00" # 22: color planes: 1
bmp += b"\x01\x00" # 24: bits per pixel: 1 bmp += b"\x01\x00" # 24: bits per pixel: 1
bmp += b"\xff\xff\xff" # 26: color 0 bmp += emit24(light) # 26: color 0
bmp += b"\x00\x00\x00" # 29: color 1 bmp += emit24(dark) # 29: color 1
# 32: start of pixel data # 32: start of pixel data
# ICN is composed of a grid of 8x8 tiles. for BMP we need # ICN is composed of a grid of 8x8 tiles. for BMP we need
@ -48,13 +52,26 @@ def tobmp(icn):
return bmp return bmp
# read the icon from the given binary data and address # 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: if len(data[pos0:]) < 512:
print('needed 512 bytes, only had %d' % len(data[pos0:])) print('needed 512 bytes, only had %d' % len(data[pos0:]))
icn = data[pos0:pos0+512] icn = data[pos0:pos0+512]
bmp = tobmp(icn) bmp = tobmp(icn, light, dark)
return bmp 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 # parse the metadata from the given binary data and address
def parsemeta(path, data, pos0): def parsemeta(path, data, pos0):
a,b,c,d = data[pos0:pos0+4] a,b,c,d = data[pos0:pos0+4]
@ -66,15 +83,11 @@ def parsemeta(path, data, pos0):
pos4, author = parsestr(data, pos3) pos4, author = parsestr(data, pos3)
if pos4 != endaddr: if pos4 != endaddr:
print('%s: data ended by %04x but expected %04x' % (path, pos4, endaddr)) print('%s: data ended by %04x but expected %04x' % (path, pos4, endaddr))
bmp = parseicon(path, data, iconaddr) meta = {'name': name, 'version': version, 'desc': desc, 'author': author, 'icon': iconaddr}
return {'name': name, 'version': version, 'desc': desc, 'author': author, 'icon': bmp} return meta
# parse metadata from the given uxn rom # parse metadata from the given uxn rom
def parse(path): def parse(path, data):
f = open(path, 'rb')
data = f.read()
f.close()
if len(data) < 6: if len(data) < 6:
print("%s: file too small (%d bytes)" % (path, len(data))) print("%s: file too small (%d bytes)" % (path, len(data)))
exit(1) exit(1)
@ -93,11 +106,34 @@ def main():
exit(1) exit(1)
path = argv[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' iconpath = path + '.bmp'
bmp = parseicon(path, data, meta['icon'], light, dark)
with open(iconpath, 'wb') as f: with open(iconpath, 'wb') as f:
f.write(meta['icon']) f.write(bmp)
print('%s:' % path) print('%s:' % path)
print(' Name: %s' % meta['name']) print(' Name: %s' % meta['name'])