Files
OpenRA3/README.md
T

6.1 KiB

OpenRA3

A from-scratch, portable re-implementation of Command & Conquer: Red Alert 3 in C++26 using C++ modules, built with GCC 16.

Red Alert 3 runs SAGE 2.0. EA never released that engine's C++ source, but it did open-source the closely related SAGE 1.0 engine as electronicarts/CnC_Generals_Zero_Hour (GPLv3). OpenRA3 uses that tree as the architectural reference and reconstructs the RA3-specific behaviour by decompiling the retail ra3_1.12.game binary with Ghidra.

OpenRA3 ships no game assets or binaries. You must own Red Alert 3. The engine reads your own local installation at runtime; nothing from it is ever copied into this repository. Command & Conquer and Red Alert are trademarks of Electronic Arts; this project is unaffiliated with and unsupported by EA.

Status

OpenRA3 is at v0.0.1. The engine compiles and runs headless, and a minimal skirmish is playable: it reads a real multiplayer map out of your install, recovers the player start waypoints, and simulates two sides earning credits, training units and fighting until one base falls. The map and match state can be rendered to a window (SDL3) or to an image.

$ openra3 skirmish --game-dir "/game" --map map_mp_2_feasel4
OpenRA3 skirmish  map=map_mp_2_feasel4  source=archive:map_mp_2_feasel4  seed=1
start positions:
  P0 (1338, 1940)
  P1 (1291, 1404)
result: decided  winner=0  frames=3397 (113.2 s)
  P0 Commander  Allied  money=   129 units=19 kills=21 losses=3
  P1 AI         Soviet  money=   840 units= 0 kills=3 losses=21

Offline only

OpenRA3 implements offline skirmish and, eventually, LAN/single-player. There is deliberately no online mode: no EA account, no online service, no matchmaking, no GameSpy/Steam integration, and no networking in the simulation. The match loop is deterministic and self-contained so it can be replayed and tested without any external service.

Assets

The engine reads the retail game from your local install:

  • default path C:\Red Alert 3, or --game-dir DIR, or $RA3_GAME_DIR;
  • Data\MapsMultiplayer.big is read for the map catalog;
  • maps are unpacked from BIG4 + RefPack and their start waypoints recovered.

No game data is committed or distributed. reference/ (the GPLv3 Generals source) and any extracted assets are git-ignored; tools/fetch_reference.sh fetches the former on demand. Without an install, the engine falls back to a built-in test map so the project still builds and runs in CI.

Layout

Path Purpose
src/core/ra3.core.cppm fundamental types, math, strings, random, message stream
src/logic/ra3.logic.cppm objects, players, teams, spatial partition, game loop
src/client/ra3.client.cppm display abstraction + client facade / frame loop
src/game/ra3.game.cppm RA3 sides, player templates, skirmish defaults
src/fs/ra3.fs.cppm BIG4 archives, RefPack codec, local install locator
src/map/ra3.map.cppm map catalog, EAR/RefPack unwrap, start waypoints
src/skirmish/ra3.skirmish.cppm units, economy, AI, combat, win condition
src/render/ra3.render.cppm ARGB framebuffer, TGA decode, BMP encode, map compositing
src/ui/ra3.ui.*.cppm SDL3 window viewer (null backend when SDL3 is absent)
src/ra3.cppm umbrella module re-exporting the SDK
apps/openra3/main.cpp maps / skirmish CLI
tests/ra3_tests.cpp smoke tests (run via ctest)
tools/ reference fetch + Ghidra-driven reconstruction helpers
docs/ architecture, reverse-engineering notes, roadmap
Dockerfile dev (toolchain) and deploy (runtime) targets
.gitlab-ci.yml build → test → package pipeline

Build

The host needs no toolchain: build inside the container.

docker build --target dev -t openra3-dev:local .

docker run --rm -v "$PWD:/work" -w /work openra3-dev:local cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
docker run --rm -v "$PWD:/work" -w /work openra3-dev:local cmake --build build -j
docker run --rm -v "$PWD:/work" -w /work openra3-dev:local ctest --test-dir build --output-on-failure

Behind a slow or blocked mirror, pass --build-arg APT_MIRROR=<url>.

Running a skirmish

# list the maps in your install
docker run --rm -v "/path/to/Red Alert 3:/game:ro" openra3-dev:local \
    ./build/bin/openra3 maps --game-dir /game

# play a headless skirmish on a real map
docker run --rm -v "/path/to/Red Alert 3:/game:ro" openra3-dev:local \
    ./build/bin/openra3 skirmish --game-dir /game --map map_mp_2_feasel4 --seed 7

--frames N caps the simulation length (default 15 minutes of game time at 30 Hz). The result is deterministic for a given map and seed.

Rendering the map

The renderer draws the map's own overview art, a world grid and the match state (start markers in yellow, player 0 in blue, player 1 in red).

Offscreen image (works anywhere, no display needed):

docker run --rm -v "/path/to/Red Alert 3:/game:ro" -v "$PWD/out:/out" openra3-dev:local \
    /work/build/bin/openra3 render --game-dir /game --map map_mp_2_feasel4 --out /out/map.bmp

Interactive window (SDL3; drag to pan, wheel to zoom, Esc to quit). In a container you need an X server on the host — on Windows run VcXsrv and launch it with "Disable access control", then:

docker run --rm -v "/path/to/Red Alert 3:/game:ro" -e DISPLAY=host.docker.internal:0.0 \
    openra3-dev:local /work/build/bin/openra3 render --game-dir /game --map map_mp_2_feasel4

If no display is available the viewer falls back to writing openra3_view.bmp. The unit overlay uses an approximate world scale (--world-size, default 5120); exact calibration from the map's heightmap is on the roadmap.

Reverse engineering

The reconstruction is driven by Ghidra against the retail binary. See docs/REVERSE_ENGINEERING.md for the workflow and the recovered symbol map, and tools/ for the helpers.

License

Project code: GPLv3, matching the CnC_Generals_Zero_Hour reference (see LICENSE).