1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: r_draw24.c 902 2012-02-29 07:30:00Z wesleyjohnson $
5 //
6 // Copyright (C) 2012-2012 by DooM Legacy Team.
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 //
19 // DESCRIPTION:
20 //      24bpp span/column drawer functions
21 //
22 //  NOTE: no includes because this is included as part of r_draw.c
23 //
24 //-----------------------------------------------------------------------------
25 
26 
27 // ==========================================================================
28 // COLUMNS
29 // ==========================================================================
30 
31 // r_data.c
32   // include: color8.to32
33 
34 
35 // 24bpp composite (ENABLE_DRAW24) is 8:8:8
36 // color_8.to32 color is aligned with pix24 for speed
37 
38 //  standard upto 128high posts column drawer
39 //
R_DrawColumn_24(void)40 void R_DrawColumn_24 (void)
41 {
42     unsigned int heightmask = dc_texheight - 1;
43     int     count;
44     byte *  dest;  // within screen buffer
45     fixed_t frac;
46     fixed_t fracstep;
47     pixelunion32_t c32;
48 
49     count = dc_yh - dc_yl+1;
50 
51     // Zero length, column does not exceed a pixel.
52     if (count <= 0)
53         return;
54 
55 #ifdef RANGECHECK_DRAW_LIMITS
56     if ((unsigned)dc_x >= vid.width
57         || dc_yl < 0
58         || dc_yh >= vid.height)
59     {
60         I_SoftError ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
61         return;
62     }
63 #endif
64 
65     // Screen buffer destination address.
66     // Use ylookup LUT to avoid multiply with ScreenWidth.
67     dest = ylookup[dc_yl] + columnofs[dc_x];
68 
69     // Determine scaling, which is the only mapping to be done.
70     fracstep = dc_iscale;
71     frac = dc_texturemid + (dc_yl-centery)*fracstep;
72 
73     if( dc_texheight & heightmask )
74     {
75         // Odd size texture, use texheight
76         fixed_t texheight = dc_texheight << FRACBITS;
77         // Inner loop that does the actual texture mapping.
78         do
79         {
80             // Re-map color indices from wall texture column
81             //  using a lighting/special effects LUT.
82             c32.ui32 = color8.to32[ dc_colormap[ dc_source[(frac>>FRACBITS)] ] ];
83             *(pixel24_t*)dest = c32.pix24;
84             dest += vid.ybytes;
85             frac += fracstep;
86             if( frac >= texheight )
87                 frac -= texheight;
88         } while (--count);
89     }
90     else
91     {
92         // Inner loop that does the actual texture mapping.
93         do
94         {
95             // Re-map color indices from wall texture column
96             //  using a lighting/special effects LUT.
97             c32.ui32 = color8.to32[ dc_colormap[ dc_source[(frac>>FRACBITS)&heightmask] ] ];
98             *(pixel24_t*)dest = c32.pix24;
99             dest += vid.ybytes;
100             frac += fracstep;
101         } while (--count);
102     }
103 }
104 
105 
106 //  Same as R_DrawColumn_24 but wraps around 256
107 //  instead of 128 for the tall sky textures (256x240)
108 //
R_DrawSkyColumn_24(void)109 void R_DrawSkyColumn_24 (void)
110 {
111     int     count;
112     byte *  dest;  // within screen buffer
113     fixed_t frac;
114     fixed_t fracstep;
115     pixelunion32_t c32;
116 
117     count = dc_yh - dc_yl+1;
118 
119     // Zero length, column does not exceed a pixel.
120     if (count <= 0)
121         return;
122 
123 #ifdef RANGECHECK_DRAW_LIMITS
124     if ((unsigned)dc_x >= vid.width
125         || dc_yl < 0
126         || dc_yh >= vid.height)
127     {
128         I_SoftError ("R_DrawSkyColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
129         return;
130     }
131 #endif
132 
133     dest = ylookup[dc_yl] + columnofs[dc_x];
134 
135     fracstep = dc_iscale;
136     frac = dc_texturemid + (dc_yl-centery)*fracstep;
137 
138     do
139     {
140         c32.ui32 = color8.to32[ dc_colormap[ dc_source[(frac>>FRACBITS)&255] ] ];
141         *(pixel24_t*)dest = c32.pix24;
142         dest += vid.ybytes;
143         frac += fracstep;
144     } while (--count);
145 }
146 
147 
R_DrawFuzzColumn_24(void)148 void R_DrawFuzzColumn_24 (void)
149 {
150     int     count;
151     byte*   dest;
152 
153     // Adjust borders. Low...
154     if (!dc_yl)
155         dc_yl = 1;
156 
157     // .. and high.
158     if (dc_yh == rdraw_viewheight-1)
159         dc_yh = rdraw_viewheight - 2;
160 
161     count = dc_yh - dc_yl;
162 
163     // Zero length.
164     if (count < 0)
165         return;
166 
167 
168 #ifdef RANGECHECK_DRAW_LIMITS
169     if ((unsigned)dc_x >= vid.width
170         || dc_yl < 0 || dc_yh >= vid.height)
171     {
172         I_SoftError ("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
173         return;
174     }
175 #endif
176 
177     // Does not work with blocky mode.
178     dest = ylookup[dc_yl] + columnofs[dc_x];
179 
180     do
181     {
182         // Retrieve a pixel that is either one column left or right
183         // of the dest, dim it 8%, and write it as dest.
184         // 8bpp: *dest = reg_colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
185         register pixel24_t * src = (pixel24_t*)(dest + fuzzoffset[fuzzpos]);
186         ((pixel24_t*)dest)->b = src->b - (src->b >> 3);
187         ((pixel24_t*)dest)->g = src->g - (src->g >> 3);
188         ((pixel24_t*)dest)->r = src->r - (src->r >> 3);
189 
190         dest += vid.ybytes;
191         // Clamp table lookup index.
192         if (++fuzzpos == FUZZTABLE)
193             fuzzpos = 0;
194     } while (count--);
195 }
196 
197 
198 // To draw FF_SMOKESHADE things, sprite is an \alpha channel
R_DrawShadeColumn_24(void)199 void R_DrawShadeColumn_24(void)
200 {
201     fixed_t texheight = dc_texheight << FRACBITS;  // any texture size
202     int count;
203     register byte *dest;
204     register fixed_t frac;
205     register fixed_t fracstep;
206     unsigned int  alpha;
207 
208     // [WDJ] Source check has been added to all the callers of colfunc().
209 
210     count = dc_yh - dc_yl;
211     if (count < 0)
212         return;
213 
214 #ifdef RANGECHECK_DRAW_LIMITS
215     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
216     {
217         I_SoftError("R_DrawShadeColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
218         return;
219     }
220 #endif
221 
222     // FIXME. As above.
223     dest = ylookup[dc_yl] + columnofs[dc_x];
224 
225     // Looks familiar.
226     fracstep = dc_iscale;
227     frac = dc_texturemid + (dc_yl - centery) * fracstep;
228     if (texheight > 0)  // hangs when texheight==0
229     {
230         // From Boom, to fix the odd frac
231         if (frac < 0)
232             while ((frac += texheight) < 0);
233         else
234             while (frac >= texheight)  frac -= texheight;
235     }
236 
237     do
238     {
239         // 8bpp: *dest = reg_colormaps[ LIGHTTABLE(dc_source[frac >> FRACBITS]) + (*dest) ];
240         // [WDJ] The source is a patch of alpha values, 0..255..
241         // light level values are 0..NUMCOLORMAPS-1, which is 0..32
242 //        alpha = dc_source[frac >> FRACBITS] >> 3;  // reduce 0..255 to 0..32
243         alpha = dc_source[frac >> FRACBITS];
244         register pixel24_t * p24 = (pixel24_t*)dest;
245         p24->b = (p24->b * alpha) >> 5;
246         p24->g = (p24->g * alpha) >> 5;
247         p24->r = (p24->r * alpha) >> 5;
248 
249         dest += vid.ybytes;
250         frac += fracstep;
251         if( frac >= texheight )
252             frac -= texheight;
253     }
254     while (count--);
255 }
256 
257 
258 #ifdef ENABLE_DRAW_ALPHA
R_DrawAlphaColumn_24(void)259 void R_DrawAlphaColumn_24(void)
260 {
261 #if 0
262     fixed_t texheight = dc_texheight << FRACBITS;  // any texture size
263 #endif
264     int count;
265     register byte *dest;
266     register fixed_t frac;
267     register fixed_t fracstep;
268     unsigned int  alpha, alpha_r;
269 
270     // [WDJ] Source check has been added to all the callers of colfunc().
271 
272     count = dc_yh - dc_yl;
273     if (count < 0)
274         return;
275 
276 #ifdef RANGECHECK_DRAW_LIMITS
277     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
278     {
279         I_SoftError("R_DrawAlphaColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
280         return;
281     }
282 #endif
283 
284     dest = ylookup[dc_yl] + columnofs[dc_x];
285     fracstep = dc_iscale;
286     frac = dc_texturemid + (dc_yl - centery) * fracstep;
287 
288 #if 0
289     // [WDJ] Only draws sprite for now.
290     if (texheight > 0)  // hangs when texheight==0
291     {
292         // From Boom, to fix the odd frac
293         if (frac < 0)
294             while ((frac += texheight) < 0);
295         else
296             while (frac >= texheight)  frac -= texheight;
297     }
298 #endif
299 
300   switch( dr_alpha_mode )
301   {
302 
303    case 0: // Alpha blend
304     do
305     {
306         // [WDJ] The source is a patch of alpha values, 0..255.
307         alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
308         alpha_r = 255 - alpha;
309         register pixel24_t * p24 = (pixel24_t*)dest;
310         p24->b = ((p24->b * alpha_r) + (dr_color.s.blue * alpha))  >> 8;
311         p24->g = ((p24->g * alpha_r) + (dr_color.s.green * alpha)) >> 8;
312         p24->r = ((p24->r * alpha_r) + (dr_color.s.red * alpha))   >> 8;
313 
314         dest += vid.ybytes;
315         frac += fracstep;
316 #if 0
317         if( frac >= texheight )
318             frac -= texheight;
319 #endif
320     }
321     while (count--);
322     break;
323 
324    case 1: // Alpha blend with constant background alpha.
325     // Caller must set dr_alpha_background at (255 - dr_alpha) or less.
326     alpha_r = dr_alpha_background;
327     do
328     {
329         // [WDJ] The source is a patch of alpha values, 0..255.
330         alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
331         register pixel24_t * p24 = (pixel24_t*)dest;
332         p24->b = (((unsigned int)p24->b * alpha_r) + ((unsigned int)dr_color.s.blue * alpha))  >> 8;
333         p24->g = (((unsigned int)p24->g * alpha_r) + ((unsigned int)dr_color.s.green * alpha)) >> 8;
334         p24->r = (((unsigned int)p24->r * alpha_r) + ((unsigned int)dr_color.s.red * alpha))   >> 8;
335 
336         dest += vid.ybytes;
337         frac += fracstep;
338 #if 0
339         if( frac >= texheight )
340             frac -= texheight;
341 #endif
342     }
343     while (count--);
344     break;
345 
346    case 2: // Additive alpha
347     // Additive alpha
348     do
349     {
350         // [WDJ] The source is a patch of alpha values, 0..255.
351         alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
352         register pixel24_t * p24 = (pixel24_t*)dest;
353         p24->b += (((unsigned int)dr_color.s.blue  * alpha * (255 - p24->b))) >> 16;
354         p24->g += (((unsigned int)dr_color.s.green * alpha * (255 - p24->g))) >> 16;
355         p24->r += (((unsigned int)dr_color.s.red   * alpha * (255 - p24->r))) >> 16;
356 
357         dest += vid.ybytes;
358         frac += fracstep;
359 #if 0
360         if( frac >= texheight )
361             frac -= texheight;
362 #endif
363     }
364     while (count--);
365     break;
366 
367    case 3: // Additive alpha, with background alpha
368     alpha_r = dr_alpha_background;
369     do
370     {
371         // [WDJ] The source is a patch of alpha values, 0..255.
372         alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
373         register pixel24_t * p24 = (pixel24_t*)dest;
374         register unsigned int r,g,b;
375         b = (p24->b * alpha_r)>>8;
376         p24->b = (((unsigned int)dr_color.s.blue  * alpha * (255 - b)) >> 16) + b;
377         g = (p24->g * alpha_r)>>8;
378         p24->g = (((unsigned int)dr_color.s.green * alpha * (255 - g)) >> 16) + g;
379         r = (p24->r * alpha_r)>>8;
380         p24->r = (((unsigned int)dr_color.s.red   * alpha * (255 - r)) >> 16) + r;
381 
382         dest += vid.ybytes;
383         frac += fracstep;
384 #if 0
385         if( frac >= texheight )
386             frac -= texheight;
387 #endif
388     }
389     while (count--);
390     break;
391 
392    case 4: // Additive alpha, limit math
393     do
394     {
395         // [WDJ] The source is a patch of alpha values, 0..255.
396         alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
397         register pixel24_t * p24 = (pixel24_t*)dest;
398         register unsigned int r,g,b;
399         b = (((unsigned int)dr_color.s.blue * alpha) >> 8) + p24->b;
400         p24->b = (b > 255)? 255 : b;
401         g = (((unsigned int)dr_color.s.green * alpha) >> 8) + p24->g;
402         p24->g = (g > 255)? 255 : g;
403         r = (((unsigned int)dr_color.s.red * alpha) >> 8) + p24->r;
404         p24->r = (r > 255)? 255 : r;
405 
406         dest += vid.ybytes;
407         frac += fracstep;
408 #if 0
409         if( frac >= texheight )
410             frac -= texheight;
411 #endif
412     }
413     while (count--);
414     break;
415   }
416 
417 }
418 #endif
419 
R_DrawTranslucentColumn_24(void)420 void R_DrawTranslucentColumn_24 (void)
421 {
422     fixed_t texheight = dc_texheight << FRACBITS;  // any texture size
423     int     count;
424     byte*   dest;  // within screen buffer
425     fixed_t frac;
426     fixed_t fracstep;
427     pixelunion32_t c32;
428 
429     // [WDJ] Source check has been added to all the callers of colfunc().
430 
431     count = dc_yh - dc_yl;
432     if (count < 0)
433         return;
434 
435 #ifdef RANGECHECK_DRAW_LIMITS
436     if ((unsigned)dc_x >= vid.width
437         || dc_yl < 0
438         || dc_yh >= vid.height)
439     {
440         I_SoftError ( "R_DrawTranslucentColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
441         return;
442     }
443 
444 #endif
445 
446     dest = ylookup[dc_yl] + columnofs[dc_x];
447 
448     // Looks familiar.
449     fracstep = dc_iscale;
450     frac = dc_texturemid + (dc_yl-centery)*fracstep;
451     if (texheight > 0)  // hangs when texheight==0
452     {
453         // From Boom, to fix the odd frac
454         if (frac < 0)
455             while ((frac += texheight) < 0);
456         else
457             while (frac >= texheight)  frac -= texheight;
458     }
459 
460     // 8bpp: *dest = dc_colormap[ dc_translucentmap[ (dc_source[frac >> FRACBITS] << 8) + (*dest) ]];
461     switch( dc_translucent_index )
462     {
463      case 0:
464         {
465             // alpha translucent, by dr_alpha
466             unsigned int alpha_d = dr_alpha;
467             unsigned int alpha_r = 255 - alpha_d;
468             do
469             {
470                 c32.ui32 = color8.to32[dc_colormap[dc_source[frac>>FRACBITS]]];
471 //               c32.ui32 = color8.to32[dc_source[frac>>FRACBITS]];
472                 // alpha translucent
473                 register pixel24_t * p24 = (pixel24_t*)dest;
474                 p24->b = (((unsigned int)p24->b * alpha_r) + (c32.pix24.b * alpha_d)) >> 8;
475                 p24->g = (((unsigned int)p24->g * alpha_r) + (c32.pix24.g * alpha_d)) >> 8;
476                 p24->r = (((unsigned int)p24->r * alpha_r) + (c32.pix24.r * alpha_d)) >> 8;
477                 dest += vid.ybytes;
478                 frac += fracstep;
479                 if( frac >= texheight )
480                     frac -= texheight;
481             } while (count--);
482         }
483         break;
484      case TRANSLU_more: // 20 80  puffs, Linedef 285
485         do
486         {
487             // 25/75 translucent
488             c32.ui32 = color8.to32[dc_colormap[dc_source[frac>>FRACBITS]]];
489 //	    c32.ui32 = color8.to32[dc_source[frac>>FRACBITS]];
490             register uint16_t dc0, dc1, dc2; // for overlapped execution
491             register pixel24_t * p24 = (pixel24_t*)dest;
492             dc0 = p24->b;
493             p24->b = (dc0 + dc0 + dc0 + c32.pix24.b) >> 2;
494             dc1 = p24->g;
495             p24->g = (dc1 + dc1 + dc1 + c32.pix24.g) >> 2;
496             dc2 = p24->r;
497             p24->r = (dc2 + dc2 + dc2 + c32.pix24.r) >> 2;
498             dest += vid.ybytes;
499             frac += fracstep;
500             if( frac >= texheight )
501                 frac -= texheight;
502         } while (count--);
503         break;
504      case TRANSLU_hi:   // 10 90  blur effect, Linedef 286
505         do
506         {
507             // 15/85 translucent
508             c32.ui32 = color8.to32[dc_colormap[dc_source[frac>>FRACBITS]]];
509 //	    c32.ui32 = color8.to32[dc_source[frac>>FRACBITS]];
510             register uint16_t dc0, dc1, dc2; // for overlapped execution
511             register pixel24_t * p24 = (pixel24_t*)dest;
512             dc0 = p24->b;
513             p24->b = ((dc0<<3) - dc0 + c32.pix24.b) >> 3;
514             dc1 = p24->g;
515             p24->g = ((dc1<<3) - dc1 + c32.pix24.g) >> 3;
516             dc2 = p24->r;
517             p24->r = ((dc2<<3) - dc2 + c32.pix24.r) >> 3;
518             dest += vid.ybytes;
519             frac += fracstep;
520             if( frac >= texheight )
521                 frac -= texheight;
522         } while (count--);
523         break;
524      case TRANSLU_med:  // sprite 50 backg 50, Linedef 260, 284, 300
525      default:
526         do
527         {
528             // 50/50 translucent
529             c32.ui32 = color8.to32[dc_colormap[dc_source[frac>>FRACBITS]]];
530 //	    c32.ui32 = color8.to32[dc_source[frac>>FRACBITS]];
531             register uint16_t dc0, dc1, dc2; // for overlapped execution
532             register pixel24_t * p24 = (pixel24_t*)dest;
533             dc0 = p24->b;
534             p24->b = (dc0 + c32.pix24.b) >> 1;
535             dc1 = p24->g;
536             p24->g = (dc1 + c32.pix24.g) >> 1;
537             dc2 = p24->r;
538             p24->r = (dc2 + c32.pix24.r) >> 1;
539             dest += vid.ybytes;
540             frac += fracstep;
541             if( frac >= texheight )
542                 frac -= texheight;
543         } while (count--);
544         break;
545      case TRANSLU_fire: // Linedef 287
546         // 50 50 but brighter for fireballs, shots
547 #define TFIRE_OPTION  1
548         do
549         {
550             // 50/50 translucent with modifications
551             register int sb = dc_source[frac>>FRACBITS];
552 #if TFIRE_OPTION==4
553 //	    sb = dc_translucentmap[ (sb << 8) + 80 ]; // grays 80..111; // faded
554 //	    sb = dc_translucentmap[ (sb << 8) + 110 ]; // grays 80..111;
555             sb = dc_translucentmap[ (sb << 8) ]; // black
556 #endif
557             c32.ui32 = color8.to32[dc_colormap[ sb ]];
558 //	    c32.ui32 = color8.to32[ sb ];
559 #if TFIRE_OPTION==1
560             // dark background is enhanced before avg, to give light add effect
561             register pixelunion32_t sh32;
562             sh32.ui32 = (c32.ui32 >> 1) & 0x70707070;  // tint
563 //	    sh32.ui32 = (c32.ui32 >> 1) & 0x7F7F7F7F;  // heavy
564             register uint16_t dc0, dc1, dc2; // for overlapped execution
565             register pixel24_t * p24 = (pixel24_t*)dest;
566             dc0 = p24->b;
567             p24->b = ((dc0 | sh32.pix32.b) + c32.pix24.b) >> 1;
568             dc1 = p24->g;
569             p24->g = ((dc1 | sh32.pix32.g) + c32.pix24.g) >> 1;
570             dc2 = p24->r;
571             p24->r = ((dc2 | sh32.pix32.r) + c32.pix24.r) >> 1;
572 #endif
573 #if TFIRE_OPTION==2
574             // Bright and nearly opaque
575             // additive light (not average)
576             register uint16_t dc0, dc1, dc2; // for overlapped execution
577             register pixel24_t * p24 = (pixel24_t*)dest;
578             dc0 = p24->b;
579             p24->b = (dc0 | c32.pix24.b);
580             dc1 = p24->g;
581             p24->g = (dc1 | c32.pix24.g);
582             dc2 = p24->r;
583             p24->r = (dc2 | c32.pix24.r);
584 #endif
585             dest += vid.ybytes;
586             frac += fracstep;
587             if( frac >= texheight )
588                 frac -= texheight;
589         } while (count--);
590         break;
591      case TRANSLU_fx1:  // Linedef 288
592         // 50 50 brighter some colors, else opaque for torches
593         // fire translucent texture
594 #define FX1_OPTION 1
595         do
596         {
597             // 50/50 translucent with modifications
598             register int sb = dc_source[frac>>FRACBITS];
599             c32.ui32 = color8.to32[dc_colormap[ sb ]];
600 //	    c32.ui32 = color8.to32[ sb ];
601 #if FX1_OPTION==1
602             // check translucent map for opaque, sprite vrs white bkg
603             register byte twht = dc_translucentmap[ (sb << 8) + 4 ];
604             register int  tdiff = sb - twht;  // any change
605 #else
606             // check translucent map for opaque, blk bkg vrs white bkg
607             register byte tblk = dc_translucentmap[ (sb << 8) ];
608             register byte twht = dc_translucentmap[ (sb << 8) + 4 ];
609             register int  tdiff = tblk - twht;
610 #endif
611 
612             if( tdiff > 2 || tdiff < -2 )
613             {
614                 // 50/50
615                 register uint16_t dc0, dc1, dc2;
616                 register pixel24_t * p24 = (pixel24_t*)dest;
617                 dc0 = p24->b;
618                 p24->b = (dc0 + c32.pix24.b) >> 1;
619                 dc1 = p24->g;
620                 p24->g = (dc1 + c32.pix24.g) >> 1;
621                 dc2 = p24->r;
622                 p24->r = (dc2 + c32.pix24.r) >> 1;
623             }
624             else
625             {
626                 *(pixel24_t*)dest = c32.pix24;  // opaque
627             }
628             dest += vid.ybytes;
629             frac += fracstep;
630             if( frac >= texheight )
631                 frac -= texheight;
632         } while (count--);
633         break;
634      case TRANSLU_75: // 75 25
635         do
636         {
637             // 75/25 translucent
638             c32.ui32 = color8.to32[dc_colormap[dc_source[frac>>FRACBITS]]];
639             register uint16_t dc0, dc1, dc2; // for overlapped execution
640             register pixel24_t * p24 = (pixel24_t*)dest;
641             dc0 = c32.pix24.b;
642             p24->b = (dc0 + dc0 + dc0 + p24->b) >> 2;
643             dc1 = c32.pix24.g;
644             p24->g = (dc1 + dc1 + dc1 + p24->g) >> 2;
645             dc2 = c32.pix24.r;
646             p24->r = (dc2 + dc2 + dc2 + p24->r) >> 2;
647             dest += vid.ybytes;
648             frac += fracstep;
649             if( frac >= texheight )
650                 frac -= texheight;
651         } while (count--);
652         break;
653     }
654 }
655 
656 
657 // transparent with skin translations
658 // Although the vissprite has capability for any transparency,
659 // Called with TRANSLU_hi or TRANSLU_more, or arbitrary by thing TRANSMASK
R_DrawTranslatedTranslucentColumn_24(void)660 void R_DrawTranslatedTranslucentColumn_24(void)
661 {
662     R_DrawTranslucentColumn_24();
663 }
664 
665 
666 // Skin
R_DrawTranslatedColumn_24(void)667 void R_DrawTranslatedColumn_24 (void)
668 {
669     fixed_t texheight = dc_texheight << FRACBITS;  // any texture size
670     int     count;
671     byte*   dest;  // within screen buffer
672     fixed_t frac;
673     fixed_t fracstep;
674     pixelunion32_t c32;
675 
676     count = dc_yh - dc_yl;
677     if (count < 0)
678         return;
679 
680 #ifdef RANGECHECK_DRAW_LIMITS
681     if ((unsigned)dc_x >= vid.width
682         || dc_yl < 0
683         || dc_yh >= vid.height)
684     {
685         I_SoftError ( "R_DrawTranslatedColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
686         return;
687     }
688 
689 #endif
690 
691     dest = ylookup[dc_yl] + columnofs[dc_x];
692 
693     // Looks familiar.
694     fracstep = dc_iscale;
695     frac = dc_texturemid + (dc_yl-centery)*fracstep;
696     if (texheight > 0)  // hangs when texheight==0
697     {
698         // From Boom, to fix the odd frac
699         if (frac < 0)
700             while ((frac += texheight) < 0);
701         else
702             while (frac >= texheight)  frac -= texheight;
703     }
704 
705     // Here we do an additional skin re-mapping.
706     do
707     {
708         c32.ui32 = color8.to32[ dc_colormap[ dc_skintran[ dc_source[frac>>FRACBITS]]] ];
709         *(pixel24_t*)dest = c32.pix24;  // opaque
710         dest += vid.ybytes;
711         frac += fracstep;
712         if( frac >= texheight )
713             frac -= texheight;
714     } while (count--);
715 }
716 
717 
718 
719 // ==========================================================================
720 // SPANS
721 // ==========================================================================
722 
R_DrawSpan_24(void)723 void R_DrawSpan_24 (void)
724 {
725     fixed_t xfrac;
726     fixed_t yfrac;
727     pixel24_t *  p24;
728     int     count;
729     pixelunion32_t c32;
730 
731 #ifdef RANGECHECK_DRAW_LIMITS
732     if (ds_x2 < ds_x1
733         || ds_x1<0
734         || ds_x2>=vid.width
735         || (unsigned)ds_y>vid.height)
736     {
737         I_SoftError( "R_DrawSpan: %i to %i at %i", ds_x1,ds_x2,ds_y);
738         return;
739     }
740 #endif
741 
742     xfrac = ds_xfrac;
743     yfrac = ds_yfrac;
744 
745     p24 = (pixel24_t*)( ylookup[ds_y] + columnofs[ds_x1] );
746 
747     // We do not check for zero spans here?
748     count = ds_x2 - ds_x1;
749 
750     do
751     {
752         // Current texture index in u,v.
753         xfrac &= flat_imask;
754         register int spot = ((yfrac >> flatfracbits) & flat_ymask) | (xfrac >> 16);
755         // Lookup pixel from flat texture tile,
756         //  re-index using light/colormap.
757         c32.ui32 = color8.to32[ ds_colormap[ds_source[spot]] ];
758         *(p24++) = c32.pix24;  // opaque
759         // Next step in u,v.
760         xfrac += ds_xstep;
761         yfrac += ds_ystep;
762     } while (count--);
763 }
764 
765 
R_DrawTranslucentSpan_24(void)766 void R_DrawTranslucentSpan_24(void)
767 {
768     fixed_t xfrac, yfrac;
769     fixed_t xstep, ystep;
770     pixel24_t *  p24;
771     unsigned int alpha_d = dr_alpha;
772     unsigned int alpha_r = 255 - alpha_d;
773     int count;
774     pixelunion32_t c32;
775 
776 #ifdef RANGECHECK_DRAW_LIMITS
777     if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= rdraw_viewwidth || (unsigned) ds_y > rdraw_viewheight)
778     {
779         I_SoftError("R_DrawTranslucentSpan: %i to %i at %i\n", ds_x1, ds_x2, ds_y);
780         return;
781     }
782 #endif
783 
784     xfrac = ds_xfrac & flat_imask;
785     yfrac = ds_yfrac;
786 
787     p24 = (pixel24_t*)( ylookup[ds_y] + columnofs[ds_x1] );
788 
789     // We do not check for zero spans here?
790     count = ds_x2 - ds_x1 + 1;
791 
792     xstep = ds_xstep;
793     ystep = ds_ystep;
794 
795     do
796     {
797         // Current texture index in u,v.
798         // Lookup pixel from flat texture tile,
799         xfrac &= flat_imask;
800         register int spot = ((yfrac >> flatfracbits) & flat_ymask) | (xfrac >> FRACBITS);
801         // Lookup pixel from flat texture tile,
802         //  re-index using light/colormap.
803         c32.ui32 = color8.to32[ ds_colormap[ds_source[spot]] ];
804         // alpha translucent
805         p24->b = (((unsigned int)p24->b * alpha_r) + (c32.pix24.b * alpha_d)) >> 8;
806         p24->g = (((unsigned int)p24->g * alpha_r) + (c32.pix24.g * alpha_d)) >> 8;
807         p24->r = (((unsigned int)p24->r * alpha_r) + (c32.pix24.r * alpha_d)) >> 8;
808         p24 ++;  // *3
809 
810         // Next step in u,v.
811         xfrac += xstep;
812         yfrac += ystep;
813         xfrac &= flat_imask;
814     }
815     while (--count);
816 }
817 
818 
819 // Used for Legacy linetype 302, ceiling and floor of 3D fog in tagged
R_DrawFogSpan_24(void)820 void R_DrawFogSpan_24(void)
821 {
822     pixelunion32_t fogcolor;
823     unsigned int alpha_d = dr_alpha;
824     unsigned int alpha_r = (255 - alpha_d) * 0.84;  // cloudy fog
825     unsigned int count;
826     pixel24_t *  p24;
827 
828     fogcolor.ui32 = color8.to32[ ds_colormap[ ds_source[0] ]];
829     p24 = (pixel24_t*)( ylookup[ds_y] + columnofs[ds_x1] );
830     count = ds_x2 - ds_x1 + 1;
831 
832     {
833         register int fb = fogcolor.pix32.b * alpha_d;
834         register int fg = fogcolor.pix32.g * alpha_d;
835         register int fr = fogcolor.pix32.r * alpha_d;
836         while (count--)
837         {
838             p24->b = ((p24->b * alpha_r) + fb) >> 8;
839             p24->g = ((p24->g * alpha_r) + fg) >> 8;
840             p24->r = ((p24->r * alpha_r) + fr) >> 8;
841             p24 ++;  // *3
842         }
843     }
844 }
845 
846 //SoM: Fog wall.
847 // Used for Legacy linetype 302, walls of 3D fog in tagged
848 // Used for Legacy linetype 283, fog sheet
R_DrawFogColumn_24(void)849 void R_DrawFogColumn_24(void)
850 {
851 static pixelunion32_t fogcolor = {.ui32=0x00101010};
852     pixelunion32_t fc, fc2, fc3;
853     unsigned int alpha_d = dr_alpha;
854     unsigned int alpha_r = (255 - alpha_d) * 0.84;  // cloudy fog
855     int count, fi;
856     byte * dest;
857 
858     // fog_index 0.. column height
859     // always average three pixels of source texture
860     fc.ui32 = color8.to32[ dc_colormap[ dc_source[fog_index] ]];
861     fi = fog_index + 3;
862     if( fi >= fog_col_length )  fi -= fog_col_length;
863     fc2.ui32 = color8.to32[ dc_colormap[ dc_source[fi] ]];
864     fi += 3;
865     if( fi >= fog_col_length )  fi -= fog_col_length;
866     fc3.ui32 = color8.to32[ dc_colormap[ dc_source[fi] ]];
867     fc.pix32.r = ((unsigned int)fc.pix32.r + fc2.pix32.r + fc3.pix32.r) /3;
868     fc.pix32.g = ((unsigned int)fc.pix32.g + fc2.pix32.g + fc3.pix32.g) /3;
869     fc.pix32.b = ((unsigned int)fc.pix32.b + fc2.pix32.b + fc3.pix32.b) /3;
870     if( fog_init )
871     {
872         // init blur
873         fogcolor.pix32 = fc.pix32;
874         fog_init = 0;
875     }
876     else
877     {
878         // blur
879         fogcolor.pix32.r = ((((unsigned int)fogcolor.pix32.r)*31) + fc.pix32.r) >> 5;
880         fogcolor.pix32.g = ((((unsigned int)fogcolor.pix32.g)*31) + fc.pix32.g) >> 5;
881         fogcolor.pix32.b = ((((unsigned int)fogcolor.pix32.b)*31) + fc.pix32.b) >> 5;
882     }
883 
884     count = dc_yh - dc_yl;
885 
886     // Zero length, column does not exceed a pixel.
887     if (count < 0)
888         return;
889 
890 #ifdef RANGECHECK_DRAW_LIMITS
891     // [WDJ] Draw window is actually rdraw_viewwidth and rdraw_viewheight
892     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
893     {
894         I_SoftError("R_DrawFogColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
895         return;
896     }
897 #endif
898 
899     // Framebuffer destination address.
900     // Use ylookup LUT to avoid multiply with ScreenWidth.
901     // Use columnofs LUT for subwindows?
902     dest = ylookup[dc_yl] + columnofs[dc_x];
903 
904     {
905         register unsigned int fb = fogcolor.pix32.b * alpha_d;
906         register unsigned int fg = fogcolor.pix32.g * alpha_d;
907         register unsigned int fr = fogcolor.pix32.r * alpha_d;
908         do
909         {
910             register pixel24_t * p24 = (pixel24_t*)dest;
911             p24->b = ((p24->b * alpha_r) + fb) >> 8;
912             p24->g = ((p24->g * alpha_r) + fg) >> 8;
913             p24->r = ((p24->r * alpha_r) + fr) >> 8;
914             dest += vid.ybytes;
915         }
916         while (count--);
917     }
918 }
919