Skip to content
Daniel Jacobs edited this page Mar 4, 2024 · 29 revisions

Note: This document has not been significantly updated since 2020 and does not represent the current state of the project. For AVM2 status, see: https://ruffle.rs/compatibility

Motivation

The Flash Player has existed since 1996, and there are millions of pieces of Flash content around the web. This content represents an important piece of computing history and culture. Unfortunately, as browser support has faded, this history is no longer easily accessible. This will become even worse as the Flash Player has reached end of life.

Ruffle's chief goal is to preserve this legacy content and keep it accessible for the future. Ruffle is an Adobe Flash Player emulator written in the Rust programming language, compiling both to the desktop and to the web.

Ruffle has 4 goals, roughly in order of priority:

  1. Ease of Use: SWF content should remain easily accessible. Ruffle's HTML5 client is a first-class citizen, allowing the playback of SWFs without external software, even on mobile.
  2. Compatibility: Strive to acceptably display the wide range of SWF content available on the web.
  3. Accuracy: Behave as close to the original Flash Player as possible.
  4. Speed: The content should run full-speed.

In-browser emulation is the best way to accomplish these goals:

  • Manual conversion to modern platforms is time-consuming and simply not possible given the vast amount of SWF content.
  • Automatic conversion is possible, but still requires user intervention. Ideally users can run the SWF content directly without a conversion process.
  • Desktop players and plug-ins have the best performance, but most users do not want to install extra software. Ruffle offers a desktop player, but the primary focus is on the web client.
  • Accurate emulation of the majority of SWF content is possible given the current state of web APIs.
  • WebAssembly has opened the door for better performance in the browser.

Rust was chosen as the programming language because:

  • Rust is a systems programming language, giving the tools and performance necessary for emulation.
  • Rust is the best way to target WebAssembly. Rust considers WebAssembly a primary platform, allowing Ruffle to run in the browser with high speed.
  • Rust has a thriving community, which is key for attracting contributors.
  • Rust has a large focus on memory safety, avoiding bugs and easing traditional concerns about the security of Flash content.

There have been existing efforts to re-implement the Flash Player, including Gnash, Shumway, and Lightspark. Of these, only Lightspark is still maintained. Porting one of the existing C++ projects to Web using Emscripten is another path forward, and, in fact, may be the fastest way to getting a large amount of content running quickly. This project's goal is a fresh start in a modern codebase with the web as a primary platform.

Milestones

At a glance:

Feature % Complete
AVM1 ~90
AVM2 ~60
AS1/2 API ~60
AS3 API ~25

This is meant to give a rough estimation of where the project is currently at from a birds-eye view. Development for Ruffle is not necessarily linear and therefore you may notice a few milestones being worked on in parallel. For a more detailed overview of what is being worked on please refer to the issues tracking page. Active pull requests sometimes also reflect the real-time development status of some particular features.

✅ = done/basic support
⏳ = currently in progress


  • Initial proof-of-concept
    • Status: Complete
    • Estimated time: 2 months
    • Core Features:
      • First display of animations and SWF content ✅
      • Basic animations and test movies ✅
      • Initial audio output ✅
      • Functionality both on the desktop and the web ✅
    • Example SWFs:
  • Interactivity and basic ActionScript 1.0/2.0
    • Status: In Progress, nearly done
    • Estimated time: 3 months
    • Core Features:
      • Interaction (play buttons, keyboard, mouse) ✅
      • V-Cam ✅
      • Preloaders (support streaming download of the SWF) ⏳
    • Example SWFs:
  • Full ActionScript 1.0/2.0
  • Initial ActionScript 3.0
    • Status: Initial Research Phase
    • Estimated time: 4 months
    • Core Features:
      • Execution of AVM2 bytecode (ABC)
      • Implementation of key AS3 APIs (DisplayObject, MovieClip, EventListener, etc.)
    • Example SWFs:

Rendering

Ruffle supports/could support multiple rendering backends:

  • GPU rendering via tessellation using lyon. This is the current method used in the Ruffle desktop player.
  • GPU rendering using the WebGL API. This is the current default method used by the web player.
  • Rendering using the Canvas API. The vector art is converted to SVG and drawn onto an HTML Canvas element. This is currently used as a fallback in the web player, in case WebGL is not supported, is blocked, or has an error. There are some innate issues with SVG rendering, such as visible seams between paths.
  • Pure software rendering. It would be good to have a pure software renderer for reference. Ideally, this could be a pixel-perfect match to the official Flash Player renderer, which may be necessary for 100% accuracy in some cases.

Audio

Flash has support for many codecs, including:

  • Raw PCM
  • Adaptive PCM
  • MP3
  • Nellymoser
  • Speex

The vast majority of content uses MP3, but some content may use the more exotic codecs. Pure Rust decoders will have to be implemented to support all of these formats.

Research will have to be done to decide the best way to play back audio on web. It may be worthwhile to jump directly to using AudioWorklet.

ActionScript VM

Executing ActionScript is key to preserving most Flash content. In 2006, the Flash Player forked into two different ActionScript VMs, AVM1 (ActionScript 1.0/2.0) and AVM2 (ActionScript 3.0). These both must be supported independently.

A simple interpreter would be built initially, and this is probably enough to run most SWF content at full speed. However, the official Flash Player uses a JIT compiler for AVM2 content. Implementing a JIT compiler would be an open area of research for the future (could we use something like cranelift? Is it possible to JIT code directly to WebAssembly for the web client?)

Quality of Life features

New features could be added to improve the playback of legacy SWF content:

  • Touch and gamepad support for legacy content before AS3 APIs existed
  • Rebindable keyboard config
  • Fixes for site-locked and http <-> https cross-origin problems (URLs could dynamically be swapped out by the player)
  • Full-screen support for all content
  • Save states

Advanced features

The Flash Player is a 20-year-old piece of technology, and accrued some sophisticated features by the end of its life. Some of these features may be difficult to implement and will require research.

Haxe-generated SWFs

Haxe is a popular programming language that was used to cross-compile to AS2/AS3. Haxe-generated SWFs perform many tricks to inject the Haxe standard library functionality (for example, adding properties to the prototype of core Flash objects). Very accurate emulation of the AVM1 and AVM2 will be necessary to support these files. Additionally, some Haxe frameworks like HaxeFlixel use other advanced features such as Stage3D.

Pixel Bender

Adobe toyed with making their own shader language called Pixel Bender. The Flash Player had support for applying custom filters to movie clips using Pixel Bender. Notably, this was used by Closure. The Flash Player ran this code on the CPU using a JIT compiler.

Stage3D

Adobe provided true support for GPU rendering with the Stage3D API. This was a platform-independent API that provided access to GPU rendering and used their own shader language, AGAL. It may be possible to translate this directly to OpenGL/WebGL. A transpiler would have to convert AGAL bytecode to whatever shader language/bytecode the rendering backend uses. Notably, this was used by Starling (and some versions of HaxeFlixel?)

Alchemy/FlashCC/Crossbridge

In the early days of LLVM, Adobe provided a toolkit called Alchemy (now called Crossbridge) to cross-compile C code to AS3 bytecode. This involved some special fast-memory opcodes added to the AVM2 virtual machine. Implementing these bytecodes should be the only step needed to support Alchemy content. Notably used by Flash Doom Triple Pack.