#!/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()