#!/usr/bin/env python3 # vim:set tabstop=4 shiftwidth=4 expandtab smarttab from sys import argv, exit, stderr from struct import unpack, calcsize from enum import Enum class nodetype(Enum): REPT = 0 FILE = 1 MACRO = 2 class symtype(Enum): LOCAL = 0 IMPORT = 1 EXPORT = 2 class sectype(Enum): WRAM0 = 0 VRAM = 1 ROMX = 2 ROM0 = 3 HRAM = 4 WRAMX = 5 SRAM = 6 OAM = 7 class patchtype(Enum): BYTE = 0 WORD = 1 LONG = 2 JR = 3 class asserttype(Enum): WARN = 0 ERROR = 1 FAIL = 2 def unpack_file(fmt, file): size = calcsize(fmt) return unpack(fmt, file.read(size)) def read_string(file): buf = bytearray() while True: b = file.read(1) if b is None or b == b'\0': return buf.decode() else: buf += b def parse_object(filename): file = open(filename, "rb") obj = { "nodes": [], "symbols": [], "sections": [], "assertions": [], } magic = unpack_file("4s", file)[0] if magic == b'RGB6': obj_ver = 6 elif magic == b'RGB9': obj_ver = 10 + unpack_file("= 16: num_nodes = unpack_file("= 16: node = unpack_file("= 14: section["align"], section["offset"] = unpack_file("= 16: node = unpack_file("= 16: patch["line"] = unpack_file("= 14: patch["pcsectionid"], patch["pcoffset"] = unpack_file("= 13: num_assertions = unpack_file("= 16: node = unpack_file("= 14: assertion["section"], assertion["pcoffset"] = unpack_file("" % argv[0], file=stderr) exit(1) argi = 1 just_dump = False if argv[argi] == "-D": just_dump = True argi += 1 if argv[argi] == "--": argi += 1 globalsyms = {} for filename in argv[argi:]: print(filename, file=stderr) obj = parse_object(filename) if obj is None: exit(1) if just_dump: for symbol in obj["symbols"]: print(symbol["name"]) continue localsyms = {} imports = 0 exports = 0 for symbol in obj["symbols"]: if symbol["type"] == symtype.LOCAL: if symbol["name"] not in localsyms: localsyms[symbol["name"]] = 0 elif symbol["type"] == symtype.IMPORT: imports += 1 if symbol["name"] not in globalsyms: globalsyms[symbol["name"]] = 0 elif symbol["type"] == symtype.EXPORT: exports += 1 if symbol["name"] not in globalsyms: globalsyms[symbol["name"]] = 0 print("Locals:", len(localsyms), file=stderr) print("Imports:", imports, file=stderr) print("Exports:", exports, file=stderr) def parse_rpn(rpn): pos = 0 while pos < len(rpn): if rpn[pos] == 0x51: pos += 1 while rpn[pos] != 0: pos += 1 pos += 1 elif rpn[pos] == 0x80: pos += 5 elif rpn[pos] == 0x50 or rpn[pos] == 0x81: symbol_id = unpack("