Exemple #1
0
    def __init__(self, filename: str, cb_open_view: Callable[[Gtk.TreeIter],
                                                             None]):
        self.filename = filename
        self._rom: NintendoDSRom = None  # type: ignore
        self._rom_module: Optional['RomModule'] = None
        self._loaded_modules: Dict[str, AbstractModule] = {}
        self._sprite_renderer: Optional[SpriteProvider] = None
        self._string_provider: Optional[StringProvider] = None
        # Dict of filenames -> models
        self._opened_files: Dict[str, Any] = {}
        self._opened_files_contexts: Dict[str, ModelContext] = {}
        # List of filenames that were requested to be opened threadsafe.
        self._files_threadsafe: List[str] = []
        self._files_unsafe: List[str] = []
        # Dict of filenames -> file handler object
        self._file_handlers: Dict[str, Type[DataHandler]] = {}
        self._file_handler_kwargs: Dict[str, Dict[str, Any]] = {}
        # List of modified filenames
        self._modified_files: List[str] = []
        self._forced_modified = False
        # Callback for opening views using iterators from the main view list.
        self._cb_open_view: Callable[[Gtk.TreeIter], None] = cb_open_view
        self._project_fm = ProjectFileManager(filename)

        self._icon_banner: Optional[IconBanner] = None

        # Lazy
        self._patcher: Optional[Patcher] = None
Exemple #2
0
 def __init__(self):
     self.config_dir = os.path.join(ProjectFileManager.shared_config_dir())
     os.makedirs(self.config_dir, exist_ok=True)
     self.config_file = os.path.join(self.config_dir, CONFIG_FILE_NAME)
     self.loaded_config = configparser.ConfigParser()
     if os.path.exists(self.config_file):
         with open_utf8(self.config_file, 'r') as f:
             self.loaded_config.read_file(f)
Exemple #3
0
 def __init__(self):
     self.config_dir = os.path.join(ProjectFileManager.shared_config_dir())
     os.makedirs(self.config_dir, exist_ok=True)
     self.config_file = os.path.join(self.config_dir, CONFIG_FILE_NAME)
     self.loaded_config = configparser.ConfigParser()
     if os.path.exists(self.config_file):
         try:
             with open_utf8(self.config_file, 'r') as f:
                 self.loaded_config.read_file(f)
         except BaseException as err:
             logger.error("Error reading config, falling back to default.", exc_info=err)
Exemple #4
0
def setup_logging():
    """
    Creates a rotating log
    """

    sys.excepthook = handle_exception

    dirn = ProjectFileManager.shared_config_dir()
    os.makedirs(dirn, exist_ok=True)
    handler = RotatingFileHandler(os.path.join(dirn, 'skytemple.log'),
                                  maxBytes=100000,
                                  backupCount=5)
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        handlers=[logging.StreamHandler(), handler])
Exemple #5
0
 def open_rom(self, filename: str):
     self._rom = NintendoDSRom.fromFile(filename)
     self._rom_filename = filename
     self._project_fm = ProjectFileManager(filename)
     self._static_data = get_ppmdu_config_for_rom(self._rom)
     self._open_files = {}
