Lunatic: various.

- Fix "gv" access.
- camera
- translator: comparison predicates, predefs...

git-svn-id: https://svn.eduke32.com/eduke32@3406 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-01-19 18:28:40 +00:00
parent c9190e79ae
commit fbaa00665d
6 changed files with 178 additions and 80 deletions

View file

@ -995,6 +995,9 @@ end
function _sound(aci, sndidx)
check_sprite_idx(aci)
-- A_PlaySound() returns early if the sound index is oob, but IMO it's good
-- style to throw an error in instead of silently failing.
check_sound_idx(sndidx)
ffiC.A_PlaySound(sndidx, aci)
end
@ -1010,19 +1013,22 @@ local function S_StopSound(sndidx)
ffiC.S_StopEnvSound(sndidx, -1)
end
function _stopsound(aci, sndidx)
function _soundplaying(aci, sndidx)
check_sprite_idx(aci)
check_sound_idx(sndidx)
return (ffiC.S_CheckSoundPlaying(aci, sndidx) ~= 0)
end
function _stopsound(aci, sndidx)
-- XXX: This is weird: the checking is done wrt a sprite, but the sound not.
-- NOTE: S_StopSound() stops sound <sndidx> that started playing most recently.
if (ffiC.S_CheckSoundPlaying(aci, sndidx) ~= 0) then
if (_soundplaying(aci, sndidx)) then
S_StopSound(sndidx)
end
end
function _soundonce(aci, sndidx)
check_sound_idx(sndidx)
if (ffiC.S_CheckSoundPlaying(aci, sndidx) == 0) then
if (not _soundplaying(aci, sndidx)) then
_sound(aci, sndidx)
end
end

View file

@ -23,15 +23,12 @@ local tonumber = tonumber
local tostring = tostring
local type = type
-- The "gv" global will provide access to C global *scalars* and safe functions.
-- XXX: still exposes C library functions etc. contained in ffi.C, problem?
local gv_ = {
-- All non-scalars need to be explicitly listed here and access to them is
-- redirected to the dummy empty table...
}
local dummy_empty_table = {}
-- NOTE: This exposes C library functions from e.g. the global C namespace, but
-- without their declarations, they will be sitting there like a stone.
local gv_ = {}
-- [key]=true forbids, [key]=<table> overrides
local gv_access = {}
-- This is for declarations of arrays or pointers which should not be
-- accessible through the "gv" global. The "defs_common" module will
@ -44,8 +41,10 @@ function decl(str)
-- NOTE that the regexp also catches non-array/non-function identifiers
-- like "user_defs ud;"
for varname in string.gmatch(str, "([%a_][%w_]*)[[(;]") do
-- print("DUMMY "..varname)
gv_[varname] = dummy_empty_table
if (ffiC._DEBUG_LUNATIC ~= 0) then
print("FORBID "..varname)
end
gv_access[varname] = true
end
ffi.cdef(str)
@ -464,6 +463,7 @@ const char *g_sizes_of_what[];
int32_t g_sizes_of[];
int32_t g_elCallDepth;
actor_t actor[MAXSPRITES];
camera_t g_camera;
user_defs ud;
playerdata_t g_player[MAXPLAYERS];
weapondata_t g_playerWeapon[MAXPLAYERS][MAX_WEAPONS];
@ -548,6 +548,7 @@ end
-- Add game-side metamethods to "spritetype" and register it with "metatype"
defs_c.spritetype_mt.__index.isenemy = function(s)
-- CODEDUP control.lua: isenemytile
return (bit.band(ffiC.g_tile[s.picnum].flags, ffiC.SFLAG_BADGUY)~=0)
end
ffi.metatype("spritetype", defs_c.spritetype_mt)
@ -772,6 +773,7 @@ local function get_weapondata_accessor(pli, weap)
__newindex = function(_, member, val)
if (string.match(member, "sound")) then
-- TODO: set to 0 if oob? (e.g. CrackDown)
check_sound_idx(val)
elseif (member=="workslike") then
check_weapon_idx(val)
@ -871,15 +873,24 @@ local player_mt = {
pals.f = f
pals.r, pals.g, pals.b = r, g, b
end,
-- XXX: is this so useful without z offset?
_cansee = function(p, otherpos, othersect)
return cansee(p.pos, sprite[p.i].sectnum, otherpos, othersect)
end,
},
}
ffi.metatype("DukePlayer_t", player_mt)
local camera_mt = {
-- TODO: "set position" method, which also updates the sectnum
__index = ffiC.g_camera,
__newindex = function(_, key, val)
if (key=="sect") then
defs_c.check_sector_idx(val)
end
ffiC.g_camera[key] = val
end,
__metatable = true
}
gv_access.cam = setmetatable({}, camera_mt)
-- Declare all con_lang.labels constants in the global FFI namespace.
for i=1,#con_lang.labels do
local strbuf = {"enum {"}
@ -1253,16 +1264,19 @@ end
-- error(..., 2) is to blame the caller and get its line numbers
local tmpmt = {
__index = function() error("dummy variable: read access forbidden", 2) end,
__newindex = function() error("dummy variable: write access forbidden", 2) end,
}
setmtonce(dummy_empty_table, tmpmt)
gv = gv_
local tmpmt = {
__index = ffiC,
__newindex = function() error("cannot create new or write into existing fields of 'gv'", 2) end,
__index = function(gv, key)
if (gv_access[key] == nil) then
return ffiC[key]
end
if (type(gv_access[key])=="table") then
-- overridden...
return gv_access[key]
end
error("access forbidden", 2)
end,
__newindex = function() error("write access forbidden", 2) end,
}
setmtonce(gv, tmpmt)

