A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
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 * Rendering main loop and setup functions,
29 * utility functions (BSP, geometry, trigonometry).
30 * See tables.c, too.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "w_wad.h"
36#include "r_main.h"
37#include "r_things.h"
38#include "r_plane.h"
39#include "r_bsp.h"
40#include "r_draw.h"
41#include "m_bbox.h"
42#include "r_sky.h"
43#include "v_video.h"
44#include "i_system.h"
45//#include "lprintf.h"
46#include "st_stuff.h"
47#include "rockmacros.h"
48
49// Fineangles in the SCREENWIDTH wide window.
50#define FIELDOFVIEW 2048
51
52// killough: viewangleoffset is a legacy from the pre-v1.2 days, when Doom
53// had Left/Mid/Right viewing. +/-ANG90 offsets were placed here on each
54// node, by d_net.c, to set up a L/M/R session.
55
56int viewangleoffset;
57
58int validcount = 1; // increment every time a check is made
59lighttable_t *fixedcolormap;
60int centerx IBSS_ATTR;
61int centery IBSS_ATTR;
62fixed_t centerxfrac, centeryfrac;
63fixed_t projection;
64// proff 11/06/98: Added for high-res
65fixed_t projectiony;
66fixed_t viewx, viewy, viewz;
67angle_t viewangle;
68fixed_t viewcos, viewsin;
69player_t *viewplayer;
70extern lighttable_t **walllights;
71
72//
73// precalculated math tables
74//
75
76angle_t clipangle;
77
78// The viewangletox[viewangle + FINEANGLES/4] lookup
79// maps the visible view angles to screen X coordinates,
80// flattening the arc to a flat projection plane.
81// There will be many angles mapped to the same X.
82
83int *viewangletox=0;
84
85// The xtoviewangleangle[] table maps a screen pixel
86// to the lowest viewangle that maps back to x ranges
87// from clipangle to -clipangle.
88
89angle_t xtoviewangle[MAX_SCREENWIDTH+1]; // killough 2/8/98
90
91// killough 3/20/98: Support dynamic colormaps, e.g. deep water
92// killough 4/4/98: support dynamic number of them as well
93
94int numcolormaps;
95lighttable_t *(*c_scalelight)[LIGHTLEVELS][MAXLIGHTSCALE];
96lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ];
97lighttable_t *(*scalelight)[MAXLIGHTSCALE];
98lighttable_t *(*zlight)[MAXLIGHTZ];
99lighttable_t *fullcolormap;
100lighttable_t **colormaps;
101
102// killough 3/20/98, 4/4/98: end dynamic colormaps
103
104int extralight; // bumped light from gun blasts
105
106void (*colfunc)(void);
107
108//
109// R_PointOnSide
110// Traverse BSP (sub) tree,
111// check point against partition plane.
112// Returns side 0 (front) or 1 (back).
113//
114// killough 5/2/98: reformatted
115//
116
117int R_PointOnSide(fixed_t x, fixed_t y, const node_t *node)
118{
119 if (!node->dx)
120 return x <= node->x ? node->dy > 0 : node->dy < 0;
121
122 if (!node->dy)
123 return y <= node->y ? node->dx < 0 : node->dx > 0;
124
125 x -= node->x;
126 y -= node->y;
127
128 // Try to quickly decide by looking at sign bits.
129 if ((node->dy ^ node->dx ^ x ^ y) < 0)
130 return (node->dy ^ x) < 0; // (left is negative)
131 return FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x);
132}
133
134// killough 5/2/98: reformatted
135
136int R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line)
137{
138 fixed_t lx = line->v1->x;
139 fixed_t ly = line->v1->y;
140 fixed_t ldx = line->v2->x - lx;
141 fixed_t ldy = line->v2->y - ly;
142
143 if (!ldx)
144 return x <= lx ? ldy > 0 : ldy < 0;
145
146 if (!ldy)
147 return y <= ly ? ldx < 0 : ldx > 0;
148
149 x -= lx;
150 y -= ly;
151
152 // Try to quickly decide by looking at sign bits.
153 if ((ldy ^ ldx ^ x ^ y) < 0)
154 return (ldy ^ x) < 0; // (left is negative)
155 return FixedMul(y, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, x);
156}
157
158//
159// R_PointToAngle
160// To get a global angle from cartesian coordinates,
161// the coordinates are flipped until they are in
162// the first octant of the coordinate system, then
163// the y (<=x) is scaled and divided by x to get a
164// tangent (slope) value which is looked up in the
165// tantoangle[] table. The +1 size of tantoangle[]
166// is to handle the case when x==y without additional
167// checking.
168//
169// killough 5/2/98: reformatted, cleaned up
170
171angle_t R_PointToAngle(fixed_t x, fixed_t y)
172{
173 return (y -= viewy, (x -= viewx) || y) ?
174 x >= 0 ?
175 y >= 0 ?
176 (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0
177 ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1
178 x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8
179 ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7
180 y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3
181 ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2
182 (x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4
183 ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5
184 0;
185}
186
187angle_t R_PointToAngle2(fixed_t viewx, fixed_t viewy, fixed_t x, fixed_t y)
188{
189 return (y -= viewy, (x -= viewx) || y) ?
190 x >= 0 ?
191 y >= 0 ?
192 (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0
193 ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1
194 x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8
195 ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7
196 y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3
197 ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2
198 (x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4
199 ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5
200 0;
201}
202
203//
204// R_InitTextureMapping
205//
206// killough 5/2/98: reformatted
207
208static void R_InitTextureMapping (void)
209{
210 register int i,x;
211 fixed_t focallength;
212
213 // Use tangent table to generate viewangletox:
214 // viewangletox will give the next greatest x
215 // after the view angle.
216 //
217 // Calc focallength
218 // so FIELDOFVIEW angles covers SCREENWIDTH.
219
220 if(viewangletox==NULL)
221 viewangletox=malloc(sizeof(int)*FINEANGLES/2);
222
223 focallength = FixedDiv(centerxfrac, finetangent[FINEANGLES/4+FIELDOFVIEW/2]);
224
225 for (i=0 ; i<FINEANGLES/2 ; i++)
226 {
227 int t;
228 if (finetangent[i] > FRACUNIT*2)
229 t = -1;
230 else
231 if (finetangent[i] < -FRACUNIT*2)
232 t = viewwidth+1;
233 else
234 {
235 t = FixedMul(finetangent[i], focallength);
236 t = (centerxfrac - t + FRACUNIT-1) >> FRACBITS;
237 if (t < -1)
238 t = -1;
239 else
240 if (t > viewwidth+1)
241 t = viewwidth+1;
242 }
243 viewangletox[i] = t;
244 }
245
246 // Scan viewangletox[] to generate xtoviewangle[]:
247 // xtoviewangle will give the smallest view angle
248 // that maps to x.
249
250 for (x=0; x<=viewwidth; x++)
251 {
252 for (i=0; viewangletox[i] > x; i++)
253 ;
254 xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
255 }
256
257 // Take out the fencepost cases from viewangletox.
258 for (i=0; i<FINEANGLES/2; i++)
259 if (viewangletox[i] == -1)
260 viewangletox[i] = 0;
261 else
262 if (viewangletox[i] == viewwidth+1)
263 viewangletox[i] = viewwidth;
264
265 clipangle = xtoviewangle[0];
266}
267
268//
269// R_InitLightTables
270// Only inits the zlight table,
271// because the scalelight table changes with view size.
272//
273
274#define DISTMAP 2
275
276void R_InitLightTables (void)
277{
278 int i;
279
280 // killough 4/4/98: dynamic colormaps
281 c_zlight = malloc(sizeof(*c_zlight) * numcolormaps);
282 c_scalelight = malloc(sizeof(*c_scalelight) * numcolormaps);
283
284 // Calculate the light levels to use
285 // for each level / distance combination.
286 for (i=0; i< LIGHTLEVELS; i++)
287 {
288 int j, startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
289 for (j=0; j<MAXLIGHTZ; j++)
290 {
291 // CPhipps - use 320 here instead of SCREENWIDTH, otherwise hires is
292 // brighter than normal res
293 int scale = FixedDiv ((320/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
294 int t, level = startmap - (scale >>= LIGHTSCALESHIFT)/DISTMAP;
295
296 if (level < 0)
297 level = 0;
298 else
299 if (level >= NUMCOLORMAPS)
300 level = NUMCOLORMAPS-1;
301
302 // killough 3/20/98: Initialize multiple colormaps
303 level *= 256;
304 for (t=0; t<numcolormaps; t++) // killough 4/4/98
305 c_zlight[t][i][j] = colormaps[t] + level;
306 }
307 }
308}
309
310//
311// R_SetViewSize
312// Do not really change anything here,
313// because it might be in the middle of a refresh.
314// The change will take effect next refresh.
315//
316
317boolean setsizeneeded;
318int setblocks;
319
320void R_SetViewSize(int blocks)
321{
322 setsizeneeded = true;
323 setblocks = blocks;
324}
325
326//
327// R_ExecuteSetViewSize
328//
329
330void R_ExecuteSetViewSize (void)
331{
332 int i;
333
334 setsizeneeded = false;
335
336 if (setblocks == 11)
337 {
338 scaledviewwidth = SCREENWIDTH;
339 viewheight = SCREENHEIGHT;
340 }
341 // proff 09/24/98: Added for high-res
342 else if (setblocks == 10)
343 {
344 scaledviewwidth = SCREENWIDTH;
345 viewheight = SCREENHEIGHT-ST_SCALED_HEIGHT;
346 }
347 else
348 {
349 // proff 08/17/98: Changed for high-res
350 scaledviewwidth = setblocks*SCREENWIDTH/10;
351 viewheight = (setblocks*(SCREENHEIGHT-ST_SCALED_HEIGHT)/10) & ~7;
352 }
353
354 viewwidth = scaledviewwidth;
355
356 centery = viewheight/2;
357 centerx = viewwidth/2;
358 centerxfrac = centerx<<FRACBITS;
359 centeryfrac = centery<<FRACBITS;
360 projection = centerxfrac;
361 // proff 11/06/98: Added for high-res
362 projectiony = ((SCREENHEIGHT * centerx * 320) / 200) / SCREENWIDTH * FRACUNIT;
363
364 R_InitBuffer (scaledviewwidth, viewheight);
365
366 R_InitTextureMapping();
367
368 // psprite scales
369 // proff 08/17/98: Changed for high-res
370 pspritescale = FRACUNIT*viewwidth/320;
371 pspriteiscale = FRACUNIT*320/viewwidth;
372 // proff 11/06/98: Added for high-res
373 pspriteyscale = (((SCREENHEIGHT*viewwidth)/SCREENWIDTH) << FRACBITS) / 200;
374
375 // thing clipping
376 for (i=0 ; i<viewwidth ; i++)
377 screenheightarray[i] = viewheight;
378
379 // planes
380 for (i=0 ; i<viewheight ; i++)
381 { // killough 5/2/98: reformatted
382 fixed_t dy = D_abs(((i-viewheight/2)<<FRACBITS)+FRACUNIT/2);
383 // proff 08/17/98: Changed for high-res
384 yslope[i] = FixedDiv(projectiony, dy);
385 }
386
387 for (i=0 ; i<viewwidth ; i++)
388 {
389 fixed_t cosadj = D_abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
390 distscale[i] = FixedDiv(FRACUNIT,cosadj);
391 }
392
393 // Calculate the light levels to use
394 // for each level / scale combination.
395 for (i=0; i<LIGHTLEVELS; i++)
396 {
397 int j, startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
398 for (j=0 ; j<MAXLIGHTSCALE ; j++)
399 {
400 int t, level = startmap - j*320/viewwidth/DISTMAP;
401
402 if (level < 0)
403 level = 0;
404
405 if (level >= NUMCOLORMAPS)
406 level = NUMCOLORMAPS-1;
407
408 // killough 3/20/98: initialize multiple colormaps
409 level *= 256;
410
411 for (t=0; t<numcolormaps; t++) // killough 4/4/98
412 c_scalelight[t][i][j] = colormaps[t] + level;
413 }
414 }
415}
416
417//
418// R_Init
419//
420
421extern int screenblocks;
422
423void R_Init (void)
424{
425 // CPhipps - R_DrawColumn isn't constant anymore, so must
426 // initialise in code
427 colfunc = R_DrawColumn; // current column draw function
428// if (SCREENWIDTH<320)
429// I_Error("R_Init: Screenwidth(%d) < 320",SCREENWIDTH);
430#if 1
431
432 printf("\nR_LoadTrigTables: ");
433 R_LoadTrigTables();
434#endif
435
436 printf("\nR_InitData: ");
437 R_InitData();
438 R_SetViewSize(screenblocks);
439 printf("\nR_Init: R_InitPlanes ");
440 R_InitPlanes();
441 printf("R_InitLightTables ");
442 R_InitLightTables();
443 printf("R_InitSkyMap ");
444 R_InitSkyMap();
445 printf("R_InitTranslationsTables ");
446 R_InitTranslationTables();
447}
448
449//
450// R_PointInSubsector
451//
452// killough 5/2/98: reformatted, cleaned up
453
454subsector_t *R_PointInSubsector(fixed_t x, fixed_t y)
455{
456 int nodenum = numnodes-1;
457 while (!(nodenum & NF_SUBSECTOR))
458 nodenum = nodes[nodenum].children[R_PointOnSide(x, y, nodes+nodenum)];
459 return &subsectors[nodenum & ~NF_SUBSECTOR];
460}
461
462//
463// R_SetupFrame
464//
465
466void R_SetupFrame (player_t *player)
467{
468 int i, cm;
469
470 viewplayer = player;
471 viewx = player->mo->x;
472 viewy = player->mo->y;
473 viewangle = player->mo->angle + viewangleoffset;
474 extralight = player->extralight;
475
476 viewz = player->viewz;
477
478 viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
479 viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
480
481 // killough 3/20/98, 4/4/98: select colormap based on player status
482
483 if (player->mo->subsector->sector->heightsec != -1)
484 {
485 const sector_t *s = player->mo->subsector->sector->heightsec + sectors;
486 cm = viewz < s->floorheight ? s->bottommap : viewz > s->ceilingheight ?
487 s->topmap : s->midmap;
488 if (cm < 0 || cm > numcolormaps)
489 cm = 0;
490 }
491 else
492 cm = 0;
493
494 fullcolormap = colormaps[cm];
495 zlight = c_zlight[cm];
496 scalelight = c_scalelight[cm];
497
498 if (player->fixedcolormap)
499 {
500 // killough 3/20/98: localize scalelightfixed (readability/optimization)
501 static lighttable_t *scalelightfixed[MAXLIGHTSCALE];
502
503 fixedcolormap = fullcolormap // killough 3/20/98: use fullcolormap
504 + player->fixedcolormap*256*sizeof(lighttable_t);
505
506 walllights = scalelightfixed;
507
508 for (i=0 ; i<MAXLIGHTSCALE ; i++)
509 scalelightfixed[i] = fixedcolormap;
510 }
511 else
512 fixedcolormap = 0;
513
514 validcount++;
515}
516
517//
518// R_RenderView
519//
520void R_RenderPlayerView (player_t* player)
521{
522 R_SetupFrame (player);
523
524 // Clear buffers.
525 R_ClearClipSegs ();
526 R_ClearDrawSegs ();
527 R_ClearPlanes ();
528 R_ClearSprites ();
529
530 // check for new console commands.
531 // NetUpdate ();
532
533 // The head node is the last node output.
534 R_RenderBSPNode (numnodes-1);
535
536 // Check for new console commands.
537 // NetUpdate ();
538
539 R_DrawPlanes ();
540
541 // Check for new console commands.
542 // NetUpdate ();
543
544 R_DrawMasked ();
545
546 // Check for new console commands.
547 // NetUpdate ();
548}