Skip to content

Latest commit

 

History

55 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MiniDoom

License: Apache-2.0 Language: MiniLang

MiniDoom is a full MiniLang port of the original DOOM engine codebase, focused on gameplay parity, classic behavior, and native Windows/Linux x64 execution.

This project keeps the original DOOM architecture and module split concept, but translates the implementation to MiniLang (.ml) with platform-specific runtime bindings where needed (video, audio, input, window handling).

Highlights

  • Native x64 builds for Windows and Linux from the same MiniLang source tree.
  • Original software renderer plus an accelerated OpenGL renderer, switchable at runtime with Alt+G.
  • DOOM and DOOM II IWAD/PWAD support, savegames, demos, menus, HUD, sound effects, and MUS music.
  • Built-in drop-down console with classic cheats and developer commands.
  • Host-authoritative UDP multiplayer for up to four players in cooperative and deathmatch modes.
  • Automatic 3× HDWAD rendering cache for OpenGL textures, sprites, UI graphics, and level geometry.
Feature Windows x64 Linux x64
Classic software renderer Win32/GDI presentation SDL2/OpenGL presentation
Accelerated renderer OpenGL compatibility profile SDL2/OpenGL compatibility profile
Sound effects WinMM PCM SDL2 queued audio
MUS music Windows MIDI mapper FluidSynth + MuseScore General Lite
Input and windowing Win32 SDL2
Multiplayer UDP/WinSock UDP/POSIX sockets

Download and Quick Start

Prebuilt Windows and Linux packages are available on the GitHub Releases page. The packages contain the engine only; copyrighted DOOM IWADs are never included.

Windows:

.\MiniDoom.exe -iwad "C:\Games\DOOM\DOOM2.WAD" -windowed -opengl

Linux (install libsdl2-2.0-0 and libgl1 first):

./run-minidoom -iwad "$HOME/games/doom/DOOM2.WAD" -windowed -opengl

The first OpenGL start creates <IWAD>.hdwad next to the selected IWAD. This one-time build can take a while and requires several hundred megabytes of free space; later starts reuse the validated cache.

Level Gallery

All 59 levels available in the locally tested registered DOOM IWAD (27) and DOOM II (32) are captured from the same player start in both renderers. Classic is shown on the left, OpenGL on the right. The IWAD files are not part of this repository.

DOOM II MAP01 with the Classic renderer DOOM II MAP01 with the OpenGL renderer

DOOM II MAP01 — Classic (left) and OpenGL (right)

DOOM — Episode 1 (E1M1–E1M9)
LevelClassicOpenGL
E1M1E1M1 Classic rendererE1M1 OpenGL renderer
E1M2E1M2 Classic rendererE1M2 OpenGL renderer
E1M3E1M3 Classic rendererE1M3 OpenGL renderer
E1M4E1M4 Classic rendererE1M4 OpenGL renderer
E1M5E1M5 Classic rendererE1M5 OpenGL renderer
E1M6E1M6 Classic rendererE1M6 OpenGL renderer
E1M7E1M7 Classic rendererE1M7 OpenGL renderer
E1M8E1M8 Classic rendererE1M8 OpenGL renderer
E1M9E1M9 Classic rendererE1M9 OpenGL renderer
DOOM — Episode 2 (E2M1–E2M9)
LevelClassicOpenGL
E2M1E2M1 Classic rendererE2M1 OpenGL renderer
E2M2E2M2 Classic rendererE2M2 OpenGL renderer
E2M3E2M3 Classic rendererE2M3 OpenGL renderer
E2M4E2M4 Classic rendererE2M4 OpenGL renderer
E2M5E2M5 Classic rendererE2M5 OpenGL renderer
E2M6E2M6 Classic rendererE2M6 OpenGL renderer
E2M7E2M7 Classic rendererE2M7 OpenGL renderer
E2M8E2M8 Classic rendererE2M8 OpenGL renderer
E2M9E2M9 Classic rendererE2M9 OpenGL renderer
DOOM — Episode 3 (E3M1–E3M9)
LevelClassicOpenGL
E3M1E3M1 Classic rendererE3M1 OpenGL renderer
E3M2E3M2 Classic rendererE3M2 OpenGL renderer
E3M3E3M3 Classic rendererE3M3 OpenGL renderer
E3M4E3M4 Classic rendererE3M4 OpenGL renderer
E3M5E3M5 Classic rendererE3M5 OpenGL renderer
E3M6E3M6 Classic rendererE3M6 OpenGL renderer
E3M7E3M7 Classic rendererE3M7 OpenGL renderer
E3M8E3M8 Classic rendererE3M8 OpenGL renderer
E3M9E3M9 Classic rendererE3M9 OpenGL renderer
DOOM II — MAP01–MAP11
LevelClassicOpenGL
MAP01MAP01 Classic rendererMAP01 OpenGL renderer
MAP02MAP02 Classic rendererMAP02 OpenGL renderer
MAP03MAP03 Classic rendererMAP03 OpenGL renderer
MAP04MAP04 Classic rendererMAP04 OpenGL renderer
MAP05MAP05 Classic rendererMAP05 OpenGL renderer
MAP06MAP06 Classic rendererMAP06 OpenGL renderer
MAP07MAP07 Classic rendererMAP07 OpenGL renderer
MAP08MAP08 Classic rendererMAP08 OpenGL renderer
MAP09MAP09 Classic rendererMAP09 OpenGL renderer
MAP10MAP10 Classic rendererMAP10 OpenGL renderer
MAP11MAP11 Classic rendererMAP11 OpenGL renderer
DOOM II — MAP12–MAP20
LevelClassicOpenGL
MAP12MAP12 Classic rendererMAP12 OpenGL renderer
MAP13MAP13 Classic rendererMAP13 OpenGL renderer
MAP14MAP14 Classic rendererMAP14 OpenGL renderer
MAP15MAP15 Classic rendererMAP15 OpenGL renderer
MAP16MAP16 Classic rendererMAP16 OpenGL renderer
MAP17MAP17 Classic rendererMAP17 OpenGL renderer
MAP18MAP18 Classic rendererMAP18 OpenGL renderer
MAP19MAP19 Classic rendererMAP19 OpenGL renderer
MAP20MAP20 Classic rendererMAP20 OpenGL renderer
DOOM II — MAP21–MAP32
LevelClassicOpenGL
MAP21MAP21 Classic rendererMAP21 OpenGL renderer
MAP22MAP22 Classic rendererMAP22 OpenGL renderer
MAP23MAP23 Classic rendererMAP23 OpenGL renderer
MAP24MAP24 Classic rendererMAP24 OpenGL renderer
MAP25MAP25 Classic rendererMAP25 OpenGL renderer
MAP26MAP26 Classic rendererMAP26 OpenGL renderer
MAP27MAP27 Classic rendererMAP27 OpenGL renderer
MAP28MAP28 Classic rendererMAP28 OpenGL renderer
MAP29MAP29 Classic rendererMAP29 OpenGL renderer
MAP30MAP30 Classic rendererMAP30 OpenGL renderer
MAP31MAP31 Classic rendererMAP31 OpenGL renderer
MAP32MAP32 Classic rendererMAP32 OpenGL renderer

Regenerate the gallery from local IWADs with:

.\tools\capture_readme_gallery.ps1

Project Goals

  • Port original DOOM engine logic to MiniLang as faithfully as possible.
  • Preserve classic gameplay behavior (movement, combat, AI, doors/switches/triggers, HUD/menu flow).
  • Keep rendering semantics close to the original pipeline (BSP, walls, visplanes, sprites, clipping).
  • Run as a native Windows x64 executable or Linux x64 ELF built with the MiniLang compiler.

How This Port Was Built

  • The original C/H codebase was mapped module-by-module to MiniLang.
  • In most cases, one gameplay/render/system C module is represented by one MiniLang file.
  • Data structures (struct, enums, tables, globals) were ported explicitly.
  • Platform services use Win32 on Windows and a compact SDL2/OpenGL bridge on Linux.
  • The Python build flow selects the correct native helpers and handles Windows EXE icon injection.

Repository Structure

MiniDoom/
  src/                       # MiniLang game/engine source files and platform bindings
  docs/api/                  # Generated MiniDoc HTML and Markdown reference
  docs/gallery/              # Classic/OpenGL level comparison screenshots
  icons/                     # PNG + ICO assets for EXE icon resources
  tests/                     # Smoke, renderer, console, multiplayer, and regression tests
  tools/
    capture_readme_gallery.ps1 # Regenerates the README screenshot gallery
    check_source_comments.ps1 # Audits MiniDoc declaration documentation
    generate_minidoc.ps1     # Checks or regenerates the API reference
    exe_icon_injector.ml     # MiniLang tool: injects .ico into Windows .exe resources
    minidoom_gl_helper.c     # Cross-platform accelerated rendering helper
    minidoom_linux_platform.c # Linux SDL2 window/input/audio bridge
  build.py                   # Windows/Linux native build orchestrator
  minidoc.toml               # Strict MiniDoc project configuration
  THIRD_PARTY_NOTICES.md     # Notices for bundled Linux audio components
  LICENSE
  README.md

