parse colors out of rom
This commit is contained in:
parent
e74ef2bde2
commit
62bb579153
64
uxnmeta
64
uxnmeta
|
@ -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'])
|
||||||
|
|
Loading…
Reference in New Issue