Skip to content

Latest commit

 

History

44 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MiniDoom

MiniDoom is a full MiniLang port of the original DOOM engine codebase, focused on gameplay parity, classic behavior, and native Windows 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).

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 executable (MiniDoom.exe) 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.
  • Win32-facing parts (graphics/audio/system) are implemented via native bindings used by MiniLang.
  • The build flow is automated with a Python script that also handles EXE icon injection.

Repository Structure

MiniDoom/
  src/                       # MiniLang game/engine source files
  docs/gallery/              # Classic/OpenGL level comparison screenshots
  icons/                     # PNG + ICO assets for EXE icon resources
  tools/
    capture_readme_gallery.ps1 # Regenerates the README screenshot gallery
    exe_icon_injector.ml     # MiniLang tool: injects .ico into Windows .exe resources
  build.py                   # Main build script (builds tool + MiniDoom + icon injection)
  LICENSE
  README.md

Prerequisites

  • Windows (x64)
  • Python 3.10+ (recommended: 3.11+)
  • MiniLang compiler (Python implementation):
    MiniLangCompilerPy
  • A DOOM IWAD file (for example DOOM.WAD, DOOM1.WAD, DOOM2.WAD) for runtime testing

Note: IWAD files are not shipped with this repository.

Build MiniDoom (Recommended)

Use build.py from this repository root.

Example

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

What this does:

  1. Compiles tools/exe_icon_injector.ml to build/tools/exe_icon_injector.exe
  2. Compiles tools/wad_upscale.ml to build/tools/wad_upscale.exe
  3. Compiles src/i_main.ml to build/MiniDoom.exe
  4. Injects icons/MiniDoom.ico into build/MiniDoom.exe

Final output:

build/MiniDoom.exe
build/tools/wad_upscale.exe

Useful Build Options

  • --output-dir <path>: change output directory
  • --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-upscale-tool: build without tools/wad_upscale.ml

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 `
  --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 `
  --subsystem console

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

Running MiniDoom

Example run:

.\build\MiniDoom.exe -iwad "C:\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" -opengl

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.

Optional Upscaled Graphics

MiniDoom can load an optional sidecar graphics package next to the original WAD:

DOOM2.WAD
DOOM2.WAD.UPSCALED

Generate the package with palette-aware xBRZ scaling:

.\build\tools\wad_upscale.exe "C:\Games\DOOM\DOOM2.WAD" "C:\Games\DOOM\DOOM2.WAD.UPSCALED" 2

Run with a physical presentation scale and the package:

.\build\MiniDoom.exe -iwad "C:\Games\DOOM\DOOM2.WAD" -renderscale 2 -upscaled "C:\Games\DOOM\DOOM2.WAD.UPSCALED"

If -upscaled is omitted, MiniDoom automatically tries <iwad>.UPSCALED. Missing upscaled graphics fall back to the original WAD.

The upscaled package stores prepared wall textures, flats, sprites, HUD/menu patches, fonts, and full-screen patch graphics. During normal high-resolution gameplay, MiniDoom consumes those prepared images directly; the xBRZ-style scaler belongs to the offline wad_upscale tool rather than the frame loop.

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).
  • 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>

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).

Notes vs Original DOOM

  • Core engine behavior targets original DOOM parity while using MiniLang runtime semantics.
  • Platform layer is adapted for modern Windows execution.
  • Build and tooling are modernized (single Python build script + MiniLang resource tool).

License

See LICENSE.

About

MiniDoom is a complete port of the original DOOM source code to MiniLang, created entirely with AI assistance

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages