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>
This commit is contained in:
Joe DiPrima
2026-08-06 11:31:49 -05:00
co-authored by Claude Fable 5
parent bf39b81b9d
commit 67a4f09e86
4 changed files with 281 additions and 4 deletions
+150
View File
@@ -0,0 +1,150 @@
# podprobe.ps1 -- pod / crash-cart display + I/O topology probe.
#
# Run ON THE POD PC (PowerShell, no install, no admin):
# powershell -ExecutionPolicy Bypass -File podprobe.ps1
#
# Prints and writes podprobe.txt: GPUs, every monitor with its VIRTUAL DESKTOP
# rect (the coordinates glass_layout.cfg needs), EDID make/model (to identify
# the original pod panels), serial ports (the RIO board), and a PROPOSED
# glass_layout.cfg mapping the six pod surfaces onto the non-primary monitors.
#
# Then, in the game's working directory:
# copy the proposed glass_layout.cfg in
# set BT_GLASS=1 & set BT_GLASS_PANELS=1 & set BT_POD_SURFACES=1
# set BT_GLASS_LAYOUT=load (add =save to persist drags instead)
# btl4.exe -platform pod
# The log prints one "[glasswin] '<title>' ... -> monitor \\.\DISPLAYn" line per
# surface: that is the receipt that a picture landed on the right panel.
$ErrorActionPreference = 'Continue'
$out = New-Object System.Collections.ArrayList
function W($s) { [void]$out.Add($s); Write-Host $s }
W "==================== BT411 POD PROBE ===================="
W ("host : {0}" -f $env:COMPUTERNAME)
W ("when : {0}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'))
W ("windows : {0}" -f (Get-CimInstance Win32_OperatingSystem).Caption)
W ""
W "---- GPUs ----"
try {
Get-CimInstance Win32_VideoController | ForEach-Object {
W (" {0}" -f $_.Name)
W (" driver {0} ({1}) mode {2}x{3} ram {4} MB" -f `
$_.DriverVersion, $_.DriverDate, $_.CurrentHorizontalResolution,
$_.CurrentVerticalResolution, [int]($_.AdapterRAM / 1MB))
}
} catch { W " (video controller query failed: $_)" }
W ""
W "---- MONITORS (virtual-desktop rects -- these are the layout coordinates) ----"
Add-Type -AssemblyName System.Windows.Forms | Out-Null
$screens = [System.Windows.Forms.Screen]::AllScreens
$i = 0
foreach ($s in $screens) {
$b = $s.Bounds
W (" [{0}] {1}{2} x={3} y={4} {5}x{6} bpp={7}" -f `
$i, $s.DeviceName, $(if ($s.Primary) { " *PRIMARY*" } else { "" }),
$b.X, $b.Y, $b.Width, $b.Height, $s.BitsPerPixel)
$i++
}
W (" total screens: {0}" -f $screens.Count)
W ""
W "---- EDID identity (which physical panel is which) ----"
try {
Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object {
$mk = -join ($_.ManufacturerName | Where-Object { $_ -ne 0 } | ForEach-Object { [char]$_ })
$nm = -join ($_.UserFriendlyName | Where-Object { $_ -ne 0 } | ForEach-Object { [char]$_ })
$sn = -join ($_.SerialNumberID | Where-Object { $_ -ne 0 } | ForEach-Object { [char]$_ })
W (" {0} | make={1} model='{2}' serial={3} year={4}" -f `
$_.InstanceName, $mk, $nm, $sn, $_.YearOfManufacture)
}
} catch { W " (EDID query failed -- normal over some remote sessions: $_)" }
W ""
W "---- SERIAL PORTS (the RIO board lives on one of these) ----"
try {
$sp = Get-CimInstance Win32_SerialPort
if ($sp) { $sp | ForEach-Object { W (" {0} {1}" -f $_.DeviceID, $_.Name) } }
else {
$reg = 'HKLM:\HARDWARE\DEVICEMAP\SERIALCOMM'
if (Test-Path $reg) {
(Get-ItemProperty $reg).PSObject.Properties |
Where-Object { $_.Name -notlike 'PS*' } |
ForEach-Object { W (" {0} -> {1}" -f $_.Name, $_.Value) }
} else { W " (none found)" }
}
} catch { W " (serial query failed: $_)" }
W ""
W "---- REMOTE SESSION ----"
W (" SESSIONNAME={0} (a console session drives the real panels; an RDP" -f $env:SESSIONNAME)
W " session gets a VIRTUAL display and will NOT light the pod monitors."
W " Chrome Remote Desktop attaches to the CONSOLE -- that is what we want."
W ""
# ---------------- proposed layout ----------------
# Pod surface roles, in the order the cab reads them. Sizes are the native
# surface sizes the game creates in BT_POD_SURFACES mode.
$roles = @(
@{ title = 'Heat MFD'; w = 640; h = 480; note = 'upper LEFT (coolant)' },
@{ title = 'Engineering'; w = 640; h = 480; note = 'upper CENTER (engineering)' },
@{ title = 'Comm MFD'; w = 640; h = 480; note = 'upper RIGHT (hot box / comm)' },
@{ title = 'Left Weapons'; w = 640; h = 480; note = 'lower LEFT (weapons)' },
@{ title = 'Right Weapons'; w = 640; h = 480; note = 'lower RIGHT (weapons)' },
@{ title = 'Secondary / Radar'; w = 480; h = 640; note = 'secondary screen (radar, portrait)' }
)
$targets = @($screens | Where-Object { -not $_.Primary } | Sort-Object { $_.Bounds.Y }, { $_.Bounds.X })
W "---- PROPOSED glass_layout.cfg ----"
if ($targets.Count -eq 0) {
W " ! No non-primary monitors found. Either the pod panels are not attached to"
W " this PC, or this is a remote/virtual display session. Nothing to map yet."
} else {
W (" {0} non-primary monitor(s) available; assigning in top-to-bottom, left-to-right order." -f $targets.Count)
if ($targets.Count -lt $roles.Count) {
W (" ! Fewer panels than surfaces -- the last {0} surface(s) stay on the primary display." -f ($roles.Count - $targets.Count))
}
}
$cfg = New-Object System.Collections.ArrayList
[void]$cfg.Add('# BT411 glass cockpit window layout -- generated by tools/podprobe.ps1')
[void]$cfg.Add('# "<title>=x,y,w,h,noframe,bare" (bare = surface only, no desktop buttons)')
[void]$cfg.Add('# Coordinates are VIRTUAL DESKTOP pixels; run the probe again after any')
[void]$cfg.Add('# display rearrangement, because Windows renumbers the desktop origin.')
for ($r = 0; $r -lt $roles.Count; $r++) {
$role = $roles[$r]
if ($r -lt $targets.Count) {
$b = $targets[$r].Bounds
# centre the surface on the panel (exact fit when the panel is 640x480)
$x = $b.X + [int](($b.Width - $role.w) / 2)
$y = $b.Y + [int](($b.Height - $role.h) / 2)
$line = "{0}={1},{2},{3},{4},noframe,bare" -f $role.title, $x, $y, $role.w, $role.h
[void]$cfg.Add($line)
W (" {0,-18} -> {1} ({2}x{3}) at {4},{5} [{6}]" -f `
$role.title, $targets[$r].DeviceName, $b.Width, $b.Height, $x, $y, $role.note)
} else {
[void]$cfg.Add(("# {0}=<x>,<y>,{1},{2},noframe,bare # no panel assigned" -f $role.title, $role.w, $role.h))
}
}
$cfgPath = Join-Path (Get-Location) 'glass_layout.cfg.proposed'
$cfg | Set-Content -Path $cfgPath -Encoding ASCII
W ""
W (" wrote {0}" -f $cfgPath)
W " -> review it, rename to glass_layout.cfg in the game's working directory."
W ""
W "---- NOTES ----"
W " * The pod's main 3D view is the GAME's own window (not a glass panel); put it"
W " on the main-view monitor with the normal window/fullscreen controls."
W " * 640x480 panels: if Windows does not offer that mode, the surface still"
W " renders 640x480 inside whatever mode the panel runs -- centred, not scaled."
W " * The 1995 rig spanned the five MFDs as ONE 1280x480 surface via NVIDIA"
W " Horizontal Span, which modern drivers removed. This per-panel window path"
W " replaces it and needs no special driver."
$txt = Join-Path (Get-Location) 'podprobe.txt'
$out | Set-Content -Path $txt -Encoding ASCII
Write-Host ""
Write-Host ("full report written to {0}" -f $txt)