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