]> icculus.org git repositories - btb/d2x.git/blob - 2d/palette.c
Fix crash if Num_walls=0
[btb/d2x.git] / 2d / palette.c
1 /* $Id: palette.c,v 1.12 2004-08-28 23:17:45 schaffner 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  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "pstypes.h"
29 #include "u_mem.h"
30 #include "gr.h"
31 #include "grdef.h"
32 #include "cfile.h"
33 #include "error.h"
34 #include "mono.h"
35 #include "fix.h"
36 //added/remove by dph on 1/9/99
37 //#include "key.h"
38 //end remove
39
40 #include "palette.h"
41
42 extern int gr_installed;
43
44 #define SQUARE(x) ((x)*(x))
45
46 #define MAX_COMPUTED_COLORS     32
47
48 int     Num_computed_colors=0;
49
50 typedef struct {
51         ubyte   r,g,b,color_num;
52 } color_record;
53
54 color_record Computed_colors[MAX_COMPUTED_COLORS];
55
56 ubyte gr_palette[256*3];
57 ubyte gr_current_pal[256*3];
58 ubyte gr_fade_table[256*34];
59
60 ubyte gr_palette_gamma = 0;
61 int gr_palette_gamma_param = 0;
62 ubyte gr_palette_faded_out = 1;
63
64 int grd_fades_disabled=0;   // Used to skip fading for development
65
66 void gr_palette_set_gamma( int gamma )
67 {
68         if ( gamma < 0 ) gamma = 0;
69 //added/changed on 10/27/98 by Victor Rachels to increase brightness slider
70         if ( gamma > 16 ) gamma = 16;      //was 8
71 //end this section change - Victor Rachels
72
73         if (gr_palette_gamma_param != gamma )   {
74                 gr_palette_gamma_param = gamma;
75                 gr_palette_gamma = gamma;
76                 if (!gr_palette_faded_out)
77                         gr_palette_load( gr_palette );
78         }
79 }
80
81 int gr_palette_get_gamma()
82 {
83         return gr_palette_gamma_param;
84 }
85
86
87 void gr_copy_palette(ubyte *gr_palette, ubyte *pal, int size)
88 {
89                 memcpy(gr_palette, pal, size);
90
91                 Num_computed_colors = 0;
92 }
93
94
95 void gr_use_palette_table( char * filename )
96 {
97         CFILE *fp;
98         int i,fsize;
99 #ifdef SWAP_0_255
100         ubyte c;
101 #endif
102
103         fp = cfopen( filename, "rb" );
104
105         // the following is a hack to enable the loading of d2 levels
106         // even if only the d2 mac shareware datafiles are present.
107         // However, if the pig file is present but the palette file isn't,
108         // the textures in the level will look wierd...
109         if ( fp==NULL)
110                 fp = cfopen( DEFAULT_LEVEL_PALETTE, "rb" );
111         if ( fp==NULL)
112                 Error("Can open neither palette file <%s> "
113                       "nor default palette file <"
114                       DEFAULT_LEVEL_PALETTE
115                       ">.\n",
116                       filename);
117
118         fsize   = cfilelength( fp );
119         Assert( fsize == 9472 );
120         cfread( gr_palette, 256*3, 1, fp );
121         cfread( gr_fade_table, 256*34, 1, fp );
122         cfclose(fp);
123
124         // This is the TRANSPARENCY COLOR
125         for (i=0; i<GR_FADE_LEVELS; i++ )       {
126                 gr_fade_table[i*256+255] = 255;
127         }
128
129         Num_computed_colors = 0;        //      Flush palette cache.
130 #if defined(POLY_ACC)
131         pa_update_clut(gr_palette, 0, 256, 0);
132 #endif
133
134 // swap colors 0 and 255 of the palette along with fade table entries
135
136 #ifdef SWAP_0_255
137         for (i = 0; i < 3; i++) {
138                 c = gr_palette[i];
139                 gr_palette[i] = gr_palette[765+i];
140                 gr_palette[765+i] = c;
141         }
142
143         for (i = 0; i < GR_FADE_LEVELS * 256; i++) {
144                 if (gr_fade_table[i] == 0)
145                         gr_fade_table[i] = 255;
146         }
147         for (i=0; i<GR_FADE_LEVELS; i++)
148                 gr_fade_table[i*256] = TRANSPARENCY_COLOR;
149 #endif
150 }
151
152 //      Add a computed color (by gr_find_closest_color) to list of computed colors in Computed_colors.
153 //      If list wasn't full already, increment Num_computed_colors.
154 //      If was full, replace a random one.
155 void add_computed_color(int r, int g, int b, int color_num)
156 {
157         int     add_index;
158
159         if (Num_computed_colors < MAX_COMPUTED_COLORS) {
160                 add_index = Num_computed_colors;
161                 Num_computed_colors++;
162         } else
163                 add_index = (d_rand() * MAX_COMPUTED_COLORS) >> 15;
164
165         Computed_colors[add_index].r = r;
166         Computed_colors[add_index].g = g;
167         Computed_colors[add_index].b = b;
168         Computed_colors[add_index].color_num = color_num;
169 }
170
171 void init_computed_colors(void)
172 {
173         int     i;
174
175         for (i=0; i<MAX_COMPUTED_COLORS; i++)
176                 Computed_colors[i].r = 255;             //      Make impossible to match.
177 }
178
179 int gr_find_closest_color( int r, int g, int b )
180 {
181         int i, j;
182         int best_value, best_index, value;
183
184         if (Num_computed_colors == 0)
185                 init_computed_colors();
186
187         //      If we've already computed this color, return it!
188         for (i=0; i<Num_computed_colors; i++)
189                 if (r == Computed_colors[i].r)
190                         if (g == Computed_colors[i].g)
191                                 if (b == Computed_colors[i].b) {
192                                         if (i > 4) {
193                                                 color_record    trec;
194                                                 trec = Computed_colors[i-1];
195                                                 Computed_colors[i-1] = Computed_colors[i];
196                                                 Computed_colors[i] = trec;
197                                                 return Computed_colors[i-1].color_num;
198                                         }
199                                         return Computed_colors[i].color_num;
200                                 }
201
202 //      r &= 63;
203 //      g &= 63;
204 //      b &= 63;
205
206         best_value = SQUARE(r-gr_palette[0])+SQUARE(g-gr_palette[1])+SQUARE(b-gr_palette[2]);
207         best_index = 0;
208         if (best_value==0) {
209                 add_computed_color(r, g, b, best_index);
210                 return best_index;
211         }
212         j=0;
213         // only go to 255, 'cause we dont want to check the transparent color.
214         for (i=1; i<254; i++ )  {
215                 j += 3;
216                 value = SQUARE(r-gr_palette[j])+SQUARE(g-gr_palette[j+1])+SQUARE(b-gr_palette[j+2]);
217                 if ( value < best_value )       {
218                         if (value==0) {
219                                 add_computed_color(r, g, b, i);
220                                 return i;
221                         }
222                         best_value = value;
223                         best_index = i;
224                 }
225         }
226         add_computed_color(r, g, b, best_index);
227         return best_index;
228 }
229
230 int gr_find_closest_color_15bpp( int rgb )
231 {
232         return gr_find_closest_color( ((rgb>>10)&31)*2, ((rgb>>5)&31)*2, (rgb&31)*2 );
233 }
234
235
236 int gr_find_closest_color_current( int r, int g, int b )
237 {
238         int i, j;
239         int best_value, best_index, value;
240
241 //      r &= 63;
242 //      g &= 63;
243 //      b &= 63;
244
245         best_value = SQUARE(r-gr_current_pal[0])+SQUARE(g-gr_current_pal[1])+SQUARE(b-gr_current_pal[2]);
246         best_index = 0;
247         if (best_value==0)
248                 return best_index;
249
250         j=0;
251         // only go to 255, 'cause we dont want to check the transparent color.
252         for (i=1; i<254; i++ )  {
253                 j += 3;
254                 value = SQUARE(r-gr_current_pal[j])+SQUARE(g-gr_current_pal[j+1])+SQUARE(b-gr_current_pal[j+2]);
255                 if ( value < best_value )       {
256                         if (value==0)
257                                 return i;
258                         best_value = value;
259                         best_index = i;
260                 }
261         }
262         return best_index;
263 }
264
265 void gr_make_cthru_table(ubyte * table, ubyte r, ubyte g, ubyte b )
266 {
267         int i;
268         ubyte r1, g1, b1;
269
270         for (i=0; i<256; i++ )  {
271                 r1 = gr_palette[i*3+0] + r;
272                 if ( r1 > 63 ) r1 = 63;
273                 g1 = gr_palette[i*3+1] + g;
274                 if ( g1 > 63 ) g1 = 63;
275                 b1 = gr_palette[i*3+2] + b;
276                 if ( b1 > 63 ) b1 = 63;
277                 table[i] = gr_find_closest_color( r1, g1, b1 );
278         }
279 }
280
281 void gr_make_blend_table(ubyte *blend_table, ubyte r, ubyte g, ubyte b)
282 {
283         int i, j;
284         float alpha;
285         ubyte r1, g1, b1;
286
287         for (j = 0; j < GR_FADE_LEVELS; j++)
288         {
289                 alpha = 1.0 - (float)j / ((float)GR_FADE_LEVELS - 1);
290                 for (i = 0; i < 255; i++)
291                 {
292                         r1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 0] + (alpha * (float)r));
293                         g1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 1] + (alpha * (float)g));
294                         b1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 2] + (alpha * (float)b));
295                         blend_table[i + j * 256] = gr_find_closest_color(r1, g1, b1);
296                 }
297                 blend_table[i + j * 256] = 255; // leave white alone
298         }
299 }