Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.
Layout:
engine/ MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
models) + image codec; the minimal rp/ headers the audio HAL needs
game/ reconstructed BT logic + surviving-original BT source + fwd shims
+ WinMain launcher
content/ full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
docs/ format specs + reconstruction ledgers
reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
tools/ MP console emulator + map/resource scanners
One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1027 lines
27 KiB
C++
1027 lines
27 KiB
C++
#include "mungal4.h"
|
|
#pragma hdrstop
|
|
|
|
#include "l4icom.h"
|
|
#include "l4host.h"
|
|
#include "l4app.h"
|
|
#include "l4grend.h"
|
|
#include "..\munga\hostmgr.h"
|
|
|
|
//-----------------------------------------------------------
|
|
// Timing values (in seconds) for CB button control
|
|
// All values derived experimentally
|
|
//-----------------------------------------------------------
|
|
#define SEEK_STEP_TIME 0.28 // seek step delay
|
|
#define NORMAL_STEP_TIME 0.05 // normal step delay
|
|
#define BEEP_TIME 0.2 // length of beep
|
|
|
|
//-----------------------------------------------------------
|
|
// Special code & data to test recalibration:
|
|
// set to '1' to create and use 'home' button
|
|
//-----------------------------------------------------------
|
|
#if 1
|
|
# define HOMETEST
|
|
static ControlsButton
|
|
resetButton;
|
|
enum
|
|
{
|
|
resetButtonNumber = LBE4ControlsManager::ButtonSecondary6
|
|
};
|
|
#endif
|
|
//-----------------------------------------------------------
|
|
// Debugging aid
|
|
//-----------------------------------------------------------
|
|
#if 0
|
|
# define LOCAL_TEST
|
|
# define Test_Tell(n) cout << n << flush;
|
|
#else
|
|
# define Test_Tell(n)
|
|
#endif
|
|
|
|
//-----------------------------------------------------------
|
|
// Button/lamp assignments
|
|
//-----------------------------------------------------------
|
|
static int
|
|
channelButtonNumber[L4Icom::numberOfChannels] =
|
|
{
|
|
LBE4ControlsManager::ButtonAuxUpperCenter1,
|
|
LBE4ControlsManager::ButtonAuxUpperCenter2,
|
|
LBE4ControlsManager::ButtonAuxUpperCenter3,
|
|
LBE4ControlsManager::ButtonAuxUpperCenter4,
|
|
LBE4ControlsManager::ButtonAuxUpperCenter5,
|
|
LBE4ControlsManager::ButtonAuxUpperCenter6,
|
|
LBE4ControlsManager::ButtonAuxUpperCenter7
|
|
};
|
|
|
|
#if 0
|
|
enum
|
|
{
|
|
//
|
|
// TEST I/O
|
|
//
|
|
pttButtonNumber = LBE4ControlsManager::ButtonAuxUpperCenter8,
|
|
homeSensorInput = LBE4ControlsManager::ButtonPanic,
|
|
pttRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight5,
|
|
ampEnableOutput = LBE4ControlsManager::ButtonAuxLowerRight6,
|
|
IncrementRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight7,
|
|
DecrementRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight8
|
|
};
|
|
#else
|
|
enum
|
|
{
|
|
//
|
|
// These are the "real" assignments
|
|
//
|
|
pttButtonNumber = LBE4ControlsManager::ButtonAuxUpperCenter8,
|
|
homeSensorInput = LBE4ControlsManager::ButtonIcomSensor,
|
|
pttRelayOutput = LBE4ControlsManager::LampIcomPTTRelay,
|
|
ampEnableOutput = LBE4ControlsManager::LampIcomAmpEnable,
|
|
IncrementRelayOutput = LBE4ControlsManager::LampIcomIncRelay,
|
|
DecrementRelayOutput = LBE4ControlsManager::LampIcomDecRelay
|
|
};
|
|
#endif
|
|
|
|
//-----------------------------------------------------------
|
|
// Handy routine to mute audio output
|
|
//-----------------------------------------------------------
|
|
void
|
|
amp_enable(LBE4ControlsManager * controls_manager, Logical on)
|
|
{
|
|
controls_manager->SetLamp(
|
|
ampEnableOutput,
|
|
(on ?
|
|
LBE4ControlsManager::LampSolidBright :
|
|
LBE4ControlsManager::LampSolidOff
|
|
)
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//##########################################################################
|
|
//############################ L4Icom ################################
|
|
//##########################################################################
|
|
|
|
//---------------------------------------------------------------------
|
|
// Creator
|
|
//---------------------------------------------------------------------
|
|
L4Icom::L4Icom(HostID host_id, int channel_offset)
|
|
:
|
|
Icom(host_id,0)
|
|
{
|
|
Test_Tell("L4Icom::L4Icom(" << host_id << ", " << channel_offset << ")\n");
|
|
Check_Pointer(this);
|
|
//--------------------------------------
|
|
// Initialize values
|
|
//--------------------------------------
|
|
channelOffset = channel_offset;
|
|
|
|
Check(application);
|
|
controlsManager = (LBE4ControlsManager *)
|
|
application->GetControlsManager();
|
|
Check(controlsManager);
|
|
|
|
hardwareChannel = Icom::undefinedChannel;
|
|
previousChannel = Icom::undefinedChannel;
|
|
previousPTTStatus = False;
|
|
//--------------------------------------
|
|
// Clear controls inputs
|
|
//--------------------------------------
|
|
homeSensor = 0;
|
|
channelButton = 0;
|
|
pttButton = 0;
|
|
//--------------------------------------
|
|
// Enable only if allowed
|
|
//--------------------------------------
|
|
char
|
|
*controlString(getenv("L4INTERCOM"));
|
|
|
|
if (controlString != NULL)
|
|
{
|
|
//--------------------------------------
|
|
// Seek channel 40, move to 1st channel
|
|
//--------------------------------------
|
|
Recalibrate();
|
|
}
|
|
else
|
|
{
|
|
//--------------------------------------
|
|
// Don't even try.
|
|
//--------------------------------------
|
|
state = disabled;
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// Destructor
|
|
//---------------------------------------------------------------------
|
|
L4Icom::~L4Icom()
|
|
{
|
|
Test_Tell("L4Icom::~L4Icom()\n");
|
|
Check(this);
|
|
//--------------------------------------
|
|
// Make sure intercom is turned off
|
|
//--------------------------------------
|
|
SetPTTStatusValue(False);
|
|
amp_enable(controlsManager, False);
|
|
//--------------------------------------
|
|
// Make note of failure state
|
|
//--------------------------------------
|
|
if (state == failed)
|
|
{
|
|
Tell("L4Icom::~L4Icom(), Icom had failed!\n");
|
|
NotationFile
|
|
*failureFile = new NotationFile("FAILURE.LOG");
|
|
Check(failureFile);
|
|
|
|
failureFile->SetEntry("Intercom","seekError",1);
|
|
|
|
delete failureFile;
|
|
}
|
|
//--------------------------------------
|
|
// The plug automatically unlinks
|
|
// from the L4Icom Manager upon deletion.
|
|
//--------------------------------------
|
|
Check_Fpu();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// Test instance
|
|
//---------------------------------------------------------------------
|
|
Logical
|
|
L4Icom::TestInstance() const
|
|
{
|
|
Icom::TestInstance();
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// SetChannelValue
|
|
//---------------------------------------------------------------------
|
|
void
|
|
L4Icom::SetChannelValue(int new_channel)
|
|
{
|
|
Test_Tell("L4Icom::SetChannelValue(" << new_channel << ")\n");
|
|
Check(this);
|
|
|
|
if ((state != disabled) && (state != failed))
|
|
{
|
|
//--------------------------------------
|
|
// Call overridden method
|
|
//--------------------------------------
|
|
Icom::SetChannelValue(new_channel);
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// Set PTTStatusValue
|
|
//---------------------------------------------------------------------
|
|
void
|
|
L4Icom::SetPTTStatusValue(Logical new_ptt)
|
|
{
|
|
Test_Tell("L4Icom::SetPTTStatusValue(" << new_ptt << ")\n");
|
|
Check(this);
|
|
|
|
if (state == onChannel)
|
|
{
|
|
//--------------------------------------
|
|
// Call overridden method
|
|
//--------------------------------------
|
|
Icom::SetPTTStatusValue(new_ptt);
|
|
//--------------------------------------
|
|
// Turn on/off PTT output and lamp
|
|
//--------------------------------------
|
|
if (previousPTTStatus != PTTStatus)
|
|
{
|
|
previousPTTStatus = PTTStatus;
|
|
|
|
Check(controlsManager);
|
|
int
|
|
relay_output =
|
|
PTTStatus ?
|
|
LBE4ControlsManager::LampSolidBright :
|
|
LBE4ControlsManager::LampSolidOff;
|
|
|
|
controlsManager->SetLamp(pttRelayOutput, relay_output);
|
|
|
|
controlsManager->SetLamp(
|
|
pttButtonNumber,
|
|
(PTTStatus ?
|
|
LBE4ControlsManager::LampSolidBright :
|
|
LBE4ControlsManager::LampSolidDim
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// SetPACaptiveValue
|
|
//---------------------------------------------------------------------
|
|
void
|
|
L4Icom::SetPACaptiveValue(Logical new_pa)
|
|
{
|
|
Test_Tell("L4Icom::SetPACaptiveValue(" << new_pa << ")\n");
|
|
Check(this);
|
|
|
|
//-----------------------------------------------
|
|
// If entering captivity, disable channel select
|
|
//-----------------------------------------------
|
|
if (new_pa && (!PACaptive))
|
|
{
|
|
//--------------------------------------
|
|
// Call overridden method
|
|
//--------------------------------------
|
|
Icom::SetPACaptiveValue(new_pa);
|
|
//--------------------------------------
|
|
// turn off PTT lamp
|
|
//--------------------------------------
|
|
controlsManager->SetLamp(
|
|
pttButtonNumber,
|
|
LBE4ControlsManager::LampSolidOff
|
|
);
|
|
//--------------------------------------
|
|
// Turn off channel indicators
|
|
//--------------------------------------
|
|
ChannelSelectState(False);
|
|
}
|
|
//-----------------------------------------------
|
|
// If exiting captivity, enable channel select
|
|
//-----------------------------------------------
|
|
if ((!new_pa) && PACaptive)
|
|
{
|
|
//--------------------------------------
|
|
// Call overridden method
|
|
//--------------------------------------
|
|
// This must be done BEFORE
|
|
// attempting to set the PTT status!
|
|
// (hence the duplicated call)
|
|
//--------------------------------------
|
|
Icom::SetPACaptiveValue(new_pa);
|
|
|
|
ChannelSelectState(True);
|
|
previousPTTStatus = 2; // non-Logical value, forces update
|
|
SetPTTStatusValue(PTTStatus); // force hardware update
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// Recalibrate
|
|
//---------------------------------------------------------------------
|
|
void
|
|
L4Icom::Recalibrate()
|
|
{
|
|
Test_Tell("L4Icom::Recalibrate()\n");
|
|
Check(this);
|
|
|
|
seekRequired = False;
|
|
timeAccumulator = 0.0;
|
|
seekCount = 84; // twice around plus a few more
|
|
ChannelSelectState(False); // Turn off selection lamps
|
|
amp_enable(controlsManager, False); // turn off the speaker
|
|
state = seek40;
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// Update
|
|
//---------------------------------------------------------------------
|
|
void
|
|
L4Icom::Update(Scalar delta_t)
|
|
{
|
|
Test_Tell("L4Icom::Update(" << delta_t << ")\n");
|
|
Check(this);
|
|
|
|
//------------------------------------------------------------------
|
|
// Do nothing if disabled or failed!
|
|
//------------------------------------------------------------------
|
|
if ((state == disabled) || (state == failed))
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
//------------------------------------------------------------------
|
|
// PTT control
|
|
//------------------------------------------------------------------
|
|
if (state == onChannel)
|
|
{
|
|
if (pttButton > 0)
|
|
{
|
|
SetPTTStatus(True);
|
|
pttButton = 0;
|
|
}
|
|
else if (pttButton < 0)
|
|
{
|
|
SetPTTStatus(False);
|
|
pttButton = 0;
|
|
}
|
|
}
|
|
else if (previousPTTStatus)
|
|
{
|
|
SetPTTStatus(False);
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
// Channel selection
|
|
//------------------------------------------------------------------
|
|
if (channelSelectEnabled)
|
|
{
|
|
//--------------------------------------
|
|
// Process button if pressed
|
|
//--------------------------------------
|
|
if (channelButton > 0)
|
|
{
|
|
//--------------------------------------
|
|
// Convert button press to icom channel
|
|
//--------------------------------------
|
|
int
|
|
button_number = channelButton - 1, // convert to button number
|
|
new_channel = Icom::undefinedChannel;
|
|
|
|
for(int i=0; i<numberOfChannels; ++i)
|
|
{
|
|
if (button_number == channelButtonNumber[i])
|
|
{
|
|
new_channel = i + channelOffset;
|
|
break;
|
|
}
|
|
}
|
|
//--------------------------------------
|
|
// Set the channel
|
|
//--------------------------------------
|
|
if (new_channel != Icom::undefinedChannel)
|
|
{
|
|
SetChannel(new_channel);
|
|
}
|
|
//--------------------------------------
|
|
// Clear the button
|
|
//--------------------------------------
|
|
channelButton = 0;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
// CB channel control logic
|
|
//------------------------------------------------------------------
|
|
if (seekRequired)
|
|
{
|
|
Test_Tell("...seek requested!\n");
|
|
Recalibrate();
|
|
}
|
|
|
|
timeAccumulator += delta_t;
|
|
|
|
//--------------------------------------
|
|
// Channel changer state machine
|
|
//--------------------------------------
|
|
switch(state)
|
|
{
|
|
case seek40:
|
|
if (WaitedLongEnough(SEEK_STEP_TIME))
|
|
{
|
|
Test_Tell("L4Icom::Update, seek40 ");
|
|
//-------------------------------------------
|
|
// Check for failure
|
|
//-------------------------------------------
|
|
if (--seekCount <= 0)
|
|
{
|
|
Test_Tell("SEEK FAILED!\n");
|
|
//-------------------------------------------
|
|
// FAILURE: went through all the channels
|
|
// and could not find channel 40!!!!
|
|
//
|
|
// This state is detected in the L4Icom
|
|
// destructor, which then writes to
|
|
// the failure log. Until then, all
|
|
// other intercom functions are disabled.
|
|
//-------------------------------------------
|
|
state = failed;
|
|
channel = Icom::undefinedChannel;
|
|
}
|
|
//-------------------------------------------
|
|
// Check for success
|
|
//-------------------------------------------
|
|
else if (homeSensor > 0)
|
|
{
|
|
//-------------------------------------------
|
|
// Found 40!
|
|
//-------------------------------------------
|
|
Test_Tell("--> reachedChannel\n");
|
|
hardwareChannel = (40-1);
|
|
state = reachedChannel;
|
|
//-------------------------------------------
|
|
// Display auxiliary intercom labels
|
|
//-------------------------------------------
|
|
{
|
|
Check(application);
|
|
|
|
L4GaugeRenderer
|
|
*gauge_renderer = ((L4Application *)application)->
|
|
GetGaugeRenderer();
|
|
Check(gauge_renderer);
|
|
|
|
gauge_renderer->Configure("intercomEnable", (Entity *) NULL);
|
|
}
|
|
//-------------------------------------------
|
|
// Everybody starts up on the 'first' channel
|
|
//-------------------------------------------
|
|
if (PACaptive)
|
|
{
|
|
channelBeforePA = channelOffset;
|
|
}
|
|
else
|
|
{
|
|
ChannelSelectState(True);
|
|
SetChannel(channelOffset);
|
|
}
|
|
//-------------------------------------------
|
|
// Update the lamp display
|
|
//-------------------------------------------
|
|
ChannelStatusUpdate();
|
|
}
|
|
//-------------------------------------------
|
|
// Try next channel
|
|
//-------------------------------------------
|
|
else
|
|
{
|
|
DecrementChannel();
|
|
}
|
|
}
|
|
break;
|
|
|
|
//---------------------------------------------------
|
|
case offChannel:
|
|
if (WaitedLongEnough(NORMAL_STEP_TIME))
|
|
{
|
|
int
|
|
delta = channel - hardwareChannel;
|
|
if (delta == 0)
|
|
{
|
|
state = reachedChannel;
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------------
|
|
// Choose direction, modulo 40
|
|
//-------------------------------------------
|
|
// channel = desired channel
|
|
// hardwareChannel = current channel
|
|
//-------------------------------------------
|
|
if (delta > 20)
|
|
{
|
|
delta -= 40;
|
|
}
|
|
else if (delta < -20)
|
|
{
|
|
delta += 40;
|
|
}
|
|
|
|
if (delta < 0)
|
|
{
|
|
DecrementChannel();
|
|
}
|
|
else
|
|
{
|
|
IncrementChannel();
|
|
}
|
|
//-------------------------------------------
|
|
// Update the lamp display
|
|
//-------------------------------------------
|
|
ChannelStatusUpdate();
|
|
}
|
|
}
|
|
break;
|
|
|
|
//---------------------------------------------------
|
|
// reachedChannel: this is a delay to allow to CB
|
|
// to finish "beeping" before the audio is turned on.
|
|
//---------------------------------------------------
|
|
case reachedChannel:
|
|
if (WaitedLongEnough(BEEP_TIME))
|
|
{
|
|
Test_Tell("L4Icom::Update, reachedChannel --> onChannel\n");
|
|
amp_enable(controlsManager, True);
|
|
state = onChannel;
|
|
}
|
|
break;
|
|
//---------------------------------------------------
|
|
case onChannel:
|
|
Test_Tell("L4Icom::Update, onChannel\n");
|
|
|
|
if (channel != hardwareChannel)
|
|
{
|
|
state = offChannel;
|
|
timeAccumulator = NORMAL_STEP_TIME; // bypass the delay
|
|
amp_enable(controlsManager, False); // mute the output
|
|
}
|
|
break;
|
|
//---------------------------------------------------
|
|
case disabled:
|
|
case failed:
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// LongEnough
|
|
//---------------------------------------------------------------------
|
|
Logical
|
|
L4Icom::WaitedLongEnough(Scalar delay_time)
|
|
{
|
|
Test_Tell("L4Icom::WaitedLongEnough(" << delay_time >> ") ");
|
|
Check(this);
|
|
|
|
//-------------------------------------------
|
|
// Check to see if delayed long enough
|
|
//-------------------------------------------
|
|
if (timeAccumulator >= delay_time)
|
|
{
|
|
Test_Tell("long enough!\n");
|
|
timeAccumulator = 0.0;
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
Test_Tell("\n");
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// IncrementChannel
|
|
//---------------------------------------------------------------------
|
|
void
|
|
L4Icom::IncrementChannel()
|
|
{
|
|
Test_Tell("L4Icom::IncrementChannel()\n");
|
|
Check(this);
|
|
Check(controlsManager);
|
|
|
|
//--------------------------------------
|
|
// Increment the channel number counter
|
|
//--------------------------------------
|
|
if (++hardwareChannel > (40-1))
|
|
{
|
|
hardwareChannel = 0;
|
|
}
|
|
//--------------------------------------
|
|
// Press the 'inc' button on the CB
|
|
//--------------------------------------
|
|
controlsManager->SetLamp(
|
|
IncrementRelayOutput,
|
|
LBE4ControlsManager::LampSolidBright
|
|
);
|
|
//--------------------------------------
|
|
// ...and again, for a fixed delay
|
|
//--------------------------------------
|
|
controlsManager->SetLamp(
|
|
IncrementRelayOutput,
|
|
LBE4ControlsManager::LampSolidBright
|
|
);
|
|
//--------------------------------------
|
|
// Release the 'inc' button on the CB
|
|
//--------------------------------------
|
|
controlsManager->SetLamp(
|
|
IncrementRelayOutput,
|
|
LBE4ControlsManager::LampSolidOff
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// DecrementChannel
|
|
//---------------------------------------------------------------------
|
|
void
|
|
L4Icom::DecrementChannel()
|
|
{
|
|
Test_Tell("L4Icom::DecrementChannel()\n");
|
|
Check(this);
|
|
Check(controlsManager);
|
|
|
|
//--------------------------------------
|
|
// Decrement the channel number counter
|
|
//--------------------------------------
|
|
if (--hardwareChannel < 0)
|
|
{
|
|
hardwareChannel = (40-1);
|
|
}
|
|
//--------------------------------------
|
|
// Press the 'dec' button on the CB
|
|
//--------------------------------------
|
|
controlsManager->SetLamp(
|
|
DecrementRelayOutput,
|
|
LBE4ControlsManager::LampSolidBright
|
|
);
|
|
//--------------------------------------
|
|
// ...and again, for a fixed delay
|
|
//--------------------------------------
|
|
controlsManager->SetLamp(
|
|
DecrementRelayOutput,
|
|
LBE4ControlsManager::LampSolidBright
|
|
);
|
|
//--------------------------------------
|
|
// Release the 'dec' button on the CB
|
|
//--------------------------------------
|
|
controlsManager->SetLamp(
|
|
DecrementRelayOutput,
|
|
LBE4ControlsManager::LampSolidOff
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// ChannelStatusUpdate
|
|
//---------------------------------------------------------------------
|
|
void
|
|
L4Icom::ChannelStatusUpdate()
|
|
{
|
|
Test_Tell("L4Icom::ChannelStatusUpdate()\n");
|
|
Check(this);
|
|
Check(controlsManager);
|
|
|
|
int
|
|
logical_channel_number;
|
|
|
|
if (channelSelectEnabled)
|
|
{
|
|
//--------------------------------------
|
|
// Has the channel changed?
|
|
//--------------------------------------
|
|
if (previousChannel != hardwareChannel)
|
|
{
|
|
//----------------------------------------
|
|
// Yes. Is the previous channel undefined?
|
|
//----------------------------------------
|
|
if (previousChannel != Icom::undefinedChannel)
|
|
{
|
|
//--------------------------------------
|
|
// No, set previous button to dim
|
|
//--------------------------------------
|
|
logical_channel_number = previousChannel - channelOffset;
|
|
if (logical_channel_number < L4Icom::numberOfChannels)
|
|
{
|
|
controlsManager->SetLamp(
|
|
channelButtonNumber[logical_channel_number],
|
|
LBE4ControlsManager::LampSolidDim
|
|
);
|
|
}
|
|
}
|
|
previousChannel = hardwareChannel;
|
|
//--------------------------------------
|
|
// Is the new channel undefined?
|
|
//--------------------------------------
|
|
if (previousChannel != Icom::undefinedChannel)
|
|
{
|
|
//--------------------------------------
|
|
// No, set current button to bright
|
|
//--------------------------------------
|
|
logical_channel_number = hardwareChannel - channelOffset;
|
|
if (logical_channel_number < L4Icom::numberOfChannels)
|
|
{
|
|
controlsManager->SetLamp(
|
|
channelButtonNumber[logical_channel_number],
|
|
LBE4ControlsManager::LampSolidBright
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// ChannelSelectState
|
|
//---------------------------------------------------------------------
|
|
void
|
|
L4Icom::ChannelSelectState(Logical state)
|
|
{
|
|
Test_Tell("L4Icom::ChannelStatusUpdate(" << state << ")\n");
|
|
Check(this);
|
|
Check(controlsManager);
|
|
|
|
int
|
|
i,
|
|
logical_channel_number;
|
|
|
|
if ((state != disabled) && (state != failed))
|
|
{
|
|
channelSelectEnabled = True;
|
|
|
|
for(i=0; i<L4Icom::numberOfChannels; ++i)
|
|
{
|
|
logical_channel_number = hardwareChannel - channelOffset;
|
|
|
|
controlsManager->SetLamp(
|
|
channelButtonNumber[i],
|
|
(i==logical_channel_number ?
|
|
LBE4ControlsManager::LampSolidBright :
|
|
LBE4ControlsManager::LampSolidDim
|
|
)
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
channelSelectEnabled = False;
|
|
|
|
for(i=0; i<L4Icom::numberOfChannels; ++i)
|
|
{
|
|
controlsManager->SetLamp(
|
|
channelButtonNumber[i],
|
|
LBE4ControlsManager::LampSolidOff
|
|
);
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//##########################################################################
|
|
//######################## L4IcomManager #############################
|
|
//##########################################################################
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Virtual Data support
|
|
//
|
|
|
|
Derivation* L4IcomManager::GetClassDerivations()
|
|
{
|
|
static Derivation classDerivations(IcomManager::GetClassDerivations(), "L4IcomManager");
|
|
return &classDerivations;
|
|
}
|
|
|
|
L4IcomManager::SharedData
|
|
L4IcomManager::DefaultData(
|
|
L4IcomManager::GetClassDerivations(),
|
|
L4IcomManager::GetMessageHandlers()
|
|
);
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Creator
|
|
//
|
|
|
|
L4IcomManager::L4IcomManager(
|
|
SharedData &shared_data
|
|
):
|
|
IcomManager(shared_data),
|
|
localIcom(NULL)
|
|
{
|
|
Test_Tell("L4IcomManager::L4IcomManager()\n");
|
|
Check_Pointer(this);
|
|
|
|
previousUpdateTime = Now();
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Destructor
|
|
//
|
|
L4IcomManager::~L4IcomManager()
|
|
{
|
|
Test_Tell("L4IcomManager::~L4IcomManager()\n");
|
|
Check(this);
|
|
|
|
// We don't need to delete the local Icom object: it's a member
|
|
// of the instanceList in the IcomManager class, which is deleted
|
|
// by the IcomManager destructor.
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
Logical
|
|
L4IcomManager::TestInstance() const
|
|
{
|
|
return IsDerivedFrom(*GetClassDerivations());
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
L4Icom *
|
|
L4IcomManager::MakeIcom(HostID host_id, int /*unit_number*/)
|
|
{
|
|
Test_Tell("L4IcomManager::MakeIcom(" << host_id << ")\n");
|
|
Check(this);
|
|
|
|
//------------------------------------------
|
|
// Create, register icom object
|
|
//------------------------------------------
|
|
L4Icom
|
|
*icom = new L4Icom(host_id, 0); // HACK - eventually set channel offset based on cockpit group!
|
|
Check(icom);
|
|
Register_Object(icom);
|
|
//------------------------------------------
|
|
// Add to global list
|
|
//------------------------------------------
|
|
instanceList.Add(icom);
|
|
//------------------------------------------
|
|
// Get local host ID
|
|
// (we need to do because the local host is
|
|
// created quite late in the whole process)
|
|
//------------------------------------------
|
|
Check(application);
|
|
HostManager
|
|
*host_manager = application->GetHostManager();
|
|
Check(host_manager);
|
|
Host
|
|
*local_host = host_manager->GetLocalHost();
|
|
Check(local_host);
|
|
HostID
|
|
local_host_id = local_host->GetHostID();
|
|
//------------------------------------------
|
|
// If assigned to a local host, make
|
|
// this intercom object local as well
|
|
//------------------------------------------
|
|
Test_Tell(
|
|
"L4IcomManager::MakeIcom local_host_id = " << local_host_id << "\n"
|
|
);
|
|
Test_Tell(
|
|
"L4IcomManager::MakeIcom host_id = " << host_id << "\n"
|
|
);
|
|
if (host_id == local_host_id)
|
|
{
|
|
Test_Tell("L4IcomManager::MakeIcom, set local icom\n");
|
|
//-----------------------------------------------------------------
|
|
// Set localIcom socket
|
|
//-----------------------------------------------------------------
|
|
Verify(localIcom.GetCurrent() == NULL);
|
|
localIcom.AddPlug(icom);
|
|
//-----------------------------------------------------------------
|
|
// Add connections
|
|
//-----------------------------------------------------------------
|
|
#if 0
|
|
Check(icom->controlsManager);
|
|
ControlsUpdateManager<ControlsButton>
|
|
*button_pointer;
|
|
//------------------------------------------
|
|
// Add connection to home sensor
|
|
//------------------------------------------
|
|
button_pointer = &icom->controlsManager->buttonGroup[homeSensorInput];
|
|
Check(button_pointer);
|
|
button_pointer->Add(
|
|
ModeManager::ModeAlwaysActive, &icom->homeSensor, icom
|
|
);
|
|
//------------------------------------------
|
|
// Add connections to channel buttons
|
|
//------------------------------------------
|
|
for(int i=0; i<L4Icom::numberOfChannels; ++i)
|
|
{
|
|
button_pointer =
|
|
&icom->controlsManager->buttonGroup[channelButtonNumber[i]];
|
|
Check(button_pointer);
|
|
button_pointer->Add(
|
|
L4ModeManager::ModeIntercom, &icom->channelButton, icom
|
|
);
|
|
icom->controlsManager->MakeLinkedLamp(channelButtonNumber[i]);
|
|
}
|
|
# if defined(HOMETEST)
|
|
//------------------------------------------
|
|
// Add connection to reset button
|
|
//------------------------------------------
|
|
button_pointer =
|
|
&icom->controlsManager->buttonGroup[resetButtonNumber];
|
|
Check(button_pointer);
|
|
button_pointer->Add(
|
|
ModeManager::ModeAlwaysActive, &resetButton, icom
|
|
);
|
|
|
|
resetButton = 0;
|
|
# endif
|
|
//------------------------------------------
|
|
// Add connection to PTT button
|
|
//------------------------------------------
|
|
button_pointer = &icom->controlsManager->buttonGroup[pttButtonNumber];
|
|
Check(button_pointer);
|
|
button_pointer->Add(
|
|
ModeManager::ModeAlwaysActive, &icom->pttButton, icom
|
|
);
|
|
icom->controlsManager->MakeLinkedLamp(pttButtonNumber);
|
|
#endif
|
|
}
|
|
|
|
Check_Fpu();
|
|
return icom;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
void
|
|
L4IcomManager::LoadMission(Mission *mission)
|
|
{
|
|
Check(this);
|
|
IcomManager::LoadMission(mission);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
void
|
|
L4IcomManager::Shutdown()
|
|
{
|
|
Check(this);
|
|
IcomManager::Shutdown();
|
|
Check_Fpu();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
void
|
|
L4IcomManager::Execute()
|
|
{
|
|
// Test_Tell("L4IcomManager::Execute()\n");
|
|
Check(this);
|
|
|
|
Scalar
|
|
delta_t;
|
|
Time
|
|
right_now;
|
|
|
|
# if defined(HOMETEST)
|
|
//------------------------------------------
|
|
// If reset button pressed, recalibrate
|
|
//------------------------------------------
|
|
if (resetButton > 0)
|
|
{
|
|
resetButton = 0;
|
|
|
|
L4Icom
|
|
*local_icom = localIcom.GetCurrent();
|
|
|
|
if (local_icom != NULL)
|
|
{
|
|
std::cout << "L4IcomManager::Execute, Reset!!!!!\n";
|
|
local_icom->Recalibrate();
|
|
}
|
|
}
|
|
# endif
|
|
//------------------------------------------
|
|
// Get time, generate delta_t
|
|
//------------------------------------------
|
|
right_now = Now();
|
|
delta_t = (Scalar) (right_now - previousUpdateTime);
|
|
|
|
if (delta_t > 0.0)
|
|
{
|
|
previousUpdateTime = right_now;
|
|
//------------------------------------------
|
|
// Process local icom object
|
|
//------------------------------------------
|
|
L4Icom
|
|
*local_icom = localIcom.GetCurrent();
|
|
|
|
if (local_icom != NULL)
|
|
{
|
|
local_icom->Update(delta_t);
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|