The 1997 Linux DOOM source release (linuxdoom-1.10), ported from X11 and
/dev/dsp to raylib and made to run on 64-bit
systems. The original release notes are in README.TXT.
The software renderer is untouched: it still draws 8-bit paletted pixels into a 320x200 buffer. raylib opens the window, shows that buffer scaled to 4:3, reads the keyboard and mouse, and plays the sound effects and music.
We have releases ready to play, for the following platforms:
- Windows
- MacOS (Intel and Apple Sillicon)
- Linux (Omarchy and Ubuntu)
- Android
- Web (You can go play now the web version on https://www.raydelto.org/doom
We have tested on iOS as a local build, we currently don't provide a iOS release but you can build it yourself.
We have also confirmed that it works well on AndroidXR and Meta Quest 3.
You need a C compiler, CMake 3.16+, and raylib's system dependencies
(on Debian/Ubuntu: libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libgl1-mesa-dev libasound2-dev).
cmake -B build
cmake --build build -jCMake uses an installed raylib 5.x or 6.x if it finds one, and
otherwise downloads and builds raylib 5.5. -DRAYLIB_DOOM_FETCH_RAYLIB=OFF
turns the download off (a missing raylib is then an error), and
-DFETCHCONTENT_SOURCE_DIR_RAYLIB=DIR builds the raylib source in
DIR instead. cmake --install build --component raylibdoom installs
the game, its menu entry, icon, AppStream metadata and manual page
(-DRAYLIB_DOOM_INSTALL_BINDIR=games puts the game in games/, as
Debian does).
The original Makefile also still works if raylib is installed with pkg-config support:
cd linuxdoom-1.10
makeInstall the Xcode Command Line Tools (xcode-select --install) and
CMake (brew install cmake), then build as above. raylib uses Cocoa
and OpenGL, which ship with macOS; nothing else is needed. Works on
Apple Silicon and Intel.
The macOS release is a .dmg for Apple Silicon (macOS 11+), made by
.github/workflows/release-macos.yml with packaging/macos/make-dmg.sh.
Inside raylibDOOM.app the game looks for its IWAD in $DOOMWADDIR,
~/Library/Application Support/raylibDOOM and the folder holding the
app, saves games to that Application Support folder, and logs to
~/Library/Logs/raylibDOOM.log; see packaging/macos/README.txt.
The release app also holds the shareware DOOM1.WAD in
Contents/Resources, looked in last (see "Shareware DOOM1.WAD in the
release packages" below).
The Windows x64 release, raylibdoom-<version>-windows-x64.zip, is a
portable folder with a single statically linked raylibdoom.exe, built
by .github/workflows/release-windows.yml with
packaging/windows/make-package.sh. On Windows the game looks for
IWADs next to raylibdoom.exe when DOOMWADDIR is not set; the
release zip has the shareware DOOM1.WAD there. Started
from Explorer, it hides its console window, keeps savegames next to
the executable, and shows fatal errors in a message box.
Build with MinGW-w64 GCC, for example from w64devkit or MSYS2:
cmake -B build -G "MinGW Makefiles"
cmake --build build -jor cross-compile from Linux with a MinGW-w64 toolchain file
(CMAKE_SYSTEM_NAME Windows, CMAKE_C_COMPILER x86_64-w64-mingw32-gcc).
MSVC is not supported: the code uses C11 atomics and POSIX headers such
as <unistd.h> and <dirent.h>, which MinGW provides and MSVC does not.
Settings go to %USERPROFILE%\.doomrc when HOME is not set.
.github/workflows/release-linux.yml builds raylibdoom_<version>_amd64.deb
and raylibdoom-<version>-linux-x86_64.tar.gz on Ubuntu 22.04, and the
same for arm64 (_arm64.deb, -linux-aarch64.tar.gz) natively on
GitHub's ubuntu-22.04-arm runner, no cross-compiling or QEMU (they run
on 22.04, 24.04 and newer, including JetPack 6 on Jetson boards); the
scripts are in packaging/linux/. Pushing a v* tag uploads both
architectures to the draft release; running the workflow by hand keeps
them as an Actions artifact, and can also build an existing tag's
source (the tag input) as an artifact only, without touching that
tag's release. sudo apt install ./raylibdoom_*.deb installs
/usr/games/raylibdoom with a menu entry, and the release packages'
shareware DOOM1.WAD in /usr/share/raylibdoom (next to the binary in
the .tar.gz); sudo apt install freedoom adds free IWADs it finds
and prefers over the shareware one.
debian/ is the source package meant for Debian unstable (and from
there Ubuntu): it builds against the system libraylib-dev, has no
network access, and leaves out the shareware WAD. Instead it
recommends freedoom | doom-wad, so apt install raylibdoom brings
Freedoom and apt install raylibdoom doom-wad-shareware (Debian
non-free, Ubuntu multiverse) gets the shareware DOOM, which the game
prefers when both are installed. The orig tarball is the GitHub tag's,
repacked by uscan without the files debian/copyright lists under
Files-Excluded, hence the +ds version.
packaging/ppa/make-source.sh SERIES ORIG_TARBALL OUT_DIR makes the
same package for a Launchpad PPA on Ubuntu releases that have no
raylib 5.5+ (jammy, noble, resolute), with raylib 5.5 built in from a
second orig tarball; sign it with debsign and upload it with dput.
.github/workflows/release-arch.yml builds
raylibdoom-<version>-1-x86_64.pkg.tar.zst with
packaging/arch/PKGBUILD in an archlinux:base-devel container, and
checks it with namcap. Pushing a v* tag uploads it to the draft
release; running the workflow by hand keeps it as an Actions artifact,
unless it is given the tag of an existing draft release, which it then
builds and adds the package to. Install it with
sudo pacman -U raylibdoom-*.pkg.tar.zst: it puts /usr/bin/raylibdoom
in the app launcher, and the game finds IWADs copied to
/usr/share/games/doom (the release package's shareware DOOM1.WAD
is in /usr/share/raylibdoom). sudo pacman -R raylibdoom removes it. As
committed, the PKGBUILD builds the release tarball of its pkgver and
can go to the AUR. The Ubuntu raylibdoom-<version>-linux-x86_64.tar.gz
runs on Omarchy too, unpacked anywhere, and is the fallback for other
distributions.
Every package a v* tag releases (Windows zip, Ubuntu .deb and
.tar.gz, Arch package, macOS dmg, Android APK) includes the free
shareware DOOM1.WAD (DOOM 1.9, episode 1), unmodified, so it plays
right after install, with packaging/shareware/DOOM1-NOTICE.txt
("DOOM shareware © id Software. Not affiliated with id Software /
ZeniMax / Microsoft.", the GPL notice and a link to the source). The
WAD is never in git: each release workflow downloads it at build time
with packaging/shareware/fetch-doom1-wad.sh, which fails the job
unless it is 4,196,020 bytes with SHA-256
1d7d43be501e67d927e415e0b8f3e29c3bf33075e859721816f652a526cac771
(the URL can be overridden with the DOOM1_WAD_URL repository
variable), and packaging/shareware/check-wad-in-package.sh checks
every package for it before uploading. Pull requests, the build
workflow and manual runs stay WAD-free; a manual run with the
shareware input builds the release packages with the WAD as an
artifact, to try them before tagging.
The bundled WAD is the game's last choice: on Linux it is looked for
after $DOOMWADDIR, the current directory, -file and
/usr/share/games/doom; on macOS after $DOOMWADDIR, Application
Support and the app's folder; -iwad FILE always wins. On Windows it
sits next to raylibdoom.exe, where doom.wad or doom2.wad win over
it, and -iwad or DOOMWADDIR pick any other IWAD.
On Hyprland the game runs through XWayland. The window tiles like any
other; to float it at its own size instead, add a window rule for the
class DOOM (in Omarchy's Lua config,
o.window("DOOM", { float = true, center = true })). Alt+Enter
toggles borderless fullscreen; -fullscreen starts that way. If another
window on the workspace is fullscreen, Omarchy hands fullscreen to the
new window, so the game can open fullscreen then. While you play the
mouse is captured and the pointer hidden; in menus, when paused, and
when the window loses focus, it is released.
The game also runs in a desktop browser, built with
Emscripten and raylib's web platform. The
page bundles Freedoom: Phase 1 (freedoom1.wad, BSD licensed; its
COPYING.txt ships next to it), which CMake downloads and checks
against its SHA-256 at configure time; it is not in this repository.
Install the emsdk outside this repository (CI uses 6.0.10), then:
source /path/to/emsdk/emsdk_env.sh
emcmake cmake -B build-web
cmake --build build-web -j-DPLATFORM=Web may be given, but is implied. Add
-DFREEDOOM_ZIP=/path/to/freedoom-0.13.0.zip to use a zip you already
have instead of downloading it. build-web/ then holds
raylibdoom.html, .js, .wasm, .data (the WAD) and
freedoom-COPYING.txt; the web job in .github/workflows/build.yml
uploads the same files as the raylibdoom-web artifact.
Browsers do not load the .data file from file://, so serve the
folder over HTTP and open the page:
python3 -m http.server -d build-web 8000
# then open http://localhost:8000/raylibdoom.html
# or: emrun build-web/raylibdoom.htmlClick the page to start; that click also lets the browser start the
audio. Click again in a level to capture the mouse (Esc lets go of
it); Alt+Enter toggles fullscreen. Saved games and settings are kept
in the browser's IndexedDB, so they survive a reload. "Load your own
IWAD / PWAD" stores WADs from your disk in the same place and reloads
the page with them in the URL (?iwad=NAME&file=NAME,NAME); "Back to
Freedoom" removes them. Other options go in ?args=, for example
raylibdoom.html?args=-warp%201%201%20-skill%204.
On a phone or tablet (a device whose main pointer is a finger, or
once the screen is touched) the page draws touch controls over the
side bars: a stick that moves and turns (hold STRAFE to sidestep
with it), FIRE, USE, RUN, previous and next weapon, MENU (Esc),
ENTER, Y for the yes/no prompts, MAP and, where the browser allows
it, FULL for fullscreen. Several can be held at once. In menus the
stick moves the cursor, FIRE and USE pick, RUN and MAP go back, and
a savegame without a name is named after its slot. The mouse is not
captured while they are shown, and a key on a real keyboard hides
them. ?touch=1 or ?touch=0 forces them on or off. The page
passes the buttons held to the game (RL_WebTouch), which turns
them into keys the same way as the Android touch controls.
In the browser the frame loop is driven by
emscripten_set_main_loop (once per display refresh) instead of
ASYNCIFY: D_DoomLoop's body is D_RunFrame, TryRunTics returns
instead of spinning until the next tic is due, and the screen wipe
runs one step per frame. Sound effects and the OPL music go through
the same raylib audio streams as on the desktop, over Web Audio.
Netgames are not supported, and quitting from the menu ends the game
until the page is reloaded.
Put an IWAD (doom1.wad, doom.wad, doom2.wad, plutonia.wad,
tnt.wad, Freedoom's freedoom1.wad / freedoom2.wad, ...) in
$DOOMWADDIR or the current directory, then:
./build/raylibdoomUpper- or mixed-case names such as DOOM1.WAD are found too. To use an
IWAD under any other name or path, name it with -iwad; the game is
identified from the maps it contains:
./build/raylibdoom -iwad ~/wads/freedoom2.wadAn IWAD passed with -file (-file DOOM1.WAD) is also used as the IWAD.
On Linux, the game then looks in /usr/local/share/games/doom and
/usr/share/games/doom, where distribution packages such as freedoom
install IWADs, and last next to the executable and in its
../share/raylibdoom, where the release packages put the shareware
DOOM1.WAD. If no IWAD is found, the game says where it looked and
exits.
| Option | Effect |
|---|---|
-1 ... -4 |
Window size as a multiple of 320x240 (default 3) |
-scale N |
Any window multiple |
-fullscreen |
Start borderless fullscreen |
-nosound |
No audio device |
-nomusic |
Sound effects only |
-iwad FILE |
Use FILE as the IWAD |
-warp E M / -warp M, -skill N, -loadgame N |
As in the original |
PWADs that add episodes past E4, such as SIGIL (E5) and SIGIL II (E6),
work with a DOOM 1 IWAD: their UMAPINFO puts the episode in the New
Game menu and supplies level names, music, sky, intermission pictures,
par times, the next and secret levels, and the end text and picture:
./build/raylibdoom -iwad freedoom1.wad -file SIGIL_II_V1_0.WAD -warp 6 1These WADs replace the IWAD's texture list, so Freedoom's own episodes may not load while one is added.
Only part of UMAPINFO is supported (see the top of
linuxdoom-1.10/u_mapinfo.c). NoIntermission is ignored, EndCast
ends the game without the cast, InterText shows only on a level that
ends the game, and a BossAction other than clear keeps the default
boss behaviour.
The picture is scaled to the window in two steps, first by a whole
number with sharp pixels and then smoothly to the final size, so every
pixel row comes out the same height. Alt+Enter toggles fullscreen. The
mouse is captured while you are playing and released in menus, when
paused, and during demos. Settings are saved to ~/.doomrc.
Under WSL (WSLg) GLFW cannot lock the pointer, so the game detects WSL at
run time and starts a small powershell.exe helper that keeps the Windows
pointer inside the window while you play. Set DOOM_WSL_MOUSE=0 to turn
that off, or DOOM_WSL_MOUSE=1 to force it.
On Linux an opt-in second target, raylib_doom_xr, shows the game on
a large virtual screen floating in front of you in an OpenXR headset,
with head tracking. It is still the flat 320x200 game, not a
stereoscopic 3D renderer. raylibdoom and the other platforms are
built as before. Besides raylib's dependencies it needs the OpenXR
loader and headers (sudo apt install libopenxr-dev), found through
their CMake config or, failing that, pkg-config (openxr.pc); without them
CMake downloads and builds the loader from the OpenXR SDK
(OpenXR-SDK 1.0.34 by
the Khronos Group, mainly under the Apache License 2.0, with bundled
parts such as jsoncpp under the licenses in its LICENSES/; see
COPYING.adoc in build-xr/_deps/openxr-src). A raylib_doom_xr
shipped with that loader has to carry those notices.
cmake -B build-xr -DRAYLIB_DOOM_XR=ON
cmake --build build-xr -j
ctest --test-dir build-xrThe xr test runs i_xr.c against a fake runtime under
AddressSanitizer: overlong extension and swapchain image lists,
swapchain image waits and releases that fail, a runtime that is lost
or quits, and the window's vsync.
To try it without a headset, run the Monado
runtime with its simulated headset (sudo apt install monado-service libopenxr1-monado), which shows both eyes in a desktop window:
SIMULATED_ENABLE=1 XRT_COMPOSITOR_FORCE_XCB=1 monado-serviceand in another terminal:
XR_RUNTIME_JSON=/usr/share/openxr/1/openxr_monado.json \
./build-xr/raylib_doom_xr -iwad freedoom1.wadXR_RUNTIME_JSON is only needed when no runtime is set as the active
one, or when the one in ~/.config/openxr/1/active_runtime.json is
broken. monado-service exits at once if its standard input is not a
terminal or pipe (epoll_ctl(stdin) failed); start it from a terminal,
or as sleep infinity | monado-service. On a laptop with two GPUs the
game's OpenGL and Monado's Vulkan have to be on the same one, or the
game crashes in the OpenGL driver while creating the swapchain. Monado
usually picks the discrete GPU, so when the NVIDIA driver is loaded
raylib_doom_xr sets __NV_PRIME_RENDER_OFFLOAD=1 and
__GLX_VENDOR_LIBRARY_NAME=nvidia before it opens its window.
DOOM_XR_PRIME=0 turns that off, and a __GLX_VENDOR_LIBRARY_NAME
you set yourself is left alone.
Without a runtime or headset, or if the session can not be created, the
game says why on the XR: lines and plays in the window. If the runtime
goes away during the game (monado-service stopped, headset unplugged),
it says so once and goes on in the window; quitting from the runtime
still quits the game. While the session runs, the headset paces the
frames and the window's vsync is off; it is back on otherwise.
The desktop window keeps a copy of the picture, and the keyboard and mouse work as usual while it has focus. Controllers (the ones OpenXR calls simple, Oculus Touch, Valve Index, HTC Vive and Windows Mixed Reality) are mapped to your key bindings:
| Control | In the game | In menus |
|---|---|---|
| Left stick / trackpad | Move and strafe | Up, down, left, right |
| Right stick / trackpad | Turn | Left, right |
| Right trigger (simple: right select) | Fire | Enter |
| Right A or grip (simple: left select) | Use | Enter |
| Left trigger | Run | Backspace |
| Right B, or right menu | Automap | Backspace |
| Left menu (Index: left B) | Menu (Esc) | Esc |
Hands (XR_EXT_hand_interaction): right pinch |
Fire | Enter |
| Left pinch | Use | Enter |
| Right grasp (closed hand) | Automap | Backspace |
| Left grasp | Menu (Esc) | Esc |
In a yes/no prompt, such as "are you sure you want to quit?", fire or use answers yes, run or automap answers no, and menu cancels. So to quit, press menu, pick Quit Game with fire, then press fire again.
| Option | Effect |
|---|---|
-xrflat |
Accepted for older scripts; playing in the window without a runtime or headset is now the default |
-noxr |
Play in the window without trying OpenXR |
-xrdist M |
Screen distance in meters (default 2.5) |
-xrwidth M |
Screen width in meters (default: fitted to the field of view, at most 3.2) |
-xrlift N |
Raise black to N% of white, 0 to 50 (default 12 on see-through glasses, 0 on other headsets) |
-xrstats |
Log frame pacing every 10 seconds |
On the desktop only OpenGL on X11 is supported (XR_KHR_opengl_enable
with GLX), which is how raylib runs on Linux; the Android APK uses
OpenGL ES on EGL (see Android and Android XR). See the top of linuxdoom-1.10/i_xr.c for
how the frame reaches the headset.
android/ is a Gradle project that builds the game as an APK:
CMakeLists.txt, configured by the NDK with
-DRAYLIB_DOOM_ANDROID=ON, makes libraylibdoom.so, which
NativeActivity loads (raylib's PLATFORM=Android), started by a
small Java launcher that finds the player's WADs. The desktop,
Windows, macOS, web and OpenXR builds are not affected; the option is
off unless Gradle sets it. There are two flavors, each for
arm64-v8a (devices) and x86_64 (the emulator):
| Flavor | Package | What it is |
|---|---|---|
flat |
com.raylib.doom |
A normal Android app (OpenGL ES 2) for phones, tablets and TVs. On Android XR it opens as a 4:3 panel in the Home Space. |
xr |
com.raylib.doom.xr |
The same with OpenXR (OpenGL ES 3, XR_KHR_opengl_es_enable, the Khronos loader AAR): on Android XR it starts in Full Space and shows the game on the virtual screen of VR headsets. Without a runtime or headset it logs why and plays as the flat app. |
You need the Android SDK with NDK 28.1.13356709 and CMake 3.22.1
(Android Studio's SDK Manager, or sdkmanager "ndk;28.1.13356709" "cmake;3.22.1"), and a JDK 17 or newer (with javac, not only a
JRE; set JAVA_HOME to it). The Gradle wrapper fetches
Gradle and the Android Gradle plugin. With ANDROID_HOME set, or
sdk.dir in android/local.properties:
cd android
./gradlew assembleFlatDebug assembleXrDebug
# app/build/outputs/apk/flat/debug/app-flat-debug.apk
# app/build/outputs/apk/xr/debug/app-xr-debug.apkThe android job in .github/workflows/build.yml uploads both debug
APKs as the raylibdoom-android artifact.
The APK holds no WAD at all, not even a free one: the player supplies
their own, and the app never downloads any. It is an engine
compatible with DOOM WAD files. A launcher screen (WadActivity, the
only Java in the app) finds the WADs and starts the game:
- Add WAD files… opens the system file picker
(
ACTION_OPEN_DOCUMENT). The chosen files are copied into the app's internal storage (files/wads), so they stay usable whatever happens to the original. - Add a folder with WAD files… asks for a folder
(
ACTION_OPEN_DOCUMENT_TREE) such asDocumentsor a folder insideDownload(Android 11 and newer do not let apps haveDownloaditself). The grant is kept, and on every start the folder's*.wadfiles (any case) are copied intofiles/folders/, again only when one changes; Stop using the folder forgets it. - WADs copied over USB or with
adb pushtoAndroid/data/com.raylib.doom/files/(com.raylib.doom.xrfor thexrflavor) are found too; tap Rescan.
None needs a storage permission. IWADs are told apart as on the
desktop, by the maps in their lump directory (after checking that the
directory and the lumps fit in the file); with several, the player
picks one. PWADs are ticked as add-ons and loaded in that order, as
with -file. The choice is remembered. A file that is not a WAD, or a
damaged one, is refused with a message, and a PWAD alone is told it
needs an IWAD. With no IWAD the screen says what is needed and links
to Freedoom's download page
(opened in the browser), and explains that the original game's IWAD
(DOOM.WAD, DOOM2.WAD, ...) is in the player's own copy, from Steam
or GOG for example. About / Licenses shows the GPL-2.0, the Nuked
OPL3 LGPL, the third-party notices for raylib, miniaudio and the rest
(packaging/android/THIRD-PARTY-NOTICES.txt), and a link to the
source of the exact tag. The app's name, "raylib 1.10 Engine", and
its icon use no id Software or Bethesda trademark or artwork.
The game runs in a process of its own (:game), so when it quits,
or stops on an error, the launcher comes back; an error (I_Error)
is shown there. packaging/android/check-no-wad.sh APK... fails if an
APK has an entry ending in .wad (any case) or another game-data
extension (.pk3, .lmp, ...), or any file starting with a WAD
header; CI runs it on every APK it builds.
Install and start one with adb:
adb install -r app/build/outputs/apk/flat/debug/app-flat-debug.apk
adb push freedoom1.wad /sdcard/Android/data/com.raylib.doom/files/
adb shell monkey -p com.raylib.doom -c android.intent.category.LAUNCHER 1
adb logcat -s raylibdoom # DOOM's console outputThe settings (.doomrc) and saved games go to the app's internal
storage (/data/user/0/<package>/files). The launcher writes the
command line it starts the game with to launch.txt there, one
argument per line. To pass more options, put them in args.txt (a
debug build allows run-as):
echo '-warp 1 -skill 4' > args.txt
adb push args.txt /data/local/tmp/
adb shell run-as com.raylib.doom cp /data/local/tmp/args.txt files/On a v*
8DCF
tag, .github/workflows/release-android.yml builds
raylibdoom-<version>-android-shareware.apk (the flat flavor,
arm64-v8a and x86_64 in one APK, with the shareware DOOM1.WAD as
below) with its .sha256, checks the WAD in it, and uploads both to
the tag's draft release, adding the
Android section of the release notes
(packaging/android/RELEASE-NOTES.md). versionName is the tag
without the v and versionCode is major*1000000 + minor*1000 + patch (-PappVersion=1.2.3). Pull requests that touch the Android
build, and a manual run, build the same release APK unsigned and
WAD-free (checked with check-no-wad.sh) as an artifact. The xr flavor is not released: it is for headsets and
glasses, and its OpenXR loader adds another component to ship; it
stays a CI artifact.
The release APK is signed with a key kept in four repository secrets. Without them the tag's job fails rather than upload an unsigned or debug-signed APK. To make the key (once; keep the keystore and its passwords safe and out of the repository, as every later update must be signed with the same key):
keytool -genkeypair -v -keystore raylibdoom-release.jks \
-alias raylibdoom -keyalg RSA -keysize 4096 -validity 10000 \
-dname "CN=raylib DOOM, O=raylib DOOM"
base64 -w0 raylibdoom-release.jks > raylibdoom-release.jks.b64
gh secret set ANDROID_KEYSTORE_BASE64 < raylibdoom-release.jks.b64
gh secret set ANDROID_KEYSTORE_PASSWORD # the keystore password
gh secret set ANDROID_KEY_ALIAS --body raylibdoom
gh secret set ANDROID_KEY_PASSWORD # the key password
rm raylibdoom-release.jks.b64To sign locally, pass the keystore and set the same variables:
ANDROID_KEYSTORE_PASSWORD=... ANDROID_KEY_ALIAS=... ANDROID_KEY_PASSWORD=... ./gradlew assembleFlatRelease -PappVersion=1.2.3 -PreleaseKeystore=/path/to/raylibdoom-release.jks.
Players install it by opening the downloaded APK on the device and allowing their browser or file manager to install unknown apps.
The release APK includes the shareware DOOM1.WAD (episode 1),
unmodified, as assets/doom1.wad: -PbundleWad=FILE adds it, after
checking its SHA-256 and that the file is outside the checkout, so it
can never be committed. Builds without the property, CI and pull
requests among them, stay WAD-free. The launcher
unpacks it and chooses it when nothing else is chosen; a fresh install
goes straight into the game. Other IWADs and PWADs are added as above,
and the launcher shows "DOOM shareware © id Software. Not affiliated
with id Software / ZeniMax / Microsoft." To build, sign and name it
locally (raylibdoom-<version>-android-shareware.apk and its
.sha256), as the release workflow does:
ANDROID_KEYSTORE_PASSWORD=... ANDROID_KEY_ALIAS=... ANDROID_KEY_PASSWORD=... \
packaging/android/build-shareware.sh 0.1.3 /path/to/DOOM1.WAD \
/path/to/raylibdoom-release.jks out/A Bluetooth or USB gamepad plays with the controller mapping of the VR headsets table: left stick (or d-pad up and down) moves and strafes, right stick (or d-pad left and right) turns, right trigger or X fires, A uses, left trigger runs, B or Y is the automap and Start is the menu. On a touchscreen, buttons for turning, moving, fire, use, run, the menu and the automap are drawn over the picture; they hide once a gamepad is used and come back when the screen is touched. The system Back button is Esc.
In the xr flavor the first run on a device logs the runtime's
OpenXR extensions (XR: runtime extension ...), then the session's
state changes. Android XR recommends Vulkan, but its runtime offers
XR_KHR_opengl_es_enable, which is what raylib's EGL context needs.
Both flavors have been run on XREAL's Project Aura glasses (Android
XR, Adreno, OpenGL ES 3.2) and on the x86_64 Android XR emulator;
the flat one also on a plain x86_64 phone emulator image. The
shared i_xr.c code is also tested on Monado on the desktop.
On see-through glasses such as the Aura (70° diagonal, about 58° x 34° per eye) two things differ from a VR headset:
- Their optics add the picture to the room, so black is transparent
and DOOM's dark areas vanish. The runtime lists the
additiveblend mode for them (the Aura listsopaquefirst, but offersadditive), and then the game raises black to 12% of white, scaling the rest so white stays white: dark rooms show as a dim image.-xrlift Nsets another level (-xrlift 0turns it off), and DOOM's own gamma (F11, or the options menu) brightens the mid tones on top. - The screen is sized to the field of view the runtime reports: at
2.5 m it is 1.85 m wide on the Aura, so the whole 4:3 picture,
status bar included, is in view.
-xrwidthstill sets it.
Hand tracking works without a controller, through
XR_EXT_hand_interaction (see the controls above); the Aura's
runtime picks that profile for both hands. A Bluetooth gamepad pairs
with the compute puck and plays as on a phone.
i_raylib.c/i_raylib.h: new, the only code that talks to raylib.raylib.hand DOOM's headers clash (KEY_*,<stdbool.h>vs. thebooleanenum), so the rest of the game sees a small plain-C API.i_video.c: X11/MIT-SHM code replaced with palette expansion and calls intoi_raylib.c.i_sound.c: the original software mixer, now feeding a raylib audio stream instead of/dev/dsp. Sounds stop, update and report "playing" by handle, and play at their own sample rate.i_music.c: new. Plays the music the way DOS DOOM did on an AdLib or Sound Blaster: the MUS score drives an emulated OPL2 FM chip, with the instruments from the IWAD'sGENMIDIlump and DMX's voice allocation, pitch table and volume curve. The title usesD_INTROA, the OPL arrangement, like the DOS version. Standard MIDI music lumps (as in Freedoom and many PWADs) play through the same chip and voices.s_sound.c,i_sound.h:I_RegisterSongalso takes the lump length, so MIDI files can be read safely.opl3.c/opl3.h: Nuked OPL3 1.8 by Nuke.YKT, unmodified, under the LGPL 2.1 or later (opl3-LICENSE.txt).i_xr.c/i_xr.h: new, the OpenXR output ofraylib_doom_xr(-DRAYLIB_DOOM_XR=ON), compiled into that target only;tests/xr_test.ctests it.- Android: the launcher in
android/app/src/main/java(the player's WADs: file picker, shared folder, IWAD detection, About / Licenses),i_android.c/i_android.h(logcat, the data folder,launch.txtandargs.txt, errors for the launcher), the gamepad and touch controls ini_raylib.c, and the EGL / OpenGL ES graphics binding andxrInitializeLoaderKHRini_xr.cfor thexrflavor of the APK inandroid/. doomkeys.h: the key codes, split out ofdoomdef.h.- Browser build:
web/web.cmakeandweb/shell.html(the page, with the IndexedDB mount and the WAD picker);d_main.csplits the game loop intoD_RunFrameforemscripten_set_main_loop, andi_system.c/i_raylib.cend the game, report errors and handle the mouse the way a page needs. - 64-bit fixes: pointer arrays sized with
sizeofinstead of4, pointer/integer casts throughintptr_t, the on-disk texture struct no longer holds a pointer, the config file's string settings, the savegame buffer, and the zone heap size. - arm/aarch64 Linux: built with
-fsigned-char, because the code assumes a signedchar(movement inticcmd_tamong others) and plaincharis unsigned there. Without it backward and left moves went forward and right, and demos desynced. u_mapinfo.c/u_mapinfo.h: new, aUMAPINFOparser.g_game.c,m_menu.c,s_sound.c,wi_stuff.c,f_finale.c,hu_stuff.candp_enemy.cuse it for PWAD episodes;G_InitNewno longer turns E5 and E6 into E4 when the maps are there. Flats are gathered from every WAD'sF_START/F_END, not only the last one's, and the rendering limits (visplanes, drawsegs, sprites, openings) and the unchecked arrays behind them are raised for limit-removing maps.- Ultimate DOOM skies:
G_DoLoadLevelcomparedgamemodewith the mission valuespack_tntandpack_plut, andretailequalspack_plut, so E2-E4 levels got DOOM II'sSKY1. - Fixes for bugs modern compilers and glibc catch: undersized WAD path
buffers, the unterminated sprite name list, undefined event queue
increments, and a
memsetthat cleared only part of the mouse and joystick button state.