Subversion Repositories eduke32

Rev

Rev 6919 | Rev 6939 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5789 terminx 1
#include "compat.h"
2
#include "build.h"
5872 hendricks2 3
#include "engine_priv.h"
5862 hendricks2 4
#include "baselayer.h"
5789 terminx 5
#include "colmatch.h"
6
#include "cache1d.h"
7
#include "palette.h"
8
#include "a.h"
9
#include "xxhash.h"
10
 
6919 pogokeen 11
#ifdef USE_OPENGL
12
# include "glsurface.h"
13
#endif
14
 
6061 hendricks2 15
uint8_t *basepaltable[MAXBASEPALS] = { palette };
5789 terminx 16
uint8_t basepalreset=1;
17
uint8_t curbasepal;
18
int32_t globalblend;
19
 
20
uint32_t g_lastpalettesum = 0;
21
palette_t curpalette[256];                      // the current palette, unadjusted for brightness or tint
22
palette_t curpalettefaded[256];         // the current palette, adjusted for brightness and tint (ie. what gets sent to the card)
6061 hendricks2 23
palette_t palfadergb = { 0, 0, 0, 0 };
5789 terminx 24
char palfadedelta = 0;
25
uint8_t blackcol;
26
 
6514 hendricks2 27
int32_t realmaxshade;
28
float frealmaxshade;
29
 
5789 terminx 30
#if defined(USE_OPENGL)
31
palette_t palookupfog[MAXPALOOKUPS];
32
#endif
33
 
34
// For every pal number, whether tsprite pal should not be taken over from
35
// floor pal.
36
// NOTE: g_noFloorPal[0] is irrelevant as it's never checked.
37
int8_t g_noFloorPal[MAXPALOOKUPS];
38
 
39
int32_t curbrightness = 0, gammabrightness = 0;
40
 
6829 terminx 41
static void paletteSetFade(uint8_t offset);
5789 terminx 42
 
6827 terminx 43
#ifdef USE_OPENGL
44
void fullscreen_tint_gl(uint8_t r, uint8_t g, uint8_t b, uint8_t f)
45
{
46
    glMatrixMode(GL_PROJECTION);
47
    glPushMatrix();
48
    glLoadIdentity();
49
    glMatrixMode(GL_MODELVIEW);
50
    glPushMatrix();
51
    glLoadIdentity();
52
 
53
    glDisable(GL_DEPTH_TEST);
54
    glDisable(GL_ALPHA_TEST);
55
    glDisable(GL_TEXTURE_2D);
56
    polymost_setFogEnabled(false);
57
 
58
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
59
    glEnable(GL_BLEND);
60
    glColor4ub(r, g, b, f);
61
 
62
    polymost_useColorOnly(true);
63
    glBegin(GL_TRIANGLES);
64
    glVertex2f(-2.5f, 1.f);
65
    glVertex2f(2.5f, 1.f);
66
    glVertex2f(.0f, -2.5f);
67
    glEnd();
68
    polymost_useColorOnly(false);
69
 
70
    glPopMatrix();
71
    glMatrixMode(GL_PROJECTION);
72
    glPopMatrix();
73
}
74
#endif
75
 
6829 terminx 76
void videoFadeToBlack(int32_t moreopaquep)
5789 terminx 77
{
78
#ifdef USE_OPENGL
6829 terminx 79
    if (videoGetRenderMode() >= REND_POLYMOST)
5789 terminx 80
        fullscreen_tint_gl(0, 0, 0, moreopaquep ? 168 : 84);
81
    else
82
#endif
83
    {
84
        Bassert(!offscreenrendering);
85
 
6828 terminx 86
        videoBeginDrawing();
6829 terminx 87
        char *const p = (char *) frameplace;
88
        const char *const trans = paletteGetBlendTable(0);
89
        const int32_t shiftamnt = ((!!moreopaquep)*8);
90
        const int32_t dimprod = xdim*ydim;
91
        int32_t i = 0;
5789 terminx 92
 
93
#ifdef CLASSIC_SLICE_BY_4
6829 terminx 94
        for (; i<dimprod-4; i+=4)
95
        {
96
            p[i] = trans[p[i]<<shiftamnt];
97
            p[i+1] = trans[p[i+1]<<shiftamnt];
98
            p[i+2] = trans[p[i+2]<<shiftamnt];
99
            p[i+3] = trans[p[i+3]<<shiftamnt];
100
        }
5789 terminx 101
#endif
102
 
6829 terminx 103
        for (; i<dimprod; i++)
104
            p[i] = trans[p[i]<<shiftamnt];
6828 terminx 105
        videoEndDrawing();
5789 terminx 106
    }
107
}
108
 
