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