View file

@ -7,6 +7,8 @@
local ffi = require("ffi")
local ffiC = ffi.C
ffi.cdef "enum { _DEBUG_LUNATIC=1 }"
local bit = require("bit")
local string = require("string")
@ -133,7 +135,7 @@ typedef struct {
local vec3_ct = ffi.typeof("vec3_t")
local hitdata_ct = ffi.typeof("hitdata_t")
ffi.cdef[[const int32_t engine_main_arrays_are_static, engine_v8;]]
decl[[const int32_t engine_main_arrays_are_static, engine_v8;]]
--== Engine data and functions ==--
@ -196,7 +198,7 @@ enum {
ffi.cdef[[
const int16_t numsectors, numwalls;
const int32_t numyaxbunches;
const int32_t numyaxbunches; // XXX
const int32_t totalclock;
const int32_t xdim, ydim;
]]
@ -384,10 +386,18 @@ function creategtab(ctab, maxidx, name)
return setmtonce(tab, tmpmt)
end
function check_sector_idx(sectnum)
if (sectnum >= ffiC.numsectors+0ULL) then
error("passed out-of-bounds sector number "..sectnum, 3)
end
end
local vars_to_ignore = {}
for varname,_ in pairs(getfenv(1)) do
-- print("IGNORE "..varname)
if (ffiC._DEBUG_LUNATIC ~= 0) then
print("IGNORE "..varname)
end
vars_to_ignore[varname] = true
end
@ -406,12 +416,6 @@ nextspritestat = creategtab(ffiC.nextspritestat, ffiC.MAXSPRITES, 'nextspritesta
prevspritesect = creategtab(ffiC.prevspritesect, ffiC.MAXSPRITES, 'prevspritesect[]')
prevspritestat = creategtab(ffiC.prevspritestat, ffiC.MAXSPRITES, 'prevspritestat[]')
function check_sector_idx(sectnum)
if (sectnum >= ffiC.numsectors+0ULL) then
error("passed out-of-bounds sector number "..sectnum, 3)
end
end
local function iter_wallsofsec(endwall, w)
w = w+1
if (w < endwall) then
@ -579,7 +583,9 @@ function create_globals(_G_their)
for varname,obj in pairs(_G_our) do
if (not vars_to_ignore[varname]) then
-- print("EXPORT "..varname)
if (ffiC._DEBUG_LUNATIC ~= 0) then
print("EXPORT "..varname)
end
_G_their[varname] = obj
end
end

View file

@ -76,6 +76,7 @@ C_DefineSkillName;
C_DefineLevelName;
actor;
g_camera;
ud;
g_player;
g_playerWeapon;

View file

@ -91,7 +91,7 @@ local g_warn = { ["not-redefined"]=true, ["bad-identifier"]=true,
["number-conversion"]=true, }
-- Code generation options.
local g_cgopt = { ["no"]=false, }
local g_cgopt = { ["no"]=false, ["_incomplete"]=false, }
-- How many 'if' statements are following immediately each other,
-- needed to cope with CONs dangling-else resolution
@ -128,7 +128,7 @@ local function new_initial_codetab()
return {
"local _con, _bit, _math = require'con', require'bit', require'math';",
"local sector, sprite, actor, player = sector, sprite, actor, player;",
"local gameactor, gameevent = gameactor, gameevent;"
"local gameactor, gameevent, _gv = gameactor, gameevent, gv;"
}
end
@ -136,10 +136,41 @@ end
-- KEEPINSYNC gamevars.c: Gv_AddSystemVars()
local function new_initial_gvartab()
local wmembers = conl.wdata_members
local gamevar = {}
local MAX_WEAPONS = ffiC and ffiC.MAX_WEAPONS or 12
local RW = function(varname)
return { name=varname, flags=GVFLAG.SYSTEM }
end
local RO = function(varname)
return { name=varname, flags=GVFLAG.SYSTEM+GVFLAG.READONLY }
end
local gamevar = {
-- XXX: TODO: THISACTOR can mean different things in some contexts,
-- e.g. sector[THISACTOR] is sector[sprite[<current actor>].sectnum]
THISACTOR = RO "_aci",
-- TODO
RETURN = RW "_RETURN_",
xdim = RO "_gv.xdim",
ydim = RO "_gv.ydim",
numsectors = RO "_gv.numsectors",
NUMSECTORS = RO "_gv.numsectors",
NUMWALLS = RO "_gv.numwalls",
camerax = RW "_gv.cam.pos.x",
cameray = RW "_gv.cam.pos.y",
cameraz = RW "_gv.cam.pos.z",
cameraang = RW "_gv.cam.ang",
camerahoriz = RW "_gv.cam.horiz",
camerasect = RW "_gv.cam.sect",
cameradist = RW "_gv.cam.dist",
cameraclock = RW "_gv.cam.clock",
}
for w=0,MAX_WEAPONS-1 do
for i=1,#wmembers do
local member = wmembers[i]:gsub(".* ","") -- strip e.g. "int32_t "
@ -308,8 +339,18 @@ local function reset_labels()
-- NO is also a valid `move', `ai' or `action', but they are handled
-- separately in lookup_composite().
g_labeldef = { NO=0 }
g_labeltype = { NO=LABEL.NUMBER }
g_labeldef = {
NO = 0,
-- NOTE: these are read-only gamevars in C-CON
CLIPMASK0 = 65536+1, -- blocking
CLIPMASK1 = (256*65536)+64, -- hittable
}
g_labeltype = {
NO = LABEL.NUMBER,
CLIPMASK0 = LABEL.NUMBER,
CLIPMASK1 = LABEL.NUMBER,
}
-- Initialize default defines.
for i=1,#conl.labels do
@ -1419,31 +1460,47 @@ local Cif = {
ifangdiffl = cmd(D)
/ format("_con._angdiffabs(%s,%s)<=%%1", PLS".ang", SPS".ang"),
ifsound = cmd(D)
/ "",
/ "_con._soundplaying(_aci,%1)",
-- vvv TODO: this is not correct for GET_ACCESS or GET_SHIELD.
ifpinventory = cmd(D,D)
/ format("_con._getinventory(%s,%%1,_aci)~=%%2", PLS""),
ifvarl = cmd(R,D),
ifvarg = cmd(R,D),
ifvarl = cmd(R,D)
/ "%1<%2",
ifvarg = cmd(R,D)
/ "%1>%2",
ifvare = cmd(R,D)
/ "%1==%2",
ifvarn = cmd(R,D),
ifvarand = cmd(R,D),
ifvaror = cmd(R,D),
ifvarxor = cmd(R,D),
ifvareither = cmd(R,D),
ifvarn = cmd(R,D)
/ "%1~=%2",
ifvarand = cmd(R,D)
/ "_bit.band(%1,%2)~=0",
ifvaror = cmd(R,D)
/ "_bit.bor(%1,%2)~=0",
ifvarxor = cmd(R,D)
/ "_bit.bxor(%1,%2)~=0",
ifvareither = cmd(R,D)
/ "%1~=0 or %2~=0",
ifvarvarg = cmd(R,R),
ifvarvarl = cmd(R,R),
ifvarvare = cmd(R,R),
ifvarvarn = cmd(R,R),
ifvarvarand = cmd(R,R),
ifvarvaror = cmd(R,R),
ifvarvarxor = cmd(R,R),
ifvarvareither = cmd(R,R),
ifvarvarl = cmd(R,R)
/ "%1<%2",
ifvarvarg = cmd(R,R)
/ "%1>%2",
ifvarvare = cmd(R,R)
/ "%1==%2",
ifvarvarn = cmd(R,R)
/ "%1~=%2",
ifvarvarand = cmd(R,R)
/ "_bit.band(%1,%2)~=0",
ifvarvaror = cmd(R,R)
/ "_bit.bor(%1,%2)~=0",
ifvarvarxor = cmd(R,R)
/ "_bit.bxor(%1,%2)~=0",
ifvarvareither = cmd(R,R)
/ "%1~=0 or %2~=0",
ifactorsound = cmd(R,R),
ifactorsound = cmd(R,R)
/ "_con._soundplaying(%1,%2)",
ifp = (sp1 * tok.define)^1
/ function (...) return format("_con._ifp(%d,_pli,_aci)", bit.bor(...)) end,
@ -1609,15 +1666,15 @@ local function after_if_cmd_Cmt(subj, pos, ...)
if (g_numerrors == inf) then
return nil
end
---[[
if (capts[1] ~= nil) then
if (not g_cgopt["_incomplete"] and capts[1] ~= nil) then
assert(#capts <= 3)
for i=1,#capts do
assert(type(capts[i]=="string"))
end
return true, unpack(capts, 1, #capts)
end
--]]
return true
end
@ -2017,6 +2074,11 @@ local function handle_cmdline_arg(str)
elseif (str:sub(2)=="fno") then
-- Disable printing code.
g_cgopt["no"] = true
ok = true
elseif (str:sub(2)=="f_incomplete") then
-- TEMP
g_cgopt["_incomplete"] = true
ok = true
end
if (not ok) then

View file

@ -77,12 +77,9 @@ if (vol==1 and lev==1) then -- E1L1
spriteext[i].roll = 256;
for spr in spritesofsect(307) do -- some fence sprites in E1L1
print('spr', spr)
printf('spr %d', spr)
sprite[spr].pal = 6
end
for spr in spritesofsect(236) do
print('#spr', spr)
end
--this is a problem
--actor = {}
@ -110,30 +107,31 @@ local unsafe = pcall(function() string.UNSAFE=true; end)
--DBG_.printkv('_G in test.elua', _G)
-- direct gv array access forbidden
checkfail('gv.sprite[0].yrepeat = 100', "dummy variable: read access forbidden")
checkfail('gv.sprite[0].yrepeat = 100', "access forbidden")
-- indexing struct array with non-numeric type
checkfail('local i = sprite["qwe"]') -- this will produce an error inside the sprite metatable
checkfail('print(sprite[100000].ceilingpal)', "out-of-bounds sprite[] struct read access")
-- NOTE: gv.sprite doesn't fail, but we can't use it
checkfail('print(gv.sprite[0])', "dummy variable: read access forbidden")
checkfail('print(gv.sprite[0])', "access forbidden")
-- set metatable forbidden
checkfail('setmetatable(sprite, {})', "attempt to read undeclared variable 'setmetatable'")
-- oob write access
checkfail('sector[-1].ceilingpal = 4', "out-of-bounds sector[] read access") -- note the strange err msg
-- OOB write access.
-- Note that indexing ("reading") sector fails, even if the user wants to
-- assign to a sector member. Potentially confusing error message.
checkfail('sector[-1].ceilingpal = 4', "out-of-bounds sector[] read access")
-- wallnum member is read-only
checkfail('sector[0].wallnum = 0', "attempt to write to constant location") -- this comes from LJ/FFI
-- gv.numsectors is read-only
checkfail('gv.numsectors = 4', "cannot create new or write into existing fields of 'gv'")
checkfail('gv.numsectors = 4', "write access forbidden")
-- cannot create new fields in 'gv'
checkfail('gv.QWE = 4', "cannot create new or write into existing fields of 'gv'")
checkfail('gv.QWE = 4', "write access forbidden")
-- direct sector write access forbidden
checkfail('sector[4] = sector[6]', "cannot write directly to sector[] struct")
@ -154,7 +152,7 @@ checkfail('wall[4].QWE = 123', "has no member named 'QWE'")
checkfail("new_global = 345", "attempt to write to undeclared variable 'new_global'")
-- can't redefine constants in 'gv'
checkfail('gv.CEILING = 3', "cannot create new or write into existing fields of 'gv'")
checkfail('gv.CEILING = 3', "write access forbidden")
-- string.dump is unavailable
checkfail('local s=require[[string]]; local tmp=s.dump(gameevent)',
@ -174,8 +172,8 @@ print('')
checkfail('gv.luaJIT_setmode(nil, 0, 0)', "missing declaration for symbol 'luaJIT_setmode'")
checkfail('gv.luaJIT_BC_con_lang', "attempt to call a nil value")
checkfail('gv.yax_getbunch(0,0)', "attempt to call field 'yax_getbunch' (a table value)")
checkfail('gv.gethitickms = nil', "cannot create new or write into existing fields of 'gv'")
checkfail('gv.yax_getbunch(0,0)', "access forbidden")
checkfail('gv.gethitickms = nil', "write access forbidden")
-- we don't have arrays in Lua-accessible structs now
checkfail('local i = actor[0].t_data[15]', "has no member named 't_data'")
@ -188,8 +186,10 @@ checkfail('gameactor(1680, 0)', "invalid last argument to gameactor: must be a f
checkfail("do local bt=require'bittest'; bt.QWE=1; end", "modifying module table forbidden")
-- the cdata returned by player[] can't be made into a pointer!
checkfail("do local pl=player[0]; i=pl[1]; end")
checkfail("do local ud=gv.ud.camera; end", "dummy variable: read access forbidden") -- test for proper decl()
checkfail("do local ud=gv.ud.camerasprite; end", "access forbidden") -- test for proper decl()
checkfail("sprite[0]:set_picnum(-10)", "attempt to set invalid picnum")
checkfail("gv.g_sizes_of=nil; print(gv.g_sizes_of[0])", "write access forbidden")
checkfail("gv.cam.sect=-1", "passed out-of-bounds sector number")
printf('ceilingbunch of sector 0: %d', getbunch(0, gv.CEILING))
@ -298,6 +298,13 @@ gameactor(1680, TROOPSTRENGTH, "TROOPSTAND", -- LIZTROOP
end
)
gameevent("DISPLAYROOMS",
function()
local cam = gv.cam
cam.pos.z = cam.pos.z + 64*16*math.sin(gv.totalclock/30)
end
)
printf("EVENT_INIT = %d", gv.EVENT_INIT) -- tests default defines
local bittest = require "bittest"
@ -308,9 +315,11 @@ require("test/test_rotspr")
print('---=== END TEST SCRIPT ===---')
--[[
function check_sector_idx()
error("bla")
end
--]]
spritesofsect(0)
--DBG_.oom()