109
void setup_blend(int32_t blend, int32_t doreverse)
110
{
111
    if (blendtable[blend] == NULL)
112
        blend = 0;
113
 
114
    if (globalblend != blend)
115
    {
116
        globalblend = blend;
6829 terminx 117
        fixtransluscence(FP_OFF(paletteGetBlendTable(blend)));
5789 terminx 118
    }
119
 
120
    if (doreverse)
121
        settransreverse();
122
    else
123
        settransnormal();
124
}
125
 
126
static void alloc_palookup(int32_t pal)
127
{
128
    // The asm functions vlineasm1, mvlineasm1 (maybe others?) access the next
129
    // palookup[...] shade entry for tilesizy==512 tiles.
130
    // See DEBUG_TILESIZY_512 and the comment in a.nasm: vlineasm1.
6438 terminx 131
    palookup[pal] = (char *) Xaligned_alloc(16, (numshades + 1) * 256);
132
    memset(palookup[pal], 0, (numshades + 1) * 256);
5789 terminx 133
}
134
 
135
static void maybe_alloc_palookup(int32_t palnum);
136
 
137
//
138
// loadpalette (internal)
139
//
6829 terminx 140
void paletteLoadFromDisk(void)
5789 terminx 141
{
142
    initfastcolorlookup_scale(30, 59, 11);
143
    initfastcolorlookup_gridvectors();
144
 
5888 hendricks2 145
#ifdef USE_OPENGL
146
    for (size_t x = 0; x < MAXBLENDTABS; ++x)
147
        glblend[x] = defaultglblend;
148
#endif
149
 
5789 terminx 150
    int32_t fil;
151
    if ((fil = kopen4load("palette.dat", 0)) == -1)
152
        return;
153
 
154
 
155
    // PALETTE_MAIN
156
 
157
    if (kread_and_test(fil, palette, 768))
158
        return kclose(fil);
159
 
5829 terminx 160
    for (bssize_t k = 0; k < 768; k++)
5789 terminx 161
        palette[k] <<= 2;
162
 
163
    initfastcolorlookup_palette(palette);
164
 
165
    paletteloaded |= PALETTE_MAIN;
166
 
167
 
168
    // PALETTE_SHADES
169
 
170
    if (kread_and_test(fil, &numshades, 2))
171
        return kclose(fil);
172
    numshades = B_LITTLE16(numshades);
173
 
174
    if (numshades <= 1)
175
    {
176
        initprintf("Warning: Invalid number of shades in \"palette.dat\"!\n");
177
        numshades = 0;
178
        return kclose(fil);
179
    }
180
 
181
    // Auto-detect LameDuke. Its PALETTE.DAT doesn't have a 'numshades' 16-bit
182
    // int after the base palette, but starts directly with the shade tables.
183
    // Thus, the first two bytes will be 00 01, which is 256 if read as
184
    // little-endian int16_t.
185
    int32_t lamedukep = 0;
186
    if (numshades >= 256)
187
    {
188
        static char const * const seekfail = "Warning: klseek() failed in loadpalette()!\n";
189
 
190
        uint16_t temp;
191
        if (kread_and_test(fil, &temp, 2))
192
            return kclose(fil);
193
        temp = B_LITTLE16(temp);
194
        if (temp == 770 || numshades > 256) // 02 03
195
        {
196
            if (klseek(fil, -4, BSEEK_CUR) < 0)
197
            {
198
                initputs(seekfail);
199
                return kclose(fil);
200
            }
201
 
202
            numshades = 32;
203
            lamedukep = 1;
204
        }
205
        else
206
        {
207
            if (klseek(fil, -2, BSEEK_CUR) < 0)
208
            {
209
                initputs(seekfail);
210
                return kclose(fil);
211
            }
212
        }
213
    }
214
 
215
    // Read base shade table (palookup 0).
216
    maybe_alloc_palookup(0);
217
    if (kread_and_test(fil, palookup[0], numshades<<8))
218
        return kclose(fil);
219
 
220
    paletteloaded |= PALETTE_SHADE;
221
 
222
 
223
    // PALETTE_TRANSLUC
224
 
225
    char * const transluc = blendtable[0] = (char *) Xcalloc(256, 256);
226
 
227
    // Read translucency (blending) table.
228
    if (lamedukep)
229
    {
5829 terminx 230
        for (bssize_t i=0; i<255; i++)
5789 terminx 231
        {
232
            // NOTE: LameDuke's table doesn't have the last row or column (i==255).
233
 
234
            // Read the entries above and on the diagonal, if the table is
235
            // thought as being row-major.
236
            if (kread_and_test(fil, &transluc[256*i + i], 256-i-1))
237
                return kclose(fil);
238
 
239
            // Duplicate the entries below the diagonal.
5829 terminx 240
            for (bssize_t j=0; j<i; j++)
5789 terminx 241
                transluc[256*i + j] = transluc[256*j + i];
242
        }
243
    }
244
    else
245
    {
246
        if (kread_and_test(fil, transluc, 65536))
247
            return kclose(fil);
248
    }
249
 
250
    paletteloaded |= PALETTE_TRANSLUC;
251
 
252
 
253
    // additional blending tables
254
 
255
    uint8_t magic[12];
256
    if (!kread_and_test(fil, magic, sizeof(magic)) && !Bmemcmp(magic, "MoreBlendTab", sizeof(magic)))
257
    {
258
        uint8_t addblendtabs;
259
        if (kread_and_test(fil, &addblendtabs, 1))
260
        {
261
            initprintf("Warning: failed reading additional blending table count\n");
262
            return kclose(fil);
263
        }
264
 
265
        uint8_t blendnum;
266
        char *tab = (char *) Xmalloc(256*256);
5829 terminx 267
        for (bssize_t i=0; i<addblendtabs; i++)
5789 terminx 268
        {
269
            if (kread_and_test(fil, &blendnum, 1))
270
            {
271
                initprintf("Warning: failed reading additional blending table index\n");
272
                Bfree(tab);
273
                return kclose(fil);
274
            }
275
 
6829 terminx 276
            if (paletteGetBlendTable(blendnum) != NULL)
5789 terminx 277
                initprintf("Warning: duplicate blending table index %3d encountered\n", blendnum);
278
 
279
            if (kread_and_test(fil, tab, 256*256))
280
            {
281
                initprintf("Warning: failed reading additional blending table\n");
282
                Bfree(tab);
283
                return kclose(fil);
284
            }
285
 
6829 terminx 286
            paletteSetBlendTable(blendnum, tab);
5789 terminx 287
        }
288
        Bfree(tab);
289
 
290
        // Read log2 of count of alpha blending tables.
291
        uint8_t lognumalphatabs;
292
        if (!kread_and_test(fil, &lognumalphatabs, 1))
293
        {
294
            if (!(lognumalphatabs >= 1 && lognumalphatabs <= 7))
295
                initprintf("invalid lognumalphatabs value, must be in [1 .. 7]\n");
296
            else
297
                numalphatabs = 1<<lognumalphatabs;
298
        }
299
    }
300
 
301
    kclose(fil);
302
}
303
 
