Beispiel #1
0
 def hook__ground_start(self, address, size):
     if not self.overlay11_loaded():
         return
     self._print("Ground Start")
     threadsafe_gtk_nonblocking(lambda: self.reset())
     ground_engine_lock.acquire()
     self._running = True
     ground_engine_lock.release()
     self._inform_ground_engine_start_cb()
Beispiel #2
0
 def _do_sync(self):
     self._tables = []
     self._current_table = 0
     if self.rom_data:
         address_table_head = self.rom_data.binaries['arm9.bin'].symbols['MemoryAllocTable'].begin_absolute
         accessor = self.emu_thread.emu.memory.unsigned
         for x in range(accessor.read_long(address_table_head)):
             address_table = address_table_head+0x20+0x4*x
             self._tables.append(self._read_table(accessor.read_long(address_table)))
     threadsafe_gtk_nonblocking(self._do_sync_gtk)
Beispiel #3
0
 def _do_sync(self):
     for var in self.rom_data.script_data.game_variables:
         var_values = []
         for offset in range(0, var.nbvalues):
             if not var.is_local:
                 _, val = GameVariable.read(self.emu_thread.emu.memory,
                                            self.rom_data, var.id, offset)
                 var_values.append(val)
         self._variable_cache[self.rom_data.script_data.
                              game_variables__by_id[var.id]] = var_values
     threadsafe_gtk_nonblocking(self._do_sync_gtk)
Beispiel #4
0
    def hook__variable_set_with_offset(self, address: int, size: int):
        if self._boost:
            return
        var_id = self.emu_thread.emu.memory.register_arm9.r1
        if var_id >= 0x400:
            return
        var_offset = self.emu_thread.emu.memory.register_arm9.r2
        value_raw = self.emu_thread.emu.memory.register_arm9.r3
        # TODO: Do we need to process the raw value...?

        self._variable_cache[self.rom_data.script_data.game_variables__by_id[
            var_id]][var_offset] = value_raw
        threadsafe_gtk_nonblocking(
            partial(self.hook__variable_set_gtk, var_id, var_offset,
                    value_raw))
Beispiel #5
0
    def hook__ssb_load(self, address, size):
        if not self.overlay11_loaded():
            return
        name = self.emu_thread.emu.memory.read_string(
            self.emu_thread.emu.memory.register_arm9.r1)
        load_for = self._load_ssb_for if self._load_ssb_for is not None else 0
        self._print(f"SSB Load {name} for hanger {load_for}")
        self._load_ssb_for = None

        if load_for > MAX_SSB:
            warnings.warn(
                f"Ground Engine debugger: Invalid hanger ID for ssb: {load_for}"
            )
            return
        threadsafe_gtk_nonblocking(
            lambda: self.ssb_file_manager.open_in_ground_engine(name))
        self._loaded_ssb_files[load_for] = (SsbFileInRam(name, load_for))
