podprobe: emit boot-STABLE panel identities + ready-to-paste monitor🆔 lines
Adds a section resolving each screen's panel identity via the SAME Win32 API the game uses (EnumDisplayDevices on the display's MONITOR child) rather than the WmiMonitorID query above -- if probe and engine read different sources the printed fragments could fail to match what the engine tests. Verified on the dev box: probe and engine emit byte-identical identities. Answers the open [T3] multi-panel question WITHOUT deploying a build (pure OS data). When one EDID code appears on SEVERAL panels (identical MFD models) it detects the collision and emits the per-connector UID form instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018SgmXGNMXavXiafKXf9MDC
This commit is contained in:
co-authored by
Claude Opus 5
parent
ec080cd61d
commit
990ad52563
@@ -82,6 +82,94 @@ try {
|
||||
} catch { W " (EDID query failed -- normal over some remote sessions: $_)" }
|
||||
W ""
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# BOOT-STABLE panel identity. Windows renumbers \\.\DISPLAYn and reorders the
|
||||
# enumeration when a panel is power-cycled or re-cabled, so binding the pod by
|
||||
# index or device name is fragile (Nick, 2026-08-07: "the order changed ... even
|
||||
# if the visual desktop tool looks the same"). Bind by the panel's own EDID
|
||||
# identity instead: glass_layout.cfg accepts `monitor:id:<fragment>`.
|
||||
#
|
||||
# This deliberately calls the SAME Win32 API the game does (EnumDisplayDevices
|
||||
# on the display's MONITOR child) rather than the WmiMonitorID above -- if the
|
||||
# probe and the engine read different sources, the fragments printed here might
|
||||
# not be what the engine actually matches against.
|
||||
# ---------------------------------------------------------------------------
|
||||
W "---- BOOT-STABLE panel identity (paste these into glass_layout.cfg) ----"
|
||||
try {
|
||||
if (-not ("BTDisp" -as [type])) {
|
||||
Add-Type -TypeDefinition @'
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
public class BTDisp {
|
||||
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
|
||||
public struct DISPLAY_DEVICE {
|
||||
public int cb;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public string DeviceName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public string DeviceString;
|
||||
public int StateFlags;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public string DeviceID;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public string DeviceKey;
|
||||
}
|
||||
[DllImport("user32.dll", CharSet=CharSet.Ansi)]
|
||||
public static extern bool EnumDisplayDevicesA(string dev, uint num, ref DISPLAY_DEVICE dd, uint flags);
|
||||
public static string MonitorId(string display) {
|
||||
DISPLAY_DEVICE dd = new DISPLAY_DEVICE();
|
||||
dd.cb = Marshal.SizeOf(typeof(DISPLAY_DEVICE));
|
||||
// 0x1 = EDD_GET_DEVICE_INTERFACE_NAME (richer path, includes connector UID)
|
||||
if (!EnumDisplayDevicesA(display, 0, ref dd, 0x1)) {
|
||||
dd = new DISPLAY_DEVICE();
|
||||
dd.cb = Marshal.SizeOf(typeof(DISPLAY_DEVICE));
|
||||
if (!EnumDisplayDevicesA(display, 0, ref dd, 0)) return "";
|
||||
}
|
||||
return dd.DeviceID;
|
||||
}
|
||||
}
|
||||
'@
|
||||
}
|
||||
$codes = @{}
|
||||
$rows = @()
|
||||
foreach ($s in [System.Windows.Forms.Screen]::AllScreens) {
|
||||
$sid = [BTDisp]::MonitorId($s.DeviceName)
|
||||
# EDID PnP code = 3 letters + 4 hex digits (AUO10ED, DEL4231)
|
||||
$code = ""
|
||||
if ($sid -match '[\\#\?]([A-Za-z]{3}[0-9A-Fa-f]{4})[\\#\?]') { $code = $Matches[1] }
|
||||
elseif ($sid -match '([A-Za-z]{3}[0-9A-Fa-f]{4})') { $code = $Matches[1] }
|
||||
$rows += [pscustomobject]@{ Dev=$s.DeviceName; Prim=$s.Primary; Sid=$sid; Code=$code
|
||||
X=$s.Bounds.X; Y=$s.Bounds.Y; W=$s.Bounds.Width; H=$s.Bounds.Height }
|
||||
if ($code -ne "") { $codes[$code] = 1 + $(if ($codes.ContainsKey($code)) { $codes[$code] } else { 0 }) }
|
||||
}
|
||||
foreach ($r in $rows) {
|
||||
W (" {0}{1} {2},{3} {4}x{5}" -f $r.Dev, $(if ($r.Prim) { " *PRIMARY*" } else { "" }), $r.X, $r.Y, $r.W, $r.H)
|
||||
W (" stable-id : {0}" -f $(if ($r.Sid) { $r.Sid } else { "(unavailable)" }))
|
||||
if ($r.Code -ne "" -and $codes[$r.Code] -gt 1) {
|
||||
# Same model on more than one output: the EDID code alone is ambiguous.
|
||||
# The connector UID in the tail is what separates them.
|
||||
$uid = ""
|
||||
if ($r.Sid -match '(UID[0-9]+)') { $uid = $Matches[1] }
|
||||
if ($uid -ne "") {
|
||||
W (" cfg form : monitor:id:{0} <-- code '{1}' is on {2} panels, so use the UID" -f $uid, $r.Code, $codes[$r.Code])
|
||||
} else {
|
||||
W (" cfg form : (AMBIGUOUS -- '{0}' appears on {1} panels and no UID found;" -f $r.Code, $codes[$r.Code])
|
||||
W " use a longer unique substring of stable-id above)"
|
||||
}
|
||||
} elseif ($r.Code -ne "") {
|
||||
W (" cfg form : monitor:id:{0}" -f $r.Code)
|
||||
} else {
|
||||
W " cfg form : (no EDID code parsed -- use a substring of stable-id)"
|
||||
}
|
||||
}
|
||||
$dupes = ($codes.GetEnumerator() | Where-Object { $_.Value -gt 1 } | Measure-Object).Count
|
||||
if ($dupes -gt 0) {
|
||||
W ""
|
||||
W (" NOTE: {0} EDID code(s) appear on more than one panel (identical models)." -f $dupes)
|
||||
W " Those lines use the connector UID instead, which is per-output."
|
||||
}
|
||||
W ""
|
||||
W " Run this again AFTER a reboot or a panel power-cycle: the device names"
|
||||
W " and ordering above may move, but stable-id / cfg form must NOT."
|
||||
} catch { W " (stable-identity probe failed: $_)" }
|
||||
W ""
|
||||
|
||||
W "---- SERIAL PORTS (the RIO board lives on one of these) ----"
|
||||
try {
|
||||
$sp = Get-CimInstance Win32_SerialPort
|
||||
|
||||
Reference in New Issue
Block a user