Class Vaadoom

java.lang.Object
com.vaadin.flow.component.Component
org.vaadin.addons.enverhaase.vaadoom.Vaadoom
All Implemented Interfaces:
com.vaadin.flow.component.AttachNotifier, com.vaadin.flow.component.DetachNotifier, com.vaadin.flow.component.HasElement, com.vaadin.flow.component.HasSize, com.vaadin.flow.component.HasStyle, Serializable

@Tag("vaadoom-viewport") @JsModule("./vaadoom-viewport.js") public class Vaadoom extends com.vaadin.flow.component.Component implements com.vaadin.flow.component.HasSize
Vaadoom — a Flow component that renders a DOOM viewport.

DOOM runs inside a NOMMU Linux which itself runs on Adrian Cable's single-instruction SUBLEQ virtual machine, compiled to WebAssembly and driven from a Web Worker. The worker paints the emulated framebuffer onto an OffscreenCanvas inside the <vaadoom-viewport> custom element.

The IWAD

The game data comes from a WAD the browser fetches at start-up:
add(new Vaadoom(Vaadoom.SHAREWARE_WAD));
SHAREWARE_WAD is id Software's freely redistributable shareware doom1.wad (episode 1, "Knee-Deep in the Dead"). Any other IWAD works too: the engine reads the lump directory and presents the file to DOOM under the name that selects the matching game mode (doom2.wad, doomu.wad, doom.wad, doom1.wad), so the full games play as they should.

Where those full IWADs come from is up to you. The commercial WADs are not freely redistributable and this add-on deliberately ships no links to copies of them — if you own DOOM, The Ultimate DOOM, DOOM II or Final DOOM, put the .wad from your own copy on your own server and pass that URL. Serving it from your own Vaadin application needs no CORS setup at all; a cross-origin URL must send Access-Control-Allow-Origin, since the worker uses fetch().

The WAD is handed to the guest through a host-file device: the bytes stay in the host's memory and are copied straight into guest RAM on demand, so the (slow) emulated CPU never moves the file itself. If the fetch fails, DOOM falls back to the shareware WAD contained in the boot image.

Playing

The DOOM framebuffer is 800×512. By default the component is sized to those pixels; use HasSize.setWidth(String) / HasSize.setHeight(String) (from HasSize) to scale the viewport.

The engine boots a NOMMU Linux and launches fbdoom; first paint takes ~15 seconds (a loading overlay is shown meanwhile). It is playable: when the component has focus it forwards keyboard input to DOOM (arrows move, Ctrl fires, Space uses, Alt strafes, 1–7 select weapons). Disable input with setPlayable(boolean). Sound effects are played through the Web Audio API (see setSound(boolean)); the browser only starts them once the user has interacted with the page.

Needs a browser with OffscreenCanvas, WebAssembly and DecompressionStream; no cross-origin-isolation (COOP/COEP) headers are required (input is delivered between VM slices, without SharedArrayBuffer).

