Iskhodnyy_kod_Doom
.pdfwhile (++p != myargc && myargv[p][0] != ’-’) D_AddFile (myargv[p]);
}
p = M_CheckParm ("-playdemo");
if (!p)
p = M_CheckParm ("-timedemo");
if (p && p < myargc-1)
{
sprintf (file,"%s.lmp", myargv[p+1]); D_AddFile (file);
printf("Playing demo %s.lmp.\n",myargv[p+1]);
}
// get skill / episode / map from parms startskill = sk_medium;
startepisode = 1; startmap = 1; autostart = false;
p = M_CheckParm ("-skill"); if (p && p < myargc-1)
{
startskill = myargv[p+1][0]-’1’; autostart = true;
}
p = M_CheckParm ("-episode"); if (p && p < myargc-1)
{
startepisode = myargv[p+1][0]-’0’; startmap = 1;
autostart = true;
}
p = M_CheckParm ("-timer");
if (p && p < myargc-1 && deathmatch)
{
int time;
time = atoi(myargv[p+1]);
printf("Levels will end after %d minute",time); if (time>1)
printf("s");
printf(".\n");
}
p = M_CheckParm ("-avg");
if (p && p < myargc-1 && deathmatch)
printf("Austin Virtual Gaming: Levels will end after 20 minutes\n");
p = M_CheckParm ("-warp"); if (p && p < myargc-1)
{
if (gamemode == commercial) startmap = atoi (myargv[p+1]);
else
{
startepisode = myargv[p+1][0]-’0’; startmap = myargv[p+2][0]-’0’;
}
autostart = true;
}
81
// init subsystems
printf ("V_Init: allocate screens.\n");
V_Init |
(); |
|
printf |
("M_LoadDefaults: Load system defaults.\n"); |
|
M_LoadDefaults (); |
// load before initing other systems |
printf ("Z_Init: Init zone memory allocation daemon. \n"); Z_Init ();
printf ("W_Init: Init WADfiles.\n"); W_InitMultipleFiles (wadfiles);
// Check for -file in shareware if (modifiedgame)
{
//These are the lumps that will be checked in IWAD,
//if any one is not present, execution will be aborted. char name[23][8]=
{
"e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9",
"e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9",
"dphoof","bfgga0","heada1","cybra1","spida1d1"
};
int i;
if ( gamemode == shareware)
I_Error("\nYou cannot -file with the shareware " "version. Register!");
//Check for fake IWAD with right name,
//but w/o all the lumps of the registered version. if (gamemode == registered)
for (i = 0;i < 23; i++)
if (W_CheckNumForName(name[i])<0)
I_Error("\nThis is not the registered version.");
}
// Iff additonal PWAD files are used, print modified banner if (modifiedgame)
{
/*m*/printf ( "===========================================================================\n" "ATTENTION: This version of DOOM has been modified. If you would like to\n" "get a copy of the original game, call 1-800-IDGAMES or see the readme file.\n"
"You will not receive technical support for modified games.\n"
" press enter to continue\n"
"===========================================================================\n"
); getchar ();
}
// Check and print which version is executed. switch ( gamemode )
{
case shareware: case indetermined:
printf ( "===========================================================================\n" " Shareware!\n" "===========================================================================\n"
);
82
break;
case registered: case retail: case commercial:
printf ( "===========================================================================\n" " Commercial product - do not distribute!\n"
" Please report software piracy to the SPA: 1-800-388-PIR8\n" "===========================================================================\n"
);
break;
default: // Ouch. break;
}
printf ("M_Init: Init miscellaneous info.\n"); M_Init ();
printf ("R_Init: Init DOOM refresh daemon - "); R_Init ();
printf ("\nP_Init: Init Playloop state.\n"); P_Init ();
printf ("I_Init: Setting up machine state.\n"); I_Init ();
printf ("D_CheckNetGame: Checking network game status.\n"); D_CheckNetGame ();
printf ("S_Init: Setting up sound.\n");
S_Init (snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/ );
printf ("HU_Init: Setting up heads up display.\n"); HU_Init ();
printf ("ST_Init: Init status bar.\n"); ST_Init ();
// check for a driver that wants intermission stats p = M_CheckParm ("-statcopy");
if (p && p<myargc-1)
{
// for statistics driver
extern |
void* |
statcopy; |
statcopy = (void*)atoi(myargv[p+1]); |
||
printf |
("External statistics registered.\n"); |
}
// start the apropriate game based on parms p = M_CheckParm ("-record");
if (p && p < myargc-1)
{
G_RecordDemo (myargv[p+1]); autostart = true;
}
p = M_CheckParm ("-playdemo"); if (p && p < myargc-1)
{
singledemo = true; |
// quit after one demo |
83
G_DeferedPlayDemo (myargv[p+1]);
D_DoomLoop (); // never returns
}
p = M_CheckParm ("-timedemo"); if (p && p < myargc-1)
{
G_TimeDemo (myargv[p+1]);
D_DoomLoop (); // never returns
}
p = M_CheckParm ("-loadgame"); if (p && p < myargc-1)
{
if (M_CheckParm("-cdrom"))
sprintf(file, "c:\\doomdata\\"SAVEGAMENAME"%c.dsg",myargv[p+1][0]);
else
sprintf(file, SAVEGAMENAME"%c.dsg",myargv[p+1][0]);
G_LoadGame (file);
}
if ( gameaction != ga_loadgame )
{
if (autostart || netgame)
G_InitNew (startskill, startepisode, startmap);
else |
|
D_StartTitle (); |
// start up intro loop |
}
D_DoomLoop (); // never returns
}
3.7 d main.h
// Emacs style mode select -*- C++ -*- //-----------------------------------------------------------------------------
//
//$Id:$
//Copyright (C) 1993-1996 by id Software, Inc.
//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.
//
//$Log:$
//DESCRIPTION:
//System specific interface stuff.
//-----------------------------------------------------------------------------
#ifndef __D_MAIN__ #define __D_MAIN__
#include "d_event.h"
84
#ifdef __GNUG__ #pragma interface #endif
#define MAXWADFILES |
20 |
extern char* |
wadfiles[MAXWADFILES]; |
void D_AddFile (char *file); |
|
//
//D_DoomMain()
//Not a globally visible function, just included for source reference,
//calls all startup code, parses command line options.
//If not overrided by user input, calls N_AdvanceDemo.
//
void D_DoomMain (void);
// Called by IO functions when input is detected. void D_PostEvent (event_t* ev);
//
// BASE LEVEL
//
void D_PageTicker (void); void D_PageDrawer (void); void D_AdvanceDemo (void); void D_StartTitle (void);
#endif
3.8d net.c
// Emacs style mode select -*- C++ -*- //-----------------------------------------------------------------------------
//
//$Id:$
//Copyright (C) 1993-1996 by id Software, Inc.
//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.
//
//$Log:$
//DESCRIPTION:
//DOOM Network game communication and protocol,
//all OS independend parts.
//
//-----------------------------------------------------------------------------
85
static const char rcsid[] = "$Id: d_net.c,v 1.3 1997/02/03 22:01:47 b1 Exp $";
#include "m_menu.h" #include "i_system.h" #include "i_video.h" #include "i_net.h" #include "g_game.h" #include "doomdef.h" #include "doomstat.h"
#define |
NCMD_EXIT |
0x80000000 |
|
#define |
NCMD_RETRANSMIT |
0x40000000 |
|
#define |
NCMD_SETUP |
0x20000000 |
|
#define |
NCMD_KILL |
0x10000000 |
// kill game |
#define |
NCMD_CHECKSUM |
0x0fffffff |
|
doomcom_t* |
doomcom; |
|
|
doomdata_t* |
netbuffer; |
// points inside doomcom |
//
//NETWORKING
//gametic is the tic about to (or currently being) run
//maketic is the tick that hasn’t had control made for it yet
//nettics[] has the maketics for all players
//
// a gametic cannot be run until nettics[] > gametic for all players
// |
|
|
|
|
#define |
RESENDCOUNT |
10 |
|
|
#define |
PL_DRONE |
0x80 |
// bit flag in doomdata->player |
|
ticcmd_t |
localcmds[BACKUPTICS]; |
|
|
|
ticcmd_t |
netcmds[MAXPLAYERS][BACKUPTICS]; |
|
||
int |
nettics[MAXNETNODES]; |
|
|
|
boolean |
nodeingame[MAXNETNODES]; |
// set false as nodes leave game |
||
boolean |
remoteresend[MAXNETNODES]; |
// set when local needs tics |
||
int |
resendto[MAXNETNODES]; |
|
// set when remote needs tics |
|
int |
resendcount[MAXNETNODES]; |
|
||
int |
nodeforplayer[MAXPLAYERS]; |
|
||
int |
maketic; |
|
|
|
int |
lastnettic; |
|
|
|
int |
skiptics; |
|
|
|
int |
ticdup; |
|
|
|
int |
maxsend; |
// BACKUPTICS/(2*ticdup)-1 |
|
|
void D_ProcessEvents (void); |
|
|
|
|
void G_BuildTiccmd (ticcmd_t *cmd); |
|
|
||
void D_DoAdvanceDemo (void); |
|
|
|
|
boolean |
reboundpacket; |
|
|
|
doomdata_t |
reboundstore; |
|
|
|
//
//
//
int NetbufferSize (void)
86
{
return (int)&(((doomdata_t *)0)->cmds[netbuffer->numtics]);
}
//
// Checksum
//
unsigned NetbufferChecksum (void)
{
unsigned |
c; |
|
int |
|
i,l; |
c = |
0x1234567; |
|
// FIXME -endianess?
#ifdef NORMALUNIX
return 0; |
// byte order problems |
#endif |
|
l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4; for (i=0 ; i<l ; i++)
c += ((unsigned *)&netbuffer->retransmitfrom)[i] * (i+1);
return c & NCMD_CHECKSUM;
}
//
//
//
int ExpandTics (int low)
{
int delta;
delta = low - (maketic&0xff);
if (delta >= -64 && delta <= 64) return (maketic&~0xff) + low;
if (delta > 64)
return (maketic&~0xff) - 256 + low; if (delta < -64)
return (maketic&~0xff) + 256 + low;
I_Error ("ExpandTics: strange value %i at maketic %i",low,maketic); return 0;
}
//
// HSendPacket
// |
|
void |
|
HSendPacket |
|
(int |
node, |
int |
flags ) |
{ |
|
netbuffer->checksum = NetbufferChecksum () | flags;
if (!node)
{
reboundstore = *netbuffer; reboundpacket = true; return;
}
87
if (demoplayback) return;
if (!netgame)
I_Error ("Tried to transmit to another node");
doomcom->command = CMD_SEND; doomcom->remotenode = node; doomcom->datalength = NetbufferSize ();
if (debugfile) |
|
{ |
|
int |
i; |
int |
realretrans; |
if (netbuffer->checksum & NCMD_RETRANSMIT)
realretrans = ExpandTics (netbuffer->retransmitfrom);
else
realretrans = -1;
fprintf (debugfile,"send (%i + %i, R %i) [%i] ", ExpandTics(netbuffer->starttic),
netbuffer->numtics, realretrans, doomcom->datalength);
for (i=0 ; i<doomcom->datalength ; i++)
fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
fprintf (debugfile,"\n");
}
I_NetCmd ();
}
//
//HGetPacket
//Returns false if no packet is waiting
boolean HGetPacket (void)
{
if (reboundpacket)
{
*netbuffer = reboundstore; doomcom->remotenode = 0; reboundpacket = false; return true;
}
if (!netgame) return false;
if (demoplayback) return false;
doomcom->command = CMD_GET; I_NetCmd ();
if (doomcom->remotenode == -1) return false;
if (doomcom->datalength != NetbufferSize ())
{
if (debugfile)
fprintf (debugfile,"bad packet length %i\n",doomcom->datalength); return false;
}
88
if (NetbufferChecksum () != (netbuffer->checksum&NCMD_CHECKSUM) )
{
if (debugfile)
fprintf (debugfile,"bad packet checksum\n"); return false;
}
if (debugfile)
{
int |
realretrans; |
int |
i; |
if (netbuffer->checksum & NCMD_SETUP) fprintf (debugfile,"setup packet\n");
else
{
if (netbuffer->checksum & NCMD_RETRANSMIT)
realretrans = ExpandTics (netbuffer->retransmitfrom);
else
realretrans = -1;
fprintf (debugfile,"get %i = (%i + %i, R %i)[%i] ", doomcom->remotenode, ExpandTics(netbuffer->starttic),
netbuffer->numtics, realretrans, doomcom->datalength);
for (i=0 ; i<doomcom->datalength ; i++)
fprintf (debugfile,"%i ",((byte *)netbuffer)[i]); fprintf (debugfile,"\n");
}
|
} |
|
|
|
return true; |
|
|
} |
|
|
|
// |
|
|
|
// GetPackets |
|
|
|
// |
|
|
|
char |
exitmsg[80]; |
|
|
void GetPackets (void) |
|
||
{ |
|
|
|
|
int |
|
netconsole; |
|
int |
|
netnode; |
|
ticcmd_t |
*src, *dest; |
|
|
int |
|
realend; |
|
int |
|
realstart; |
|
while ( HGetPacket() ) |
||
|
{ |
|
|
|
if (netbuffer->checksum & NCMD_SETUP) |
||
|
continue; |
// extra setup packet |
netconsole = netbuffer->player & ~PL_DRONE; netnode = doomcom->remotenode;
//to save bytes, only the low byte of tic numbers are sent
//Figure out what the rest of the bytes are
realstart = ExpandTics (netbuffer->starttic); realend = (realstart+netbuffer->numtics);
// check for exiting the game
if (netbuffer->checksum & NCMD_EXIT)
{
if (!nodeingame[netnode])
89
continue; nodeingame[netnode] = false;
playeringame[netconsole] = false;
strcpy (exitmsg, "Player 1 left the game"); exitmsg[7] += netconsole; players[consoleplayer].message = exitmsg; if (demorecording)
G_CheckDemoStatus (); continue;
}
// check for a remote game kill
if (netbuffer->checksum & NCMD_KILL) I_Error ("Killed by network driver");
nodeforplayer[netconsole] = netnode;
//check for retransmit request if ( resendcount[netnode] <= 0
&&(netbuffer->checksum & NCMD_RETRANSMIT) )
{
resendto[netnode] = ExpandTics(netbuffer->retransmitfrom); if (debugfile)
fprintf (debugfile,"retransmit from %i\n", resendto[netnode]); resendcount[netnode] = RESENDCOUNT;
}
else
resendcount[netnode]--;
//check for out of order / duplicated packet
if (realend == nettics[netnode]) continue;
if (realend < nettics[netnode])
{
if (debugfile)
fprintf (debugfile,
"out of order packet (%i + %i)\n" , realstart,netbuffer->numtics);
continue;
}
// check for a missed packet
if (realstart > nettics[netnode])
{
// stop processing until the other system resends the missed tics if (debugfile)
fprintf (debugfile,
"missed tics from %i (%i - %i)\n", netnode, realstart, nettics[netnode]);
remoteresend[netnode] = true; continue;
}
// update command store from the packet
{
int start;
remoteresend[netnode] = false;
start = nettics[netnode] - realstart; src = &netbuffer->cmds[start];
while (nettics[netnode] < realend)
{
90