Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * Portions of this file are copyright Rebirth contributors and licensed as
3
 * described in COPYING.txt.
4
 * Portions of this file are copyright Parallax Software and licensed
5
 * according to the Parallax license below.
6
 * See COPYING.txt for license details.
7
 
8
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9
SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12
IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14
FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17
COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18
*/
19
 
20
/*
21
 *
22
 * Graphical routines for setting the palette
23
 *
24
 */
25
 
26
#include <algorithm>
27
#include <stdlib.h>
28
#include <stdio.h>
29
#include <string.h>
30
 
31
#include "physfsx.h"
32
#include "pstypes.h"
33
#include "u_mem.h"
34
#include "gr.h"
35
#include "grdef.h"
36
#include "dxxerror.h"
37
#include "maths.h"
38
#include "palette.h"
39
 
40
#include "dxxsconf.h"
41
#include "dsx-ns.h"
42
#include "compiler-range_for.h"
43
#include <array>
44
 
45
namespace dcx {
46
 
47
#define SQUARE(x) ((x)*(x))
48
 
49
#define MAX_COMPUTED_COLORS     32
50
 
51
static unsigned Num_computed_colors;
52
 
53
struct color_record {
54
        ubyte   r,g,b;
55
        color_palette_index color_num;
56
};
57
 
58
static std::array<color_record, MAX_COMPUTED_COLORS> Computed_colors;
59
 
60
palette_array_t gr_palette;
61
palette_array_t gr_current_pal;
62
gft_array1 gr_fade_table;
63
 
64
ubyte gr_palette_gamma = 0;
65
int gr_palette_gamma_param = 0;
66
 
67
void copy_bound_palette(palette_array_t &d, const palette_array_t &s)
68
{
69
        auto a = [](rgb_t c) {
70
                const ubyte bound = 63;
71
                c.r = std::min(c.r, bound);
72
                c.g = std::min(c.g, bound);
73
                c.b = std::min(c.b, bound);
74
                return c;
75
        };
76
        std::transform(s.begin(), s.end(), d.begin(), a);
77
}
78
 
79
}
80
 
81
namespace dcx {
82
 
83
static void diminish_entry(rgb_t &c)
84
{
85
        c.r >>= 2;
86
        c.g >>= 2;
87
        c.b >>= 2;
88
}
89
 
90
void diminish_palette(palette_array_t &palette)
91
{
92
        range_for (rgb_t &c, palette)
93
                diminish_entry(c);
94
}
95
 
96
void gr_palette_set_gamma( int gamma )
97
{
98
        if ( gamma < 0 ) gamma = 0;
99
        if ( gamma > 16 ) gamma = 16;      //was 8
100
 
101
        if (gr_palette_gamma_param != gamma )   {
102
                gr_palette_gamma_param = gamma;
103
                gr_palette_gamma = gamma;
104
                gr_palette_load( gr_palette );
105
        }
106
}
107
 
108
int gr_palette_get_gamma()
109
{
110
        return gr_palette_gamma_param;
111
}
112
 
113
}
114
 
115
namespace dsx {
116
 
117
#if defined(DXX_BUILD_DESCENT_I)
118
void copy_diminish_palette(palette_array_t &palette, const uint8_t *p)
119
{
120
        range_for (auto &i, palette)
121
        {
122
                i.r = *p++ >> 2;
123
                i.g = *p++ >> 2;
124
                i.b = *p++ >> 2;
125
        }
126
}
127
#endif
128
 
129
#if defined(DXX_BUILD_DESCENT_II)
130
void gr_copy_palette(palette_array_t &gr_palette, const palette_array_t &pal)
131
{
132
        gr_palette = pal;
133
 
134
                Num_computed_colors = 0;
135
}
136
#endif
137
 
138
void gr_use_palette_table(const char * filename )
139
{
140
        int fsize;
141
 
142
        auto fp = PHYSFSX_openReadBuffered(filename);
143
#if defined(DXX_BUILD_DESCENT_I)
144
#define FAILURE_FORMAT  "Can't open palette file <%s>"
145
#elif defined(DXX_BUILD_DESCENT_II)
146
#define FAILURE_FORMAT  "Can open neither palette file <%s> nor default palette file <" DEFAULT_LEVEL_PALETTE ">"
147
        // the following is a hack to enable the loading of d2 levels
148
        // even if only the d2 mac shareware datafiles are present.
149
        // However, if the pig file is present but the palette file isn't,
150
        // the textures in the level will look wierd...
151
        if (!fp)
152
                fp = PHYSFSX_openReadBuffered( DEFAULT_LEVEL_PALETTE );
153
#endif
154
        if (!fp)
155
                Error(FAILURE_FORMAT,
156
                      filename);
157
 
158
        fsize   = PHYSFS_fileLength( fp );
159
        Assert( fsize == 9472 );
160
        (void)fsize;
161
        PHYSFS_read( fp, &gr_palette[0], sizeof(gr_palette[0]), gr_palette.size() );
162
        PHYSFS_read( fp, gr_fade_table, 256*34, 1 );
163
        fp.reset();
164
 
165
        // This is the TRANSPARENCY COLOR
166
        range_for (auto &i, gr_fade_table)
167
                i[255] = 255;
168
#if defined(DXX_BUILD_DESCENT_II)
169
        Num_computed_colors = 0;        //      Flush palette cache.
170
// swap colors 0 and 255 of the palette along with fade table entries
171
 
172
#ifdef SWAP_0_255
173
        for (i = 0; i < 3; i++) {
174
                ubyte c;
175
                c = gr_palette[i];
176
                gr_palette[i] = gr_palette[765+i];
177
                gr_palette[765+i] = c;
178
        }
179
 
180
        for (i = 0; i < GR_FADE_LEVELS * 256; i++) {
181
                if (gr_fade_table[i] == 0)
182
                        gr_fade_table[i] = 255;
183
        }
184
        for (i=0; i<GR_FADE_LEVELS; i++)
185
                gr_fade_table[i*256] = TRANSPARENCY_COLOR;
186
#endif
187
#endif
188
}
189
 
190
}
191
 
