Skip to content

Repository files navigation

DoomConsole

DoomConsole is a JaszczurHAL firmware port of Doom for RP2040 and RP2350 boards. It is based on Graham Sanderson's kilograham/rp2040-doom, which in turn is derived from Chocolate Doom.

This repository is no longer a stock rp2040-doom tree. The current active port replaces the original application-specific VGA, I2S, and TinyUSB platform layer with the JaszczurHAL application model, TFT output, and HAL-backed input, audio, and storage glue. Firmware builds through JaszczurHAL's native RP dispatcher and the official Pico SDK.

RP2040 ILI9341 320x200: DoomConsole demo

RP2350 ILI9341 320x200: DoomConsole demo

RP2350 ST7796S 480x320: DoomConsole demo

What This Port Is

The original rp2040-doom project proved that real Doom can run on RP2040 by heavily compressing game data into WHD/WHX and carefully shrinking Chocolate Doom. DoomConsole keeps that core idea and much of the renderer/data-format work, but changes the platform layer:

  • Application entry is JaszczurHAL-style app_start(), app_task0(), app_task1().
  • Firmware is built by CMake against the official Pico SDK through JaszczurHAL's native RP build.
  • Video output is a 320x200 indexed Doom framebuffer converted to RGB565 and streamed to a HAL TFT display.
  • Core1 is used for asynchronous TFT flush and experimental renderer helper work.
  • Audio is routed through JaszczurHAL DMA PWM audio.
  • Game data is expected as a raw WHD/WHX flash payload, separate from the UF2 firmware image.
  • Most legacy desktop, SDL, OPL, network, setup, and old Pico SDK backend files have been moved out of the active source tree.

The active platform code lives mostly in:

  • doom_main_config.h - central port configuration.
  • hal_project_config.h - thin JaszczurHAL config wrapper.
  • src/jaszczurhal/ - current HAL backends and application wrapper.
  • src/doom/ - Doom game and renderer code retained from the port lineage.
  • src/whd_gen/ - WHD/WHX generation tooling retained for the data format.

Current Status

The port builds and runs as RP2040/RP2350 firmware. The renderer is functional but still performance-oriented work in progress. PCB is not ready yet. Current measurements show the main cost in wall/BSP column rendering.

Important current traits:

  • Tested configuration uses Waveshare RP2040 Plus / 4 MB style target, and Raspberry pi pico2 (RP2350).
  • The default WHD/WHX payload address is 0x10200000.
  • The active build is tuned for a TFT display and HAL GPIO/button input.

See port_issues.md for the short current performance plan.

Configuration

Common groups in doom_main_config.h:

  • TFT display: SPI pins, panel dimensions, rotation, color order, flush mode.
  • GPIO input: active-low mode and button pins.
  • Audio: PWM pin, PWM resolution, block size, sample rate, mixer channels.
  • Flash/WHD: XIP base, flash size, payload address, scan step.
  • Zone/heap: Doom zone size and heap reserve.
  • Renderer/performance: patch/flat decoder buffers, column cache, plane queue, dual-core column mode, sentinel/debug values.

Most values can still be overridden from CMake/compiler definitions before doom_main_config.h is included.

VS Code Build Options

VS Code uses the shared JaszczurHAL entrypoint:

../libraries/JaszczurHAL/vscode/entry/jh-vscode

The firmware module contract lives in .vscode/jaszczurhal.project.json. That manifest is the source of truth for the target, board profile, generated CMake build directory, USB identity, artifacts, and Doom-specific CMake cache values. The most useful Doom CMake cache keys are:

  • DOOM_TFT_PANEL - display driver, either ili9341 or st7796s.
  • DOOM_HIGHRES_SCENE - render the scene at the full panel resolution: 320x240 on ILI9341 or 480x320 on ST7796S. The ST7796S path is supported only for RP2350/Pico 2.
  • JH_ILI9341_SPI_DEFAULT_HZ - requested TFT SPI clock.
  • DOOM_SYS_CLOCK_KHZ - RP2040/RP2350 system clock request.
  • DOOM_DUAL_CORE_COLUMNS, DOOM_RENDER_ASYNC_PLANES, DOOM_VIDEO_SYNC_FLUSH - renderer/flush experiments; the default active values are conservative.

To use the classic ILI9341 path, keep highres disabled:

{
    "cmake": {
        "cache": {
            "DOOM_TFT_PANEL": "ili9341",
            "DOOM_HIGHRES_SCENE": "0"
        }
    }
}

This works on RP2040 and RP2350 builds. For a Raspberry Pi Pico, select the native RP2040 target and its pico board profile:

{
    "target": "rp2040",
    "board": "pico"
}

To fill the whole 320x240 ILI9341 panel, enable highres while keeping the ILI9341 driver:

{
    "cmake": {
        "cache": {
            "DOOM_TFT_PANEL": "ili9341",
            "DOOM_HIGHRES_SCENE": "1"
        }
    }
}

To use the 4.0 inch ST7796S 480x320 path, select an RP2350/Pico 2 board and enable highres:

