Added in Bizhawk 2.11
Table of contents
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:
- Load the base IWAD
- Go to Tools -> Multi-disk Bundler to create a
.xmland name it as you like - 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.
- Launch that
.xmlfile 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.
- Note that capturing mouse may glitch out if Bizhawk is covered by another window, and contents of the latter will become clickable. To avoid that, go to Config -> Display -> Window tab, and check Mouse Capture Forces Stay on Top. That way whenever mouse is captured, Bizhawk window will be set to Topmost, which minimizes the risk of its window getting covered (however OS Start menu will still appear above it).
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.
- Note that raw mouse inputs can be recorded to movies in real time, but they can't be recorded frame by frame.
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:
-
-1is default value meaning "do nothing" and doesn't appear in HUD or TAStudio -
0resets camera mode to default and locks it to player POV -
1keeps the camera attached to player position but allows turning it freely -
2detaches camera from the player completely, allowing free movement:- Run forward/backward
- Strafe left/right
- Fly up/down
- Turn
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:
- Shows player info. If you have several players in-game you can hover on player info and scroll the mouse wheel to show info for different players.
- Shows current tic, in-game time, and RNG index along with value at that index.
- Shows Automap consisting of linedefs, sectors, and things (toggled via the 'Map' button).
- Shows blockmap grid (toggled via the 'Grid' button).
- The 'Reset View' button zooms and pans the automap to make all things visible.
- The 'Follow' button makes the camera stick to the player that is currently selected on the left panel.
- The 'Hilite' buttons enables highlight/selection mode where you can hover on sectors, linedefs, and things to see their info on the left, in corresponding colors.
- Use Mouse Wheel to zoom in and out, and mouse movement with the 'Space' key held down to pan.
- Buttons for adding things, lines, and sectors allow to track those entities. If more than one object of a given type is tracked, you can hoven on them and scroll through them with the mouse wheel. They can also be removed from the tracked list by hitting the red cross button that appears on hover.
- Tracked and highlighted entities show info similar to what XDRE shows. For linedefs, distance from the currently selected player is shown in 2 ways: "distance from line" is similar to that in XDRE, when the line is assumed to be infinite and player position is projected onto it at a right angle. "Distance from segment" assumes line to be finite and only calculates distance to the closest point of that segment regardless of the angle.
- Tracked entity lists and Automap config are saved when the script is stopped or restarted or when you add or remove tracked entities. To manually edit the config file, disable the script, edit the 'doom.settings.lua' file if it exists, then start the script again. Editing it while the script is running will overwrite your edits later. Config also stored Angle type which has no other way to change it.
- You can log which thing has used or crossed linedefs, with options being None, Player, and All
- You can log various info every time a P_Random() call happens with a class that changes the RNG value. Log prints tic count when the call happened, which call it is per that tic, the RNG index, the value at that index, and the call stack (while file and line called P_Random() within which function).
- You can display intercepts on the Automap: tracelines and blockmap blocks where intercepts happen. Red color means an intercept happened on this tic, then the color fades to grey.
- And the most complicated feature is intercept logging. It will inform you when the intercept count exceeded a user-defined limit, which is 128 by default but can be changed in config (the 'InterceptLimit' value). If the intercept count exceeded that value, a button will appear that will print info on all the intercepts, as well as info on all the vanilla addresses they corrupted, if any. Boom fixed intercept overflow, so in Boom complevel this feature is disabled.