// sersetup.c

#include "sersetup.h"
#include "DoomNet.h"
#include <time.h>

extern	que_t		inque, outque;

void jump_start( void );
void GetUart (void);
extern int 	uart;

int			usemodem;


void ModemCommand (char *str);
int ModemResponse (char *resp);
void configure (void);
void reset_counters (void);

time_t starttime = 0;
time_t endtime = 0;
time_t playtime = 0;

char init1 [256+1];
char init2 [256+1];
char hangup [256+1];
char config [256+1];
char devparm [256+1];
unsigned long baud = 9600;
char dial [256+1];
int comport = 1;
int irq = -1;
int uart = -1;
int vector = -1;
int loadgame = -1;
int episode = -1;
int map = -1;
int skill = -1;
int deathmatch = 0;
int pulsedial = 0;
int player = 0;
int nomonsters = 0;
int respawn = 0;

/* showReadStats() counters. */
unsigned long writeBufferOverruns       = 0;
unsigned long bytesRead                 = 0;
unsigned long packetsRead               = 0;
unsigned long largestReadPacket         = 0;
unsigned long smallestReadPacket        = 0xFFFFFFFFl;
unsigned long readBufferOverruns        = 0;
unsigned long totalReadPacketBytes      = 0;
unsigned long oversizeReadPackets       = 0;
unsigned long largestOversizeReadPacket = 0;
unsigned long overReadPacketLen         = 0;

/* showWriteStats() counters. */
unsigned long bytesWritten               = 0;
unsigned long packetsWrite               = 0;
unsigned long largestWritePacket         = 0;
unsigned long smallestWritePacket        = 0xFFFFFFFFl;
unsigned long totalWritePacketBytes      = 0;
unsigned long oversizeWritePackets       = 0;
unsigned long largestOversizeWritePacket = 0;

/* showUartErrors() counters. */
unsigned long numBreak          = 0;
unsigned long numFramingError   = 0;
unsigned long numParityError    = 0;
unsigned long numOverrunError   = 0;
unsigned long numTxInterrupts   = 0;
unsigned long numRxInterrupts   = 0;


void showReadStats()
{
	if ( smallestReadPacket == 0xFFFFFFFFl )
		smallestReadPacket = 0;

	printf ("Read statistics:\n");

	printf ("%9lu Largest packet      %9lu Smallest packet\n",
				largestReadPacket, smallestReadPacket);

	printf ("%9lu Oversize packets    %9lu Largest oversize packet\n",
				oversizeReadPackets, largestOversizeReadPacket);

	printf ("%9lu Total packets       %9lu Buffer overruns\n",
				packetsRead, readBufferOverruns);

	printf ("%9lu Total bytes         %9.1f Average bytes/minute\n",
				totalReadPacketBytes,
				starttime == 0 || playtime == 0 ? 0 :
					(float) totalReadPacketBytes / (float) ((float) playtime / 60));

	printf ("%9lu Receive interrupts  %9.1f Average bytes/interrupt\n",
		numRxInterrupts,
		numRxInterrupts == 0 ? 0 :
			(float) totalReadPacketBytes / (float) numRxInterrupts);

	printf ("\n");
}



void showWriteStats()
{
	if ( smallestWritePacket == 0xFFFFFFFFl )
		smallestWritePacket = 0;

	printf ("Write statistics:\n");

	printf ("%9lu Largest packet      %9lu Smallest packet\n",
				largestWritePacket, smallestWritePacket);

	printf ("%9lu Oversize packets    %9lu Largest oversize packet\n",
				oversizeWritePackets, largestOversizeWritePacket);

	printf ("%9lu Total packets       %9lu Buffer overruns\n",
				packetsWrite, writeBufferOverruns);

	printf ("%9lu Total bytes         %9.1f Average bytes/minute\n",
				totalWritePacketBytes,
				starttime == 0 || playtime == 0 ? 0 :
					(float) totalWritePacketBytes / (float) ((float) playtime / 60));

	printf ("%9lu Transmit interrupts %9.1f Average bytes/interrupt\n",
		numTxInterrupts,
		numTxInterrupts == 0 ? 0 :
			(float) totalWritePacketBytes / (float) numTxInterrupts);

	printf ("\n");
}

