Subversion Repositories eduke32

Rev

Rev 5804 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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