Added in Bizhawk 2.11
Might as well stop being completely useless and finally run Doom.
The core ported for this is DSDA-Doom, which focuses on speedrunning and compatibility for vanilla and modern features.

Loading files

The only supported extension is .WAD, which may contain an IWAD or a PWAD inside. All IWADs can be launched directly (including chex.wad and rekkrsa.wad, which are IWADs in terms of contents but erroneously have PWAD headers). To run PWADs you need to load them alongside IWADs they're made for.
Doom 2 PWADs can be launched directly if you have doom2.wad as a firmware. Everything else requires a Multi-Disk Bundler XML file:
  1. Load the base IWAD
  2. Go to Tools -> Multi-disk Bundler to create a .xml and name it as you like
  3. Add all the required .WAD files to the list (drag'n'drop works). Order doesn't matter, BizHawk will automatically detect which of them is an IWAD and which is PWAD.
  4. Launch that .xml file in BizHawk.
Example of contents:
<BizHawk-XMLGame System="Doom" Name="btsx">
  <LoadAssets>
    <Asset FileName=".\doom2.wad" />
    <Asset FileName=".\btsx_e1a.wad" />
    <Asset FileName=".\btsx_e1b.wad" />
  </LoadAssets>
</BizHawk-XMLGame>
Information about the loaded files can be seen by clicking the icon in the bottom right corner of the BizHawk window (dump status report).

Configuration

Bizhawk always runs Doom in a demo recording mode, so you don't have access to startup screen or menu: it launches straight into the game. Initial level (and episode, among other things) can be specified in Doom -> Settings -> Sync Settings menu.
Default settings are configured to be as close to vanilla Doom as possible, but useful modern features are also available: increased internal resolution, secret reveal notice, all sorts of heads-up-displays, etc.
For maximum immersion you can capture mouse so its pointer is hidden and expand Bizhawk to fullscreen, using the corresponding hotkeys.

Controls

Doom demo files store movement as analog axes (vertical movement, horizontal movement, turning), XDRE and DSDA-Doom's input display shows positive and negative speed (which defines direction) as 2 separate positive axes, but Bizhawk shows them both combined and signed.
Relative (raw) mouse input has to be mapped to mouse controls: RMouse Y to mouse running and RMouse X to mouse turning. That allows us to manipulate mouse movement to make it feel authentic, because the original game did that (as well as source ports). Direct access to run and turn speeds is only for precise editing, like in TAStudio.
Default binds for key-based turning look reversed: Q is Turn Right and E is Turn Left. But real-time players bind them that way to make "strafe50" feasible. Since "strafe50" requires pressing Forward, Directional Strafe, Turn, and Strafe Modifier keys all at once, the most practical way to press that combo is Q+W+D or A+W+E with the left hand and Strafe Modifier with the right hand. If turn direction keys weren't reversed, one would have to press A+Q+W for strafe50 to the left, which is too hard to do quickly and reliably.

Turning

Normally Doom demos reduce actual turning resolution (2-byte signed) to just the higher byte. At some point, an option to use full turning resolution in demos was added to some source ports, so Bizhawk has that option too.
Note that Doom counts angle values counterclockwise, so positive turn value turns you left, and negative turns you right. This can be tracked on the in-built coordinate display.
Since editing a 2-byte value in TAStudio would be a nightmare, Bizhawk splits longtic turning value into 2 values: higher byte (whole angle values) and lower byte (fractional angle values). Higher byte equals the shorttic angle input, therefore its range is [-128, 127] (sign indicates turning direction).
Lower byte has somewhat counter-intuitive range of [-255, 255]. Of course when the final value is composed and sent to the core, lower byte is actually only a value between 0 and 255. However for movie editing purposes, negative range is allowed so that "sub-angle" turning could be done in both directions. Without this feature, it'd be impossible to turn by -0.1 or -0.255, because sign would only be available for the higher byte and you can't set it to -0.
The ultimate value that's sent to the core is high_byte * 256 + low_byte. If the 2 values have different signs, low_byte is subtracted from high_byte, so the final turn value is reduced.

Walking camera

Camera movement can be controlled separately from the player, by using the Camera Mode values:
Camera movement speed is not limited to player movement speed, only to a signed 32-bit integer. That allows jumping across the entire map in one frame. DSDA-Doom's walking camera can only walk, not fly, but ours lets you fully control height, it won't snap to floor at all.

Audio

In order to make it work inside the Waterbox environment we had to remove all SDL2 from the code, which resulted in inability to load MIDI soundfonts or pre-recorded music. The only option currently is OPL3.

Movies

The core aims to be fully compatible with Doom demo files (.LMP), and those that can run on vanilla Doom can be imported into Bizhawk and automatically converted into .bk2 format. Newer formats (Boom and above) can be imported, but their options are not passed to the core aside from RNG seed, and they may desync.
.LMP export is planned in the future, but can already be implemented in Lua.
Wipe/melt effect screen is automatically disabled for imported movies, because Doom doesn't process inputs during it but does render frames. In Bizhawk those 2 concepts can't be separated: for some frame to be rendered it has to be an input frame too, but demo files don't have those extra blank frames in them.
If you want wipe to appear in your imported movie, you sill need to enable it in SyncSettings inside the movie file and then to add empty inputs on lag frames that represent wipe duration. Keep in mind that wide duration may change depending on resolution, tho differences for higher resolutions are not drastic and may not be there.

Memory domains

Doom source ports are not emulators, so they don't have dedicated memory domains representing different internal memory regions. But we still expose internal memory of the core using the System Bus domain, as well as 4 artificial domains representing internal arrays:
All known memory addresses inside System Bus are listed in Lua/Doom/dsda/symbols.lua

Memory problems

The core is ported using Waterbox, which means all the memory that the core changes after init will be serialized to savestates to guarantee determinism. But for big WADs with hundreds of enemies in the same room this can be a problem, because when enemies are fighting and shooting projectiles, extra memory is being changed, and serialized by Waterbox. Uncompressed savestate in nuts.wad can reach several hundred megabytes in size, in bigger slaughtermaps it would be even bigger. Some of them will even crash the core because they require several gigabytes of memory to function and Waterbox limit is 4GB. And even if they don't crash, savestates being that huge makes TASing a nightmare because it's very slow (especially with TAStudio).
Internal savestates might be used at some point, but they have determinism problems.

Doom lua script

We include a lua script that attempts to combine XDRE functionality with automap basics and adds some loggers not available normally (P_Random() details, line crossing/using, intercept overflow details). Script path is Lua/Doom/doom.lua.
Features as printed by the Help button:

Bizhawk/Doom last edited by feos on 5/2/2026 7:51 AM
Page History Latest diff List referrers View Source