summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTravis Bradshaw <travis.bradshaw@idsoftware.com>2012-01-31 15:57:38 -0600
committerTravis Bradshaw <travis.bradshaw@idsoftware.com>2012-01-31 15:57:38 -0600
commit77735c3ff0772609e9c8d29e3ce2ab42ff54d20b (patch)
tree4a8a3dce746276f1283417386a8d12d24a9d86b0
parent73424b6129f1c3ca9fc22aedcfe1f5330db137a9 (diff)
The source for the DOOM serial / model driver.
-rw-r--r--sersrc/DOOMNET.C126
-rw-r--r--sersrc/DOOMNET.H60
-rw-r--r--sersrc/PORT.C428
-rw-r--r--sersrc/README.TXT1
-rw-r--r--sersrc/SERSETUP.C680
-rw-r--r--sersrc/SERSETUP.H102
-rw-r--r--sersrc/SERSTR.H21
-rw-r--r--sersrc/SER_FRCH.H25
8 files changed, 1443 insertions, 0 deletions
diff --git a/sersrc/DOOMNET.C b/sersrc/DOOMNET.C
new file mode 100644
index 0000000..c027ec7
--- /dev/null
+++ b/sersrc/DOOMNET.C
@@ -0,0 +1,126 @@
+#include <stdio.h>
+#include <io.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+#include <dos.h>
+#include "doomnet.h"
+
+//#include "serstr.h"
+#include "ser_frch.h" // FRENCH VERSION
+
+#define DOOM2
+
+extern int myargc;
+extern char **myargv;
+
+doomcom_t doomcom;
+int vectorishooked;
+void interrupt (*olddoomvect) (void);
+
+
+
+/*
+=================
+=
+= CheckParm
+=
+= Checks for the given parameter in the program's command line arguments
+=
+= Returns the argument number (1 to argc-1) or 0 if not present
+=
+=================
+*/
+
+int CheckParm (char *check)
+{
+ int i;
+
+ for (i = 1;i<myargc;i++)
+ if ( !stricmp(check,myargv[i]) )
+ return i;
+
+ return 0;
+}
+
+
+/*
+=============
+=
+= LaunchDOOM
+=
+These fields in doomcom should be filled in before calling:
+
+ short numnodes; // console is allways node 0
+ short ticdup; // 1 = no duplication, 2-5 = dup for slow nets
+ short extratics; // 1 = send a backup tic in every packet
+
+ short consoleplayer; // 0-3 = player number
+ short numplayers; // 1-4
+ short angleoffset; // 1 = left, 0 = center, -1 = right
+ short drone; // 1 = drone
+=============
+*/
+
+void LaunchDOOM (void)
+{
+ char *newargs[99];
+ char adrstring[10];
+ long flatadr;
+ int p;
+ unsigned char far *vector;
+
+// prepare for DOOM
+ doomcom.id = DOOMCOM_ID;
+
+// hook an interrupt vector
+ p= CheckParm ("-vector");
+
+ if (p)
+ {
+ doomcom.intnum = sscanf ("0x%x",_argv[p+1]);
+ }
+ else
+ {
+ for (doomcom.intnum = 0x60 ; doomcom.intnum <= 0x66 ; doomcom.intnum++)
+ {
+ vector = *(char far * far *)(doomcom.intnum*4);
+ if ( !vector || *vector == 0xcf )
+ break;
+ }
+ if (doomcom.intnum == 0x67)
+ {
+ printf (STR_WARNING);
+ doomcom.intnum = 0x66;
+ }
+ }
+ printf (STR_COMM"\n",doomcom.intnum);
+
+ olddoomvect = getvect (doomcom.intnum);
+ setvect (doomcom.intnum,NetISR);
+ vectorishooked = 1;
+
+// build the argument list for DOOM, adding a -net &doomcom
+ memcpy (newargs, myargv, (myargc+1)*2);
+ newargs[myargc] = "-net";
+ flatadr = (long)_DS*16 + (unsigned)&doomcom;
+ sprintf (adrstring,"%lu",flatadr);
+ newargs[myargc+1] = adrstring;
+ newargs[myargc+2] = NULL;
+
+// spawnv (P_WAIT, "m:\\newdoom\\doom", newargs);
+ if (!access("doom2.exe",0))
+ spawnv (P_WAIT, "doom2", newargs);
+ else
+ spawnv (P_WAIT, "doom", newargs);
+
+ #ifdef DOOM2
+ printf (STR_RETURNED"\n");
+ #else
+ printf ("Returned from DOOM\n");
+ #endif
+
+
+}
+
+
diff --git a/sersrc/DOOMNET.H b/sersrc/DOOMNET.H
new file mode 100644
index 0000000..06007e6
--- /dev/null
+++ b/sersrc/DOOMNET.H
@@ -0,0 +1,60 @@
+// doomnet.h
+
+
+#define PEL_WRITE_ADR 0x3c8
+#define PEL_DATA 0x3c9
+
+#define I_ColorBlack(r,g,b) {outp(PEL_WRITE_ADR,0);outp(PEL_DATA,r);outp(PEL_DATA,g);outp(PEL_DATA,b);};
+
+
+
+
+#define MAXNETNODES 8 // max computers in a game
+#define MAXPLAYERS 4 // 4 players max + drones
+
+
+#define CMD_SEND 1
+#define CMD_GET 2
+
+#define DOOMCOM_ID 0x12345678l
+
+typedef struct
+{
+ long id;
+ short intnum; // DOOM executes an int to send commands
+
+// communication between DOOM and the driver
+ short command; // CMD_SEND or CMD_GET
+ short remotenode; // dest for send, set by get (-1 = no packet)
+ short datalength; // bytes in doomdata to be sent / bytes read
+
+// info common to all nodes
+ short numnodes; // console is allways node 0
+ short ticdup; // 1 = no duplication, 2-5 = dup for slow nets
+ short extratics; // 1 = send a backup tic in every packet
+ short deathmatch; // 1 = deathmatch
+ short savegame; // -1 = new game, 0-5 = load savegame
+ short episode; // 1-3
+ short map; // 1-9
+ short skill; // 1-5
+
+// info specific to this node
+ short consoleplayer; // 0-3 = player number
+ short numplayers; // 1-4
+ short angleoffset; // 1 = left, 0 = center, -1 = right
+ short drone; // 1 = drone
+
+// packet data to be sent
+ char data[512];
+} doomcom_t;
+
+
+
+extern doomcom_t doomcom;
+extern void interrupt (*olddoomvect) (void);
+extern int vectorishooked;
+
+int CheckParm (char *check);
+void LaunchDOOM (void);
+void interrupt NetISR (void);
+
diff --git a/sersrc/PORT.C b/sersrc/PORT.C
new file mode 100644
index 0000000..d9eb036
--- /dev/null
+++ b/sersrc/PORT.C
@@ -0,0 +1,428 @@
+// port.c
+
+#include "doomnet.h"
+#include "sersetup.h"
+//#include "serstr.h"
+#include "ser_frch.h" // FRENCH VERSION
+
+
+void jump_start( void );
+
+void interrupt isr_8250 (void);
+void interrupt isr_16550 (void);
+
+union REGS regs;
+struct SREGS sregs;
+
+que_t inque, outque;
+
+
+int uart; // io address
+enum {UART_8250, UART_16550} uart_type;
+int irq;
+
+int modem_status = -1;
+int line_status = -1;
+
+void interrupt (*oldirqvect) (void);
+int irqintnum;
+
+int comport;
+
+int baudbits;
+
+
+/*
+==============
+=
+= GetUart
+=
+==============
+*/
+
+void GetUart (void)
+{
+ char far *system_data;
+ static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8};
+ static int ISA_IRQs[] = {4,3,4,3};
+ static int MCA_uarts[] = {0x03f8,0x02f8,0x3220,0x3228};
+ static int MCA_IRQs[] = {4,3,3,3};
+ int p;
+
+ if (CheckParm ("-com2"))
+ comport = 2;
+ else if (CheckParm ("-com3"))
+ comport = 3;
+ else if (CheckParm ("-com4"))
+ comport = 4;
+ else
+ comport = 1;
+
+ regs.h.ah = 0xc0;
+ int86x( 0x15, &regs, &regs, &sregs );
+ if ( regs.x.cflag )
+ {
+ irq = ISA_IRQs[ comport-1 ];
+ uart = ISA_uarts[ comport-1 ];
+ return;
+ }
+ system_data = ( char far *) ( ( (long) sregs.es << 16 ) + regs.x.bx );
+ if ( system_data[ 5 ] & 0x02 )
+ {
+ irq = MCA_IRQs[ comport-1 ];
+ uart = MCA_uarts[ comport-1 ];
+ }
+ else
+ {
+ irq = ISA_IRQs[ comport-1 ];
+ uart = ISA_uarts[ comport-1 ];
+ }
+
+ p = CheckParm ("-port");
+ if (p)
+ sscanf (_argv[p+1],"0x%x",&uart);
+ p = CheckParm ("-irq");
+ if (p)
+ sscanf (_argv[p+1],"%i",&irq);
+
+
+ printf (STR_PORTLOOK" 0x%x, irq %i\n",uart,irq);
+}
+
+
+
+
+/*
+===============
+=
+= InitPort
+=
+===============
+*/
+
+void InitPort (void)
+{
+ int mcr;
+ int temp;
+ int u;
+
+//
+// find the irq and io address of the port
+//
+ GetUart ();
+
+//
+// disable all uart interrupts
+//
+ OUTPUT( uart + INTERRUPT_ENABLE_REGISTER, 0 );
+
+//
+// init com port settings
+//
+
+ printf (STR_PORTSET"\n",115200l/baudbits);
+
+// set baud rate
+ OUTPUT(uart + LINE_CONTROL_REGISTER, 0x83);
+ OUTPUT(uart, baudbits);
+ OUTPUT(uart + 1, 0);
+
+// set line control register (N81)
+ OUTPUT(uart + LINE_CONTROL_REGISTER, 0x03);
+
+// set modem control register (OUT2+RTS+DTR)
+ OUTPUT( uart + MODEM_CONTROL_REGISTER,8+2+1);
+
+//
+// check for a 16550
+//
+ if (CheckParm("-8250"))
+ // allow a forced 8250
+ {
+ uart_type = UART_8250;
+ printf (STR_UART8250"\n\n");
+ }
+ else
+ {
+ OUTPUT ( uart + FIFO_CONTROL_REGISTER,
+ FCR_FIFO_ENABLE + FCR_TRIGGER_04 );
+ temp = INPUT( uart + INTERRUPT_ID_REGISTER );
+ if ( ( temp & 0xf8 ) == 0xc0 )
+ {
+ uart_type = UART_16550;
+ }
+ else
+ {
+ uart_type = UART_8250;
+ OUTPUT( uart + FIFO_CONTROL_REGISTER, 0 );
+ }
+ }
+
+//
+// clear out any pending uart events
+//
+ printf (STR_CLEARPEND);
+ for (u=0 ; u<16 ; u++) // clear an entire 16550 silo
+ INPUT( uart + RECEIVE_BUFFER_REGISTER );
+
+ do
+ {
+ switch( u = INPUT( uart + INTERRUPT_ID_REGISTER ) & 7 )
+ {
+ case IIR_MODEM_STATUS_INTERRUPT :
+ modem_status = INPUT( uart + MODEM_STATUS_REGISTER );
+ break;
+
+ case IIR_LINE_STATUS_INTERRUPT :
+ line_status = INPUT( uart + LINE_STATUS_REGISTER );
+ break;
+
+ case IIR_TX_HOLDING_REGISTER_INTERRUPT :
+ break;
+
+ case IIR_RX_DATA_READY_INTERRUPT :
+ INPUT( uart + RECEIVE_BUFFER_REGISTER );
+ break;
+ }
+ } while (! (u&1) );
+
+
+//
+// hook the irq vector
+//
+ irqintnum = irq + 8;
+
+ oldirqvect = getvect (irqintnum);
+ if (uart_type == UART_16550)
+ {
+ setvect (irqintnum,isr_16550);
+ printf (STR_UART16550"\n\n");
+ }
+ else
+ {
+ setvect (irqintnum,isr_8250);
+ printf (STR_UART8250"\n\n");
+
+ }
+
+
+ OUTPUT( 0x20 + 1, INPUT( 0x20 + 1 ) & ~(1<<irq) );
+
+ CLI();
+
+// enable RX and TX interrupts at the uart
+
+ OUTPUT( uart + INTERRUPT_ENABLE_REGISTER,IER_RX_DATA_READY + IER_TX_HOLDING_REGISTER_EMPTY);
+
+// enable interrupts through the interrupt controller
+
+ OUTPUT( 0x20, 0xc2 );
+
+ STI();
+}
+
+
+/*
+=============
+=
+= ShutdownPort
+=
+=============
+*/
+
+void ShutdownPort ( void )
+{
+ int u;
+
+ OUTPUT( uart + INTERRUPT_ENABLE_REGISTER, 0 );
+ OUTPUT( uart + MODEM_CONTROL_REGISTER, 0 );
+
+ for (u=0 ; u<16 ; u++) // clear an entire 16550 silo
+ INPUT( uart + RECEIVE_BUFFER_REGISTER );
+
+ OUTPUT( 0x20 + 1, INPUT( 0x20 + 1 ) | (1<<irq) );
+
+ setvect (irqintnum,oldirqvect);
+
+//
+// init com port settings to defaults
+//
+ regs.x.ax = 0xf3; //f3= 9600 n 8 1
+ regs.x.dx = comport - 1;
+ int86 (0x14, &regs, &regs);
+}
+
+
+int read_byte( void )
+{
+ int c;
+
+ if (inque.tail >= inque.head)
+ return -1;
+ c = inque.data[inque.tail&(QUESIZE-1)];
+ inque.tail++;
+ return c;
+}
+
+
+void write_byte( int c )
+{
+ outque.data[outque.head&(QUESIZE-1)] = c;
+ outque.head++;
+}
+
+
+
+//==========================================================================
+
+
+/*
+==============
+=
+= isr_8250
+=
+==============
+*/
+
+void interrupt isr_8250(void)
+{
+ int c;
+
+ while (1)
+ {
+ switch( INPUT( uart + INTERRUPT_ID_REGISTER ) & 7 )
+ {
+// not enabled
+ case IIR_MODEM_STATUS_INTERRUPT :
+ modem_status = INPUT( uart + MODEM_STATUS_REGISTER );
+ break;
+
+// not enabled
+ case IIR_LINE_STATUS_INTERRUPT :
+ line_status = INPUT( uart + LINE_STATUS_REGISTER );
+ break;
+
+//
+// transmit
+//
+ case IIR_TX_HOLDING_REGISTER_INTERRUPT :
+//I_ColorBlack (63,0,0);
+ if (outque.tail < outque.head)
+ {
+ c = outque.data[outque.tail&(QUESIZE-1)];
+ outque.tail++;
+ OUTPUT( uart + TRANSMIT_HOLDING_REGISTER, c );
+ }
+ break;
+
+//
+// receive
+//
+ case IIR_RX_DATA_READY_INTERRUPT :
+//I_ColorBlack (0,63,0);
+ c = INPUT( uart + RECEIVE_BUFFER_REGISTER );
+ inque.data[inque.head&(QUESIZE-1)] = c;
+ inque.head++;
+ break;
+
+//
+// done
+//
+ default :
+//I_ColorBlack (0,0,0);
+ OUTPUT( 0x20, 0x20 );
+ return;
+ }
+ }
+}
+
+
+/*
+==============
+=
+= isr_16550
+=
+==============
+*/
+
+void interrupt isr_16550(void)
+{
+ int c;
+ int count;
+
+ while (1)
+ {
+ switch( INPUT( uart + INTERRUPT_ID_REGISTER ) & 7 )
+ {
+// not enabled
+ case IIR_MODEM_STATUS_INTERRUPT :
+ modem_status = INPUT( uart + MODEM_STATUS_REGISTER );
+ break;
+
+// not enabled
+ case IIR_LINE_STATUS_INTERRUPT :
+ line_status = INPUT( uart + LINE_STATUS_REGISTER );
+ break;
+
+//
+// transmit
+//
+ case IIR_TX_HOLDING_REGISTER_INTERRUPT :
+//I_ColorBlack (63,0,0);
+ count = 16;
+ while (outque.tail < outque.head && count--)
+ {
+ c = outque.data[outque.tail&(QUESIZE-1)];
+ outque.tail++;
+ OUTPUT( uart + TRANSMIT_HOLDING_REGISTER, c );
+ }
+ break;
+
+//
+// receive
+//
+ case IIR_RX_DATA_READY_INTERRUPT :
+//I_ColorBlack (0,63,0);
+ do
+ {
+ c = INPUT( uart + RECEIVE_BUFFER_REGISTER );
+ inque.data[inque.head&(QUESIZE-1)] = c;
+ inque.head++;
+ } while (INPUT( uart + LINE_STATUS_REGISTER ) & LSR_DATA_READY );
+
+ break;
+
+//
+// done
+//
+ default :
+//I_ColorBlack (0,0,0);
+ OUTPUT( 0x20, 0x20 );
+ return;
+ }
+ }
+}
+
+
+/*
+===============
+=
+= jump_start
+=
+= Start up the transmition interrupts by sending the first char
+===============
+*/
+
+void jump_start( void )
+{
+ int c;
+
+ if (outque.tail < outque.head)
+ {
+ c = outque.data [outque.tail&(QUESIZE-1)];
+ outque.tail++;
+ OUTPUT( uart, c );
+ }
+}
+
+
diff --git a/sersrc/README.TXT b/sersrc/README.TXT
new file mode 100644
index 0000000..94ce053
--- /dev/null
+++ b/sersrc/README.TXT
@@ -0,0 +1 @@
+This is the source for the DOOM serial / modem driver.
diff --git a/sersrc/SERSETUP.C b/sersrc/SERSETUP.C
new file mode 100644
index 0000000..eeee006
--- /dev/null
+++ b/sersrc/SERSETUP.C
@@ -0,0 +1,680 @@
+// sersetup.c
+#define DOOM2
+#include "sersetup.h"
+//#include "serstr.h"
+#include "ser_frch.h" // FRENCH VERSION
+#include "DoomNet.h"
+
+extern que_t inque, outque;
+
+void jump_start( void );
+extern int uart;
+
+int usemodem;
+char startup[256], shutdown[256], baudrate[256];
+
+extern int baudbits;
+
+void ModemCommand (char *str);
+
+int myargc;
+char **myargv;
+
+//======================================
+//
+// I_Error
+//
+//======================================
+void I_Error(char *string)
+{
+ printf("%s\n",string);
+ exit(1);
+}
+
+/*
+================
+=
+= write_buffer
+=
+================
+*/
+
+void write_buffer( char *buffer, unsigned int count )
+{
+ int i;
+
+// if this would overrun the buffer, throw everything else out
+ if (outque.head-outque.tail+count > QUESIZE)
+ outque.tail = outque.head;
+
+ while (count--)
+ write_byte (*buffer++);
+
+ if ( INPUT( uart + LINE_STATUS_REGISTER ) & 0x40)
+ jump_start();
+}
+
+
+/*
+=================
+=
+= Error
+=
+= For abnormal program terminations
+=
+=================
+*/
+
+void Error (char *error, ...)
+{
+ va_list argptr;
+
+ if (usemodem)
+ {
+ printf ("\n");
+ printf ("\n"STR_DROPDTR"\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);
+ ModemCommand(shutdown);
+ delay (1250);
+
+ }
+
+ ShutdownPort ();
+
+ if (vectorishooked)
+ setvect (doomcom.intnum,olddoomvect);
+
+ if (error)
+ {
+ va_start (argptr,error);
+ vprintf (error,argptr);
+ va_end (argptr);
+ printf ("\n");
+ exit (1);
+ }
+
+ printf (STR_CLEANEXIT"\n");
+ exit (0);
+}
+
+
+/*
+================
+=
+= 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.head-inque.tail > QUESIZE - 4) // check for buffer overflow
+ {
+ inque.tail = inque.head;
+ newpacket = true;
+ return false;
+ }
+
+ if (newpacket)
+ {
+ packetlen = 0;
+ newpacket = 0;
+ }
+
+ do
+ {
+ c = read_byte ();
+ if (c < 0)
+ return false; // haven't read a complete packet
+//printf ("%c",c);
+ if (inescape)
+ {
+ inescape = false;
+ if (c!=FRAMECHAR)
+ {
+ newpacket = 1;
+ 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)
+ 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)
+ return;
+
+ 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
+=================
+*/
+
+void Connect (void)
+{
+ struct time time;
+ int oldsec;
+ int localstage, remotestage;
+ char str[20];
+ char idstr[7];
+ char remoteidstr[7];
+ unsigned long idnum;
+ int i;
+
+//
+// wait for a good packet
+//
+ printf (STR_ATTEMPT"\n");
+
+//
+// build a (hopefully) unique id string by hashing up the current milliseconds
+// and the interrupt table
+//
+ if (CheckParm ("-player1"))
+ idnum = 0;
+ else if (CheckParm ("-player2"))
+ idnum = 999999;
+ else
+ {
+ gettime (&time);
+ idnum = time.ti_sec*100+time.ti_hund;
+ for (i=0 ; i<512 ; i++)
+ idnum += ((unsigned far *)0)[i];
+ idnum %= 1000000;
+ }
+
+ idstr[0] = '0' + idnum/ 100000l;
+ idnum -= (idstr[0]-'0')*100000l;
+ idstr[1] = '0' + idnum/ 10000l;
+ idnum -= (idstr[1]-'0')*10000l;
+ idstr[2] = '0' + idnum/ 1000l;
+ idnum -= (idstr[2]-'0')*1000l;
+ idstr[3] = '0' + idnum/ 100l;
+ idnum -= (idstr[3]-'0')*100l;
+ idstr[4] = '0' + idnum/ 10l;
+ idnum -= (idstr[4]-'0')*10l;
+ idstr[5] = '0' + idnum;
+ idstr[6] = 0;
+
+//
+// sit in a loop until things are worked out
+//
+// the packet is: ID000000_0
+// the first field is the idnum, the second is the acknowledge stage
+// ack stage starts out 0, is bumped to 1 after the other computer's id
+// is known, and is bumped to 2 after the other computer has raised to 1
+//
+ oldsec = -1;
+ localstage = remotestage = 0;
+
+ do
+ {
+ while ( bioskey(1) )
+ {
+ if ( (bioskey (0) & 0xff) == 27)
+ Error ("\n\n"STR_NETABORT);
+ }
+
+ if (ReadPacket ())
+ {
+ packet[packetlen] = 0;
+ printf ("read : %s\n",packet);
+ if (packetlen != 10)
+ continue;
+ if (strncmp(packet,"ID",2) )
+ continue;
+ if (!strncmp (packet+2,idstr,6))
+ Error ("\n\n"STR_DUPLICATE);
+ strncpy (remoteidstr,packet+2,6);
+
+ remotestage = packet[9] - '0';
+ localstage = remotestage+1;
+ oldsec = -1;
+ }
+
+ gettime (&time);
+ if (time.ti_sec != oldsec)
+ {
+ oldsec = time.ti_sec;
+ sprintf (str,"ID%s_%i",idstr,localstage);
+ WritePacket (str,strlen(str));
+ printf ("wrote: %s\n",str);
+ }
+
+ } while (localstage < 2);
+
+//
+// decide who is who
+//
+ if (strcmp(remoteidstr,idstr) > 0)
+ doomcom.consoleplayer = 0;
+ else
+ doomcom.consoleplayer = 1;
+
+
+//
+// flush out any extras
+//
+ while (ReadPacket ())
+ ;
+}
+
+
+
+/*
+==============
+=
+= ModemCommand
+=
+==============
+*/
+
+void ModemCommand (char *str)
+{
+ int i,l;
+
+ printf (STR_MODEMCMD,str);
+ l = strlen(str);
+ for (i=0 ; i<l ; i++)
+ {
+ write_buffer (str+i,1);
+ printf ("%c",str[i]);
+ delay (100);
+ }
+
+ write_buffer ("\r",1);
+ printf ("\n");
+}
+
+
+/*
+==============
+=
+= ModemResponse
+=
+= Waits for OK, RING, CONNECT, etc
+==============
+*/
+
+char response[80];
+
+void ModemResponse (char *resp)
+{
+ int c;
+ int respptr;
+
+ do
+ {
+ printf (STR_MODEMRESP);
+ respptr=0;
+ do
+ {
+ while ( bioskey(1) )
+ {
+ if ( (bioskey (0) & 0xff) == 27)
+ Error ("\n"STR_RESPABORT);
+ }
+ 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)));
+}
+
+
+/*
+=============
+=
+= ReadLine
+=
+=============
+*/
+
+void ReadLine (FILE *f, char *dest)
+{
+ int c;
+
+ do
+ {
+ c = fgetc (f);
+ if (c == EOF || c == '\r' || c == '\n')
+ break;
+ *dest++ = c;
+ } while (1);
+ *dest = 0;
+}
+
+
+/*
+=============
+=
+= ReadModemCfg
+=
+=============
+*/
+
+void ReadModemCfg (void)
+{
+ int mcr;
+ FILE *f;
+ unsigned baud;
+
+ f = fopen ("modem.cfg","r");
+ if (!f)
+ Error (STR_CANTREAD);
+ ReadLine (f, startup);
+ ReadLine (f, shutdown);
+ ReadLine (f, baudrate);
+ fclose (f);
+
+ baud = atol(baudrate);
+ if (baud)
+ baudbits = 115200l/baud;
+
+ usemodem = true;
+}
+
+
+/*
+=============
+=
+= Dial
+=
+=============
+*/
+
+void Dial (void)
+{
+ char cmd[80];
+ int p;
+
+ ModemCommand(startup);
+ ModemResponse ("OK");
+
+ printf ("\n"STR_DIALING"\n\n");
+ p = CheckParm ("-dial");
+ sprintf (cmd,"ATDT%s",myargv[p+1]);
+
+ ModemCommand(cmd);
+ ModemResponse (STR_CONNECT);
+ doomcom.consoleplayer = 1;
+}
+
+
+/*
+=============
+=
+= Answer
+=
+=============
+*/
+
+void Answer (void)
+{
+ ModemCommand(startup);
+ ModemResponse ("OK");
+ printf ("\n"STR_WAITRING"\n\n");
+
+ ModemResponse (STR_RING);
+ ModemCommand ("ATA");
+ ModemResponse (STR_CONNECT);
+
+ doomcom.consoleplayer = 0;
+}
+
+//========================================================
+//
+// Find a Response File
+//
+//========================================================
+void FindResponseFile (void)
+{
+ int i;
+ #define MAXARGVS 100
+
+ for (i = 1;i < myargc;i++)
+ if (myargv[i][0] == '@')
+ {
+ FILE * handle;
+ int size;
+ int k;
+ int index;
+ int indexinfile;
+ char *infile;
+ char *file;
+ char *moreargs[20];
+ char *firstargv;
+
+ // READ THE RESPONSE FILE INTO MEMORY
+ handle = fopen (&myargv[i][1],"rb");
+ if (!handle)
+ I_Error (STR_NORESP);
+ printf("Found response file \"%s\"!\n",strupr(&myargv[i][1]));
+ fseek (handle,0,SEEK_END);
+ size = ftell(handle);
+ fseek (handle,0,SEEK_SET);
+ file = malloc (size);
+ fread (file,size,1,handle);
+ fclose (handle);
+
+ // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
+ for (index = 0,k = i+1; k < myargc; k++)
+ moreargs[index++] = myargv[k];
+
+ firstargv = myargv[0];
+ myargv = malloc(sizeof(char *)*MAXARGVS);
+ memset(myargv,0,sizeof(char *)*MAXARGVS);
+ myargv[0] = firstargv;
+
+ infile = file;
+ indexinfile = k = 0;
+ indexinfile++; // SKIP PAST ARGV[0] (KEEP IT)
+ do
+ {
+ myargv[indexinfile++] = infile+k;
+ while(k < size &&
+ ((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
+ k++;
+ *(infile+k) = 0;
+ while(k < size &&
+ ((*(infile+k)<= ' ') || (*(infile+k)>'z')))
+ k++;
+ } while(k < size);
+
+ for (k = 0;k < index;k++)
+ myargv[indexinfile++] = moreargs[k];
+ myargc = indexinfile;
+
+ // DISPLAY ARGS
+// printf("%d command-line args:\n",myargc);
+// for (k=1;k<myargc;k++)
+// printf("%s\n",myargv[k]);
+
+ break;
+ }
+}
+
+
+
+/*
+=================
+=
+= main
+=
+=================
+*/
+
+void main(void)
+{
+ int p;
+
+//
+// set network characteristics
+//
+ doomcom.ticdup = 1;
+ doomcom.extratics = 0;
+ doomcom.numnodes = 2;
+ doomcom.numplayers = 2;
+ doomcom.drone = 0;
+
+ printf("\n"
+ "---------------------------------\n"
+ #ifdef DOOM2
+ STR_DOOMSERIAL"\n"
+ #else
+ "DOOM SERIAL DEVICE DRIVER v1.4\n"
+ #endif
+ "---------------------------------\n");
+ myargc = _argc;
+ myargv = _argv;
+ FindResponseFile();
+
+//
+// allow override of automatic player ordering to allow a slower computer
+// to be set as player 1 allways
+//
+
+//
+// establish communications
+//
+
+ baudbits = 0x08; // default to 9600 if not specified on cmd line
+ // or in modem.cfg
+
+ if (CheckParm ("-dial") || CheckParm ("-answer") )
+ ReadModemCfg (); // may set baudbits
+
+//
+// allow command-line override of modem.cfg baud rate
+//
+ if (CheckParm ("-9600")) baudbits = 0x0c;
+ else if (CheckParm ("-14400")) baudbits = 0x08;
+ else if (CheckParm ("-19200")) baudbits = 0x06;
+ else if (CheckParm ("-38400")) baudbits = 0x03;
+ else if (CheckParm ("-57600")) baudbits = 0x02;
+ else if (CheckParm ("-115200")) baudbits = 0x01;
+
+ InitPort ();
+
+ if (CheckParm ("-dial"))
+ Dial ();
+ else if (CheckParm ("-answer"))
+ Answer ();
+
+ Connect ();
+
+//
+// launch DOOM
+//
+ LaunchDOOM ();
+
+ Error (NULL);
+}
+
diff --git a/sersrc/SERSETUP.H b/sersrc/SERSETUP.H
new file mode 100644
index 0000000..7bb8f5e
--- /dev/null
+++ b/sersrc/SERSETUP.H
@@ -0,0 +1,102 @@
+#include <conio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <conio.h>
+#include <ctype.h>
+#include <dos.h>
+#include <process.h>
+#include <stdarg.h>
+#include <bios.h>
+#include <ctype.h>
+
+
+#define INPUT(port) inportb(port)
+#define OUTPUT(port,data) outportb(port,data)
+#define CLI() disable()
+#define STI() enable()
+
+
+typedef enum {false, true} boolean;
+typedef unsigned char byte;
+
+
+#define TRANSMIT_HOLDING_REGISTER 0x00
+#define RECEIVE_BUFFER_REGISTER 0x00
+#define INTERRUPT_ENABLE_REGISTER 0x01
+#define IER_RX_DATA_READY 0x01
+#define IER_TX_HOLDING_REGISTER_EMPTY 0x02
+#define IER_LINE_STATUS 0x04
+#define IER_MODEM_STATUS 0x08
+#define INTERRUPT_ID_REGISTER 0x02
+#define IIR_MODEM_STATUS_INTERRUPT 0x00
+#define IIR_TX_HOLDING_REGISTER_INTERRUPT 0x02
+#define IIR_RX_DATA_READY_INTERRUPT 0x04
+#define IIR_LINE_STATUS_INTERRUPT 0x06
+#define FIFO_CONTROL_REGISTER 0x02
+#define FCR_FIFO_ENABLE 0x01
+#define FCR_RCVR_FIFO_RESET 0x02
+#define FCR_XMIT_FIFO_RESET 0x04
+#define FCR_RCVR_TRIGGER_LSB 0x40
+#define FCR_RCVR_TRIGGER_MSB 0x80
+#define FCR_TRIGGER_01 0x00
+#define FCR_TRIGGER_04 0x40
+#define FCR_TRIGGER_08 0x80
+#define FCR_TRIGGER_14 0xc0
+#define LINE_CONTROL_REGISTER 0x03
+#define LCR_WORD_LENGTH_MASK 0x03
+#define LCR_WORD_LENGTH_SELECT_0 0x01
+#define LCR_WORD_LENGTH_SELECT_1 0x02
+#define LCR_STOP_BITS 0x04
+#define LCR_PARITY_MASK 0x38
+#define LCR_PARITY_ENABLE 0x08
+#define LCR_EVEN_PARITY_SELECT 0x10
+#define LCR_STICK_PARITY 0x20
+#define LCR_SET_BREAK 0x40
+#define LCR_DLAB 0x80
+#define MODEM_CONTROL_REGISTER 0x04
+#define MCR_DTR 0x01
+#define MCR_RTS 0x02
+#define MCR_OUT1 0x04
+#define MCR_OUT2 0x08
+#define MCR_LOOPBACK 0x10
+#define LINE_STATUS_REGISTER 0x05
+#define LSR_DATA_READY 0x01
+#define LSR_OVERRUN_ERROR 0x02
+#define LSR_PARITY_ERROR 0x04
+#define LSR_FRAMING_ERROR 0x08
+#define LSR_BREAK_DETECT 0x10
+#define LSR_THRE 0x20
+#define MODEM_STATUS_REGISTER 0x06
+#define MSR_DELTA_CTS 0x01
+#define MSR_DELTA_DSR 0x02
+#define MSR_TERI 0x04
+#define MSR_DELTA_CD 0x08
+#define MSR_CTS 0x10
+#define MSR_DSR 0x20
+#define MSR_RI 0x40
+#define MSR_CD 0x80
+#define DIVISOR_LATCH_LOW 0x00
+#define DIVISOR_LATCH_HIGH 0x01
+
+
+
+#define QUESIZE 2048
+
+typedef struct
+{
+ long head, tail; // bytes are put on head and pulled from tail
+ unsigned char data[QUESIZE];
+} que_t;
+
+void InitPort (void);
+void ShutdownPort (void);
+
+int read_byte( void );
+void write_byte( int c );
+
+
+void Error (char *error, ...);
+
+extern int argc;
+extern char **argv;
diff --git a/sersrc/SERSTR.H b/sersrc/SERSTR.H
new file mode 100644
index 0000000..39ce5dc
--- /dev/null
+++ b/sersrc/SERSTR.H
@@ -0,0 +1,21 @@
+#define STR_DROPDTR "Dropping DTR"
+#define STR_CLEANEXIT "Clean exit from SERSETUP"
+#define STR_ATTEMPT "Attempting to connect across serial link, press escape to abort."
+#define STR_NETABORT "Network game synchronization aborted."
+#define STR_DUPLICATE "Duplicate id string, try again or check modem init string."
+#define STR_MODEMCMD "Modem command : "
+#define STR_MODEMRESP "Modem response: "
+#define STR_RESPABORT "Modem response aborted."
+#define STR_CANTREAD "Couldn't read MODEM.CFG"
+#define STR_DIALING "Dialing..."
+#define STR_CONNECT "CONNECT"
+#define STR_WAITRING "Waiting for ring..."
+#define STR_RING "RING"
+#define STR_NORESP "No such response file!"
+#define STR_DOOMSERIAL "DOOM II SERIAL DEVICE DRIVER v1.4"
+#define STR_WARNING \
+"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> parameter.\n"
+#define STR_COMM "Communicating with interrupt vector 0x%x"
+#define STR_RETURNED "Returned from DOOM II"
+#define STR_PORTSET "Setting port to %lu baud"
diff --git a/sersrc/SER_FRCH.H b/sersrc/SER_FRCH.H
new file mode 100644
index 0000000..f265058
--- /dev/null
+++ b/sersrc/SER_FRCH.H
@@ -0,0 +1,25 @@
+#define STR_DROPDTR "Abandon de DTR"
+#define STR_CLEANEXIT "Sortie normale de SERSETUP"
+#define STR_ATTEMPT "Tentative de connexion en s‚rie, appuyez sur ESC pour annuler."
+#define STR_NETABORT "Synchronisation de jeu sur r‚seau annul‚e."
+#define STR_DUPLICATE "ChaŒne id en double. R‚essayez ou v‚rifiez la chaŒne d'initialistion du modem."
+#define STR_MODEMCMD "Commande du modem: "
+#define STR_MODEMRESP "R‚ponse du modem: "
+#define STR_RESPABORT "R‚ponse du modem annul‚e."
+#define STR_CANTREAD "Lecture de MODEM.CFG impossible"
+#define STR_DIALING "Composition du num‚ro..."
+#define STR_CONNECT "CONNECTION"
+#define STR_WAITRING "Attente d'appel..."
+#define STR_RING "APPEL"
+#define STR_NORESP "Ce fichier de r‚ponse n'existe pas!"
+#define STR_DOOMSERIAL "GESTIONNAIRE DE LIAISON SERIE DOOM II v1.4"
+#define STR_WARNING \
+"Attention: pas de vecteurs d'interruption NULL ou iret trouv‚s entre 0x60 et 0x66.\n"\
+"Vous pouvez sp‚cifier un vecteur avec le paramŠtre -vector 0x<num‚ro>."
+#define STR_COMM "Communication avec le vecteur d'interruption 0x%x"
+#define STR_RETURNED "Retour de DOOM II"
+#define STR_PORTLOOK "Recherche de l'UART sur le port"
+#define STR_UART8250 "UART = 8250"
+#define STR_UART16550 "UART = 16550"
+#define STR_CLEARPEND "Riinitilisation des interruptions en attente.\n"
+#define STR_PORTSET "Réglage du port à %lu baud"