The wireframe key works and Steam is optional

Alt+W had been a no-op since the 2007 DPL->Direct3D port, which stubbed
DPLToggleWireframe along with every other dpl_ call. D3D9 has no global
wireframe property, so the toggle now records the intent in gWireframe
and ExecuteImplementation applies D3DRS_FILLMODE once per frame - which
also means it re-asserts itself after a device Reset. The sky dome and
the 2D pass are held solid: a wireframed dome buries the geometry you
turned the key on to look at, and the gunsight would otherwise come out
as bare diagonals.

Proving it needed a working copy, and that turned up a separate problem.
steam_api.dll was a hard import, so a machine without it died at load
time with 0xC0000135 - before a window, before a log line. It is now
delay-loaded, and because delay loading only moves that failure to the
first call, every Steam path is gated on
SteamNetTransport_ClientLibraryPresent(): Install and the two lobby
entries, with everything else downstream of one of them. Absent DLL
boots and races; absent DLL with RP412STEAM=1 logs the reason and stays
on TCP; DLL present brings the transport up exactly as before.

The documentation now says which debug keys are real. Five of the seven
are still 2007 stubs and always have been, so they are named as inert in
environ.ini's template and at the dispatch site - that beats letting the
next person debug a dead key, which is how this started. BUILD.md gains
a debug-key table, the delay-load contract for anyone adding a Steam
call site, and the environ.ini BOM trap that silently reverts
L4CONTROLS to KEYBOARD and then fail-fasts for want of a pod mapper.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-10 11:15:11 -05:00
co-authored by Claude Opus 5
parent 34abf40e7f
commit 0f4592c39a
10 changed files with 265 additions and 27 deletions
+45
View File
@@ -3,6 +3,41 @@
#include "l4steamtransport.h"
//########################################################################
// Is steam_api.dll actually here?
//
// Defined outside the RP412_STEAM guard on purpose: callers ask without
// caring how the build was configured, and a build without the SDK
// truthfully has no client library. See the header for why every Steam
// path has to come through here first.
//
// The answer is cached because it is asked on menu paint, and because a
// DLL that appeared halfway through a session is not a case worth
// supporting - the delay-load helper would have bound the first miss
// anyway.
//########################################################################
Logical
SteamNetTransport_ClientLibraryPresent()
{
#ifdef RP412_STEAM
static int present = -1;
if (present < 0)
{
present = (LoadLibraryA("steam_api.dll") != NULL) ? 1 : 0;
if (!present)
{
DEBUG_STREAM << "Steam: steam_api.dll not found beside the exe - "
<< "Steam features off, staying on TCP\n" << std::flush;
}
}
return present ? True : False;
#else
return False;
#endif
}
#ifdef RP412_STEAM
#include "l4nettransport.h"
@@ -686,6 +721,16 @@ Logical
return True;
}
//
// Before ANY Steam symbol: steam_api.dll is delay-loaded, so calling
// into it when it is missing raises the helper's fatal exception
// rather than failing. This is the gate that makes the DLL optional.
//
if (!SteamNetTransport_ClientLibraryPresent())
{
return False;
}
if (!SteamAPI_Init())
{
DEBUG_STREAM << "SteamNetTransport: SteamAPI_Init failed "