Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

avm2: Use actual ShowFrame tag count instead of header for most things #16730

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Aaron1011
Copy link
Member

@Aaron1011 Aaron1011 commented Jun 15, 2024

Some SWFS have 2 frames, but only declare 1 frames in the SWF header. This PR allows those swfs to advance to the next frame (either normally or via a goto).


if is_root && !swf.is_empty() {
let mut reader = swf.read_from(0);
let _ = tag_utils::decode_tags(&mut reader, tag_callback);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean we have to decode all the SWF tags twice now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but the actual decoding work here is just repeatedly reading tag codes and lengths. Also, it's only done for root clips.

frame.min(max(mc.frames_loaded_ignore_header(), 0) as FrameNumber)
} else {
// Sanity; let's make sure we don't seek way too far.
frame.min(max(mc.frames_loaded(), 0) as FrameNumber)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean gotos in AVM1 that go past the frames in the header are clamped? I made a small test and AVM1 also seems to ignore the header frame count in FP.

@torokati44
Copy link
Member

Possibly distantly related: #6144 and #2705.

@adrian17
Copy link
Collaborator

adrian17 commented Jun 21, 2024

Just for completeness, as researched on Discord, this doesn't feel correct; as in: in FP, I can observe that the playhead doesn't stop at the last ShowFrame, but instead it actually processes tags until the last one, and only then it either loops or stops (but it doesn't treat it as a real "frame"). Ways to observe it:

  • with DoABC2 and looping (the tag runs, the script initializer runs; I assume that the "script initializer queue" is executed after the loop reaches the first ShowFrame, because the script does not visibly run with a manual gotoAndStop(), just with a loop)
  • with a control tag like RemoveObject2 past the last ShowFrame. The requested DO actually gets destroyed, even if after calling .gotoAndStop(), the .currentFrame looks as-if the playhead stopped on the last "real" ShowFrame. (I don't know whether the "playhead pointer" actually stopped at the EOF, or rolled back to the last "real frame". Might be possible to somehow observe it by repeatedly calling .gotoAndStop(past_the_end) and looking for some observable side effects)
  • I wasn't able to observe this with PlaceObject; maybe it's possible with a more complex test, but I don't really know yet :( Maybe it just figures out that the DO is to die anyway and doesn't actually instantiate it; or all the DO AVM2 constructors are delayed until ShowFrame (which doesn't exist here)... needs futher research

Also, intuitively, the count-in-advance logic would interact badly with possible async download implementation. The way FP works does make sense if you think of the playhead as not knowing anything about the bytestream in advance and just parsing tags until either a ShowFrame or EOF.
(and just personally, I'm not a fan of parsing tags twice ;) )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants