Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
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>
This commit is contained in:
@@ -0,0 +1,715 @@
|
||||
#include "munga.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "simulate.h"
|
||||
#include "update.h"
|
||||
#include "app.h"
|
||||
|
||||
#if defined(TRACE_EXECUTE_WATCHERS)
|
||||
static BitTrace Execute_Watchers("Execute Watchers");
|
||||
#define SET_EXECUTE_WATCHERS() Execute_Watchers.Set()
|
||||
#define CLEAR_EXECUTE_WATCHERS() Execute_Watchers.Clear()
|
||||
#else
|
||||
#define SET_EXECUTE_WATCHERS()
|
||||
#define CLEAR_EXECUTE_WATCHERS()
|
||||
#endif
|
||||
|
||||
//#############################################################################
|
||||
//######################## StateIndicator ###############################
|
||||
//#############################################################################
|
||||
|
||||
//#############################################################################
|
||||
// Construction and Destruction
|
||||
//
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
StateIndicator::StateIndicator():
|
||||
audioWatcherSocket(NULL),
|
||||
videoWatcherSocket(NULL),
|
||||
gaugeWatcherSocket(NULL)
|
||||
{
|
||||
Check_Pointer(this);
|
||||
stateCount = 0;
|
||||
oldState = 0;
|
||||
currentState = 0;
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
StateIndicator::StateIndicator(unsigned max_states):
|
||||
audioWatcherSocket(NULL),
|
||||
videoWatcherSocket(NULL),
|
||||
gaugeWatcherSocket(NULL)
|
||||
{
|
||||
Check_Pointer(this);
|
||||
stateCount = max_states;
|
||||
oldState = max_states;
|
||||
currentState = max_states;
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
StateIndicator::StateIndicator(const StateIndicator &state_indicator):
|
||||
audioWatcherSocket(NULL),
|
||||
videoWatcherSocket(NULL),
|
||||
gaugeWatcherSocket(NULL)
|
||||
{
|
||||
Check_Pointer(this);
|
||||
|
||||
// Do not perform deep copy of watchers
|
||||
stateCount = state_indicator.stateCount;
|
||||
oldState = state_indicator.oldState;
|
||||
currentState = state_indicator.currentState;
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
StateIndicator::~StateIndicator()
|
||||
{
|
||||
Check(this);
|
||||
|
||||
//
|
||||
// Manual deletion of existing watchers
|
||||
//
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(&audioWatcherSocket);
|
||||
#if DEBUG_LEVEL>2
|
||||
Component *component;
|
||||
while ((component = iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
Check(component);
|
||||
Dump(component->GetClassID());
|
||||
}
|
||||
Warn(iterator.GetSize() != 0);
|
||||
#endif
|
||||
iterator.DeletePlugs();
|
||||
}
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(&videoWatcherSocket);
|
||||
#if DEBUG_LEVEL>2
|
||||
Component *component;
|
||||
while ((component = iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
Check(component);
|
||||
Dump(component->GetClassID());
|
||||
}
|
||||
Warn(iterator.GetSize() != 0);
|
||||
#endif
|
||||
iterator.DeletePlugs();
|
||||
}
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(&gaugeWatcherSocket);
|
||||
#if DEBUG_LEVEL>2
|
||||
Component *component;
|
||||
while ((component = iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
Check(component);
|
||||
Dump(component->GetClassID());
|
||||
}
|
||||
Warn(iterator.GetSize() != 0);
|
||||
#endif
|
||||
iterator.DeletePlugs();
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// State stuff
|
||||
//
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
StateIndicator&
|
||||
StateIndicator::operator=(const StateIndicator &state_indicator)
|
||||
{
|
||||
// Do not perform assignment of watchers
|
||||
stateCount = state_indicator.stateCount;
|
||||
oldState = state_indicator.oldState;
|
||||
currentState = state_indicator.currentState;
|
||||
|
||||
Check_Fpu();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Logical
|
||||
StateIndicator::operator==(const StateIndicator &state_indicator) const
|
||||
{
|
||||
Check_Fpu();
|
||||
return
|
||||
(
|
||||
stateCount == state_indicator.stateCount &&
|
||||
oldState == state_indicator.oldState &&
|
||||
currentState == state_indicator.currentState
|
||||
);
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
StateIndicator::SetState(unsigned new_state)
|
||||
{
|
||||
Check(this);
|
||||
Verify(new_state < stateCount);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// See if the state really changes
|
||||
//
|
||||
// NOTE - the old state does change to the current state, simulating a loop
|
||||
// in the state engine. If it turns out that someone is watching the
|
||||
// level of the state indicator and doing their own edge detection,
|
||||
// this might possibly maybe screw something up
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
oldState = currentState;
|
||||
if (new_state == currentState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
// If the state has changed, update the state values and then run any
|
||||
// watchers
|
||||
//-------------------------------------------------------------------
|
||||
//
|
||||
currentState = new_state;
|
||||
Component *watcher;
|
||||
|
||||
SET_EXECUTE_WATCHERS();
|
||||
|
||||
// Audio
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(audioWatcherSocket);
|
||||
Check(&iterator);
|
||||
while ((watcher = iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
watcher->Execute();
|
||||
}
|
||||
}
|
||||
|
||||
// Video
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(videoWatcherSocket);
|
||||
Check(&iterator);
|
||||
while ((watcher = iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
watcher->Execute();
|
||||
}
|
||||
}
|
||||
|
||||
// Gauge
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(gaugeWatcherSocket);
|
||||
Check(&iterator);
|
||||
while ((watcher = iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
watcher->Execute();
|
||||
}
|
||||
}
|
||||
|
||||
CLEAR_EXECUTE_WATCHERS();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
std::ostream& operator << (std::ostream &strm, const StateIndicator &state_indicator)
|
||||
{
|
||||
Check(&state_indicator);
|
||||
|
||||
strm << "[" << state_indicator.stateCount << ",";
|
||||
strm << state_indicator.oldState << ",";
|
||||
strm << state_indicator.currentState << "]";
|
||||
|
||||
return strm;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Test Support
|
||||
//
|
||||
Logical
|
||||
StateIndicator::TestInstance() const
|
||||
{
|
||||
return True;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
//########################## Simulation #################################
|
||||
//#############################################################################
|
||||
|
||||
//#############################################################################
|
||||
// Virtual Data support
|
||||
//
|
||||
Derivation* Simulation::GetClassDerivations()
|
||||
{
|
||||
static Derivation classDerivations(Receiver::GetClassDerivations(), "Simulation");
|
||||
return &classDerivations;
|
||||
}
|
||||
|
||||
Simulation::SharedData
|
||||
Simulation::DefaultData(
|
||||
Simulation::GetClassDerivations(),
|
||||
Simulation::GetMessageHandlers(),
|
||||
Simulation::GetAttributeIndex(),
|
||||
Simulation::StateCount
|
||||
);
|
||||
|
||||
//#############################################################################
|
||||
// Model support
|
||||
//
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Simulation::ReadUpdateRecord(UpdateRecord *message)
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(message);
|
||||
|
||||
lastUpdate = Now(); // HACK - should be based upon message->timeStamp
|
||||
SetSimulationState(message->simulationState);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Simulation::WriteUpdateRecord(
|
||||
UpdateRecord *message,
|
||||
int update_model
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(message);
|
||||
|
||||
message->timeStamp = lastPerformance;
|
||||
message->simulationState = GetSimulationState();
|
||||
message->recordLength = sizeof(*message);
|
||||
message->recordID = (Word)update_model;
|
||||
lastUpdate = lastPerformance;
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Simulation::WriteSimulationUpdate(MemoryStream *update_stream)
|
||||
{
|
||||
Check(this);
|
||||
Check(update_stream);
|
||||
|
||||
//
|
||||
//-----------------
|
||||
// Write the update
|
||||
//-----------------
|
||||
//
|
||||
int bit=0;
|
||||
int update_model = updateModel;
|
||||
updateModel = 0;
|
||||
while (update_model)
|
||||
{
|
||||
|
||||
if (update_model & 1)
|
||||
{
|
||||
UpdateRecord* update = (UpdateRecord*)update_stream->GetPointer();
|
||||
WriteUpdateRecord(update, bit);
|
||||
update_stream->AdvancePointer(update->recordLength);
|
||||
}
|
||||
update_model >>= 1;
|
||||
++bit;
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Construction and Destruction
|
||||
//
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Simulation::Simulation(
|
||||
Simulation::ClassID class_ID,
|
||||
Simulation::SharedData &virtual_data
|
||||
):
|
||||
Receiver(class_ID, virtual_data),
|
||||
simulationState(GetSharedData()->stateCount),
|
||||
audioWatcherSocket(NULL),
|
||||
videoWatcherSocket(NULL),
|
||||
gaugeWatcherSocket(NULL),
|
||||
effectWatcherSocket(NULL)
|
||||
{
|
||||
Check_Pointer(this);
|
||||
|
||||
SetSimulationState(DefaultState);
|
||||
lastPerformance = Now();
|
||||
lastUpdate = lastPerformance;
|
||||
activePerformance = &Simulation::DoNothingOnce;
|
||||
updateModel = 0;
|
||||
simulationFlags = 0;
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Simulation::~Simulation()
|
||||
{
|
||||
Check(this);
|
||||
|
||||
//
|
||||
// Watchers should be deleted by renderers by now
|
||||
//
|
||||
#if DEBUG_LEVEL>0
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(&audioWatcherSocket);
|
||||
Verify(iterator.GetSize() == 0);
|
||||
}
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(&videoWatcherSocket);
|
||||
Verify(iterator.GetSize() == 0);
|
||||
}
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(&gaugeWatcherSocket);
|
||||
Verify(iterator.GetSize() == 0);
|
||||
}
|
||||
#endif
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Attribute Support
|
||||
//
|
||||
const Simulation::AttributePointer
|
||||
Simulation::NullAttribute = NULL;
|
||||
|
||||
const Simulation::IndexEntry
|
||||
Simulation::AttributePointers[]=
|
||||
{
|
||||
{
|
||||
Simulation::SimulationStateAttributeID,
|
||||
"SimulationState",
|
||||
(Simulation::AttributePointer)&Simulation::simulationState
|
||||
}
|
||||
};
|
||||
|
||||
Simulation::AttributeIndexSet& Simulation::GetAttributeIndex()
|
||||
{
|
||||
static Simulation::AttributeIndexSet attributeIndex(ELEMENTS(Simulation::AttributePointers),
|
||||
Simulation::AttributePointers
|
||||
);
|
||||
return attributeIndex;
|
||||
}
|
||||
|
||||
void*
|
||||
Simulation::GetAttributePointer(Simulation::AttributeID attribute)
|
||||
{
|
||||
Check(this);
|
||||
|
||||
AttributePointer attr =
|
||||
GetSharedData()->activeAttributeIndex->Find(attribute);
|
||||
Check_Fpu();
|
||||
if (attr == NullAttribute)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &(this->*attr);
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
Simulation::GetAttributePointer(const char* attribute_name)
|
||||
{
|
||||
Check(this);
|
||||
|
||||
AttributePointer attr =
|
||||
GetSharedData()->activeAttributeIndex->Find(attribute_name);
|
||||
Check_Fpu();
|
||||
if (attr == NullAttribute)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &(this->*attr);
|
||||
}
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Simulation Support
|
||||
//
|
||||
void
|
||||
Simulation::PerformAndWatch(
|
||||
const Time& till,
|
||||
MemoryStream *update_stream
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(&till);
|
||||
|
||||
Scalar slice = till - lastPerformance;
|
||||
lastPerformance = till;
|
||||
|
||||
Perform(slice);
|
||||
if (!AreWatchersDelayed())
|
||||
{
|
||||
ExecuteWatchers();
|
||||
}
|
||||
WriteSimulationUpdate(update_stream);
|
||||
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Simulation::DoNothingOnce(Scalar)
|
||||
{
|
||||
NeverExecute();
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Simulation::DoNothing(Scalar)
|
||||
{
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Watcher Support
|
||||
//
|
||||
void
|
||||
Simulation::ExecuteWatchers()
|
||||
{
|
||||
SET_EXECUTE_WATCHERS();
|
||||
|
||||
Component *watcher;
|
||||
|
||||
// Audio
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(audioWatcherSocket);
|
||||
while ((watcher = iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
watcher->Execute();
|
||||
}
|
||||
}
|
||||
|
||||
// Video
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(videoWatcherSocket);
|
||||
while ((watcher = iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
watcher->Execute();
|
||||
}
|
||||
}
|
||||
|
||||
// Gauge
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(gaugeWatcherSocket);
|
||||
while ((watcher = iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
watcher->Execute();
|
||||
}
|
||||
}
|
||||
|
||||
// Effect
|
||||
{
|
||||
SChainIteratorOf<Component*> iterator(effectWatcherSocket);
|
||||
while ((watcher = iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
watcher->Execute();
|
||||
}
|
||||
}
|
||||
CLEAR_EXECUTE_WATCHERS();
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Test Support
|
||||
//
|
||||
|
||||
Logical
|
||||
Simulation::TestInstance() const
|
||||
{
|
||||
return IsDerivedFrom(*GetClassDerivations());
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
//################### Simulation::AttributeIndexSet #####################
|
||||
//#############################################################################
|
||||
|
||||
const Simulation::AttributeIndexSet
|
||||
Simulation::AttributeIndexSet::NullSet;
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Simulation__AttributeIndexSet::~Simulation__AttributeIndexSet()
|
||||
{
|
||||
if (attributeIndex)
|
||||
{
|
||||
Unregister_Pointer(attributeIndex);
|
||||
delete[] attributeIndex;
|
||||
}
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Simulation::AttributeIndexSet::Build(
|
||||
Simulation::AttributeID count,
|
||||
const Simulation::IndexEntry index_table[],
|
||||
const Simulation::AttributeIndexSet *inheritance
|
||||
)
|
||||
{
|
||||
//
|
||||
//-------------------------------------------------------
|
||||
// Find out the highest message type we have to deal with
|
||||
//-------------------------------------------------------
|
||||
//
|
||||
Check(this);
|
||||
Check_Pointer(index_table);
|
||||
entryCount = 0;
|
||||
Simulation::AttributeID i;
|
||||
for (i=0; i<count; ++i)
|
||||
{
|
||||
if (index_table[i].entryID > entryCount)
|
||||
{
|
||||
entryCount = index_table[i].entryID;
|
||||
}
|
||||
}
|
||||
if (inheritance)
|
||||
{
|
||||
Check(inheritance);
|
||||
if (entryCount<inheritance->entryCount)
|
||||
{
|
||||
entryCount = inheritance->entryCount;
|
||||
}
|
||||
#if DEBUG_LEVEL>0
|
||||
else if (entryCount > inheritance->entryCount)
|
||||
{
|
||||
i = inheritance->entryCount+1;
|
||||
goto Check_Table;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Verify(entryCount == count);
|
||||
#if DEBUG_LEVEL>0
|
||||
i = 1;
|
||||
Check_Table:
|
||||
while (i <= entryCount)
|
||||
{
|
||||
int j;
|
||||
for (j=0; j<count; ++j)
|
||||
{
|
||||
if (index_table[j].entryID == i)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
Verify(i > count);
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
// Allocate the memory for the new handler set, and copy the inherited
|
||||
// handlers to the new table. We are guaranteed to have enough space for
|
||||
// the inherited table
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
attributeIndex = new Simulation::IndexEntry[entryCount];
|
||||
Check_Pointer(attributeIndex);
|
||||
Register_Pointer(attributeIndex);
|
||||
i = 0;
|
||||
if (inheritance)
|
||||
{
|
||||
for (; i<inheritance->entryCount; ++i)
|
||||
{
|
||||
attributeIndex[i] = inheritance->attributeIndex[i];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
// Step through the new table supplied, placing each handler in the slot
|
||||
// determined by the message type
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
for (i=0; i<count; ++i)
|
||||
{
|
||||
Verify(!inheritance || index_table[i].entryID > inheritance->entryCount);
|
||||
attributeIndex[index_table[i].entryID-1] = index_table[i];
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Simulation::AttributePointer
|
||||
Simulation::AttributeIndexSet::Find(const char* attribute_name) const
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(attribute_name);
|
||||
|
||||
for (int attribute=0; attribute<entryCount; ++attribute)
|
||||
{
|
||||
if (!strcmp(attribute_name, attributeIndex[attribute].entryName))
|
||||
{
|
||||
Check_Fpu();
|
||||
return attributeIndex[attribute].entryAddress;
|
||||
}
|
||||
}
|
||||
Check_Fpu();
|
||||
return Simulation::NullAttribute;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
const Simulation::IndexEntry*
|
||||
Simulation::AttributeIndexSet::FindEntry(const char* attribute_name) const
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(attribute_name);
|
||||
|
||||
for (int attribute=0; attribute<entryCount; ++attribute)
|
||||
{
|
||||
if (!strcmp(attribute_name, attributeIndex[attribute].entryName))
|
||||
{
|
||||
Check_Fpu();
|
||||
return &attributeIndex[attribute];
|
||||
}
|
||||
}
|
||||
Check_Fpu();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
Simulation::RequestEncore(Encore encore)
|
||||
{
|
||||
Check(this);
|
||||
SetWatcherDelay();
|
||||
|
||||
Check(application);
|
||||
UpdateManager *updater = application->GetUpdateManager();
|
||||
Check(updater);
|
||||
updater->RequestEncore(this, encore);
|
||||
}
|
||||
|
||||
#if defined(TEST_CLASS) && 0
|
||||
#include "model.tcp"
|
||||
#endif
|
||||
Reference in New Issue
Block a user