Subversion Repositories eduke32

Rev

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