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>
446 lines
20 KiB
C++
446 lines
20 KiB
C++
//===========================================================================//
|
|
// File: btstubs.cpp //
|
|
// Project: BattleTech port (WinTesla / btl4) //
|
|
//---------------------------------------------------------------------------//
|
|
// BRING-UP STUBS + engine data-global definitions needed to LINK btl4.exe. //
|
|
// //
|
|
// Every definition in this file is a flagged first-link placeholder. None //
|
|
// of these carry the real shipped behaviour yet -- they exist only so the //
|
|
// executable links and can be booted. Each must be replaced with the real //
|
|
// body recovered from BTL4OPT.EXE (the binary oracle) / the RP analogue. //
|
|
// //
|
|
// == RUNTIME BRING-UP WORKLIST (replace these) == //
|
|
// Mech::GetMissionReviewMode / IsAirborne / SetTargetRange / //
|
|
// SetMappingSubsystem / RaiseStatusAlarm //
|
|
// Mech__DamageZone::LoadCriticalSubsystems //
|
|
// MechSubsystem::TakeDamage / OnAlarmChanged //
|
|
// Generator::ForceShortRecovery //
|
|
// Is_Destroyed / ToggleVoiceAssist / Set_Alarm_Level / //
|
|
// Notify_Objective_Reached //
|
|
// data: FrameTimeScale, StatusMessagePool, BTPlayerVTable, //
|
|
// BTStatusMessageVTable, allPresets //
|
|
//===========================================================================//
|
|
|
|
#include <bt.hpp> // Mech, MechSubsystem, BTPlayer, Damage, Scalar, ...
|
|
#pragma hdrstop
|
|
|
|
#if !defined(POWERSUB_HPP)
|
|
# include <powersub.hpp> // Generator
|
|
#endif
|
|
|
|
#if !defined(MECHDMG_HPP)
|
|
# include <mechdmg.hpp> // Mech__DamageZone (full definition)
|
|
#endif
|
|
|
|
#include <L4AUDLVL.hpp> // PRESETINFO + extern allPresets[2][100]
|
|
#include <MEMBLOCK.hpp> // MemoryBlock
|
|
|
|
#if !defined(BTL4VID_HPP)
|
|
# include <btl4vid.hpp> // BT*Renderable hierarchy + dpl2d_* prototypes
|
|
#endif
|
|
|
|
//===========================================================================//
|
|
// Engine data globals (declared extern by the engine/game but defined in a
|
|
// .cpp that is not part of munga_engine.lib).
|
|
//===========================================================================//
|
|
|
|
// TODO(bring-up): per-frame time scale; real value is set by the sim clock.
|
|
// Default 1.0 so the mech-age divide in mech.cpp does not divide by zero.
|
|
Scalar FrameTimeScale = 1.0f;
|
|
|
|
// TODO(bring-up): audio preset bank table (real data lives in WTPresets/L4AUDLVL).
|
|
// Zero-initialised -> PRESET_isImplemented() returns false (no presets) at boot.
|
|
PRESETINFO allPresets[2][100] = {};
|
|
|
|
//===========================================================================//
|
|
// BattleTech globals (status-message pool + hand-rolled vtable pointers the
|
|
// recovered ctors splice in). Real homes were btplayer.cpp .data.
|
|
//===========================================================================//
|
|
|
|
// TODO(bring-up): BT StatusMessage MemoryBlock pool (@00512f6c). Must be a real
|
|
// MemoryBlock sized for StatusMessage before status messages are allocated.
|
|
MemoryBlock *StatusMessagePool = 0;
|
|
|
|
// TODO(bring-up): hand-built vtables the recovered BTPlayer/StatusMessage ctors
|
|
// patch into the object's first word (PTR_FUN_00513300 / PTR_LAB_00513344).
|
|
// Null for now -- any virtual call through these will fault until reconstructed.
|
|
void *BTPlayerVTable = 0;
|
|
void *BTStatusMessageVTable = 0;
|
|
|
|
//===========================================================================//
|
|
// Free-function stubs (declared extern at the call sites).
|
|
//===========================================================================//
|
|
|
|
// TODO(bring-up): true when the entity handle refers to a destroyed entity.
|
|
Logical Is_Destroyed(int /*entity_handle*/)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
// TODO(bring-up): toggle the pilot voice-assist subsystem.
|
|
void ToggleVoiceAssist(int /*voice_assist_subsystem*/)
|
|
{
|
|
}
|
|
|
|
// TODO(bring-up): raise/clear a cockpit alarm indicator to the given level.
|
|
void Set_Alarm_Level(void * /*alarm_indicator*/, int /*level*/)
|
|
{
|
|
}
|
|
|
|
// TODO(bring-up): notify mission scoring that an objective subsystem was reached.
|
|
void Notify_Objective_Reached(int * /*objective_subsystem*/, Mech * /*mech*/)
|
|
{
|
|
}
|
|
|
|
//===========================================================================//
|
|
// Mech method stubs.
|
|
//===========================================================================//
|
|
|
|
// TODO(bring-up): reads mech+0x414 (mission-review playback flag).
|
|
int Mech::GetMissionReviewMode()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// TODO(bring-up): true while the mech is off the ground (jump-jet / fall state).
|
|
int Mech::IsAirborne()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// FUN_0049fb54 -- true when the mech is destroyed/shut down (masks control input
|
|
// and freezes gait). For the drivable bring-up the mech is always live.
|
|
// TODO(bring-up): derive from the status/master alarm once damage is wired.
|
|
// Mech::IsDisabled -- @0049fb54. Reconstructed: the mech is "disabled" (its action
|
|
// requests are masked, gait frozen) when its movementMode (mech+0x40, the gait/death
|
|
// selector) is in a death state -- 2 or 9. movementMode is driven to those values by
|
|
// the gait/death-transition code (mech2 SetLegAnimation/SetBodyAnimation family) when a
|
|
// vital zone is destroyed; that transition path is part of the locomotion/Simulate
|
|
// reconstruction (bypassed in the bring-up drive override), so this reads false until
|
|
// that lands. Faithful to the binary regardless.
|
|
Logical Mech::IsDisabled()
|
|
{
|
|
return (movementMode == 2 || movementMode == 9) ? True : False;
|
|
}
|
|
|
|
// TODO(bring-up): writes mech+0x404 (HUD/weapon target range).
|
|
void Mech::SetTargetRange(Scalar /*range*/)
|
|
{
|
|
}
|
|
|
|
// Install the cockpit-mapping subsystem into the Mech's reserved ControlsMapper
|
|
// roster slot (index 0), mirroring VTV::SetMappingSubsystem (RP/VTV.cpp:394) and
|
|
// VTV::ControlsMapperSubsystem==0. The streamed control-mapping resource binds
|
|
// its DirectMappings to subsystemID 0, so the mapper MUST live there for
|
|
// Entity::GetSimulation(0) to resolve it. (Previously a no-op -> slot 0 stayed
|
|
// NULL -> LBE4ControlsManager::CreateStreamedMappings dereferenced a NULL
|
|
// subsystem.) controlsMapper mirrors the same pointer for the gameplay path.
|
|
void Mech::SetMappingSubsystem(Subsystem *subsystem)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(subsystemArray);
|
|
|
|
if (subsystemArray[0] != 0)
|
|
{
|
|
// re-spawn: drop the previous mapper (NULL on first spawn).
|
|
Unregister_Object(subsystemArray[0]);
|
|
delete subsystemArray[0];
|
|
}
|
|
subsystemArray[0] = subsystem;
|
|
controlsMapper = (MechControlsMapper *)subsystem;
|
|
}
|
|
|
|
// TODO(bring-up): raise a mech-level status alarm of the given id.
|
|
void Mech::RaiseStatusAlarm(int /*alarm_id*/)
|
|
{
|
|
}
|
|
|
|
// Mech::Reset (@0049fb74) -- place the mech at a (re)spawn origin.
|
|
// The shipped Reset additionally zeroes ~50 heat/damage/motion state fields and
|
|
// resets every subsystem in the roster (slot vtable+0x28 with the reset mode);
|
|
// that full sweep is deferred (TODO(bring-up)). For first spawn a freshly
|
|
// constructed mech is already clean, so positioning it + refreshing the world
|
|
// transform + forcing an update is enough to get it placed and rendering.
|
|
void Mech::Reset(const Origin &origin, int /*mode*/)
|
|
{
|
|
Check(this);
|
|
localOrigin = origin; // this+0x100 (FUN_0040a938 copy)
|
|
localToWorld = localOrigin; // this+0xd0 (FUN_0040ab44 rebuild)
|
|
ForceUpdate(); // FUN_004a4c54 family -- push to renderer/replicants
|
|
|
|
// BRING-UP (Tier-2 locomotion): get the player mech onto the per-frame
|
|
// simulation path so it can walk. Two engine gates block a freshly spawned
|
|
// master entity from being executed:
|
|
// (1) Entity::Execute only calls PerformAndWatch when the app is in
|
|
// RunningMission/EndingMission OR the entity IsPreRunnable()
|
|
// (ENTITY.cpp:~549) -> set the pre-run flag.
|
|
// (2) UpdateManager::Execute skips a master unless IsInteresting()
|
|
// (interestCount!=0) && IsNonReplicantExecutable() (UPDATE.cpp:148)
|
|
// -> force it interesting so the update manager ticks it.
|
|
// Without these the mech renders but is never simulated (static
|
|
// localToWorld). See Mech::PerformAndWatch (mech4.cpp).
|
|
SetPreRunFlag();
|
|
if (interestCount == 0) interestCount = 1; // Entity::interestCount (public)
|
|
DEBUG_STREAM << "[drive] Mech::Reset spawn at ("
|
|
<< localOrigin.linearPosition.x << ", "
|
|
<< localOrigin.linearPosition.y << ", "
|
|
<< localOrigin.linearPosition.z << ") -- prerun+interest forced\n" << std::flush;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//===========================================================================//
|
|
// Mech__DamageZone method stub.
|
|
//===========================================================================//
|
|
|
|
// TODO(bring-up): stream in the per-zone critical-subsystem plug list.
|
|
void Mech__DamageZone::LoadCriticalSubsystems(MemoryStream * /*stream*/)
|
|
{
|
|
}
|
|
|
|
//===========================================================================//
|
|
// MechSubsystem method stubs.
|
|
//===========================================================================//
|
|
|
|
// TODO(bring-up): apply damage to a generic mech subsystem (virtual override).
|
|
void MechSubsystem::TakeDamage(Damage & /*damage*/)
|
|
{
|
|
}
|
|
|
|
// TODO(bring-up): react to a change in this subsystem's alarm level.
|
|
void MechSubsystem::OnAlarmChanged()
|
|
{
|
|
}
|
|
|
|
//===========================================================================//
|
|
// Generator method stub.
|
|
//===========================================================================//
|
|
|
|
// TODO(bring-up): force the generator into the short-event fast-recovery path.
|
|
void Generator::ForceShortRecovery()
|
|
{
|
|
}
|
|
|
|
//===========================================================================//
|
|
// BT subsystem<->Mech bridge accessors (declared extern in powersub.hpp).
|
|
//---------------------------------------------------------------------------//
|
|
// INTEGRATION NOTE (Task 2): the shipped binary reads these off fixed Mech byte
|
|
// offsets (msg-mgr @+0x190, bus-live @*(+0x190)+0x274, myomers @+0x374). The
|
|
// reconstructed Mech is NOT byte-exact (named members + a Wword scratch bank),
|
|
// so a raw `*(owner+0x190)` would read an unrelated member and, when chased one
|
|
// level further for the bus flag, dereference garbage. These are therefore
|
|
// implemented against intent rather than raw offsets, and kept deref-safe:
|
|
// * BT_IsBusLive -> True: the running player mech is a powered master; this
|
|
// un-gates the power-dependent subsystem paths (PoweredSubsystem/Generator)
|
|
// so they compute when those real classes are wired (today their consumers
|
|
// are RECON_SUBSYS stubs -- see RECONCILE.md -- so this is latent but safe).
|
|
// * BT_GetMessageManager -> 0: the SubsystemMessageManager IS in the roster
|
|
// (slot "MessageManager") but cannot be located here without the byte-exact
|
|
// layout; returning a bogus non-null would be WORSE (callers deref it). Left
|
|
// 0 (callers null-guard) until the roster lookup / real layout is restored.
|
|
// * BT_ClearMyomers -> no-op: no myomer back-pointer member exists at a known
|
|
// offset in the reconstructed Mech to clear.
|
|
//===========================================================================//
|
|
|
|
// Real impl reads *(owner+0x190). No byte-exact +0x190 in the reconstructed
|
|
// Mech; callers null-guard, so 0 is the safe value (see note above).
|
|
SubsystemMessageManager *BT_GetMessageManager(Mech * /*owner*/)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// The running player mech is a live, powered master -> its electrical bus is up.
|
|
// (Real impl read *(*(owner+0x190)+0x274); see layout note above.)
|
|
Logical BT_IsBusLive(Mech * /*owner*/)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
// No known-offset myomer back-pointer in the reconstructed Mech to clear.
|
|
void BT_ClearMyomers(Mech * /*owner*/)
|
|
{
|
|
}
|
|
|
|
// BT_GetSegmentFlags -- the per-subsystem segment-flag accessor the HUD (hud.cpp)
|
|
// and the segment-flag-gated subsystem ctors call. It was DECLARED extern but
|
|
// never DEFINED, so it only linked under /FORCE (an unresolved external whose
|
|
// return was undefined if ever called). The oracle-verified authoritative source
|
|
// for the master/copy + master-bit gate is the OWNER's simulationFlags
|
|
// (owner+0x28): (flags & 0xC)==0 (master, not a replicant copy) && (flags & 0x100)
|
|
// (master bit). Defining it here resolves the dangling symbol and feeds the gate
|
|
// the same authoritative value the reconciled subsystem gates now read directly.
|
|
LWord BT_GetSegmentFlags(Mech *owner)
|
|
{
|
|
return owner ? owner->simulationFlags : 0;
|
|
}
|
|
|
|
//===========================================================================//
|
|
// Legacy libDPL material-name callback.
|
|
//---------------------------------------------------------------------------//
|
|
// The dpl2d_ 2D display-list API (NewDisplayList/Begin/SetColor/Circle/
|
|
// PushMatrix/PopMatrix/MoveTo/End/Compile) was MOVED OUT of this file and
|
|
// reimplemented over Direct3D 9 in decomp/reconstructed/dpl2d.cpp (the HUD/
|
|
// reticle 2D layer). Only the 3D material-name-substitution hook -- which is
|
|
// part of the world renderer, not the 2D HUD -- remains stubbed here.
|
|
// TODO(bring-up): wire the material substitution table (FUN_00459eb8).
|
|
//===========================================================================//
|
|
void dpl_SetMaterialNameCallback(char *(*)(char *)) {}
|
|
|
|
//===========================================================================//
|
|
// BTL4VideoRenderer helper methods whose bodies were not reconstructed.
|
|
//---------------------------------------------------------------------------//
|
|
// TODO(bring-up): real bodies @FUN_0045a724 / 00498448 / 0045a994 / 00489cec
|
|
// and LoadMissionImplementation drive the D3D scene/object pipeline.
|
|
//===========================================================================//
|
|
Scene *BTL4VideoRenderer::GetScene() { return 0; }
|
|
d3d_OBJECT *BTL4VideoRenderer::LoadObject(const char * /*name*/) { return 0; }
|
|
void BTL4VideoRenderer::AttachToEyeDCS(dpl_DCS *, LinearMatrix &) {}
|
|
void BTL4VideoRenderer::AddDynamicRenderable(VideoComponent *, Entity *) {}
|
|
void BTL4VideoRenderer::LoadMissionImplementation(Mission *mission)
|
|
{
|
|
// Load the real BattleTech renderer environment for this mission: paths,
|
|
// clip range, projection, fog, ambient + directional lights, cached shapes,
|
|
// effects -- driven by BTDPL.INI (L4DPLCFG, set in btl4main.cpp). This is
|
|
// what RP does (RPL4VideoRenderer::LoadMissionImplementation -> base), and is
|
|
// what gives the cavern world its environment. DPLReadINIPage builds a valid
|
|
// RH projection from the INI viewangle/clip, so the mech view is preserved.
|
|
DPLRenderer::LoadMissionImplementation(mission);
|
|
|
|
// Safety net (mProjectionMatrix is private to DPLRenderer, so we cannot
|
|
// inspect it here): unconditionally re-assert a known-good RH projection and
|
|
// disable fog so the freshly loaded mech body + cavern geometry are not
|
|
// clipped or fogged to the background. DPLReadINIPage already set the
|
|
// background colour / paths / lights from BTDPL.INI; this only guarantees the
|
|
// view stays valid. TODO(bring-up): once the env-driven projection/fog are
|
|
// confirmed good, drop this and honour the INI fog/clip directly.
|
|
EnsureValidProjection();
|
|
}
|
|
|
|
//===========================================================================//
|
|
// BattleTech renderable hierarchy (the unreconstructed "BT renderables" module).
|
|
//---------------------------------------------------------------------------//
|
|
// TODO(bring-up): these ctors (FUN_0045xxxx) built the D3D DCS/instance graph
|
|
// for each mech part/effect. Stubbed to chain to BTRenderableBase so the object
|
|
// is a valid (empty) VideoComponent; nothing is drawn until reconstructed.
|
|
//===========================================================================//
|
|
|
|
BTWorldContainerRenderable::BTWorldContainerRenderable(
|
|
Entity *entity, int, int, Scene *)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTRootRenderable::BTRootRenderable(
|
|
Entity *entity, int, d3d_OBJECT *, Scene *, int, uint32)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTDCSObjectRenderable::BTDCSObjectRenderable(
|
|
Entity *entity, Scene *, d3d_OBJECT *, int, uint32, LinearMatrix *, dpl_DCS *)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTHingeRenderable::BTHingeRenderable(
|
|
Entity *entity, int, d3d_OBJECT *, Scene *, int, uint32, dpl_DCS *,
|
|
LinearMatrix *, const Hinge *)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTBallJointRenderable::BTBallJointRenderable(
|
|
Entity *entity, int, d3d_OBJECT *, Scene *, int, uint32, dpl_DCS *,
|
|
LinearMatrix *, const EulerAngles *)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTBallTranslateJointRenderable::BTBallTranslateJointRenderable(
|
|
Entity *entity, int, d3d_OBJECT *, Scene *, int, uint32, dpl_DCS *,
|
|
LinearMatrix *, const EulerAngles *, const Point3D *)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTEyeRenderable::BTEyeRenderable(
|
|
Entity *entity, Scene *, LinearMatrix *, dpl_DCS *, dpl_VIEW *, EulerAngles *)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTDeathEffectRenderable::BTDeathEffectRenderable(
|
|
Entity *entity, int, dpl_VIEW *, Scene *, dpl_DCS *, StateIndicator *, int)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTMarkerWatcherRenderable::BTMarkerWatcherRenderable(
|
|
Entity *entity, int, dpl_VIEW *, dpl_DCS *)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTTranslocationRenderable::BTTranslocationRenderable(
|
|
Entity *entity, int, dpl_VIEW *, StateIndicator *, Point3D *, int)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTPOVStartEndRenderable::BTPOVStartEndRenderable(
|
|
Entity *entity, int, dpl_VIEW *, dpl_ZONE *, dpl_ZONE *, StateIndicator *,
|
|
float, float, float, float, float, int, int)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTTracerEffectRenderable::BTTracerEffectRenderable(
|
|
Entity *entity, int, void *, int, dpl_ZONE *, dpl_DCS *, LinearMatrix *)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTEmitterBeamRenderable::BTEmitterBeamRenderable(
|
|
Entity *entity, int, d3d_OBJECT *, Scene *, int, uint32, dpl_DCS *,
|
|
LinearMatrix *, void *, int, void *, void *)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTPPCBeamRenderable::BTPPCBeamRenderable(
|
|
Entity *entity, int, d3d_OBJECT *, Scene *, int, uint32, dpl_DCS *,
|
|
LinearMatrix *, void *, int, void *, void *, float)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
BTLightConnection::BTLightConnection(
|
|
Entity *entity, int, dpl_INSTANCE *, int, int *)
|
|
: BTRenderableBase(entity) {}
|
|
|
|
//===========================================================================//
|
|
// BTReticleRenderable ctor/dtor/Execute (AddWeapon lives in btl4vid.cpp).
|
|
//---------------------------------------------------------------------------//
|
|
// TODO(bring-up): real ctor @004cc40c builds the reticle 2D display lists.
|
|
//===========================================================================//
|
|
BTReticleRenderable::BTReticleRenderable(
|
|
Entity *entity, int, Reticle **, dpl_VIEW *,
|
|
void *, void *, void *, void *, void *, Scalar, int,
|
|
void *, void *, void *)
|
|
: VideoRenderable(entity, VideoRenderable::Dynamic), weaponCount(0)
|
|
{
|
|
}
|
|
|
|
BTReticleRenderable::~BTReticleRenderable()
|
|
{
|
|
}
|
|
|
|
void BTReticleRenderable::Execute()
|
|
{
|
|
}
|
|
|
|
//===========================================================================//
|
|
// VideoComponent (legacy renderable base) -- declared in L4VIDRND.h but NOT
|
|
// implemented anywhere in the WinTesla engine (superseded by VideoRenderable).
|
|
// BTRenderableBase still derives from it, so provide first-link stub bodies.
|
|
//---------------------------------------------------------------------------//
|
|
// TODO(bring-up): either reimplement VideoComponent over the new D3D renderable
|
|
// hierarchy or reparent BTRenderableBase onto VideoRenderable.
|
|
//===========================================================================//
|
|
VideoComponent::VideoComponent(Entity * /*entity*/, VideoExecutionType /*type*/)
|
|
: HierarchicalDrawComponent((RegisteredClass::ClassID)0)
|
|
, videoComponentSocket((Node *)0) // TODO(bring-up): owner node when reimplemented
|
|
{
|
|
}
|
|
|
|
VideoComponent::~VideoComponent()
|
|
{
|
|
}
|
|
|
|
void VideoComponent::Add(VideoComponent * /*component_to_add*/)
|
|
{
|
|
}
|
|
|
|
void VideoComponent::Connect(VideoComponent * /*component_to_connect*/)
|
|
{
|
|
}
|
|
|
|
void VideoComponent::ReceiveControl(VideoControlID /*control_ID*/, Scalar /*control_value*/)
|
|
{
|
|
}
|
|
|
|
void VideoComponent::Execute()
|
|
{
|
|
}
|