Files
RP412/MUNGA_L4/L4GREND.cpp
T
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet',
built on the MUNGA engine and its L4 (Win32/DirectX) platform layer:

- MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend
- RP / RP_L4: Red Planet game logic and Win32 application
- DivLoader, Setup1: asset loader and installer project
- lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies

Removed stale Subversion metadata and added .gitignore/.gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 07:59:51 -05:00

837 lines
21 KiB
C++

#include "mungal4.h"
#pragma hdrstop
#include "l4app.h"
#include "..\munga\time.h"
#include "l4grend.h"
#include "l4gauge.h"
#include "..\munga\mission.h"
#include "l4plasma.h"
#include "..\munga\notation.h"
// #define LOCAL_TEST
#if defined(LOCAL_TEST)
# define Test_Tell(n) DEBUG_STREAM << n << std::flush
#else
# define Test_Tell(n)
#endif
//
//#############################################################################
// L4MethodDescription list
//#############################################################################
//
MethodDescription
L4ChainToPrevious = METHOD_DESCRIPTION_CHAIN(NULL); // Null:end of chain
MethodDescription
*L4MethodDescription[] =
{
&MakeConfigMethodDescription,
&MakeExternConfigMethodDescription,
&BackgroundReconfig::methodDescription,
&BackgroundLine::methodDescription,
&BackgroundRect::methodDescription,
&BackgroundFilledRect::methodDescription,
&BackgroundPixelmap::methodDescription,
&BackgroundBitmap::methodDescription,
&NumericDisplayScalar::methodDescription,
&NumericDisplaySpeed::methodDescription,
&NumericDisplayInteger::methodDescription,
&DigitalClock::methodDescription,
&RankAndScore::methodDescription,
&BarGraphSolidScalar::methodDescription,
&BarGraphPixelMapScalar::methodDescription,
&ColorState::methodDescription,
&TwoState::methodDescription,
&SegmentArcNormalized::methodDescription,
&L4ChainToPrevious
};
//
//#############################################################################
// L4GaugeRenderer
//#############################################################################
//
L4GaugeRenderer::L4GaugeRenderer(bool windowed, int *secondaryIndex, int *aux1Index, int *aux2Index):
GaugeRenderer()
{
//
//---------------------------------------------------------------------
// Ensure that graphicsDisplay is NULL
//---------------------------------------------------------------------
//
graphicsDisplay = NULL;
externalDisplay = NULL;
palettesAreActive = True;
scrambleVideoFlag = False;
char
*mode_string = getenv("L4GAUGE");
//
//---------------------------------------------------------------------
// NOTE that L4Application::Initialize() searches for the environment
// variable "L4GAUGE" to determine whether or not to create
// a gauge renderer.
//---------------------------------------------------------------------
//
if (mode_string != NULL)
{
//
//---------------------------------------------------------------------
// Attempt to initialize external display
//---------------------------------------------------------------------
//
char
*plasma_string = getenv("L4PLASMA");
if (plasma_string != NULL)
{
//Win32 Serial support: ADB 06/30/07
//if (strnicmp(plasma_string, "COM2", 4) == 0)
//{
// Tell("Plasma display created on COM2\n");
// externalDisplay = new PlasmaDisplay(PCS_COM2);
//}
//else
//{
// Tell("Plasma display created on COM1\n");
// externalDisplay = new PlasmaDisplay(PCS_COM1);
//}
Tell("Plasma display created on "); Tell(plasma_string); Tell("\n");
externalDisplay = new PlasmaDisplay(plasma_string);
if (externalDisplay != NULL)
{
Register_Object(externalDisplay);
}
}
//
//---------------------------------------------------------------------
// Attempt to initialize main display
//---------------------------------------------------------------------
//-------------------------------------------------
// Search notation file for specified resolution
//-------------------------------------------------
//
NotationFile
notation_file("GAUGE\\L4GAUGE.INI");
if (!notation_file.PageExists(mode_string))
{
Tell("L4GaugeRenderer::L4GaugeRenderer - '" <<
mode_string <<
"' not found in L4GAUGE.INI!\n"
);
}
else
{
//
//-------------------------------------------------
// Requested resolution exists, read parameters
//-------------------------------------------------
//
int
mode(0),
width(640),
height(480),
page_size(64),
gran(64),
bpl(640*2),
pfp(0),
special(0),
q(0);
q += notation_file.GetEntry(mode_string, "mode", &mode);
q += notation_file.GetEntry(mode_string, "width", &width);
q += notation_file.GetEntry(mode_string, "height", &height);
q += notation_file.GetEntry(mode_string, "sizeInKB", &page_size);
q += notation_file.GetEntry(mode_string, "granularityInKB", &gran);
q += notation_file.GetEntry(mode_string, "bytesPerLine", &bpl);
q += notation_file.GetEntry(mode_string, "pageFcnPtr", &pfp);
q += notation_file.GetEntry(mode_string, "special", &special);
if (q == 8)
{
graphicsDisplay = new
SVGA16(
mode,
width,
height,
page_size,
gran,
bpl,
pfp,
special,
windowed,
secondaryIndex,
aux1Index,
aux2Index
);
if (graphicsDisplay != NULL)
{
Register_Object(graphicsDisplay);
}
}
}
}
Check_Fpu();
}
//
//#############################################################################
// ~L4GaugeRenderer
//#############################################################################
//
L4GaugeRenderer::~L4GaugeRenderer()
{
# if defined (LOCAL_TEST)
Tell("L4GaugeRenderer::~L4GaugeRenderer()\n");
# endif
Check(this);
int i;
//----------------------------------------------------
// Make sure all gauges removed first
//----------------------------------------------------
Remove(0);
//----------------------------------------------------
// Delete the graphics ports
//----------------------------------------------------
for(i=0; i<maximumGraphicsPorts; ++i)
{
if (graphicsPort[i] != NULL)
{
Check(graphicsPort[i]);
Unregister_Object(graphicsPort[i]);
delete graphicsPort[i];
}
}
if (graphicsDisplay != NULL)
{
Check(graphicsDisplay);
Unregister_Object(graphicsDisplay);
delete graphicsDisplay;
}
if (externalDisplay != NULL)
{
Check(externalDisplay);
Unregister_Object(externalDisplay);
delete externalDisplay;
}
Check_Fpu();
}
//
//#############################################################################
// LocalEmergencyShutdown - restore the ABSOLUTE MINIMUM to get back
// to the system!
//#############################################################################
//
void
L4GaugeRenderer::LocalEmergencyShutdown()
{
if (graphicsDisplay != NULL)
{
// It's an EMERGENCY: a 'verify' somewhere may have already failed.
// Therefore don't check it, just kill it!
delete graphicsDisplay;
}
GaugeRenderer::LocalEmergencyShutdown();
}
//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
L4GaugeRenderer::TestInstance() const
{
return GaugeRenderer::TestInstance();
}
//
//#############################################################################
// StartImplementation
//#############################################################################
//
void
L4GaugeRenderer::LoadMissionImplementation(Mission *mission)
{
Check(this);
# if defined (LOCAL_TEST)
Tell("L4GaugeRenderer::LoadMissionImplementation()\n");
# endif
GaugeRenderer::LoadMissionImplementation(mission);
Check_Fpu();
}
//
//#############################################################################
// StopImplementation
//#############################################################################
//
void
L4GaugeRenderer::ShutdownImplementation()
{
Check(this);
# if defined (LOCAL_TEST)
Tell("L4GaugeRenderer::ShutdownImplementation()\n");
# endif
// EVENTUALLY kill all interrupt-driven processes (if they exist)
GaugeRenderer::ShutdownImplementation();
Check_Fpu();
}
//
//#############################################################################
// SuspendImplementation
//#############################################################################
//
void
L4GaugeRenderer::SuspendImplementation()
{
Check(this);
# if defined (LOCAL_TEST)
Tell("L4GaugeRenderer::SuspendImplementation()\n");
# endif
GaugeRenderer::SuspendImplementation();
Check_Fpu();
}
//
//#############################################################################
// ResumeImplementation
//#############################################################################
//
void
L4GaugeRenderer::ResumeImplementation()
{
Check(this);
# if defined (LOCAL_TEST)
Tell("L4GaugeRenderer::ResumeImplementation()\n");
# endif
GaugeRenderer::ResumeImplementation();
Check_Fpu();
}
//
//#############################################################################
// ExecuteForeground
//#############################################################################
//
void
L4GaugeRenderer::ExecuteForeground()
{
Check(this);
//---------------------------------------
// We must call the ancestral method!
//---------------------------------------
Time old = Now();
GaugeRenderer::ExecuteForeground();
//---------------------------------------
// Process special effects
//---------------------------------------
if (graphicsDisplay != NULL)
{
Check(graphicsDisplay);
ProcessVideoEffects();
((SVGA16 *) graphicsDisplay)->UpdatePalette();
}
Time newTime = Now();
Scalar diff = newTime - old;
Check_Fpu();
}
//
//#############################################################################
// ExecuteImplementation
//#############################################################################
//
Logical
L4GaugeRenderer::ExecuteBackgroundDisplayUpdate()
{
Check(this);
Logical
result = False; // False == 'all done'
//--------------------------------------------------------
// Update external annunciator
//
// Allow the plasma display to continue if there's
// more background time available.
//
// This method is still called if taskmode is set to
// 'foreground'. If it's called in 'foreground' mode,
// it really means that we're still waiting for foreground
// to begin processing, so we might as well update the
// external display (if needed).
//--------------------------------------------------------
if (externalDisplay != NULL)
{
Check(externalDisplay);
result = externalDisplay->Update(False); // returns 'False' if done
}
//-------------------------------------------------------
// Update display ONLY in 'copy' mode
//--------------------------------------------------------
if (taskMode == copy)
{
if (graphicsDisplay != NULL)
{
Check(graphicsDisplay);
if (graphicsDisplay->Update(False) == False)
{
//--------------------------------------------------------
// Tell executionImplementation that we're basically done.
//--------------------------------------------------------
taskMode = foreground;
}
else
{
result = True; // We're not done yet!
}
}
} else if (l4_application->GetApplicationState() == Application::WaitingForEgg)
{
((SVGA16*)graphicsDisplay)->Refresh();
}
return result;
}
//
//#############################################################################
// NotifyOfNewInterestingEntity
//#############################################################################
//
void
L4GaugeRenderer::NotifyOfNewInterestingEntity(
Entity *interesting_entity
)
{
SET_GAUGE_RENDERER();
Check(this);
Check(interesting_entity);
//----------------------------------------------
// Make sure gaugeImage exists for entity
//----------------------------------------------
Check(warehousePointer);
((L4Warehouse*)warehousePointer)->gaugeImageBin.Get(
interesting_entity->GetResourceID()
);
//----------------------------------------------
// Update gaugeRenderer
//----------------------------------------------
GaugeRenderer::NotifyOfNewInterestingEntity(interesting_entity);
Check_Fpu();
CLEAR_GAUGE_RENDERER();
}
//
//#############################################################################
// NotifyOfBecomingUninterestingEntity
//#############################################################################
//
void
L4GaugeRenderer::NotifyOfBecomingUninterestingEntity(
Entity *uninteresting_entity
)
{
SET_GAUGE_RENDERER();
Check(this);
Check(uninteresting_entity);
//----------------------------------------------
// Remove gaugeImage if no longer used
//----------------------------------------------
Check(warehousePointer);
((L4Warehouse*)warehousePointer)->gaugeImageBin.Release(
uninteresting_entity->GetResourceID()
);
//----------------------------------------------
// Update gaugeRenderer
//----------------------------------------------
GaugeRenderer::NotifyOfBecomingUninterestingEntity(uninteresting_entity);
Check_Fpu();
CLEAR_GAUGE_RENDERER();
}
//
//#############################################################################
// BuildGraphicsPort
//#############################################################################
//
void
L4GaugeRenderer::BuildGraphicsPort(
int port_number,
const char *name,
int rotation,
int bitAllocation,
SVGA16::PaletteID palette_ID,
L4GraphicsPort::ChannelEnableID enable_ID,
Palette8 *palette
)
{
Test_Tell("L4GaugeRenderer::BuildGraphicsPort\n");
Check(this);
if (graphicsDisplay != NULL)
{
Test_Tell("...non-NULL display\n");
Verify(port_number < maximumGraphicsPorts);
Verify(port_number >= 0);
Test_Tell("...port_number= " << port_number << "\n");
//
//---------------------------------------------------------
// If it already exists, delete it
//---------------------------------------------------------
//
L4GraphicsPort
*graphics_port = (L4GraphicsPort *) graphicsPort[port_number];
if (graphics_port != NULL)
{
Test_Tell("...deleting existing port\n");
Check(graphics_port);
Unregister_Object(graphics_port);
delete graphics_port;
}
//
//---------------------------------------------------------
// Attempt to create it
//---------------------------------------------------------
//
graphicsPort[port_number] = new L4GraphicsPort(
(Video16BitBuffered *) graphicsDisplay,
name,
rotation,
bitAllocation,
palette_ID,
enable_ID
);
graphics_port = (L4GraphicsPort *) graphicsPort[port_number];
Test_Tell("...new port at " << graphics_port << "\n");
//
//---------------------------------------------------------
// If created, register it and build the palette
//---------------------------------------------------------
//
if (graphics_port != NULL)
{
Check(graphics_port);
Register_Object(graphics_port);
//
// Set the palette for the port
// (Note: secondary uses lowest 8 bits)
//
if ((bitAllocation > 0) && (bitAllocation < 0x0100))
{
Test_Tell("...secondary\n");
graphics_port->SetSecondaryPalette(palette);
}
else
{
Test_Tell("...auxiliary\n");
graphics_port->SetAuxiliaryPalette();
}
}
}
Check_Fpu();
}
//
//#############################################################################
// RemapGraphicsPort
//#############################################################################
//
void
L4GaugeRenderer::RemapGraphicsPort(
int port_number,
SVGA16::PaletteID palette_ID,
L4GraphicsPort::ChannelEnableID enable_ID,
Palette8 *palette
)
{
Check(this);
Test_Tell("L4GaugeRenderer::RemapGraphicsPort\n");
if (graphicsDisplay != NULL)
{
Test_Tell("...non-NULL display\n");
Verify(port_number < maximumGraphicsPorts);
Verify(port_number >= 0);
Test_Tell("...port_number= " << port_number << "\n");
//---------------------------------------------------------
// If it exists, change the palette ID and set the palette
//---------------------------------------------------------
L4GraphicsPort
*graphics_port = (L4GraphicsPort *) graphicsPort[port_number];
if (graphics_port != NULL)
{
Check(graphics_port);
//
// Set the palette ID
//
graphics_port->SetPaletteID(palette_ID);
graphics_port->SetEnableID(enable_ID);
//
// Set the palette for the port
// (Note: secondary uses lowest 8 bits)
//
int
bit_mask = graphics_port->GetBitMask();
if (bit_mask & 0x00FF) // must be secondary
{
Test_Tell("...secondary\n");
Verify(palette != NULL);
graphics_port->SetSecondaryPalette(palette);
}
else
{
Test_Tell("...auxiliary\n");
graphics_port->SetAuxiliaryPalette();
}
}
}
Check_Fpu();
}
//
//#############################################################################
// BuildExternalGraphicsPort
//#############################################################################
//
void
L4GaugeRenderer::BuildExternalGraphicsPort(
int port_number,
const char *name,
int /*bitAllocation*/
)
{
Check(this);
Test_Tell(
"L4GaugeRenderer::BuildExternalGraphicsPort(" << port_number << ")\n"
);
if (externalDisplay != NULL)
{
Test_Tell("...non-NULL display\n");
Verify(port_number < maximumGraphicsPorts);
Verify(port_number >= 0);
Test_Tell("...port_number= " << port_number << "\n");
//
//---------------------------------------------------------
// If it already exists, delete it
//---------------------------------------------------------
//
L4GraphicsPort
*graphics_port = (L4GraphicsPort *) graphicsPort[port_number];
if (graphics_port != NULL)
{
Test_Tell("...deleting existing port\n");
Check(graphics_port);
Unregister_Object(graphics_port);
delete graphics_port;
}
//
//---------------------------------------------------------
// Attempt to create it
//---------------------------------------------------------
//
graphicsPort[port_number] = new L4BytePort(
(Video8BitBuffered *) externalDisplay,
name,
0 // rotation
);
graphics_port = (L4GraphicsPort *) graphicsPort[port_number];
Test_Tell("...new port at " << graphics_port << "\n");
//
//---------------------------------------------------------
// If created, register it
//---------------------------------------------------------
//
if (graphics_port != NULL)
{
Check(graphics_port);
Register_Object(graphics_port);
}
}
Check_Fpu();
}
//
//#############################################################################
// FadeToWhite, FadeToGame
//#############################################################################
//
void
L4GaugeRenderer::FadeToWhite(Scalar number_of_seconds)
{
Check(this);
Verify(number_of_seconds >= 0.0); // zero is allowed (instant change)
// cout << "L4GaugeRenderer::FadeToWhite(" << number_of_seconds << ")\n";
if (graphicsDisplay != NULL)
{
Check(graphicsDisplay);
((SVGA16 *)graphicsDisplay)->FadeToWhite(number_of_seconds);
}
Check_Fpu();
}
void
L4GaugeRenderer::FadeToNormal(Scalar number_of_seconds)
{
Check(this);
Verify(number_of_seconds >= 0.0); // zero is allowed (instant change)
// cout << "L4GaugeRenderer::FadeToNormal(" << number_of_seconds << ")\n";
if (graphicsDisplay != NULL)
{
Check(graphicsDisplay);
((SVGA16 *)graphicsDisplay)->FadeToPalettes(number_of_seconds);
}
Check_Fpu();
}
//
//#############################################################################
// Configure
//#############################################################################
//
void
L4GaugeRenderer::ConfigureForModel(
const char *configuration_name,
Entity *entity
)
{
Check(this);
Check_Pointer(configuration_name);
Test_Tell(
"L4GaugeRenderer::ConfigureForModel(" <<
configuration_name << ", " <<
entity << ")\n"
);
Check(application);
Check(entity);
Mission
*mission = application->GetCurrentMission();
Check(mission);
const char
*model_name = mission->GetGameModel();
Check_Pointer(model_name);
char
full_name[64];
Str_Copy(full_name, model_name, sizeof(full_name));
Str_Cat(full_name, configuration_name, sizeof(full_name));
Test_Tell(
"L4GaugeRenderer::ConfigureForModel, full_name=" << full_name <<
")\n"
);
Configure(full_name, entity);
Check_Fpu();
}
//
//#############################################################################
// SpecialEffect
//#############################################################################
//
void
L4GaugeRenderer::SpecialEffect(
VideoEffectType type,
Scalar duration
)
{
Check(this);
switch (type)
{
case scrambleVideo:
if (graphicsDisplay != NULL)
{
scrambleVideoFlag = True;
scrambleVideoTimeout = ((Scalar)Now()) + duration;
Check(graphicsDisplay);
((SVGA16*) graphicsDisplay)->FunkyVideo(True);
}
break;
// other modes go here
}
Check_Fpu();
}
void
L4GaugeRenderer::ProcessVideoEffects()
{
Check(this);
Check(graphicsDisplay);
Time
now = Now();
if (scrambleVideoFlag)
{
if (now >= scrambleVideoTimeout)
{
scrambleVideoFlag = False;
((SVGA16*) graphicsDisplay)->FunkyVideo(False);
}
}
Check_Fpu();
}
//--------------------------------------------------------------------
// Profiling support
//--------------------------------------------------------------------
Scalar
L4GaugeRenderer::GetCurrentFramePercentage()
{
Check(this);
return Get_Frame_Percent_Used();
}