304
uint32_t PaletteIndexFullbrights[8];
305
 
6829 terminx 306
void palettePostLoadTables(void)
5789 terminx 307
{
308
    globalpal = 0;
5872 hendricks2 309
 
5789 terminx 310
    globalpalwritten = palookup[0];
311
    setpalookupaddress(globalpalwritten);
312
 
313
    fixtransluscence(FP_OFF(blendtable[0]));
314
 
6513 hendricks2 315
    char const * const palookup0 = palookup[0];
316
 
5789 terminx 317
#ifdef DEBUG_TILESIZY_512
318
    // Bump shade 1 by 16.
5829 terminx 319
    for (bssize_t i=256; i<512; i++)
6513 hendricks2 320
        palookup0[i] = palookup0[i+(16<<8)];
5789 terminx 321
#endif
322
 
6831 terminx 323
    blackcol = paletteGetClosestColor(0, 0, 0);
324
    whitecol = paletteGetClosestColor(255, 255, 255);
325
    redcol = paletteGetClosestColor(255, 0, 0);
5789 terminx 326
 
6461 terminx 327
    for (size_t i = 0; i<16; i++)
328
    {
329
        palette_t *edcol = (palette_t *) &vgapal16[4*i];
330
        editorcolors[i] = getclosestcol_lim(edcol->b, edcol->g, edcol->r, 239);
331
    }
332
 
5789 terminx 333
    // Bmemset(PaletteIndexFullbrights, 0, sizeof(PaletteIndexFullbrights));
5829 terminx 334
    for (bssize_t c = 0; c < 255; ++c) // skipping transparent color
5789 terminx 335
    {
6513 hendricks2 336
        uint8_t const index = palookup0[c];
337
        rgb24_t const & color = *(rgb24_t *)&palette[index*3];
5789 terminx 338
 
6513 hendricks2 339
        // don't consider #000000 fullbright
340
        if (EDUKE32_PREDICT_FALSE(color.r == 0 && color.g == 0 && color.b == 0))
341
            continue;
5789 terminx 342
 
6513 hendricks2 343
        for (size_t s = c + 256, s_end = 256*numshades; s < s_end; s += 256)
344
            if (EDUKE32_PREDICT_FALSE(palookup0[s] != index))
5789 terminx 345
                goto PostLoad_NotFullbright;
346
 
347
        SetPaletteIndexFullbright(c);
348
 
6513 hendricks2 349
        PostLoad_NotFullbright: ;
5789 terminx 350
    }
6514 hendricks2 351
 
6592 hendricks2 352
    if (realmaxshade == 0)
6514 hendricks2 353
    {
6592 hendricks2 354
        uint8_t const * const blackcolor = &palette[blackcol*3];
355
        size_t s;
356
        for (s = numshades < 2 ? 0 : numshades-2; s > 0; --s)
6514 hendricks2 357
        {
6592 hendricks2 358
            for (size_t c = s*256, c_end = c+255; c < c_end; ++c) // skipping transparent color
359
            {
360
                uint8_t const index = palookup0[c];
361
                uint8_t const * const color = &palette[index*3];
362
                if (!IsPaletteIndexFullbright(index) && memcmp(blackcolor, color, sizeof(rgb24_t)))
363
                    goto PostLoad_FoundShade;
364
            }
6514 hendricks2 365
        }
6592 hendricks2 366
        PostLoad_FoundShade: ;
367
        frealmaxshade = (float)(realmaxshade = s+1);
6514 hendricks2 368
    }
5789 terminx 369
}
370
 
