]> icculus.org git repositories - taylor/freespace2.git/blob - src/palman/palman.cpp
The Great Newline Fix
[taylor/freespace2.git] / src / palman / palman.cpp
1 /*
2  * $Logfile: /Freespace2/code/Palman/PalMan.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Palette manager routines
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:48  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:10  root
14  * Initial import.
15  *
16  * 
17  * 5     3/31/99 8:24p Dave
18  * Beefed up all kinds of stuff, incluging beam weapons, nebula effects
19  * and background nebulae. Added per-ship non-dimming pixel colors.
20  * 
21  * 4     2/05/99 12:52p Dave
22  * Fixed Glide nondarkening textures.
23  * 
24  * 3     2/03/99 6:06p Dave
25  * Groundwork for FS2 PXO usertracker support.  Gametracker support next.
26  * 
27  * 2     10/07/98 10:53a Dave
28  * Initial checkin.
29  * 
30  * 1     10/07/98 10:50a Dave
31  * 
32  * 55    5/20/98 9:46p John
33  * added code so the places in code that change half the palette don't
34  * have to clear the screen.
35  * 
36  * 54    5/16/98 4:37p John
37  * 
38  * 53    5/16/98 4:34p John
39  * fixed bug where only colors divisible by 4 would work.
40  * 
41  * 52    5/15/98 3:28p John
42  * fixed bug with blue nondarkening colors
43  * 
44  * 51    5/14/98 3:38p John
45  * Added in more non-darkening colors for Adam.  Had to fix some bugs in
46  * BmpMan and Ani stuff to get this to work.
47  * 
48  * 50    5/13/98 10:22p John
49  * Added cfile functions to read/write rle compressed blocks of data.
50  * Made palman use it for .clr files.  Made alphacolors calculate on the
51  * fly rather than caching to/from disk.
52  * 
53  * 49    4/30/98 4:53p John
54  * Restructured and cleaned up cfile code.  Added capability to read off
55  * of CD-ROM drive and out of multiple pack files.
56  * 
57  * 48    4/20/98 4:44p John
58  * Fixed problems with black being xparent on model cache rneders.  Made
59  * model cache key off of detail level setting and framerate.
60  * 
61  * 47    4/15/98 5:44p John
62  * Made no colors except green map to 0,255,0
63  * 
64  * 46    4/09/98 11:04p John
65  * Changed ID's in output files to make more sense.
66  * 
67  * 45    4/01/98 5:35p John
68  * Made only the used POFs page in for a level.   Reduced some interp
69  * arrays.    Made custom detail level work differently.
70  * 
71  * 44    3/25/98 8:08p John
72  * Restructured software rendering into two modules; One for windowed
73  * debug mode and one for DirectX fullscreen.   
74  * 
75  * 43    3/24/98 3:58p John
76  * Put in (hopefully) final gamma setting code.
77  * 
78  * 42    2/24/98 1:59p John
79  * Made fade table use a gamma
80  * 
81  * 41    1/29/98 8:18a John
82  * Put in some commented out hooks for RGB lighting
83  * 
84  * 40    1/19/98 6:15p John
85  * Fixed all my Optimized Build compiler warnings
86  * 
87  * 39    1/10/98 1:14p John
88  * Added explanation to debug console commands
89  * 
90  * 38    12/21/97 4:33p John
91  * Made debug console functions a class that registers itself
92  * automatically, so you don't need to add the function to
93  * debugfunctions.cpp.  
94  * 
95  * 37    12/17/97 5:11p John
96  * Added brightening back into fade table.  Added code for doing the fast
97  * dynamic gun flashes and thruster flashes.
98  * 
99  * 36    12/17/97 1:16p John
100  * Made bright white not fade.
101  * 
102  * 35    12/03/97 4:48p Adam
103  * JOHN: Made engine glow scale, made thrust blend be additive.
104  * 
105  * 34    12/02/97 4:00p John
106  * Added first rev of thruster glow, along with variable levels of
107  * translucency, which retquired some restructing of palman.
108  * 
109  * 33    11/22/97 1:05p John
110  * added back in reverse palette lookup table.
111  * 
112  * 32    11/21/97 1:32p John
113  * made palette caching work on game palette better.
114  * 
115  * 31    11/21/97 11:32a John
116  * Added nebulas.   Fixed some warpout bugs.
117  * 
118  * 30    11/14/97 12:31p John
119  * Fixed some DirectX bugs.  Moved the 8-16 xlat tables into Graphics
120  * libs.  Made 16-bpp DirectX modes know what bitmap format they're in.
121  * 
122  * 29    10/31/97 10:48a John
123  * upped clr version to force rebuild after changing palette code.
124  * 
125  * 28    10/14/97 8:08a John
126  * added a bunch more 16 bit support
127  * 
128  * 27    10/03/97 9:10a John
129  * added better antialiased line drawer
130  * 
131  * 26    9/20/97 8:16a John
132  * Made .clr files go into the Cache directory. Replaced cfopen(name,NULL)
133  * to delete a file with cf_delete.
134  * 
135  * 25    9/09/97 3:39p Sandeep
136  * warning level 4 bugs
137  * 
138  * 24    7/28/97 5:08p John
139  * changed the color blending calculations.
140  * 
141  * 23    7/17/97 11:37a John
142  * made the fullscreen and windowed use separate palette cache files.
143  * 
144  * 22    7/16/97 5:29p John
145  * added palette table caching and made scaler and liner no light tmapper
146  * do alpha blending in 8 bpp mode.
147  * 
148  * 21    7/16/97 3:07p John
149  * 
150  * 20    7/10/97 2:06p John
151  * added code to specify alphablending type for bitmaps.
152  * 
153  * 19    6/11/97 6:00p John
154  * sped up alpha matching a bit.
155  * 
156  * 18    6/11/97 5:49p John
157  * Changed palette code to only recalculate alphacolors when needed, not
158  * when palette changes.
159  * 
160  * 17    6/11/97 1:13p John
161  * Started fixing all the text colors in the game.
162  * 
163  * 16    5/21/97 11:06a Lawrance
164  * added user_palette_find()
165  * 
166  * 15    5/14/97 10:53a John
167  * fixed some discrepencies between d3d and software palette setting.
168  * 
169  * 14    5/12/97 12:27p John
170  * Restructured Graphics Library to add support for multiple renderers.
171  * 
172  * 13    4/10/97 4:47p John
173  * used .3R .5G .1B for color matching.  Made palette brightening not be
174  * quite so much.
175  * 
176  * 12    4/08/97 5:18p John
177  * First rev of decent (dynamic, correct) lighting in FreeSpace.
178  * 
179  * 11    11/26/96 6:50p John
180  * Added some more hicolor primitives.  Made windowed mode run as current
181  * bpp, if bpp is 8,16,or 32.
182  * 
183  * 10    11/26/96 2:53p Allender
184  * simplify restore palette code
185  * 
186  * 9     11/26/96 9:44a Allender
187  * allow for use of different bitmap palettes
188  *
189  * $NoKeywords: $
190  */
191
192 #include "pstypes.h"
193 #include "cfile.h"
194 #include "palman.h"
195 #include "bmpman.h"
196 #include "2d.h"
197 #include "pcxutils.h"
198 #include "parselo.h"
199 #include "grinternal.h"
200
201 #define SQUARE(x) ((x)*(x))
202
203 #define NUM_BLEND_TABLES 3
204 float blend_table_factors[NUM_BLEND_TABLES] = { 0.5f, 1.0f, 1.2f };
205
206 ubyte palette_org[256*3];
207 ubyte gr_palette[256*3];
208 ubyte gr_fade_table[(256*34)*2];
209 static ubyte palette_blend_table[NUM_BLEND_TABLES*256*256];
210
211 int palette_blend_table_calculated = 0;
212 int palette_fade_table_calculated = 0;
213
214 uint gr_palette_checksum = 0;
215
216 uint palman_screen_signature = 0;
217
218 #define LOOKUP_SIZE (64*64*64)
219 ubyte palette_lookup[64*64*64];
220
221 static char palette_name[128] = { "none" };
222
223 static int Palman_restrict_colors = 0;
224
225 //extern ubyte palette_org[256*3];
226
227 int Palman_num_nondarkening_default = 0;
228 ubyte Palman_non_darkening_default[MAX_NONDARK_COLORS][3];
229
230 int Palman_num_nondarkening = 0;
231 ubyte Palman_non_darkening[MAX_NONDARK_COLORS][3];
232
233 int palman_is_nondarkening(int r,int g, int b)
234 {
235         int i;  
236
237         for (i=0; i<Palman_num_nondarkening; i++ )      {
238                 if ( (r==Palman_non_darkening[i][0]) && (g==Palman_non_darkening[i][1]) && (b==Palman_non_darkening[i][2]) )    {
239                         return 1;
240                 }
241         }
242         return 0;
243 }
244
245 void palman_load_pixels()
246 {
247         // open pixels.tbl
248         read_file_text("pixels.tbl");
249         reset_parse();
250
251         // parse pixels 
252         while(!optional_string("#END")){
253                 // nondarkening pixel
254                 if(required_string("+ND")){
255                         stuff_byte(&Palman_non_darkening_default[Palman_num_nondarkening_default][0]);
256                         stuff_byte(&Palman_non_darkening_default[Palman_num_nondarkening_default][1]);
257                         stuff_byte(&Palman_non_darkening_default[Palman_num_nondarkening_default++][2]);
258                 }
259         }
260
261         // set this to be the active table
262         palman_set_nondarkening(Palman_non_darkening_default, Palman_num_nondarkening_default);
263 }
264
265 void palman_set_nondarkening(ubyte colors[MAX_NONDARK_COLORS][3], int size)
266 {
267         // if we're supposed to use the passed table
268         memcpy(Palman_non_darkening, colors, MAX_NONDARK_COLORS * 3);
269         Palman_num_nondarkening = size;
270 }
271
272 void palette_cache_clear()
273 {
274         int i;
275
276         for (i=0; i<LOOKUP_SIZE; i++ )  {
277                 palette_lookup[i] = 255;
278         }
279 }
280
281 int palette_cache_find( int r, int g, int b )
282 {
283         if ( !palman_is_nondarkening(r,g,b))    {
284                 int value = ((r/4)<<12)+((g/4)<<6)+(b/4);
285                 if ( palette_lookup[value] != 255 )     {
286                         return palette_lookup[value];
287                 }
288         }
289         return -1;
290 }
291
292 void palette_cache_add( int r, int g, int b, int index )
293 {
294         int value = ((r/4)<<12)+((g/4)<<6)+(b/4);
295
296         if ( !palman_is_nondarkening(r,g,b))    {
297                 palette_lookup[value] = (ubyte)index;
298         }
299 }
300
301 char palette_base_filename[128] = { "default" };
302 int palette_base_loaded = 0;
303
304 void palette_load_table( char * filename )
305 {
306         int i;
307         int w, h;
308         int pcx_error;
309
310         strcpy( palette_base_filename, filename );
311         char * p = strchr(palette_base_filename,'.');
312         if ( p )        {
313                 *p = 0;
314         }
315
316         pcx_error = pcx_read_header(palette_base_filename, &w, &h, palette_org );
317         if ( pcx_error != PCX_ERROR_NONE )      {
318                 // Read the old .256 file
319                 CFILE *fp;
320                 int fsize;
321                 fp = cfopen( palette_base_filename, "rb" );
322                 if ( fp==NULL)
323                         Error( LOCATION, "Can't open palette file <%s>",palette_base_filename);
324
325                 fsize   = cfilelength( fp );
326                 Assert( fsize == 9472 );
327                 cfread( palette_org, 256*3, 1, fp );
328                 cfclose(fp);
329
330                 for (i=0; i<768; i++ )  {       
331                         palette_org[i] = ubyte((palette_org[i]*255)/63);
332                 }
333         }
334
335         palette_base_loaded = 1;
336
337         gr_set_palette(palette_base_filename, palette_org);
338 }
339
340
341 DCF(palette,"Loads a new palette")
342 {
343         if ( Dc_command )       {
344                 dc_get_arg(ARG_STRING|ARG_NONE);
345                 if ( Dc_arg_type == ARG_NONE )  {
346                 } else {
347                         palette_load_table( Dc_arg );
348                 }
349         }
350         if ( Dc_help )  {
351                 dc_printf( "Usage: palette filename\nLoads the palette file.\n" );
352         }
353
354 }
355
356 int Palman_allow_any_color = 0;
357
358
359 uint palette_find( int r, int g, int b )
360 {
361         int i, j;
362         int best_value, best_index, value;
363
364         int     is_transparent = 0;
365         if ( (r == 0) && (g==255) && (b==0) )   {
366                 is_transparent = 1;
367         }
368
369         int restrict = 0;
370         if ( Palman_restrict_colors && (!Palman_allow_any_color) )      {
371                 restrict = 1;
372         }
373                         
374 //      int     rgb = ((r/4)<<12)+((g/4)<<6)+(b/4);
375
376         i = palette_cache_find(r,g,b);
377         if ( i != -1 )  {
378                 if ( restrict ) {
379                         if ( i > 127 )  {
380                                 return i;
381                         }
382                 } else {
383                         return i;
384                 }
385         }
386
387         best_value = 1000000000;
388         best_index = -1;
389
390         int bottom_color = 0;
391         if ( restrict ) {
392                 bottom_color = 128;
393         }
394
395         j=3*bottom_color; 
396
397         for (i=bottom_color; i<255; i++ )       {
398                 int pr, pg, pb;
399
400                 pr = gr_palette[j];
401                 pg = gr_palette[j+1];
402                 pb = gr_palette[j+2];
403
404                 value = SQUARE(r-pr) + SQUARE(g-pg) + SQUARE(b-pb);
405
406                 if ( (best_index==-1) || (value < best_value) ) {
407                         // Don't map anything to 0,255,0 (transparent) ever, except 0,255,0
408                         if (value==0) {
409                                 palette_cache_add( r, g, b, i );
410                                 return i;
411                         }
412                         // Not an exact match, so don't let anything map to a nondarkening color.
413                         if ( (!is_transparent) && (!palman_is_nondarkening( pr, pg, pb ))  )    {
414                                 best_value = value;
415                                 best_index = i;
416                         }
417                 }
418                 j += 3;
419         }
420
421         if ( best_index == -1 ) {
422                 best_index = bottom_color;
423         }
424
425         palette_cache_add( r, g, b, best_index );
426         return best_index;
427 }
428
429 // version 0 - initial revision
430 // version 2 - changed 16-bpp fade table to include the 1.5 brightening factor
431 // version 3 - changed to put black in color 0 all the time
432 // version 4 - took out all truecolor lookup tables
433 // version 5 - changed palette to use 254 entries for nebula, made color mapping different
434 // version 6 - took out 1.5 brightness
435 // version 7 - added blending tables
436 // version 8 - made glows use additive blending
437 // version 9 - made 255,255,255 not fade
438 // version 10 - made fade table go to white again for anything l above 0.75.
439 // version 11 - made fade table go from 0-1 instead of 0-0.75
440 // version 12 - added variable gamma
441 // version 13 - Reduced blending tables from 5 to 3. Save 128KB RAM.
442 // version 14 - made palette never map anything to green.
443 // version 15 - made green blending with anything be black
444 // version 16 - added compression
445 // version 17 - added more nondarkening colors
446 // version 18 - fixed bug with blue nondarkening colors
447 // version 19 - fixed bug where only colors divisible by 4 got used.
448 // version 20 - added flag to only use lower 128 colors for palette.
449 #define PAL_ID 'LAPV'                   // VPAL (Volition Palette)
450 #define PAL_VERSION  20
451 #define PAL_LAST_COMPATIBLE_VERSION 20
452
453 void palette_write_cached1( char *name )
454 {
455         CFILE *fp;
456         char new_name[128];
457
458         strcpy( new_name, name );
459         strcat( new_name, ".clr" );
460         
461 //      mprintf(( "Writing palette cache file '%s'\n", new_name ));
462
463         fp = cfopen( new_name, "wb", CFILE_NORMAL, CF_TYPE_CACHE );
464         if ( !fp ) return;
465         
466         cfwrite_uint( PAL_ID, fp );
467         cfwrite_int(PAL_VERSION, fp );
468         cfwrite( &gr_palette_checksum, 4, 1, fp );
469
470         cfwrite_compressed( &gr_palette, 256*3, 1, fp );                                                // < 1 KB
471
472         cfwrite_compressed( &palette_lookup, LOOKUP_SIZE, 1, fp );                      // 256KB
473         
474         if ( palette_fade_table_calculated )    {
475                 cfwrite_int(1,fp);
476                 cfwrite_int(Gr_gamma_int,fp);
477                 cfwrite_compressed( &gr_fade_table,   256*34*2, 1, fp );                // 17KB
478         } else {
479                 cfwrite_int(0,fp);
480         }
481         
482         if ( palette_blend_table_calculated )   {
483                 cfwrite_int(NUM_BLEND_TABLES,fp);
484                 cfwrite_compressed( &palette_blend_table,  256*256, NUM_BLEND_TABLES, fp );     //64KB*
485         } else {
486                 cfwrite_int(0,fp);
487         }
488
489         cfclose(fp);
490 //      mprintf(( "Done.\n" ));
491 }
492
493 // Returns TRUE if successful, else 0
494
495 int palette_read_cached( char *name )
496 {
497         CFILE *fp;
498         char new_name[128];
499         int version;
500         uint id, new_checksum;
501         ubyte new_palette[768];
502
503         strcpy( new_name, name );
504         strcat( new_name, ".clr" );
505
506 //      mprintf(( "Reading palette '%s'\n", name ));
507         
508         fp = cfopen( new_name, "rb", CFILE_NORMAL, CF_TYPE_CACHE );
509
510         // Couldn't find file
511         if ( !fp ) {
512                 mprintf(( "No cached palette file\n" ));
513                 return 0;
514         }
515
516         id  = cfread_uint( fp );
517         if ( id != PAL_ID )     {
518                 mprintf(( "Cached palette file has incorrect ID\n" ));
519                 cfclose(fp);
520                 return 0;
521         }
522         version = cfread_int( fp );
523         if ( version < PAL_LAST_COMPATIBLE_VERSION ) {
524                 mprintf(( "Cached palette file is an older incompatible version\n" ));
525                 cfclose(fp);
526                 return 0;
527         }
528         
529         cfread( &new_checksum, 4, 1, fp );
530         if ( gr_palette_checksum != new_checksum )      {
531                 mprintf(( "Cached palette file is out of date (Checksum)\n" ));
532                 cfclose(fp);
533                 return 0;
534         }
535
536         cfread_compressed( &new_palette, 256*3, 1, fp );
537         if ( memcmp( new_palette, gr_palette, 768 ) )   {
538                 mprintf(( "Cached palette file is out of date (Contents)\n" ));
539                 cfclose(fp);
540                 return 0;
541         }
542
543         cfread_compressed( &palette_lookup, LOOKUP_SIZE, 1, fp );                       // 256KB
544
545         int fade_table_saved = cfread_int(fp);
546         
547         if ( fade_table_saved ) {
548                 int new_gamma;
549                 cfread( &new_gamma, 4, 1, fp );
550                 cfread_compressed( &gr_fade_table,   256*34*2, 1, fp );         // 17KB
551                 if ( new_gamma == Gr_gamma_int )        {
552                         palette_fade_table_calculated = 1;
553                 } else {
554                         palette_fade_table_calculated = 0;
555                 }
556         } else {
557                 palette_fade_table_calculated = 0;
558         }
559         
560         int num_blend_tables_saved = cfread_int(fp);
561         if ( (num_blend_tables_saved == NUM_BLEND_TABLES) && (num_blend_tables_saved>0))        {
562                 palette_blend_table_calculated = 1;
563                 cfread_compressed( &palette_blend_table,  256*256, NUM_BLEND_TABLES, fp );      //64KB*
564         } else {
565                 palette_blend_table_calculated = 0;
566         }
567
568         cfclose(fp);
569
570 //      mprintf(( "Done.\n" ));
571
572         return 1;
573 }
574
575 void palman_create_blend_table(float factor, ubyte *table)
576 {
577         int i;
578
579         // Make the blending table
580         for (i=0; i<256; i++ )  {
581                 int j, r, g, b;
582                 float si, fr, fg, fb, br, bg, bb;
583                 float Sf, Df;
584
585                 fr = i2fl(gr_palette[i*3+0]);
586                 fg = i2fl(gr_palette[i*3+1]);
587                 fb = i2fl(gr_palette[i*3+2]);
588
589                 // Make everything blended with Xparent be black
590                 if ( i==255 )   {
591                         fr = fg = fb = 0.0f;
592                 }
593
594                 si = (( fr+fg+fb ) / (256.0f*3.0f)) * factor;
595
596                 if ( factor > 1.0f )    {
597                         if ( si > 1.0f )        {
598                                 Sf = 1.0f;
599                                 Df = 0.0f;
600                         } else  {
601                                 Sf = 1.0f;
602                                 Df = 1.0f - si;
603                         }
604                 } else {
605                         if ( si > 1.0f )        {
606                                 Sf = 1.0f;
607                                 Df = 0.0f;
608                         } else  {
609                                 Sf = si;
610                                 Df = 1.0f;
611                         }
612                         Sf = factor;
613                         Df = 1.0f;
614                 }
615  
616 //              Sf = Df =1.0f;
617
618                 for (j=0; j<256; j++ )  {
619                         br = i2fl(gr_palette[j*3+0]);
620                         bg = i2fl(gr_palette[j*3+1]);
621                         bb = i2fl(gr_palette[j*3+2]);
622
623                         // Make all things on top of Xparent be black
624                         if ( j==255 )   {
625                                 br = bg = bb = 0.0f;
626                         }
627
628                         r = fl2i( fr*Sf + br*Df );
629                         g = fl2i( fg*Sf + bg*Df );
630                         b = fl2i( fb*Sf + bb*Df );
631
632                         int max = r;
633                         if ( g > max ) max = g;
634                         if ( b > max ) max = b;
635                         if ( max > 255 )        {
636                                 r = (255*r)/max;
637                                 g = (255*g)/max;
638                                 b = (255*b)/max;
639                         }
640                         if ( r > 255 ) r = 255; else if ( r < 0 ) r = 0;
641                         if ( g > 255 ) g = 255; else if ( g < 0 ) g = 0;
642                         if ( b > 255 ) b = 255; else if ( b < 0 ) b = 0;
643
644                         if ( i == 255 )
645                                 table[i*256+j] = (unsigned char)j;
646                         else {
647                                 // If background transparent, and color isn't bright, call it transparent.
648                                 if ( j == 255 && ((r+g+b) < 110))       {
649                                         table[i*256+j] = 255;
650                                 } else {
651                                         table[i*256+j] = (unsigned char)palette_find(r,g,b);
652                                 }
653                         }
654                 }
655         }
656 }
657
658 void palette_flush()
659 {
660         // DB 2/3/99 - I think this was causing some wacky unhandled exceptions at game shutdown. Since we don't use palettes anymore.....
661         /*
662         if ( stricmp( palette_name, "none" ) )  {
663                 palette_write_cached1( palette_name );
664         }
665         */
666 }
667
668
669 // When gr_set_palette is called, it fills in gr_palette and then calls this
670 // function, which should update all the tables.
671 // Pass NULL to flush current palette.
672 void palette_update(char *name_with_extension, int restrict_font_to_128)
673 {
674 //      int i;
675         uint tmp_checksum;
676         char name[128];
677
678         Palman_restrict_colors = restrict_font_to_128;
679         
680 //      mprintf(( "<<<<<<<<< PALETTE UPDATE (%s) >>>>>>>>>>>\n", (name_with_extension?name_with_extension:"null") ));
681
682         strcpy( name, name_with_extension );
683         char *p = strchr( name, '.' );
684         if ( p ) *p = 0;
685
686         strcpy( palette_name, name );
687
688         tmp_checksum = palette_compute_checksum( gr_palette );
689         if ( tmp_checksum == gr_palette_checksum ) return;
690
691         gr_palette_checksum = tmp_checksum;
692
693         // Clear the lookup cache, since the palette has changed
694         palette_cache_clear();
695         palette_blend_table_calculated = 0;
696         palette_fade_table_calculated = 0;
697
698         // For "none" palettes, don't calculate tables
699         if ( !stricmp( name, "none" ) ) {
700                 bm_update();                    // update the bitmap palette's
701                 return;
702         }
703
704         // Read in the cached info if there is any.
705         if ( palette_read_cached( name ) )      {
706                 bm_update();                    // update the bitmap palette's
707                 return;
708         }
709         
710         bm_update();                    // update the bitmap palette's
711 }
712
713 ubyte *palette_get_fade_table()
714 {
715         int i,l;
716
717         if ( palman_screen_signature != gr_screen.signature )   {
718                 palman_screen_signature = gr_screen.signature;
719                 palette_fade_table_calculated = 0;
720         }
721
722
723         if ( !palette_fade_table_calculated )   {
724                 //mprintf(( "Creating fading table..." ));      
725
726                 for (i=0; i<256; i++ )  {
727                         int r, g, b;
728                         int ur, ug, ub;
729                         r = gr_palette[i*3+0];
730                         g = gr_palette[i*3+1];
731                         b = gr_palette[i*3+2];
732
733                         if ( palman_is_nondarkening(r,g,b))             {
734                                 // Make pure white not fade
735                                 for (l=0; l<32; l++ )   {
736                                         gr_fade_table[((l+1)*256)+i] = (unsigned char)i;
737                                 }
738                         } else {
739                                 for (l=0; l<32; l++ )   {
740
741                                         if ( l < 24 )   {
742                                                 float f = (float)pow(i2fl(l)/23.0f, 1.0f/Gr_gamma);
743                                                 ur = fl2i(i2fl(r)*f); if ( ur > 255 ) ur = 255;
744                                                 ug = fl2i(i2fl(g)*f); if ( ug > 255 ) ug = 255;
745                                                 ub = fl2i(i2fl(b)*f); if ( ub > 255 ) ub = 255;
746                                         } else {
747                                                 int x,y;
748                                                 int gi, gr, gg, gb;
749                         
750                                                 gi = (r+g+b)/3;
751
752                                                 #ifdef RGB_LIGHTING
753                                                         gr = r;
754                                                         gg = g;
755                                                         gb = gi*2;
756                                                 #else
757                                                         gr = r*2;
758                                                         gg = g*2;
759                                                         gb = b*2;
760                                                 #endif
761                                 
762                                                 x = l-24;                       // x goes from 0 to 7
763                                                 y = 31-l;                       // y goes from 7 to 0
764
765                                                 ur = ((gr*x)+(r*y))/7; if ( ur > 255 ) ur = 255;
766                                                 ug = ((gg*x)+(g*y))/7; if ( ug > 255 ) ug = 255;
767                                                 ub = ((gb*x)+(b*y))/7; if ( ub > 255 ) ub = 255;
768                                         }
769                                         gr_fade_table[((l+1)*256)+i] = (unsigned char)palette_find( ur, ug, ub );
770
771                                 }
772                         }
773                         gr_fade_table[ (0*256)+i ] = gr_fade_table[ (1*256)+i ];
774                         gr_fade_table[ (33*256)+i ] = gr_fade_table[ (32*256)+i ];
775                 }
776
777                 // Mirror the fade table
778                 for (i=0; i<34; i++ )   {
779                         for ( l = 0; l < 256; l++ )     {
780                                 gr_fade_table[ ((67-i)*256)+l ] = gr_fade_table[ (i*256)+l ];
781                         }
782                 }
783
784 //              mprintf(( "done\n" ));  
785                 palette_fade_table_calculated = 1;
786         }
787
788         return &gr_fade_table[0];
789 }
790
791
792 ubyte *palette_get_blend_table(float alpha)
793 {
794         int i;
795
796         if ( !palette_blend_table_calculated )  {
797 //              mprintf(( "Creating blending table..." ));      
798                 for (i=0; i<NUM_BLEND_TABLES; i++ )     {
799                         palman_create_blend_table(blend_table_factors[i], &palette_blend_table[i*256*256] );
800                 }
801 //              mprintf(( "done\n" ));  
802                 palette_blend_table_calculated = 1;
803         }
804         
805         for (i=0; i<NUM_BLEND_TABLES; i++ )     {
806                 if ( alpha <= blend_table_factors[i] )  
807                         break;
808         } 
809         if ( i<0 ) i = 0;
810         if ( i>NUM_BLEND_TABLES-1 ) i = NUM_BLEND_TABLES-1;
811
812         return &palette_blend_table[i*256*256];
813 }
814
815
816
817 // compute a simple checksum on the given palette.  Used by the bitmap manager
818 // to determine if we need to reload a new palette for a bitmap.  Code liberally
819 // stolen from descent networking checksum code
820 uint palette_compute_checksum( ubyte *pal )
821 {
822         int i;
823         uint sum1, sum2;
824
825         sum1 = sum2 = 0;
826
827         for (i = 0; i < 768; i++) {
828                 sum1 += (uint)pal[i];
829                 if ( sum1 >= 255 ) sum1 -= 255;
830                 sum2 += sum1;
831         }
832         sum2 %= 255;
833
834         return ((sum1<<8)+sum2);
835 }
836
837 // this function takes a bitmap number and sets the game palette to the palette of this
838 // bitmap.
839 void palette_use_bm_palette(int n)
840 {
841         ubyte tmp[768];
842         char name[128];
843
844         bm_get_palette(n, tmp, name);                           // get the palette for this bitmap
845
846         gr_set_palette(name, tmp);                              // load the new palette.
847 }
848
849 void palette_restore_palette()
850 {
851         ubyte tmp[768];
852         memcpy(tmp, palette_org, 3*256);
853
854         if ( palette_base_loaded )              {
855                 gr_set_palette(palette_base_filename, tmp);
856         }
857 }
858