Classic: support for multiple blending tables + Lunatic interfaces.

Currently, sprite[].filler (to be renamed) selects a blending table. If none
is installed with that index, the blending table at index 0 is taken (which is
read from PALETTE.DAT on engine startup). Thus, for now, the non-Lunatic build
will never use a custom blending table because there's no way to register one!
But the functionality is there.

git-svn-id: https://svn.eduke32.com/eduke32@4301 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2014-02-08 14:37:49 +00:00
parent 54c74ca78e
commit 330b744a1b
4 changed files with 147 additions and 16 deletions

View file

@ -79,6 +79,7 @@ enum rendmode_t {
#define MAXPLAYERS 16 #define MAXPLAYERS 16
#define MAXBASEPALS 8 #define MAXBASEPALS 8
#define MAXPALOOKUPS 256 #define MAXPALOOKUPS 256
#define MAXBLENDTABS 256
// Maximum number of defined multi-pskies: // Maximum number of defined multi-pskies:
#define MAXPSKYMULTIS 8 #define MAXPSKYMULTIS 8
// Maximum number of component tiles in a multi-psky: // Maximum number of component tiles in a multi-psky:
@ -760,6 +761,7 @@ EXTERN int16_t sintable[2048];
EXTERN uint8_t palette[768]; EXTERN uint8_t palette[768];
EXTERN int16_t numshades; EXTERN int16_t numshades;
EXTERN char *palookup[MAXPALOOKUPS]; EXTERN char *palookup[MAXPALOOKUPS];
EXTERN char *blendtable[MAXBLENDTABS];
EXTERN uint8_t **basepaltableptr; EXTERN uint8_t **basepaltableptr;
EXTERN char showinvisibility; EXTERN char showinvisibility;
EXTERN int32_t g_visibility, parallaxvisibility; EXTERN int32_t g_visibility, parallaxvisibility;

View file

@ -2333,6 +2333,7 @@ static int32_t *horizlookup=0, *horizlookup2=0;
int32_t globalposx, globalposy, globalposz, globalhoriz; int32_t globalposx, globalposy, globalposz, globalhoriz;
int16_t globalang, globalcursectnum; int16_t globalang, globalcursectnum;
int32_t globalpal, cosglobalang, singlobalang; int32_t globalpal, cosglobalang, singlobalang;
static int32_t globalblend;
int32_t cosviewingrangeglobalang, sinviewingrangeglobalang; int32_t cosviewingrangeglobalang, sinviewingrangeglobalang;
static char *globalpalwritten; static char *globalpalwritten;
static int32_t globaluclip, globaldclip; static int32_t globaluclip, globaldclip;
@ -2364,7 +2365,6 @@ int16_t sectorborder[256], sectorbordercnt;
int32_t ydim16, qsetmode = 0; int32_t ydim16, qsetmode = 0;
int16_t pointhighlight=-1, linehighlight=-1, highlightcnt=0; int16_t pointhighlight=-1, linehighlight=-1, highlightcnt=0;
static int32_t lastx[MAXYDIM]; static int32_t lastx[MAXYDIM];
static char *transluc;
static char paletteloaded = 0; static char paletteloaded = 0;
@ -2469,7 +2469,8 @@ char palfadedelta = 0;
// //
// Internal Engine Functions // Internal Engine Functions
// //
//int32_t cacheresets = 0,cacheinvalidates = 0;
#define getblendtab(blend) (blendtable[blend])
static void setpalettefade_calc(uint8_t offset); static void setpalettefade_calc(uint8_t offset);
@ -2488,7 +2489,7 @@ void fade_screen_black(int32_t moreopaquep)
begindrawing(); begindrawing();
{ {
char *const p = (char *)frameplace; char *const p = (char *)frameplace;
const char *const trans = transluc; const char *const trans = getblendtab(0);
const int32_t shiftamnt = ((!!moreopaquep)*8); const int32_t shiftamnt = ((!!moreopaquep)*8);
const int32_t dimprod = xdim*ydim; const int32_t dimprod = xdim*ydim;
@ -4123,7 +4124,7 @@ static void nonpow2_thline(intptr_t bufplc, uint32_t bx, int32_t cntup16, int32_
const char *const buf = (char *)bufplc; const char *const buf = (char *)bufplc;
const char *const pal = (char *)asm3; const char *const pal = (char *)asm3;
const char *const trans = transluc; const char *const trans = getblendtab(globalblend);
const uint32_t xdiv = globalxspan > 1 ? (uint32_t)ourdivscale32(1, globalxspan) : UINT32_MAX; const uint32_t xdiv = globalxspan > 1 ? (uint32_t)ourdivscale32(1, globalxspan) : UINT32_MAX;
const uint32_t ydiv = globalyspan > 1 ? (uint32_t)ourdivscale32(1, globalyspan) : UINT32_MAX; const uint32_t ydiv = globalyspan > 1 ? (uint32_t)ourdivscale32(1, globalyspan) : UINT32_MAX;
@ -4249,7 +4250,7 @@ static void tslopevlin(uint8_t *p, int32_t i, const intptr_t *slopalptr, int32_t
{ {
const char *const buf = ggbuf; const char *const buf = ggbuf;
const char *const pal = ggpal; const char *const pal = ggpal;
const char *const trans = transluc; const char *const trans = getblendtab(0);
const int32_t bzinc = (asm1>>3), pinc = ggpinc; const int32_t bzinc = (asm1>>3), pinc = ggpinc;
const int32_t transmode = (globalorientation&128); const int32_t transmode = (globalorientation&128);
@ -5589,6 +5590,18 @@ static void drawsprite_opengl(int32_t snum)
//============================================================================= //POLYMOST ENDS //============================================================================= //POLYMOST ENDS
} }
static void setup_blend(int32_t blend)
{
if (blendtable[blend] == NULL)
blend = 0;
if (globalblend != blend)
{
globalblend = blend;
fixtransluscence(FP_OFF(getblendtab(blend)));
}
}
static void drawsprite_classic(int32_t snum) static void drawsprite_classic(int32_t snum)
{ {
int32_t xoff, yoff, xspan, yspan; int32_t xoff, yoff, xspan, yspan;
@ -5668,6 +5681,8 @@ static void drawsprite_classic(int32_t snum)
if (palookup[globalpal] == NULL) globalpal = 0; // JBF: fixes null-pointer crash if (palookup[globalpal] == NULL) globalpal = 0; // JBF: fixes null-pointer crash
globalshade = tspr->shade; globalshade = tspr->shade;
setup_blend(tspr->filler);
if (cstat&2) if (cstat&2)
{ {
if (cstat&512) settransreverse(); else settransnormal(); if (cstat&512) settransreverse(); else settransnormal();
@ -7981,6 +7996,7 @@ static int32_t loadpalette_err(const char *msg)
static int32_t loadpalette(void) static int32_t loadpalette(void)
{ {
int32_t fil, lamedukep=0; int32_t fil, lamedukep=0;
char *transluc;
if (paletteloaded != 0) return 0; if (paletteloaded != 0) return 0;
if ((fil = kopen4load("palette.dat",0)) == -1) if ((fil = kopen4load("palette.dat",0)) == -1)
@ -8001,6 +8017,7 @@ static int32_t loadpalette(void)
globalpalwritten = palookup[0]; globalpal = 0; globalpalwritten = palookup[0]; globalpal = 0;
setpalookupaddress(globalpalwritten); setpalookupaddress(globalpalwritten);
blendtable[0] = transluc;
fixtransluscence(FP_OFF(transluc)); fixtransluscence(FP_OFF(transluc));
// Auto-detect LameDuke. Its PALETTE.DAT doesn't have a 'numshades' 16-bit // Auto-detect LameDuke. Its PALETTE.DAT doesn't have a 'numshades' 16-bit
@ -8719,8 +8736,6 @@ void uninitengine(void)
{ {
int32_t i; int32_t i;
//OSD_Printf("cacheresets = %d, cacheinvalidates = %d\n", cacheresets, cacheinvalidates);
#ifdef USE_OPENGL #ifdef USE_OPENGL
polymost_glreset(); polymost_glreset();
hicinit(); hicinit();
@ -8737,7 +8752,6 @@ void uninitengine(void)
for (i=0; i<MAXARTFILES_TOTAL; i++) for (i=0; i<MAXARTFILES_TOTAL; i++)
DO_FREE_AND_NULL(artptrs[i]); DO_FREE_AND_NULL(artptrs[i]);
DO_FREE_AND_NULL(transluc);
DO_FREE_AND_NULL(pic); DO_FREE_AND_NULL(pic);
DO_FREE_AND_NULL(lookups); DO_FREE_AND_NULL(lookups);
@ -14659,6 +14673,23 @@ static void maybe_alloc_palookup(int32_t palnum)
} }
#ifdef LUNATIC #ifdef LUNATIC
const char *(getblendtab)(int32_t blend)
{
return blendtable[blend];
}
void setblendtab(int32_t blend, const char *tab)
{
if (blendtable[blend] == NULL)
{
blendtable[blend] = Bmalloc(256*256);
if (blendtable[blend] == NULL)
exit(1);
}
Bmemcpy(blendtable[blend], tab, 256*256);
}
int32_t setpalookup(int32_t palnum, const uint8_t *shtab) int32_t setpalookup(int32_t palnum, const uint8_t *shtab)
{ {
if (numshades != 32) if (numshades != 32)

View file

@ -18,6 +18,9 @@ int32_t getclosestcol(int32_t r, int32_t g, int32_t b);
char *palookup[256]; // MAXPALOOKUPS char *palookup[256]; // MAXPALOOKUPS
uint8_t palette[768]; uint8_t palette[768];
const char *getblendtab(int32_t blend);
void setblendtab(int32_t blend, const char *tab);
int32_t setpalookup(int32_t palnum, const uint8_t *shtab); int32_t setpalookup(int32_t palnum, const uint8_t *shtab);
]] ]]
@ -30,8 +33,8 @@ local engine = {}
local shtab_t -- forward-decl local shtab_t -- forward-decl
local function cast_u8ptr(pal256) local function cast_u8ptr(sth)
return ffi.cast("uint8_t *", pal256) return ffi.cast("uint8_t *", sth)
end end
local shtab_methods = { local shtab_methods = {
@ -73,20 +76,31 @@ local function shtab_mt__index(sht, idx)
end end
end end
local pal256_t = bcarray.new("uint8_t", 256, "shade table 256-tuple") local pal256_t = bcarray.new("uint8_t", 256, "color index 256-tuple")
-- The shade table type, effectively a bound-checked uint8_t [32][256]: -- The shade table type, effectively a bound-checked uint8_t [32][256]:
shtab_t = bcarray.new(pal256_t, 32, "shade table", nil, nil, { __index = shtab_mt__index }) shtab_t = bcarray.new(pal256_t, 32, "shade table", nil, nil, { __index = shtab_mt__index })
local SIZEOF_SHTAB = ffi.sizeof(shtab_t) local SIZEOF_SHTAB = ffi.sizeof(shtab_t)
local blendtab_t = bcarray.new(pal256_t, 256, "blending table")
local SIZEOF_BLENDTAB = ffi.sizeof(blendtab_t)
local RESERVEDPALS = 8 -- KEEPINSYNC build.h: assure that ours is >= theirs local RESERVEDPALS = 8 -- KEEPINSYNC build.h: assure that ours is >= theirs
engine.RESERVEDPALS = RESERVEDPALS engine.RESERVEDPALS = RESERVEDPALS
local MAXBLENDTABS = 256 -- KEEPINSYNC build.h
local function check_palidx(i) local function check_palidx(i)
if (type(i) ~= "number" or not (i >= 0 and i <= 255-RESERVEDPALS)) then if (type(i) ~= "number" or not (i >= 0 and i <= 255-RESERVEDPALS)) then
error("invalid argument #1: palette swap index must be in the range [0 .. "..255-RESERVEDPALS.."]", 3) error("invalid argument #1: palette swap index must be in the range [0 .. "..255-RESERVEDPALS.."]", 3)
end end
end end
local function check_blendidx(i)
if (type(i) ~= "number" or not (i >= 0 and i <= MAXBLENDTABS-1)) then
error("invalid argument #1: blending table index must be in the range [0 .. ".. MAXBLENDTABS-1 .."]", 3)
end
end
local function err_uncommon_shade_table(ret) local function err_uncommon_shade_table(ret)
if (ret == -1) then if (ret == -1) then
error("loaded engine shade tables don't have 32 gradients of shade", 3) error("loaded engine shade tables don't have 32 gradients of shade", 3)
@ -101,6 +115,10 @@ function engine.shadetab()
return shtab_t() return shtab_t()
end end
function engine.blendtab()
return blendtab_t()
end
function engine.getshadetab(palidx) function engine.getshadetab(palidx)
check_palidx(palidx) check_palidx(palidx)
if (palookup_isdefault(palidx)) then if (palookup_isdefault(palidx)) then
@ -115,13 +133,31 @@ function engine.getshadetab(palidx)
return sht return sht
end end
function engine.setshadetab(palidx, shtab) function engine.getblendtab(blendidx)
if (not ismapster32 and C.g_elFirstTime == 0) then check_blendidx(blendidx)
error("setshadetab() may be run only while LUNATIC_FIRST_TIME is true", 2)
local ptr = C.getblendtab(blendidx)
if (ptr == nil) then
return nil
end end
local tab = blendtab_t()
ffi.copy(tab, ptr, SIZEOF_BLENDTAB)
return tab
end
local function check_first_time()
if (not ismapster32 and C.g_elFirstTime == 0) then
error("may be called only while LUNATIC_FIRST_TIME is true", 3)
end
end
function engine.setshadetab(palidx, shtab)
check_first_time()
check_palidx(palidx) check_palidx(palidx)
if (not ffi.istype(shtab_t, shtab_t)) then
if (not ffi.istype(shtab_t, shtab)) then
error("invalid argument #2: must be a shade table obtained by shadetab()", 2) error("invalid argument #2: must be a shade table obtained by shadetab()", 2)
end end
@ -129,10 +165,25 @@ function engine.setshadetab(palidx, shtab)
error("attempt to override already defined shade table", 2) error("attempt to override already defined shade table", 2)
end end
local ret = C.setpalookup(palidx, ffi.cast("uint8_t *", shtab)) local ret = C.setpalookup(palidx, cast_u8ptr(shtab))
err_uncommon_shade_table(ret) err_uncommon_shade_table(ret)
end end
function engine.setblendtab(blendidx, tab)
check_first_time()
check_blendidx(blendidx)
if (not ffi.istype(blendtab_t, tab)) then
error("invalid argument #2: must be a blending table obtained by blendtab()", 2)
end
if (not ismapster32 and C.getblendtab(blendidx) ~= nil) then
error("attempt to override already defined blending table", 2)
end
C.setblendtab(blendidx, cast_u8ptr(tab))
end
local function check_colcomp(a) local function check_colcomp(a)
if (type(a) ~= "number" or not (a >= 0 and a <= 63)) then if (type(a) ~= "number" or not (a >= 0 and a <= 63)) then
@ -147,6 +198,15 @@ function engine.getrgb(colidx)
error("color index must be in the range [0 .. 255]", 2) error("color index must be in the range [0 .. 255]", 2)
end end
-- NOTE: In the game, palette[255*{0..2}] is set to 0 in
-- G_LoadExtraPalettes() via G_Startup(). However, that's after Lua state
-- initialization (i.e. when LUNATIC_FIRST_TIME would be true), and in the
-- editor, it's never changed from the purple color. Therefore, I think
-- it's more useful to always return the fully black color here.
if (colidx == 255) then
return 0, 0, 0
end
local rgbptr = C.palette + 3*colidx local rgbptr = C.palette + 3*colidx
return rgbptr[0], rgbptr[1], rgbptr[2] return rgbptr[0], rgbptr[1], rgbptr[2]
end end

View file

@ -273,6 +273,44 @@ function shadexfog.test_create0()
end end
end end
---------- Blending table tests ----------
function shadexfog.create_128_trans(startblendidx)
for alpha=1,128 do
local f = alpha/256
local F = 1-f
local tab = engine.blendtab()
for i=0,255 do
for j=0,255 do
local r,g,b = engine.getrgb(i)
local R,G,B = engine.getrgb(j)
tab[i][j] = engine.nearcolor(f*r+F*R, f*g+F*G, f*b+F*B)
end
end
engine.setblendtab(startblendidx + alpha-1, tab)
end
end
function shadexfog.create_additive_trans(blendidx)
local tab = engine.blendtab()
for i=0,255 do
for j=0,255 do
local r,g,b = engine.getrgb(i)
local R,G,B = engine.getrgb(j)
tab[i][j] = engine.nearcolor(min(r+R, 63), min(g+G, 63), min(b+B, 63))
end
end
engine.setblendtab(blendidx, tab)
end
do do
return shadexfog return shadexfog
end end