Cockpit: fix button lamp brightness -- decode the bitfield, subdue the idle baseline
The buttons all read fully bright once PadRIO went live. Two causes: 1. The lamp value is a BITFIELD (RP412 LampLevel): bits 0-1 flash mode, bits 2-3 state1 brightness, bits 4-5 state2 (flash alternate). My code treated any non-zero as bright. Now decode it: solid -> state1 level; flashing -> alternate state1/state2 at the flash rate. Level 0=off, 1-2=dim, 3=bright. 2. Diagnosed (BT_LAMP_LOG): the pod lights EVERY mapped button's lamp to a uniform DIM baseline (0x14 = state1Dim+state2Dim, L4Lamp NotifyOfStateChange) -- 'button present, function idle' -- and only an ACTIVE function to bright (0x3C). So the dim baseline is on all buttons; rendering it at RP412's dim red (150,44,28) made the whole field look lit. Darkened off/dim so the idle field reads as unlit dark keys; bright (active) keeps RP412's full values and pops. Verified: idle cockpit shows dark/subdued button keys, not an all-lit field; the lamp decode animates flash modes and lights bright only on an active function. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -558,18 +558,70 @@ static void BTFillRect(LPDIRECT3DDEVICE9 device, float x, float y, float w, floa
|
||||
device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, sizeof(CVert));
|
||||
}
|
||||
|
||||
// Lamp byte -> current brightness level (0 off / 1-2 dim / 3 bright),
|
||||
// animating flash modes -- RP412 MFDSplitView::LampLevel. The lamp state is a
|
||||
// BITFIELD, not a boolean: low 2 bits = flash mode (solid/slow/med/fast), bits
|
||||
// 2-3 = state1 brightness, bits 4-5 = state2 (the flash alternate). Treating
|
||||
// any non-zero value as "lit" made every commanded lamp read fully bright.
|
||||
static int BTLampLevel(int lamp_state)
|
||||
{
|
||||
int mode = lamp_state & 0x03;
|
||||
int level1 = (lamp_state >> 2) & 0x03;
|
||||
int level2 = (lamp_state >> 4) & 0x03;
|
||||
if (mode == 0)
|
||||
return level1; // solid: state1 brightness
|
||||
static const int half_period[4] = { 0, 500, 250, 125 };
|
||||
return ((GetTickCount() / half_period[mode]) & 1) ? level2 : level1;
|
||||
}
|
||||
|
||||
// Fill colour by lamp brightness (ARGB). The pod lights EVERY mapped button's
|
||||
// lamp to a DIM baseline (0x14) -- "button present, function idle" -- and only
|
||||
// an ACTIVE function to bright. So the dim baseline must read as an unlit dark
|
||||
// key (else the whole field looks lit); only bright (level 3) glows. Bright
|
||||
// keeps RP412's ButtonFill values; off/dim are darkened so the idle field is
|
||||
// subdued.
|
||||
static DWORD BTButtonFill(int amber, int level)
|
||||
{
|
||||
if (amber)
|
||||
{
|
||||
if (level >= 3) return 0xFFFFD230; // active: RGB(255,210,48)
|
||||
if (level >= 1) return 0xFF4A3C0E; // dim baseline: subdued
|
||||
return 0xFF2E2508; // off
|
||||
}
|
||||
if (level >= 3) return 0xFFFF482C; // active: RGB(255,72,44)
|
||||
if (level >= 1) return 0xFF4A140D; // dim baseline: subdued
|
||||
return 0xFF2E0D08; // off
|
||||
}
|
||||
|
||||
static void BTDrawCockpitButtons(LPDIRECT3DDEVICE9 device, float W, float H)
|
||||
{
|
||||
BTCockpitBtn btn[64];
|
||||
int count = BTBuildCockpitButtons(W, H, btn, 64);
|
||||
// BT_LAMP_LOG: dump ALL 64 lamp states + decoded levels a few times so we
|
||||
// can see what the game actually commands vs what my buttons read.
|
||||
if (PadRIO::IsActive() && getenv("BT_LAMP_LOG") != NULL)
|
||||
{
|
||||
static int s_dumps = 0;
|
||||
static unsigned long s_last = 0;
|
||||
unsigned long now = GetTickCount();
|
||||
if (s_dumps < 3 && now - s_last > 2000)
|
||||
{
|
||||
s_last = now; ++s_dumps;
|
||||
DEBUG_STREAM << "[lampdump] all 64 lamps:";
|
||||
for (int u = 0; u < 64; ++u)
|
||||
{
|
||||
int raw = PadRIO::GetLampState(u);
|
||||
if (raw != 0)
|
||||
DEBUG_STREAM << " 0x" << std::hex << u << "=0x" << raw
|
||||
<< "(L" << std::dec << BTLampLevel(raw) << ")";
|
||||
}
|
||||
DEBUG_STREAM << "\n" << std::flush;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
int lit = PadRIO::IsActive() ? PadRIO::GetLampState(btn[i].unit) : 0;
|
||||
DWORD color;
|
||||
if (btn[i].amber)
|
||||
color = lit ? 0xFFFFB000 : 0xFF3A2A00; // amber lit / dim
|
||||
else
|
||||
color = lit ? 0xFFFF2020 : 0xFF3A0808; // red lit / dim
|
||||
int level = PadRIO::IsActive() ? BTLampLevel(PadRIO::GetLampState(btn[i].unit)) : 0;
|
||||
DWORD color = BTButtonFill(btn[i].amber, level);
|
||||
// a thin dark border reads as a raised key
|
||||
BTFillRect(device, btn[i].x - 1, btn[i].y - 1, btn[i].w + 2, btn[i].h + 2, 0xFF101010);
|
||||
BTFillRect(device, btn[i].x, btn[i].y, btn[i].w, btn[i].h, color);
|
||||
|
||||
Reference in New Issue
Block a user