summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTravis Bradshaw <travis.bradshaw@idsoftware.com>2012-01-31 15:32:25 -0600
committerTravis Bradshaw <travis.bradshaw@idsoftware.com>2012-01-31 15:32:25 -0600
commit73424b6129f1c3ca9fc22aedcfe1f5330db137a9 (patch)
tree08514cf10746e3b3bf3d7884800b0a8f8d9df919
parent4eb368a960647c8cc82d721d0183629ae10759d1 (diff)
Adding the release of the DOOM IPX driver.
-rw-r--r--ipx/DOOMNET.C73
-rw-r--r--ipx/DOOMNET.H58
-rw-r--r--ipx/IPXNET.C294
-rw-r--r--ipx/IPXNET.H117
-rw-r--r--ipx/IPXSETUP.C420
-rw-r--r--ipx/IPXSTR.H19
-rw-r--r--ipx/IPX_FRCH.H21
-rw-r--r--ipx/README1
8 files changed, 1003 insertions, 0 deletions
diff --git a/ipx/DOOMNET.C b/ipx/DOOMNET.C
new file mode 100644
index 0000000..0f9c55b
--- /dev/null
+++ b/ipx/DOOMNET.C
@@ -0,0 +1,73 @@
+//#define DOOM2
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+#include <conio.h>
+#include <dos.h>
+
+#include "doomnet.h"
+//#include "ipxstr.h"
+#include "ipx_frch.h" // FRENCH VERSION
+
+doomcom_t doomcom;
+int vectorishooked;
+void interrupt (*olddoomvect) (void);
+
+
+
+/*
+=============
+=
+= 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;
+
+// prepare for DOOM
+ doomcom.id = DOOMCOM_ID;
+
+// hook the interrupt vector
+ olddoomvect = getvect (doomcom.intnum);
+ setvect (doomcom.intnum,(void interrupt (*)(void))MK_FP(_CS,
+(int)NetISR));
+ vectorishooked = 1;
+
+// build the argument list for DOOM, adding a -net &doomcom
+ memcpy (newargs, _argv, (_argc+1)*2);
+ newargs[_argc] = "-net";
+ flatadr = (long)_DS*16 + (unsigned)&doomcom;
+ sprintf (adrstring,"%lu",flatadr);
+ newargs[_argc+1] = adrstring;
+ newargs[_argc+2] = NULL;
+
+ 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/ipx/DOOMNET.H b/ipx/DOOMNET.H
new file mode 100644
index 0000000..f0319d9
--- /dev/null
+++ b/ipx/DOOMNET.H
@@ -0,0 +1,58 @@
+// 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/ipx/IPXNET.C b/ipx/IPXNET.C
new file mode 100644
index 0000000..f2fa935
--- /dev/null
+++ b/ipx/IPXNET.C
@@ -0,0 +1,294 @@
+// ipxnet.c
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dos.h>
+#include <string.h>
+#include <process.h>
+#include <values.h>
+
+#include "ipxnet.h"
+
+/*
+==========================================================================
+===
+
+ IPX PACKET DRIVER
+
+==========================================================================
+===
+*/
+
+packet_t packets[NUMPACKETS];
+
+nodeadr_t nodeadr[MAXNETNODES+1]; // first is local, last is broadcast
+
+nodeadr_t remoteadr; // set by each GetPacket
+
+localadr_t localadr; // set at startup
+
+extern int socketid;
+
+void far (*IPX)(void);
+
+long localtime; // for time stamp in packets
+long remotetime;
+
+//===========================================================================
+
+int OpenSocket(short socketNumber)
+{
+ _DX = socketNumber;
+ _BX = 0;
+ _AL = 0;
+ IPX();
+ if(_AL)
+ Error ("OpenSocket: 0x%x", _AL);
+ return _DX;
+}
+
+
+void CloseSocket(short socketNumber)
+{
+ _DX = socketNumber;
+ _BX = 1;
+ IPX();
+}
+
+void ListenForPacket(ECB *ecb)
+{
+ _SI = FP_OFF(ecb);
+ _ES = FP_SEG(ecb);
+ _BX = 4;
+ IPX();
+ if(_AL)
+ Error ("ListenForPacket: 0x%x", _AL);
+}
+
+
+void GetLocalAddress (void)
+{
+ _SI = FP_OFF(&localadr);
+ _ES = FP_SEG(&localadr);
+ _BX = 9;
+ IPX();
+}
+
+
+
+/*
+====================
+=
+= InitNetwork
+=
+====================
+*/
+
+void InitNetwork (void)
+{
+ int i,j;
+
+//
+// get IPX function address
+//
+ _AX = 0x7a00;
+ geninterrupt(0x2f);
+ if(_AL != 0xff)
+ Error ("IPX not detected\n");
+ IPX = MK_FP(_ES, _DI);
+
+
+//
+// allocate a socket for sending and receiving
+//
+ socketid = OpenSocket ( (socketid>>8) + ((socketid&255)<<8) );
+
+ GetLocalAddress();
+
+//
+// set up several receiving ECBs
+//
+ memset (packets,0,NUMPACKETS*sizeof(packet_t));
+
+ for (i=1 ; i<NUMPACKETS ; i++)
+ {
+ packets[i].ecb.ECBSocket = socketid;
+ packets[i].ecb.FragmentCount = 1;
+ packets[i].ecb.fAddress[0] = FP_OFF(&packets[i].ipx);
+ packets[i].ecb.fAddress[1] = FP_SEG(&packets[i].ipx);
+ packets[i].ecb.fSize = sizeof(packet_t)-sizeof(ECB);
+
+ ListenForPacket (&packets[i].ecb);
+ }
+
+//
+// set up a sending ECB
+//
+ memset (&packets[0],0,sizeof(packets[0]));
+
+ packets[0].ecb.ECBSocket = socketid;
+ packets[0].ecb.FragmentCount = 2;
+ packets[0].ecb.fAddress[0] = FP_OFF(&packets[0].ipx);
+ packets[0].ecb.fAddress[1] = FP_SEG(&packets[0].ipx);
+ for (j=0 ; j<4 ; j++)
+ packets[0].ipx.dNetwork[j] = localadr.network[j];
+ packets[0].ipx.dSocket[0] = socketid&255;
+ packets[0].ipx.dSocket[1] = socketid>>8;
+ packets[0].ecb.f2Address[0] = FP_OFF(&doomcom.data);
+ packets[0].ecb.f2Address[1] = FP_SEG(&doomcom.data);
+
+// known local node at 0
+ for (i=0 ; i<6 ; i++)
+ nodeadr[0].node[i] = localadr.node[i];
+
+// broadcast node at MAXNETNODES
+ for (j=0 ; j<6 ; j++)
+ nodeadr[MAXNETNODES].node[j] = 0xff;
+}
+
+
+/*
+====================
+=
+= ShutdownNetwork
+=
+====================
+*/
+
+void ShutdownNetwork (void)
+{
+ if (IPX)
+ CloseSocket (socketid);
+}
+
+
+/*
+==============
+=
+= SendPacket
+=
+= A destination of MAXNETNODES is a broadcast
+==============
+*/
+
+void SendPacket (int destination)
+{
+ int j;
+
+// set the time
+ packets[0].time = localtime;
+
+// set the address
+ for (j=0 ; j<6 ; j++)
+ packets[0].ipx.dNode[j] =
+packets[0].ecb.ImmediateAddress[j] =
+ nodeadr[destination].node[j];
+
+// set the length (ipx + time + datalength)
+ packets[0].ecb.fSize = sizeof(IPXPacket) + 4;
+ packets[0].ecb.f2Size = doomcom.datalength + 4;
+
+// send the packet
+ _SI = FP_OFF(&packets[0]);
+ _ES = FP_SEG(&packets[0]);
+ _BX = 3;
+ IPX();
+ if(_AL)
+ Error("SendPacket: 0x%x", _AL);
+
+ while(packets[0].ecb.InUseFlag != 0)
+ {
+ // IPX Relinquish Control - polled drivers MUST have this here!
+ _BX = 10;
+ IPX();
+ }
+}
+
+
+unsigned short ShortSwap (unsigned short i)
+{
+ return ((i&255)<<8) + ((i>>8)&255);
+}
+
+/*
+==============
+=
+= GetPacket
+=
+= Returns false if no packet is waiting
+=
+==============
+*/
+
+int GetPacket (void)
+{
+ int packetnum;
+ int i, j;
+ long besttic;
+ packet_t *packet;
+
+// if multiple packets are waiting, return them in order by time
+
+ besttic = MAXLONG;
+ packetnum = -1;
+ doomcom.remotenode = -1;
+
+ for ( i = 1 ; i < NUMPACKETS ; i++)
+ {
+ if (packets[i].ecb.InUseFlag)
+ {
+ continue;
+ }
+
+ if (packets[i].time < besttic)
+ {
+ besttic = packets[i].time;
+ packetnum = i;
+ }
+ }
+
+ if (besttic == MAXLONG)
+ return 0; // no packets
+
+ packet = &packets[packetnum];
+
+ if (besttic == -1 && localtime != -1)
+ {
+ ListenForPacket (&packet->ecb);
+ return 0; // setup broadcast from other game
+ }
+
+ remotetime = besttic;
+
+//
+// got a good packet
+//
+ if (packet->ecb.CompletionCode)
+ Error ("GetPacket: ecb.ComletionCode = 0x%x",packet->ecb.CompletionCode);
+
+// set remoteadr to the sender of the packet
+ memcpy (&remoteadr, packet->ipx.sNode, sizeof(remoteadr));
+ for (i=0 ; i<doomcom.numnodes ; i++)
+ if (!memcmp(&remoteadr, &nodeadr[i], sizeof(remoteadr)))
+ break;
+ if (i < doomcom.numnodes)
+ doomcom.remotenode = i;
+ else
+ {
+ if (localtime != -1)
+ { // this really shouldn't happen
+ ListenForPacket (&packet->ecb);
+ return 0;
+ }
+ }
+
+// copy out the data
+ doomcom.datalength = ShortSwap(packet->ipx.PacketLength) - 38;
+ memcpy (&doomcom.data, &packet->data, doomcom.datalength);
+
+// repost the ECB
+ ListenForPacket (&packet->ecb);
+
+ return 1;
+}
+
diff --git a/ipx/IPXNET.H b/ipx/IPXNET.H
new file mode 100644
index 0000000..2c5e14d
--- /dev/null
+++ b/ipx/IPXNET.H
@@ -0,0 +1,117 @@
+// ipxnet.h
+
+
+typedef struct
+{
+ char private[512];
+} doomdata_t;
+
+
+#include "DoomNet.h"
+
+//===========================================================================
+
+#define NUMPACKETS 10 // max outstanding packets before loss
+
+// setupdata_t is used as doomdata_t during setup
+typedef struct
+{
+ short gameid; // so multiple games can setup at once
+ short drone;
+ short nodesfound;
+ short nodeswanted;
+} setupdata_t;
+
+
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long LONG;
+
+typedef struct IPXPacketStructure
+{
+ WORD PacketCheckSum; /* high-low */
+ WORD PacketLength; /* high-low */
+ BYTE PacketTransportControl;
+ BYTE PacketType;
+
+ BYTE dNetwork[4]; /* high-low */
+ BYTE dNode[6]; /* high-low */
+ BYTE dSocket[2]; /* high-low */
+
+ BYTE sNetwork[4]; /* high-low */
+ BYTE sNode[6]; /* high-low */
+ BYTE sSocket[2]; /* high-low */
+} IPXPacket;
+
+
+typedef struct
+{
+ BYTE network[4]; /* high-low */
+ BYTE node[6]; /* high-low */
+} localadr_t;
+
+typedef struct
+{
+ BYTE node[6]; /* high-low */
+} nodeadr_t;
+
+typedef struct ECBStructure
+{
+ WORD Link[2]; /* offset-segment */
+ WORD ESRAddress[2]; /* offset-segment */
+ BYTE InUseFlag;
+ BYTE CompletionCode;
+ WORD ECBSocket; /* high-low */
+ BYTE IPXWorkspace[4]; /* N/A */
+ BYTE DriverWorkspace[12]; /* N/A */
+ BYTE ImmediateAddress[6]; /* high-low */
+ WORD FragmentCount; /* low-high */
+
+ WORD fAddress[2]; /* offset-segment */
+ WORD fSize; /* low-high */
+
+ WORD f2Address[2]; /* offset-segment */
+ WORD f2Size; /* low-high */
+} ECB;
+
+
+// time is used by the communication driver to sequence packets returned
+// to DOOM when more than one is waiting
+
+typedef struct
+{
+ ECB ecb;
+ IPXPacket ipx;
+
+ long time;
+ doomdata_t data;
+} packet_t;
+
+
+extern doomcom_t doomcom;
+extern int gameid;
+
+extern nodeadr_t nodeadr[MAXNETNODES+1];
+extern int localnodenum;
+
+extern long localtime; // for time stamp in packets
+extern long remotetime; // timestamp of last packet gotten
+
+extern nodeadr_t remoteadr;
+
+extern int myargc;
+
+extern char **myargv;
+
+void Error (char *error, ...);
+
+
+void InitNetwork (void);
+void ShutdownNetwork (void);
+void SendPacket (int destination);
+int GetPacket (void);
+int CheckParm (char *check);
+
+void PrintAddress (nodeadr_t *adr, char *str);
+
diff --git a/ipx/IPXSETUP.C b/ipx/IPXSETUP.C
new file mode 100644
index 0000000..c5f3099
--- /dev/null
+++ b/ipx/IPXSETUP.C
@@ -0,0 +1,420 @@
+// ipxsetup.c
+
+#define DOOM2
+
+#include <conio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dos.h>
+#include <string.h>
+#include <process.h>
+#include <stdarg.h>
+#include <bios.h>
+
+#include "ipxnet.h"
+//#include "ipxstr.h"
+#include "ipx_frch.h" // FRENCH VERSION
+
+int gameid;
+int numnetnodes;
+int socketid = 0x869c; // 0x869c is the official DOOM socket
+int myargc;
+char **myargv;
+
+setupdata_t nodesetup[MAXNETNODES];
+
+
+/*
+=================
+=
+= Error
+=
+= For abnormal program terminations
+=
+=================
+*/
+
+void Error (char *error, ...)
+{
+ va_list argptr;
+
+ if (vectorishooked)
+ setvect (doomcom.intnum,olddoomvect);
+
+ va_start (argptr,error);
+ vprintf (error,argptr);
+ va_end (argptr);
+ printf ("\n");
+ ShutdownNetwork ();
+ exit (1);
+}
+
+
+/*
+=================
+=
+= 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 *parm)
+ {
+ int i;
+
+ for(i = 1; i < myargc; i++)
+ if(stricmp(parm, myargv[i]) == 0)
+ return i;
+
+ return 0;
+ }
+
+
+/*
+=============
+=
+= NetISR
+=
+=============
+*/
+
+void interrupt NetISR (void)
+{
+ if (doomcom.command == CMD_SEND)
+ {
+ localtime++;
+ SendPacket (doomcom.remotenode);
+ }
+ else if (doomcom.command == CMD_GET)
+ {
+ GetPacket ();
+ }
+}
+
+
+
+/*
+===================
+=
+= LookForNodes
+=
+= Finds all the nodes for the game and works out player numbers among
+them
+=
+= Exits with nodesetup[0..numnodes] and nodeadr[0..numnodes] filled in
+===================
+*/
+
+void LookForNodes (void)
+{
+ int i,j,k;
+ int netids[MAXNETNODES];
+ int netplayer[MAXNETNODES];
+ struct time time;
+ int oldsec;
+ setupdata_t *setup, *dest;
+ char str[80];
+ int total, console;
+
+//
+// wait until we get [numnetnodes] packets, then start playing
+// the playernumbers are assigned by netid
+//
+ printf(STR_ATTEMPT, numnetnodes);
+
+ printf (STR_LOOKING);
+
+ oldsec = -1;
+ setup = (setupdata_t *)&doomcom.data;
+ localtime = -1; // in setup time, not game time
+
+//
+// build local setup info
+//
+ nodesetup[0].nodesfound = 1;
+ nodesetup[0].nodeswanted = numnetnodes;
+ doomcom.numnodes = 1;
+
+ do
+ {
+//
+// check for aborting
+//
+ while ( bioskey(1) )
+ {
+ if ( (bioskey (0) & 0xff) == 27)
+ Error ("\n\n"STR_NETABORT);
+ }
+
+//
+// listen to the network
+//
+ while (GetPacket ())
+ {
+ if (doomcom.remotenode == -1)
+ dest = &nodesetup[doomcom.numnodes];
+ else
+ dest = &nodesetup[doomcom.remotenode];
+
+ if (remotetime != -1)
+ { // an early game packet, not a setup packet
+ if (doomcom.remotenode == -1)
+ Error (STR_UNKNOWN);
+ // if it allready started, it must have found all nodes
+ dest->nodesfound = dest->nodeswanted;
+ continue;
+ }
+
+ // update setup ingo
+ memcpy (dest, setup, sizeof(*dest) );
+
+ if (doomcom.remotenode != -1)
+ continue; // allready know that node address
+
+ //
+ // this is a new node
+ //
+ memcpy (&nodeadr[doomcom.numnodes], &remoteadr
+ , sizeof(nodeadr[doomcom.numnodes]) );
+
+ //
+ // if this node has a lower address, take all startup info
+ //
+ if ( memcmp (&remoteadr, &nodeadr[0], sizeof(&remoteadr) )
+< 0 )
+ {
+ }
+
+ doomcom.numnodes++;
+
+ printf ("\n"STR_FOUND"\n");
+
+ if (doomcom.numnodes < numnetnodes)
+ printf (STR_LOOKING);
+ }
+//
+// we are done if all nodes have found all other nodes
+//
+ for (i=0 ; i<doomcom.numnodes ; i++)
+ if (nodesetup[i].nodesfound != nodesetup[i].nodeswanted)
+ break;
+
+ if (i == nodesetup[0].nodeswanted)
+ break; // got them all
+
+//
+// send out a broadcast packet every second
+//
+ gettime (&time);
+ if (time.ti_sec == oldsec)
+ continue;
+ oldsec = time.ti_sec;
+
+ printf (".");
+ doomcom.datalength = sizeof(*setup);
+
+ nodesetup[0].nodesfound = doomcom.numnodes;
+
+ memcpy (&doomcom.data, &nodesetup[0], sizeof(*setup));
+
+ SendPacket (MAXNETNODES); // send to all
+
+ } while (1);
+
+//
+// count players
+//
+ total = 0;
+ console = 0;
+
+ for (i=0 ; i<numnetnodes ; i++)
+ {
+ if (nodesetup[i].drone)
+ continue;
+ total++;
+ if (total > MAXPLAYERS)
+ Error (STR_MORETHAN,MAXPLAYERS);
+ if (memcmp (&nodeadr[i], &nodeadr[0], sizeof(nodeadr[0])) < 0)
+ console++;
+ }
+
+
+ if (!total)
+ Error (STR_NONESPEC);
+
+ doomcom.consoleplayer = console;
+ doomcom.numplayers = total;
+
+ printf (STR_CONSOLEIS"\n", console+1, total);
+}
+
+
+//========================================================
+//
+// 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)
+ Error (STR_NORESP);
+ printf(STR_FOUNDRESP" \"%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 i;
+ unsigned char far *vector;
+
+//
+// determine game parameters
+//
+ gameid = 0;
+ numnetnodes = 2;
+ doomcom.ticdup = 1;
+ doomcom.extratics = 1;
+ doomcom.episode = 1;
+ doomcom.map = 1;
+ doomcom.skill = 2;
+ doomcom.deathmatch = 0;
+
+ printf("\n"
+ "-----------------------------\n"
+ #ifdef DOOM2
+ STR_DOOMNETDRV"\n"
+ #else
+ "DOOM NETWORK DEVICE DRIVER\n"
+ #endif
+ "v1.22\n"
+ "-----------------------------\n");
+
+ myargc = _argc;
+ myargv = _argv;
+ FindResponseFile();
+
+ if((i = CheckParm("-nodes")) != 0)
+ numnetnodes = atoi(myargv[i+1]);
+
+ if((i = CheckParm("-vector")) != 0)
+ {
+ doomcom.intnum = sscanf ("0x%x",myargv[i+1]);
+ vector = *(char far * far *)(doomcom.intnum*4);
+ if(vector != NULL && *vector != 0xcf)
+ {
+ printf(STR_VECTSPEC"\n", doomcom.intnum);
+ exit(-1);
+ }
+ }
+ else
+ {
+ for(doomcom.intnum = 0x60 ; doomcom.intnum <= 0x66 ;
+doomcom.intnum++)
+ {
+ vector = *(char far * far *)(doomcom.intnum*4);
+ if(vector == NULL || *vector == 0xcf)
+ break;
+ }
+ if(doomcom.intnum == 0x67)
+ {
+ printf(STR_NONULL"\n");
+ exit(-1);
+ }
+ }
+ printf(STR_COMMVECT"\n",doomcom.intnum);
+
+ if((i = CheckParm("-port")) != 0)
+ {
+ socketid = atoi (myargv[i+1]);
+ printf (STR_USEALT"\n", socketid);
+ }
+
+ InitNetwork ();
+
+ LookForNodes ();
+
+ localtime = 0;
+
+ LaunchDOOM ();
+
+ ShutdownNetwork ();
+
+ if (vectorishooked)
+ setvect (doomcom.intnum,olddoomvect);
+
+ exit(0);
+ }
+
+
diff --git a/ipx/IPXSTR.H b/ipx/IPXSTR.H
new file mode 100644
index 0000000..ac2995a
--- /dev/null
+++ b/ipx/IPXSTR.H
@@ -0,0 +1,19 @@
+#define STR_NETABORT "Network game synchronization aborted."
+#define STR_UNKNOWN "Got an unknown game packet during setup"
+#define STR_FOUND "Found a node!"
+#define STR_LOOKING "Looking for a node"
+#define STR_MORETHAN "More than %i players specified!"
+#define STR_NONESPEC "No players specified for game!"
+#define STR_CONSOLEIS "Console is player %i of %i"
+#define STR_NORESP "No such response file!"
+#define STR_FOUNDRESP "Found response file"
+#define STR_DOOMNETDRV "DOOM II NETWORK DEVICE DRIVER"
+#define STR_VECTSPEC "The specified vector (0x%02x) was already hooked."
+#define STR_NONULL \
+"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."
+#define STR_COMMVECT "Communicating with interrupt vector 0x%x"
+#define STR_USEALT "Using alternate port %i for network"
+#define STR_RETURNED "Returned from DOOM II"
+#define STR_ATTEMPT "Attempting to find all players for %i player net play. "\
+ "Press ESC to exit.\n"
diff --git a/ipx/IPX_FRCH.H b/ipx/IPX_FRCH.H
new file mode 100644
index 0000000..6178eea
--- /dev/null
+++ b/ipx/IPX_FRCH.H
@@ -0,0 +1,21 @@
+#define STR_NETABORT "Synchronisation du jeu sur r‚seau annul‚e."
+#define STR_UNKNOWN "Paquet de jeu inconnu durant la configuration"
+#define STR_FOUND "Noeud d‚tect‚!"
+#define STR_LOOKING "Recherche d'un noeud"
+#define STR_MORETHAN "Plus de %i joueurs sp‚cifi‚s!"
+#define STR_NONESPEC "Pas de joueurs sp‚cifi‚s pour le jeu!"
+#define STR_CONSOLEIS "Console: joueur %i sur %i"
+#define STR_NORESP "Ce fichier de r‚ponse n'existe pas!"
+#define STR_FOUNDRESP "Fichier de r‚ponse trouv‚"
+#define STR_DOOMNETDRV "GESTIONNAIRE DE RESEAU DOOM II"
+#define STR_VECTSPEC "Le vecteur sp‚cifi‚ (0x%02x) ‚tait d‚j… connect‚."
+#define STR_NONULL \
+"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_COMMVECT "Communication avec le vecteur d'interruption 0x%x"
+#define STR_USEALT "Utilisation du port alternatif %i pour le r‚seau"
+#define STR_RETURNED "Retour de DOOM II"
+#define STR_ATTEMPT \
+"Tentatative de recherche de tous les joueurs pour le jeu en riseau `%i jouers\n" \
+"Appuyez sur ECHAP pour quitter.\n"
+
diff --git a/ipx/README b/ipx/README
new file mode 100644
index 0000000..d96a75b
--- /dev/null
+++ b/ipx/README
@@ -0,0 +1 @@
+This is the source for the DOOM ipx network driver.