raze/polymer/eduke32/source/lunatic/defs.ilua

309 lines
7.6 KiB
Text
Raw Normal View History

-- definitions of BUILD and game types for the Lunatic Interpreter
-- INTERNAL!
local ffi = require("ffi")
---- sector, wall, sprite, ... ----
ffi.cdef[[
#pragma pack(push,1)
typedef struct
{
const int16_t wallptr, wallnum;
int32_t ceilingz, floorz;
int16_t ceilingstat, floorstat;
int16_t ceilingpicnum, ceilingheinum;
int8_t ceilingshade;
uint8_t ceilingpal, ceilingxpanning, ceilingypanning;
int16_t floorpicnum, floorheinum;
int8_t floorshade;
uint8_t floorpal, floorxpanning, floorypanning;
uint8_t visibility, filler;
int16_t lotag, hitag, extra;
} sectortype;
typedef struct
{
int32_t x, y;
const int16_t point2, nextwall, nextsector; int16_t cstat;
int16_t picnum, overpicnum;
int8_t shade;
uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
int16_t lotag, hitag, extra;
} walltype;
typedef struct
{
int32_t x, y, z;
int16_t cstat, picnum;
int8_t shade;
uint8_t pal, clipdist, filler;
uint8_t xrepeat, yrepeat;
int8_t xoffset, yoffset;
const int16_t sectnum, statnum;
int16_t ang, owner, xvel, yvel, zvel;
int16_t lotag, hitag, extra;
} spritetype;
typedef struct {
const uint32_t mdanimtims;
const int16_t mdanimcur;
int16_t angoff, pitch, roll;
int32_t xoff, yoff, zoff;
uint8_t flags;
uint8_t xpanning, ypanning;
const uint8_t filler;
float alpha;
const int32_t _do_not_use1;
const int32_t _do_not_use2;
} spriteext_t;
#pragma pack(pop)
]]
-- game structs
ffi.cdef[[
#pragma pack(push,1)
// ACTOR_T, might still need to make some fields read-only
typedef struct
{
const int32_t t_data[10]; // 40b sometimes used to hold offsets to con code
int16_t picnum,ang,extra,owner; //8b
int16_t movflag,tempang,timetosleep; //6b
int32_t flags, bposx,bposy,bposz; //16b
int32_t floorz,ceilingz,lastvx,lastvy; //16b
int32_t lasttransport; //4b
const int16_t lightId, lightcount, lightmaxrange, cgg; //8b
int16_t actorstayput, dispicnum, shootzvel; // 6b
const int8_t _do_not_use[24];
} actor_t;
#pragma pack(pop)
int32_t engine_main_arrays_are_static;
]]
if (ffi.C.engine_main_arrays_are_static) then
ffi.cdef[[
sectortype sector[];
walltype wall[];
spritetype sprite[];
spriteext_t spriteext[];
]]
else
ffi.cdef[[
sectortype *sector;
walltype *wall;
spritetype *sprite;
spriteext_t *spriteext;
]]
end
ffi.cdef[[
const int16_t numsectors, numwalls;
const int16_t headspritesect[16384+1], headspritestat[1024+1];
const int16_t prevspritesect[16384], prevspritestat[16384];
const int16_t nextspritesect[16384], nextspritestat[16384];
]]
ffi.cdef[[
actor_t actor[16384];
]]
---- _G tweaks -- pull in only 'safe' stuff ----
local G_ = {} -- our soon-to-be global environment
local oG = _G
G_.coroutine = coroutine
G_.assert = assert
G_.tostring = tostring
G_.tonumber = tonumber
--rawget
G_.xpcall = xpcall
G_.ipairs = ipairs
G_.print = print
G_.pcall = pcall
--gcinfo --DEPRECATED
--module
--setfenv
--require
--rawset
--jit
G_.bit = bit
--package
G_.error = error
--debug
--loadfile
--rawequal
--load
G_.unpack = unpack
G_.pairs = pairs
G_.table = table
G_._VERSION = _VERSION
--newproxy --NOT STD?
--collectgarbage
--dofile
G_.next = next
G_.math = math
--loadstring
--_G
G_.select = select
G_.string = string
G_.type = type
--getmetatable
--getfenv
--setmetatable
G_._G = G_
-- REMOVE this for release
DBG_ = {}
DBG_.loadstring = oG.loadstring
---- Set up restricted access to ffi.C from lunatic. ----
local ffiC = ffi.C
local det = {} -- dummy empty table
local tmpmt = {
__index = function() error('dummy variable: read access forbidden') end,
__newindex = function() error('dummy variable: write access forbidden') end,
__metatable = true -- forbid setting the metatable
}
oG.setmetatable(det, tmpmt)
-- GLOBAL gv: provides access to C global *scalars*
gv = {
-- all non-scalars need to be explicitly listed
-- and access to them is redirected to the dummy
-- empty table... this is somewhat ugly
sector = det,
wall = det,
sprite = det,
spriteext = det,
headspritesect = det, headspritestat = det,
prevspritesect = det, prevspritestat = det,
nextspritesect = det, nextspritestat = det,
actor = det,
}
local tmpmt = {
__index = ffiC,
__newindex = function() error("cannot create new fields in 'gv'") end,
__metatable = true,
}
oG.setmetatable(gv, tmpmt)
---- indirect C array access ----
sector = {}
local tmpmt = {
__index = function(tab, key)
if (key >= 0 and key < ffiC.numsectors) then return ffiC.sector[key] end
error('out-of-bounds sector[] read access')
end,
__newindex = function(tab, key, val) error('cannot write to sector[] struct directly') end,
__metatable = true,
}
oG.setmetatable(sector, tmpmt)
wall = {}
local tmpmt = {
__index = function(tab, key)
if (key >= 0 and key < ffiC.numwalls) then return ffiC.wall[key] end
error('out-of-bounds wall[] read access')
end,
__newindex = function(tab, key, val) error('cannot write to wall[] struct directly') end,
__metatable = true,
}
oG.setmetatable(wall, tmpmt)
-- create a safe indirection for a ffi.C array
local function creategtab(ctab, maxidx, name)
local tab = {}
local tmpmt = {
__index = function(tab, key)
if (key>=0 and key < maxidx) then
return ctab[key]
end
error('out-of-bounds '..name..' read access')
end,
__newindex = function(tab, key, val)
error('cannot write to '..name)
end,
__metatable = true,
}
oG.setmetatable(tab, tmpmt)
return tab
end
sprite = creategtab(ffiC.sprite, 16384, 'sprite[] struct')
spriteext = creategtab(ffiC.spriteext, 16384, 'spriteext[] struct')
headspritesect = creategtab(ffiC.headspritesect, 16384, 'headspritesect[]')
headspritestat = creategtab(ffiC.headspritestat, 1024, 'headspritestat[]')
nextspritesect = creategtab(ffiC.nextspritesect, 16384, 'nextspritesect[]')
nextspritestat = creategtab(ffiC.nextspritestat, 16384, 'nextspritestat[]')
prevspritesect = creategtab(ffiC.prevspritesect, 16384, 'prevspritesect[]')
prevspritestat = creategtab(ffiC.prevspritestat, 16384, 'prevspritestat[]')
actor = creategtab(ffiC.actor, 16384, 'actor[]')
---- per-sector/per-statnum sprite iterators ----
local function iter_spritesofsect(sect, i)
if (i < 0) then
i = ffiC.headspritesect[sect]
else
i = ffiC.nextspritesect[i]
end
if (i >= 0) then return i, i end
end
function spritesofsect(sect)
assert(sect >= 0 and sect < ffiC.numsectors, "passed invalid sectnum to spritesofsect iterator")
return iter_spritesofsect, sect, -1
end
local function iter_spritesofstat(stat, i)
if (i < 0) then
i = ffiC.headspritestat[stat]
else
i = ffiC.nextspritestat[i]
end
if (i >= 0) then return i, i end
end
function spritesofstat(stat)
assert(stat >= 0 and stat < 1024, "passed invalid statnum to spritesofstat iterator")
return iter_spritesofstat , stat, -1
end
-- add new variables/functions living in the global environment
G_.DBG_ = DBG_ -- REMOVE this for release
G_.gv = gv
G_.sector = sector
G_.wall = wall
G_.sprite = sprite
G_.spriteext = spriteext
G_.headspritesect = headspritesect
G_.headspritestat = headspritestat
G_.nextspritesect = nextspritesect
G_.nextspritestat = nextspritestat
G_.prevspritesect = prevspritesect
G_.prevspritestat = prevspritestat
G_.actor = actor
G_.spritesofsect = spritesofsect
G_.spritesofstat = spritesofstat
-- change the environment of the running Lua thread to the table G_
setfenv(0, G_)