CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

NULLMGR.CPP (89979B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\nullmgr.cpv   1.10   16 Oct 1995 16:51:52   JOE_BOSTIC  $ */
     17 /***************************************************************************
     18  **   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        **
     19  ***************************************************************************
     20  *                                                                         *
     21  *                 Project Name : Command & Conquer                        *
     22  *                                                                         *
     23  *                    File Name : NULLMGR.CPP                              *
     24  *                                                                         *
     25  *                   Programmer : Bill Randolph                            *
     26  *                                                                         *
     27  *                   Start Date : April 5, 1995       	 						*
     28  *                                                                         *
     29  *                  Last Update : May 1, 1995 [BRR]                        *
     30  *                                                                         *
     31  *-------------------------------------------------------------------------*
     32  * Functions:    			                                                   *
     33  *   NullModemClass::NullModemClass -- class constructor                   *
     34  *   NullModemClass::~NullModemClass -- class destructor                   *
     35  *   NullModemClass::Init -- initialization											*
     36  *   NullModemClass::Send_Message -- sends a message								*
     37  *   NullModemClass::Get_Message -- polls the Queue for a message				*
     38  *   NullModemClass::Service -- main polling routine								*
     39  *   NullModemClass::Num_Send -- Returns # of unACK'd send entries			*
     40  *   NullModemClass::Num_Receive -- Returns # entries in the receive queue *
     41  *   NullModemClass::Response_Time -- Returns Queue's avg response time    *
     42  *   NullModemClass::Reset_Response_Time -- Resets response time computatio*
     43  *   NullModemClass::Oldest_Send -- Returns ptr to oldest unACK'd send buf *
     44  *   NullModemClass::Detect_Modem -- Detects and initializes the modem     *
     45  *   NullModemClass::Dial_Modem -- dials a number passed                   *
     46  *   NullModemClass::Answer_Modem -- waits for call and answers            *
     47  *   NullModemClass::Hangup_Modem -- hangs up the modem                    *
     48  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     49 
     50 #include "function.h"
     51 #include "wincomm.h"
     52 #include "modemreg.h"
     53 //#include "i86.h"
     54 #include "tcpip.h"
     55 
     56 //PG_TO_FIX
     57 #if (0)
     58 
     59 extern ModemRegistryEntryClass *ModemRegistry;
     60 
     61 // the following line was taken from Greenleaf's <ibmkeys.h> <asciidef.h>
     62 // because of other define conflicts
     63 
     64 #define ESC		         27
     65 #define NOKEY           0xffff
     66 #define INIT_COMMAND_RETRIES	2
     67 
     68 // this time is in milliseconds
     69 
     70 #define DEFAULT_TIMEOUT			2000
     71 
     72 //
     73 // the following is for a fix around a greenleaf bug
     74 // where they do not check for the value of abortkey
     75 // to determine whether or not they call the abort modem function.
     76 //
     77 extern "C" {
     78 	extern void (*_AbortModemFunctionPtr)(int);
     79 }
     80 
     81 static void (*NullModemClass::OrigAbortModemFunc)(int);
     82 
     83 static KeyNumType NullModemClass::Input;
     84 static GadgetClass *NullModemClass::Commands;		// button list
     85 
     86 /*
     87 ** Ugly hack: this string stores the string received from the modem
     88 */
     89 char ModemRXString[80];
     90 
     91 /***************************************************************************
     92  * NullModemClass::NullModemClass -- class constructor                     *
     93  *                                                                         *
     94  * INPUT:                                                                  *
     95  *		numsend			# desired entries for the send queue						*
     96  *		numreceive		# desired entries for the receive queue					*
     97  *		maxlen			application's max packet length								*
     98  *		magicnum			application-specific magic # (so we don't 				*
     99  *							accidentally end up talking to another one of our own	*
    100  *							products using the same protocol)							*
    101  *                                                                         *
    102  * OUTPUT:                                                                 *
    103  *		none.																						*
    104  *                                                                         *
    105  * WARNINGS:                                                               *
    106  *		none.																						*
    107  *                                                                         *
    108  * HISTORY:                                                                *
    109  *   12/20/1994 BR : Created.                                              *
    110  *=========================================================================*/
    111 NullModemClass::NullModemClass (int numsend, int numreceive, int maxlen,
    112 	unsigned short magicnum) : ConnManClass()
    113 {
    114 	/*------------------------------------------------------------------------
    115 	Init Port to NULL; we haven't opened Greenleaf yet.
    116 	------------------------------------------------------------------------*/
    117 	PortHandle = NULL;
    118 	Connection = NULL;
    119 
    120 	NumSend = numsend;
    121 	NumReceive = numreceive;
    122 	MaxLen = maxlen;
    123 	MagicNum = magicnum;
    124 
    125 	RXBuf = 0;
    126 	BuildBuf = 0;
    127 
    128 	EchoSize = 500;
    129 	EchoBuf = 0;
    130 
    131 	OldIRQPri = -1;
    132 
    133 	ModemVerboseOn = false;					// default true
    134 	ModemEchoOn = false;						// default true
    135 	ModemWaitCarrier = 50000;				// default 50 * 1000ms = 50 secs
    136 	ModemCarrierDetect = 600;				// default 6  * 100ms  = .6 secs
    137 	ModemCarrierLoss = 1400;				// default 14 * 100ms  = 1.4 secs
    138 	ModemHangupDelay = 20000;				// default 20 * 1000ms = 20 secs
    139 	ModemGuardTime = 1000;					// default 50 * 20ms   = 1 sec
    140 	ModemEscapeCode = '+';					// default ASCII 43
    141 
    142 	SendOverflows = 0;
    143 	ReceiveOverflows = 0;
    144 	CRCErrors = 0;
    145 
    146 	NumConnections = 0;
    147 
    148 	/*........................................................................
    149 	Init timing parameters
    150 	........................................................................*/
    151 	RetryDelta = 60;		// 60 ticks between retries
    152 	MaxRetries = -1;		// disregard # retries
    153 	Timeout = 1200;		// report bad connection after 20 seconds
    154 
    155 }	/* end of NullModemClass */
    156 
    157 
    158 /***************************************************************************
    159  * NullModemClass::~NullModemClass -- class destructor                     *
    160  *                                                                         *
    161  * INPUT:                                                                  *
    162  *		none.																						*
    163  *                                                                         *
    164  * OUTPUT:                                                                 *
    165  *		none.																						*
    166  *                                                                         *
    167  * WARNINGS:                                                               *
    168  *		none.																						*
    169  *                                                                         *
    170  * HISTORY:                                                                *
    171  *   12/20/1994 BR : Created.                                              *
    172  *=========================================================================*/
    173 NullModemClass::~NullModemClass ()
    174 {
    175 	Delete_Connection();
    176 }	/* end of ~NullModemClass */
    177 
    178 
    179 /***************************************************************************
    180  * NullModemClass::Init -- initialization												*
    181  *                                                                         *
    182  * INPUT:                                                                  *
    183  *		port				address  															*
    184  *		irq				2-15     															*
    185  *		baud				300, 1200, 9600, etc												*
    186  *		parity			'O' (odd), 'E' (even), 'N' (none), 'S' (space),			*
    187  *							'M' (mark)															*
    188  *		wordlength		5, 6, 7, or 8														*
    189  *		stopbits			1 or 2																*
    190  *                                                                         *
    191  * OUTPUT:                                                                 *
    192  *		1 = OK, 0 = error																		*
    193  *                                                                         *
    194  * WARNINGS:                                                               *
    195  *		none.																						*
    196  *                                                                         *
    197  * HISTORY:                                                                *
    198  *   12/20/1994 BR : Created.                                              *
    199  *=========================================================================*/
    200 //int NullModemClass::Init (int port, int irq, int baud, char parity, int wordlen, int stopbits)
    201 #pragma off (unreferenced)
    202 int NullModemClass::Init (int port, int ,char *dev_name, int baud, char parity, int wordlen, int stopbits, int flowcontrol)
    203 {
    204 	int com;
    205 	//int irqnum;
    206 	//int address;
    207 	//int status;
    208 
    209 
    210 	if (PortHandle) {
    211 		CloseHandle(PortHandle);
    212 		PortHandle = NULL;
    213 	}
    214 
    215 	if (!Connection){
    216 		/*------------------------------------------------------------------------
    217 		Init our Connection
    218 		------------------------------------------------------------------------*/
    219 		Connection = new NullModemConnClass (NumSend, NumReceive, MaxLen,
    220 			MagicNum);
    221 
    222 		Connection->Set_Retry_Delta (RetryDelta);
    223 		Connection->Set_Max_Retries (MaxRetries);
    224 		Connection->Set_TimeOut (Timeout);
    225 
    226 		/*------------------------------------------------------------------------
    227 		Allocate our packet parsing buffer; make it the same # of packets as the
    228 		# of receive queue entries the application has requested.  Use the
    229 		"Actual" maximum packet size, given from the connection; this allows for
    230 		both headers that get added to the packet.
    231 		------------------------------------------------------------------------*/
    232 		RXSize = Connection->Actual_Max_Packet() * NumReceive;
    233 		RXBuf = new char [RXSize];
    234 
    235 		BuildBuf = new char [MaxLen];
    236 
    237 		EchoBuf = new char [ EchoSize ];
    238 	}
    239 
    240 	RXCount = 0;
    241 	EchoCount = 0;
    242 
    243 
    244 	/*------------------------------------------------------------------------
    245 	This call allocates all necessary queue buffers
    246 	------------------------------------------------------------------------*/
    247 	switch (port) {
    248 		case 0x3f8:
    249 			com = COM1;
    250 			break;
    251 
    252 		case 0x2f8:
    253 			com = COM2;
    254 			break;
    255 
    256 		case 0x3e8:
    257 			com = COM3;
    258 			break;
    259 
    260 		case 0x2e8:
    261 			com = COM4;
    262 			break;
    263 
    264 		default:
    265 			com = COM5;
    266 			break;
    267 	}
    268 
    269 	int	i;
    270 
    271 	/*
    272 	** Create a new modem class for our com port
    273 	*/
    274 	if (!SerialPort) {
    275 		SerialPort = new WinModemClass;
    276 	}
    277 
    278 	/*
    279 	** Shift up the baud rate to sensible values
    280 	*/
    281 //	if (baud == 14400) baud = 19200;
    282 //	if (baud == 28800) baud = 38400;
    283 
    284 	static char com_ids[9][5]={
    285 		"COM1",
    286 		"COM2",
    287 		"COM3",
    288 		"COM4",
    289 		"COM5",
    290 		"COM6",
    291 		"COM7",
    292 		"COM8",
    293 		"COM9"
    294 	};
    295 
    296 	char *device;
    297 
    298 	switch ( port ) {
    299 
    300 		case 0x3f8:
    301 			device = com_ids[0];
    302 			break;
    303 
    304 		case 0x2f8:
    305 			device = com_ids[1];
    306 			break;
    307 
    308 		case 0x3e8:
    309 			device = com_ids[2];
    310 			break;
    311 
    312 		case 0x2e8:
    313 			device = com_ids[3];
    314 			break;
    315 
    316 		case 1:
    317 			/*
    318 			** 1 is a special value. It means use the device name not the port address.
    319 			*/
    320 			device = dev_name;
    321 
    322 			/*
    323 			** If we can match a registry entry with the device name then use that, otherwise use
    324 			** the device name directly to open the port with.
    325 			*/
    326 			if (ModemRegistry){
    327 				delete ModemRegistry;
    328 				ModemRegistry = NULL;
    329 			}
    330 			for ( i=0 ; i<10 ; i++ ){
    331 				ModemRegistry = new ModemRegistryEntryClass (i);
    332 				if (ModemRegistry->Get_Modem_Name()){
    333 					if (!strcmp (dev_name, ModemRegistry->Get_Modem_Name() )){
    334 						device = ModemRegistry->Get_Modem_Device_Name();
    335 						break;
    336 					}
    337 				}
    338 				delete ModemRegistry;
    339 				ModemRegistry = NULL;
    340 			}
    341 			break;
    342 
    343 		default:
    344 			device = NULL;
    345 	}
    346 
    347 	/*
    348 	** Open the com port
    349 	*/
    350 	PortHandle = SerialPort->Serial_Port_Open (device, baud, parity, wordlen, stopbits, flowcontrol);
    351 	if (PortHandle == INVALID_HANDLE_VALUE) {
    352 		Shutdown();
    353 		return(false);
    354 	}
    355 
    356 	/*------------------------------------------------------------------------
    357 	Init the Connection
    358 	------------------------------------------------------------------------*/
    359 	Connection->Init(PortHandle);
    360 
    361 	NumConnections = 1;
    362 
    363 	return(true);
    364 }
    365 
    366 
    367 /***********************************************************************************************
    368  * NMC::Num_Connections -- returns NumConnections member                                       *
    369  *                                                                                             *
    370  *                                                                                             *
    371  *                                                                                             *
    372  * INPUT:    Nothing                                                                           *
    373  *                                                                                             *
    374  * OUTPUT:   NumConnections                                                                    *
    375  *                                                                                             *
    376  * WARNINGS: None                                                                              *
    377  *                                                                                             *
    378  * HISTORY:                                                                                    *
    379  *    8/2/96 11:44AM ST : Documented / Win32 support                                           *
    380  *=============================================================================================*/
    381 int NullModemClass::Num_Connections( void )
    382 {
    383 	return(NumConnections);
    384 }
    385 
    386 
    387 
    388 /***********************************************************************************************
    389  * NMC::Delete_Connection -- removes the connection                                            *
    390  *                                                                                             *
    391  *                                                                                             *
    392  *                                                                                             *
    393  * INPUT:    Nothing                                                                           *
    394  *                                                                                             *
    395  * OUTPUT:   true                                                                              *
    396  *                                                                                             *
    397  * WARNINGS: None                                                                              *
    398  *                                                                                             *
    399  * HISTORY:                                                                                    *
    400  *    8/2/96 11:44AM ST : Documented / Win32 support                                           *
    401  *=============================================================================================*/
    402 int NullModemClass::Delete_Connection( void )
    403 {
    404 	if (Connection) {
    405 		delete Connection;
    406 		Connection = NULL;
    407 	}
    408 
    409 	if (RXBuf) {
    410 		delete [] RXBuf;
    411 		RXBuf = NULL;
    412 	}
    413 
    414 	if (BuildBuf) {
    415 		delete [] BuildBuf;
    416 		BuildBuf = NULL;
    417 	}
    418 
    419 	if (EchoBuf) {
    420 		delete [] EchoBuf;
    421 		EchoBuf = NULL;
    422 	}
    423 
    424 	NumConnections = 0;
    425 
    426 	return( true );
    427 }	/* end of Delete_Connection */
    428 
    429 
    430 /***********************************************************************************************
    431  * NMC::Init_Send_Queue -- Initialises the connections send queue                              *
    432  *                                                                                             *
    433  *                                                                                             *
    434  *                                                                                             *
    435  * INPUT:    Nothing                                                                           *
    436  *                                                                                             *
    437  * OUTPUT:   true                                                                              *
    438  *                                                                                             *
    439  * WARNINGS: None                                                                              *
    440  *                                                                                             *
    441  * HISTORY:                                                                                    *
    442  *    8/2/96 11:46AM ST : Documented / Win32 support                                           *
    443  *=============================================================================================*/
    444 int NullModemClass::Init_Send_Queue( void )
    445 {
    446 
    447 	/*---------------------------------------------------------------
    448 	Init the send queue
    449 	-----------------------------------------------------------------*/
    450 	if ( Connection ) {
    451 		Connection->Queue->Init_Send_Queue();
    452 	}
    453 
    454 	return(true);
    455 }
    456 
    457 
    458 //DetectPortType NullModemClass::Detect_Port( SerialSettingsType *settings )
    459 /***********************************************************************************************
    460  * NMC::Detect_Port -- Checks that the specified com port exists                               *
    461  *                                                                                             *
    462  *                                                                                             *
    463  *                                                                                             *
    464  * INPUT:    ptr to SerialSettingsType                                                         *
    465  *                                                                                             *
    466  * OUTPUT:   true if port is valid                                                             *
    467  *                                                                                             *
    468  * HISTORY:                                                                                    *
    469  *    8/2/96 11:47AM ST : Documented / Win32 support                                           *
    470  *=============================================================================================*/
    471 DetectPortType NullModemClass::Detect_Port( SerialSettingsType *settings)
    472 {
    473 
    474 	static char com_ids[9][5]={
    475 		"COM1",
    476 		"COM2",
    477 		"COM3",
    478 		"COM4",
    479 		"COM5",
    480 		"COM6",
    481 		"COM7",
    482 		"COM8",
    483 		"COM9"
    484 	};
    485 
    486 	int	i;
    487 
    488 	/*
    489 	** Create a new modem class for our com port
    490 	*/
    491 	if (!SerialPort) {
    492 		SerialPort = new WinModemClass;
    493 	}else{
    494 		SerialPort->Serial_Port_Close();
    495 	}
    496 
    497 	/*
    498 	** Shift up the baud rate to sensible values
    499 	*/
    500 	int baud = settings->Baud;
    501 //	if (baud == 14400) baud = 19200;
    502 //	if (baud == 28800) baud = 38400;
    503 
    504 
    505 	/*
    506 	** Translate the port address into a usable device name
    507 	*/
    508 	char *device;
    509 
    510 	switch ( settings->Port ) {
    511 
    512 		case 0x3f8:
    513 			device = com_ids[0];
    514 			break;
    515 
    516 		case 0x2f8:
    517 			device = com_ids[1];
    518 			break;
    519 
    520 		case 0x3e8:
    521 			device = com_ids[2];
    522 			break;
    523 
    524 		case 0x2e8:
    525 			device = com_ids[3];
    526 			break;
    527 
    528 		case 1:
    529 			/*
    530 			** 1 is a special value. It means use the device name not the port address.
    531 			*/
    532 			device = settings->ModemName;
    533 
    534 			/*
    535 			** If we can match a registry entry with the device name then use that, otherwise use
    536 			** the device name directly to open the port with.
    537 			*/
    538 			if (ModemRegistry){
    539 				delete ModemRegistry;
    540 				ModemRegistry = NULL;
    541 			}
    542 			for ( i=0 ; i<10 ; i++){
    543 				ModemRegistry = new ModemRegistryEntryClass (i);
    544 				if (ModemRegistry->Get_Modem_Name()){
    545 					if (!strcmp (device, ModemRegistry->Get_Modem_Name() )){
    546 						/*
    547 						** Got a match. Break out leaving the registry info intact.
    548 						*/
    549 						device = ModemRegistry->Get_Modem_Device_Name();
    550 						break;
    551 					}
    552 				}
    553 				delete ModemRegistry;
    554 				ModemRegistry = NULL;
    555 			}
    556 			break;
    557 
    558 		default:
    559 			return (PORT_INVALID);
    560 	}
    561 
    562 	/*
    563 	** Open the com port
    564 	*/
    565 	HANDLE porthandle = SerialPort->Serial_Port_Open (device, baud, 0, 8, 1, settings->HardwareFlowControl);
    566 
    567 	if (porthandle == INVALID_HANDLE_VALUE){
    568 		return (PORT_INVALID);
    569 	}
    570 
    571 	SerialPort->Serial_Port_Close();
    572 	return (PORT_VALID);
    573 
    574 }
    575 
    576 
    577 
    578 
    579 /***********************************************************************************************
    580  * NullModemClass::ShutDown -- Closes serial port and removes the connection                   *
    581  *                                                                                             *
    582  *                                                                                             *
    583  *                                                                                             *
    584  * INPUT:    Nothing                                                                           *
    585  *                                                                                             *
    586  * OUTPUT:   Nothing                                                                           *
    587  *                                                                                             *
    588  * WARNINGS: None                                                                              *
    589  *                                                                                             *
    590  * HISTORY:                                                                                    *
    591  *    8/2/96 11:43AM ST : Documented / Win32 support                                           *
    592  *=============================================================================================*/
    593 void NullModemClass::Shutdown ( void )
    594 {
    595 	if (PortHandle && SerialPort) {
    596 		SerialPort->Serial_Port_Close();
    597 		delete SerialPort;
    598 		SerialPort = NULL;
    599 		PortHandle = NULL;
    600 		Delete_Connection();
    601 	}
    602 
    603 #ifdef FORCE_WINSOCK
    604 	if (Winsock.Get_Connected()){
    605 		Delete_Connection();
    606 	}
    607 #endif
    608 
    609 }	/* end of Shutdown */
    610 
    611 
    612 /***************************************************************************
    613  * NullModemClass::Set_Timing -- sets timing for all connections				*
    614  *                                                                         *
    615  * This will set the timing parameters.  This allows an application to		*
    616  * measure the Response_Time while running, and adjust timing accordingly.	*
    617  *                                                                         *
    618  * INPUT:                                                                  *
    619  *		retrydelta	value to set for retry delta 										*
    620  *		maxretries	value to set for max # retries									*
    621  *		timeout		value to set for connection timeout								*
    622  *                                                                         *
    623  * OUTPUT:                                                                 *
    624  *		none.																						*
    625  *                                                                         *
    626  * WARNINGS:                                                               *
    627  *		none.																						*
    628  *                                                                         *
    629  * HISTORY:                                                                *
    630  *   08/07/1995 DRD : Created.                                             *
    631  *=========================================================================*/
    632 void NullModemClass::Set_Timing (unsigned long retrydelta,
    633 	unsigned long maxretries, unsigned long timeout)
    634 {
    635 	RetryDelta = retrydelta;
    636 	MaxRetries = maxretries;
    637 	Timeout = timeout;
    638 
    639 	Connection->Set_Retry_Delta (RetryDelta);
    640 	Connection->Set_Max_Retries (MaxRetries);
    641 	Connection->Set_TimeOut (Timeout);
    642 
    643 }	/* end of Set_Timing */
    644 
    645 
    646 /***************************************************************************
    647  * NullModemClass::Send_Message -- sends a message									*
    648  *                                                                         *
    649  * For clarity's sake, here's what happens to the buffer passed in:			*
    650  * - It gets passed to the Connection's Send_Packet() routine					*
    651  * - The CommHeaderType header gets tacked onto it									*
    652  * - The resulting buffer gets added to the Connection's Send Queue			*
    653  * - When Service() determines that it needs to send the data, it				*
    654  *   copies the entire packet (CommHeaderType and all) into its local 		*
    655  *   SendBuf, adds the packet start ID, length, and CRC, then sends it out.*
    656  *                                                                         *
    657  * The ack_req argument will almost always be '1' (the default).  The only	*
    658  * reason to use 0 is if you don't know whether the other system is			*
    659  * ready or not, so you have to periodically send out a query packet,		*
    660  * and wait for a response.  (Using the connection's built-in retry			*
    661  * system would just blast out useless data if the other system isn't		*
    662  * even there.)																				*
    663  *                                                                         *
    664  * INPUT:                                                                  *
    665  *		buf			buffer to send															*
    666  *		buflen		length of buffer														*
    667  *		ack_req		1 = ACK is required; 0 = not										*
    668  *                                                                         *
    669  * OUTPUT:                                                                 *
    670  *		1 = OK; 0 = error																		*
    671  *                                                                         *
    672  * WARNINGS:                                                               *
    673  *		none.																						*
    674  *                                                                         *
    675  * HISTORY:                                                                *
    676  *   12/20/1994 BR : Created.                                              *
    677  *=========================================================================*/
    678 int NullModemClass::Send_Message (void *buf, int buflen, int ack_req)
    679 {
    680 	int rc;
    681 
    682 	if (NumConnections == 0) {
    683 		return( false );
    684 	}
    685 
    686 	rc = Connection->Send_Packet(buf,buflen,ack_req);
    687 	if (!rc)
    688 		SendOverflows++;
    689 
    690 	return(rc);
    691 
    692 }	/* end of Send_Message */
    693 
    694 
    695 /***************************************************************************
    696  * NullModemClass::Get_Message -- polls the Queue for a message				*
    697  *                                                                         *
    698  * INPUT:                                                                  *
    699  *		buf			buffer to store message in											*
    700  *		buflen		ptr filled in with length of message							*
    701  *                                                                         *
    702  * OUTPUT:                                                                 *
    703  *		1 = message was received; 0 = wasn't											*
    704  *                                                                         *
    705  * WARNINGS:                                                               *
    706  *		none.																						*
    707  *                                                                         *
    708  * HISTORY:                                                                *
    709  *   12/20/1994 BR : Created.                                              *
    710  *=========================================================================*/
    711 int NullModemClass::Get_Message (void *buf, int *buflen)
    712 {
    713 	if (NumConnections == 0) {
    714 		return( false );
    715 	}
    716 	return( Connection->Get_Packet( buf, buflen ) );
    717 }
    718 
    719 
    720 /***************************************************************************
    721  * NullModemClass::Service -- main polling routine									*
    722  *                                                                         *
    723  * INPUT:                                                                  *
    724  *		none.																						*
    725  *                                                                         *
    726  * OUTPUT:                                                                 *
    727  *		1 = OK, 0 = connection has gone bad												*
    728  *                                                                         *
    729  * WARNINGS:                                                               *
    730  *		none.																						*
    731  *                                                                         *
    732  * HISTORY:                                                                *
    733  *   12/20/1994 BR : Created.                                              *
    734  *=========================================================================*/
    735 int NullModemClass::Service (void)
    736 {
    737 	int pos;				// current position in RXBuf
    738 	int i;				// loop counter
    739 	//int status;
    740 	unsigned short length;
    741 	SerialHeaderType *header;	// decoded packet start, length
    742 	SerialCRCType *crc;			// decoded packet CRC
    743 	char moredata = 0;
    744 
    745 	if (NumConnections == 0) {
    746 		return( false );
    747 	}
    748 
    749 	/*------------------------------------------------------------------------
    750 	First, copy all the bytes we can from the Greenleaf RX buffer to our
    751 	own buffer.
    752 	------------------------------------------------------------------------*/
    753 	RXCount += SerialPort->Read_From_Serial_Port((unsigned char*)(RXBuf + RXCount), int(RXSize - RXCount) );
    754 
    755 //	if (RXCount){
    756 //char port[128];
    757 //sprintf (port, "C&C95 - RXCount = %d bytes.\n", RXCount);
    758 //CCDebugString (port);
    759 //	}
    760 
    761 BOOL enabled = FALSE;
    762 
    763 #if (0)
    764 if (SerialPort->FramingErrors ||
    765 	SerialPort->IOErrors ||
    766 	SerialPort->InBufferOverflows ||
    767 	SerialPort->BufferOverruns ||
    768 	SerialPort->InBufferOverflows ||
    769 	SerialPort->OutBufferOverflows){
    770 
    771 
    772 if (!MonoClass::Is_Enabled()) {
    773 MonoClass::Enable();
    774 enabled = TRUE;
    775 }
    776 Special.IsMonoEnabled = TRUE;
    777 Debug_Smart_Print = TRUE;
    778 Mono_Set_Cursor(0,0);
    779 Smart_Printf( "            In Queue: %5d  \n", SerialPort->InQueue);
    780 Smart_Printf( "           Out Queue: %5d  \n", SerialPort->OutQueue);
    781 Smart_Printf( "      Framing errors: %5d  \n", SerialPort->FramingErrors);
    782 Smart_Printf( "           IO errors: %5d  \n", SerialPort->IOErrors);
    783 Smart_Printf( "       Parity Errors: %5d  \n", SerialPort->InBufferOverflows);
    784 Smart_Printf( "     Buffer overruns: %5d  \n", SerialPort->BufferOverruns);
    785 Smart_Printf( " In buffer overflows: %5d  \n", SerialPort->InBufferOverflows);
    786 Smart_Printf( "Out buffer overflows: %5d  \n", SerialPort->OutBufferOverflows);
    787 
    788 MonoClass::Disable();
    789 Debug_Smart_Print = FALSE;
    790 }
    791 #endif	//(0)
    792 
    793 	// minimum packet size
    794 
    795 	if ( RXCount < (PACKET_SERIAL_OVERHEAD_SIZE + 1) ) {
    796 		return( Connection->Service() );
    797 	}
    798 
    799 	/*------------------------------------------------------------------------
    800 	Now scan the buffer for the start of a packet.
    801 	------------------------------------------------------------------------*/
    802 	pos = -1;
    803 	for (i = 0; i <= RXCount - sizeof( short ); i++) {
    804 		if ( *((unsigned short *)(RXBuf + i)) == PACKET_SERIAL_START ) {
    805 			pos = i;
    806 			break;
    807 		}
    808 	}
    809 
    810 	/*------------------------------------------------------------------------
    811 	No start code was found; throw away all bytes except the last few, and
    812 	return.
    813 	------------------------------------------------------------------------*/
    814 	if (pos==-1) {
    815 // Smart_Printf( "No magic number found \n" );
    816 		/*.....................................................................
    817 		move the remaining, un-checked bytes to the start of the buffer
    818 		.....................................................................*/
    819 		memmove (RXBuf, RXBuf + i, sizeof( short ) - 1);
    820 		RXCount = sizeof( short ) - 1;
    821 		return( Connection->Service() );
    822 	}
    823 
    824 	/*........................................................................
    825 	Check to see if there are enough bytes for the header to be decoded
    826 	........................................................................*/
    827 	if ( (RXCount - pos) < sizeof( SerialHeaderType ) ) {
    828 		memmove (RXBuf, RXBuf + pos, RXCount - pos);
    829 		RXCount -= pos;
    830 		return(Connection->Service());
    831 	}
    832 
    833 	/*------------------------------------------------------------------------
    834 	A start code was found; check the packet's length & CRC
    835 	------------------------------------------------------------------------*/
    836 	header = (SerialHeaderType *)(RXBuf + pos);
    837 
    838 	/*........................................................................
    839 	If we lost a byte in the length, we may end up waiting a very long time
    840 	for the buffer to get to the right length; check the verify value to
    841 	make sure this didn't happen.
    842 	........................................................................*/
    843 	if ( header->MagicNumber2 != PACKET_SERIAL_VERIFY ) {
    844 // Smart_Printf( "Verify failed\n");
    845 //		Hex_Dump_Data( (RXBuf + pos), PACKET_SERIAL_OVERHEAD_SIZE );
    846 
    847 		pos += sizeof ( short );		// throw away the bogus start code
    848 		memmove (RXBuf, RXBuf + pos, RXCount - pos);
    849 		RXCount -= pos;
    850 		return(Connection->Service());
    851 	}
    852 
    853 	length = header->Length;
    854 
    855 	/*........................................................................
    856 	Special case: if the length comes out too long for us to process:
    857 	- Assume the packet is bad
    858 	- Throw away the bogus packet-start code
    859 	- Return;  we'll search for another packet-start code next time.
    860 	........................................................................*/
    861 	if (length > MaxLen) {
    862 #if (CONN_DEBUG)
    863 		printf( "length too lonnng\n" );
    864 #endif
    865 // Smart_Printf( "length too lonnng %d, max %d \n", length, MaxLen );
    866 
    867 		pos += sizeof ( short );		// throw away the bogus start code
    868 		memmove (RXBuf, RXBuf + pos, RXCount - pos);
    869 		RXCount -= pos;
    870 		return(Connection->Service());
    871 	}
    872 
    873 	/*........................................................................
    874 	If the entire packet isn't stored in our buffer, copy the remaining bytes
    875 	to the front of the buffer & return.
    876 	........................................................................*/
    877 	if ( (pos + length + PACKET_SERIAL_OVERHEAD_SIZE) > RXCount) {
    878 
    879 		if ( moredata ) {
    880 // Smart_Printf( "waiting for more data %d, pos = %d \n", ((length + PACKET_SERIAL_OVERHEAD_SIZE) - (RXCount - pos)), pos );
    881 		}
    882 
    883 		if (pos) {
    884 			memmove (RXBuf, RXBuf + pos, RXCount - pos);
    885 			RXCount -= pos;
    886 		}
    887 		return(Connection->Service());
    888 	}
    889 
    890 	/*........................................................................
    891 	Now grab the CRC value in the packet, & compare it to the CRC value
    892 	computed from the actual data.  If they don't match, throw away the bogus
    893 	start-code, move the rest to the front of the buffer, & return.
    894 	We'll continue parsing this data when we're called next time.
    895 	........................................................................*/
    896 	crc = (SerialCRCType *)(RXBuf + pos + sizeof( SerialHeaderType ) + length);
    897 	if (NullModemConnClass::Compute_CRC(RXBuf + pos +
    898 		sizeof( SerialHeaderType ), length) != crc->SerialCRC) {
    899 
    900 		CRCErrors++;
    901 
    902 #if (CONN_DEBUG)
    903 		printf( "CRC check failed\n" );
    904 #endif
    905 // Smart_Printf( "CRC check failed for packet of length %d \n", length );
    906 
    907 //		if (length < 100) {
    908 //			Hex_Dump_Data( (RXBuf + pos), (PACKET_SERIAL_OVERHEAD_SIZE + length) );
    909 //		}
    910 
    911 		pos += sizeof ( short );		// throw away the bogus start code
    912 		memmove (RXBuf, RXBuf + pos, RXCount - pos);
    913 		RXCount -= pos;
    914 		return(Connection->Service());
    915 	}
    916 
    917 	/*------------------------------------------------------------------------
    918 	Give the new packet to the Connection to process.
    919 	------------------------------------------------------------------------*/
    920 	if (!Connection->Receive_Packet(RXBuf + pos + sizeof( SerialHeaderType ), length)) {
    921 		ReceiveOverflows++;
    922 // Smart_Printf( "Received overflows %d \n", ReceiveOverflows );
    923 	}
    924 
    925 #if (0)
    926 	Hex_Dump_Data( (RXBuf + pos), (PACKET_SERIAL_OVERHEAD_SIZE + length) );
    927 #endif
    928 
    929 	/*------------------------------------------------------------------------
    930 	Move all data past this packet to the front of the buffer.
    931 	------------------------------------------------------------------------*/
    932 	pos += (PACKET_SERIAL_OVERHEAD_SIZE + length);
    933 	memmove (RXBuf, RXBuf + pos, RXCount - pos);
    934 	RXCount -= pos;
    935 
    936 	/*------------------------------------------------------------------------
    937 	Now, service the connection's Queue's; this will handle ACK & Retries.
    938 	------------------------------------------------------------------------*/
    939 	return(Connection->Service());
    940 
    941 }	/* end of Service */
    942 
    943 
    944 /***************************************************************************
    945  * NullModemClass::Num_Send -- Returns # of unACK'd send entries				*
    946  *                                                                         *
    947  * INPUT:                                                                  *
    948  *                                                                         *
    949  * OUTPUT:                                                                 *
    950  *                                                                         *
    951  * WARNINGS:                                                               *
    952  *                                                                         *
    953  * HISTORY:                                                                *
    954  *   05/01/1995 BRR : Created.                                             *
    955  *=========================================================================*/
    956 int NullModemClass::Num_Send(void)
    957 {
    958 	if (Connection)
    959 		return( Connection->Queue->Num_Send() );
    960 	else
    961 		return (0);
    962 
    963 }	/* end of Num_Send */
    964 
    965 
    966 /***************************************************************************
    967  * NullModemClass::Num_Receive -- Returns # entries in the receive queue   *
    968  *                                                                         *
    969  * INPUT:                                                                  *
    970  *                                                                         *
    971  * OUTPUT:                                                                 *
    972  *                                                                         *
    973  * WARNINGS:                                                               *
    974  *                                                                         *
    975  * HISTORY:                                                                *
    976  *   05/01/1995 BRR : Created.                                             *
    977  *=========================================================================*/
    978 int NullModemClass::Num_Receive(void)
    979 {
    980 	if (Connection)
    981 		return( Connection->Queue->Num_Receive() );
    982 	else
    983 		return (0);
    984 
    985 }	/* end of Num_Receive */
    986 
    987 
    988 /***************************************************************************
    989  * NullModemClass::Response_Time -- Returns Queue's avg response time      *
    990  *                                                                         *
    991  * INPUT:                                                                  *
    992  *                                                                         *
    993  * OUTPUT:                                                                 *
    994  *                                                                         *
    995  * WARNINGS:                                                               *
    996  *                                                                         *
    997  * HISTORY:                                                                *
    998  *   05/01/1995 BRR : Created.                                             *
    999  *=========================================================================*/
   1000 unsigned long NullModemClass::Response_Time(void)
   1001 {
   1002 	if (Connection)
   1003 		return( Connection->Queue->Avg_Response_Time() );
   1004 	else
   1005 		return (0);
   1006 
   1007 }	/* end of Response_Time */
   1008 
   1009 
   1010 /***************************************************************************
   1011  * NullModemClass::Reset_Response_Time -- Resets response time computation *
   1012  *                                                                         *
   1013  * INPUT:                                                                  *
   1014  *                                                                         *
   1015  * OUTPUT:                                                                 *
   1016  *                                                                         *
   1017  * WARNINGS:                                                               *
   1018  *                                                                         *
   1019  * HISTORY:                                                                *
   1020  *   05/01/1995 BRR : Created.                                             *
   1021  *=========================================================================*/
   1022 void NullModemClass::Reset_Response_Time(void)
   1023 {
   1024 	if (Connection)
   1025 		Connection->Queue->Reset_Response_Time();
   1026 
   1027 }	/* end of Reset_Response_Time */
   1028 
   1029 
   1030 /***************************************************************************
   1031  * Oldest_Send -- Returns ptr to oldest unACK'd send buffer                *
   1032  *                                                                         *
   1033  * INPUT:                                                                  *
   1034  *                                                                         *
   1035  * OUTPUT:                                                                 *
   1036  *                                                                         *
   1037  * WARNINGS:                                                               *
   1038  *                                                                         *
   1039  * HISTORY:                                                                *
   1040  *   05/01/1995 BRR : Created.                                             *
   1041  *=========================================================================*/
   1042 void * NullModemClass::Oldest_Send(void)
   1043 {
   1044 	int i;
   1045 	SendQueueType *send_entry;				// ptr to send entry header
   1046 	CommHeaderType *packet;
   1047 	void *buf = NULL;
   1048 
   1049 	for (i = 0; i < Connection->Queue->Num_Send(); i++) {
   1050 		send_entry = Connection->Queue->Get_Send(i);
   1051 		if (send_entry) {
   1052 			packet = (CommHeaderType *)send_entry->Buffer;
   1053 			if (packet->Code == ConnectionClass::PACKET_DATA_ACK && send_entry->IsACK == 0) {
   1054 				buf = send_entry->Buffer;
   1055 				break;
   1056 			}
   1057 		}
   1058 	}
   1059 
   1060 	return(buf);
   1061 
   1062 }	/* end of Oldest_Send */
   1063 
   1064 
   1065 /***************************************************************************
   1066  * NullModemClass::Configure_Debug -- sets up special debug values         *
   1067  *                                                                         *
   1068  * Mono_Debug_Print2() can look into a packet to pull out a particular		*
   1069  * ID, and can print both that ID and a string corresponding to				*
   1070  * that ID.  This routine configures these values so it can find				*
   1071  * and decode the ID.  This ID is used in addition to the normal				*
   1072  * CommHeaderType values.																	*
   1073  *                                                                         *
   1074  * INPUT:                                                                  *
   1075  *		index			connection index to configure (-1 = Global Channel)		*
   1076  *		offset		ID's byte offset into packet										*
   1077  *		size			size of ID, in bytes; 0 if none									*
   1078  *		names			ptr to array of names; use ID as an index into this		*
   1079  *		maxnames		max # in the names array; 0 if none.							*
   1080  *                                                                         *
   1081  * OUTPUT:                                                                 *
   1082  *		none.																						*
   1083  *                                                                         *
   1084  * WARNINGS:                                                               *
   1085  *		Names shouldn't be longer than 12 characters.								*
   1086  *                                                                         *
   1087  * HISTORY:                                                                *
   1088  *   05/31/1995 BRR : Created.                                             *
   1089  *=========================================================================*/
   1090 void NullModemClass::Configure_Debug(int , int offset, int size,
   1091 	char **names, int maxnames)
   1092 {
   1093 	if (Connection)
   1094 		Connection->Queue->Configure_Debug (offset, size, names, maxnames);
   1095 }
   1096 
   1097 
   1098 /***************************************************************************
   1099  * Mono_Debug_Print -- Debug output routine                                *
   1100  *                                                                         *
   1101  * INPUT:                                                                  *
   1102  *		refresh		1 = clear screen & completely refresh							*
   1103  *                                                                         *
   1104  * OUTPUT:                                                                 *
   1105  *		none.																						*
   1106  *                                                                         *
   1107  * WARNINGS:                                                               *
   1108  *		none.																						*
   1109  *                                                                         *
   1110  * HISTORY:                                                                *
   1111  *   05/02/1995 BRR : Created.                                             *
   1112  *=========================================================================*/
   1113 void NullModemClass::Mono_Debug_Print(int, int refresh)
   1114 {
   1115 	if (!Connection)
   1116 		return;
   1117 
   1118 	Connection->Queue->Mono_Debug_Print (refresh);
   1119 
   1120 	if (refresh) {
   1121 		Mono_Set_Cursor (31,1);
   1122 		Mono_Printf ("Serial Port Queues");
   1123 
   1124 		Mono_Set_Cursor (9,2);
   1125 		Mono_Printf ("Average Response Time:");
   1126 
   1127 		Mono_Set_Cursor (20,3);
   1128 		Mono_Printf ("CRC Errors:");
   1129 
   1130 		Mono_Set_Cursor (43,2);
   1131 		Mono_Printf ("Send Overflows:");
   1132 
   1133 		Mono_Set_Cursor (40,3);
   1134 		Mono_Printf ("Receive Overflows:");
   1135 	}
   1136 
   1137 	Mono_Set_Cursor (32,2);
   1138 	Mono_Printf ("%d  ", Connection->Queue->Avg_Response_Time());
   1139 
   1140 	Mono_Set_Cursor (32,3);
   1141 	Mono_Printf ("%d  ", CRCErrors);
   1142 
   1143 	Mono_Set_Cursor (59,2);
   1144 	Mono_Printf ("%d  ", SendOverflows);
   1145 
   1146 	Mono_Set_Cursor (59,3);
   1147 	Mono_Printf ("%d  ", ReceiveOverflows);
   1148 
   1149 	Mono_Set_Cursor (2,5);
   1150 	Mono_Printf ("%d  ", Num_Send());
   1151 
   1152 	Mono_Set_Cursor (41,5);
   1153 	Mono_Printf ("%d  ", Num_Receive());
   1154 
   1155 }	/* end of Mono_Debug_Print */
   1156 
   1157 
   1158 void Timer_Test (int line, char *file)
   1159 {
   1160 
   1161 	char abuffer [128];
   1162 
   1163 	sprintf (abuffer, "Testing timer at line %d in file %s", line, file);
   1164 	CCDebugString (abuffer);
   1165 
   1166 	CountDownTimerClass timer;
   1167 
   1168 	timer.Set (1);
   1169 
   1170 	while (timer.Time()){
   1171 		CCDebugString (".");
   1172 	}
   1173 
   1174 	CCDebugString ("OK\n");
   1175 }
   1176 
   1177 
   1178 
   1179 
   1180 /***************************************************************************
   1181  * NullModemClass::Detect_Modem -- Detects and initializes the modem       *
   1182  *                                                                         *
   1183  * INPUT:                                                                  *
   1184  *		settings		ptr to SerialSettings structure     							*
   1185  *                                                                         *
   1186  * OUTPUT:                                                                 *
   1187  *		-1				init string invalid													*
   1188  *		0				no modem found															*
   1189  *		1				modem found			  													*
   1190  *                                                                         *
   1191  * WARNINGS:                                                               *
   1192  *		none.																						*
   1193  *                                                                         *
   1194  * HISTORY:                                                                *
   1195  *   06/02/1995 DRD : Created.                                             *
   1196  *=========================================================================*/
   1197 int NullModemClass::Detect_Modem( SerialSettingsType *settings, bool reconnect )
   1198 {
   1199 	/*........................................................................
   1200 	Button Enumerations
   1201 	........................................................................*/
   1202 //	enum {
   1203 //		BUTTON_CANCEL = 100,
   1204 //	};
   1205 
   1206 	int status;
   1207 //	int modemstatus;
   1208 	int value;
   1209 	int error_count = 0;
   1210 
   1211 	int x,y,width,height;					// dialog dimensions
   1212 	char buffer[80*3];
   1213 
   1214 	int	factor = SeenBuff.Get_Width()/320;
   1215 
   1216 
   1217 
   1218 //Timer_Test(__LINE__, __FILE__);
   1219 
   1220 
   1221 	/*
   1222 	**	Determine the dimensions of the text to be used for the dialog box.
   1223 	**	These dimensions will control how the dialog box looks.
   1224 	*/
   1225 	strcpy( buffer, Text_String( TXT_INITIALIZING_MODEM ) );
   1226 
   1227 	Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
   1228 	Format_Window_String(buffer, SeenBuff.Get_Height(), width, height);
   1229 
   1230 	width = MAX(width, 50*factor);
   1231 	width += 40*factor;
   1232 	height += 60*factor;
   1233 
   1234 	x = (SeenBuff.Get_Width() - width) / 2;
   1235 	y = (SeenBuff.Get_Height() - height) / 2;
   1236 
   1237 	/*
   1238 	------------------------------- Initialize -------------------------------
   1239 	*/
   1240 	Set_Logic_Page(SeenBuff);
   1241 
   1242 	/*
   1243 	............................ Draw the dialog .............................
   1244 	*/
   1245 	Hide_Mouse();
   1246 	if ( !reconnect ) {
   1247 		Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   1248 		Blit_Hid_Page_To_Seen_Buff();
   1249 	}
   1250 
   1251 	Dialog_Box(x, y, width, height);
   1252 	Draw_Caption(TXT_NONE, x, y, width);
   1253 
   1254 	Fancy_Text_Print(buffer, x + 20*factor, y + 25*factor, CC_GREEN, TBLACK,
   1255 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1256 
   1257 	Show_Mouse();
   1258 
   1259 	HMWaitForOK( 0, NULL );
   1260 
   1261 
   1262 
   1263 
   1264 	/*
   1265 	** OK, lets not mess about any more. Just turn on echo, verbose, and result codes
   1266 	** before we even begin. At least this way when we get an error later on we have already
   1267 	** removed all the steps we use to try and recover.
   1268 	** The timeouts need to be quite small in case the modem is turned off.
   1269 	*/
   1270 
   1271 	/*
   1272 	** Turn on result codes.
   1273 	*/
   1274 	Send_Modem_Command ( "ATQ0", '\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2);
   1275 
   1276 	/*
   1277 	** Make result codes verbose.
   1278 	*/
   1279 	Send_Modem_Command ( "ATV1", '\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2);
   1280 
   1281 	/*
   1282 	** Turn on echo.
   1283 	*/
   1284 	Send_Modem_Command ( "ATE1", '\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2);
   1285 
   1286 	ModemVerboseOn = true;
   1287 	ModemEchoOn = true;
   1288 
   1289 
   1290 
   1291 	/*
   1292 	** Try sending a plain old AT command to the modem. Now that we have theoretically
   1293 	** turned on verbose result codes we should get an 'OK' back.
   1294 	**
   1295 	*/
   1296 	status = Send_Modem_Command( "AT", '\r', buffer, 81, DEFAULT_TIMEOUT, 2 );
   1297 
   1298 	if (status < ASSUCCESS) {
   1299 		/*
   1300 		** No 'OK' came back so return failure. We cant print an error message here because
   1301 		** the calling function may want to upshift the baud rate (eg from 14400 to 19200) and
   1302 		** try again.
   1303 		*/
   1304 		return (false);
   1305 	}
   1306 
   1307 	/*
   1308 	** Send the user supplied modem init string
   1309 	*/
   1310 	if (settings->InitStringIndex == -1) {
   1311 		status = Send_Modem_Command( "", '\r', buffer, 81, 300, 1 );
   1312 	} else {
   1313 		/*
   1314 		** Split up the init string into seperate strings if it contains one or more '|' characters.
   1315 		** This character acts as a carriage return/pause.
   1316 		*/
   1317 		char *istr = new char [2 + strlen( InitStrings [settings->InitStringIndex] )];
   1318 		char *tokenptr;
   1319 		strcpy (istr, InitStrings [settings->InitStringIndex] );
   1320 
   1321 		/*
   1322 		** Tokenise the string and send it in chunks
   1323 		*/
   1324 		tokenptr = strtok ( istr, "|" );
   1325 		while ( tokenptr ) {
   1326 
   1327 			status = Send_Modem_Command( tokenptr, '\r', buffer, 81, DEFAULT_TIMEOUT, 1 );
   1328 			/*
   1329 			** Handle error case.
   1330 			*/
   1331 			if (status < ASSUCCESS) {
   1332 				if (CCMessageBox().Process(TXT_ERROR_NO_INIT, TXT_IGNORE, TXT_CANCEL)) {
   1333 					delete istr;
   1334 					return( false );
   1335 				}
   1336 				error_count++;
   1337 				break;
   1338 			}
   1339 
   1340 			tokenptr = strtok ( NULL, "|");
   1341 
   1342 		}
   1343 	}
   1344 	/*
   1345 	** Use the settings from the registry to further initialise the modem
   1346 	*/
   1347 	if (settings->Port == 1 && ModemRegistry) {
   1348 		/*
   1349 		** Send the init strings from the registry if available
   1350 		*/
   1351 		char send_string[256] = {"AT"};
   1352 
   1353 		if (settings->HardwareFlowControl){
   1354 			/*
   1355 			** Send the init string for hardware flow control
   1356 			*/
   1357 			if (ModemRegistry->Get_Modem_Hardware_Flow_Control()) {
   1358 				strcpy (&send_string[2], ModemRegistry->Get_Modem_Hardware_Flow_Control());
   1359 				status = Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1);
   1360 				if (status != MODEM_CMD_OK && status != MODEM_CMD_0) {
   1361 					if (CCMessageBox().Process(TXT_NO_FLOW_CONTROL_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);
   1362 				}
   1363 			}
   1364 		}else{
   1365 			/*
   1366 			** Send the init string for no flow control
   1367 			*/
   1368 			if (ModemRegistry->Get_Modem_No_Flow_Control()) {
   1369 				strcpy (&send_string[2], ModemRegistry->Get_Modem_No_Flow_Control());
   1370 				status = Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1);
   1371 				if (status != MODEM_CMD_OK && status != MODEM_CMD_0) {
   1372 					if (CCMessageBox().Process(TXT_NO_FLOW_CONTROL_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);
   1373 				}
   1374 			}
   1375 		}
   1376 
   1377 
   1378 		/*
   1379 		** Send the string for data compresseion
   1380 		*/
   1381 		if (settings->Compression){
   1382 
   1383 			if (ModemRegistry->Get_Modem_Compression_Enable()) {
   1384 				strcpy (&send_string[2], ModemRegistry->Get_Modem_Compression_Enable());
   1385 				Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1);
   1386 				if (status != MODEM_CMD_OK && status != MODEM_CMD_0) {
   1387 					if (CCMessageBox().Process(TXT_NO_COMPRESSION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);
   1388 				}
   1389 			}
   1390 		}else{
   1391 
   1392 			if (ModemRegistry->Get_Modem_Compression_Disable()) {
   1393 				strcpy (&send_string[2], ModemRegistry->Get_Modem_Compression_Disable());
   1394 				Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1);
   1395 				if (status != MODEM_CMD_OK && status != MODEM_CMD_0) {
   1396 					if (CCMessageBox().Process(TXT_NO_COMPRESSION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);
   1397 				}
   1398 			}
   1399 		}
   1400 
   1401 
   1402 		/*
   1403 		** Send the string for error correction
   1404 		*/
   1405 		if (settings->ErrorCorrection){
   1406 
   1407 			if (ModemRegistry->Get_Modem_Error_Correction_Enable()) {
   1408 				strcpy (&send_string[2], ModemRegistry->Get_Modem_Error_Correction_Enable());
   1409 				Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1);
   1410 				if (status != MODEM_CMD_OK && status != MODEM_CMD_0) {
   1411 					if (CCMessageBox().Process(TXT_NO_ERROR_CORRECTION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);
   1412 				}
   1413 			}
   1414 		}else{
   1415 			if (ModemRegistry->Get_Modem_Error_Correction_Disable()) {
   1416 				strcpy (&send_string[2], ModemRegistry->Get_Modem_Error_Correction_Disable());
   1417 				Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1);
   1418 				if (status != MODEM_CMD_OK && status != MODEM_CMD_0) {
   1419 					if (CCMessageBox().Process(TXT_NO_ERROR_CORRECTION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false);
   1420 				}
   1421 			}
   1422 		}
   1423 
   1424 
   1425 	}
   1426 	/*
   1427 	** We require that auto-answer be disabled so turn it off now.
   1428 	*/
   1429 	status = Send_Modem_Command( "ATS0=0", '\r', buffer, 81, DEFAULT_TIMEOUT, INIT_COMMAND_RETRIES );
   1430 	if (status != MODEM_CMD_OK) {
   1431 		if (CCMessageBox().Process(TXT_ERROR_NO_DISABLE, TXT_IGNORE, TXT_CANCEL)) return( false );
   1432 		error_count++;
   1433 	}
   1434 
   1435 	/*
   1436 	** If we had an unreasonable number of ignored errors then return failure
   1437 	*/
   1438 	if (error_count >= 3) {
   1439 		CCMessageBox().Process(TXT_ERROR_TOO_MANY, TXT_OK);
   1440 		return (false);
   1441 	}
   1442 
   1443 	return( true );
   1444 }
   1445 
   1446 
   1447 /***************************************************************************
   1448  * NullModemClass::Dial_Modem -- dials a number passed                     *
   1449  *                                                                         *
   1450  * INPUT:                                                                  *
   1451  *		settings		ptr to SerialSettings structure     							*
   1452  *                                                                         *
   1453  * OUTPUT:                                                                 *
   1454  *		status		DialStatus																*
   1455  *                                                                         *
   1456  * WARNINGS:                                                               *
   1457  *		none.																						*
   1458  *                                                                         *
   1459  * HISTORY:                                                                *
   1460  *   06/02/1995 DRD : Created.                                             *
   1461  *=========================================================================*/
   1462 DialStatusType NullModemClass::Dial_Modem( char *string, DialMethodType method, bool reconnect )
   1463 {
   1464 
   1465 //Timer_Test(__LINE__, __FILE__);
   1466 
   1467 
   1468 	int factor = SeenBuff.Get_Width()/320;
   1469 
   1470 	/*........................................................................
   1471 	Button Enumerations
   1472 	........................................................................*/
   1473 	enum {
   1474 		BUTTON_CANCEL = 100,
   1475 	};
   1476 
   1477 	/*........................................................................
   1478 	Dialog variables
   1479 	........................................................................*/
   1480 	bool process = true;						// process while true
   1481 
   1482 	//int status;
   1483 	int delay;
   1484 	DialStatusType dialstatus;
   1485 
   1486 	int x,y,width,height;					// dialog dimensions
   1487 	char buffer[80*3];
   1488 
   1489 	Input = 0;
   1490 
   1491 
   1492 //Timer_Test(__LINE__, __FILE__);
   1493 
   1494 
   1495 	/*
   1496 	**	Determine the dimensions of the text to be used for the dialog box.
   1497 	**	These dimensions will control how the dialog box looks.
   1498 	*/
   1499 	if (reconnect) {
   1500 		strcpy( buffer, Text_String( TXT_MODEM_CONNERR_REDIALING ) );
   1501 	} else {
   1502 		strcpy( buffer, Text_String( TXT_DIALING ) );
   1503 	}
   1504 
   1505 
   1506 //Timer_Test(__LINE__, __FILE__);
   1507 
   1508 	Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
   1509 	Format_Window_String(buffer, SeenBuff.Get_Height(), width, height);
   1510 
   1511 	int text_width = width;
   1512 	width = MAX(width, 50*factor);
   1513 	width += 40*factor;
   1514 	height += 60*factor;
   1515 
   1516 	x = (SeenBuff.Get_Width() - width) / 2;
   1517 	y = (SeenBuff.Get_Height() - height) / 2;
   1518 
   1519 	TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
   1520 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   1521 		x + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8*factor)) >> 1),
   1522 		y + height - (FontHeight + FontYSpacing + 2*factor) - 5*factor);
   1523 
   1524 
   1525 //Timer_Test(__LINE__, __FILE__);
   1526 
   1527 
   1528 	/*
   1529 	------------------------------- Initialize -------------------------------
   1530 	*/
   1531 	Set_Logic_Page(SeenBuff);
   1532 
   1533 	/*
   1534 	............................ Create the list .............................
   1535 	*/
   1536 	Commands = &cancelbtn;
   1537 
   1538 
   1539 //Timer_Test(__LINE__, __FILE__);
   1540 
   1541 	Commands->Flag_List_To_Redraw();
   1542 
   1543 
   1544 //Timer_Test(__LINE__, __FILE__);
   1545 
   1546 
   1547 	/*
   1548 	............................ Draw the dialog .............................
   1549 	*/
   1550 	Hide_Mouse();
   1551 	if ( !reconnect ) {
   1552 		Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   1553 		Blit_Hid_Page_To_Seen_Buff();
   1554 	}
   1555 
   1556 
   1557 //Timer_Test(__LINE__, __FILE__);
   1558 
   1559 
   1560 
   1561 	Dialog_Box(x, y, width, height);
   1562 	Draw_Caption(TXT_NONE, x, y, width);
   1563 
   1564 
   1565 //Timer_Test(__LINE__, __FILE__);
   1566 
   1567 
   1568 	Fancy_Text_Print(buffer, SeenBuff.Get_Width()/2 - text_width/2, y + 25*factor, CC_GREEN, TBLACK,
   1569 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1570 
   1571 
   1572 //Timer_Test(__LINE__, __FILE__);
   1573 
   1574 
   1575 	CCDebugString ("C&C95 - About to draw buttons.\n");
   1576 	Commands->Draw_All();
   1577 	CCDebugString ("C&C95 - About to show mouse.\n");
   1578 	Show_Mouse();
   1579 
   1580 
   1581 //Timer_Test(__LINE__, __FILE__);
   1582 
   1583 	// start waiting
   1584 
   1585 	//CCDebugString ("C&C95 - About to delay for 2 seconds.\n");
   1586 	//Delay(120);
   1587 	//HMSetDialingMethod( Port, (int)method );
   1588 	CCDebugString ("C&C95 - About to set modem dial type.\n");
   1589 	SerialPort->Set_Modem_Dial_Type((WinCommDialMethodType) method);
   1590 
   1591 
   1592 //Timer_Test(__LINE__, __FILE__);
   1593 
   1594 	//Clear out any old modem result codes
   1595 	CCDebugString ("C&C95 - About to call 'Get_Modem_Result'.\n");
   1596 	SerialPort->Get_Modem_Result(60, buffer, 81);
   1597 	//status = HMDial( Port, string );
   1598 	CCDebugString ("C&C95 - About to call 'SerialPort->Dial_Modem'.\n");
   1599 	SerialPort->Dial_Modem(string);
   1600 
   1601 
   1602 //Timer_Test(__LINE__, __FILE__);
   1603 
   1604 
   1605 	//
   1606 	// Sets up the ability to abort modem commands when any input is in the
   1607 	// Keyboard buffer.  This also calls the game CallBack().
   1608 	//
   1609 	CCDebugString ("C&C95 - About to call 'Setup_Abort_Modem'.\n");
   1610 	Setup_Abort_Modem();
   1611 
   1612 
   1613 //Timer_Test(__LINE__, __FILE__);
   1614 
   1615 	/*
   1616 	-------------------------- Main Processing Loop --------------------------
   1617 	*/
   1618 	process = true;
   1619 	delay = ModemWaitCarrier;
   1620 	CCDebugString ("C&C95 - About to enter main process loop.\n");
   1621 	while (process) {
   1622 
   1623 
   1624 //Timer_Test(__LINE__, __FILE__);
   1625 
   1626 
   1627 		/*
   1628 		** If we have just received input focus again after running in the background then
   1629 		** we need to redraw.
   1630 		*/
   1631 		if (AllSurfaces.SurfacesRestored){
   1632 			CCDebugString ("C&C95 - About to restore video surfaces.\n");
   1633 			AllSurfaces.SurfacesRestored=FALSE;
   1634 			Commands->Draw_All();
   1635 		}
   1636 
   1637 //Timer_Test(__LINE__, __FILE__);
   1638 
   1639 
   1640 		//delay = HMInputLine( Port, delay, buffer, 81 );
   1641 		CCDebugString ("C&C95 - About to call 'Get_Modem_Result 2'.\n");
   1642 
   1643 
   1644 //Timer_Test(__LINE__, __FILE__);
   1645 
   1646 
   1647 		char abuffer [128];
   1648 		sprintf (abuffer, "C&C95 - ModemWaitCarrier delay = %d\n", delay);
   1649 		CCDebugString (abuffer);
   1650 		delay = SerialPort->Get_Modem_Result(delay, buffer, 81);
   1651 
   1652 
   1653 		/*
   1654 		............................ Process input ............................
   1655 		*/
   1656 		CCDebugString ("C&C95 - About to check for keyboard input.\n");
   1657 		if (!Input) Input = Commands->Input();
   1658 
   1659 
   1660 		switch (Input) {
   1661 			case (KN_ESC):
   1662 			case (BUTTON_CANCEL | KN_BUTTON):
   1663 				dialstatus = DIAL_CANCELED;
   1664 				process = false;
   1665 				break;
   1666 
   1667 			default:
   1668 				break;
   1669 		}
   1670 
   1671 		if (process) {
   1672 			if ( strncmp( buffer, "CON", 3 ) == 0 ) {
   1673 				memset (ModemRXString, 0, 80);
   1674 				strncpy (ModemRXString, buffer, 79);
   1675 				dialstatus = DIAL_CONNECTED;
   1676 				process = false;
   1677 			}
   1678 			else if ( strncmp( buffer, "BUSY", 4 ) == 0 ) {
   1679 				dialstatus = DIAL_BUSY;
   1680 				process = false;
   1681 			}
   1682 			else if ( strncmp( buffer, "NO C", 4 ) == 0 ) {
   1683 				dialstatus = DIAL_NO_CARRIER;
   1684 				process = false;
   1685 			}
   1686 			else if ( strncmp( buffer, "NO D", 4 ) == 0 ) {
   1687 				dialstatus = DIAL_NO_DIAL_TONE;
   1688 				process = false;
   1689 			}
   1690 			else if ( strncmp( buffer, "ERRO", 4 ) == 0 ) {
   1691 				dialstatus = DIAL_ERROR;
   1692 				process = false;
   1693 			}
   1694 		}
   1695 
   1696 		if (delay <= 0) {
   1697 			if (delay < 0) {
   1698 			}
   1699 			process = false;
   1700 		}
   1701 	}
   1702 
   1703 	Remove_Abort_Modem();
   1704 
   1705 	return( dialstatus );
   1706 
   1707 }	/* end of Dial_Modem */
   1708 
   1709 
   1710 /***************************************************************************
   1711  * NullModemClass::Answer_Modem -- waits for call and answers              *
   1712  *                                                                         *
   1713  * INPUT:                                                                  *
   1714  *		reconnect	whether this is to reconnect		     							*
   1715  *                                                                         *
   1716  * OUTPUT:                                                                 *
   1717  *		status		DialStatus																*
   1718  *                                                                         *
   1719  * WARNINGS:                                                               *
   1720  *		none.																						*
   1721  *                                                                         *
   1722  * HISTORY:                                                                *
   1723  *   06/02/1995 DRD : Created.                                             *
   1724  *=========================================================================*/
   1725 DialStatusType NullModemClass::Answer_Modem( bool reconnect )
   1726 {
   1727 	int factor 		= (SeenBuff.Get_Width() == 320) ? 1 : 2;
   1728 
   1729 	/*........................................................................
   1730 	Button Enumerations
   1731 	........................................................................*/
   1732 	enum {
   1733 		BUTTON_CANCEL = 100,
   1734 	};
   1735 
   1736 	/*........................................................................
   1737 	Redraw values: in order from "top" to "bottom" layer of the dialog
   1738 	........................................................................*/
   1739 	typedef enum {
   1740 		REDRAW_NONE = 0,
   1741 		REDRAW_BUTTONS,
   1742 		REDRAW_BACKGROUND,
   1743 		REDRAW_ALL = REDRAW_BACKGROUND
   1744 	} RedrawType;
   1745 
   1746 	/*........................................................................
   1747 	Dialog variables
   1748 	........................................................................*/
   1749 	RedrawType display = REDRAW_ALL;		// redraw level
   1750 	bool process = true;						// process while true
   1751 
   1752 	//int status;
   1753 	int delay;
   1754 	DialStatusType dialstatus;
   1755 	bool ring = false;
   1756 
   1757 	int x,y,width,height;					// dialog dimensions
   1758 	char text_buffer[80*3];
   1759 	char comm_buffer[80*3];
   1760 
   1761 	int text_width;
   1762 
   1763 	/*
   1764 	**	Determine the dimensions of the text to be used for the dialog box.
   1765 	**	These dimensions will control how the dialog box looks.
   1766 	*/
   1767 	if (reconnect) {
   1768 		strcpy( text_buffer, Text_String( TXT_MODEM_CONNERR_WAITING ) );
   1769 	} else {
   1770 		strcpy( text_buffer, Text_String( TXT_WAITING_FOR_CALL ) );
   1771 	}
   1772 
   1773 	Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
   1774 	Format_Window_String(text_buffer, SeenBuff.Get_Height(), width, height);
   1775 
   1776 	text_width = width;
   1777 	width = MAX(width, 50*factor);
   1778 	width += 40*factor;
   1779 	height += 60*factor;
   1780 
   1781 	x = (SeenBuff.Get_Width() - width) / 2;
   1782 	y = (SeenBuff.Get_Height() - height) / 2;
   1783 
   1784 	TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
   1785 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   1786 		x + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8*factor)) >> 1),
   1787 		y + height - (FontHeight + FontYSpacing + 2*factor) - 5*factor);
   1788 
   1789 	/*
   1790 	------------------------------- Initialize -------------------------------
   1791 	*/
   1792 	Set_Logic_Page(SeenBuff);
   1793 
   1794 	//Load_Picture("TITLE.CPS", HidPage, HidPage, Palette, BM_DEFAULT);
   1795 
   1796 	Input = 0;
   1797 
   1798 	/*
   1799 	............................ Create the list .............................
   1800 	*/
   1801 	Commands = &cancelbtn;
   1802 
   1803 	Commands->Flag_List_To_Redraw();
   1804 
   1805 	// start waiting
   1806 
   1807 
   1808 //	HMWaitForOK( 1000, NULL );
   1809 //	status = HMSendString( Port, "ATS0=1" );
   1810 
   1811 
   1812 	//
   1813 	// Sets up the ability to abort modem commands when any input is in the
   1814 	// Keyboard buffer.  This also calls the game CallBack() and Input().
   1815 	//
   1816 	Setup_Abort_Modem();
   1817 
   1818 	/*
   1819 	-------------------------- Main Processing Loop --------------------------
   1820 	*/
   1821 	process = true;
   1822 	delay = 60000;
   1823 	while (process) {
   1824 
   1825 		/*
   1826 		** If we have just received input focus again after running in the background then
   1827 		** we need to redraw.
   1828 		*/
   1829 		if (AllSurfaces.SurfacesRestored){
   1830 			AllSurfaces.SurfacesRestored=FALSE;
   1831 			display=REDRAW_ALL;
   1832 		}
   1833 
   1834 		/*
   1835 		...................... Refresh display if needed ......................
   1836 		*/
   1837 		if (display) {
   1838 			Hide_Mouse();
   1839 			if (display >= REDRAW_BACKGROUND) {
   1840 				/*
   1841 				..................... Refresh the backdrop ......................
   1842 				*/
   1843 				if ( !reconnect ) {
   1844 					Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   1845 					Blit_Hid_Page_To_Seen_Buff();
   1846 				}
   1847 				/*
   1848 				..................... Draw the background .......................
   1849 				*/
   1850 				Dialog_Box(x, y, width, height);
   1851 				/*
   1852 				....................... Draw the labels .........................
   1853 				*/
   1854 				Draw_Caption(TXT_NONE, x, y, width);
   1855 
   1856 				Fancy_Text_Print(text_buffer, SeenBuff.Get_Width()/2 - text_width/2, y + 25*factor, CC_GREEN, TBLACK,
   1857 					TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1858 
   1859 				Commands->Draw_All();
   1860 			}
   1861 			Show_Mouse();
   1862 			display = REDRAW_NONE;
   1863 		}
   1864 
   1865 		//delay = HMInputLine( Port, delay, buffer, 81 );
   1866 		delay = SerialPort->Get_Modem_Result(delay, comm_buffer, 81);
   1867 
   1868 		/*
   1869 		............................ Process input ............................
   1870 		*/
   1871 		if (!Input) Input = Commands->Input();
   1872 		switch (Input) {
   1873 			case (KN_ESC):
   1874 			case (BUTTON_CANCEL | KN_BUTTON):
   1875 //				Sound_Effect(VOC_BUTTON,255);
   1876 				dialstatus = DIAL_CANCELED;
   1877 				process = false;
   1878 				break;
   1879 
   1880 			default:
   1881 				break;
   1882 		}
   1883 
   1884 		if (process) {
   1885 			if ( strncmp( comm_buffer, "RING", 4 ) == 0 ) {
   1886 
   1887 				strcpy( text_buffer, Text_String( TXT_ANSWERING ) );
   1888 
   1889 				Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
   1890 				Format_Window_String(text_buffer, SeenBuff.Get_Height(), width, height);
   1891 
   1892 				text_width = width;
   1893 				width = MAX(width, 50*factor);
   1894 				width += 40*factor;
   1895 				height += 60*factor;
   1896 
   1897 				x = (SeenBuff.Get_Width() - width) / 2;
   1898 				y = (SeenBuff.Get_Height() - height) / 2;
   1899 
   1900 				//PortKillTime( Port, 100 );
   1901 
   1902 				//HMWaitForOK( 0, NULL );
   1903 				//status = HMAnswer( Port );
   1904 				SerialPort->Write_To_Serial_Port ((unsigned char*)"ATA\r", strlen("ATA\r"));
   1905 
   1906 				ring = true;
   1907 				delay = ModemWaitCarrier;
   1908 				display = REDRAW_ALL;
   1909 			}
   1910 			else if ( strncmp( comm_buffer, "CON", 3 ) == 0 ) {
   1911 				memset (ModemRXString, 0, 80);
   1912 				strncpy (ModemRXString, comm_buffer, 79);
   1913 				dialstatus = DIAL_CONNECTED;
   1914 				process = false;
   1915 			}
   1916 			else if ( strncmp( comm_buffer, "BUSY", 4 ) == 0 ) {
   1917 				dialstatus = DIAL_BUSY;
   1918 				process = false;
   1919 			}
   1920 			else if ( strncmp( comm_buffer, "NO C", 4 ) == 0 ) {
   1921 				dialstatus = DIAL_NO_CARRIER;
   1922 				process = false;
   1923 			}
   1924 			else if ( strncmp( comm_buffer, "NO D", 4 ) == 0 ) {
   1925 				dialstatus = DIAL_NO_DIAL_TONE;
   1926 				process = false;
   1927 			}
   1928 			else if ( strncmp( comm_buffer, "ERRO", 4 ) == 0 ) {
   1929 				dialstatus = DIAL_ERROR;
   1930 				CCMessageBox().Process ("Error - Modem returned error status.", TXT_OK);
   1931 				process = false;
   1932 			}
   1933 		}
   1934 
   1935 		if (delay <= 0) {
   1936 			if (ring) {
   1937 				if (SerialPort->Get_Modem_Status() & CD_SET){
   1938 					sprintf(ModemRXString, "%s", "Connected");
   1939 					dialstatus = DIAL_CONNECTED;
   1940 				}else{
   1941 					dialstatus = DIAL_ERROR;
   1942 					CCMessageBox().Process ("Error - TIme out waiting for connect.", TXT_OK);
   1943 				}
   1944 				process = false;
   1945 			} else {
   1946 				delay = 60000;
   1947 			}
   1948 		}
   1949 	}
   1950 
   1951 	Remove_Abort_Modem();
   1952 
   1953 	return( dialstatus );
   1954 
   1955 }	/* end of Answer_Modem */
   1956 
   1957 
   1958 /***************************************************************************
   1959  * NullModemClass::Hangup_Modem -- hangs up the modem                      *
   1960  *                                                                         *
   1961  * INPUT:                                                                  *
   1962  *		none																					  *
   1963  *                                                                         *
   1964  * OUTPUT:                                                                 *
   1965  *		status		successful or not													  *
   1966  *                                                                         *
   1967  * WARNINGS:                                                               *
   1968  *		none.																					  *
   1969  *                                                                         *
   1970  * HISTORY:                                                                *
   1971  *   06/02/1995 DRD : Created.                                             *
   1972  *=========================================================================*/
   1973 bool NullModemClass::Hangup_Modem( void )
   1974 {
   1975 	int status;
   1976 	int delay;
   1977 	char buffer[81];
   1978 	char escape[4];
   1979 
   1980 	/*
   1981 	**	Turn modem servicing off in the callback routine.
   1982 	*/
   1983 	ModemService = false;
   1984 
   1985 
   1986 	status = Send_Modem_Command( "AT", '\r', buffer, 81, DEFAULT_TIMEOUT, 1 );
   1987 
   1988 	if (status == MODEM_CMD_OK) {
   1989 		ModemService = true;
   1990 		return( true );
   1991 	}
   1992 
   1993 	SerialPort->Set_Serial_DTR(FALSE);
   1994 	Delay(3200/60);
   1995 	SerialPort->Set_Serial_DTR(TRUE);
   1996 
   1997 	//SetDtr( Port, 0 );
   1998 	//PortKillTime( Port, 3200 );
   1999 	//SetDtr( Port, 1 );
   2000 
   2001 	status = Send_Modem_Command( "AT", '\r', buffer, 81, DEFAULT_TIMEOUT, 1 );
   2002 
   2003 	if (status == MODEM_CMD_OK) {
   2004 		ModemService = true;
   2005 		return( true );
   2006 	}
   2007 
   2008 	delay = ModemGuardTime;
   2009 	while ( delay > 0 ) {
   2010 		//delay = HMInputLine( Port, delay, buffer, 81 );
   2011 		delay = SerialPort->Get_Modem_Result(delay, buffer, 81);
   2012 
   2013 	}
   2014 
   2015 	escape[0] = ModemEscapeCode;
   2016 	escape[1] = ModemEscapeCode;
   2017 	escape[2] = ModemEscapeCode;
   2018 	escape[3] = 0;
   2019 
   2020 	//status = HMSendStringNoWait( Port, escape, -1 );
   2021 	SerialPort->Write_To_Serial_Port((unsigned char*)escape, 3);
   2022 
   2023 	delay = ModemGuardTime;
   2024 	while ( delay > 0 ) {
   2025 		delay = SerialPort->Get_Modem_Result(delay, buffer, 81);
   2026 		//delay = HMInputLine( Port, delay, buffer, 81 );
   2027 
   2028 		if ( strncmp( buffer, "OK", 2 ) == 0 ) {
   2029 			break;
   2030 		}
   2031 	}
   2032 
   2033 	status = Send_Modem_Command( "ATH", '\r', buffer, 81, ModemHangupDelay, 1 );
   2034 
   2035 	if (status == MODEM_CMD_OK) {
   2036 	} else {
   2037 		ModemService = true;
   2038 		return( false );
   2039 	}
   2040 
   2041 	status = Send_Modem_Command( "ATZ", '\r', buffer, 81, DEFAULT_TIMEOUT, 1 );
   2042 
   2043 	if (status == MODEM_CMD_OK) {
   2044 	} else {
   2045 		ModemService = true;
   2046 		return( false );
   2047 	}
   2048 
   2049 	ModemService = true;
   2050 	return( true );
   2051 
   2052 }	/* end of Hangup_Modem */
   2053 
   2054 
   2055 /***********************************************************************************************
   2056  * NMC::Setup_Modem_Echo -- Sets the echo callback function pointer                            *
   2057  *                                                                                             *
   2058  *                                                                                             *
   2059  *                                                                                             *
   2060  * INPUT:    Ptr to callback function                                                          *
   2061  *                                                                                             *
   2062  * OUTPUT:   Nothing                                                                           *
   2063  *                                                                                             *
   2064  * WARNINGS: None                                                                              *
   2065  *                                                                                             *
   2066  * HISTORY:                                                                                    *
   2067  *    8/2/96 12:48PM ST : Documented and added WIn32 support                                   *
   2068  *=============================================================================================*/
   2069 void NullModemClass::Setup_Modem_Echo( void ( *func )( char c) )
   2070 {
   2071 	SerialPort->Set_Echo_Function(func);
   2072 	//HMSetUpEchoRoutine( func );
   2073 
   2074 }	/* end of Setup_Modem_Echo */
   2075 
   2076 
   2077 /***********************************************************************************************
   2078  * NMC::Remove_Modem_Echo -- Set the echo function callback pointer to null                    *
   2079  *                                                                                             *
   2080  *                                                                                             *
   2081  *                                                                                             *
   2082  * INPUT:    Nothing                                                                           *
   2083  *                                                                                             *
   2084  * OUTPUT:   Nothing                                                                           *
   2085  *                                                                                             *
   2086  * WARNINGS: None                                                                              *
   2087  *                                                                                             *
   2088  * HISTORY:                                                                                    *
   2089  *    8/2/96 12:50PM ST : Documented / Win32 support added                                     *
   2090  *=============================================================================================*/
   2091 void NullModemClass::Remove_Modem_Echo( void )
   2092 {
   2093 	SerialPort->Set_Echo_Function(NULL);
   2094 	//HMSetUpEchoRoutine( NULL );
   2095 
   2096 }	/* end of Remove_Modem_Echo */
   2097 
   2098 
   2099 /***********************************************************************************************
   2100  * NMC::Print_EchoBuf -- Print out the contents of the echo buffer                             *
   2101  *                                                                                             *
   2102  *                                                                                             *
   2103  *                                                                                             *
   2104  * INPUT:    Nothing                                                                           *
   2105  *                                                                                             *
   2106  * OUTPUT:   Nothing                                                                           *
   2107  *                                                                                             *
   2108  * WARNINGS: None                                                                              *
   2109  *                                                                                             *
   2110  * HISTORY:                                                                                    *
   2111  *    8/2/96 12:51PM ST : Documented                                                           *
   2112  *=============================================================================================*/
   2113 void NullModemClass::Print_EchoBuf( void )
   2114 {
   2115 	for (int i = 0; i < strlen(NullModem.EchoBuf); i++) {
   2116 		if (NullModem.EchoBuf[i] == '\r') {
   2117 			NullModem.EchoBuf[i] = 1;
   2118 		} else {
   2119 			if (NullModem.EchoBuf[i] == '\n') {
   2120 				NullModem.EchoBuf[i] = 2;
   2121 			}
   2122 		}
   2123 	}
   2124 }
   2125 
   2126 
   2127 /***********************************************************************************************
   2128  * NMC::Reset_EchoBuf -- Empties the echo buffer                                               *
   2129  *                                                                                             *
   2130  *                                                                                             *
   2131  *                                                                                             *
   2132  * INPUT:    Nothing                                                                           *
   2133  *                                                                                             *
   2134  * OUTPUT:   Nothing                                                                           *
   2135  *                                                                                             *
   2136  * WARNINGS: None                                                                              *
   2137  *                                                                                             *
   2138  * HISTORY:                                                                                    *
   2139  *    8/2/96 12:51PM ST : Documented                                                           *
   2140  *=============================================================================================*/
   2141 void NullModemClass::Reset_EchoBuf( void )
   2142 {
   2143 	*EchoBuf = 0;
   2144 	EchoCount = 0;
   2145 }
   2146 
   2147 
   2148 /***********************************************************************************************
   2149  * NMC::Abort_Modem -- Checks for user input so that modem operations can be aborted           *
   2150  *                                                                                             *
   2151  *                                                                                             *
   2152  *                                                                                             *
   2153  * INPUT:    Nothing                                                                           *
   2154  *                                                                                             *
   2155  * OUTPUT:   ASUSERABORT if abort key pressed. ASSUCESS otherwise.                             *
   2156  *                                                                                             *
   2157  * WARNINGS: None                                                                              *
   2158  *                                                                                             *
   2159  * HISTORY:                                                                                    *
   2160  *    8/2/96 12:52PM ST : Documented                                                           *
   2161  *=============================================================================================*/
   2162 int NullModemClass::Abort_Modem(void)
   2163 //int NullModemClass::Abort_Modem( PORT * )
   2164 {
   2165 	/*........................................................................
   2166 	Button Enumerations
   2167 	........................................................................*/
   2168 	enum {
   2169 		BUTTON_CANCEL = 100,
   2170 	};
   2171 
   2172 	/*
   2173 	........................ Invoke game callback .........................
   2174 	*/
   2175 	Call_Back();
   2176 
   2177 	/*
   2178 	........................... Get user input ............................
   2179 	*/
   2180 	Input = Commands->Input();
   2181 
   2182 	switch ( Input ) {
   2183 		case (KN_ESC):
   2184 		case (BUTTON_CANCEL | KN_BUTTON):
   2185 			return( ASUSERABORT );
   2186 	}
   2187 
   2188 	return( ASSUCCESS );
   2189 
   2190 }	/* end of Abort_Modem */
   2191 
   2192 
   2193 /***********************************************************************************************
   2194  * NMC::Setup_Abort_Modem -- sets the modem abort function pointer                             *
   2195  *                                                                                             *
   2196  *                                                                                             *
   2197  *                                                                                             *
   2198  * INPUT:    Nothing                                                                           *
   2199  *                                                                                             *
   2200  * OUTPUT:   Nothing                                                                           *
   2201  *                                                                                             *
   2202  * WARNINGS: None                                                                              *
   2203  *                                                                                             *
   2204  * HISTORY:                                                                                    *
   2205  *    8/2/96 2:59PM ST : Documented / Win32 support added                                      *
   2206  *=============================================================================================*/
   2207 void NullModemClass::Setup_Abort_Modem( void )
   2208 {
   2209 	SerialPort->Set_Abort_Function((int(*)(void))Abort_Modem);
   2210 }	/* end of Setup_Abort_Modem */
   2211 
   2212 
   2213 /***********************************************************************************************
   2214  * NMC::Remove_Abort_Modem -- Removes the modem abort function pointer                         *
   2215  *                                                                                             *
   2216  *                                                                                             *
   2217  *                                                                                             *
   2218  * INPUT:    Nothing                                                                           *
   2219  *                                                                                             *
   2220  * OUTPUT:   Nothing                                                                           *
   2221  *                                                                                             *
   2222  * WARNINGS: None                                                                              *
   2223  *                                                                                             *
   2224  * HISTORY:                                                                                    *
   2225  *    8/2/96 3:01PM ST : Documented / Win32 support added                                      *
   2226  *=============================================================================================*/
   2227 void NullModemClass::Remove_Abort_Modem( void )
   2228 {
   2229 	SerialPort->Set_Abort_Function(NULL);
   2230 }	/* end of Remove_Abort_Modem */
   2231 
   2232 
   2233 
   2234 /***********************************************************************************************
   2235  * NMC::Change_IRQ_Priority -- Increases the priority of the serial interrupt                  *
   2236  *                                                                                             *
   2237  *                                                                                             *
   2238  *                                                                                             *
   2239  * INPUT:    Interrupt request number                                                          *
   2240  *                                                                                             *
   2241  * OUTPUT:   ASSUCCESS if changed                                                              *
   2242  *                                                                                             *
   2243  * WARNINGS: The Win32 version of this function does nothing.                                  *
   2244  *           Priorities are controlled by windoze                                              *
   2245  *                                                                                             *
   2246  * HISTORY:                                                                                    *
   2247  *    8/2/96 3:03PM ST : Documented / Win32 support added                                      *
   2248  *=============================================================================================*/
   2249 int NullModemClass::Change_IRQ_Priority( int )
   2250 {
   2251 	return (ASSUCCESS);
   2252 }	/* end of Change_IRQ_Priority */
   2253 
   2254 
   2255 /***********************************************************************************************
   2256  * NMC::Get_Modem_Status -- returns status of modem control bits                               *
   2257  *                                                                                             *
   2258  *                                                                                             *
   2259  *                                                                                             *
   2260  * INPUT:    Nothing                                                                           *
   2261  *                                                                                             *
   2262  * OUTPUT:   Modem status                                                                      *
   2263  *                                                                                             *
   2264  * WARNINGS: None                                                                              *
   2265  *                                                                                             *
   2266  * HISTORY:                                                                                    *
   2267  *    8/2/96 3:06PM ST : Documented / Win32 support added                                      *
   2268  *=============================================================================================*/
   2269 int NullModemClass::Get_Modem_Status( void )
   2270 {
   2271 	int modemstatus;
   2272 	int status;
   2273 	char buffer[81];
   2274 
   2275 	//modemstatus = GetModemStatus( Port );
   2276 	modemstatus = SerialPort->Get_Modem_Status();
   2277 
   2278 	status = Send_Modem_Command( "AT", '\r', buffer, 81, DEFAULT_TIMEOUT, 1 );
   2279 
   2280 	if (status == MODEM_CMD_OK) {
   2281 		modemstatus &= (~CD_SET);
   2282 	}
   2283 
   2284 	return( modemstatus );
   2285 
   2286 }	/* end of Get_Modem_Status */
   2287 
   2288 
   2289 /***********************************************************************************************
   2290  * NMC::Send_Modem_Command -- Sends an 'AT' command to the modem and gets the response         *
   2291  *                                                                                             *
   2292  *                                                                                             *
   2293  *                                                                                             *
   2294  * INPUT:    command to send to modem. e.g. 'ATZ'                                              *
   2295  *           terminator byte for command string                                                *
   2296  *           buffer to put modem response into                                                 *
   2297  *           length of above buffer                                                            *
   2298  *           delay to wait for response                                                        *
   2299  *           number of times to retry when modem doesnt respond                                *
   2300  *                                                                                             *
   2301  * OUTPUT:   input delay less the time it took the modem to respond                            *
   2302  *                                                                                             *
   2303  * WARNINGS: None                                                                              *
   2304  *                                                                                             *
   2305  * HISTORY:                                                                                    *
   2306  *    8/2/96 3:09PM ST : Documented / Win32 support added                                      *
   2307  *=============================================================================================*/
   2308 int NullModemClass::Send_Modem_Command( char *command, char terminator, char *buffer, int buflen, int delay, int retries )
   2309 {
   2310 	return (SerialPort->Send_Command_To_Modem(command, terminator, buffer, buflen, delay, retries));
   2311 }
   2312 
   2313 
   2314 /***********************************************************************************************
   2315  * NMC::Verify_And_Convert_To_Int -- converts a text string of numbers to an int               *
   2316  *                                                                                             *
   2317  *                                                                                             *
   2318  *                                                                                             *
   2319  * INPUT:    ptr to buffer                                                                     *
   2320  *                                                                                             *
   2321  * OUTPUT:   value of text number in buffer                                                    *
   2322  *                                                                                             *
   2323  * WARNINGS: None                                                                              *
   2324  *                                                                                             *
   2325  * HISTORY:                                                                                    *
   2326  *    8/2/96 3:13PM ST : Documented                                                            *
   2327  *=============================================================================================*/
   2328 int NullModemClass::Verify_And_Convert_To_Int( char *buffer )
   2329 {
   2330 	int value = 0;
   2331 	int len = strlen(buffer);
   2332 
   2333 
   2334 	for (int i = 0; i < len; i++) {
   2335 		if ( !isdigit( *(buffer + i) ) ) {
   2336 			value = -1;
   2337 			break;
   2338 		}
   2339 	}
   2340 
   2341 	if (value == 0) {
   2342 		value = atoi( buffer );
   2343 	}
   2344 
   2345 	return( value );
   2346 
   2347 }	/* end of Verify_And_Convert_To_Int */
   2348 
   2349 /*************************** end of nullmgr.cpp ****************************/
   2350 #endif