Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
@argument("label_or_pc", complete_label)
def do_query_references(self, label_or_pc: str) -> None:
"""Given an address, list the instructions pointing to it."""
pc = self._label_to_pc(label_or_pc)
references = self.log.references[pc]
s, last_sub = [], None
for instr_pc, sub_pc in references:
subroutine = self.log.subroutines[sub_pc]
instruction = subroutine.instructions[instr_pc]
disassembly = SubroutineDisassembly(subroutine)
if not last_sub or sub_pc != last_sub.pc:
s.append(
"{}{:16}".format(
"\n" if last_sub else "", subroutine.label + ":"
)
)
@argument("label_or_pc", complete_label)
def do_translate(self, label_or_pc: str) -> None:
"""Translate a SNES address to a PC address."""
pc = self._label_to_pc(label_or_pc)
s = []
s.append("SNES: ${:06X}\n".format(pc))
s.append("PC: ${:06X}\n".format(self.rom._translate(pc)))
print_html("".join(s))
@argument("opcode", complete_opcode)
def do_describe(self, opcode: str):
"""Describe an opcode."""
op = Op.__members__[opcode.upper()]
description = descriptions[op] + "\n"
print_html(description)
@argument("label", complete_subroutine)
def do_subroutine(self, label: str) -> None:
"""Select which subroutine to inspect."""
if not label:
self.subroutine = None
elif label in self.log.subroutines_by_label:
self.subroutine = self.log.subroutines_by_label[label]
else:
print_error("No such subroutine.")
@argument("caller_pc", complete_label)
def do_jumptable_complete(self, caller_pc: str) -> None:
"""Flag a jumptable as completely explored."""
caller_pc_int = self._label_to_pc(caller_pc)
self.log.complete_jump_tables.add(caller_pc_int)
@argument("state_expr")
def do_assert_subroutine(self, label_or_pc: str, state_expr: str) -> None:
"""Define a known processor return state for a given subroutine.
STATE_EXPR can accept the following values:
- "none" -> The subroutine does not change the state.
- "m=0" or "m=1" -> The subroutine changes the state of m to 0 or 1.
- "x=0" or "x=1" -> The subroutine changes the state of x to 0 or 1.
- "m=0,x=0" -> The subroutine changes the state of m to 0 and x to 0.
- "m=0,x=1" -> The subroutine changes the state of m to 0 and x to 1.
- "m=1,x=0" -> The subroutine changes the state of m to 1 and x to 0.
- "m=1,x=1" -> The subroutine changes the state of m to 1 and x to 1."""
if not self.subroutine:
raise GilgameshError("No selected subroutine.")
# TODO: check that pc is an instruction inside the subroutine.
instr_pc = self._label_to_pc(label_or_pc)
state_change = StateChange.from_expr(state_expr)
@argument("comment")
def do_comment(self, label_or_pc: str, comment="") -> None:
"""Add comment to an instruction.
If no comment is specified, delete the existing comment."""
pc = self._label_to_pc(label_or_pc)
if comment:
self.log.comments[pc] = comment
else:
self.log.comments.pop(pc, None)
@argument("range_or_target_pc")
def do_jumptable_delete(
self, caller_pc: str, range_or_target_pc: Optional[str] = None
) -> None:
"""Remove a jump table entry."""
self._do_jumptable_op(self.log.deassert_jump, caller_pc, range_or_target_pc)
@argument("label_or_pc", complete_label)
def do_query_instruction(self, label_or_pc: str) -> None:
"""Query various info on an instruction.
Includes the subroutine it belongs to, and all the possible
states it was encountered at."""
pc = self._label_to_pc(label_or_pc)
instr_ids = self.log.instructions.get(pc, None)
if instr_ids is None:
actual_pc = self.log.find_instruction(pc)
if actual_pc is not None:
print_html(
"The given PC belongs to an instruction that "
+ f"starts at ${actual_pc:06X}.\n"
)
return
@argument("caller_pc", complete_label)
@argument("range_or_target_pc")
def do_jumptable_delete(
self, caller_pc: str, range_or_target_pc: Optional[str] = None
) -> None:
"""Remove a jump table entry."""
self._do_jumptable_op(self.log.deassert_jump, caller_pc, range_or_target_pc)