Files
CydandClaude Fable 5 fdd9ac9d97 Initial import: Tesla Release 4.10 (Tesla:BattleTech & Tesla:Red Planet)
Archival snapshot of the Virtual World Entertainment Tesla cockpit
software, 1994-1996: MUNGA engine and L4 pod layer source (Borland
C++ 5.0), BT/RP game code, and game content (models, audio, maps,
gauges, Division renderer data). Includes third-party libraries:
Division dVS/DPL graphics, HMI SOS audio, WATTCP networking.

Files are preserved byte-for-byte (.gitattributes disables all
line-ending conversion). README.md documents the layout, target
hardware, and toolchain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 13:21:58 -05:00

485 lines
16 KiB
C++

//===========================================================================//
// File: l4vidper.cpp //
// Project: MUNGA Brick: Video Renderer Manager //
// Contents: Interface specification Video performance monitoring tools //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 03/5/96 GAC initial coding //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include "l4munga.hpp"
#if !defined(L4VIDPER_HPP)
# include "l4vidper.hpp"
#endif
extern "C" const int32 __sect_time;
extern "C" const int32 __last_cull_time;
extern "C" const int32 __last_draw_time;
extern "C" const int32 __last_frame_time;
extern "C" const int32 __last_pxpl_time;
extern "C" const int32 __last_frame_prims;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructor for the StripChartRenderable
// Used to performance monitor a variable that can change every frame
//
StripChartRenderable::StripChartRenderable(
Entity *entity, // Entity to attach the renderable to
ExecutionType execution_type, // How/when to execute the renderable
dpl_VIEW *this_view, // the view associated with our eye
float left,
float right,
float top,
float bottom,
int max_samples, // The number of samples to hold
int max_value, // The maximum value allowed
int min_value, // the minimum value allowed
int *value_to_chart, // the value we will be graphing
int update_interval // How frequently (in frames) to update the graphics
):
VideoRenderable(entity, execution_type)
{
int
i;
//
// Save the incoming data inside this class
//
myView = this_view;
myLeft = left;
myRight = right;
myTop = top;
myBottom = bottom;
myMaxSamples = max_samples;
myMaxValue = max_value;
myMinValue = min_value;
myValue = value_to_chart;
myUpdateInterval = update_interval;
myFrameCount = 0;
myCurrentSample = 0;
//
// Allocate the RAM to store the values we are charting and clear them out
//
myValueStorage = new int[max_samples];
if(!myValueStorage)
Fail("stripchart couldn't allocate value storage\n");
Check_Pointer(myValueStorage);
for(i = 0; i<max_samples; i++)
{
myValueStorage[i] = 0;
}
//
// Allocate space for the display list
//
myDisplayList = dpl2d_NewDisplayList();
if(!myDisplayList)
Fail("stripchart couldn't allocate a display list\n");
//
// Draw the bounding box for the chart
//
dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear);
dpl2d_AddFullScreenClipRegion (myDisplayList);
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f);
dpl2d_AddOpenPolyline (myDisplayList);
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
dpl2d_AddPoint (myDisplayList, myRight, myBottom);
dpl2d_AddPoint (myDisplayList, myRight, myTop);
dpl2d_AddPoint (myDisplayList, myLeft, myTop);
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
dpl2d_AddClosePolyline (myDisplayList);
dpl2d_CloseDisplayList (myDisplayList);
dpl2d_FlushDisplayList (myDisplayList);
//
// Bind the chart to our eyepoint
//
dpl2d_SetViewDisplayList ( myView, myDisplayList );
dpl_FlushView ( myView );
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Destructor for the StripChartRenderable
//
StripChartRenderable::~StripChartRenderable()
{
//
// Make sure our structure is still in one piece
//
Check(this);
//
// Unhook the display list from the view, then delete both lists
//
dpl2d_SetViewDisplayList ( myView, NULL );
dpl_FlushView ( myView );
dpl2d_DeleteDisplayList(myDisplayList);
delete myValueStorage;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// TestInstance for the StripChartRenderable
//
Logical
StripChartRenderable::TestInstance() const
{
VideoRenderable::TestInstance();
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Execute for the StripChartRenderable
//
void
StripChartRenderable::Execute()
{
int
i;
//
// Increment frame counter
//
myFrameCount++;
//
// Grab the statistic we're tracking and stuff it into the buffer
//
myValueStorage[myCurrentSample] = *myValue;
//
// If it's time to redraw the graph, do it
//
if(myFrameCount >= myUpdateInterval)
{
myFrameCount = 0;
//
// Figure the scale factor for the graph
//
float
current_x,
current_y,
x_increment,
y_increment;
x_increment = (myRight - myLeft)/ (float)(myMaxSamples);
y_increment = (myBottom - myTop)/((float)myMaxValue - (float)myMinValue);
dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear);
dpl2d_AddFullScreenClipRegion (myDisplayList);
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f);
dpl2d_AddOpenPolyline (myDisplayList);
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
dpl2d_AddPoint (myDisplayList, myRight, myBottom);
dpl2d_AddPoint (myDisplayList, myRight, myTop);
dpl2d_AddPoint (myDisplayList, myLeft, myTop);
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
dpl2d_AddClosePolyline (myDisplayList);
dpl2d_AddOpenPolyline (myDisplayList);
current_x = myLeft;
for(i = 0; i < myMaxSamples; i++)
{
current_y = myBottom-((float)myValueStorage[i] * y_increment);
dpl2d_AddPoint(myDisplayList,current_x,current_y);
current_x += x_increment;
}
dpl2d_AddClosePolyline (myDisplayList);
dpl2d_AddOpenLines (myDisplayList);
dpl2d_AddPoint (myDisplayList,
myLeft + (x_increment*myCurrentSample),
myBottom);
dpl2d_AddPoint (myDisplayList,
myLeft + (x_increment*myCurrentSample),
myTop);
dpl2d_AddCloseLines (myDisplayList);
dpl2d_CloseDisplayList (myDisplayList);
dpl2d_FlushDisplayList (myDisplayList);
}
//
// Update the current sample pointer
//
myCurrentSample ++;
if(myCurrentSample >= myMaxSamples)
myCurrentSample = 0;
//
// Call the execute method in our parent
//
VideoRenderable::Execute();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructor for the RendererChartRenderable
// Used to performance monitor a variable that can change every frame
//
RendererChartRenderable::RendererChartRenderable(
Entity *entity, // Entity to attach the renderable to
ExecutionType execution_type, // How/when to execute the renderable
dpl_VIEW *this_view, // the view associated with our eye
float left,
float right,
float top,
float bottom,
int max_samples, // The number of samples to hold
int max_value, // The maximum value allowed
int min_value, // the minimum value allowed
int update_interval // How frequently (in frames) to update the graphics
):
VideoRenderable(entity, execution_type)
{
int
i;
//
// Save the incoming data inside this class
//
myView = this_view;
myLeft = left;
myRight = right;
myTop = top;
myBottom = bottom;
myMaxSamples = max_samples;
myMaxValue = max_value;
myMinValue = min_value;
myUpdateInterval = update_interval;
myFrameCount = 0;
myCurrentSample = 0;
//
// Allocate the RAM to store the values we are charting and clear them out
//
myCullStorage = new int[max_samples];
myDrawStorage = new int[max_samples];
myFrameStorage = new int[max_samples];
myPixelPlanesStorage = new int[max_samples];
myPrimativeStorage = new int[max_samples];
if(!myCullStorage || !myDrawStorage || !myFrameStorage || !myPixelPlanesStorage || !myPrimativeStorage)
Fail("RendererChartRenderable couldn't allocate storage\n");
Check_Pointer(myValueStorage);
for(i = 0; i<max_samples; i++)
{
myCullStorage[i] = 0;
myDrawStorage[i] = 0;
myFrameStorage[i] = 0;
myPixelPlanesStorage[i] = 0;
myPrimativeStorage[i] = 0;
}
//
// Allocate space for the display list
//
myDisplayList = dpl2d_NewDisplayList();
if(!myDisplayList)
Fail("stripchart couldn't allocate a display list\n");
//
// Draw the bounding box for the chart
//
dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear);
dpl2d_AddFullScreenClipRegion (myDisplayList);
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f);
dpl2d_AddSetLineWidth (myDisplayList,1.0);
dpl2d_AddOpenPolyline (myDisplayList);
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
dpl2d_AddPoint (myDisplayList, myRight, myBottom);
dpl2d_AddPoint (myDisplayList, myRight, myTop);
dpl2d_AddPoint (myDisplayList, myLeft, myTop);
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
dpl2d_AddClosePolyline (myDisplayList);
//
// Bind the chart to our eyepoint
//
mySystemDisplayList = dpl2d_GetViewDisplayList (myView);
if(mySystemDisplayList)
{
// If a display list was already installed, call it at the end of this
// 2d display list so it will still show up. (ugley, but as this is
// test code only it should be sufficient)
dpl2d_AddCallDisplayList (myDisplayList, mySystemDisplayList );
}
dpl2d_CloseDisplayList (myDisplayList);
dpl2d_FlushDisplayList (myDisplayList);
//
// hook our dlist up to the view so it will be drawn
//
dpl2d_SetViewDisplayList ( myView, myDisplayList );
dpl_FlushView ( myView );
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Destructor for the RendererChartRenderable
//
RendererChartRenderable::~RendererChartRenderable()
{
//
// Make sure our structure is still in one piece
//
Check(this);
//
// Unhook the display list from the view, then delete both lists
//
dpl2d_SetViewDisplayList ( myView, NULL );
dpl_FlushView ( myView );
dpl2d_DeleteDisplayList(myDisplayList);
delete myCullStorage;
delete myDrawStorage;
delete myFrameStorage;
delete myPixelPlanesStorage;
delete myPrimativeStorage;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// TestInstance for the RendererChartRenderable
//
Logical
RendererChartRenderable::TestInstance() const
{
VideoRenderable::TestInstance();
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Execute for the RendererChartRenderable
//
void
RendererChartRenderable::Execute()
{
int
i;
//
// Increment frame counter
//
myFrameCount++;
//
// Grab the statistic we're tracking and stuff it into the buffer
//
myCullStorage[myCurrentSample] = __last_cull_time;
myDrawStorage[myCurrentSample] = __last_draw_time;
myFrameStorage[myCurrentSample] = __last_frame_time;
myPixelPlanesStorage[myCurrentSample] = __last_pxpl_time;
myPrimativeStorage[myCurrentSample] = __last_frame_prims;
//
// If it's time to redraw the graph, do it
//
if(myFrameCount >= myUpdateInterval)
{
myFrameCount = 0;
//
// Figure the scale factor for the graph
//
float
current_x,
current_y,
x_increment,
y_increment;
x_increment = (myRight - myLeft)/ (float)(myMaxSamples);
y_increment = (myBottom - myTop)/((float)myMaxValue - (float)myMinValue);
dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear);
dpl2d_AddFullScreenClipRegion (myDisplayList);
dpl2d_AddSetLineWidth (myDisplayList,1.0);
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f);
dpl2d_AddOpenPolyline (myDisplayList);
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
dpl2d_AddPoint (myDisplayList, myRight, myBottom);
dpl2d_AddPoint (myDisplayList, myRight, myTop);
dpl2d_AddPoint (myDisplayList, myLeft, myTop);
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
dpl2d_AddClosePolyline (myDisplayList);
//
// Draw the primative count trace
//
dpl2d_AddOpenLines (myDisplayList);
dpl2d_AddPoint(myDisplayList,myLeft, myBottom + (500.0f * y_increment * 50.0f));
dpl2d_AddPoint(myDisplayList,myRight, myBottom + (500.0f * y_increment * 50.0f));
dpl2d_AddPoint(myDisplayList,myLeft, myBottom + (1000.0f * y_increment * 50.0f));
dpl2d_AddPoint(myDisplayList,myRight, myBottom + (1000.0f * y_increment * 50.0f));
dpl2d_AddCloseLines (myDisplayList);
dpl2d_AddOpenPolyline (myDisplayList);
current_x = myLeft;
for(i = 0; i < myMaxSamples; i++)
{
current_y = myBottom+((float)myPrimativeStorage[i] * y_increment * 50.0f);
dpl2d_AddPoint(myDisplayList,current_x,current_y);
current_x += x_increment;
}
dpl2d_AddClosePolyline (myDisplayList);
//
// Draw the frame time trace
//
dpl2d_AddSetColor (myDisplayList, 0.75f, 0.75f, 0.75f);
dpl2d_AddOpenPolyline (myDisplayList);
current_x = myLeft;
for(i = 0; i < myMaxSamples; i++)
{
current_y = myBottom-((float)myFrameStorage[i] * y_increment);
dpl2d_AddPoint(myDisplayList,current_x,current_y);
current_x += x_increment;
}
dpl2d_AddClosePolyline (myDisplayList);
//
// Draw the draw time trace
//
dpl2d_AddSetColor (myDisplayList, 0.75f, 0.0f, 0.0f);
dpl2d_AddOpenPolyline (myDisplayList);
current_x = myLeft;
for(i = 0; i < myMaxSamples; i++)
{
current_y = myBottom-((float)myDrawStorage[i] * y_increment);
dpl2d_AddPoint(myDisplayList,current_x,current_y);
current_x += x_increment;
}
dpl2d_AddClosePolyline (myDisplayList);
//
// Draw the pixel planes time trace
//
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.0f, 0.75f);
dpl2d_AddOpenPolyline (myDisplayList);
current_x = myLeft;
for(i = 0; i < myMaxSamples; i++)
{
current_y = myBottom-((float)myPixelPlanesStorage[i] * y_increment);
dpl2d_AddPoint(myDisplayList,current_x,current_y);
current_x += x_increment;
}
dpl2d_AddClosePolyline (myDisplayList);
//
// Stack the cull time on top of the draw
//
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f);
dpl2d_AddOpenPolyline (myDisplayList);
current_x = myLeft;
for(i = 0; i < myMaxSamples; i++)
{
current_y = myBottom-(((float)myCullStorage[i] + (float)myDrawStorage[i]) * y_increment);
dpl2d_AddPoint(myDisplayList,current_x,current_y);
current_x += x_increment;
}
dpl2d_AddClosePolyline (myDisplayList);
//
// Draw a line indicating the current time
//
dpl2d_AddOpenLines (myDisplayList);
dpl2d_AddPoint (myDisplayList,
myLeft + (x_increment*myCurrentSample),
myBottom);
dpl2d_AddPoint (myDisplayList,
myLeft + (x_increment*myCurrentSample),
myTop);
dpl2d_AddCloseLines (myDisplayList);
//
// If there is a pre existing dlist, insert a call to it here
//
if(mySystemDisplayList)
{
dpl2d_AddCallDisplayList (myDisplayList, mySystemDisplayList );
}
//
// Close up the display list and flush it
//
dpl2d_CloseDisplayList (myDisplayList);
dpl2d_FlushDisplayList (myDisplayList);
}
//
// Update the current sample pointer
//
myCurrentSample ++;
if(myCurrentSample >= myMaxSamples)
myCurrentSample = 0;
//
// Call the execute method in our parent
//
VideoRenderable::Execute();
}