Search documentation

Find pages, sections, and content across all docs.

WavedashDocs

js-dos

Ship DOS games to Wavedash — the platform wraps them in js-dos and handles the SDK load lifecycle.

View example project on GitHub Playtest the example project

js-dos is a DOSBox-based emulator that runs classic DOS executables in the browser via WebAssembly. Wavedash has first-class support for js-dos: upload a .jsdos bundle, point wavedash.toml at it, and the platform wraps it in the js-dos runtime automatically. No SDK code is required inside your DOS game.

Create a .jsdos bundle

A .jsdos file is a standard ZIP archive (renamed to .jsdos) that contains your DOS executable plus a .jsdos/dosbox.conf describing how to run it. The minimum layout is:

game.jsdos (zip)
├── GAME.EXE               ; or .COM / .BAT — your game
├── dosbox.conf            ; short root-level override (usually just [cpu] cycles)
└── .jsdos/
    └── dosbox.conf        ; full DOSBox config with [autoexec] that runs your game

The .jsdos/dosbox.conf needs an [autoexec] section that launches your game. A minimal working config:

[sdl]
autolock=false

[cpu]
cycles=fixed 3000

[autoexec]
GAME.EXE

Zip it up:

cd game-files && zip -r ../game.jsdos . && cd ..

The js-dos Studio has a visual tool for creating bundles from existing DOS games if you'd rather not hand-write the config.

Upload your bundle

Put game.jsdos in your upload directory, then in wavedash.toml:

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

[jsdos]
version = "v8"
executable = "game.jsdos"

Run wavedash dev to test locally. When ready to ship, upload your build and publish it from the Developer Portal.

SDK integration

None required inside the DOS game. The platform loads js-dos from a CDN, configures the emulator (kiosk mode, auto-start, aspect-preserving render), and calls Wavedash.loadComplete() as soon as js-dos is launched — before the emulator has actually booted. To wait for the real ci-ready event instead, use a custom loader script with onEvent.

The platform does not call Wavedash.init(). Without it, no SDK events are ever delivered (lobby, P2P, backend, stats, fullscreen, entitlements), P2P runs on its default settings because init() is where the p2p config is applied, and readyForEvents() and the getP2P* getters throw. Everything else on window.Wavedash works. If your game needs events, call Wavedash.init() from your onEvent handler in place of loadComplete() — init() calls loadComplete() for you.

Custom loader script

If you want to configure js-dos options yourself — render aspect, input mappings, event handlers, cloud-save wiring — add a loader_url:

[jsdos]
version = "v8"
executable = "game.jsdos"
loader_url = "loader.js"

Place loader.js in your upload directory. Set window.dosOptions to any valid js-dos options object (or a Promise resolving to one); js-dos will merge it with the platform's defaults:

// build/loader.js
window.dosOptions = {
    renderAspect: "4/3",
    onEvent: function (event, ci) {
        if (event === "ci-ready") {
            Wavedash.loadComplete();
            // Game is running; you can stash `ci` and submit scores via the SDK later.
        }
    },
};

If you override onEvent, you're responsible for calling Wavedash.loadComplete() yourself — the default loader hands that off to you.

See the js-dos v8 options for the full surface.

The js-dos runtime (including wdosbox.wasm, worker scripts, and CSS) is loaded from jsdelivr — the platform doesn't host its own copy. First-time loads fetch from the CDN, then the browser caches the wasm for subsequent plays.