ruffle-rs / ruffle Goto Github PK
View Code? Open in Web Editor NEWA Flash Player emulator written in Rust
Home Page: https://ruffle.rs
License: Other
A Flash Player emulator written in Rust
Home Page: https://ruffle.rs
License: Other
If you watch the Swivel'd version of Synj vs Horrid, at the 1:09 mark you see Synj running through the jungle. His post is static but his body shakes violently as it tweens across the screen.
https://www.newgrounds.com/portal/view/79158
In Ruffle, Synj's body tweens across the screen but isn't shaking. Something about that shaking body movieclip may be unusual.
If an instance name is not provided to a MovieClip, Button, or other interactive object, the Flash Player automatically assigns one of the form "instanceN
", where N is an increasing index starting at 1. The index is global across the entire SWF file. This is done at the runtime level and not stored in the SWF PlaceObject.
Hi,
I encounter a error below.
[2019-09-03T04:38:16Z ERROR ruffle_core::avm1] AVM1 error: Expected Number, found String("4")
[2019-09-03T04:38:16Z ERROR ruffle_core::avm1] AVM1 error: Expected Number, found String("4")
Does is support AS2/AS3 and what features of it (full support/partial support)?
Run hand-crafted SWFs through official Flash Player and Ruffle and compare the trace output. In particular, we need to figure out the order of execution for scripts when many display objects are interacting.
A simple example would be having a parent and a child clip, each tracing a string on frame 1, and verify that the order is accurate.
More examples:
child.gotoAndStop
parent.gotoAndStop
Animations in the web backend should not auto-play. Instead, a play button should be displayed, and the user must click to start playback. This is necessary for audio to work due to auto-play rules in browsers.
Since it's a core component of Ruffle, the swf-rs repo should be moved to the Ruffle organization.
This is a tracking issue for improvements to the example/test page for the web frontend:
https://github.com/ruffle-rs/ruffle/blob/master/web/packages/demo/www/index.html
In The Final Task (https://www.newgrounds.com/portal/view/7549), the opening text that says "flash animation" renders incorrectly on both web and destkop.
The API could be use a more streaming approach to avoid copying and allocations.
Currently a user can use Reader::read_tag
to manually step through the SWF, but there are still many allocations while reading the individual tags:
Vec
of tags (better to return an iterator of tags)Vec<u8>
(better to return a slice of input data)Ideally the above can be avoided while still keeping the API simple for the common use-cases.
Add simple instructions (either in README or the wiki) on how to build and use the web frontend without a bundler, using simple <script>
tags. It can be based on the instructions in the Rust Wasm book.
Hi,
I was checking AVM1 functionality. I am getting below error,
SWF file: https://drive.google.com/file/d/14cn4VqL2KyISsMtmU7rk42WPQ6_Ayps8/view?usp=sharing
Browser: Firefox 68
OS: Windows 10
Currently the JavaScript API accepts a Uint8Array of the SWF data to load, requiring the user to fetch the data manually. This was because I didn't want to deal with JS futures/promises in wasm-bindgen while it was not stable. Now that this has stabilized, the API should take in the URL as a string and fetch the content itself. This is also necessary to support streaming downloads (#18).
I know this has been tested on that historic dog flash animation on Newgrounds (whose name I forgot so I can't find it), but would it be a good idea to put some of these test files in the repo? They could be a collection of ones that have specific features, some that work, and some that don't yet. That would make it really easy for a new contributor to take on a specific new feature and have a real test case to be working towards.
Or would that bloat the size of the repo? Perhaps we could put a list of links then in the README or wiki? @Herschel what do you think?
I tried it on my oldest favorite animation (https://www.newgrounds.com/portal/view/454086) and got:
Fatal error:
Couldn't find any pixel format that matches the criteria.
Currently expected since most actionscript is not working, but basic interpretation of the member access operator (.) and things like "this" and "_root" may offer a lot of coverage in terms of getting more .swf content to play correctly. Included is a .swf that relies on:
on(release){ this.nextFrame(); }
to start
"temple.swf"
https://www.newgrounds.com/dump/item/5f5cb1f6499f562d69b3f13bd0f35799
today is a nice day
everything will be just nice
enjoy the sun
with ❤️
k
I started with glium just to get something up and running quickly, but ideally we'd use gfx-rs for the rendering backend on desktop platforms. wasm support also just landed in gfx-rs thanks to glow, so maybe this backend could also be used on web.
edit 4-25: Instead of gfx-rs, we could use webgpu-rs, which will soon have browser support, and is a better level of abstraction for us.
austin is a hot
place how can you survive i
hope you ate some bbq
with ❤️
k
fecb981 added color-interpolation-filters="sRGB"
to the feColorMatrixFilter
to correct colors on Firefox. However, this attribute makes Firefox incorrectly render color transforms with an additive alpha component. See the Firefox rendering of synj vs. horrid 1 here:
This seems to be some Firefox issue involving filters doing sRGB interpolation and possibly converting to/from premultiplied alpha? The zero alpha pixels end up having alpha and color. This also occurs when I tried the feComponentTransfer
filter instead. The issue goes away if you remove color-interpolation-filters
, but then the colors aren't correct.
mik it will be ok
we love you and care for you
you did a cool thing
with ❤️
k
Safari does not support CanvasRenderingContext2d.filter
which is used to render the color transforms on display objects. I tried a few tricks such as putting the filter directly on the image element, but no luck.
Not sure how to solve this one. Either we find a better, fast way to apply color transforms on all browsers, or we add a potentially slower workaround for Safari.
Each bitmap fill has flags that determine whether it is smoothed (bilinear filtered) or repeated/clamped. Currently both desktop and web don't honor these flags, so all bitmaps will appear filtered, which is particularly bad for pixel art/sprite animations.
I wasn't sure what to use as the primary "official" terminology for the project:
I chose "emulator" to place the emphasis on the archival+documentation of a legacy platform, and to set expectations that it will probably not be completely accurate. But I don't feel strongly one way or another. So I figure I'd open this up to discussion in case anyone has opinions (and to head off any potential flame wars 😄)
The Pathfinder crate by pcwalton allows very high-quality rendering of vector shapes using shaders as opposed to tessellation. It'd be great to integrate this as a backend, at least for desktop, but possibly for WebGL as well.
Desktop:
Web canvas:
ActionScript:
DisplayObject.blendMode
DisplayObject.blendShader
In the flash animation Hyakugojyuuichi!!!, the opening text renders wrong in Firefox on Windows 10. I've also tested it in Chrome and the desktop player, and it renders as it would in Flash.
Above is how the text is supposed to be rendered, as seen in Chrome.
This is the same text as seen in Firefox.
I've also noticed that in the same animation, gaps appear between sliced images where there were none in Flash. (This happens in both Chrome and Firefox.) Also, some text that's yellow with a black outline in Flash is entirely white in Ruffle.
Due to the method of anti-aliasing in most SVG renderers, shared edges will appear to have seams in the canvas render backend. "Conflation artifacts" are the technical term for these.
Example (Ruffle canvas backend on top, Flash on bottom):
(Also see #24)
The standard advice to avoid this is to overlap the paths, e.g. an outline fill should appear on top of the fill underneath it. But Flash almost always generates non-overlapping paths to avoid overdraw.
I'm not sure there is an easy fix for this beyond disabling AA completely with SVG properties like shape-rendering: crispEdges
. But I think this will be kind of moot, as WebGL rendering (via tessellation and/or Pathfinder) will be the long-term goal over canvas.
When gotoing an earlier frame, movieclips should not be destroyed and recreated if they exist both in the current frame and the new frame. This includes when a parent clip loops back to frame 1 when reaching the end of the timeline.
DisplayObjects should keep track of which frame they are placed on, and the goto logic needs to figure out which movieclips will still exist after the goto.
Currently the SWF is downloaded entirely before being displayed. SWF was designed to be a streaming format, so Ruffle should allow for playback to begin while downloading and decoding assets. This allows for Flash movie preloaders to work.
On web, we should use the streams API to stream the download. On desktop, we should multi-thread the file load as well as asset creation. For example, tessellation of a shape should occur asynchronously, and the shape shouldn't be considered loaded until this is done.
This will require the SWF byte stream to be access from multiple threads, so it'll need to be wrapped in an Arc
.
Additionally, we can implement a network simulator option that simulates a slow download speed, similar to the official debug Flash Player.
As a former flash-enthusiast I would like to show my appreciation for your project. I still have many flash sandboxes and tiny projects I would like to keep online when the flashplayer is ultimately deactivated in 2020. Since my knowledge of Rust is rather limited and my time is needed for other projects, I wonder if you considered a fundraiser to help you maintaining the development. I am pretty sure many people would contribute to protect a piece of good old quirky web-history.
mik your beard is bright
and gingery and luscious
how did this happen
with ❤️
k
movieClip.setMask
displayObject.mask
In desktop/src/render.rs
, the code for gradients crashes when the gradient has more than 8 colors/ratios. This code has the same issue for linear, radial, and focal gradients. As an example, here is the code for linear gradients (line 169 on master ba36435):
PathCommandType::Fill(FillStyle::LinearGradient(gradient)) => {
let mut colors = [[0.0; 4]; 8];
let mut ratios = [0.0; 8];
for (i, record) in gradient.records.iter().enumerate() {
colors[i] = [
record.color.r as f32 / 255.0,
record.color.g as f32 / 255.0,
record.color.b as f32 / 255.0,
record.color.a as f32 / 255.0,
];
ratios[i] = record.ratio as f32 / 255.0;
}
...
}
This could be fixed by converting the arrays to Vec
types.
The current rendering method in the HTML5 canvas backend:
context.drawImage
to draw the image to the canvas.Other possibilities:
DOMParser
to parse the SVG string into a true SVG DOM element, and then draw that.createElement
etc. JS APIs.These could all be benchmarked and tested to see which is the best.
Dynamic/editable text is created with the DefineEditText
tag:
SWF19 pp. 171-172
We have to figure out how to support this on various backends. To start, we can just attempt to display this tag without edit capabilities (similar to DefineText).
We need decoders for the more complex codecs (MP3, Nellymoser, Speex), ideally in pure Rust for ease of compilation on the wasm32 target.
For MP3, currently I am calling out to the decodeAudioData
web API, but this requires collecting all of the MP3 frames and decoding it entirely into memory, which is both slow and memory intensive.
do you like the fog
covering the earth wholly
still wear sunblock please
with ❤️
k
do you like bright days
and being outside in the sun
please wear sunblock k
with ❤️
k
All Your Base (https://www.newgrounds.com/portal/view/11940) crashes on load with "Character ID doesn't exist". Need to investigate why this is happening, and also change this panic into a warning.
Side effect of #54
getURL calls to fscommand are treated like regular URLs and go through a browser's regular handling and manifest as a popup leading nowhere. This is very noticeable when testing on web.
Examples:
getURL("FSCommand:trapallkeys",true)
getURL("FSCommand:showmenu","false")
In a situation where these fire repeatedly under normal conditions (such as frames looping during a preloader), they spam requests or popups using web.
Some quick googling reveals there's also a more proper accompanying function.
I have tested this test swf with swf2JS with success but no sound [pass 3 out of 4 test].
I have tested it also with MozillaShumway and it works but failed the scene change test [fail only one test].
http://www.stevenchorney.com/del/FlashSavingTestKit.html
The exact URL of the swf file is:
http://www.stevenchorney.com/del/FlashSavingTestKit.swf
This SWF completely renders incorrectly. To start, there looks to be issues with the text rendering.
http://www.stevenchorney.com/del/FlashSavingTestKit.swf
(courtesy of @BracerJack)
It would be nice to have basic developer documentation with information required to work on ruffle.
It looks like this test is failing for me;
cargo test --package=ruffle_core
[...]
failures:
---- avm1::globals::math::tests::test_tan stdout ----
thread 'avm1::globals::math::tests::test_tan' panicked at 'assertion failed: `(left == right)`
left: `Number(1.557407724654902)`,
right: `Number(1.5574077246549023)`', core/src/avm1/globals/math.rs:216:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
The test is passing fine in circleci (https://circleci.com/gh/ruffle-rs/ruffle/309) so I assume it is something specific to my setup. Dump of obvious details below. I guess my question is whether we would expect any variation based on setup or if the value needs to be exactly consistent across all environments in order to be a faithful emulation (i.e. is it a case of loosening up the test(s) slightly to check they're approx equal to 1.0e-12 or something or is it a bug that should be addressed).
cargo 1.37.0 (9edd08916 2019-08-02)
OS: osx 10.13.6
Processor: 2.9 GHz Intel Core i7
Memory: 16 GB 2133 MHz LPDDR3
Graphics: Radeon Pro 560 4096 MB, Intel HD Graphics 630 1536 MB
Text is sometimes not rendered in the correct position (I think when it has center alignment).
An example:
https://www.newgrounds.com/portal/view/7
(Missing letters are part of the animation)
According to the SWF spec, DefineBitsJPEG2+ tags also allow for PNG and GIF data (as opposed to JPEG). I wasn't sure how to convince Flash to export these variants or of any cases in the wild, so I didn't implement it.
Ego Orb on Discord was kind of enough to share an example SWF with PNG data:
281463_plus.zip
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.