void showUartErrors()
{
	puts ("UART line status");

	printf ("%9lu Breaks detected     %9lu Framing errors\n",
		numBreak, numFramingError);
	printf ("%9lu Parity errors       %9lu Overrun errors\n",
		numParityError, numOverrunError);
}

/*
================
=
= write_buffer
=
================
*/

void write_buffer( char *buffer, unsigned int count )
{
// if this would overrun the buffer, throw everything else out
	if (outque.size + count > QUESIZE)
	{
		++writeBufferOverruns;
		outque.tail = outque.head;
		outque.size = 0;
	}

   write_bytes (buffer, count);

	if ( INPUT( uart + LINE_STATUS_REGISTER ) & 0x40)
		jump_start();
}


void hangup_modem (void)
{
	printf ("\n");
	printf ("\nDropping DTR\n");
	OUTPUT( uart + MODEM_CONTROL_REGISTER
		, INPUT( uart + MODEM_CONTROL_REGISTER ) & ~MCR_DTR );
	delay (1250);
	OUTPUT( uart + MODEM_CONTROL_REGISTER
		, INPUT( uart + MODEM_CONTROL_REGISTER ) | MCR_DTR );
	ModemCommand("+++");
	delay (1250);
	if (hangup [0] != EOS)
		ModemCommand(hangup);
	else
	{
		printf ("Warning: No HANGUP= string in MODEM.CFG file. Using default.\n");
		ModemCommand("ATH0");
	}
	delay (1250);
	while (read_byte () != -1)
	;
}


/*
=================
=
= Error
=
= For abnormal program terminations
=
=================
*/

void Error (char *error, ...)
{
	va_list argptr;

	if (usemodem)
		hangup_modem ();

	ShutdownPort ();

	if (vectorishooked)
		setvect (doomcom.intnum,olddoomvect);

	if (error)
	{
		va_start (argptr,error);
		vprintf (error,argptr);
		va_end (argptr);
		printf ("\n\n");
	//	exit (1);
	}

	//	printf ("Clean exit from SERSETUP\n");

	exit (error != (char *) NULL);
}


/*
================
=
= ReadPacket
=
================
*/

#define MAXPACKET	512
#define	FRAMECHAR	0x70

char	packet[MAXPACKET];
int		packetlen;
int		inescape;
int		newpacket;

boolean ReadPacket (void)
{
	int	c;

// if the buffer has overflowed, throw everything out

	if (inque.size > QUESIZE - 4)	// check for buffer overflow
	{
		++readBufferOverruns;           /* Count read overruns */
		inque.tail = inque.head;
		inque.size = 0;
		newpacket = true;
		return false;
	}

	if (newpacket)
	{
		packetlen = 0;
		newpacket = 0;
		overReadPacketLen = 0;
	}

	do
	{
		if ((c = read_byte ()) < 0)
			return false;      // haven't read a complete packet
		if (inescape)
		{
			inescape = false;
			if (c!=FRAMECHAR)
			{
				newpacket = 1;

				++packetsRead;  /* Count packets read */

				if ( packetlen > largestReadPacket ) /* Track largest packet */
					largestReadPacket = packetlen;

				if ( packetlen < smallestReadPacket ) /* Track smallest packet */
					smallestReadPacket = packetlen;

				totalReadPacketBytes += packetlen;    /* Count total packet bytes */

				return true;    // got a good packet
			}
		}
		else if (c==FRAMECHAR)
		{
			inescape = true;
			continue;			// don't know yet if it is a terminator
		}						// or a literal FRAMECHAR

		if (packetlen >= MAXPACKET)
		{
			++overReadPacketLen;			/* Keep track of size of oversize packet */
			oversizeReadPackets++;		/* Count oversize packets */

			if ( overReadPacketLen > largestOversizeReadPacket )
				largestOversizeReadPacket = overReadPacketLen;

			continue;			// oversize packet
		}

		packet[packetlen] = c;
		packetlen++;
	} while (1);

}


