This commit is contained in:
Dragorn421 2025-07-15 01:53:35 -04:00 committed by GitHub
commit 5367b6e097
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 53 additions and 46 deletions

View File

@ -1,9 +1,18 @@
<Root> <Root>
<File Name="spot05_scene" Segment="2"> <File Name="spot05_scene" Segment="2">
<Cutscene Name="gMeadowMinuetCs" Offset="0x3F80"/> <Cutscene Name="gMeadowMinuetCs">
<Cutscene Name="gMeadowSariasSongCs" Offset="0x5730"/> <Version Pattern="pal-1\.[01]" Offset="0x3F84"/>
<Version Pattern=".*" Offset="0x3F80"/>
</Cutscene>
<Cutscene Name="gMeadowSariasSongCs">
<Version Pattern="pal-1\.[01]" Offset="0x5740"/>
<Version Pattern=".*" Offset="0x5730"/>
</Cutscene>
<Path Name="spot05_scenePathList_0069D8" Offset="0x69D8" NumPaths="5"/> <Path Name="spot05_scenePathList_0069D8" NumPaths="5">
<Version Pattern="pal-1\.[01]" Offset="0x69E8"/>
<Version Pattern=".*" Offset="0x69D8"/>
</Path>
<Scene Name="spot05_scene" Offset="0x0"/> <Scene Name="spot05_scene" Offset="0x0"/>
</File> </File>

View File

@ -1,15 +0,0 @@
<Root>
<File Name="spot05_scene" Segment="2">
<Cutscene Name="gMeadowMinuetCs" Offset="0x3F84"/>
<Cutscene Name="gMeadowSariasSongCs" Offset="0x5740"/>
<Path Name="spot05_scenePathList_0069D8" Offset="0x69E8" NumPaths="5"/>
<Scene Name="spot05_scene" Offset="0x0"/>
</File>
<File Name="spot05_room_0" Segment="3">
<DList Name="gSpot05DL_009A60" Offset="0x9A60"/>
<DList Name="gSpot05DL_009EE0" Offset="0x9EE0"/>
<Room Name="spot05_room_0" Offset="0x0"/>
</File>
</Root>

View File

@ -1134,7 +1134,7 @@ assets:
- name: scenes/overworld/spot04 - name: scenes/overworld/spot04
xml_path: assets/xml/scenes/overworld/spot04_pal_n64.xml xml_path: assets/xml/scenes/overworld/spot04_pal_n64.xml
- name: scenes/overworld/spot05 - name: scenes/overworld/spot05
xml_path: assets/xml/scenes/overworld/spot05_pal_n64.xml xml_path: assets/xml/scenes/overworld/spot05.xml
- name: scenes/overworld/spot06 - name: scenes/overworld/spot06
xml_path: assets/xml/scenes/overworld/spot06_pal_n64.xml xml_path: assets/xml/scenes/overworld/spot06_pal_n64.xml
- name: scenes/overworld/spot07 - name: scenes/overworld/spot07

View File

@ -1134,7 +1134,7 @@ assets:
- name: scenes/overworld/spot04 - name: scenes/overworld/spot04
xml_path: assets/xml/scenes/overworld/spot04_pal_n64.xml xml_path: assets/xml/scenes/overworld/spot04_pal_n64.xml
- name: scenes/overworld/spot05 - name: scenes/overworld/spot05
xml_path: assets/xml/scenes/overworld/spot05_pal_n64.xml xml_path: assets/xml/scenes/overworld/spot05.xml
- name: scenes/overworld/spot06 - name: scenes/overworld/spot06
xml_path: assets/xml/scenes/overworld/spot06_pal_n64.xml xml_path: assets/xml/scenes/overworld/spot06_pal_n64.xml
- name: scenes/overworld/spot07 - name: scenes/overworld/spot07

View File

