From 150961176cfc75be674b95626d2908152388853a Mon Sep 17 00:00:00 2001 From: arcattack Date: Sun, 26 Jul 2026 13:24:22 -0500 Subject: [PATCH] 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) --- CMakeLists.txt | 15 +++++++++ docs/CONTROLS.md | 5 +-- engine/MUNGA_L4/L4KEYLIGHT.cpp | 36 ++++++++++++++++++++ engine/MUNGA_L4/L4PADBINDINGS.cpp | 3 ++ engine/MUNGA_L4/L4PADRIO.cpp | 9 ++++- game/btl4main.cpp | 20 +++++++++++ players/README.txt | 56 +++++++++++++++++++------------ 7 files changed, 119 insertions(+), 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 741bed6..6a26664 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/docs/CONTROLS.md b/docs/CONTROLS.md index ece9804..437e693 100644 --- a/docs/CONTROLS.md +++ b/docs/CONTROLS.md @@ -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. diff --git a/engine/MUNGA_L4/L4KEYLIGHT.cpp b/engine/MUNGA_L4/L4KEYLIGHT.cpp index d08aee7..9d39bb7 100644 --- a/engine/MUNGA_L4/L4KEYLIGHT.cpp +++ b/engine/MUNGA_L4/L4KEYLIGHT.cpp @@ -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 #include @@ -404,3 +438,5 @@ void gWorker.join(); } } + +#endif // BT_KEYLIGHT_STUB diff --git a/engine/MUNGA_L4/L4PADBINDINGS.cpp b/engine/MUNGA_L4/L4PADBINDINGS.cpp index af68103..38849f1 100644 --- a/engine/MUNGA_L4/L4PADBINDINGS.cpp +++ b/engine/MUNGA_L4/L4PADBINDINGS.cpp @@ -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" diff --git a/engine/MUNGA_L4/L4PADRIO.cpp b/engine/MUNGA_L4/L4PADRIO.cpp index 40229a0..51f23bf 100644 --- a/engine/MUNGA_L4/L4PADRIO.cpp +++ b/engine/MUNGA_L4/L4PADRIO.cpp @@ -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) { diff --git a/game/btl4main.cpp b/game/btl4main.cpp index 3d60afd..85820b9 100644 --- a/game/btl4main.cpp +++ b/game/btl4main.cpp @@ -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; } diff --git a/players/README.txt b/players/README.txt index 0ff9e82..2198994 100644 --- a/players/README.txt +++ b/players/README.txt @@ -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