/*
=============
=
= WritePacket
=
=============
*/



void WritePacket (char *buffer, int len)
{
	int		b;
	char	static localbuffer[MAXPACKET*2+2];

	b = 0;
	if (len > MAXPACKET)
	{
		++oversizeWritePackets;         /* Count oversize write packets */
		if ( len > largestOversizeWritePacket )
			++largestOversizeWritePacket;

		return;
	}

	if ( len > largestWritePacket )
		largestWritePacket = len;

	if ( len < smallestWritePacket )
		smallestWritePacket = len;

	totalWritePacketBytes += len;

	++packetsWrite;

	while (len--)
	{
		if (*buffer == FRAMECHAR)
			localbuffer[b++] = FRAMECHAR;	// escape it for literal
		localbuffer[b++] = *buffer++;
	}

	localbuffer[b++] = FRAMECHAR;
	localbuffer[b++] = 0;

	write_buffer (localbuffer, b);
}


/*
=============
=
= NetISR
=
=============
*/

void interrupt NetISR (void)
{
	if (doomcom.command == CMD_SEND)
	{
//I_ColorBlack (0,0,63);
		WritePacket ((char *)&doomcom.data, doomcom.datalength);
	}
	else if (doomcom.command == CMD_GET)
	{
//I_ColorBlack (63,63,0);

		if (ReadPacket () && packetlen <= sizeof(doomcom.data) )
		{
			doomcom.remotenode = 1;
			doomcom.datalength = packetlen;
			memcpy (&doomcom.data, &packet, packetlen);
		}
		else
			doomcom.remotenode = -1;

	}
//I_ColorBlack (0,0,0);
}




/*
=================
=
= Connect
=
= Figures out who is player 0 and 1
=================
*/

int Connect (void)
{
	struct time		time;
	int				oldsec;
	int		localstage, remotestage;
	char	str[20];

//
// wait for a good packet
//
	printf ("Attempting to connect across serial link, press escape to abort.\n");

	doomcom.consoleplayer = player;
	oldsec = -1;
	localstage = remotestage = 0;

	do
	{
		while ( bioskey(1) )
		{
			if ( (bioskey (0) & 0xff) == ESC)
			{
				// Error ("\n\nNetwork game synchronization aborted.");
				printf ("\n\nNetwork game synchronization aborted.\n");
				while (read_byte () != -1)
				;
				return FALSE;
			}
		}

		while (ReadPacket ())
		{
			packet[packetlen] = 0;
			printf ("read: '%s'\n", packet);
			if (packetlen != 7)
			{
				printf ("bad packet len = %d (should be 7)\n", packetlen);
				goto badpacket;
			}
			if (strncmp(packet,"PLAY",4) )
			{
				printf ("error: first 4 char's aren't 'PLAY'\n");
				goto badpacket;
			}
			remotestage = packet[6] - '0';
			localstage = remotestage+1;
			if (packet[4] == '0'+doomcom.consoleplayer)
			{
				doomcom.consoleplayer ^= 1;
				localstage = remotestage = 0;
			}
			oldsec = -1;
		}
badpacket:

		gettime (&time);
		if (time.ti_sec != oldsec)
		{
			oldsec = time.ti_sec;
			sprintf (str,"PLAY%i_%i",doomcom.consoleplayer,localstage);
			WritePacket (str,strlen(str));
			printf ("wrote: '%s'\n",str);
		}

	} while (remotestage < 1);

//
// flush out any extras
//
	while (ReadPacket ())
	;
	return TRUE;
}



/*
==============
=
= ModemCommand
=
==============
*/

void ModemCommand (char *str)
{
	int i;
	char *ptr;

	printf ("Modem command : %s\n",str);
	ptr = str;
	for (i = 0; i < strlen (str); i++)
	{
		write_buffer (ptr++, 1);
		delay (20);
	}
	write_buffer ("\r",1);
}


/*
==============
=
= ModemResponse
=
= Waits for OK, RING, CONNECT, etc
==============
*/


