# Building Red Planet 4.12 (Win32) This is the Win32 source for the pod-racing game **Red Planet**, built on the in-house **MUNGA** engine and its **L4** (Win32 / DirectX 9) platform layer. As of RP 4.12 the build targets **Visual Studio 2022 (v143)**; the legacy VS 2005/2008 projects are retained for reference (see §5). > ✅ **Verified build (2026-07-12):** all 4 projects build clean (`Release|Win32`) > with **VS2022 Build Tools 17.14** (MSVC 14.44, v143) + **Windows 11 SDK > (10.0.26100)** + **DirectX SDK (June 2010)**. Outputs: `Release\rpl4opt.exe` > (the game), `Release\RPL4TOOL.exe`, `lib\Munga_l4.lib`, `lib\DivLoader.lib`. > Runtime-verified against the VC9 baseline built from the same tree: identical > log output and behavior at every checkpoint, including RIO init against vRIO > and mission load (see §4 for the pre-existing crash both builds share). --- ## 1. Requirements | Component | Version | Notes | |-----------|---------|-------| | **VS2022 Build Tools** (or any VS2022 with C++ workload) | 17.x, MSVC v143 | Installed at `C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools`. Install via `winget install Microsoft.VisualStudio.2022.BuildTools --override "--quiet --wait --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"`. | | **Windows 10/11 SDK** | any recent (26100 verified) | Comes with the VCTools workload. | | **DirectX SDK (June 2010)** | — | Still needed for **d3dx9** and **dxerr** only; everything else now comes from the Windows SDK. The projects reference it via `$(DXSDK_DIR)`, which the SDK installer sets machine-wide. The DXSDK include/lib paths are appended **after** the Windows SDK paths (see the `IncludePath`/`LibraryPath` properties in the projects) so modern headers win — do not move them to `AdditionalIncludeDirectories`. | ### Bundled third-party libraries (already in the repo) Committed under [lib/](lib/), no install needed: `OpenAL32.lib`, `libsndfile-1.lib` (import libs). At **run time** the game needs `OpenAL32.dll` (system-wide install — `assets/RP411/oalinst.exe` — or beside the exe) and `libsndfile-1.dll` (beside the exe; a copy ships in `assets/RP411/`). ## 2. Building ```powershell & "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\MSBuild.exe" ` WinTesla.sln /p:Configuration=Release /p:Platform=Win32 /m ``` `Debug|Win32` also builds. `x64` is not configured — this is a 32-bit build. The solution is [WinTesla.sln](WinTesla.sln) with four v143 projects: | Project | Type | Output | |---------|------|--------| | [MUNGA_L4/Munga_L4.vcxproj](MUNGA_L4/Munga_L4.vcxproj) | Static lib | `lib\Munga_l4.lib` | | [RP_L4/RP_L4.vcxproj](RP_L4/RP_L4.vcxproj) | App (Windows) | `Release\rpl4opt.exe` — **the game** | | [RP_L4/RPL4TOOL.vcxproj](RP_L4/RPL4TOOL.vcxproj) | App (Console) | `Release\RPL4TOOL.exe` | | [DivLoader/DivLoader.vcxproj](DivLoader/DivLoader.vcxproj) | Static lib | `lib\DivLoader.lib` (Release) | Build order is resolved by `ProjectReference` (RP_L4 and RPL4TOOL both reference Munga_L4). **Packaging:** [pack-dist.ps1](pack-dist.ps1) assembles a runnable game into `dist\` (exe + PDB, game data, OpenAL/libsndfile runtimes, desktop `environ.ini`, `start-windowed.bat`, README). Pass `-Zip` to also produce `dist\RedPlanet412-prototype.zip` for handing to someone else. ## 3. VS2022 migration notes (what changed and why) Settings preserved from the VC9 projects: **`/Zp1` struct packing** in Munga_L4 and RP_L4 (the engine's on-disk/on-wire binary formats depend on it — RPL4TOOL and DivLoader never had it), Unicode, subsystems, x86, `/DYNAMICBASE:NO`, optimization levels, and `/FORCE:MULTIPLE` (see below). Deliberate changes: - **CRT unified to `/MD` (Release) / `/MDd` (Debug).** The VC9 build mixed `/MT` (Munga_L4, RPL4TOOL) with `/MD` (RP_L4) and forced the link. - **Import libs are no longer merged into `Munga_L4.lib`** by the librarian; the exes link OpenAL32/d3d9/d3dx9/dinput8/dxguid/ws2_32 directly. - `WINDOWS_IGNORE_PACKING_MISMATCH` is defined: the modern Windows SDK `static_assert`s against `/Zp1`; the VC9 build always compiled Windows headers at `/Zp1`, so this preserves those exact semantics. Un-`/Zp1`-ing the engine (pragma-pack only the serialized structs) is future work. - `_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS` is defined: the code still uses `stdext::hash_map`; porting to `std::unordered_map` is future work. - `legacy_stdio_definitions.lib` is linked: the June-2010 `dxerr.lib` references pre-UCRT stdio symbols. - **Source fixes** (behavior-preserving): standard copy-ctor/assignment overloads added to `Time` (rvalues can't bind to `volatile&` in standard C++); `operator==(SOCKADDR_IN&,...)` in `NETWORK.h` made `inline`; the L4DINPUT callbacks renamed `DIEnum*` (they collided with L4CTRL's under LTCG); `std::ios.in` → `std::ios::in` in `CAMMGR.cpp`. - `/FORCE:MULTIPLE` is still required: `gOpNames`, `gReplacementData` (hash_maps defined in a header) and `GlobalEggFileName` are genuinely defined in multiple TUs (LNK4006 warnings, same as the VC9 build). Moving them to a single TU is future cleanup. ## 4. Runtime notes **Fixed (2026-07-12):** standalone mission load used to crash with an access violation in `d3d_OBJECT::LoadTexture` ([MUNGA_L4/L4D3D.cpp](MUNGA_L4/L4D3D.cpp)): `D3DXCreateTextureFromFileA` failures were never checked and the NULL texture was cached and `AddRef()`ed. It crashed identically on VC9 — a latent defect in the 2007 DPL→D3D9 port, exposed by the pod-skin textures (`VIDEO\player1–8`) that a bare working copy doesn't contain (they normally come from the replacement-material/presets path, `WTPresets` → `VIDEO\.png`). Missing textures now log `L4D3D.cpp couldn't load texture …` and render untextured; the game boots to a running window with `-windowed -res 640 480 -egg TEST.EGG` from a working copy like `assets/RP411/`. For runtime debugging the v143 build produces full PDBs — run `cdb -g -G -lines -y Release rpl4opt.exe ...` from the working directory (cdb ships in this machine's Windows Kits). ### Running without the cockpit (Workstream A prototype) Two new environment options remove the hardware dependency entirely: - **`L4CONTROLS=PAD;KEYBOARD`** — selects **PadRIO** ([MUNGA_L4/L4PADRIO.cpp](MUNGA_L4/L4PADRIO.cpp)), an in-process RIO that speaks the full RIO control surface (buttons, axes, lamps) from an XInput controller + the PC keyboard. The stock `VTVRIOMapper` path runs unchanged. Hot-plugging works; with no controller it falls back to keyboard only. - **`L4PLASMA=SCREEN`** — renders the 128×32 plasma display as its own desktop window ("Plasma Display", plasma orange, `L4PLASMASCALE` sets the pixel size, default 4). It opens directly below the main view; `L4PLASMAPOS=x,y` overrides. No COM port. Closing the window hides it. - **`L4MFDSPLIT=1`** — un-packs the 7-display cockpit. The pod hardware drove five monochrome MFDs from the color channels of two video outputs (window 3 = upper MFDs in R/G/B, window 4 = lower MFDs in R/G) and mounted the map display portrait. With split mode the game itself opens seven proper windows — main view, five green-screen MFDs ("MFD upper left/center/right", "MFD lower left/right") and the 90°-rotated "Map" — rendered CPU-side from the shared gauge canvas; the packed windows stay hidden. `L4MFDSCALE` sets the view size in percent of the gauge canvas (default 50). Default layout is the pod grid to the right of the main view; all windows are draggable. This replaces the external BitBlt-mirror launcher wrapper. Each split window also carries its display's **physical button bank** (geometry per vRIO's `CockpitLayout`): 4 red buttons above and below each MFD glass (RIO addresses descending from the cluster anchor — upper left 0x2F, upper center 0x27, upper right 0x37, lower left 0x0F, lower right 0x07), and 6 amber buttons down each side of the map (Secondary 0x10–0x15 left, Screen 0x18–0x1D right; the columns' other addresses are Tesla relays, not buttons). They **light from the lamp states the game commands** (dim/bright, flash modes animate) and press the corresponding RIO unit with the mouse — active when `PadRIO` is the control device, dark and inert with real serial hardware. Bindings (vRIO's default profile, condensed): | Input | Pod control | |-------|-------------| | Left stick / WASD | joystick X/Y | | LT / RT, Q / E | left / right pedal | | Right stick Y, PgUp / PgDn | throttle (rate; position holds) | | A / Space | joystick trigger | | B / R | reverse thrust (ButtonThrottle1) | | DPad / arrows | joystick hat (look) | | X, Y, LB, RB | pinky / thumb-low / thumb-low / thumb-high | | Start / F1, Back / F2 | config buttons (AuxUpperRight 1 / 2) | `L4PADFLIP=XY` (or `X` / `Y`) inverts the stick axes if the feel is wrong. Example desktop `environ.ini`: ```ini L4CONTROLS=PAD;KEYBOARD DPLARG=1 L4DPLCFG=RPDPL.INI L4GAUGE=640x480x16 L4PLASMA=SCREEN L4MFDSPLIT=1 TARGETFPS=60 ``` Lamp commands land in `PadRIO::lampState[]` — the hook for the planned on-screen cockpit panel (vRIO buttons arranged around the displays). Also note: `Fail()` compiles to `abort()` in release (`MUNGA/DEBUGOFF.h`) — e.g. running with `L4CONTROLS=KEYBOARD` alone aborts at VTV creation because no keyboard-only pod mapper exists (the old CRT showed a blocking R6010 dialog; the UCRT fail-fasts). Use `L4CONTROLS=RIO;KEYBOARD` with vRIO serving the RIO side, exactly like the arcade config. ## 5. Legacy VS2005/2008 build The original `.vcproj` files and solution are kept as [WinTesla_vc9.sln](WinTesla_vc9.sln) and still build with VC++ 2008 Express SP1 + DXSDK June 2010: ```bat @echo off call "C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat" set "DXSDK_DIR=C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\" vcbuild /nologo /rebuild WinTesla_vc9.sln "Release|Win32" ``` See [docs/BUILD-NOTES.md](docs/BUILD-NOTES.md) for the original repository cleanup history and the findings behind the legacy build.