A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 255 lines 7.5 kB view raw
1/* Emacs style mode select -*- C++ -*- 2 *----------------------------------------------------------------------------- 3 * 4 * 5 * PrBoom a Doom port merged with LxDoom and LSDLDoom 6 * based on BOOM, a modified and improved DOOM engine 7 * Copyright (C) 1999 by 8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman 9 * Copyright (C) 1999-2000 by 10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 25 * 02111-1307, USA. 26 * 27 * DESCRIPTION: 28 * Thinker, Ticker. 29 * 30 *-----------------------------------------------------------------------------*/ 31 32#include "doomstat.h" 33#include "p_user.h" 34#include "p_spec.h" 35#include "p_tick.h" 36#include "p_map.h" 37#include "rockmacros.h" 38int leveltime; 39 40// 41// THINKERS 42// All thinkers should be allocated by Z_Malloc 43// so they can be operated on uniformly. 44// The actual structures will vary in size, 45// but the first element must be thinker_t. 46// 47 48// Both the head and tail of the thinker list. 49thinker_t thinkercap; 50 51// killough 8/29/98: we maintain several separate threads, each containing 52// a special class of thinkers, to allow more efficient searches. 53 54thinker_t thinkerclasscap[NUMTHCLASS]; 55 56// 57// P_InitThinkers 58// 59 60void P_InitThinkers(void) 61{ 62 int i; 63 64 for (i=0; i<NUMTHCLASS; i++) // killough 8/29/98: initialize threaded lists 65 thinkerclasscap[i].cprev = thinkerclasscap[i].cnext = &thinkerclasscap[i]; 66 67 thinkercap.prev = thinkercap.next = &thinkercap; 68} 69 70// 71// killough 8/29/98: 72// 73// We maintain separate threads of friends and enemies, to permit more 74// efficient searches. 75// 76 77void P_UpdateThinker(thinker_t *thinker) 78{ 79 // find the class the thinker belongs to 80 81 int class = thinker->function == P_MobjThinker && 82 ((mobj_t *) thinker)->health > 0 && 83 (((mobj_t *) thinker)->flags & MF_COUNTKILL || 84 ((mobj_t *) thinker)->type == MT_SKULL) ? 85 ((mobj_t *) thinker)->flags & MF_FRIEND ? 86 th_friends : th_enemies : th_misc; 87 88 // Remove from current thread 89 thinker_t *th = thinker->cnext; 90 (th->cprev = thinker->cprev)->cnext = th; 91 92 // Add to appropriate thread 93 th = &thinkerclasscap[class]; 94 th->cprev->cnext = thinker; 95 thinker->cnext = th; 96 thinker->cprev = th->cprev; 97 th->cprev = thinker; 98} 99 100// 101// P_AddThinker 102// Adds a new thinker at the end of the list. 103// 104 105void P_AddThinker(thinker_t* thinker) 106{ 107 thinkercap.prev->next = thinker; 108 thinker->next = &thinkercap; 109 thinker->prev = thinkercap.prev; 110 thinkercap.prev = thinker; 111 112 thinker->references = 0; // killough 11/98: init reference counter to 0 113 114 // killough 8/29/98: set sentinel pointers, and then add to appropriate list 115 thinker->cnext = thinker->cprev = thinker; 116 P_UpdateThinker(thinker); 117} 118 119// 120// killough 11/98: 121// 122// Make currentthinker external, so that P_RemoveThinkerDelayed 123// can adjust currentthinker when thinkers self-remove. 124 125static thinker_t *currentthinker; 126 127// 128// P_RemoveThinkerDelayed() 129// 130// Called automatically as part of the thinker loop in P_RunThinkers(), 131// on nodes which are pending deletion. 132// 133// If this thinker has no more pointers referencing it indirectly, 134// remove it, and set currentthinker to one node preceeding it, so 135// that the next step in P_RunThinkers() will get its successor. 136// 137 138void P_RemoveThinkerDelayed(thinker_t *thinker) 139{ 140 if (!thinker->references) 141 { 142 thinker_t *next = thinker->next; 143 (next->prev = currentthinker = thinker->prev)->next = next; 144 Z_Free(thinker); 145 } 146} 147 148// 149// P_RemoveThinker 150// 151// Deallocation is lazy -- it will not actually be freed 152// until its thinking turn comes up. 153// 154// killough 4/25/98: 155// 156// Instead of marking the function with -1 value cast to a function pointer, 157// set the function to P_RemoveThinkerDelayed(), so that later, it will be 158// removed automatically as part of the thinker process. 159// 160 161void P_RemoveThinker(thinker_t *thinker) 162{ 163 thinker->function = P_RemoveThinkerDelayed; 164 165 // killough 8/29/98: remove immediately from threaded list 166 (thinker->cnext->cprev = thinker->cprev)->cnext = thinker->cnext; 167} 168 169/* 170 * P_SetTarget 171 * 172 * This function is used to keep track of pointer references to mobj thinkers. 173 * In Doom, objects such as lost souls could sometimes be removed despite 174 * their still being referenced. In Boom, 'target' mobj fields were tested 175 * during each gametic, and any objects pointed to by them would be prevented 176 * from being removed. But this was incomplete, and was slow (every mobj was 177 * checked during every gametic). Now, we keep a count of the number of 178 * references, and delay removal until the count is 0. 179 */ 180 181void P_SetTarget(mobj_t **mop, mobj_t *targ) 182{ 183 if (*mop) // If there was a target already, decrease its refcount 184 (*mop)->thinker.references--; 185 if ((*mop = targ)) // Set new target and if non-NULL, increase its counter 186 targ->thinker.references++; 187} 188 189// 190// P_RunThinkers 191// 192// killough 4/25/98: 193// 194// Fix deallocator to stop using "next" pointer after node has been freed 195// (a Doom bug). 196// 197// Process each thinker. For thinkers which are marked deleted, we must 198// load the "next" pointer prior to freeing the node. In Doom, the "next" 199// pointer was loaded AFTER the thinker was freed, which could have caused 200// crashes. 201// 202// But if we are not deleting the thinker, we should reload the "next" 203// pointer after calling the function, in case additional thinkers are 204// added at the end of the list. 205// 206// killough 11/98: 207// 208// Rewritten to delete nodes implicitly, by making currentthinker 209// external and using P_RemoveThinkerDelayed() implicitly. 210// 211 212static void P_RunThinkers (void) 213{ 214 for (currentthinker = thinkercap.next; 215 currentthinker != &thinkercap; 216 currentthinker = currentthinker->next) 217 if (currentthinker->function) 218 currentthinker->function(currentthinker); 219} 220 221// 222// P_Ticker 223// 224 225void P_Ticker (void) 226{ 227 int i; 228 229 /* pause if in menu and at least one tic has been run 230 * 231 * killough 9/29/98: note that this ties in with basetic, 232 * since G_Ticker does the pausing during recording or 233 * playback, and compenates by incrementing basetic. 234 * 235 * All of this complicated mess is used to preserve demo sync. 236 */ 237 238 if (paused || (menuactive && !demoplayback && !netgame && 239 players[consoleplayer].viewz != 1)) 240 return; 241 242 P_MapStart(); 243 // not if this is an intermission screen 244 if(gamestate==GS_LEVEL) 245 for (i=0; i<MAXPLAYERS; i++) 246 if (playeringame[i]) 247 P_PlayerThink(&players[i]); 248 249 P_RunThinkers(); 250 P_UpdateSpecials(); 251 P_RespawnSpecials(); 252 P_MapEnd(); 253 leveltime++; // for par times 254} 255