Audio: KILL THE CHIRP -- ConfigureActivePress backed real (idle -1) on Sensor+Myomers (task #50)

The obnoxious always-on clicking was the cockpit CONFIGURE-MODE ticker: an
authored looped sequence gated by an AudioIntegerTrigger with threshold -1 on
<subsystem>.ConfigureActivePress (the held-configure-button index; -1 = none).
The attribute was one of the inert-pad redirects -- the pad reads 0 = "button 0
held forever" -> the ticker Start-fired at load and pulsed 2.7/s eternally.
Found via [sendcfg]/[seqstart] traces: the first seq start immediately follows
the trigcfg(thresh=-1, onID=Start) construction on the pad address.

Fix: real int configureActivePress = -1 APPENDED to Sensor ("Avionics") and
Myomers, registered in their attribute tables.  Both classes are byte-exact
factory allocs, so the sizeof locks AND the placement-new alloc constants are
bumped TOGETHER (Sensor 0x328->0x32C, Myomers 0x358->0x35C) -- the tripwire
caught a mid-layout insert (seekVoltage@0x330 shift) and a fixed-alloc overrun
before they shipped; member moved to the true tail.  Wiring the live value
(EnterConfiguration/ExitConfiguration sets/clears the index) restores the
authored hold-to-configure tick later; idle -1 is the correct silent state.

VERIFIED: ProgramButton01 plays ZERO times (was the 2.7/s chirp);
ConfigureActivePress binds real (vtbl=FFFFFFFF = the -1); FootFallInt at 0.98
gain; stable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-16 08:47:52 -05:00
co-authored by Claude Opus 4.8
parent 847b9b85cd
commit be626c71ce
6 changed files with 32 additions and 7 deletions
+5
View File
@@ -291,6 +291,11 @@ AudioControlSend::AudioControlSend(
MemoryStream_Read(stream, &control_ID);
MemoryStream_Read(stream, &control_value);
if (getenv("BT_ATTRBIND_LOG")) { static int s_sd=0; if (s_sd++<80)
DEBUG_STREAM << "[sendcfg] tgt=" << (void*)audio_component
<< " ctl=" << (int)control_ID << "/" << control_value
<< " entity=" << (void*)entity << "\n" << std::flush; }
Check(entity);
entity->AddAudioComponent(this);
+3
View File
@@ -392,6 +392,9 @@ Logical
void
AudioControlSequence::StartSequence()
{
if (getenv("BT_ATTRBIND_LOG")) { static int s_ss=0; if (s_ss++<40)
DEBUG_STREAM << "[seqstart] seq=" << (void*)this << "\n" << std::flush; }
Check(this);
//
+6 -3
View File
@@ -102,7 +102,8 @@ Myomers::AttributeIndexSet&
ATTRIBUTE_ENTRY(Myomers, MinSeekVoltageIndex, minSeekVoltageIndex), // 0x15 @0x328
ATTRIBUTE_ENTRY(Myomers, MaxSeekVoltageIndex, maxSeekVoltageIndex), // 0x16 @0x32C
ATTRIBUTE_ENTRY(Myomers, SeekVoltage, seekVoltage), // 0x17 @0x330 (array base)
ATTRIBUTE_ENTRY(Myomers, OutputVoltage, outputVoltage) // 0x18 @0x344
ATTRIBUTE_ENTRY(Myomers, OutputVoltage, outputVoltage), // 0x18 @0x344
ATTRIBUTE_ENTRY(Myomers, ConfigureActivePress, configureActivePress) // 0x19 audio configure-ticker gate
};
static Myomers::AttributeIndexSet attributeIndex(
ELEMENTS(entries), entries,
@@ -164,6 +165,7 @@ Myomers::Myomers(
// vtable @005117dc installed by the compiler here.
speedEffect = 1.0f; // @0x31C
configureActivePress = -1; // APPENDED: no configure button held
heatRange = failureTemperature - degradationTemperature; // @0x348 (this[0x11C]-this[0x118])
heatRangeSquared = heatRange * heatRange; // @0x34C
velocityEfficiency = resource->velocityEfficiency; // @0x350 res+0x190
@@ -569,7 +571,7 @@ struct MyomersLayoutCheck
// .. accelerationEfficiency@0x354) land exactly at 0x31C..0x358.
static_assert(offsetof(Myomers, speedEffect) == 0x31C, "Myomers::speedEffect @0x31C (attr 0x12)");
static_assert(offsetof(Myomers, seekVoltage) == 0x330, "Myomers::seekVoltage @0x330 (attr 0x17)");
static_assert(sizeof(Myomers) == 0x358, "sizeof(Myomers) 0x358 (factory alloc, byte-exact)");
static_assert(sizeof(Myomers) == 0x35C, "sizeof(Myomers) 0x358 binary + 4 appended (alloc bumped in CreateMyomersSubsystem)");
};
@@ -584,6 +586,7 @@ struct MyomersLayoutCheck
//===========================================================================//
Subsystem *CreateMyomersSubsystem(Mech *owner, int id, void *seg)
{
return (Subsystem *) new (Memory::Allocate(0x358))
// 0x35C = the 0x358 binary object + 4 appended (configureActivePress; sizeof lock bumped too)
return (Subsystem *) new (Memory::Allocate(0x35C))
Myomers(owner, id, (Myomers::SubsystemResource *)seg);
}
+6 -1
View File
@@ -162,7 +162,8 @@ class Mech;
MaxSeekVoltageIndexAttributeID, // 0x16
SeekVoltageAttributeID, // 0x17
OutputVoltageAttributeID, // 0x18
NextAttributeID // 0x19
ConfigureActivePressAttributeID, // 0x19 audio configure-ticker gate (idle -1)
NextAttributeID // 0x1a
};
private:
@@ -340,6 +341,10 @@ class Mech;
Scalar heatRangeSquared; // @0x34C ctor = heatRange*heatRange (degradation-curve denominator)
Scalar velocityEfficiency; // @0x350 resource +0x190
Scalar accelerationEfficiency; // @0x354 resource +0x194
int configureActivePress; // @0x358 APPENDED (audio): configure held-button
// index; -1 = none. The audio configure-ticker gates
// on > -1; the inert-pad 0 ticked forever (the chirp).
// Alloc + sizeof lock bumped 0x358 -> 0x35C together.
friend struct MyomersLayoutCheck;
};
+6 -3
View File
@@ -117,7 +117,8 @@ const Sensor::IndexEntry
{
ATTRIBUTE_ENTRY(Sensor, RadarPercent, radarPercent), // @0x31C (map capabilities ratio)
ATTRIBUTE_ENTRY(Sensor, SelfTest, selfTest),
ATTRIBUTE_ENTRY(Sensor, BadVoltage, badVoltage)
ATTRIBUTE_ENTRY(Sensor, BadVoltage, badVoltage),
ATTRIBUTE_ENTRY(Sensor, ConfigureActivePress, configureActivePress) // audio configure-ticker gate
};
Sensor::AttributeIndexSet
@@ -162,6 +163,7 @@ Sensor::Sensor(
radarPercent = RadarBaseline; // @0x31C = 1.0f
selfTest = False; // @0x320 = 0
badVoltage = False; // @0x324 = 0
configureActivePress = -1; // APPENDED: no configure button held (audio ticker OFF)
// this[0x28] |= 0x8 -- flag "has an active per-frame Performance".
SetHasPerformanceFlag(); // param_1[10] |= 8
@@ -410,7 +412,7 @@ struct SensorLayoutCheck
static_assert(offsetof(Sensor, radarPercent) == 0x31C, "Sensor::radarPercent @0x31C (attr 0x12)");
static_assert(offsetof(Sensor, selfTest) == 0x320, "Sensor::selfTest @0x320");
static_assert(offsetof(Sensor, badVoltage) == 0x324, "Sensor::badVoltage @0x324");
static_assert(sizeof(Sensor) == 0x328, "sizeof(Sensor) 0x328 (factory alloc, byte-exact)");
static_assert(sizeof(Sensor) == 0x32C, "sizeof(Sensor) 0x328 binary + 4 appended (alloc bumped in CreateSensorSubsystem)");
};
@@ -424,6 +426,7 @@ struct SensorLayoutCheck
//===========================================================================//
Subsystem *CreateSensorSubsystem(Mech *owner, int id, void *seg)
{
return (Subsystem *) new (Memory::Allocate(0x328))
// 0x32C = the 0x328 binary object + 4 appended (configureActivePress; sizeof lock bumped too)
return (Subsystem *) new (Memory::Allocate(0x32C))
Sensor(owner, id, (Sensor::SubsystemResource *)seg);
}
+6
View File
@@ -149,6 +149,7 @@
RadarPercentAttributeID = PoweredSubsystem::NextAttributeID,
SelfTestAttributeID,
BadVoltageAttributeID,
ConfigureActivePressAttributeID, // audio configure-ticker gate (idle -1)
NextAttributeID
};
@@ -166,6 +167,11 @@
Logical
selfTest, // @0x320 ctor init 0
badVoltage; // @0x324 ctor init 0
int
configureActivePress; // APPENDED (audio): the cockpit-configure held-button
// index; -1 = none. The audio config gates the
// configure-mode ticker on this > -1 -- the inert-pad 0
// read as "button 0 held" and ticked FOREVER (the chirp).
//##########################################################################