Relevant source files
This document provides a comprehensive overview of the core game engine components in the Cloudflare Doom WASM project. It describes the main subsystems that make up the Doom engine, their purposes, and how they interact to create the game experience. For information about the networking system specifically, see Networking, and for build system details, see Build System.
Core Engine Architecture
The Doom engine is organized into several interconnected subsystems, each responsible for specific aspects of the game's functionality. The engine's architecture follows a modular design pattern with clear separation of concerns.
Sources: src/Makefile.am13-84
Main System Initialization
The engine initialization begins in i_main.c
, which contains the entry point of the application. This module initializes the system interface (i_system.c
), which then initializes the various subsystems before starting the game loop.
The initialization sequence:
- Parse command-line arguments
- Initialize system-dependent interfaces
- Set up subsystems (video, audio, input, timer)
- Load game resources
- Start the game loop
Sources: src/Makefile.am15-19
Game Loop Architecture
The game loop is the heart of the engine, coordinating all subsystems to create the game experience. It's implemented in d_loop.c
and follows a fixed-time-step pattern.
The game loop maintains a fixed cadence of game updates (ticks) regardless of rendering performance, ensuring consistent gameplay across different systems.
Sources: src/Makefile.am29
Subsystems
Video Subsystem
The video subsystem handles all aspects of rendering the game to the screen.
Key components:
i_video.c
: Interfaces with SDL to create the display window and handle renderingv_video.c
: Contains higher-level drawing functionsv_diskicon.c
: Manages the disk activity indicatorv_patch.h
: Defines structures for graphics patches
In the WASM port, rendering is performed to an HTML Canvas element rather than a traditional window.
Sources: src/Makefile.am47-48 src/Makefile.am73-75
Sound Subsystem
The sound subsystem manages audio effects and music playback.
Key components:
i_sound.c
: Main interface for sound functionalityi_sdlsound.c
: SDL-specific sound implementationi_sdlmusic.c
: SDL-specific music implementationi_oplmusic.c
: OPL (FM synthesis) music implementationi_pcsound.c
: PC speaker emulationmus2mid.c
: Converts MUS format music to MIDI
The WASM port uses the browser's audio capabilities via SDL's audio abstraction.
Sources: src/Makefile.am41-46
Input Subsystem
The input subsystem processes player input from keyboard, mouse, and joystick.
Key components:
i_input.c
: Manages input event processingi_joystick.c
: Handles joystick inputm_controls.c
: Manages control bindings and configuration
In the WASM port, browser keyboard and mouse events are translated into the appropriate input events for the game engine.
Sources: src/Makefile.am37-38 src/Makefile.am55
Timer Subsystem
The timer subsystem manages game timing and synchronization, which is critical for maintaining consistent game speed.
Key functions:
I_InitTimer()
: Initializes the timer system using SDLI_GetTime()
: Returns time in 1/35th second tics (game's internal time unit)I_GetTimeMS()
: Returns time in millisecondsI_Sleep()
: Pauses execution for a specified time usingemscripten_sleep()
I_WaitVBL()
: Waits for a specified number of vertical blanks (1/70th of a second)
The timer system uses SDL's timing functions to track time, with a special adaptation for the WebAssembly environment using emscripten_sleep()
instead of SDL_Delay()
for the sleep functionality.
Sources: src/i_timer.c1-85
Resource Management
The resource management subsystem loads and manages game assets from WAD files.
Key components:
w_wad.c
: Core WAD file loading and lump managementw_file.c
: File I/O abstractionw_merge.c
: Merges multiple WAD filesw_checksum.c
: Computes checksums for WAD validationw_main.c
: Initialization and shutdown of the WAD system
In the WebAssembly port, WAD files are loaded into the browser's virtual file system before being accessed by the resource management subsystem.
Sources: src/Makefile.am76-84
Memory Management
Memory management in Doom is handled by the zone memory allocator in z_zone.c
. This custom memory allocator provides features such as:
- Block allocation with tags for grouped freeing
- Memory purging under low-memory conditions
- Debugging facilities for memory leaks
Sources: src/Makefile.am84
Component Interactions
The engine components interact in a structured manner to create the game experience. Here's an overview of key interactions:
Sources: src/Makefile.am15-84
Data Flow Between Components
The engine components exchange data through several key channels:
Game Tic Commands: Input events are collected and converted into "ticcmds" (
d_ticcmd.h
), which represent player actions for a single game tic.Game State: The game state includes the world state, player positions, monster states, etc., and is updated by the game logic component based on ticcmds.
Rendering Data: The game state is processed to create rendering instructions for the video subsystem.
Sound Requests: Sound effects and music commands are sent to the sound subsystem.
Network Messages: For multiplayer, network packets synchronize game state between clients.
Sources: src/Makefile.am30-31
WebAssembly-Specific Adaptations
The Doom engine has been adapted for the WebAssembly environment with several modifications:
Timer System: Uses
emscripten_sleep()
instead ofSDL_Delay()
for better browser integration.Input Handling: Adapted to work with browser keyboard and mouse events.
File System: Uses Emscripten's virtual file system to load WAD files in the browser.
Networking: Reimplemented using WebSockets for browser compatibility. For details, see WebSockets Integration.
Audio: Adapted to use the browser's Web Audio API via SDL's audio abstraction.
Sources: src/i_timer.c64-68 src/Makefile.am64
Performance Considerations
The Doom engine is designed for efficiency, with several performance optimizations:
Fixed-point math: Uses fixed-point arithmetic (
m_fixed.c
) for consistent calculations across platforms.Precalculated tables: Many mathematical operations use lookup tables (
tables.c
) for speed.Custom memory management: The zone allocator minimizes fragmentation and provides fast allocation.
Rendering optimizations: The renderer uses BSP trees and PVS (Potentially Visible Sets) to minimize overdraw.
In the WebAssembly environment, performance is further optimized through Emscripten compilation flags and browser-specific adaptations.
Sources: src/Makefile.am54 src/Makefile.am72
Conclusion
The Doom engine's component architecture provides a robust foundation for the game, with clear separation of concerns and well-defined interfaces between subsystems. The WebAssembly port maintains this architecture while adapting specific components to work in the browser environment, particularly the timer, input, and networking subsystems.
For detailed information on specific subsystems, refer to their dedicated wiki pages:
- Timer System - For in-depth information about the timer implementation
- Networking - For details on the multiplayer networking system
- Browser Integration - For browser-specific adaptations