Lunatic: custom integer types treated as bitfields.

Used for engine struct's (c)stat and actor[].flags members.

git-svn-id: https://svn.eduke32.com/eduke32@3643 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-04-05 17:53:10 +00:00
parent 023ff8f190
commit 6ebe2d4745
3 changed files with 96 additions and 24 deletions

View file

@ -137,6 +137,8 @@ typedef struct {
} con_ai_t;
]]
defs_c.bitint_new_struct_type("int32_t", "SBit32")
-- Struct template for actor_t. It already has 'const' fields (TODO: might need
-- to make more 'const'), but still has array members exposed, so is unsuited
-- for external exposure.
@ -147,7 +149,7 @@ __attribute__((packed)) struct {
const struct action ac;
const int16_t _padding[1];
int32_t flags; //4b
]]..defs_c.bitint_member("SBit32", "flags")..[[
vec3_t bpos; //12b
int32_t floorz,ceilingz,lastvx,lastvy; //16b
int32_t lasttransport; //4b
@ -1453,7 +1455,6 @@ G_.ipairs = ipairs
G_.pairs = pairs
G_.pcall = pcall
G_.print = print
G_.printf = printf
G_.module = our_module
G_.next = next
G_.require = our_require

View file

@ -56,7 +56,66 @@ local print=print
module(...)
local band = bit.band
local bor = bit.bor
local bnot = bit.bnot
local lshift = bit.lshift
local rshift = bit.rshift
local xor = bit.bxor
--== bitint type factory ==--
-- Metatable for an integer type that is treated as bitfield. The integer
-- itself must be named '_v'.
local bitint_mt = {
__index = {
set = function(self, bits)
self._v = bor(self._v, bits)
end,
clear = function(self, bits)
self._v = band(self._v, bnot(bits))
end,
flip = function(self, bits)
self._v = xor(self._v, bits)
end,
test = function(self, bits)
return (band(self._v, bits) ~= 0)
end,
},
__metatable = true,
}
local bitint_to_base_type = {}
function bitint_new_struct_type(basetypename, newtypename)
assert(bitint_to_base_type[newtypename] == nil)
assert(type(basetypename)=="string")
assert(type(newtypename)=="string")
local bitint_struct_t = ffi.typeof("struct { $ _v; }", ffi.typeof(basetypename))
ffi.metatype(bitint_struct_t, bitint_mt)
ffi.cdef("typedef $ $;", bitint_struct_t, newtypename)
bitint_to_base_type[newtypename] = basetypename
end
function bitint_member(bitint_struct_typename, membname)
return string.format("union { %s %s; %s %sx; };",
bitint_to_base_type[bitint_struct_typename], membname,
bitint_struct_typename, membname)
end
bitint_new_struct_type("uint8_t", "UBit8")
bitint_new_struct_type("uint16_t", "UBit16")
--== Core engine structs ==--
local SECTOR_STRUCT = [[
struct {
const int16_t wallptr, wallnum;
@ -77,7 +136,7 @@ struct {
local SPRITE_STRUCT = [[
struct {
int32_t x, y, z;
uint16_t cstat;
]]..bitint_member("UBit16", "cstat")..[[
const int16_t picnum;
int8_t shade;
uint8_t pal, clipdist, filler;
@ -99,7 +158,7 @@ local WALL_STRUCT = [[
struct {
int32_t x, y;
const int16_t point2, nextwall, nextsector;
uint16_t cstat;
]]..bitint_member("UBit16", "cstat")..[[
const int16_t picnum, overpicnum;
int8_t shade;
uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
@ -130,7 +189,7 @@ typedef struct {
int16_t angoff, pitch, roll;
// TODO: make into an ivec3_t
int32_t xoff, yoff, zoff;
uint8_t flags;
]]..bitint_member("UBit8", "flags")..[[
uint8_t xpanning, ypanning;
const uint8_t filler;
float alpha;
@ -313,13 +372,6 @@ local check_sector_idx = bcheck.sector_idx
local check_sprite_idx = bcheck.sprite_idx
local check_tile_idx = bcheck.tile_idx
local band = bit.band
local bor = bit.bor
local bnot = bit.bnot
local lshift = bit.lshift
local rshift = bit.rshift
local xor = bit.bxor
local wallsofsec -- fwd-decl
local sectortype_ptr_ct = ffi.typeof("$ *", ffi.typeof(strip_const(SECTOR_STRUCT)))
@ -494,15 +546,6 @@ local spritetype_mt = {
check_sprite_idx(owner)
ffi.cast(spritetype_ptr_ct, s).owner = owner
end,
--- Custom setters
set_cstat_bits = function(s, bits)
s.cstat = bor(s.cstat, bits)
end,
clear_cstat_bits = function(s, bits)
s.cstat = band(s.cstat, bnot(bits))
end,
},
}
@ -621,24 +664,45 @@ local static_members = { sector={}, wall={}, sprite={} }
static_members.sector.STAT = conststruct
{
PARALLAX = 1,
SLOPED = 2,
XFLIP = 16,
YFLIP = 32,
RELATIVE = 64,
MASKED = 128,
-- NOTE the reversed order
TRANSLUCENT2 = 128,
TRANSLUCENT1 = 256,
TRANSLUCENT_BOTH_BITS = 256+128,
BLOCKING = 512,
HITSCAN = 1024,
}
static_members.wall.CSTAT = conststruct
{
MASKED = 64,
BLOCKING = 1,
XFLIP = 8,
MASKED = 16,
ONEWAY = 32,
HITSCAN = 64,
TRANSLUCENT1 = 128,
YFLIP = 256,
TRANSLUCENT2 = 512,
TRANSLUCENT_BOTH_BITS = 512+128,
}
static_members.sprite.CSTAT = conststruct
{
BLOCKING = 1,
TRANSLUCENT1 = 2,
XFLIP = 4,
YFLIP = 8,
WALLALIGN = 16,
FLOORALIGN = 32,
ONESIDED = 64,
CENTERED = 128,
HITSCAN = 256,
TRANSLUCENT2 = 512,
TRANSLUCENT_BOTH_BITS = 512+2,
}

View file

@ -364,6 +364,7 @@ con.ai("AITEMP", "TROOPFLINTCH", "SHRUNKVELS", 0)
local TROOPSTRENGTH = 30
local AF = actor.FLAGS
local CS = sprite.CSTAT
-- Also test actor code chaining: strength is doubled.
gameactor(1680, AF.chain_end+AF.enemy, 2*TROOPSTRENGTH, "TROOPSTAND", -- LIZTROOP
@ -386,6 +387,13 @@ gameactor(1680, AF.chain_end+AF.enemy, 2*TROOPSTRENGTH, "TROOPSTAND", -- LIZTROO
error("greetings from LIZTROOP actor")
end
local actr = actor[i]
if (actr:get_count() % 30 == 0) then
spr.cstatx:flip(CS.YFLIP)
end
actr.flagsx:test(AF.NVG) -- test of bitint's ":test()" for actor[].flags
if (dist < 4096) then
-- Duke Vader / Anakin Nukewalker?
actor[i]:set_action("TROOPFLINTCH")
@ -431,7 +439,6 @@ gameactor(1405, actor.FLAGS.chain_beg, function(aci, pli)
end
end)
local CS = sprite.CSTAT
gameevent("ANIMATESPRITES",
function(aci)
@ -441,7 +448,7 @@ function(aci)
if (tspr2) then
tspr2.x = tspr2.x + 512*math.cos(gv.totalclock/60)
tspr2.y = tspr2.y + 512*math.sin(gv.totalclock/60)
tspr2:set_cstat_bits(CS.TRANSLUCENT_BOTH_BITS)
tspr2.cstatx:set(CS.TRANSLUCENT_BOTH_BITS)
end
end
end)