int ModemResponse (char *resp)
{
	int		c;
	int		respptr;
	char	response[80];

	do
	{
		printf ("Modem response: ");
		respptr=0;
		do
		{
			while ( bioskey(1) )
			{
				if ( (bioskey (0) & 0xff) == ESC)
				{
					// Error ("\nModem response aborted.");
					printf ("\nModem response aborted.\n");
					hangup_modem ();
					return FALSE;
				}
			}
			c = read_byte ();
			if (c==-1)
				continue;
			if (c=='\n' || respptr == 79)
			{
				response[respptr] = 0;
				printf ("%s\n",response);
				break;
			}
			if (c>=' ')
			{
				response[respptr] = c;
				respptr++;
			}
		} while (1);

	} while (strncmp(response,resp,strlen(resp)));
	return TRUE;
}


/*
=============
=
= InitModem
=
=============
*/

void InitModem (void)
{
	if (init1 [0] != EOS)
	{
		ModemCommand (init1);
		if (! ModemResponse ("OK"))
			return;
	}

	if (init2 [0] != EOS)
	{
		ModemCommand (init2);
		ModemResponse ("OK");
	}
}


/*
=============
=
= Dial
=
=============
*/

int Dial (void)
{
	char	cmd[80];
	int ch;
	char line [256+1];
	FILE	*infile;
	int found_name = FALSE;
	int prompt = TRUE;

	usemodem = true;
	InitModem ();

	if (dial [0] != EOS)
	{
		printf ("\nDial %s? (y/n): ", dial);
		if ((ch = getch()) == 'y' || ch == 'Y')
			prompt = FALSE;
	}

	if (prompt)
	{
		printf ("\nEnter number to dial or phonebook name: ");
		gets (line);
		if (sscanf (line, "%s", dial) == EOF)
			return FALSE;

		if ((infile = fopen ("modem.cfg", "r")) == NULL)
			Error ("Couldn't read MODEM.CFG file.");

		while (fgets (line, 256, infile) != NULL)
		{
			if (line [0] == 'N' && line [1] == 'A')	/* NAME */
			{
				if (strncmp (&line [5], dial, strlen (dial)) == 0)
					found_name = TRUE;
			}
			else if (found_name && line [0] == 'N' && line [1] == 'U')
			{
				sscanf (&line [7], "%s", dial);			/* NUMBER */
				break;
			}
		}
		fclose (infile);
	}

	printf ("\nDialing %s\n\n", dial);
	if (pulsedial)
		sprintf (cmd,"ATDP%s", dial);
	else
		sprintf (cmd,"ATDT%s", dial);

	ModemCommand(cmd);
	return ModemResponse ("CONNECT");

	/** doomcom.consoleplayer = 1; **/
}


/*
=============
=
= Answer
=
=============
*/

int Answer (void)
{
	usemodem = true;
	InitModem ();
	printf ("\nWaiting for ring...\n\n");

	if (! ModemResponse ("RING"))
		return FALSE;
	ModemCommand ("ATA");
	return ModemResponse ("CONNECT");

	/** doomcom.consoleplayer = 0; **/
}


