Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,23 @@ dependencies = [

[project.optional-dependencies]
mips = [
"splat64[mips-min,assets-n64,compression]",
]

mips-min = [
"spimdisasm>=1.42.1,<2.0.0", # This value should be keep in sync with the version listed on disassembler/spimdisasm_disassembler.py
"rabbitizer>=1.12.0,<2.0.0",
]
assets-n64 = [
"splat64[mips-min]",
"pygfxd>=1.0.5",
"n64img>=0.3.3",
]
compression = [
"splat64[mips-min]",
"crunch64>=0.5.1,<1.0.0",
]

dev = [
"splat64[mips]",
"ruff",
Expand Down
47 changes: 32 additions & 15 deletions src/splat/segtypes/n64/__init__.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,38 @@
from . import ci as ci
from . import ci4 as ci4
from . import ci8 as ci8
from . import decompressor as decompressor
from . import gfx as gfx
from . import header as header
from . import i1 as i1
from . import i4 as i4
from . import i8 as i8
from . import ia16 as ia16
from . import ia4 as ia4
from . import ia8 as ia8
from . import img as img
from . import ipl3 as ipl3
from . import mio0 as mio0
from . import palette as palette
from . import rgba16 as rgba16
from . import rgba32 as rgba32
from . import rsp as rsp
from . import vtx as vtx
from . import yay0 as yay0

# Segments that require optional dependencies

# assets-n64 (pygfxd)
try:
from . import gfx as gfx
except ImportError:
pass

# assets-n64 (n64img)
try:
from . import ci as ci
from . import ci4 as ci4
from . import ci8 as ci8
from . import i1 as i1
from . import i4 as i4
from . import i8 as i8
from . import ia16 as ia16
from . import ia4 as ia4
from . import ia8 as ia8
from . import img as img
from . import rgba16 as rgba16
from . import rgba32 as rgba32
except ImportError:
pass

# compression (crunch64)
try:
from . import mio0 as mio0
from . import yay0 as yay0
except ImportError:
pass
41 changes: 36 additions & 5 deletions src/splat/segtypes/segment.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,34 @@ def empty_statistics() -> SegmentStatistics:
return collections.defaultdict(lambda: SegmentStatisticsInfo(size=0, count=0))


# Mapping for segments that are enabled only when the corresponding dependency
# is available at runtime.
# The value corresponds to the dependency group listed on the pyproject.toml
# file installs the required Python dependencies for the given segment.
_segments_from_optional_dependencies: dict[str, str] = {
"yay0": "compression",
"mio0": "compression",
"gfx": "assets-n64",
"ci": "assets-n64",
"ci4": "assets-n64",
"ci8": "assets-n64",
"i1": "assets-n64",
"i4": "assets-n64",
"i8": "assets-n64",
"ia16": "assets-n64",
"ia4": "assets-n64",
"ia8": "assets-n64",
"img": "assets-n64",
"rgba16": "assets-n64",
"rgba32": "assets-n64",
}


class Segment:
require_unique_name = True

@staticmethod
def get_class_for_type(seg_type) -> Type["Segment"]:
def get_class_for_type(seg_type: str) -> Type["Segment"]:
# so .data loads SegData, for example
seg_type = seg_type.removeprefix(".")

Expand All @@ -115,14 +138,21 @@ def get_class_for_type(seg_type) -> Type["Segment"]:
segment_class = Segment.get_extension_segment_class(seg_type)

if segment_class is None:
dependency_group = _segments_from_optional_dependencies.get(seg_type)
if dependency_group is not None:
log.error(
f"Could not load segment type '{seg_type}'.\n"
f"This segment is available by installing the optional dependency group `splat64[{dependency_group}]`"
)
log.error(
f"could not load segment type '{seg_type}'\n(hint: confirm your extension directory is configured correctly)"
f"Could not load segment type '{seg_type}'\n"
"(hint: confirm your extension directory is configured correctly)"
)

return segment_class

@staticmethod
def get_base_segment_class(seg_type):
def get_base_segment_class(seg_type: str) -> Optional[Type["Segment"]]:
platform = options.opts.platform
is_platform_seg = False

Expand All @@ -144,7 +174,7 @@ def get_base_segment_class(seg_type):
return getattr(segmodule, f"{seg_prefix}Seg{seg_type.capitalize()}")

@staticmethod
def get_extension_segment_class(seg_type):
def get_extension_segment_class(seg_type: str) -> Optional[Type["Segment"]]:
platform = options.opts.platform

ext_path = options.opts.extensions_path
Expand All @@ -167,7 +197,8 @@ def get_extension_segment_class(seg_type):
return None

return getattr(
ext_mod, f"{platform.upper()}Seg{seg_type[0].upper()}{seg_type[1:]}"
ext_mod,
f"{platform.upper()}Seg{seg_type[0].upper()}{seg_type[1:]}",
)

@staticmethod
Expand Down