Example #1
0
    def __init__(self, paramdef_bnd_source=None):
        """BND container with all the `ParamDef` definitions for a given game.

        The latest versions of these files are included with Soulstruct for some games, and can be loaded simply by
        passing the game name to this constructor. They will also be loaded automatically when needed by `Param`
        instances.

        If you want to modify a `ParamDefBND`, you are far too powerful a modder for Soulstruct, and I cannot make that
        journey with you at this time.
        """
        if paramdef_bnd_source is None:
            paramdef_bnd_source = self.GAME
        elif isinstance(paramdef_bnd_source, str):
            try:
                paramdef_bnd_source = get_game(paramdef_bnd_source)
            except ValueError:
                # Will try to use as a path.
                pass
        if isinstance(paramdef_bnd_source, Game):
            # Load vanilla ParamDefBND bundled with Soulstruct (easiest).
            if not paramdef_bnd_source.bundled_paramdef_path:
                raise NotImplementedError(
                    f"Soulstruct does not have a bundled `paramdefbnd` file for game {paramdef_bnd_source.name}."
                )
            paramdef_bnd_source = PACKAGE_PATH(
                paramdef_bnd_source.bundled_paramdef_path)
            if not paramdef_bnd_source.is_file():
                raise FileNotFoundError(
                    f"Could not find bundled `paramdefbnd` file for game {paramdef_bnd_source.name} in Soulstruct.\n"
                    "Update/reinstall Soulstruct or copy the ParamDef files in yourself."
                )

        self._bnd = Binder(paramdef_bnd_source)

        self.paramdefs = {}  # type: dict[str, ParamDef]
        for entry in self.bnd.entries:
            try:
                paramdef = self.PARAMDEF_CLASS(entry)
            except Exception:
                _LOGGER.error(
                    f"Could not load ParamDefBND entry {entry.name}.")
                raise
            if paramdef.param_type in self.paramdefs:
                raise KeyError(
                    f"ParamDef type {paramdef.param_type} was loaded more than once in ParamDefBND."
                )
            self.paramdefs[paramdef.param_type] = paramdef
Example #2
0
def convert_dds_file(dds_path: tp.Union[str, Path],
                     output_dir: tp.Union[str, Path],
                     output_format: str,
                     input_format: str = None):
    """Convert DDS file path to a different format using DirectX-powered `texconv.exe`.

    If `input_format` is given, the source DDS will be checked to make sure it matches that format.
    """
    texconv_path = PACKAGE_PATH("base/textures/texconv.exe")
    if not texconv_path.is_file():
        raise FileNotFoundError(
            "Cannot find `texconv.exe` that should be bundled with Soulstruct in 'base/textures'."
        )
    if input_format is not None:
        dds = DDS(dds_path)
        if dds.header.fourcc.decode() != input_format:
            raise ValueError(
                f"DDS format {dds.header.fourcc} does not match `input_format` {input_format}"
            )
    subprocess.run(
        f"{texconv_path} -f {output_format} -o {output_dir} {dds_path}",
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
Example #3
0
def fsbext(fsb_path: Path | str, options=""):
    """Call `fsbext.exe` with given options on `fsb_path`."""
    executable = PACKAGE_PATH("darksouls1r/sound/fsbext.exe")
    if not executable.is_file():
        raise FileNotFoundError("`fsbext.exe` is missing from Soulstruct package. Cannot extract FSB file.")
    sp.call(f"{executable} {options} {fsb_path}")