6829 terminx 371
void paletteFixTranslucencyMask(void)
5789 terminx 372
{
5829 terminx 373
    for (bssize_t i=0; i<MAXPALOOKUPS; i++)
5789 terminx 374
    {
375
        char * const thispalookup = palookup[i];
376
        if (thispalookup == NULL)
377
            continue;
378
 
5829 terminx 379
        for (bssize_t j=0; j<numshades; j++)
5789 terminx 380
        {
381
            thispalookup[(j<<8) + 255] = 255;
382
        }
383
    }
384
 
385
    // fix up translucency table so that transluc(255,x)
386
    // and transluc(x,255) is black instead of purple.
5829 terminx 387
    for (bssize_t i=0; i<MAXBLENDTABS; i++)
5789 terminx 388
    {
389
        char * const transluc = blendtable[i];
390
        if (transluc == NULL)
391
            continue;
392
 
5829 terminx 393
        for (bssize_t j=0; j<255; j++)
5789 terminx 394
        {
395
            transluc[(255<<8) + j] = transluc[(blackcol<<8) + j];
396
            transluc[255 + (j<<8)] = transluc[blackcol + (j<<8)];
397
        }
398
        transluc[(255<<8) + 255] = transluc[(blackcol<<8) + blackcol];
399
    }
400
}
401
 
