docs: rewrite ARCHITECTURE as a Module/Function/Feature master plan

Decompose the full Red Alert 3 feature set three levels deep (29 modules, 169 functions, ~500 features) with per-feature status and milestone tags. Fold the release roadmap into ARCHITECTURE section 5 and remove docs/ROADMAP.md.
This commit is contained in:
EnderTheCoder
2026-09-26 22:28:19 +08:00
parent a7612878e5
commit 59261868e1
3 changed files with 741 additions and 162 deletions
+1 -1
View File
@@ -97,7 +97,7 @@ built-in test map so the project still builds and runs in CI.
| `apps/openra3/main.cpp` | `menu` / `maps` / `skirmish` / `render` CLI |
| `tests/ra3_tests.cpp` | smoke tests (run via `ctest`) |
| `tools/` | reference fetch + Ghidra-driven reconstruction helpers |
| `docs/` | architecture, reverse-engineering notes, roadmap |
| `docs/` | architecture & master plan, reverse-engineering notes |
| `Dockerfile` | Linux build image (`dev` toolchain + `deploy` runtime) |
| `Dockerfile.win` | isolated Windows cross-build image (llvm-mingw + SDL3 MinGW) |
| `cmake/toolchains/` | `llvm-mingw-x86_64.cmake` cross toolchain |
+740 -101
View File
@@ -1,131 +1,770 @@
# Architecture
# Architecture & Master Plan
OpenRA3 is organised as a stack of C++26 modules. Each layer may import the ones
below it, never the ones above. Every module uses `import std;` for the standard
library; the engine is built with Clang + libc++ on Linux and cross-compiled
with llvm-mingw for Windows.
OpenRA3 is a from-scratch, portable re-implementation of **Command & Conquer:
Red Alert 3** (SAGE 2.0) in **pure C++26** — C++ modules, `import std;`, no
scripting language, no managed runtime, no other programming language anywhere
in the tree. It is built with Clang + libc++ on Linux and cross-compiled to
Windows with llvm-mingw.
This document is two things at once:
1. the **layer architecture** (how the modules sit on top of one another), and
2. the **master plan** — the complete Red Alert 3 feature set decomposed three
levels deep into **Module → Function → Feature**, each tagged with its
implementation status and target milestone.
The decomposition is the contract: every feature RA3 has is either implemented,
being implemented, or explicitly planned here. Nothing is silently dropped.
> **Scope.** Offline only. Single-player campaign, skirmish, Commander's
> Challenge and LAN lockstep — never an online service, matchmaking, EA account
> or GameSpy/Steam integration. The simulation is deterministic and
> self-contained. No game assets or binaries are shipped; the engine reads the
> user's own install at runtime.
---
## 1. Principles
Same five rules as the rest of the tree, restated because the plan is written
against them:
1. **Pure C++.** One language. No Lua, no JS, no C#, no Python at runtime.
Python is allowed *only* in offline build tooling (`tools/`, cmake helper
scripts), never linked into `openra3`.
2. **No raw owning pointers.** Ownership is `std::unique_ptr`; cross-references
are non-owning views (`thing *`, handles, indices).
3. **Portable simulation.** No platform API in the foundation or simulation
layers. All platform concerns live behind `display` / `audio` / `video`.
4. **Determinism.** Anything that can diverge between runs (RNG, iteration
order, float accumulation, hash order) is explicit, seeded and testable.
5. **RE-traceable.** Every structure or constant taken from the retail
`ra3_1.12.game` (image base `0x400000`) or from the GPLv3 SAGE 1.0 reference
cites its origin. No asserted fact without a source.
---
## 2. Layer architecture
Each layer may import the ones below it, never the ones above. The `ra3`
umbrella module re-exports the SDK; applications import `ra3` only.
```
┌───────────────────────────────────────┐
applications │ openra3 (apps/openra3) │
└───────────────────┬───────────────────┘
│ import ra3
┌───────────────────▼───────────────────┐
umbrella │ ra3 (re-exports everything) │
└───────────────────┬───────────────────┘
┌──────────────┬───────────────┼───────────────┬──────────────┐
▼ ▼ ▼ ▼ ▼
ra3.display ra3.render ra3.skirmish ra3.client ra3.game
backend pick framebuffer match rules display+loops RA3 sides
│ │ │ │ │
┌──┴───┐ │ └───────┬───────┘ │
▼ ▼ ▼ ▼ │
ra3.ui ra3.vulkan ra3.terrain ra3.logic │
SDL Vulkan heightmap/blends simulation │
┌──────────────────────┘
▼
ra3.map / ra3.fs
catalog / BIG4 + RefPack
L6 tooling / apps openra3 (CLI) tools/ (offline, Python allowed)
| import ra3
---------------------------------------------------------------------------
v
L5 meta ra3.i18n ra3.mod ra3.net (deferred)
|
L4 match services ra3.match ra3.replay ra3.save
|
L3 presentation ra3.client ── ra3.render ── ra3.audio ── ra3.video
| \ |
| \ v
| ra3.display (backend pick)
| / \
v ra3.ui ra3.vulkan
| (SDL3) (Vulkan)
---------------------------------------------------------------------------
v
L2 simulation ra3.logic ra3.modules ra3.combat ra3.movement
ra3.economy ra3.ai ra3.script ra3.powers ra3.shroud
|
L1 data & assets ra3.data ── ra3.assets ── ra3.map ── ra3.terrain
| |
v v
ra3.fs (BIG4 / RefPack / install)
|
L0 foundation ra3.core (types, math, containers, RNG, message bus)
```
## Presentation layer
The current concrete modules (`ra3.core`, `ra3.logic`, `ra3.data`,
`ra3.skirmish`, `ra3.fs`, `ra3.map`, `ra3.terrain`, `ra3.render`, `ra3.ui.*`,
`ra3.vulkan.*`, `ra3.display`, `ra3.game`, `ra3.client`) are the **seeds** of the
target modules below. `ra3.skirmish` and `ra3.game` will be absorbed into
`ra3.ai` / `ra3.match`; new modules are added as their subsystems are recovered.
`ra3.client::display` is the single seam between the engine and the windowing
stack. A backend implements only the low-level primitives (`init`, `present`,
`poll_event`, `window_size`, `key_down`, `shutdown`) and, optionally,
`present_terrain`; the interactive loops (menu, image viewer, camera viewer,
GPU terrain) and the native-to-`ui_event` mapping live once in the base class,
so the SDL and Vulkan paths cannot drift. SDL3 remains the platform layer (it
owns the window, input and the low-cost blit backend); Vulkan is the accelerated
backend. `ra3.display` selects the first backend that starts, and the app never
references a backend by name.
### Status legend
The Vulkan backend currently hand-rolls its pipelines. As materials, skybox and
HUD arrive, a thin RHI + render-graph belongs between `ra3.client` and the
Vulkan/SDL backends; `present_terrain` is the placeholder for that step.
| Tag | Meaning |
| --- | --- |
| `[x]` | implemented and tested on `main` |
| `[~]` | partially implemented / works for the happy path |
| `[ ]` | planned, not started |
| `(vX.Y)` | target milestone (see the roll-up in §5) |
| `!!` | needs reverse engineering before it can be built |
| Function tag | Meaning |
| --- | --- |
| `D` | **done** — the function's features are largely present |
| `P` | **partial** — some features present |
## Module responsibilities
---
### `ra3.core`
The vocabulary every other module shares, mirroring SAGE's `GameEngine/Common`:
`real`/`int32`/`uint32`, `coord3d`/`coord2d`/`rgb_color`, `ascii_string` +
`make_name_key`, the deterministic `random` stream, and the `message_stream`
command bus (node layout derived from retail `MessageStream::appendMessage`,
`0x0060c4a0`).
## 3. Master plan — Module → Function → Feature
### `ra3.logic`
The deterministic simulation, mirroring SAGE's `GameLogic`: `thing` → `object`
with pluggable `update_module`s, `player`/`player_list`, the `partition_manager`
spatial grid, and the 30 Hz `game_logic` driver (`prepare_new_game` /
`start_new_game` / `update`).
### M00 `ra3.core` — foundation vocabulary `[D]`
### `ra3.client`
The presentation boundary: the abstract `display` (low-level primitives plus the
shared interactive loops and `ui_event` mapping), a `headless_display` for
CPU-only runs, and `game_client`, the facade that owns the simulation and drives
the frame loop.
Mirrors SAGE `GameEngine/Common`. Everything else speaks this.
### `ra3.display`
Backend selection: tries Vulkan, then SDL, then reports failure so the caller can
fall back to an offscreen image. The only module that names a concrete backend.
- **F1 Types & math** `[D]`
- `[x]` `real` (float), `int32`/`uint32`/`uint16`/`uint8`, `bool` aliases
- `[x]` `coord2d` / `coord3d` vectors, dot/cross/length/normalize
- `[x]` `rgb_color` / `argb_color`, packing and lerp
- `[x]` geometry: `segment`, `triangle`, `plane`, ray/segment intersection
- `[ ]` fixed-point helpers for replay-stable accumulation `(v0.4)`
- `[ ]` matrix / quaternion (needed by W3D models) `(v0.6)`
- `[ ]` `KindOf` flag bitset (SAGE object taxonomy) `(v0.4)`
- **F2 Containers** `[D]`
- `[x]` `ascii_string` + `make_name_key` (case-folded hash for data lookup)
- `[x]` intrusive doubly linked list (message stream node layout)
- `[x]` deterministic iteration-order map (insertion-ordered)
- `[ ]` object pool / arena for per-frame allocations `(v0.4)`
- `[ ]` interned string table `(v0.5)`
- **F3 Deterministic RNG** `[D]`
- `[x]` seedable `random` stream (`game_logic` random)
- `[ ]` independent per-player / per-subsystem streams `(v0.4)`
- `[ ]` shuffle / weighted-pick primitives `(v0.4)`
- **F4 Message stream** `[D]`
- `[x]` command bus with retail node layout (`appendMessage` `0x0060c4a0`)
- `[x]` ordered per-frame command drain
- `[ ]` command argument blocks (build/target/waypoint payloads) `(v0.4)`
- `[ ]` network/replay source tagging `(v0.4)`
- **F5 Diagnostics** `[~]`
- `[x]` logging sink + assert macro
- `[ ]` scoped profiling timers, per-subsystem counters `(v0.4)`
- `[ ]` structured crash/report capture `(v0.8)`
- **F6 Serialization primitives** `[~]`
- `[x]` little-endian byte reader/writer
- `[ ]` chunked binary reader/writer with versioning `(v0.5)`
- `[ ]` stable content hashing (replay/desync checks) `(v0.4)`
- **F7 Localization primitives** `[~]` (see M26)
- `[x]` UTF-16 unit access, CSF low-byte `^0xFF` decode
- `[ ]` placeholder substitution, plural/gender rules `(v0.5)`
### `ra3.terrain`
The real map terrain: parses `CkMp`'s `HeightMapData` and `BlendTileData`
(tiles, `Blends`/`ThreeWayBlends` and their `BlendDescription`s), loads the
`Terrain.big` tile textures, and rasterises the map (software `render`/`render3d`
and the GPU `gpu_terrain` for `present_terrain`).
### M01 `ra3.fs` — containers & install `[D]`
### `ra3.game`
Red Alert 3 data that SAGE keeps in `PlayerTemplate`: the three sides
(`faction` flags `Empire=2`, `Allied=4`, `Soviet=8`, `Random=7`, recovered from
the retail skirmish setup) and skirmish defaults.
- **F1 BIG archive** `[D]`
- `[x]` `BIG4` header parse (`fileSize` LE, `fileCount`/offsets BE) + name index
- `[x]` payload read on demand (index-only resident memory)
- `[ ]` `BIGF` (RefPack whole-archive) variant `!!` `(v0.5)`
- `[ ]` write support (pack/repack, used by tooling) `(v0.8)`
- **F2 RefPack codec** `[D]`
- `[x]` decode: 2/3/4-byte commands, long-literal, stop opcode
- `[x]` `refpack_output_size` without full decompress
- `[ ]` encode (for tooling round-trips) `(v0.8)`
- **F3 Install locator** `[D]`
- `[x]` `--game-dir` / `$RA3_GAME_DIR` / `C:\Red Alert 3` defaults
- `[ ]` registry / Steam / EA-app discovery `(v0.5)`
- `[ ]` Uprising as an optional content source `(v0.5)`
- **F4 Virtual file system** `[~]`
- `[x]` layered archive mounts (loose files → `*.big`)
- `[ ]` patch/language precedence rules (newest `Lang-*.big` wins) `(v0.5)`
- `[ ]` case-insensitive lookup + path normalisation `(v0.5)`
- **F5 Extraction targets** `[D]`
- `[x]` `openra3 extract` dumps maps/terrain to `assets/`
- `[ ]` full asset dump via `ra3tools` integration as a build target `(v0.5)`
### `ra3.fs`
Reading the user's installation. Implements the `BIG4` archive container and
EA's RefPack codec, plus `find_game_dir` (`--game-dir` / `$RA3_GAME_DIR` /
`C:\Red Alert 3`). Only the archive index is held in memory; payloads are read
on demand.
### M02 `ra3.data` — data schema & balance `[P]`
### `ra3.map`
Map discovery and loading: scans `MapsMultiplayer.big` for main map entries,
unwraps the two compression layers (`BIG4` RefPack → `EAR\0` wrapper → RefPack →
`CkMp`), recovers `Player_N_Start` waypoint coordinates, and decodes the
localized display names from the install's `gamestrings.csf`. Degenerate
extractions are rejected so the caller can fall back.
- **F1 Data schema** `[ ]` `!!`
- `[ ]` SAGE INI parser (`#include`, `#define`, inheritance) `(v0.5)`
- `[ ]` XML rule schema
- `[ ]` `.manifest` compiled-blob schema `!!` `(v0.5)`
- **F2 Compiled asset blobs** `[ ]` `!!`
- `[ ]` `global.bin` deserialisation `(v0.5)`
- `[ ]` `static.*.bin` deserialisation `(v0.5)`
- `[ ]` version/dependency validation `(v0.5)`
- **F3 Balance tables** `[~]`
- `[x]` damage types, `ArmorTemplate` percentages
- `[x]` weapon target masks, weapon definitions
- `[x]` unit/structure build costs, times, prerequisites
- `[x]` ore economy constants
- `[ ]` read these from the install instead of pinned constants `(v0.5)`
- **F4 Object definitions** `[ ]`
- `[ ]` `ThingTemplate`/`ObjectTemplate` inheritance graph `(v0.5)`
- `[ ]` module descriptor lists (per-object update/draw module sets)
- `[ ]` `WeaponTemplate`/`ArmorTemplate`/`LocomotorTemplate` stores
- **F5 Faction & player templates** `[~]`
- `[x]` Allied / Soviet / Empire side flags (`2/4/8`), match templates
- `[ ]` commander/sub-commander definitions `(v0.7)`
- `[ ]` build/upgrade unlock trees per faction `(v0.5)`
- **F6 Rules & settings** `[ ]`
- `[ ]` skirmish options (cash, crates, superweapons, speed, limits)
- `[ ]` bonus crate effect table
- `[ ]` AI personality tables
- `[ ]` map-specific rule overrides (`map.ini`)
- **F7 Validation** `[ ]`
- `[ ]` schema diagnostics with source location
- `[ ]` cross-reference integrity (missing templates/refs)
### `ra3.skirmish`
The minimal match: two players, unit classes (harvester/infantry/tank/base),
passive + harvester income, a simple build AI, movement and combat on a fixed
30 Hz step, and a base-destruction win condition. Fully deterministic.
### M03 `ra3.assets` — runtime asset manager `[ ]`
### `ra3.render`
A dependency-free software renderer: an ARGB8888 `image` framebuffer with
blit/line/circle/text primitives (an embedded 8x8 bitmap font), a TGA decoder for
the game's map art, a 24-bit BMP encoder for headless output, and `compose` which
overlays a world grid and markers (start positions, live units) onto the map art.
- **F1 Textures** `[~]`
- `[x]` TGA decode (`ra3.render`); 256×256 terrain cells
- `[ ]` DDS / DXT compressed textures `(v0.5)`
- `[ ]` atlas + mip generation, gutter padding (GPU) `[~]`
- `[ ]` async upload / streaming `(v0.6)`
- **F2 Models** `[ ]` `!!`
- `[ ]` W3D container parse (chunks, hierarchy, meshes) `(v0.6)`
- `[ ]` materials, shaders, texture references
- `[ ]` LOD sets, collision meshes
- **F3 Animation** `[ ]` `!!`
- `[ ]` W3D animation chunks, bone poses `(v0.6)`
- `[ ]` blend trees / transition animations
- **F4 Audio** `[ ]` `!!`
- `[ ]` audio container + codec decode `(v0.7)`
- `[ ]` cue/event tables (unit responses, weapon foley)
- **F5 Fonts & glyphs** `[ ]`
- `[ ]` bitmap/vector font load; CJK coverage `(v0.5)`
- **F6 Asset registry** `[ ]`
- `[ ]` cache with ref counting, eviction `(v0.6)`
- `[ ]` name-key lookup into the data schema
- **F7 UI art (`.apt`)** `[ ]` `!!`
- `[ ]` RA3 interface art decode (HUD/command bar) `(v0.7)`
### `ra3.ui`
The SDL3 backend: `sdl_display` implements the `ra3.client::display` primitives
using an `SDL_Renderer` streaming texture. Cheap and dependency-light, it is the
fallback when Vulkan is unavailable. A null backend returns `false` so the build
still runs without SDL3.
### M04 `ra3.map` — map catalog & loader `[D]`
### `ra3.vulkan`
The accelerated backend: `vulkan_display` implements the same primitives and
adds `present_terrain`, a GPU heightfield raymarcher (mipmapped tile atlas with a
replicated gutter and the retail SAGE blend ramp). A null backend reports failure
when no Vulkan loader is present.
- **F1 Catalog** `[D]`
- `[x]` scan `MapsMultiplayer.big` for main map entries
- `[ ]` campaign + challenge map catalog `(v0.7)`
- **F2 Compiled map (`CkMp`)** `[D]`
- `[x]` double unwrap (`BIG4` RefPack → `EAR\0` → RefPack → `CkMp`)
- `[x]` name table + chunk list (`{index,version,size,data}`)
- `[ ]` full typed chunk dispatch for all chunk kinds `(v0.5)`
- **F3 Start positions** `[~]`
- `[x]` `Player_N_Start` waypoint scan → `coord3d`
- `[ ]` `MPPositionList` layout for maps without waypoints `!!` `(v0.5)`
- **F4 Metadata** `[~]`
- `[x]` display names from `gamestrings.csf` (`MAP:<ID>`)
- `[ ]` player count, size, supported game modes `(v0.5)`
- **F5 Map rules** `[ ]`
- `[ ]` `map.ini` override application `(v0.5)`
- **F6 Preview art** `[~]`
- `[x]` `<map>_art.tga` overview decode (`--thumbnail`)
- **F7 Validation & fallback** `[D]`
- `[x]` reject degenerate extractions, fall back to built-in test map
- `[ ]` integrity/version checks with actionable errors `(v0.5)`
## Design rules
### M05 `ra3.terrain` — terrain `[P]`
- **F1 Heightmap** `[D]`
- `[x]` `HeightMapData` v6 (grid, border, `u16` elevations, scale)
- `[ ]` multi-resolution / LOD height sampling `(v0.6)`
- **F2 Blend tiles** `[D]`
- `[x]` `BlendTileData` v27: tile grid, blends/three-way/cliff tables
- `[x]` `BlendDescription` parse; `secondaryTile` decode
- `[x]` retail `Terrain.fx` blend ramp (`blend_factor`, axis flags)
- **F3 Terrain textures** `[D]`
- `[x]` `art\terrain\*.tga` from `Terrain.big` / `Core11.big`
- `[x]` cell atlas with replicated gutter (GPU bleeding fix)
- `[ ]` continuous 32 px / Morton layout (kill residual grid lines) `(v0.4)`
- **F4 Water** `[ ]` `!!`
- `[ ]` water height/type, sea level `(v0.6)`
- `[ ]` animated waves + shoreline blending `(v0.6)`
- `[ ]` shroud-aware water rendering `(v0.6)`
- **F5 Cliffs & roads** `[ ]` `!!`
- `[x]` `CliffTextures` table parsed
- `[ ]` cliff mesh + `CliffTextureMapping` UV remap `(v0.6)`
- `[ ]` roads and bridges (passability + render) `(v0.6)`
- **F6 Terrain lighting** `[ ]`
- `[ ]` per-vertex normals, cell lighting, global light `(v0.6)`
- **F7 Terrain queries** `[~]`
- `[x]` height lookup (render)
- `[ ]` passability grid (ground/naval/amphibious/air) `(v0.4)`
- `[ ]` buildability grid (flatness, slope, water) `(v0.4)`
### M06 `ra3.logic` — simulation core `[P]`
- **F1 Objects & things** `[~]`
- `[x]` `thing` → `object` with pluggable `update_module`s
- `[x]` global object registry with stable ids
- `[ ]` handle/reference system (survives deletion) `(v0.4)`
- `[ ]` object destruction lifecycle + death dispatch `(v0.4)`
- **F2 Players & teams** `[~]`
- `[x]` `player` / `player_list`
- `[x]` money (`std::vector<Money*>`) and power fields
- `[x]` team assignment and relations
- `[ ]` diplomacy matrix, ally vision sharing `(v0.5)`
- **F3 Partition manager** `[~]`
- `[x]` spatial grid, neighborhood queries
- `[ ]` cell-resolution + large-object multi-cell registration `(v0.4)`
- **F4 Game loop** `[~]`
- `[x]` 30 Hz deterministic step with frame counter
- `[x]` `prepare_new_game` / `start_new_game` two-phase start
- `[ ]` per-tick module scheduling with stable ordering `(v0.4)`
- **F5 Commands** `[~]`
- `[x]` `message_stream` bus
- `[ ]` typed commands (build, attack, move, ability, sell, repair) `(v0.4)`
- `[ ]` command validation + feedback (insufficient funds, etc.) `(v0.4)`
- **F6 Determinism** `[~]`
- `[x]` seeded logic random
- `[ ]` replay-hash of state per tick `(v0.4)`
- `[ ]` float determinism policy / fixed-point where required `(v0.4)`
- **F7 Victory / defeat** `[~]`
- `[x]` team-wipe / base-destruction win condition
- `[ ]` surrender, disconnection, timed, objective victories `(v0.5)`
- `[ ]` score / stats accumulation `(v0.8)`
### M07 `ra3.modules` — object update & draw modules `[P]`
- **F1 Module system** `[~]`
- `[x]` update modules attached to objects with a simple order
- `[ ]` module descriptor data-binding (from `ThingTemplate`) `(v0.5)`
- `[ ]` interface queries (get WeaponModule / ContainModule on demand) `(v0.4)`
- **F2 Locomotor** `[ ]`
- `[ ]` movement state machine (idle/moving/attacking) `(v0.4)`
- **F3 Weapon module** `[~]`
- `[x]` simple weapons on units, auto-target + fire
- `[ ]` multi-weapon slots, turret aiming/rotation `(v0.4)`
- `[ ]` reload/clip, deploy/undeploy states `(v0.6)`
- **F4 Contain** `[ ]`
- `[ ]` transport passenger slots, load/unload `(v0.4)`
- `[ ]` garrison of civilian structures `(v0.6)`
- `[ ]` paradrop / airdrop `(v0.6)`
- **F5 Production** `[~]`
- `[x]` pay-as-you-go build queue on a factory
- `[ ]` per-factory queues, rally points, queue reordering `(v0.4)`
- `[ ]` building placement → production handoff `(v0.4)`
- **F6 Power** `[~]`
- `[x]` power production/consumption fields
- `[ ]` brownout/blackout effects on radar + build speed `(v0.4)`
- **F7 Upgrades** `[ ]`
- `[ ]` upgrade research, unlock dependent modules/weapons `(v0.5)`
- **F8 Experience / veterancy** `[ ]`
- `[ ]` XP from kills, ranks (veteran/elite/heroic), bonuses `(v0.6)`
- `[ ]` chevron rendering `(v0.6)`
- **F9 Special abilities** `[~]`
- `[ ]` secondary ability slots with cooldown, target/area types `(v0.6)`
- `[ ]` toggle/instant/targeted ability kinds `(v0.6)`
- **F10 Stealth / disguise / detection** `[ ]`
- `[ ]` stealth states, detection radius, decloak on fire `(v0.6)`
- `[ ]` disguise (spy-like) and detection interaction `(v0.6)`
- **F11 Structure modules** `[~]`
- `[x]` base structures, destruction
- `[ ]` construction/assembly animation, sell, repair `(v0.4)`
- `[ ]` walls/gates if present, defensive structures `(v0.6)`
- **F12 Resource modules** `[~]`
- `[x]` harvester ↔ refinery ore cycle
- `[ ]` ore field spread/depletion, multiple miners, dock queue `(v0.4)`
- **F13 Shroud modules** `[ ]`
- `[ ]` per-object shroud reveal / clearance `(v0.4)`
- **F14 Draw modules** `[ ]`
- `[ ]` model draw, animation, particles, construction ghost, temp effects `(v0.6)`
### M08 `ra3.combat` — weapons, warheads, damage `[P]`
- **F1 Weapons** `[~]`
- `[x]` damage, range, rate of fire, target masks
- `[ ]` clip/burst, scatter, arc, continuous beam `(v0.4)`
- `[ ]` primary vs secondary weapon selection `(v0.4)`
- **F2 Warheads** `[~]`
- `[x]` damage type + armor multiplier resolution
- `[ ]` radius/falloff, affects mask, death type on kill `(v0.4)`
- **F3 Armor** `[~]`
- `[x]` `ArmorTemplate` percentage table
- `[ ]` armor upgrades and per-state armor `(v0.6)`
- **F4 Damage application** `[~]`
- `[x]` damage resolution against armor
- `[ ]` conditional modifiers (from above, in air, moving) `(v0.4)`
- `[ ]` friendly-fire policy, self-damage `(v0.4)`
- **F5 Projectiles** `[ ]`
- `[ ]` ballistic / laser / missile / beam / homing / arcing `(v0.4)`
- `[ ]` projectile draw + impact VFX hook `(v0.6)`
- **F6 Targeting** `[~]`
- `[x]` simple nearest/in-range acquisition
- `[ ]` priority scans (attack-move, guard, force-attack) `(v0.4)`
- `[ ]` re-targeting, leash, target ground `(v0.4)`
- **F7 Special effects** `[ ]`
- `[ ]` EMP/stun, flame/radiation DoT, mind-control, shrink/grow `(v0.7)`
- **F8 Death & corpses** `[ ]`
- `[ ]` death types, wrecks, gibs, salvage, rebuild `(v0.6)`
### M09 `ra3.movement` — locomotion & pathfinding `[ ]`
- **F1 Locomotors** `[ ]`
- `[ ]` ground / air / naval / amphibious / hover / teleport `!!` `(v0.4)`
- `[ ]` turn rates, acceleration, braking, banking `(v0.6)`
- **F2 Pathfinding** `[ ]`
- `[ ]` grid A* over the passability grid `(v0.4)`
- `[ ]` hierarchical / jump-point refinement `(v0.6)`
- `[ ]` dynamic obstacle integration (buildings, units) `(v0.6)`
- **F3 Steering & flocking** `[ ]`
- `[ ]` separation, avoidance, group cohesion `(v0.6)`
- `[ ]` formation slots (line/wedge/box) `(v0.6)`
- **F4 Orders & waypoints** `[~]`
- `[x]` straight-line move toward a target (skirmish)
- `[ ]` waypoint queues, queued orders with shift `(v0.4)`
- `[ ]` guard / patrol / attack-move / stop / scatter `(v0.4)`
- **F5 Collision & crush** `[ ]`
- `[ ]` unit-unit collision, pushing, crush damage `(v0.6)`
- **F6 Naval & amphibious** `[ ]`
- `[ ]` water-only movement, amphibious land↔water transition `!!` `(v0.6)`
- **F7 Transport & airdrop** `[ ]`
- `[ ]` boarding/unloading, airdrop descent `(v0.6)`
### M10 `ra3.economy` — resources, power, construction `[P]`
- **F1 Ore / resource** `[~]`
- `[x]` ore fields and harvester↔refinery cycle
- `[ ]` ore spread/regrowth, depletion, ore density `(v0.4)`
- **F2 Power** `[~]`
- `[x]` power balance fields
- `[ ]` brownout/blackout consequences `(v0.4)`
- **F3 Construction** `[~]`
- `[x]` pay-as-you-go queue, tech prerequisites, build times
- `[ ]` build-radius rules (structures must be in base vicinity) `(v0.4)`
- `[ ]` low-power build-speed penalty `(v0.4)`
- **F4 Placement** `[ ]`
- `[ ]` placement grid, footprint validation, green/red ghost `(v0.4)`
- `[ ]` adjacency bonuses / prerequisite-adjacent structures `(v0.6)`
- **F5 Repair & sell** `[ ]`
- `[ ]` structure repair over time, cost, sell refund `(v0.4)`
- `[ ]` unit repair pads if present `(v0.6)`
- **F6 Rally points** `[ ]`
- `[ ]` factory rally, rally preview, waypoint rally `(v0.6)`
- **F7 Income modifiers** `[ ]`
- `[ ]` bonus crates (cash/units/repair/heal, `random_bonus_crates`) `(v0.5)`
### M11 `ra3.ai` — computer opponents `[P]`
- **F1 Skirmish AI** `[~]`
- `[x]` simple build AI (base, ore, a couple of unit types)
- `[ ]` data-driven build orders per faction `(v0.5)`
- `[ ]` economy management (expand, defend harvesters) `(v0.5)`
- **F2 Attack management** `[~]`
- `[x]` send units at the enemy base
- `[ ]` attack force assembly, waves, retreat/regroup `(v0.5)`
- `[ ]` targeting priorities (harvesters, key structures) `(v0.6)`
- **F3 Team AI / diplomacy** `[ ]`
- `[ ]` allied coordination, shared attacks, base defense `(v0.6)`
- **F4 Difficulty & personalities** `[ ]`
- `[ ]` easy/normal/hard modifiers, AI cheating options `(v0.5)`
- `[ ]` commander personalities (aggressive/turtle/air/naval) `(v0.7)`
- **F5 Scouting** `[ ]`
- `[ ]` exploration, map awareness, threat response `(v0.6)`
- **F6 Superweapon usage** `[ ]`
- `[ ]` AI powers/power targeting `(v0.7)`
- **F7 Script hooks** `[ ]`
- `[ ]` AI cooperation with script triggers (campaign) `(v0.7)`
### M12 `ra3.script` — triggers & missions `[ ]`
- **F1 Trigger system** `[ ]` `!!`
- `[ ]` conditions (elapsed, object in region, destroyed, flag) `(v0.7)`
- `[ ]` actions (spawn, order, reveal, camera, dialog, win/lose) `(v0.7)`
- **F2 Script engine** `[ ]` `!!`
- `[ ]` SAGE script language / mission script parse `(v0.7)`
- `[ ]` timers, counters, flags, per-player state `(v0.7)`
- **F3 Campaign missions** `[ ]`
- `[ ]` mission objectives, sequential phases, briefing `(v0.8)`
- `[ ]` three faction campaigns (Allied/Soviet/Empire) `(v0.8)`
- **F4 Reinforcements & spawns** `[ ]`
- `[ ]` scripted spawns, cinematic units, capture `(v0.8)`
- **F5 Tutorials** `[ ]`
- `[ ]` tutorial message gates, camera lock/unlock actions `(v0.8)`
- **F6 Co-op** `[ ]`
- `[ ]` co-op commander missions `(v0.9)`
### M13 `ra3.powers` — superweapons & support powers `[ ]`
- **F1 Superweapons** `[ ]` `!!`
- `[ ]` Allied Chronosphere `(v0.7)`
- `[ ]` Soviet Vacuum Imploder `(v0.7)`
- `[ ]` Empire Psionic Decimator `(v0.7)`
- `[ ]` charge timer, targeting, ready state, HUD `(v0.7)`
- **F2 Support powers** `[ ]`
- `[ ]` per-faction powers (spy satellite, air support, etc.) `(v0.7)`
- `[ ]` cooldowns, targeting types, cost `(v0.7)`
- **F3 Commander's Challenge powers** `[ ]`
- `[ ]` challenge-mode power loadouts `(v0.8)`
### M14 `ra3.shroud` — fog of war & radar `[ ]`
- **F1 Shroud** `[ ]`
- `[ ]` per-player unexplored grid `(v0.4)`
- **F2 Fog of war** `[ ]`
- `[ ]` explored-but-unseen dimming `(v0.4)`
- **F3 Reveal sources** `[ ]`
- `[ ]` units/structures reveal radius, abilities, spy satellite `(v0.6)`
- **F4 Radar / minimap** `[ ]`
- `[ ]` radar texture, unit blips, radar-offline on low power `(v0.6)`
- **F5 Shroud ↔ logic** `[ ]`
- `[ ]` targetability gating, option for AI to ignore shroud `(v0.4)`
### M15 `ra3.client` — game client & shell `[P]`
- **F1 Game client** `[~]`
- `[x]` `game_client` facade owning the sim, driving the frame loop
- `[ ]` sim/present decoupling, interpolation, catch-up `(v0.6)`
- **F2 Tactical view / camera** `[~]`
- `[x]` controls: wheel zoom, edge scroll, clamped pan, open on player start
- `[x]` camera tuning table (`cameraMinHeight` …) + lock actions
- `[ ]` retail perspective camera, pitch/yaw, FOV (needs 3D terrain) `(v0.6)`
- **F3 Selection** `[ ]`
- `[ ]` click select, drag-box, double-click type select `(v0.6)`
- `[ ]` control groups (Ctrl+N), type filters, select-all-of-type `(v0.6)`
- **F4 Orders** `[ ]`
- `[ ]` contextual right-click orders, force-attack, force-move `(v0.6)`
- `[ ]` order queue with shift, formation move `(v0.6)`
- **F5 Command bar** `[ ]` `!!`
- `[ ]` build/production palettes, ability buttons, portraits `(v0.7)`
- `[ ]` tooltips, cost/time, cooldown sweep, disabled states `(v0.7)`
- **F6 HUD** `[ ]`
- `[x]` minimal match-state overlay (units, start markers)
- `[ ]` resource/power readouts, objectives, notifications `(v0.7)`
- `[ ]` EVA voice announcements hook `(v0.7)`
- **F7 Shell menus** `[~]`
- `[x]` map list by localized name + full render/skirmish options; console fallback
- `[ ]` main menu, skirmish setup, faction/team/color pickers `(v0.7)`
- `[ ]` options (video/audio/keybinds), pause, load/save, credits `(v0.8)`
- **F8 Feedback & cursors** `[ ]`
- `[ ]` action cursor, placement ghost, move/attack markers `(v0.6)`
### M16 `ra3.render` — renderer & RHI `[P]`
- **F1 RHI** `[ ]`
- `[ ]` device/queue/swapchain abstraction over Vulkan `(v0.6)`
- `[ ]` buffers, textures, samplers, descriptor sets, pipelines `(v0.6)`
- `[ ]` `present_terrain` is the seam where this lands today `[~]`
- **F2 Render graph** `[ ]`
- `[ ]` pass scheduling, barriers, transient/aliased resources `(v0.6)`
- **F3 Terrain render** `[~]`
- `[x]` top-down software + GPU heightfield with blend ramp + gutter atlas
- `[ ]` perspective terrain mesh, LOD, cliff, water `(v0.6)`
- **F4 Model render** `[ ]` `!!`
- `[ ]` W3D draw, skinning, materials, team colors `(v0.6)`
- `[ ]` shadows, decals, ground marks `(v0.6)`
- **F5 VFX** `[ ]`
- `[ ]` particle systems, beams, muzzle flashes, explosions `(v0.6)`
- `[ ]` shader effect graph (retail `.fxo` parity where feasible) `!!` `(v0.7)`
- **F6 Sky & atmosphere** `[ ]`
- `[ ]` skybox, fog, weather, time-of-day `(v0.7)`
- **F7 HUD render** `[ ]`
- `[ ]` 2D art layer, fonts, minimap/radar texture `(v0.7)`
- **F8 Software renderer** `[D]`
- `[x]` ARGB framebuffer, blit/line/circle/text, TGA decode, BMP encode
- `[x]` map compositing, grid, markers; headless output
- **F9 Post-processing** `[ ]`
- `[ ]` bloom, color grading, AA, resolution scaling `(v0.7)`
### M17 `ra3.ui` — platform layer & backends `[D]`
- **F1 Display abstraction** `[D]`
- `[x]` shared primitives + interactive loops + `ui_event` mapping in the base
- `[x]` backends implement primitives only (SDL/Vulkan cannot drift)
- **F2 SDL3 backend** `[D]`
- `[x]` window, streaming-texture blit, input polling
- `[ ]` gamepad support `(v0.8)`
- **F3 Backend selection (`ra3.display`)** `[D]`
- `[x]` try Vulkan → SDL → report failure for offscreen fallback
- **F4 Input mapping** `[~]`
- `[x]` keyboard/mouse state, modifier masks
- `[ ]` rebindable keybinds, mouse capture, scroll wheel events `(v0.6)`
- **F5 Window modes** `[ ]`
- `[ ]` windowed/fullscreen/borderless, resize, multi-monitor `(v0.6)`
- **F6 Null/headless backend** `[D]`
- `[x]` returns false so the tree builds and runs without SDL3/Vulkan
### M18 `ra3.vulkan` — Vulkan backend `[P]`
- **F1 Device & swapchain** `[~]`
- `[x]` embedded SPIR-V, SDL3 surface, present path
- `[ ]` formal RHI integration (see M16 F1) `(v0.6)`
- **F2 Terrain presentation** `[D]`
- `[x]` GPU heightfield raymarch, mipmapped atlas, gutter, retail blend ramp
- **F3 Materials & pipelines** `[ ]`
- `[ ]` model/particle/HUD pipelines `(v0.6)`
- **F4 Null fallback** `[D]`
- `[x]` report failure when no Vulkan loader is present
### M19 `ra3.audio` — audio `[ ]`
- **F1 SFX** `[ ]`
- `[ ]` 3D positional sound from cues/events `(v0.7)`
- **F2 Music** `[ ]`
- `[ ]` streaming music, playlists, combat stingers `(v0.7)`
- **F3 Voice & EVA** `[ ]`
- `[ ]` unit response lines, announcer (EVA) events `(v0.7)`
- **F4 Mixer** `[ ]`
- `[ ]` buses (master/sfx/music/voice), volume, ducking, reverb `(v0.7)`
- **F5 Codecs** `[ ]` `!!`
- `[ ]` decode RA3 audio formats `(v0.7)`
### M20 `ra3.video` — movies & cutscenes `[ ]`
- **F1 Movie playback** `[ ]` `!!`
- `[ ]` intro/briefing/ending video decode + playback `(v0.8)`
- `[ ]` skip, subtitles, aspect handling `(v0.8)`
- **F2 In-engine cutscenes** `[ ]`
- `[ ]` scripted camera + unit animation sequences `(v0.8)`
### M21 `ra3.match` — game setup & match rules `[P]`
- **F1 Game setup** `[~]`
- `[x]` map + two players + seed defaults
- `[ ]` faction/color/team/start-slot selection, AI personalities `(v0.7)`
- **F2 Rules & options** `[ ]`
- `[ ]` starting cash, crates on/off, superweapons on/off, speed, limits `(v0.7)`
- **F3 Match flow** `[~]`
- `[x]` `prepare_new_game` / `start_new_game` split mirroring retail
- `[ ]` loading progress, in-game start countdown `(v0.7)`
- **F4 Factions** `[~]`
- `[x]` Allied / Soviet / Empire player templates
- `[ ]` full faction tech trees and rosters `(v0.5)`
- **F5 Victory & scoring** `[~]`
- `[x]` team-wipe victory
- `[ ]` full victory conditions, post-match score screen `(v0.8)`
### M22 `ra3.replay` — recording & playback `[ ]`
- **F1 Recorder** `[ ]`
- `[ ]` capture command stream + seed + map id per match `(v0.4)`
- **F2 Replay format** `[ ]`
- `[ ]` self-describing header, command log, checksums `(v0.4)`
- `[ ]` compatibility with retail `.RA3Replay` playback `!!` `(v0.9)`
- **F3 Playback** `[ ]`
- `[ ]` deterministic re-simulation, speed control, seek `(v0.4)`
- **F4 Golden replays** `[ ]`
- `[ ]` curated replay corpus as a regression test `(v0.4)`
- **F5 Observer / spectator** `[ ]`
- `[ ]` watch live or recorded matches, fog option `(v0.9)`
### M23 `ra3.save` — save/load & profiles `[ ]`
- **F1 Save / load** `[ ]`
- `[ ]` full simulation state serialization (objects, modules, queues) `(v0.8)`
- `[ ]` versioned saves with migration `(v0.8)`
- **F2 Profiles** `[ ]`
- `[ ]` player profile, stats, progress/unlocks `(v0.8)`
- **F3 Options persistence** `[ ]`
- `[ ]` settings, keybinds, last-used skirmish config `(v0.7)`
- **F4 Checkpoints** `[ ]`
- `[ ]` campaign checkpoint save/restore `(v0.9)`
### M24 `ra3.mod` — data packages `[ ]`
- **F1 Data packages** `[ ]`
- `[ ]` load order, override precedence, loose-file mounting `(v0.8)`
- **F2 Content discovery** `[ ]`
- `[ ]` scan user mod dirs and additional `.big` archives `(v0.8)`
- **F3 Mod validation** `[ ]`
- `[ ]` schema + reference checks, actionable errors `(v0.8)`
### M25 `ra3.net` — LAN lockstep `[ ]` *(deferred, offline-only)*
- **F1 Lockstep** `[ ]`
- `[ ]` deterministic lockstep over LAN, command-exchange only `(v1.0)`
- **F2 Lobby & sync** `[ ]`
- `[ ]` lobby, slot/team assignment, start sync `(v1.0)`
- **F3 Desync detection** `[ ]`
- `[ ]` state-hash comparison, desync report `(v1.0)`
> No online service, matchmaking, EA account or third-party network
> integration — ever. LAN only.
### M26 `ra3.i18n` — localization `[P]`
- **F1 CSF strings** `[~]`
- `[x]` parse `gamestrings.csf` (UTF-16 units, low byte `^0xFF`)
- `[x]` map display-name lookup (`MAP:<ID>`)
- `[ ]` full string-table load for all UI text `(v0.5)`
- **F2 Language selection** `[~]`
- `[x]` newest `Lang-English*.big` wins
- `[ ]` all supported languages, fallback chain `(v0.5)`
- **F3 Fonts & shaping** `[ ]`
- `[ ]` glyph coverage, CJK/RTL shaping where applicable `(v0.6)`
- **F4 Substitution** `[ ]`
- `[ ]` placeholders, numbers, plurals `(v0.5)`
### M27 `apps` — applications `[D]`
- **F1 CLI** `[D]`
- `[x]` `menu` / `menu-preview` / `maps` / `skirmish` / `render` / `extract`
- `[ ]` `replay`, `benchmark`, `validate-data` subcommands `(v0.5)`
- **F2 Extraction pipeline** `[~]`
- `[x]` `extract` → `assets/` (maps, terrain)
- `[ ]` full asset dump (models/textures/audio/movies) as a build target `(v0.5)`
- **F3 Diagnostics** `[ ]`
- `[ ]` headless render/benchmark modes for CI `(v0.4)`
### M28 `tools` — offline tooling `[~]`
*(Python is permitted here; it is never linked into `openra3`.)*
- **F1 Reference fetch** `[D]`
- `[x]` sparse-clone SAGE 1.0 reference into git-ignored `reference/`
- **F2 Ghidra workflow** `[D]`
- `[x]` MCP-driven recovery loop + recovered symbol map (see RE doc)
- `[ ]` automated structure/table extractors `(v0.5)`
- **F3 Format inspectors** `[ ]`
- `[ ]` BIG/RefPack/CkMp/W3D/APT dumpers `(v0.5)`
- **F4 CI & packaging** `[D]`
- `[x]` GitLab CI builds both targets → test → package
---
## 4. Cross-cutting invariants
These hold across **every** module above and are enforced in review:
1. **Language** — runtime code is C++ only. Build tooling may use Python.
2. **Ownership** — no raw owning pointers; `unique_ptr` for ownership, handles or
`thing *` views for references.
3. **Layering** — a module imports only lower layers. `ra3.core` imports no
engine module and no platform API.
4. **Determinism** — RNG, iteration, hashing and float use are explicit and
seedable; the logic step must be bit-reproducible for a given input stream.
5. **RE-traceable** — retail structure/constant changes cite an address in
[`REVERSE_ENGINEERING.md`](REVERSE_ENGINEERING.md).
6. **Offline** — no online service; LAN lockstep (M25) is the only networking,
and only command exchange.
7. **No bundled assets** — game data is read from the user's install; nothing
from it is committed. The tree builds and runs in CI on a built-in test map.
---
## 5. Milestone mapping
The plan rolls up to these releases:
| Milestone | Modules advanced | Delivers |
| --- | --- | --- |
| `v0.3.x` (done) | M00, M01, M04, M05(F1–F3), M06, M07(partial), M08(partial), M10(partial), M16(F3,F8), M17, M18 | minimal deterministic skirmish, real terrain, Vulkan present, menu |
| `v0.4.0` | M05(F4–F7), M06, M07, M08, M09(F1,F2,F4), M14, M22(F1–F4) | real update modules: locomotor, projectiles/warheads, placement, shroud, pathfinding, replay |
| `v0.5.0` | M02, M03, M04(F3,F4), M08, M10(F3,F4), M11(F1,F2), M26 | data-driven content: deserialise `.bin`/`.manifest`, real rosters, maps, strings |
| `v0.6.0` | M03(F1–F3), M07(F4,F6,F8,F14), M09(F2–F7), M16(F1,F2,F4,F5), M18(F3), M15(F1–F4,F8) | full renderer: perspective terrain, W3D models, in-game client + input |
| `v0.7.0` | M13, M15(F5–F7), M19, M11(F4–F6), M20, M21 | HUD/command bar, audio, superweapons, Commander's Challenge |
| `v0.8.0` | M12, M20(F1), M23, M24, M21(F5) | campaigns, cutscenes, save/load, mods |
| `v0.9.0` | M22(F2,F5), M12(F6), M25 | retail replay playback, co-op, LAN lockstep |
| `v1.0.0` | all | feature-complete offline RA3 |
---
## 6. Design rules
The five rules the codebase is held to (restated from §1, with the concrete
consequences that trip people up):
1. **No raw owning pointers.** Ownership is `std::unique_ptr`; the partition
manager holds non-owning `thing *` views only.
2. **Portable simulation.** No platform APIs in `ra3.core` / `ra3.logic`. All
platform concerns live behind `display`.
manager and object registry hold non-owning `thing *` views only.
2. **Portable simulation.** No platform APIs in `ra3.core` / simulation
modules. All platform concerns live behind `display`.
3. **Determinism.** Anything that can diverge between runs (random, iteration
order) is explicit and seedable.
4. **RE-traceable.** Where a structure or constant comes from the retail
binary, the address is cited in the comment.
5. **No bundled assets, no online.** Game data is read from the user's install
and never committed; there is no networking or online service.
---
## 7. Where to start
- New to the codebase: read this plan top-to-bottom (§3 is the feature set,
§5 the near-term order of work).
- Picking up a feature: find its **Function** above, take the lowest-numbered
unmet `[ ]` **Feature**, and cite its supporting retail address.
- Reverse engineering a subsystem: follow the loop in
[`REVERSE_ENGINEERING.md`](REVERSE_ENGINEERING.md); the `!!` tags above mark
the functions that still need a recovery pass before they can be built.
-60
View File
@@ -1,60 +0,0 @@
# Roadmap
OpenRA3 is a very large undertaking. This roadmap is deliberately honest about
scope: reconstructing a 2008 RTS engine from a decompiler plus a related open
engine is a multi-year, multi-person effort. The milestones below are ordered so
that each one produces something that builds and runs.
## Done
- [x] **v0.0.1 — skeleton + minimal skirmish.** C++26 modules, GCC 16,
CMake/Ninja, Docker `dev`/`deploy`, GitLab CI. Reads `BIG4`/RefPack data
from a local install, recovers map start waypoints, and runs a
deterministic headless two-player skirmish to a decision.
- [x] **v0.1.0 — map renderer + window.** Software ARGB framebuffer, TGA
decoder for the map art, BMP output, map/grid/unit compositing, and an
SDL3 window viewer (pan/zoom).
- [x] **v0.2.0 — dual toolchain.** Switched to Clang + libc++ with
`import std;` in every module; added an isolated Windows cross-build
(llvm-mingw + SDL3 MinGW) producing `openra3.exe` + `SDL3.dll`, alongside
the Linux build. Both images are separate to keep the toolchains apart.
- [x] **v0.3.2 — real terrain.** `ra3.terrain` parses the map's `HeightMapData`
and `BlendTileData` and rasterises the actual terrain from the install's
`Terrain.big` tile textures (top-down, elevation-shaded), replacing the
`<map>_art.tga` overview as what `render` draws.
- [x] **v0.3.0 — real balance + skirmish + Vulkan.** `ra3.data` pins the retail
numbers (damage types, `ArmorTemplate` percentages, weapons, units,
structures, ore economy) audited from EA's open RA3 XML; `ra3.skirmish` is
rebuilt on them (armour resolution, weapon target masks, pay-as-you-go
build queue, power, tech prerequisites, refinery ore cycle, team-wipe
victory); and `ra3.vulkan` replaces the presentation stack with Vulkan
(SDL3 surface, embedded SPIR-V), with a null fallback where no loader
exists.
## Next
- [ ] **v0.3.1 — tactical map view.** The Vulkan/SDL viewer reproduces the
retail tactical view (`TheTacticalView`, `ra3_1.12.game` `0x00cdb7b4`):
opens centred on the player's start, wheel zoom, edge scroll and clamped
pan. A hand-rolled HUD was tried and removed — the real in-game interface
is `.apt` art that must be recovered first, so it is not on the near
roadmap.
- [ ] **v0.4.0 — real update modules.** Locomotor movement, projectiles and
warheads, build placement, shroud, and pathfinding, driven by the
`GameObject` module set recovered from the binary.
- [ ] **v0.5.0 — data-driven content.** Deserialise the compiled assets
(`global.bin`/`static.*.bin` + `.manifest`) so `ra3.data` reads the
install instead of pinned constants; real maps, models and strings.
- [ ] **v0.6.0 — full renderer.** Perspective terrain (the heightmap is decoded
but drawn top-down today), W3D models and the full in-game client on
Vulkan, plus input.
## Cross-cutting tracks
- **RE depth** — keep recovering retail layouts (see
[`REVERSE_ENGINEERING.md`](REVERSE_ENGINEERING.md)); every structure gets an
address citation and a test.
- **Determinism & replay** — the logic random stream and frame ordering must be
reproducible; replay format and a golden-replay test suite.
- **Offline only** — no online mode. Multiplayer, if pursued, is LAN lockstep on
the message stream, never an online service.