added function to create blend tables
[btb/d2x.git] / 2d / palette.c
1 /* $Id: palette.c,v 1.11 2004-05-12 22:06:02 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  * Graphical routines for setting the palette
17  *
18  * Old Log:
19  * Revision 1.41  1995/02/02  14:26:31  john
20  * Made palette fades work better with gamma thingy..
21  *
22  * Revision 1.40  1994/12/08  19:03:46  john
23  * Made functions use cfile.
24  *
25  * Revision 1.39  1994/12/01  11:23:27  john
26  * Limited Gamma from 0-8.
27  *
28  * Revision 1.38  1994/11/28  01:31:08  mike
29  * optimize color lookup function, caching recently used colors.
30  *
31  * Revision 1.37  1994/11/18  22:50:18  john
32  * Changed shorts to ints in parameters.
33  *
34  * Revision 1.36  1994/11/15  17:54:59  john
35  * Made text palette fade in when game over.
36  *
37  * Revision 1.35  1994/11/10  19:53:14  matt
38  * Fixed error handling is gr_use_palette_table()
39  *
40  * Revision 1.34  1994/11/07  13:53:48  john
41  * Added better gamma stufff.
42  *
43  * Revision 1.33  1994/11/07  13:37:56  john
44  * Added gamma correction stuff.
45  *
46  * Revision 1.32  1994/11/05  13:20:14  john
47  * Fixed bug with find_closest_color_current not working.
48  *
49  * Revision 1.31  1994/11/05  13:08:09  john
50  * MAde it return 0 when palette already faded out.
51  *
52  * Revision 1.30  1994/11/05  13:05:34  john
53  * Added back in code to allow keys during fade.
54  *
55  * Revision 1.29  1994/11/05  12:49:50  john
56  * Fixed bug with previous comment..
57  *
58  * Revision 1.28  1994/11/05  12:48:46  john
59  * Made palette only fade in / out when its supposed to.
60  *
61  * Revision 1.27  1994/11/05  12:46:43  john
62  * Changed palette stuff a bit.
63  *
64  * Revision 1.26  1994/11/01  12:59:35  john
65  * Reduced palette.256 size.
66  *
67  * Revision 1.25  1994/10/26  23:55:35  john
68  * Took out roller; Took out inverse table.
69  *
70  * Revision 1.24  1994/10/04  22:03:05  matt
71  * Fixed bug: palette wasn't fading all the way out or in
72  *
73  * Revision 1.23  1994/09/22  16:08:40  john
74  * Fixed some palette stuff.
75  *
76  * Revision 1.22  1994/09/19  11:44:31  john
77  * Changed call to allocate selector to the dpmi module.
78  *
79  * Revision 1.21  1994/09/12  19:28:09  john
80  * Fixed bug with unclipped fonts clipping.
81  *
82  * Revision 1.20  1994/09/12  18:18:39  john
83  * Set 254 and 255 to fade to themselves in fadetable
84  *
85  * Revision 1.19  1994/09/12  14:40:10  john
86  * Neatend.
87  *
88  * Revision 1.18  1994/09/09  09:31:55  john
89  * Made find_closest_color not look at superx spot of 254
90  *
91  * Revision 1.17  1994/08/09  11:27:08  john
92  * Add cthru stuff.
93  *
94  * Revision 1.16  1994/08/01  11:03:51  john
95  * MAde it read in old/new palette.256
96  *
97  * Revision 1.15  1994/07/27  18:30:27  john
98  * Took away the blending table.
99  *
100  * Revision 1.14  1994/06/09  10:39:52  john
101  * In fade out.in functions, returned 1 if key was pressed...
102  *
103  * Revision 1.13  1994/05/31  19:04:16  john
104  * Added key to stop fade if desired.
105  *
106  * Revision 1.12  1994/05/06  12:50:20  john
107  * Added supertransparency; neatend things up; took out warnings.
108  *
109  * Revision 1.11  1994/05/03  19:39:02  john
110  * *** empty log message ***
111  *
112  * Revision 1.10  1994/04/22  11:16:07  john
113  * *** empty log message ***
114  *
115  * Revision 1.9  1994/04/08  16:59:40  john
116  * Add fading poly's; Made palette fade 32 instead of 16.
117  *
118  * Revision 1.8  1994/03/16  17:21:17  john
119  * Added slow palette searching options.
120  *
121  * Revision 1.7  1994/01/07  11:47:33  john
122  * made use cflib
123  *
124  * Revision 1.6  1993/12/21  11:41:04  john
125  * *** empty log message ***
126  *
127  * Revision 1.5  1993/12/09  15:02:47  john
128  * Changed palette stuff majorly
129  *
130  * Revision 1.4  1993/12/07  12:31:41  john
131  * moved bmd_palette to gr_palette
132  *
133  * Revision 1.3  1993/10/15  16:22:23  john
134  * *** empty log message ***
135  *
136  * Revision 1.2  1993/09/26  18:59:46  john
137  * fade stuff
138  *
139  * Revision 1.1  1993/09/08  11:44:03  john
140  * Initial revision
141  *
142  */
143
144 #ifdef HAVE_CONFIG_H
145 #include <conf.h>
146 #endif
147
148 #include <stdlib.h>
149 #include <stdio.h>
150 #include <string.h>
151
152 #include "pstypes.h"
153 #include "u_mem.h"
154 #include "gr.h"
155 #include "grdef.h"
156 #include "cfile.h"
157 #include "error.h"
158 #include "mono.h"
159 #include "fix.h"
160 //added/remove by dph on 1/9/99
161 //#include "key.h"
162 //end remove
163
164 #include "palette.h"
165
166 extern int gr_installed;
167
168 #define SQUARE(x) ((x)*(x))
169
170 #define MAX_COMPUTED_COLORS     32
171
172 int     Num_computed_colors=0;
173
174 typedef struct {
175         ubyte   r,g,b,color_num;
176 } color_record;
177
178 color_record Computed_colors[MAX_COMPUTED_COLORS];
179
180 ubyte gr_palette[256*3];
181 ubyte gr_current_pal[256*3];
182 ubyte gr_fade_table[256*34];
183
184 ubyte gr_palette_gamma = 0;
185 int gr_palette_gamma_param = 0;
186 ubyte gr_palette_faded_out = 1;
187
188 int grd_fades_disabled=0;   // Used to skip fading for development
189
190 void gr_palette_set_gamma( int gamma )
191 {
192         if ( gamma < 0 ) gamma = 0;
193 //added/changed on 10/27/98 by Victor Rachels to increase brightness slider
194         if ( gamma > 16 ) gamma = 16;      //was 8
195 //end this section change - Victor Rachels
196
197         if (gr_palette_gamma_param != gamma )   {
198                 gr_palette_gamma_param = gamma;
199                 gr_palette_gamma = gamma;
200                 if (!gr_palette_faded_out)
201                         gr_palette_load( gr_palette );
202         }
203 }
204
205 int gr_palette_get_gamma()
206 {
207         return gr_palette_gamma_param;
208 }
209
210
211 void gr_copy_palette(ubyte *gr_palette, ubyte *pal, int size)
212 {
213                 memcpy(gr_palette, pal, size);
214
215                 Num_computed_colors = 0;
216 }
217
218
219 void gr_use_palette_table( char * filename )
220 {
221         CFILE *fp;
222         int i,fsize;
223 #ifdef SWAP_0_255
224         ubyte c;
225 #endif
226
227         fp = cfopen( filename, "rb" );
228
229         // the following is a hack to enable the loading of d2 levels
230         // even if only the d2 mac shareware datafiles are present.
231         // However, if the pig file is present but the palette file isn't,
232         // the textures in the level will look wierd...
233         if ( fp==NULL)
234                 fp = cfopen( DEFAULT_LEVEL_PALETTE, "rb" );
235         if ( fp==NULL)
236                 Error("Can open neither palette file <%s> "
237                       "nor default palette file <"
238                       DEFAULT_LEVEL_PALETTE
239                       ">.\n",
240                       filename);
241
242         fsize   = cfilelength( fp );
243         Assert( fsize == 9472 );
244         cfread( gr_palette, 256*3, 1, fp );
245         cfread( gr_fade_table, 256*34, 1, fp );
246         cfclose(fp);
247
248         // This is the TRANSPARENCY COLOR
249         for (i=0; i<GR_FADE_LEVELS; i++ )       {
250                 gr_fade_table[i*256+255] = 255;
251         }
252
253         Num_computed_colors = 0;        //      Flush palette cache.
254 #if defined(POLY_ACC)
255         pa_update_clut(gr_palette, 0, 256, 0);
256 #endif
257
258 // swap colors 0 and 255 of the palette along with fade table entries
259
260 #ifdef SWAP_0_255
261         for (i = 0; i < 3; i++) {
262                 c = gr_palette[i];
263                 gr_palette[i] = gr_palette[765+i];
264                 gr_palette[765+i] = c;
265         }
266
267         for (i = 0; i < GR_FADE_LEVELS * 256; i++) {
268                 if (gr_fade_table[i] == 0)
269                         gr_fade_table[i] = 255;
270         }
271         for (i=0; i<GR_FADE_LEVELS; i++)
272                 gr_fade_table[i*256] = TRANSPARENCY_COLOR;
273 #endif
274 }
275
276 //      Add a computed color (by gr_find_closest_color) to list of computed colors in Computed_colors.
277 //      If list wasn't full already, increment Num_computed_colors.
278 //      If was full, replace a random one.
279 void add_computed_color(int r, int g, int b, int color_num)
280 {
281         int     add_index;
282
283         if (Num_computed_colors < MAX_COMPUTED_COLORS) {
284                 add_index = Num_computed_colors;
285                 Num_computed_colors++;
286         } else
287                 add_index = (d_rand() * MAX_COMPUTED_COLORS) >> 15;
288
289         Computed_colors[add_index].r = r;
290         Computed_colors[add_index].g = g;
291         Computed_colors[add_index].b = b;
292         Computed_colors[add_index].color_num = color_num;
293 }
294
295 void init_computed_colors(void)
296 {
297         int     i;
298
299         for (i=0; i<MAX_COMPUTED_COLORS; i++)
300                 Computed_colors[i].r = 255;             //      Make impossible to match.
301 }
302
303 int gr_find_closest_color( int r, int g, int b )
304 {
305         int i, j;
306         int best_value, best_index, value;
307
308         if (Num_computed_colors == 0)
309                 init_computed_colors();
310
311         //      If we've already computed this color, return it!
312         for (i=0; i<Num_computed_colors; i++)
313                 if (r == Computed_colors[i].r)
314                         if (g == Computed_colors[i].g)
315                                 if (b == Computed_colors[i].b) {
316                                         if (i > 4) {
317                                                 color_record    trec;
318                                                 trec = Computed_colors[i-1];
319                                                 Computed_colors[i-1] = Computed_colors[i];
320                                                 Computed_colors[i] = trec;
321                                                 return Computed_colors[i-1].color_num;
322                                         }
323                                         return Computed_colors[i].color_num;
324                                 }
325
326 //      r &= 63;
327 //      g &= 63;
328 //      b &= 63;
329
330         best_value = SQUARE(r-gr_palette[0])+SQUARE(g-gr_palette[1])+SQUARE(b-gr_palette[2]);
331         best_index = 0;
332         if (best_value==0) {
333                 add_computed_color(r, g, b, best_index);
334                 return best_index;
335         }
336         j=0;
337         // only go to 255, 'cause we dont want to check the transparent color.
338         for (i=1; i<254; i++ )  {
339                 j += 3;
340                 value = SQUARE(r-gr_palette[j])+SQUARE(g-gr_palette[j+1])+SQUARE(b-gr_palette[j+2]);
341                 if ( value < best_value )       {
342                         if (value==0) {
343                                 add_computed_color(r, g, b, i);
344                                 return i;
345                         }
346                         best_value = value;
347                         best_index = i;
348                 }
349         }
350         add_computed_color(r, g, b, best_index);
351         return best_index;
352 }
353
354 int gr_find_closest_color_15bpp( int rgb )
355 {
356         return gr_find_closest_color( ((rgb>>10)&31)*2, ((rgb>>5)&31)*2, (rgb&31)*2 );
357 }
358
359
360 int gr_find_closest_color_current( int r, int g, int b )
361 {
362         int i, j;
363         int best_value, best_index, value;
364
365 //      r &= 63;
366 //      g &= 63;
367 //      b &= 63;
368
369         best_value = SQUARE(r-gr_current_pal[0])+SQUARE(g-gr_current_pal[1])+SQUARE(b-gr_current_pal[2]);
370         best_index = 0;
371         if (best_value==0)
372                 return best_index;
373
374         j=0;
375         // only go to 255, 'cause we dont want to check the transparent color.
376         for (i=1; i<254; i++ )  {
377                 j += 3;
378                 value = SQUARE(r-gr_current_pal[j])+SQUARE(g-gr_current_pal[j+1])+SQUARE(b-gr_current_pal[j+2]);
379                 if ( value < best_value )       {
380                         if (value==0)
381                                 return i;
382                         best_value = value;
383                         best_index = i;
384                 }
385         }
386         return best_index;
387 }
388
389 void gr_make_cthru_table(ubyte * table, ubyte r, ubyte g, ubyte b )
390 {
391         int i;
392         ubyte r1, g1, b1;
393
394         for (i=0; i<256; i++ )  {
395                 r1 = gr_palette[i*3+0] + r;
396                 if ( r1 > 63 ) r1 = 63;
397                 g1 = gr_palette[i*3+1] + g;
398                 if ( g1 > 63 ) g1 = 63;
399                 b1 = gr_palette[i*3+2] + b;
400                 if ( b1 > 63 ) b1 = 63;
401                 table[i] = gr_find_closest_color( r1, g1, b1 );
402         }
403 }
404
405 void gr_make_blend_table(ubyte *blend_table, ubyte r, ubyte g, ubyte b)
406 {
407         int i, j;
408         float alpha;
409         ubyte r1, g1, b1;
410
411         for (j = 0; j < GR_FADE_LEVELS; j++)
412         {
413                 alpha = 1.0 - (float)j / ((float)GR_FADE_LEVELS - 1);
414                 for (i = 0; i < 255; i++)
415                 {
416                         r1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 0] + (alpha * (float)r));
417                         g1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 1] + (alpha * (float)g));
418                         b1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 2] + (alpha * (float)b));
419                         blend_table[i + j * 256] = gr_find_closest_color(r1, g1, b1);
420                 }
421                 blend_table[i + j * 256] = 255; // leave white alone
422         }
423 }