402
// Load LOOKUP.DAT, which contains lookup tables and additional base palettes.
403
//
404
// <fp>: kopen4load file handle
405
//
406
// Returns:
407
//  - on success, 0
408
//  - on error, -1 (didn't read enough data)
409
//  - -2: error, we already wrote an error message ourselves
6829 terminx 410
int32_t paletteLoadLookupTable(int32_t fp)
5789 terminx 411
{
412
    uint8_t numlookups;
413
    char remapbuf[256];
414
 
415
    if (kread_and_test(fp, &numlookups, 1))
416
        return -1;
417
 
5829 terminx 418
    for (bssize_t j=0; j<numlookups; j++)
5789 terminx 419
    {
420
        uint8_t palnum;
421
 
422
        if (kread_and_test(fp, &palnum, 1))
423
            return -1;
424
 
425
        if (palnum >= 256-RESERVEDPALS)
426
        {
427
            initprintf("ERROR: attempt to load lookup at reserved pal %d\n", palnum);
428
            return -2;
429
        }
430
 
431
        if (kread_and_test(fp, remapbuf, 256))
432
            return -1;
433
 
6829 terminx 434
        paletteMakeLookupTable(palnum, remapbuf, 0, 0, 0, 0);
5789 terminx 435
    }
436
 
437
    return 0;
438
}
439
 
6829 terminx 440
void paletteSetupDefaultFog(void)
5789 terminx 441
{
442
    // Find a gap of four consecutive unused pal numbers to generate fog shade
443
    // tables.
5829 terminx 444
    for (bssize_t j=1; j<=255-3; j++)
5789 terminx 445
        if (!palookup[j] && !palookup[j+1] && !palookup[j+2] && !palookup[j+3])
446
        {
6829 terminx 447
            paletteMakeLookupTable(j, NULL, 60, 60, 60, 1);
448
            paletteMakeLookupTable(j+1, NULL, 60, 0, 0, 1);
449
            paletteMakeLookupTable(j+2, NULL, 0, 60, 0, 1);
450
            paletteMakeLookupTable(j+3, NULL, 0, 0, 60, 1);
5789 terminx 451
 
452
            break;
453
        }
454
}
455
 
6829 terminx 456
void palettePostLoadLookups(void)
5789 terminx 457
{
458
    // Alias remaining unused pal numbers to the base shade table.
5829 terminx 459
    for (bssize_t j=1; j<MAXPALOOKUPS; j++)
5789 terminx 460
    {
461
        // If an existing lookup is identical to #0, free it.
462
        if (palookup[j] && palookup[j] != palookup[0] && !Bmemcmp(palookup[0], palookup[j], 256*numshades))
6829 terminx 463
            paletteFreeLookupTable(j);
5789 terminx 464
 
465
        if (!palookup[j])
6829 terminx 466
            paletteMakeLookupTable(j, NULL, 0, 0, 0, 1);
5789 terminx 467
    }
468
}
469
 
470
static int32_t palookup_isdefault(int32_t palnum)  // KEEPINSYNC engine.lua
471
{
472
    return (palookup[palnum] == NULL || (palnum!=0 && palookup[palnum] == palookup[0]));
473
}
474
 
475
static void maybe_alloc_palookup(int32_t palnum)
476
{
477
    if (palookup_isdefault(palnum))
478
    {
479
        alloc_palookup(palnum);
480
        if (palookup[palnum] == NULL)
481
            Bexit(1);
482
    }
483
}
484
 
6829 terminx 485
void paletteSetBlendTable(int32_t blend, const char *tab)
5789 terminx 486
{
487
    if (blendtable[blend] == NULL)
488
        blendtable[blend] = (char *) Xmalloc(256*256);
489
 
490
    Bmemcpy(blendtable[blend], tab, 256*256);
491
}
6829 terminx 492
void paletteFreeBlendTable(int32_t const blend)
5789 terminx 493
{
494
    DO_FREE_AND_NULL(blendtable[blend]);
495
}
496
 
497
#ifdef LUNATIC
6829 terminx 498
const char *(paletteGetBlendTable) (int32_t blend)
5789 terminx 499
{
500
    return blendtable[blend];
501
}
502
#endif
503
 
5888 hendricks2 504
#ifdef USE_OPENGL
505
glblend_t const nullglblend =
506
{
507
    {
508
        { 1.f, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, 0 },
509
        { 1.f, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, 0 },
510
    },
511
};
512
glblend_t const defaultglblend =
513
{
514
    {
515
        { 2.f/3.f, BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 0 },
516
        { 1.f/3.f, BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 0 },
517
    },
518
};
519
 
520
glblend_t glblend[MAXBLENDTABS];
521
 
