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