void get_config_settings (void)
{
	char line [256+1];
	int len;
	FILE	*infile;
	int i;
	unsigned char far *vectorptr;
	unsigned long lnum;

	if ((infile = fopen ("modem.cfg", "r")) == NULL)
		Error ("Couldn't read MODEM.CFG file.");

	printf ("\n\n\n\nReading MODEM.CFG file...\n\n");
	while (fgets (line, 256, infile) != NULL)
	{
		switch (line [0])
		{
			case 'B' :
				/* BAUD */
				if (sscanf (&line [5], "%lu", &baud) != EOF &&
					baud != 9600 && baud != 14400 && baud != 19200 &&
					baud != 38400 && baud != 57600 && baud != 115200)
				{
					baud = 9600;
				}
				break;
			case 'C' :
				if (line [2] == 'N')
				{
					/* CONFIG */
					strcpy (config, &line [7]);
					if (config [(len = strlen (config))-1] == '\n')
						config [len-1] = EOS;
				}
				else
				{
					/* COM */
					sscanf (&line [4], "%d", &comport);
					if (comport < 1 || comport > 4)
						comport = 1;
				}
				break;
			case 'D' :
				if (line [3] == 'P')
				{
					/* DEVPARM */
					strcpy (devparm, &line [8]);
					if (devparm [(len = strlen (devparm))-1] == '\n')
						devparm [len-1] = EOS;
				}
				else if (line [3] == 'L')
				{
					/* DIAL */
					strcpy (dial, &line [5]);
					if (dial [(len = strlen (dial))-1] == '\n')
						dial [len-1] = EOS;
				}
				else
				{
					/* DEATHMATCH */
					sscanf (&line [11], "%d", &deathmatch);
				}
				break;
			case 'E' :
				/* EPISODE */
				sscanf (&line [8], "%d", &episode);
				if (episode < 1 || episode > 3)
					episode = -1;
				break;
			case 'H' :
				/* HANGUP */
				strcpy (hangup, &line [7]);
				if (hangup [(len = strlen (hangup))-1] == '\n')
					hangup [len-1] = EOS;
				break;
			case 'I' :
				if (line [1] == 'N')
				{
					if (line [4] == '1')
					{
						/* INIT1 */
						strcpy (init1, &line [6]);
						if (init1 [(len = strlen (init1))-1] == '\n')
							init1 [len-1] = EOS;
					}
					else
					{
						/* INIT2 */
						strcpy (init2, &line [6]);
						if (init2 [(len = strlen (init2))-1] == '\n')
							init2 [len-1] = EOS;
					}
				}
				else
				{
					/* IRQ */
					sscanf (&line [4], "%d", &irq);
				}
				break;
			case 'L' :
				/* LOADGAME */
				sscanf (&line [9], "%d", &loadgame);
				if (loadgame < 0 || loadgame > 5)
					loadgame = -1;
				break;
			case 'M' :
				/* MAP */
				sscanf (&line [4], "%d", &map);
				if (map < 1 || map > 9)
					map = -1;
				break;
			case 'N' :
				if (line [1] == 'O')
				{
					/* NOMONSTERS (as opposed to NAME or NUMBER) */
					sscanf (&line [11], "%d", &nomonsters);
				}
				break;
			case 'P' :
				if (line [1] == 'O')
				{
					/* PORT */
					sscanf (&line [5], "0x%x", &uart);
				}
				else if (line [1] == 'L')
				{
					/* PLAYER */
					sscanf (&line [7], "%d", &player);
					if (player < 0 || player > 1)
						player = 0;
				}
				else
				{
					/* PULSEDIAL */
					sscanf (&line [10], "%d", &pulsedial);
				}
				break;
			case 'R' :
				/* RESPAWN */
				sscanf (&line [8], "%d", &respawn);
				break;
			case 'S' :
				/* SKILL */
				sscanf (&line [6], "%d", &skill);
				if (skill < 1 || skill > 5)
					skill = -1;
				break;
			case 'V' :
				/* VECTOR */
				sscanf (&line [7], "0x%x", &vector);
				break;
		}
	}
	fclose (infile);

	/* Get irq and uart if not already set */
	if (irq == -1 || uart == -1)
		GetUart ();

	/* Get an interrupt vector if not already set */
	if (vector == -1)
	{
		for (vector = 0x60 ; vector <= 0x66 ; vector++)
		{
			vectorptr = *(unsigned char far * far *)(vector*4);
			if ( !vectorptr || *vectorptr == 0xcf )
				break;
		}
		if (vector == 0x67)
		{
			printf ("Warning: no NULL or iret interrupt vectors were found in the 0x60 to 0x66\n"
					"range.  You can specify a vector with the VECTOR=0x<num> line in modem.cfg.\n"
					"Press a key to continue...\n");
			getch ();
			vector = 0x66;
		}
	}
	doomcom.intnum = vector;
}