522
void handle_blend(uint8_t enable, uint8_t blend, uint8_t def)
523
{
524
    static GLenum const blendFuncTokens[NUMBLENDFACTORS] =
525
    {
526
        GL_ZERO,
527
        GL_ONE,
528
        GL_SRC_COLOR,
529
        GL_ONE_MINUS_SRC_COLOR,
530
        GL_SRC_ALPHA,
531
        GL_ONE_MINUS_SRC_ALPHA,
532
        GL_DST_ALPHA,
533
        GL_ONE_MINUS_DST_ALPHA,
534
        GL_DST_COLOR,
535
        GL_ONE_MINUS_DST_COLOR,
536
    };
537
 
538
    if (!enable)
539
    {
6656 pogokeen 540
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5888 hendricks2 541
        return;
542
    }
543
 
544
    glblenddef_t const * const glbdef = glblend[blend].def + def;
6656 pogokeen 545
    glBlendFunc(blendFuncTokens[glbdef->src], blendFuncTokens[glbdef->dst]);
5888 hendricks2 546
}
547
#endif
548
 
6829 terminx 549
int32_t paletteSetLookupTable(int32_t palnum, const uint8_t *shtab)
5789 terminx 550
{
551
    if (numshades != 32)
552
        return -1;
553
 
554
    if (shtab != NULL)
555
    {
556
        maybe_alloc_palookup(palnum);
557
        Bmemcpy(palookup[palnum], shtab, 256*numshades);
558
    }
559
 
560
    return 0;
561
}
6829 terminx 562
 
563
void paletteFreeLookupTable(int32_t const palnum)
5789 terminx 564
{
565
    if (palnum == 0 && palookup[palnum] != NULL)
566
    {
5829 terminx 567
        for (bssize_t i = 1; i < MAXPALOOKUPS; i++)
5789 terminx 568
            if (palookup[i] == palookup[palnum])
569
                palookup[i] = NULL;
570
 
6438 terminx 571
        ALIGNED_FREE_AND_NULL(palookup[palnum]);
5789 terminx 572
    }
573
    else if (palookup[palnum] == palookup[0])
574
        palookup[palnum] = NULL;
575
    else
6438 terminx 576
        ALIGNED_FREE_AND_NULL(palookup[palnum]);
5789 terminx 577
}
578
 
579
//
580
// makepalookup
581
//
6829 terminx 582
void paletteMakeLookupTable(int32_t palnum, const char *remapbuf, uint8_t r, uint8_t g, uint8_t b, char noFloorPal)
5789 terminx 583
{
584
    int32_t i, j;
585
 
6061 hendricks2 586
    static char idmap[256] = { 1 };
5789 terminx 587
 
588
    if (paletteloaded == 0)
589
        return;
590
 
591
    // NOTE: palnum==0 is allowed
592
    if ((unsigned) palnum >= MAXPALOOKUPS)
593
        return;
594
 
595
    g_noFloorPal[palnum] = noFloorPal;
596
 
597
    if (remapbuf==NULL)
598
    {
599
        if ((r|g|b) == 0)
600
        {
601
            palookup[palnum] = palookup[0];  // Alias to base shade table!
602
            return;
603
        }
604
 
605
        if (idmap[0]==1)  // init identity map
606
            for (i=0; i<256; i++)
607
                idmap[i] = i;
608
 
609
        remapbuf = idmap;
610
    }
611
 
612
    maybe_alloc_palookup(palnum);
613
 
614
    if ((r|g|b) == 0)
615
    {
616
        // "black fog"/visibility case -- only remap color indices
617
 
618
        for (j=0; j<numshades; j++)
619
            for (i=0; i<256; i++)
620
            {
621
                const char *src = palookup[0];
622
                palookup[palnum][256*j + i] = src[256*j + remapbuf[i]];
623
            }
624
    }
625
    else
626
    {
627
        // colored fog case
628
 
629
        char *ptr2 = palookup[palnum];
630
 
631
        for (i=0; i<numshades; i++)
632
        {
633
            int32_t palscale = divscale16(i, numshades-1);
634
 
635
            for (j=0; j<256; j++)
636
            {
637
                const char *ptr = (const char *) &palette[remapbuf[j]*3];
6831 terminx 638
                *ptr2++ = paletteGetClosestColor(ptr[0] + mulscale16(r-ptr[0], palscale),
5789 terminx 639
                    ptr[1] + mulscale16(g-ptr[1], palscale),
640
                    ptr[2] + mulscale16(b-ptr[2], palscale));
641
            }
642
        }
643
    }
644
 
645
#if defined(USE_OPENGL)
646
    palookupfog[palnum].r = r;
647
    palookupfog[palnum].g = g;
648
    palookupfog[palnum].b = b;
649
#endif
650
}
651
 