See Also:
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    Native height, in pixels, of the DOOM framebuffer.
    static final int
    Native width, in pixels, of the DOOM framebuffer.
    static final String
    id Software's shareware doom1.wad (v1.9, 4,196,020 bytes) on the Internet Archive, served with CORS headers.
  • Constructor Summary

    Constructors
    Constructor
    Description
    Creates a Vaadoom viewport that plays the shareware WAD bundled in the boot image (no download).
    Vaadoom(String wadUrl)
    Creates a Vaadoom viewport that plays the WAD at the given URL, sized to the native DOOM framebuffer (800×512).
  • Method Summary

    Modifier and Type
    Method
    Description
    double
     
     
    boolean
     
    boolean
     
    boolean
     
    void
    setAutostart(boolean autostart)
    Whether the emulator starts automatically when the component is attached.
    void
    setMusicGain(double gain)
    Playback gain applied to the OPL3 music stream, defaulting to 0.6.
    void
    setPlayable(boolean playable)
    Whether keyboard input is enabled (the viewport becomes focusable and forwards key events to DOOM).
    void
    setSound(boolean sound)
    Whether DOOM's sound effects are played.
    void
    setWadUrl(String wadUrl)
    Sets the URL of the WAD to fetch and play.

    Methods inherited from class com.vaadin.flow.component.Component

    addListener, bindVisible, findAncestor, fireEvent, from, get, getChildren, getElement, getEventBus, getId, getListeners, getLocale, getParent, getTestId, getTranslation, getTranslation, getTranslation, getTranslation, getTranslation, getTranslation, getUI, hasListener, isAttached, isTemplateMapped, isVisible, onAttach, onDetach, onEnabledStateChanged, removeFromParent, scrollIntoView, scrollIntoView, set, setElement, setId, setTestId, setVisible

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface com.vaadin.flow.component.AttachNotifier

    addAttachListener

    Methods inherited from interface com.vaadin.flow.component.DetachNotifier

    addDetachListener

    Methods inherited from interface com.vaadin.flow.component.HasSize

    bindHeight, bindWidth, getHeight, getHeightUnit, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getWidth, getWidthUnit, setHeight, setHeight, setHeightFull, setMaxHeight, setMaxHeight, setMaxWidth, setMaxWidth, setMinHeight, setMinHeight, setMinWidth, setMinWidth, setSizeFull, setSizeUndefined, setWidth, setWidth, setWidthFull

    Methods inherited from interface com.vaadin.flow.component.HasStyle

    addClassName, addClassNames, bindClassName, bindClassNames, getClassName, getClassNames, getStyle, hasClassName, removeClassName, removeClassNames, setClassName, setClassName
  • Field Details

    • FB_WIDTH

      public static final int FB_WIDTH
      Native width, in pixels, of the DOOM framebuffer.
      See Also:
    • FB_HEIGHT

      public static final int FB_HEIGHT
      Native height, in pixels, of the DOOM framebuffer.
      See Also:
    • SHAREWARE_WAD

      public static final String SHAREWARE_WAD
      id Software's shareware doom1.wad (v1.9, 4,196,020 bytes) on the Internet Archive, served with CORS headers. This is the episode id Software released for free distribution, so it is the one this add-on points at.
      See Also:
  • Constructor Details

    • Vaadoom

      public Vaadoom(String wadUrl)
      Creates a Vaadoom viewport that plays the WAD at the given URL, sized to the native DOOM framebuffer (800×512).
      Parameters:
      wadUrl - URL of the IWAD to play, e.g. SHAREWARE_WAD, or a WAD you host yourself; null to use the shareware WAD bundled in the boot image. Cross-origin URLs must allow CORS.
    • Vaadoom

      public Vaadoom()
      Creates a Vaadoom viewport that plays the shareware WAD bundled in the boot image (no download). Equivalent to new Vaadoom(null).
  • Method Details

    • setWadUrl

      public void setWadUrl(String wadUrl)
      Sets the URL of the WAD to fetch and play. Takes effect on the next attach.
      Parameters:
      wadUrl - URL of the IWAD, or null for the bundled shareware WAD
    • getWadUrl

      public String getWadUrl()
      Returns:
      the WAD URL, or null if the bundled shareware WAD is used
    • setAutostart

      public void setAutostart(boolean autostart)
      Whether the emulator starts automatically when the component is attached. Defaults to true.
      Parameters:
      autostart - true to start on attach
    • isAutostart

      public boolean isAutostart()
      Returns:
      whether the emulator starts automatically on attach
    • setPlayable

      public void setPlayable(boolean playable)
      Whether keyboard input is enabled (the viewport becomes focusable and forwards key events to DOOM). Defaults to true. Input works without any cross-origin-isolation headers.
      Parameters:
      playable - true to enable keyboard control
    • isPlayable

      public boolean isPlayable()
      Returns:
      whether keyboard input is enabled
    • setSound

      public void setSound(boolean sound)
      Whether DOOM's sound effects are played. Defaults to true. The guest produces PCM frames which the VM's sound card hands to the page's AudioContext; browsers keep that context suspended until the user interacts with the page, so the first sounds arrive after the first click.
      Parameters:
      sound - true to play sound effects
    • isSound

      public boolean isSound()
      Returns:
      whether sound effects are played
    • setMusicGain

      public void setMusicGain(double gain)
      Playback gain applied to the OPL3 music stream, defaulting to 0.6.

      Music plays continuously where sound effects are sparse, so at equal gain it dominates: measured on the shareware WAD, the effects average −38 dBFS against the music's −28.5 dBFS. The default attenuates the music to sit under them. Both streams then pass a limiter just below full scale, so raising this cannot make the mix clip — only louder.

      Parameters:
      gain - linear gain for the music stream (1 = as the chip emits it)
    • getMusicGain

      public double getMusicGain()
      Returns:
      the playback gain applied to the music stream