Giter VIP home page Giter VIP logo

ruffle's Introduction

Ruffle

Rust Build Status Web Build Status Ruffle npm Ruffle AUR Ruffle Discord Ruffle translations
website | demo | nightly builds | wiki

Ruffle

Ruffle is an Adobe Flash Player emulator written in the Rust programming language. Ruffle targets both the desktop and the web using WebAssembly.

Table of Contents

Project status

Ruffle supports ActionScript 1, 2 and 3 pretty well, but it's still not finished by any means. Please report any issues in the Issue Tracker.

Using Ruffle

The easiest way to try out Ruffle is to visit the web demo page, then click the "Select File" button to load a SWF file of your choice.

Nightly builds of Ruffle are available for desktop and web platforms.

For more detailed instructions, see our wiki page.

Building from source

Prerequisites

  • Latest stable channel of Rust
  • Java, available on your PATH as java (required for building the library containing the builtin Flash classes for ActionScript 3)

Linux prerequisites

The following are typical dependencies for Linux:

  • libasound2-dev
  • libxcb-shape0-dev
  • libxcb-xfixes0-dev
  • libgtk-3-dev
  • libudev-dev
  • libxcb-xinput-dev
  • libxcb-xkb-dev
  • libxcb-cursor-dev
  • default-jre-headless
  • cmake
  • g++

Desktop

Build

Use the following command to build and run the desktop app:

cargo run --release --package=ruffle_desktop

To run a specific SWF file, pass the SWF path as an argument:

cargo run --release --package=ruffle_desktop -- test.swf

To build in debug mode, simply omit --release from the command.

macOS

Ruffle desktop can be built from our Homebrew Tap:

brew install --HEAD ruffle-rs/ruffle/ruffle

Note: because it is HEAD-only, you'll need to run brew upgrade --fetch-HEAD ruffle each time you want to update.

Web or Extension

Follow the instructions in the web directory for building either the web or browser extension version of Ruffle.

This project is tested with BrowserStack.

Android

Follow the instructions in the ruffle-android project for building the Android application of Ruffle.

Scanner

If you have a collection of "real world" SWFs to test against, the scanner may be used to benchmark ruffle's parsing capabilities. Provided with a folder and an output filename, it will attempt to read all of the Flash files and report on the success of such a task.

cargo run --release --package=ruffle_scanner -- folder/with/swfs/ results.csv

Exporter

If you have a SWF file and would like to capture an image of it, you may use the exporter tool. This currently requires hardware acceleration, but can be run headless (with no window).

  • cargo run --release --package=exporter -- path/to/file.swf
  • cargo run --release --package=exporter -- path/to/file.swf path/to/screenshots --frames 5

Structure

  • core - core emulator and common code
  • swf - SWF and ActionScript parser
  • desktop - desktop client (uses wgpu-rs)
  • web - web client and browser extension (uses wasm-bindgen)
  • render - various rendering backends for both desktop and web
  • video - video decoding backends
  • flv - Flash Video decoder
  • wstr - a Flash-compatible implementation of strings
  • scanner - a utility to bulk parse SWF files
  • exporter - a utility to generate PNG screenshots of a SWF file

Sponsors

You can support the development of Ruffle via GitHub Sponsors. Your sponsorship will help to ensure the accessibility of Flash content for the future. Thank you!

Sincere thanks to the diamond level sponsors of Ruffle:

Newgrounds.com CPMStar Sébastien Bénard Crazy Games Cool Math Games The New York Times Armor Games Onda Educa TwoPlayerGames.org wowgame.jp Matt Roszak Doll Divine Movavi Kongregate Bubble Shooter Neopets

License

Ruffle is licensed under either of

at your option.

Ruffle depends on third-party libraries under compatible licenses. See LICENSE.md for full information.

Contributing

Ruffle welcomes contribution from everyone. See CONTRIBUTING.md for help getting started.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions.

The entire Ruffle community, including the chat room and GitHub project, is expected to abide by the Code of Conduct that the Rust project itself follows.

ruffle's People

Contributors

aaron1011 avatar adrian17 avatar bale001 avatar crowdin-bot avatar cub3d avatar danielhjacobs avatar dependabot-preview[bot] avatar dependabot[bot] avatar dinnerbone avatar evilpie avatar flawake avatar herschel avatar iwannabethedev avatar jmckiern avatar justincb avatar kjarosh avatar kmeisthax avatar korne127 avatar kukininj avatar lord-mcsweeney avatar midgleyc avatar moulins avatar mrcheeze avatar n0samu avatar paq avatar relrelb avatar renovate[bot] avatar sleepycatcoding avatar toad06 avatar torokati44 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ruffle's Issues

Add AVM1 execution order tests

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:

  • Order of parent vs. newly placed/removed child (this affects the order!)
  • Order when parent calling child.gotoAndStop
  • Order when child calling parent.gotoAndStop
  • etc.

Dynamic/editable text tracking issue

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).

Funding

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.

Developer documentation

It would be nice to have basic developer documentation with information required to work on ruffle.

  • Is ruffle using rustfmt
  • 1-2 sentence high level modules (core, desktop, web, swf-rs)
  • The kinds of test suits and how to run them
  • Useful documents describing flash player, probably the the SWF spec, later AVM2 document. What are the latest versions and where to get them. Any other documents.
  • Useful tools for analyzing swf files third party flash dissembler/decompiler or some kind of dump command in ruffle or swf-rs, tool for creating test swf files or anything else that helps making, testing or debugging ruffle.