652
//
653
// setbasepal
654
//
6829 terminx 655
void paletteSetColorTable(int32_t id, uint8_t const * const table)
5789 terminx 656
{
657
    if (basepaltable[id] == NULL)
658
        basepaltable[id] = (uint8_t *) Xmalloc(768);
659
 
660
    Bmemcpy(basepaltable[id], table, 768);
6776 pogokeen 661
 
6915 pogokeen 662
#ifdef USE_OPENGL
6932 pogokeen 663
    if (videoGetRenderMode() >= REND_POLYMOST)
6919 pogokeen 664
    {
665
        uploadbasepalette(id);
666
    }
6915 pogokeen 667
#endif
5789 terminx 668
}
6829 terminx 669
 
670
void paletteFreeColorTable(int32_t const id)
5789 terminx 671
{
672
    if (id == 0)
673
        Bmemset(basepaltable[id], 0, 768);
674
    else
675
        DO_FREE_AND_NULL(basepaltable[id]);
676
}
677
 
678
//
679
// setbrightness
680
//
681
// flags:
682
//  1: don't setpalette(),  DON'T USE THIS FLAG!
683
//  2: don't gltexinvalidateall()
684
//  4: don't calc curbrightness from dabrightness,  DON'T USE THIS FLAG!
685
//  8: don't gltexinvalidate8()
686
// 16: don't reset palfade*
6829 terminx 687
void videoSetPalette(char dabrightness, uint8_t dapalid, uint8_t flags)
5789 terminx 688
{
5884 terminx 689
    int32_t i, j;
5789 terminx 690
    const uint8_t *dapal;
691
 
692
#ifdef USE_OPENGL
693
    int32_t paldidchange;
694
#endif
695
    int32_t palsumdidchange;
696
    //    uint32_t lastbright = curbrightness;
697
 
698
    Bassert((flags&4)==0);
699
 
700
    if (/*(unsigned)dapalid >= MAXBASEPALS ||*/ basepaltable[dapalid] == NULL)
701
        dapalid = 0;
702
#ifdef USE_OPENGL
703
    paldidchange = (curbasepal != dapalid || basepalreset);
704
#endif
705
    curbasepal = dapalid;
706
    basepalreset = 0;
707
 
708
    dapal = basepaltable[curbasepal];
709
 
710
    if (!(flags&4))
711
    {
712
        curbrightness = clamp(dabrightness, 0, 15);
713
        //        if (lastbright != (unsigned)curbrightness)
714
        //            vid_gamma = 1.0 + ((float)curbrightness / 10.0);
715
    }
716
 
6828 terminx 717
    videoSetGamma();
5884 terminx 718
    j = !gammabrightness ? curbrightness : 0;
5789 terminx 719
 
720
    for (i=0; i<256; i++)
721
    {
722
        // save palette without any brightness adjustment
723
        curpalette[i].r = dapal[i*3+0];
724
        curpalette[i].g = dapal[i*3+1];
725
        curpalette[i].b = dapal[i*3+2];
726
        curpalette[i].f = 0;
727
 
728
        // brightness adjust the palette
729
        curpalettefaded[i].b = britable[j][curpalette[i].b];
730
        curpalettefaded[i].g = britable[j][curpalette[i].g];
731
        curpalettefaded[i].r = britable[j][curpalette[i].r];
732
        curpalettefaded[i].f = 0;
733
    }
734
 
735
    if ((flags&16) && palfadedelta)  // keep the fade
6829 terminx 736
        paletteSetFade(palfadedelta>>2);
5789 terminx 737
 
6829 terminx 738
    static uint32_t lastpalettesum=0;
739
    uint32_t newpalettesum = XXH32((uint8_t *) curpalettefaded, sizeof(curpalettefaded), sizeof(curpalettefaded));
5789 terminx 740
 
6829 terminx 741
    palsumdidchange = (newpalettesum != lastpalettesum);
5789 terminx 742
 
6829 terminx 743
    if (palsumdidchange || newpalettesum != g_lastpalettesum)
744
    {
6932 pogokeen 745
        glsurface_setPalette(curpalettefaded);
6829 terminx 746
        //            if ((flags&1) == 0)
747
        videoUpdatePalette(0, 256);
5789 terminx 748
    }
749
 
6829 terminx 750
    g_lastpalettesum = lastpalettesum = newpalettesum;
751
 
5789 terminx 752
#ifdef USE_OPENGL
6829 terminx 753
    if (videoGetRenderMode() >= REND_POLYMOST)
5789 terminx 754
    {
755
        // Only reset the textures if the corresponding preserve flags are clear and
756
        // either (a) the new palette is different to the last, or (b) the brightness
757
        // changed and we couldn't set it using hardware gamma.
758
 
759
        // XXX: no-HW-gamma OpenGL platforms will exhibit bad performance with
760
        // simultaneous basepal and tint changes?
5884 terminx 761
        const int32_t doinvalidate = (paldidchange || (palsumdidchange && !gammabrightness));
5789 terminx 762
 
763
        if (!(flags&2) && doinvalidate)
6776 pogokeen 764
            gltexinvalidatetype(INVALIDATE_ALL_NON_INDEXED);
5789 terminx 765
        if (!(flags&8) && doinvalidate)
6776 pogokeen 766
            gltexinvalidatetype(INVALIDATE_ART_NON_INDEXED);
5789 terminx 767
#ifdef POLYMER
6829 terminx 768
        if ((videoGetRenderMode() == REND_POLYMER) && doinvalidate)
5789 terminx 769
            polymer_texinvalidate();
770
#endif
771
    }
772
#endif
773
 
774
    if ((flags&16)==0)
775
    {
776
        palfadergb.r = palfadergb.g = palfadergb.b = 0;
777
        palfadedelta = 0;
778
    }
779
}
780
 
