ref: 59e6baee1eba3ad659d86f5fff6b73d367b12203
dir: /tools/sort_map.py/
#!/usr/bin/env python from __future__ import print_function import sys import re def total_bank_size(type): # used to output the size of EMPTY banks sizes = { 'ROM0': 0x4000, # 0000-3FFF 'ROMX': 0x4000, # 4000-7FFF 'VRAM': 0x2000, # 8000-9FFF 'SRAM': 0x2000, # A000-BFFF 'WRAM0': 0x1000, # C000-CFFF 'WRAMX': 0x1000, # D000-DFFF # E000-FDFF: echo RAM 'OAM': 0xA0, # FE00-FE9F # FEA0-FEFF: unusable # FF00-FF7F: hardware I/O registers 'HRAM': 0x80, # FF80-FFFF } return sizes[type] def sorted_mapfile(input): # ex: OAM: unused_rx = re.compile(r'^([A-Z]+):$') # ex: ROM Bank #1: bank_rx = re.compile(r'^([A-Z]+) Bank #([0-9]+)') # ex: SECTION: $4000-$747A ($347B bytes) ["bank1"] section_rx = re.compile(r' +SECTION: \$([0-9A-F]+)(?:-\$([0-9A-F]+))? \(\$([0-9A-F]+) bytes\) \["(.+)"\]') # ex: $4025 = PlaceWaitingText.Waiting label_rx = re.compile(r' +\$([0-9A-F]+) = (.+)') # ex: SLACK: $0B85 bytes slack_rx = re.compile(r' +SLACK: \$([0-9A-F]+) bytes') bank_type = None bank_number = None bank_size = 0 bank_queue = [] section_queue = [] for line in input: if line.startswith(' EMPTY'): # empty banks have their entire capacity as slack line = ' SLACK: $%04X bytes\n' % total_bank_size(bank_type) x = re.match(unused_rx, line) if x: # start an unused bank bank_type = x.group(1) bank_number = '00' bank_size = 0 del bank_queue[:] del section_queue[:] continue x = re.match(bank_rx, line) if x: # start a new bank bank_type = x.group(1) bank_number = '%02X' % int(x.group(2)) if bank_type == 'ROM': bank_type = 'ROM0' if bank_number == '00' else 'ROMX' if bank_type == 'WRAM': bank_type = 'WRAM0' if bank_number == '00' else 'WRAMX' bank_size = 0 del bank_queue[:] del section_queue[:] continue x = re.match(section_rx, line) if x: # finish current section bank_queue.extend(sorted(section_queue)) # start a new section start = x.group(1) end = x.group(2) or start size = x.group(3).zfill(4) name = x.group(4) bank_size += int(size, 16) bank_queue.append('; %s:%s-%s ($%s) %s\n' % (bank_number, start, end, size, name)) del section_queue[:] continue x = re.match(label_rx, line) if x: # add label to section address = x.group(1) label = x.group(2) section_queue.append('%s:%s %s\n' % (bank_number, address, label)) continue x = re.match(slack_rx, line) if x: # finish current section bank_queue.extend(sorted(section_queue)) # finish current bank slack = int(x.group(1), 16) yield '; %s $%s ($%04X) ($%04X free)\n' % (bank_type, bank_number, bank_size, slack) for line in bank_queue: yield line continue def main(): if len(sys.argv) < 3: print('Usage: %s pokecrystal.map sorted.sym' % sys.argv[0], file=sys.stderr) sys.exit(1) input_filename = sys.argv[1] output_filename = sys.argv[2] with open(input_filename, 'r') as infile: input = infile.readlines() output = sorted_mapfile(input) with open(output_filename, 'w') as outfile: for line in output: outfile.write(line) if __name__ == '__main__': main()