diff options
Diffstat (limited to 'pokemontools/sym.py')
-rw-r--r-- | pokemontools/sym.py | 116 |
1 files changed, 79 insertions, 37 deletions
diff --git a/pokemontools/sym.py b/pokemontools/sym.py index f78b9af..ebd8532 100644 --- a/pokemontools/sym.py +++ b/pokemontools/sym.py @@ -1,54 +1,96 @@ -# -*- coding: utf-8 -*- +# coding: utf-8 +import os +import sys import json -# from crystal import load_rom -# from gbz80disasm import load_labels - - def make_sym_from_json(filename = '../pokecrystal.sym', j = 'labels.json'): - # todo: delete and remake labels.json at runtime + output = '' + labels = json.load(open(j)) + for label in labels: + output += '{0:x}:{1:x} {2}\n'.format(label['bank'], label['address'], label['label']) with open(filename, 'w') as sym: - for label in json.load(open(j)): - sym.write('{0:x}:{1:x} {2}\n'.format(label['bank'], label['address']%0x4000 + (0x4000 if label['bank'] else 0), label['label'])) + sym.write(output) + +def make_json_from_mapfile(filename='labels.json', mapfile='../pokecrystal.map'): + output = [] + labels = filter_wram_addresses(read_mapfile(mapfile)) + with open(filename, 'w') as out: + out.write(json.dumps(labels)) + +def read_mapfile(filename='../pokecrystal.map'): + """ + Scrape label addresses from an rgbds mapfile. + """ + + labels = [] + + with open(filename, 'r') as mapfile: + lines = mapfile.readlines() + + for line in lines: + # bank # + if 'Bank #' in line: + cur_bank = int(line.lstrip('Bank #').strip(';\n').strip(' (HOME)')) + # label definition + elif '=' in line: + address, label = line.split('=') + address = int(address.lstrip().replace('$', '0x'), 16) + label = label.strip() + + # rgbds doesn't support ram banks yet + bank = cur_bank + offset = address + + ranges = [ + 0x8000 <= address < 0xa000, + 0xa000 <= address < 0xc000, + 0xc000 <= address < 0xd000, + 0xd000 <= address < 0xe000, + ] + + if any(ranges): + bank = 0 + else: + offset += (bank * 0x4000 - 0x4000) if bank > 0 else 0 + + labels += [{ + 'label': label, + 'bank': bank, + 'address': offset, + 'offset': offset, + 'local_address': address, + }] + + return labels + +def filter_wram_addresses(labels): + filtered_labels = [] + for label in labels: + if label['local_address'] < 0x8000: + filtered_labels += [label] + return filtered_labels def make_sym_from_mapfile(filename = '../pokecrystal.sym', mapfile = '../mapfile.txt'): # todo: sort label definitions by address output = '' - # get label definitions - with open(mapfile,'r') as map: - lines = map.readlines() - for line in lines: - # bank # - if 'Bank #' in line: - cur_bank = int(line.lstrip('Bank #').strip(':\n').strip(' (HOME)')) - - # label definition - elif '=' in line: - thing = line.split('=') - spacing = ' ' * 11 # arbitrary - addr = int(thing[0].lstrip(spacing)[1:5],16) - - # rgbds doesn't support wram banks yet, - # so this hack is applied instead - if addr > 0xbfff: # 0xc000+ (wram only) - cur_bank = 0 - if addr > 0xcfff: # 0xd000+ (wram only) - cur_bank = 1 - - # convert to sym format (bank:addr label) - label = thing[1].strip('\n') - output += hex(cur_bank)[2:] + ':' + hex(addr)[2:] + ' ' + label + '\n' + labels = read_mapfile() + + # convert to sym format (bank:addr label) + for label in labels: + output += '%.2x:%.4x %s\n' % (label['bank'], label['address'], label['label']) # dump contents to symfile with open(filename, 'w') as sym: sym.write(output) - if __name__ == "__main__": - # default behavior: generate sym file from rgbds mapfile - try: make_sym_from_mapfile() - # if no mapfile exists, generate from labels.json - except: make_sym_from_json() + #if os.path.exists('../pokecrystal.sym'): + # sys.exit() + #elif os.path.exists('../pokecrystal.map'): + # make_sym_from_mapfile() + #elif os.path.exists('labels.json'): + # make_sym_from_json() + make_json_from_mapfile() |