Prerequisites

  • Windows x64 or Linux x64
  • Python 3.10+ (recommended: 3.11+)
  • MiniLang compiler (Python implementation):
    MiniLangCompilerPy
  • Compiler version 1.1.0 or newer with windows-x64 and linux-x64 targets
  • Windows builds: MSVC x64 build tools and the Windows 10/11 SDK
  • Linux builds: GCC, the SDL2 runtime (libSDL2-2.0.so.0), OpenGL (libGL.so.1), FluidSynth (libfluidsynth.so.3), and a GM SoundFont
  • A legally obtained DOOM IWAD such as DOOM.WAD, DOOM1.WAD, or DOOM2.WAD

IWAD, PWAD, generated HDWAD, configuration, and save files are not shipped in the repository or release archives.

Source Documentation

MiniDoom uses MiniDoc's native //! file comments and /// declaration comments, including parameter and return contracts. The generated reference is available as repository-friendly Markdown and as an offline HTML site at docs/api/html/index.html.

Regenerate both formats with a current MiniDoc and MiniLang compiler checkout:

pwsh .\tools\generate_minidoc.ps1 `
  -MiniDoc "C:\path\to\MiniDoc\build\minidoc.exe" `
  -CompilerRoot "C:\path\to\MiniLangCompilerPy"

Use -Check to perform the same strict documentation validation without rewriting generated files.

Build MiniDoom (Recommended)

Use build.py from this repository root.

Windows x64

