merge fix-ups: the four review findings + a build portability gate the merge exposed

Applied on top of the glass-cockpit-refit merge, all from the pre-merge review:

1. README CONTROLS TABLE REWRITTEN for the new default board.  It still taught
   "W/S throttle, A/D turn" while the defaults moved flight to the numpad and
   handed the letter rows to the MFD banks -- a fresh install would read
   controls that do not work.  The new table teaches the numpad flight block,
   the panel-on-your-keys groups, F7 for control mode (was M), backtick for the
   camera (was V), the coolant valves on 1-3/QWE with the detent warning kept,
   and PgUp/PgDn volume.  UPGRADERS ARE TOLD EXPLICITLY that their preserved
   bindings.txt keeps their old keys, and that deleting it opts into the board.

2. BACKTICK VIEW-TOGGLE GUARDED.  The bindings-row-wins rule (KeyHasBinding)
   covered V and J/K/L but not backtick itself, which polled unconditionally --
   and BACKTICK is a nameable, unbound key, so binding it to a button
   double-dispatched (button + camera).  Both halves of the view poll are now
   guarded.

3. ENVIRON.INI REFUSES ONE-SHOTS.  The loader applied ANY key=value line, and
   BT_JOYCONFIG in the file would defeat the #66 one-shot in a sneaky way: the
   wizard DELETES the process var after running, so in every relaunched child
   there is no real env var left to win over the file -- capture wizard at
   every mission start.  BT_JOYCONFIG is now skipped with the reason in the
   template header, which also warns that test/debug hooks (BT_MP_FORCE_DMG
   and friends) do not belong in a file that silently persists forever.

4. VOLUME DOCUMENTED EVERYWHERE IT WAS MISSING.  CONTROLS.md gains the
   PgUp/PgDn row (the old "- / = (see below)" cell pointed at a note that never
   mentioned volume) and the note that the keys moved so they no longer share a
   key with anything in any layout; the bindings template header reserves
   PgUp/PgDn informally.

5. L4KEYLIGHT BUILD GATE (found by building the merge on this machine).  The
   C++/WinRT Dynamic Lighting TU does not compile against SDK 10.0.19041 --
   its bundled cppwinrt fails inside winrt/base itself (C2039 'wait_for').
   CMake now detects an SDK older than 10.0.22000 and builds a dormant stub
   with the same five-function scalar interface (logs once at Start, identical
   behaviour otherwise) -- extending the feature's own runtime philosophy
   ("no Dynamic Lighting -> log once, stay dormant") to build time.  Dynamic
   Lighting is a Windows 11 22H2 feature, so nothing real is lost on an older
   build machine, and machines with a newer SDK build the real mirror
   unchanged.

VERIFIED on the merged tree (4.11.572):
  * build clean -- 0 compile errors; the 40 /FORCE-tolerated unresolved
    externals are byte-identical to every pre-merge build (20
    CreateStreamedSubsystem + 20 DefaultData; the earlier claim that all 40
    were CSS was shorthand -- corrected here for the record).
  * solo boot: environ.ini template written + loaded, mode resolver announces
    the surround, historical bands L276/R276/T223/B336 confirmed, keylight
    stub logs its dormant line, BT_SHOT capture shows the under-glass button
    treatment and the corrected hat labels, 0 faults.
  * PgUp/PgDn volume PROVEN LIVE via injected keys: 5%->10%->15%->10%, saved
    to volume.cfg.  (Side catch: content\volume.cfg had been sitting at 0.00
    from an old test -- anyone using this tree had a silent game; reset.)
  * full relay cycle on the merged exe: 2 pods staged, launch pair, mission,
    StopMission, round RESET -- all clean.
  * all three console suites still pass; checkctx CLEAN.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-26 13:24:22 -05:00
