diff options
author | Bryan Bishop <kanzure@gmail.com> | 2013-05-15 12:09:31 -0700 |
---|---|---|
committer | Bryan Bishop <kanzure@gmail.com> | 2013-05-15 12:09:31 -0700 |
commit | 5feb5fd208d68a3d8f4d0ce4d925512a8fbe3b97 (patch) | |
tree | 831df9be5469d1390f9b279a013ed0251c24fca7 | |
parent | 14567c2beeeb9272bcd98dfc68e0729ac3b3929e (diff) | |
parent | 5521aa5ce0ad5249ff0d369dd33b4f63cd804b73 (diff) |
Merge pull request #137 from yenatch/master
gbz80disasm reads wram/gbhw/hram and spaces blocks of asm
-rw-r--r-- | extras/gbz80disasm.py | 120 | ||||
-rw-r--r-- | extras/wram.py | 61 | ||||
-rw-r--r-- | main.asm | 69 | ||||
-rw-r--r-- | preprocessor.py | 23 |
4 files changed, 178 insertions, 95 deletions
diff --git a/extras/gbz80disasm.py b/extras/gbz80disasm.py index d57a1905a..b27ce17ad 100644 --- a/extras/gbz80disasm.py +++ b/extras/gbz80disasm.py @@ -6,16 +6,15 @@ from copy import copy, deepcopy from ctypes import c_int8 import random import json +from wram import * # New versions of json don't have read anymore. if not hasattr(json, "read"): json.read = json.loads -from romstr import RomStr - def load_rom(filename="../baserom.gbc"): global rom - rom = RomStr.load(filename=filename) + rom = bytearray(open(filename,'rb').read()) return rom spacing = "\t" @@ -543,10 +542,11 @@ for line in temp_opt_table: del line end_08_scripts_with = [ +0xc9, #ret +0xd9, #reti 0xe9, #jp hl #0xc3, #jp ##0x18, #jr -0xc9, #ret ###0xda, 0xe9, 0xd2, 0xc2, 0xca, 0xc3, 0x38, 0x30, 0x20, 0x28, 0x18, 0xd8, 0xd0, 0xc0, 0xc8, 0xc9 ] relative_jumps = [0x38, 0x30, 0x20, 0x28, 0x18, 0xc3, 0xda, 0xc2] @@ -565,27 +565,20 @@ def load_labels(filename="labels.json"): crystal.scan_for_predefined_labels() def find_label(local_address, bank_id=0): - global all_labels - # keep an integer if type(local_address) == str: - local_address1 = int(local_address.replace("$", "0x"), 16) - else: local_address1 = local_address - - # turn local_address into an integer - if type(local_address) == str: - if "0x" in local_address: - local_address = local_address.replace("0x", "$") - elif "$" in local_address: - local_address = local_address.replace("$", "") - - if type(local_address) == str: - local_address = int(local_address, 16) - - for label_entry in all_labels: - if label_entry["address"] == local_address: - if label_entry["bank"] == bank_id or (local_address1 < 0x8000 and (label_entry["bank"] == 0 or label_entry["bank"] == 1)): - return label_entry["label"] + local_address = int(local_address.replace("$", "0x"), 16) + + if local_address < 0x8000: + for label_entry in all_labels: + if label_entry["address"] == local_address: + if label_entry["bank"] == bank_id or label_entry["bank"] == 0: + return label_entry["label"] + if local_address in wram_labels.keys(): + return wram_labels[local_address][-1] + for constants in [gbhw_constants, hram_constants]: + if local_address in constants.keys(): + return constants[local_address] return None def asm_label(address): @@ -608,9 +601,7 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add load_labels() load_rom() - bank_id = 0 - if original_offset > 0x8000: - bank_id = original_offset / 0x4000 + bank_id = original_offset / 0x4000 if debug: print "bank id is: " + str(bank_id) last_hl_address = None #for when we're scanning the main map script @@ -630,7 +621,7 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add output = "" keep_reading = True while offset <= end_address and keep_reading: - current_byte = ord(rom[offset]) + current_byte = rom[offset] is_data = False maybe_byte = current_byte @@ -645,6 +636,7 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add if offset in byte_labels.keys(): line_label = byte_labels[offset]["name"] byte_labels[offset]["usage"] += 1 + output += "\n" else: line_label = asm_label(offset) byte_labels[offset] = {} @@ -655,13 +647,13 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add #find out if there's a two byte key like this temp_maybe = maybe_byte - temp_maybe += ( ord(rom[offset+1]) << 8) - if temp_maybe in opt_table.keys() and ord(rom[offset+1])!=0: + temp_maybe += ( rom[offset+1] << 8) + if temp_maybe in opt_table.keys() and rom[offset+1]!=0: opstr = opt_table[temp_maybe][0].lower() if "x" in opstr: for x in range(0, opstr.count("x")): - insertion = ord(rom[offset + 1]) + insertion = rom[offset + 1] insertion = "$" + hex(insertion)[2:] opstr = opstr[:opstr.find("x")].lower() + insertion + opstr[opstr.find("x")+1:].lower() @@ -670,8 +662,8 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add offset += 1 if "?" in opstr: for y in range(0, opstr.count("?")): - byte1 = ord(rom[offset + 1]) - byte2 = ord(rom[offset + 2]) + byte1 = rom[offset + 1] + byte2 = rom[offset + 2] number = byte1 number += byte2 << 8; @@ -695,7 +687,7 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add #type = -1 when it's the E op #if op_code_type != -1: - if op_code_type == 0 and ord(rom[offset]) == op_code_byte: + if op_code_type == 0 and rom[offset] == op_code_byte: op_str = op_code[0].lower() output += spacing + op_code[0].lower() #+ " ; " + hex(offset) @@ -703,18 +695,18 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add offset += 1 current_byte_number += 1 - elif op_code_type == 1 and ord(rom[offset]) == op_code_byte: + elif op_code_type == 1 and rom[offset] == op_code_byte: oplen = len(op_code[0]) opstr = copy(op_code[0]) xes = op_code[0].count("x") include_comment = False for x in range(0, xes): - insertion = ord(rom[offset + 1]) + insertion = rom[offset + 1] insertion = "$" + hex(insertion)[2:] if current_byte == 0x18 or current_byte==0x20 or current_byte in relative_jumps: #jr or jr nz #generate a label for the byte we're jumping to - target_address = offset + 2 + c_int8(ord(rom[offset + 1])).value + target_address = offset + 2 + c_int8(rom[offset + 1]).value if target_address in byte_labels.keys(): byte_labels[target_address]["usage"] = 1 + byte_labels[target_address]["usage"] line_label2 = byte_labels[target_address]["name"] @@ -726,29 +718,34 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add byte_labels[target_address]["definition"] = False insertion = line_label2.lower() - include_comment = True + if has_outstanding_labels(byte_labels) and all_outstanding_labels_are_reverse(byte_labels, offset): + include_comment = True elif current_byte == 0x3e: - last_a_address = ord(rom[offset + 1]) + last_a_address = rom[offset + 1] opstr = opstr[:opstr.find("x")].lower() + insertion + opstr[opstr.find("x")+1:].lower() # because the $ff00+$ff syntax is silly - if opstr.count("$") > 0 and "+" in opstr: - first_orig = opstr.split("$")[1].split("+")[0] - first_num = "0x"+first_orig - first_val = int(first_num, 16) - second_orig = opstr.split("+$")[1].split("]")[0] - second_num = "0x"+second_orig - second_val = int(second_num, 16) - combined_val = "$" + hex(first_val + second_val)[2:] - replacetron = "[$"+first_orig+"+$"+second_orig+"]" - opstr = opstr.replace(replacetron, "["+combined_val+"]") + if opstr.count("$") > 1 and "+" in opstr: + first_orig = opstr[opstr.find("$"):opstr.find("+")] + first_val = eval(first_orig.replace("$","0x")) + + second_orig = opstr[opstr.find("+$")+1:opstr.find("]")] + second_val = eval(second_orig.replace("$","0x")) + + combined_val = "$%.4x" % (first_val + second_val) + result = find_label(combined_val, bank_id) + if result != None: + combined_val = result + + replacetron = "[%s+%s]" % (first_orig, second_orig) + opstr = opstr.replace(replacetron, "[%s]" % combined_val) output += spacing + opstr if include_comment: output += " ; " + hex(offset) if current_byte in relative_jumps: - output += " $" + hex(ord(rom[offset + 1]))[2:] + output += " $" + hex(rom[offset + 1])[2:] output += "\n" current_byte_number += 1 @@ -758,22 +755,21 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add current_byte_number += 1 offset += 1 include_comment = False - elif op_code_type == 2 and ord(rom[offset]) == op_code_byte: + elif op_code_type == 2 and rom[offset] == op_code_byte: oplen = len(op_code[0]) opstr = copy(op_code[0]) qes = op_code[0].count("?") for x in range(0, qes): - byte1 = ord(rom[offset + 1]) - byte2 = ord(rom[offset + 2]) + byte1 = rom[offset + 1] + byte2 = rom[offset + 2] number = byte1 - number += byte2 << 8; + number += byte2 << 8 insertion = "$%.4x" % (number) - if maybe_byte in call_commands or current_byte in relative_unconditional_jumps or current_byte in relative_jumps: - result = find_label(insertion, bank_id) - if result != None: - insertion = result + result = find_label(insertion, bank_id) + if result != None: + insertion = result opstr = opstr[:opstr.find("?")].lower() + insertion + opstr[opstr.find("?")+1:].lower() output += spacing + opstr #+ " ; " + hex(offset) @@ -804,7 +800,7 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add #stop reading at a jump, relative jump or return if current_byte in end_08_scripts_with: - if not has_outstanding_labels(byte_labels) and all_outstanding_labels_are_reverse(byte_labels, offset): + if not has_outstanding_labels(byte_labels) or all_outstanding_labels_are_reverse(byte_labels, offset): keep_reading = False is_data = False #cleanup break @@ -816,7 +812,7 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add keep_reading = True else: #if is_data and keep_reading: - output += spacing + "db $" + hex(ord(rom[offset]))[2:] #+ " ; " + hex(offset) + output += spacing + "db $" + hex(rom[offset])[2:] #+ " ; " + hex(offset) output += "\n" offset += 1 current_byte_number += 1 @@ -826,6 +822,9 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add #offset += 1 #current_byte_number += 1 + if current_byte in relative_unconditional_jumps + end_08_scripts_with: + output += "\n" + first_loop = False #clean up unused labels @@ -835,6 +834,9 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_add if label_line["usage"] == 0: output = output.replace((label_line["name"] + "\n").lower(), "") + #tone down excessive spacing + output = output.replace("\n\n\n","\n\n") + #add the offset of the final location if include_last_address: output += "; " + hex(offset) diff --git a/extras/wram.py b/extras/wram.py new file mode 100644 index 000000000..bad0b9fa9 --- /dev/null +++ b/extras/wram.py @@ -0,0 +1,61 @@ +# coding: utf-8 + +# RGBDS BSS section and constant parsing. + +def read_bss_sections(bss): + sections = [] + section = {} + address = None + if type(bss) is not list: bss = bss.split('\n') + for line in bss: + line = line.lstrip() + if 'SECTION' in line: + if section: sections.append(section) # last section + + address = eval(line[line.find('[')+1:line.find(']')].replace('$','0x')) + section = { + 'name': line.split('"')[1], + #'type': line.split(',')[1].split('[')[0].strip(), + 'start': address, + 'labels': [], + } + elif ':' in line: + # the only labels that don't use :s so far are enders, + # which we typically don't want to end up in the output + label = line[:line.find(':')] + if ';' not in label: + section['labels'] += [{'label': label, 'address': address, 'length': 0}] + elif line[:3] == 'ds ': + length = eval(line[3:line.find(';')].replace('$','0x')) + address += length + if section['labels']: + section['labels'][-1]['length'] += length + sections.append(section) + return sections + +wram_sections = read_bss_sections(open('../wram.asm', 'r').readlines()) + + +def make_wram_labels(): + wram_labels = {} + for section in wram_sections: + for label in section['labels']: + if label['address'] not in wram_labels.keys(): + wram_labels[label['address']] = [] + wram_labels[label['address']] += [label['label']] + return wram_labels + +wram_labels = make_wram_labels() + + +def constants_to_dict(constants): + return dict((eval(constant[constant.find('EQU')+3:constant.find(';')].replace('$','0x')), constant[:constant.find('EQU')].strip()) for constant in constants) + +def scrape_constants(text): + if type(text) is not list: + text = text.split('\n') + return constants_to_dict([line for line in text if 'EQU' in line[:line.find(';')]]) + +hram_constants = scrape_constants(open('../hram.asm','r').readlines()) +gbhw_constants = scrape_constants(open('../gbhw.asm','r').readlines()) + @@ -1281,7 +1281,7 @@ CheckDict: ; 1087 cp $15 jp z, $117b cp $4f - jp z, Char4f + jp z, Char4F cp $4e jp z, $12a7 cp $16 @@ -1291,7 +1291,7 @@ CheckDict: ; 1087 cp $4c jp z, $1337 cp $4b - jp z, $131f + jp z, Char4B cp $51 ; Player name jp z, $12f2 cp $49 @@ -1395,7 +1395,7 @@ CheckDict: ; 1087 INCBIN "baserom.gbc", $117b, $1203 - $117b -Char5D: +Char5D: ; 1203 ld a, [hBattleTurn] push de and a @@ -1404,7 +1404,7 @@ Char5D: jr .asm_126a ; 0x120c $5c .asm_120e ld de, Char5AText ; Enemy - call $1078 + call PlaceString ld h, b ld l, c ld de, $c616 @@ -1419,11 +1419,11 @@ Char5D: cp $2a jr z, .asm_1248 ; 0x122b $1b ld de, $c656 - call $1078 + call PlaceString ld h, b ld l, c ld de, $12a2 - call $1078 + call PlaceString push bc ld hl, $5939 ld a, $e @@ -1439,7 +1439,7 @@ Char5D: jr .asm_126a ; 0x1250 $18 push de ld de, PlayerName - call $1078 + call PlaceString ld h, b ld l, c ld a, [$d472] @@ -1449,7 +1449,7 @@ Char5D: ld de, $12a6 jr .asm_126a ; 0x1268 $0 .asm_126a - call $1078 + call PlaceString ld h, b ld l, c pop de @@ -1473,36 +1473,63 @@ Char5AText: ; 0x1295 INCBIN "baserom.gbc", $129c, $12ea - $129c -Char4f: ; 12ea +Char4F: ; 12ea pop hl - ld hl, $c5e1 + hlcoord 1, 16 push hl jp NextChar ; 0x12f2 -INCBIN "baserom.gbc", $12f2, $1345 - $12f2 +INCBIN "baserom.gbc", $12f2, $131f - $12f2 + +Char4B: ; 131f + ld a, [InLinkBattle] + or a + jr nz, .asm_1328 + call $13c7 + +.asm_1328 + call $13b6 -Char55: ; $1345 push de - ld de, $1354 + call $aaf + pop de + + ld a, [InLinkBattle] + or a + call z, $13cd + + push de + call $138c + call $138c + hlcoord 1, 16 + pop de + jp NextChar +; 1345 + + +Char55: ; 1345 + push de + ld de, .text_1354 ld b, h ld c, l - call $1078 + call PlaceString ld h, b ld l, c pop de jp NextChar -; 0x1354 -; ??? - ld c, e - ld d, b +.text_1354 + db $4b, "@" +; 1356 -Char5F: ; 0x1356 + +Char5F: ; 1356 ; ends a Pokédex entry - ld [hl],"." + ld [hl], "." pop hl ret +; 135a INCBIN "baserom.gbc", $135a, $15d8 - $135a @@ -17859,7 +17886,7 @@ Function117b31: call $1cfd ld hl, $c550 ld de, YesNo117ccc - call $1078 + call PlaceString ld hl, $c54f ld a, "▶" ld [hl], a diff --git a/preprocessor.py b/preprocessor.py index 67e4cdb9f..18e96dff0 100644 --- a/preprocessor.py +++ b/preprocessor.py @@ -314,26 +314,19 @@ def separate_comment(l): asm = "" comment = None in_quotes = False - in_comment = False # token either belongs to the line or to the comment for token in l: - if in_comment: + if comment: comment += token - elif in_quotes and token != "\"": - asm += token - elif in_quotes and token == "\"": - in_quotes = False - asm += token - elif not in_quotes and token == "\"": - in_quotes = True + else: + if not in_quotes: + if token == ";": + comment = ";" + continue + if token == "\"": + in_quotes = not in_quotes asm += token - elif not in_quotes and token != "\"": - if token == ";": - in_comment = True - comment = ";" - else: - asm += token return asm, comment def quote_translator(asm): |