|
| 1 | +from decode_common import * |
| 2 | + |
| 3 | +BANK = 0x87 |
| 4 | + |
| 5 | +kInstructionSet = { |
| 6 | + 0x8780b2: ('Delete', ''), |
| 7 | + 0x8780b7: ('Goto', 'G'), |
| 8 | + 0x87813f: ('GotoIfEventHappened', 'HG'), |
| 9 | + 0x878150: ('SetEventHappened', 'H'), |
| 10 | + 0x8781ba: ('WaitUntilAreaBossDead_DoubleRet', ''), |
| 11 | + 0x878303: ('GotoIfBossBitSetInArea', 'BBG'), |
| 12 | + 0x878320: ('SpawnTourianStatueEyeGlow', 'H'), |
| 13 | + 0x87832f: ('SpawnTourianStatueSoul', 'H'), |
| 14 | + 0x87833e: ('GotoIfTourianStatueBusy', 'G'), |
| 15 | + 0x878349: ('TourianStatueSetState', 'H'), |
| 16 | + 0x878352: ('TourianStatueClearState', 'H'), |
| 17 | + 0x87835b: ('Clear3PaletteColors', 'H'), |
| 18 | + 0x878372: ('SpawnPalfxObj', 'H'), |
| 19 | + 0x87837f: ('Write8PaletteColors', 'H'), |
| 20 | +} |
| 21 | + |
| 22 | +kCommandByName = {v[0] : (k, v[1]) for k, v in kInstructionSet.items()} |
| 23 | + |
| 24 | +class AnimtilesParser(InstrParserCommon): |
| 25 | + instruction_set = kInstructionSet |
| 26 | + instruction_set_term = {0x8780b7, 0x8780b2} |
| 27 | + TAG = 'animtiles' |
| 28 | + |
| 29 | + def __init__(self): |
| 30 | + super().__init__() |
| 31 | + self.current_array_size = None |
| 32 | + |
| 33 | + def handle_draw_command(self, ins, ea): |
| 34 | + drawp = get_word(ea + 2) | (BANK << 16) |
| 35 | + assert self.current_array_size != None |
| 36 | + self.blobs[drawp] = self.current_array_size |
| 37 | + self.print_line(ea, f' {ins} ! {get_ea_name(drawp)}') |
| 38 | + return 4 |
| 39 | + |
| 40 | + def visit(self, ea, cur_size = None): |
| 41 | + if cur_size == None: |
| 42 | + super().visit(ea) |
| 43 | + return |
| 44 | + self.current_array_size = cur_size |
| 45 | + super().visit(ea) |
| 46 | + self.process_queue(final = False) |
| 47 | + |
| 48 | + def process_queue_entry(self, ea): |
| 49 | + assert ea & 0x8000 |
| 50 | + while ea not in self.visited: |
| 51 | + self.visited.add(ea) |
| 52 | + ins = get_word(ea) |
| 53 | + if ins & 0x8000: |
| 54 | + ea_org = ea |
| 55 | + ins = (BANK << 16) | ins |
| 56 | + if ins not in self.instruction_set: |
| 57 | + raise Exception(f'Ins {ins:X} not in iset at {ea:X}') |
| 58 | + name, operands = self.instruction_set[ins] |
| 59 | + ea += 2 |
| 60 | + r = [] |
| 61 | + for op in operands: |
| 62 | + if op == 'B': |
| 63 | + r.append('%d' % get_byte(ea)) |
| 64 | + ea += 1 |
| 65 | + elif op == 'H': |
| 66 | + r.append('%d' % get_word(ea)) |
| 67 | + ea += 2 |
| 68 | + elif op == 'G': |
| 69 | + addr = (BANK << 16) | get_word(ea) |
| 70 | + r.append(get_ea_name(addr, short_label=True)) |
| 71 | + self.visit(addr) |
| 72 | + ea += 2 |
| 73 | + else: |
| 74 | + assert 0 |
| 75 | + self.print_line(ea_org, f' {name}({", ".join(r)})') |
| 76 | + if ins in self.instruction_set_term: |
| 77 | + self.print_line(ea_org + 1, '') |
| 78 | + break |
| 79 | + else: |
| 80 | + ea += self.handle_draw_command(ins, ea) |
0 commit comments