void print_config_settings (void)
{
	clrscr ();
	printf ("\nUsing the following settings:\n");
	printf ("  INIT1=%s\n", init1);
	printf ("  INIT2=%s\n", init2);
	printf ("  HANGUP=%s\n", hangup);
	printf ("  CONFIG=%s\n", config);
	printf ("  DEVPARM=%s\n", devparm);
	printf ("  BAUD=%lu\n", baud);
	printf ("  DIAL=%s\n", dial);
	printf ("  COM=%d\n", comport);
	printf ("  IRQ=%d\n", irq);
	printf ("  PORT=0x%x\n", uart);
	printf ("  VECTOR=0x%x\n", vector);
	printf ("  LOADGAME=%c\n", loadgame == -1 ? ' ' : loadgame + '0');
	printf ("  EPISODE=%d\n", episode == -1 ? 1 : episode);
	printf ("  MAP=%d\n", map == -1 ? 1 : map);
	printf ("  SKILL=%d\n", skill == -1 ? 3 : skill);
	printf ("  PLAYER=%d\n", player);
	printf ("  PULSEDIAL=%d\n", pulsedial);
	printf ("  DEATHMATCH=%d\n", deathmatch);
	printf ("  NOMONSTERS=%d\n", nomonsters);
	printf ("  RESPAWN=%d\n", respawn);
}


void configure (void)
{
	char line [256];
	int i = 0;

	clrscr ();
	printf (
		"Configure...  Press ENTER to keep current value shown in [].\n\n");

	printf ("  deathmatch (0/1)     [%d]: ", deathmatch);
	gets (line);
	sscanf (line, "%d", &deathmatch);

	printf ("  nomonsters (0/1)     [%d]: ", nomonsters);
	gets (line);
	sscanf (line, "%d", &nomonsters);

	printf ("  respawn (0/1)        [%d]: ", respawn);
	gets (line);
	sscanf (line, "%d", &respawn);

	printf ("  episode (1-3)        [%d]: ", episode == -1 ? 1 : episode);
	gets (line);
	sscanf (line, "%d", &episode);
	if (episode < 2 || episode > 3)	/* If default, set back to -1 */
		episode = -1;

	printf ("  map (1-9)            [%d]: ", map == -1 ? 1 : map);
	gets (line);
	sscanf (line, "%d", &map);
	if (map < 2 || map > 9)				/* If default, set back to -1 */
		map = -1;

	printf ("  skill (1-5)          [%d]: ", skill == -1 ? 3 : skill);
	gets (line);
	sscanf (line, "%d", &skill);
	if (skill < 1 || skill > 5 || skill == 3)	/* If default, set back to -1 */
		skill = -1;

	printf ("  loadgame (0-5 or -1) [%c]: ", loadgame == -1 ? ' ' : loadgame + '0');
	gets (line);
	sscanf (line, "%d", &loadgame);
	if (loadgame < 0 || loadgame > 5)
		loadgame = -1;

	printf ("  devparm (args or -1) [");
	while (devparm [i] != EOS)
		putchar (devparm [i++]);
	if (i == 0)
   	putchar (' ');
	printf ("]\n    new devparm string: ");
	gets (line);
	if (strcmp (line, "-1") == 0)
		devparm [0] = EOS;
	else if (line [0] != EOS)
		strcpy (devparm, line);

	printf ("\n");
}


void stats (void)
{
	time_t hrs;
	time_t mins;
	time_t secs;

	clrscr ();
	if (starttime != 0)
	{
		printf ("Start Time:    %s", ctime (&starttime));
		playtime = endtime - starttime;
		hrs = playtime / 3600;
		mins = (playtime - (hrs * 3600)) / 60;
		secs = playtime - (hrs * 3600) - (mins * 60);
		printf ("Playing Time:  %d:%02d:%02d\n\n",
			(int) hrs, (int) mins, (int) secs);
	}
	showReadStats();
	showWriteStats();
	showUartErrors();
	printf ("\n");
}


