1
0
mirror of synced 2024-09-24 11:28:25 +02:00

Initial RE of new tags and flags seen in some IIDX versions.

This commit is contained in:
Jennifer Taylor 2021-05-17 03:48:05 +00:00
parent ace6bd54c4
commit f2be6d2bb8

View File

@ -201,6 +201,18 @@ class AP2DefineButtonTag(Tag):
}
class AP2PlaceCameraTag(Tag):
def __init__(self) -> None:
# TODO: I need to figure out what camera placements actually DO, and take the
# values that I parsed out store them here...
super().__init__(None)
def as_dict(self, *args: Any, **kwargs: Any) -> Dict[str, Any]:
return {
**super().as_dict(*args, **kwargs),
}
class AP2DefineTextTag(Tag):
def __init__(self, id: int, lines: List[AP2TextLine]) -> None:
super().__init__(id)
@ -1017,12 +1029,22 @@ class SWF(TrackedCoverage, VerboseOutput):
datachunk = ap2data[dataoffset:(dataoffset + size)]
flags, depth, object_id = struct.unpack("<IHH", datachunk[0:8])
self.add_coverage(dataoffset, 8)
running_pointer = 8
# Make sure we grab the second half of flags as well, since this is read first for
# newer games.
if flags & 0x80000000:
more_flags = struct.unpack("<I", datachunk[running_pointer:(running_pointer + 4)])[0]
self.add_coverage(dataoffset + running_pointer, 4)
running_pointer += 4
flags = flags | (more_flags << 32)
unhandled_flags = flags & ~0x80000000
else:
unhandled_flags = flags
self.vprint(f"{prefix} Flags: {hex(flags)}, Object ID: {object_id}, Depth: {depth}")
running_pointer = 8
unhandled_flags = flags
if flags & 0x2:
# Has a shape component.
unhandled_flags &= ~0x2
@ -1267,6 +1289,18 @@ class SWF(TrackedCoverage, VerboseOutput):
rotation_offset = Point(float(x) / 20.0, float(y) / 20.0)
self.vprint(f"{prefix} Rotation Origin: {rotation_offset}")
if flags & 0x200000000:
# TODO: This might be z rotation origin? I've only seen it on files that have a place
# camera, and its setting a local value that is close to the rotation origin
# x and y constants.
unhandled_flags &= ~0x200000000
z_int = struct.unpack("<i", datachunk[running_pointer:(running_pointer + 4)])[0]
self.add_coverage(dataoffset + running_pointer, 4)
running_pointer += 4
z = float(z_int) / 20.0
self.vprint(f"{prefix} Unknown Rotation Origin Float: {z}")
if flags & 0x2000000:
# Same as above, but initializing to 0, 0 instead of from data.
unhandled_flags &= ~0x2000000
@ -1306,8 +1340,59 @@ class SWF(TrackedCoverage, VerboseOutput):
transform.c = float(c_int) / 32768.0
self.vprint(f"{prefix} Transform Matrix B: {transform.b}, C: {transform.c}")
if flags & 0x100000:
# TODO: Some unknown short.
unhandled_flags &= ~0x100000
unk_4 = struct.unpack("<H", datachunk[running_pointer:(running_pointer + 2)])[0]
self.add_coverage(dataoffset + running_pointer, 2)
running_pointer += 2
self.vprint(f"{prefix} Unk 4: {unk_4}")
# Due to possible misalignment, we need to realign.
misalignment = running_pointer & 3
if misalignment > 0:
catchup = 4 - misalignment
self.add_coverage(dataoffset + running_pointer, catchup)
running_pointer += catchup
if flags & 0x8000000:
# TODO: Some unknown float. This might be the "tz" value for a 3D matrix.
unhandled_flags &= ~0x8000000
unk_5 = struct.unpack("<i", datachunk[running_pointer:(running_pointer + 4)])[0]
self.add_coverage(dataoffset + running_pointer, 4)
running_pointer += 4
unk_5_f = unk_5 / 20.0
self.vprint(f"{prefix} Unk 5: {unk_5_f}")
if flags & 0x10000000:
# TODO: Absolutely no idea, the games that use this reuse the transform
# matrix variables but then don't put them in the same spot, so
# this might be a 3D transform matrix? Would make sense given the
# unknown float above as well as the unknown rotation origin above
# as well as the newly-discovered AP2_PLACE_CAMERA tag.
unhandled_flags &= ~0x10000000
ints = struct.unpack("<iiiiiiiii", datachunk[running_pointer:(running_pointer + 36)])
self.add_coverage(dataoffset + running_pointer, 36)
running_pointer += 36
floats = [float(i) / 1024.0 for i in ints]
self.vprint(f"{prefix} Unknown 3D Transform Matrix: {', '.join(str(f) for f in floats)}")
if flags & 0x20000000:
# TODO: Again, absolutely no idea, gets passed into a function and I
# don't see how its used.
unk_a, unk_b, unk_c = struct.unpack("<hbb", datachunk[running_pointer:(running_pointer + 4)])
self.add_coverage(dataoffset + running_pointer, 4)
running_pointer += 4
self.vprint(f"{prefix} Unknown Data: {unk_a}, {unk_b}, {unk_c}")
# This flag states whether we are creating a new object on this depth, or updating one.
unhandled_flags &= ~0xD
unhandled_flags &= ~0x400000D
if flags & 0x1:
self.vprint(f"{prefix} Update object request")
else:
@ -1320,6 +1405,10 @@ class SWF(TrackedCoverage, VerboseOutput):
self.vprint(f"{prefix} Use color information")
else:
self.vprint(f"{prefix} Ignore color information")
if flags & 0x4000000:
self.vprint(f"{prefix} Use 3D transform matrix?")
else:
self.vprint(f"{prefix} Ignore 3D transform matrix?")
if unhandled_flags != 0:
raise Exception(f"Did not handle {hex(unhandled_flags)} flag bits!")
@ -1773,6 +1862,44 @@ class SWF(TrackedCoverage, VerboseOutput):
raise Exception("TODO: Need to examine this section further if I find data with it!")
return AP2DefineButtonTag(button_id)
elif tagid == AP2Tag.AP2_PLACE_CAMERA:
flags, unk1, = struct.unpack("<HH", ap2data[dataoffset:(dataoffset + 4)])
self.add_coverage(dataoffset, 4)
running_data_ptr = dataoffset + 4
self.vprint(f"{prefix} Flags: {hex(flags)}, Unknown: {unk1}")
if flags & 1:
i1, i2, i3 = struct.unpack("<iii", ap2data[running_data_ptr:(running_data_ptr + 12)])
self.add_coverage(running_data_ptr, 12)
running_data_ptr += 12
# These appear to be camera x, y, z coordinates.
f1 = i1 / 20.0
f2 = i2 / 20.0
f3 = i3 / 20.0
self.vprint(f"{prefix} Unknown Floats: {f1}, {f2}, {f3}")
if flags & 0x2:
i4 = struct.unpack("<i", ap2data[running_data_ptr:(running_data_ptr + 4)])[0]
self.add_coverage(running_data_ptr, 4)
running_data_ptr += 4
# I have no idea what this is for. The game adds this to f3 above for
# some stored calculation.
f4 = i4 / 20.0
self.vprint(f"{prefix} Unknown Float: {f4}")
else:
# The games I've looked at will take the stored value of a previously
# parsed place camera for f4 if this is set to zero.
pass
if dataoffset + size != running_data_ptr:
raise Exception(f"Failed to parse {dataoffset + size - running_data_ptr} bytes of data!")
return AP2PlaceCameraTag()
else:
self.vprint(f"Unknown tag {hex(tagid)} with data {ap2data[dataoffset:(dataoffset + size)]!r}")
raise Exception(f"Unimplemented tag {hex(tagid)}!")