# Ruffle

Ship Flash (SWF) games to Wavedash — the platform wraps them in Ruffle and handles SDK init.

Source: https://docs.wavedash.com/engines/ruffle

<GithubLink href="https://github.com/wvdsh/examples/tree/main/example-ruffle" />
<PlaytestLink href="https://wavedash.com/playtest/ruffle-example/e0ee2f1a-39ee-4259-8df7-cc1eeb903a26" />

[Ruffle](https://ruffle.rs/) is an open-source Flash Player emulator written in Rust. Wavedash has first-class support for Ruffle: upload your `.swf`, point `wavedash.toml` at it, and the platform wraps the SWF in Ruffle automatically. You don't need to bundle the Ruffle runtime or write any SDK code in your Flash game.

## Upload your SWF

1. Put your compiled `.swf` file in your upload directory (e.g. `build/game.swf`).
2. In `wavedash.toml`, add a `[ruffle]` section pointing at the file:

```toml
game_id = "YOUR_GAME_ID_HERE"
upload_dir = "./build"

[ruffle]
version = "0.2.0-nightly.2026.2.24"
executable = "game.swf"
```

3. Run `wavedash dev` to test locally. When ready to ship, [upload your build](/publishing/upload) and publish it from the Developer Portal.

## Ruffle version

`version` pins the Ruffle nightly the platform loads for you. Check [ruffle.rs/builds](https://ruffle.rs/downloads) for available builds. The platform tracks the `@ruffle-rs/ruffle` npm package versions (nightly builds formatted as `0.2.0-nightly.YYYY.M.D`).

## SDK integration

None required in your SWF. The platform runs the SDK init automatically — `Wavedash.updateLoadProgressZeroToOne(...)` is called while the Ruffle runtime downloads and your SWF loads, then `Wavedash.loadComplete()` fires once the SWF is ready to play.

If you want to call the SDK from ActionScript, use `ExternalInterface.call(...)`:

```actionscript
import flash.external.ExternalInterface;

if (ExternalInterface.available) {
    ExternalInterface.call("Wavedash.setAchievement", "first_win", true);
}
```

## Custom loader script

If you need to run JavaScript before your SWF starts — for example, to set up save-data bridges, attach Ruffle player event listeners, or register `ExternalInterface` hooks — add a `loader_url`:

```toml
[ruffle]
version = "0.2.0-nightly.2026.2.24"
executable = "game.swf"
loader_url = "loader.js"
```

Place `loader.js` in your upload directory alongside the SWF. It runs after the Ruffle runtime is ready and the player element exists, but before `player.load()` is called for your SWF. At that point both `window.Wavedash` and `window.rufflePlayer` (the [`RufflePlayer`](https://github.com/ruffle-rs/ruffle/wiki/Using-Ruffle#javascript-api) Web Component) are available, so the loader is the right place to attach event listeners, register `ExternalInterface` bridges, or hook save-data persistence:

```javascript
// build/loader.js
window.rufflePlayer.addEventListener("loadeddata", () => {
    console.log("SWF ready");
});
```

The platform owns the Ruffle load config (`autoplay`, `letterbox`, `allowScriptAccess`, etc.) and you can't override those defaults from the loader.

<Note>
The Ruffle runtime is loaded from [jsDelivr](https://www.jsdelivr.com/) — the platform doesn't host its own copy. First-time loads fetch from the CDN, then the browser caches the wasm for subsequent plays.
</Note>
