mirror of https://github.com/zeldaret/oot.git
Assets system: reconcile xml versions using implicit offsets
This commit is contained in:
parent
39de1e0204
commit
3dcba7e70a
|
@ -1,20 +1,51 @@
|
||||||
<Root>
|
<Root>
|
||||||
<File Name="object_mag" Segment="6">
|
<File Name="object_mag" Segment="6">
|
||||||
<Texture Name="gTitleDiskTex" Format="ia8" Width="48" Height="16" Offset="0x0"/>
|
<Version Pattern="(ntsc|pal)-.*">
|
||||||
<Texture Name="gTitleZeldaShieldLogoTex" Format="rgba32" Width="160" Height="160" Offset="0x300"/>
|
<Texture Name="gTitleDiskTex" Format="ia8" Width="48" Height="16"/>
|
||||||
<Texture Name="gTitleCopyright1998Tex" Format="ia8" Width="128" Height="16" Offset="0x19300"/>
|
</Version>
|
||||||
<Texture Name="gTitleEffectMask00Tex" Format="i4" Width="64" Height="64" Offset="0x19B00"/>
|
<Texture Name="gTitleZeldaShieldLogoTex" Format="rgba32" Width="160" Height="160"/>
|
||||||
<Texture Name="gTitleEffectMask01Tex" Format="i4" Width="64" Height="64" Offset="0x1A300"/>
|
<Version Pattern="(ntsc|pal)-.*">
|
||||||
<Texture Name="gTitleEffectMask02Tex" Format="i4" Width="64" Height="64" Offset="0x1AB00"/>
|
<Texture Name="gTitleCopyright1998Tex" Format="ia8" Width="128" Height="16"/>
|
||||||
<Texture Name="gTitleEffectMask10Tex" Format="i4" Width="64" Height="64" Offset="0x1B300"/>
|
</Version>
|
||||||
<Texture Name="gTitleEffectMask11Tex" Format="i4" Width="64" Height="64" Offset="0x1BB00"/>
|
<Version Pattern="gc-.*">
|
||||||
<Texture Name="gTitleEffectMask12Tex" Format="i4" Width="64" Height="64" Offset="0x1C300"/>
|
<Texture Name="gTitleCopyright19982002Tex" Format="ia8" Width="160" Height="16"/>
|
||||||
<Texture Name="gTitleEffectMask20Tex" Format="i4" Width="64" Height="64" Offset="0x1CB00"/>
|
</Version>
|
||||||
<Texture Name="gTitleEffectMask21Tex" Format="i4" Width="64" Height="64" Offset="0x1D300"/>
|
<Version Pattern="gc-eu.*|gc-jp-ce|gc-us.*">
|
||||||
<Texture Name="gTitleEffectMask22Tex" Format="i4" Width="64" Height="64" Offset="0x1DB00"/>
|
<Texture Name="gTitleCopyright19982003Tex" Format="ia8" Width="160" Height="16"/>
|
||||||
<Texture Name="gTitleFlameEffectTex" Format="i8" Width="32" Height="32" Offset="0x1E300"/>
|
</Version>
|
||||||
<Texture Name="gTitleTheLegendOfTextTex" Format="i8" Width="72" Height="8" Offset="0x1E700"/>
|
<Version Pattern="ique-cn">
|
||||||
<Texture Name="gTitleOcarinaOfTimeTMTextTex" Format="i8" Width="96" Height="8" Offset="0x1E940"/>
|
<Texture Name="gTitleCopyright19982003IQueTex" Format="ia8" Width="128" Height="32"/>
|
||||||
<Texture Name="gTitleTitleJPNTex" Format="i8" Width="128" Height="16" Offset="0x1EC40"/>
|
</Version>
|
||||||
|
<Version Pattern="gc-jp-mq">
|
||||||
|
<Texture Name="gTitleUraLogoTex" Format="rgba32" Width="40" Height="40"/>
|
||||||
|
</Version>
|
||||||
|
<Version Pattern="gc-jp.*|gc-eu|gc-us|ique-cn">
|
||||||
|
<Texture Name="gTitleDiskTex" Format="ia8" Width="48" Height="16"/>
|
||||||
|
</Version>
|
||||||
|
<Version Pattern="gc-eu-mq(-dbg)?|gc-us-mq">
|
||||||
|
<Texture Name="gTitleMasterQuestSubtitleTex" Format="rgba32" Width="128" Height="32"/>
|
||||||
|
</Version>
|
||||||
|
<Version Pattern="gc-eu-mq(-dbg)?|gc-us-mq">
|
||||||
|
<Texture Name="gTitleUraLogoTex" Format="rgba32" Width="40" Height="40"/>
|
||||||
|
<Texture Name="gTitleDiskTex" Format="ia8" Width="48" Height="16"/>
|
||||||
|
</Version>
|
||||||
|
<Texture Name="gTitleEffectMask00Tex" Format="i4" Width="64" Height="64"/>
|
||||||
|
<Texture Name="gTitleEffectMask01Tex" Format="i4" Width="64" Height="64"/>
|
||||||
|
<Texture Name="gTitleEffectMask02Tex" Format="i4" Width="64" Height="64"/>
|
||||||
|
<Texture Name="gTitleEffectMask10Tex" Format="i4" Width="64" Height="64"/>
|
||||||
|
<Texture Name="gTitleEffectMask11Tex" Format="i4" Width="64" Height="64"/>
|
||||||
|
<Texture Name="gTitleEffectMask12Tex" Format="i4" Width="64" Height="64"/>
|
||||||
|
<Texture Name="gTitleEffectMask20Tex" Format="i4" Width="64" Height="64"/>
|
||||||
|
<Texture Name="gTitleEffectMask21Tex" Format="i4" Width="64" Height="64"/>
|
||||||
|
<Texture Name="gTitleEffectMask22Tex" Format="i4" Width="64" Height="64"/>
|
||||||
|
<Texture Name="gTitleFlameEffectTex" Format="i8" Width="32" Height="32"/>
|
||||||
|
<Texture Name="gTitleTheLegendOfTextTex" Format="i8" Width="72" Height="8"/>
|
||||||
|
<Texture Name="gTitleOcarinaOfTimeTMTextTex" Format="i8" Width="96" Height="8"/>
|
||||||
|
<Version Pattern="(ntsc|pal)-.*|gc-.*">
|
||||||
|
<Texture Name="gTitleTitleJPNTex" Format="i8" Width="128" Height="16"/>
|
||||||
|
</Version>
|
||||||
|
<Version Pattern="ique-cn">
|
||||||
|
<Texture Name="gTitleTitleCHNTex" Format="i8" Width="128" Height="16"/>
|
||||||
|
</Version>
|
||||||
</File>
|
</File>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -522,7 +522,7 @@ assets:
|
||||||
- name: objects/object_ma2
|
- name: objects/object_ma2
|
||||||
xml_path: assets/xml/objects/object_ma2.xml
|
xml_path: assets/xml/objects/object_ma2.xml
|
||||||
- name: objects/object_mag
|
- name: objects/object_mag
|
||||||
xml_path: assets/xml/objects/object_mag_v3_mq.xml
|
xml_path: assets/xml/objects/object_mag.xml
|
||||||
- name: objects/object_mamenoki
|
- name: objects/object_mamenoki
|
||||||
xml_path: assets/xml/objects/object_mamenoki.xml
|
xml_path: assets/xml/objects/object_mamenoki.xml
|
||||||
- name: objects/object_mastergolon
|
- name: objects/object_mastergolon
|
||||||
|
|
|
@ -514,7 +514,7 @@ assets:
|
||||||
- name: objects/object_ma2
|
- name: objects/object_ma2
|
||||||
xml_path: assets/xml/objects/object_ma2.xml
|
xml_path: assets/xml/objects/object_ma2.xml
|
||||||
- name: objects/object_mag
|
- name: objects/object_mag
|
||||||
xml_path: assets/xml/objects/object_mag_v3_mq.xml
|
xml_path: assets/xml/objects/object_mag.xml
|
||||||
- name: objects/object_mamenoki
|
- name: objects/object_mamenoki
|
||||||
xml_path: assets/xml/objects/object_mamenoki.xml
|
xml_path: assets/xml/objects/object_mamenoki.xml
|
||||||
- name: objects/object_mastergolon
|
- name: objects/object_mastergolon
|
||||||
|
|
|
@ -514,7 +514,7 @@ assets:
|
||||||
- name: objects/object_ma2
|
- name: objects/object_ma2
|
||||||
xml_path: assets/xml/objects/object_ma2.xml
|
xml_path: assets/xml/objects/object_ma2.xml
|
||||||
- name: objects/object_mag
|
- name: objects/object_mag
|
||||||
xml_path: assets/xml/objects/object_mag_v3.xml
|
xml_path: assets/xml/objects/object_mag.xml
|
||||||
- name: objects/object_mamenoki
|
- name: objects/object_mamenoki
|
||||||
xml_path: assets/xml/objects/object_mamenoki.xml
|
xml_path: assets/xml/objects/object_mamenoki.xml
|
||||||
- name: objects/object_mastergolon
|
- name: objects/object_mastergolon
|
||||||
|
|
|
@ -513,7 +513,7 @@ assets:
|
||||||
- name: objects/object_ma2
|
- name: objects/object_ma2
|
||||||
xml_path: assets/xml/objects/object_ma2.xml
|
xml_path: assets/xml/objects/object_ma2.xml
|
||||||
- name: objects/object_mag
|
- name: objects/object_mag
|
||||||
xml_path: assets/xml/objects/object_mag_v3.xml
|
xml_path: assets/xml/objects/object_mag.xml
|
||||||
- name: objects/object_mamenoki
|
- name: objects/object_mamenoki
|
||||||
xml_path: assets/xml/objects/object_mamenoki.xml
|
xml_path: assets/xml/objects/object_mamenoki.xml
|
||||||
- name: objects/object_mastergolon
|
- name: objects/object_mastergolon
|
||||||
|
|
|
@ -513,7 +513,7 @@ assets:
|
||||||
- name: objects/object_ma2
|
- name: objects/object_ma2
|
||||||
xml_path: assets/xml/objects/object_ma2.xml
|
xml_path: assets/xml/objects/object_ma2.xml
|
||||||
- name: objects/object_mag
|
- name: objects/object_mag
|
||||||
xml_path: assets/xml/objects/object_mag_v2_mq.xml
|
xml_path: assets/xml/objects/object_mag.xml
|
||||||
- name: objects/object_mamenoki
|
- name: objects/object_mamenoki
|
||||||
xml_path: assets/xml/objects/object_mamenoki.xml
|
xml_path: assets/xml/objects/object_mamenoki.xml
|
||||||
- name: objects/object_mastergolon
|
- name: objects/object_mastergolon
|
||||||
|
|
|
@ -513,7 +513,7 @@ assets:
|
||||||
- name: objects/object_ma2
|
- name: objects/object_ma2
|
||||||
xml_path: assets/xml/objects/object_ma2.xml
|
xml_path: assets/xml/objects/object_ma2.xml
|
||||||
- name: objects/object_mag
|
- name: objects/object_mag
|
||||||
xml_path: assets/xml/objects/object_mag_v2.xml
|
xml_path: assets/xml/objects/object_mag.xml
|
||||||
- name: objects/object_mamenoki
|
- name: objects/object_mamenoki
|
||||||
xml_path: assets/xml/objects/object_mamenoki.xml
|
xml_path: assets/xml/objects/object_mamenoki.xml
|
||||||
- name: objects/object_mastergolon
|
- name: objects/object_mastergolon
|
||||||
|
|
|
@ -513,7 +513,7 @@ assets:
|
||||||
- name: objects/object_ma2
|
- name: objects/object_ma2
|
||||||
xml_path: assets/xml/objects/object_ma2.xml
|
xml_path: assets/xml/objects/object_ma2.xml
|
||||||
- name: objects/object_mag
|
- name: objects/object_mag
|
||||||
xml_path: assets/xml/objects/object_mag_v3_mq.xml
|
xml_path: assets/xml/objects/object_mag.xml
|
||||||
- name: objects/object_mamenoki
|
- name: objects/object_mamenoki
|
||||||
xml_path: assets/xml/objects/object_mamenoki.xml
|
xml_path: assets/xml/objects/object_mamenoki.xml
|
||||||
- name: objects/object_mastergolon
|
- name: objects/object_mastergolon
|
||||||
|
|
|
@ -513,7 +513,7 @@ assets:
|
||||||
- name: objects/object_ma2
|
- name: objects/object_ma2
|
||||||
xml_path: assets/xml/objects/object_ma2.xml
|
xml_path: assets/xml/objects/object_ma2.xml
|
||||||
- name: objects/object_mag
|
- name: objects/object_mag
|
||||||
xml_path: assets/xml/objects/object_mag_v3.xml
|
xml_path: assets/xml/objects/object_mag.xml
|
||||||
- name: objects/object_mamenoki
|
- name: objects/object_mamenoki
|
||||||
xml_path: assets/xml/objects/object_mamenoki.xml
|
xml_path: assets/xml/objects/object_mamenoki.xml
|
||||||
- name: objects/object_mastergolon
|
- name: objects/object_mastergolon
|
||||||
|
|
|
@ -513,7 +513,7 @@ assets:
|
||||||
- name: objects/object_ma2
|
- name: objects/object_ma2
|
||||||
xml_path: assets/xml/objects/object_ma2.xml
|
xml_path: assets/xml/objects/object_ma2.xml
|
||||||
- name: objects/object_mag
|
- name: objects/object_mag
|
||||||
xml_path: assets/xml/objects/object_mag_ique.xml
|
xml_path: assets/xml/objects/object_mag.xml
|
||||||
- name: objects/object_mamenoki
|
- name: objects/object_mamenoki
|
||||||
xml_path: assets/xml/objects/object_mamenoki.xml
|
xml_path: assets/xml/objects/object_mamenoki.xml
|
||||||
- name: objects/object_mastergolon
|
- name: objects/object_mastergolon
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# SPDX-FileCopyrightText: © 2025 ZeldaRET
|
# SPDX-FileCopyrightText: © 2025 ZeldaRET
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
import argparse
|
||||||
from pprint import pprint as vanilla_pprint
|
from pprint import pprint as vanilla_pprint
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -14,17 +15,37 @@ from . import base
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
vc = version_config.load_version_config("gc-eu-mq-dbg")
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--version", "-v", default="gc-eu-mq-dbg")
|
||||||
|
parser.add_argument("--all", action="store_true")
|
||||||
|
parser.add_argument("-s", dest="single", default=None)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if not args.all and args.single is None:
|
||||||
|
parser.error("Must specify --all or -s")
|
||||||
|
|
||||||
|
vc = version_config.load_version_config(args.version)
|
||||||
|
|
||||||
pools = base.get_resources_desc(vc)
|
pools = base.get_resources_desc(vc)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for pool in pools:
|
for pool in pools:
|
||||||
|
if not args.all and not any(
|
||||||
|
coll.backing_memory.name == args.single
|
||||||
|
for coll in pool.collections
|
||||||
|
if isinstance(coll.backing_memory, base.BaseromFileBackingMemory)
|
||||||
|
):
|
||||||
|
continue
|
||||||
if any(coll.out_path.name == "gameplay_keep" for coll in pool.collections):
|
if any(coll.out_path.name == "gameplay_keep" for coll in pool.collections):
|
||||||
vanilla_pprint(pool)
|
vanilla_pprint(pool)
|
||||||
else:
|
else:
|
||||||
pprint(pool)
|
pprint(pool)
|
||||||
input("Press enter for next pool")
|
for coll in pool.collections:
|
||||||
|
print(coll.out_path)
|
||||||
|
for res in coll.resources:
|
||||||
|
print(f"0x{res.offset:06X}", res.symbol_name)
|
||||||
|
if args.all:
|
||||||
|
input("Press enter for next pool")
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
@ -27,6 +28,10 @@ class NoBackingMemory(BackingMemory):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceHasNoSizeError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# eq=False so this uses id-based equality and hashing
|
# eq=False so this uses id-based equality and hashing
|
||||||
# Subclasses must also be made to use id-based equality and hashing
|
# Subclasses must also be made to use id-based equality and hashing
|
||||||
@dataclasses.dataclass(eq=False)
|
@dataclasses.dataclass(eq=False)
|
||||||
|
@ -43,6 +48,9 @@ class ResourceDesc(abc.ABC):
|
||||||
|
|
||||||
hack_modes: set[str] = dataclasses.field(init=False, default_factory=set)
|
hack_modes: set[str] = dataclasses.field(init=False, default_factory=set)
|
||||||
|
|
||||||
|
def get_size(self) -> int:
|
||||||
|
raise ResourceHasNoSizeError()
|
||||||
|
|
||||||
|
|
||||||
class StartAddress(abc.ABC):
|
class StartAddress(abc.ABC):
|
||||||
pass
|
pass
|
||||||
|
@ -197,6 +205,15 @@ def get_resources_desc(vc: version_config.VersionConfig):
|
||||||
return pools
|
return pools
|
||||||
|
|
||||||
|
|
||||||
|
def _get_version_resources(fileelem: ElementTree.Element, version: str):
|
||||||
|
for reselem in fileelem:
|
||||||
|
if reselem.tag == "Version":
|
||||||
|
if re.fullmatch(reselem.attrib["Pattern"], version):
|
||||||
|
yield from reselem
|
||||||
|
else:
|
||||||
|
yield reselem
|
||||||
|
|
||||||
|
|
||||||
def _get_resources_fileelem_to_resourcescollection_pass1(
|
def _get_resources_fileelem_to_resourcescollection_pass1(
|
||||||
vc: version_config.VersionConfig,
|
vc: version_config.VersionConfig,
|
||||||
pool: list[AssetConfigPiece],
|
pool: list[AssetConfigPiece],
|
||||||
|
@ -257,10 +274,21 @@ def _get_resources_fileelem_to_resourcescollection_pass1(
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
needs_pass2_exceptions: list[ResourceHandlerNeedsPass2Exception] = []
|
needs_pass2_exceptions: list[ResourceHandlerNeedsPass2Exception] = []
|
||||||
for reselem in fileelem:
|
|
||||||
|
prev_resource_end_offset = 0
|
||||||
|
|
||||||
|
for reselem in _get_version_resources(fileelem, vc.version):
|
||||||
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:
|
||||||
|
if prev_resource_end_offset is None:
|
||||||
|
raise Exception(
|
||||||
|
f"Resource {symbol_name} has no Offset"
|
||||||
|
" and previous resource has no known end offset"
|
||||||
|
)
|
||||||
|
offset = prev_resource_end_offset
|
||||||
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)
|
||||||
|
@ -269,6 +297,10 @@ def _get_resources_fileelem_to_resourcescollection_pass1(
|
||||||
needs_pass2_exceptions.append(needs_pass2_exc)
|
needs_pass2_exceptions.append(needs_pass2_exc)
|
||||||
assert isinstance(res, ResourceDesc)
|
assert isinstance(res, ResourceDesc)
|
||||||
resources.append(res)
|
resources.append(res)
|
||||||
|
try:
|
||||||
|
prev_resource_end_offset = res.offset + res.get_size()
|
||||||
|
except ResourceHasNoSizeError:
|
||||||
|
prev_resource_end_offset = None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Error with resource element:\n"
|
"Error with resource element:\n"
|
||||||
|
|
|
@ -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]
|
||||||
|
@ -126,6 +126,9 @@ class TextureResourceDesc(ResourceDesc):
|
||||||
width: int
|
width: int
|
||||||
height: int
|
height: int
|
||||||
|
|
||||||
|
def get_size(self):
|
||||||
|
return self.width * self.height * self.format.siz.bpp // 8
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(eq=False)
|
@dataclasses.dataclass(eq=False)
|
||||||
class CITextureResourceDesc(TextureResourceDesc):
|
class CITextureResourceDesc(TextureResourceDesc):
|
||||||
|
@ -137,9 +140,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 +173,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 +197,6 @@ def handler_Texture(
|
||||||
reselem,
|
reselem,
|
||||||
{
|
{
|
||||||
"Name",
|
"Name",
|
||||||
"Offset",
|
|
||||||
"Format",
|
"Format",
|
||||||
"Width",
|
"Width",
|
||||||
"Height",
|
"Height",
|
||||||
|
@ -201,7 +204,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 +232,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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue