#include "compat.h" #include "build.h" #include "colmatch.h" #include "cache1d.h" #include "palette.h" #include "a.h" #include "xxhash.h" uint8_t *basepaltable[MAXBASEPALS] ={ palette }; uint8_t basepalreset=1; uint8_t curbasepal; int32_t globalblend; uint32_t g_lastpalettesum = 0; palette_t curpalette[256]; // the current palette, unadjusted for brightness or tint palette_t curpalettefaded[256]; // the current palette, adjusted for brightness and tint (ie. what gets sent to the card) palette_t palfadergb ={ 0,0,0,0 }; char palfadedelta = 0; uint8_t blackcol; #if defined(USE_OPENGL) palette_t palookupfog[MAXPALOOKUPS]; #endif // For every pal number, whether tsprite pal should not be taken over from // floor pal. // NOTE: g_noFloorPal[0] is irrelevant as it's never checked. int8_t g_noFloorPal[MAXPALOOKUPS]; int32_t curbrightness = 0, gammabrightness = 0; static void setpalettefade_calc(uint8_t offset); void fade_screen_black(int32_t moreopaquep) { #ifdef USE_OPENGL if (getrendermode() >= REND_POLYMOST) fullscreen_tint_gl(0, 0, 0, moreopaquep ? 168 : 84); else #endif { Bassert(!offscreenrendering); begindrawing(); { char *const p = (char *) frameplace; const char *const trans = getblendtab(0); const int32_t shiftamnt = ((!!moreopaquep)*8); const int32_t dimprod = xdim*ydim; int32_t i = 0; #ifdef CLASSIC_SLICE_BY_4 for (; i= 256) { static char const * const seekfail = "Warning: klseek() failed in loadpalette()!\n"; uint16_t temp; if (kread_and_test(fil, &temp, 2)) return kclose(fil); temp = B_LITTLE16(temp); if (temp == 770 || numshades > 256) // 02 03 { if (klseek(fil, -4, BSEEK_CUR) < 0) { initputs(seekfail); return kclose(fil); } numshades = 32; lamedukep = 1; } else { if (klseek(fil, -2, BSEEK_CUR) < 0) { initputs(seekfail); return kclose(fil); } } } // Read base shade table (palookup 0). maybe_alloc_palookup(0); if (kread_and_test(fil, palookup[0], numshades<<8)) return kclose(fil); paletteloaded |= PALETTE_SHADE; // PALETTE_TRANSLUC char * const transluc = blendtable[0] = (char *) Xcalloc(256, 256); // Read translucency (blending) table. if (lamedukep) { for (int i=0; i<255; i++) { // NOTE: LameDuke's table doesn't have the last row or column (i==255). // Read the entries above and on the diagonal, if the table is // thought as being row-major. if (kread_and_test(fil, &transluc[256*i + i], 256-i-1)) return kclose(fil); // Duplicate the entries below the diagonal. for (int j=0; j= 1 && lognumalphatabs <= 7)) initprintf("invalid lognumalphatabs value, must be in [1 .. 7]\n"); else numalphatabs = 1< k) { k = j; whitecol = i; } } for (int i=0, j, k=768; i<256; i++) { j = palette[i*3] + palette[i*3+1] + palette[i*3+2]; if (j < k) { k = j; blackcol = i; } } redcol = getclosestcol(255, 0, 0); // Bmemset(PaletteIndexFullbrights, 0, sizeof(PaletteIndexFullbrights)); for (int c = 0; c < 255; ++c) // skipping transparent color { char const * const thispalookup = palookup[0]; char const color = thispalookup[c]; if (EDUKE32_PREDICT_FALSE(palette[color*3] == 0 && palette[color*3+1] == 0 && palette[color*3+2] == 0)) continue; // don't consider #000000 fullbright for (int s = c + 256; s < 256*32; s += 256) if (EDUKE32_PREDICT_FALSE(thispalookup[s] != color)) goto PostLoad_NotFullbright; SetPaletteIndexFullbright(c); PostLoad_NotFullbright: continue; // should be optimized out } } // // E_PostInitTables // int32_t E_PostInitTables(void) { if (!(paletteloaded & PALETTE_MAIN)) return E_FatalError("No palette found."); if (!(paletteloaded & PALETTE_SHADE)) return E_FatalError("No shade table found."); if (!(paletteloaded & PALETTE_TRANSLUC)) return E_FatalError("No translucency table found."); E_PostLoadPalette(); return 0; } void E_ReplaceTransparentColorWithBlack(void) { for (int i=0; i: kopen4load file handle // // Returns: // - on success, 0 // - on error, -1 (didn't read enough data) // - -2: error, we already wrote an error message ourselves int32_t loadlookups(int32_t fp) { uint8_t numlookups; char remapbuf[256]; if (kread_and_test(fp, &numlookups, 1)) return -1; for (int j=0; j= 256-RESERVEDPALS) { initprintf("ERROR: attempt to load lookup at reserved pal %d\n", palnum); return -2; } if (kread_and_test(fp, remapbuf, 256)) return -1; makepalookup(palnum, remapbuf, 0, 0, 0, 0); } return 0; } void generatefogpals(void) { // Find a gap of four consecutive unused pal numbers to generate fog shade // tables. for (int32_t j=1; j<=255-3; j++) if (!palookup[j] && !palookup[j+1] && !palookup[j+2] && !palookup[j+3]) { makepalookup(j, NULL, 60, 60, 60, 1); makepalookup(j+1, NULL, 60, 0, 0, 1); makepalookup(j+2, NULL, 0, 60, 0, 1); makepalookup(j+3, NULL, 0, 0, 60, 1); break; } } void fillemptylookups(void) { // Alias remaining unused pal numbers to the base shade table. for (int32_t j=1; j= MAXPALOOKUPS) return; g_noFloorPal[palnum] = noFloorPal; if (remapbuf==NULL) { if ((r|g|b) == 0) { palookup[palnum] = palookup[0]; // Alias to base shade table! return; } if (idmap[0]==1) // init identity map for (i=0; i<256; i++) idmap[i] = i; remapbuf = idmap; } maybe_alloc_palookup(palnum); if ((r|g|b) == 0) { // "black fog"/visibility case -- only remap color indices for (j=0; j= MAXBASEPALS ||*/ basepaltable[dapalid] == NULL) dapalid = 0; #ifdef USE_OPENGL paldidchange = (curbasepal != dapalid || basepalreset); #endif curbasepal = dapalid; basepalreset = 0; dapal = basepaltable[curbasepal]; if (!(flags&4)) { curbrightness = clamp(dabrightness, 0, 15); // if (lastbright != (unsigned)curbrightness) // vid_gamma = 1.0 + ((float)curbrightness / 10.0); } nohwgamma = setgamma(); j = nohwgamma ? curbrightness : 0; for (i=0; i<256; i++) { // save palette without any brightness adjustment curpalette[i].r = dapal[i*3+0]; curpalette[i].g = dapal[i*3+1]; curpalette[i].b = dapal[i*3+2]; curpalette[i].f = 0; // brightness adjust the palette curpalettefaded[i].b = britable[j][curpalette[i].b]; curpalettefaded[i].g = britable[j][curpalette[i].g]; curpalettefaded[i].r = britable[j][curpalette[i].r]; curpalettefaded[i].f = 0; } if ((flags&16) && palfadedelta) // keep the fade setpalettefade_calc(palfadedelta>>2); { static uint32_t lastpalettesum=0; uint32_t newpalettesum = XXH32((uint8_t *) curpalettefaded, sizeof(curpalettefaded), sizeof(curpalettefaded)); palsumdidchange = (newpalettesum != lastpalettesum); if (palsumdidchange || newpalettesum != g_lastpalettesum) { // if ((flags&1) == 0) setpalette(0, 256); } g_lastpalettesum = lastpalettesum = newpalettesum; } #ifdef USE_OPENGL if (getrendermode() >= REND_POLYMOST) { // Only reset the textures if the corresponding preserve flags are clear and // either (a) the new palette is different to the last, or (b) the brightness // changed and we couldn't set it using hardware gamma. // XXX: no-HW-gamma OpenGL platforms will exhibit bad performance with // simultaneous basepal and tint changes? const int32_t doinvalidate = (paldidchange || (palsumdidchange && nohwgamma)); if (!(flags&2) && doinvalidate) gltexinvalidatetype(INVALIDATE_ALL); if (!(flags&8) && doinvalidate) gltexinvalidatetype(INVALIDATE_ART); #ifdef POLYMER if ((getrendermode() == REND_POLYMER) && doinvalidate) polymer_texinvalidate(); #endif } #endif if ((flags&16)==0) { palfadergb.r = palfadergb.g = palfadergb.b = 0; palfadedelta = 0; } } palette_t getpal(int32_t col) { if (!gammabrightness) { palette_t p ={ britable[curbrightness][curpalette[col].b], britable[curbrightness][curpalette[col].g], britable[curbrightness][curpalette[col].r], 0 }; return p; } return curpalette[col]; } static void setpalettefade_calc(uint8_t offset) { int32_t i; palette_t p; for (i=0; i<256; i++) { p = getpal(i); curpalettefaded[i].b = p.b + (((palfadergb.b - p.b) * offset) >> 8); curpalettefaded[i].g = p.g + (((palfadergb.g - p.g) * offset) >> 8); curpalettefaded[i].r = p.r + (((palfadergb.r - p.r) * offset) >> 8); curpalettefaded[i].f = 0; } } //#define DEBUG_PALETTEFADE // // setpalettefade // void setpalettefade(uint8_t r, uint8_t g, uint8_t b, uint8_t offset) { palfadergb.r = r; palfadergb.g = g; palfadergb.b = b; #ifdef DEBUG_PALETTEFADE if (offset) offset = max(offset, 128); #endif palfadedelta = offset; setpalettefade_calc(offset); { static uint32_t lastpalettesum=0; uint32_t newpalettesum = XXH32((uint8_t *) curpalettefaded, sizeof(curpalettefaded), sizeof(curpalettefaded)); if (newpalettesum != lastpalettesum || newpalettesum != g_lastpalettesum) setpalette(0, 256); g_lastpalettesum = lastpalettesum = newpalettesum; } }