co-authored by Claude Opus 5
parent 62e89018f5
commit 150961176c
7 changed files with 119 additions and 25 deletions
+15
View File
@@ -278,6 +278,21 @@ target_sources(munga_engine PRIVATE
# /Zp, so that part does not apply -- see the file header.)
set_source_files_properties("engine/MUNGA_L4/L4KEYLIGHT.cpp" PROPERTIES
COMPILE_OPTIONS "/std:c++17;/permissive-")
# ... and only where the SDK can actually compile it. SDK 10.0.19041's
# bundled cppwinrt fails inside winrt/base itself (C2039 'wait_for'), so on a
# machine with only an older SDK the TU builds its dormant stub instead --
# same interface, logs once, everything else identical. Dynamic Lighting is
# a Windows 11 22H2 feature anyway, so nothing real is lost on such a machine.
set(_bt_sdk "${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
if(NOT _bt_sdk)
set(_bt_sdk "${CMAKE_SYSTEM_VERSION}")
endif()
if(_bt_sdk VERSION_LESS "10.0.22000")
message(STATUS "keylight: Windows SDK ${_bt_sdk} too old for C++/WinRT "
"Dynamic Lighting -- building the dormant stub")
set_property(SOURCE "engine/MUNGA_L4/L4KEYLIGHT.cpp" APPEND PROPERTY
COMPILE_DEFINITIONS BT_KEYLIGHT_STUB)
endif()
target_include_directories(munga_engine BEFORE PRIVATE
"${CMAKE_SOURCE_DIR}/engine/shim"
"${DXSDK}/Include")
+3 -2
View File
@@ -23,7 +23,7 @@ Flight lives on the number pad so the board stays free.
| NumPad 0, Space | main trigger | | NumPad 1 / 3 / . | pinky / middle / upper |
| Shift / Ctrl | throttle up / down (the lever sticks) | | Alt | reverse thrust |
| ← ↓ → | look left / behind / right | | ↑ | torso centre |
| ` | cockpit / chase camera | | / = *(see below)* | — |
| ` | cockpit / chase camera | | PgUp / PgDn | volume up / down (saved) |
**You spawn in BASIC control mode.** In BASIC the stick steers and the pedals do nothing.
Press **F7** once for MID, where the pedals steer and the stick twists the torso — the full
@@ -66,7 +66,8 @@ ammo bay before it detonates).
Binding a key removes it from the authentic 1995 typed-hotkey channel so it cannot
double-dispatch. This board binds nearly everything, so those hotkeys are given up by design:
`5` = MFD1 Quad page, `z` = MFD3 Eng1, `t/y/u/i/o` = pilot select, `+`/`-` = target zoom.
Unbind a key in `bindings.txt` to get its 1995 meaning back. Same rule for the built-ins:
Unbind a key in `bindings.txt` to get its 1995 meaning back. (The old `-`/`=` VOLUME keys
moved to **PgUp/PgDn** -- they no longer share a key with anything, in any layout.) Same rule for the built-ins:
**`** is the view toggle (V is a board button now), and J/K/L cycle the MFD preset pages only
while unbound.
+36
View File
@@ -20,6 +20,40 @@
// on-screen cockpit buttons blink in step).
//===========================================================================//
//
// BUILD-TIME STUB GATE (merge 2026-07-26). The C++/WinRT body below needs a
// Windows SDK whose cppwinrt headers are new enough for Dynamic Lighting --
// SDK 10.0.19041's fail inside winrt/base itself (C2039 'wait_for'). On a
// build machine with only an older SDK, CMake defines BT_KEYLIGHT_STUB and
// this TU compiles the dormant stub instead: same five-function scalar
// interface, logs once at Start(), the game runs identically otherwise.
// This extends the feature's own runtime philosophy (no Dynamic Lighting ->
// log once, stay dormant) to build time, and keeps the link closed on every
// machine without demanding an SDK upgrade.
//
#if defined(BT_KEYLIGHT_STUB)
#include "l4keylight.h"
static void (*s_stubLogger)(const char *line) = 0;
void KeyLight_SetLogger(void (*logger)(const char *line))
{
s_stubLogger = logger;
}
void KeyLight_SetMap(const int *, const int *, const unsigned char *, int) {}
void KeyLight_UpdateLamps(const unsigned char *, int) {}
void KeyLight_Start()
{
if (s_stubLogger)
s_stubLogger("[keylight] built without Dynamic Lighting support "
"(Windows SDK too old at COMPILE time) -- RGB mirror "
"dormant on this build");
}
void KeyLight_Stop() {}
#else // the real C++/WinRT mirror
#include <windows.h>
#include <atomic>
@@ -404,3 +438,5 @@ void
gWorker.join();
}
}
#endif // BT_KEYLIGHT_STUB
+3
View File
@@ -277,6 +277,9 @@ static const char *defaultProfileText =
"key LALT button 0x3F\n"
"key RALT button 0x3F\n"
"\n"
"# PgUp/PgDn are the VOLUME keys (built in; they produce no typed character\n"
"# so they can never collide with a hotkey) -- leave them unbound.\n"
"\n"
"# --- the four mappable fire buttons ------------------------------------\n"
"# The mouse's side buttons are free if you want them on the trigger:\n"
"# key MOUSE4 button 0x40\n"
+8 -1
View File
@@ -649,8 +649,15 @@ void
// exists to prevent. Bind the key, and the built-in stands down.
{
static int s_backtickWas = 0;
// BOTH halves are KeyHasBinding-guarded (merge review 2026-07-26): the
// V half already was, but backtick polled unconditionally -- and
// BACKTICK is a nameable, unbound key, so a player who bound it to a
// button got a double-dispatch (button + camera toggle), the exact
// hazard the bindings-row-wins rule exists to prevent, in the one poll
// it had not been applied to.
int backtick_held = focused &&
(((GetAsyncKeyState(VK_OEM_3) & 0x8000) != 0) ||
((!KeyHasBinding(VK_OEM_3)
&& (GetAsyncKeyState(VK_OEM_3) & 0x8000) != 0) ||
(!KeyHasBinding('V') && (GetAsyncKeyState('V') & 0x8000) != 0));
if (backtick_held && !s_backtickWas)
{
+20
View File
@@ -254,6 +254,12 @@ static const char *kEnvironIniDefault =
"# a launcher .bat can override anything here. Delete a line to fall back to\n"
"# the built-in default.\n"
"#\n"
"# This file is for PERSISTENT settings only. One-shot switches (BT_JOYCONFIG\n"
"# -- use joyconfig.bat instead) are ignored here on purpose: they are designed\n"
"# to clear themselves after running once, and a file line would re-arm them at\n"
"# every mission start. Test/debug hooks (BT_MP_FORCE_DMG and friends) do not\n"
"# belong here either -- they would silently persist across every session.\n"
"#\n"
"# Input bindings live in bindings.txt beside this file (written with the\n"
"# full documented layout on first run; delete it to restore defaults).\n"
"\n"
@@ -483,6 +489,20 @@ static void BTLoadEnvironIni(void)
if (getenv(key) != NULL)
continue;
// ONE-SHOT variables never load from the file (merge review
// 2026-07-26). BT_JOYCONFIG is deliberately DELETED from the process
// environment after the wizard runs (the #66 one-shot) so the
// front-end relaunch chain cannot re-run it -- but a file line would
// re-arm it in every relaunched child, since by then there is no real
// env var left to win over the file. Result: the capture wizard at
// every mission start. environ.ini is for persistent settings;
// anything designed to clear itself cannot live in it.
if (_stricmp(key, "BT_JOYCONFIG") == 0)
{
++skipped;
continue;
}
putenv(p);
++applied;
}
+34 -22
View File
@@ -46,31 +46,43 @@ around the view (one window). The red MFD buttons, radar rails and
joystick buttons are all MOUSE-CLICKABLE -- right-click a button to
latch it held. Press V any time to toggle the external camera.
CONTROLS (keyboard):
W/S or Up/Down ....... throttle lever X / NumPad5 ... all stop
A/D or Left/Right .... turn pedals Alt ........... reverse thrust
Q/E .................. torso twist R/F ........... torso aim
NumPad 8/2/4/6 ....... torso aim/twist (alt) Shift ......... throttle up
1 or Space ........... main trigger 2 ............. middle thumb
3 or Ctrl ............ upper thumb (missiles) 4 ............ pinky
V view | B look-behind | M control mode | N schematic | J/K/L MFD pages
CONTROLS (keyboard) -- NEW DEFAULT LAYOUT THIS BUILD:
The keyboard IS the cockpit button board now: the letter and number
rows are the MFD button banks laid out where they sit on the panel,
and FLIGHT LIVES ON THE NUMBER PAD. Full map: CONTROLS.txt.
UPGRADING? Your saved content\bindings.txt is kept, so YOUR KEYS DO
NOT CHANGE (W/S throttle etc. still works for you). Delete
bindings.txt to switch to the new board described below.
FLIGHT (number pad -- NUMLOCK ON):
NumPad 8/2 ........... torso aim up/down NumPad 7/9 .... left/right pedal
NumPad 4/6 ........... torso twist NumPad 5 ...... all stop
NumPad 0 or Space .... main trigger NumPad 1/3/. .. pinky/middle/upper
Shift/Ctrl ........... throttle up/down Alt ........... reverse thrust
Left/Down/Right ...... look left/behind/right Up .......... torso centre
` (backtick) ......... cockpit / chase camera
PgUp / PgDn .......... game volume up/down (saved between sessions)
THE PANEL ON YOUR KEYS: 1-4/QWER = heat & coolant, 5-8/TYUI =
engineering, 9-0-minus-equals/OP[] = comm, ASDF/ZXCV = left weapons,
HJKL/NM,. = right weapons, F1-F12 = the map columns (F1/F2 zoom,
F4 crouch, F7 CONTROL MODE, F9-F12 Generators A-D). G and B are
deliberately unbound -- feel for the gap. Every button also stays
mouse-clickable on screen (right-click latches it held).
NOTE: you SPAWN IN BASIC control mode (the pod's rookie setting) --
in BASIC the stick steers and the pedal keys (A/D, arrows) do
NOTHING. Press M once for MID (pedals steer, stick twists the
torso -- the full experience). If 'turning does not work', it is
this, not a bug.
CONTROL MODE (BAS/MID/ADV, the M key IN the cockpit) is NOT the
in BASIC the stick steers and the pedals do NOTHING. Press F7 once
for MID (pedals steer, stick twists the torso -- the full
experience). If 'turning does not work', it is this, not a bug.
CONTROL MODE (BAS/MID/ADV, the F7 key IN the cockpit) is NOT the
menu's EXPERIENCE setting (novice/standard/veteran/expert) -- that
one changes the simulation (heat, damage), not your controls.
Numpad aim keys (8/2/4/6) need NUMLOCK ON; with it off they act as
arrow keys instead.
- / = ................ game volume down/up (saved between sessions)
H (hold) ............. coolant flush (dumps reservoir to cool everything)
C .................... cycle a coolant valve. CAREFUL: the detents go
1 - 5 - 50 (max) - 0 (CLOSED!) - back to 1. One press past max
SHUTS THE LOOP OFF and everything on it will overheat -- watch the
valve dial on the coolant screen. Boosting one loop starves the
others (the coolant supply is shared).
1/2/3/Q/W/E are the six coolant valves and 4 (hold) is the flush.
CAREFUL with the valves: the detents go 1 - 5 - 50 (max) -
0 (CLOSED!) - back to 1. One press past max SHUTS THE LOOP OFF and
everything on it will overheat -- watch the valve dial on the coolant
screen. Boosting one loop starves the others (the supply is shared).
A weapon gone quiet with ammo left has probably JAMMED (heat makes
ballistic weapons jam -- authentic!). Check its panel's ENG DATA page
for the jam lamp (a cocked round with warning bolts). The pod's fix