void talk (void)
{
	int c;

	clrscr ();
	printf ("Talk mode...  Press ESC to return\n\n");
	while (TRUE)
	{
		/* Check for keypress */
		if (bioskey (1))
		{
			if ((c = bioskey (0) & 0xff) == ESC)
			{
				/* ESC key -- Exit talk mode -- Flush both sides */
				while (read_byte () != -1)
				;
				while (bioskey (1))
					bioskey (0);
				printf ("\n\n");
				return;
			}
			if (c == 0x0D)		/* Change cr to crlf */
				c = 0x0A;
			write_buffer (&(char)c, 1);
			printf ("%c", c);
		}
		/* Check for received byte */
		if ((c = read_byte ()) != -1)
			printf ("%c", c);
	}
}


void reset_counters (void)
{
	/* showReadStats() counters. */
	writeBufferOverruns       = 0;
	bytesRead                 = 0;
	packetsRead               = 0;
	largestReadPacket         = 0;
	smallestReadPacket        = 0xFFFFFFFFl;
	readBufferOverruns        = 0;
	totalReadPacketBytes      = 0;
	oversizeReadPackets       = 0;
	largestOversizeReadPacket = 0;
	overReadPacketLen         = 0;

	/* showWriteStats() counters. */
	bytesWritten               = 0;
	packetsWrite               = 0;
	largestWritePacket         = 0;
	smallestWritePacket        = 0xFFFFFFFFl;
	totalWritePacketBytes      = 0;
	oversizeWritePackets       = 0;
	largestOversizeWritePacket = 0;

	/* showUartErrors() counters. */
	numBreak          = 0;
	numFramingError   = 0;
	numParityError    = 0;
	numOverrunError   = 0;
	numTxInterrupts   = 0;
	numRxInterrupts   = 0;
}


void usage (void)
{
	clrscr ();
	printf ("\n\n\n\n\nSER4.EXE is run without arguments.  Just type \"ser4.exe\"\n\n"
		"To change computer-related settings, edit the MODEM.CFG file,\n"
		"and to change game settings, use the CONFIGURE option while running.\n\n"
		"Yes, this means setup.exe won't work, but don't sweat the small stuff. :-)\n\n"
		"Press a key to continue...\n");
	getch ();
}


/*
=================
=
= main
=
=================
*/

void main(void)
{
	int ch;

	if (_argc > 1)
		usage ();

	clrscr ();
	printf(
		   "                         -----------------------------\n"
		   "                                   SER4.EXE           \n"
		   "                           DOOM SERIAL DEVICE DRIVER  \n"
		   "                         -----------------------------\n");

//
// set network characteristics
//
	/* Make "extratics" the default, it runs much better */
	doomcom.extratics = 1;

	doomcom.id = DOOMCOM_ID;
	doomcom.ticdup = 1;
	doomcom.numnodes = 2;
	doomcom.numplayers = 2;
	doomcom.drone = 0;
	doomcom.consoleplayer = 0;		/* Default - may be overridden later. */

	get_config_settings ();

//
// establish communications
//
	InitPort ();

	printf ("Press any key to continue...");
	getch ();
	print_config_settings ();

	while ( 0 <= read_byte() );	/* Flush any old stuff from uart buffer */

	while (TRUE)
	{
		printf (
			"\nSelect an option: 'D'ial, 'A'nswer, 'C'onnected already, 'Q'uit: ");
		ch = tolower (getch ());
		printf ("\n");
		if (ch == 'd')
		{
			if (Dial ())
				break;
		}
		else if (ch == 'a')
		{
			if (Answer ())
				break;
		}
		else if (ch == 'q')
			Error (NULL);
		else
			break;
	}

	printf ("\n");
	while (TRUE)
	{
		printf (
			"Select an option: 'D'oom, 'S'tats, 'C'onfigure, 'T'alk, 'Quit': ");
		ch = tolower (getch ());
		printf ("\n");
		switch (ch)
		{
			case 'd' : 
				if (Connect ())
				{
					reset_counters ();
					time (&starttime);
					LaunchDOOM ();
					time (&endtime);
				}
				break;
			case 's' : 
				stats ();
				break;
			case 'c' : 
				configure ();
				break;
			case 't' : 
				talk ();
				break;
			case 'q' :
				Error (NULL);
		}
	}
}

