A tester ran 4.12.233 under Proton and it died on first mission load. The cause turned out to name itself, and to be a Windows bug we have been shipping the whole time. Wine implements d3dx9_43 itself, and 63 of its 329 exports are stubs. The game imports twenty of them and exactly one is stubbed: D3DXConcatenateMeshes, called once per session from ConsolidateStaticObjects on the first-mission-load latch - so every player hits it on their first race. Wine raised EXCEPTION_WINE_STUB naming the function in plain text, and our own crash filter caught it and wrote a minidump, which is how a self-describing failure arrived as a mystery. The fix is one file, and it was overdue on Windows. d3dx9_43.dll is a HARD import of the exe - only steam_api.dll is delay-loaded - and it is not part of Windows. It ships with the June 2010 DirectX End-User Runtime and nothing else. Any customer on a clean Windows 10 or 11 who never installed that redistributable cannot start the game at all: the loader fails at 0xC0000135 before WinMain, no window, no log line. Every machine this has been built or tested on had the SDK or some older game installed, which is precisely why nobody has ever seen it. pack-dist now extracts the DLL from the SDK's redist cab into dist. Wine prefers an application-directory DLL over its builtin, so the same file closes the Windows failure and the Linux blocker together, and it is verified working on a stock prefix with nothing installed. The SDK terms nominate DXSETUP as the delivery method for this redistributable; the loose DLL is what is verified and is near-universal practice, but that wants confirming before a public release. /LARGEADDRESSAWARE, because the same session reported VmSize 3193MB and an older Wine that died before video init with the address space exhausted. The game is not using that memory: measured here, a standalone mission peaks at 166MB committed against 795MB of address space. The gap is reservations, mapped files, and mostly the graphics driver mapping VRAM apertures into our process - under wined3d's OpenGL path that grows several times over. For a 32-bit process the 2GB address ceiling is a hard limit with nothing to do with RAM, so it is entirely possible to run out of addresses while using 170MB. The flag raises it to 4GB, frees nothing, and changes no behaviour. Worth having on Windows too: 795MB of 2GB is already 40% before 1080p, eight pods, and the 100MB buffer RP412RECORDSIZE takes when recording is armed. And two diagnostics so the next one costs a log line instead of an investigation. The crash filter now decodes 0x80000100 and writes the offending module.function before the minidump; startup probes wine_get_version in ntdll and logs the platform beside the version banner. Neither can appear on Windows - verified: the smoke run's log has the version line and no platform line. Not fixed here, deliberately: the durable version of this is to write the mesh merge by hand, since D3DXSimplifyMesh and D3DXSplitMesh are stubs too and any future mesh work hits the same wall. And the field test ran wined3d, not DXVK, so the child-window Present with GDI panes clipped over it - the risk the assessment led with - is still untested. The doc records both, along with the prediction it got wrong: the windowsapp.lib import was called a load-time failure risk under Wine, and it simply is not one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
326 lines
18 KiB
Markdown
326 lines
18 KiB
Markdown
# 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/`).
|
||
|
||
It also needs **`d3dx9_43.dll`**, which is a hard import and is *not* part of
|
||
Windows — it ships only with the June 2010 DirectX End-User Runtime. A dev box
|
||
with the SDK installed has it system-wide and never notices; a clean Windows
|
||
10/11 fails to start the exe at all (0xC0000135, before `WinMain`).
|
||
[pack-dist.ps1](pack-dist.ps1) therefore extracts it from the SDK's
|
||
`Redist\Jun2010_d3dx9_43_x86.cab` into `dist\`. That same file is also what
|
||
makes the game run under Wine/Proton, whose builtin `d3dx9_43` stubs
|
||
`D3DXConcatenateMeshes` — see [docs/RP412-LINUX.md](docs/RP412-LINUX.md).
|
||
|
||
## 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).
|
||
|
||
**Versioning:** the patch number *is* the repository's commit count, so a
|
||
build always names the commit it came from and there is no question about
|
||
which changes a given binary contains.
|
||
[stamp-version.ps1](stamp-version.ps1) runs as RP_L4's pre-build step and
|
||
writes the generated, uncommitted `RP_L4\rpl4build.h`:
|
||
|
||
```
|
||
#define RP412_VERSION "4.12.96"
|
||
#define RP412_VERSION_LONG "4.12.96 (a1b2c3d)"
|
||
```
|
||
|
||
The game logs the long form on its first line. A trailing `+` on the hash
|
||
means the tree had uncommitted changes to tracked files when it was built —
|
||
useful when a test machine reports something a clean build cannot reproduce.
|
||
Only the `4.12` product line is set by hand, at the top of the script.
|
||
|
||
**Test builds expire.** `$expireDays` at the top of the same script is the
|
||
shelf life in days (currently **14**, counted from the day it was *built*,
|
||
not the day the code was written — rebuilding an old commit gives a usable
|
||
binary rather than one born stale). An expired build says so in a dialog,
|
||
names its version and expiry date, points at the releases page, and exits
|
||
without running. It stops a tester spending an afternoon on something that
|
||
was fixed a week ago.
|
||
|
||
> ⚠️ **Set `$expireDays = 0` for a real release.** A shipped build that
|
||
> expires is a catastrophe, and that one line is what decides it.
|
||
|
||
`RP412NOEXPIRY=1` waives the check when an old build has to be run on
|
||
purpose, and says so in the log so a waived build is never mistaken for a
|
||
current one. It is deliberately **not** listed in `environ.ini` — a bypass
|
||
every tester can see is a bypass every tester will use. Negative
|
||
`$expireDays` backdates the expiry, which is how the refusal gets tested
|
||
without touching the machine's clock.
|
||
|
||
The header is deliberately not committed: the commit that recorded a
|
||
hardcoded number would itself change the count, so the file would be stale
|
||
the moment it landed. It is rewritten only when the stamp actually changes,
|
||
so ordinary rebuilds do not recompile `RPL4.CPP` for nothing. Building
|
||
outside a git checkout stamps `4.12.x (no repository)` rather than inventing
|
||
a number that would sort against real ones.
|
||
|
||
**Packaging:** [pack-dist.ps1](pack-dist.ps1) assembles a runnable game into
|
||
`dist\` (exe + PDB, game data, OpenAL/libsndfile runtimes, launch scripts,
|
||
HANDBOOK.html, README). It deliberately does **not** write `environ.ini` —
|
||
the exe carries that template and writes it on first run
|
||
([RP_L4/RPL4ENVIRON.cpp](RP_L4/RPL4ENVIRON.cpp)), so a tester can drop a new
|
||
build over an old folder without losing their settings. Pass `-Zip` to also produce
|
||
`RedPlanet-<version>.zip` for handing to someone else. It reads the version
|
||
from `rpl4build.h` rather than asking git again, so the package and the
|
||
binary inside it cannot disagree, and it warns if the build it is packing
|
||
came from a modified tree.
|
||
|
||
## 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\<name>.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/`.
|
||
|
||
**`steam_api.dll` is optional.** It is **delay-loaded**
|
||
(`DelayLoadDLLs` in [RP_L4/RP_L4.vcxproj](RP_L4/RP_L4.vcxproj), with
|
||
`delayimp.lib` supplying the helper), so a working copy that has never seen
|
||
Steam — like `assets/RP411/`, which predates the Steam work — boots and races
|
||
normally. Only Steam itself is switched off, logged as
|
||
`Steam: steam_api.dll not found beside the exe - Steam features off, staying
|
||
on TCP`.
|
||
|
||
Delay loading alone would only move the failure: the first call into a
|
||
delay-loaded DLL that cannot be found raises the helper's fatal exception
|
||
rather than returning an error. So every path that reaches a Steam symbol
|
||
first asks `SteamNetTransport_ClientLibraryPresent()`
|
||
([MUNGA_L4/L4STEAMTRANSPORT.cpp](MUNGA_L4/L4STEAMTRANSPORT.cpp)) — a cached
|
||
`LoadLibrary` probe using the same plain-name lookup the helper does. The
|
||
gates are `SteamNetTransport_Install` and the two lobby entries
|
||
`RPL4Lobby_Host`/`_Join`; everything else in the transport and lobby is
|
||
downstream of one of those. **Adding a new Steam call site means checking
|
||
which gate covers it.**
|
||
|
||
For Steam features you need the DLL from
|
||
[extern/steamworks_sdk_165/sdk/redistributable_bin/steam_api.dll](extern/steamworks_sdk_165/sdk/redistributable_bin/steam_api.dll)
|
||
(the 32-bit one, not `win64\`) beside the exe, plus `steam_appid.txt` — with
|
||
the DLL but no appid file `SteamAPI_Init` fails and the game falls back to TCP.
|
||
|
||
`environ.ini` must be written **without a BOM**. The parser matches key names
|
||
from the start of the line, so a leading UTF-8 BOM silently invalidates the
|
||
first key in the file — put `L4CONTROLS` there and it reverts to the built-in
|
||
`KEYBOARD` default, which then fail-fasts on `0xC0000409` with
|
||
`*****VTV has no controls mapping!*****` in the log (there is no keyboard-only
|
||
pod mapper). PowerShell's `Set-Content -Encoding utf8` writes a BOM in 5.1;
|
||
use `[System.IO.File]::WriteAllText` with an `ASCIIEncoding`. The log line
|
||
`Environ: environ.ini does not mention N option(s)` naming a key that is
|
||
plainly in the file is the tell.
|
||
|
||
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).
|
||
|
||
### Debug keys
|
||
|
||
`RP412DEVKEYS=1` arms them, and they arrive through the engine keyboard
|
||
handler, so `L4CONTROLS` must include `KEYBOARD`. That handler takes one key
|
||
per frame off the front of the message queue and genuinely drops presses, so
|
||
press again before concluding a key is broken.
|
||
|
||
| Key | State |
|
||
|-----|-------|
|
||
| **Alt+W** wireframe | **Live.** Reimplemented on D3D9 as a per-frame `D3DRS_FILLMODE` (`gWireframe`, [MUNGA_L4/L4VIDEO.cpp](MUNGA_L4/L4VIDEO.cpp)). The view clears to black and the sky pass is skipped, so the edges stand on their own — with the lit dome in place the far half of the scene is unreadable. The 2D pass (gunsight, cam-ship HUD) is held solid; particles are wireframed with everything else. Fog still applies, so distant edges tint toward the fog colour rather than staying white. |
|
||
| **Alt+E** event-queue dump | **Live.** Reaches `GeneralEventQueue::DumpEventQueue`. |
|
||
| Alt+V predator vision | Inert. |
|
||
| Alt+F frame dump | Inert. |
|
||
| Alt+/ perf stats | Inert. |
|
||
| Alt+K free memory | Inert, silent. |
|
||
| Alt+R dither, Alt+P eyepoint | Inert; they log "Function net yet enabled." |
|
||
| Alt+Q abort | Always live, no `RP412DEVKEYS` needed. |
|
||
|
||
The inert ones call `DPLRenderer` methods whose bodies were commented out
|
||
with the rest of the DPL calls in the 2007 port (`STUBBED: DPL RB 1/14/07`).
|
||
Reviving one means writing it against D3D9 rather than un-commenting
|
||
anything: the `dpl_*` types those bodies used are empty placeholder classes
|
||
now ([DPLSTUB.h](DPLSTUB.h)), and `libDPL/` is reference headers that are not
|
||
compiled. Alt+V is the worst of them — the DPL renderer implemented predator
|
||
vision internally, reached by passing an out-of-band explosion effect type
|
||
(`-1` on, `-2` off) with a NULL DCS, and nothing in this tree records what it
|
||
actually looked like.
|
||
|
||
### 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`** — assembles the **whole pod interior in one window**.
|
||
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. In split mode the
|
||
main game window becomes the cockpit shell and every display is a
|
||
chrome-less child pane, arranged as in the pod:
|
||
|
||
```
|
||
[ MFD UL ] [ MFD UC ] [ MFD UR ]
|
||
[ plasma (reduced) ][ viewscreen (centered) ]
|
||
[ MFD LL ] [ Map ] [ MFD LR ]
|
||
```
|
||
|
||
The cockpit is a fixed **1920×1080 internal canvas** (scaled down
|
||
uniformly on smaller work areas): the viewscreen fills the whole
|
||
canvas (launch with `-res 1920 1080` for native 1:1 3D), with compact
|
||
320×240 MFD glasses in the four corners, the score glass top-center,
|
||
and the portrait map bottom-center. The panes deliberately **overlap
|
||
the viewscreen and render over it** — in the pod the MFD bezels
|
||
partially occluded the viewport, and the same trick gives a
|
||
full-screen 3D view with the cockpit floating over its edges. MFDs render green-screen and the map full-color/rotated,
|
||
CPU-side from the shared gauge canvas (the packed D3D windows stay
|
||
hidden); the 3D scene presents into the viewscreen pane via
|
||
`Present`'s `hDestWindowOverride` (`gMainPresentWindow`), clipped
|
||
around the panes (viewscreen pinned to the bottom of the z-order).
|
||
Mouse clicks over the viewscreen fall through to the game window
|
||
(STATIC pane hit-test transparency). The plasma glass is currently
|
||
hidden in cockpit mode. 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.
|