ruffle-rs / ruffle

A Flash Player emulator written in Rust
https://ruffle.rs
Other
15.76k stars 820 forks source link

SpongeBob's Bumper Subs freezes Ruffle right as gameplay starts #1086

Closed WumboSpasm closed 4 years ago

WumboSpasm commented 4 years ago

https://www.nick.com/games/data/spongebob/sb_bumpersub/bumper.swf

After you select a character, the desktop window / browser tab freezes about half a second into the game (and on desktop you can't even close the window, you have to close the command prompt to shut it down). For clarity, the shape hit test PR doesn't fix the problem.

Running through the debug executable didn't give any warnings.

Herschel commented 4 years ago

Occurs because some opcodes gets executed with an incorrect SWF version. The game is SWFv5, but a bug causes function calls to run with SWF ver of 32. This makes the Less2 op return undefined instead of false, causing an infinite loop.

Offending code is in avm1/function.rs:

let effective_ver = if activation.current_swf_version() > 5 {
                    af.swf_version()
                } else {
                    this.as_display_object()
                        .map(|dn| dn.swf_version())
                        .unwrap_or(activation.context.player_version)
                };

DisplayObject::swf_version tries to grab self.parent.swf_version(), which seems to be umimplemented everywhere and defaults to returning NEWEST_PLAYER_VERSION. 1) If the > v5 check is necessary, we need to ensure that DisplayObject::swf_version returns a proper value. Seems like we forgot to override this method for MovieClip. 2) It seems dangerous for DisplayObject::swf_version to default to NEWEST_PLAYER_VERSION. It should default to the version in the SWF header, or return an Option with None. But maybe this is moot when the function actually returns a proper value.

Sample SWF showing the problem (Ruffle traces undefined, should trace false): lt.zip