1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: r_draw8.c 1557 2020-11-17 23:34:31Z wesleyjohnson $
5 //
6 // Copyright (C) 1998-2000 by DooM Legacy Team.
7 // Portions Copyright (C) 2000-2016 by DooM Legacy Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 //
20 // $Log: r_draw8.c,v $
21 // Revision 1.25  2003/07/13 18:04:57  hurdler
22 // Revision 1.24  2003/07/13 13:16:15  hurdler
23 //
24 // Revision 1.23  2003/06/10 23:36:09  ssntails
25 // Variable flat support (32x32 to 2048x2048)
26 //
27 // Revision 1.22  2002/11/12 00:06:05  ssntails
28 // Support for translated translucent columns in software mode.
29 //
30 // Revision 1.21  2002/01/12 02:21:36  stroggonmeth
31 //
32 // Revision 1.20  2001/08/06 23:57:09  stroggonmeth
33 // Removed portal code, improved 3D floors in hardware mode.
34 //
35 // Revision 1.19  2001/04/02 18:54:32  bpereira
36 // Revision 1.18  2001/04/01 17:35:07  bpereira
37 //
38 // Revision 1.17  2001/03/21 18:24:39  stroggonmeth
39 // Misc changes and fixes. Code cleanup
40 //
41 // Revision 1.16  2001/03/13 22:14:20  stroggonmeth
42 // Long time no commit. 3D floors, FraggleScript, portals, ect.
43 //
44 // Revision 1.15  2001/01/25 22:15:44  bpereira
45 // added heretic support
46 //
47 // Revision 1.14  2000/11/21 21:13:18  stroggonmeth
48 // Optimised 3D floors and fixed crashing bug in high resolutions.
49 //
50 // Revision 1.13  2000/11/06 20:52:16  bpereira
51 //
52 // Revision 1.12  2000/11/02 17:50:09  stroggonmeth
53 // Big 3Dfloors & FraggleScript commit!!
54 //
55 // Revision 1.11  2000/09/28 20:57:17  bpereira
56 // Revision 1.10  2000/04/30 10:30:10  bpereira
57 // Revision 1.9  2000/04/24 20:24:38  bpereira
58 // Revision 1.8  2000/04/18 17:39:39  stroggonmeth
59 // Revision 1.7  2000/04/08 17:29:25  stroggonmeth
60 //
61 // Revision 1.6  2000/04/06 21:06:19  stroggonmeth
62 // Optimized extra_colormap code...
63 // Added #ifdefs for older water code.
64 //
65 // Revision 1.5  2000/04/05 15:47:46  stroggonmeth
66 // Added hack for Dehacked lumps. Transparent sprites are now affected by colormaps.
67 //
68 // Revision 1.4  2000/04/04 19:28:43  stroggonmeth
69 // Global colormaps working. Added a new linedef type 272.
70 //
71 // Revision 1.3  2000/04/04 00:32:47  stroggonmeth
72 // Initial Boom compatability plus few misc changes all around.
73 //
74 // Revision 1.2  2000/02/27 00:42:10  hurdler
75 // Revision 1.1.1.1  2000/02/22 20:32:32  hurdler
76 // Initial import into CVS (v1.29 pr3)
77 //
78 //
79 // DESCRIPTION:
80 //      8bpp span/column drawer functions
81 //
82 //  NOTE: no includes because this is included as part of r_draw.c
83 //
84 //-----------------------------------------------------------------------------
85 
86 // [WDJ] Window limit checks have been added to all the callers of colfunc().
87 
88 // [WDJ] Combine the Boom enhancements into our draw functions,
89 // so modifications do not have to be made in two functions.
90 #define USEBOOMFUNC
91 
92 
93 // ==========================================================================
94 // COLUMNS
95 // ==========================================================================
96 
97 //  A column is a vertical slice/span of a wall texture that uses
98 //  a has a constant z depth from top to bottom.
99 //
100 
101 #ifndef USEASM
R_DrawColumn_8(void)102 void R_DrawColumn_8(void)
103 {
104     register int count;
105     register byte *dest;
106     register fixed_t frac;
107     register fixed_t fracstep;
108 
109     count = dc_yh - dc_yl + 1;
110     if (count <= 0)
111         return;  // Zero length, column does not exceed a pixel.
112 
113 #ifdef RANGECHECK_DRAW_LIMITS
114     // [WDJ] Draw window is actually rdraw_viewwidth and rdraw_viewheight
115     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
116     {
117         I_SoftError("R_DrawColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
118         return;
119     }
120 #endif
121 
122     // Framebuffer destination address.
123     // Use ylookup LUT to avoid multiply with ScreenWidth.
124     // Use columnofs LUT for subwindows?
125     dest = ylookup[dc_yl] + columnofs[dc_x];
126 
127     // Determine scaling,
128     //  which is the only mapping to be done.
129     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.
135 #ifdef USEBOOMFUNC
136     // Do two pixels per loop when possible.
137     {
138         register const byte *source = dc_source;
139         register const lighttable_t *colormap = dc_colormap;
140         register int heightmask = dc_texheight - 1;
141         if (dc_texheight & heightmask)
142         {
143             heightmask++;
144             heightmask <<= FRACBITS;
145 
146             if (frac < 0)
147                 while ((frac += heightmask) < 0);
148             else
149                 while (frac >= heightmask)
150                     frac -= heightmask;
151 
152             do
153             {
154                 // Re-map color indices from wall texture column
155                 //  using a lighting/special effects LUT.
156                 // heightmask is the Tutti-Frutti fix -- killough
157 
158                 *dest = colormap[source[frac >> FRACBITS]];
159                 dest += vid.ybytes;
160                 if ((frac += fracstep) >= heightmask)
161                     frac -= heightmask;
162             }
163             while (--count);
164         }
165         else
166         {
167             while ((count -= 2) >= 0)   // texture height is a power of 2 -- killough
168             {
169                 *dest = colormap[source[(frac >> FRACBITS) & heightmask]];
170                 dest += vid.ybytes;
171                 frac += fracstep;
172                 *dest = colormap[source[(frac >> FRACBITS) & heightmask]];
173                 dest += vid.ybytes;
174                 frac += fracstep;
175             }
176             if (count & 1)
177                 *dest = colormap[source[(frac >> FRACBITS) & heightmask]];
178         }
179     }
180 #else
181     // Simple loop.  Fixed tile 128.
182     do
183     {
184         // Re-map color indices from wall texture column
185         //  using a lighting/special effects LUT.
186         *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]];
187 
188         dest += vid.ybytes;
189         frac += fracstep;
190 
191     }
192     while (--count);
193 #endif
194 }
195 #endif
196 
197 
198 #ifndef USEASM
R_DrawSkyColumn_8(void)199 void R_DrawSkyColumn_8(void)
200 {
201     register int count;
202     register byte *dest;
203     register fixed_t frac;
204     register fixed_t fracstep;
205 
206 #ifdef USEBOOMFUNC
207     count = dc_yh - dc_yl + 1;
208     if (count <= 0)
209         return;  // Zero length, column does not exceed a pixel.
210     // while(--count)
211 #else
212     count = dc_yh - dc_yl;
213     if (count < 0)
214         return;  // Zero length, column does not exceed a pixel.
215     // while(count--)
216 #endif
217 
218 #ifdef RANGECHECK_DRAW_LIMITS
219     // [WDJ] Draw window is actually rdraw_viewwidth and rdraw_viewheight
220     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
221     {
222         I_SoftError("R_DrawSkyColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
223         return;
224     }
225 #endif
226 
227     // Framebuffer destination address.
228     // Use ylookup LUT to avoid multiply with ScreenWidth.
229     // Use columnofs LUT for subwindows?
230     dest = ylookup[dc_yl] + columnofs[dc_x];
231 
232     // Determine scaling,
233     //  which is the only mapping to be done.
234     fracstep = dc_iscale;
235     frac = dc_texturemid + (dc_yl - centery) * fracstep;
236 
237     // Inner loop that does the actual texture mapping,
238     //  e.g. a DDA-lile scaling.
239     // This is as fast as it gets.
240 
241     // [WDJ] FIXME: heightmask=255 is wrong, height is 128 or 240.  Looking up, this could segfault.
242 #ifdef USEBOOMFUNC
243     // Do two pixels per loop when possible.
244     {
245         register const byte *source = dc_source;
246         register const lighttable_t *colormap = dc_colormap;
247         register int heightmask = 255;
248         if (dc_texheight & heightmask)
249         {
250             heightmask++;
251             heightmask <<= FRACBITS;
252 
253             if (frac < 0)
254                 while ((frac += heightmask) < 0);
255             else
256                 while (frac >= heightmask)
257                     frac -= heightmask;
258 
259             do
260             {
261                 // Re-map color indices from wall texture column
262                 //  using a lighting/special effects LUT.
263                 // heightmask is the Tutti-Frutti fix -- killough
264 
265                 *dest = colormap[source[frac >> FRACBITS]];
266                 dest += vid.ybytes;
267                 if ((frac += fracstep) >= heightmask)
268                     frac -= heightmask;
269             }
270             while (--count);
271         }
272         else
273         {
274             while ((count -= 2) >= 0)   // texture height is a power of 2 -- killough
275             {
276                 *dest = colormap[source[(frac >> FRACBITS) & heightmask]];
277                 dest += vid.ybytes;
278                 frac += fracstep;
279                 *dest = colormap[source[(frac >> FRACBITS) & heightmask]];
280                 dest += vid.ybytes;
281                 frac += fracstep;
282             }
283             if (count & 1)
284                 *dest = colormap[source[(frac >> FRACBITS) & heightmask]];
285         }
286     }
287 #else
288     // Simple loop.  Fixed tile 256.
289     do
290     {
291         // Re-map color indices from wall texture column
292         //  using a lighting/special effects LUT.
293         *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 255]];
294 
295         dest += vid.ybytes;
296         frac += fracstep;
297 
298     }
299     while (count--);
300 #endif
301 }
302 #endif
303 
304 //  The standard Doom 'fuzzy' (blur, shadow) effect
305 //  originally used for spectres and when picking up the blur sphere
306 //
307 //#ifndef USEASM // NOT IN ASSEMBLER, TO DO.. IF WORTH IT
R_DrawFuzzColumn_8(void)308 void R_DrawFuzzColumn_8(void)
309 {
310     register int count;
311     register byte *dest;
312     register fixed_t frac;
313     register fixed_t fracstep;
314 
315     // Adjust borders. Low...
316     if (dc_yl <= 0)
317         dc_yl = 1;
318 
319     // .. and high.
320     if (dc_yh >= rdraw_viewheight - 1)
321         dc_yh = rdraw_viewheight - 2;
322 
323     count = dc_yh - dc_yl;
324     if (count < 0)
325         return;  // Zero length, column does not exceed a pixel.
326     // while(count--)
327 
328 #ifdef RANGECHECK_DRAW_LIMITS
329     // [WDJ] Draw window is actually rdraw_viewwidth and rdraw_viewheight
330     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
331     {
332         I_SoftError("R_DrawFuzzColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
333         return;
334     }
335 #endif
336 
337     // Does not work with blocky mode.
338     dest = ylookup[dc_yl] + columnofs[dc_x];
339 
340     // Looks familiar.
341     fracstep = dc_iscale;
342     frac = dc_texturemid + (dc_yl - centery) * fracstep;
343 
344     do
345     {
346         // Lookup framebuffer, and retrieve a pixel that is either one column
347         //  left or right of the current one.
348         // Add index from colormap to index.
349         // Remap existing dest, modify position, dim through LIGHTTABLE[6].
350 //        *dest = reg_colormaps[6 * 256 + dest[fuzzoffset[fuzzpos]]];
351         *dest = reg_colormaps[LIGHTTABLE(6) + dest[fuzzoffset[fuzzpos]]];
352 
353         // Clamp table lookup index.
354         if (++fuzzpos == FUZZTABLE)
355             fuzzpos = 0;
356 
357         dest += vid.ybytes;
358 
359         frac += fracstep;
360     }
361     while (count--);
362 }
363 
364 //#endif
365 
366 #ifndef USEASM
367 // used in tiltview, but never called for now, but who know...
R_DrawSpanNoWrap(void)368 void R_DrawSpanNoWrap(void)
369 {
370 }
371 #endif
372 
373 #ifndef USEASM
R_DrawShadeColumn_8(void)374 void R_DrawShadeColumn_8(void)
375 {
376     register int count;
377     register byte *dest;
378     register fixed_t frac;
379     register fixed_t fracstep;
380 
381     // [WDJ] This check has been added to all the callers of colfunc().
382     // check out coords for src*
383 //    if ((dc_yl < 0) || (dc_x >= vid.width))
384 //        return;
385 
386     count = dc_yh - dc_yl;
387     if (count < 0)
388         return;
389 
390 #ifdef RANGECHECK_DRAW_LIMITS
391     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
392     {
393         I_SoftError("R_DrawShadeColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
394         return;
395     }
396 #endif
397 
398     // FIXME. As above.
399     //src  = ylookup[dc_yl] + columnofs[dc_x+2];
400     dest = ylookup[dc_yl] + columnofs[dc_x];
401 
402     // Looks familiar.
403     fracstep = dc_iscale;
404     frac = dc_texturemid + (dc_yl - centery) * fracstep;
405 
406     // Here we do an additional index re-mapping.
407     do
408     {
409         // apply shading/translucent with existing showing through
410         // Remap the existing dest color, dimming it through source LIGHTTABLE.
411 //        *dest = *(reg_colormaps + (dc_source[frac >> FRACBITS] << 8) + (*dest));
412         *dest = reg_colormaps[ LIGHTTABLE(dc_source[frac >> FRACBITS]) + (*dest) ];
413 
414         dest += vid.ybytes;
415         frac += fracstep;
416     }
417     while (count--);
418 }
419 #endif
420 
421 #ifdef ENABLE_DRAW_ALPHA
422 # ifndef ENABLE_DRAW8_USING_12
423 // switch at TRANSLU_REV_ALPHA
424 byte  dr8_src_shift[16]  = { 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0 };
425 byte  dr8_dest_shift[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8 };
426 # endif
427 
R_DrawAlphaColumn_8(void)428 void R_DrawAlphaColumn_8(void)
429 {
430     register int count;
431     register byte *dest;
432     register fixed_t frac;
433     register fixed_t fracstep;
434     register unsigned int  alpha;
435 #ifdef ENABLE_DRAW8_USING_12
436     register unsigned int  alpha_r;
437 #endif
438 
439     // [WDJ] Source check has been added to all the callers of colfunc().
440 
441     count = dc_yh - dc_yl;
442     if (count < 0)
443         return;
444 
445 #ifdef RANGECHECK_DRAW_LIMITS
446     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
447     {
448         I_SoftError("R_DrawAlphaColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
449         return;
450     }
451 #endif
452 
453     dest = ylookup[dc_yl] + columnofs[dc_x];
454 
455     // Looks familiar.
456     fracstep = dc_iscale;
457     frac = dc_texturemid + (dc_yl - centery) * fracstep;
458 
459     // Colormap the dr_color at the source.
460 
461 #ifdef ENABLE_DRAW8_USING_12
462   switch( dr_alpha_mode )
463   {
464    case 0: // Alpha blend
465     do
466     {
467         // [WDJ] The source is a patch of alpha values, 0..255.
468         alpha = ((dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) + 0x0080) >> 8;  // alpha 0..255
469         if( alpha > 14 )
470         {
471             unsigned int alpha_r = 255 - alpha;
472 
473             // Calculate transparency using RGBA
474             register RGBA_t p = pLocalPalette[*dest];
475             register unsigned int p12 = // 12 bit r,g,b color
476               (((((unsigned int)p.s.blue * alpha_r) + ((unsigned int)dr_color.s.blue * alpha)   + 0x0080) >> (8+4-0)) & 0x000F)
477             | (((((unsigned int)p.s.green * alpha_r) + ((unsigned int)dr_color.s.green * alpha) + 0x0080) >> (8+4-4)) & 0x00F0)
478             | (((((unsigned int)p.s.red * alpha_r) + ((unsigned int)dr_color.s.red * alpha)     + 0x0080) >> (8+4-8)) & 0x0F00);
479            *dest = color12_to_8[p12];  // lookup palette
480         }
481         dest += vid.ybytes;
482         frac += fracstep;
483     }
484     while (count--);
485     break;
486 
487    case 1: // Alpha blend with constant background alpha.
488     // Caller must set dr_alpha_background at (255 - dr_alpha) or less.
489     alpha_r = dr_alpha_background;
490     do
491     {
492         // [WDJ] The source is a patch of alpha values, 0..255.
493         alpha = ((dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) + 0x0080) >> 8;  // alpha 0..255
494         if( alpha > 14 )
495         {
496             // Calculate transparency using RGBA
497             register RGBA_t p = pLocalPalette[*dest];
498             register unsigned int p12 = // 12 bit r,g,b color
499               (((((unsigned int)p.s.blue * alpha_r) + ((unsigned int)dr_color.s.blue * alpha)   + 0x0080) >> (8+4-0)) & 0x000F)
500             | (((((unsigned int)p.s.green * alpha_r) + ((unsigned int)dr_color.s.green * alpha) + 0x0080) >> (8+4-4)) & 0x00F0)
501             | (((((unsigned int)p.s.red * alpha_r) + ((unsigned int)dr_color.s.red * alpha)     + 0x0080) >> (8+4-8)) & 0x0F00);
502            *dest = color12_to_8[p12];  // lookup palette
503         }
504         dest += vid.ybytes;
505         frac += fracstep;
506     }
507     while (count--);
508     break;
509 
510    case 2: // Additive alpha
511     do
512     {
513         // [WDJ] The source is a patch of alpha values, 0..255.
514         alpha = ((dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) + 0x0080) >> 8;  // alpha 0..255
515         if( alpha > 14 )
516         {
517             // Calculate transparency using RGBA
518             register RGBA_t p = pLocalPalette[*dest];
519             unsigned int r,g,b;
520             // (0xFF * 0xFF * 0xFF) = 0xFD02FF
521             b = p.s.blue;
522             b += ((((unsigned int)dr_color.s.blue  * alpha * (255 - b)) + 0x8000) >> 16);
523             g = p.s.green;
524             g += ((((unsigned int)dr_color.s.green * alpha * (255 - g)) + 0x8000) >> 16);
525             r = p.s.red;
526             r += ((((unsigned int)dr_color.s.red   * alpha * (255 - r)) + 0x8000) >> 16);
527 
528             register unsigned int p12 = // 12 bit r,g,b color
529               ((b & 0xF0) >> 4) | (g & 0xF0) | ((r & 0xF0) << 4);
530            *dest = color12_to_8[p12];  // lookup palette
531         }
532         dest += vid.ybytes;
533         frac += fracstep;
534     }
535     while (count--);
536     break;
537 
538    case 3: // Additive alpha, with background alpha
539     alpha_r = dr_alpha_background;
540     do
541     {
542         // [WDJ] The source is a patch of alpha values, 0..255.
543         alpha = ((dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) + 0x0080) >> 8;  // alpha 0..255
544         if( alpha > 14 )
545         {
546             // Calculate transparency using RGBA
547             register RGBA_t p = pLocalPalette[*dest];
548             unsigned int r,g,b;
549             // (0xFF * 0xFF * 0xFF) = 0xFD02FF
550             b = (p.s.blue * alpha_r)>>8;
551             b += ((((unsigned int)dr_color.s.blue  * alpha * (255 - b)) + 0x8000) >> 16);
552             g = (p.s.green * alpha_r)>>8;
553             g += ((((unsigned int)dr_color.s.green * alpha * (255 - g)) + 0x8000) >> 16);
554             r = (p.s.red * alpha_r)>>8;
555             r += ((((unsigned int)dr_color.s.red   * alpha * (255 - r)) + 0x8000) >> 16);
556 
557             register unsigned int p12 = // 12 bit r,g,b color
558               ((b & 0xF0) >> 4) | (g & 0xF0) | ((r & 0xF0) << 4);
559            *dest = color12_to_8[p12];  // lookup palette
560         }
561         dest += vid.ybytes;
562         frac += fracstep;
563     }
564     while (count--);
565     break;
566 
567    case 4: // Additive alpha, limit math
568     do
569     {
570         // [WDJ] The source is a patch of alpha values, 0..255.
571         alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
572         if( alpha > 14 )
573         {
574             // Calculate transparency using RGBA
575             register RGBA_t p = pLocalPalette[*dest];
576             unsigned int r,g,b;
577             b = ((((unsigned int)dr_color.s.blue  * alpha ) + 0x0080) >> 8) + p.s.blue;
578             if(b > 255)  b = 255;
579             g = ((((unsigned int)dr_color.s.green * alpha ) + 0x0080) >> 8) + p.s.green;
580             if(g > 255)  g = 255;
581             r = ((((unsigned int)dr_color.s.red   * alpha ) + 0x0080) >> 8) + p.s.red;
582             if(r > 255)  r = 255;
583 
584             register unsigned int p12 = // 12 bit r,g,b color
585               ((b & 0xF0) >> 4) | (g & 0xF0) | ((r & 0xF0) << 4);
586            *dest = color12_to_8[p12];  // lookup palette
587         }
588         dest += vid.ybytes;
589         frac += fracstep;
590     }
591     while (count--);
592     break;
593   }
594 #else
595     // Without ENABLE_DRAW8_USING_12 there is only a coarse table lookup.
596     do
597     {
598         // Apply the dr_color, using the patch as alpha.
599         // Colormap the dr_color at the source.
600         alpha = ((dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha)) >> 12;  // alpha 0..16
601 
602         // Select a transparent table to do alpha
603         dc_translucentmap = & translucenttables[ translucent_alpha_table[ alpha ] ];
604 //        *dest = reg_colormaps[ dc_translucentmap[ (dr_color8 << dr8_src_shift[alpha]) + ((*dest) << dr8_src_shift[alpha]) ]];
605         *dest = dc_translucentmap[ (dr_color8 << dr8_src_shift[alpha]) + ((*dest) << dr8_src_shift[alpha]) ];
606 
607         dest += vid.ybytes;
608         frac += fracstep;
609     }
610     while (count--);
611 #endif
612 
613 }
614 #endif
615 
616 //
617 // I've made an asm routine for the transparency, because it slows down
618 // a lot in 640x480 with big sprites (bfg on all screen, or transparent
619 // walls on fullscreen)
620 //
621 // [WDJ] asm does not have latest changes
622 #ifndef USEASM
R_DrawTranslucentColumn_8(void)623 void R_DrawTranslucentColumn_8(void)
624 {
625     register int count;
626     register byte *dest;
627     register fixed_t frac;
628     register fixed_t fracstep;
629 
630     // [WDJ] This check has been added to all the callers of colfunc().
631     // check out coords for src*
632 //    if ((dc_yl < 0) || (dc_x >= vid.width))
633 //        return;
634 
635 #ifdef USEBOOMFUNC
636     count = dc_yh - dc_yl + 1;
637     if (count <= 0)
638         return;  // Zero length, column does not exceed a pixel.
639 #else
640     count = dc_yh - dc_yl;
641     if (count < 0)
642         return;  // Zero length, column does not exceed a pixel.
643 #endif
644 
645 #ifdef RANGECHECK_DRAW_LIMITS
646     // [WDJ] Draw window is actually rdraw_viewwidth and rdraw_viewheight
647     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
648     {
649         I_SoftError("R_DrawTranslucentColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
650         return;
651     }
652 #endif
653     // FIXME. As above.
654     //src  = ylookup[dc_yl] + columnofs[dc_x+2];
655 
656     // Framebuffer destination address.
657     // Use ylookup LUT to avoid multiply with ScreenWidth.
658     // Use columnofs LUT for subwindows?
659     dest = ylookup[dc_yl] + columnofs[dc_x];
660 
661     // Determine scaling, which is the only mapping to be done.
662     fracstep = dc_iscale;
663     frac = dc_texturemid + (dc_yl - centery) * fracstep;
664 
665 #ifdef USEBOOMFUNC
666     // Do two pixels per loop when possible.
667     {
668         register const byte *source = dc_source;
669         register int heightmask = dc_texheight - 1;
670         if (dc_texheight & heightmask)
671         {
672             heightmask++;
673             heightmask <<= FRACBITS;
674 
675             if (frac < 0)
676                 while ((frac += heightmask) < 0);
677             else
678                 while (frac >= heightmask)
679                     frac -= heightmask;
680 
681             if( dr_alpha < TRANSLU_REV_ALPHA )
682             {
683               do
684               {
685                 // Re-map color indices from wall texture column
686                 //  using a lighting/special effects LUT.
687                 // heightmask is the Tutti-Frutti fix -- killough
688 
689                 *dest = dc_colormap[ dc_translucentmap[ (source[frac >> FRACBITS] << 8) + (*dest) ]];
690                 dest += vid.ybytes;
691                 if ((frac += fracstep) >= heightmask)
692                     frac -= heightmask;
693               }
694               while (--count);
695             }
696             else
697             {
698               do
699               {
700                 // alpha >= TRANSLU_REV_ALPHA, reversed translucent table usage
701                 *dest = dc_colormap[ dc_translucentmap[ (source[frac >> FRACBITS]) + ((*dest)<<8) ]];
702                 dest += vid.ybytes;
703                 if ((frac += fracstep) >= heightmask)
704                     frac -= heightmask;
705               }
706               while (--count);
707             }
708         }
709         else
710         {
711           if( dr_alpha < TRANSLU_REV_ALPHA )
712           {
713             while ((count -= 2) >= 0)   // texture height is a power of 2 -- killough
714             {
715                 *dest = dc_colormap[ dc_translucentmap[ (source[frac >> FRACBITS] << 8) + (*dest) ]];
716                 dest += vid.ybytes;
717                 frac += fracstep;
718                 *dest = dc_colormap[ dc_translucentmap[ (source[frac >> FRACBITS] << 8) + (*dest) ]];
719                 dest += vid.ybytes;
720                 frac += fracstep;
721             }
722             if (count & 1)
723                 *dest = dc_colormap[ dc_translucentmap[ (source[frac >> FRACBITS] << 8) + (*dest) ]];
724           }
725           else
726           {
727             while ((count -= 2) >= 0)   // texture height is a power of 2 -- killough
728             {
729                 // alpha >= TRANSLU_REV_ALPHA, reversed translucent table usage
730                 *dest = dc_colormap[ dc_translucentmap[ (source[frac >> FRACBITS]) + ((*dest)<<8) ]];
731                 dest += vid.ybytes;
732                 frac += fracstep;
733                 *dest = dc_colormap[ dc_translucentmap[ (source[frac >> FRACBITS]) + ((*dest)<<8) ]];
734                 dest += vid.ybytes;
735                 frac += fracstep;
736             }
737             if (count & 1)
738                 *dest = dc_colormap[ dc_translucentmap[ (source[frac >> FRACBITS]) + ((*dest)<<8) ]];
739           }
740         }
741     }
742 #else
743     // Simple loops.  No Tile.
744     if( dr_alpha < TRANSLU_REV_ALPHA )
745     {
746       // Here we do an additional index re-mapping.
747       do
748       {
749         *dest = dc_colormap[ dc_translucentmap[ (dc_source[frac >> FRACBITS] << 8) + (*dest) ]];
750         dest += vid.ybytes;
751         frac += fracstep;
752       }
753       while (count--);
754     }
755     else
756     {
757       do
758       {
759         // alpha >= TRANSLU_REV_ALPHA, reversed translucent table usage
760         *dest = dc_colormap[ dc_translucentmap[ (dc_source[frac >> FRACBITS]) + ((*dest) << 8) ]];
761         dest += vid.ybytes;
762         frac += fracstep;
763       }
764       while (count--);
765     }
766 #endif
767 }
768 #endif
769 
770 // New spiffy function.
771 // Not only does it colormap a sprite,
772 // but does translucency as well.
773 // SSNTails 11-11-2002
774 // Uber-kudos to Cyan Helkaraxe for
775 // helping me get the brain juices flowing!
776 // Called with TRANSLU_hi or TRANSLU_more, or arbitrary by thing TRANSMASK
R_DrawTranslatedTranslucentColumn_8(void)777 void R_DrawTranslatedTranslucentColumn_8(void)
778 {
779     register int count;
780     register fixed_t frac;
781     register fixed_t fracstep;
782     register byte *dest;
783 
784     count = dc_yh - dc_yl + 1;
785 
786     if (count <= 0)     // Zero length, column does not exceed a pixel.
787         return;
788 
789     // FIXME. As above.
790     //src  = ylookup[dc_yl] + columnofs[dc_x+2];
791     dest = ylookup[dc_yl] + columnofs[dc_x];
792 
793     // Looks familiar.
794     fracstep = dc_iscale;
795     frac = dc_texturemid + (dc_yl - centery) * fracstep;
796 
797     // Inner loop that does the actual texture mapping,
798     //  e.g. a DDA-lile scaling.
799     // This is as fast as it gets.
800 
801     {
802         //register const byte *source = dc_source;
803         register int heightmask = dc_texheight - 1;
804         if (dc_texheight & heightmask)
805         {
806             heightmask++;
807             heightmask <<= FRACBITS;
808 
809             if (frac < 0)
810                 while ((frac += heightmask) < 0);
811             else
812             {
813                 while (frac >= heightmask)
814                     frac -= heightmask;
815             }
816 
817             if( dr_alpha < TRANSLU_REV_ALPHA )
818             {
819               do
820               {
821                 // Re-map color indices from wall texture column
822                 //  using a lighting/special effects LUT.
823                 // heightmask is the Tutti-Frutti fix -- killough
824                 *dest = dc_colormap[ dc_translucentmap[ (dc_colormap[dc_skintran[dc_source[frac >> FRACBITS]]] << 8) + (*dest) ]];
825                 dest += vid.ybytes;
826                 if ((frac += fracstep) >= heightmask)
827                     frac -= heightmask;
828               }
829               while (--count);
830             }
831             else
832             {
833               do
834               {
835                 // alpha >= TRANSLU_REV_ALPHA, reversed translucent table usage
836                 *dest = dc_colormap[ dc_translucentmap[ (dc_colormap[dc_skintran[dc_source[frac >> FRACBITS]]]) + ((*dest)<<8) ]];
837                 dest += vid.ybytes;
838                 if ((frac += fracstep) >= heightmask)
839                     frac -= heightmask;
840               }
841               while (--count);
842             }
843         }
844         else
845         {
846           if( dr_alpha < TRANSLU_REV_ALPHA )
847           {
848             while ((count -= 2) >= 0)   // texture height is a power of 2 -- killough
849             {
850                 *dest = dc_colormap[ dc_translucentmap[ (dc_colormap[dc_skintran[dc_source[frac >> FRACBITS]]] << 8) + (*dest) ]];
851                 dest += vid.ybytes;
852                 frac += fracstep;
853                 *dest = dc_colormap[ dc_translucentmap[ (dc_colormap[dc_skintran[dc_source[frac >> FRACBITS]]] << 8) + (*dest) ]];
854                 dest += vid.ybytes;
855                 frac += fracstep;
856             }
857             if (count & 1)
858             {
859                 *dest = dc_colormap[ dc_translucentmap[ (dc_colormap[dc_skintran[dc_source[frac >> FRACBITS]]] << 8) + (*dest) ]];
860             }
861           }
862           else
863           {
864             while ((count -= 2) >= 0)   // texture height is a power of 2 -- killough
865             {
866                 // alpha >= TRANSLU_REV_ALPHA, reversed translucent table usage
867                 *dest = dc_colormap[ dc_translucentmap[ (dc_colormap[dc_skintran[dc_source[frac >> FRACBITS]]]) + ((*dest)<<8) ]];
868                 dest += vid.ybytes;
869                 frac += fracstep;
870                 *dest = dc_colormap[ dc_translucentmap[ (dc_colormap[dc_skintran[dc_source[frac >> FRACBITS]]]) + ((*dest)<<8) ]];
871                 dest += vid.ybytes;
872                 frac += fracstep;
873             }
874             if (count & 1)
875             {
876                 *dest = dc_colormap[ dc_translucentmap[ (dc_colormap[dc_skintran[dc_source[frac >> FRACBITS]]]) + ((*dest)<<8) ]];
877             }
878           }
879         }
880     }
881 }
882 
883 //
884 //  Draw columns upto 128high but remap the green ramp to other colors
885 //
886 //#ifndef USEASM        // STILL NOT IN ASM, TO DO..
R_DrawTranslatedColumn_8(void)887 void R_DrawTranslatedColumn_8(void)
888 {
889     register int count;
890     register byte *dest;
891     register fixed_t frac;
892     register fixed_t fracstep;
893 
894     count = dc_yh - dc_yl;
895     if (count < 0)
896         return;
897 
898 #ifdef RANGECHECK_DRAW_LIMITS
899     // [WDJ] Draw window is actually rdraw_viewwidth and rdraw_viewheight
900     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
901     {
902         I_SoftError("R_DrawTranslatedColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
903         return;
904     }
905 #endif
906 
907     // FIXME. As above.
908     dest = ylookup[dc_yl] + columnofs[dc_x];
909 
910     // Looks familiar.
911     fracstep = dc_iscale;
912     frac = dc_texturemid + (dc_yl - centery) * fracstep;
913 
914     // Here we do an additional index re-mapping.
915     do
916     {
917         // Skin Translation tables are used
918         //  to map certain colorramps to other ones,
919         //  used with PLAYER sprites.
920         // Thus the "green" ramp of the player 0 sprite
921         //  is mapped to gray, red, black/indigo.
922         *dest = dc_colormap[dc_skintran[dc_source[frac >> FRACBITS]]];
923 
924         dest += vid.ybytes;
925 
926         frac += fracstep;
927     }
928     while (count--);
929 }
930 
931 //#endif
932 
933 // ==========================================================================
934 // SPANS
935 // ==========================================================================
936 
937 //  Draws the actual span.
938 //
939 //#ifndef USEASM //Hurdler: in tmap.nas the old func is now called R_DrawSpan_8a
940 // [WDJ] Boom func modified several times
R_DrawSpan_8(void)941 void R_DrawSpan_8(void)
942 {
943     // [WDJ] was ULONG=32bit, use uint_fast32_t which can exceed 32bit in size.
944     register uint_fast32_t  xfrac;
945     register uint_fast32_t  yfrac;
946     register byte *dest;
947     register int count;
948 
949 #ifdef RANGECHECK_DRAW_LIMITS
950     if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= rdraw_viewwidth || (unsigned) ds_y > rdraw_viewheight)
951     {
952         I_SoftError("R_DrawSpan: %i to %i at %i\n", ds_x1, ds_x2, ds_y);
953         return;
954     }
955 #endif
956 
957     xfrac = ds_xfrac & flat_imask;
958     yfrac = ds_yfrac;
959 
960     dest = ylookup[ds_y] + columnofs[ds_x1];
961 
962     // We do not check for zero spans here?
963     count = ds_x2 - ds_x1;
964 
965      // [WDJ] note:  prboom has while(count)
966     do
967     {
968         // Lookup pixel from flat texture tile,
969         //  re-index using light/colormap.
970         *dest = ds_colormap[ds_source[((yfrac >> flatfracbits) & (flat_ymask)) | (xfrac >> FRACBITS)]];
971         dest++;
972 
973         // Next step in u,v.
974         xfrac += ds_xstep;
975         yfrac += ds_ystep;
976         xfrac &= flat_imask;
977     }
978     while (count--);
979 }
980 //#endif USESASM
981 
R_DrawTranslucentSpan_8(void)982 void R_DrawTranslucentSpan_8(void)
983 {
984     fixed_t xfrac, yfrac;
985     fixed_t xstep, ystep;
986     byte *dest;
987     int count;
988 
989 #ifdef RANGECHECK_DRAW_LIMITS
990     if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= rdraw_viewwidth || (unsigned) ds_y > rdraw_viewheight)
991     {
992         I_SoftError("R_DrawTranslucentSpan: %i to %i at %i\n", ds_x1, ds_x2, ds_y);
993         return;
994     }
995 #endif
996 
997     xfrac = ds_xfrac & flat_imask;
998     yfrac = ds_yfrac;
999 
1000     dest = ylookup[ds_y] + columnofs[ds_x1];
1001 
1002     // We do not check for zero spans here?
1003     count = ds_x2 - ds_x1 + 1;
1004 
1005     xstep = ds_xstep;
1006     ystep = ds_ystep;
1007 
1008     if( dr_alpha < TRANSLU_REV_ALPHA )
1009     {
1010       do
1011       {
1012         // Current texture index in u,v.
1013 
1014         // Awesome! 256x256 flats!
1015 //              spot = ((yfrac>>(FRACBITS-8))&(0xff00)) + (xfrac>>(FRACBITS));
1016 
1017         // Lookup pixel from flat texture tile,
1018         //  re-index using light/colormap.
1019         //      *dest++ = ds_colormap[ds_source[spot]];
1020 //              *dest++ = ds_colormap[*(ds_translucentmap + (ds_source[spot] << 8) + (*dest))];
1021         *dest = ds_colormap[ ds_translucentmap[ (ds_source[((yfrac >> flatfracbits) & (flat_ymask)) | (xfrac >> FRACBITS)] << 8) + (*dest) ]];
1022         dest++;	// [WDJ] warning: undetermined order when combined with above
1023 
1024         // Next step in u,v.
1025         xfrac += xstep;
1026         yfrac += ystep;
1027         xfrac &= flat_imask;
1028       }
1029       while (--count);
1030     }
1031     else
1032     {
1033       do
1034       {
1035         // alpha >= TRANSLU_REV_ALPHA, reversed translucent table usage
1036         *dest = ds_colormap[ ds_translucentmap[ (ds_source[((yfrac >> flatfracbits) & (flat_ymask)) | (xfrac >> FRACBITS)]) + ((*dest)<<8) ]];
1037         dest++;	// [WDJ] warning: undetermined order when combined with above
1038         // Next step in u,v.
1039         xfrac += xstep;
1040         yfrac += ystep;
1041         xfrac &= flat_imask;
1042       }
1043       while (--count);
1044     }
1045     /*
1046        register unsigned position;
1047        unsigned step;
1048 
1049        byte *source;
1050        byte *colormap;
1051        byte *transmap;
1052        byte *dest;
1053 
1054        unsigned count;
1055        unsigned spot;
1056        unsigned xtemp;
1057        unsigned ytemp;
1058 
1059        position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff);
1060        step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff);
1061 
1062        source = ds_source;
1063        colormap = ds_colormap;
1064        transmap = ds_translucentmap;
1065        dest = ylookup[ds_y] + columnofs[ds_x1];
1066        count = ds_x2 - ds_x1 + 1;
1067 
1068        while (count >= 4)
1069        {
1070        ytemp = position>>4;
1071        ytemp = ytemp & 0xff00;
1072        xtemp = position>>26;
1073        spot = xtemp | ytemp;
1074        position += step;
1075        dest[0] = colormap[*(transmap + (source[spot] << 8) + (dest[0]))];
1076 
1077        ytemp = position>>4;
1078        ytemp = ytemp & 0xff00;
1079        xtemp = position>>26;
1080        spot = xtemp | ytemp;
1081        position += step;
1082        dest[1] = colormap[*(transmap + (source[spot] << 8) + (dest[1]))];
1083 
1084        ytemp = position>>4;
1085        ytemp = ytemp & 0xff00;
1086        xtemp = position>>26;
1087        spot = xtemp | ytemp;
1088        position += step;
1089        dest[2] = colormap[*(transmap + (source[spot] << 8) + (dest[2]))];
1090 
1091        ytemp = position>>4;
1092        ytemp = ytemp & 0xff00;
1093        xtemp = position>>26;
1094        spot = xtemp | ytemp;
1095        position += step;
1096        dest[3] = colormap[*(transmap + (source[spot] << 8) + (dest[3]))];
1097 
1098        dest += 4;
1099        count -= 4;
1100        }
1101 
1102        while (count--)
1103        {
1104        ytemp = position>>4;
1105        ytemp = ytemp & 0xff00;
1106        xtemp = position>>26;
1107        spot = xtemp | ytemp;
1108        position += step;
1109        *dest++ = colormap[*(transmap + (source[spot] << 8) + (*dest))];
1110        //count--;
1111        }
1112      */
1113 }
1114 
1115 // blend of four translucents to imitate alpha translucent
1116 static byte  fog_tran_table[16][4] = {
1117  { TRANSLU_hi, TRANSLU_hi, TRANSLU_hi, TRANSLU_hi },  // 10%
1118  { TRANSLU_hi, TRANSLU_hi, TRANSLU_hi, TRANSLU_hi },  // 10%
1119  { TRANSLU_more, TRANSLU_hi, TRANSLU_hi, TRANSLU_hi },  // 12.5%
1120  { TRANSLU_more, TRANSLU_hi, TRANSLU_more, TRANSLU_hi },  // 15%
1121  { TRANSLU_more, TRANSLU_more, TRANSLU_more, TRANSLU_hi },  // 17.5%
1122  { TRANSLU_more, TRANSLU_more, TRANSLU_more, TRANSLU_more },  // 20%
1123 //   { TRANSLU_med, TRANSLU_hi, TRANSLU_hi, TRANSLU_hi },  // 20%
1124  { TRANSLU_med, TRANSLU_hi, TRANSLU_more, TRANSLU_hi },  // 22.5%
1125  { TRANSLU_med, TRANSLU_hi, TRANSLU_more, TRANSLU_hi },  // 22.5%
1126  { TRANSLU_med, TRANSLU_hi, TRANSLU_med, TRANSLU_hi },  // 30%
1127  { TRANSLU_med, TRANSLU_more, TRANSLU_med, TRANSLU_hi },  // 32.5%
1128  { TRANSLU_med, TRANSLU_more, TRANSLU_med, TRANSLU_more },  // 35%
1129  { TRANSLU_med, TRANSLU_more, TRANSLU_med, TRANSLU_more },  // 35%
1130  { TRANSLU_med, TRANSLU_med, TRANSLU_med, TRANSLU_hi },  // 40%
1131  { TRANSLU_med, TRANSLU_med, TRANSLU_med, TRANSLU_more },  // 42.5%
1132  { TRANSLU_med, TRANSLU_med, TRANSLU_med, TRANSLU_more },  // 42.5%
1133  { TRANSLU_med, TRANSLU_med, TRANSLU_med, TRANSLU_med },  // 50%
1134 };
1135 
1136 static byte fogstir = 0;
1137 
R_DrawFogSpan_8(void)1138 void R_DrawFogSpan_8(void)
1139 {
1140     uint16_t fogcolor = ds_colormap[ ds_source[fog_index] ];  // to allow shift by 8
1141     byte alpha16;
1142     int count, count4;
1143     byte * ftranslucent[4];
1144     byte *dest;
1145 
1146     alpha16 = dr_alpha >> 3;  // dr_alpha 0..255 => 0..31
1147     if( alpha16 > 15 )
1148     {
1149         if( alpha16 > 31 )  alpha16 = 31;
1150         alpha16 = 31 - alpha16; // high alpha reverse trans
1151     }
1152     fogstir ++;
1153     for( count = 0; count < 4; count++ )
1154     {
1155         byte fogtran = fog_tran_table[ alpha16 ][ (count+fogstir) & 0x03 ];
1156         dc_translucentmap = & translucenttables[ TRANSLU_TABLE_INDEX(fogtran) ];
1157         ftranslucent[count] =   // normal table, or rev table
1158          & dc_translucentmap[ (dr_alpha<128) ? (fogcolor<<8) : fogcolor ];
1159     }
1160 
1161     count = ds_x2 - ds_x1 + 1;
1162     dest = ylookup[ds_y] + columnofs[ds_x1];
1163 
1164     count4 = count>>2;
1165     count -= count4<<2;
1166     if( dr_alpha < 128 )
1167     {
1168         // low alpha, use four translucent tables
1169         while (count4--)
1170         {
1171             *dest = ds_colormap[ ftranslucent[3][ (*dest) ]];
1172             dest ++;
1173             *dest = ds_colormap[ ftranslucent[2][ (*dest) ]];
1174             dest ++;
1175             *dest = ds_colormap[ ftranslucent[1][ (*dest) ]];
1176             dest ++;
1177             *dest = ds_colormap[ ftranslucent[0][ (*dest) ]];
1178             dest ++;
1179         }
1180         while( count-- )
1181         {
1182             *dest = ds_colormap[ ftranslucent[count&0x03][ (*dest) ]];
1183             dest ++;
1184         }
1185     }
1186     else
1187     {
1188         // high alpha, reversed use of four translucent tables
1189         while (count4--)
1190         {
1191             *dest = ds_colormap[ ftranslucent[3][ (*dest) << 8 ]];
1192             dest ++;
1193             *dest = ds_colormap[ ftranslucent[2][ (*dest) << 8 ]];
1194             dest ++;
1195             *dest = ds_colormap[ ftranslucent[1][ (*dest) << 8 ]];
1196             dest ++;
1197             *dest = ds_colormap[ ftranslucent[0][ (*dest) << 8 ]];
1198             dest ++;
1199         }
1200         while( count-- )
1201         {
1202             *dest = ds_colormap[ ftranslucent[count&0x03][ (*dest) << 8 ]];
1203             dest ++;
1204         }
1205     }
1206 }
1207 
1208 
1209 //SoM: Fog wall.
R_DrawFogColumn_8(void)1210 void R_DrawFogColumn_8(void)
1211 {
1212    // fogcolor blur needs to be kept as 8 bit or else the blur is inadequate
1213 static byte  fogcolor_c;
1214     int count, count4, fi;
1215     byte * ftranslucent[4];
1216     byte fc, fc2;
1217     byte alpha16;
1218     uint16_t fogcolor;  // to allow shift by 8
1219 
1220     fogstir ++;
1221     // fog_index 0.. column height
1222     // always average two pixels of source texture
1223     fi = fog_index + 3;
1224     fc = dc_colormap[ dc_source[fog_index] ];
1225     if( fi >= fog_col_length )  fi -= fog_col_length;
1226     fc2 = dc_colormap[ dc_source[fi] ];
1227     fc = translucenttables[ TRANSLU_TABLE_med + (fc2 << 8) + fc ];
1228     if( fog_init )
1229     {
1230         // init blur
1231         fogcolor_c = fc;
1232         fog_init = 0;
1233     }
1234     else
1235     {
1236         // blur
1237         fogcolor_c = translucenttables[ TRANSLU_TABLE_more + (fc << 8) + fogcolor_c ];
1238     }
1239     fogcolor = dc_colormap[ fogcolor_c ];
1240 
1241     alpha16 = dr_alpha >> 3;  // dr_alpha 0..255 => 0..31
1242     if( alpha16 > 15 )
1243     {
1244         if( alpha16 > 31 )  alpha16 = 31;
1245         alpha16 = 31 - alpha16; // high alpha reverse trans
1246     }
1247     for( count = 0; count < 4; count++ )
1248     {
1249         byte fogtran = fog_tran_table[ alpha16 ][ (count+fogstir) & 0x03 ];
1250         dc_translucentmap = & translucenttables[ TRANSLU_TABLE_INDEX(fogtran) ];
1251         if( dr_alpha < 128 )
1252            ftranslucent[count] = & dc_translucentmap[ fogcolor << 8 ];
1253         else
1254            ftranslucent[count] = & dc_translucentmap[ fogcolor ];  // rev table
1255     }
1256 
1257     count = dc_yh - dc_yl + 1;
1258 
1259     // Zero length, column does not exceed a pixel.
1260     if (count < 0)
1261         return;
1262 
1263 #ifdef RANGECHECK_DRAW_LIMITS
1264     // [WDJ] Draw window is actually rdraw_viewwidth and rdraw_viewheight
1265     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
1266     {
1267         I_SoftError("R_DrawFogColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
1268         return;
1269     }
1270 #endif
1271 
1272     // Framebuffer destination address.
1273     // Use ylookup LUT to avoid multiply with ScreenWidth.
1274     // Use columnofs LUT for subwindows?
1275     byte * dest = ylookup[dc_yl] + columnofs[dc_x];
1276 
1277     count4 = count>>2;
1278     count -= count4<<2;
1279     if( dr_alpha < 128 )
1280     {
1281         // low alpha, use four translucent tables
1282         while (count4--)
1283         {
1284             *dest = dc_colormap[ ftranslucent[3][ (*dest) ]];
1285             dest += vid.ybytes;
1286             *dest = dc_colormap[ ftranslucent[2][ (*dest) ]];
1287             dest += vid.ybytes;
1288             *dest = dc_colormap[ ftranslucent[1][ (*dest) ]];
1289             dest += vid.ybytes;
1290             *dest = dc_colormap[ ftranslucent[0][ (*dest) ]];
1291             dest += vid.ybytes;
1292         }
1293         while( count-- )
1294         {
1295             *dest = dc_colormap[ ftranslucent[count&0x03][ (*dest) ]];
1296             dest += vid.ybytes;
1297         }
1298     }
1299     else
1300     {
1301         // high alpha, reversed use of four translucent tables
1302         while (count4--)
1303         {
1304             *dest = dc_colormap[ ftranslucent[3][ (*dest) << 8 ]];
1305             dest += vid.ybytes;
1306             *dest = dc_colormap[ ftranslucent[2][ (*dest) << 8 ]];
1307             dest += vid.ybytes;
1308             *dest = dc_colormap[ ftranslucent[1][ (*dest) << 8 ]];
1309             dest += vid.ybytes;
1310             *dest = dc_colormap[ ftranslucent[0][ (*dest) << 8 ]];
1311             dest += vid.ybytes;
1312         }
1313         while( count-- )
1314         {
1315             *dest = dc_colormap[ ftranslucent[count&0x03][ (*dest) << 8 ]];
1316             dest += vid.ybytes;
1317         }
1318     }
1319 }
1320 
1321 #if 0
1322 // [WDJ] Replaced by generic R_DrawColumnShadowed
1323 // SoM: This is for 3D floors that cast shadows on walls.
1324 // This function just cuts the column up into sections and calls
1325 // R_DrawColumn_8
1326 void R_DrawColumnShadowed_8(void)
1327 {
1328     int count;
1329     int realyh, realyl;
1330     int i;
1331     int height, bheight = 0;
1332     int solid = 0;
1333 
1334     realyh = dc_yh;
1335     realyl = dc_yl;
1336 
1337     count = dc_yh - dc_yl;
1338 
1339     // Zero length, column does not exceed a pixel.
1340     if (count < 0)
1341         return;
1342 
1343 #ifdef RANGECHECK_DRAW_LIMITS
1344     // [WDJ] Draw window is actually rdraw_viewwidth and rdraw_viewheight
1345     if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
1346     {
1347         I_SoftError("R_DrawShadowedColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
1348         return;
1349     }
1350 #endif
1351 
1352     // SoM: This runs through the lightlist from top to bottom and cuts up
1353     // the column accordingly.
1354     for (i = 0; i < dc_numlights; i++)
1355     {
1356         // If the height of the light is above the column, get the colormap
1357         // anyway because the lighting of the top should be effected.
1358         solid = dc_lightlist[i].flags & FF_CUTSOLIDS;
1359 
1360         height = dc_lightlist[i].height >> 12;
1361         if (solid)
1362             bheight = dc_lightlist[i].botheight >> 12;
1363         if (height <= dc_yl)
1364         {
1365             dc_colormap = dc_lightlist[i].rcolormap;
1366             if (solid && dc_yl < bheight)
1367                 dc_yl = bheight;
1368             continue;
1369         }
1370         // Found a break in the column!
1371         dc_yh = height;
1372 
1373         if (dc_yh > realyh)
1374             dc_yh = realyh;
1375         R_DrawColumn_8();
1376         if (solid)
1377             dc_yl = bheight;
1378         else
1379             dc_yl = dc_yh + 1;
1380 
1381         dc_colormap = dc_lightlist[i].rcolormap;
1382     }
1383     dc_yh = realyh;
1384     if (dc_yl <= realyh)
1385         R_DrawColumn_8();
1386 }
1387 #endif
1388