Terminology: Emulator vs. virtual machine vs. runtime?

I wasn't sure what to use as the primary "official" terminology for the project:

  • Emulator
    • Behaves like a different system
    • Implies archival + documentation of an outdated platform
    • But implies emulating actual, physical hardware
  • Virtual machine
    • Used to describe other platform-independent runtimes as Java and the AVM itself
    • Not based on physical hardware
    • But implies a single component of the overall runtime (AVM vs. Flash as a whole)
    • Overloaded term, often means system virtualization (e.g. VirtualBox)
  • Runtime
    • Emphasizes the code as a whole that is necessary to run a Flash file

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 😄)

Movie clips are incorrectly destroyed when rewinding the timeline

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.

mik

today is a nice day
everything will be just nice
enjoy the sun

with ❤️
k

Investigate Pathfinder for rendering

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.

Allow JavaScript API to load via URL

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).

Seams between fills in canvas renderer

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):

image
(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.

Audio tracking issue

  • Audio codecs
    • Raw PCM
    • ADPCM
    • MP3
    • Speex
    • Nellymoser
  • Event sounds
    • Event sounds
      • Event
      • Start
      • Stop
      • Loops
      • Sound envelopes
  • Stream sounds
    • Play
    • Sync with timeline
    • Sync multiple stream sounds?
  • ActionScript sounds
    • Start/stop
    • Position info
    • Panning

mik

mik it will be ok
we love you and care for you
you did a cool thing

with ❤️
k

Investigate best way to render in canvas backend

The current rendering method in the HTML5 canvas backend:

  • Convert the Flash vector art to an SVG string.
    • Color/gradient fills get converted to their SVG equivalent.
    • Bitmap fills get turned into a base64-encoded data URI inside an SVG pattern.
  • Make an img element, and set the source to a data URI of the URL-enocded SVG.
  • Use context.drawImage to draw the image to the canvas.

Other possibilities:

  • Create an in-memory canvas for each SWF shape, and draw the shape using the canvas drawing API. Draw the shape's canvas to the main canvas when rendering the shape.
  • Use DOMParser to parse the SVG string into a true SVG DOM element, and then draw that.
  • Construct the SVG DOM by hand using the createElement etc. JS APIs.

These could all be benchmarked and tested to see which is the best.

DisplayObject blend mode tracking issue

Desktop:

  • Normal
  • Layer
  • Add
  • Alpha
  • Darken
  • Difference
  • Erase
  • Hardlight
  • Invert
  • Lighten
  • Multiply
  • Overlay
  • Screen
  • Subtract
  • Shader (Pixel Bender)

Web canvas:

  • Normal
  • Layer
  • Add
  • Alpha
  • Darken
  • Difference
  • Erase
  • Hardlight
  • Invert
  • Lighten
  • Multiply
  • Overlay
  • Screen
  • Subtract
  • Shader (Pixel Bender)

ActionScript:

  • DisplayObject.blendMode
  • DisplayObject.blendShader

Gradients with more than 8 colors cause a crash

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.

ActionScript tracking issue

  • AVM1 (ActionScript 1.0/2.0)
    • Flash Player 4 actions
      • Decoding
      • Slash syntax
      • gotoAndPlay/Stop
      • Buttons
    • ActionScript 1.0/2.0
  • AVM2 (ActionScript 3.0)

Switch to webgpu-rs for rendering backend

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.

Support PNG/GIF data in DefineBitsJPEG tags

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

FSCommand tracking issue

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.

mik's beard

mik your beard is bright
and gingery and luscious
how did this happen

with ❤️
k

Bitmap fills should honor the smoothing and repeat properties

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.

Display object instances should be assigned instance names if none are provided

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.

Pure Rust MP3/Speex/Nellymoser decoders

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.

What SWFs do we use for testing?

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.

Support streaming download and playback of SWFs

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.

  • ifFrameIsLoaded (Flash 4)
  • framesLoaded (AVM1)
  • getBytesLoaded (AVM1)
  • loaderInfo.bytesLoaded (AVM2)
  • Network simulator

Firefox incorrectly renders additive alpha in color transforms

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:
image

Correct Chrome rendering:
image

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.

Various minor graphical issues

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.

hyaku2
Above is how the text is supposed to be rendered, as seen in Chrome.

hyaku1
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.

hyaku3

hyaku4

Add play button for web backend

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.

math::tests::test_tan failing (OSX)

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

mik

do you like bright days
and being outside in the sun
please wear sunblock k

with ❤️
k

mik

do you like the fog
covering the earth wholly
still wear sunblock please

with ❤️
k

AS2/AS3 support

Does is support AS2/AS3 and what features of it (full support/partial support)?

mik

austin is a hot
place how can you survive i
hope you ate some bbq

with ❤️
k

AVM1 error: Expected Number, found String(...)

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")

Avoid allocations and copies in SWF parsing

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:

  • DefineSprite returning a Vec of tags (better to return an iterator of tags)
  • DefineShape always reads the entire Shape (better to return an iterator that returns shape records)
  • Various bitmap tags and binary blobs copying into 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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.