6829 terminx 781
palette_t paletteGetColor(int32_t col)
5789 terminx 782
{
783
    if (!gammabrightness)
784
    {
5884 terminx 785
        palette_t const p = { britable[curbrightness][curpalette[col].r], britable[curbrightness][curpalette[col].g],
786
                              britable[curbrightness][curpalette[col].b], 0 };
5789 terminx 787
        return p;
788
    }
789
 
790
    return curpalette[col];
791
}
792
 
6829 terminx 793
static void paletteSetFade(uint8_t offset)
5789 terminx 794
{
6829 terminx 795
    for (native_t i=0; i<256; i++)
5789 terminx 796
    {
6829 terminx 797
        palette_t const p = paletteGetColor(i);
5789 terminx 798
 
6829 terminx 799
        curpalettefaded[i].b = p.b + (((palfadergb.b - p.b) * offset) >> 8);
800
        curpalettefaded[i].g = p.g + (((palfadergb.g - p.g) * offset) >> 8);
801
        curpalettefaded[i].r = p.r + (((palfadergb.r - p.r) * offset) >> 8);
5789 terminx 802
        curpalettefaded[i].f = 0;
803
    }
804
}
805
 
806
//#define DEBUG_PALETTEFADE
807
 
808
//
809
// setpalettefade
810
//
6829 terminx 811
void videoFadePalette(uint8_t r, uint8_t g, uint8_t b, uint8_t offset)
5789 terminx 812
{
813
    palfadergb.r = r;
814
    palfadergb.g = g;
815
    palfadergb.b = b;
816
#ifdef DEBUG_PALETTEFADE
817
    if (offset)
818
        offset = max(offset, 128);
819
#endif
820
    palfadedelta = offset;
821
 
6829 terminx 822
    paletteSetFade(offset);
5789 terminx 823
 
6829 terminx 824
    static uint32_t lastpalettesum=0;
825
    uint32_t newpalettesum = XXH32((uint8_t *) curpalettefaded, sizeof(curpalettefaded), sizeof(curpalettefaded));
5789 terminx 826
 
6829 terminx 827
    if (newpalettesum != lastpalettesum || newpalettesum != g_lastpalettesum)
6932 pogokeen 828
    {
829
        glsurface_setPalette(curpalettefaded);
6829 terminx 830
        videoUpdatePalette(0, 256);
6932 pogokeen 831
    }
5789 terminx 832
 
6829 terminx 833
    g_lastpalettesum = lastpalettesum = newpalettesum;
5789 terminx 834
}