Subversion Repositories eduke32

Rev

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