amd64 fixes
[btb/d2x.git] / 2d / palette.c
1 /* $Id: palette.c,v 1.13 2005-07-30 01:51:42 chris 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 // swap colors 0 and 255 of the palette along with fade table entries
131
132 #ifdef SWAP_0_255
133         for (i = 0; i < 3; i++) {
134                 c = gr_palette[i];
135                 gr_palette[i] = gr_palette[765+i];
136                 gr_palette[765+i] = c;
137         }
138
139         for (i = 0; i < GR_FADE_LEVELS * 256; i++) {
140                 if (gr_fade_table[i] == 0)
141                         gr_fade_table[i] = 255;
142         }
143         for (i=0; i<GR_FADE_LEVELS; i++)
144                 gr_fade_table[i*256] = TRANSPARENCY_COLOR;
145 #endif
146 }
147
148 //      Add a computed color (by gr_find_closest_color) to list of computed colors in Computed_colors.
149 //      If list wasn't full already, increment Num_computed_colors.
150 //      If was full, replace a random one.
151 void add_computed_color(int r, int g, int b, int color_num)
152 {
153         int     add_index;
154
155         if (Num_computed_colors < MAX_COMPUTED_COLORS) {
156                 add_index = Num_computed_colors;
157                 Num_computed_colors++;
158         } else
159                 add_index = (d_rand() * MAX_COMPUTED_COLORS) >> 15;
160
161         Computed_colors[add_index].r = r;
162         Computed_colors[add_index].g = g;
163         Computed_colors[add_index].b = b;
164         Computed_colors[add_index].color_num = color_num;
165 }
166
167 void init_computed_colors(void)
168 {
169         int     i;
170
171         for (i=0; i<MAX_COMPUTED_COLORS; i++)
172                 Computed_colors[i].r = 255;             //      Make impossible to match.
173 }
174
175 int gr_find_closest_color( int r, int g, int b )
176 {
177         int i, j;
178         int best_value, best_index, value;
179
180         if (Num_computed_colors == 0)
181                 init_computed_colors();
182
183         //      If we've already computed this color, return it!
184         for (i=0; i<Num_computed_colors; i++)
185                 if (r == Computed_colors[i].r)
186                         if (g == Computed_colors[i].g)
187                                 if (b == Computed_colors[i].b) {
188                                         if (i > 4) {
189                                                 color_record    trec;
190                                                 trec = Computed_colors[i-1];
191                                                 Computed_colors[i-1] = Computed_colors[i];
192                                                 Computed_colors[i] = trec;
193                                                 return Computed_colors[i-1].color_num;
194                                         }
195                                         return Computed_colors[i].color_num;
196                                 }
197
198 //      r &= 63;
199 //      g &= 63;
200 //      b &= 63;
201
202         best_value = SQUARE(r-gr_palette[0])+SQUARE(g-gr_palette[1])+SQUARE(b-gr_palette[2]);
203         best_index = 0;
204         if (best_value==0) {
205                 add_computed_color(r, g, b, best_index);
206                 return best_index;
207         }
208         j=0;
209         // only go to 255, 'cause we dont want to check the transparent color.
210         for (i=1; i<254; i++ )  {
211                 j += 3;
212                 value = SQUARE(r-gr_palette[j])+SQUARE(g-gr_palette[j+1])+SQUARE(b-gr_palette[j+2]);
213                 if ( value < best_value )       {
214                         if (value==0) {
215                                 add_computed_color(r, g, b, i);
216                                 return i;
217                         }
218                         best_value = value;
219                         best_index = i;
220                 }
221         }
222         add_computed_color(r, g, b, best_index);
223         return best_index;
224 }
225
226 int gr_find_closest_color_15bpp( int rgb )
227 {
228         return gr_find_closest_color( ((rgb>>10)&31)*2, ((rgb>>5)&31)*2, (rgb&31)*2 );
229 }
230
231
232 int gr_find_closest_color_current( int r, int g, int b )
233 {
234         int i, j;
235         int best_value, best_index, value;
236
237 //      r &= 63;
238 //      g &= 63;
239 //      b &= 63;
240
241         best_value = SQUARE(r-gr_current_pal[0])+SQUARE(g-gr_current_pal[1])+SQUARE(b-gr_current_pal[2]);
242         best_index = 0;
243         if (best_value==0)
244                 return best_index;
245
246         j=0;
247         // only go to 255, 'cause we dont want to check the transparent color.
248         for (i=1; i<254; i++ )  {
249                 j += 3;
250                 value = SQUARE(r-gr_current_pal[j])+SQUARE(g-gr_current_pal[j+1])+SQUARE(b-gr_current_pal[j+2]);
251                 if ( value < best_value )       {
252                         if (value==0)
253                                 return i;
254                         best_value = value;
255                         best_index = i;
256                 }
257         }
258         return best_index;
259 }
260
261 void gr_make_cthru_table(ubyte * table, ubyte r, ubyte g, ubyte b )
262 {
263         int i;
264         ubyte r1, g1, b1;
265
266         for (i=0; i<256; i++ )  {
267                 r1 = gr_palette[i*3+0] + r;
268                 if ( r1 > 63 ) r1 = 63;
269                 g1 = gr_palette[i*3+1] + g;
270                 if ( g1 > 63 ) g1 = 63;
271                 b1 = gr_palette[i*3+2] + b;
272                 if ( b1 > 63 ) b1 = 63;
273                 table[i] = gr_find_closest_color( r1, g1, b1 );
274         }
275 }
276
277 void gr_make_blend_table(ubyte *blend_table, ubyte r, ubyte g, ubyte b)
278 {
279         int i, j;
280         float alpha;
281         ubyte r1, g1, b1;
282
283         for (j = 0; j < GR_FADE_LEVELS; j++)
284         {
285                 alpha = 1.0 - (float)j / ((float)GR_FADE_LEVELS - 1);
286                 for (i = 0; i < 255; i++)
287                 {
288                         r1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 0] + (alpha * (float)r));
289                         g1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 1] + (alpha * (float)g));
290                         b1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 2] + (alpha * (float)b));
291                         blend_table[i + j * 256] = gr_find_closest_color(r1, g1, b1);
292                 }
293                 blend_table[i + j * 256] = 255; // leave white alone
294         }
295 }