81 lines
2.1 KiB
Python
81 lines
2.1 KiB
Python
#!/usr/bin/env python
|
|
|
|
# currently only extracts text metadata
|
|
|
|
import sys
|
|
|
|
def error(msg):
|
|
print(msg)
|
|
sys.exit(1)
|
|
|
|
def parsestr(data, start):
|
|
end = start + data[start:].find(b'\0')
|
|
return end + 1, data[start:end].decode('ascii')
|
|
|
|
def parsefields(data, pos0):
|
|
pos1, name = parsestr(data, pos0)
|
|
pos2, version = parsestr(data, pos1)
|
|
pos3, author = parsestr(data, pos2)
|
|
pos4, desc = parsestr(data, pos3)
|
|
return {'name': name, 'version': version, 'author': author, 'desc': desc}
|
|
|
|
def parse(data, pos0):
|
|
if len(data[pos0:]) < 6:
|
|
raise Exception('not enough data!')
|
|
a,b,c,d,e,f = data[pos0:pos0+6]
|
|
if a != 0xa0 or d != 0x80 or f != 0x37:
|
|
return None
|
|
else:
|
|
return (e, b, c)
|
|
|
|
def toaddr(x, y):
|
|
return x * 256 + y - 256
|
|
|
|
def main():
|
|
if len(sys.argv[1:]) != 1:
|
|
print('usage: %s ROMFILE' % sys.argv[0])
|
|
sys.exit(1)
|
|
|
|
f = open(sys.argv[1], 'rb')
|
|
data = f.read()
|
|
f.close()
|
|
|
|
if len(data) < 6:
|
|
return error("file too small: %d bytes" % len(data))
|
|
|
|
(kind, x, y) = parse(data, 0)
|
|
if kind != 0xf0:
|
|
head = ''.join(['%02x' % n for n in data[0:6]])
|
|
return error("file should start with 'a0____804037' but got %r" % head)
|
|
|
|
icon_type = None
|
|
icon_data = None
|
|
|
|
i = 6
|
|
while True:
|
|
res = parse(data, i)
|
|
if res is None:
|
|
break
|
|
i += 6
|
|
kind, x, y = res
|
|
xy = '%02x%02x' % (x, y)
|
|
if kind == 0xf2:
|
|
fields = parsefields(data, toaddr(x, y))
|
|
print('fields: %r' % fields)
|
|
elif kind == 0xf4:
|
|
icon_type = x * 256 - y
|
|
print('icon type: %s' % xy)
|
|
elif kind == 0xf6:
|
|
# TODO: extract icon data as BMP or similar
|
|
print('icon data at %s' % xy)
|
|
elif kind == 0xf8:
|
|
print('maximum memory address is %s' % xy)
|
|
elif kind == 0xfa:
|
|
# TODO: parse manifest structure
|
|
print('manifest data at %s' % xy)
|
|
else:
|
|
print('unknown field: %02x (%s)' % (kind, xy))
|
|
|
|
if __name__ == "__main__":
|
|
main()
|