Files
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

661 lines
15 KiB
C++

#include "munga.h"
#pragma hdrstop
#include "controls.h"
#include "app.h"
#if defined(DEBUG)
# define Test_Tell(n) DEBUG_STREAM << n
#else
# define Test_Tell(n)
#endif
//############################################################################
//####################### ControlsInstance #############################
//############################################################################
ControlsInstance::ControlsInstance(
ClassID class_ID,
ModeMask mode_mask,
Plug *dependant
):
Node(class_ID),
dependantPlug(this)
{
Check_Pointer(this);
modeMask = mode_mask;
dependantPlug.Add(dependant);
Check_Fpu();
}
ControlsInstance::~ControlsInstance()
{
Check(this);
Check_Fpu();
}
void
ControlsInstance::Update(void *)
{
Fail("ControlsInstance::Update not overridden!");
}
//
//#############################################################################
//#############################################################################
//
void
ControlsInstance::ReleaseLinkHandler(
Socket*,
Plug*
)
{
Unregister_Object(this);
delete this;
Check_Fpu();
}
//############################################################################
//######################### ControlsMappingGroup #############################
//############################################################################
//
// The ControlsMappingGroup object maintains a group of ControlInstances.
//
// ControlsMappingGroup.Update() will call ControlsInstance.Update()
// for each instance in the group.
//
ControlsMappingGroup::ControlsMappingGroup():
Node(ControlsMappingGroup::ControlsMappingGroupClassID),
instanceList(this)
{
Check_Pointer(this);
Check_Fpu();
}
ControlsMappingGroup::~ControlsMappingGroup()
{
Check(this);
Remove(0); // remove all mappings
Check_Fpu();
}
void ControlsMappingGroup::Remove(ModeMask mode_mask)
{
Check(this);
ChainIteratorOf<ControlsInstance*>
i(instanceList);
ControlsInstance
*controls_instance;
while ((controls_instance=i.ReadAndNext()) != NULL)
{
Check(controls_instance);
//---------------------------------------------
// Remove mapping bit(s)
//---------------------------------------------
controls_instance->modeMask &= ~mode_mask;
//---------------------------------------------
// If no bits left, delete mapping
//---------------------------------------------
if (controls_instance->modeMask == (ModeMask)0)
{
Unregister_Object(controls_instance);
delete controls_instance;
}
}
Check_Fpu();
}
void
ControlsMappingGroup::Update(void *data_source, ModeMask mode_mask)
{
Check(this);
Check_Pointer(data_source);
ChainIteratorOf<ControlsInstance*>
i(instanceList);
ControlsInstance
*controls_instance;
while ((controls_instance=i.ReadAndNext()) != NULL)
{
//------------------------------------------------
// Process only if at least one mode bit matches
//------------------------------------------------
Check(controls_instance);
if (controls_instance->modeMask & mode_mask)
{
controls_instance->Update(data_source);
}
}
Check_Fpu();
}
Logical
ControlsMappingGroup::CurrentFilterStatus(ModeMask mode_mask)
{
Check(this);
ChainIteratorOf<ControlsInstance*>
i(instanceList);
ControlsInstance
*controls_instance;
while ((controls_instance=i.ReadAndNext()) != NULL)
{
Check(controls_instance);
if (controls_instance->modeMask & mode_mask)
{
Check_Fpu();
return True;
}
}
Check_Fpu();
return False;
}
//############################################################################
//########################### ControlsManager ################################
//############################################################################
//---------------------------------------------------------------------------
// Class derivation
//---------------------------------------------------------------------------
Derivation* ControlsManager::GetClassDerivations()
{
static Derivation classDerivations(Receiver::GetClassDerivations(), "ControlsManager");
return &classDerivations;
}
unsigned int
ControlsManager::nextOwnerID=0;
ControlsManager
*ControlsManager::headControlsManager = NULL;
//
//############################################################################
// ControlsManager
//
// Creator method
//----------------------------------------------------------------------------
// Enter: virtualDataPtr
//############################################################################
//
ControlsManager::ControlsManager(
ClassID class_ID,
SharedData &shared_data
):
Receiver(
class_ID,
shared_data
)
{
activeDestination = NULL;
activeReceiver = NULL;
activeMessageID = (Receiver::MessageID) 0;
activeDependant = NULL;
//----------------------------------------------------
// Add this object to the chain
//----------------------------------------------------
nextControlsManager = headControlsManager;
headControlsManager = this;
Check_Fpu();
}
//
//############################################################################
// ~ControlsManager
//
// Destructor method
//############################################################################
//
ControlsManager::~ControlsManager()
{
//----------------------------------------------------
// Unlink this object from the chain
//----------------------------------------------------
ControlsManager
*controls_manager,
*previous_controls_manager(NULL);
//
// Search for 'this' in the chain
//
for(
controls_manager = headControlsManager;
controls_manager != NULL;
controls_manager = controls_manager->nextControlsManager
)
{
if (controls_manager == this)
{
//
// Found! head of list?
//
if (previous_controls_manager == NULL)
{
headControlsManager = nextControlsManager;
}
//
// Not head, remove from chain
//
else
{
previous_controls_manager->nextControlsManager =
nextControlsManager;
}
break;
}
//
// Keep track of 'previous' object
//
previous_controls_manager = controls_manager;
}
Check_Fpu();
}
void
ControlsManager::Remove(ModeMask /*mode_mask*/)
{
Fail("ControlsManager::Remove should not be called!\n");
}
void
ControlsManager::Execute()
{
Fail("ControlsManager::Execute should not be called!\n");
}
void
ControlsManager::StartMappableButtonsConfigure(
void *active_direct_target,
Receiver *target,
Plug *dependant,
Receiver::MessageID active_message_id,
ModeMask remove_mode_mask,
ModeMask add_mode_mask
)
{
Check(this);
activeReceiver = target;
activeMessageID = active_message_id;
activeDestination = active_direct_target;
activeDependant = dependant;
Check(application);
ModeManager
*mode_manager = application->GetModeManager();
Check(mode_manager);
mode_manager->RemoveModeMask(remove_mode_mask);
mode_manager->AddModeMask(add_mode_mask);
Check_Fpu();
}
void
ControlsManager::StopMappableButtonsConfigure(
ModeMask remove_mode_mask,
ModeMask add_mode_mask
)
{
Check(this);
Check(application);
ModeManager
*mode_manager = application->GetModeManager();
Check(mode_manager);
mode_manager->RemoveModeMask(remove_mode_mask);
mode_manager->AddModeMask(add_mode_mask);
activeDestination = NULL;
activeReceiver = NULL;
activeMessageID = (Receiver::MessageID) 0;
activeDependant = NULL;
Check_Fpu();
}
void
ControlsManager::AddOrEraseMappableButton(
int /*button_number*/,
ModeMask /*mode_mask*/
)
{
Check(this);
Check_Fpu();
}
//
//############################################################################
// TestInstance
//
//############################################################################
//
Logical
ControlsManager::TestInstance() const
{
return IsDerivedFrom(*GetClassDerivations());
}
//
//############################################################################
// Shutdown
//
//############################################################################
//
void
ControlsManager::Shutdown()
{
ControlsManager
*controls_manager;
for(
controls_manager = headControlsManager;
controls_manager != NULL;
controls_manager = controls_manager->nextControlsManager
)
{
controls_manager->LocalShutdown();
}
Check_Fpu();
}
void
ControlsManager::LocalShutdown()
{
Check(this);
Check_Fpu();
}
//#########################################################################
//############################# ControlsString ############################
//#########################################################################
int
ControlsString::nextID = 1;
ControlsString::ControlsString(
const char *new_string,
int keypad_unit_number,
Receiver *receiver_pointer,
Receiver::MessageID message_id,
int user_code
):
Node(RegisteredClass::ControlsStringClassID)
{
Test_Tell(
"ControlsString creator('" new_string <<
"'," << keypad_unit_number <<
"," << receiver_pointer <<
"," << message_id <<
")\n"
);
Check_Pointer(this);
Check_Pointer(new_string);
Check(receiver_pointer);
//----------------------------------------------
// Assign unique ID
//----------------------------------------------
id = nextID++;
matchStringPointer = new_string;
keypadUnitNumber = keypad_unit_number;
//----------------------------------------------
// Save message data
//----------------------------------------------
receiverPointer = receiver_pointer;
messageID = message_id;
userCode = user_code;
//----------------------------------------------
// Clear the buffer
//----------------------------------------------
string[0] = '\0';
stringLength = 0;
Check_Fpu();
}
ControlsString::~ControlsString()
{
Test_Tell("ControlsString destructor\n");
Check(this);
Check_Fpu();
}
Logical
ControlsString::TestInstance() const
{
return True;
}
void
ControlsString::Update(int keypad_unit_number, ControlsKey new_key)
{
Test_Tell(
"ControlsString::Update(" << keypad_unit_number <<
"," << new_key <<
"\n"
);
Check(this);
//----------------------------------------------
// Update only if proper keyboard unit
//----------------------------------------------
if (keypad_unit_number == keypadUnitNumber)
{
//--------------------------------------
// Get string length
//--------------------------------------
Check_Pointer(matchStringPointer);
int
length = strlen(matchStringPointer);
if (length > maxStringLength)
{
length = maxStringLength;
}
if (stringLength > length) // in case matchString changes
{
stringLength = length;
string[stringLength] = '\0';
}
//--------------------------------------
// Update string buffer
//--------------------------------------
if (stringLength < length)
{
string[stringLength++] = (char) new_key;
string[stringLength] = '\0';
}
else
{
if (length > 1)
{
memmove(&string[0],&string[1], length-1);
}
string[length-1] = (char) new_key;
}
Test_Tell("string=" << string << "\n");
//--------------------------------------
// Check for match
//--------------------------------------
if (strnicmp(string, matchStringPointer, length) == 0)
{
Test_Tell(
"ControlsString::Update, '" << matchStringPointer <<
"' matched!\n"
);
//--------------------------------------
// Match found, send message
//--------------------------------------
Check(receiverPointer);
Check(application);
ControlsStringMessage
message(messageID, this->userCode);
receiverPointer->Dispatch(&message);
//--------------------------------------
// Clear the string
//--------------------------------------
string[0] = '\0';
stringLength = 0;
}
}
Check_Fpu();
}
//#########################################################################
//######################## ControlsStringManager ##########################
//#########################################################################
ControlsStringManager::ControlsStringManager() :
Node(RegisteredClass::ControlsStringManagerClassID),
instanceList(this)
{
Test_Tell("ControlsStringManager creator\n");
Check_Pointer(this);
}
ControlsStringManager::~ControlsStringManager()
{
Test_Tell("ControlsStringManager destructor\n");
Check(this);
//----------------------------------------------
// Remove all ControlStrings
//----------------------------------------------
Remove(0);
Check_Fpu();
}
Logical
ControlsStringManager::TestInstance() const
{
return True;
}
ControlsStringID
ControlsStringManager::Add(
const char *new_string,
int keypad_unit_number,
Receiver *receiver_pointer,
Receiver::MessageID message_id,
int user_code
)
{
Test_Tell("ControlsStringManager::Add(" << new_string <<
"," << keypad_unit_number <<
"," << receiver_pointer <<
"," << message_id <<
"\n"
);
Check(this);
Check_Pointer(new_string);
Check(receiver_pointer);
//----------------------------------------------
// Create the ControlsString
//----------------------------------------------
ControlsString
*string_item = new ControlsString(
new_string,
keypad_unit_number,
receiver_pointer,
message_id,
user_code
);
Check(string_item);
Register_Object(string_item);
//----------------------------------------------
// Add to the instance list
//----------------------------------------------
instanceList.Add(string_item);
//----------------------------------------------
// return the new string's (unique) ID
//----------------------------------------------
Check_Fpu();
return string_item->id;
}
void
ControlsStringManager::Remove(ControlsStringID string_id)
{
Test_Tell("ControlsStringManager::Remove(" << string_id << ")\n");
Check(this);
ChainIteratorOf<ControlsString*>
i(instanceList);
ControlsString
*controls_string;
//----------------------------------------------
// Search for the given ID (or universal match)
//----------------------------------------------
while ((controls_string=i.ReadAndNext()) != NULL)
{
Check(controls_string);
if (
(string_id == 0) ||
(controls_string->id == string_id)
)
{
Unregister_Object(controls_string);
delete controls_string;
//------------------------------------------
// If this is not a 'universal' remove,
// we're done (ID's are unique)
//------------------------------------------
if (string_id != 0)
{
break;
}
}
}
Check_Fpu();
}
void
ControlsStringManager::Update(
int keypad_unit_number,
ControlsKey new_key
)
{
Test_Tell("ControlsStringManager::Update(" << keypad_unit_number <<
"," << new_key <<
")\n"
);
Check(this);
//--------------------------------------
// Update all matching string items
//--------------------------------------
ChainIteratorOf<ControlsString*>
i(instanceList);
ControlsString
*controls_string;
while ((controls_string=i.ReadAndNext()) != NULL)
{
Check(controls_string);
controls_string->Update(keypad_unit_number, new_key);
}
Check_Fpu();
}
#if defined(TEST_CLASS)
#include "controls.tcp"
#endif