Exemple #6
0
class StandaloneDebuggerControlContext(AbstractDebuggerControlContext):
    """Context for running the debugger as a standalone application."""
    def __init__(self, main_window: Gtk.Window):
        self._rom: Optional[NintendoDSRom] = None
        self._rom_filename: Optional[str] = None
        self._project_fm: Optional[ProjectFileManager] = None
        self._static_data: Optional[Pmd2Data] = None
        self._open_files: Dict[str, SsbLoadedFile] = {}
        self._main_window = main_window

    def allows_interactive_file_management(self) -> bool:
        return True

    def before_quit(self) -> bool:
        return True

    def on_quit(self):
        Gtk.main_quit()
        emu_instance = EmulatorThread.instance()
        if emu_instance is not None:
            emu_instance.end()
        EmulatorThread.destroy_lib()

    def on_focus(self):
        pass

    def on_blur(self):
        pass

    def on_selected_string_changed(self, string: str):
        pass

    def show_ssb_script_editor(self) -> bool:
        return True

    def open_rom(self, filename: str):
        self._rom = NintendoDSRom.fromFile(filename)
        self._rom_filename = filename
        self._project_fm = ProjectFileManager(filename)
        self._static_data = get_ppmdu_config_for_rom(self._rom)
        self._open_files = {}

    def get_project_dir(self) -> str:
        return self._project_fm.dir()  # type: ignore

    def load_script_files(self) -> ScriptFiles:
        return load_script_files(get_rom_folder(self._rom,
                                                SCRIPT_DIR))  # type: ignore

    def is_project_loaded(self) -> bool:
        return self._rom is not None

    def get_rom_filename(self) -> str:
        self._check_loaded()
        return self._rom_filename  # type: ignore

    def save_rom(self):
        self._check_loaded()
        self._rom.saveToFile(self._rom_filename)

    def get_static_data(self) -> Pmd2Data:
        self._check_loaded()
        return self._static_data  # type: ignore

    def get_project_filemanager(self) -> ProjectFileManager:
        self._check_loaded()
        return self._project_fm  # type: ignore

    @synchronized_now(file_load_lock)
    def get_ssb(self, filename,
                ssb_file_manager: 'SsbFileManager') -> 'SsbLoadedFile':
        self._check_loaded()
        if filename not in self._open_files:
            try:
                ssb_bin = self._rom.getFileByName(filename)  # type: ignore
            except ValueError as err:
                raise FileNotFoundError(str(err)) from err
            self._open_files[filename] = SsbLoadedFile(
                filename,
                FileType.SSB.deserialize(ssb_bin, self._static_data),
                ssb_file_manager,
                self._project_fm  # type: ignore
            )
            self._open_files[filename].exps.ssb_hash = ssb_file_manager.hash(
                ssb_bin)
        return self._open_files[filename]

    def on_script_edit(self, filename):
        pass

    @synchronized_now(file_load_lock)
    def save_ssb(self, filename, ssb_model,
                 ssb_file_manager: 'SsbFileManager'):
        self._check_loaded()
        self._rom.setFileByName(  # type: ignore
            filename, FileType.SSB.serialize(ssb_model, self._static_data))
        self.save_rom()

    def _check_loaded(self):
        if self._rom is None:
            raise RuntimeError("No ROM is currently loaded.")

    def open_scene_editor(self, type_of_scene, filename):
        self._scene_editing_not_supported()

    def open_scene_editor_for_map(self, map_name):
        self._scene_editing_not_supported()

    def edit_position_mark(self, mapname: str, scene_name: str,
                           scene_type: str,
                           pos_marks: List[SourceMapPositionMark],
                           pos_mark_to_edit: int) -> bool:
        self.display_error(
            None,
            f"Visual Position Mark editing is not supported in the standalone version of "
            f"SkyTemple Script Engine Debugger.\n"
            f"Please open the debugger through the SkyTemple main application "
            f"instead.")
        return False

    def _scene_editing_not_supported(self):
        self.display_error(
            None,
            f"Scene editing is not supported in the standalone version of "
            f"SkyTemple Script Engine Debugger.\n"
            f"Please open the debugger through the SkyTemple main application "
            f"instead.", "Action not supported")

    def display_error(self,
                      exc_info,
                      error_message,
                      error_title='SkyTemple Script Engine Debugger - Error',
                      *,
                      context: Optional[Dict[str, Capturable]] = None):
        logger.error(error_message, exc_info=exc_info)
        md = self.message_dialog_cls()(self._main_window,
                                       Gtk.DialogFlags.DESTROY_WITH_PARENT,
                                       Gtk.MessageType.ERROR,
                                       Gtk.ButtonsType.OK,
                                       error_message,
                                       title=error_title)
        md.set_position(Gtk.WindowPosition.CENTER)
        md.run()
        md.destroy()

    def capture_error(self,
                      exc_info,
                      *,
                      context: Optional[Dict[str, Capturable]] = None):
        pass

    def get_special_words(self) -> Iterable[str]:
        """
        Just returns the script operations and constants,
        more data is only supported by the main SkyTemple application
        """
        yield from self._static_data.script_data.op_codes__by_name.keys(
        )  # type: ignore
        yield from (
            x.name.replace('$', '')
            for x in SsbConstant.collect_all(self._static_data.script_data)
        )  # type: ignore
        yield from EXPS_KEYWORDS

    @staticmethod
    def message_dialog_cls():
        return Gtk.MessageDialog
Exemple #7
0
 def on_settings_dir_clicked(self, *args):
     open_dir(ProjectFileManager.shared_config_dir())