Close
0%
0%

doom-avr

DOOM raycaster on Arduino Uno. Real 3D math on a 16MHz ATmega328P with 2KB RAM. Actual E1M1 geometry from doom1.wad. Built in 3 days.

Similar projects worth following
0 followers
DOOM, ported to an Arduino Uno (ATmega328P, 2KB SRAM, 32KB flash, 16MHz, no FPU).
The chip itself computes the raycasting: wall distances, fisheye correction, texture hit fractions, sprite visibility, collision detection, enemy AI, hitscan combat, and player health, using 404 real wall segments parsed directly from doom1.wad's E1M1 linedefs. A Python/pygame host receives the computed frame data over UART and renders it using real WAD textures and sprites. The host is a display driver. All the 3D math happens on the chip.
The game is split into independently-compiled binary chunks (menu, level, options, save, load, help). When a chunk needs to swap, it sends a REQ over serial and halts. The host reflashes the chip via avrdude and the existing Optiboot bootloader, no custom self-programming code. EEPROM (the only memory that survives a reflash) is used as a cross-chunk message channel for save data and settings.
Built in 3 days.

DOOM, ported to an Arduino Uno (ATmega328P, 2KB SRAM, 32KB flash, 16MHz, no FPU).

The chip itself computes the raycasting: wall distances, fisheye correction, texture hit fractions, sprite visibility, collision detection, enemy AI, hitscan combat, and player health, using 404 real wall segments parsed directly from doom1.wad's E1M1 linedefs. A Python/pygame host receives the computed frame data over UART and renders it using real WAD textures and sprites. The host is a display driver. All the 3D math happens on the chip.

The game is split into independently compiled binary chunks (menu, level, options, save, load, help). When a chunk needs to swap, it sends a REQ over serial and halts. The host reflashes the chip via avrdude and the existing Optiboot bootloader, no custom self-programming code. EEPROM (the only memory that survives a reflash) is used as a cross-chunk message channel for save data and settings.

Performance was tuned entirely on real hardware. The naive version ran at 4.1 seconds per frame. A candidate-list prefilter (compute once per frame which walls could possibly be visible, not once per ray) plus column count reduction brought it down to 0.83 seconds per frame at 16 columns.

The Arduino IDE and .ino sketches were deliberately avoided. A .ino sketch compiles against the Arduino core library which pulls in a setup()/loop() wrapper, Serial (a buffered interrupt-driven UART wrapper), and various other conveniences, all of which cost SRAM on a chip that only has 2KB total. This project instead compiles bare C against avr-libc directly with avr-gcc, writing UART registers by hand. That difference is why level1.c fits in about 800 bytes of RAM with room to spare, instead of not fitting at all.

Built in 3 days.

  • 1 × Arduino UNO

  • 1
    Download the repo.

    Run "git clone https://github.com/Artfical/doom-avr/" on your computer.

  • 2
    Get in to the directory.

    Run "cd doom-avr" on your computer.

  • 3
    Run the quick setup script and connect the Arduino UNO to your computer.

    If you are using Windows run "powershell -ExecutionPolicy Bypass -File scripts\setup_windows.ps1" on your computer. If you are using MacOS run "chmod +x scripts/setup_macos.sh && ./scripts/setup_macos.sh" on your computer. If you are using Linux run "chmod +x scripts/setup_linux.sh && ./scripts/setup_linux.sh" on your computer. After the setup is complete plug your Arduino UNO in to your computer.

View all 7 instructions

Enjoy this project?

Share

Discussions

Does this project spark your interest?

Become a member to follow this project and never miss any updates