39144813a4bfd5ab42bf101cfe8205a66591572e
16
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
654277bb7b |
pod: freeze the ALPHA-MR rig in environ.ini (BT_FIT, L4PLASMA=NONE)
The cart's display config was carried by a launcher .bat, so it only came up
right if the game was started one particular way. Move it into the file the
engine already reads before anything touches the environment.
content/environ.ini <- scratchpad/pod/podprofile.ini, merged idempotently
between markers by scratchpad/pod/mergeprofile.ps1
Two gates were missing for that to be enough:
BT_FIT=1 the env spelling of -fit, so the borderless main view does not
depend on one launcher's command line (shortcut, scheduled
task and autostart all have to produce the same rig)
L4PLASMA= NONE / OFF / 0 -> no marquee at all. Leaving it unset does
NOT work: the GLASS profile force-defaults it to SCREEN, which
drops a desktop plasma window on the cab's glass. The boot
banner now reports the live state instead of always claiming
"plasma window".
Also lands the bring-up engine work this depended on: monitor:<name|index>
layout binding (device-bound, not pixel-bound -- desktop rects move when a
display re-enumerates), ",bare" implying frameless, rotation-aware radar
surface sizing, BT_GAUGE_SEC_ROT accepting 0-3 (it silently forced 3 for
anything but 1), 180-degree ExpandPlaneToBGRA, and the BT_POD_CHANMAP /
BT_POD_IDENT / BT_POD_CHANTEST identification gates.
Verified on the cart, build 4.11.813, launcher carrying none of it:
[boot] environ.ini: 9 setting(s) applied
[boot] platform profile: GLASS (PadRIO; plasma off [L4PLASMA])
[cockpit] -fit: borderless 800x600
[glasswin] radar rotation 0 (none)
... all three surfaces on their intended \.\DISPLAYn
No [plasmawin] line in an otherwise-logging run = the ctor never ran.
KB: pod-hardware.md gains the ALPHA-MR section (mapping, the two wiring
deviations, the frozen profile, the session-0 remote-work traps) and its RGB
SPLIT "OPEN: which way is the cart wired" is now SETTLED -- it is splitter
wired, the composite is what lit it. glass-cockpit.md documents monitor:
binding, BT_FIT and L4PLASMA=NONE.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rw7No5wLTpkaUgA3ANbtZZ
|
||
|
|
e179c7033f |
BT_POD_RGB: the authentic RGB-split output -- one window per VGA PORT
Implements what the pod actually does (pod-hardware.md THE RGB SPLIT): a VGA port's R/G/B lines each drive a separate mono MFD monitor, so a window is not one MFD -- it is one PORT carrying up to three. BT_POD_RGB=1 collapses the five MFD windows into the two ports the cab drives (Port A: Comm=red, Mfd2=green, Heat=blue; Port B: Mfd1=red, Mfd3=green) and composites each group's planes into the colour channels, leaving the radar on its own full-colour port. Channel comes from the live port (GetEnableID), never a hardcoded table, so an Eng-page swap follows automatically; BlankColor planes contribute nothing, exactly as on the pod. Implies BT_POD_SURFACES (bare 640x480 pictures -- the cab's buttons are physical). Verified locally (bare windows, "RGB COMPOSITE of 2 plane(s): Comm Mfd2") and LIVE ON NICK'S CRASH CART over the tailnet: Port A -> DISPLAY4, Port B -> DISPLAY2, radar -> DISPLAY1, all exact-fit. Pod scratch kit included (ssh helper, layout cfgs for both modes, launcher; the mission-egg launcher fix -- a bare MP.EGG exits the mission loop with no relay, and BT_FE_SOLO parks at the menu, so neither lights the panels). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
67a4f09e86 |
POD MFD bring-up: BT_POD_SURFACES bare-panel mode + placement receipts + probe
Nick's crash cart is the first shot at driving the real MFD panels, so the
pieces the cab needs that the desktop glass path lacked:
- BT_POD_SURFACES=1 (L4GLASSWIN): crop every display window to its SURFACE
(MFDs exactly 640x480, radar 480x640 portrait), drop the on-screen RIO
button banks -- the cab's buttons are PHYSICAL, so drawing fake ones onto a
real panel is exactly wrong -- go frameless, and skip the Flight Controls
pad entirely (6 windows, not 7). Per-window ",bare" in glass_layout.cfg
for mixed rigs (idempotent with the global mode).
- Placement receipts: each window logs which PHYSICAL monitor it landed on
("[glasswin] 'Heat MFD' surface=Heat at X,Y 640x480 bare -> monitor
\.\DISPLAYn (...)"). Nobody can see 7 surfaces at once on a cab, and over
Chrome Remote Desktop you cannot see the panels at all -- the log is the
only confirmation the map is right.
- tools/podprobe.ps1: run-on-the-pod topology probe (no install/admin) --
GPUs, every monitor's virtual-desktop rect, EDID make/model, serial ports
(the RIO board), session type, plus a PROPOSED glass_layout.cfg assigning
the six surfaces to the non-primary monitors. Self-tested here (correctly
reports a single-monitor laptop and declines to map).
Local verify: 5 MFDs at 640x480 bare + portrait radar + Flight Controls
dropped, receipts printed. KB: pod-hardware §MFD PANELS ON REAL HARDWARE
(incl. WHY the 1995 path is not the route -- NVIDIA Horizontal Span is gone
from post-XP drivers and per-adapter exclusive fullscreen is fragile over a
remote session) + glass-cockpit env table.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
4beac48f31 |
Merge Cyd's glass-lamp-latency: #138 unfocused flash-rate fix + red Panic/Eject + plasma no-frame
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
67074c80e2 |
Plasma window joins the glass_layout.cfg no-frame list
The desktop plasma window (L4PLASMAWIN, "BattleTech - Plasma") is created by a
different TU than the per-display panels, so it couldn't be a gWins[] entry and
sat outside the sticky-layout / ,noframe system. Add a tiny extern-window
registry to L4GLASSWIN so it rides the same glass_layout.cfg:
- BTGlassLayout_QueryWindow(title, rect, noframe) -- read a title's saved rect
and ,noframe flag (used by the plasma on creation, BEFORE sizing, since
WS_POPUP's frame extent differs from the framed tool window).
- BTGlassLayout_RegisterExtern(hwnd, title) -- register an externally-created
window so SaveLayout writes its line (with a last-known-rect cache so a
teardown before the save still preserves the line).
- BTGlassLayout_Save() -- public save trigger the plasma WndProc calls on
WM_EXITSIZEMOVE / teardown.
L4PLASMAWIN now reads its saved rect+flag on create (WS_POPUP when ,noframe,
position restored), registers itself, and saves on finished-drag/teardown. All
BT_GLASS-gated; the pod is untouched. The plasma blits directly every frame, so
it has no WM_TIMER focus-throttle.
Verified: Release links clean; drag wrote "BattleTech - Plasma=321,222,528,167",
reload with ,noframe brought it up WS_POPUP (WS_CAPTION absent) at 321,222.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
7d112ce309 |
Glass panels: flash at full rate when unfocused + red Panic/Eject button
Two glass-panel indicator fixes reported by playtesters. 1. FLASH SLOW UNLESS FOCUSED. The per-display panel windows repaint off a 62ms WM_TIMER, and Windows coalesces/throttles timer + paint messages for a window that is in the BACKGROUND (unfocused) -- so with the game window holding focus the panels' lamp flash (a repaint-driven animation) crawled, and giving a panel focus un-throttled it. (My earlier surround fix drew in the main D3D frame and never touched these separate windows.) New BTGlassPanels_Tick(), called once per frame from the main render loop (L4VIDEO), drives a synchronous InvalidateRect+UpdateWindow at the ~16Hz flash cadence -- the main loop runs every frame regardless of which window has focus, and the forced paint bypasses the throttled timer-message path. The WM_TIMER stays for its one-shot re-snap. 2. RED PANIC/EJECT. 0x3D is the Panic/Eject button; on the blue flight panel it was just another blue block. The shared flight-grid geometry (L4RIOBANK) now tags 0x3D as colorClass 0 (red); L4GLASSWIN's AdoptBank maps colorClass 0 -> ClrRed explicitly (the flight bank's ClrBlue default no longer swallows it), and the surround (L4VB16) already renders non-blue/yellow as red -- so the eject stands out red in both the surround and the exploded window. Verified: Release links clean (40 tolerated /FORCE externals only); exploded panels boot + run 13s no crash under the per-frame repaint pump; riobank dump confirms 0x3d class=0 (red), neighbours class=2 (blue). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
78722542fd |
#118: REMOVE the full-face flash overlays -- the MFD corruption, root-caused
The operator's three captures decode as ONE mistake drawn two ways: the cockpit compositor deliberately draws the side buttons as BIG rects tucked UNDER the display surfaces (step 2), with only the protruding edge visible -- the edge IS the port's lamp light (the pod's backlit keys sat beside the CRT; there is no in-display face to light). My on-top "flash overlay" ( |
||
|
|
5f79dcee3b |
#118: flashing lamps draw ON TOP of the MFD imagery -- the invite is visible
The glass windows paint buttons UNDER the display surface (only a sliver of edge protrudes), so the RIO flash commands were arriving ([lamp] 0xb <- 0x37 FLASHING in every trace) while the operator "never saw it flash" -- the blink was a few masked pixels. Lamps carrying RIO flash bits (state & 3) now re-draw their full face above the surface with the tick-phased shade: the gotoEngineering / engEject invites read like the pod's backlit keys. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
aa788bc56d |
noframe: drop the drag-by-surface -- it is a finishing step, not a mode
Author's correction to the shape of yesterday's option. The intended workflow is: place the displays where you want them WITH their frames, quit, then edit glass_layout.cfg to turn the frame off. So a ,noframe window should be pinned, not draggable -- removed the WM_NCHITTEST -> HTCAPTION handler that made the surface a drag handle. The arrangement being finished is the point: with no caption there is nothing to drag it by, which is exactly what you want on a wall of monitors. Delete the flag to get the frame (and the dragging) back. Unchanged and still needed: SaveLayout writes the flag back, because any later drag of a FRAMED window rewrites the whole file and would otherwise strip it. Re-verified live: - Heat MFD comes up with WS_CAPTION clear and answers WM_NCHITTEST on its surface with HTCLIENT (pinned) -- no window reports HTCAPTION any more. - Comm MFD (unflagged) keeps its caption. - A framed window's WM_EXITSIZEMOVE rewrote the file and BOTH ,noframe flags survived, with the new header explaining the arrange-first workflow. - surround / exploded / pod / dev boot and simulate clean. Docs updated to describe the two-stage workflow rather than surface dragging: the file's own header, environ.ini's BT_GLASS_LAYOUT block, context/ glass-cockpit.md and the ledger (which records the removed behaviour so the next reader does not re-add it). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
f5f4c6c198 |
glass_layout.cfg: ",noframe" per-line option strips a window's title bar
Append it to a window's line and that window becomes a bare WS_POPUP -- no
caption, no border, just the display and its buttons -- for a multi-monitor
wall where the chrome is only noise:
Heat MFD=1920,0,657,539,noframe
Options are comma-separated after the four numbers and unknown ones are
ignored, so an older build reading a newer file loses the option but never the
line (the bindings.txt grammar rule, applied here).
TWO THINGS THAT WOULD HAVE MADE IT A TRAP, both handled:
- A frameless window has NO TITLE BAR TO DRAG, which is the entire point of
the sticky layout. So a noframe window is dragged BY ITS SURFACE:
WM_NCHITTEST returns HTCAPTION anywhere that is not a button, HTCLIENT over
one. Buttons stay clickable, and because Windows drives the move the drag
still ends in WM_EXITSIZEMOVE -- so it still saves.
- SaveLayout rewrites the WHOLE file, so it writes the flag back. Without
that, the first finished-drag after adding the option would have silently
stripped it.
Ordering: the flag is read BEFORE frame sizing (a quiet LoadLayout pre-pass,
then the normal pass after ComputeLayout), because AdjustWindowRect -- and
therefore the ring placement -- depends on whether a window carries chrome.
The pre-pass is quiet so the restore still logs exactly once.
Verified live: two flagged windows came up with WS_CAPTION clear while the
other five kept it (read back with GetWindowLong(GWL_STYLE)); a click still
dispatched on the frameless radar (CLICK 'Secondary / Radar' addr=0x18); and a
WM_EXITSIZEMOVE save round-tripped both flags back into the rewritten file.
surround / exploded / layout=off / pod / dev all boot and simulate clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
29c502df83 |
Glass windows remember where you drag them (BT_GLASS_LAYOUT)
The BT_GLASS_PANELS windows self-place in a pod-faithful ring and re-snap
once the main window is up. They carry WS_CAPTION so a dev can drag them,
but the drag never survived the menu->mission->menu relaunch loop.
BT_GLASS_LAYOUT (L4GLASSWIN.cpp) adds opt-in persistence to a cwd-relative
glass_layout.cfg beside bindings.txt (gitignored):
off/0/unset computed ring only, no file I/O (default, pod-faithful)
load restore saved positions on startup (per-window fallback
to computed); never writes
save/adjust restore first, then rewrite on each finished drag
(WM_EXITSIZEMOVE) and on teardown -- the round trip
One "<title>=x,y,w,h" line per window; position restored, size ignored
(frame size is deterministic from content, so an old w,h can't distort a
later geometry change). A restored window is flagged so ComputeLayout's
post-main-window re-snap leaves hand-placed windows alone. Native
analogue of TeslaRel410 pod-launch's per-rig --bridge-pos/--layout args.
Verified [T2 runtime round-trip]: load restored 7 from a seeded cfg;
save wrote all 7 with a window moved to 777,333 (GetWindowRect read the
live window); relaunch in load put that window physically at 777,333
after the re-snap fired. Release links clean (only the 40 tolerated
/FORCE externals).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
8284b8d9a7 |
Glass panels: MFD phosphor green (21FF42) + respect BT_COCKPIT_TINT
The BT_GLASS_PANELS=1 per-display windows tinted the mono MFD surfaces pure WHITE (MfdMonoTint 0x00FFFFFF) -- the cockpit surround already used phosphor green via BT_COCKPIT_TINT (L4VB16 CkTint). New GlassMfdTint(): default the standard green rgb(33,255,66)=0x0021FF42, overridable by the SAME BT_COCKPIT_TINT=RRGGBB env the surround honours (used verbatim as the 0x00RRGGBB ExpandPlaneToBGRA tint -- no R5G6B5 packing, which is the surround's D3D path). Pixel-verified live (BT_GLASS_PANELS=1): all lit interior MFD pixels R33 G255 B66 = 21FF42 by default (was white); BT_COCKPIT_TINT=FF8000 -> R255 G128 B0. Radar keeps its amber palette (monoTint -1, unchanged). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
5f88a4eeb2 |
The keyboard becomes the button board (RP412 bindings port) + a controls page
Ported RP412's bindings design and made it the DEFAULT: the letter and number rows are the MFD button banks laid out WHERE THEY SIT ON THE PANEL, flight moves to the numpad so the board stays free, F1-F12 are the map's two columns, and G/B stay unbound as the physical gap between the lower clusters. Expressed in BT's OWN grammar (slew/deflect/set, the Turn channel) -- bindings.txt is a documented compatibility surface and was not touched. Coverage: 61 of 72 addresses on the keyboard, and the 11 absent ones are exactly those the pod never wired (0x16/0x17/0x1E/0x1F column gaps, 0x38-0x3E intercom/door). All 72 stay clickable on the panel. It lands on BT's addresses unreasonably well: 1-4 + QWER are the ENTIRE coolant system (Condensers 1-6, flush, balance), F6/F7 the display and control-mode cycles, F9-F12 Generators A-D, F4 the crouch button reconstructed earlier today. THE DELIBERATE COST. A bound key is removed from the authentic 1995 typed-hotkey channel so it cannot double-dispatch, and this board binds nearly everything -- so 5 (Quad page), z (Eng1), t/y/u/i/o (pilot select) and +/- (target zoom) are given up. Unbind a key to get its 1995 meaning back. Documented in the file header, the markdown and the page. NEW RULE: A BINDINGS ROW WINS OVER A BUILT-IN CONVENIENCE KEY (PadRIO::KeyHasBinding). V and J/K/L are board buttons now, and those polls read GetAsyncKeyState directly -- without this they would have fired BOTH the button and the built-in. View toggle lives on BACKTICK alone. CONTROLS.MAP rewritten to mirror the board so glass/pod/dev still feel identical (the 2026-07-21 settlement): 90 bindings, 0 parse complaints. HAT LABELS CORRECTED [T1]. INPUT_PATH_AUDIT flagged 0x41-0x44 and was right. Settled from the streamed mapping (BT_CTRLMAP_LOG): elem 66 -> subsys 17 attrID 14, i.e. 0x42 is the TORSO subsystem, not a look; 0x44/0x43/0x41 are the mapper's LookLeft/LookRight/LookBehind (attrID 10/11/12). The .RES has no "TORSO CENTER" string -- its names are LookBehind/Down/Forward/Left/Right -- so the audit's wording was loose but its substance correct. Swept L4GLASSWIN, L4PADPANEL and L4VB16. docs/CONTROLS.html: interactive keyboard (hover a key for its address and meaning, MFD clusters outlined), pad diagram, panel map, the under-glass press-target figure, radar placement thumbnails and the environ.ini table -- modelled on RP412's page, rewritten for BT's addresses and hazards. mkdist wraps the fragment in a doctype/charset shell and ships it beside CONTROLS.txt. Verified: bindings.txt regenerates and loads (74 keys, 0 errors); CONTROLS.MAP 90 bindings, 0 errors; 72/72 panel addresses still dispatch; surround / exploded / dock / pod / dev boot and simulate with zero faults. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
61563c9efe |
Glass cockpit refit: one mode resolver, one button geometry, and a cockpit that scales
Replicates the RP412 cockpit line into BT411's own architecture -- porting the geometry and keeping our renderers, so BT_SHOT single-frame verification stays intact. MODE RESOLVER. Where the secondary displays go was decided in TWO places with duplicated precedence, and the boot banner read NEITHER -- it announced "per-display cockpit windows" for every glass boot, surround included. The split had also broken BT_COCKPIT=0: documented as the dock-bottom opt-out, the profile block converted it to BT_GLASS_PANELS=1, so the docked strip was UNREACHABLE under the glass profile. One resolver now, consumed by the banner, the pad-panel decision and the window sizing; BT_GLASS_PANELS is explicit-only; dock/window modes auto-raise BT_PAD_PANEL so the button field always has a home. L4RIOBANK -- one button geometry. Both renderers carried their own copy and had drifted: an MFD button was 156x138 reaching under the glass in the exploded window and a 76x24 sliver entirely OUTSIDE the glass in the surround. One module owns it now, both are consumers, placement stays per-renderer. The pod's under-glass rule (RP412 L4MFDVIEW): reach half the glass in behind the display, leave a lamp strip clearing the edge, paint buttons first and imagery over -- so the lamp reads as a bar and practically the whole display is the press target. The strip scales off the display's SHORT axis (the map is portrait) with a readable floor. Retired L4GLASSWIN's three local placers and seven layout constants. LAMP FLASH DECODE was wrong [T1]. BTLampBrightnessOf returned max(state1, state2) and blanked on the alternate phase; RIO::LampState (L4RIO.h [T0]) says solid shows state 1 and flashing ALTERNATES the two. Agrees only when one state is Off -- true for the Panic lamp, which is why it survived -- but L4LAMP.cpp:252 commands flashFast + state1Dim + state2Bright, a dim->bright pulse that rendered as a hard bright->off blink. Three copies existed (l4vb16.h, L4GLASSWIN, L4PADPANEL), all three wrong; the two locals now forward to the one fixed inline. THE COCKPIT SCALES. The fixed canvas was stretched into whatever the client area was, so a window dragged to a different shape squashed the instruments (the projection was aspect-corrected in task #20; the panels never were). Now one uniform scale, centred, leftover black. D3D9 applies it as a Present destination rect, which DISCARD forbids -- so the WINDOWED swap effect becomes COPY when the surround is up and multisampling is off. The click mapping had to follow (mapping against the full client drifts the hit test off every button by the bar width), as did the world aspect (under a uniform scale it is the view rect's own). -fit / -windowed-fullscreen: borderless over the monitor. - ordering trap: the first WM_SIZE beats the device, so a -fit boot logged aspect=3.14 and applied it on frame 1. The letterbox INTENT is decided in btl4main; L4VIDEO only confirms or withdraws it. PLAYER-TUNABLE DISPLAYS. BT_MFD_SCALE (+ _UL/_UC/_UR/_LL/_LR), BT_RADAR_SCALE, BT_RADAR_POS (CENTER/LEFT/RIGHT/MIDLEFT/MIDRIGHT). The surround BANDS derive from the resolved sizes -- that is why the sizes could not stay constants: the band a display hangs in has to grow with it or the canvas clips it. 100% reproduces the historical L276 R276 T223 B336 exactly. A corner map goes flush to the CANVAS edge and the lower MFD slides beside it (measuring off the view edge overlapped them by 232px). MAP LEGEND GRID -- measured, not inherited. scratchpad/measurelegend.py over a native capture: top 3, cell 102, pitch 107 of 640. RP412's map is 13 + 6x102 @ 105 -- same cell height, different top and pitch, so its numbers do NOT transfer. Our old even division had the pitch right by luck and sat 3px high of the labels. environ.ini. It was read ~300 lines into WinMain, AFTER the platform-profile block had run its getenv()s -- so every setting the profile reads was silently ignored FROM THE FILE and only worked as a real env var. It also putenv()'d comments verbatim. Now loaded immediately after the first-breath line, comments skipped, the real environment WINS over the file, and a fully documented default is written on first run (the bindings.txt convention: untracked, so extract-over-top never clobbers a player's settings). VERIFICATION HARNESS (new, reusable): BT_RIOBANK_LOG=1 dumps every bank; checkbank.py proves no address is SHADOWED (an address whose rect is covered by earlier buttons is dead however big it looks -- the overlapping under-glass banks make that a live hazard); clickbank.py posts a real click at every button centre. Verified: 72/72 placed, 0 shadowed, 72/72 dispatched in BOTH modes, after a resize, at 150%/135%, and at 75%+BOTTOMRIGHT; wide/tall drags and -fit undistorted on a 3440x1440; exploded/dock/pod/dev un-regressed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
5ba5697a08 |
Fix glass panel dead-button crash: null-init MessageHandlerSet gap slots (Gitea #18)
Clicking a per-display glass Engineering panel button (0x21 on an Eng page) hard-crashed via a wild call through an uninitialised pointer (eip=cdcdcdcd debug / 0x01048748 release), zero btl4 frames above Receiver::Receive. Root cause is the dense message-handler-table gap hazard (reconstruction- gotchas #11), the message-side twin of the attribute-table one -- NOT a /FORCE unresolved external (the glass link log carried only the known-benign mech3.obj CreateStreamedSubsystem set). Receiver::MessageHandlerSet::Find(id) returns messageHandlers[id-1].entryHandler for any id <= entryCount with no populated- check, and Receive() calls it when != NullHandler. The streamed Eng-page .CTL dispatches subsystem msg id 3/0xb to whatever subsystem is shown; a weapon (Emitter) registers only PoweredSubsystem 4-8 + MechWeapon 9-10, so id 3 is a gap below entryCount 10. Build did new HandlerEntry[entryCount] and left gaps uninitialised -> (this->*garbage)(msg). The 1995 binary has the identical non- zeroing new[] (part_002.c Build) and survived only on fresh-heap-zero luck: a weapon receiving id 3 was always meant to IGNORE it (id 3 = a Condenser/ Reservoir action in a different subsystem branch; the uniform Eng-page button template makes buttons for unimplemented actions authentically inert). The new per-display windows just made the id reachable live. Fix (engine, class-wide, faithful): Build now null-inits every slot (entryID=0/entryName=""/entryHandler=NullHandler) before copying inherited / placing supplied, so a gap is deterministically NullHandler -> Receive drops it (the authentic "Receiver ignores unhandled messages"), with an empty never-NULL name so the name-based Find() strcmp can't deref a gap. Correct dispatch contract, not a glass-path guard -> protects the whole dead-button class (#14). Also lands the [glasswin] CLICK crash-forensics log (names the button before dispatch). Verified under cdb: click-soaked every MFD bank (Engineering/L+R Weapons/Heat/ Comm, ~130 clicks through Quad<->Eng page cycles) -> zero AVs, reconstructed mapper preset selects still fire ([mode] preset (1,1)/(2,1)...); pod build + solo mission un-regressed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f338595685 |
Glass cockpit: per-display windows (BT_GLASS_PANELS)
Break the desktop glass cockpit's secondary displays out of the single combined pad panel + D3D gauge strip into ONE window per pod display, each carrying that display's surface with its RIO button bank, arranged pod-faithfully around the main view. New TU engine/MUNGA_L4/L4GLASSWIN.* (BT_GLASS-only), selected by the -platform glass preset via the new runtime gate BT_GLASS_PANELS (=0 falls back to the legacy single panel + dock). - Surfaces are CPU-expanded from the shared gauge buffer (SVGA16::ExpandPlaneToBGRA, no D3D) and StretchDIBits'd in -- the D3D dev-composite path (dock / window / overlay) stands down while active. - Buttons sit UNDER the imagery: big hidden click targets that reach into the display, with only a small protruding edge showing as a lamp light. Red MFD banks tile the top/bottom; radar rails run the sides + a bottom row; a Flight Controls window hosts the no-display banks. - Windows: Heat / Engineering / Comm / Left Weapons / Right Weapons / radar + Flight Controls; edge-to-edge (no in-client margin/title; OS caption labels each). - Fix blank surfaces: application/ghWnd are duplicate-defined and bind non-deterministically under /FORCE, so the fresh L4GLASSWIN TU read NULL. Reach the renderer/window via BTResolveGaugeRenderer/BTResolveMainWindow defined in btl4main.cpp off the real btl4App/hWnd pointers. New gotcha: reconstruction-gotchas.md S6 duplicate-GLOBAL corollary. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |