2018-11-05 07:28:01 +00:00
|
|
|
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
|
|
|
|
// Ken Silverman's official web site: "http://www.advsys.net/ken"
|
|
|
|
// See the included license file "BUILDLIC.TXT" for license info.
|
|
|
|
//
|
|
|
|
// This file has been modified from Ken Silverman's original release
|
|
|
|
// by Jonathon Fowler (jf@jonof.id.au)
|
|
|
|
// by the EDuke32 team (development@voidpoint.com)
|
|
|
|
|
2016-06-21 00:33:06 +00:00
|
|
|
#include "compat.h"
|
|
|
|
#include "build.h"
|
2016-09-17 19:57:58 +00:00
|
|
|
#include "engine_priv.h"
|
2016-09-16 21:55:21 +00:00
|
|
|
#include "baselayer.h"
|
2020-01-28 09:31:59 +00:00
|
|
|
#include "imagehelpers.h"
|
2019-12-17 22:25:07 +00:00
|
|
|
|
2016-06-21 00:33:06 +00:00
|
|
|
#include "palette.h"
|
2019-11-02 21:52:13 +00:00
|
|
|
#include "superfasthash.h"
|
2019-10-10 22:34:27 +00:00
|
|
|
#include "common.h"
|
2019-09-16 19:08:42 +00:00
|
|
|
#include "../../glbackend/glbackend.h"
|
2016-06-21 00:33:06 +00:00
|
|
|
|
2017-02-05 20:58:33 +00:00
|
|
|
uint8_t *basepaltable[MAXBASEPALS] = { palette };
|
2016-06-21 00:33:06 +00:00
|
|
|
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
|
2017-02-05 20:58:33 +00:00
|
|
|
palette_t palfadergb = { 0, 0, 0, 0 };
|
2020-01-19 22:18:38 +00:00
|
|
|
unsigned char palfadedelta = 0;
|
2020-01-26 09:58:00 +00:00
|
|
|
ESetPalFlags curpaletteflags;
|
2016-06-21 00:33:06 +00:00
|
|
|
|
2017-11-29 07:29:30 +00:00
|
|
|
int32_t realmaxshade;
|
|
|
|
float frealmaxshade;
|
|
|
|
|
2016-06-21 00:33:06 +00:00
|
|
|
#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];
|
|
|
|
|
2019-10-05 19:59:03 +00:00
|
|
|
int32_t curbrightness = 0;
|
2016-06-21 00:33:06 +00:00
|
|
|
|
2019-11-10 14:15:14 +00:00
|
|
|
void setBlendFactor(int index, int alpha);
|
2016-06-21 00:33:06 +00:00
|
|
|
|
2019-09-19 20:02:45 +00:00
|
|
|
|
2019-11-10 14:15:14 +00:00
|
|
|
int DetermineTranslucency(const uint8_t *table)
|
2019-09-19 20:02:45 +00:00
|
|
|
{
|
2019-11-10 14:15:14 +00:00
|
|
|
uint8_t index;
|
|
|
|
PalEntry newcolor;
|
|
|
|
PalEntry newcolor2;
|
|
|
|
|
|
|
|
index = table[blackcol * 256 + whitecol];
|
|
|
|
auto pp = &basepaltable[0][index];
|
|
|
|
newcolor = PalEntry(pp[0], pp[1], pp[2]);
|
|
|
|
|
|
|
|
index = table[whitecol * 256 + blackcol];
|
|
|
|
pp = &basepaltable[0][index];
|
|
|
|
newcolor2 = PalEntry(pp[0], pp[1], pp[2]);
|
|
|
|
if (newcolor2.r == 255) // if black on white results in white it's either
|
|
|
|
// fully transparent or additive
|
|
|
|
{
|
|
|
|
return -newcolor.r;
|
|
|
|
}
|
2019-10-04 16:12:03 +00:00
|
|
|
|
2019-11-10 14:15:14 +00:00
|
|
|
return newcolor.r;
|
2019-09-19 20:02:45 +00:00
|
|
|
}
|
2019-11-10 14:15:14 +00:00
|
|
|
|
|
|
|
void fullscreen_tint_gl(PalEntry pe);
|
2018-04-12 21:02:31 +00:00
|
|
|
|
2016-06-21 00:33:06 +00:00
|
|
|
static void alloc_palookup(int32_t pal)
|
|
|
|
{
|
|
|
|
// The asm functions vlineasm1, mvlineasm1 (maybe others?) access the next
|
|
|
|
// palookup[...] shade entry for tilesizy==512 tiles.
|
|
|
|
// See DEBUG_TILESIZY_512 and the comment in a.nasm: vlineasm1.
|
2017-09-19 19:10:19 +00:00
|
|
|
palookup[pal] = (char *) Xaligned_alloc(16, (numshades + 1) * 256);
|
|
|
|
memset(palookup[pal], 0, (numshades + 1) * 256);
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void maybe_alloc_palookup(int32_t palnum);
|
|
|
|
|
2019-09-19 20:02:45 +00:00
|
|
|
void (*paletteLoadFromDisk_replace)(void) = NULL;
|
|
|
|
|
2019-10-20 22:13:17 +00:00
|
|
|
inline bool read_and_test(FileReader& handle, void* buffer, int32_t leng)
|
|
|
|
{
|
|
|
|
return handle.Read(buffer, leng) != leng;
|
|
|
|
};
|
|
|
|
|
2016-06-21 00:33:06 +00:00
|
|
|
//
|
|
|
|
// loadpalette (internal)
|
|
|
|
//
|
2018-04-12 21:03:12 +00:00
|
|
|
void paletteLoadFromDisk(void)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
|
2016-10-09 07:55:23 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-10-25 23:33:40 +00:00
|
|
|
for (auto & x : glblend)
|
|
|
|
x = defaultglblend;
|
2016-10-09 07:55:23 +00:00
|
|
|
#endif
|
|
|
|
|
2019-09-19 20:02:45 +00:00
|
|
|
if (paletteLoadFromDisk_replace)
|
|
|
|
{
|
|
|
|
paletteLoadFromDisk_replace();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-12-07 09:14:51 +00:00
|
|
|
auto fil = fileSystem.OpenFileReader("palette.dat", 0);
|
2019-10-20 22:13:17 +00:00
|
|
|
if (!fil.isOpen())
|
2016-06-21 00:33:06 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// PALETTE_MAIN
|
|
|
|
|
2019-10-20 22:13:17 +00:00
|
|
|
if (768 != fil.Read(palette, 768))
|
|
|
|
return;
|
2016-06-21 00:33:06 +00:00
|
|
|
|
2018-10-25 23:33:40 +00:00
|
|
|
for (unsigned char & k : palette)
|
|
|
|
k <<= 2;
|
2016-06-21 00:33:06 +00:00
|
|
|
|
|
|
|
paletteloaded |= PALETTE_MAIN;
|
|
|
|
|
|
|
|
|
|
|
|
// PALETTE_SHADES
|
|
|
|
|
2019-10-20 22:13:17 +00:00
|
|
|
if (2 != fil.Read(&numshades, 2))
|
|
|
|
return;
|
|
|
|
|
2016-06-21 00:33:06 +00:00
|
|
|
numshades = B_LITTLE16(numshades);
|
|
|
|
|
|
|
|
if (numshades <= 1)
|
|
|
|
{
|
2020-04-11 21:45:45 +00:00
|
|
|
Printf("Warning: Invalid number of shades in \"palette.dat\"!\n");
|
2016-06-21 00:33:06 +00:00
|
|
|
numshades = 0;
|
2019-10-20 22:13:17 +00:00
|
|
|
return;
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Auto-detect LameDuke. Its PALETTE.DAT doesn't have a 'numshades' 16-bit
|
|
|
|
// int after the base palette, but starts directly with the shade tables.
|
|
|
|
// Thus, the first two bytes will be 00 01, which is 256 if read as
|
|
|
|
// little-endian int16_t.
|
|
|
|
int32_t lamedukep = 0;
|
|
|
|
if (numshades >= 256)
|
|
|
|
{
|
|
|
|
uint16_t temp;
|
2019-10-20 22:13:17 +00:00
|
|
|
if (read_and_test(fil, &temp, 2))
|
|
|
|
return;
|
2016-06-21 00:33:06 +00:00
|
|
|
temp = B_LITTLE16(temp);
|
|
|
|
if (temp == 770 || numshades > 256) // 02 03
|
|
|
|
{
|
2019-10-20 22:13:17 +00:00
|
|
|
if (fil.Seek(-4, FileReader::SeekCur) < 0)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
2020-04-11 21:45:45 +00:00
|
|
|
Printf("Warning: seek failed in loadpalette()!\n");
|
2019-10-20 22:13:17 +00:00
|
|
|
return;
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
numshades = 32;
|
|
|
|
lamedukep = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-10-20 22:13:17 +00:00
|
|
|
if (fil.Seek(-2, FileReader::SeekCur) < 0)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
2020-04-11 21:45:45 +00:00
|
|
|
Printf("Warning: seek failed in loadpalette()!\n");
|
2019-10-20 22:13:17 +00:00
|
|
|
return;
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read base shade table (palookup 0).
|
|
|
|
maybe_alloc_palookup(0);
|
2019-10-20 22:13:17 +00:00
|
|
|
if (read_and_test(fil, palookup[0], numshades<<8))
|
|
|
|
return;
|
2016-06-21 00:33:06 +00:00
|
|
|
|
|
|
|
paletteloaded |= PALETTE_SHADE;
|
|
|
|
paletteloaded |= PALETTE_TRANSLUC;
|
|
|
|
|
|
|
|
|
|
|
|
// additional blending tables
|
|
|
|
|
|
|
|
uint8_t magic[12];
|
2019-10-20 22:13:17 +00:00
|
|
|
if (!read_and_test(fil, magic, sizeof(magic)) && !Bmemcmp(magic, "MoreBlendTab", sizeof(magic)))
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
uint8_t addblendtabs;
|
2019-10-20 22:13:17 +00:00
|
|
|
if (read_and_test(fil, &addblendtabs, 1))
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
2020-04-11 21:45:45 +00:00
|
|
|
Printf("Warning: failed reading additional blending table count\n");
|
2019-10-20 22:13:17 +00:00
|
|
|
return;
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t blendnum;
|
|
|
|
char *tab = (char *) Xmalloc(256*256);
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<addblendtabs; i++)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
2019-10-20 22:13:17 +00:00
|
|
|
if (read_and_test(fil, &blendnum, 1))
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
2020-04-11 21:45:45 +00:00
|
|
|
Printf("Warning: failed reading additional blending table index\n");
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(tab);
|
2019-10-20 22:13:17 +00:00
|
|
|
return;
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
2019-10-20 22:13:17 +00:00
|
|
|
if (read_and_test(fil, tab, 256*256))
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
2020-04-11 21:45:45 +00:00
|
|
|
Printf("Warning: failed reading additional blending table\n");
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(tab);
|
2019-10-20 22:13:17 +00:00
|
|
|
return;
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
2019-11-10 14:15:14 +00:00
|
|
|
setBlendFactor(blendnum, DetermineTranslucency((const uint8_t*)tab));
|
|
|
|
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(tab);
|
2016-06-21 00:33:06 +00:00
|
|
|
|
|
|
|
// Read log2 of count of alpha blending tables.
|
|
|
|
uint8_t lognumalphatabs;
|
2019-10-20 22:13:17 +00:00
|
|
|
if (!read_and_test(fil, &lognumalphatabs, 1))
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
if (!(lognumalphatabs >= 1 && lognumalphatabs <= 7))
|
2020-04-11 21:45:45 +00:00
|
|
|
Printf("invalid lognumalphatabs value, must be in [1 .. 7]\n");
|
2016-06-21 00:33:06 +00:00
|
|
|
else
|
|
|
|
numalphatabs = 1<<lognumalphatabs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-23 07:03:36 +00:00
|
|
|
uint8_t PaletteIndexFullbrights[32];
|
2016-06-21 00:33:06 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
void palettePostLoadTables(void)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
globalpal = 0;
|
2016-09-17 19:57:58 +00:00
|
|
|
|
2016-06-21 00:33:06 +00:00
|
|
|
globalpalwritten = palookup[0];
|
|
|
|
|
2017-11-29 07:29:27 +00:00
|
|
|
char const * const palookup0 = palookup[0];
|
|
|
|
|
2016-06-21 00:33:06 +00:00
|
|
|
#ifdef DEBUG_TILESIZY_512
|
|
|
|
// Bump shade 1 by 16.
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=256; i<512; i++)
|
2017-11-29 07:29:27 +00:00
|
|
|
palookup0[i] = palookup0[i+(16<<8)];
|
2016-06-21 00:33:06 +00:00
|
|
|
#endif
|
2020-01-30 21:05:18 +00:00
|
|
|
PalEntry pe[256];
|
|
|
|
for (int i = 0; i < 256; i++) pe[i] = PalEntry(palette[i * 3], palette[i * 3 + 1], palette[i * 3 + 2]);
|
|
|
|
ImageHelpers::SetPalette(pe);
|
2020-01-28 09:31:59 +00:00
|
|
|
blackcol = ImageHelpers::BestColor(0, 0, 0);
|
|
|
|
whitecol = ImageHelpers::BestColor(255, 255, 255);
|
|
|
|
redcol = ImageHelpers::BestColor(255, 0, 0);
|
2016-06-21 00:33:06 +00:00
|
|
|
|
|
|
|
// Bmemset(PaletteIndexFullbrights, 0, sizeof(PaletteIndexFullbrights));
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t c = 0; c < 255; ++c) // skipping transparent color
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
2017-11-29 07:29:27 +00:00
|
|
|
uint8_t const index = palookup0[c];
|
|
|
|
rgb24_t const & color = *(rgb24_t *)&palette[index*3];
|
2016-06-21 00:33:06 +00:00
|
|
|
|
2017-11-29 07:29:27 +00:00
|
|
|
// don't consider #000000 fullbright
|
|
|
|
if (EDUKE32_PREDICT_FALSE(color.r == 0 && color.g == 0 && color.b == 0))
|
|
|
|
continue;
|
2016-06-21 00:33:06 +00:00
|
|
|
|
2017-11-29 07:29:27 +00:00
|
|
|
for (size_t s = c + 256, s_end = 256*numshades; s < s_end; s += 256)
|
|
|
|
if (EDUKE32_PREDICT_FALSE(palookup0[s] != index))
|
2016-06-21 00:33:06 +00:00
|
|
|
goto PostLoad_NotFullbright;
|
|
|
|
|
|
|
|
SetPaletteIndexFullbright(c);
|
|
|
|
|
2017-11-29 07:29:27 +00:00
|
|
|
PostLoad_NotFullbright: ;
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
2017-11-29 07:29:30 +00:00
|
|
|
|
2018-01-26 04:35:15 +00:00
|
|
|
if (realmaxshade == 0)
|
2017-11-29 07:29:30 +00:00
|
|
|
{
|
2018-01-26 04:35:15 +00:00
|
|
|
uint8_t const * const blackcolor = &palette[blackcol*3];
|
|
|
|
size_t s;
|
|
|
|
for (s = numshades < 2 ? 0 : numshades-2; s > 0; --s)
|
2017-11-29 07:29:30 +00:00
|
|
|
{
|
2018-01-26 04:35:15 +00:00
|
|
|
for (size_t c = s*256, c_end = c+255; c < c_end; ++c) // skipping transparent color
|
|
|
|
{
|
|
|
|
uint8_t const index = palookup0[c];
|
|
|
|
uint8_t const * const color = &palette[index*3];
|
|
|
|
if (!IsPaletteIndexFullbright(index) && memcmp(blackcolor, color, sizeof(rgb24_t)))
|
|
|
|
goto PostLoad_FoundShade;
|
|
|
|
}
|
2017-11-29 07:29:30 +00:00
|
|
|
}
|
2018-01-26 04:35:15 +00:00
|
|
|
PostLoad_FoundShade: ;
|
|
|
|
frealmaxshade = (float)(realmaxshade = s+1);
|
2017-11-29 07:29:30 +00:00
|
|
|
}
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
void paletteFixTranslucencyMask(void)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
2018-12-15 01:39:51 +00:00
|
|
|
for (auto thispalookup : palookup)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
if (thispalookup == NULL)
|
|
|
|
continue;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j=0; j<numshades; j++)
|
2016-06-21 00:33:06 +00:00
|
|
|
thispalookup[(j<<8) + 255] = 255;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load LOOKUP.DAT, which contains lookup tables and additional base palettes.
|
|
|
|
//
|
2019-10-20 22:13:17 +00:00
|
|
|
// <fp>: open file handle
|
2016-06-21 00:33:06 +00:00
|
|
|
//
|
|
|
|
// Returns:
|
|
|
|
// - on success, 0
|
|
|
|
// - on error, -1 (didn't read enough data)
|
|
|
|
// - -2: error, we already wrote an error message ourselves
|
2019-10-20 20:26:53 +00:00
|
|
|
int32_t paletteLoadLookupTable(FileReader &fp)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
uint8_t numlookups;
|
|
|
|
char remapbuf[256];
|
|
|
|
|
2019-10-20 20:26:53 +00:00
|
|
|
if (1 != fp.Read(&numlookups, 1))
|
2016-06-21 00:33:06 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j=0; j<numlookups; j++)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
uint8_t palnum;
|
|
|
|
|
2019-10-20 20:26:53 +00:00
|
|
|
if (1 != fp.Read(&palnum, 1))
|
2016-06-21 00:33:06 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (palnum >= 256-RESERVEDPALS)
|
|
|
|
{
|
2020-04-11 21:45:45 +00:00
|
|
|
Printf("ERROR: attempt to load lookup at reserved pal %d\n", palnum);
|
2016-06-21 00:33:06 +00:00
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2019-10-20 20:26:53 +00:00
|
|
|
if (256 != fp.Read(remapbuf, 256))
|
2016-06-21 00:33:06 +00:00
|
|
|
return -1;
|
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
paletteMakeLookupTable(palnum, remapbuf, 0, 0, 0, 0);
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
void paletteSetupDefaultFog(void)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
// Find a gap of four consecutive unused pal numbers to generate fog shade
|
|
|
|
// tables.
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j=1; j<=255-3; j++)
|
2016-06-21 00:33:06 +00:00
|
|
|
if (!palookup[j] && !palookup[j+1] && !palookup[j+2] && !palookup[j+3])
|
|
|
|
{
|
2018-04-12 21:03:12 +00:00
|
|
|
paletteMakeLookupTable(j, NULL, 60, 60, 60, 1);
|
|
|
|
paletteMakeLookupTable(j+1, NULL, 60, 0, 0, 1);
|
|
|
|
paletteMakeLookupTable(j+2, NULL, 0, 60, 0, 1);
|
|
|
|
paletteMakeLookupTable(j+3, NULL, 0, 0, 60, 1);
|
2016-06-21 00:33:06 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
void palettePostLoadLookups(void)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
// Alias remaining unused pal numbers to the base shade table.
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j=1; j<MAXPALOOKUPS; j++)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
// If an existing lookup is identical to #0, free it.
|
|
|
|
if (palookup[j] && palookup[j] != palookup[0] && !Bmemcmp(palookup[0], palookup[j], 256*numshades))
|
2018-04-12 21:03:12 +00:00
|
|
|
paletteFreeLookupTable(j);
|
2016-06-21 00:33:06 +00:00
|
|
|
|
|
|
|
if (!palookup[j])
|
2018-04-12 21:03:12 +00:00
|
|
|
paletteMakeLookupTable(j, NULL, 0, 0, 0, 1);
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32_t palookup_isdefault(int32_t palnum) // KEEPINSYNC engine.lua
|
|
|
|
{
|
|
|
|
return (palookup[palnum] == NULL || (palnum!=0 && palookup[palnum] == palookup[0]));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void maybe_alloc_palookup(int32_t palnum)
|
|
|
|
{
|
|
|
|
if (palookup_isdefault(palnum))
|
|
|
|
{
|
|
|
|
alloc_palookup(palnum);
|
|
|
|
if (palookup[palnum] == NULL)
|
|
|
|
Bexit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-09 07:55:23 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
glblend_t const nullglblend =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{ 1.f, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, 0 },
|
|
|
|
{ 1.f, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, 0 },
|
|
|
|
},
|
|
|
|
};
|
|
|
|
glblend_t const defaultglblend =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{ 2.f/3.f, BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 0 },
|
|
|
|
{ 1.f/3.f, BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 0 },
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
glblend_t glblend[MAXBLENDTABS];
|
|
|
|
|
2019-11-10 14:15:14 +00:00
|
|
|
void setBlendFactor(int index, int alpha)
|
|
|
|
{
|
|
|
|
if (index >= 0 && index < MAXBLENDTABS)
|
|
|
|
{
|
|
|
|
auto& myblend = glblend[index];
|
|
|
|
if (index >= 0)
|
|
|
|
{
|
|
|
|
myblend.def[0].alpha = index / 255.f;
|
|
|
|
myblend.def[1].alpha = 1.f - (index / 255.f);
|
|
|
|
myblend.def[0].src = myblend.def[1].src = BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
|
|
|
|
myblend.def[0].dst = myblend.def[1].dst = BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
myblend.def[0].alpha = 1;
|
|
|
|
myblend.def[1].alpha = 1;
|
|
|
|
myblend.def[0].src = myblend.def[1].src = BLENDFACTOR_ONE;
|
|
|
|
myblend.def[0].dst = myblend.def[1].dst = BLENDFACTOR_ONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-29 20:36:21 +00:00
|
|
|
FRenderStyle GetBlend(int blend, int def)
|
2016-10-09 07:55:23 +00:00
|
|
|
{
|
2019-12-23 20:19:42 +00:00
|
|
|
static uint8_t const blendFuncTokens[NUMBLENDFACTORS] =
|
2016-10-09 07:55:23 +00:00
|
|
|
{
|
2019-10-04 17:17:55 +00:00
|
|
|
STYLEALPHA_Zero,
|
|
|
|
STYLEALPHA_One,
|
|
|
|
STYLEALPHA_SrcCol,
|
|
|
|
STYLEALPHA_InvSrcCol,
|
|
|
|
STYLEALPHA_Src,
|
|
|
|
STYLEALPHA_InvSrc,
|
|
|
|
STYLEALPHA_Dst,
|
2019-12-29 20:36:21 +00:00
|
|
|
STYLEALPHA_InvDst,
|
|
|
|
STYLEALPHA_DstCol,
|
|
|
|
STYLEALPHA_InvDstCol,
|
|
|
|
};
|
|
|
|
FRenderStyle rs;
|
|
|
|
rs.BlendOp = STYLEOP_Add;
|
|
|
|
glblenddef_t const* const glbdef = glblend[blend].def + def;
|
|
|
|
rs.SrcAlpha = blendFuncTokens[glbdef->src];
|
2019-12-30 20:03:15 +00:00
|
|
|
rs.DestAlpha = blendFuncTokens[glbdef->dst];
|
2019-12-29 20:36:21 +00:00
|
|
|
rs.Flags = 0;
|
|
|
|
return rs;
|
|
|
|
}
|
2016-10-09 07:55:23 +00:00
|
|
|
|
2019-12-29 20:36:21 +00:00
|
|
|
void handle_blend(uint8_t enable, uint8_t blend, uint8_t def)
|
|
|
|
{
|
2016-10-09 07:55:23 +00:00
|
|
|
if (!enable)
|
|
|
|
{
|
2020-01-03 09:09:38 +00:00
|
|
|
GLInterface.SetRenderStyle(LegacyRenderStyles[STYLE_Translucent]);
|
2019-10-04 17:17:55 +00:00
|
|
|
return;
|
2016-10-09 07:55:23 +00:00
|
|
|
}
|
2019-12-29 20:36:21 +00:00
|
|
|
auto rs = GetBlend(blend, def);
|
2020-01-03 09:09:38 +00:00
|
|
|
GLInterface.SetRenderStyle(rs);
|
2019-12-29 20:36:21 +00:00
|
|
|
}
|
2016-10-09 07:55:23 +00:00
|
|
|
|
2019-12-29 20:36:21 +00:00
|
|
|
float float_trans(uint32_t maskprops, uint8_t blend)
|
|
|
|
{
|
|
|
|
switch (maskprops)
|
|
|
|
{
|
|
|
|
case DAMETH_TRANS1:
|
|
|
|
case DAMETH_TRANS2:
|
|
|
|
return glblend[blend].def[maskprops - 2].alpha;
|
|
|
|
default:
|
|
|
|
return 1.0f;
|
|
|
|
}
|
2016-10-09 07:55:23 +00:00
|
|
|
}
|
2019-12-29 20:36:21 +00:00
|
|
|
|
2016-10-09 07:55:23 +00:00
|
|
|
#endif
|
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
int32_t paletteSetLookupTable(int32_t palnum, const uint8_t *shtab)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
if (shtab != NULL)
|
|
|
|
{
|
|
|
|
maybe_alloc_palookup(palnum);
|
|
|
|
Bmemcpy(palookup[palnum], shtab, 256*numshades);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2018-04-12 21:03:12 +00:00
|
|
|
|
|
|
|
void paletteFreeLookupTable(int32_t const palnum)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
if (palnum == 0 && palookup[palnum] != NULL)
|
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i = 1; i < MAXPALOOKUPS; i++)
|
2016-06-21 00:33:06 +00:00
|
|
|
if (palookup[i] == palookup[palnum])
|
|
|
|
palookup[i] = NULL;
|
|
|
|
|
2017-09-19 19:10:19 +00:00
|
|
|
ALIGNED_FREE_AND_NULL(palookup[palnum]);
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
else if (palookup[palnum] == palookup[0])
|
|
|
|
palookup[palnum] = NULL;
|
|
|
|
else
|
2017-09-19 19:10:19 +00:00
|
|
|
ALIGNED_FREE_AND_NULL(palookup[palnum]);
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// makepalookup
|
|
|
|
//
|
2018-04-12 21:03:12 +00:00
|
|
|
void paletteMakeLookupTable(int32_t palnum, const char *remapbuf, uint8_t r, uint8_t g, uint8_t b, char noFloorPal)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
int32_t i, j;
|
|
|
|
|
2017-02-05 20:58:33 +00:00
|
|
|
static char idmap[256] = { 1 };
|
2016-06-21 00:33:06 +00:00
|
|
|
|
|
|
|
if (paletteloaded == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// NOTE: palnum==0 is allowed
|
|
|
|
if ((unsigned) palnum >= 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<numshades; j++)
|
|
|
|
for (i=0; i<256; i++)
|
|
|
|
{
|
|
|
|
const char *src = palookup[0];
|
|
|
|
palookup[palnum][256*j + i] = src[256*j + remapbuf[i]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// colored fog case
|
|
|
|
|
|
|
|
char *ptr2 = palookup[palnum];
|
|
|
|
|
|
|
|
for (i=0; i<numshades; i++)
|
|
|
|
{
|
|
|
|
int32_t palscale = divscale16(i, numshades-1);
|
|
|
|
|
|
|
|
for (j=0; j<256; j++)
|
|
|
|
{
|
|
|
|
const char *ptr = (const char *) &palette[remapbuf[j]*3];
|
2020-01-28 09:31:59 +00:00
|
|
|
*ptr2++ = ImageHelpers::BestColor(ptr[0] + mulscale16(r-ptr[0], palscale),
|
2016-06-21 00:33:06 +00:00
|
|
|
ptr[1] + mulscale16(g-ptr[1], palscale),
|
|
|
|
ptr[2] + mulscale16(b-ptr[2], palscale));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(USE_OPENGL)
|
|
|
|
palookupfog[palnum].r = r;
|
|
|
|
palookupfog[palnum].g = g;
|
|
|
|
palookupfog[palnum].b = b;
|
2019-11-10 20:11:17 +00:00
|
|
|
palookupfog[palnum].f = 1;
|
2016-06-21 00:33:06 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// setbasepal
|
|
|
|
//
|
2019-10-06 17:32:35 +00:00
|
|
|
void paletteSetColorTable(int32_t id, uint8_t const * const table, bool transient)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
if (basepaltable[id] == NULL)
|
|
|
|
basepaltable[id] = (uint8_t *) Xmalloc(768);
|
|
|
|
|
|
|
|
Bmemcpy(basepaltable[id], table, 768);
|
2018-03-21 20:41:26 +00:00
|
|
|
|
2018-06-12 02:13:32 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-06-25 14:53:46 +00:00
|
|
|
if (videoGetRenderMode() >= REND_POLYMOST)
|
2018-06-13 19:15:16 +00:00
|
|
|
{
|
2019-10-19 20:46:37 +00:00
|
|
|
uploadbasepalette(id);
|
2018-06-13 19:15:16 +00:00
|
|
|
}
|
2018-06-12 02:13:32 +00:00
|
|
|
#endif
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
2018-04-12 21:03:12 +00:00
|
|
|
|
|
|
|
void paletteFreeColorTable(int32_t const id)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
if (id == 0)
|
|
|
|
Bmemset(basepaltable[id], 0, 768);
|
|
|
|
else
|
|
|
|
DO_FREE_AND_NULL(basepaltable[id]);
|
|
|
|
}
|
|
|
|
|
2019-12-24 18:47:34 +00:00
|
|
|
void paletteFreeColorTables()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < countof(basepaltable); i++)
|
|
|
|
{
|
|
|
|
paletteFreeColorTable(i);
|
|
|
|
}
|
|
|
|
}
|
2016-06-21 00:33:06 +00:00
|
|
|
//
|
|
|
|
// setbrightness
|
|
|
|
//
|
|
|
|
// flags:
|
2019-10-10 18:28:41 +00:00
|
|
|
// 1: don't setpalette(), not checked anymore.
|
2016-06-21 00:33:06 +00:00
|
|
|
// 2: don't gltexinvalidateall()
|
|
|
|
// 4: don't calc curbrightness from dabrightness, DON'T USE THIS FLAG!
|
|
|
|
// 8: don't gltexinvalidate8()
|
|
|
|
// 16: don't reset palfade*
|
2019-10-10 18:28:41 +00:00
|
|
|
// 32: apply brightness to scene in OpenGL
|
2020-01-26 09:58:00 +00:00
|
|
|
void videoSetPalette(int dabrightness, int dapalid, ESetPalFlags flags)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
2020-03-29 15:23:57 +00:00
|
|
|
int32_t i;
|
2019-10-10 18:28:41 +00:00
|
|
|
|
|
|
|
if (/*(unsigned)dapalid >= MAXBASEPALS ||*/ basepaltable[dapalid] == NULL)
|
|
|
|
dapalid = 0;
|
|
|
|
curbasepal = dapalid;
|
|
|
|
basepalreset = 0;
|
|
|
|
|
2020-03-29 15:23:57 +00:00
|
|
|
auto dapal = basepaltable[curbasepal];
|
2019-10-10 18:28:41 +00:00
|
|
|
|
|
|
|
// In-scene brightness mode for RR's thunderstorm. This shouldn't affect the global gamma ramp.
|
2020-01-26 09:58:00 +00:00
|
|
|
if ((videoGetRenderMode() >= REND_POLYMOST) && (flags & Pal_SceneBrightness))
|
2019-10-10 18:28:41 +00:00
|
|
|
{
|
2020-01-26 09:58:00 +00:00
|
|
|
r_scenebrightness = clamp(dabrightness, 0, 15);
|
2019-10-10 18:28:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r_scenebrightness = 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;
|
|
|
|
}
|
|
|
|
|
2020-01-26 09:58:00 +00:00
|
|
|
if ((flags & Pal_DontResetFade) == 0)
|
2019-10-10 18:28:41 +00:00
|
|
|
{
|
|
|
|
palfadergb.r = palfadergb.g = palfadergb.b = 0;
|
|
|
|
palfadedelta = 0;
|
|
|
|
}
|
2020-01-26 09:58:00 +00:00
|
|
|
|
|
|
|
curpaletteflags = flags;
|
2016-06-21 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
palette_t paletteGetColor(int32_t col)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
return curpalette[col];
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// setpalettefade
|
|
|
|
//
|
2018-04-12 21:03:12 +00:00
|
|
|
void videoFadePalette(uint8_t r, uint8_t g, uint8_t b, uint8_t offset)
|
2016-06-21 00:33:06 +00:00
|
|
|
{
|
|
|
|
palfadergb.r = r;
|
|
|
|
palfadergb.g = g;
|
|
|
|
palfadergb.b = b;
|
|
|
|
palfadedelta = offset;
|
|
|
|
}
|