A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 442 lines 13 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 * Here is a core component: drawing the floors and ceilings, 29 * while maintaining a per column clipping list only. 30 * Moreover, the sky areas have to be determined. 31 * 32 * MAXVISPLANES is no longer a limit on the number of visplanes, 33 * but a limit on the number of hash slots; larger numbers mean 34 * better performance usually but after a point they are wasted, 35 * and memory and time overheads creep in. 36 * 37 * For more information on visplanes, see: 38 * 39 * http://classicgaming.com/doom/editing/ 40 * 41 * Lee Killough 42 * 43 *-----------------------------------------------------------------------------*/ 44 45#include "z_zone.h" /* memory allocation wrappers -- killough */ 46 47#include "doomstat.h" 48#include "w_wad.h" 49#include "r_main.h" 50#include "r_draw.h" 51#include "r_things.h" 52#include "r_sky.h" 53#include "r_plane.h" 54#include "rockmacros.h" 55 56#define MAXVISPLANES 128 /* must be a power of 2 */ 57 58static visplane_t *visplanes[MAXVISPLANES] IBSS_ATTR; // killough 59static visplane_t *freetail; // killough 60static visplane_t **freehead = &freetail; // killough 61visplane_t *floorplane, *ceilingplane; 62 63// killough -- hash function for visplanes 64// Empirically verified to be fairly uniform: 65 66#define visplane_hash(picnum,lightlevel,height) \ 67 ((unsigned)((picnum)*3+(lightlevel)+(height)*7) & (MAXVISPLANES-1)) 68 69size_t maxopenings; 70short *openings,*lastopening; 71 72// Clip values are the solid pixel bounding the range. 73// floorclip starts out SCREENHEIGHT 74// ceilingclip starts out -1 75 76short floorclip[MAX_SCREENWIDTH], ceilingclip[MAX_SCREENWIDTH]; 77 78// spanstart holds the start of a plane span; initialized to 0 at start 79 80static int spanstart[MAX_SCREENHEIGHT]; // killough 2/8/98 81 82// 83// texture mapping 84// 85 86static lighttable_t **planezlight; 87static fixed_t planeheight; 88 89// killough 2/8/98: make variables static 90 91static fixed_t basexscale, baseyscale; 92static fixed_t cachedheight[MAX_SCREENHEIGHT]; 93static fixed_t cacheddistance[MAX_SCREENHEIGHT]; 94static fixed_t cachedxstep[MAX_SCREENHEIGHT]; 95static fixed_t cachedystep[MAX_SCREENHEIGHT]; 96static fixed_t xoffs, yoffs; // killough 2/28/98: flat offsets 97 98fixed_t yslope[MAX_SCREENHEIGHT], distscale[MAX_SCREENWIDTH]; 99 100// 101// R_InitPlanes 102// Only at game startup. 103// 104void R_InitPlanes (void) 105{ 106} 107 108// 109// R_MapPlane 110// 111// Uses global vars: 112// planeheight 113// ds_source 114// basexscale 115// baseyscale 116// viewx 117// viewy 118// xoffs 119// yoffs 120// 121// BASIC PRIMITIVE 122// 123 124static void R_MapPlane(int y, int x1, int x2) 125{ 126 angle_t angle; 127 fixed_t distance, length; 128 unsigned index; 129 130#ifdef RANGECHECK 131 132 if (x2 < x1 || x1<0 || x2>=viewwidth || (unsigned)y>(unsigned)viewheight) 133 I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y); 134#endif 135 136 if (planeheight != cachedheight[y]) 137 { 138 cachedheight[y] = planeheight; 139 distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]); 140 ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale); 141 ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale); 142 } 143 else 144 { 145 distance = cacheddistance[y]; 146 ds_xstep = cachedxstep[y]; 147 ds_ystep = cachedystep[y]; 148 } 149 150 length = FixedMul (distance,distscale[x1]); 151 angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; 152 153 // killough 2/28/98: Add offsets 154 ds_xfrac = viewx + FixedMul(finecosine[angle], length) + xoffs; 155 ds_yfrac = -viewy - FixedMul(finesine[angle], length) + yoffs; 156 157 if (!(ds_colormap = fixedcolormap)) 158 { 159 index = distance >> LIGHTZSHIFT; 160 if (index >= MAXLIGHTZ ) 161 index = MAXLIGHTZ-1; 162 ds_colormap = planezlight[index]; 163 } 164 165 ds_y = y; 166 ds_x1 = x1; 167 ds_x2 = x2; 168 169 R_DrawSpan(); 170} 171 172// 173// R_ClearPlanes 174// At begining of frame. 175// 176 177void R_ClearPlanes(void) 178{ 179 int i; 180 angle_t angle; 181 182 // opening / clipping determination 183 for (i=0 ; i<viewwidth ; i++) 184 floorclip[i] = viewheight, ceilingclip[i] = -1; 185 186 for (i=0;i<MAXVISPLANES;i++) // new code -- killough 187 for (*freehead = visplanes[i], visplanes[i] = NULL; *freehead; ) 188 freehead = &(*freehead)->next; 189 190 lastopening = openings; 191 192 // texture calculation 193 memset (cachedheight, 0, sizeof(cachedheight)); 194 195 // left to right mapping 196 angle = (viewangle-ANG90)>>ANGLETOFINESHIFT; 197 198 // scale will be unit scale at SCREENWIDTH/2 distance 199 basexscale = FixedDiv (finecosine[angle],centerxfrac); 200 baseyscale = -FixedDiv (finesine[angle],centerxfrac); 201} 202 203// New function, by Lee Killough 204 205static visplane_t *new_visplane(unsigned hash) 206{ 207 visplane_t *check = freetail; 208 if (!check) 209 check = calloc(1, sizeof *check); 210 else 211 if (!(freetail = freetail->next)) 212 freehead = &freetail; 213 check->next = visplanes[hash]; 214 visplanes[hash] = check; 215 return check; 216} 217 218/* 219 * R_DupPlane 220 * 221 * cph 2003/04/18 - create duplicate of existing visplane and set initial range 222 */ 223visplane_t *R_DupPlane(const visplane_t *pl, int start, int stop) 224{ 225 unsigned hash = visplane_hash(pl->picnum, pl->lightlevel, pl->height); 226 visplane_t *new_pl = new_visplane(hash); 227 228 new_pl->height = pl->height; 229 new_pl->picnum = pl->picnum; 230 new_pl->lightlevel = pl->lightlevel; 231 new_pl->xoffs = pl->xoffs; // killough 2/28/98 232 new_pl->yoffs = pl->yoffs; 233 new_pl->minx = start; 234 new_pl->maxx = stop; 235 memset(new_pl->top, 0xff, sizeof new_pl->top); 236 return new_pl; 237} 238 239// 240// R_FindPlane 241// 242// killough 2/28/98: Add offsets 243 244visplane_t *R_FindPlane(fixed_t height, int picnum, int lightlevel, 245 fixed_t xoffs, fixed_t yoffs) 246{ 247 visplane_t *check; 248 unsigned hash; // killough 249 250 if (picnum == skyflatnum || picnum & PL_SKYFLAT) 251 height = lightlevel = 0; // killough 7/19/98: most skies map together 252 253 // New visplane algorithm uses hash table -- killough 254 hash = visplane_hash(picnum,lightlevel,height); 255 256 for (check=visplanes[hash]; check; check=check->next) // killough 257 if (height == check->height && 258 picnum == check->picnum && 259 lightlevel == check->lightlevel && 260 xoffs == check->xoffs && // killough 2/28/98: Add offset checks 261 yoffs == check->yoffs) 262 return check; 263 264 check = new_visplane(hash); // killough 265 266 check->height = height; 267 check->picnum = picnum; 268 check->lightlevel = lightlevel; 269 check->minx = viewwidth; // Was SCREENWIDTH -- killough 11/98 270 check->maxx = -1; 271 check->xoffs = xoffs; // killough 2/28/98: Save offsets 272 check->yoffs = yoffs; 273 274 memset (check->top, 0xff, sizeof check->top); 275 276 return check; 277} 278 279// 280// R_CheckPlane 281// 282visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop) 283{ 284 int intrl, intrh, unionl, unionh, x; 285 286 if (start < pl->minx) 287 intrl = pl->minx, unionl = start; 288 else 289 unionl = pl->minx, intrl = start; 290 291 if (stop > pl->maxx) 292 intrh = pl->maxx, unionh = stop; 293 else 294 unionh = pl->maxx, intrh = stop; 295 296 for (x=intrl ; x <= intrh && pl->top[x] == 0xffff; x++) 297 ; 298 299 if (x > intrh) 300 { /* Can use existing plane; extend range */ 301 pl->minx = unionl; 302 pl->maxx = unionh; 303 return pl; 304 } 305 else /* Cannot use existing plane; create a new one */ 306 return R_DupPlane(pl,start,stop); 307} 308 309// 310// R_MakeSpans 311// 312 313static void R_MakeSpans(int x, int t1, int b1, int t2, int b2) 314{ 315 for (; t1 < t2 && t1 <= b1; t1++) 316 R_MapPlane(t1, spanstart[t1], x-1); 317 for (; b1 > b2 && b1 >= t1; b1--) 318 R_MapPlane(b1, spanstart[b1] ,x-1); 319 while (t2 < t1 && t2 <= b2) 320 spanstart[t2++] = x; 321 while (b2 > b1 && b2 >= t2) 322 spanstart[b2--] = x; 323} 324 325// New function, by Lee Killough 326 327static void R_DoDrawPlane(visplane_t *pl) 328{ 329 register int x; 330 if (pl->minx <= pl->maxx) 331 { 332 if (pl->picnum == skyflatnum || pl->picnum & PL_SKYFLAT) 333 { // sky flat 334 int texture; 335 angle_t an, flip; 336 337 // killough 10/98: allow skies to come from sidedefs. 338 // Allows scrolling and/or animated skies, as well as 339 // arbitrary multiple skies per level without having 340 // to use info lumps. 341 342 an = viewangle; 343 344 if (pl->picnum & PL_SKYFLAT) 345 { 346 // Sky Linedef 347 const line_t *l = &lines[pl->picnum & ~PL_SKYFLAT]; 348 349 // Sky transferred from first sidedef 350 const side_t *s = *l->sidenum + sides; 351 352 // Texture comes from upper texture of reference sidedef 353 texture = texturetranslation[s->toptexture]; 354 355 // Horizontal offset is turned into an angle offset, 356 // to allow sky rotation as well as careful positioning. 357 // However, the offset is scaled very small, so that it 358 // allows a long-period of sky rotation. 359 360 an += s->textureoffset; 361 362 // Vertical offset allows careful sky positioning. 363 364 dc_texturemid = s->rowoffset - 28*FRACUNIT; 365 366 // We sometimes flip the picture horizontally. 367 // 368 // Doom always flipped the picture, so we make it optional, 369 // to make it easier to use the new feature, while to still 370 // allow old sky textures to be used. 371 372 flip = l->special==272 ? 0u : ~0u; 373 } 374 else 375 { // Normal Doom sky, only one allowed per level 376 dc_texturemid = skytexturemid; // Default y-offset 377 texture = skytexture; // Default texture 378 flip = 0; // Doom flips it 379 } 380 381 /* Sky is always drawn full bright, i.e. colormaps[0] is used. 382 * Because of this hack, sky is not affected by INVUL inverse mapping. 383 * Until Boom fixed this. Compat option added in MBF. */ 384 385 if (comp[comp_skymap] || !(dc_colormap = fixedcolormap)) 386 dc_colormap = fullcolormap; // killough 3/20/98 387 dc_texheight = textureheight[skytexture]>>FRACBITS; // killough 388 // proff 09/21/98: Changed for high-res 389 dc_iscale = FRACUNIT*200/viewheight; 390 391 // killough 10/98: Use sky scrolling offset, and possibly flip picture 392 for (x = pl->minx; (dc_x = x) <= pl->maxx; x++) 393 if ((dc_yl = pl->top[x]) <= (dc_yh = pl->bottom[x])) 394 { 395 dc_source = R_GetColumn(texture, ((an + xtoviewangle[x])^flip) >> 396 ANGLETOSKYSHIFT); 397 colfunc(); 398 } 399 } 400 else 401 { // regular flat 402 403 int stop, light; 404 405 ds_source = W_CacheLumpNum(firstflat + flattranslation[pl->picnum]); 406 407 xoffs = pl->xoffs; // killough 2/28/98: Add offsets 408 yoffs = pl->yoffs; 409 planeheight = D_abs(pl->height-viewz); 410 light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight; 411 412 if (light >= LIGHTLEVELS) 413 light = LIGHTLEVELS-1; 414 415 if (light < 0) 416 light = 0; 417 418 stop = pl->maxx + 1; 419 planezlight = zlight[light]; 420 pl->top[pl->minx-1] = pl->top[stop] = 0xffff; 421 422 for (x = pl->minx ; x <= stop ; x++) 423 R_MakeSpans(x,pl->top[x-1],pl->bottom[x-1],pl->top[x],pl->bottom[x]); 424 425 W_UnlockLumpNum(firstflat + flattranslation[pl->picnum]); 426 } 427 } 428} 429 430// 431// RDrawPlanes 432// At the end of each frame. 433// 434 435void R_DrawPlanes (void) 436{ 437 visplane_t *pl; 438 int i; 439 for (i=0;i<MAXVISPLANES;i++) 440 for (pl=visplanes[i]; pl; pl=pl->next) 441 R_DoDrawPlane(pl); 442}