Ruffle Flash Player Emulator

repository·master·Indexed 10 days ago

https://github.com/ruffle-rs/ruffle

An Adobe Flash Player emulator written in Rust that targets desktop and web platforms using WebAssembly. The project includes tools for defining native ActionScript methods in Rust, managing AVM2 globals, building Windows MSI installers via WiX Toolset, and creating Ruffle Bundles (.ruf) using the ruffle-bundle.toml specification.

Tokens
54.9K
Snippets
179
Records
272
Agent score
97%

What's inside Ruffle

  1. Use ruffle-web for websites or browser extensions

    master

    The ruffle-web project provides a WebAssembly (Wasm) version of the Ruffle Flash player. It is designed to be used in two primary ways:

    1. Self-hosted: Use the ruffle-selfhosted NPM package to embed Ruffle directly into your own website. This allows you to control how Ruffle behaves and can be configured to polyfill (automatically detect and replace) embedded Flash content.
    2. Browser Extension: Use the ruffle-extension NPM package to create a browser extension that injects the Ruffle player into websites visited by users.

    By default, Ruffle attempts to 'polyfill' embedded Flash content, making it an 'out of the box' solution for Flash compatibility. It prefers using WebGL for hardware-accelerated rendering but includes a fallback to the Canvas API for browsers or environments where WebGL is disabled.

    npm install ruffle-selfhosted
    # or
    npm install ruffle-extension
  2. Overview of Ruffle project structure

    master

    Understanding the core components of the Ruffle repository:

    • 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
  3. Understand the Ruffle fuzzing directory layout

    master

    The fuzzing directory is organized as a separate Cargo workspace. The layout is as follows:

    • fuzz_targets/: libFuzzer entry points (one .rs file per target).
    • fuzz_targets_afl/: AFL++ entry points for the same targets.
    • src/: Shared fuzzing logic used by both engines.
    • corpus/: Seed inputs used by the fuzzers, organized according to corpuses.toml.
    • corpuses.toml: A mapping file that connects each target to its specific corpus subdirectory.
    • out/, artifacts/, target/: Directories for generated output (these are git-ignored).
  4. Understand the ruffle-web project structure

    master

    The ruffle-web repository is organized into several key packages:

    • Root directory: A Cargo crate containing the actual Flash player and the root Node package.
    • packages/core: Contains the core Ruffle Web API and WebAssembly (Wasm) bindings.
    • packages/selfhosted: A package intended for websites to include Ruffle directly.
    • packages/extension: A package that turns Ruffle into a browser extension.
    • packages/demo: An example package demonstrating how to use the self-hosted version locally.
  5. How to call AS3 methods with explicit namespaces

    master

    When calling methods with an explicitly-qualified AS3 namespace (e.g., xml.AS3::appendChild(elem)), you must include the namespace declaration in your package block to ensure efficient bytecode generation.

    Required Declaration: namespace AS3 = "http://adobe.com/AS3/2006/builtin";

    Failure to include this in the package block will result in a compile-time error: Found getlex of "AS3" in method body. Make sure you have namespace AS3 = "http://adobe.com/AS3/2006/builtin"; in your package block.

    package {
        namespace AS3 = "http://adobe.com/AS3/2006/builtin";
        // ...
    }
  6. Ruffle Bundle (.ruf) Directory Structure

    master

    A valid Ruffle Bundle must follow this structure:

    • ruffle-bundle.toml: Required. Contains the bundle configuration and metadata.
    • content/: A directory containing the .swf files and any additional assets (images, XML, etc.) required by the game.

    Note: Files and subdirectories within content/ are exposed to the Flash content as a virtual filesystem using the file:/// protocol. For example, a file located at content/game.swf is accessed by the Flash content as file:///game.swf.

  7. Optimize wgpu render pass performance with binding groups

    master

    Ruffle's wgpu renderer is limited to a maximum of 4 binding groups per pipeline to maintain compatibility with GLES-3.1 minimum requirements.

    To achieve optimal performance, you should minimize group switching by following a hierarchical binding pattern. Draw as many items as possible using the same bound groups before switching to a new group. The frequency of changes should follow this order:

    1. Group 0 (Globals) should change the least frequently.
    2. Group 1 (Mesh-level) should change less frequently than Group 2.
    3. Group 2 (Texture/Material-level) should change most frequently.

    An ideal render pass follows this nested structure:

    • Set group 0
      • Set group 1
        • Set group 2
          • Draw calls
        • Set group 2 (new texture)
          • Draw calls
      • Set group 1 (new mesh)
        • Set group 2
          • Draw calls
  8. Run tests for ruffle-web

    master

    Node Tests

    Run standard unit tests using:

    npm run test

    Note: You must run npm run build before running these tests.

    Browser-Based Integration Tests

    These require a browser environment and are run via WebdriverIO. Use the following syntax:

    npm run wdio -- [arguments]

    Arguments

    • Local Browsers (must be installed locally):
      • --chrome: Run in Chrome
      • --firefox: Run in Firefox
      • --edge: Run in Edge
    • Mobile/BrowserStack:
      • --browserstack: Run on BrowserStack mobile devices. Requires BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY environment variables.
      • --oldVersions: Includes 'minimum supported desktop browsers' in the test suite.
    • General Flags:
      • --headless: Hides browser windows (recommended for CI).
      • --spec <name>: Filters tests by name (e.g., --spec external_interface).

    Debugging Tips

    If a test fails, do not use --headless. You can add await browser.pause(100000); to the test file to pause execution so you can manually inspect the browser state.

    npm run test
    # or for browser tests
    npm run wdio -- --chrome --headless
  9. Run fuzz tests to find bugs

    master

    You can search for bugs, crashes, or hangs in Ruffle by running specific fuzz targets using the cargo fuzzer helper from the repository root. This is useful for discovering edge cases in SWF parsing, ActionScript bytecode interpretation, media decoding, or regex handling.

    To run a specific target (for example, parse_swf), use the following command:

    cargo fuzzer run parse_swf

    If the fuzzer identifies a crash or a hang, it will report the count and exit with a non-zero status. Artifacts (the inputs that caused the failure) are saved to the artifacts directory for reproduction and minimization.

  10. Compile AVM2 globals

    master

    The AVM2 globals are compiled into a playerglobal_avm2.swf file.

    Prerequisites:

    • Java must be installed.

    Build Process:

    1. The core/build_playerglobal tool uses asc.jar (from the Flex SDK) to compile ActionScript files into ABC (bytecode).
    2. The produced ABC files are combined into playerglobal_avm2.swf.
    3. The core/build_playerglobal tool is automatically triggered by the core build script whenever ActionScript classes are modified.

    Note: The resulting .swf is written to the build directory and is not checked into Git.