From be626c71ce29fbfd6ab96fd457478d9f1b9dd3b4 Mon Sep 17 00:00:00 2001 From: arcattack Date: Thu, 16 Jul 2026 08:47:52 -0500 Subject: [PATCH] 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 .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) --- engine/MUNGA/AUDCMP.cpp | 5 +++++ engine/MUNGA/AUDSEQ.cpp | 3 +++ game/reconstructed/myomers.cpp | 9 ++++++--- game/reconstructed/myomers.hpp | 7 ++++++- game/reconstructed/sensor.cpp | 9 ++++++--- game/reconstructed/sensor.hpp | 6 ++++++ 6 files changed, 32 insertions(+), 7 deletions(-) diff --git a/engine/MUNGA/AUDCMP.cpp b/engine/MUNGA/AUDCMP.cpp index 362f97c..886fb35 100644 --- a/engine/MUNGA/AUDCMP.cpp +++ b/engine/MUNGA/AUDCMP.cpp @@ -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); diff --git a/engine/MUNGA/AUDSEQ.cpp b/engine/MUNGA/AUDSEQ.cpp index 63018fb..9f83104 100644 --- a/engine/MUNGA/AUDSEQ.cpp +++ b/engine/MUNGA/AUDSEQ.cpp @@ -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); // diff --git a/game/reconstructed/myomers.cpp b/game/reconstructed/myomers.cpp index 5eced4c..a2e1054 100644 --- a/game/reconstructed/myomers.cpp +++ b/game/reconstructed/myomers.cpp @@ -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); } diff --git a/game/reconstructed/myomers.hpp b/game/reconstructed/myomers.hpp index 9bf14ed..3c90a29 100644 --- a/game/reconstructed/myomers.hpp +++ b/game/reconstructed/myomers.hpp @@ -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; }; diff --git a/game/reconstructed/sensor.cpp b/game/reconstructed/sensor.cpp index 7910fc8..644586d 100644 --- a/game/reconstructed/sensor.cpp +++ b/game/reconstructed/sensor.cpp @@ -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); } diff --git a/game/reconstructed/sensor.hpp b/game/reconstructed/sensor.hpp index 9b5db12..62092b6 100644 --- a/game/reconstructed/sensor.hpp +++ b/game/reconstructed/sensor.hpp @@ -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). //##########################################################################