1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: r_data.c 1564 2020-12-19 06:21:07Z wesleyjohnson $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Portions Copyright (C) 1998-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_data.c,v $
21 // Revision 1.31  2003/05/04 04:12:54  sburke
22 // Replace memcpy with memmove, to prevent a misaligned access fault on sparc.
23 //
24 // Revision 1.30  2002/12/13 19:22:12  ssntails
25 // Fix for the Z_CheckHeap and random crashes! (I hope!)
26 //
27 // Revision 1.29  2002/01/12 12:41:05  hurdler
28 // Revision 1.28  2002/01/12 02:21:36  stroggonmeth
29 //
30 // Revision 1.27  2001/12/27 22:50:25  hurdler
31 // fix a colormap bug, add scrolling floor/ceiling in hw mode
32 //
33 // Revision 1.26  2001/08/13 22:53:40  stroggonmeth
34 // Revision 1.25  2001/03/21 18:24:39  stroggonmeth
35 // Revision 1.24  2001/03/19 18:52:01  hurdler
36 //
37 // Revision 1.23  2001/03/13 22:14:20  stroggonmeth
38 // Long time no commit. 3D floors, FraggleScript, portals, ect.
39 //
40 // Revision 1.22  2000/11/04 16:23:43  bpereira
41 //
42 // Revision 1.21  2000/11/02 17:50:09  stroggonmeth
43 // Big 3Dfloors & FraggleScript commit!!
44 //
45 // Revision 1.20  2000/10/04 16:19:23  hurdler
46 // Change all those "3dfx names" to more appropriate names
47 //
48 // Revision 1.19  2000/09/28 20:57:17  bpereira
49 //
50 // Revision 1.18  2000/08/11 12:25:23  hurdler
51 // latest changes for v1.30
52 //
53 // Revision 1.17  2000/07/01 09:23:49  bpereira
54 // Revision 1.16  2000/05/03 23:51:01  stroggonmeth
55 // Revision 1.15  2000/04/23 16:19:52  bpereira
56 // Revision 1.14  2000/04/18 17:39:39  stroggonmeth
57 //
58 // Revision 1.13  2000/04/18 12:54:58  hurdler
59 // software mode bug fixed
60 //
61 // Revision 1.12  2000/04/16 18:38:07  bpereira
62 // Revision 1.11  2000/04/15 22:12:58  stroggonmeth
63 //
64 // Revision 1.10  2000/04/13 23:47:47  stroggonmeth
65 // See logs
66 //
67 // Revision 1.9  2000/04/08 17:45:11  hurdler
68 // fix some boom stuffs
69 //
70 // Revision 1.8  2000/04/08 17:29:25  stroggonmeth
71 // Revision 1.7  2000/04/08 11:27:29  hurdler
72 // fix some boom stuffs
73 //
74 // Revision 1.6  2000/04/07 01:39:53  stroggonmeth
75 // Fixed crashing bug in Linux.
76 // Made W_ColormapNumForName search in the other direction to find newer colormaps.
77 //
78 // Revision 1.5  2000/04/06 21:06:19  stroggonmeth
79 // Optimized extra_colormap code...
80 // Added #ifdefs for older water code.
81 //
82 // Revision 1.4  2000/04/06 20:40:22  hurdler
83 // Mostly remove warnings under windows
84 //
85 // Revision 1.3  2000/04/04 00:32:47  stroggonmeth
86 // Initial Boom compatability plus few misc changes all around.
87 //
88 // Revision 1.2  2000/02/27 00:42:10  hurdler
89 // Revision 1.1.1.1  2000/02/22 20:32:32  hurdler
90 // Initial import into CVS (v1.29 pr3)
91 //
92 //
93 // DESCRIPTION:
94 //      Preparation of data for rendering,
95 //      generation of lookups, caching, retrieval by name.
96 //
97 //-----------------------------------------------------------------------------
98 
99 #include "doomincl.h"
100 #include "p_local.h"
101 #include "p_tick.h"
102   // thinker
103 #include "p_setup.h" //levelflats
104 #include "g_game.h"
105 #include "i_video.h"
106 #include "r_local.h"
107 #include "r_sky.h"
108 #include "r_data.h"
109 #include "w_wad.h"
110   // numwadfiles
111 #include "z_zone.h"
112 #include "v_video.h" //pLocalPalette
113 #include "m_swap.h"
114 
115 
116 // [WDJ] debug flat
117 //#define DEBUG_FLAT
118 
119 // [WDJ] Generate texture controls
120 
121 // [WDJ] For y clipping to be technically correct, the pixels in the source
122 // post must be skipped. To maintain compatibility with the original doom
123 // engines, which had this bug, other engines do not skip the post pixels either.
124 // Enabling corrected_clipping will make some textures slightly different
125 // than displayed in other engines.
126 // TEKWALL1 will have two boxes in the upper left corner with this off and one
127 // box with it enabled.  The differences in other textures are less noticable.
128 // This only affects software rendering, hardware rendering is correct.
129 boolean corrected_clipping = 0;
130 
131 
132 //
133 // Graphics.
134 // DOOM graphics for walls and sprites
135 // is stored in vertical runs of opaque pixels (posts).
136 // A column is composed of zero or more posts,
137 // a patch or sprite is composed of zero or more columns.
138 //
139 
140 int             firstflat, lastflat, numflats;
141 int             firstpatch, lastpatch, numpatches;
142 
143 
144 // textures
145 int             numtextures=0;      // total number of textures found,
146 // size of following tables
147 
148 // Array [ num_textures ], owned, Z_Malloc
149 texture_t**     textures = NULL;
150 
151 // [WDJ] To reduce the repeated indexing using texture id num, better locality of reference.
152 // To allow creating a texture that was not loaded from textures[].
153 // Holds all the software render information.
154 // Array [ num_textures ], owned, Z_Malloc
155 texture_render_t * texture_render = NULL;
156 
157 // Array [ num_textures ], owned, Z_Malloc
158 fixed_t*        textureheight;      // needed for texture pegging
159 
160 
161 #if 0
162 int       *flattranslation;             // for global animation
163 #endif
164 // Array [ num_textures+1 ], owned, Z_Malloc
165 int *  texturetranslation;
166 
167 // needed for pre rendering
168 spritelump_t *  spritelumps = NULL;  // array of sprite lump values, endian swapped
169 int             num_spritelump = 0;  // already allocated
170 int             num_free_spritelump = 0;  // free for allocation
171 
172 // colormap lightmaps from wad COLORMAP lump
173 lighttable_t *  reg_colormaps;
174 
175 
176 //faB: for debugging/info purpose
177 int             flatmemory;
178 int             spritememory;
179 int             texturememory;	// all textures
180 
181 
182 //faB: highcolor stuff
183 // [WDJ] 2012-02-06 shared for DRAW15, DRAW16, DRAW24, DRAW32
184 union color8_u   color8;  // remap color index to rgb value
185 #ifdef ENABLE_DRAW8_USING_12
186 byte  color12_to_8[ 0x1000 ];
187 #endif
188 
189 
190 //  src_type : TM_row_image (pic_t), TM_column_image (patch, picture)
191 //  src_data : source data
192 //  bytepp : source pixel size in bytes
193 //  sel_offset  : offset into pixel, 0..3
194 //  blank_value : pixel value that is blank space, >255 = no blank pixel value
195 //  out_type :  TM_patch, TM_picture, TM_column_image
196 //  out_flags : in created patch
197 //    CPO_blank_trim : trim blank columns
198 //  out_header : temp patch header for width and offset
R_Create_Patch(unsigned int width,unsigned int height,byte src_type,byte * src_data,byte bytepp,byte sel_offset,uint16_t blank_value,byte out_type,byte out_flags,patch_t * out_header)199 byte * R_Create_Patch( unsigned int width, unsigned int height,
200              /*SRC*/   byte src_type, byte * src_data, byte bytepp, byte sel_offset, uint16_t blank_value,
201              /*DEST*/  byte out_type, byte out_flags, patch_t * out_header )
202 {
203     byte  postbuf[ 1024 ];
204     unsigned int  head_empty_columns = 0;  // left
205     unsigned int  tail_empty_columns = 0;  // right
206     unsigned int  mid_empty_columns = 0;
207     unsigned int  count_good_columns = 0;
208     unsigned int  colofs_size, head_size, wb_blocksize;
209     signed int    leftoffset = 0;
210     unsigned int  col, length, dest_used, max_length;
211     unsigned int  row_inc, col_inc;
212     byte          empty_column = 0;
213     byte          out_patch_header, out_columnofs, out_post;
214     byte       *  wb_dest;  // output, ZMalloc
215     uint32_t   *  colofs0 = NULL;
216     post_t     *  destpost = NULL;
217     byte       *  dest_term = NULL;
218     byte       *  destp;
219     byte       *  pb;  // in postbuf
220     byte       *  src0, * src_end, * src ;
221 
222     // Source
223     if( src_type == TM_column_image )
224     {
225         row_inc = bytepp;  // row to row, along col
226         col_inc = bytepp * height;  // col to col
227     }
228     else  // TM_row_image
229     {
230         col_inc = bytepp;  // col to col, along row
231         row_inc = bytepp * width;  // row to row
232     }
233 
234     out_patch_header = out_columnofs = out_post = 0;
235     switch( out_type )
236     {
237      case TM_patch:
238         out_patch_header = out_columnofs = out_post = 1;
239         break;
240      case TM_picture:
241         out_columnofs = 1;
242         break;
243      case TM_column_image:
244      default:
245 	break;
246     }
247 
248     // Dest
249     head_size = 0;
250     colofs_size = 0;
251     dest_used = 0;
252     if( out_patch_header )
253     {
254         head_size += 8;
255     }
256     if( out_columnofs )
257     {
258         colofs_size = width * sizeof( uint32_t );  // width * 4
259         head_size += colofs_size;
260     }
261     wb_blocksize = head_size + (width * height);  // guess
262     max_length = 1024;  // buffer length
263     if( out_post )
264     {
265         wb_blocksize += 4;
266         max_length = 255;
267     }
268 
269     wb_dest = (byte*) Z_Malloc( wb_blocksize, PU_IN_USE, NULL );
270 
271     if( out_patch_header )
272     {
273         patch_t * wb_patch = (patch_t*) wb_dest;
274 	wb_patch->width = width;
275         wb_patch->height = height;
276         wb_patch->leftoffset = 0;
277         wb_patch->topoffset = 0;
278         colofs0 = & wb_patch->columnofs[0];
279     }
280     else if( out_columnofs )
281     {
282         colofs0 = (uint32_t*) wb_dest;  // no header
283     }
284 
285     destp = wb_dest + head_size;  // posting area
286     for( col=0; col<width; col++ )
287     {
288         destpost = NULL;
289         empty_column = 1;  // flag column with no-posts value
290         if( colofs0 )
291         {
292             colofs0[col] = 0;  // header entry for this column
293         }
294         src = src0 = & src_data[ col * col_inc ];
295         src_end = src0 + (row_inc * (height-1)) + 1;  // past last byte of column
296         while( src < src_end )
297         {
298             // traverse column
299             for( ; src < src_end ; src += row_inc )
300             {
301                 if( src[sel_offset] != blank_value )
302                     goto start_post; // find first non blank pixel
303             }
304             // only blanks found
305             if( empty_column )  // if no posts, then will need to fix later
306             {
307                 if( count_good_columns )
308                     tail_empty_columns++;
309                 else
310                     head_empty_columns++;
311             }
312             break;
313 
314         start_post:
315             // Must be at least one pixel, because blank span found a non-blank.
316             // Enter into header
317             if( empty_column )
318             {
319 	        if( colofs0 )
320                 {
321                     colofs0[col] = destp - wb_dest; // offset within patch
322                 }
323                 // maintain empty column count
324                 count_good_columns ++;
325                 mid_empty_columns += tail_empty_columns;
326                 tail_empty_columns = 0;
327 	        empty_column = 0;
328             }
329 
330             dest_used = destp - wb_dest;
331             if( out_post )
332             {
333                 unsigned int topdelta = (src - src0) / row_inc;
334                 if( topdelta > 254 )  // topdelta would be too large
335                     break;  // skip rest of height
336 
337                 destpost = (post_t*) destp;  // posting area
338                 destpost->topdelta = topdelta;
339                 dest_used += 5;  // post + 2 pad + term
340             }
341 
342             // traverse source column
343             length = 0;
344 	    pb = postbuf;  // must use a buffer to convert row indexing to column indexing
345             for( ; src < src_end ; src += row_inc )
346             {
347                 if(src[sel_offset] == blank_value)  break;  // find first blank pixel
348                 if( length >= max_length )  break;  // max post length
349                 length++;
350 	        *(pb++) = src[sel_offset];  // into buffer
351             }
352             // src must point to next, not included in this post
353 
354             dest_used += length;
355             if( dest_used + 8 > wb_blocksize )
356             {
357                 // Will not fit in the allocation
358                 // Copy to new allocation.
359                 unsigned int  wb2_len = dest_used + 1024;  // allocation increment
360                 byte * wb2 = (byte*) Z_Malloc( wb2_len, PU_IN_USE, NULL );
361                 intptr_t  adjustdiff = (void*) wb2 - (void*) wb_dest;  // byte difference in locations
362 
363                 // Move data to wb2
364                 memcpy( wb2, wb_dest, wb_blocksize );
365 
366                 // Release old allocation
367                 Z_Free( wb_dest );
368                 wb_dest = wb2;
369                 wb_blocksize = wb2_len;
370 
371                 // Move ptrs to wb2
372                 destp += adjustdiff;
373 	        if( colofs0 )  colofs0 += adjustdiff;
374 	        if( destpost )  destpost += adjustdiff;
375             }
376 
377             // Form postbuf into a column post.
378             if( destpost )
379             {
380                 destpost->length = length;
381                 destp[2] = 0;	// pad 0
382                 destp += 3;  // post pixel data
383             }
384 
385 	    // Copy must be after allocation size check.
386             memcpy( destp, postbuf, length );
387             destp += length;
388 
389             if( destpost )
390             {
391                 *(destp++) = 0; // pad 0
392                 // Keep ptr to term, for empty columns.
393 		dest_term = destp;
394                 *dest_term = 0xFF; // term, may get overwritten by next post
395                 // next source colpost, adv by (length + 2 byte header + 2 extra bytes)
396                 // next post overwrites previous term
397             }
398         }
399         // start new column
400         if( destpost )
401         {
402             destp ++;  // skip 0xFF column termination
403             dest_used++;
404         }
405     }
406 
407     if( colofs0 && dest_term && mid_empty_columns )
408     {
409         // Must fix colofs that are still 0.
410         // Point column at last 0xFF written.
411         unsigned int term_offset = dest_term - wb_dest;  // offset of last 0xFF
412         for( col=0; col<width; col++ )
413         {
414             if( colofs0[col] == 0 )
415                 colofs0[col] = term_offset;
416         }
417     }
418 
419     if( (out_flags & CPO_blank_trim) && ((head_empty_columns + tail_empty_columns) > 0) )
420     {
421         unsigned int  new_head_size = 0;
422         // trim off the empty columns
423         unsigned int  trim_width = head_empty_columns + tail_empty_columns;
424         width = width - trim_width;
425 
426         if( out_patch_header )
427             new_head_size += 8;
428 
429         if( colofs0 )  // out_patch_header or out_columnofs
430         {
431             unsigned int  new_colofs_size = width * sizeof(uint32_t);  // width * 4
432             unsigned int  adjustcol = colofs_size - new_colofs_size;  // byte difference in colorofs locations
433             new_head_size += new_colofs_size;
434 
435             if( head_empty_columns )
436             {
437                 // remove head_empty_columns of colofs table
438                 memmove( colofs0, & colofs0[head_empty_columns], new_colofs_size );
439             }
440 
441             // Move ptrs to new positions
442             for( col=0; col<width; col++ )  // new width
443             {
444                 colofs0[col] -= adjustcol;
445             }
446 
447             // move data due to smaller columnofs
448             memmove( wb_dest + new_head_size, wb_dest + head_size, dest_used - head_size );
449             // colofs_size = new_colofs_size;  // unnecessary
450         }
451 
452         dest_used = dest_used - head_size + new_head_size;
453 
454         leftoffset -= head_empty_columns;
455         if( out_patch_header )
456 	{
457             // update
458             patch_t * wb_patch = (patch_t*)  wb_dest;
459             wb_patch->leftoffset = leftoffset;
460             wb_patch->width = width;
461         }
462     }
463 
464     // Resize if necessary
465     if( dest_used + 32 < wb_blocksize )
466     {
467         // excessive allocation
468         // Copy to new allocation.
469         byte * wb2 = (byte*) Z_Malloc( dest_used, PU_IN_USE, NULL );
470         memcpy( wb2, wb_dest, dest_used );
471         // Release old allocation
472         Z_Free( wb_dest );
473         wb_dest = wb2;
474     }
475 
476     if( out_header )
477     {
478         out_header->height = height;
479         out_header->width = width;
480         out_header->leftoffset = leftoffset;
481         out_header->topoffset = 0;
482     }
483     return wb_dest;
484 }
485 
486 
487 //  Fixed, solid, image.
488 //  column_oriented : source data orientation, 0 = row x column (image), 1 = column x row (pic_t)
489 //  data : source data of width x height (in rows)
R_Create_Image(unsigned int width,unsigned int height,byte column_oriented,byte * data)490 byte * R_Create_Image( unsigned int width, unsigned int height, byte column_oriented, byte * data )
491 {
492     byte  postbuf[ 256 ];
493     unsigned int  wb_blocksize = (width * height);
494     unsigned int  col, length;
495     unsigned int  row_inc, col_inc;
496     byte       *  pb;
497     byte       *  src ;
498     byte       *  dest;
499 
500     byte * wb_image = Z_Malloc( wb_blocksize, PU_IN_USE, NULL );
501 
502     if( column_oriented )
503     {
504         row_inc = 1;  // row to row, along col
505         col_inc = height;  // col to col
506     }
507     else
508     {
509         col_inc = 1;  // col to col, along row
510         row_inc = width;  // row to row
511     }
512 
513     dest = wb_image;  // posting area
514     for( col=0; col<width; col++ )
515     {
516         src = & data[ col * col_inc ];
517 
518         // Copy column
519         pb = postbuf;  // put into postbuf
520         for( ;  ; src += row_inc )
521         {
522             if( pb >= & postbuf[height] )  break;  // max post length
523             *(pb++) = *src;
524         }
525         length = pb - postbuf;  // must be at least 1
526 
527         // Form postpuf into a column post.
528         memcpy( dest, postbuf, length );
529         if( length < height )
530         {
531             memset( &dest[length], 0, height - length ) ;
532         }
533 
534         dest += height;
535     }
536 
537     return wb_image;
538 }
539 
540 
541 #if 0
542 // indexed by pic_selection_e
543 byte pic_pixel_offset_table[ 3 ] = { 0, 0, 1 };
544 
545 // indexed by pic_mode_t
546 // byte per pixel
547 byte pic_bytepp_table[ 5 ] = { 1, 1, 2, 3, 4 };
548 
549 typedef enum {
550     PM_PALETTE,
551     PM_INTENSITY,
552     PM_ALPHA,
553 } patch_mode_e;
554 
555 byte pic_operation_table[5][3] =
556 {
557   // 255 cannot be done.
558   { // Have PALETTE
559     // Want PM_PALETTE, PM_INTENSITY, PM_ALPHA
560     0, 40, 40
561   },
562   { // Have INTENSITY
563     // Want PM_PALETTE, PM_INTENSITY, PM_ALPHA
564     255, 0, 0
565   },
566   { // Have INTENSITY_ALPHA
567     // Want PM_PALETTE, PM_INTENSITY, PM_ALPHA
568     255, 0, 1
569   },
570   { // Have RGBA24
571     // Want PM_PALETTE, PM_INTENSITY, PM_ALPHA
572     49, 48, 255
573   },
574   { // Have RGBA32
575     // Want PM_PALETTE, PM_INTENSITY, PM_ALPHA
576     49, 48, 3
577   }
578 }
579 
580 //  mode : patch_mode_e
581 patch_t * R_Pic_to_Patch( pic_t * pic, byte patch_mode )
582 {
583     byte picmode = pic->mode;
584     byte sel_offset = 0;
585     byte blank_value = 0;
586     byte operation = pic_operation_table[picmode][patch_mode];
587     byte bytepp = pic_bytepp_table[ picmode ];
588 
589     if( operation == 255 )
590         return NULL;
591 
592     if( operation <= 4 )
593     {
594         sel_offset = operation;
595     }
596     else
597     {
598         // destructive operation, put into 0 byte
599         byte * w;
600         byte * w_end = &pic->data[pic->width * pic->height]
601         for( w= &pic->data[0]; w < w_end; w += bytepp )
602         {
603             RGBA_t p;
604             switch( picmode )
605             {
606              case PALETTE:
607                p = pLocalPalette[w[0]];
608                p.s.alpha = 0;
609                break;
610              case INTENSITY:
611                p.s.red = p.s.green = p.s.blue = w[0];
612                p.s.alpha = 0;
613                break;
614              case INTENSITY_ALPHA:
615                p.s.red = p.s.green = p.s.blue = w[0];
616                p.s.alpha = w[1];
617                break;
618              case RGBA24:
619                p.s.red   = w[0];
620                p.s.green = w[1];
621                p.s.blue  = w[2];
622                p.s.alpha = 0;
623                break;
624              case RGBA32:
625                p = ((RGBA32_t*)w)[0];
626                break;
627             }
628             switch( patch_mode )
629             {
630              case PM_PALETTE:
631                w[0] = NearestColor(p.s.red, p.s.green, p.s.blue);
632                break;
633              case PM_INTENSITY:
634                w[0] = (p.s.red + p.s.green + p.s.blue) / 3;
635                break;
636              case PM_ALPHA:
637                w[0] = p.s.alpha;
638                break;
639             }
640         }
641     }
642 
643     return  R_Create_Patch( pic->width, pic->height, 1, & pic->data[0],
644                             bytepp, sel_offset, blank_value );
645 }
646 #endif
647 
648 
649 #if 0
650 // [WDJ] This description applied to previous code. It is kept for historical
651 // reasons. We may have to restore some of this functionality, but this scheme
652 // would not work with z_zone freeing cache blocks.
653 //
654 // MAPTEXTURE_T CACHING
655 // When a texture is first needed,
656 //  it counts the number of composite columns
657 //  required in the texture and allocates space
658 //  for a column directory and any new columns.
659 // The directory will simply point inside other patches
660 //  if there is only one patch in a given column,
661 //  but any columns with multiple patches
662 //  will have new column_t generated.
663 //
664 
665 
666 #endif
667 
668 
669 // [WDJ] Need extra texture_render when need both picture and patch for a texture.
670 // This will not be used most of the time, but when it is needed, there
671 // is no way around it.  When that happens there will likely be several textures
672 // involved, because it is triggered by how the textures are used in the wad.
673 
674 #ifdef RENDER_TEXTURE_EXTRA_FULL
675 // The texture_render_t will hold a Z_Malloc, and cannot be moved nor reallocated.
676 // The array of ptrs can be realloc-ed.
677 static texture_render_t * *  texture_render_extra = NULL;  // array of ptr
678 static byte texture_render_extra_alloc = 0;  // number allocated
679 static byte texture_render_extra_count = 0;  // number used
680 #endif
681 
682 // One extra texren, for all uses.  Will thrash when have too many needy textures.
683 static int               common_texren_texture_num = 0;
684 static unsigned int      common_texren_usage_count = 0;  // number of times flushed
685 static texture_render_t  common_texren = { 0, 0 };  // reused
686 
687 // Cannot return NULL.
R_Get_extra_texren(int texture_num,texture_render_t * base_texren,byte model)688 texture_render_t *  R_Get_extra_texren( int texture_num, texture_render_t * base_texren, byte model )
689 {
690 #ifdef RENDER_TEXTURE_EXTRA_FULL
691     texture_render_t *  trep;
692     int index = base_texren->extra_index;  // 1..
693 
694     // If existing matching texture cache entry.
695     if( index && (index <= texture_render_extra_count) && texture_render_extra )
696     {
697         // There is an existing extra.
698 	trep = texture_render_extra[ index - 1 ];
699 
700         if( trep->texture_model == model )
701 	    goto done;
702 
703         // do not need more than one extra, for now.
704     }
705 
706     if( texture_render_extra_count > 253 )
707         goto use_common_texren;  // exceeds what can be saved as index
708 
709     if( texture_render_extra_count >= texture_render_extra_alloc )
710     {
711         // Alloc the array of ptrs.
712         int new_alloc = texture_render_extra_alloc + 8;
713         void * new_array = realloc( texture_render_extra, sizeof( texture_render_t* ) * new_alloc );
714         if( new_array == NULL )
715             goto use_common_texren;
716 
717         texture_render_extra = new_array;
718 	texture_render_extra_alloc = new_alloc;
719     }
720 
721     // Not found, create new.
722     trep = (texture_render_t*) malloc( sizeof(texture_render_t) );
723     if( trep == NULL )
724         goto use_common_texren;
725 
726     texture_render_extra[ texture_render_extra_count ] = trep;
727     // link to base_texren
728     base_texren->extra_index = ++ texture_render_extra_count;  // 1..
729 
730     memset( trep, 0, sizeof(texture_render_t) );
731     trep->texture_model = model;
732 
733 done:
734     return trep;
735 
736 #endif
737 
738 #ifdef RENDER_TEXTURE_EXTRA_FULL
739 use_common_texren:
740 #endif
741     // Use the common_texren for all textures.
742     // This may thrash if the wad design was sloppy.
743     if( (common_texren_texture_num != texture_num)
744         || (common_texren.texture_model != model) )
745     {
746         if( common_texren_usage_count < 0xFFFFFFFF )
747             common_texren_usage_count ++;
748         // Wrong content, so clear it.
749         if( common_texren.cache )
750             Z_Free( common_texren.cache );
751 
752     }
753 
754     return & common_texren; // must return something
755 }
756 
757 static
R_Release_all_extra_texren(void)758 void  R_Release_all_extra_texren( void )
759 {
760     if( verbose && common_texren_usage_count )
761     {
762         GenPrintf( EMSG_ver, "Common Extra texren used: %i\n", common_texren_usage_count );
763         common_texren_usage_count = 0;
764     }
765 
766 #ifdef RENDER_TEXTURE_EXTRA_FULL
767     if( texture_render_extra == NULL )
768         return;
769 
770     if( verbose )
771         GenPrintf( EMSG_ver, "Extra texren used: %i\n", texture_render_extra_count );
772 
773     int i;
774     for( i=0; i<texture_render_extra_count; i++ )
775     {
776         texture_render_t * trep = texture_render_extra[i];
777         if( trep )
778         {
779             if( trep->cache )
780 	        Z_Free( trep->cache );
781             free( trep );
782         }
783     }
784 
785     free( texture_render_extra );
786     texture_render_extra_alloc = texture_render_extra_count = 0;
787 #endif
788 }
789 
790 
791 
792 #if 0
793 // Some unique Texture setup for installing a patch.
794 void  R_Set_Texture_Patch( int texnum, patch_t * patch )
795 {
796     uint32_t*  colofs;  // to match size in wad
797 
798     if( texturecache[texnum] )
799         Z_Free( texturecache[texnum] );
800 
801     texturecache[texnum] = (byte*) patch;
802 
803     // determine width power of 2
804     int j = 1;
805     while (j*2 <= patch->width)  j<<=1;
806     texturewidthmask[texnum] = j-1;
807     textureheight[texnum] = patch->height<<FRACBITS;
808 
809     colofs = &(patch->columnofs[0]);;
810 #ifdef COLOFS_PLUS_3
811     if( colofs[0] == ((patch->width * sizeof(uint32_t)) + 8) )
812     {
813         // offset to pixels instead of post header
814         // Many callers will use colofs-3 to get back to header, but
815         // some drawing functions need pixels.
816         int i;
817         for (i=0; i<patch->width; i++)
818             colofs[i] = colofs[i] + 3;  // adjust colofs from wad
819     }
820 #endif
821     texturecolumnofs[texnum] = colofs;
822 }
823 #endif
824 
825 
826 // [WDJ] 2/5/2010
827 // See LITE96 originx=-1, LITERED originx=-4, SW1WOOD originx=-64
828 // See TEKWALL1 originy=-27, STEP2 originy=-112, and other such textures in doom wad.
829 // Patches leftoffset and topoffset are ignored when composing textures.
830 
831 // The original doom has a clipping bug when originy < 0.
832 // The patch position is moved instead of clipped, the height is clipped.
833 
834 //
835 // R_DrawColumnInCache
836 // Clip and draw a column from a patch into a cached post.  Dest is in columns.
837 //
838 
839 static
R_DrawColumnInCache(column_t * colpost,byte * cache,int originy,int cacheheight)840 void R_DrawColumnInCache ( column_t*     colpost,	// source, list of 0 or more post_t
841                            byte*         cache,		// dest
842                            int           originy,
843                            int           cacheheight )  // limit
844 {
845     int         count;
846     int         position;  // dest
847 #ifdef DEEPSEA_TALL_PATCH
848     // [MB] [WDJ]  Support for DeePsea tall patches,
849     int   cur_topdelta = -1;
850 #endif
851     byte*       source;
852 //    byte*       dest;
853 
854 //    dest = (byte *)cache;// + 3;
855 
856     // Assemble a texture from column post data from wad lump.
857     // Column is a series of posts (post_t), terminated by 0xFF
858     while (colpost->topdelta != 0xff)	// end of posts
859     {
860         // post has 2 byte header (post_t),
861         // and has extra byte before and after pixel data
862         source = (byte *)colpost + 3;	// pixel data after post header
863         count = colpost->length;
864 
865 #ifdef DEEPSEA_TALL_PATCH
866         // When the column topdelta is <= the current topdelta,
867         // it is a DeePsea tall patch relative topdelta.
868         int topdelta = colpost->topdelta;
869         if( topdelta <= cur_topdelta )
870         {
871              // DeePsea relative topdelta
872              topdelta += cur_topdelta;
873         }
874         cur_topdelta = topdelta;
875         position = originy + topdelta;  // position in dest
876 #else
877         position = originy + colpost->topdelta;  // position in dest
878 #endif
879 
880         if (position < 0)
881         {
882             count += position;  // skip pixels off top
883             // [WDJ] For this clipping to be technically correct, the pixels
884             // in the source must be skipped too.
885             // Other engines do not skip the post pixels either, to maintain
886             // compatibility with the original doom engines, which had this bug.
887             // Enabling this will make some textures slightly different
888             // than displayed in other engines.
889             // TEKWALL1 will have two boxes in the upper left corner with this
890             // off and one box with it enabled.  The differences in other
891             // textures are less noticable.
892             if( corrected_clipping )
893             {
894                 source -= position; // [WDJ] 1/29/2010 skip pixels in post
895             }
896             position = 0;
897         }
898 
899         if (position + count > cacheheight)  // trim off bottom
900             count = cacheheight - position;
901 
902         // copy column (full or partial) to dest cache at position
903         if (count > 0)
904             memcpy (cache + position, source, count);
905 
906         // next source colpost, adv by (length + 2 byte header + 2 extra bytes)
907         colpost = (column_t *)(  (byte *)colpost + colpost->length + 4);
908     }
909 }
910 
911 
912 
913 //
914 // R_GenerateTexture
915 //
916 //   Allocate space for full size texture, either single patch or 'composite'
917 //   Build the full textures from patches.
918 //   The texture caching system is a little more hungry of memory, but has
919 //   been simplified for the sake of highcolor, dynamic lighting, & speed.
920 //
921 //   This is not optimized, but it's supposed to be executed only once
922 //   per level, when enough memory is available.
923 
924 // Temp structure element used to combine patches into one dest patch.
925 typedef struct {
926     int   nxt_y, bot_y;		// current post segment in dest coord.
927     int   width;
928     int   originx, originy;	// add to patch to get texture
929 #ifdef DEEPSEA_TALL_PATCH
930     // [MB] [WDJ]  Support for DeePsea tall patches,
931     int   cur_topdelta;
932 #endif
933     post_t *  postptr;		// post within that patch
934     patch_t * patch;     	// patch source
935     // [WDJ] Generate_Texture can now reuse columns (as done in Requiem compacted patches).
936     uint32_t  usedpatchdata;    // to detect reuse, compaction
937     // [WDJ] Bad patch detection
938     int   patchsize;
939 } compat_t;
940 
941 #ifdef DEEPSEA_TALL_PATCH
942 // [MB] [WDJ] DeePsea tall patch.
943 // DeepSea allows the patch to exceed 254 height.
944 // A Doom patch has monotonic ascending topdelta values, 0..254.
945 // DeePsea tall patches have an optional relative delta detected
946 // when col->topdelta < cur_topdelta.
947 // When the column topdelta is less than the current topdelta,
948 // it is a DeePsea tall patch relative topdelta.
949 #endif
950 
951 
952 
953 //  texnum : index into textures
954 //  texture_req : requirement,  TM_none, TM_masked, TM_picture, or TM_picture_column
R_GenerateTexture2(int texnum,texture_render_t * texren,byte texture_req)955 byte* R_GenerateTexture2 ( int texnum, texture_render_t *  texren, byte  texture_req )
956 {
957     texture_t*          texture; // texture info from wad
958     texpatch_t*         texpatch;  // patch info to make texture
959     patch_t*            realpatch; // patch lump
960     uint32_t*           colofs;  // to match size in wad
961 
962     byte     * txcblock; // allocated texture memory
963     byte     * texture_end; // end of allocated texture area
964     patch_t  * txcpatch; // header of txcblock
965     byte     * txcdata;  // posting area
966     byte     * destpixels;  // current post pixel in txcdata
967 
968     int	txcblocksize;
969 
970     // array to hold all patches for combine
971 # define MAXPATCHNUM 256
972     compat_t   compat[MAXPATCHNUM];
973     post_t   * srcpost, * destpost;
974 
975     unsigned int patchcount;
976     unsigned int compostsize;
977     byte  detect_post = 0;  // detect patch post incomptible with single column
978     byte  detect_hole = 0;
979     byte  detect = (texren->detect & TD_masked);
980     byte  make_picture = 0;
981 #ifdef DEEPSEA_TALL_PATCH
982     int seg_topdelta;  // current seg_topdelta
983 #endif
984     int patchsize;
985     int	colofs_size;
986     int x, x1, x2, i, p;
987     int postlength;  // length of current post
988     int segnxt_y, segbot_y; // may be negative
989     int bottom;		// next y in column
990 
991 
992     texture = textures[texnum];
993     // [WDJ] Do not save GenerateTexture texture_model in the texture.
994     // There may be more than one needed, and upon reload the last
995     // generated model will appear to be a texture requirement.
996     detect |= texture->detect;  // texture hints from texture load
997 
998     if( texture_req == TM_none )
999         texture_req = texren->texture_model;  // previous generate
1000 
1001     if( texture_req == TM_picture )
1002         make_picture = 1;
1003 
1004     if( texren->cache )
1005         Z_Free( texren->cache );
1006 
1007     // Column offset table size as determined by wad specs.
1008     // Column pixel data starts after the table.
1009     colofs_size = texture->width * sizeof( uint32_t );  // width * 4
1010     // to allocate texture column offset lookup
1011 
1012 #if 0
1013     // To debug problems with specific textures
1014     if( strncmp(texture->name, "TEKWALL5", 8 ) == 0 )
1015        debug_Printf("GenerateTexture - match\n");
1016 #endif
1017 
1018     // single-patch textures can have holes and may be used on
1019     // 2sided lines so they need to be kept in 'packed' format
1020     patchcount = texture->patchcount;
1021 
1022     if( patchcount >= MAXPATCHNUM )
1023     {
1024        I_SoftError("R_GenerateTexture: Patch count %i exceeds %i, ignoring rest\n",
1025                    patchcount, MAXPATCHNUM);
1026        patchcount = MAXPATCHNUM - 1;
1027     }
1028 
1029     // [WDJ] Protect every alloc using PU_CACHE from all Z_Malloc that
1030     // follow it, as that can deallocate the PU_CACHE unexpectedly.
1031 
1032     // Texture patch format:
1033     //   patch header (8 bytes), ignored
1034     //   array[ texture_width ] of column offset
1035     //   concatenated column posts, of variable length, terminate 0xFF
1036     //        ( post header (topdelta,length), pixel data )
1037 
1038     // First examination of the source patches
1039     compostsize = 0;
1040     texpatch = texture->patches;
1041     for (p=0; p<patchcount; p++, texpatch++)
1042     {
1043         compat_t * cp = &compat[p];
1044         cp->postptr = NULL;	// disable until reach starting column
1045         cp->nxt_y = INT_MAX;	// disable
1046 
1047         // Track patch memory usage to detect reused columns.
1048         cp->usedpatchdata = 0;
1049         cp->originx = texpatch->originx;
1050         cp->originy = texpatch->originy;
1051 
1052         // To avoid hardware render cache.
1053         realpatch = W_CachePatchNum_Endian(texpatch->lumpnum, PU_IN_USE);  // patch temp
1054         // Preliminary characteristics of the patch.
1055         cp->patch = realpatch;
1056         cp->width = realpatch->width;
1057         int patch_colofs_size = realpatch->width * sizeof( uint32_t );  // width * 4
1058         // Need patchsize to detect invalid patches.
1059         patchsize = W_LumpLength(texpatch->lumpnum);
1060         cp->patchsize = patchsize;
1061 
1062         // [WDJ] Detect PNG patches.
1063         if(    ((byte*)realpatch)[0]==137
1064             && ((byte*)realpatch)[1]=='P'
1065             && ((byte*)realpatch)[2]=='N'
1066             && ((byte*)realpatch)[3]=='G' )
1067         {
1068             // Found a PNG patch, which will crash the draw8 routine.
1069             // Must assume could be used for top or bottom of wall,
1070             // which require the patch run full height (no transparent).
1071 #if 1
1072             // Enable when want to know which textures are triggering this.
1073             GenPrintf(EMSG_info,"R_GenerateTexture: Texture %8s has PNG patch.\n", texture->name );
1074 #endif
1075             goto disable_patch;
1076         }
1077 
1078         // [WDJ] W_CachePatchNum should only get lumps from PATCH section,
1079         // but it will return a colormap of the same name.
1080         // Here are some validity checks, to ensure we are working with a patch.
1081         // colormap size = 0x2200 to 0x2248
1082         {
1083             uint32_t* pat_colofs = (uint32_t*)&(realpatch->columnofs); // to match size in wad
1084             if( patch_colofs_size + 8 > patchsize )  // column list exceeds patch size
1085                 goto disable_patch;
1086 
1087             // Look at patch columns
1088             for( i=0; i< realpatch->width; i++ )
1089             {
1090                 uint32_t cofs = pat_colofs[i];  // column offset
1091                 if( cofs > patchsize )
1092                     goto disable_patch;  // invalid column offset
1093 
1094                 post_t * ppp = (post_t*)( (byte*)realpatch + cofs );
1095                 if( ppp->topdelta || (ppp->length != realpatch->height) )
1096                     detect_post = TD_post;  // patch is not single column
1097 
1098                 // Look for holes
1099                 segbot_y = -1;
1100 #ifdef DEEPSEA_TALL_PATCH
1101                 seg_topdelta = -1;
1102 #endif
1103                 while( ppp->topdelta != 0xFF )
1104                 {
1105                     int topdelta = ppp->topdelta;
1106 #ifdef DEEPSEA_TALL_PATCH
1107 		    if( topdelta <= seg_topdelta )
1108                     {
1109                         // DeePsea relative topdelta
1110                         topdelta += seg_topdelta;
1111                     }
1112                     seg_topdelta = topdelta;
1113 #endif
1114                     if( topdelta > (segbot_y + 1) )    detect_hole = TD_hole;
1115                     segbot_y = topdelta + ppp->length;
1116                     ppp = (post_t*)((byte*)ppp + ppp->length + 4);
1117                 }
1118             }
1119         }
1120 
1121         // Add posts, without columnofs table and 8 byte patch header.
1122         compostsize += patchsize - patch_colofs_size - 8;
1123         continue;
1124 
1125     disable_patch:
1126         cp->originx = 7999;  // to disable this patch
1127         cp->patchsize = 0;
1128         cp->width = 0;
1129         continue;
1130     }
1131 
1132     // [WDJ] When rejected PNG patches and bad patches.
1133     if( compostsize == 0 )  // no valid patches found
1134     {
1135 #if 1
1136         // Enable when want to know which textures are triggering this.
1137         GenPrintf(EMSG_info,"R_GenerateTexture: Texture %8s has no valid patches, using dummy texture.\n", texture->name );
1138 #endif
1139         goto make_dummy_texture;
1140     }
1141 
1142     if( make_picture )
1143         goto multipatch_combine;
1144 
1145     if( patchcount > 1 )
1146         goto multipatch_combine;
1147 
1148     if( texture_req == TM_picture_column )
1149     {
1150         if( detect_hole )
1151             goto multipatch_combine;
1152         if( detect_post )
1153             goto multipatch_combine;
1154     }
1155 
1156     if( patchcount==1 )
1157     {
1158         // Single patch texture, simplify
1159 
1160         // [WDJ] Detect shifted origin, cannot use the simple copy.
1161         texpatch = texture->patches;
1162         if( texpatch->originx != 0 || texpatch->originy != 0 )
1163         {
1164             // [WDJ] Cannot copy patch to texture.
1165             // Fixes tekwall2, tekwall3, tekwall5 in FreeDoom,
1166             // which use right half of large combined patches.
1167 //	    debug_Printf("GenerateTexture %s: offset forced multipatch\n", texture->name );
1168             goto multipatch_combine;
1169         }
1170 
1171         // [WDJ] Only need patch lump for the following memcpy.
1172         realpatch = compat[0].patch;
1173         patchsize = compat[0].patchsize;
1174 
1175         // [WDJ] Detect mismatch of patch width, too large.
1176         if( realpatch->width > texture->width )
1177         {
1178             // [WDJ] Texture is a portion of a large patch.
1179             // To prevent duplicate large copies.
1180             // Unfortunately this also catches the large RSKY that legacy
1181             // has in legacy.wad.
1182             if( strncmp(texture->name, "SKY", 3 ) == 0 )
1183             {
1184                 // let sky match patch
1185                 texture->height = realpatch->height;
1186             }
1187             else
1188             {
1189 //	        debug_Printf("GenerateTexture %s: width forced multipatch\n", texture->name );
1190                 goto multipatch_combine;
1191             }
1192         }
1193         else
1194 
1195         // [WDJ] Detect mismatch of patch width, too small.
1196         if( realpatch->width < texture->width )
1197         {
1198             // [WDJ] Messy situation. Single patch texture where the patch
1199             // width is smaller than the texture.  There will be segfaults when
1200             // texture columns are accessed that are not in the patch.
1201             // Rebuild the patch to meet draw expectations.
1202             // This occurs in phobiata and maybe heretic.
1203             // [WDJ] Too late to change texture size to match patch,
1204             // the caller can already be violating the patch width.
1205             // Single-sided textures need to be kept packed to preserve holes.
1206             // The texture may be rebuilt several times due to cache.
1207             int patch_colofs_size = realpatch->width * sizeof( uint32_t );  // width * 4
1208             int ofsdiff = colofs_size - patch_colofs_size;
1209             // reserve 4 bytes at end for empty post handling
1210             txcblocksize = patchsize + ofsdiff + 4;
1211 #if 0
1212             // Enable when want to know which textures are triggering this.
1213             GenPrintf(EMSG_info,"R_GenerateTexture: single patch width does not match texture width %8s\n",
1214                    texture->name );
1215 #endif
1216             txcblock = Z_Malloc (txcblocksize,
1217                           PU_LEVEL,         // will change tag at end of this function
1218                           (void**)&texren->cache);
1219 
1220             // patches have 8 byte patch header, part of patch_t
1221             memcpy (txcblock, realpatch, 8); // header
1222             memcpy (txcblock + colofs_size + 8, ((byte*)realpatch) + patch_colofs_size + 8, patchsize - patch_colofs_size - 8 ); // posts
1223             // build new column offset table of texture width
1224             {
1225                 // Copy patch columnofs table to texture, adjusted for new
1226                 // length of columnofs table.
1227                 uint32_t* pat_colofs = (uint32_t*)&(realpatch->columnofs); // to match size in wad
1228                 colofs = (uint32_t*)&(((patch_t*)txcblock)->columnofs); // new
1229                 for( i=0; i< realpatch->width; i++)
1230                         colofs[i] = pat_colofs[i] + ofsdiff;
1231                 // put empty post for all columns not in the patch.
1232                 // txcblock has 4 bytes reserved for this.
1233                 int empty_post = txcblocksize - 4;
1234                 txcblock[empty_post] = 0xFF;  // empty post list
1235                 txcblock[empty_post+3] = 0xFF;  // paranoid
1236                 for( ; i< texture->width ; i++ )
1237                         colofs[i] = empty_post;
1238             }
1239             goto single_patch_finish;
1240         }
1241 
1242 
1243         {
1244             // Normal: Most often use patch as it is.
1245             // texture_render cache gets copy so that PU_CACHE deallocate clears the
1246             // cache automatically
1247             txcblock = Z_Malloc (patchsize,
1248                           PU_IN_USE,  // will change tag at end of this function
1249                           (void**)&texren->cache);
1250 
1251             memcpy (txcblock, realpatch, patchsize);
1252             txcblocksize = patchsize;
1253         }
1254 
1255   single_patch_finish:
1256         // Textures do not use the realpatch offsets, which may be garbage.
1257         txcpatch = (patch_t*)txcblock;
1258         txcpatch->leftoffset = 0;
1259         txcpatch->topoffset = 0;
1260 
1261         // Interface for texture draw.
1262         // Use the single patch, single column lookup.
1263         colofs = (uint32_t*)&(((patch_t*)txcblock)->columnofs);
1264         // colofs from patch are relative to start of table
1265         texren->columnofs = colofs;
1266         texren->pixel_data_offset = 3;  // skip over post header and pad byte
1267         texren->texture_model = TM_patch;
1268         //debug_Printf ("R_GenTex SINGLE %.8s size: %d\n",texture->name,patchsize);
1269         detect |= detect_hole | detect_post;
1270         goto done;
1271 
1272         // [WDJ] Dummy texture generation.
1273   make_dummy_texture:
1274         {
1275             // make a dummy texture
1276             int head_size = colofs_size + 8;
1277             txcblocksize = head_size + 4 + texture->height + 4;
1278             // will change tag at end of this function
1279             txcblock = Z_Malloc (txcblocksize, PU_IN_USE, (void**)&texren->cache);
1280             patch_t * txcpatch = (patch_t*) txcblock;
1281             txcpatch->width = texture->width;
1282             txcpatch->height = texture->height;
1283             txcpatch->leftoffset = 0;
1284             txcpatch->topoffset = 0;
1285             destpost = (post_t*) ((byte*)txcblock + head_size);  // posting area;
1286             destpost->topdelta = 0;
1287             destpost->length = texture->height;
1288             destpixels = (byte*)destpost + 3;
1289             destpixels[-1] = 0;	// pad 0
1290             for( i=0; i<texture->height; i++ )
1291             {
1292                 destpixels[i] = 8; // mono color
1293             }
1294             destpixels[i++] = 0; // pad 0
1295             destpixels[i] = 0xFF; // term
1296             // all columns use the same post
1297             colofs = (uint32_t*)&(txcpatch->columnofs);  // has patch header
1298             for(i=0 ; i< texture->width ; i++ )
1299                  colofs[i] = head_size;
1300         }
1301         goto single_patch_finish;
1302     }
1303     // End of Single-patch texture
1304 
1305  multipatch_combine:
1306     // TM_combine_patch or TM_picture: Multiple patch textures.
1307     // Decide TM_ format
1308     // Combined patches + table + header
1309     compostsize += colofs_size + 8;	// combined patch size
1310     txcblocksize = colofs_size + (texture->width * texture->height); // picture format size
1311 
1312     if( texture_req == TM_masked )
1313         goto combine_format;
1314     if( (texture_req == TM_picture_column) && (detect_hole | detect_post) )
1315         goto picture_format;
1316     // If cache was flushed then do not change model
1317     if( texture_req == TM_picture )
1318         goto picture_format;
1319     if( texture_req == TM_combine_patch )
1320         goto combine_format;
1321     // new texture, decide on a model
1322     // if patches would not cover picture, then must have transparent regions
1323     if( compostsize < txcblocksize )
1324         goto combine_format;
1325     if( detect & TD_masked )  // hint
1326         goto combine_format;
1327     // If many patches and high overlap, then picture format is best.
1328     // This will need to be tuned if it makes mistakes.
1329     if( texture->patchcount >= 4 && compostsize > txcblocksize*4 )
1330         goto picture_format;
1331 
1332  combine_format:
1333     // TM_combine_patch: Combine multiple patches into one patch.
1334 
1335     // Size the new texture.  It may be too big, but must not be too small.
1336     // Will usually fit into compostsize because it does so as separate patches.
1337     // Overlap of normal posts will only reduce the size.
1338     // Worst case is (width * (height/2) * (1 pixel + 4 byte overhead))
1339     //   worstsize = colofs_size + 8 + (width * height * 5/2)
1340     // Usually the size will be much smaller, but it is not predictable.
1341     // all posts + new columnofs table + patch header
1342     // Compacted patches, like SW1COMM in Requiem MAP08, usually get expanded,
1343     // and they expand in the texture when they combine with other patches.
1344 
1345     // [WDJ] Generate_Texture will now realloc a texture when estimate was too small.
1346     // Combined patches + table + header + 1 byte per empty column
1347     txcblocksize = compostsize + texture->width;
1348 
1349     txcblock = Z_Malloc (txcblocksize, PU_IN_USE, (void**)&texren->cache);
1350     txcpatch = (patch_t*) txcblock;
1351     txcpatch->width = texture->width;
1352     txcpatch->height = texture->height;
1353     txcpatch->leftoffset = 0;
1354     txcpatch->topoffset = 0;
1355     // column offset lookup table
1356     colofs = (uint32_t*)&(txcpatch->columnofs);  // has patch header
1357 
1358     txcdata = (byte*)txcblock + colofs_size + 8;  // posting area
1359     // starts as empty post, with 0xFF a possibility
1360     destpixels = txcdata;
1361     texture_end = txcblock + txcblocksize - 2; // do not exceed
1362     detect_post = 0;  // combine has own detect
1363     detect_hole = 0;
1364 
1365     // Composite the columns together.
1366     for (x=0; x<texture->width; x++)
1367     {
1368         int nxtpat;	// patch number with next post
1369         int seglen, offset;
1370         // [WDJ] Detect column reuse (Requiem compacted patches).
1371         int livepatchcount = 0;
1372         int reuse_column = -1;
1373 
1374         // offset to post header
1375         colofs[x] = destpixels - (byte*)txcblock;  // this column
1376         destpost = (post_t*)destpixels;	// first post in column
1377         postlength = 0;  // length of current post
1378         bottom = 0;	 // next y in column
1379         segnxt_y = INT_MAX - 10;	// init to very large, but less than disabled
1380         segbot_y = INT_MAX - 10;
1381 #ifdef DEEPSEA_TALL_PATCH
1382         seg_topdelta = -1;  // current dest topdelta
1383 #endif
1384 
1385         // setup the columns, active or inactive
1386         for (p=0; p<patchcount; p++ )
1387         {
1388             compat_t * cp = &compat[p];
1389             int patch_x = x - cp->originx;	// within patch
1390             if( patch_x >= 0 && patch_x < cp->width )
1391             {
1392                 realpatch = cp->patch;
1393                 uint32_t* pat_colofs = (uint32_t*)&(realpatch->columnofs); // to match size in wad
1394 
1395                 // [WDJ] Detect bad column offset.
1396                 if( pat_colofs[patch_x] > cp->patchsize )  // detect bad patch
1397                     goto patch_off;  // post is not within patch memory
1398 
1399                 cp->postptr = (post_t*)( (byte*)realpatch + pat_colofs[patch_x] );  // patch column
1400                 if ( cp->postptr->topdelta == 0xFF )
1401                     goto patch_off;
1402 
1403 #ifdef DEEPSEA_TALL_PATCH
1404                 cp->cur_topdelta = -1;
1405 #endif
1406 
1407                 // To handle Requiem compacted patches, where column data is reused.
1408                 // Empty columns may be shared too, but they are very small,
1409                 // and it really adds to logic complexity, so only look at non-empty.
1410                 if ( pat_colofs[patch_x] > cp->usedpatchdata )
1411                     cp->usedpatchdata = pat_colofs[patch_x];  // track normal usage pattern
1412                 else
1413                 {
1414                     // compaction detected, look for reused column
1415                     int rpx = (cp->originx < 0) ? -cp->originx : 0;  // x in patch
1416 #ifdef DEBUG_REUSECOL
1417                     if( DEBUG_REUSECOL )
1418                        debug_Printf("GenerateTexture: %8s detected reuse of column %i in patch %i\n", texture->name, patch_x, p );
1419 #endif
1420                     for( ; rpx<patch_x; rpx++ )  // find reused column
1421                     {
1422                         if( pat_colofs[rpx] == pat_colofs[patch_x] )  // reused in patch
1423                         {
1424                             int rtx = rpx + cp->originx; // x in texture
1425 #if 1
1426                             // Test for reused column is from single patch
1427                             int p2;
1428                             int livepatchcount2 = 0;
1429 #ifdef DEBUG_REUSECOL
1430                             if( DEBUG_REUSECOL )
1431                                debug_Printf("GenerateTexture: testing reuse of %i, as %i\n", rpx, patch_x);
1432 #endif
1433                             // [WDJ] If reused column is reused alone in both cases,
1434                             // then assume they will be identical in final texture too.
1435                             for (p2=0; p2<patchcount; p2++ )
1436                             {
1437                                 compat_t * cp2 = &compat[p2];
1438                                 int p2_x = rtx - cp2->originx; // within patch
1439                                 if( p2_x >= 0 && p2_x < cp2->width )
1440                                 {
1441                                    livepatchcount2 ++;
1442                                 }
1443                             }
1444                             if ( livepatchcount2 == 1 )
1445                             {
1446                                 reuse_column = rpx + cp->originx; // column in generated texture
1447                                 break;
1448                             }
1449 #else
1450                             // Compare with texture column, reuse when identical
1451                             post_t * rpp = (post_t*)( txcblock + colofs[rtx] );  // texture column
1452                             post_t * ppp = cp->postptr;
1453 #ifdef DEBUG_REUSECOL
1454                             if( DEBUG_REUSECOL )
1455                                debug_Printf("GenerateTexture: testing reuse of %i, as %i\n", rpx, patch_x);
1456 #endif
1457                             // [WDJ] Comparision is made difficult by the pad bytes,
1458                             // which we set to 0, and Requiem.wad does not.
1459                             while (rpp->topdelta != 0xff)  // find column end
1460                             {
1461                                 int len = rpp->length;
1462                                 if( rpp->topdelta != ppp->topdelta )  goto reject_1;
1463                                 if( rpp->length != ppp->length )  goto reject_1;
1464                                 // skip leading pad, and trailing pad
1465                                 if( memcmp( ((byte*)rpp)+3, ((byte*)ppp)+3, len ) )  goto reject_1;
1466                                 // next post
1467                                 len += 4;  // sizeof post_t + lead pad + trail pad
1468                                 rpp = (post_t *) (((byte *)rpp) + len);
1469                                 ppp = (post_t *) (((byte *)ppp) + len);
1470                             }
1471                             if ( ppp->topdelta == 0xff )
1472                             {
1473                                 // columns match
1474                                 reuse_column = rtx;
1475                                 break;
1476                             }
1477                            reject_1:
1478                             continue;
1479 #endif
1480                         }
1481                     }
1482                 }
1483                 livepatchcount++;
1484 
1485 #ifdef DEEPSEA_TALL_PATCH
1486                 // When the column topdelta is <= the current topdelta,
1487                 // it is a DeePsea tall patch relative topdelta.
1488                 int topdelta = cp->postptr->topdelta;
1489                 if( topdelta <= cp->cur_topdelta )
1490                 {
1491                     // DeePsea relative topdelta
1492                     topdelta += cp->cur_topdelta;
1493                 }
1494                 cp->cur_topdelta = topdelta;
1495                 cp->nxt_y = cp->originy + topdelta;
1496 #else
1497                 cp->nxt_y = cp->originy + cp->postptr->topdelta;
1498 #endif
1499                 cp->bot_y = cp->nxt_y + cp->postptr->length;
1500             }else{
1501                patch_off: // empty post
1502                 // clip left and right by turning this patch off
1503                 cp->postptr = NULL;
1504                 cp->nxt_y = INT_MAX;
1505                 cp->bot_y = INT_MAX;
1506             }
1507         }  // for all patches
1508 
1509         // [WDJ] Reuse shared column data instead of creating multiple copies.
1510         if( livepatchcount == 1 )
1511         {
1512             if( reuse_column >= 0 )
1513             {
1514                  // reuse the column
1515                  colofs[x] = colofs[reuse_column];
1516 #ifdef DEBUG_REUSECOL
1517                  // DEBUG: enable to see column reuse
1518                  if( DEBUG_REUSECOL )
1519                    debug_Printf("GenerateTexture: reuse %i\n", reuse_column);
1520 #endif
1521                  continue;  // next x
1522             }
1523         }
1524 
1525         // Assemble the patch column data from multiple patches to the composite.
1526         for(;;) // all posts in column
1527         {
1528             // Find next post y in this column.
1529             // Only need the last patch, as that overwrites every other patch.
1530             nxtpat = -1;	// patch with next post
1531             segnxt_y = INT_MAX-64;	// may be negative, must be < INT_MAX
1532             compat_t * cp = &compat[0];
1533             for (p=0; p<patchcount; p++, cp++)
1534             {
1535                 // Skip over any patches that have been passed.
1536                 // Includes those copied, or covered by those copied.
1537                 while( cp->bot_y <= bottom )
1538                 {
1539                     // this post has been passed, go to next post
1540                     cp->postptr = (post_t*)( ((byte*)cp->postptr) + cp->postptr->length + 4);
1541                     if( cp->postptr->topdelta == 0xFF )  // end of post column
1542                     {
1543                         // turn this patch off
1544                         cp->postptr = NULL;
1545                         cp->nxt_y = INT_MAX;	// beyond texture size
1546                         cp->bot_y = INT_MAX;
1547                         break;
1548                     }
1549 
1550 #ifdef DEEPSEA_TALL_PATCH
1551                     // When the column topdelta is <= the current topdelta,
1552                     // it is a DeePsea tall patch relative topdelta.
1553 		    int topdelta = cp->postptr->topdelta;
1554                     if( topdelta <= cp->cur_topdelta )
1555                     {
1556                         // DeePsea relative topdelta
1557                         topdelta += cp->cur_topdelta;
1558                     }
1559                     cp->cur_topdelta = topdelta;
1560                     cp->nxt_y = cp->originy + topdelta;
1561 #else
1562                     cp->nxt_y = cp->originy + cp->postptr->topdelta;
1563 #endif
1564                     cp->bot_y = cp->nxt_y + cp->postptr->length;
1565                 }
1566 
1567                 if( cp->nxt_y <= segnxt_y )
1568                 {
1569                     // Found an active post
1570                     nxtpat = p;	// last draw into this segment
1571                     // Check for continuing in the middle of a post.
1572                     segnxt_y = (cp->nxt_y < bottom)?
1573                        bottom	// continue previous
1574                        : cp->nxt_y; // start at top of post
1575                     // Only a later drawn patch can overwrite this post.
1576                     segbot_y = cp->bot_y;
1577                 }
1578                 else
1579                 {
1580                     // Limit bottom of this post segment by later drawn posts.
1581                     if( cp->nxt_y < segbot_y )   segbot_y = cp->nxt_y;
1582                 }
1583             }
1584             // Exit test, end of column, which may be empty
1585             if( segnxt_y >= texture->height )   break;
1586 
1587             // copy whole/remainder of post, or cut it short
1588             // assert: segbot_y <= cp->bot_y+1  because it is set in loop
1589             if( segbot_y > texture->height )   segbot_y = texture->height;
1590 
1591             seglen = segbot_y - segnxt_y;
1592 
1593             if( postlength != 0 )
1594             {
1595                // Check if next patch does not append to bottom of current patch
1596                // Combined with Detect.
1597                if( segnxt_y > bottom )
1598                {
1599                    detect_hole = TD_hole;  // whole texture
1600                    if( bottom > 0 )   postlength = 0;  // start new post
1601                }
1602                if( postlength + seglen > 255 )   // if postlength would be too long
1603                {
1604                    detect_post = TD_post;  // whole texture
1605                    postlength = 0;  // start new post
1606                }
1607                if( postlength == 0 )
1608                {
1609                    // does not append, start new post after existing post
1610                    destpost = (post_t*)((byte*)destpost + destpost->length + 4);
1611                }
1612             }
1613 
1614             // Only one patch is drawn last in this segment, copy that one
1615             cp = &compat[nxtpat];
1616             srcpost = cp->postptr;
1617             // offset>0 when copy starts part way into this source post
1618             // NOTE: cp->nxt_y = cp->originy + srcpost->topdelta;
1619             offset = ( segnxt_y > cp->nxt_y )? (segnxt_y - cp->nxt_y) : 0;
1620             // consider y clipping problem
1621             if( cp->nxt_y < 0  &&  !corrected_clipping )
1622             {
1623                 // Original doom had bug in y clipping, such that it
1624                 // would clip the width but not skip the source pixels.
1625                 // Given that segnxt_y was already correctly clipped.
1626                 offset += cp->nxt_y; // reproduce original doom clipping
1627             }
1628 
1629             if( postlength == 0 )
1630             {
1631                 // Start a new post
1632                 if( destpixels + 3 >= texture_end )  goto exceed_alloc_error;
1633 
1634 #ifdef DEEPSEA_TALL_PATCH
1635                 if( segnxt_y > 254 )
1636                 {
1637                     // Can also create a DeePsea patch.
1638                     // When the column topdelta is <= the current topdelta,
1639                     // it is a DeePsea tall patch relative topdelta.
1640                     int ds_topdelta = segnxt_y - seg_topdelta;
1641                     if( ds_topdelta > seg_topdelta )  goto exceed_topdelta;
1642                     // DeePsea relative topdelta successful.
1643                     destpost->topdelta = ds_topdelta;
1644 		    detect_post = TD_post;  // Due to DeePsea
1645                 }
1646                 else
1647                 {
1648                     // new post header and 0 pad byte
1649                     destpost->topdelta = segnxt_y;
1650                 }
1651                 seg_topdelta = segnxt_y;
1652 #else
1653                 if( segnxt_y > 254 )   goto exceed_topdelta;
1654                 // new post header and 0 pad byte
1655                 destpost->topdelta = segnxt_y;
1656 #endif
1657                 // append at
1658                 destpixels = (byte*)destpost + 3;
1659                 destpixels[-1] = 0;	// pad 0
1660             }
1661 
1662             seglen = segbot_y - segnxt_y;
1663             if( destpixels + seglen + 3 >= texture_end )  goto exceed_alloc_error;
1664 
1665             // append to existing post
1666             memcpy( destpixels, ((byte*)srcpost + offset + 3), seglen );
1667             destpixels += seglen;
1668             postlength += seglen;
1669             bottom = segbot_y;
1670             // finish post bookkeeping so can terminate loop easily
1671             *destpixels = 0;	// pad 0
1672             if( postlength > 255 )   goto exceed_post_length;
1673             destpost->length = postlength;
1674         } // for all posts in column
1675         destpixels++;		// skip pad 0
1676         *destpixels++ = 0xFF;	// mark end of column
1677         // may be empty column so do not reference destpost
1678         continue; // next x
1679 
1680        // [WDJ] Realloc texture memory, when estimate was too small.
1681  exceed_alloc_error:
1682        {
1683         // Re-alloc the texture
1684         byte* old_txcblock = txcblock;
1685         int old_txcblocksize = txcblocksize;
1686         // inc alloc by a proportional amount, plus one column
1687         txcblocksize += (texture->width - x + 1) * txcblocksize / texture->width;
1688 #if 1
1689         // enable to print re-alloc events
1690         if( verbose )
1691             GenPrintf(EMSG_ver, "R_GenerateTexture: %8s re-alloc from %i to %i\n",
1692                     texture->name, old_txcblocksize, txcblocksize );
1693 #endif
1694         txcblock = Z_Malloc (txcblocksize, PU_IN_USE, (void**)&texren->cache);
1695         memcpy( txcblock, old_txcblock, old_txcblocksize );
1696         texture_end = txcblock + txcblocksize - 2; // do not exceed
1697         txcdata = (byte*)txcblock + colofs_size + 8;  // posting area
1698         destpixels = (byte*)txcblock + colofs[x] - 3;  // this column
1699         {
1700             patch_t * txcpatch = (patch_t*) txcblock; // header of txcblock
1701             colofs = (uint32_t*)&(txcpatch->columnofs);  // has patch header
1702         }
1703         x--;  // redo this column
1704         Z_Free(old_txcblock);  // also nulls texturecache ptr
1705         texren->cache = txcblock; // replace ptr undone by Z_Free
1706        }
1707 
1708     } // for x
1709 
1710     if( destpixels >= texture_end )
1711     {
1712         I_SoftError("R_GenerateTexture: %8s final exceeds allocation %i, used %i bytes\n",
1713                      texture->name, txcblocksize, destpixels - txcblock );
1714     }
1715 
1716     // Interface for texture draw.
1717     // Texture data is after the offset table, no patch header.
1718     texren->columnofs = colofs;
1719     texren->pixel_data_offset = 3;  // skip over post header and pad byte
1720     texren->texture_model = TM_combine_patch;  // transparent combined
1721 
1722     detect |= detect_hole | detect_post;
1723 #if 0
1724     // Enable to print memory usage
1725     I_SoftError("R_GenerateTexture: %8s allocated %i, used %i bytes\n",
1726             texture->name, txcblocksize, destpixels - txcblock );
1727 #endif
1728     goto done;
1729 
1730  exceed_topdelta:
1731     I_SoftError("R_GenerateTexture: %8s topdelta= %i exceeds 254, make picture\n",
1732             texture->name, segnxt_y );
1733     goto error_redo_as_picture;
1734 
1735  exceed_post_length:
1736     I_SoftError("R_GenerateTexture: %8s post length= %i exceeds 255, make picture\n",
1737             texture->name, postlength );
1738 
1739  error_redo_as_picture:
1740     Z_Free( txcblock );
1741 
1742  picture_format:
1743     //
1744     // multi-patch textures (or 'composite')
1745     // These are stored in a picture format and use a different drawing routine,
1746     // which is flagged by TM_picture.
1747     // Format:
1748     //   array[ width ] of column offset
1749     //   array[ width ] of column ( array[ height ] pixels )
1750 
1751     txcblocksize = colofs_size + (texture->width * texture->height);
1752     //debug_Printf ("R_GenTex MULTI  %.8s size: %d\n",texture->name,txcblocksize);
1753 
1754     // will change PU_ at end of this function
1755     txcblock = Z_Malloc (txcblocksize, PU_IN_USE, (void**)&texren->cache);
1756     memset( txcblock + colofs_size, 0, txcblocksize - colofs_size ); // black background
1757 
1758     // columns lookup table
1759     colofs = (uint32_t*)txcblock;  // has no patch header
1760 
1761     // [WDJ] column offset must cover entire texture, not just under patches
1762     // and it does not vary with the patches.
1763     x1 = colofs_size;  // offset to first column, past colofs array
1764     for (x=0; x<texture->width; x++)
1765     {
1766        // generate column offset lookup
1767        // colofs[x] = (x * texture->height) + (texture->width*4);
1768        colofs[x] = x1;
1769        x1 += texture->height;
1770     }
1771 
1772     // Composite the columns together.
1773     // The TM_picture format has data in full height columns.
1774     texpatch = texture->patches;
1775     for (i=0; i<texture->patchcount; i++, texpatch++)
1776     {
1777         // [WDJ] patch only used in this loop, without any other Z_Malloc
1778         // [WDJ] Must use common patch read to preserve endian consistency.
1779         // otherwise it will be in cache without endian changes.
1780         // To avoid hardware render cache.
1781         realpatch = W_CachePatchNum_Endian(texpatch->lumpnum, PU_CACHE);  // patch temp
1782         x1 = texpatch->originx;
1783         if( x1 > texture->width )
1784 	    continue;  // ignore PNG and other bad patches
1785 
1786         x2 = x1 + realpatch->width;
1787         if( x2 < 0 )
1788 	    continue;  // ignore PNG and other bad patches
1789 
1790         if (x2 > texture->width)
1791             x2 = texture->width;
1792 
1793         for( x = (x1<0)? 0 : x1; x<x2 ; x++ )
1794         {
1795             // source patch column from wad, to be copied
1796             column_t* patchcol =
1797              (column_t *)( (byte *)realpatch + realpatch->columnofs[x-x1] );
1798 
1799             R_DrawColumnInCache (patchcol,		// source
1800                                  txcblock + colofs[x],	// dest
1801                                  texpatch->originy,
1802                                  texture->height);	// limit
1803         }
1804     }
1805 
1806     // Interface for texture draw.
1807     // Texture data is after the offset table, no patch header.
1808     texren->columnofs = colofs;
1809     texren->pixel_data_offset = 0;
1810     texren->texture_model = TM_picture;  // non-transparent picture format
1811 
1812 done:
1813     if( (detect & (TD_post | TD_hole)) == 0 )
1814         detect |= TD_solid_column;  // can be drawn by wall column draw
1815     texren->detect = detect;
1816 
1817     // unlock all the patches, no longer needed, but may be in another texture
1818     for( p=0; p<patchcount; p++ )
1819     {
1820         Z_ChangeTag (compat[p].patch, PU_CACHE);
1821     }
1822 
1823     // Now that the texture has been built in column cache,
1824     //  texture cache is purgable from zone memory.
1825     Z_ChangeTag (txcblock, PU_PRIV_CACHE);  // priority because of expense
1826     texturememory += txcblocksize;  // global
1827 
1828     return txcblock;
1829 }
1830 
1831 
1832 // Public
1833 //  texture_req : requirement,  TM_none, TM_masked, TM_picture, or TM_picture_column
R_GenerateTexture(texture_render_t * texren,byte texture_req)1834 byte* R_GenerateTexture ( texture_render_t *  texren, byte  texture_req )
1835 {
1836     return  R_GenerateTexture2( texren - texture_render, texren, texture_req );
1837 }
1838 
1839 
1840 
1841 
1842 //  convert flat to hicolor as they are requested
1843 //
1844 //byte**  flatcache;
1845 
R_GetFlat(int flatlumpnum)1846 byte* R_GetFlat (int  flatlumpnum)
1847 {
1848    // [WDJ] Checking all callers shows that they might tolerate PU_CACHE,
1849    // but this is safer, and has less reloading of the flats
1850     return W_CacheLumpNum (flatlumpnum, PU_LUMP);	// flat image
1851 //    return W_CacheLumpNum (flatlumpnum, PU_CACHE);
1852 
1853 /*  // this code work but is useless
1854     byte*    data;
1855     short*   wput;
1856     int      i,j;
1857 
1858     //FIXME: work with run time pwads, flats may be added
1859     // lumpnum to flatnum in flatcache
1860     if ((data = flatcache[flatlumpnum-firstflat])!=0)
1861                 return data;
1862 
1863     data = W_CacheLumpNum (flatlumpnum, PU_CACHE);
1864     i=W_LumpLength(flatlumpnum);
1865 
1866     Z_Malloc (i,PU_STATIC,&flatcache[flatlumpnum-firstflat]);
1867     memcpy (flatcache[flatlumpnum-firstflat], data, i);
1868 
1869     return flatcache[flatlumpnum-firstflat];
1870 */
1871 
1872 /*  // this code don't work because it don't put a proper user in the z_block
1873     if ((data = flatcache[flatlumpnum-firstflat])!=0)
1874        return data;
1875 
1876     data = (byte *) W_CacheLumpNum(flatlumpnum,PU_LEVEL);
1877     flatcache[flatlumpnum-firstflat] = data;
1878     return data;
1879 
1880     flatlumpnum -= firstflat;
1881 
1882     if (vid.drawmode==DRAW8PAL)
1883     {
1884                 flatcache[flatlumpnum] = data;
1885                 return data;
1886     }
1887 
1888     // allocate and convert to high color
1889 
1890     wput = (short*) Z_Malloc (64*64*2,PU_STATIC,&flatcache[flatlumpnum]);
1891     //flatcache[flatlumpnum] =(byte*) wput;
1892 
1893     for (i=0; i<64; i++)
1894        for (j=0; j<64; j++)
1895                         wput[i*64+j] = ((color8to16[*data++]&0x7bde) + ((i<<9|j<<4)&0x7bde))>>1;
1896 
1897                 //Z_ChangeTag (data, PU_CACHE);
1898 
1899                 return (byte*) wput;
1900 */
1901 }
1902 
1903 //
1904 // Empty the texture cache (used for load wad at runtime)
1905 //
R_Flush_Texture_Cache(void)1906 void R_Flush_Texture_Cache (void)
1907 {
1908     int i;
1909 
1910     if (numtextures>0)
1911     {
1912         for (i=0; i<numtextures; i++)
1913         {
1914             // Z_Free also sets the cache ptr to NULL
1915             if( texture_render[i].cache )
1916                 Z_Free( texture_render[i].cache );
1917         }
1918     }
1919 
1920     R_Release_all_extra_texren();
1921 }
1922 
1923 //
1924 // R_Load_Textures
1925 // Initializes the texture list with the textures from the world map.
1926 //
1927 // [WDJ] Original Doom bug: conflict between texture[0] and 0=no-texture.
1928 // Their solution was to not use the first texture.
1929 // In Doom1 == AASTINKY, FreeDoom == AASHITTY, Heretic = BADPATCH.
1930 // Because any wad compatible with other doom engines, like prboom,
1931 // will not be using texture[0], there is little incentive to fix this bug.
1932 // It is likely that texture[0] will be a duplicate of some other texture.
1933 #define BUGFIX_TEXTURE0
1934 //
1935 //
R_Load_Textures(void)1936 void R_Load_Textures (void)
1937 {
1938     maptexture_t*       mtexture;
1939     texture_t*          texture;
1940     mappatch_t*         mpatch;
1941     texpatch_t*         texpatch;
1942     char*               pnames;
1943 
1944     int                 i,j;
1945 
1946     uint32_t	      * maptex, * maptex1, * maptex2;  // 4 bytes, in wad
1947     uint32_t          * directory;	// in wad
1948 
1949     char                name[9];
1950     char*               name_p;
1951 
1952     lumpnum_t         * patch_to_num;  // patch name to num lookup
1953 
1954     int                 nummappatches;
1955     int                 offset;
1956     int                 maxoff;
1957     int                 maxoff2;
1958     int                 numtextures1;
1959     int                 numtextures2;
1960 
1961 
1962 
1963     // free previous memory before numtextures change
1964 
1965     if (numtextures>0)
1966     {
1967         for (i=0; i<numtextures; i++)
1968         {
1969             // Z_Free also sets the cache ptr to NULL
1970             if (textures[i])
1971                 Z_Free (textures[i]);
1972             if( texture_render[i].cache )
1973                 Z_Free( texture_render[i].cache );
1974         }
1975     }
1976 
1977     // Load the patch names from pnames.lmp.
1978     name[8] = 0;
1979     pnames = W_CacheLumpName ("PNAMES", PU_LUMP);  // temp
1980     // [WDJ] Do endian as use pnames temp
1981     nummappatches = LE_SWAP32 ( *((uint32_t *)pnames) );  // pnames lump [0..3]
1982     name_p = pnames+4;  // in lump, after number (uint32_t) is list of patch names
1983 
1984     // create name index to patch index lookup table, will free before return
1985     patch_to_num = calloc (nummappatches, sizeof(*patch_to_num));
1986     for (i=0 ; i<nummappatches ; i++)
1987     {
1988         strncpy (name,name_p+i*8, 8);
1989         patch_to_num[i] = W_Check_Namespace( name, LNS_patch );  // NO_LUMP when invalid
1990     }
1991     Z_Free (pnames);
1992 
1993     // Load the map texture definitions from textures.lmp.
1994     // The data is contained in one or two lumps,
1995     //  TEXTURE1 for shareware, plus TEXTURE2 for commercial.
1996     maptex = maptex1 = W_CacheLumpName ("TEXTURE1", PU_LUMP); // will be freed
1997     numtextures1 = LE_SWAP32(*maptex);  // number of textures, lump[0..3]
1998     maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1"));
1999     directory = maptex+1;  // after number of textures, at lump[4]
2000 
2001     if( VALID_LUMP( W_CheckNumForName ("TEXTURE2") ) )
2002     {
2003         maptex2 = W_CacheLumpName ("TEXTURE2", PU_LUMP); // will be freed
2004         numtextures2 = LE_SWAP32(*maptex2); // number of textures, lump[0..3]
2005         maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
2006     }
2007     else
2008     {
2009         maptex2 = NULL;
2010         numtextures2 = 0;
2011         maxoff2 = 0;
2012     }
2013 #ifdef BUGFIX_TEXTURE0
2014 #define FIRST_TEXTURE  1
2015     // [WDJ] make room for using 0 as no-texture and keeping first texture
2016     numtextures = numtextures1 + numtextures2 + 1;
2017 #else
2018     numtextures = numtextures1 + numtextures2;
2019 #define FIRST_TEXTURE  0
2020 #endif
2021 
2022 
2023     // [smite] separate allocations, fewer horrible bugs
2024     if (textures)
2025     {
2026         Z_Free(textures);
2027         Z_Free(texture_render);
2028         Z_Free(textureheight);
2029     }
2030 
2031     textures         = Z_Malloc(numtextures * sizeof(*textures),         PU_STATIC, 0);
2032     texture_render   = Z_Malloc(numtextures * sizeof(texture_render_t),  PU_STATIC, 0);
2033     // NULL the cache ptrs, format, and flags.
2034     memset( texture_render, 0, sizeof(texture_render_t) * numtextures );
2035     textureheight    = Z_Malloc(numtextures * sizeof(*textureheight),    PU_STATIC, 0);
2036 
2037 #ifdef BUGFIX_TEXTURE0
2038     for (i=0 ; i<numtextures-1 ; i++, directory++)
2039 #else
2040     for (i=0 ; i<numtextures ; i++, directory++)
2041 #endif
2042     {
2043         //only during game startup
2044         //if (!(i&63))
2045         //    CONS_Printf (".");
2046 
2047         if (i == numtextures1)
2048         {
2049             // Start looking in second texture file.
2050             maptex = maptex2;
2051             maxoff = maxoff2;
2052             directory = maptex+1;  // after number of textures, at lump[4]
2053         }
2054 
2055         // offset to the current texture in TEXTURESn lump
2056         offset = LE_SWAP32(*directory);  // next uint32_t
2057 
2058         if (offset > maxoff)
2059             I_Error ("R_Load_Textures: bad texture directory\n");
2060 
2061         // maptexture describes texture name, size, and
2062         // used patches in z order from bottom to top
2063         // Ptr to texture header in lump
2064         mtexture = (maptexture_t *) ( (byte *)maptex + offset);
2065 
2066         // Texture struct allocation is dependent upon number of patches.
2067         texture = textures[i] =
2068             Z_Malloc (sizeof(texture_t)
2069                       + sizeof(texpatch_t)*((uint16_t)(LE_SWAP16(mtexture->patchcount))-1),
2070                       PU_STATIC, 0);
2071 
2072         // get texture info from texture lump
2073         texture->width  = (uint16_t)( LE_SWAP16(mtexture->width) );
2074         texture->height = (uint16_t)( LE_SWAP16(mtexture->height) );
2075         texture->patchcount = (uint16_t)( LE_SWAP16(mtexture->patchcount) );
2076         texture->detect = (mtexture->masked)? TD_masked : 0; // hint
2077 
2078         // Sparc requires memmove, becuz gcc doesn't know mtexture is not aligned.
2079         // gcc will replace memcpy with two 4-byte read/writes, which will bus error.
2080         memmove(texture->name, mtexture->name, sizeof(texture->name));
2081 #if 0
2082         // [WDJ] DEBUG TRACE, watch where the textures go
2083         debug_Printf( "Texture[%i] = %8.8s\n", i, mtexture->name);
2084 #endif
2085         mpatch = &mtexture->patches[0]; // first patch ind in texture lump
2086         texpatch = &texture->patches[0];
2087 
2088         for (j=0 ; j<texture->patchcount ; j++, mpatch++, texpatch++)
2089         {
2090             // get texture patch info from texture lump
2091             texpatch->originx = LE_SWAP16(mpatch->originx);
2092             texpatch->originy = LE_SWAP16(mpatch->originy);
2093             texpatch->lumpnum = patch_to_num[ (uint16_t)( LE_SWAP16(mpatch->patchnum) )];
2094             if( texpatch->lumpnum == NO_LUMP )
2095             {
2096                 I_Error ("R_Load_Textures: Missing patch in texture %s\n",
2097                          texture->name);
2098             }
2099         }
2100 
2101         // determine width power of 2
2102 #if 1
2103         // [WDJ] only need to determine if exact power of 2.
2104         j = 1;
2105         while (j < texture->width)
2106             j<<=1;
2107 #else
2108         // Largest power of 2 that fits within width.
2109         j = 1;
2110         while (j*2 <= texture->width)
2111             j<<=1;
2112 #endif
2113         if( j != texture->width )
2114         {
2115 	    // Odd width
2116 	    texture->detect |= TD_odd_width;
2117             j = 1;  // make width_tile_mask = 0
2118 	}
2119         texture_render[i].width_tile_mask = j-1;
2120         texture_render[i].width = texture->width;
2121         textureheight[i] = texture->height<<FRACBITS;
2122     }
2123 
2124     Z_Free (maptex1);
2125     if (maptex2)
2126         Z_Free (maptex2);
2127     free(patch_to_num);
2128 
2129 #ifdef BUGFIX_TEXTURE0
2130     // Move texture[0] to texture[numtextures-1]
2131     textures[numtextures-1] = textures[0];
2132     texture_render[numtextures-1] = texture_render[0];
2133     textureheight[numtextures-1] = textureheight[0];
2134     // cannot have ptr to texture in two places, will deallocate twice
2135     textures[0] = NULL;	// force segfault on any access to textures[0]
2136 #endif
2137 
2138     //added:01-04-98: this takes 90% of texture loading time..
2139     // Precalculate whatever possible.
2140 
2141     // Create translation table for global animation.
2142     if (texturetranslation)
2143         Z_Free (texturetranslation);
2144 
2145     // texturetranslation is 1 larger than texture tables, for some unknown reason
2146     texturetranslation = Z_Malloc ((numtextures+1)*sizeof(*texturetranslation),
2147                                    PU_STATIC, 0);
2148 
2149     for (i=0 ; i<numtextures ; i++)
2150         texturetranslation[i] = i;
2151 }
2152 
2153 
R_CheckNumForNameList(const char * name,lumplist_t * list,int listsize)2154 lumpnum_t  R_CheckNumForNameList(const char *name, lumplist_t* list, int listsize)
2155 {
2156   int   i;
2157   lumpnum_t  ln;
2158   // from last entry to first entry
2159   for(i = listsize - 1; i > -1; i--)
2160   {
2161     ln = W_CheckNumForNamePwad(name, list[i].wadfile, list[i].firstlump);
2162     if( ! VALID_LUMP(ln) )
2163       continue;  // not found
2164     if(LUMPNUM(ln) > (list[i].firstlump + list[i].numlumps) )
2165       continue;  // not within START END
2166 
2167     return ln;
2168   }
2169   return NO_LUMP;
2170 }
2171 
2172 
2173 // Extra colormaps
2174 lumplist_t * colormaplumps = NULL;  // malloc
2175 int          numcolormaplumps = 0;
2176 
2177 // called by R_Load_Colormaps
R_Load_ExtraColormaps()2178 static void R_Load_ExtraColormaps()
2179 {
2180     lumpnum_t  start_ln, end_ln;
2181     int       cfile;
2182     int  ln1;
2183 
2184     numcolormaplumps = 0;
2185     colormaplumps = NULL;
2186     cfile = 0;
2187 
2188     for(;cfile < numwadfiles; cfile ++)
2189     {
2190         start_ln = W_CheckNumForNamePwad("C_START", cfile, 0);
2191         if( ! VALID_LUMP(start_ln) )
2192             continue;
2193 
2194         ln1 = LUMPNUM( start_ln );
2195         end_ln = W_CheckNumForNamePwad("C_END", cfile, ln1);
2196 
2197         if( ! VALID_LUMP(end_ln) )
2198         {
2199             I_SoftError("R_Load_Colormaps: C_START without C_END\n");
2200             continue;
2201         }
2202 
2203         if(WADFILENUM(start_ln) != WADFILENUM(end_ln))
2204         {
2205             I_SoftError("R_Load_Colormaps: C_START and C_END in different wad files!\n");
2206             continue;
2207         }
2208 
2209         colormaplumps = (lumplist_t *)realloc(colormaplumps, sizeof(lumplist_t) * (numcolormaplumps + 1));
2210         colormaplumps[numcolormaplumps].wadfile = WADFILENUM(start_ln);
2211         ln1++;
2212         colormaplumps[numcolormaplumps].firstlump = ln1;
2213         colormaplumps[numcolormaplumps].numlumps = LUMPNUM(end_ln) - ln1;
2214         numcolormaplumps++;
2215     }
2216 }
2217 
2218 
2219 
2220 lumplist_t*  flats;
2221 int          numflatlists;
2222 
2223 
2224 static
R_Load_Flats()2225 void R_Load_Flats ()
2226 {
2227   lumpnum_t  start_ln, end_ln;
2228   int       cfile, ln1, ln2;
2229 
2230   numflatlists = 0;
2231   flats = NULL;
2232   cfile = 0;
2233 
2234   for(;cfile < numwadfiles; cfile ++)
2235   {
2236 #ifdef DEBUG_FLAT
2237     debug_Printf( "Flats in file %i\n", cfile );
2238 #endif
2239     start_ln = W_CheckNumForNamePwad("F_START", cfile, 0);
2240     if( ! VALID_LUMP(start_ln) )
2241     {
2242 #ifdef DEBUG_FLAT
2243       debug_Printf( "F_START not found, file %i\n", cfile );
2244 #endif
2245       start_ln = W_CheckNumForNamePwad("FF_START", cfile, 0);
2246 
2247       if( ! VALID_LUMP(start_ln) )  //If STILL NO_LUMP, search the whole file!
2248       {
2249 #ifdef DEBUG_FLAT
2250         debug_Printf( "FF_START not found, file %i\n", cfile );
2251 #endif
2252         end_ln = NO_LUMP;
2253         goto save_flat_list;
2254       }
2255     }
2256 
2257     // Search for END after START.
2258     ln1 = LUMPNUM( start_ln );
2259     end_ln = W_CheckNumForNamePwad("F_END", cfile, ln1);
2260     if( ! VALID_LUMP(end_ln) )
2261     {
2262 #ifdef DEBUG_FLAT
2263       debug_Printf( "F_END not found, file %i\n", cfile );
2264 #endif
2265       end_ln = W_CheckNumForNamePwad("FF_END", cfile, ln1);
2266 #ifdef DEBUG_FLAT
2267       if( ! VALID_LUMP(end_ln) ) {
2268          debug_Printf( "FF_END not found, file %i\n", cfile );
2269       }
2270 #endif
2271     }
2272 
2273 save_flat_list:
2274     flats = (lumplist_t *)realloc(flats, sizeof(lumplist_t) * (numflatlists + 1));
2275     flats[numflatlists].wadfile = cfile;
2276     if(end_ln == NO_LUMP)
2277     {
2278       flats[numflatlists].firstlump = 0;
2279       flats[numflatlists].numlumps = 0xffff; //Search the entire file!
2280     }
2281     else
2282     {
2283       // delimiting markers were found
2284       ln2 = LUMPNUM( end_ln );
2285       if( ln2 <= ln1 )  // should not be able to happen
2286         ln2 = 0xffff;  // search entire wad
2287       flats[numflatlists].firstlump = ln1 + 1;
2288       flats[numflatlists].numlumps = ln2 - (ln1 + 1);
2289     }
2290     numflatlists++;
2291     continue;
2292   }
2293 
2294   if(!numflatlists)
2295     I_Error("R_Load_Flats: No flats found!\n");
2296 }
2297 
2298 
2299 
2300 // [WDJ] was R_GetFlatNumForName, but it does not cache like GetFlat
R_FlatNumForName(const char * name)2301 lumpnum_t  R_FlatNumForName(const char *name)
2302 {
2303   // [WDJ] No use in saving F_START if are not going to use them.
2304   // FreeDoom, where a flat and sprite both had same name,
2305   // would display sprite as a flat, badly.
2306   // Use F_START and F_END first, to find flats without getting a non-flat,
2307   // and only if not found then try whole file.
2308 
2309   lumpnum_t f_lumpnum = R_CheckNumForNameList(name, flats, numflatlists);
2310 
2311   if( ! VALID_LUMP(f_lumpnum) ) {
2312      // BP:([WDJ] R_CheckNumForNameList) don't work with gothic2.wad
2313      // [WDJ] Some wads are reported to use a flat as a patch, but that would
2314      // have to be handled in the patch display code.
2315      // If this search finds a sprite, sound, etc., it will display
2316      // multi-colored confetti.
2317      f_lumpnum = W_CheckNumForName(name);
2318   }
2319 
2320   if( ! VALID_LUMP(f_lumpnum) ) {
2321      // [WDJ] When not found, dont quit, use first flat by default.
2322      I_SoftError("R_FlatNumForName: Could not find flat %.8s\n", name);
2323      f_lumpnum = WADLUMP( flats[0].wadfile, flats[0].firstlump );  // default to first flat
2324   }
2325 
2326   return f_lumpnum;
2327 }
2328 
2329 // [WDJ] Manage the spritelump_t allocations
2330 // Still use this array so that rot=0 sprite can share one entry for all 8 rotations.
2331 
expand_spritelump_alloc(void)2332 void expand_spritelump_alloc( void )
2333 {
2334     // [WDJ] Expand array and copy
2335     num_free_spritelump = 256;
2336     int request = num_spritelump + num_free_spritelump;
2337     // new array of spritelumps
2338     spritelump_t * sl_new = Z_Malloc (request*sizeof(spritelump_t), PU_STATIC, 0);
2339     if( spritelumps ) // existing
2340     {
2341         // move existing data
2342         memcpy( sl_new, spritelumps, sizeof(spritelump_t)*num_spritelump);
2343         Z_Free( spritelumps ); // old
2344     }
2345     spritelumps = sl_new;
2346 }
2347 
2348 // Next free spritelump
R_Get_spritelump(void)2349 int  R_Get_spritelump( void )
2350 {
2351     if( num_free_spritelump == 0 )
2352        expand_spritelump_alloc();
2353     num_free_spritelump--;
2354     return  num_spritelump ++;
2355 }
2356 
2357 //
2358 // R_Init_SpriteLumps
2359 // Finds the width and hoffset of all sprites in the wad,
2360 //  so the sprite does not need to be cached completely
2361 //  just for having the header info ready during rendering.
2362 //
2363 
2364 //
2365 //   allocate sprite lookup tables
2366 //
R_Init_SpriteLumps(void)2367 void R_Init_SpriteLumps (void)
2368 {
2369     // the original Doom used to set numspritelumps from S_END-S_START+1
2370 
2371     // [WDJ] Initial allocation, will be expanded as needed
2372     expand_spritelump_alloc();
2373 }
2374 
2375 
2376 // ----------------------------------------
2377 // COLORMAPS
2378 //
2379 // COLORMAP lump : array[34]  of mapping tables [256].
2380 //   [0]  : brightest, light level = 248..255, maps direct to palette colors
2381 //   [31] : darkest, light level = 0..7,       maps to grey,black
2382 //   [32] : invulnerability map,               maps to whites and grays
2383 //   [33] : black map,			       maps entirely to black
2384 //
2385 // Specific palette colors:
2386 //  [0] = black 0,0,0
2387 //  [4] = white 255,255,255
2388 //  [176] = red 255,0,0
2389 //  [112] = green 103,223,95
2390 //  [200] = blue 0,0,255
2391 
2392 // Boom: Extra colormaps can be included in the wad.  They are the same
2393 // size and format as the Doom colormap.
2394 // WATERMAP is predefined by Boom, but may be overloaded.
2395 
2396 
2397 // called by R_Load_Data
2398 static
R_Load_Colormaps(void)2399 void R_Load_Colormaps (void)
2400 {
2401     lumpnum_t ln;
2402 
2403     // Load in the standard colormap lightmap tables (defined by lump),
2404     // now 64k aligned for smokie...
2405     ln = W_GetNumForName("COLORMAP");
2406     reg_colormaps = Z_MallocAlign ( W_LumpLength(ln), PU_STATIC, NULL, 16);
2407     W_ReadLump( ln, reg_colormaps );
2408 
2409     //SoM: 3/30/2000: Init Boom colormaps.
2410     {
2411       R_Clear_Colormaps();
2412       R_Load_ExtraColormaps();
2413     }
2414 }
2415 
2416 
2417 static lumpnum_t  extra_colormap_lumpnum[MAXCOLORMAPS];  // lump number
2418 
2419 //SoM: Clears out extra colormaps between levels.
2420 // called by P_SetupLevel after ZFree(PU_LEVEL,..)
2421 // called by R_Load_Colormaps
R_Clear_Colormaps()2422 void R_Clear_Colormaps()
2423 {
2424   int   i;
2425 #if 0
2426   if( num_extra_colormaps > 30 )
2427      GenPrintf(EMSG_warn, "Number of colormaps: %i\n", num_extra_colormaps );
2428 #endif
2429 
2430   // extra_colormaps are always present [MAXCOLORMAPS]
2431   num_extra_colormaps = 0;
2432   for(i = 0; i < MAXCOLORMAPS; i++)
2433   {
2434     extra_colormap_lumpnum[i] = NO_LUMP;
2435     // [WDJ] The ZMalloc colormap used to be PU_LEVEL, releasing memory without setting the ptrs NULL.
2436     // It is now PU_COLORMAP, and it is released only by this function.
2437     if( extra_colormaps[i].colormap )
2438     {
2439         Z_Free( extra_colormaps[i].colormap );
2440         extra_colormaps[i].colormap = NULL;
2441     }
2442   }
2443 //  memset(extra_colormaps, 0, sizeof(extra_colormaps));
2444 }
2445 
2446 
2447 // [WDJ] Enable to print out results of colormap generate.
2448 //#define VIEW_COLORMAP_GEN
2449 
2450 // In order: whiteindex, lightgreyindex, medgreyindex, darkgreyindex, grayblackindex
2451 // redindex, greenindex, blueindex
2452 #define NUM_ANALYZE_COLORS  8
2453 static byte  doom_analyze_index[NUM_ANALYZE_COLORS] = {
2454     4, 87, 96, 106, 7, 188, 123, 206
2455 };
2456 static byte  heretic_analyze_index[NUM_ANALYZE_COLORS] = {
2457     35, 26, 18, 10, 253, 148, 213, 192
2458 };
2459 
2460 // [WDJ] Analyze an extra colormap to derive some GL parameters
R_Colormap_Analyze(int mapnum)2461 void  R_Colormap_Analyze( int mapnum )
2462 {
2463     extracolormap_t * colormapp = & extra_colormaps[ mapnum ];
2464     colormapp->fadestart = 0;
2465     colormapp->fadeend = 33;
2466 //    colormapp->maskalpha = 0x0;  // now in maskcolor
2467     colormapp->fog = 0;
2468 
2469 #ifdef HWRENDER
2470   // Hardware renderer does not use, nor allocate, the colormap.
2471   // It uses the rgba field instead.
2472   if( rendermode == render_soft )
2473 #endif
2474   {
2475     // Software renderer defaults.
2476     // SoM: Added, we set all params of the colormap to normal because there
2477     // is no real way to tell how GL should handle a colormap lump anyway..
2478     colormapp->maskcolor.rgba = 0xffffffff; // white
2479     colormapp->maskcolor.s.alpha = 0;
2480     colormapp->fadecolor.rgba = 0x0; // black
2481     colormapp->rgba[0].rgba = 0xffffffff;
2482     colormapp->rgba[0].s.alpha = 0xe1;
2483   }
2484 #ifdef HWRENDER
2485   else
2486   {
2487     // Analyze the Boom colormap for the hardware renderer.
2488     // The Boom colormap has been loaded already.
2489     // lighttable_t = byte array
2490     byte * cm = colormapp->colormap; // Boom colormap
2491     byte * tstcolor = & doom_analyze_index[0];  // colors to test
2492     RGBA_t work_rgba;
2493     int i;
2494 
2495     if( cm == NULL )  // no colormap to analyze
2496     {
2497         GenPrintf(EMSG_warn, "R_Colormap_Analyze: map %i, has no colormap\n", mapnum );
2498         return;
2499     }
2500 
2501     if( EN_heretic )
2502        tstcolor = & heretic_analyze_index[0];  // heretic colors to test
2503 
2504     // [WDJ] Analyze the colormap to get some imitative parameters.
2505     for(i=0; i<NUM_RGBA_LEVELS; i++)
2506     {
2507         // rgba[0]=darkest, rgba[NUM_RGBA_LEVELS-1] is the brightest
2508         // Within a range, analyze a map nearer the middle of the range.
2509         int mapindex = (((NUM_RGBA_LEVELS-1-i) * 32) + 8) / NUM_RGBA_LEVELS;
2510         // Estimate an alpha, could set it to max,
2511         // smaller alpha indicates washed out color.
2512         // This is completely ad-hoc, and rough.  It purposely favors high alpha.
2513 
2514 // Analyze 4
2515         // the brightest red, green, blue should have the same brightness
2516         float h4r = 0.0; // alpha = 1
2517         int cnt =0;
2518         int try_cnt = 0;
2519         int dd4, dn4, k1, k2;
2520         // for all combinations of tstcolor
2521         for( k1=0; k1<NUM_ANALYZE_COLORS-1; k1++ )
2522         {
2523             byte i1 = tstcolor[k1];
2524             byte cm1 = cm[ LIGHTTABLE(mapindex) + i1 ];
2525             for( k2=k1+1; k2<NUM_ANALYZE_COLORS; k2++ )
2526             {
2527                 byte i2 = tstcolor[k2];
2528                 byte cm2 = cm[ LIGHTTABLE(mapindex) + i2 ];
2529                 // for each color
2530                 int krgb;
2531                 for( krgb=0; krgb<3; krgb++ )  // red, green, blue
2532                 {
2533                     //  (1-h) = (cm[b].r - cm[r].r) / (p[b].r -  p[r].r)
2534                     switch( krgb )
2535                     {
2536                      case 0: // red
2537                         dd4 = pLocalPalette[i1].s.red -  pLocalPalette[i2].s.red;
2538                         dn4 = pLocalPalette[cm1].s.red - pLocalPalette[cm2].s.red;
2539                         break;
2540                      case 1: // green
2541                         dd4 = pLocalPalette[i1].s.green -  pLocalPalette[i2].s.green;
2542                         dn4 = pLocalPalette[cm1].s.green - pLocalPalette[cm2].s.green;
2543                         break;
2544                      default: // blue
2545                         dd4 = pLocalPalette[i1].s.blue -  pLocalPalette[i2].s.blue;
2546                         dn4 = pLocalPalette[cm1].s.blue - pLocalPalette[cm2].s.blue;
2547                         break;
2548                     }
2549                     if( dn4 && (dd4 > 0.01f || dd4 < -0.01f))
2550                     {
2551                         float h3 = (float)dn4 / (float)dd4;
2552                         if( h3 > 1.0f )   h3 = 1.0;
2553                         if( h3 < 0.01f )  h3 = 0.01f;
2554                         h4r += h3;  // total for avg
2555                         cnt ++;
2556                     }
2557                     try_cnt ++;  // for fog
2558                 }
2559             }
2560         }
2561         h4r /= cnt;
2562         int m4_fog = 0;
2563         // h = 0.0 is a useless table
2564         if( h4r > 0.99 ) {
2565             h4r = 0.99f;
2566             m4_fog = 1;
2567         }
2568         if( h4r < 0.00 ) {
2569             h4r = 0.00;
2570             m4_fog = 1;
2571         }
2572         if( cnt * 2 < try_cnt )
2573             m4_fog = 1;
2574         h4r = h4r * (0.66f / 1.732f);  // correction for testing at 1/3 max brightness
2575         float h4 = 1.0 - h4r;
2576         int m4_red, m4_blue, m4_green;
2577 #if 0
2578         // Generate color tint from changes grey.
2579         byte greyindex = tstcolor[2];
2580         byte cm_grey = cm[ LIGHTTABLE(mapindex) + greyindex ];  // grey
2581         // cr = (cm[w].r - (1-h) * p[w].r) / h ;
2582         m4_red = ( pLocalPalette[cm_grey].s.red - (h4r* pLocalPalette[greyindex].s.red)) / h4;
2583         if( m4_red > 255 ) m4_red = 255;
2584         if( m4_red < 0 ) m4_red = 0;
2585         // cg = (cm[w].g - (1-h) * p[w].g) / h ;
2586         m4_green = ( pLocalPalette[cm_grey].s.green - (h4r* pLocalPalette[greyindex].s.green)) / h4;
2587         if( m4_green > 255 ) m4_green = 255;
2588         if( m4_green < 0 ) m4_green = 0;
2589         // cb = (cm[w].b - (1-h) * p[w].b) / h ;
2590         m4_blue = ( pLocalPalette[cm_grey].s.blue - (h4r* pLocalPalette[greyindex].s.blue)) / h4;
2591         if( m4_blue > 255 ) m4_blue = 255;
2592         if( m4_blue < 0 ) m4_blue = 0;
2593 #else
2594         // Generate color tint from changes white.
2595         byte whiteindex = tstcolor[0];
2596         byte cm_white = cm[ LIGHTTABLE(mapindex) + whiteindex ];  // white
2597         // cr = (cm[w].r - (1-h) * p[w].r) / h ;
2598         m4_red = ( pLocalPalette[cm_white].s.red - (h4r* pLocalPalette[whiteindex].s.red)) / h4;
2599         if( m4_red > 255 ) m4_red = 255;
2600         if( m4_red < 0 ) m4_red = 0;
2601         // cg = (cm[w].g - (1-h) * p[w].g) / h ;
2602         m4_green = ( pLocalPalette[cm_white].s.green - (h4r* pLocalPalette[whiteindex].s.green)) / h4;
2603         if( m4_green > 255 ) m4_green = 255;
2604         if( m4_green < 0 ) m4_green = 0;
2605         // cb = (cm[w].b - (1-h) * p[w].b) / h ;
2606         m4_blue = ( pLocalPalette[cm_white].s.blue - (h4r* pLocalPalette[whiteindex].s.blue)) / h4;
2607         if( m4_blue > 255 ) m4_blue = 255;
2608         if( m4_blue < 0 ) m4_blue = 0;
2609 #endif
2610 #ifdef VIEW_COLORMAP_GEN
2611         // Enable to see results of analysis.
2612         GenPrintf(EMSG_info,
2613                "Analyze4: alpha=%i  red=%i  green=%i  blue=%i  fog=%i\n",
2614                (int)(255.0f*h4), m4_red, m4_green, m4_blue, m4_fog );
2615 #endif
2616         // Not great, get some tints wrong, and sometimes too light.
2617         // Give m4_fog some treatment, to stop compiler messages.
2618         work_rgba.s.alpha = (int)(h4 * 255.0f) - (m4_fog * 2.0f);
2619         work_rgba.s.red = m4_red;
2620         work_rgba.s.green = m4_green;
2621         work_rgba.s.blue = m4_blue;
2622 
2623         colormapp->rgba[i].rgba = work_rgba.rgba;  // to extra_colormap
2624 
2625 #ifdef VIEW_COLORMAP_GEN
2626         // Enable to view settings of RGBA for hardware renderer.
2627         GenPrintf(EMSG_info,"RGBA[%i]: %8x   (alpha=%i, R=%i, G=%i, B=%i)\n",
2628               i, colormapp->rgba[i].rgba,
2629               (int)work_rgba.s.alpha,
2630               (int)work_rgba.s.red, (int)work_rgba.s.green, (int)work_rgba.s.blue );
2631 #endif
2632     }
2633     // They had plans, but these are still unused in hardware renderer.
2634     colormapp->maskcolor.rgba = colormapp->rgba[NUM_RGBA_LEVELS-1].rgba;
2635     colormapp->fadecolor.rgba = colormapp->rgba[0].rgba;
2636 
2637   }
2638 #endif
2639 }
2640 
2641 
2642 
2643 
2644 // [WDJ] The name parameter has trailing garbage, but the name lookup
2645 // only uses the first 8 chars.
2646 // Return the new colormap id number
R_ColormapNumForName(const char * name)2647 int R_ColormapNumForName(const char *name)
2648 {
2649   lumpnum_t lumpnum;
2650   int i;
2651 
2652   // Check for existing colormap of same name
2653   lumpnum = R_CheckNumForNameList(name, colormaplumps, numcolormaplumps);
2654   if( ! VALID_LUMP(lumpnum) )
2655   {
2656     I_SoftError("R_ColormapNumForName: Cannot find colormap lump %8s\n", name);
2657     return 0;
2658   }
2659 
2660   for(i = 0; i < num_extra_colormaps; i++)
2661   {
2662     if(lumpnum == extra_colormap_lumpnum[i])
2663       return i;
2664   }
2665 
2666   // Add another colormap
2667   if(num_extra_colormaps == MAXCOLORMAPS)
2668   {
2669     I_SoftError("R_ColormapNumForName: Too many colormaps!\n");
2670     return 0;
2671   }
2672 
2673   extra_colormap_lumpnum[num_extra_colormaps] = lumpnum;
2674   extracolormap_t * ecmp = & extra_colormaps[num_extra_colormaps];
2675 
2676   // The extra_colormap structure is static and allocated ptrs in it must be set NULL upon release.
2677   // Align on 16 bits, like other colormap allocations.
2678   // ecmp->colormap =
2679       Z_MallocAlign (W_LumpLength(lumpnum), PU_COLORMAP, (void**)&(ecmp->colormap), 16);
2680   // read colormap tables [][] of byte, mapping to alternative palette colors
2681   W_ReadLump( lumpnum, ecmp->colormap );
2682 
2683 #ifdef VIEW_COLORMAP_GEN
2684   GenPrintf(EMSG_info, "\nBoom Colormap: num=%i name= %8.8s\n", num_extra_colormaps, name );
2685 #endif
2686   R_Colormap_Analyze( num_extra_colormaps );
2687 
2688   num_extra_colormaps++;
2689   return num_extra_colormaps - 1;
2690 }
2691 
2692 
2693 
2694 // SoM:
2695 //
2696 // R_Create_Colormap
2697 // This is a more GL friendly way of doing colormaps: Specify colormap
2698 // data in a special linedef's texture areas and use that to generate
2699 // custom colormaps at runtime. NOTE: For GL mode, we only need to color
2700 // data and not the colormap data.
2701 
2702 byte NearestColor(byte r, byte g, byte b);
2703 int  RoundUp(double number);
2704 void R_Create_Colormap_ex( extracolormap_t * extra_colormap_p );
2705 
2706 #define HEX_TO_INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
2707 #define ALPHA_TO_INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : 0)
2708 #define CHAR_TO_INT(c)  (c >= '0' && c <= '9' ? c - '0' : 0)
2709 #define ABS2(x) ((x) < 0 ? -(x) : (x))
2710 
2711 // [WDJ]
2712 // The colorstr is the toptexture name:   '#' R(2) G(2) B(2) A(1)
2713 // The ctrlstr is the midtexture name.    '#' FOG(1) FADE_BEGIN(2)  FADE_END(2)
2714 // The fadestr is the bottomtexture name: '#' R(2) G(2) B(2).
2715 // Translations:
2716 //   R(2), G(2), B(2):   2-digit HEX => 256 color (8bit)
2717 //   A(1): char a-z or A-Z  => 0 to 25 alpha
2718 //   FOG: '0'= not-fog, '1'= fog-effect
2719 //   FADE_BEGIN: 2-digit decimal (0..32) colormap where fade begins
2720 //   FADE_END:   2-digit decimal (1..33) colormap where fade-to color is reached.
2721 // Return the new colormap id number
R_Create_Colormap_str(char * colorstr,char * ctrlstr,char * fadestr)2722 int R_Create_Colormap_str(char *colorstr, char *ctrlstr, char *fadestr)
2723 {
2724   extracolormap_t * extra_colormap_p;
2725   RGBA_t  maskcolor, fadecolor;
2726   unsigned int  fadestart = 0, fadeend = 33;
2727   int    c_alpha = 0;
2728   int    i;
2729   int    fog = 0;
2730   int    mapnum = num_extra_colormaps;  // the new colormap id number
2731 
2732   if(colorstr[0] == '#')  // colormap generate string is recognized
2733   {
2734     // color value from top texture string
2735     maskcolor.s.red = ((HEX_TO_INT(colorstr[1])<<4) + HEX_TO_INT(colorstr[2]));
2736     maskcolor.s.green = ((HEX_TO_INT(colorstr[3])<<4) + HEX_TO_INT(colorstr[4]));
2737     maskcolor.s.blue = ((HEX_TO_INT(colorstr[5])<<4) + HEX_TO_INT(colorstr[6]));
2738     if(colorstr[7] >= 'a' && colorstr[7] <= 'z')
2739       c_alpha = (colorstr[7] - 'a');
2740     else if(colorstr[7] >= 'A' && colorstr[7] <= 'Z')
2741       c_alpha = (colorstr[7] - 'A');
2742     else
2743       c_alpha = 25;
2744     maskcolor.s.alpha = (c_alpha * 255) / 25;  // convert from 0..25 to 0..255
2745   }
2746   else
2747   {
2748     // [WDJ] default for missing upper is not in docs, and was inconsistent
2749     // Cannot be 0xff after multiply by maskalpha=0.
2750     maskcolor.s.red = 0xff;
2751     maskcolor.s.green = 0xff;
2752     maskcolor.s.blue = 0xff;
2753     maskcolor.s.alpha = 0;
2754   }
2755 
2756   if(ctrlstr[0] == '#')
2757   {
2758     // SoM: Get parameters like, fadestart, fadeend, and the fogflag...
2759     fadestart = CHAR_TO_INT(ctrlstr[3]) + (CHAR_TO_INT(ctrlstr[2]) * 10);
2760     fadeend = CHAR_TO_INT(ctrlstr[5]) + (CHAR_TO_INT(ctrlstr[4]) * 10);
2761     if(fadestart > 32 || fadestart < 0)
2762       fadestart = 0;
2763     if(fadeend > 33 || fadeend < 1)
2764       fadeend = 33;
2765     fog = CHAR_TO_INT(ctrlstr[1]) ? 1 : 0;
2766   }
2767 
2768   fadecolor.rgba = 0;
2769   if(fadestr[0] == '#')
2770   {
2771     fadecolor.s.red = ((HEX_TO_INT(fadestr[1]) * 16) + HEX_TO_INT(fadestr[2]));
2772     fadecolor.s.green = ((HEX_TO_INT(fadestr[3]) * 16) + HEX_TO_INT(fadestr[4]));
2773     fadecolor.s.blue = ((HEX_TO_INT(fadestr[5]) * 16) + HEX_TO_INT(fadestr[6]));
2774   }
2775 
2776   // find any identical existing colormap
2777   for(i = 0; i < num_extra_colormaps; i++)
2778   {
2779     // created colormaps only
2780     if( VALID_LUMP(extra_colormap_lumpnum[i]) )
2781       continue;
2782     if(   maskcolor.rgba == extra_colormaps[i].maskcolor.rgba
2783        && fadecolor.rgba == extra_colormaps[i].fadecolor.rgba
2784 // [WDJ] maskalpha is now in maskcolor.alpha
2785 //       && maskalpha == extra_colormaps[i].maskalpha
2786        && fadestart == extra_colormaps[i].fadestart
2787        && fadeend == extra_colormaps[i].fadeend
2788        && fog == extra_colormaps[i].fog )
2789       return i;
2790   }
2791 
2792 #ifdef VIEW_COLORMAP_GEN
2793   GenPrintf(EMSG_info, "\nGenerate Colormap: num=%i\n", num_extra_colormaps );
2794   GenPrintf(EMSG_info, " alpha=%2x, color=(%2x,%2x,%2x), fade=(%2x,%2x,%2x), fog=%i\n",
2795           maskcolor.s.alpha, maskcolor.s.red, maskcolor.s.green, maskcolor.s.blue,
2796           fadecolor.s.red, fadecolor.s.green, fadecolor.s.blue,
2797           fog );
2798 #endif
2799 
2800   if(num_extra_colormaps == MAXCOLORMAPS)
2801   {
2802     I_SoftError("R_Create_Colormap: Too many colormaps!\n");
2803     return 0;
2804   }
2805 
2806   num_extra_colormaps++;
2807 
2808   // Created colormaps do not have lumpnum
2809   extra_colormap_lumpnum[mapnum] = NO_LUMP;
2810   extra_colormap_p = &extra_colormaps[mapnum];
2811 
2812   extra_colormap_p->colormap = NULL;
2813   extra_colormap_p->maskcolor.rgba = maskcolor.rgba;
2814   extra_colormap_p->fadecolor.rgba = fadecolor.rgba;
2815 //  extra_colormap_p->maskalpha = maskalpha;  // 0.0 .. 1.0  // now in maskcolor
2816   extra_colormap_p->fadestart = fadestart;
2817   extra_colormap_p->fadeend = fadeend;
2818   extra_colormap_p->fog = fog;
2819 
2820   R_Create_Colormap_ex( extra_colormap_p );
2821 
2822 #if 0
2823 #ifdef VIEW_COLORMAP_GEN
2824   if(rendermode != render_soft)
2825   {
2826     // [WDJ] DEBUG, TEST AGAINST OLD HDW CODE
2827     uint32_t rgba_oldhw =
2828           (HEX_TO_INT(colorstr[1]) << 4) + (HEX_TO_INT(colorstr[2]) << 0) +
2829           (HEX_TO_INT(colorstr[3]) << 12) + (HEX_TO_INT(colorstr[4]) << 8) +
2830           (HEX_TO_INT(colorstr[5]) << 20) + (HEX_TO_INT(colorstr[6]) << 16) +
2831           (ALPHA_TO_INT(colorstr[7]) << 24);
2832    if( rgba_oldhw != extra_colormap_p->rgba[0].rgba )
2833       GenPrintf(EMSG_info,"RGBA: old=%X, new=%x\n", rgba_oldhw, extra_colormap_p->rgba[i-1].rgba);
2834   }
2835 #endif
2836 #endif
2837 
2838   return mapnum;
2839 }
2840 
2841 
2842 // Analyze param and create the colormap data for the rendermode.
2843 // Called when rendermode change.
R_Create_Colormap_ex(extracolormap_t * extra_colormap_p)2844 void R_Create_Colormap_ex( extracolormap_t * extra_colormap_p )
2845 {
2846   RGBA_t maskcolor, fadecolor;
2847   double color_r, color_g, color_b; // color RGB from top-texture
2848   double cfade_r, cfade_g, cfade_b; // fade-to color from bottom-texture
2849   double maskalpha;
2850   unsigned int  fadestart, fadeend, c_alpha;
2851   int  i;
2852   unsigned int p;
2853 
2854   maskcolor.rgba = extra_colormap_p->maskcolor.rgba;
2855   fadecolor.rgba = extra_colormap_p->fadecolor.rgba;
2856   fadestart = extra_colormap_p->fadestart;
2857   fadeend = extra_colormap_p->fadeend;
2858 
2859   c_alpha = maskcolor.s.alpha;
2860   maskalpha = (double)maskcolor.s.alpha / (double)255;  // 0.0 .. 1.0
2861   color_r = (double)maskcolor.s.red;
2862   color_g = (double)maskcolor.s.green;
2863   color_b = (double)maskcolor.s.blue;
2864 
2865   cfade_r = (double)fadecolor.s.red;
2866   cfade_g = (double)fadecolor.s.green;
2867   cfade_b = (double)fadecolor.s.blue;
2868 
2869 
2870 #ifdef HWRENDER
2871   // Hardware renderer does not use, nor allocate, the colormap.
2872   // It uses the rgba field instead.
2873   if(rendermode == render_soft)
2874 #endif
2875   {
2876     byte * colormap_p;
2877     double othermask = 1.0 - maskalpha;
2878     double by_alpha = maskalpha / 255.0;
2879     double fadedist = fadeend - fadestart;
2880     double  deltas[256][3], map[256][3];
2881 
2882     // The extra_colormap structure is static and allocated ptrs in it must be set NULL upon release.
2883     // Aligning on 16 bits, NOT 8, keeps it from crashing! SSNTails 12-13-2002
2884     if( extra_colormap_p->colormap == NULL )
2885     {
2886         // extra_colormap_p->colormap =
2887         Z_MallocAlign((256 * 34) + 10, PU_COLORMAP, (void**)&(extra_colormap_p->colormap), 16);
2888     }
2889     colormap_p = extra_colormap_p->colormap;
2890 
2891     // premultiply, this messes up rgba calc so it must be done here
2892     color_r *= by_alpha;  // to 0.0 .. 1.0 range
2893     color_g *= by_alpha;
2894     color_b *= by_alpha;
2895     for(i = 0; i < 256; i++)
2896     {
2897       double r = pLocalPalette[i].s.red;
2898       double g = pLocalPalette[i].s.green;
2899       double b = pLocalPalette[i].s.blue;
2900       double cbrightness = sqrt((r*r) + (g*g) + (b*b));
2901 
2902       map[i][0] = (cbrightness * color_r) + (r * othermask);
2903       if(map[i][0] > 255.0)
2904         map[i][0] = 255.0;
2905       deltas[i][0] = (map[i][0] - cfade_r) / fadedist;
2906 
2907       map[i][1] = (cbrightness * color_g) + (g * othermask);
2908       if(map[i][1] > 255.0)
2909         map[i][1] = 255.0;
2910       deltas[i][1] = (map[i][1] - cfade_g) / fadedist;
2911 
2912       map[i][2] = (cbrightness * color_b) + (b * othermask);
2913       if(map[i][2] > 255.0)
2914         map[i][2] = 255.0;
2915       deltas[i][2] = (map[i][2] - cfade_b) / fadedist;
2916     }
2917 
2918     for(p = 0; p < 34; p++)
2919     {
2920       for(i = 0; i < 256; i++)
2921       {
2922         *colormap_p = NearestColor(RoundUp(map[i][0]), RoundUp(map[i][1]), RoundUp(map[i][2]));
2923         colormap_p++;
2924 
2925         if( p < fadestart )
2926           continue;
2927 
2928         if(ABS2(map[i][0] - cfade_r) > ABS2(deltas[i][0]))
2929           map[i][0] -= deltas[i][0];
2930         else
2931           map[i][0] = cfade_r;
2932 
2933         if(ABS2(map[i][1] - cfade_g) > ABS2(deltas[i][1]))
2934           map[i][1] -= deltas[i][1];
2935         else
2936           map[i][1] = cfade_g;
2937 
2938         if(ABS2(map[i][2] - cfade_b) > ABS2(deltas[i][1]))
2939           map[i][2] -= deltas[i][2];
2940         else
2941           map[i][2] = cfade_b;
2942       }
2943     }
2944   }
2945 #ifdef HWRENDER
2946   else
2947   {
2948       if( extra_colormap_p->colormap )
2949       {
2950           // Does not use colormap
2951           Z_Free( extra_colormap_p->colormap );
2952           extra_colormap_p->colormap = NULL;
2953       }
2954 
2955       // hardware needs color_r, color_g, color_b, before they get *maskalpha.
2956       for( i=0; i<NUM_RGBA_LEVELS; i++ )
2957       {
2958           // rgba[0]=darkest, rgba[NUM_RGBA_LEVELS-1] is the brightest
2959           int mapindex = ((NUM_RGBA_LEVELS-1-i) * 34) / NUM_RGBA_LEVELS;
2960           double colorper, fadeper;
2961           if( mapindex <= fadestart )
2962           {
2963               colorper = 1.0; // rgba = color
2964               fadeper = 0.0;
2965           }
2966           else if( mapindex < fadeend )
2967           {
2968               // mapindex != fadeend, fadeend != fadestart
2969               // proportional ramp from color to fade color
2970               colorper = ((double)(fadeend-mapindex))/(fadeend-fadestart);
2971               fadeper = 1.0 - colorper;
2972           }
2973           else
2974           {
2975               // fadeend and after
2976               colorper = 0.0;
2977               fadeper = 1.0; // rgba = fade
2978           }
2979 
2980           RGBA_t * cp = & extra_colormap_p->rgba[i];
2981           cp->s.red = (int)( colorper*color_r + fadeper*cfade_r );
2982           cp->s.green = (int)( colorper*color_g + fadeper*cfade_g );
2983           cp->s.blue = (int)( colorper*color_b + fadeper*cfade_b );
2984           cp->s.alpha = c_alpha;
2985 #ifdef VIEW_COLORMAP_GEN
2986           GenPrintf(EMSG_info,"RGBA[%i]: %x\n", i, extra_colormap_p->rgba[i].rgba);
2987 #endif
2988       }
2989   }
2990 #endif
2991 }
2992 #undef ALPHA_TO_INT
2993 #undef HEX_TO_INT
2994 #undef ABS2
2995 
2996 
2997 //Thanks to quake2 source!
2998 //utils3/qdata/images.c
NearestColor(byte r,byte g,byte b)2999 byte NearestColor(byte r, byte g, byte b)
3000 {
3001   int dr, dg, db;
3002   int distortion;
3003   int bestdistortion = 256 * 256 * 4;
3004   int bestcolor = 0;
3005   int i;
3006 
3007   for(i = 0; i < 256; i++) {
3008     dr = r - pLocalPalette[i].s.red;
3009     dg = g - pLocalPalette[i].s.green;
3010     db = b - pLocalPalette[i].s.blue;
3011     distortion = dr*dr + dg*dg + db*db;
3012     if(distortion < bestdistortion) {
3013 
3014       if(!distortion)
3015         return i;
3016 
3017       bestdistortion = distortion;
3018       bestcolor = i;
3019     }
3020   }
3021 
3022   return bestcolor;
3023 }
3024 
3025 
3026 // Rounds off floating numbers and checks for 0 - 255 bounds
RoundUp(double number)3027 int RoundUp(double number)
3028 {
3029   if(number > 255.0)
3030     return 255;
3031   if(number < 0)
3032     return 0;
3033 
3034   if((int)number <= (int)(number -0.5))
3035     return (int)number + 1;
3036 
3037   return (int)number;
3038 }
3039 
3040 
3041 
3042 
R_ColormapNameForNum(int num)3043 char * R_ColormapNameForNum(int num)
3044 {
3045   if(num == -1)
3046     return "NONE";
3047 
3048   if(num < 0 || num > MAXCOLORMAPS)
3049   {
3050     I_SoftError("R_ColormapNameForNum: num is invalid!\n");
3051     return "NONE";
3052   }
3053 
3054   if( ! VALID_LUMP(extra_colormap_lumpnum[num]) )
3055     return "INLEVEL";  // created colormap
3056 
3057   return wadfiles[WADFILENUM(extra_colormap_lumpnum[num])]->lumpinfo[LUMPNUM(extra_colormap_lumpnum[num])].name;
3058 }
3059 
3060 
3061 #if defined( ENABLE_DRAW15 ) || defined( ENABLE_DRAW16 ) || defined( ENABLE_DRAW24 ) || defined( ENABLE_DRAW32 )
3062 //
3063 //  build a table for quick conversion from 8bpp to 15bpp, 16bpp, 24bpp, 32bpp
3064 //
3065 // covert 8 bit colors
R_Init_color8_translate(RGBA_t * palette)3066 void R_Init_color8_translate ( RGBA_t * palette )
3067 {
3068     int  i;
3069 
3070     // [WDJ] unconditional now, palette flashes etc.
3071     {
3072         for (i=0;i<256;i++)
3073         {
3074             // use palette after gamma modified
3075             register byte r = palette[i].s.red;
3076             register byte g = palette[i].s.green;
3077             register byte b = palette[i].s.blue;
3078             switch( vid.drawmode )
3079             {
3080 #ifdef ENABLE_DRAW15
3081              case DRAW15: // 15 bpp (5,5,5)
3082                color8.to16[i] = (((r >> 3) << 10) | ((g >> 3) << 5) | ((b >> 3)));
3083                break;
3084 #endif
3085 #ifdef ENABLE_DRAW16
3086              case DRAW16: // 16 bpp (5,6,5)
3087                color8.to16[i] = (((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3)));
3088                break;
3089 #endif
3090 #ifdef ENABLE_DRAW24
3091              case DRAW24:
3092                {
3093                    // different alignment from DRAW32, for speed
3094                    pixelunion32_t c32;
3095                    c32.pix24.r = r;
3096                    c32.pix24.g = g;
3097                    c32.pix24.b = b;
3098                    color8.to32[i] = c32.ui32;
3099                }
3100                break;
3101 #endif
3102 #ifdef ENABLE_DRAW32
3103              case DRAW32:
3104                {
3105                    pixelunion32_t c32;
3106                    c32.pix32.r = r;
3107                    c32.pix32.g = g;
3108                    c32.pix32.b = b;
3109                    c32.pix32.alpha = 0xFF;
3110                    color8.to32[i] = c32.ui32;
3111                }
3112                break;
3113 #endif
3114              default:
3115                break;  // should not be calling
3116             }
3117         }
3118     }
3119 
3120 }
3121 #endif
3122 
3123 #ifdef ENABLE_DRAW8_USING_12
3124 //#define COLOR12_QUALITY_CHECK
3125 // covert 8 bit colors
R_Init_color12_translate(RGBA_t * palette)3126 void R_Init_color12_translate ( RGBA_t * palette )
3127 {
3128     unsigned int i;
3129 
3130 #ifdef COLOR12_QUALITY_CHECK
3131     printf(" color12 quality check:\n" );
3132 #endif
3133 
3134     // Fill table
3135     for( i=0; i <= 0x0FFF; i++ )
3136     {
3137         // 12 bit color is  R,G,B  4 bits each.
3138         // Must shift 4 bit color up to be 8 bit color;
3139         register byte r = ((i & 0x0F00) >> 4) + 0x08;
3140         register byte g = ((i & 0x00F0)     ) + 0x08;
3141         register byte b = ((i & 0x000F) << 4) + 0x08;
3142         color12_to_8[i] = NearestColor( r, g, b );
3143 
3144 #ifdef COLOR12_QUALITY_CHECK
3145         unsigned int  b1 = ((i << 4) & 0xF0);
3146         unsigned int  g1 = ((i ) & 0xF0);
3147         unsigned int  r1 = ((i >> 4) & 0xF0);
3148         register RGBA_t p = pLocalPalette[ color12_to_8[i] ];
3149         unsigned int  er = (abs( b1 - p.s.blue ) + abs( g1 - p.s.green ) + abs( r1 - p.s.red )) * 100 / 255;  // 0 to 300%
3150         if(   ( abs( b1 - p.s.blue  ) > 0x3F )
3151            || ( abs( g1 - p.s.green ) > 0x3F )
3152            || ( abs( r1 - p.s.red   ) > 0x3F )
3153            || ( er > 99) )
3154         {
3155             printf(" color12_translate[%4i]: (%2X,%2X,%2X) ==> (%2X,%2X,%2X)  ERROR= %4i\n", i,  r1,g1,b1, p.s.red,p.s.green,p.s.blue, er );
3156         }
3157 #endif
3158     }
3159 }
3160 #endif
3161 
3162 
3163 typedef struct
3164 {
3165     byte  alpha;  // 0..255
3166     byte  opaque, clear;  // 0..100
3167 } translucent_subst_info_t;
3168 
3169 // From analyze of std translucent maps (with adjustments)
3170 static  translucent_subst_info_t   translucent_subst[] =
3171 {
3172     {131, 2, 0}, // TRANSLU_med
3173     {62, 0, 4}, // TRANSLU_more
3174     {60, 1, 22}, // TRANSLU_hi
3175     {140, 11, 0}, // TRANSLU_fire
3176     {200, 71, 3},  // TRANSLU_fx1
3177     {182, 0, 0}  // TRANSLU_75
3178 };
3179 
3180 
3181 //#define VIEW_TRANSLUMAP_GEN
3182 //#define VIEW_TRANSLUMAP_GEN_DETAIL
3183 
3184 // [WDJ] Analyze a Boom Translucent Map to derive some GL parameters
R_TranslucentMap_Analyze(translucent_map_t * transp,byte * tmap)3185 void  R_TranslucentMap_Analyze( translucent_map_t * transp, byte * tmap )
3186 {
3187     // Analyze the Boom translucent map for rgb drawing.
3188     byte * tstcolor = & doom_analyze_index[0];  // colors to test
3189     int ti;
3190 
3191     if( EN_heretic )
3192        tstcolor = & heretic_analyze_index[0];  // heretic colors to test
3193 
3194     float h4 = 0.0; // alpha = 0
3195     int alpha;
3196     int tot_cnt = 0;
3197     int opaque_cnt = 0;
3198     int clear_cnt = 0;
3199     int dd4, dn4, k1, k2;
3200     // tm3 = i1 * (1-alpha) + i2 * alpha
3201     // alpha = (i1-tm3) / (i1-i2)
3202     for( k1=0; k1<NUM_ANALYZE_COLORS; k1++ )
3203     {
3204         byte i1 = tstcolor[k1];  // background
3205         for( k2=0; k2<NUM_ANALYZE_COLORS; k2++ )
3206         {
3207             if( k1 == k2 ) continue;
3208             byte i2 = tstcolor[k2];  // translucent
3209             byte tm3 = tmap[ (i2<<8) + i1 ];
3210             // for each color
3211             int krgb;
3212 #ifdef  VIEW_TRANSLUMAP_GEN_DETAIL
3213 GenPrintf(EMSG_info, "bg(%i,%i,%i):fb(%i,%i,%i):>(%i,%i,%i) ",
3214   pLocalPalette[i1].s.red,pLocalPalette[i1].s.green,pLocalPalette[i1].s.blue,
3215   pLocalPalette[i2].s.red,pLocalPalette[i2].s.green,pLocalPalette[i2].s.blue,
3216   pLocalPalette[tm3].s.red,pLocalPalette[tm3].s.green,pLocalPalette[tm3].s.blue
3217 );
3218 #endif
3219             for( krgb=0; krgb<3; krgb++ )  // red, green, blue
3220             {
3221                 // alpha = (i1-tm3) / (i1-i2)
3222                 switch( krgb )
3223                 {
3224                  case 0: // red
3225                    dd4 = (int)pLocalPalette[i1].s.red -  (int)pLocalPalette[i2].s.red;
3226                    dn4 = (int)pLocalPalette[i1].s.red - (int)pLocalPalette[tm3].s.red;
3227                    break;
3228                  case 1: // green
3229                    dd4 = (int)pLocalPalette[i1].s.green -  (int)pLocalPalette[i2].s.green;
3230                    dn4 = (int)pLocalPalette[i1].s.green - (int)pLocalPalette[tm3].s.green;
3231                    break;
3232                  default: // blue
3233                    dd4 = (int)pLocalPalette[i1].s.blue -  (int)pLocalPalette[i2].s.blue;
3234                    dn4 = (int)pLocalPalette[i1].s.blue - (int)pLocalPalette[tm3].s.blue;
3235                    break;
3236                 }
3237                 // eliminate cases where equation is least accurate
3238                 if( dn4 && (dd4 > 10.0 || dd4 < -10.0))
3239                 {
3240                     float h3 = (float)dn4 / (float)dd4;
3241 #ifdef VIEW_TRANSLUMAP_GEN_DETAIL
3242                     GenPrintf(EMSG_info, " %i", (int)(h3*255) );
3243 #endif
3244                     // eliminate wierd alpha (due to color quantization in making the transmap)
3245                     if( h3 > 0.0 && h3 < 1.1 )
3246                     {
3247                         h4 += h3;  // total for avg
3248                         tot_cnt ++;
3249                         if( h3 > 0.9 )   opaque_cnt++;
3250                         if( h3 < 0.1 )   clear_cnt++;
3251                     }
3252                 }
3253 #ifdef VIEW_TRANSLUMAP_GEN_DETAIL
3254                 else
3255                 {
3256                     GenPrintf(EMSG_info, " -" );
3257                 }
3258 #endif
3259             }
3260 #ifdef VIEW_TRANSLUMAP_GEN_DETAIL
3261             GenPrintf(EMSG_info,"\n");
3262 #endif
3263         }
3264     }
3265     alpha = (int) (255.0 * h4 / tot_cnt);
3266     if( alpha > 255 )  alpha = 255;
3267     if( alpha < 0 )    alpha = 0;
3268     transp->alpha = alpha;
3269     transp->opaque = (opaque_cnt*100)/tot_cnt;
3270     transp->clear = (clear_cnt*100/tot_cnt);
3271     transp->substitute_std_translucent = TRANSLU_med;  // default
3272     transp->substitute_error = 255;
3273     {
3274         // find closest standard transparency
3275         float bestdist = 1E20;
3276         for(ti=1; ti<TRANSLU_75; ti++)
3277         {
3278             translucent_subst_info_t * tinfop = & translucent_subst[ti-1];
3279             float dista = tinfop->alpha - alpha;  // 0..255
3280             float distop = tinfop->opaque - transp->opaque;  // 0..100
3281             float distcl = tinfop->clear - transp->clear;  // 0..100
3282             float dist = (dista*dista) + (distop*distop) + (distcl*distcl);
3283             if( dist < bestdist )
3284             {
3285                 bestdist = dist;
3286                 dist *= (255.0/(40.0*40.0 + 20.0*20.0  + 10.0*10.0));
3287                 if( dist > 255 )  dist = 255;
3288                 transp->substitute_error = dist;
3289                 transp->substitute_std_translucent = ti;
3290             }
3291         }
3292     }
3293 #ifdef VIEW_TRANSLUMAP_GEN
3294     // Enable to see results of analysis.
3295     GenPrintf(EMSG_info,
3296              "Analyze Trans: alpha=%i  opaque=%i%%  clear=%i%%  subst=%i  subst_err=%i\n",
3297               alpha, transp->opaque, transp->clear,
3298               transp->substitute_std_translucent, transp->substitute_error);
3299 #endif
3300 }
3301 
3302 #define TRANSLU_STORE_INC  8
3303 translucent_map_t *  translu_store = NULL;
3304 int translu_store_num = 0;
3305 int translu_store_len = 0;
3306 
3307 // Return translu_store index
R_setup_translu_store(int lump_num)3308 int  R_setup_translu_store( int lump_num )
3309 {
3310    int ti;
3311    translucent_map_t * tranlu_map;
3312    // check if already in store
3313    for(ti=0; ti< translu_store_num; ti++ )
3314    {
3315        if( translu_store[ti].translu_lump_num == lump_num )
3316           goto done;
3317    }
3318    // check for expand store
3319    if( translu_store_num >= translu_store_len )
3320    {
3321        translu_store_len += TRANSLU_STORE_INC;
3322        translu_store = realloc( translu_store, translu_store_len );
3323        if( translu_store == NULL )
3324           I_Error( "Translucent Store: cannot alloc\n" );
3325    }
3326    // create new store and fill it in
3327    ti = translu_store_num++;
3328    tranlu_map = & translu_store[ti];
3329    tranlu_map->translu_lump_num = lump_num;
3330    R_TranslucentMap_Analyze( tranlu_map, W_CacheLumpNum( lump_num, PU_CACHE ) );
3331    if( verbose>1 )
3332       GenPrintf(EMSG_ver, "TRANSLU STORE lump=%i, subst=%i\n", lump_num, tranlu_map->substitute_std_translucent );
3333 done:
3334    return ti;
3335 }
3336 
3337 #if 0
3338 // [WDJ] Only enable to setup colormap analyze tables
3339 #define ANALYZE_GAMEMAP
3340 void Analyze_gamemap( void )
3341 {
3342 #define NUMTESTCOLOR  8
3343     // For new port, analyze the colormap to find white, grey, red, blue, green.
3344     // This only affects this color analyzer, and is not fatal.
3345     static const char * name[NUMTESTCOLOR]=
3346      {"white", "light grey", "med grey", "dark grey", "grayblack", "red", "green", "blue" };
3347     typedef struct { byte red, green, blue; } test_rgb_t;
3348     static const test_rgb_t ideal[NUMTESTCOLOR]=
3349      {{255,255,255}, {192,192,192}, {128,128,128}, {64,64,64}, {10,10,10}, {100,0,0}, {0,100,0}, {0,0,100} };
3350     float bestdist[NUMTESTCOLOR];
3351     byte bestcolor[NUMTESTCOLOR];
3352     int i, k;
3353 
3354     GenPrintf(EMSG_info, "Game colormap analyze:\n" );
3355     for(k=0; k<8; k++ )   bestdist[k] = 1E20;
3356 
3357     for(i=0; i<256; i++)
3358     {
3359         int cr = pLocalPalette[i].s.red;
3360         int cg = pLocalPalette[i].s.green;
3361         int cb = pLocalPalette[i].s.blue;
3362         for(k=0; k<NUMTESTCOLOR; k++ )
3363         {
3364             float dr = cr - ideal[k].red;
3365             float dg = cg - ideal[k].green;
3366             float db = cb - ideal[k].blue;
3367             float d = dr*dr + dg*dg + db*db;
3368             if( d < bestdist[k] )
3369             {
3370                 bestdist[k] = d;
3371                 bestcolor[k] = i;
3372             }
3373         }
3374     }
3375     for(k=0; k<NUMTESTCOLOR; k++ )
3376     {
3377         GenPrintf(EMSG_info, "Analyze Index %s = %i\n", name[k], bestcolor[k] );
3378     }
3379 }
3380 #endif
3381 
3382 #if 0
3383 // [WDJ] Only enable to setup translucent analyze tables
3384 #define ANALYZE_TRANSLUCENT_MAPS
3385 void Analyze_translucent_maps( void )
3386 {
3387     // translucent maps
3388     translucent_map_t trans;
3389     int k;
3390     GenPrintf(EMSG_info, "Game translucent maps analyze:\n" );
3391     if( translucenttables == NULL )   return;
3392     for(k=1; k<=TRANSLU_fx1; k++ )  // Doom2 maps
3393     {
3394         byte * tmap = & translucenttables[ TRANSLU_TABLE_INDEX(k) ];
3395         if( tmap )
3396         {
3397             GenPrintf(EMSG_info, "  Analyze translucent map %i:\n", k );
3398             R_TranslucentMap_Analyze( &trans, tmap);
3399         }
3400     }
3401 }
3402 #endif
3403 
3404 
3405 // Table of alpha = 0..255 to translucent tables to be used for r_draw8
3406 // For use by DRAW8PAL, Not for draw modes that can use dr_alpha.
3407 // index by alpha >> 4
3408 const unsigned int  translucent_alpha_table[16] =
3409 {
3410    // hi=10..15%, more=20..25%, med=50%
3411    TRANSLU_TABLE_hi,   // 0..15    ( 0.. 6%)
3412    TRANSLU_TABLE_hi,   // 16..31   ( 6..12%)
3413    TRANSLU_TABLE_hi,   // 32..47   (12..18%)
3414    TRANSLU_TABLE_more, // 48..63   (18..25%)
3415    TRANSLU_TABLE_more, // 64..79   (25..31%)
3416    TRANSLU_TABLE_more, // 80..95   (31..37%)
3417    TRANSLU_TABLE_med,  // 96..111  (37..43%)
3418    TRANSLU_TABLE_med,  // 112..127 (44..50%)
3419    TRANSLU_TABLE_med,  // 128..143 (50..56%)
3420  // reversed table usage, per TRANSLU_REV_ALPHA
3421    TRANSLU_TABLE_med,  // 144..159 (56..62%)
3422    TRANSLU_TABLE_more, // 160..177 (63..69%)
3423    TRANSLU_TABLE_more, // 176..191 (69..75%)
3424    TRANSLU_TABLE_more, // 192..207 (75..81%)
3425    TRANSLU_TABLE_hi,   // 208..223 (81..87%)
3426    TRANSLU_TABLE_hi,   // 224..239 (88..93%)
3427    TRANSLU_TABLE_hi,   // 240..255 (94..100%)
3428 };
3429 
3430 
3431 
3432 // Fake floor fog and water effect structure
3433 #define FWE_STORE_INC  16
3434 fogwater_t *  fweff = NULL;  // array
3435 // 0 of the array is not used
3436 static int fweff_num = 0;
3437 static int fweff_len = 0;  // num allocated
3438 
R_get_fweff(void)3439 int  R_get_fweff( void )
3440 {
3441    // check for expand store
3442    if( fweff_num >= fweff_len )
3443    {
3444        fweff_len += FWE_STORE_INC;
3445        fweff = (fogwater_t*) realloc( fweff, fweff_len * sizeof(fogwater_t) );
3446        if( fweff == NULL )
3447           I_Error( "Fog Store: cannot alloc\n" );
3448    }
3449    memset( &fweff[fweff_num], 0, sizeof( fogwater_t ) );
3450    return fweff_num++;
3451 }
3452 
3453 
3454 // update config settings
R_FW_config_update(void)3455 void R_FW_config_update( void )
3456 {
3457    int i;
3458    // If not init yet, then init will call this again
3459    if( ! fweff )
3460        return;
3461 
3462    // defaults affected by controls
3463    fweff[1].effect = (fogwater_effect_e) cv_water_effect.value;
3464    fweff[2].effect = (fogwater_effect_e) cv_fog_effect.value;
3465    fweff[3].effect = fweff[1].effect;
3466    // update all fweff settings that were defaulted
3467    for( i=5; i<fweff_num; i++ )
3468    {
3469        byte fwf = fweff[i].flags;
3470        fogwater_t * def = & fweff[ fwf & FWF_index ];
3471        if( fwf & FWF_default_effect )
3472        {
3473            fweff[i].effect = def->effect;
3474        }
3475        if( fwf & FWF_default_alpha )
3476        {
3477            fweff[i].alpha = def->alpha;
3478            fweff[i].fsh_alpha = def->fsh_alpha;
3479        }
3480    }
3481    // Must also change the affected FakeFloor flags
3482    P_Config_FW_Specials ();
3483 }
3484 
3485 // start of level
R_Clear_FW_effect(void)3486 void R_Clear_FW_effect( void )
3487 {
3488     if( ! fweff )  // no memory yet
3489     {
3490         // init
3491         R_get_fweff();  // [0] unused
3492         R_get_fweff();  // [1] water
3493         R_get_fweff();  // [2] fog
3494         R_get_fweff();  // [3] opaque water
3495         R_get_fweff();  // [4] solid floor
3496         fweff[0].effect = FW_clear; // unused
3497         fweff[0].alpha = 0;
3498         fweff[0].fsh_alpha = 0;
3499         fweff[0].flags = 0;
3500         fweff[1].effect = FW_clear;
3501         fweff[1].alpha = 128;  // default water alpha
3502         fweff[1].fsh_alpha = 128;
3503         fweff[1].flags = FWF_water | FWF_default_alpha | FWF_default_effect;
3504         fweff[2].effect = FW_fogdust;
3505         fweff[2].alpha = 110;  // default fog alpha
3506         fweff[2].fsh_alpha = 110 * 0.90;
3507         fweff[2].flags = FWF_fog | FWF_default_alpha | FWF_default_effect;
3508         fweff[3].effect = FW_clear;
3509         fweff[3].alpha = 190;  // default opaque water
3510         fweff[3].fsh_alpha = 190;
3511         fweff[3].flags = FWF_opaque_water | FWF_default_alpha | FWF_default_effect;
3512         fweff[4].effect = FW_clear;  // does not matter
3513         fweff[4].alpha = 128;  // default solid translucent floor
3514         fweff[4].fsh_alpha = 128;
3515         fweff[4].flags = FWF_solid_floor;  // not settable defaults
3516         R_FW_config_update();  // config settings
3517     }
3518     fweff_num = 5;  // only save the defaults
3519 }
3520 
3521 
3522 // Create Fog Effect from texture name string
3523 // Syntax: #aaaN
3524 // where aaa is alpha, in decimal, 0..255
3525 // where N is fog_effect, from this table
3526 fogwater_effect_e  fwe_code_table[FW_num] =
3527 {
3528    FW_clear,     // 'A' no fog  (old WATER default)
3529    FW_cast,      // 'B' paint all surfaces with textures
3530    FW_colormap,  // 'C' use colormap fog (which only colors all sectors)
3531    FW_inside,    // 'D' render inside side, plane views (old FOG)
3532    FW_foglite,   // 'E' outside side, plane views, low alpha overall fog sheet
3533    FW_fogdust,   // 'F' outside, when in fog apply overall fog sheet (FOG default)
3534    FW_fogsheet,  // 'G' outside, overall fog sheet, sector join fog sheet
3535    FW_fogfluid,  // 'H' outside, inside fluid, fogsheet
3536 };
3537 
3538 
3539 // return index into fweff
R_Create_FW_effect(int special_linedef,char * tstr)3540 int R_Create_FW_effect( int special_linedef, char * tstr )
3541 {
3542     int def_index =  // of fweff[]
3543        ( special_linedef == 304 )? FWF_opaque_water  // opaque water
3544      : ( special_linedef == 302 )? FWF_fog           // fog
3545      : ( special_linedef == 301 )? FWF_water         // water
3546      : ( special_linedef == 300 )? FWF_solid_floor   // solid floor
3547      : 0;
3548     int fwe_index;
3549     byte wflags = 0;
3550     fogwater_t * fwp;
3551 
3552     if( tstr[0] != '#' )
3553     {
3554         return def_index;  // can use a default
3555     }
3556     // make a unique entry for this situation
3557     fwe_index = R_get_fweff();
3558     fwp = &fweff[fwe_index];
3559     fwp->effect = fweff[def_index].effect;  // get default settings
3560     fwp->alpha = fweff[def_index].alpha;
3561     wflags = fweff[def_index].flags;
3562 
3563     if( tstr[0] == '#')  // decode upper texture string
3564     {
3565         // alpha
3566         fwp->alpha = CHAR_TO_INT(tstr[1])*100 + CHAR_TO_INT(tstr[2])*10 + CHAR_TO_INT(tstr[3]);
3567         wflags &= ~ FWF_default_alpha;
3568         // fog type
3569         char chf = tstr[4];
3570         if( chf >= 'A' && chf <= ('A'+FW_num) )
3571         {
3572             fwp->effect = fwe_code_table[ chf - 'A' ];
3573             wflags &= ~ FWF_default_effect;
3574         }
3575     }
3576     if( special_linedef == 300 )  // FWF_solid_floor
3577     {
3578         fwp->effect = FW_clear;  // no internal fog effect
3579     }
3580     switch( fwp->effect )
3581     {
3582      case FW_foglite:
3583         fwp->fsh_alpha = fwp->alpha * 0.60;
3584         break;
3585      case FW_fogdust:
3586         fwp->fsh_alpha = fwp->alpha * 0.90;
3587         break;
3588      case FW_fogsheet:
3589         fwp->fsh_alpha = fwp->alpha * 0.80;
3590         break;
3591      case FW_fogfluid:
3592      default:
3593         fwp->fsh_alpha = fwp->alpha;
3594         break;
3595     }
3596     fwp->flags = wflags;
3597     return fwe_index;
3598 }
3599 
3600 
3601 // R_Load_Data
3602 // Locates all the lumps that will be used by all views
3603 // Must be called after W_Init.
3604 //
R_Load_Data(void)3605 void R_Load_Data (void)
3606 {
3607     CONS_Printf ("\nLoad Textures...");
3608     R_Load_Textures ();
3609     CONS_Printf ("\nLoad Flats...");
3610     R_Load_Flats ();
3611 
3612     CONS_Printf ("\nInitSprites...\n");
3613     R_Init_SpriteLumps ();
3614     R_Init_Sprites (sprnames);
3615 
3616     CONS_Printf ("\nLoad Colormaps...\n");
3617     R_Load_Colormaps ();
3618 #ifdef ANALYZE_GAMEMAP
3619     Analyze_gamemap();
3620 #endif
3621 }
3622 
3623 
3624 //
3625 // R_CheckTextureNumForName
3626 // Check whether texture is available.
3627 // Filter out NoTexture indicator.
3628 //
3629 // [WDJ] Original Doom bug: conflict between texture[0] and 0=no-texture.
3630 //
3631 // Parameter name is 8 char without term.
3632 // Return -1 for not found, 0 for no texture
R_CheckTextureNumForName(const char * name)3633 int  R_CheckTextureNumForName (const char *name)
3634 {
3635     int  i;
3636 
3637     // "NoTexture" marker.
3638     if (name[0] == '-')
3639         return 0;
3640 
3641     for (i=FIRST_TEXTURE ; i<numtextures ; i++)
3642         if (!strncasecmp (textures[i]->name, name, 8) )
3643             return i;
3644 #ifdef RANGECHECK
3645     if( i == 0 )
3646         GenPrintf(EMSG_warn, "Texture %8.8s  is texture[0], imitates no-texture.\n", name);
3647 #endif
3648 
3649     return -1;
3650 }
3651 
3652 
3653 
3654 //
3655 // R_TextureNumForName
3656 // Calls R_CheckTextureNumForName,
3657 //
3658 // Return  0 for no texture "-".
3659 // Return default texture when texture not found (would HOM otherwise).
3660 // Parameter name is 8 char without term.
3661 // Is used for side_t texture fields, which are used for array access
3662 // without further error checks, so never returns -1.
R_TextureNumForName(const char * name)3663 int R_TextureNumForName (const char* name)
3664 {
3665     int i;
3666 
3667     i = R_CheckTextureNumForName (name);
3668 #if 0
3669 // [WDJ] DEBUG TRACE, to see where textures have ended up and which are accessed.
3670 #  define trace_SIZE 512
3671    static char debugtrace_RTNFN[ trace_SIZE ];
3672    if( i<trace_SIZE && debugtrace_RTNFN[i] != 0x55 ) {
3673       debug_Printf( "Texture %8.8s is texture[%i]\n", name, i);
3674       debugtrace_RTNFN[i] = 0x55;
3675    }
3676 #  undef trace_SIZE
3677 #endif
3678 
3679     if(i==-1)
3680     {
3681         // Exclude # parameters from "not found" message.
3682         // Prevent warning due to using signed char as index
3683         if( isalpha((unsigned char) name[0]) )
3684             I_SoftError("R_TextureNumForName: %.8s not found\n", name);
3685 
3686         i=1;	// default to texture[1]
3687     }
3688     return i;
3689 }
3690 
3691 
3692 
3693 
3694 //
3695 // R_PrecacheLevel
3696 // Preloads all relevant graphics for the level.
3697 //
3698 
R_PrecacheLevel(void)3699 void R_PrecacheLevel (void)
3700 {
3701     char*  texturepresent;
3702     char*  spritepresent;
3703 
3704     int i,j,k,n;
3705     lumpnum_t  lumpnum;
3706 
3707     thinker_t*          th;
3708     spriteframe_t *     sf;
3709     sprite_frot_t *     sv;
3710 
3711     //int numgenerated;  //faB:debug
3712 
3713     if (demoplayback)
3714         return;
3715 
3716     // do not flush the memory, Z_Malloc twice with same user
3717     // will cause error in Z_CheckHeap(), 19991022 by Kin
3718     if (rendermode != render_soft)
3719         return;
3720 
3721     // Precache flats.
3722     flatmemory = P_PrecacheLevelFlats();
3723 
3724     //
3725     // Precache textures.
3726     //
3727     // no need to precache all software textures in 3D mode
3728     // (note they are still used with the reference software view)
3729     texturepresent = calloc(numtextures,sizeof(char));  // temp alloc, zeroed
3730 
3731     for (i=0 ; i<numsides ; i++)
3732     {
3733         // for all sides
3734         // texture num 0=no-texture, otherwise is valid texture
3735 #if 1
3736         if (sides[i].toptexture)
3737             texturepresent[sides[i].toptexture] = 1;
3738         if (sides[i].midtexture)
3739             texturepresent[sides[i].midtexture] = 1;
3740         if (sides[i].bottomtexture)
3741             texturepresent[sides[i].bottomtexture] = 1;
3742 #else
3743         //Hurdler: huh, a potential bug here????
3744         if (sides[i].toptexture < numtextures)
3745             texturepresent[sides[i].toptexture] = 1;
3746         if (sides[i].midtexture < numtextures)
3747             texturepresent[sides[i].midtexture] = 1;
3748         if (sides[i].bottomtexture < numtextures)
3749             texturepresent[sides[i].bottomtexture] = 1;
3750 #endif
3751     }
3752 
3753 #if 0
3754     // Sky texture is always present.
3755     // Note that F_SKY1 is the name used to
3756     //  indicate a sky floor/ceiling as a flat,
3757     //  while the sky texture is stored like
3758     //  a wall texture, with an episode dependent name.
3759     texturepresent[sky_texture] = 1;
3760 #endif
3761 
3762     //if (devparm)
3763     //    GenPrintf(EMSG_dev, "Generating textures..\n");
3764 
3765     texturememory = 0;  // global
3766     for (i=FIRST_TEXTURE ; i<numtextures ; i++)
3767     {
3768         if (!texturepresent[i])
3769             continue;
3770 
3771         //texture = textures[i];
3772         if( texture_render[i].cache == NULL )
3773              R_GenerateTexture2 ( i, &texture_render[i], TM_none );
3774         //numgenerated++;
3775 
3776         // note: pre-caching individual patches that compose textures became
3777         //       obsolete since we now cache entire composite textures
3778     }
3779     //debug_Printf("total mem for %d textures: %d k\n",numgenerated,texturememory>>10);
3780     free(texturepresent);
3781 
3782     //
3783     // Precache sprites.
3784     //
3785     spritepresent = calloc(numsprites,sizeof(char));  // temp alloc, zeroed
3786 
3787     for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
3788     {
3789         if (th->function.acp1 == (actionf_p1)P_MobjThinker)
3790             spritepresent[((mobj_t *)th)->sprite] = 1;
3791     }
3792 
3793     spritememory = 0;
3794     for (i=0 ; i<numsprites ; i++)
3795     {
3796         if (!spritepresent[i])
3797             continue;
3798 
3799         for (j=0 ; j<sprites[i].numframes ; j++)
3800         {
3801             sf = get_spriteframe( &sprites[i], j );
3802             n = srp_to_num_rot[ sf->rotation_pattern ];
3803             for (k=0 ; k<n ; k++)
3804             {
3805                 sv = get_framerotation( &sprites[i], j, k );
3806                 //Fab: see R_Init_Sprites for more about pat_lumpnum,lumpid
3807                 lumpnum = sv->pat_lumpnum;
3808                 if(devparm)
3809                    spritememory += W_LumpLength(lumpnum);
3810                 W_CachePatchNum( lumpnum, PU_CACHE );
3811             }
3812         }
3813     }
3814     free(spritepresent);
3815 
3816     //FIXME: this is no more correct with glide render mode
3817     if (devparm)
3818     {
3819         GenPrintf(EMSG_dev,
3820                     "Precache level done:\n"
3821                     "flatmemory:    %ld k\n"
3822                     "texturememory: %ld k\n"
3823                     "spritememory:  %ld k\n", flatmemory>>10, texturememory>>10, spritememory>>10 );
3824     }
3825 #ifdef ANALYZE_TRANSLUCENT_MAPS
3826     // maps are loaded by now
3827     Analyze_translucent_maps();
3828 #endif
3829 }
3830 
3831 
R_Init_rdata(void)3832 void R_Init_rdata(void)
3833 {
3834     int i;
3835 
3836     // clear for easier debugging
3837     memset(extra_colormaps, 0, sizeof(extra_colormaps));
3838 
3839     for(i = 0; i < MAXCOLORMAPS; i++)
3840     {
3841         extra_colormap_lumpnum[i] = NO_LUMP;
3842         extra_colormaps[i].colormap = NULL;
3843     }
3844 }
3845 
3846 // Upon change in rendermode.
R_rdata_setup_rendermode(void)3847 void R_rdata_setup_rendermode( void )
3848 {
3849     int i;
3850 
3851     // Colormaps are depedent upon rendermode.
3852     for( i=0; i<num_extra_colormaps; i++ )
3853     {
3854         if( VALID_LUMP( extra_colormap_lumpnum[i] ) )
3855         {
3856             // Analyze the lump
3857             R_Colormap_Analyze( i );
3858         }
3859         else
3860         {
3861             // Create from parameters
3862             R_Create_Colormap_ex( & extra_colormaps[i] );
3863         }
3864     }
3865 }
3866