Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def setUpClass(cls):
instruction_id = InstructionID(
pc=0x000000, p=0b0000_0000, subroutine_pc=0x000000
)
cls.brl = Instruction(None, *instruction_id, 0x82, 0xFFFD, None, None)
cls.lda = Instruction(None, *instruction_id, 0xA9, 0x1234, None, None)
def setUpClass(cls):
instruction_id = InstructionID(
pc=0x000000, p=0b0000_0000, subroutine_pc=0x000000
)
cls.brl = Instruction(None, *instruction_id, 0x82, 0xFFFD, None, None)
cls.lda = Instruction(None, *instruction_id, 0xA9, 0x1234, None, None)
def __init__(self, log, pc: int, label: str):
super().__init__()
self.log = log
self.pc = pc
self.label = label
# Instructions belonging to the subroutine.
self.instructions: Dict[int, Instruction] = SortedDict()
# Calling the subroutine results in the following state changes.
self.state_changes: Dict[int, StateChange] = {}
# The stack of calls that brought us to the current subroutine.
self.stack_traces: Set[Tuple[int, ...]] = set()
# Whether an instruction inside the subroutine performs stack manipulation.
self.has_stack_manipulation = False
# Whether a subroutine calls itself down the line.
self.is_recursive = False
def step(self) -> bool:
# We can't analyze code that lives in RAM.
if self.rom.is_ram(self.pc):
return False
# Don't visit the exact same instruction twice.
if self.log.is_visited(self.instruction_id):
return False
# Disassemble and log the instruction.
opcode = self.rom.read_byte(self.pc)
argument = self.rom.read_address(self.pc + 1)
instruction = Instruction(
self.log,
*self.instruction_id,
opcode,
argument,
self.registers.snapshot(),
copy(self.state_change)
)
self.log.add_instruction(instruction)
# Emulate the instruction.
keep_going = self.execute(instruction)
# Apply asserted state changes if any, and log it inside the instruction object.
instruction.state_change_after = self._maybe_apply_asserted_state_change(
instruction
)
from copy import copy
from dataclasses import dataclass
from typing import Any, Dict, List, Optional
from gilgamesh.snes.instruction import Instruction
@dataclass
class StackEntry:
instruction: Optional[Instruction] = None
data: Any = None
class Stack:
def __init__(self):
self.memory: Dict[int, StackEntry] = {}
self.stack_change_instruction: Optional[Instruction] = None
self.pointer = 0
def copy(self) -> "Stack":
stack = copy(self)
stack.memory = copy(self.memory)
return stack
def set_pointer(
self, instruction: Instruction, pointer: Optional[int] = None