DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

doomlib.cpp (16575B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #include "Precompiled.h"
     30 #include "globaldata.h"
     31 #include "doomlib.h"
     32 #include <assert.h>
     33 #include "Main.h"
     34 #include "sys/sys_session.h"
     35 #include "idlib/Thread.h"
     36 
     37 
     38 #include <sys/types.h>
     39 
     40 // Store master volume settings in archived cvars, becausue we want them to apply
     41 // even if a user isn't signed in.
     42 // The range is from 0 to 15, which matches the setting in vanilla DOOM.
     43 idCVar s_volume_sound( "s_volume_sound", "8", CVAR_ARCHIVE | CVAR_INTEGER, "sound volume", 0, 15 );
     44 idCVar s_volume_midi( "s_volume_midi", "8", CVAR_ARCHIVE | CVAR_INTEGER, "music volume", 0, 15 );
     45 idCVar m_show_messages( "m_show_messages", "1", CVAR_ARCHIVE | CVAR_INTEGER, "show messages", 0, 1 );
     46 idCVar m_inDemoMode( "m_inDemoMode", "1", CVAR_INTEGER, "in demo mode", 0, 1 );
     47 
     48 bool	globalNetworking	= false;
     49 bool	globalPauseTime		= false;
     50 int		PLAYERCOUNT			= 1;
     51 
     52 #ifdef _DEBUG
     53 bool	debugOutput			= true;
     54 #else
     55 bool	debugOutput			= false;
     56 #endif
     57 
     58 namespace DoomLib
     59 {
     60 	static const char * Expansion_Names[] = {
     61 		"Ultimate DOOM", "DOOM II: Hell On Earth", "Final DOOM: TNT Evilution", "Final DOOM: Plutonia Experiment", "DOOM II: Master Levels", "DOOM II: No Rest For The Living"
     62 	};
     63 
     64 	static const char* Skill_Names[] = {
     65 		"I'm Too Young To Die!", "Hey, Not Too Rough!", "Hurt Me Plenty!", "Ultra-Violence", "Nightmare"
     66 	};
     67 
     68 	static const char* Filter_Names[] = {
     69 		"#str_friends", "#str_around", "#str_top15"
     70 	};
     71 
     72 	// Game-specific setup values.
     73 	static const char *  Doom_MapNames[] = {
     74 		"E1M1: Hangar", "E1M2: Nuclear Plant", "E1M3: Toxin Refinery", "E1M4: Command Control", "E1M5: Phobos Lab", "E1M6: Central Processing", "E1M7: Computer Station", "E1M8: Phobos Anomaly", "E1M9: Military Base",
     75 		"E2M1: Deimos Anomaly", "E2M2: Containment Area", "E2M3: Refinery", "E2M4: Deimos Lab", "E2M5: Command Center", "E2M6: Halls of the Damned", "E2M7: Spawning Vats", "E2M8: Tower of Babel",  "E2M9: Fortress of Mystery",
     76 		"E3M1: Hell Keep", "E3M2: Slough of Despair", "E3M3: Pandemonium", "E3M4: House of Pain", "E3M5: Unholy Cathedral", "E3M6: MT. Erebus", "E3M7: Gate to Limbo", "E3M8: DIS", "E3M9: Warrens", 
     77 		"E4M1: Hell Beneath", "E4M2: Perfect Hatred", "E4M3: Sever The Wicked", "E4M4: Unruly Evil", "E4M5: They Will Repent", "E4M6: Against Thee Wickedly", "E4M7: And Hell Followed", "E4M8: Unto The Cruel", "E4M9: Fear"
     78 	};
     79 
     80 	static const char * Doom2_MapNames[] = {
     81 		"1: Entryway", "2: Underhalls", "3: The Gantlet", "4: The Focus", "5: The Waste Tunnels", "6: The Crusher", "7: Dead Simple", "8: Tricks and Traps", "9: The Pit", "10: Refueling Base", 
     82 		"11: Circle of Death", "12: The Factory", "13: Downtown", "14: The Inmost Dens", "15: Industrial Zone", "16: Suburbs", "17: Tenements", "18: The Courtyard", "19: The Citadel", "20: Gotcha!", 
     83 		"21: Nirvana", "22: The Catacombs", "23: Barrels O' Fun", "24: The Chasm", "25: Bloodfalls", "26: The Abandoned Mines", "27: Monster Condo", "28: The Spirit World", "29: The Living End",
     84 		"30: Icon of Sin", "31: IDKFA", "32: Keen"
     85 	};
     86 
     87 	static const char * TNT_MapNames[] = {
     88 		"1: System Control", "2: Human BBQ", "3: Power Control", "4: Wormhole", "5: Hangar", "6: Open Season", "7: Prison", "8: Metal", "9: Stronghold", "10: Redemption", "11: Storage Facility",
     89 		"12: Crater", "13: Nukage Processing", "14: Steel Works", "15: Dead Zone", "16: Deepest Reaches", "17: Processing Area", "18: Mill", "19: Shipping & Respawning", "20: Central Processing",
     90 		"21: Administration Center", "22: Habitat", "23: Lunar Mining Project", "24: Quarry", "25: Baron's Den", "26: Ballistyx", "27: Mount Pain", "28: Heck", "29: River Styx", "30: Last Call", "31: Pharaoh", "32: Caribbean"
     91 	};
     92 
     93 	static const char * Plut_MapNames[] = {
     94 		"1: Congo", "2: Well of Souls", "3: Aztec", "4: Caged", "5: Ghost Town", "6: Baron's Lair", "7: Caughtyard", "8: Realm", "9: Abattoire", "10: Onslaught", "11: Hunted", "12: Speed", "13: The Crypt", "14: Genesis", 
     95 		"15: The Twilight", "16: The Omen", "17: Compound", "18: Neurosphere", "19: NME", "20: The Death Domain", "21: Slayer", "22: Impossible Mission", "23: Tombstone", "24: The Final Frontier", "25: The Temple of Darkness",
     96 		"26: Bunker", "27: Anti-Christ", "28: The Sewers", "29: Odyssey of Noises", "30: The Gateway of Hell", "31: Cyberden", "32: Go 2 It"
     97 	};
     98 
     99 	static const char * Mast_MapNames[] = {
    100 		"1: Attack", "2: Canyon","3: The Catwalk", "4: The Combine", "5: The Fistula", "6: The Garrison", "7: Titan Manor", "8: Paradox", "9: Subspace", "10: Subterra", "11: Trapped On Titan", "12: Virgil's Lead", "13: Minos' Judgement", 
    101 		"14: Bloodsea Keep", "15: Mephisto's Maosoleum", "16: Nessus", "17: Geryon", "18: Vesperas", "19: Black Tower", "20: The Express Elevator To Hell", "21: Bad Dream"
    102 	};
    103 
    104 	static const char * Nerve_MapNames[] = {
    105 		"1: The Earth Base", "2: The Pain Labs", "3: Canyon of the Dead", "4: Hell Mountain", "5: Vivisection", "6: Inferno of Blood", "7: Baron's Banquet", "8: Tomb of Malevolence", "9: March of Demons"
    106 	};
    107 
    108 	const ExpansionData App_Expansion_Data_Local[] = {
    109 		{	ExpansionData::IWAD, retail,		doom,			"DOOM",								DOOMWADDIR"DOOM.WAD",		NULL,							"base/textures/DOOMICON.PNG"	, Doom_MapNames },
    110 		{	ExpansionData::IWAD, commercial,	doom2,			"DOOM 2",							DOOMWADDIR"DOOM2.WAD",		NULL,							"base/textures/DOOM2ICON.PNG"	, Doom2_MapNames },
    111 		{	ExpansionData::IWAD, commercial,	pack_tnt,		"FINAL DOOM: TNT EVILUTION",		DOOMWADDIR"TNT.WAD",		NULL,							"base/textures/TNTICON.PNG"		, TNT_MapNames },
    112 		{	ExpansionData::IWAD, commercial,	pack_plut,		"FINAL DOOM: PLUTONIA EXPERIMENT",	DOOMWADDIR"PLUTONIA.WAD",	NULL,							"base/textures/PLUTICON.PNG"	, Plut_MapNames },
    113 		{	ExpansionData::PWAD, commercial,	pack_master,	"DOOM 2: MASTER LEVELS",			DOOMWADDIR"DOOM2.WAD",		DOOMWADDIR"MASTERLEVELS.WAD",	"base/textures/MASTICON.PNG"	, Mast_MapNames },
    114 		{	ExpansionData::PWAD, commercial,	pack_nerve,		"DOOM 2: NO REST FOR THE LIVING",	DOOMWADDIR"DOOM2.WAD",		DOOMWADDIR"NERVE.WAD",			"base/textures/NERVEICON.PNG"	, Nerve_MapNames },
    115 	};
    116 
    117 	int classicRemap[K_LAST_KEY];
    118 
    119 	const ExpansionData * GetCurrentExpansion() {
    120 		return &App_Expansion_Data_Local[ DoomLib::expansionSelected ];
    121 	}
    122 
    123 	void				  SetCurrentExpansion( int expansion )  { 
    124 		expansionDirty = true; 
    125 		expansionSelected = expansion; 
    126 	}
    127 
    128 	void						SetIdealExpansion( int expansion ) {
    129 		idealExpansion = expansion;
    130 	}
    131 
    132 	idStr						currentMapName;
    133 	idStr						currentDifficulty;
    134 
    135 	void						SetCurrentMapName( idStr name ) { currentMapName = name; }
    136 	const idStr &				GetCurrentMapName() { return currentMapName; }
    137 	void						SetCurrentDifficulty( idStr name ) { currentDifficulty = name; }
    138 	const idStr &				GetCurrentDifficulty() { return currentDifficulty; }
    139 
    140 	int currentplayer = -1;
    141 
    142 	Globals *globaldata[4];
    143 
    144 	RecvFunc Recv;
    145 	SendFunc Send;
    146 	SendRemoteFunc SendRemote;
    147 
    148 
    149 	bool							Active = true;
    150 	DoomInterface					Interface;
    151 
    152 	int								idealExpansion = 0;
    153 	int								expansionSelected = 0;
    154 	bool							expansionDirty = true;
    155 
    156 	bool							skipToLoad = false;
    157 	char							loadGamePath[MAX_PATH];
    158 
    159 	bool							skipToNew = false;
    160 	int								chosenSkill = 0;
    161 	int								chosenEpisode = 1;
    162 
    163 	idMatchParameters				matchParms;
    164 
    165 	void * (*Z_Malloc)( int size, int tag, void* user ) = NULL;
    166 	void 	(*Z_FreeTag)(int lowtag );
    167 
    168 	idArray< idSysMutex, 4 >		playerScreenMutexes;
    169 
    170 	void ExitGame() {
    171 		// TODO: If we ever support splitscreen and online,
    172 		// we'll have to call D_QuitNetGame for all local players.
    173 		DoomLib::SetPlayer( 0 );
    174 		D_QuitNetGame();
    175 
    176 		session->QuitMatch();
    177 	}
    178 
    179 	void ShowXToContinue( bool activate ) {
    180 	}
    181 
    182 	/*
    183 	========================
    184 	DoomLib::GetGameSKU
    185 	========================
    186 	*/
    187 	gameSKU_t GetGameSKU() {
    188 	
    189 		if ( common->GetCurrentGame() == DOOM_CLASSIC ) {
    190 			return GAME_SKU_DOOM1_BFG;
    191 		} else if ( common->GetCurrentGame() == DOOM2_CLASSIC ) {
    192 			return GAME_SKU_DOOM2_BFG;
    193 		}
    194 
    195 		assert( false && "Invalid basepath" );
    196 		return GAME_SKU_DCC;
    197 	}
    198 
    199 	/*
    200 	========================
    201 	DoomLib::ActivateGame
    202 	========================
    203 	*/
    204 	void ActivateGame() {
    205 		Active = true;
    206 
    207 		// Turn off menu toggler
    208 		int originalPlayer = DoomLib::GetPlayer();
    209 
    210 		for ( int i = 0; i < Interface.GetNumPlayers(); i++ ) {
    211 			DoomLib::SetPlayer(i);
    212 			::g->menuactive = false;
    213 		}
    214 
    215 		globalPauseTime = false;
    216 
    217 		DoomLib::SetPlayer( originalPlayer );
    218 	}
    219 
    220 	/*
    221 	========================
    222 	DoomLib::HandleEndMatch
    223 	========================
    224 	*/
    225 	void HandleEndMatch() {
    226 		if ( session->GetGameLobbyBase().IsHost() ) {
    227 			ShowXToContinue( false );
    228 			session->EndMatch();
    229 		}
    230 	}
    231 };
    232 
    233 
    234 extern void I_InitGraphics();
    235 extern void D_DoomMain();
    236 extern bool D_DoomMainPoll();
    237 extern void I_InitInput();
    238 extern void D_RunFrame( bool );
    239 extern void I_ShutdownSound();
    240 extern void I_ShutdownMusic();
    241 extern void I_ShutdownGraphics();
    242 extern void I_ProcessSoundEvents( void );
    243 
    244 
    245 void DoomLib::InitGlobals( void *ptr /* = NULL */ )
    246 {
    247 	if (ptr == NULL)
    248 		ptr = new Globals;
    249 
    250 	globaldata[currentplayer] = static_cast<Globals*>(ptr);
    251 
    252 	memset( globaldata[currentplayer], 0, sizeof(Globals) );
    253 	g = globaldata[currentplayer];
    254 	g->InitGlobals();
    255 	
    256 }
    257 
    258 void *DoomLib::GetGlobalData( int player ) {
    259 	return globaldata[player];
    260 }
    261 
    262 void DoomLib::InitControlRemap() {
    263 
    264 	memset( classicRemap, K_NONE, sizeof( classicRemap ) );
    265 
    266 	classicRemap[K_JOY3] = KEY_TAB ; 
    267 	classicRemap[K_JOY4] = K_MINUS;
    268 	classicRemap[K_JOY2] = K_EQUALS;
    269 	classicRemap[K_JOY9] = K_ESCAPE ;
    270 	classicRemap[K_JOY_STICK1_UP] = K_UPARROW ;
    271 	classicRemap[K_JOY_DPAD_UP] = K_UPARROW ;
    272 	classicRemap[K_JOY_STICK1_DOWN] = K_DOWNARROW ;
    273 	classicRemap[K_JOY_DPAD_DOWN] = K_DOWNARROW ;
    274 	classicRemap[K_JOY_STICK1_LEFT] = K_LEFTARROW ;
    275 	classicRemap[K_JOY_DPAD_LEFT] = K_LEFTARROW ;
    276 	classicRemap[K_JOY_STICK1_RIGHT] = K_RIGHTARROW ;
    277 	classicRemap[K_JOY_DPAD_RIGHT] = K_RIGHTARROW ;	
    278 	classicRemap[K_JOY1] = K_ENTER;
    279 
    280 
    281 }
    282 
    283 keyNum_t DoomLib::RemapControl( keyNum_t key ) {
    284 
    285 	if( classicRemap[ key ] == K_NONE ) {
    286 		return key;
    287 	} else {
    288 
    289 		if( ::g->menuactive && key == K_JOY2 ) {
    290 			return K_BACKSPACE;
    291 		}
    292 
    293 		return (keyNum_t)classicRemap[ key ];
    294 	}
    295 
    296 }
    297 
    298 void DoomLib::InitGame( int argc, char** argv )
    299 {
    300 	::g->myargc = argc;
    301 	::g->myargv = argv;
    302 
    303 	InitControlRemap();
    304 		
    305 
    306 
    307 	D_DoomMain();
    308 }
    309 
    310 bool DoomLib::Poll()
    311 {
    312 	return D_DoomMainPoll();
    313 }
    314 
    315 bool TryRunTics( idUserCmdMgr * userCmdMgr );
    316 bool DoomLib::Tic( idUserCmdMgr * userCmdMgr )
    317 {
    318 	return TryRunTics( userCmdMgr );
    319 }
    320 
    321 void D_Wipe();
    322 void DoomLib::Wipe()
    323 {
    324 	D_Wipe();
    325 }
    326 
    327 void DoomLib::Frame( int realoffset, int buffer )
    328 {
    329 	::g->realoffset = realoffset;
    330 
    331 	// The render thread needs to read the player's screens[0] array,
    332 	// so updating it needs to be in a critical section.
    333 	// This may seem like a really broad mutex (which it is), and if performance
    334 	// suffers too much, we can try to narrow the scope.
    335 	// Just be careful, because the player's screen data is updated in many different
    336 	// places.
    337 	if ( 0 <= currentplayer && currentplayer <= 4 ) {
    338 		idScopedCriticalSection crit( playerScreenMutexes[currentplayer] );
    339 
    340 		D_RunFrame( true );
    341 	}
    342 }
    343 
    344 void DoomLib::Draw()
    345 {
    346 	R_RenderPlayerView (&::g->players[::g->displayplayer]);
    347 }
    348 
    349 angle_t GetViewAngle()
    350 {
    351 	return g->viewangle;
    352 }
    353 
    354 void SetViewAngle( angle_t ang )
    355 {
    356 	g->viewangle = ang;
    357 	::g->viewxoffset = (finesine[g->viewangle>>ANGLETOFINESHIFT]*::g->realoffset) >> 8;
    358 	::g->viewyoffset = (finecosine[g->viewangle>>ANGLETOFINESHIFT]*::g->realoffset) >> 8;
    359 	
    360 }
    361 
    362 
    363 void SetViewX( fixed_t x )
    364 {
    365 	::g->viewx = x;
    366 }
    367 
    368 void SetViewY( fixed_t y )
    369 {
    370 	::g->viewy = y;
    371 }
    372 
    373 
    374 fixed_t GetViewX()
    375 {
    376 	return ::g->viewx + ::g->viewxoffset;
    377 }
    378 
    379 fixed_t GetViewY()
    380 {
    381 	return ::g->viewy + ::g->viewyoffset;
    382 }
    383 
    384 void DoomLib::Shutdown() {
    385 	//D_QuitNetGame ();
    386 	I_ShutdownSound();
    387 	I_ShutdownGraphics();
    388 
    389 	W_Shutdown();
    390 
    391 	// De-allocate the zone memory (never happened in original doom, until quit)
    392 	if ( ::g->mainzone ) {
    393 		free( ::g->mainzone );
    394 	}
    395 
    396 	// Delete the globals
    397 	if ( globaldata[currentplayer] ) {
    398 		delete globaldata[currentplayer];
    399 		globaldata[currentplayer] = NULL;
    400 	}
    401 }
    402 
    403 // static
    404 void DoomLib::SetPlayer( int id )
    405 {
    406 	currentplayer = id;
    407 
    408 	if ( id < 0 || id >= MAX_PLAYERS ) {
    409 		g = NULL;
    410 	}
    411 	else {
    412 
    413 		// Big Fucking hack.
    414 		if( globalNetworking && session->GetGameLobbyBase().GetMatchParms().matchFlags | MATCH_ONLINE ) {
    415 			currentplayer = 0;
    416 		} 
    417 		
    418 		g = globaldata[currentplayer];
    419 	}
    420 }
    421 
    422 void DoomLib::SetNetworking( RecvFunc rf, SendFunc sf, SendRemoteFunc sendRemote )
    423 {
    424 	Recv = rf;
    425 	Send = sf;
    426 	SendRemote = sendRemote;
    427 }
    428 
    429 int DoomLib::GetPlayer() 
    430 { 
    431 	return currentplayer; 
    432 }
    433 
    434 byte DoomLib::BuildSourceDest( int toNode ) {
    435 	byte sourceDest = 0;
    436 	sourceDest |= ::g->consoleplayer << 2;
    437 	sourceDest |= RemoteNodeToPlayerIndex( toNode );
    438 	return sourceDest;
    439 }
    440 
    441 void I_Printf(char *error, ...);
    442 
    443 void DoomLib::GetSourceDest( byte sourceDest, int* source, int* dest ) {
    444 
    445 	int src = (sourceDest & 12) >> 2;
    446 	int dst = sourceDest & 3;
    447 
    448 	*source = PlayerIndexToRemoteNode( src );
    449 
    450 	//I_Printf( "GetSourceDest Current Player(%d) %d --> %d\n", GetPlayer(), src, *source );
    451 	*dest = PlayerIndexToRemoteNode( dst );
    452 }
    453 
    454 int nodeMap[4][4] = {
    455 	{0, 1, 2, 3},	//Player 0
    456 	{1, 0, 2, 3},	//Player 1
    457 	{2, 0, 1, 3},	//Player 2
    458 	{3, 0, 1, 2}	//Player 3
    459 };
    460 
    461 int DoomLib::RemoteNodeToPlayerIndex( int node ) {
    462 	//This needs to be called with the proper doom globals set so this calculation will work properly
    463 	
    464 	/*
    465 	int player = ::g->consoleplayer;
    466 	if (player == 2 && node == 2 ) {
    467 		int suck = 0;
    468 	}
    469 	if( node == player ) {
    470 		return 0;
    471 	}
    472 	if( node - player <= 0 ) {
    473 		return node+1;
    474 	}
    475 	return node;*/
    476 	return nodeMap[::g->consoleplayer][node];
    477 
    478 }
    479 
    480 int indexMap[4][4] = {
    481 	{0, 1, 2, 3},	//Player 0
    482 	{1, 0, 2, 3},	//Player 1
    483 	{1, 2, 0, 3},	//Player 2
    484 	{1, 2, 3, 0}	//Player 3
    485 };
    486 
    487 int DoomLib::PlayerIndexToRemoteNode( int index ) {
    488 	/*int player = ::g->consoleplayer;
    489 	if( index == 0 ) {
    490 		return player;
    491 	}
    492 	if( index <= player ) {
    493 		return index-1;
    494 	}
    495 	return index;*/
    496 	return indexMap[::g->consoleplayer][index];
    497 }
    498 
    499 void I_Error (char *error, ...);
    500 extern bool useTech5Packets;
    501 
    502 void DoomLib::PollNetwork() {
    503 #if 0
    504 	if ( !useTech5Packets ) {
    505 
    506 		if ( !globalNetworking ) {
    507 			return;
    508 		}
    509 
    510 		int			c;
    511 		struct sockaddr	fromaddress;
    512 		socklen_t		fromlen;
    513 		doomdata_t		sw;
    514 
    515 		while(1) {
    516 			int receivedSize = recvfrom( ::g->insocket, &sw, sizeof( doomdata_t ), MSG_DONTWAIT, &fromaddress, &fromlen );
    517 			//c = WSARecvFrom(::g->insocket, &buffer, 1, &num_recieved, &flags, (struct sockaddr*)&fromaddress, &fromlen, 0, 0);
    518 
    519 			if ( receivedSize < 0 )
    520 			{
    521 				int err = sys_net_errno;
    522 				if (err != SYS_NET_EWOULDBLOCK ) {
    523 					I_Error ("GetPacket: %d", err );
    524 					//I_Printf ("GetPacket: %s",strerror(errno));
    525 				}
    526 				return;
    527 			}
    528 
    529 			printf( "RECEIVED PACKET!!\n" );
    530 
    531 			int source;
    532 			int dest;
    533 			GetSourceDest( sw.sourceDest, &source, &dest );
    534 
    535 			//Push the packet onto the network stack to be processed.
    536 			DoomLib::Send( (char*)&sw, receivedSize, NULL, dest );
    537 		}
    538 	}
    539 #endif
    540 }
    541 
    542 void DoomLib::SendNetwork() {
    543 
    544 	if ( !globalNetworking ) {
    545 		return;
    546 	}
    547 	DoomLib::SendRemote();	
    548 }
    549 
    550 void DoomLib::RunSound() {
    551 
    552 	I_ProcessSoundEvents();
    553 }
    554