Hack/fix for SWFs with orphaned tags, I think this is correct?
This commit is contained in:
parent
838f151234
commit
7fd194d98b
@ -124,6 +124,7 @@ class PlacedClip(PlacedObject):
|
||||
super().__init__(object_id, depth, rotation_offset, transform, mult_color, add_color, blend, mask)
|
||||
self.placed_objects: List[PlacedObject] = []
|
||||
self.frame: int = 0
|
||||
self.unplayed_tags: List[int] = [i for i in range(len(source.tags))]
|
||||
self.__source = source
|
||||
|
||||
# Dynamic properties that are adjustable by SWF bytecode.
|
||||
@ -138,6 +139,11 @@ class PlacedClip(PlacedObject):
|
||||
if self.frame < len(self.source.frames):
|
||||
self.frame += 1
|
||||
|
||||
def rewind(self) -> None:
|
||||
self.frame = 0
|
||||
self.unplayed_tags = [i for i in range(len(self.__source.tags))]
|
||||
self.placed_objects = []
|
||||
|
||||
@property
|
||||
def finished(self) -> bool:
|
||||
return self.frame == len(self.source.frames)
|
||||
@ -954,8 +960,7 @@ class AFPRenderer(VerboseOutput):
|
||||
# during some bytecode update in this loop.
|
||||
if clip.frame > clip.requested_frame:
|
||||
# Rewind this clip to the beginning so we can replay until the requested frame.
|
||||
clip.placed_objects = []
|
||||
clip.frame = 0
|
||||
clip.rewind()
|
||||
|
||||
self.vprint(f"{prefix} Processing frame {clip.frame} on our way to frame {clip.requested_frame}")
|
||||
|
||||
@ -965,8 +970,24 @@ class AFPRenderer(VerboseOutput):
|
||||
# Execute each tag in the frame if we need to move forward to a new frame.
|
||||
if clip.frame != clip.requested_frame:
|
||||
frame = clip.source.frames[clip.frame]
|
||||
tags = clip.source.tags[frame.start_tag_offset:(frame.start_tag_offset + frame.num_tags)]
|
||||
orphans: List[Tag] = []
|
||||
played_tags: Set[int] = set()
|
||||
|
||||
# See if we have any orphans that need to be placed before this frame will work.
|
||||
for unplayed_tag in clip.unplayed_tags:
|
||||
if unplayed_tag < frame.start_tag_offset:
|
||||
self.vprint(f"{prefix} Including orphaned tag {unplayed_tag} in frame evaluation")
|
||||
played_tags.add(unplayed_tag)
|
||||
orphans.append(clip.source.tags[unplayed_tag])
|
||||
|
||||
for tagno in range(frame.start_tag_offset, frame.start_tag_offset + frame.num_tags):
|
||||
played_tags.add(tagno)
|
||||
|
||||
# Check these off our future todo list.
|
||||
clip.unplayed_tags = [t for t in clip.unplayed_tags if t not in played_tags]
|
||||
|
||||
# Grab the normal list of tags, add to the orphans.
|
||||
tags = orphans + clip.source.tags[frame.start_tag_offset:(frame.start_tag_offset + frame.num_tags)]
|
||||
for tagno, tag in enumerate(tags):
|
||||
# Perform the action of this tag.
|
||||
self.vprint(f"{prefix} Sprite Tag ID: {clip.source.tag_id}, Current Tag: {frame.start_tag_offset + tagno}, Num Tags: {frame.num_tags}")
|
||||
|
@ -956,7 +956,7 @@ class SWF(TrackedCoverage, VerboseOutput):
|
||||
size: int,
|
||||
dataoffset: int,
|
||||
tag_parent_sprite: Optional[int],
|
||||
tag_frame: int,
|
||||
tag_frame: str,
|
||||
prefix: str = "",
|
||||
) -> Tag:
|
||||
if tagid == AP2Tag.AP2_SHAPE:
|
||||
@ -1021,7 +1021,7 @@ class SWF(TrackedCoverage, VerboseOutput):
|
||||
return AP2DefineFontTag(font_id, fontname, xml_prefix, heights, text_indexes)
|
||||
elif tagid == AP2Tag.AP2_DO_ACTION:
|
||||
datachunk = ap2data[dataoffset:(dataoffset + size)]
|
||||
bytecode = self.__parse_bytecode(f"on_enter_{f'sprite_{tag_parent_sprite}' if tag_parent_sprite is not None else 'main'}_frame_{tag_frame}", datachunk, prefix=prefix)
|
||||
bytecode = self.__parse_bytecode(f"on_enter_{f'sprite_{tag_parent_sprite}' if tag_parent_sprite is not None else 'main'}_{tag_frame}", datachunk, prefix=prefix)
|
||||
self.add_coverage(dataoffset, size)
|
||||
|
||||
return AP2DoActionTag(bytecode)
|
||||
@ -1941,7 +1941,7 @@ class SWF(TrackedCoverage, VerboseOutput):
|
||||
|
||||
# First, parse frames.
|
||||
frames: List[Frame] = []
|
||||
tag_to_frame: Dict[int, int] = {}
|
||||
tag_to_frame: Dict[int, str] = {}
|
||||
self.vprint(f"{prefix}Number of Frames: {frame_count}")
|
||||
for i in range(frame_count):
|
||||
frame_info = struct.unpack("<I", ap2data[frame_offset:(frame_offset + 4)])[0]
|
||||
@ -1955,7 +1955,7 @@ class SWF(TrackedCoverage, VerboseOutput):
|
||||
for j in range(num_tags_to_play):
|
||||
if start_tag_offset + j in tag_to_frame:
|
||||
raise Exception("Logic error!")
|
||||
tag_to_frame[start_tag_offset + j] = i
|
||||
tag_to_frame[start_tag_offset + j] = f"frame_{i}"
|
||||
frame_offset += 4
|
||||
|
||||
# Now, parse regular tags.
|
||||
@ -1972,7 +1972,7 @@ class SWF(TrackedCoverage, VerboseOutput):
|
||||
raise Exception(f"Invalid tag size {size} ({hex(size)})")
|
||||
|
||||
self.vprint(f"{prefix} Tag: {hex(tagid)} ({AP2Tag.tag_to_name(tagid)}), Size: {hex(size)}, Offset: {hex(tags_offset + 4)}")
|
||||
tags.append(self.__parse_tag(ap2_version, afp_version, ap2data, tagid, size, tags_offset + 4, sprite, tag_to_frame[i], prefix=prefix))
|
||||
tags.append(self.__parse_tag(ap2_version, afp_version, ap2data, tagid, size, tags_offset + 4, sprite, tag_to_frame.get(i, 'orphan'), prefix=prefix))
|
||||
tags_offset += ((size + 3) & 0xFFFFFFFC) + 4 # Skip past tag header and data, rounding to the nearest 4 bytes.
|
||||
|
||||
# Finally, parse frame labels
|
||||
|
Loading…
x
Reference in New Issue
Block a user