192
namespace dcx {
193
 
194
//      Add a computed color (by gr_find_closest_color) to list of computed colors in Computed_colors.
195
//      If list wasn't full already, increment Num_computed_colors.
196
//      If was full, replace a random one.
197
static void add_computed_color(int r, int g, int b, color_t color_num)
198
{
199
        int     add_index;
200
 
201
        if (Num_computed_colors < MAX_COMPUTED_COLORS) {
202
                add_index = Num_computed_colors;
203
                Num_computed_colors++;
204
        } else
205
                add_index = (d_rand() * MAX_COMPUTED_COLORS) >> 15;
206
 
207
        Computed_colors[add_index].r = r;
208
        Computed_colors[add_index].g = g;
209
        Computed_colors[add_index].b = b;
210
        Computed_colors[add_index].color_num = color_num;
211
}
212
 
213
void init_computed_colors(void)
214
{
215
        range_for (auto &i, Computed_colors)
216
                i.r = 255;              //      Make impossible to match.
217
}
218
 
219
color_palette_index gr_find_closest_color(const int r, const int g, const int b)
220
{
221
        int j;
222
        int best_value, value;
223
 
224
        if (Num_computed_colors == 0)
225
                init_computed_colors();
226
 
227
        //      If we've already computed this color, return it!
228
        for (unsigned i=0; i<Num_computed_colors; i++)
229
        {
230
                auto &c = Computed_colors[i];
231
                if (r == c.r && g == c.g && b == c.b)
232
                {
233
                        const auto color_num = c.color_num;
234
                                        if (i > 4) {
235
                                                std::swap(Computed_colors[i-1], c);
236
                                        }
237
                                        return color_num;
238
                                }
239
        }
240
 
241
//      r &= 63;
242
//      g &= 63;
243
//      b &= 63;
244
 
245
        best_value = SQUARE(r-gr_palette[0].r)+SQUARE(g-gr_palette[0].g)+SQUARE(b-gr_palette[0].b);
246
        color_palette_index best_index = 0;
247
        if (best_value==0) {
248
                add_computed_color(r, g, b, best_index);
249
                return best_index;
250
        }
251
        j=0;
252
        // only go to 255, 'cause we dont want to check the transparent color.
253
        for (color_palette_index i{1}; i < 254; ++i)
254
        {
255
                ++j;
256
                value = SQUARE(r-gr_palette[j].r)+SQUARE(g-gr_palette[j].g)+SQUARE(b-gr_palette[j].b);
257
                if ( value < best_value )       {
258
                        if (value==0) {
259
                                add_computed_color(r, g, b, i);
260
                                return i;
261
                        }
262
                        best_value = value;
263
                        best_index = i;
264
                }
265
        }
266
        add_computed_color(r, g, b, best_index);
267
        return best_index;
268
}
269
 
270
color_palette_index gr_find_closest_color_15bpp( int rgb )
271
{
272
        return gr_find_closest_color( ((rgb>>10)&31)*2, ((rgb>>5)&31)*2, (rgb&31)*2 );
273
}
274
 
275
 
276
color_palette_index gr_find_closest_color_current( int r, int g, int b )
277
{
278
        int j;
279
        int best_value, value;
280
 
281
//      r &= 63;
282
//      g &= 63;
283
//      b &= 63;
284
 
285
        best_value = SQUARE(r-gr_current_pal[0].r)+SQUARE(g-gr_current_pal[0].g)+SQUARE(b-gr_current_pal[0].b);
286
        color_t best_index = 0;
287
        if (best_value==0)
288
                return best_index;
289
 
290
        j=0;
291
        // only go to 255, 'cause we dont want to check the transparent color.
292
        for (color_t i=1; i < 254; i++ )        {
293
                ++j;
294
                value = SQUARE(r-gr_current_pal[j].r)+SQUARE(g-gr_current_pal[j].g)+SQUARE(b-gr_current_pal[j].b);
295
                if ( value < best_value )       {
296
                        if (value==0)
297
                                return i;
298
                        best_value = value;
299
                        best_index = i;
300
                }
301
        }
302
        return best_index;
303
}
304
 
305
}