python .\build.py `
  --compiler "C:\path\to\MiniLangCompilerPy\mlc_win64.py" `
  --std "C:\path\to\MiniLangCompilerPy\std" `
  --target windows-x64

What this does:

  1. Builds MiniDoomGL.dll
  2. Compiles tools/exe_icon_injector.ml
  3. Compiles src/i_main.ml to build/MiniDoom.exe
  4. Injects icons/MiniDoom.ico into the executable

Final output:

build/MiniDoom.exe
build/MiniDoomGL.dll

Linux x64

On Linux, install GCC plus the SDL2 and OpenGL runtime libraries, then run:

sudo apt install gcc libsdl2-2.0-0 libgl1 libfluidsynth3 musescore-general-soundfont-small
python3 ./build.py \
  --compiler /path/to/MiniLangCompilerPy/mlc_win64.py \
  --std /path/to/MiniLangCompilerPy/std \
  --target linux-x64 \
  --clean

The same Linux build can be cross-built from Windows when WSL with GCC is available:

python .\build.py `
  --compiler "C:\path\to\MiniLangCompilerPy\mlc_win64.py" `
  --std "C:\path\to\MiniLangCompilerPy\std" `
  --target linux-x64 `
  --clean

Linux output is placed in build/linux/:

build/linux/MiniDoom
build/linux/run-minidoom
build/linux/libMiniDoomPlatform.so
build/linux/libMiniDoomGL.so

Use run-minidoom; it sets the local shared-library search path before starting the ELF. Both the classic and OpenGL renderers, keyboard/mouse input, SDL2 sound effects, screenshots, saves, and UDP multiplayer use native Linux services. Doom's MUS tracks play through FluidSynth. The prebuilt release includes FluidSynth and the MIT-licensed MuseScore General Lite SoundFont, so it needs no MIDI daemon or extra SoundFont installation.

For a source build, install libfluidsynth.so.3 and place a compatible GM SoundFont beside the executable as MiniDoom.sf3/MiniDoom.sf2, or select one with MINIDOOM_SOUNDFONT=/path/to/soundfont.sf3. Release builders can copy a self-contained runtime into the output directory with:

python3 ./build.py \
  --compiler /path/to/MiniLangCompilerPy/mlc_win64.py \
  --std /path/to/MiniLangCompilerPy/std \
  --target linux-x64 \
  --linux-music-runtime /path/to/runtime \
  --clean

The runtime directory must contain libfluidsynth.so.3, libinstpatch-1.0.so.2, and MiniDoom.sf3. See THIRD_PARTY_NOTICES.md for licenses and attribution.

Useful Build Options

  • --output-dir <path>: change output directory
  • --target windows-x64|linux-x64: choose PE or ELF output
  • --skip-icon: build without icon injection
  • --clean: remove output directory before build
  • --icon <path.ico>: use a custom icon file
  • --icon-group <id> / --icon-lang <id>: resource ids for icon injection
  • --skip-gl-helper: reuse an existing Windows MiniDoomGL.dll without rebuilding it (Linux always builds its helpers)
  • --linux-music-runtime <path>: bundle FluidSynth, libinstpatch, and MiniDoom.sf3 in a Linux build

Build MiniDoom Manually (Without build.py)

Compile directly via MiniLang compiler:

python C:\path\to\mlc_win64.py `
  .\src\i_main.ml `
  .\MiniDoom.exe `
  -I .\src `
  -I C:\path\to\MiniLangCompilerPy `
  --target windows-x64 `
  --subsystem windows

If you want the EXE icon embedded, build and run the icon injector:

python C:\path\to\mlc_win64.py `
  .\tools\exe_icon_injector.ml `
  .\exe_icon_injector.exe `
  -I .\src `
  -I C:\path\to\MiniLangCompilerPy `
  --target windows-x64 `
  --subsystem console

.\exe_icon_injector.exe .\MiniDoom.exe .\icons\MiniDoom.ico

Running MiniDoom

Example run:

.\build\MiniDoom.exe -iwad "C:\Games\DOOM\DOOM2.WAD"

Linux:

./build/linux/run-minidoom -iwad "$HOME/games/doom/DOOM2.WAD"

If no -iwad is provided, the engine uses its internal IWAD search order and loads the first matching file it finds.

OpenGL Renderer and Frame Pacing

The classic renderer remains the default. Start the accelerated 3D renderer with:

.\build\MiniDoom.exe -iwad "C:\Games\DOOM\DOOM2.WAD" -windowed -opengl
./build/linux/run-minidoom -iwad "$HOME/games/doom/DOOM2.WAD" -windowed -opengl

Press Alt+G while running to switch between OpenGL and the classic pixel renderer. OpenGL uses VSync by default to avoid tearing and uneven presentation. Runtime options:

  • -novsync: disable VSync (useful for profiling)
  • -vsync: explicitly enable VSync
  • -maxfps <0..1000>: apply an additional frame-rate cap; 0 disables that cap
  • -profile-render: write per-second frame percentiles and renderer-stage timings to minidoom_profile.log

If the graphics driver does not expose swap-interval control, MiniDoom falls back to a 60 FPS high-resolution limiter.

Drop-Down Console and Classic Cheats

Open or close the in-game console with ~, Ö, or ^ (depending on the active keyboard layout; German AltGr++ is also supported). The console slides over the upper third of the screen, pauses the current single-player game, and captures all movement and fire input while it is open. HUD notices, multiplayer chat, errors, and command results are mirrored into its scrollback.

MiniDoom drop-down console showing the built-in help

Console controls:

  • Enter: execute the current command.
  • Up / Down: navigate command history.
  • Page Up / Page Down: scroll the log.
  • Escape: close the console.

Available commands:

Command Effect
help Show console controls and utility commands.
cheats List all gameplay cheats.
iddqd Toggle god mode.
idkfa Give all weapons, full ammo, armor, and all keys.
idfa Give all weapons, full ammo, and armor without keys.
idclip Toggle wall collision.
idclev <NN> Warp to MAPNN, or to episode/map ExMy for episodic DOOM.
invisible Toggle persistent notarget mode; monsters do not react to the player.
freeze Freeze monsters, animations, and world specials while leaving player movement active.
kill monsters Kill all active monsters in the current level.
name [Player Name] Show or change the local player name. Active multiplayer sessions receive the change immediately.
fps Toggle the on-screen FPS display.
clear Clear console scrollback.
quit Exit MiniDoom.

Gameplay-changing cheats are single-player only to prevent multiplayer desynchronization. The original quick-warp form also works without opening the console: type idclev12 during normal play for DOOM II MAP12, or idclev23 for DOOM E2M3. These typed cheat keys do not block ordinary movement controls.

Automatic HDWAD Cache

The OpenGL renderer uses a generated sidecar cache next to the selected IWAD:

DOOM2.WAD
DOOM2.WAD.hdwad

When -opengl is requested and no valid sidecar exists, MiniDoom builds it automatically. The cache contains palette-aware 3× wall textures, flats, sprites, HUD/menu graphics, fonts, full-screen patches, and precomputed OpenGL geometry for every discovered map. A loading screen reports the current phase, percentage, and estimated remaining time.

Useful options:

  • -rebuildhdwad: regenerate the automatic cache even when a valid one exists.
  • -hdwad <path>: load an explicitly selected HDWAD instead of auto-generating one.
  • -nohdwad: disable automatic cache attachment/generation for diagnostics.

The generated file can be several hundred megabytes. It is renderer-only, excluded from multiplayer WAD fingerprints, and can be deleted safely; the next OpenGL start will recreate it. Classic rendering does not require an HDWAD.

Multiplayer Mode

MiniDoom includes an in-game UDP multiplayer mode with host-authoritative simulation.

Current Capabilities

  • Up to 4 players total (slots 0..3).
  • Modes: Coop and Deathmatch.
  • Host-configurable map, skill, max players, frag limit, and time limit.
  • Player names (max 25 characters), including host-authoritative runtime renaming through name <Player Name> in the console.
  • HUD join/leave/kill messages and chat relay.
  • Intermission/state synchronization between peers.

Start Multiplayer From the Main Menu

  1. Open Multiplayer from the main menu.
  2. Choose one of:
    • Host Game
    • Join Game
    • Player Name

Host Game

In Host Game, configure:

  • Mode (COOP / DEATHMATCH)
  • Map
  • Skill
  • Max Players
  • Frag Limit (0 = unlimited)
  • Time Limit (0 = unlimited)
  • Port (default: 2342)

Then select Start Host.

Join Game

In Join Game, set:

  • Host (numeric IPv4 address, for example 127.0.0.1)
  • Port (must match host)

Then select Join.

Start Multiplayer From the Command Line

The command-line path uses the same host/join handshake and game bootstrap as the menus. Start a host with:

.\build\MiniDoom.exe -iwad "C:\Games\DOOM\DOOM2.WAD" -mp-host 2342 -mp-mode coop -mp-map MAP01 -mp-skill 2 -mp-maxplayers 4 -mp-fraglimit 0 -mp-timelimit 0 -mp-name Host

Join it from another process or machine with:

.\build\MiniDoom.exe -iwad "C:\Games\DOOM\DOOM2.WAD" -mp-join 127.0.0.1 2342 -mp-name Marine

Available options:

  • -mp-host <port>: host a session on UDP port 1..65535.
  • -mp-join <numeric-ipv4> <port>: join a host; DNS hostnames are not currently accepted.
  • -mp-mode <coop|deathmatch>: select the host game mode.
  • -mp-map <MAP01|E1M1>: select a map present in the loaded WAD set.
  • -mp-skill <0..4>: select the host skill from baby through nightmare.
  • -mp-maxplayers <2..4>: cap total active slots, including the host.
  • -mp-fraglimit <0..999> and -mp-timelimit <0..180>: configure deathmatch limits; zero disables a limit.
  • -mp-name <name>: set the local sanitized player name (up to 25 characters).
  • -mp-log <path>: write machine-readable connection, slot, map, and disconnect status lines to a per-process log. Runtime continues on stdout if the file cannot be opened.

WAD Compatibility Check

On host and client startup for multiplayer, MiniDoom computes a load-order-sensitive fingerprint (FNV-1a) over the IWAD and all gameplay PWADs. Optional generated .hdwad rendering caches are excluded. Join is rejected if fingerprints do not match.

Practical recommendation: all players should use the same IWAD/PWAD files in the same load order.

Chat

  • Press T in-game to open chat input.
  • Send with Enter.
  • Messages are relayed host-authoritatively and shown as:
    • <PlayerName>: <message>
  • Use name <Player Name> in the drop-down console to rename yourself while connected. The host validates the sender slot and distributes the refreshed name table to every client, including late joiners.

Player names accept ASCII letters, digits, spaces, hyphens, and underscores. Leading/trailing spaces are removed and names are limited to 25 characters.

Networking Model (High Level)

  • Transport: UDP.
  • Server-authoritative world state.
  • Clients send inputs; host simulates the world and sends snapshots/events.

Multiplayer Troubleshooting

  • Host did not respond (timeout): verify host address/port and firewall/NAT rules.
  • WAD fingerprint mismatch: ensure all peers use the same IWAD.
  • Server full: lower active players or increase max players (up to 4).

Tests and Source Audit

The PowerShell test harness covers software/OpenGL rendering, renderer toggling, sprites, wall offsets, moving geometry, sky behavior, wipes, console commands, frame pacing, invisibility, HDWAD generation, and multiplayer transport/loopback.

pwsh .\tests\run_tests.ps1 `
  -Compiler "C:\path\to\MiniLangCompilerPy\mlc_win64.py" `
  -Std "C:\path\to\MiniLangCompilerPy\std" `
  -Iwad "C:\Games\DOOM\DOOM2.WAD"

pwsh .\tools\check_source_comments.ps1 -Summary

Notes vs Original DOOM

  • Core engine behavior targets original DOOM parity while using MiniLang runtime semantics.
  • Platform services are adapted to native Win32 and Linux SDL2/OpenGL execution.
  • Build and tooling are modernized (single Python build script + MiniLang resource tool).

License

See LICENSE.

About

MiniLang port of DOOM with classic and OpenGL renderers, multiplayer, console, and native Windows/Linux x64 builds.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages