| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer - Red Alert *
- * *
- * File Name : CCDDE.CPP *
- * *
- * Programmer : Steve Tall *
- * *
- * Start Date : 10/04/95 *
- * *
- * Last Update : August 5th, 1996 [ST] *
- * *
- *---------------------------------------------------------------------------------------------*
- * Overview: *
- * C&C's interface to the DDE class *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * Functions: *
- * DDE_Callback -- DDE server callback function *
- * DDEServerClass::DDEServerClass -- class constructor *
- * DDEServerClass::Enable -- Enables the DDE callback *
- * DDEServerClass::Disable -- Disables the DDE callback *
- * DDEServerClass::~DDEServerClass -- class destructor *
- * DDESC::Callback -- callback function. Called from the DDE_Callback wrapper function *
- * DDESC::Get_MPlayer_Game_Info -- returns a pointer to the multiplayer setup info from wchat *
- * DDESC::Delete_MPlayer_Game_Info -- clears out multi player game setup info *
- * DDESC::Time_Since_Heartbeat -- returns the time in ticks since the last heartbeat from wchat*
- * *
- * Send_Data_To_DDE_Server -- sends a packet to WChat *
- * *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #ifdef WIN32
- #include <WINDOWS.H>
- #include "ccdde.h"
- #include <stdio.h>
- #include <timer.h>
- DDEServerClass DDEServer; //Instance of the DDE Server class
- Instance_Class *DDE_Class = NULL; // pointer for client callback
- // this *must* be called DDE_Class
- BOOL RA95AlreadyRunning = FALSE; //Was there an instance of Red Alert 95 already running when we started?
- /*
- ** Misc externs so we dont have to include FUNCTION.H
- */
- extern HWND MainWindow;
- extern TimerClass GameTimer;
- extern BOOL GameTimerInUse;
- extern void WWDebugString (char *string);
- /***********************************************************************************************
- * DDE_Callback -- DDE server callback function *
- * *
- * Just acts as a wrapper for the DDEServerClass callback function *
- * *
- * INPUT: ptr to data from client *
- * length of data *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 6/8/96 3:19PM ST : Created *
- *=============================================================================================*/
- BOOL CALLBACK DDE_Callback (unsigned char *data, long length)
- {
- return (DDEServer.Callback(data, length));
- }
- /***********************************************************************************************
- * DDEServerClass::DDEServerClass -- class constructor *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 6/8/96 3:20PM ST : Created *
- *=============================================================================================*/
- DDEServerClass::DDEServerClass(void)
- {
- MPlayerGameInfo = NULL; //Flag that we havnt received a start game info packet yet
- //DDE_Class = new Instance_Class ("CONQUER", "WCHAT");
- DDE_Class = new Instance_Class ("REDALERT", "WCHAT");
- DDE_Class->Enable_Callback( TRUE );
- IsEnabled = TRUE;
- if (DDE_Class->Test_Server_Running(DDE_Class->local_name)){
- RA95AlreadyRunning = TRUE;
- }else{
- DDE_Class->Register_Server( DDE_Callback );
- }
- }
- /***********************************************************************************************
- * DDEServerClass::Enable -- Enables the DDE callback *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/5/96 9:44PM ST : Created *
- *=============================================================================================*/
- void DDEServerClass::Enable(void)
- {
- if (!IsEnabled){
- DDE_Class->Enable_Callback( TRUE );
- IsEnabled = TRUE;
- }
- }
- /***********************************************************************************************
- * DDEServerClass::Disable -- Disables the DDE callback *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/5/96 9:44PM ST : Created *
- *=============================================================================================*/
- void DDEServerClass::Disable(void)
- {
- if (IsEnabled){
- DDE_Class->Enable_Callback( FALSE );
- IsEnabled = FALSE;
- }
- }
- /***********************************************************************************************
- * DDEServerClass::~DDEServerClass -- class destructor *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 6/8/96 3:20PM ST : Created *
- *=============================================================================================*/
- DDEServerClass::~DDEServerClass(void)
- {
- Delete_MPlayer_Game_Info();
- delete( DDE_Class );
- }
- /***********************************************************************************************
- * DDESC::Callback -- callback function. Called from the DDE_Callback wrapper function *
- * *
- * *
- * *
- * INPUT: data from DDE client *
- * length of data *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: Data has length and type as first 2 ints *
- * *
- * HISTORY: *
- * 6/8/96 3:21PM ST : Created *
- *=============================================================================================*/
- BOOL DDEServerClass::Callback(unsigned char *data, long length)
- {
- /*
- ** If the packet length < 0 then this is a special advisory packet
- */
- if ( length<0 ) {
- switch( length ) {
- case DDE_ADVISE_CONNECT:
- WWDebugString("RA95 - DDE advisory: client connect detected.");
- return TRUE;
- case DDE_ADVISE_DISCONNECT:
- WWDebugString("RA95 - DDE advisory: client disconnect detected.");
- return TRUE;
- default:
- WWDebugString("RA95 - DDE advisory: Unknown DDE advise type.");
- return FALSE;
- }
- }else{
- /*
- ** Packet must be at least the length of the packet type & size fields to be valid
- */
- if (length < 2*sizeof(int)) {
- WWDebugString ("RA95 - Received invalid packet.");
- return (FALSE);
- }
- /*
- ** Find out what kind of packet this is and its length.
- */
- int *packet_pointer = (int *)data;
- int actual_length = ntohl(*packet_pointer++);
- int packet_type = ntohl(*packet_pointer++);
- /*
- ** Strip the ID int from the start of the packet
- */
- data += 2*sizeof (int);
- length -= 2*sizeof (int);
- actual_length -= 2*sizeof (int);
- /*
- ** Take the appropriate action for the packet type
- */
- switch ( packet_type ){
- /*
- ** This is a packet with the info required for starting a new internet game. This is really
- * just C&CSPAWN.INI sent from WChat instead of read from disk.
- */
- case DDE_PACKET_START_MPLAYER_GAME:
- WWDebugString("RA95 - Received start game packet.");
- Delete_MPlayer_Game_Info();
- MPlayerGameInfo = new char [actual_length + 1];
- memcpy (MPlayerGameInfo, data, actual_length);
- *(MPlayerGameInfo + actual_length) = 0; //Terminator in case we treat it as a string
- MPlayerGameInfoLength = actual_length;
- LastHeartbeat = 0;
- break;
- case DDE_TICKLE:
- WWDebugString("RA95 - Received 'tickle' packet.");
- //SetForegroundWindow ( MainWindow );
- //ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
- break;
- case DDE_PACKET_HEART_BEAT:
- WWDebugString("RA95 - Received heart beat packet.");
- if (GameTimerInUse){
- LastHeartbeat = GameTimer.Time();
- }else{
- LastHeartbeat = 0;
- }
- break;
- default:
- WWDebugString("RA95 - Received unrecognised packet.");
- break;
- }
- }
- return (TRUE);
- }
- /***********************************************************************************************
- * DDESC::Get_MPlayer_Game_Info -- returns a pointer to the multiplayer setup info from wchat *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: ptr to data in .INI file format *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 6/8/96 3:23PM ST : Created *
- *=============================================================================================*/
- char *DDEServerClass::Get_MPlayer_Game_Info (void)
- {
- return (MPlayerGameInfo);
- }
- /***********************************************************************************************
- * DDESC::Delete_MPlayer_Game_Info -- clears out multi player game setup info *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 6/8/96 3:24PM ST : Created *
- *=============================================================================================*/
- void DDEServerClass::Delete_MPlayer_Game_Info(void)
- {
- if (MPlayerGameInfo){
- delete [] MPlayerGameInfo;
- MPlayerGameInfo = NULL;
- }
- }
- /***********************************************************************************************
- * DDESC::Time_Since_Heartbeat -- returns the time in ticks since the last heartbeat from wchat*
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: time since heartbeat *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 6/9/96 11:05PM ST : Created *
- *=============================================================================================*/
- int DDEServerClass::Time_Since_Heartbeat(void)
- {
- return (GameTimer.Time() - LastHeartbeat);
- }
- /***********************************************************************************************
- * Send_Data_To_DDE_Server -- sends a packet to WChat *
- * *
- * *
- * *
- * INPUT: ptr to the data to send *
- * length of data *
- * packet type identifier *
- * *
- * OUTPUT: true if packet successfully sent *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 6/9/96 11:07PM ST : Created *
- *=============================================================================================*/
- BOOL Send_Data_To_DDE_Server (char *data, int length, int packet_type)
- {
- if( DDE_Class->Open_Poke_Connection(DDE_Class->remote_name) == FALSE) {
- WWDebugString("RA95 - Failed to connect for POKE!");
- return (FALSE);
- }
- char *poke_data = new char [length + 2*sizeof(int)];
- int *poke_data_int = (int*)poke_data;
- *poke_data_int = htonl (length + 2*sizeof(int));
- *(poke_data_int+1)= htonl (packet_type);
- memcpy (poke_data + 8, data, length);
- if(DDE_Class->Poke_Server( (LPBYTE) poke_data, ntohl(*poke_data_int) ) == FALSE) {
- WWDebugString("RA95 - POKE failed!\n");
- DDE_Class->Close_Poke_Connection(); // close down the link
- delete poke_data;
- return (FALSE);
- }
- DDE_Class->Close_Poke_Connection(); // close down the link
- delete poke_data;
- return (TRUE);
- }
- #endif //WIN32
|