mirror of
https://github.com/zeldaret/oot
synced 2026-05-22 22:44:26 -04:00
tools/assets cleanup pass (mostly typing) (#2705)
* address easy todos * add type asserts * format * add type hints * more typing fixes * more asserts for typing * break long f string
This commit is contained in:
@@ -16,9 +16,6 @@ from .base import (
|
||||
)
|
||||
from . import xml_errors
|
||||
|
||||
# TODO remove
|
||||
STATIC_ATTRIB = {"Static"}
|
||||
|
||||
|
||||
class GfxMicroCode(enum.Enum):
|
||||
F3DEX = enum.auto()
|
||||
@@ -33,9 +30,7 @@ class DListResourceDesc(ResourceDesc):
|
||||
|
||||
|
||||
def handler_DList(symbol_name, offset, collection, reselem: Element):
|
||||
xml_errors.check_attrib(
|
||||
reselem, {"Name", "Offset"}, {"Ucode", "RawPointers"} | STATIC_ATTRIB
|
||||
)
|
||||
xml_errors.check_attrib(reselem, {"Name", "Offset"}, {"Ucode", "RawPointers"})
|
||||
if "Ucode" in reselem.attrib:
|
||||
ucode = GfxMicroCode[reselem.attrib["Ucode"].upper()]
|
||||
else:
|
||||
@@ -54,7 +49,7 @@ class BlobResourceDesc(ResourceDesc):
|
||||
|
||||
|
||||
def handler_Blob(symbol_name, offset, collection, reselem: Element):
|
||||
xml_errors.check_attrib(reselem, {"Name", "Offset", "Size"}, STATIC_ATTRIB)
|
||||
xml_errors.check_attrib(reselem, {"Name", "Offset", "Size"})
|
||||
size = int(reselem.attrib["Size"], 16)
|
||||
return BlobResourceDesc(symbol_name, offset, collection, reselem, size)
|
||||
|
||||
@@ -65,7 +60,7 @@ class MtxResourceDesc(ResourceDesc):
|
||||
|
||||
|
||||
def handler_Mtx(symbol_name, offset, collection, reselem: Element):
|
||||
xml_errors.check_attrib(reselem, {"Name", "Offset"}, STATIC_ATTRIB)
|
||||
xml_errors.check_attrib(reselem, {"Name", "Offset"})
|
||||
return MtxResourceDesc(symbol_name, offset, collection, reselem)
|
||||
|
||||
|
||||
@@ -85,7 +80,7 @@ class VtxArrayResourceDesc(ResourceDesc):
|
||||
|
||||
|
||||
def handler_Array(symbol_name, offset, collection, reselem: Element):
|
||||
xml_errors.check_attrib(reselem, {"Name", "Offset", "Count"}, STATIC_ATTRIB)
|
||||
xml_errors.check_attrib(reselem, {"Name", "Offset", "Count"})
|
||||
count = int(reselem.attrib["Count"])
|
||||
assert len(reselem) == 1, "Expected exactly one child of Array node"
|
||||
array_elem = reselem[0]
|
||||
@@ -138,16 +133,14 @@ def handler_Texture(
|
||||
xml_errors.check_attrib(
|
||||
reselem,
|
||||
{"Name", "Offset", "Format", "Width", "Height"},
|
||||
# TODO remove OutName, SplitTlut
|
||||
# TODO remove SplitTlut
|
||||
{
|
||||
"OutName",
|
||||
"SplitTlut",
|
||||
"TlutOffset",
|
||||
"ExternalTlut",
|
||||
"ExternalTlutOffset",
|
||||
"HackMode",
|
||||
}
|
||||
| STATIC_ATTRIB,
|
||||
},
|
||||
)
|
||||
format = TextureFormat[reselem.attrib["Format"].upper()]
|
||||
width = int(reselem.attrib["Width"])
|
||||
@@ -170,8 +163,8 @@ def handler_Texture(
|
||||
xml_errors.check_attrib(
|
||||
reselem,
|
||||
{"Name", "Offset", "Format", "Width", "Height", "TlutOffset"},
|
||||
# TODO remove OutName, SplitTlut
|
||||
{"OutName", "SplitTlut", "HackMode"} | STATIC_ATTRIB,
|
||||
# TODO remove SplitTlut
|
||||
{"SplitTlut", "HackMode"},
|
||||
)
|
||||
tlut_offset = int(reselem.attrib["TlutOffset"], 16)
|
||||
|
||||
@@ -200,8 +193,8 @@ def handler_Texture(
|
||||
"ExternalTlut",
|
||||
"ExternalTlutOffset",
|
||||
},
|
||||
# TODO remove OutName, SplitTlut
|
||||
{"OutName", "SplitTlut", "HackMode"} | STATIC_ATTRIB,
|
||||
# TODO remove SplitTlut
|
||||
{"SplitTlut", "HackMode"},
|
||||
)
|
||||
external_tlut_file = reselem.attrib["ExternalTlut"]
|
||||
external_tlut_offset = int(reselem.attrib["ExternalTlutOffset"], 16)
|
||||
@@ -230,8 +223,7 @@ def handler_Texture(
|
||||
xml_errors.check_attrib(
|
||||
reselem,
|
||||
{"Name", "Offset", "Format", "Width", "Height"},
|
||||
# TODO remove OutName
|
||||
{"OutName", "HackMode"} | STATIC_ATTRIB,
|
||||
{"HackMode"},
|
||||
)
|
||||
res = TextureResourceDesc(
|
||||
symbol_name, offset, collection, reselem, format, width, height
|
||||
|
||||
@@ -8,7 +8,7 @@ import enum
|
||||
import reprlib
|
||||
|
||||
import io
|
||||
from typing import TYPE_CHECKING, Sequence, Optional, Union, Any, Iterable
|
||||
from typing import TYPE_CHECKING, Sequence, Optional, Union, Any, Iterable, Generator
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
@@ -398,6 +398,8 @@ class File:
|
||||
# Ignore markers falling within existing resources
|
||||
result, resource = self.get_resource_at(file_start)
|
||||
if result == GetResourceAtResult.DEFINITIVE:
|
||||
assert resource is not None
|
||||
assert resource.range_end is not None
|
||||
if resource.range_start <= file_start < file_end <= resource.range_end:
|
||||
assert isinstance(resource, resource_type)
|
||||
resource.reporters.add(reporter)
|
||||
@@ -491,6 +493,8 @@ class File:
|
||||
self.add_resource(resource)
|
||||
else:
|
||||
assert result == GetResourceAtResult.DEFINITIVE
|
||||
assert resource is not None
|
||||
assert resource.range_end is not None
|
||||
assert (
|
||||
resource.range_start
|
||||
<= rbm.file_start
|
||||
@@ -515,6 +519,7 @@ class File:
|
||||
unaccounted_resources: list[Resource] = []
|
||||
|
||||
def add_unaccounted(range_start, range_end):
|
||||
assert self.data is not None
|
||||
if I_D_OMEGALUL:
|
||||
# IDO aligns every declaration to 4, so declaring zeros
|
||||
# that is actually padding for that purpose throws off matching.
|
||||
@@ -577,6 +582,10 @@ class File:
|
||||
|
||||
# Add unaccounted if needed at the end of the file
|
||||
resource_last = self._resources[-1]
|
||||
assert resource_last.range_end is not None, (
|
||||
"add_unaccounted_resources should be called once all"
|
||||
" resources are parsed and have a definitive range"
|
||||
)
|
||||
if resource_last.range_end < len(self.data):
|
||||
add_unaccounted(
|
||||
resource_last.range_end,
|
||||
@@ -589,6 +598,10 @@ class File:
|
||||
for i in range(1, len(self._resources)):
|
||||
resource_a = self._resources[i - 1]
|
||||
resource_b = self._resources[i]
|
||||
assert resource_a.range_end is not None, (
|
||||
"add_unaccounted_resources should be called once all"
|
||||
" resources are parsed and have a definitive range"
|
||||
)
|
||||
assert resource_a.range_end <= resource_b.range_start
|
||||
|
||||
# Add unaccounted if needed between two successive resources
|
||||
@@ -641,11 +654,12 @@ class File:
|
||||
self.source_h_path = source_path / f"{file_name}.h"
|
||||
|
||||
def write_source(self):
|
||||
def strip_extracted_prefix(path : Path) -> Path:
|
||||
def strip_extracted_prefix(path: Path) -> Path:
|
||||
parts = path.parts
|
||||
if parts[0] == "extracted":
|
||||
return Path(*parts[2:]) # Skip first two parts
|
||||
return path # Return original path if condition not met
|
||||
|
||||
assert hasattr(
|
||||
self, "source_c_path"
|
||||
), "set_source_path must be called before write_source"
|
||||
@@ -665,7 +679,9 @@ class File:
|
||||
referenced_file,
|
||||
)
|
||||
assert hasattr(referenced_file, "source_h_path")
|
||||
file_include_paths_complete.append(strip_extracted_prefix(referenced_file.source_h_path))
|
||||
file_include_paths_complete.append(
|
||||
strip_extracted_prefix(referenced_file.source_h_path)
|
||||
)
|
||||
|
||||
# Same as file_include_paths_complete,
|
||||
# but paths that can be are made relative to the source C.
|
||||
@@ -838,7 +854,7 @@ class Resource(abc.ABC):
|
||||
TODO figure out what to do with this, for now thinking debugging"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def try_parse_data(self, memory_context: "MemoryContext"):
|
||||
def try_parse_data(self, memory_context: "MemoryContext") -> object:
|
||||
"""Parse this resource's data bytes
|
||||
|
||||
This can typically result in finding more resources,
|
||||
@@ -879,7 +895,7 @@ class Resource(abc.ABC):
|
||||
"""
|
||||
...
|
||||
|
||||
def get_c_expression_length(self, resource_offset: int):
|
||||
def get_c_expression_length(self, resource_offset: int) -> str:
|
||||
"""Get a C expression for referencing the length of data in this resource
|
||||
|
||||
The offset `resource_offset` is relative to the resource, as in get_c_reference.
|
||||
@@ -1049,7 +1065,7 @@ class Resource(abc.ABC):
|
||||
+ ")"
|
||||
)
|
||||
|
||||
def __rich_repr__(self):
|
||||
def __rich_repr__(self) -> Generator[str | tuple[str, Any], None, None]:
|
||||
yield self.name
|
||||
yield (
|
||||
f"0x{self.range_start:08X}-"
|
||||
@@ -1070,13 +1086,15 @@ class ZeroPaddingResource(Resource):
|
||||
*,
|
||||
include_in_source=True,
|
||||
):
|
||||
# TODO move to try_parse_data ?
|
||||
assert set(file.data[range_start:range_end]) == {0}
|
||||
super().__init__(file, range_start, range_end, name)
|
||||
self.include_in_source = include_in_source
|
||||
|
||||
def try_parse_data(self, memory_context):
|
||||
# Nothing specific to do
|
||||
# Check the data is 0s
|
||||
assert self.file.data is not None
|
||||
if set(self.file.data[self.range_start : self.range_end]) != {0}:
|
||||
raise ResourceParseImpossible("Not zero padding")
|
||||
|
||||
return RESOURCE_PARSE_SUCCESS
|
||||
|
||||
def get_c_reference(self, resource_offset):
|
||||
@@ -1090,6 +1108,7 @@ class ZeroPaddingResource(Resource):
|
||||
pass
|
||||
|
||||
def get_c_declaration_base(self):
|
||||
assert self.range_end is not None
|
||||
length_bytes = self.range_end - self.range_start
|
||||
assert length_bytes > 0
|
||||
return f"u8 {self.symbol_name}[{length_bytes}]"
|
||||
@@ -1116,6 +1135,7 @@ class BinaryBlobResource(Resource):
|
||||
return RESOURCE_PARSE_SUCCESS
|
||||
|
||||
def get_as_xml(self):
|
||||
assert self.range_end is not None
|
||||
return f"""\
|
||||
<Blob Name="{self.symbol_name}" Size="0x{self.range_end - self.range_start:X}" Offset="0x{self.range_start:X}"/>"""
|
||||
|
||||
@@ -1129,6 +1149,8 @@ class BinaryBlobResource(Resource):
|
||||
return ("ultra64.h",)
|
||||
|
||||
def write_extracted(self, memory_context):
|
||||
assert self.file.data is not None
|
||||
assert self.range_end is not None
|
||||
data = self.file.data[self.range_start : self.range_end]
|
||||
assert len(data) == self.range_end - self.range_start
|
||||
self.extract_to_path.write_bytes(data)
|
||||
|
||||
@@ -168,6 +168,20 @@ class CDataExt_Value(CData_Value, CDataExt):
|
||||
else:
|
||||
return False
|
||||
|
||||
s8: "CDataExt_Value"
|
||||
u8: "CDataExt_Value"
|
||||
s16: "CDataExt_Value"
|
||||
u16: "CDataExt_Value"
|
||||
s32: "CDataExt_Value"
|
||||
u32: "CDataExt_Value"
|
||||
f32: "CDataExt_Value"
|
||||
f64: "CDataExt_Value"
|
||||
pointer: "CDataExt_Value"
|
||||
|
||||
pad8: "CDataExt_Value"
|
||||
pad16: "CDataExt_Value"
|
||||
pad32: "CDataExt_Value"
|
||||
|
||||
|
||||
CDataExt_Value.s8 = CDataExt_Value("b").freeze()
|
||||
CDataExt_Value.u8 = CDataExt_Value("B").freeze()
|
||||
@@ -277,6 +291,7 @@ class CDataResource(Resource):
|
||||
self._is_cdata_processed = False
|
||||
|
||||
def try_parse_data(self, memory_context: "MemoryContext"):
|
||||
assert self.file.data is not None
|
||||
if self.can_size_be_unknown:
|
||||
assert hasattr(self, "cdata_ext") and self.cdata_ext is not None, (
|
||||
"Subclasses with can_size_be_unknown=True should redefine try_parse_data"
|
||||
|
||||
@@ -38,6 +38,16 @@ class CData_Value(CData):
|
||||
def unpack_from(self, data: memoryview, offset: int = 0):
|
||||
return self.unpack_struct.unpack_from(data, offset)[0]
|
||||
|
||||
s8: "CData_Value"
|
||||
u8: "CData_Value"
|
||||
s16: "CData_Value"
|
||||
u16: "CData_Value"
|
||||
s32: "CData_Value"
|
||||
u32: "CData_Value"
|
||||
f32: "CData_Value"
|
||||
f64: "CData_Value"
|
||||
pointer: "CData_Value"
|
||||
|
||||
|
||||
CData_Value.s8 = CData_Value("b")
|
||||
CData_Value.u8 = CData_Value("B")
|
||||
@@ -142,26 +152,30 @@ def try_stuff():
|
||||
} data = { varLenArray, 3, { 421, 0x01020304 } };
|
||||
"""
|
||||
|
||||
array_bytes = bytes(
|
||||
[
|
||||
1,
|
||||
0,
|
||||
*(0, 2),
|
||||
3,
|
||||
0,
|
||||
*(0, 4),
|
||||
]
|
||||
array_bytes = memoryview(
|
||||
bytes(
|
||||
[
|
||||
1,
|
||||
0,
|
||||
*(0, 2),
|
||||
3,
|
||||
0,
|
||||
*(0, 4),
|
||||
]
|
||||
)
|
||||
)
|
||||
varLenArray_bytes = bytes([1, 2, 3])
|
||||
data_bytes = bytes(
|
||||
[
|
||||
*(0x12, 0x34, 0x56, 0x78),
|
||||
*(0, 3),
|
||||
0,
|
||||
0,
|
||||
*(0, 0, 421 >> 8, 421 & 0xFF),
|
||||
*(1, 2, 3, 4),
|
||||
]
|
||||
varLenArray_bytes = memoryview(bytes([1, 2, 3]))
|
||||
data_bytes = memoryview(
|
||||
bytes(
|
||||
[
|
||||
*(0x12, 0x34, 0x56, 0x78),
|
||||
*(0, 3),
|
||||
0,
|
||||
0,
|
||||
*(0, 0, 421 >> 8, 421 & 0xFF),
|
||||
*(1, 2, 3, 4),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
arrayElem_CData_Struct = CData_Struct(
|
||||
|
||||
@@ -30,7 +30,7 @@ class AnimationFrameDataResource(CDataResource, can_size_be_unknown=True):
|
||||
|
||||
def __init__(self, file: File, range_start: int, name: str):
|
||||
super().__init__(file, range_start, name)
|
||||
self.length = None
|
||||
self.length: int | None = None
|
||||
|
||||
def try_parse_data(self, memory_context):
|
||||
if self.length is not None:
|
||||
@@ -64,7 +64,7 @@ class AnimationJointIndicesResource(CDataResource, can_size_be_unknown=True):
|
||||
|
||||
def __init__(self, file: File, range_start: int, name: str):
|
||||
super().__init__(file, range_start, name)
|
||||
self.length = None
|
||||
self.length: int | None = None
|
||||
|
||||
def try_parse_data(self, memory_context):
|
||||
if self.length is not None:
|
||||
|
||||
@@ -42,6 +42,7 @@ class CollisionVtxListResource(CDataResource):
|
||||
|
||||
def get_c_declaration_base(self):
|
||||
if hasattr(self, "HACK_IS_STATIC_ON"):
|
||||
assert isinstance(self.cdata_ext, CDataExt_Array)
|
||||
return f"Vec3s {self.symbol_name}[{self.cdata_ext.length}]"
|
||||
return f"Vec3s {self.symbol_name}[]"
|
||||
|
||||
@@ -161,6 +162,7 @@ class CollisionPolyListResource(CDataResource):
|
||||
|
||||
def get_c_declaration_base(self):
|
||||
if hasattr(self, "HACK_IS_STATIC_ON"):
|
||||
assert isinstance(self.cdata_ext, CDataExt_Array)
|
||||
return f"CollisionPoly {self.symbol_name}[{self.cdata_ext.length}]"
|
||||
return f"CollisionPoly {self.symbol_name}[]"
|
||||
|
||||
@@ -292,6 +294,7 @@ class CollisionSurfaceTypeListResource(CDataResource):
|
||||
|
||||
def get_c_declaration_base(self):
|
||||
if hasattr(self, "HACK_IS_STATIC_ON"):
|
||||
assert isinstance(self.cdata_ext, CDataExt_Array)
|
||||
return f"SurfaceType {self.symbol_name}[{self.cdata_ext.length}]"
|
||||
return f"SurfaceType {self.symbol_name}[]"
|
||||
|
||||
@@ -318,6 +321,7 @@ class BgCamFuncDataResource(CDataResource):
|
||||
|
||||
def get_c_declaration_base(self):
|
||||
if hasattr(self, "HACK_IS_STATIC_ON"):
|
||||
assert isinstance(self.cdata_ext, CDataExt_Array)
|
||||
return f"Vec3s {self.symbol_name}[{self.cdata_ext.length}]"
|
||||
return f"Vec3s {self.symbol_name}[]"
|
||||
|
||||
@@ -337,7 +341,7 @@ class BgCamFuncDataResource(CDataResource):
|
||||
|
||||
class CollisionBgCamListResource(CDataResource):
|
||||
def write_bgCamFuncData(
|
||||
resource: "CollisionSurfaceTypeListResource",
|
||||
resource: "CollisionBgCamListResource",
|
||||
memory_context: "MemoryContext",
|
||||
v,
|
||||
wctx: CDataExtWriteContext,
|
||||
@@ -419,6 +423,7 @@ class CollisionBgCamListResource(CDataResource):
|
||||
|
||||
def get_c_declaration_base(self):
|
||||
if hasattr(self, "HACK_IS_STATIC_ON"):
|
||||
assert isinstance(self.cdata_ext, CDataExt_Array)
|
||||
return f"BgCamInfo {self.symbol_name}[{self.cdata_ext.length}]"
|
||||
return f"BgCamInfo {self.symbol_name}[]"
|
||||
|
||||
@@ -438,11 +443,19 @@ class CollisionBgCamListResource(CDataResource):
|
||||
class CollisionWaterBoxesResource(CDataResource):
|
||||
|
||||
def write_properties(v):
|
||||
assert isinstance(v, int)
|
||||
bgCamIndex = (v >> 0) & 0xFF
|
||||
lightIndex = (v >> 8) & 0x1F
|
||||
room = (v >> 13) & 0x3F
|
||||
setFlag19 = (v >> 19) & 1
|
||||
return f"WATERBOX_PROPERTIES(/* bgCamIndex */ {bgCamIndex}, /* lightIndex */ {lightIndex}, /* room */ {room}, /* setFlag19 */ {'true' if setFlag19 else 'false'})"
|
||||
return (
|
||||
"WATERBOX_PROPERTIES("
|
||||
f"/* bgCamIndex */ {bgCamIndex}, "
|
||||
f"/* lightIndex */ {lightIndex}, "
|
||||
f"/* room */ {room}, "
|
||||
f"/* setFlag19 */ {'true' if setFlag19 else 'false'}"
|
||||
")"
|
||||
)
|
||||
|
||||
elem_cdata_ext = CDataExt_Struct(
|
||||
(
|
||||
|
||||
@@ -147,6 +147,7 @@ class VtxArrayResource(CDataResource):
|
||||
super().__init__(file, range_start, name)
|
||||
|
||||
def get_as_xml(self):
|
||||
assert self.range_end is not None
|
||||
return f"""\
|
||||
<Array Name="{self.symbol_name}" Count="{(self.range_end - self.range_start) // self.element_cdata_ext.size}" Offset="0x{self.range_start:X}">
|
||||
<Vtx/>
|
||||
@@ -154,6 +155,7 @@ class VtxArrayResource(CDataResource):
|
||||
|
||||
def get_c_declaration_base(self):
|
||||
if hasattr(self, "HACK_IS_STATIC_ON"):
|
||||
assert isinstance(self.cdata_ext, CDataExt_Array)
|
||||
return f"Vtx {self.symbol_name}[{self.cdata_ext.length}]"
|
||||
return f"Vtx {self.symbol_name}[]"
|
||||
|
||||
@@ -343,10 +345,11 @@ class TextureResource(Resource):
|
||||
if resource_ci.siz == G_IM_SIZ._4b:
|
||||
v_max = max(max((b >> 4) & 0xF, b & 0xF) for b in resource_ci_data)
|
||||
assert v_max < 16
|
||||
|
||||
if resource_ci.siz == G_IM_SIZ._8b:
|
||||
elif resource_ci.siz == G_IM_SIZ._8b:
|
||||
v_max = max(resource_ci_data)
|
||||
assert v_max < 256
|
||||
else:
|
||||
assert False, resource_ci.siz
|
||||
|
||||
new_min_count = v_max + 1
|
||||
|
||||
@@ -446,6 +449,9 @@ class TextureResource(Resource):
|
||||
return f"{self.name}.{format_name}{elem_type_suffix}"
|
||||
|
||||
def write_extracted(self, memory_context):
|
||||
assert self.file.data is not None
|
||||
assert self.range_end is not None
|
||||
|
||||
if self.is_tlut():
|
||||
# TLUTs are extracted as part of the color-indexed textures using them
|
||||
|
||||
@@ -605,10 +611,11 @@ class TLUTResource(TextureResource, can_size_be_unknown=True):
|
||||
if resource_ci.siz == G_IM_SIZ._4b:
|
||||
v_max = max(max((b >> 4) & 0xF, b & 0xF) for b in resource_ci_data)
|
||||
assert v_max < 16
|
||||
|
||||
if resource_ci.siz == G_IM_SIZ._8b:
|
||||
elif resource_ci.siz == G_IM_SIZ._8b:
|
||||
v_max = max(resource_ci_data)
|
||||
assert v_max < 256
|
||||
else:
|
||||
assert False, resource_ci.siz
|
||||
|
||||
new_min_count = v_max + 1
|
||||
|
||||
@@ -645,6 +652,7 @@ class TextureSplitTlutResource(TextureResource):
|
||||
return f"{self.name}.ci8.split_{'lo' if self.lo_half else 'hi'}.tlut_{self.resource_tlut.name}"
|
||||
|
||||
def write_extracted(self, memory_context):
|
||||
assert self.file.data is not None
|
||||
data = self.file.data[self.range_start : self.range_end]
|
||||
assert len(data) == self.range_end - self.range_start
|
||||
|
||||
@@ -652,7 +660,7 @@ class TextureSplitTlutResource(TextureResource):
|
||||
assert all(_b < 128 for _b in data)
|
||||
else:
|
||||
assert all(_b >= 128 for _b in data)
|
||||
data = bytes(_b - 128 for _b in data)
|
||||
data = memoryview(bytes(_b - 128 for _b in data))
|
||||
|
||||
tlut_data = self.resource_tlut.file.data[
|
||||
self.resource_tlut.range_start : self.resource_tlut.range_end
|
||||
@@ -1024,9 +1032,9 @@ class ColorIndexedTexturesManager:
|
||||
texs: list["ColorIndexedTexturesManager.Tex"]
|
||||
|
||||
def __init__(self, *, HACK_late_SetTextureLUT=False):
|
||||
self.cur_tlut_mode: G_TT = None
|
||||
self.cur_tlut_mode: G_TT | None = None
|
||||
|
||||
self.cur_tluts_count: int = None
|
||||
self.cur_tluts_count: int | None = None
|
||||
self.cur_tluts: dict[int, ColorIndexedTexturesManager.Tlut] = dict()
|
||||
self.cur_texs: list[ColorIndexedTexturesManager.Tex] = []
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ class CutsceneResource(Resource, can_size_be_unknown=True):
|
||||
super().__init__(file, range_start, None, name)
|
||||
|
||||
def try_parse_data(self, memory_context):
|
||||
assert self.file.data is not None
|
||||
assert self.range_start % 4 == 0
|
||||
data = self.file.data[self.range_start :]
|
||||
num_bytes = len(data)
|
||||
|
||||
@@ -56,6 +56,8 @@ def report_room_shape_at_segmented(
|
||||
|
||||
|
||||
def get_room_shape_resource_type(file: File, offset: int):
|
||||
assert file.data is not None
|
||||
|
||||
room_shape_type_int = file.data[offset]
|
||||
room_shape_type = RoomShapeType(room_shape_type_int)
|
||||
|
||||
@@ -269,6 +271,7 @@ class JFIFResource(Resource):
|
||||
return f"{self.name}.jpg"
|
||||
|
||||
def write_extracted(self, memory_context):
|
||||
assert self.file.data is not None
|
||||
# TODO trim zeros at the end of the data
|
||||
self.extract_to_path.write_bytes(
|
||||
self.file.data[self.range_start : self.range_end]
|
||||
|
||||
@@ -111,6 +111,7 @@ class SceneCommandsResource(Resource, can_size_be_unknown=True):
|
||||
self.exit_list_length = None
|
||||
|
||||
def try_parse_data(self, memory_context: "MemoryContext"):
|
||||
assert self.file.data is not None
|
||||
data = self.file.data[self.range_start :]
|
||||
|
||||
new_progress_done = []
|
||||
@@ -265,7 +266,6 @@ class SceneCommandsResource(Resource, can_size_be_unknown=True):
|
||||
new_progress_done.append(("reported ActorEntryListResource", cmd_id))
|
||||
|
||||
if cmd_id == SceneCmdId.SCENE_CMD_ID_EXIT_LIST:
|
||||
# TODO length from collision
|
||||
assert data1 == 0
|
||||
resource = memory_context.report_resource_at_segmented(
|
||||
self,
|
||||
@@ -423,6 +423,7 @@ class SceneCommandsResource(Resource, can_size_be_unknown=True):
|
||||
return f"SceneCmd {self.symbol_name}[]"
|
||||
|
||||
def write_extracted(self, memory_context):
|
||||
assert self.file.data is not None
|
||||
data = self.file.data[self.range_start : self.range_end]
|
||||
with self.extract_to_path.open("w") as f:
|
||||
if not self.braces_in_source:
|
||||
@@ -431,10 +432,12 @@ class SceneCommandsResource(Resource, can_size_be_unknown=True):
|
||||
(cmd_id_int, data1, pad2, data2_I) = struct.unpack_from(
|
||||
">BBHI", data, offset
|
||||
)
|
||||
(_, data2_H0, data2_H1) = struct.unpack_from(">IHH", data, offset)
|
||||
(_, data2_B0, data2_B1, data2_B2, data2_B3) = struct.unpack_from(
|
||||
">IBBBB", data, offset
|
||||
)
|
||||
(_, data2_b0, data2_b1, data2_b2, data2_b3) = struct.unpack_from(
|
||||
">Ibbbb", data, offset
|
||||
)
|
||||
cmd_id = SceneCmdId(cmd_id_int)
|
||||
f.write(" " * 4)
|
||||
f.write(scene_cmd_macro_name_by_cmd_id[cmd_id])
|
||||
@@ -468,10 +471,9 @@ class SceneCommandsResource(Resource, can_size_be_unknown=True):
|
||||
f.write(memory_context.get_c_reference_at_segmented(address))
|
||||
if cmd_id == SceneCmdId.SCENE_CMD_ID_WIND_SETTINGS:
|
||||
assert data1 == 0
|
||||
# TODO cast x,y,z to s8
|
||||
xDir = data2_B0
|
||||
yDir = data2_B1
|
||||
zDir = data2_B2
|
||||
xDir = data2_b0
|
||||
yDir = data2_b1
|
||||
zDir = data2_b2
|
||||
strength = data2_B3
|
||||
f.write(f"{xDir}, {yDir}, {zDir}, {strength}")
|
||||
if cmd_id == SceneCmdId.SCENE_CMD_ID_SPAWN_LIST:
|
||||
@@ -676,6 +678,7 @@ class AltHeadersResource(CDataArrayResource):
|
||||
) # SceneCmd*
|
||||
|
||||
def try_parse_data(self, memory_context):
|
||||
assert self.file.data is not None
|
||||
length = 0
|
||||
for i, (v,) in enumerate(
|
||||
struct.iter_unpack(">I", self.file.data[self.range_start :])
|
||||
|
||||
@@ -158,8 +158,8 @@ class SpawnListResource(CDataArrayResource):
|
||||
)
|
||||
|
||||
# (eventually) set by SceneCommandsResource
|
||||
player_entry_list_length = None
|
||||
room_list_length = None
|
||||
player_entry_list_length: int | None = None
|
||||
room_list_length: int | None = None
|
||||
|
||||
def try_parse_data(self, memory_context):
|
||||
if self.player_entry_list_length is None or self.room_list_length is None:
|
||||
|
||||
@@ -27,7 +27,7 @@ class KnotCountsArrayResource(CDataResource, can_size_be_unknown=True):
|
||||
|
||||
def __init__(self, file: File, range_start: int, name: str):
|
||||
super().__init__(file, range_start, name)
|
||||
self.length = None
|
||||
self.length: int | None = None
|
||||
|
||||
def try_parse_data(self, memory_context: "MemoryContext"):
|
||||
if self.length is not None:
|
||||
@@ -63,7 +63,7 @@ class CurveInterpKnotArrayResource(CDataResource, can_size_be_unknown=True):
|
||||
|
||||
def __init__(self, file: File, range_start: int, name: str):
|
||||
super().__init__(file, range_start, name)
|
||||
self.length = None
|
||||
self.length: int | None = None
|
||||
|
||||
def try_parse_data(self, memory_context: "MemoryContext"):
|
||||
if self.length is not None:
|
||||
@@ -91,7 +91,7 @@ class ConstantDataArrayResource(CDataResource, can_size_be_unknown=True):
|
||||
|
||||
def __init__(self, file: File, range_start: int, name: str):
|
||||
super().__init__(file, range_start, name)
|
||||
self.length = None
|
||||
self.length: int | None = None
|
||||
|
||||
def try_parse_data(self, memory_context: "MemoryContext"):
|
||||
if self.length is not None:
|
||||
|
||||
@@ -216,6 +216,7 @@ class SkeletonResourceBaseABC(CDataResource):
|
||||
return RESOURCE_PARSE_SUCCESS
|
||||
|
||||
def write_c_declaration(self, h):
|
||||
assert self.limbs_array_resource is not None
|
||||
h.write(f"typedef enum {self.enum_name} {{\n")
|
||||
limb_enum_members = (
|
||||
self.enum_member_name_none,
|
||||
@@ -231,7 +232,6 @@ class SkeletonResourceBaseABC(CDataResource):
|
||||
)
|
||||
h.write(f"}} {self.enum_name};\n")
|
||||
super().write_c_declaration(h)
|
||||
return True
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_skeleton_header_cdata_unpacked(self) -> dict: ...
|
||||
|
||||
@@ -127,5 +127,6 @@ def get_skybox_id(skybox_id: int) -> str:
|
||||
def get_light_mode(light_mode: int) -> str:
|
||||
return misc_ids.LIGHT_MODES[light_mode]
|
||||
|
||||
|
||||
def get_navi_quest_hint_file_id_name(navi_quest_hint_file_id: int) -> str:
|
||||
return misc_ids.NAVI_QUEST_HINT_FILE_IDS[navi_quest_hint_file_id]
|
||||
|
||||
@@ -449,7 +449,7 @@ def register_resource_handlers():
|
||||
)
|
||||
|
||||
|
||||
RESOURCE_HANDLERS: dict[str, ResourceHandler] = {}
|
||||
RESOURCE_HANDLERS: dict[type[ResourceDesc], ResourceHandler] = {}
|
||||
|
||||
|
||||
def get_resource_from_desc(
|
||||
|
||||
Reference in New Issue
Block a user