rp2040-doom runs the shareware Doom on a 2MB Raspberry Pi Pico
Fully-featured Doom port for the Raspberry Pi RP2040 microcontroller
At a glance
- What is it?
- kilograham/rp2040-doom is a Doom port for RP2040 and RP2350 microcontrollers derived from Chocolate Doom, built around a custom WHD and WHX compressed WAD format so that the 4MB shareware DOOM1.WAD fits on a Pico with 2MB of flash. The result is VGA output, OPL2 music and four player I2C networking on a chip with no framebuffer.
- Who is it for?
- Adopt rp2040-doom when you want an authentic Doom experience on an RP2040 or RP2350 board with a VGA output and stereo OPL2 sound, and verify first that your flash chip can run at 135Mhz, because the build depends on a 270Mhz overclock. Do not adopt it as a codebase to extend, since the README states that cleaning up the code was never the focus and that changing the defunct ifdefs can break the build.
- Can I use it commercially?
- Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 113 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem: a 4MB WAD on a chip with 2MB of flash
The Raspberry Pi Pico has 2MB of flash and an RP2040 that has no display output of its own. Doom needs a 4MB shareware data file and a machine that can push frames fast enough to be playable. That is the whole problem this port attacks. The answer, according to the README, is a custom WAD format. The shared DOOM1.WAD is converted into an RP2040 specific WHD or WHX format by a tool called whd_gen, and the compressed result is what gets loaded alongside the firmware. The super tiny variants use WHX, which is the more compressed format and is what makes DOOM1.WAD fit in 2MB. The non super tiny variants use WHD, which is larger and is what Ultimate Doom and Doom II require, which means an 8MB board. The firmware binaries themselves do not contain the WAD data. The README is explicit about that, and it matters operationally, because the data file has to be flashed at a specific address that depends on which firmware you chose. The upstream lineage matters too. This is a port derived from Chocolate Doom, and the README notes that a hopefully fully functional chocolate-doom executable can still be built from this code base as a way to verify that everything works. The Chocolate Doom commit the code is branched from is available in the upstream branch, and the original project README is kept as README-chocolate.md.
Four firmware targets, and why the flash address moves
The build produces four RP2040 targets, and each one changes where the WAD has to live in flash. Understanding the table before you flash anything saves a lot of confusion. doom_tiny is the super tiny version with no USB keyboard support. Keyboard input comes from the host over UART through the SDL Event Forwarder, and the WHX file loads at 0x10040000. doom_tiny_usb adds USB keyboard support through a modified TinyUSB, which pushes the WHX load address to 0x10042000 because the extra USB code grows the binary by 2K. That growth eats into the space left for saved games, which also live in flash. The other two are the non super tiny builds, which use the larger WHD format for bigger WADs, and both load their file at 0x10048000. They are named doom_tiny_nost and doom_tiny_nost_usb. The README explains the rationale for splitting the formats rather than supporting both in one binary: it would have made things bigger and slower. The practical consequence is that the firmware and the data file are a matched pair. Flashing doom_tiny_usb and loading the WHX at 0x10040000 will not work, because that address is reserved for the smaller binary layout. To check which pins a given build uses, the README points at picotool, since picotool info -a shows the pins used by a particular UF2 file.
Building the firmware with CMake, pico-sdk and a pinned compiler
The build uses CMake. You need pico-sdk, the latest version of pico-extras, and the usual pico-sdk prerequisites such as arm-none-eabi-gcc. The README recommends building against the develop branch of pico-sdk.
mkdir rp2040-build
cd rp2040-build
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DPICO_BOARD=vgaboard -DPICO_SDK_PATH=/path/to/pico-sdk -DPICO_EXTRAS_PATH=/path/to/pico-extras ..After that, use make or make with a target name, the same as the native build. The compiler version is not a detail here, because binary size is the binding constraint. The README states that the author builds with arm-none-eabi-gcc 13.2.rel1, that other versions may work, and that changes in compiler version may affect the binary size, which being tight can cause problems, either a link failure or a stack overflow showing up as colour palette corruption. It also warns specifically that arm-none-eabi-gcc 10.x versions do not work well. The MinSizeRel build type in the cmake line is the other half of that squeeze. USB keyboard support needs one more step. RP2040 Doom uses a modified version of TinyUSB included as a submodule, so the submodule has to be initialised first.
git submodule update --initThe README notes that the build should work fine on Linux and macOS, and that the RP2040 targeting builds should also work on Windows, though the author has not tried that.
The native chocolate-doom build as a regression check
One of the more thoughtful choices in this port is that the same tree still builds the original desktop game. The instructions are the standard CMake dance, with SDL2 dependencies assumed to be installed.
mkdir build
cd build
cmake ..Then run make, or make -j with a CPU count, from that directory, or make with a specific target such as chocolate-doom for one binary only. The whd_gen tool is built the same way, which matters because it is the tool that produces the WHD and WHX files the device needs. Having a native build available means you can check that a change did not break the shared logic, and you can produce and inspect the data files on a workstation before flashing them. For a project that squeezes a data file into the smallest possible flash, having the conversion tool buildable on the same machine is a practical necessity rather than a nicety. The repository is a full Chocolate Doom tree rather than a thin port layer. The top level entries include 3rdparty/, autogen.sh, configure.ac, Makefile.am, cmake/, src/, textscreen/, opl/, pcsound/, midiproc/, data/, man/, win32/, pkg/ and an rpm.spec.in, along with the usual project documents such as PHILOSOPHY.md, HACKING.md, NOT-BUGS.md and TODO.md.
What the hardware does: VGA on RGB565 pins, OPL2 over I2S, four players on I2C
The feature list in the README describes the output path in detail, and it is the part that separates this from a framebuffer port. The RP2040 outputs directly to VGA with 16 colour pins for RGB565 plus HSync and VSync. The result is 320x200x60 VGA output, which the README notes is really 1280x1024x60. Sound is 9 channel OPL2 at 49716Hz, which is how the original music was synthesised, plus 9 channel stereo sound effects. Networking is I2C, for up to 4 players. Save and load of games work, all cheats are supported, demos from the original WADs run correctly, and the end scenes, intermissions and help screens are all present. The stated goals were strict. Everything should match the original game experience, with no sneaky discarding of splash screens, no altering of levels, no downsampling of textures. The consequence of that goal is the whole reason for the custom WAD format, and it is why the project needed a 270Mhz overclock, which the README says requires a flash chip that will run at 135Mhz. Frame rate is generally 30 to 35 FPS or better. That last detail is a constraint worth planning around. If your board has a slow flash chip, the overclock is not available to you, and the README does not describe a fallback configuration.
Code state, licence and the gap between commits and releases
The README is unusually candid about the condition of the source, and any evaluation should read that paragraph first. It says the focus has been entirely on getting RP2040 Doom running, that not a lot of time has been spent cleaning up the code, that there are a bunch of defunct ifdefs and other code that was useful at some point but no longer is, and that changing them may result in non-functional code. The whd_gen tool is singled out as probably completely incomprehensible. That is a maintenance warning, not a defect report. This is a port whose job is to run, and it is a reasonable trade for a project of this kind, but it rules out treating the tree as a base for further work. The licence is GPL-2.0, and COPYING.md sits at the root of the tree alongside AUTHORS. A port of a game engine and its data conversion tool sits in the same copyleft category as the upstream project, which is what you would expect from a derivative work. On activity, the last push was on 2026-07-02 and the repository is not archived. The releases are not a version line for this port in the usual sense. They are hardware artefacts: DEFCON32 Badge Doom V1, dated 2024-08-18, with better audio, input and multiplayer, its V0 predecessor from 2024-08-11, and a cosmic unicorn version from 2023-03-19 that the README describes as just for fun. Those release names tell you where this goes. The project was presented at a hardware conference, and the binary artefacts are UF2 files for specific boards, with versions that have DOOM1.WAD already embedded.
Editorial conclusion
Adopt rp2040-doom when you want an authentic Doom experience on an RP2040 or RP2350 board with a VGA output and stereo OPL2 sound, and verify first that your flash chip can run at 135Mhz, because the build depends on a 270Mhz overclock. Do not adopt it as a codebase to extend, since the README states that cleaning up the code was never the focus and that changing the defunct ifdefs can break the build. Before flashing, pick the firmware variant that matches your WAD size and load the WHX or WHD file at the address given for that target.
Frequently asked questions
What is rp2040-doom and what is it based on?
It is a port of Doom for RP2040 and RP2350 devices derived from Chocolate Doom. The README says significant changes were made to support running the entire 4MB shareware DOOM1.WAD on a Raspberry Pi Pico with only 2MB of flash.
How do I build the RP2040 Doom firmware?
Use CMake with pico-sdk and the latest pico-extras, running cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DPICO_BOARD=vgaboard -DPICO_SDK_PATH=/path/to/pico-sdk -DPICO_EXTRAS_PATH=/path/to/pico-extras .. in a build directory, then make. For USB keyboard support you also need git submodule update --init for the bundled TinyUSB.
Which compiler version should I use for RP2040 Doom?
The README states the author builds with arm-none-eabi-gcc 13.2.rel1, warns that changes in compiler version can affect binary size and cause link failure or palette corruption from stack overflow, and notes that arm-none-eabi-gcc 10.x versions do not work well.
How is the WAD file loaded onto the RP2040?
The firmware UF2 does not contain the WAD data. whd_gen converts it into the WHD or WHX format, and the file is loaded with picotool at an address that depends on the target, for example 0x10042000 for doom_tiny_usb.
Can I still build Chocolate Doom from this repository?
Yes. The README says a hopefully fully functional chocolate-doom executable is buildable from this code base as a means of verification. The native build uses CMake, and the same process builds the whd_gen tool.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kilograham-rp2040-doom)Was this useful?