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>
590 lines
15 KiB
C++
590 lines
15 KiB
C++
//===========================================================================//
|
|
// File: receiver.hpp //
|
|
// Project: MUNGA Brick: Dynamic Dispatch //
|
|
// Contents: Dynamic Dispatch Interface //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 10/19/94 JMA Initial coding. //
|
|
// 10/28/94 JMA Made compatible with SGI CC //
|
|
// 11/03/94 ECH Made compatible with BC4.0 //
|
|
// 11/04/94 JMA Made compatible with GNU C++ //
|
|
// 11/04/94 ECH Added null handler set //
|
|
// 11/29/94 JMA Changed ClassIdentity to ClassID //
|
|
// 11/30/94 JMA Adapted to new style conventions //
|
|
// 12/04/94 JMA Moved Message under Receiver, merged with message.hpp //
|
|
// 12/06/94 JMA Made DefaultData publicly visible //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved //
|
|
// PROPRIETARY AND CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#if !defined(RECEIVER_HPP)
|
|
# define RECEIVER_HPP
|
|
|
|
# if !defined(NODE_HPP)
|
|
# include <node.hpp>
|
|
# endif
|
|
|
|
# if !defined(CHAIN_HPP)
|
|
# include <chain.hpp>
|
|
# endif
|
|
|
|
# if !defined(MEMBLOCK_HPP)
|
|
# include <memblock.hpp>
|
|
# endif
|
|
|
|
# if !defined(MEMSTRM_HPP)
|
|
# include <memstrm.hpp>
|
|
# endif
|
|
|
|
class Receiver__SharedData;
|
|
class Receiver__InheritanceSet;
|
|
struct Receiver__HandlerEntry;
|
|
class Receiver__MessageHandlerSet;
|
|
class Receiver__Message;
|
|
class Receiver__DynamicMessage;
|
|
class Derivation;
|
|
class Event;
|
|
class DynamicMemoryStream;
|
|
class MessageTap;
|
|
|
|
//##########################################################################
|
|
//########################## Receiver ################################
|
|
//##########################################################################
|
|
//
|
|
// It is suggested that calls to methods meant to be serviced by a receiver
|
|
// be built through inline functions in the derived class, rather than
|
|
// having to build the parameter block in the scope of the caller. Letting
|
|
// the inline code build the parameter block is much cleaner, and allows the
|
|
// message code numbers to be held inside the derived class, further
|
|
// protecting against calling methods for objects not in a proper derivation
|
|
// chain.
|
|
//
|
|
class Receiver:
|
|
public Node
|
|
{
|
|
//##########################################################################
|
|
// Shared Data Support
|
|
//
|
|
public:
|
|
typedef Receiver__SharedData SharedData;
|
|
SharedData*
|
|
GetSharedData() const;
|
|
|
|
static Derivation ClassDerivations;
|
|
Derivation*
|
|
GetDerivation() const;
|
|
|
|
static SharedData DefaultData;
|
|
|
|
Logical
|
|
IsDerivedFrom(Derivation& parent) const;
|
|
Logical
|
|
IsDerivedFrom(const char* parent) const;
|
|
|
|
protected:
|
|
const SharedData* sharedData;
|
|
|
|
//##########################################################################
|
|
// Construction and Destruction Support
|
|
//
|
|
protected:
|
|
Receiver(
|
|
ClassID class_ID,
|
|
SharedData &shared_data
|
|
):
|
|
Node(class_ID),
|
|
sharedData(&shared_data)
|
|
{}
|
|
|
|
Receiver(
|
|
PlugStream *stream,
|
|
SharedData &shared_data
|
|
):
|
|
Node(stream),
|
|
sharedData(&shared_data)
|
|
{}
|
|
|
|
//##########################################################################
|
|
// Messaging Support
|
|
//
|
|
public:
|
|
typedef Receiver__Message Message;
|
|
typedef Receiver__DynamicMessage DynamicMessage;
|
|
typedef Receiver__InheritanceSet InheritanceSet;
|
|
typedef Receiver__HandlerEntry HandlerEntry;
|
|
typedef Receiver__MessageHandlerSet MessageHandlerSet;
|
|
typedef void (Receiver::*Handler)(const Message*);
|
|
typedef Enumeration MessageID;
|
|
|
|
enum {
|
|
AnyMessageID=0,
|
|
WatcherChangedMessageID,
|
|
LoadResourceFinishedMessageID,
|
|
NextMessageID
|
|
};
|
|
|
|
static const Handler NullHandler;
|
|
|
|
void
|
|
Receive(Message *What);
|
|
|
|
virtual void
|
|
Dispatch(Message *What)
|
|
{Receive(What);}
|
|
|
|
void
|
|
DefaultMessageHandler(Message*);
|
|
|
|
typedef void (Receiver::*ScanCallback)(
|
|
Receiver::Message *message,
|
|
Receiver *receiver
|
|
);
|
|
|
|
MessageTap*
|
|
MakeMessageTap(
|
|
Derivation *derivation,
|
|
ScanCallback callback
|
|
);
|
|
MessageTap*
|
|
MakeMessageTap(
|
|
Derivation *derivation,
|
|
ScanCallback callback,
|
|
Receiver::MessageID matching_message,
|
|
Receiver *match_receiver
|
|
);
|
|
|
|
protected:
|
|
static const HandlerEntry
|
|
MessageHandlerEntries[];
|
|
static MessageHandlerSet
|
|
MessageHandlers;
|
|
|
|
//##########################################################################
|
|
// Event Support
|
|
//
|
|
public:
|
|
virtual void
|
|
Receive(Event *event);
|
|
|
|
void
|
|
FlushEvents(int max_priority=-1);
|
|
void
|
|
FlushMatchingEvents(
|
|
MessageID target_message,
|
|
int max_priority=-1
|
|
);
|
|
|
|
void
|
|
ProcessDeferredQueue();
|
|
|
|
//##########################################################################
|
|
// Test Support
|
|
//
|
|
public:
|
|
static Logical
|
|
TestClass();
|
|
Logical
|
|
TestInstance() const;
|
|
};
|
|
|
|
//##########################################################################
|
|
//###################### Receiver::Message ###########################
|
|
//##########################################################################
|
|
|
|
class Receiver__Message
|
|
{
|
|
public:
|
|
#if defined(USE_SIGNATURE)
|
|
friend int
|
|
Is_Signature_Bad(const volatile Receiver__Message *);
|
|
#endif
|
|
|
|
size_t
|
|
messageLength;
|
|
Receiver::MessageID
|
|
messageID;
|
|
|
|
enum {
|
|
ReliableBit,
|
|
NextBit
|
|
};
|
|
|
|
enum {
|
|
ReliableFlag = 1 << ReliableBit
|
|
};
|
|
|
|
LWord
|
|
messageFlags;
|
|
|
|
Receiver__Message(
|
|
Receiver::MessageID id,
|
|
size_t message_length
|
|
):
|
|
messageID(id),
|
|
messageLength(message_length),
|
|
messageFlags(ReliableFlag) // HACK
|
|
{}
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
};
|
|
|
|
//##########################################################################
|
|
//################### Receiver::DynamicMessage #######################
|
|
//##########################################################################
|
|
|
|
class Receiver__DynamicMessage:
|
|
public DynamicMemoryStream
|
|
{
|
|
public:
|
|
Receiver__DynamicMessage()
|
|
{}
|
|
Receiver__DynamicMessage(
|
|
void *stream_start,
|
|
size_t stream_size,
|
|
size_t initial_offset=0
|
|
):
|
|
DynamicMemoryStream(stream_start, stream_size, initial_offset)
|
|
{}
|
|
Receiver__DynamicMessage(
|
|
Receiver::MessageID message_ID,
|
|
size_t size = sizeof(Receiver::Message)
|
|
);
|
|
|
|
Receiver::Message*
|
|
GetMessagePointer()
|
|
{Check(this); return Cast_Object(Receiver::Message*, streamStart);}
|
|
|
|
protected:
|
|
MemoryStream&
|
|
WriteBytes(
|
|
const void *ptr,
|
|
size_t number_of_bytes
|
|
);
|
|
};
|
|
|
|
//##########################################################################
|
|
//#################### ReceiverDataMessageOf #########################
|
|
//##########################################################################
|
|
|
|
template <class T> class ReceiverDataMessageOf:
|
|
public Receiver::Message
|
|
{
|
|
public:
|
|
T
|
|
dataContents;
|
|
|
|
ReceiverDataMessageOf(
|
|
Receiver::MessageID id,
|
|
size_t message_length,
|
|
const T& data
|
|
):
|
|
Receiver::Message(id, message_length),
|
|
dataContents(data)
|
|
{}
|
|
};
|
|
|
|
//##########################################################################
|
|
//######################### MessageTap ###############################
|
|
//##########################################################################
|
|
|
|
class MessageTap:
|
|
public Plug
|
|
{
|
|
//##########################################################################
|
|
// MessageTap Functionality
|
|
//
|
|
public:
|
|
MessageTap(
|
|
Derivation *derivation,
|
|
Receiver *client,
|
|
Receiver::ScanCallback callback
|
|
);
|
|
MessageTap(
|
|
Derivation *derivation,
|
|
Receiver *client,
|
|
Receiver::ScanCallback callback,
|
|
Receiver::MessageID matching_message,
|
|
Receiver *match_receiver
|
|
);
|
|
|
|
private:
|
|
Receiver::ScanCallback scanCallback;
|
|
Receiver* clientReceiver;
|
|
Receiver* matchingReceiver;
|
|
Receiver::MessageID matchingMessageID;
|
|
|
|
public:
|
|
void
|
|
Scan(
|
|
Receiver *receiver,
|
|
Receiver::Message *message
|
|
);
|
|
|
|
//##########################################################################
|
|
// Memory Allocation
|
|
//
|
|
private:
|
|
static MemoryBlock AllocatedMemory;
|
|
|
|
public:
|
|
void*
|
|
operator new(size_t)
|
|
{return AllocatedMemory.New();}
|
|
void
|
|
operator delete(void *where)
|
|
{AllocatedMemory.Delete(where);}
|
|
|
|
//##########################################################################
|
|
// Test support
|
|
//
|
|
public:
|
|
Logical
|
|
TestInstance() const;
|
|
static Logical
|
|
TestClass();
|
|
};
|
|
|
|
//##########################################################################
|
|
//################## Receiver::InheritanceSet ########################
|
|
//##########################################################################
|
|
//
|
|
// NOTE: An InheritanceSet generated for a class should only be inherited by
|
|
// other classes derived from that base class. If this is not done,
|
|
// SEVERE run-time weirdness will happen
|
|
//
|
|
class Receiver__InheritanceSet SIGNATURED
|
|
{
|
|
public:
|
|
Logical
|
|
TestInstance() const;
|
|
Enumeration
|
|
GetEntryCount()
|
|
{Check(this); return entryCount;}
|
|
|
|
protected:
|
|
Enumeration
|
|
entryCount;
|
|
|
|
Receiver__InheritanceSet()
|
|
{}
|
|
~Receiver__InheritanceSet()
|
|
{}
|
|
};
|
|
|
|
//##########################################################################
|
|
//################### Receiver::HandlerEntry #########################
|
|
//##########################################################################
|
|
|
|
struct Receiver__HandlerEntry
|
|
{
|
|
Enumeration
|
|
entryID;
|
|
const char*
|
|
entryName;
|
|
Receiver::Handler
|
|
entryHandler;
|
|
};
|
|
|
|
#define MESSAGE_ENTRY(class,message)\
|
|
{\
|
|
class::message##MessageID,\
|
|
#message,\
|
|
(Receiver::Handler)&class::message##MessageHandler\
|
|
}
|
|
|
|
//##########################################################################
|
|
//################# Receiver::MessageHandlerSet ######################
|
|
//##########################################################################
|
|
|
|
class Receiver__MessageHandlerSet:
|
|
public Receiver__InheritanceSet
|
|
{
|
|
//##########################################################################
|
|
// Constructors and Destructors
|
|
//
|
|
public:
|
|
Receiver__MessageHandlerSet(
|
|
Receiver::MessageID count,
|
|
const Receiver::HandlerEntry handler_table[],
|
|
const Receiver::MessageHandlerSet &inheritance
|
|
)
|
|
{Build(count, handler_table, &inheritance);}
|
|
Receiver__MessageHandlerSet(
|
|
Receiver::MessageID count,
|
|
const Receiver::HandlerEntry handler_table[]
|
|
)
|
|
{Build(count, handler_table, NULL);}
|
|
Receiver__MessageHandlerSet()
|
|
{messageHandlers = NULL; entryCount = 0;}
|
|
~Receiver__MessageHandlerSet();
|
|
|
|
protected:
|
|
void
|
|
Build(
|
|
Receiver::MessageID count,
|
|
const Receiver::HandlerEntry handler_table[],
|
|
const Receiver::MessageHandlerSet *inheritance
|
|
);
|
|
|
|
//##########################################################################
|
|
// HandlerSet Functionality
|
|
//
|
|
public:
|
|
static const Receiver::MessageHandlerSet
|
|
NullSet;
|
|
|
|
Receiver::Handler
|
|
Find(Receiver::MessageID message) const
|
|
{
|
|
Check(this);
|
|
Verify(message > 0);
|
|
return (message<=entryCount)
|
|
? messageHandlers[message-1].entryHandler
|
|
: Receiver::NullHandler;
|
|
}
|
|
const Receiver::HandlerEntry*
|
|
Find(const char* name) const;
|
|
|
|
const char *
|
|
GetName(Receiver::MessageID message) const
|
|
{
|
|
Check(this);
|
|
return (message<=entryCount)
|
|
? messageHandlers[message-1].entryName
|
|
: NULL;
|
|
}
|
|
|
|
protected:
|
|
Receiver::HandlerEntry* messageHandlers;
|
|
|
|
//##########################################################################
|
|
// Test Support
|
|
//
|
|
public:
|
|
static Logical
|
|
TestClass();
|
|
};
|
|
|
|
//##########################################################################
|
|
//########################## Derivation ##############################
|
|
//##########################################################################
|
|
|
|
class Derivation:
|
|
public Node
|
|
{
|
|
friend class Receiver;
|
|
|
|
//##########################################################################
|
|
// Construction and Destruction
|
|
//
|
|
public:
|
|
Derivation(char *who);
|
|
Derivation(Derivation& parent,char *who);
|
|
|
|
char *className;
|
|
|
|
//##########################################################################
|
|
// Messagetap support
|
|
//
|
|
private:
|
|
Derivation(Derivation& copy);
|
|
ChainOf<MessageTap*>
|
|
activeTaps;
|
|
|
|
public:
|
|
void
|
|
AppendMessageTap(MessageTap* tap);
|
|
Logical
|
|
IsDescendedFrom(Derivation& parent);
|
|
Logical
|
|
IsDescendedFrom(const char* parent);
|
|
|
|
//##########################################################################
|
|
// Inheritance Registration Support
|
|
//
|
|
private:
|
|
ChainOf<Derivation*>
|
|
classDerivations;
|
|
|
|
void
|
|
AppendDerivation(Derivation* child)
|
|
{Check(this); classDerivations.Add(child);}
|
|
|
|
//##########################################################################
|
|
// Test Support
|
|
//
|
|
public:
|
|
static Logical
|
|
TestClass();
|
|
};
|
|
|
|
//##########################################################################
|
|
//################### Receiver::SharedData ##########################
|
|
//##########################################################################
|
|
|
|
class Receiver__SharedData SIGNATURED
|
|
{
|
|
public:
|
|
Receiver__SharedData(
|
|
Derivation& derivation,
|
|
Receiver::MessageHandlerSet &handler
|
|
):
|
|
derivedClasses(&derivation),
|
|
activeMessageHandlers(&handler)
|
|
{}
|
|
|
|
Derivation
|
|
*derivedClasses;
|
|
Receiver::MessageHandlerSet
|
|
*activeMessageHandlers;
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
};
|
|
|
|
inline Receiver::SharedData*
|
|
Receiver::GetSharedData() const
|
|
{Check(this); return Cast_Object(SharedData*,sharedData);}
|
|
|
|
inline Derivation*
|
|
Receiver::GetDerivation() const
|
|
{Check(this); return GetSharedData()->derivedClasses;}
|
|
|
|
inline Logical
|
|
Receiver::IsDerivedFrom(Derivation& parent) const
|
|
{return sharedData->derivedClasses->IsDescendedFrom(parent);}
|
|
|
|
inline Logical
|
|
Receiver::IsDerivedFrom(const char* parent) const
|
|
{Check(this); return GetDerivation()->IsDescendedFrom(parent);}
|
|
|
|
inline MessageTap*
|
|
Receiver::MakeMessageTap(
|
|
Derivation *derivation,
|
|
ScanCallback callback
|
|
)
|
|
{Check(this); return new MessageTap(derivation, this, callback);}
|
|
|
|
inline MessageTap*
|
|
Receiver::MakeMessageTap(
|
|
Derivation *derivation,
|
|
ScanCallback callback,
|
|
Receiver::MessageID matching_message,
|
|
Receiver *match_receiver
|
|
)
|
|
{
|
|
Check(this);
|
|
return new MessageTap(
|
|
derivation,
|
|
this,
|
|
callback,
|
|
matching_message,
|
|
match_receiver
|
|
);
|
|
}
|
|
#endif
|
|
|