doomlib.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. #include "Precompiled.h"
  21. #include "globaldata.h"
  22. #include "doomlib.h"
  23. #include <assert.h>
  24. #include "Main.h"
  25. #include "sys/sys_session.h"
  26. #include "idlib/Thread.h"
  27. #include <sys/types.h>
  28. // Store master volume settings in archived cvars, becausue we want them to apply
  29. // even if a user isn't signed in.
  30. // The range is from 0 to 15, which matches the setting in vanilla DOOM.
  31. idCVar s_volume_sound( "s_volume_sound", "8", CVAR_ARCHIVE | CVAR_INTEGER, "sound volume", 0, 15 );
  32. idCVar s_volume_midi( "s_volume_midi", "8", CVAR_ARCHIVE | CVAR_INTEGER, "music volume", 0, 15 );
  33. idCVar m_show_messages( "m_show_messages", "1", CVAR_ARCHIVE | CVAR_INTEGER, "show messages", 0, 1 );
  34. idCVar m_inDemoMode( "m_inDemoMode", "1", CVAR_INTEGER, "in demo mode", 0, 1 );
  35. bool globalNetworking = false;
  36. bool globalPauseTime = false;
  37. int PLAYERCOUNT = 1;
  38. #ifdef _DEBUG
  39. bool debugOutput = true;
  40. #else
  41. bool debugOutput = false;
  42. #endif
  43. namespace DoomLib
  44. {
  45. static const char * Expansion_Names[] = {
  46. "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"
  47. };
  48. static const char* Skill_Names[] = {
  49. "I'm Too Young To Die!", "Hey, Not Too Rough!", "Hurt Me Plenty!", "Ultra-Violence", "Nightmare"
  50. };
  51. static const char* Filter_Names[] = {
  52. "#str_friends", "#str_around", "#str_top15"
  53. };
  54. // Game-specific setup values.
  55. static const char * Doom_MapNames[] = {
  56. "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",
  57. "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",
  58. "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",
  59. "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"
  60. };
  61. static const char * Doom2_MapNames[] = {
  62. "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",
  63. "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!",
  64. "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",
  65. "30: Icon of Sin", "31: IDKFA", "32: Keen"
  66. };
  67. static const char * TNT_MapNames[] = {
  68. "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",
  69. "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",
  70. "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"
  71. };
  72. static const char * Plut_MapNames[] = {
  73. "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",
  74. "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",
  75. "26: Bunker", "27: Anti-Christ", "28: The Sewers", "29: Odyssey of Noises", "30: The Gateway of Hell", "31: Cyberden", "32: Go 2 It"
  76. };
  77. static const char * Mast_MapNames[] = {
  78. "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",
  79. "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"
  80. };
  81. static const char * Nerve_MapNames[] = {
  82. "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"
  83. };
  84. const ExpansionData App_Expansion_Data_Local[] = {
  85. { ExpansionData::IWAD, retail, doom, "DOOM", DOOMWADDIR"DOOM.WAD", NULL, "base/textures/DOOMICON.PNG" , Doom_MapNames },
  86. { ExpansionData::IWAD, commercial, doom2, "DOOM 2", DOOMWADDIR"DOOM2.WAD", NULL, "base/textures/DOOM2ICON.PNG" , Doom2_MapNames },
  87. { ExpansionData::IWAD, commercial, pack_tnt, "FINAL DOOM: TNT EVILUTION", DOOMWADDIR"TNT.WAD", NULL, "base/textures/TNTICON.PNG" , TNT_MapNames },
  88. { ExpansionData::IWAD, commercial, pack_plut, "FINAL DOOM: PLUTONIA EXPERIMENT", DOOMWADDIR"PLUTONIA.WAD", NULL, "base/textures/PLUTICON.PNG" , Plut_MapNames },
  89. { ExpansionData::PWAD, commercial, pack_master, "DOOM 2: MASTER LEVELS", DOOMWADDIR"DOOM2.WAD", DOOMWADDIR"MASTERLEVELS.WAD", "base/textures/MASTICON.PNG" , Mast_MapNames },
  90. { ExpansionData::PWAD, commercial, pack_nerve, "DOOM 2: NO REST FOR THE LIVING", DOOMWADDIR"DOOM2.WAD", DOOMWADDIR"NERVE.WAD", "base/textures/NERVEICON.PNG" , Nerve_MapNames },
  91. };
  92. int classicRemap[K_LAST_KEY];
  93. const ExpansionData * GetCurrentExpansion() {
  94. return &App_Expansion_Data_Local[ DoomLib::expansionSelected ];
  95. }
  96. void SetCurrentExpansion( int expansion ) {
  97. expansionDirty = true;
  98. expansionSelected = expansion;
  99. }
  100. void SetIdealExpansion( int expansion ) {
  101. idealExpansion = expansion;
  102. }
  103. idStr currentMapName;
  104. idStr currentDifficulty;
  105. void SetCurrentMapName( idStr name ) { currentMapName = name; }
  106. const idStr & GetCurrentMapName() { return currentMapName; }
  107. void SetCurrentDifficulty( idStr name ) { currentDifficulty = name; }
  108. const idStr & GetCurrentDifficulty() { return currentDifficulty; }
  109. int currentplayer = -1;
  110. Globals *globaldata[4];
  111. RecvFunc Recv;
  112. SendFunc Send;
  113. SendRemoteFunc SendRemote;
  114. bool Active = true;
  115. DoomInterface Interface;
  116. int idealExpansion = 0;
  117. int expansionSelected = 0;
  118. bool expansionDirty = true;
  119. bool skipToLoad = false;
  120. char loadGamePath[MAX_PATH];
  121. bool skipToNew = false;
  122. int chosenSkill = 0;
  123. int chosenEpisode = 1;
  124. idMatchParameters matchParms;
  125. void * (*Z_Malloc)( int size, int tag, void* user ) = NULL;
  126. void (*Z_FreeTag)(int lowtag );
  127. idArray< idSysMutex, 4 > playerScreenMutexes;
  128. void ExitGame() {
  129. // TODO: If we ever support splitscreen and online,
  130. // we'll have to call D_QuitNetGame for all local players.
  131. DoomLib::SetPlayer( 0 );
  132. D_QuitNetGame();
  133. session->QuitMatch();
  134. }
  135. void ShowXToContinue( bool activate ) {
  136. }
  137. /*
  138. ========================
  139. DoomLib::GetGameSKU
  140. ========================
  141. */
  142. gameSKU_t GetGameSKU() {
  143. if ( common->GetCurrentGame() == DOOM_CLASSIC ) {
  144. return GAME_SKU_DOOM1_BFG;
  145. } else if ( common->GetCurrentGame() == DOOM2_CLASSIC ) {
  146. return GAME_SKU_DOOM2_BFG;
  147. }
  148. assert( false && "Invalid basepath" );
  149. return GAME_SKU_DCC;
  150. }
  151. /*
  152. ========================
  153. DoomLib::ActivateGame
  154. ========================
  155. */
  156. void ActivateGame() {
  157. Active = true;
  158. // Turn off menu toggler
  159. int originalPlayer = DoomLib::GetPlayer();
  160. for ( int i = 0; i < Interface.GetNumPlayers(); i++ ) {
  161. DoomLib::SetPlayer(i);
  162. ::g->menuactive = false;
  163. }
  164. globalPauseTime = false;
  165. DoomLib::SetPlayer( originalPlayer );
  166. }
  167. /*
  168. ========================
  169. DoomLib::HandleEndMatch
  170. ========================
  171. */
  172. void HandleEndMatch() {
  173. if ( session->GetGameLobbyBase().IsHost() ) {
  174. ShowXToContinue( false );
  175. session->EndMatch();
  176. }
  177. }
  178. };
  179. extern void I_InitGraphics();
  180. extern void D_DoomMain();
  181. extern bool D_DoomMainPoll();
  182. extern void I_InitInput();
  183. extern void D_RunFrame( bool );
  184. extern void I_ShutdownSound();
  185. extern void I_ShutdownMusic();
  186. extern void I_ShutdownGraphics();
  187. extern void I_ProcessSoundEvents( void );
  188. void DoomLib::InitGlobals( void *ptr /* = NULL */ )
  189. {
  190. if (ptr == NULL)
  191. ptr = new Globals;
  192. globaldata[currentplayer] = static_cast<Globals*>(ptr);
  193. memset( globaldata[currentplayer], 0, sizeof(Globals) );
  194. g = globaldata[currentplayer];
  195. g->InitGlobals();
  196. }
  197. void *DoomLib::GetGlobalData( int player ) {
  198. return globaldata[player];
  199. }
  200. void DoomLib::InitControlRemap() {
  201. memset( classicRemap, K_NONE, sizeof( classicRemap ) );
  202. classicRemap[K_JOY3] = KEY_TAB ;
  203. classicRemap[K_JOY4] = K_MINUS;
  204. classicRemap[K_JOY2] = K_EQUALS;
  205. classicRemap[K_JOY9] = K_ESCAPE ;
  206. classicRemap[K_JOY_STICK1_UP] = K_UPARROW ;
  207. classicRemap[K_JOY_DPAD_UP] = K_UPARROW ;
  208. classicRemap[K_JOY_STICK1_DOWN] = K_DOWNARROW ;
  209. classicRemap[K_JOY_DPAD_DOWN] = K_DOWNARROW ;
  210. classicRemap[K_JOY_STICK1_LEFT] = K_LEFTARROW ;
  211. classicRemap[K_JOY_DPAD_LEFT] = K_LEFTARROW ;
  212. classicRemap[K_JOY_STICK1_RIGHT] = K_RIGHTARROW ;
  213. classicRemap[K_JOY_DPAD_RIGHT] = K_RIGHTARROW ;
  214. classicRemap[K_JOY1] = K_ENTER;
  215. }
  216. keyNum_t DoomLib::RemapControl( keyNum_t key ) {
  217. if( classicRemap[ key ] == K_NONE ) {
  218. return key;
  219. } else {
  220. if( ::g->menuactive && key == K_JOY2 ) {
  221. return K_BACKSPACE;
  222. }
  223. return (keyNum_t)classicRemap[ key ];
  224. }
  225. }
  226. void DoomLib::InitGame( int argc, char** argv )
  227. {
  228. ::g->myargc = argc;
  229. ::g->myargv = argv;
  230. InitControlRemap();
  231. D_DoomMain();
  232. }
  233. bool DoomLib::Poll()
  234. {
  235. return D_DoomMainPoll();
  236. }
  237. bool TryRunTics( idUserCmdMgr * userCmdMgr );
  238. bool DoomLib::Tic( idUserCmdMgr * userCmdMgr )
  239. {
  240. return TryRunTics( userCmdMgr );
  241. }
  242. void D_Wipe();
  243. void DoomLib::Wipe()
  244. {
  245. D_Wipe();
  246. }
  247. void DoomLib::Frame( int realoffset, int buffer )
  248. {
  249. ::g->realoffset = realoffset;
  250. // The render thread needs to read the player's screens[0] array,
  251. // so updating it needs to be in a critical section.
  252. // This may seem like a really broad mutex (which it is), and if performance
  253. // suffers too much, we can try to narrow the scope.
  254. // Just be careful, because the player's screen data is updated in many different
  255. // places.
  256. if ( 0 <= currentplayer && currentplayer <= 4 ) {
  257. idScopedCriticalSection crit( playerScreenMutexes[currentplayer] );
  258. D_RunFrame( true );
  259. }
  260. }
  261. void DoomLib::Draw()
  262. {
  263. R_RenderPlayerView (&::g->players[::g->displayplayer]);
  264. }
  265. angle_t GetViewAngle()
  266. {
  267. return g->viewangle;
  268. }
  269. void SetViewAngle( angle_t ang )
  270. {
  271. g->viewangle = ang;
  272. ::g->viewxoffset = (finesine[g->viewangle>>ANGLETOFINESHIFT]*::g->realoffset) >> 8;
  273. ::g->viewyoffset = (finecosine[g->viewangle>>ANGLETOFINESHIFT]*::g->realoffset) >> 8;
  274. }
  275. void SetViewX( fixed_t x )
  276. {
  277. ::g->viewx = x;
  278. }
  279. void SetViewY( fixed_t y )
  280. {
  281. ::g->viewy = y;
  282. }
  283. fixed_t GetViewX()
  284. {
  285. return ::g->viewx + ::g->viewxoffset;
  286. }
  287. fixed_t GetViewY()
  288. {
  289. return ::g->viewy + ::g->viewyoffset;
  290. }
  291. void DoomLib::Shutdown() {
  292. //D_QuitNetGame ();
  293. I_ShutdownSound();
  294. I_ShutdownGraphics();
  295. W_Shutdown();
  296. // De-allocate the zone memory (never happened in original doom, until quit)
  297. if ( ::g->mainzone ) {
  298. free( ::g->mainzone );
  299. }
  300. // Delete the globals
  301. if ( globaldata[currentplayer] ) {
  302. delete globaldata[currentplayer];
  303. globaldata[currentplayer] = NULL;
  304. }
  305. }
  306. // static
  307. void DoomLib::SetPlayer( int id )
  308. {
  309. currentplayer = id;
  310. if ( id < 0 || id >= MAX_PLAYERS ) {
  311. g = NULL;
  312. }
  313. else {
  314. // Big Fucking hack.
  315. if( globalNetworking && session->GetGameLobbyBase().GetMatchParms().matchFlags | MATCH_ONLINE ) {
  316. currentplayer = 0;
  317. }
  318. g = globaldata[currentplayer];
  319. }
  320. }
  321. void DoomLib::SetNetworking( RecvFunc rf, SendFunc sf, SendRemoteFunc sendRemote )
  322. {
  323. Recv = rf;
  324. Send = sf;
  325. SendRemote = sendRemote;
  326. }
  327. int DoomLib::GetPlayer()
  328. {
  329. return currentplayer;
  330. }
  331. byte DoomLib::BuildSourceDest( int toNode ) {
  332. byte sourceDest = 0;
  333. sourceDest |= ::g->consoleplayer << 2;
  334. sourceDest |= RemoteNodeToPlayerIndex( toNode );
  335. return sourceDest;
  336. }
  337. void I_Printf(char *error, ...);
  338. void DoomLib::GetSourceDest( byte sourceDest, int* source, int* dest ) {
  339. int src = (sourceDest & 12) >> 2;
  340. int dst = sourceDest & 3;
  341. *source = PlayerIndexToRemoteNode( src );
  342. //I_Printf( "GetSourceDest Current Player(%d) %d --> %d\n", GetPlayer(), src, *source );
  343. *dest = PlayerIndexToRemoteNode( dst );
  344. }
  345. int nodeMap[4][4] = {
  346. {0, 1, 2, 3}, //Player 0
  347. {1, 0, 2, 3}, //Player 1
  348. {2, 0, 1, 3}, //Player 2
  349. {3, 0, 1, 2} //Player 3
  350. };
  351. int DoomLib::RemoteNodeToPlayerIndex( int node ) {
  352. //This needs to be called with the proper doom globals set so this calculation will work properly
  353. /*
  354. int player = ::g->consoleplayer;
  355. if (player == 2 && node == 2 ) {
  356. int suck = 0;
  357. }
  358. if( node == player ) {
  359. return 0;
  360. }
  361. if( node - player <= 0 ) {
  362. return node+1;
  363. }
  364. return node;*/
  365. return nodeMap[::g->consoleplayer][node];
  366. }
  367. int indexMap[4][4] = {
  368. {0, 1, 2, 3}, //Player 0
  369. {1, 0, 2, 3}, //Player 1
  370. {1, 2, 0, 3}, //Player 2
  371. {1, 2, 3, 0} //Player 3
  372. };
  373. int DoomLib::PlayerIndexToRemoteNode( int index ) {
  374. /*int player = ::g->consoleplayer;
  375. if( index == 0 ) {
  376. return player;
  377. }
  378. if( index <= player ) {
  379. return index-1;
  380. }
  381. return index;*/
  382. return indexMap[::g->consoleplayer][index];
  383. }
  384. void I_Error (char *error, ...);
  385. extern bool useTech5Packets;
  386. void DoomLib::PollNetwork() {
  387. #if 0
  388. if ( !useTech5Packets ) {
  389. if ( !globalNetworking ) {
  390. return;
  391. }
  392. int c;
  393. struct sockaddr fromaddress;
  394. socklen_t fromlen;
  395. doomdata_t sw;
  396. while(1) {
  397. int receivedSize = recvfrom( ::g->insocket, &sw, sizeof( doomdata_t ), MSG_DONTWAIT, &fromaddress, &fromlen );
  398. //c = WSARecvFrom(::g->insocket, &buffer, 1, &num_recieved, &flags, (struct sockaddr*)&fromaddress, &fromlen, 0, 0);
  399. if ( receivedSize < 0 )
  400. {
  401. int err = sys_net_errno;
  402. if (err != SYS_NET_EWOULDBLOCK ) {
  403. I_Error ("GetPacket: %d", err );
  404. //I_Printf ("GetPacket: %s",strerror(errno));
  405. }
  406. return;
  407. }
  408. printf( "RECEIVED PACKET!!\n" );
  409. int source;
  410. int dest;
  411. GetSourceDest( sw.sourceDest, &source, &dest );
  412. //Push the packet onto the network stack to be processed.
  413. DoomLib::Send( (char*)&sw, receivedSize, NULL, dest );
  414. }
  415. }
  416. #endif
  417. }
  418. void DoomLib::SendNetwork() {
  419. if ( !globalNetworking ) {
  420. return;
  421. }
  422. DoomLib::SendRemote();
  423. }
  424. void DoomLib::RunSound() {
  425. I_ProcessSoundEvents();
  426. }