Run the original 1993 DOOM on bare metal RISC-V hardware with no operating system.
This port runs on QEMU's virt machine with the ramfb framebuffer device, targeting the RV32IMACV architecture (32-bit RISC-V with Vector extension).
- No OS required - Runs directly on hardware/emulator
- Full game support - Uses registered DOOM WAD (embedded in binary)
- Graphics - 320x200 resolution via QEMU ramfb device
- Input - UART keyboard input with arrow key support
- Portable - Built with Nix for reproducible builds
- Nix package manager with flakes enabled
nix buildThis produces result/bin/doom.elf.
qemu-system-riscv32 -M virt -cpu max -m 32M -device ramfb \
-bios none -kernel result/bin/doom.elfOr enter the development shell and run:
nix develop
qemu-system-riscv32 -M virt -cpu max -m 32M -device ramfb \
-bios none -kernel result/bin/doom.elfThe test navigates through menus, starts a game, and captures screenshots:
nix develop
python3 test/screenshot.py result/bin/doom.elfScreenshots are saved to build/test-output/.
Input is via UART serial console. When running QEMU with -nographic, type directly into the terminal.
| Key | Action |
|---|---|
| Arrow keys | Move/Turn |
| Enter | Select/Confirm |
| Escape | Menu |
| Space | Use/Open doors |
| Ctrl+A | Fire weapon |
| 1-7 | Select weapon |
Arrow keys use ANSI escape sequences (ESC [ A/B/C/D).
baremetal/
crt0.S - Startup code (stack, BSS, main)
i_main_baremetal.c - Entry point
i_system_baremetal.c - System functions (timing, memory)
i_video_stub.c - Video output and keyboard input
ramfb.c - QEMU ramfb framebuffer driver
w_wad_embedded.c - Embedded WAD file support
linker.ld - Memory layout (14MB ROM, 14MB RAM)
platform.h - Platform compatibility definitions
linuxdoom-1.10/ - Original DOOM source code
test/
screenshot.py - Automated test with screenshots
nix/
doom.nix - Nix build configuration
newlib.nix - C library for baremetal
For QEMU virt machine with 32MB RAM:
| Region | Address | Size | Contents |
|---|---|---|---|
| ROM | 0x80000000 | 14MB | Code, rodata, embedded WAD |
| RAM | 0x80E00000 | 14MB | Data, BSS, stack, heap |
| ramfb | 0x81C00000 | ~250KB | Framebuffer |
Uses QEMU's ramfb device configured via fw_cfg DMA interface:
- Resolution: 320x200
- Format: XRGB8888 (32-bit)
- Base address discovered at runtime
Reads from NS16550A UART at 0x10000000:
- Polls receive buffer in game loop
- Handles ANSI escape sequences for arrow keys
- Keys auto-release after ~1 second for smooth movement
Uses RISC-V rdtime instruction reading from CLINT mtime register.
Provides millisecond-precision timing for game logic (35 Hz tick rate).
See README.TXT for John Carmack's original release notes from 1997.
Original DOOM source code is released under the GNU General Public License 2.0. Copyright (c) ZeniMax Media Inc.
Baremetal port additions are also GPL-2.0.