@ -5,6 +5,7 @@ import abc
import dataclasses import dataclasses
from functools import cache from functools import cache
from pathlib import Path from pathlib import Path
import re
from typing import Callable, Optional from typing import Callable, Optional
from xml.etree import ElementTree from xml.etree import ElementTree
@ -260,7 +261,19 @@ def _get_resources_fileelem_to_resourcescollection_pass1(
for reselem in fileelem: for reselem in fileelem:
try: try:
symbol_name = reselem.attrib["Name"] symbol_name = reselem.attrib["Name"]
offset = int(reselem.attrib["Offset"], 16) if "Offset" in reselem.attrib:
offset = int(reselem.attrib["Offset"], 16)
else:
offset = None
for version_elem in reselem:
if version_elem.tag != "Version":
continue
if re.fullmatch(version_elem.attrib["Pattern"], vc.version):
offset = int(version_elem.attrib["Offset"], 16)
break
if offset is None:
raise Exception(f"No Offset on resource {symbol_name}")
res_handler = _get_resource_handler(reselem.tag) res_handler = _get_resource_handler(reselem.tag)
try: try:
res = res_handler(symbol_name, offset, collection, reselem) res = res_handler(symbol_name, offset, collection, reselem)

View File

@ -34,7 +34,7 @@ class DListResourceDesc(ResourceDesc):
def handler_DList(symbol_name, offset, collection, reselem: Element): def handler_DList(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib( xml_errors.check_attrib(
reselem, {"Name", "Offset"}, {"Ucode", "RawPointers"} | STATIC_ATTRIB reselem, {"Name"}, {"Offset", "Ucode", "RawPointers"} | STATIC_ATTRIB
) )
if "Ucode" in reselem.attrib: if "Ucode" in reselem.attrib:
ucode = GfxMicroCode[reselem.attrib["Ucode"].upper()] ucode = GfxMicroCode[reselem.attrib["Ucode"].upper()]
@ -54,7 +54,7 @@ class BlobResourceDesc(ResourceDesc):
def handler_Blob(symbol_name, offset, collection, reselem: Element): 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", "Size"}, {"Offset"} | STATIC_ATTRIB)
size = int(reselem.attrib["Size"], 16) size = int(reselem.attrib["Size"], 16)
return BlobResourceDesc(symbol_name, offset, collection, reselem, size) return BlobResourceDesc(symbol_name, offset, collection, reselem, size)
@ -65,7 +65,7 @@ class MtxResourceDesc(ResourceDesc):
def handler_Mtx(symbol_name, offset, collection, reselem: Element): 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"} | STATIC_ATTRIB)
return MtxResourceDesc(symbol_name, offset, collection, reselem) return MtxResourceDesc(symbol_name, offset, collection, reselem)
@ -85,7 +85,7 @@ class VtxArrayResourceDesc(ResourceDesc):
def handler_Array(symbol_name, offset, collection, reselem: Element): 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", "Count"}, {"Offset"} | STATIC_ATTRIB)
count = int(reselem.attrib["Count"]) count = int(reselem.attrib["Count"])
assert len(reselem) == 1, "Expected exactly one child of Array node" assert len(reselem) == 1, "Expected exactly one child of Array node"
array_elem = reselem[0] array_elem = reselem[0]
@ -137,9 +137,10 @@ def handler_Texture(
): ):
xml_errors.check_attrib( xml_errors.check_attrib(
reselem, reselem,
{"Name", "Offset", "Format", "Width", "Height"}, {"Name", "Format", "Width", "Height"},
# TODO remove OutName, SplitTlut # TODO remove OutName, SplitTlut
{ {
"Offset",
"OutName", "OutName",
"SplitTlut", "SplitTlut",
"TlutOffset", "TlutOffset",
@ -169,9 +170,9 @@ def handler_Texture(
if "TlutOffset" in reselem.attrib: if "TlutOffset" in reselem.attrib:
xml_errors.check_attrib( xml_errors.check_attrib(
reselem, reselem,
{"Name", "Offset", "Format", "Width", "Height", "TlutOffset"}, {"Name", "Format", "Width", "Height", "TlutOffset"},
# TODO remove OutName, SplitTlut # TODO remove OutName, SplitTlut
{"OutName", "SplitTlut", "HackMode"} | STATIC_ATTRIB, {"Offset", "OutName", "SplitTlut", "HackMode"} | STATIC_ATTRIB,
) )
tlut_offset = int(reselem.attrib["TlutOffset"], 16) tlut_offset = int(reselem.attrib["TlutOffset"], 16)
@ -193,7 +194,6 @@ def handler_Texture(
reselem, reselem,
{ {
"Name", "Name",
"Offset",
"Format", "Format",
"Width", "Width",
"Height", "Height",
@ -201,7 +201,7 @@ def handler_Texture(
"ExternalTlutOffset", "ExternalTlutOffset",
}, },
# TODO remove OutName, SplitTlut # TODO remove OutName, SplitTlut
{"OutName", "SplitTlut", "HackMode"} | STATIC_ATTRIB, {"Offset", "OutName", "SplitTlut", "HackMode"} | STATIC_ATTRIB,
) )
external_tlut_file = reselem.attrib["ExternalTlut"] external_tlut_file = reselem.attrib["ExternalTlut"]
external_tlut_offset = int(reselem.attrib["ExternalTlutOffset"], 16) external_tlut_offset = int(reselem.attrib["ExternalTlutOffset"], 16)
@ -229,9 +229,9 @@ def handler_Texture(
else: else:
xml_errors.check_attrib( xml_errors.check_attrib(
reselem, reselem,
{"Name", "Offset", "Format", "Width", "Height"}, {"Name", "Format", "Width", "Height"},
# TODO remove OutName # TODO remove OutName
{"OutName", "HackMode"} | STATIC_ATTRIB, {"Offset", "OutName", "HackMode"} | STATIC_ATTRIB,
) )
res = TextureResourceDesc( res = TextureResourceDesc(
symbol_name, offset, collection, reselem, format, width, height symbol_name, offset, collection, reselem, format, width, height

View File

@ -20,7 +20,7 @@ class CollisionResourceDesc(ResourceDesc):
def handler_Collision(symbol_name, offset, collection, reselem: Element): def handler_Collision(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset"}) xml_errors.check_attrib(reselem, {"Name"}, {"Offset"})
return CollisionResourceDesc(symbol_name, offset, collection, reselem) return CollisionResourceDesc(symbol_name, offset, collection, reselem)
@ -30,7 +30,7 @@ class AnimationResourceDesc(ResourceDesc):
def handler_Animation(symbol_name, offset, collection, reselem: Element): def handler_Animation(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset"}) xml_errors.check_attrib(reselem, {"Name"}, {"Offset"})
return AnimationResourceDesc(symbol_name, offset, collection, reselem) return AnimationResourceDesc(symbol_name, offset, collection, reselem)
@ -40,7 +40,7 @@ class PlayerAnimationResourceDesc(ResourceDesc):
def handler_PlayerAnimation(symbol_name, offset, collection, reselem: Element): def handler_PlayerAnimation(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset"}) xml_errors.check_attrib(reselem, {"Name"}, {"Offset"})
return PlayerAnimationResourceDesc(symbol_name, offset, collection, reselem) return PlayerAnimationResourceDesc(symbol_name, offset, collection, reselem)
@ -50,7 +50,7 @@ class LegacyAnimationResourceDesc(ResourceDesc):
def handler_LegacyAnimation(symbol_name, offset, collection, reselem: Element): def handler_LegacyAnimation(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset"}) xml_errors.check_attrib(reselem, {"Name"}, {"Offset"})
return LegacyAnimationResourceDesc(symbol_name, offset, collection, reselem) return LegacyAnimationResourceDesc(symbol_name, offset, collection, reselem)
@ -60,7 +60,7 @@ class CutsceneResourceDesc(ResourceDesc):
def handler_Cutscene(symbol_name, offset, collection, reselem: Element): def handler_Cutscene(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset"}) xml_errors.check_attrib(reselem, {"Name"}, {"Offset"})
return CutsceneResourceDesc(symbol_name, offset, collection, reselem) return CutsceneResourceDesc(symbol_name, offset, collection, reselem)
@ -70,7 +70,7 @@ class SceneResourceDesc(ResourceDesc):
def handler_Scene(symbol_name, offset, collection, reselem: Element): def handler_Scene(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset"}) xml_errors.check_attrib(reselem, {"Name"}, {"Offset"})
return SceneResourceDesc(symbol_name, offset, collection, reselem) return SceneResourceDesc(symbol_name, offset, collection, reselem)
@ -80,7 +80,7 @@ class RoomResourceDesc(ResourceDesc):
def handler_Room(symbol_name, offset, collection, reselem: Element): def handler_Room(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset"}, {"HackMode"}) xml_errors.check_attrib(reselem, {"Name"}, {"Offset", "HackMode"})
res = RoomResourceDesc(symbol_name, offset, collection, reselem) res = RoomResourceDesc(symbol_name, offset, collection, reselem)
if reselem.attrib.get("HackMode") == "syotes_room": if reselem.attrib.get("HackMode") == "syotes_room":
res.hack_modes.add("hackmode_syotes_room") res.hack_modes.add("hackmode_syotes_room")
@ -93,7 +93,7 @@ class PlayerAnimationDataResourceDesc(ResourceDesc):
def handler_PlayerAnimationData(symbol_name, offset, collection, reselem: Element): def handler_PlayerAnimationData(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset", "FrameCount"}) xml_errors.check_attrib(reselem, {"Name", "FrameCount"}, {"Offset"})
frame_count = int(reselem.attrib["FrameCount"]) frame_count = int(reselem.attrib["FrameCount"])
return PlayerAnimationDataResourceDesc( return PlayerAnimationDataResourceDesc(
symbol_name, offset, collection, reselem, frame_count symbol_name, offset, collection, reselem, frame_count
@ -106,7 +106,7 @@ class PathListResourceDesc(ResourceDesc):
def handler_PathList(symbol_name, offset, collection, reselem: Element): def handler_PathList(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset", "NumPaths"}) xml_errors.check_attrib(reselem, {"Name", "NumPaths"}, {"Offset"})
num_paths = int(reselem.attrib["NumPaths"]) num_paths = int(reselem.attrib["NumPaths"])
return PathListResourceDesc(symbol_name, offset, collection, reselem, num_paths) return PathListResourceDesc(symbol_name, offset, collection, reselem, num_paths)
@ -137,8 +137,8 @@ class SkeletonResourceDesc(ResourceDesc):
def handler_Skeleton(symbol_name, offset, collection, reselem: Element): def handler_Skeleton(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib( xml_errors.check_attrib(
reselem, reselem,
{"Name", "Offset", "Type", "LimbType"}, {"Name", "Type", "LimbType"},
{"EnumName", "LimbNone", "LimbMax"}, {"Offset", "EnumName", "LimbNone", "LimbMax"},
) )
skel_type = SkeletonType[reselem.attrib["Type"].upper()] skel_type = SkeletonType[reselem.attrib["Type"].upper()]
limb_type = LimbType[reselem.attrib["LimbType"].upper()] limb_type = LimbType[reselem.attrib["LimbType"].upper()]
@ -162,7 +162,7 @@ class LimbResourceDesc(ResourceDesc):
def handler_Limb(symbol_name, offset, collection, reselem: Element): def handler_Limb(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset", "LimbType"}, {"EnumName"}) xml_errors.check_attrib(reselem, {"Name", "LimbType"}, {"Offset", "EnumName"})
limb_type = LimbType[reselem.attrib["LimbType"].upper()] limb_type = LimbType[reselem.attrib["LimbType"].upper()]
return LimbResourceDesc( return LimbResourceDesc(
symbol_name, symbol_name,
@ -181,7 +181,7 @@ class LimbTableResourceDesc(ResourceDesc):
def handler_LimbTable(symbol_name, offset, collection, reselem: Element): def handler_LimbTable(symbol_name, offset, collection, reselem: Element):
xml_errors.check_attrib(reselem, {"Name", "Offset", "LimbType", "Count"}) xml_errors.check_attrib(reselem, {"Name", "LimbType", "Count"}, {"Offset"})
limb_type = LimbType[reselem.attrib["LimbType"].upper()] limb_type = LimbType[reselem.attrib["LimbType"].upper()]
count = int(reselem.attrib["Count"]) count = int(reselem.attrib["Count"])
return LimbTableResourceDesc( return LimbTableResourceDesc(
@ -197,7 +197,7 @@ class CurveAnimationResourceDesc(ResourceDesc):
def handler_CurveAnimation( def handler_CurveAnimation(
symbol_name, offset, collection: ResourcesDescCollection, reselem: Element symbol_name, offset, collection: ResourcesDescCollection, reselem: Element
): ):
xml_errors.check_attrib(reselem, {"Name", "Offset", "SkelOffset"}) xml_errors.check_attrib(reselem, {"Name", "SkelOffset"}, {"Offset"})
res = CurveAnimationResourceDesc(symbol_name, offset, collection, reselem, None) res = CurveAnimationResourceDesc(symbol_name, offset, collection, reselem, None)
skel_offset = int(reselem.attrib["SkelOffset"], 16) skel_offset = int(reselem.attrib["SkelOffset"], 16)