diff --git a/polymer/eduke32/build/src/engine.c b/polymer/eduke32/build/src/engine.c index 8a2772e93..feb6c7a14 100644 --- a/polymer/eduke32/build/src/engine.c +++ b/polymer/eduke32/build/src/engine.c @@ -2471,6 +2471,7 @@ char palfadedelta = 0; // static char *blendtable[MAXBLENDTABS]; +void setblendtab(int32_t blend, const char *tab); #define getblendtab(blend) (blendtable[blend]) static void setpalettefade_calc(uint8_t offset); @@ -8042,15 +8043,13 @@ static int32_t loadpalette(void) { int32_t i, j; - for (i=0; i<256; i++) + for (i=0; i<255; i++) { - // LameDuke's table doesn't have the last row or column. - if (i == 255) - continue; + // 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(fil, &transluc[256*i + i], 256-i-1) < 0) + if (kread(fil, &transluc[256*i + i], 256-i-1) != 256-i-1) return loadpalette_err("Failed reading LameDuke translucency table!"); // Duplicate the entries below the diagonal. @@ -8060,8 +8059,48 @@ static int32_t loadpalette(void) } else { - if (kread(fil, transluc, 65536) < 0) + int32_t i, n; + uint8_t magic[12]; + + if (kread(fil, transluc, 65536) != 65536) return loadpalette_err("Failed reading translucency table!"); + + n = kread(fil, magic, (int32_t)sizeof(magic)); + if (n == (int32_t)sizeof(magic) && !Bmemcmp(magic, "MoreBlendTab", sizeof(magic))) + { + // Read in additional blending tables. + uint8_t addblendtabs, blendnum; + char *tab = (char *)Bmalloc(256*256); + + if (tab == NULL) + return loadpalette_err("failed allocating temporary blending table"); + + if (kread(fil, &addblendtabs, 1) != 1) + return loadpalette_err("failed reading additional blending table count"); + + for (i=0; i `ok, errmsg` + +Writes out a full PALETTE.DAT-formatted file named `filename` with the base +shade table numbered `palnum` and the base translucency table numbered +`blendnum`, both defaulting to 0. + +Passing `moreblends` allows to specify additional blending tables to store in +EDuke32's extended PALETTE.DAT format. These must have previously been +registered with `engine.setblendtab`. The `moreblends` argument must be a +sequence table with each element being either + +* a blending table number in the range [1{nbsp}..{nbsp}255] +* a table `t` containing a pair of such numbers, in which case it is taken to + mean the inclusive range [`t[1]`{nbsp}..{nbsp}`t[2]`] + +There must be no duplicate blending table numbers. + +The function returns a status `ok` which is *true* on success and *nil* on +failure. In the latter case, `errmsg` is a diagnostic error message. + The `fs` module -- virtual file system facilities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/polymer/eduke32/source/lunatic/engine.lua b/polymer/eduke32/source/lunatic/engine.lua index afb4ef4c0..530796eb2 100644 --- a/polymer/eduke32/source/lunatic/engine.lua +++ b/polymer/eduke32/source/lunatic/engine.lua @@ -4,6 +4,7 @@ local C = ffi.C local bcarray = require("bcarray") +local assert = assert local error = error local type = type @@ -230,11 +231,61 @@ end if (ismapster32) then local io = require("io") + local math = require("math") + local string = require("string") ffi.cdef[[size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, void * restrict stream);]] - -- [ok, errmsg] = engine.savePaletteDat(filename [, palnum [, blendnum]]) - function engine.savePaletteDat(filename, palnum, blendnum) + local function validate_more_blendtabs(moreblends) + if (moreblends == nil) then + return nil, nil + end + + -- Additional blending tables: validate table. + if (type(moreblends) ~= "table") then + error("invalid argument #4: must be a table", 3) + end + + local haveblend = { [0]=true } + local blendnumtab, blendptrtab = {}, {} + + for i=1,#moreblends do + local tmp = moreblends[i] + local blendspec = (type(tmp) == "number") and { tmp, tmp } or tmp + + if (not (type(blendspec) == "table" and #blendspec == 2)) then + error("invalid argument #4: must contain numbers or 2-tables", 3) + end + + local blend1, blend2 = math.floor(blendspec[1]), math.floor(blendspec[2]) + + if (not (type(blend1)=="number" and blend1 >= 1 and blend1 <= 255 and + type(blend2)=="number" and blend2 >= 1 and blend2 <= 255)) then + error("invalid argument #4: blending table numbers must be in [1 .. 255]", 3) + end + + for bi=blend1,blend2 do + if (haveblend[bi]) then + error("invalid argument #4: duplicate blending table number "..bi, 3) + end + haveblend[bi] = true + + local ptr = C.getblendtab(bi) + if (ptr == nil) then + error("invalid argument #4: blending table for number "..bi.." is void", 3) + end + + blendnumtab[#blendnumtab+1] = bi + blendptrtab[#blendptrtab+1] = ptr + end + end + + assert(#blendnumtab <= 255) + return blendnumtab, blendptrtab + end + + -- [ok, errmsg] = engine.savePaletteDat(filename [, palnum [, blendnum [, moreblends]]]) + function engine.savePaletteDat(filename, palnum, blendnum, moreblends) local sht = engine.getshadetab(palnum or 0) local tab = engine.getblendtab(blendnum or 0) @@ -244,20 +295,35 @@ if (ismapster32) then return nil, "no blending table with number "..blendnum end + local blendnumtab, blendptrtab = validate_more_blendtabs(moreblends) + local f, errmsg = io.open(filename, "w+") if (f == nil) then return nil, errmsg end - local n1 = ffi.C.fwrite(C.palette, 3, 256, f) + local n1 = C.fwrite(C.palette, 3, 256, f) f:write("\032\000") -- int16_t numshades - local n3 = ffi.C.fwrite(sht, 256, 32, f) - local n4 = ffi.C.fwrite(tab, 256, 256, f) + local n3 = C.fwrite(sht, 256, 32, f) + local n4 = C.fwrite(tab, 256, 256, f) + + if (n1 ~= 256 or n3 ~= 32 or n4 ~= 256) then + return nil, "failed writing classic PALETTE.DAT data" + end + + if (blendnumtab ~= nil) then + f:write("MoreBlendTab") + f:write(string.char(#blendnumtab)) + + for i=1,#blendnumtab do + f:write(string.char(blendnumtab[i])) + if (C.fwrite(blendptrtab[i], 256, 256, f) ~= 256) then + return nil, "failed writing additional blending table" + end + end + end f:close() - if (n1 ~= 256 or n3 ~= 32 or n4 ~= 256) then - return nil, "failed writing enough data" - end return true end diff --git a/polymer/eduke32/source/lunatic/test/shadexfog.lua b/polymer/eduke32/source/lunatic/test/shadexfog.lua index 77cf2df36..6710211b8 100644 --- a/polymer/eduke32/source/lunatic/test/shadexfog.lua +++ b/polymer/eduke32/source/lunatic/test/shadexfog.lua @@ -197,12 +197,16 @@ end if (gv.LUNATIC_CLIENT == gv.LUNATIC_CLIENT_MAPSTER32) then -- Wrapper around engine.savePaletteDat() that errors on unexpected events. - function shadexfog.save(filename, palnum, blendnum) - local ok, errmsg = engine.savePaletteDat(filename, palnum, blendnum) + function shadexfog.save(filename, palnum, blendnum, moreblends) + local ok, errmsg = engine.savePaletteDat(filename, palnum, blendnum, moreblends) if (not ok) then error(errmsg) end - printf('Wrote base palette, shade and translucency tables to "%s"', filename) + + printf('Wrote base palette, shade and translucency tables to "%s".', filename) + if (moreblends ~= nil) then + printf(" Also wrote additional translucency tables.") + end end end