{
    "target": "rp2350-arm",
    "board": "pico2w",
    "cmake": {
        "cache": {
            "DOOM_TFT_PANEL": "st7796s",
            "DOOM_HIGHRES_SCENE": "1"
        }
    }
}

st7796s is intentionally rejected for RP2040 targets. The ST7796S full-panel framebuffer and flush buffers are RP2350-only.

After changing the manifest, regenerate the CMake cache and rebuild:

../libraries/JaszczurHAL/vscode/entry/jh-vscode build --project .

Build Requirements

Expected local tools:

  • cmake
  • JaszczurHAL checked out at ../libraries/JaszczurHAL by default

JaszczurHAL's ./runmefirst.sh prepares the pinned Pico SDK, RP toolchains, picotool, and the remaining managed dependencies required by the build.

The tracked editor configuration points jaszczurhal.root at ../libraries/JaszczurHAL; override that local setting when the checkout uses a different path.

Building Firmware

Configure (optional):

../libraries/JaszczurHAL/vscode/entry/jh-vscode config-dump --project .

Build:

../libraries/JaszczurHAL/vscode/entry/jh-vscode build --project .

Generate/update compile commands for editor tooling:

../libraries/JaszczurHAL/vscode/entry/jh-vscode refresh-intellisense --project .

Other CMake targets:

  • firmware_debug - debug build target used by the shared workflow.
  • firmware_upload - firmware build prerequisite used by the upload workflow.
  • firmware_compile_db - compile database refresh target.

The generated outputs are placed under .build/, including:

  • .build/firmware.elf
  • .build/firmware.bin
  • .build/firmware.uf2

Detailed linker output, including firmware.elf.map, remains in the resolved target/board directory below .build/cmake/.

Board And Upload Flow

Board selection uses the JaszczurHAL target and board profile in .vscode/jaszczurhal.project.json, with optional local overrides stored in .vscode/jaszczurhal.local.json. The tracked configuration selects:

target: rp2350-arm
board:  pico2w

Use the Project: Select board task or pass --target and --board to jh-vscode to select another supported RP profile.

Firmware UF2 upload and WHX/WHD payload upload are intentionally separate.

VS Code firmware tasks:

  • Project: Build
  • Project: Build (Debug)
  • Project: Upload - verified serial upload through jh-vscode; if no serial port is configured and exactly one BOOTSEL drive is visible, it falls back to UF2.
  • Project: Upload (UF2 / BOOTSEL) - builds and copies .build/firmware.uf2 to the mounted BOOTSEL drive.
  • Project: Serial Monitor
  • Project: Refresh IntelliSense
  • Project: Upload WHX Payload - runs the picotool WHX helper below.

The WHX payload upload remains a separate picotool flow and expects the board to already be in BOOTSEL mode:

sudo scripts/upload-whx-picotool.sh

By default it writes the payload at:

0x10200000

This address is controlled by DOOM_WHD_FLASH_ADDR.

WHD/WHX Game Data

Like rp2040-doom, this port does not run directly from a normal WAD file on the device. WAD data must be converted to the compact WHD/WHX format used by the RP2040/2350 renderer/data path.

The generator code is retained in:

src/whd_gen/

The active firmware expects the converted payload in flash, separate from the program image. The default payload address assumes a board with at least 4 MB of flash.

Runtime Diagnostics

The firmware prints render diagnostics such as:

[render] frame=... fps=... cols=... planes=... tus=bsp/planes/masked/pspr/hud ...

Useful fields:

  • fps - current frame-rate estimate.
  • cols - wall columns submitted/rendered.
  • planes, pdrop - floor/ceiling workload and queue drops.
  • masked - masked sprite workload.
  • black=total/top/mid/bot - undrawn sentinel pixels by screen band.
  • tus=bsp/planes/masked/pspr/hud - per-frame timing in microseconds.
  • pcache - decoded patch/column cache behavior.
  • ccol, casync - dual-core column queue/helper diagnostics.
  • flush - asynchronous TFT flush statistics.

the main optimization target remains BSP/wall column rendering and safe core1 offload.

Repository Layout

doom_main_config.h       central port configuration
hal_project_config.h     JaszczurHAL project config wrapper
CMakeLists.txt           native Pico SDK/JaszczurHAL firmware recipe
src/jaszczurhal/         active platform backends
src/doom/                Doom game and renderer code
src/whd_gen/             WHD/WHX conversion tooling
scripts/                 WHX/picotool payload helper
port_issues.md          current performance notes and next steps
_unused/                 files removed from the active port path

Lineage And Licenses

This project is a modified port based on kilograham/rp2040-doom, itself derived from Chocolate Doom.

License expectations follow the upstream lineage:

  • Code derived from Chocolate Doom keeps its original GPL licensing.
  • RP2040-specific code from the original port follows the licensing of kilograham/rp2040-doom.
  • New JaszczurHAL port glue in this repository should be treated according to the repository's existing license files and upstream compatibility.

Keep attribution to both upstream projects when redistributing modified builds.

About

rpi-pico based console with doom

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages