Files
BT411/tools/podprobe.ps1
T
Joe DiPrimaandClaude Fable 5 38b08c96d1 podprobe: run-compatibility verdict + XP-safe .bat fallback
The crash cart may BE the period pod PC (that is where NVIDIA Horizontal Span
still exists), in which case the first question is not the display map but
whether btl4.exe can launch at all -- a modern MSVC toolset needs Win7 SP1+.
The probe now states the verdict outright, and podprobe.bat covers the case
where PowerShell/.NET is not present to run the probe in the first place
(wmic + dxdiag, both XP-era tools).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 11:35:38 -05:00

170 lines
7.7 KiB
PowerShell

# 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 "---- WILL OUR BUILD EVEN RUN HERE? ----"
try {
$os = Get-CimInstance Win32_OperatingSystem
$ver = [Version]$os.Version
W (" OS version : {0} (build {1})" -f $os.Version, $os.BuildNumber)
W (" architecture: {0}" -f $os.OSArchitecture)
if ($ver.Major -lt 6) {
W " *** STOP: this is Windows XP/2003-era. btl4.exe is built with a modern MSVC"
W " toolset and WILL NOT LAUNCH here (CRT + API requirements). Options:"
W " (a) put a newer Windows on the cart, or (b) rebuild with the v141_xp"
W " toolset (VS2017), or (c) drive the panels from a modern PC instead."
} elseif ($ver.Major -eq 6 -and $ver.Minor -lt 1) {
W " *** WARNING: Vista-era. Untested; Win7 SP1+ is the practical minimum."
} else {
W " OK: modern enough for the current build."
}
} catch { W " (OS query failed: $_)" }
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)