Beispiel #6
0
 def change_current_table(self, current_table):
     self._current_table = max(0, min(current_table, len(self._tables)))
     threadsafe_gtk_nonblocking(self._do_sync_gtk)
 def _do_sync_local_vars(self, srs):
     for var in self._local_vars_specs:
         _, val = GameVariable.read(self.emu_thread.emu.memory,
                                    self._rom_data, var.id, 0, srs)
         self._local_vars_values.append(val)
     threadsafe_gtk_nonblocking(self._do_sync_gtk)
 def print_callback(self, text: str):
     threadsafe_gtk_nonblocking(lambda: self._print_callback_fn(text))
 def hook__set_debug_flag_2(self, address, size):
     flag_id = self.emu_thread.emu.memory.register_arm9.r0
     value = self.emu_thread.emu.memory.register_arm9.r1
     threadsafe_gtk_nonblocking(
         lambda: self.parent.set_check_debug_flag_2(flag_id, value))
    def hook__breaking_point(self, address, size):
        """MAIN DEBUGGER HOOK. The emulator thread pauses here and publishes it's state via BreakpointState."""
        if self._boost:
            return
        debugger_state_lock.acquire()
        srs = ScriptRuntimeStruct(self.emu_thread.emu.memory, self.rom_data,
                                  self.emu_thread.emu.memory.register_arm9.r6,
                                  self.ground_engine_state.unionall_load_addr)
        if self._log_operations:
            self.print_callback(
                f"> {srs.target_type.name}({srs.target_id}): {srs.current_opcode.name} @{srs.current_opcode_addr:0x}"
            )

        if self.breakpoint_manager:
            if not self._breakpoints_disabled and self._breakpoints_disabled_for_tick != self.emu_thread.current_frame_id:
                debugger_state_lock.release()
                self._breakpoints_disabled_for_tick = -1

                ssb = self.ground_engine_state.loaded_ssb_files[srs.hanger_ssb]
                if ssb is not None and (
                        self._breakpoint_force or self.breakpoint_manager.has(
                            ssb.file_name, srs.current_opcode_addr_relative,
                            srs.is_in_unionall, srs.script_target_type,
                            srs.script_target_slot_id)):
                    self.breakpoint_manager.reset_temporary()
                    self._breakpoint_force = False
                    state = BreakpointState(srs.hanger_ssb, srs)
                    state.acquire()
                    threadsafe_gtk_nonblocking(
                        lambda: self.parent.break_pulled(state))
                    while not state.wait(
                            0.0005
                    ) and state.state == BreakpointStateType.STOPPED:
                        # We haven't gotten the signal to resume yet, process pending events.
                        self.emu_thread.run_one_pending_task()
                    state.release()
                    if state.state == BreakpointStateType.FAIL_HARD:
                        # Ok, we won't pause again this tick.
                        self._breakpoints_disabled_for_tick = self.emu_thread.current_frame_id
                    elif state.state == BreakpointStateType.RESUME:
                        # We just resume, this is easy :)
                        pass
                    elif state.state == BreakpointStateType.STEP_NEXT:
                        # We force a break at the next run of this hook.
                        self._breakpoint_force = True
                    elif state.state == BreakpointStateType.STEP_INTO:
                        # We break at whatever is executed next for the current script target.
                        self.breakpoint_manager.add_temporary(
                            srs.script_target_type, srs.script_target_slot_id)
                    elif state.state == BreakpointStateType.STEP_OVER:
                        # We break at the next opcode in the current script file
                        self.breakpoint_manager.add_temporary(
                            srs.script_target_type,
                            srs.script_target_slot_id,
                            is_in_unionall=srs.is_in_unionall)
                        # If the current op is the last one (we will step out next) this will lead to issues.
                        # We need to alternatively break at the current stack opcode (see STEP_OUT).
                        if srs.has_call_stack:
                            self.breakpoint_manager.add_temporary(
                                srs.script_target_type,
                                srs.script_target_slot_id,
                                opcode_addr=srs.
                                call_stack__current_opcode_addr_relative)
                    elif state.state == BreakpointStateType.STEP_OUT:
                        if srs.has_call_stack:
                            # We break at the opcode address stored on the call stack position.
                            self.breakpoint_manager.add_temporary(
                                srs.script_target_type,
                                srs.script_target_slot_id,
                                opcode_addr=srs.
                                call_stack__current_opcode_addr_relative)
                        else:
                            # We just resume
                            pass
                    elif state.state == BreakpointStateType.STEP_MANUAL:
                        # We break at the requested opcode offset in the current hanger.
                        self.breakpoint_manager.add_temporary(
                            srs.script_target_type,
                            srs.script_target_slot_id,
                            is_in_unionall=srs.is_in_unionall,
                            opcode_addr=state.manual_step_opcode_offset)
            else:
                debugger_state_lock.release()
        else:
            debugger_state_lock.release()