Files

1 line
11 KiB
C++

// I_unix.c, Doom for UNIX
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifndef LINUX
#include <sys/filio.h>
#endif
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include "doomdef.h"
int isCyberPresent;
void NetSend (void);
boolean NetListen (void);
typedef union { short a; unsigned char b[sizeof(short)]; } s_endian;
typedef union { long a; unsigned char b[sizeof(long)]; } l_endian;
static s_endian endianness = { 1 };
FILE *sndserver=0;
char *sndserver_filename;
int mb_used = 6;
void I_ReadCyberCmd(ticcmd_t *cmd)
{
}
void I_Tactile(int on, int off, int total)
{
}
ticcmd_t emptycmd;
ticcmd_t *I_BaseTiccmd(void)
{
return &emptycmd;
}
short ShortSwap (short dat)
{
// if (endianness.b[0])
// return dat; // do not flip little-endian
// else
return ((dat&0xff)<<8) | ((dat>>8)&0xff);
}
long LongSwap (long dat)
{
// if (endianness.b[0])
// return dat; // do not flip little-endian
// else // otherwise flip it
// return ((l_endian) dat).b[0]
// + (((l_endian) dat).b[1] << 8)
// + (((l_endian) dat).b[2] << 16)
// + (((l_endian) dat).b[3] << 24);
return (((unsigned)dat)>>24) |
((dat>>8)&0xff00) |
((dat<<8)&0xff0000) |
(dat<<24);
}
#if !defined(USEASM) && (!defined(__WATCOMC__) || !defined(__i386) || defined(NORMALUNIX))
fixed_t FixedMul (fixed_t a, fixed_t b)
{
return ((long long) a * (long long) b) >> FRACBITS;
}
fixed_t FixedDiv2 (fixed_t a, fixed_t b)
{
#if 0
long long c;
c = ((long long)a<<16) / ((long long)b);
return (fixed_t) c;
#endif
double c;
c = ((double)a) / ((double)b) * FRACUNIT;
if (c >= 2147483648.0 || c < -2147483648.0)
I_Error("FixedDiv: divide by zero");
return (fixed_t) c;
}
#endif
int I_GetHeapSize (void)
{
return mb_used*1024*1024;
}
byte *I_ZoneBase (int *size)
{
*size = mb_used*1024*1024;
return (byte *) malloc (*size);
}
/*
=================
=
= I_GetTime
=
= returns time in 1/70th second tics
=================
*/
int I_GetTime (void)
{
struct timeval tp;
struct timezone tzp;
int newtics;
static int basetime=0;
gettimeofday(&tp, &tzp);
if (!basetime)
basetime = tp.tv_sec;
newtics = (tp.tv_sec-basetime)*TICRATE + tp.tv_usec*TICRATE/1000000;
return newtics;
}
/*
* MUSIC & SFX API
*/
void I_SetMusicVolume(int volume) { }
void I_SetSfxVolume(int volume) { }
// GENERAL SFX API
void I_SetChannels(int channels) { }
int I_GetSfxLumpNum(sfxinfo_t *sfx)
{
char namebuf[9];
sprintf(namebuf, "ds%s", sfx->name);
return W_GetNumForName(namebuf);
}
int I_StartSound (int id, void *data, int vol, int sep, int pitch, int priority)
{
if (sndserver)
{
fprintf(sndserver, "p%2.2x%2.2x%2.2x%2.2x\n", id, pitch, vol, sep);
fflush(sndserver);
}
}
void I_StopSound (int handle) { }
int I_SoundIsPlaying(int handle) { return gametic < handle; }
void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) { }
// MUSIC API
static int looping=0, musicdies=-1;
void I_StopSong(int handle) { looping = 0; musicdies = 0; }
void I_PauseSong (int handle) { }
void I_ResumeSong (int handle) { }
void I_PlaySong(int handle, int looping)
{
musicdies = gametic + TICRATE*30;
}
void I_UnRegisterSong(int handle) {}
int I_RegisterSong(void *data) { return 1; }
int I_QrySongPlaying(int handle)
{
return looping || musicdies > gametic;
}
void I_ShutdownSound(void)
{
if (sndserver)
{
fprintf(sndserver, "q\n");
fflush(sndserver);
}
}
/*
====================
=
= I_Init
=
====================
*/
void I_Init (void)
{
char buffer[256];
if (getenv("DOOMWADDIR"))
sprintf(buffer, "%s/%s", getenv("DOOMWADDIR"),
sndserver_filename);
else
sprintf(buffer, "%s", sndserver_filename);
// start sound process
if ( ! access(buffer, X_OK) )
{
strcat(buffer, " -quiet");
sndserver = popen(buffer, "w");
}
else
fprintf(stderr, "Could not start sound server [%s]\n", buffer);
// I_InitGraphics();
}
/*
================
=
= I_Quit
=
================
*/
void I_ShutdownGraphics(void);
void I_Quit (void)
{
D_QuitNetGame ();
I_ShutdownSound();
M_SaveDefaults ();
I_ShutdownGraphics();
exit(0);
}
void I_WaitVBL(int count)
{
#ifdef SGI
sginap(1);
#else
#ifdef SUN
sleep(0);
#else
usleep (count * (1000000/70) );
#endif
#endif
}
void I_BeginRead(void)
{
}
void I_EndRead(void)
{
}
byte *I_AllocLow(int length)
{
byte *mem;
mem = (byte *)malloc (length);
memset (mem,0,length);
return mem;
}
/*
==============================================================================
NETWORKING
==============================================================================
*/
#include <netdb.h>
#include <sys/ioctl.h>
int DOOMPORT = (IPPORT_USERRESERVED +0x1d );
int sendsocket, insocket;
struct sockaddr_in sendaddress[MAXNETNODES];
void (*netget) (void);
void (*netsend) (void);
/*
===============
=
= UDPsocket
=
===============
*/
int UDPsocket (void)
{
int s;
// allocate a socket
s = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s<0)
I_Error ("can't create socket: %s",strerror(errno));
return s;
}
/*
===============
=
= BindToLocalPort
=
===============
*/
void BindToLocalPort (int s, int port)
{
int v;
struct sockaddr_in address;
memset (&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = port;
v = bind (s, (void *)&address, sizeof(address));
if (v == -1)
I_Error ("BindToPort: bind: %s", strerror(errno));
}
/*
==============
=
= PacketSend
=
==============
*/
void PacketSend (void)
{
int c;
doomdata_t sw;
// byte swap
sw.checksum = htonl(netbuffer->checksum);
sw.player = netbuffer->player;
sw.retransmitfrom = netbuffer->retransmitfrom;
sw.starttic = netbuffer->starttic;
sw.numtics = netbuffer->numtics;
for (c=0 ; c< netbuffer->numtics ; c++)
{
sw.cmds[c].forwardmove = netbuffer->cmds[c].forwardmove;
sw.cmds[c].sidemove = netbuffer->cmds[c].sidemove;
sw.cmds[c].angleturn = htons(netbuffer->cmds[c].angleturn);
sw.cmds[c].consistancy = htons(netbuffer->cmds[c].consistancy);
sw.cmds[c].chatchar = netbuffer->cmds[c].chatchar;
sw.cmds[c].buttons = netbuffer->cmds[c].buttons;
}
//printf ("sending %i\n",gametic);
c = sendto (sendsocket , &sw, doomcom->datalength
,0,(void *)&sendaddress[doomcom->remotenode]
,sizeof(sendaddress[doomcom->remotenode]));
// if (c == -1)
// I_Error ("SendPacket error: %s",strerror(errno));
}
/*
==============
=
= PacketGet
=
==============
*/
void PacketGet (void)
{
int i,c;
struct sockaddr_in fromaddress;
int fromlen;
doomdata_t sw;
fromlen = sizeof(fromaddress);
c = recvfrom (insocket, &sw, sizeof(sw), 0
, (struct sockaddr *)&fromaddress, &fromlen );
if (c == -1 )
{
if (errno != EWOULDBLOCK)
I_Error ("GetPacket: %s",strerror(errno));
doomcom->remotenode = -1; // no packet
return;
}
{
static int first=1;
if (first)
printf("len=%d:p=[0x%x 0x%x] \n", c, *(int*)&sw, *((int*)&sw+1));
first = 0;
}
// find remote node number
for (i=0 ; i<doomcom->numnodes ; i++)
if ( fromaddress.sin_addr.s_addr == sendaddress[i].sin_addr.s_addr )
break;
if (i == doomcom->numnodes)
{ // packet isn't from one of the players (new game broadcast)
doomcom->remotenode = -1; // no packet
return;
}
doomcom->remotenode = i; // good packet from a game player
doomcom->datalength = c;
// byte swap
netbuffer->checksum = ntohl(sw.checksum);
netbuffer->player = sw.player;
netbuffer->retransmitfrom = sw.retransmitfrom;
netbuffer->starttic = sw.starttic;
netbuffer->numtics = sw.numtics;
for (c=0 ; c< netbuffer->numtics ; c++)
{
netbuffer->cmds[c].forwardmove = sw.cmds[c].forwardmove;
netbuffer->cmds[c].sidemove = sw.cmds[c].sidemove;
netbuffer->cmds[c].angleturn = ntohs(sw.cmds[c].angleturn);
netbuffer->cmds[c].consistancy = ntohs(sw.cmds[c].consistancy);
netbuffer->cmds[c].chatchar = sw.cmds[c].chatchar;
netbuffer->cmds[c].buttons = sw.cmds[c].buttons;
}
}
int GetLocalAddress (void)
{
char hostname[1024];
struct hostent *hostentry; // host information entry
int v;
// get local address
v = gethostname (hostname, sizeof(hostname));
if (v == -1)
I_Error ("GetLocalAddress : gethostname: errno %d",errno);
hostentry = gethostbyname (hostname);
if (!hostentry)
I_Error ("GetLocalAddress : gethostbyname: couldn't get local host");
return *(int *)hostentry->h_addr_list[0];
}
/*
====================
=
= I_InitNetwork
=
====================
*/
void I_InitNetwork (void)
{
boolean trueval = true;
int i,p;
struct hostent *hostentry; // host information entry
doomcom = malloc (sizeof (*doomcom) );
memset (doomcom, 0, sizeof(*doomcom) );
//
// set up for network
//
i = M_CheckParm ("-dup");
if (i && i< myargc-1)
{
doomcom->ticdup = myargv[i+1][0]-'0';
if (doomcom->ticdup < 1)
doomcom->ticdup = 1;
if (doomcom->ticdup > 9)
doomcom->ticdup = 9;
}
else
doomcom-> ticdup = 1;
if (M_CheckParm ("-extratic"))
doomcom-> extratics = 1;
else
doomcom-> extratics = 0;
p = M_CheckParm ("-port");
if (p && p<myargc-1)
{
DOOMPORT = atoi (myargv[p+1]);
printf ("using alternate port %i\n",DOOMPORT);
}
//
// parse network game options -net <consoleplayer> <host> <host> ...
//
i = M_CheckParm ("-net");
if (!i)
{
//
// single player game
//
netgame = false;
doomcom->id = DOOMCOM_ID;
doomcom->numplayers = doomcom->numnodes = 1;
doomcom->deathmatch = false;
doomcom->consoleplayer = 0;
return;
}
netsend = PacketSend;
netget = PacketGet;
netgame = true;
//
// parse player number and host list
//
doomcom->consoleplayer = myargv[i+1][0]-'1';
doomcom->numnodes = 1; // this node for sure
i++;
while (++i < myargc && myargv[i][0] != '-')
{
sendaddress[doomcom->numnodes].sin_family = AF_INET;
sendaddress[doomcom->numnodes].sin_port = htons(DOOMPORT);
if (myargv[i][0] == '.')
{
sendaddress[doomcom->numnodes].sin_addr.s_addr
= inet_addr (myargv[i]+1);
}
else
{
hostentry = gethostbyname (myargv[i]);
if (!hostentry)
I_Error ("gethostbyname: couldn't find %s", myargv[i]);
sendaddress[doomcom->numnodes].sin_addr.s_addr
= *(int *)hostentry->h_addr_list[0];
}
doomcom->numnodes++;
}
doomcom->id = DOOMCOM_ID;
doomcom->numplayers = doomcom->numnodes;
//
// build message to receive
//
insocket = UDPsocket ();
BindToLocalPort (insocket,htons(DOOMPORT));
ioctl (insocket, FIONBIO, &trueval);
sendsocket = UDPsocket ();
}
void I_NetCmd (void)
{
if (doomcom->command == CMD_SEND)
{
netsend ();
}
else if (doomcom->command == CMD_GET)
{
netget ();
}
else
I_Error ("Bad net cmd: %i\n",doomcom->command);
}