1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
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
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.
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.
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
28 * The actual span/column drawing functions.
29 * Here find the main potential for optimization,
30 * e.g. inline assembly, different algorithms.
32 *-----------------------------------------------------------------------------*/
41 //#include "lprintf.h"
42 #include "rockmacros.h"
45 // All drawing to the view buffer is accomplished in this file.
46 // The other refresh files only know about ccordinates,
47 // not the architecture of the frame buffer.
48 // Conveniently, the frame buffer is a linear one,
49 // and we need only the base address,
50 // and the total size == width*height*depth/8.,
60 byte
*topleft IBSS_ATTR
;
62 // Color tables for different players,
63 // translate a limited part to another
64 // (color ramps used for suit colors).
67 // CPhipps - made const*'s
68 const byte
*tranmap IBSS_ATTR
; // translucency filter maps 256x256 // phares
69 const byte
*main_tranmap IBSS_ATTR
; // killough 4/11/98
73 // Source is the top of the column to scale.
76 lighttable_t
*dc_colormap IBSS_ATTR
;
80 fixed_t dc_iscale IBSS_ATTR
;
81 fixed_t dc_texturemid IBSS_ATTR
;
82 int dc_texheight IBSS_ATTR
; // killough
83 const byte
*dc_source IBSS_ATTR
; // first pixel in a column (possibly virtual)
87 // A column is a vertical slice/span from a wall texture that,
88 // given the DOOM style restrictions on the view orientation,
89 // will always have constant z depth.
90 // Thus a special case loop for very fast rendering can
91 // be used. It has also been used with Wolfenstein 3D.
93 void R_DrawColumn (void)
96 register byte
*dest
; // killough
97 register fixed_t frac
; // killough
100 // removed the + 1 here, adjusted the if test, and added an increment
101 // later. this helps a compiler pipeline a bit better. the x86
102 // assembler also does this.
103 count
= dc_yh
- dc_yl
;
105 // Zero length, column does not exceed a pixel.
111 if ((unsigned)dc_x
>= SCREENWIDTH
113 || dc_yh
>= SCREENHEIGHT
)
114 I_Error ("R_DrawColumn: %d to %d at %d", dc_yl
, dc_yh
, dc_x
);
119 // Framebuffer destination address.
120 dest
= topleft
+ dc_yl
*SCREENWIDTH
+ dc_x
;
122 // Determine scaling,
123 // which is the only mapping to be done.
124 #define fracstep dc_iscale
126 frac
= dc_texturemid
+ (dc_yl
-centery
)*fracstep
;
128 // Inner loop that does the actual texture mapping,
129 // e.g. a DDA-lile scaling.
130 // This is as fast as it gets. (Yeah, right!!! -- killough)
132 // killough 2/1/98: more performance tuning
134 if (dc_texheight
== 128)
138 *dest
= dc_colormap
[dc_source
[(frac
>>FRACBITS
)&127]];
143 else if (dc_texheight
== 0)
145 /* cph - another special case */
148 *dest
= dc_colormap
[dc_source
[frac
>>FRACBITS
]];
155 register unsigned heightmask
= dc_texheight
-1; // CPhipps - specify type
156 if (! (dc_texheight
& heightmask
) ) // power of 2 -- killough
158 while (count
>0) // texture height is a power of 2 -- killough
160 *dest
= dc_colormap
[dc_source
[(frac
>>FRACBITS
) & heightmask
]];
169 heightmask
<<= FRACBITS
;
172 while ((frac
+= heightmask
) < 0)
175 while (frac
>= (int)heightmask
)
180 // Re-map color indices from wall texture column
181 // using a lighting/special effects LUT.
183 // heightmask is the Tutti-Frutti fix -- killough
185 *dest
= dc_colormap
[dc_source
[frac
>>FRACBITS
]];
187 if ((frac
+= fracstep
) >= (int)heightmask
)
196 // Here is the version of R_DrawColumn that deals with translucent // phares
197 // textures and sprites. It's identical to R_DrawColumn except // |
198 // for the spot where the color index is stuffed into *dest. At // V
199 // that point, the existing color index and the new color index
200 // are mapped through the TRANMAP lump filters to get a new color
201 // index whose RGB values are the average of the existing and new
204 // Since we're concerned about performance, the 'translucent or
205 // opaque' decision is made outside this routine, not down where the
206 // actual code differences are.
208 void R_DrawTLColumn (void)
211 register byte
*dest
; // killough
212 register fixed_t frac
; // killough
214 count
= dc_yh
- dc_yl
+ 1;
216 // Zero length, column does not exceed a pixel.
222 if ((unsigned)dc_x
>= (unsigned)SCREENWIDTH
224 || dc_yh
>= SCREENHEIGHT
)
225 I_Error("R_DrawTLColumn: %i to %i at %i", dc_yl
, dc_yh
, dc_x
);
228 // Framebuffer destination address.
229 dest
= topleft
+ dc_yl
*SCREENWIDTH
+ dc_x
;
231 // Determine scaling,
232 // which is the only mapping to be done.
233 #define fracstep dc_iscale
235 frac
= dc_texturemid
+ (dc_yl
-centery
)*fracstep
;
237 // Inner loop that does the actual texture mapping,
238 // e.g. a DDA-lile scaling.
239 // This is as fast as it gets. (Yeah, right!!! -- killough)
241 // killough 2/1/98, 2/21/98: more performance tuning
244 register const byte
*source
= dc_source
;
245 register const lighttable_t
*colormap
= dc_colormap
;
246 register unsigned heightmask
= dc_texheight
-1; // CPhipps - specify type
247 if (dc_texheight
& heightmask
) // not a power of 2 -- killough
250 heightmask
<<= FRACBITS
;
253 while ((frac
+= heightmask
) < 0)
256 while (frac
>= (int)heightmask
)
261 // Re-map color indices from wall texture column
262 // using a lighting/special effects LUT.
264 // heightmask is the Tutti-Frutti fix -- killough
266 *dest
= tranmap
[(*dest
<<8)+colormap
[source
[frac
>>FRACBITS
]]]; // phares
268 if ((frac
+= fracstep
) >= (int)heightmask
)
275 while ((count
-=2)>=0) // texture height is a power of 2 -- killough
277 *dest
= tranmap
[(*dest
<<8)+colormap
[source
[(frac
>>FRACBITS
) & heightmask
]]]; // phares
280 *dest
= tranmap
[(*dest
<<8)+colormap
[source
[(frac
>>FRACBITS
) & heightmask
]]]; // phares
285 *dest
= tranmap
[(*dest
<<8)+colormap
[source
[(frac
>>FRACBITS
) & heightmask
]]]; // phares
292 // Spectre/Invisibility.
296 // proff 08/17/98: Changed for high-res
297 //#define FUZZOFF (SCREENWIDTH)
300 static const int fuzzoffset_org
[FUZZTABLE
] ICONST_ATTR
= {
301 FUZZOFF
,-FUZZOFF
,FUZZOFF
,-FUZZOFF
,FUZZOFF
,FUZZOFF
,-FUZZOFF
,
302 FUZZOFF
,FUZZOFF
,-FUZZOFF
,FUZZOFF
,FUZZOFF
,FUZZOFF
,-FUZZOFF
,
303 FUZZOFF
,FUZZOFF
,FUZZOFF
,-FUZZOFF
,-FUZZOFF
,-FUZZOFF
,-FUZZOFF
,
304 FUZZOFF
,-FUZZOFF
,-FUZZOFF
,FUZZOFF
,FUZZOFF
,FUZZOFF
,FUZZOFF
,-FUZZOFF
,
305 FUZZOFF
,-FUZZOFF
,FUZZOFF
,FUZZOFF
,-FUZZOFF
,-FUZZOFF
,FUZZOFF
,
306 FUZZOFF
,-FUZZOFF
,-FUZZOFF
,-FUZZOFF
,-FUZZOFF
,FUZZOFF
,FUZZOFF
,
307 FUZZOFF
,FUZZOFF
,-FUZZOFF
,FUZZOFF
,FUZZOFF
,-FUZZOFF
,FUZZOFF
310 static int fuzzoffset
[FUZZTABLE
] IBSS_ATTR
;
312 static int fuzzpos IBSS_ATTR
= 0;
315 // Framebuffer postprocessing.
316 // Creates a fuzzy image by copying pixels
317 // from adjacent ones to left and right.
318 // Used with an all black colormap, this
319 // could create the SHADOW effect,
320 // i.e. spectres and invisible players.
323 void R_DrawFuzzColumn(void)
330 // Adjust borders. Low...
335 if (dc_yh
== viewheight
-1)
336 dc_yh
= viewheight
- 2;
338 count
= dc_yh
- dc_yl
;
346 if ((unsigned) dc_x
>= (unsigned)SCREENWIDTH
348 || (unsigned)dc_yh
>= (unsigned)SCREENHEIGHT
)
349 I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl
, dc_yh
, dc_x
);
352 // Keep till detailshift bug in blocky mode fixed,
353 // or blocky mode removed.
355 // Does not work with blocky mode.
356 dest
= topleft
+ dc_yl
*SCREENWIDTH
+ dc_x
;
359 fracstep
= dc_iscale
;
360 frac
= dc_texturemid
+ (dc_yl
-centery
)*fracstep
;
362 // Looks like an attempt at dithering,
363 // using the colormap #6 (of 0-31, a bit brighter than average).
367 // Lookup framebuffer, and retrieve
368 // a pixel that is either one column
369 // left or right of the current one.
370 // Add index from colormap to index.
371 // killough 3/20/98: use fullcolormap instead of colormaps
373 *dest
= fullcolormap
[6*256+dest
[fuzzoffset
[fuzzpos
]]];
375 // Some varying invisibility effects can be gotten by playing // phares
376 // with this logic. For example, try // phares
378 // *dest = fullcolormap[0*256+dest[FUZZOFF]]; // phares
380 // Clamp table lookup index.
381 if (++fuzzpos
== FUZZTABLE
)
392 // R_DrawTranslatedColumn
393 // Used to draw player sprites
394 // with the green colorramp mapped to others.
395 // Could be used with different translation
396 // tables, e.g. the lighter colored version
397 // of the BaronOfHell, the HellKnight, uses
398 // identical sprites, kinda brightened up.
401 byte
*dc_translation
, *translationtables
;
403 void R_DrawTranslatedColumn (void)
410 count
= dc_yh
- dc_yl
;
416 if ((unsigned)dc_x
>= (unsigned)SCREENWIDTH
418 || (unsigned)dc_yh
>= (unsigned)SCREENHEIGHT
)
419 I_Error("R_DrawColumn: %i to %i at %i", dc_yl
, dc_yh
, dc_x
);
423 dest
= topleft
+ dc_yl
*SCREENWIDTH
+ dc_x
;
426 fracstep
= dc_iscale
;
427 frac
= dc_texturemid
+ (dc_yl
-centery
)*fracstep
;
429 // Here we do an additional index re-mapping.
432 // Translation tables are used
433 // to map certain colorramps to other ones,
434 // used with PLAY sprites.
435 // Thus the "green" ramp of the player 0 sprite
436 // is mapped to gray, red, black/indigo.
438 *dest
= dc_colormap
[dc_translation
[dc_source
[frac
>>FRACBITS
]]];
447 // R_InitTranslationTables
448 // Creates the translation tables to map
449 // the green color ramp to gray, brown, red.
450 // Assumes a given structure of the PLAYPAL.
451 // Could be read from a lump instead.
454 byte playernumtotrans
[MAXPLAYERS
];
455 extern lighttable_t
*(*c_zlight
)[LIGHTLEVELS
][MAXLIGHTZ
];
457 void R_InitTranslationTables (void)
462 byte transtocolour
[MAXTRANS
];
465 // Remove dependency of colormaps aligned on 256-byte boundary
467 if (translationtables
== NULL
) // CPhipps - allow multiple calls
468 translationtables
= Z_Malloc(256*MAXTRANS
, PU_STATIC
, 0);
470 for (i
=0; i
<MAXTRANS
; i
++)
471 transtocolour
[i
] = 255;
473 for (i
=0; i
<MAXPLAYERS
; i
++)
475 byte wantcolour
= mapcolor_plyr
[i
];
476 playernumtotrans
[i
] = 0;
477 if (wantcolour
!= 0x70) // Not green, would like translation
478 for (j
=0; j
<MAXTRANS
; j
++)
479 if (transtocolour
[j
] == 255)
481 transtocolour
[j
] = wantcolour
;
482 playernumtotrans
[i
] = j
+1;
487 // translate just the 16 green colors
488 for (i
=0; i
<256; i
++)
489 if (i
>= 0x70 && i
<= 0x7f)
491 // CPhipps - configurable player colours
492 translationtables
[i
] = colormaps
[0][((i
&0xf)<<9) + transtocolour
[0]];
493 translationtables
[i
+256] = colormaps
[0][((i
&0xf)<<9) + transtocolour
[1]];
494 translationtables
[i
+512] = colormaps
[0][((i
&0xf)<<9) + transtocolour
[2]];
496 else // Keep all other colors as is.
497 translationtables
[i
]=translationtables
[i
+256]=translationtables
[i
+512]=i
;
502 // With DOOM style restrictions on view orientation,
503 // the floors and ceilings consist of horizontal slices
504 // or spans with constant z depth.
505 // However, rotation around the world z axis is possible,
506 // thus this mapping, while simpler and faster than
507 // perspective correct texture mapping, has to traverse
508 // the texture at an angle in all but a few cases.
509 // In consequence, flats are not stored by column (like walls),
510 // and the inner loop has to step in texture space u and v.
517 lighttable_t
*ds_colormap IBSS_ATTR
;
519 fixed_t ds_xfrac IBSS_ATTR
;
520 fixed_t ds_yfrac IBSS_ATTR
;
521 fixed_t ds_xstep IBSS_ATTR
;
522 fixed_t ds_ystep IBSS_ATTR
;
524 // start of a 64*64 tile image
525 byte
*ds_source IBSS_ATTR
;
527 void R_DrawSpan (void)
530 // only slightly faster
536 "move.l %[xfrac], %%d1 \n"
537 "move.l %[yfrac], %%d2 \n"
543 "and.l #4032,%%d2 \n"
545 "move.b (%[source], %%d1), %%d4 \n"
546 "add.l %[ds_xstep], %[xfrac] \n"
547 "add.l %[ds_ystep], %[yfrac] \n"
548 "move.b (%[colormap],%%d4.l), (%[dest])+ \n"
549 "subq.l #1, %[count] \n"
554 [count
] "d" (ds_x2
-ds_x1
+1),
555 [xfrac
] "d" (ds_xfrac
),
556 [yfrac
] "d" (ds_yfrac
),
557 [source
] "a" (ds_source
),
558 [colormap
] "a" (ds_colormap
),
559 [dest
] "a" (topleft
+ds_y
*SCREENWIDTH
+ds_x1
),
560 [ds_xstep
] "d" (ds_xstep
),
561 [ds_ystep
] "d" (ds_ystep
)
566 register unsigned count
= ds_x2
- ds_x1
+ 1,xfrac
= ds_xfrac
,yfrac
= ds_yfrac
;
568 register byte
*source
= ds_source
;
569 register byte
*colormap
= ds_colormap
;
570 register byte
*dest
= topleft
+ ds_y
*SCREENWIDTH
+ ds_x1
;
574 register unsigned xtemp
= xfrac
>> 16;
575 register unsigned ytemp
= yfrac
>> 10;
576 register unsigned spot
;
579 spot
= xtemp
| ytemp
;
582 *dest
++ = colormap
[source
[spot
]];
590 // Creats lookup tables that avoid
591 // multiplies and other hazzles
592 // for getting the framebuffer address
593 // of a pixel to draw.
596 void R_InitBuffer(int width
, int height
)
600 // e.g. smaller view windows
601 // with border and/or status bar.
603 viewwindowx
= (SCREENWIDTH
-width
) >> 1;
605 // Same with base row offset.
607 viewwindowy
= width
==SCREENWIDTH
? 0 : (SCREENHEIGHT
-(ST_SCALED_HEIGHT
-1)-height
)>>1;
609 topleft
= d_screens
[0] + viewwindowy
*SCREENWIDTH
+ viewwindowx
;
611 // Preclaculate all row offsets.
612 // CPhipps - merge viewwindowx into here
613 for (i
=0; i
<FUZZTABLE
; i
++)
614 fuzzoffset
[i
] = fuzzoffset_org
[i
]*SCREENWIDTH
;
620 // Fills the back screen with a pattern
621 // for variable screen sizes
622 // Also draws a beveled edge.
624 // CPhipps - patch drawing updated
626 void R_FillBackScreen (void)
630 if (scaledviewwidth
== SCREENWIDTH
)
633 V_DrawBackground(gamemode
== commercial
? "GRNROCK" : "FLOOR7_2", 1);
635 for (x
=0 ; x
<scaledviewwidth
; x
+=8)
636 V_DrawNamePatch(viewwindowx
+x
,viewwindowy
-8,1,"brdr_t", CR_DEFAULT
, VPT_NONE
);
638 for (x
=0 ; x
<scaledviewwidth
; x
+=8)
639 V_DrawNamePatch(viewwindowx
+x
,viewwindowy
+viewheight
,1,"brdr_b", CR_DEFAULT
, VPT_NONE
);
641 for (y
=0 ; y
<viewheight
; y
+=8)
642 V_DrawNamePatch(viewwindowx
-8,viewwindowy
+y
,1,"brdr_l", CR_DEFAULT
, VPT_NONE
);
644 for (y
=0 ; y
<viewheight
; y
+=8)
645 V_DrawNamePatch(viewwindowx
+scaledviewwidth
,viewwindowy
+y
,1,"brdr_r", CR_DEFAULT
, VPT_NONE
);
647 // Draw beveled edge.
648 V_DrawNamePatch(viewwindowx
-8,viewwindowy
-8,1,"brdr_tl", CR_DEFAULT
, VPT_NONE
);
650 V_DrawNamePatch(viewwindowx
+scaledviewwidth
,viewwindowy
-8,1,"brdr_tr", CR_DEFAULT
, VPT_NONE
);
652 V_DrawNamePatch(viewwindowx
-8,viewwindowy
+viewheight
,1,"brdr_bl", CR_DEFAULT
, VPT_NONE
);
654 V_DrawNamePatch(viewwindowx
+scaledviewwidth
,viewwindowy
+viewheight
,1,"brdr_br", CR_DEFAULT
, VPT_NONE
);
658 // Copy a screen buffer.
661 void R_VideoErase(unsigned ofs
, int count
)
663 memcpy(d_screens
[0]+ofs
, d_screens
[1]+ofs
, count
); // LFB copy.
668 // Draws the border around the view
669 // for different size windows?
672 void R_DrawViewBorder(void)
674 int top
, side
, ofs
, i
;
675 // proff/nicolas 09/20/98: Added for high-res (inspired by DosDOOM)
678 // proff/nicolas 09/20/98: Removed for high-res
679 // if (scaledviewwidth == SCREENWIDTH)
682 // proff/nicolas 09/20/98: Added for high-res (inspired by DosDOOM)
683 if ((SCREENHEIGHT
!= viewheight
) ||
684 ((automapmode
& am_active
) && ! (automapmode
& am_overlay
)))
686 ofs
= ( SCREENHEIGHT
- ST_SCALED_HEIGHT
) * SCREENWIDTH
;
687 side
= ( SCREENWIDTH
- ST_SCALED_WIDTH
) / 2;
690 R_VideoErase ( ofs
, side
);
692 ofs
+= ( SCREENWIDTH
- side
);
693 for ( i
= 1; i
< ST_SCALED_HEIGHT
; i
++ )
695 R_VideoErase ( ofs
, side2
);
699 R_VideoErase ( ofs
, side
);
702 if ( viewheight
>= ( SCREENHEIGHT
- ST_SCALED_HEIGHT
))
703 return; // if high-res, don't go any further!
705 top
= ((SCREENHEIGHT
-ST_SCALED_HEIGHT
)-viewheight
)/2;
706 side
= (SCREENWIDTH
-scaledviewwidth
)/2;
708 // copy top and one line of left side
709 R_VideoErase (0, top
*SCREENWIDTH
+side
);
711 // copy one line of right side and bottom
712 ofs
= (viewheight
+top
)*SCREENWIDTH
-side
;
713 R_VideoErase (ofs
, top
*SCREENWIDTH
+side
);
715 // copy sides using wraparound
716 ofs
= top
*SCREENWIDTH
+ SCREENWIDTH
-side
;
719 for (i
=1 ; i
<viewheight
; i
++)
721 R_VideoErase (ofs
, side
);