Subversion Repositories eduke32

Rev

Rev 8491 | Details | Compare with Previous | Last modification | View Log | RSS feed

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