Handle newly-discovered file flags properly in GE2D structures.
This commit is contained in:
parent
afa8214ed1
commit
5ec5068916
@ -2,7 +2,7 @@ import os
|
|||||||
import struct
|
import struct
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from .types import Color, Point
|
from .types import Color, Point, Rectangle
|
||||||
from .util import descramble_text
|
from .util import descramble_text
|
||||||
|
|
||||||
|
|
||||||
@ -31,6 +31,9 @@ class Shape:
|
|||||||
# Actual shape drawing parameters.
|
# Actual shape drawing parameters.
|
||||||
self.draw_params: List[DrawParams] = []
|
self.draw_params: List[DrawParams] = []
|
||||||
|
|
||||||
|
# Bounds of the shape.
|
||||||
|
self.bounds: Rectangle = Rectangle.Empty()
|
||||||
|
|
||||||
# Whether this is parsed.
|
# Whether this is parsed.
|
||||||
self.parsed = False
|
self.parsed = False
|
||||||
|
|
||||||
@ -41,6 +44,7 @@ class Shape:
|
|||||||
'tex_points': [p.as_dict(*args, **kwargs) for p in self.tex_points],
|
'tex_points': [p.as_dict(*args, **kwargs) for p in self.tex_points],
|
||||||
'tex_colors': [c.as_dict(*args, **kwargs) for c in self.tex_colors],
|
'tex_colors': [c.as_dict(*args, **kwargs) for c in self.tex_colors],
|
||||||
'draw_params': [d.as_dict(*args, **kwargs) for d in self.draw_params],
|
'draw_params': [d.as_dict(*args, **kwargs) for d in self.draw_params],
|
||||||
|
'bounds': self.bounds.as_dict(args, kwargs),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
@ -49,6 +53,7 @@ class Shape:
|
|||||||
*[f"tex point: {tex}" for tex in self.tex_points],
|
*[f"tex point: {tex}" for tex in self.tex_points],
|
||||||
*[f"tex color: {color}" for color in self.tex_colors],
|
*[f"tex color: {color}" for color in self.tex_colors],
|
||||||
*[f"draw params: {params}" for params in self.draw_params],
|
*[f"draw params: {params}" for params in self.draw_params],
|
||||||
|
*[f"bounds: {self.bounds}"],
|
||||||
])
|
])
|
||||||
|
|
||||||
def get_until_null(self, offset: int) -> bytes:
|
def get_until_null(self, offset: int) -> bytes:
|
||||||
@ -71,14 +76,14 @@ class Shape:
|
|||||||
|
|
||||||
# There are two integers at 0x4 and 0x8 which are basically file versions.
|
# There are two integers at 0x4 and 0x8 which are basically file versions.
|
||||||
|
|
||||||
filesize = struct.unpack(f"{endian}I", self.data[12:16])[0]
|
filesize, fileflags = struct.unpack(f"{endian}II", self.data[12:20])
|
||||||
if filesize != len(self.data):
|
if filesize != len(self.data):
|
||||||
raise Exception("Unexpected file size for GE2D structure!")
|
raise Exception("Unexpected file size for GE2D structure!")
|
||||||
|
|
||||||
# There is an integer at 0x16 which always appears to be zero. It should be
|
geo_has_bounds_floats = bool(fileflags & 0x4)
|
||||||
# file flags, but I don't know what it does since no code I've found cares.
|
vertex_well_formed_rectangle = bool(fileflags & 0x8)
|
||||||
if self.data[16:20] != b"\0\0\0\0":
|
if fileflags & ~0xC:
|
||||||
raise Exception("Unhandled flag data bytes in GE2D structure!")
|
raise Exception(f"Unexpected file flags {fileflags} in GE2D structure!")
|
||||||
|
|
||||||
vertex_count, tex_count, color_count, label_count, render_params_count, _ = struct.unpack(
|
vertex_count, tex_count, color_count, label_count, render_params_count, _ = struct.unpack(
|
||||||
f"{endian}HHHHHH",
|
f"{endian}HHHHHH",
|
||||||
@ -92,6 +97,8 @@ class Shape:
|
|||||||
|
|
||||||
vertex_points: List[Point] = []
|
vertex_points: List[Point] = []
|
||||||
if vertex_offset != 0:
|
if vertex_offset != 0:
|
||||||
|
# If fileflags & 0x8 is set, these go in clockwise order starting at the top left
|
||||||
|
# point and there are only 8 of them, making a rectangle.
|
||||||
for vertexno in range(vertex_count):
|
for vertexno in range(vertex_count):
|
||||||
vertexno_offset = vertex_offset + (8 * vertexno)
|
vertexno_offset = vertex_offset + (8 * vertexno)
|
||||||
x, y = struct.unpack(f"{endian}ff", self.data[vertexno_offset:vertexno_offset + 8])
|
x, y = struct.unpack(f"{endian}ff", self.data[vertexno_offset:vertexno_offset + 8])
|
||||||
@ -129,6 +136,39 @@ class Shape:
|
|||||||
bytedata = self.get_until_null(labelptr)
|
bytedata = self.get_until_null(labelptr)
|
||||||
labels.append(descramble_text(bytedata, text_obfuscated))
|
labels.append(descramble_text(bytedata, text_obfuscated))
|
||||||
|
|
||||||
|
# Parse rectangle bounds.
|
||||||
|
if geo_has_bounds_floats:
|
||||||
|
left, right, top, bottom = struct.unpack(f"{endian}ffff", self.data[52:68])
|
||||||
|
self.bounds = Rectangle(
|
||||||
|
left=left,
|
||||||
|
right=right,
|
||||||
|
top=top,
|
||||||
|
bottom=bottom,
|
||||||
|
)
|
||||||
|
elif vertex_well_formed_rectangle:
|
||||||
|
self.bounds = Rectangle(
|
||||||
|
left=vertex_points[0].x,
|
||||||
|
right=vertex_points[1].x,
|
||||||
|
top=vertex_points[0].y,
|
||||||
|
bottom=vertex_points[2].y,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if vertex_points:
|
||||||
|
self.bounds.left = vertex_points[0].x
|
||||||
|
self.bounds.right = vertex_points[0].x
|
||||||
|
self.bounds.top = vertex_points[0].y
|
||||||
|
self.bounds.bottom = vertex_points[0].y
|
||||||
|
|
||||||
|
for pt in vertex_points:
|
||||||
|
if pt.x < self.bounds.left:
|
||||||
|
self.bounds.left = pt.x
|
||||||
|
if pt.x > self.bounds.right:
|
||||||
|
self.bounds.right = pt.x
|
||||||
|
if pt.y < self.bounds.top:
|
||||||
|
self.bounds.top = pt.y
|
||||||
|
if pt.y > self.bounds.bottom:
|
||||||
|
self.bounds.bottom = pt.y
|
||||||
|
|
||||||
draw_params: List[DrawParams] = []
|
draw_params: List[DrawParams] = []
|
||||||
if render_params_offset != 0:
|
if render_params_offset != 0:
|
||||||
# The actual render parameters for the shape. This dictates how the texture values
|
# The actual render parameters for the shape. This dictates how the texture values
|
||||||
@ -149,7 +189,7 @@ class Shape:
|
|||||||
if tex2 != 0xFF:
|
if tex2 != 0xFF:
|
||||||
raise Exception("GE2D structure requests a second texture, but we don't support this!")
|
raise Exception("GE2D structure requests a second texture, but we don't support this!")
|
||||||
if unk != 0x0:
|
if unk != 0x0:
|
||||||
raise Exception("Unhandled unknown dadta in GE2D structure!")
|
raise Exception("Unhandled unknown data in GE2D structure!")
|
||||||
|
|
||||||
color = Color(
|
color = Color(
|
||||||
a=(rgba & 0xFF) / 255.0,
|
a=(rgba & 0xFF) / 255.0,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user