616 lines
17 KiB
C
616 lines
17 KiB
C
/*
|
|
Copyright (C) 1994-1995 Apogee Software, Ltd.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
// ipxsetup.c
|
|
|
|
#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 <time.h>
|
|
|
|
#include "..\rottnet.h"
|
|
#include "ipxnet.h"
|
|
|
|
#define VERSION "1.3"
|
|
|
|
int numnetnodes;
|
|
unsigned socketid = 0x882a; // 0x882a is the official ROTT socket
|
|
int myargc;
|
|
char **myargv;
|
|
|
|
boolean server;
|
|
boolean standalone;
|
|
boolean master;
|
|
|
|
setupdata_t nodesetup;
|
|
#define MAXNETMESSAGES 25
|
|
static int messagesused;
|
|
static boolean StringUsed[MAXNETMESSAGES];
|
|
static char * NetStrings[MAXNETMESSAGES]=
|
|
{
|
|
{"\nUm, I'm sure Player %d will join us soon.\n"},
|
|
{"\nPlayer %d is starting to tick me off.\n"},
|
|
{"\nIt seems Player %d has gone for a Moon Pie.\n"},
|
|
{"\nHow long can Player %d take setting the dang thing up?\n"},
|
|
{"\nPlayer %d...where are you?\n"},
|
|
{"\nSigh. Player %d is a toadie.\n"},
|
|
{"\nGo give Player %d a good swift kick in the...head.\n"},
|
|
{"\nIs Player %d running off a removable drive or something?\n"},
|
|
{"\nPlayer %d is a popo-head.\n"},
|
|
{"\nPlayer %d is attempting to escape off the map.\n"},
|
|
{"\nPLAYER %d!!!! GOON!\n"},
|
|
{"\nYou know, waiting for Player %d reminds me of a story....\n"},
|
|
{"\nTwo Player %d's walk into a bar....\n"},
|
|
{"\nHow many Player %d's does it take to change a lightbulb?\n"
|
|
"None, 'cause they don't DO anything. They just SIT there.\n"},
|
|
{"\nANY TIME NOW PLAYER %d!!!\n"},
|
|
{"\nI hear Player %d sucks dog's toes.\n"},
|
|
{"\nWho votes that Player %d gets left outta this game (y/n)?\n"},
|
|
{"\nLunch break's over, Player %d!\n"},
|
|
{"\nWe're all waiting, Player %d.... Hello, McFly!!!\n"},
|
|
{"\nNumber %d Player, our Number 1 delayer....\n"},
|
|
{"\nINSTRUCTIONS: Player %d runs the setup program....\n"},
|
|
{"\nOnce Player %d deigns to join us, let's toast 'em.\n"},
|
|
{"\nPssst...If you go wake up Player %d, I'll put you in God mode.\n"},
|
|
{"\nOkay, when we start, I'm giving Player %d only 5 hit points.\n"},
|
|
{"\nIs Player %d in Shrooms Mode or what?\n"}
|
|
};
|
|
|
|
/*
|
|
=============
|
|
=
|
|
= NetISR
|
|
=
|
|
=============
|
|
*/
|
|
|
|
void NetISR (void)
|
|
{
|
|
if (rottcom.command == CMD_SEND)
|
|
{
|
|
ipxlocaltime++;
|
|
SendPacket (rottcom.remotenode);
|
|
}
|
|
else if (rottcom.command == CMD_GET)
|
|
{
|
|
GetPacket ();
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= Shutdown
|
|
=
|
|
=================
|
|
*/
|
|
|
|
void Shutdown ( void )
|
|
{
|
|
ShutdownROTTCOM ();
|
|
ShutdownNetwork();
|
|
}
|
|
|
|
/*
|
|
===================
|
|
=
|
|
= SetupRandomMessages
|
|
=
|
|
===================
|
|
*/
|
|
void SetupRandomMessages ( void )
|
|
{
|
|
messagesused=0;
|
|
memset(StringUsed,0,sizeof(StringUsed));
|
|
randomize();
|
|
}
|
|
|
|
/*
|
|
===================
|
|
=
|
|
= PrintRandomMessage
|
|
=
|
|
===================
|
|
*/
|
|
void PrintRandomMessage (int message, int player)
|
|
{
|
|
printf(NetStrings[message],player);
|
|
}
|
|
|
|
/*
|
|
===================
|
|
=
|
|
= GetRandomMessage
|
|
=
|
|
===================
|
|
*/
|
|
int GetRandomMessage ( void )
|
|
{
|
|
boolean found=false;
|
|
int num;
|
|
|
|
if (messagesused==MAXNETMESSAGES)
|
|
SetupRandomMessages();
|
|
|
|
while (found==false)
|
|
{
|
|
num = random(MAXNETMESSAGES);
|
|
if (StringUsed[num]==false)
|
|
{
|
|
StringUsed[num]=true;
|
|
found=true;
|
|
messagesused++;
|
|
}
|
|
}
|
|
return num;
|
|
}
|
|
|
|
#define client_NoResponse 0
|
|
#define client_Echoed 1
|
|
#define client_Done 2
|
|
|
|
int playernumber;
|
|
int clientstate[MAXNETNODES+1];
|
|
/*
|
|
===================
|
|
=
|
|
= ResetNodeAddresses
|
|
=
|
|
= Finds all the nodes for the game and works out player numbers among them
|
|
=
|
|
===================
|
|
*/
|
|
void ResetNodeAddresses ( void )
|
|
{
|
|
int i;
|
|
|
|
// Zero out client state structure
|
|
|
|
playernumber=1;
|
|
|
|
memset(clientstate,0,sizeof(clientstate));
|
|
|
|
for (i=1 ; i<MAXNETNODES ; i++)
|
|
memset (&nodeadr[i],0,sizeof(&nodeadr[i]));
|
|
|
|
clientstate[0]=client_Done;
|
|
|
|
if (standalone==false)
|
|
{
|
|
clientstate[playernumber]=client_Done;
|
|
rottcom.consoleplayer=playernumber;
|
|
memcpy (&nodeadr[playernumber], &nodeadr[0], //copy in local address
|
|
sizeof(nodeadr[playernumber]) );
|
|
printf ("\nServer is Player %d\n",playernumber);
|
|
playernumber++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
===================
|
|
=
|
|
= LookForNodes
|
|
=
|
|
= Finds all the nodes for the game and works out player numbers among them
|
|
=
|
|
===================
|
|
*/
|
|
|
|
#define cmd_FindClient 1
|
|
#define cmd_HereIAm 2
|
|
#define cmd_YouAre 3
|
|
#define cmd_IAm 4
|
|
#define cmd_AllDone 5
|
|
#define cmd_Info 6
|
|
|
|
#define MAXWAIT 10
|
|
|
|
|
|
void LookForNodes (void)
|
|
{
|
|
int i;
|
|
struct time time;
|
|
int oldsec;
|
|
setupdata_t *setup;
|
|
boolean done;
|
|
short numplayers,extra;
|
|
boolean showednum;
|
|
short secondsleft;
|
|
boolean masterset=false;
|
|
|
|
done=false;
|
|
|
|
oldsec = -1;
|
|
secondsleft = MAXWAIT;
|
|
setup = (setupdata_t *)&rottcom.data;
|
|
ipxlocaltime = -1; // in setup time, not game time
|
|
showednum = false;
|
|
SetupRandomMessages ();
|
|
|
|
if (server==true)
|
|
{
|
|
|
|
printf("SERVER MODE:\n");
|
|
printf("============\n");
|
|
printf("Attempting to find all clients for %i player NETROTT\n",
|
|
numnetnodes);
|
|
|
|
nodesetup.client=0;
|
|
rottcom.client=0;
|
|
rottcom.numplayers=numnetnodes;
|
|
ResetNodeAddresses ();
|
|
if (standalone==false)
|
|
{
|
|
masterset=true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("CLIENT MODE:\n");
|
|
printf("============\n");
|
|
printf("Attempting to find server\n");
|
|
|
|
rottcom.numplayers=MAXPLAYERS;
|
|
nodesetup.client=1;
|
|
rottcom.client=1;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// build local setup info
|
|
//
|
|
|
|
nodesetup.playernumber = 0;
|
|
|
|
gettime (&time);
|
|
oldsec = time.ti_sec;
|
|
|
|
do
|
|
{
|
|
//
|
|
// check for aborting
|
|
//
|
|
while ( bioskey(1) )
|
|
{
|
|
if ( (bioskey (0) & 0xff) == 27)
|
|
Error ("\n\nNetwork game synchronization aborted.");
|
|
}
|
|
if (server==false) // Client code
|
|
{
|
|
//
|
|
// listen to the network
|
|
//
|
|
while (GetPacket ())
|
|
{
|
|
extra = setup->extra;
|
|
numplayers = setup->numplayers;
|
|
|
|
if (remotetime != -1)
|
|
{ // an early game packet, not a setup packet
|
|
if (rottcom.remotenode == -1)
|
|
Error ("\n\nUnkown game packet: Other ROTT server present");
|
|
}
|
|
|
|
if (setup->client==0) // It's a server packet
|
|
{
|
|
switch (setup->command)
|
|
{
|
|
case cmd_FindClient:
|
|
|
|
// copy the server's address
|
|
if (rottcom.remotenode==-1) // only set if it is an unknown pkt
|
|
{
|
|
memcpy (&nodeadr[1], &remoteadr,
|
|
sizeof(nodeadr[1]) );
|
|
}
|
|
nodesetup.command=cmd_HereIAm;
|
|
if (master==true)
|
|
nodesetup.extra=1;
|
|
else
|
|
nodesetup.extra=0;
|
|
memcpy (&rottcom.data,
|
|
&nodesetup,sizeof(*setup));
|
|
rottcom.datalength = sizeof(*setup);
|
|
SendPacket (1); // send to server
|
|
printf (".");
|
|
break;
|
|
case cmd_Info:
|
|
if (showednum==false)
|
|
{
|
|
printf("\nServer is looking for %d players\n",numplayers);
|
|
showednum = true;
|
|
}
|
|
if ((extra>>8)!=0)
|
|
{
|
|
if ((extra>>8)==100)
|
|
printf("\nServer found player %d\n",extra&0xff);
|
|
else
|
|
PrintRandomMessage((extra>>8)-1,extra&0xff);
|
|
}
|
|
break;
|
|
case cmd_YouAre:
|
|
rottcom.consoleplayer=setup->playernumber;
|
|
nodesetup.command=cmd_IAm;
|
|
nodesetup.playernumber=setup->playernumber;
|
|
memcpy (&rottcom.data,
|
|
&nodesetup,sizeof(*setup));
|
|
rottcom.datalength = sizeof(*setup);
|
|
SendPacket (1); // send to server
|
|
printf (".");
|
|
printf ("\nI am player %d\n",setup->playernumber);
|
|
break;
|
|
case cmd_AllDone:
|
|
rottcom.numplayers=setup->playernumber;
|
|
done=true;
|
|
printf ("!");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else // It's the server
|
|
{
|
|
//
|
|
// listen to the network
|
|
//
|
|
while (GetPacket ())
|
|
{
|
|
extra = setup->extra;
|
|
if (remotetime != -1)
|
|
{ // an early game packet, not a setup packet
|
|
if (rottcom.remotenode == -1)
|
|
Error ("\n\nUnkown game packet: Other clients still in game.");
|
|
}
|
|
if (setup->client==1) // It's a client packet
|
|
{
|
|
switch (setup->command)
|
|
{
|
|
case cmd_HereIAm:
|
|
{
|
|
int pnum;
|
|
|
|
if ((masterset==false) && (extra==1)) // some client is using the 'master' param
|
|
{
|
|
ResetNodeAddresses ();
|
|
masterset=true;
|
|
rottcom.remotenode=-1;
|
|
}
|
|
|
|
pnum=playernumber;
|
|
if (rottcom.remotenode==-1) // only set if it is an unknown pkt
|
|
{
|
|
// copy the client's address
|
|
printf ("\nFound Player %d\n",pnum);
|
|
memcpy (&nodeadr[playernumber], &remoteadr,
|
|
sizeof(nodeadr[playernumber]) );
|
|
nodesetup.extra=(short)(100<<8);
|
|
nodesetup.extra |= playernumber;
|
|
nodesetup.command=cmd_Info;
|
|
nodesetup.numplayers=numnetnodes;
|
|
rottcom.datalength = sizeof(*setup);
|
|
memcpy (&rottcom.data, &nodesetup,sizeof(*setup));
|
|
SendPacket (MAXNETNODES); // send to all
|
|
}
|
|
else
|
|
pnum=rottcom.remotenode;
|
|
if (clientstate[pnum]>client_Echoed)
|
|
continue;
|
|
nodesetup.command=cmd_YouAre;
|
|
nodesetup.playernumber=pnum;
|
|
memcpy (&rottcom.data,
|
|
&nodesetup,sizeof(*setup));
|
|
SendPacket (pnum); // send back to client
|
|
clientstate[pnum]=client_Echoed;
|
|
playernumber++;
|
|
}
|
|
break;
|
|
case cmd_IAm:
|
|
if (rottcom.remotenode==-1) // Shouldn't happen
|
|
continue;
|
|
// Error("\n\nReceived Identity packet before identification\n");
|
|
if (rottcom.remotenode!=setup->playernumber)
|
|
Error("\n\nReceived Incorrect player number\n");
|
|
printf ("Finished Player %d\n",rottcom.remotenode);
|
|
clientstate[rottcom.remotenode]=client_Done;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (rottcom.remotenode!=0)
|
|
Error("\n\nMultiple ROTT Servers!\n");
|
|
switch (setup->command)
|
|
{
|
|
case cmd_Info:
|
|
if (((extra>>8)!=0) && (standalone==false))
|
|
{
|
|
if ((extra>>8)==100)
|
|
printf("\nServer found player %d\n",extra&0xff);
|
|
else
|
|
PrintRandomMessage((extra>>8)-1,extra&0xff);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check to see if we are indeed done
|
|
|
|
done=true; // set it to true
|
|
if (playernumber > numnetnodes+1)
|
|
Error("\n\nFound too many players=%d\n",playernumber);
|
|
if (playernumber <= numnetnodes)
|
|
done=false;
|
|
else
|
|
{
|
|
for (i=0;i<playernumber;i++)
|
|
if (clientstate[i]!=client_Done)
|
|
done=false;
|
|
}
|
|
gettime (&time);
|
|
|
|
if (time.ti_sec == oldsec)
|
|
continue;
|
|
|
|
secondsleft--;
|
|
if (secondsleft==0)
|
|
{
|
|
secondsleft=MAXWAIT;
|
|
nodesetup.extra=(GetRandomMessage())+1;
|
|
nodesetup.extra<<=8;
|
|
nodesetup.extra|=playernumber;
|
|
nodesetup.command=cmd_Info;
|
|
nodesetup.numplayers=numnetnodes;
|
|
rottcom.datalength = sizeof(*setup);
|
|
memcpy (&rottcom.data, &nodesetup,sizeof(*setup));
|
|
|
|
SendPacket (MAXNETNODES); // send to all
|
|
}
|
|
|
|
oldsec = time.ti_sec;
|
|
printf (".");
|
|
|
|
// Make a general inquiry for any potential ROTT players
|
|
nodesetup.extra=0;
|
|
nodesetup.command=cmd_FindClient;
|
|
nodesetup.numplayers=numnetnodes;
|
|
rottcom.datalength = sizeof(*setup);
|
|
memcpy (&rottcom.data, &nodesetup,sizeof(*setup));
|
|
|
|
SendPacket (MAXNETNODES); // send to all
|
|
}
|
|
|
|
} while (done==false);
|
|
|
|
// Done with finding players send out startup info
|
|
|
|
if (server==true)
|
|
{
|
|
int otime;
|
|
|
|
gettime (&time);
|
|
oldsec = time.ti_sec+1;
|
|
if (oldsec>59)
|
|
oldsec-=60;
|
|
otime = time.ti_sec-1;
|
|
while (oldsec!=time.ti_sec)
|
|
{
|
|
gettime (&time);
|
|
|
|
if (time.ti_sec == otime)
|
|
continue;
|
|
otime = time.ti_sec;
|
|
nodesetup.command=cmd_AllDone;
|
|
nodesetup.playernumber=playernumber-1;
|
|
rottcom.datalength = sizeof(*setup);
|
|
memcpy (&rottcom.data, &nodesetup,sizeof(*setup));
|
|
|
|
SendPacket (MAXNETNODES); // send to all
|
|
}
|
|
}
|
|
|
|
if (server==true)
|
|
{
|
|
if (standalone == false)
|
|
printf ("Server is player %i of %i\n", rottcom.consoleplayer, rottcom.numplayers);
|
|
else
|
|
printf ("Server is standalone\n");
|
|
}
|
|
else
|
|
printf ("\nConsole is player %i of %i\n", rottcom.consoleplayer, rottcom.numplayers);
|
|
while (GetPacket ()) {}
|
|
}
|
|
|
|
/*
|
|
=============
|
|
=
|
|
= main
|
|
=
|
|
=============
|
|
*/
|
|
|
|
void main (void)
|
|
{
|
|
int i;
|
|
|
|
//
|
|
// determine game parameters
|
|
//
|
|
numnetnodes = 2;
|
|
rottcom.gametype=NETWORK_GAME;
|
|
rottcom.remoteridicule = 0;
|
|
|
|
|
|
printf("\n\n -----------------------------------\n");
|
|
printf(" ROTT NETWORK DEVICE DRIVER V%s \n",VERSION);
|
|
printf(" -----------------------------------\n");
|
|
|
|
i = CheckParm ("-nodes");
|
|
if (i && i < _argc-1)
|
|
{
|
|
numnetnodes = atoi(_argv[i+1]);
|
|
}
|
|
|
|
i = CheckParm ("-socket");
|
|
if (i && i < _argc-1)
|
|
{
|
|
socketid = atoi(_argv[i+1]);
|
|
}
|
|
|
|
server=false;
|
|
standalone=false;
|
|
pause=false;
|
|
master=false;
|
|
|
|
if (CheckParm ("-server"))
|
|
server=true;
|
|
|
|
if (CheckParm ("-standalone"))
|
|
standalone=true;
|
|
|
|
if (CheckParm ("-pause"))
|
|
pause=true;
|
|
|
|
if (CheckParm ("-master"))
|
|
master=true;
|
|
|
|
if (CheckParm ("-remoteridicule"))
|
|
rottcom.remoteridicule = 1;
|
|
|
|
InitNetwork ();
|
|
|
|
LookForNodes ();
|
|
|
|
ipxlocaltime = 0; // no longer in setup
|
|
|
|
LaunchROTT ();
|
|
|
|
Shutdown ();
|
|
|
|
exit(0);
|
|
}
|
|
|
|
|