summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/r_draw.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/doom/r_draw.c')
-rw-r--r--apps/plugins/doom/r_draw.c677
1 files changed, 677 insertions, 0 deletions
diff --git a/apps/plugins/doom/r_draw.c b/apps/plugins/doom/r_draw.c
new file mode 100644
index 0000000000..df682776cd
--- /dev/null
+++ b/apps/plugins/doom/r_draw.c
@@ -0,0 +1,677 @@
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 * The actual span/column drawing functions.
29 * Here find the main potential for optimization,
30 * e.g. inline assembly, different algorithms.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "w_wad.h"
36#include "r_main.h"
37#include "v_video.h"
38#include "st_stuff.h"
39#include "g_game.h"
40#include "am_map.h"
41//#include "lprintf.h"
42#include "rockmacros.h"
43
44#define MAXWIDTH 1120
45#define MAXHEIGHT 832
46
47// status bar height at bottom of screen
48#define SBARHEIGHT 32
49
50//
51// All drawing to the view buffer is accomplished in this file.
52// The other refresh files only know about ccordinates,
53// not the architecture of the frame buffer.
54// Conveniently, the frame buffer is a linear one,
55// and we need only the base address,
56// and the total size == width*height*depth/8.,
57//
58
59//byte* viewimage;
60int viewwidth;
61int scaledviewwidth;
62int viewheight;
63int viewwindowx;
64int viewwindowy;
65
66byte *topleft IBSS_ATTR;
67
68// Color tables for different players,
69// translate a limited part to another
70// (color ramps used for suit colors).
71//
72
73// CPhipps - made const*'s
74const byte *tranmap IBSS_ATTR; // translucency filter maps 256x256 // phares
75const byte *main_tranmap IBSS_ATTR; // killough 4/11/98
76
77//
78// R_DrawColumn
79// Source is the top of the column to scale.
80//
81
82lighttable_t *dc_colormap IBSS_ATTR;
83int dc_x IBSS_ATTR;
84int dc_yl IBSS_ATTR;
85int dc_yh IBSS_ATTR;
86fixed_t dc_iscale IBSS_ATTR;
87fixed_t dc_texturemid IBSS_ATTR;
88int dc_texheight IBSS_ATTR; // killough
89const byte *dc_source IBSS_ATTR; // first pixel in a column (possibly virtual)
90
91
92//
93// A column is a vertical slice/span from a wall texture that,
94// given the DOOM style restrictions on the view orientation,
95// will always have constant z depth.
96// Thus a special case loop for very fast rendering can
97// be used. It has also been used with Wolfenstein 3D.
98//
99void R_DrawColumn (void)
100{
101 int count;
102 register byte *dest; // killough
103 register fixed_t frac; // killough
104
105 // leban 1/17/99:
106 // removed the + 1 here, adjusted the if test, and added an increment
107 // later. this helps a compiler pipeline a bit better. the x86
108 // assembler also does this.
109 count = dc_yh - dc_yl;
110
111 // Zero length, column does not exceed a pixel.
112 if (count < 0)
113 return;
114
115#ifdef RANGECHECK
116 if ((unsigned)dc_x >= SCREENWIDTH
117 || dc_yl < 0
118 || dc_yh >= SCREENHEIGHT)
119 I_Error ("R_DrawColumn: %d to %d at %d", dc_yl, dc_yh, dc_x);
120#endif
121
122 count++;
123
124 // Framebuffer destination address.
125 dest = topleft + dc_yl*SCREENWIDTH + dc_x;
126
127 // Determine scaling,
128 // which is the only mapping to be done.
129#define fracstep dc_iscale
130 frac = dc_texturemid + (dc_yl-centery)*fracstep;
131
132 // Inner loop that does the actual texture mapping,
133 // e.g. a DDA-lile scaling.
134 // This is as fast as it gets. (Yeah, right!!! -- killough)
135 //
136 // killough 2/1/98: more performance tuning
137
138 if (dc_texheight == 128) {
139 while(count--)
140 {
141 *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
142 frac += fracstep;
143 dest += SCREENWIDTH;
144 }
145 } else if (dc_texheight == 0) {
146 /* cph - another special case */
147 while (count--) {
148 *dest = dc_colormap[dc_source[frac>>FRACBITS]];
149 frac += fracstep;
150 dest += SCREENWIDTH;
151 }
152 } else {
153 register unsigned heightmask = dc_texheight-1; // CPhipps - specify type
154 if (! (dc_texheight & heightmask) ) // power of 2 -- killough
155 {
156 while (count>0) // texture height is a power of 2 -- killough
157 {
158 *dest = dc_colormap[dc_source[(frac>>FRACBITS) & heightmask]];
159 dest += SCREENWIDTH;
160 frac += fracstep;
161 count--;
162 }
163 }
164 else
165 {
166 heightmask++;
167 heightmask <<= FRACBITS;
168
169 if (frac < 0)
170 while ((frac += heightmask) < 0);
171 else
172 while (frac >= (int)heightmask)
173 frac -= heightmask;
174
175 while(count>0)
176 {
177 // Re-map color indices from wall texture column
178 // using a lighting/special effects LUT.
179
180 // heightmask is the Tutti-Frutti fix -- killough
181
182 *dest = dc_colormap[dc_source[frac>>FRACBITS]];
183 dest += SCREENWIDTH;
184 if ((frac += fracstep) >= (int)heightmask)
185 frac -= heightmask;
186 count--;
187 }
188 }
189 }
190}
191#undef fracstep
192
193// Here is the version of R_DrawColumn that deals with translucent // phares
194// textures and sprites. It's identical to R_DrawColumn except // |
195// for the spot where the color index is stuffed into *dest. At // V
196// that point, the existing color index and the new color index
197// are mapped through the TRANMAP lump filters to get a new color
198// index whose RGB values are the average of the existing and new
199// colors.
200//
201// Since we're concerned about performance, the 'translucent or
202// opaque' decision is made outside this routine, not down where the
203// actual code differences are.
204
205void R_DrawTLColumn (void)
206{
207 int count;
208 register byte *dest; // killough
209 register fixed_t frac; // killough
210
211 count = dc_yh - dc_yl + 1;
212
213 // Zero length, column does not exceed a pixel.
214 if (count <= 0)
215 return;
216
217#ifdef RANGECHECK
218 if ((unsigned)dc_x >= (unsigned)SCREENWIDTH
219 || dc_yl < 0
220 || dc_yh >= SCREENHEIGHT)
221 I_Error("R_DrawTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
222#endif
223
224 // Framebuffer destination address.
225 dest = topleft + dc_yl*SCREENWIDTH + dc_x;
226
227 // Determine scaling,
228 // which is the only mapping to be done.
229#define fracstep dc_iscale
230 frac = dc_texturemid + (dc_yl-centery)*fracstep;
231
232 // Inner loop that does the actual texture mapping,
233 // e.g. a DDA-lile scaling.
234 // This is as fast as it gets. (Yeah, right!!! -- killough)
235 //
236 // killough 2/1/98, 2/21/98: more performance tuning
237
238 {
239 register const byte *source = dc_source;
240 register const lighttable_t *colormap = dc_colormap;
241 register unsigned heightmask = dc_texheight-1; // CPhipps - specify type
242 if (dc_texheight & heightmask) // not a power of 2 -- killough
243 {
244 heightmask++;
245 heightmask <<= FRACBITS;
246
247 if (frac < 0)
248 while ((frac += heightmask) < 0);
249 else
250 while (frac >= (int)heightmask)
251 frac -= heightmask;
252
253 do
254 {
255 // Re-map color indices from wall texture column
256 // using a lighting/special effects LUT.
257
258 // heightmask is the Tutti-Frutti fix -- killough
259
260 *dest = tranmap[(*dest<<8)+colormap[source[frac>>FRACBITS]]]; // phares
261 dest += SCREENWIDTH;
262 if ((frac += fracstep) >= (int)heightmask)
263 frac -= heightmask;
264 }
265 while (--count);
266 }
267 else
268 {
269 while ((count-=2)>=0) // texture height is a power of 2 -- killough
270 {
271 *dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares
272 dest += SCREENWIDTH;
273 frac += fracstep;
274 *dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares
275 dest += SCREENWIDTH;
276 frac += fracstep;
277 }
278 if (count & 1)
279 *dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares
280 }
281 }
282}
283#undef fracstep
284
285//
286// Spectre/Invisibility.
287//
288
289#define FUZZTABLE 50
290// proff 08/17/98: Changed for high-res
291//#define FUZZOFF (SCREENWIDTH)
292#define FUZZOFF 1
293
294static const int fuzzoffset_org[FUZZTABLE] ICONST_ATTR = {
295 FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
296 FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
297 FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
298 FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
299 FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
300 FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
301 FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF
302 } ;
303
304static int fuzzoffset[FUZZTABLE] IBSS_ATTR;
305
306static int fuzzpos IBSS_ATTR = 0;
307
308//
309// Framebuffer postprocessing.
310// Creates a fuzzy image by copying pixels
311// from adjacent ones to left and right.
312// Used with an all black colormap, this
313// could create the SHADOW effect,
314// i.e. spectres and invisible players.
315//
316
317void R_DrawFuzzColumn(void)
318{
319 int count;
320 byte *dest;
321 fixed_t frac;
322 fixed_t fracstep;
323
324 // Adjust borders. Low...
325 if (!dc_yl)
326 dc_yl = 1;
327
328 // .. and high.
329 if (dc_yh == viewheight-1)
330 dc_yh = viewheight - 2;
331
332 count = dc_yh - dc_yl;
333
334 // Zero length.
335 if (count < 0)
336 return;
337
338#ifdef RANGECHECK
339 if ((unsigned) dc_x >= (unsigned)SCREENWIDTH
340 || dc_yl < 0
341 || (unsigned)dc_yh >= (unsigned)SCREENHEIGHT)
342 I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
343#endif
344
345 // Keep till detailshift bug in blocky mode fixed,
346 // or blocky mode removed.
347
348 // Does not work with blocky mode.
349 dest = topleft + dc_yl*SCREENWIDTH + dc_x;
350
351 // Looks familiar.
352 fracstep = dc_iscale;
353 frac = dc_texturemid + (dc_yl-centery)*fracstep;
354
355 // Looks like an attempt at dithering,
356 // using the colormap #6 (of 0-31, a bit brighter than average).
357
358 do
359 {
360 // Lookup framebuffer, and retrieve
361 // a pixel that is either one column
362 // left or right of the current one.
363 // Add index from colormap to index.
364 // killough 3/20/98: use fullcolormap instead of colormaps
365
366 *dest = fullcolormap[6*256+dest[fuzzoffset[fuzzpos]]];
367
368 // Some varying invisibility effects can be gotten by playing // phares
369 // with this logic. For example, try // phares
370 // // phares
371 // *dest = fullcolormap[0*256+dest[FUZZOFF]]; // phares
372
373 // Clamp table lookup index.
374 if (++fuzzpos == FUZZTABLE)
375 fuzzpos = 0;
376
377 dest += SCREENWIDTH;
378
379 frac += fracstep;
380 } while (count--);
381}
382
383//
384// R_DrawTranslatedColumn
385// Used to draw player sprites
386// with the green colorramp mapped to others.
387// Could be used with different translation
388// tables, e.g. the lighter colored version
389// of the BaronOfHell, the HellKnight, uses
390// identical sprites, kinda brightened up.
391//
392
393byte *dc_translation, *translationtables;
394
395void R_DrawTranslatedColumn (void)
396{
397 int count;
398 byte *dest;
399 fixed_t frac;
400 fixed_t fracstep;
401
402 count = dc_yh - dc_yl;
403 if (count < 0)
404 return;
405
406#ifdef RANGECHECK
407 if ((unsigned)dc_x >= (unsigned)SCREENWIDTH
408 || dc_yl < 0
409 || (unsigned)dc_yh >= (unsigned)SCREENHEIGHT)
410 I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
411#endif
412
413 // FIXME. As above.
414 dest = topleft + dc_yl*SCREENWIDTH + dc_x;
415
416 // Looks familiar.
417 fracstep = dc_iscale;
418 frac = dc_texturemid + (dc_yl-centery)*fracstep;
419
420 // Here we do an additional index re-mapping.
421 do
422 {
423 // Translation tables are used
424 // to map certain colorramps to other ones,
425 // used with PLAY sprites.
426 // Thus the "green" ramp of the player 0 sprite
427 // is mapped to gray, red, black/indigo.
428
429 *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
430 dest += SCREENWIDTH;
431
432 frac += fracstep;
433 }
434 while (count--);
435}
436
437//
438// R_InitTranslationTables
439// Creates the translation tables to map
440// the green color ramp to gray, brown, red.
441// Assumes a given structure of the PLAYPAL.
442// Could be read from a lump instead.
443//
444
445byte playernumtotrans[MAXPLAYERS];
446extern lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ];
447
448void R_InitTranslationTables (void)
449{
450 int i, j;
451#define MAXTRANS 3
452 byte transtocolour[MAXTRANS];
453
454 // killough 5/2/98:
455 // Remove dependency of colormaps aligned on 256-byte boundary
456
457 if (translationtables == NULL) // CPhipps - allow multiple calls
458 translationtables = Z_Malloc(256*MAXTRANS, PU_STATIC, 0);
459
460 for (i=0; i<MAXTRANS; i++) transtocolour[i] = 255;
461
462 for (i=0; i<MAXPLAYERS; i++) {
463 byte wantcolour = mapcolor_plyr[i];
464 playernumtotrans[i] = 0;
465 if (wantcolour != 0x70) // Not green, would like translation
466 for (j=0; j<MAXTRANS; j++)
467 if (transtocolour[j] == 255) {
468 transtocolour[j] = wantcolour; playernumtotrans[i] = j+1; break;
469 }
470 }
471
472 // translate just the 16 green colors
473 for (i=0; i<256; i++)
474 if (i >= 0x70 && i<= 0x7f)
475 {
476 // CPhipps - configurable player colours
477 translationtables[i] = colormaps[0][((i&0xf)<<9) + transtocolour[0]];
478 translationtables[i+256] = colormaps[0][((i&0xf)<<9) + transtocolour[1]];
479 translationtables[i+512] = colormaps[0][((i&0xf)<<9) + transtocolour[2]];
480 }
481 else // Keep all other colors as is.
482 translationtables[i]=translationtables[i+256]=translationtables[i+512]=i;
483}
484
485//
486// R_DrawSpan
487// With DOOM style restrictions on view orientation,
488// the floors and ceilings consist of horizontal slices
489// or spans with constant z depth.
490// However, rotation around the world z axis is possible,
491// thus this mapping, while simpler and faster than
492// perspective correct texture mapping, has to traverse
493// the texture at an angle in all but a few cases.
494// In consequence, flats are not stored by column (like walls),
495// and the inner loop has to step in texture space u and v.
496//
497
498int ds_y IBSS_ATTR;
499int ds_x1 IBSS_ATTR;
500int ds_x2 IBSS_ATTR;
501
502lighttable_t *ds_colormap IBSS_ATTR;
503
504fixed_t ds_xfrac IBSS_ATTR;
505fixed_t ds_yfrac IBSS_ATTR;
506fixed_t ds_xstep IBSS_ATTR;
507fixed_t ds_ystep IBSS_ATTR;
508
509// start of a 64*64 tile image
510byte *ds_source IBSS_ATTR;
511
512void R_DrawSpan (void)
513{
514 register unsigned count,xfrac = ds_xfrac,yfrac = ds_yfrac;
515
516 byte *source;
517 byte *colormap;
518 byte *dest;
519
520 source = ds_source;
521 colormap = ds_colormap;
522 dest = topleft + ds_y*SCREENWIDTH + ds_x1;
523 count = ds_x2 - ds_x1 + 1;
524
525 while (count)
526 {
527 register unsigned xtemp = xfrac >> 16;
528 register unsigned ytemp = yfrac >> 10;
529 register unsigned spot;
530 ytemp &= 4032;
531 xtemp &= 63;
532 spot = xtemp | ytemp;
533 xfrac += ds_xstep;
534 yfrac += ds_ystep;
535 *dest++ = colormap[source[spot]];
536 count--;
537 }
538}
539
540//
541// R_InitBuffer
542// Creats lookup tables that avoid
543// multiplies and other hazzles
544// for getting the framebuffer address
545// of a pixel to draw.
546//
547
548void R_InitBuffer(int width, int height)
549{
550 int i=0;
551 // Handle resize,
552 // e.g. smaller view windows
553 // with border and/or status bar.
554
555 viewwindowx = (SCREENWIDTH-width) >> 1;
556
557 // Same with base row offset.
558
559 viewwindowy = width==SCREENWIDTH ? 0 : (SCREENHEIGHT-(ST_SCALED_HEIGHT-1)-height)>>1;
560
561 topleft = screens[0] + viewwindowy*SCREENWIDTH + viewwindowx;
562
563 // Preclaculate all row offsets.
564 // CPhipps - merge viewwindowx into here
565 for (i=0; i<FUZZTABLE; i++)
566 fuzzoffset[i] = fuzzoffset_org[i]*SCREENWIDTH;
567}
568
569
570//
571// R_FillBackScreen
572// Fills the back screen with a pattern
573// for variable screen sizes
574// Also draws a beveled edge.
575//
576// CPhipps - patch drawing updated
577
578void R_FillBackScreen (void)
579{
580 int x,y;
581
582 if (scaledviewwidth == SCREENWIDTH)
583 return;
584
585 V_DrawBackground(gamemode == commercial ? "GRNROCK" : "FLOOR7_2", 1);
586
587 for (x=0 ; x<scaledviewwidth ; x+=8)
588 V_DrawNamePatch(viewwindowx+x,viewwindowy-8,1,"brdr_t", CR_DEFAULT, VPT_NONE);
589
590 for (x=0 ; x<scaledviewwidth ; x+=8)
591 V_DrawNamePatch(viewwindowx+x,viewwindowy+viewheight,1,"brdr_b", CR_DEFAULT, VPT_NONE);
592
593 for (y=0 ; y<viewheight ; y+=8)
594 V_DrawNamePatch(viewwindowx-8,viewwindowy+y,1,"brdr_l", CR_DEFAULT, VPT_NONE);
595
596 for (y=0 ; y<viewheight ; y+=8)
597 V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy+y,1,"brdr_r", CR_DEFAULT, VPT_NONE);
598
599 // Draw beveled edge.
600 V_DrawNamePatch(viewwindowx-8,viewwindowy-8,1,"brdr_tl", CR_DEFAULT, VPT_NONE);
601
602 V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy-8,1,"brdr_tr", CR_DEFAULT, VPT_NONE);
603
604 V_DrawNamePatch(viewwindowx-8,viewwindowy+viewheight,1,"brdr_bl", CR_DEFAULT, VPT_NONE);
605
606 V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy+viewheight,1,"brdr_br", CR_DEFAULT, VPT_NONE);
607}
608
609//
610// Copy a screen buffer.
611//
612
613void R_VideoErase(unsigned ofs, int count)
614{
615 memcpy(screens[0]+ofs, screens[1]+ofs, count); // LFB copy.
616}
617
618
619//
620// R_DrawViewBorder
621// Draws the border around the view
622// for different size windows?
623//
624
625void R_DrawViewBorder(void)
626{
627 int top, side, ofs, i;
628 // proff/nicolas 09/20/98: Added for high-res (inspired by DosDOOM)
629 int side2;
630
631 // proff/nicolas 09/20/98: Removed for high-res
632 // if (scaledviewwidth == SCREENWIDTH)
633 // return;
634
635 // proff/nicolas 09/20/98: Added for high-res (inspired by DosDOOM)
636 if ((SCREENHEIGHT != viewheight) ||
637 ((automapmode & am_active) && ! (automapmode & am_overlay)))
638 {
639 ofs = ( SCREENHEIGHT - ST_SCALED_HEIGHT ) * SCREENWIDTH;
640 side= ( SCREENWIDTH - ST_SCALED_WIDTH ) / 2;
641 side2 = side * 2;
642
643 R_VideoErase ( ofs, side );
644
645 ofs += ( SCREENWIDTH - side );
646 for ( i = 1; i < ST_SCALED_HEIGHT; i++ )
647 {
648 R_VideoErase ( ofs, side2 );
649 ofs += SCREENWIDTH;
650 }
651
652 R_VideoErase ( ofs, side );
653 }
654
655 if ( viewheight >= ( SCREENHEIGHT - ST_SCALED_HEIGHT ))
656 return; // if high-res, donŽt go any further!
657
658 top = ((SCREENHEIGHT-ST_SCALED_HEIGHT)-viewheight)/2;
659 side = (SCREENWIDTH-scaledviewwidth)/2;
660
661 // copy top and one line of left side
662 R_VideoErase (0, top*SCREENWIDTH+side);
663
664 // copy one line of right side and bottom
665 ofs = (viewheight+top)*SCREENWIDTH-side;
666 R_VideoErase (ofs, top*SCREENWIDTH+side);
667
668 // copy sides using wraparound
669 ofs = top*SCREENWIDTH + SCREENWIDTH-side;
670 side <<= 1;
671
672 for (i=1 ; i<viewheight ; i++)
673 {
674 R_VideoErase (ofs, side);
675 ofs += SCREENWIDTH;
676 }
677}