Lunatic translator: nearing a workable state...

- some more outer commands
- gamearray persistence
- faster 'mod': use math.modf instead of math.fmod (the former is JIT-compiled)
- checkavail*
- THISACTOR special handling
- Fix building in Windows (export A_ShootWithZvel instead of A_Shoot).

git-svn-id: https://svn.eduke32.com/eduke32@3516 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-02-24 16:05:22 +00:00
parent b0a8a381c8
commit acddac64be
7 changed files with 383 additions and 80 deletions

View file

@ -2191,8 +2191,26 @@ void C_DefineLevelName(int32_t vol, int32_t lev, const char *fn,
map->designertime = REALGAMETICSPERSEC * designertime; map->designertime = REALGAMETICSPERSEC * designertime;
} }
} }
void C_DefineGameFuncName(int32_t idx, const char *name)
{
assert(idx < NUMGAMEFUNCTIONS);
Bstrncpyz(gamefunctions[idx], name, MAXGAMEFUNCLEN);
Bstrncpyz(keydefaults[3*idx], name, MAXGAMEFUNCLEN);
}
#endif #endif
// NOTE: external linkage for Lunatic
int32_t C_SetDefName(const char *name)
{
clearDefNamePtr();
g_defNamePtr = dup_filename(name);
if (g_defNamePtr)
initprintf("Using DEF file: %s.\n", g_defNamePtr);
return (g_defNamePtr==NULL);
}
// NOTE: external linkage for Lunatic // NOTE: external linkage for Lunatic
void C_DefineProjectile(int32_t j, int32_t what, int32_t val) void C_DefineProjectile(int32_t j, int32_t what, int32_t val)
{ {
@ -5368,10 +5386,7 @@ repeatcase:
} }
tempbuf[j] = '\0'; tempbuf[j] = '\0';
clearDefNamePtr(); C_SetDefName(tempbuf);
g_defNamePtr = dup_filename(tempbuf);
initprintf("Using DEF file: %s.\n",g_defNamePtr);
} }
continue; continue;

View file

@ -72,11 +72,15 @@ function bcheck.level_idx(level)
end end
end end
function bcheck.quote_idx(qnum) function bcheck.quote_idx(qnum, onlyidx)
if (qnum >= con_lang.MAXQUOTES+0ULL) then if (qnum >= con_lang.MAXQUOTES+0ULL) then
error("invalid quote number "..qnum, 3) error("invalid quote number "..qnum, 3)
end end
if (onlyidx) then
return nil
end
local cstr = ffiC.ScriptQuotes[qnum] local cstr = ffiC.ScriptQuotes[qnum]
if (cstr == nil) then if (cstr == nil) then
error("null quote "..qnum, 3) error("null quote "..qnum, 3)

View file

@ -5,6 +5,7 @@ local ffi = require("ffi")
local ffiC = ffi.C local ffiC = ffi.C
local bit = require("bit") local bit = require("bit")
local io = require("io")
local math = require("math") local math = require("math")
local geom = require("geom") local geom = require("geom")
local con_lang = require("con_lang") local con_lang = require("con_lang")
@ -14,7 +15,10 @@ local setmetatable = setmetatable
local assert = assert local assert = assert
local error = error local error = error
local ipairs = ipairs
local print = print local print = print
local rawget = rawget
local rawset = rawset
local tostring = tostring local tostring = tostring
local type = type local type = type
local unpack = unpack local unpack = unpack
@ -306,14 +310,16 @@ function _div(a,b)
if (b==0) then if (b==0) then
error("divide by zero", 2) error("divide by zero", 2)
end end
return (a - math.fmod(a,b))/b -- NOTE: math.modf() is compiled, math.fmod() is not:
-- http://wiki.luajit.org/NYI#Math-Library
return (a - math.modf(a,b))/b
end end
function _mod(a,b) function _mod(a,b)
if (b==0) then if (b==0) then
error("mod by zero", 2) error("mod by zero", 2)
end end
return (math.fmod(a,b)) return (math.modf(a,b))
end end
-- Sect_ToggleInterpolation() clone -- Sect_ToggleInterpolation() clone
@ -424,8 +430,11 @@ end
local MAXQUOTES = con_lang.MAXQUOTES local MAXQUOTES = con_lang.MAXQUOTES
local MAXQUOTELEN = con_lang.MAXQUOTELEN local MAXQUOTELEN = con_lang.MAXQUOTELEN
-- CON redefinequote command
function _definequote(qnum, quotestr) function _definequote(qnum, quotestr)
bcheck.quote_idx(qnum) -- NOTE: this is more permissive than C-CON: we allow to redefine quotes
-- that were not previously defined.
bcheck.quote_idx(qnum, true)
assert(type(quotestr)=="string") assert(type(quotestr)=="string")
ffiC.C_DefineQuote(qnum, quotestr) ffiC.C_DefineQuote(qnum, quotestr)
return (#quotestr >= MAXQUOTELEN) return (#quotestr >= MAXQUOTELEN)
@ -518,6 +527,11 @@ end
local buf = ffi.new("char [?]", MAXQUOTELEN) local buf = ffi.new("char [?]", MAXQUOTELEN)
function _qsprintf(qdst, qsrc, ...) function _qsprintf(qdst, qsrc, ...)
-- NOTE: more permissive than C-CON, see _definequote
if (bcheck.quote_idx(qdst, true) == nil) then
ffiC.C_DefineQuote(qdst, "") -- allocate quote
end
local dst = bcheck.quote_idx(qdst) local dst = bcheck.quote_idx(qdst)
local src = bcheck.quote_idx(qsrc) local src = bcheck.quote_idx(qsrc)
local vals = {...} local vals = {...}
@ -894,6 +908,32 @@ function _checkpinventory(ps, inv, amount, i)
end end
end end
local INV_SELECTION_ORDER = {
ffiC.GET_FIRSTAID,
ffiC.GET_STEROIDS,
ffiC.GET_JETPACK,
ffiC.GET_HOLODUKE,
ffiC.GET_HEATS,
ffiC.GET_SCUBA,
ffiC.GET_BOOTS,
}
-- checkavailinven CON command
function _selectnextinv(ps)
for _,inv in ipairs(INV_SELECTION_ORDER) do
if (ps:get_inv_amount(inv) > 0) then
ps.inven_icon = ICONS[inv]
return
end
end
ps.inven_icon = 0
end
function _checkavailweapon(pli)
ffiC.P_CheckWeapon(player[pli])
end
function _addphealth(ps, aci, hlthadd) function _addphealth(ps, aci, hlthadd)
if (ps.newowner >= 0) then if (ps.newowner >= 0) then
ffiC.G_ClearCameraView(ps) ffiC.G_ClearCameraView(ps)
@ -1504,6 +1544,46 @@ end
--- Game arrays --- --- Game arrays ---
local function moddir_filename(cstr_fn)
local fn = ffi.string(cstr_fn)
local moddir = ffi.string(ffiC.g_modDir);
if (moddir=="/") then
return fn
else
return format("%s/%s", moddir, fn)
end
end
local GAR_FOOTER = "##EDuke32GameArray##"
local GAR_FOOTER_SIZE = #GAR_FOOTER
local function gamearray_file_common(qnum, writep)
local fn = moddir_filename(bcheck.quote_idx(qnum))
local f, errmsg = io.open(fn);
if (f == nil) then
if (not writep) then
error([[failed opening "%s" for reading: %s]], fn, errmsg, 3)
else
return nil, nil, true, fn
end
end
local fsize, errmsg = assert(f:seek("end"))
local isnewgar = false
if (fsize >= GAR_FOOTER_SIZE) then
assert(f:seek("end", -GAR_FOOTER_SIZE))
isnewgar = (assert(f:read(GAR_FOOTER_SIZE)) == GAR_FOOTER)
if (isnewgar) then
fsize = fsize - GAR_FOOTER_SIZE
end
end
return f, math.floor(fsize/4), isnewgar, fn
end
local function check_gamearray_idx(gar, idx, addstr) local function check_gamearray_idx(gar, idx, addstr)
if (idx >= gar._size+0ULL) then if (idx >= gar._size+0ULL) then
addstr = addstr or "" addstr = addstr or ""
@ -1511,6 +1591,8 @@ local function check_gamearray_idx(gar, idx, addstr)
end end
end end
local intbytes_t = ffi.typeof("union { int32_t i; uint8_t b[4]; }")
local gamearray_methods = { local gamearray_methods = {
resize = function(gar, newsize) resize = function(gar, newsize)
-- NOTE: size 0 is valid (then, no index is valid) -- NOTE: size 0 is valid (then, no index is valid)
@ -1518,9 +1600,15 @@ local gamearray_methods = {
error("invalid new array size "..newsize, 2) error("invalid new array size "..newsize, 2)
end end
local MAXELTS = math.floor(0x7fffffff/4)
if (newsize > MAXELTS) then
-- mainly for some sanity with kread() (which we don't use, but still)
error("new array size "..newsize.." too large (max="..MAXELTS.." elements)", 2)
end
-- clear trailing elements in case we're shrinking -- clear trailing elements in case we're shrinking
for i=gar._size,newsize-1 do for i=gar._size,newsize-1 do
gar[i] = nil rawset(gar, i, nil)
end end
gar._size = newsize gar._size = newsize
@ -1533,15 +1621,70 @@ local gamearray_methods = {
check_gamearray_idx(dar, didx, "lower destination ") check_gamearray_idx(dar, didx, "lower destination ")
check_gamearray_idx(dar, didx+numelts-1, "upper destination ") check_gamearray_idx(dar, didx+numelts-1, "upper destination ")
for i=0,numelts-1 do for i=0,numelts-1 do
dar[dsix+i] = sar[sidx+i] rawset(dar, didx+i, rawget(sar, sidx+i))
end end
end, end,
read = function(gar, qnum)
local f, nelts, isnewgar = gamearray_file_common(qnum, false)
assert(f:seek("set"))
local str, errmsg = f:read(4*nelts)
if (#str ~= 4*nelts) then
error("failed reading whole file into gamearray: %s", errmsg, 2)
end
gar:resize(nelts)
for i=0,nelts-1 do
local b1, b2, b3, b4 = byte(str, 4*i+1, 4*i+4)
-- ints on disk are litte-endian
local int = b1 + 256*b2 + 256^2*b3 + 256^3*b4
rawset(gar, i, (int==0) and nil or int)
end
f:close()
end,
write = function(gar, qnum)
local f, _, isnewgar, fn = gamearray_file_common(qnum, true)
if (f ~= nil) then
f:close()
end
if (not isnewgar) then
error("refusing to overwrite a file not created by a previous `writearraytofile'", 2)
end
f = io.open(fn, "w+")
if (f == nil) then
error([[failed opening "%s" for writing: %s]], fn, errmsg, 3)
end
local nelts = gar._size
local cstr = ffi.new("uint8_t [?]", 4*nelts)
local isbe = ffi.abi("be") -- is big-endian?
for i=0,nelts-1 do
local diskval = intbytes_t(isbe and bit.bswap(gar[i]) or gar[i])
for bi=0,3 do
cstr[4*i+bi] = diskval.b[bi]
end
end
f:write(ffi.string(cstr, 4*nelts))
f:write(GAR_FOOTER)
f:close()
end
} }
local gamearray_mt = { local gamearray_mt = {
__index = function(gar, key) __index = function(gar, key)
if (type(key)=="number") then if (type(key)=="number") then
check_gamearray_idx(key) check_gamearray_idx(gar, key)
return 0 return 0
else else
return gamearray_methods[key] return gamearray_methods[key]
@ -1549,16 +1692,16 @@ local gamearray_mt = {
end, end,
__newindex = function(gar, idx, val) __newindex = function(gar, idx, val)
check_gamearray_idx(idx) check_gamearray_idx(gar, idx)
gar[idx] = val rawset(gar, idx, val)
end, end,
-- Calling a gamearray causes its cleanup: -- Calling a gamearray causes its cleanup:
-- * All values equal to the default one (0) are cleared. -- * All values equal to the default one (0) are cleared.
__call = function(gar) __call = function(gar)
for i=0,gar._size-1 do for i=0,gar._size-1 do
if (gar[i]==0) then if (rawget(gar, i)==0) then
gar[i] = nil rawset(gar, i, nil)
end end
end end
end, end,

View file

@ -228,6 +228,8 @@ __attribute__((packed)) struct {
uint8_t gm, on_warping_sector, footprintcount, hurt_delay; uint8_t gm, on_warping_sector, footprintcount, hurt_delay;
uint8_t hbomb_on, jumping_toggle, rapid_fire_hold, on_ground; uint8_t hbomb_on, jumping_toggle, rapid_fire_hold, on_ground;
// NOTE: there's array indexing with inven_icon, but always after a
// bound check:
uint8_t inven_icon, buttonpalette, over_shoulder_on, show_empty_weapon; uint8_t inven_icon, buttonpalette, over_shoulder_on, show_empty_weapon;
uint8_t jetpack_on, spritebridge, lastrandomspot; uint8_t jetpack_on, spritebridge, lastrandomspot;
@ -456,7 +458,7 @@ typedef struct {
int32_t ForceSetup; int32_t ForceSetup;
int32_t NoAutoLoad; int32_t NoAutoLoad;
int32_t scripthandle; const int32_t scripthandle;
int32_t setupread; int32_t setupread;
int32_t CheckForUpdates; int32_t CheckForUpdates;
@ -488,13 +490,14 @@ hudweapon_t hudweap;
]] ]]
-- INTERNAL VARIABLES/FUNCTIONS -- INTERNAL VARIABLES/FUNCTIONS
decl("map_t MapInfo[($+1)*$];", con_lang.MAXVOLUMES, con_lang.MAXLEVELS) decl("map_t MapInfo[$*$];", con_lang.MAXVOLUMES+1, con_lang.MAXLEVELS)
decl[[ decl[[
const char *s_buildRev; const char *s_buildRev;
const char *g_sizes_of_what[]; const char *g_sizes_of_what[];
int32_t g_sizes_of[]; int32_t g_sizes_of[];
int32_t g_elCallDepth; int32_t g_elCallDepth;
char g_modDir[];
actor_t actor[MAXSPRITES]; actor_t actor[MAXSPRITES];
camera_t g_camera; camera_t g_camera;
user_defs ud; user_defs ud;
@ -515,9 +518,11 @@ int32_t g_scriptVersion;
const int32_t g_currentFrameRate; const int32_t g_currentFrameRate;
const int32_t g_currentMenu; const int32_t g_currentMenu;
uint16_t g_earthquakeTime; uint16_t g_earthquakeTime;
char CheatKeys[2];
int32_t A_IncurDamage(int32_t sn); // not bound-checked! int32_t A_IncurDamage(int32_t sn); // not bound-checked!
void P_AddWeaponMaybeSwitch(DukePlayer_t *ps, int32_t weap); void P_AddWeaponMaybeSwitch(DukePlayer_t *ps, int32_t weap);
void P_CheckWeapon(DukePlayer_t *p);
int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel); int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel);
int32_t A_IncurDamage(int32_t sn); int32_t A_IncurDamage(int32_t sn);
int32_t A_Spawn(int32_t j, int32_t pn); int32_t A_Spawn(int32_t j, int32_t pn);
@ -580,6 +585,8 @@ void C_DefineLevelName(int32_t vol, int32_t lev, const char *fn,
int32_t partime, int32_t designertime, int32_t partime, int32_t designertime,
const char *levelname); const char *levelname);
void C_DefineProjectile(int32_t j, int32_t what, int32_t val); void C_DefineProjectile(int32_t j, int32_t what, int32_t val);
void C_DefineGameFuncName(int32_t idx, const char *name);
int32_t C_SetDefName(const char *name);
]] ]]

View file

@ -72,6 +72,7 @@ s_buildRev;
g_sizes_of_what; g_sizes_of_what;
g_sizes_of; g_sizes_of;
g_elCallDepth; g_elCallDepth;
g_modDir;
kopen4loadfrommod; kopen4loadfrommod;
kfilelength; kfilelength;
@ -90,6 +91,8 @@ C_DefineVolumeName;
C_DefineSkillName; C_DefineSkillName;
C_DefineLevelName; C_DefineLevelName;
C_DefineProjectile; C_DefineProjectile;
C_DefineGameFuncName;
C_SetDefName;
actor; actor;
g_camera; g_camera;
@ -130,7 +133,8 @@ md4once;
A_IncurDamage; A_IncurDamage;
P_AddWeaponMaybeSwitch; P_AddWeaponMaybeSwitch;
A_Shoot; P_CheckWeapon;
A_ShootWithZvel;
A_IncurDamage; A_IncurDamage;
A_Spawn; A_Spawn;
VM_FallSprite; VM_FallSprite;

View file

@ -145,6 +145,7 @@ local function new_initial_codetab()
"local sector, sprite, actor, player = sector, sprite, actor, player;", "local sector, sprite, actor, player = sector, sprite, actor, player;",
"local gameactor, gameevent, _gv = gameactor, gameevent, gv;", "local gameactor, gameevent, _gv = gameactor, gameevent, gv;",
"local updatesector, updatesectorz, cansee = updatesector, updatesectorz, cansee;", "local updatesector, updatesectorz, cansee = updatesector, updatesectorz, cansee;",
"local print = print;",
-- switch function table, indexed by global switch sequence number: -- switch function table, indexed by global switch sequence number:
"local _SW = {};", "local _SW = {};",
@ -172,8 +173,7 @@ local function new_initial_gvartab()
local PRO = GamevarCreationFunc(GVFLAG.READONLY+GVFLAG.PERPLAYER) local PRO = GamevarCreationFunc(GVFLAG.READONLY+GVFLAG.PERPLAYER)
local gamevar = { local gamevar = {
-- XXX: TODO: THISACTOR can mean different things in some contexts, -- NOTE: THISACTOR can mean different things in some contexts.
-- e.g. sector[THISACTOR] is sector[sprite[<current actor>].sectnum]
THISACTOR = RO "_aci", THISACTOR = RO "_aci",
RETURN = RW(CSV".RETURN"), RETURN = RW(CSV".RETURN"),
@ -424,6 +424,16 @@ local function parse_number(pos, numstr)
return num return num
end end
-- returns: OK?
local function check_tilenum(tilenum)
if (not (tilenum >= 0 and tilenum < (ffiC and ffiC.MAXTILES or 30720))) then
errprintf("invalid tile number %d", tilenum)
return false
end
return true
end
-- Mapping of various "define" types to the respective number of members and -- Mapping of various "define" types to the respective number of members and
-- vice versa -- vice versa
@ -678,6 +688,18 @@ end
-- Table of various outer command handling functions. -- Table of various outer command handling functions.
local Cmd = {} local Cmd = {}
function Cmd.NYI(msg)
return function()
errprintf(msg.." not yet implemented")
end
end
function Cmd.nyi(msg)
return function()
warnprintf(msg.." not yet implemented")
end
end
function Cmd.include(filename) function Cmd.include(filename)
do_include_file(g_directory, filename) do_include_file(g_directory, filename)
end end
@ -766,6 +788,22 @@ function Cmd.definevolumename(vol, name)
g_data.volname[vol] = name g_data.volname[vol] = name
end end
function Cmd.definegamefuncname(idx, name)
local NUMGAMEFUNCTIONS = (ffi and ffiC.NUMGAMEFUNCTIONS or 56)
if (not (idx >= 0 and idx < NUMGAMEFUNCTIONS)) then
errprintf("function number exceeds number of game functions.")
return
end
assert(type(name)=="string")
-- XXX: in place of C-CON's "invalid character in function name" report:
name:gsub("[^A-Za-z0-9]", "_")
if (ffi) then
ffiC.C_DefineGameFuncName(idx, name)
end
end
-- strip whitespace from front and back -- strip whitespace from front and back
local function stripws(str) local function stripws(str)
return str:match("^%s*(.*)%s*$") return str:match("^%s*(.*)%s*$")
@ -793,17 +831,44 @@ function Cmd.definequote(qnum, quotestr)
end end
function Cmd.defineprojectile(tilenum, what, val) function Cmd.defineprojectile(tilenum, what, val)
if (not (tilenum >= 0 and tilenum < (ffiC and ffiC.MAXTILES or 30720))) then local ok = check_tilenum(tilenum)
errprintf("invalid tile number %d", tilenum)
return
end
if (ffi) then if (ffi and ok) then
-- TODO: potentially bound-check some members? -- TODO: potentially bound-check some members?
ffiC.C_DefineProjectile(tilenum, what, val) ffiC.C_DefineProjectile(tilenum, what, val)
end end
end end
-- flags: if string, look up in ffiC and OR, else set number directly.
function Cmd.xspriteflags(tilenum, flags)
local ok = check_tilenum(tilenum)
if (ffi and ok) then
if (type(flags)=="number") then
ffiC.g_tile[tilenum].flags = flags
else
assert(type(flags)=="string")
ffiC.g_tile[tilenum].flags = bit.bor(ffiC.g_tile[tilenum].flags, ffiC[flags])
end
end
end
function Cmd.cheatkeys(sc1, sc2)
if (ffi) then
ffiC.CheatKeys[0] = sc1
ffiC.CheatKeys[1] = sc2
end
end
function Cmd.setdefname(filename)
assert(type(filename)=="string")
if (ffi) then
if (ffiC.C_SetDefName(filename) ~= 0) then
error("OUT OF MEMORY", 0)
end
end
end
function Cmd.gamestartup(...) function Cmd.gamestartup(...)
local args = {...} local args = {...}
@ -1110,63 +1175,90 @@ end
-- XXX: many of these are also allowed inside actors/states/events in CON. -- XXX: many of these are also allowed inside actors/states/events in CON.
local Couter = { local Couter = {
--- 1. Preprocessor --- 1. Preprocessor
include = sp1 * maybe_quoted_filename / Cmd.include, include = sp1 * maybe_quoted_filename
includedefault = cmd(), / Cmd.include,
define = cmd(I,D) / do_define_label, includedefault = cmd()
/ Cmd.NYI("`includedefault'"),
define = cmd(I,D)
/ do_define_label,
--- 2. Defines and Meta-Settings --- 2. Defines and Meta-Settings
dynamicremap = cmd(), dynamicremap = cmd()
setcfgname = sp1 * tok.filename, / Cmd.NYI("dynamic tile remapping"),
setdefname = sp1 * tok.filename, setcfgname = sp1 * tok.filename
setgamename = newline_term_string, / Cmd.nyi("`setcfgname'"),
setdefname = sp1 * tok.filename
/ Cmd.setdefname,
setgamename = newline_term_string
/ Cmd.nyi("`setgamename'"),
precache = cmd(D,D,D), precache = cmd(D,D,D)
, -- / Cmd.nyi("`precache'"),
scriptsize = cmd(D) scriptsize = cmd(D)
/ "", -- no-op / "", -- no-op
cheatkeys = cmd(D,D), cheatkeys = cmd(D,D)
/ Cmd.cheatkeys,
definecheat = newline_term_string, -- XXX: actually tricker syntax (TS) definecheat = newline_term_string -- XXX: actually tricker syntax (TS)
definegamefuncname = newline_term_string, -- XXX: TS? , -- / Cmd.nyi("`definecheat'"),
definegametype = n_defines(2) * newline_term_string, definegamefuncname = sp1 * tok.define * newline_term_string -- XXX: TS?
/ Cmd.definegamefuncname,
definegametype = n_defines(2) * newline_term_string
/ Cmd.NYI("`definegametype'"), -- TODO_MP
definelevelname = n_defines(2) * sp1 * tok.filename * sp1 * tok.time * sp1 * tok.time * definelevelname = n_defines(2) * sp1 * tok.filename * sp1 * tok.time * sp1 * tok.time *
newline_term_string / Cmd.definelevelname, newline_term_string
defineskillname = sp1 * tok.define * newline_term_string / Cmd.defineskillname, / Cmd.definelevelname,
definevolumename = sp1 * tok.define * newline_term_string / Cmd.definevolumename, defineskillname = sp1 * tok.define * newline_term_string
/ Cmd.defineskillname,
definevolumename = sp1 * tok.define * newline_term_string
/ Cmd.definevolumename,
definequote = sp1 * tok.define * newline_term_string / Cmd.definequote, definequote = sp1 * tok.define * newline_term_string
defineprojectile = cmd(D,D,D) / Cmd.defineprojectile, / Cmd.definequote,
definesound = sp1 * tok.define * sp1 * maybe_quoted_filename * n_defines(5) / Cmd.definesound, defineprojectile = cmd(D,D,D)
/ Cmd.defineprojectile,
definesound = sp1 * tok.define * sp1 * maybe_quoted_filename * n_defines(5)
/ Cmd.definesound,
-- NOTE: gamevar.ogg and the like is OK, too -- NOTE: gamevar.ogg and the like is OK, too
music = sp1 * tok.define * match_until(sp1 * tok.filename, sp1 * conl.keyword * sp1) / Cmd.music, music = sp1 * tok.define * match_until(sp1 * tok.filename, sp1 * conl.keyword * sp1)
/ Cmd.music,
--- 3. Game Settings --- 3. Game Settings
-- gamestartup has 26/30 fixed defines, depending on 1.3D/1.5 version: -- gamestartup has 26/30 fixed defines, depending on 1.3D/1.5 version:
gamestartup = (sp1 * tok.define)^26 / Cmd.gamestartup, gamestartup = (sp1 * tok.define)^26
spritenopal = cmd(D), / Cmd.gamestartup,
spritenoshade = cmd(D), spritenopal = cmd(D)
spritenvg = cmd(D), / function(tilenum, flags) Cmd.xspriteflags(tilenum, "SFLAG_NOPAL") end,
spriteshadow = cmd(D), spritenoshade = cmd(D)
/ function(tilenum, flags) Cmd.xspriteflags(tilenum, "SFLAG_NOSHADE") end,
spritenvg = cmd(D)
/ function(tilenum, flags) Cmd.xspriteflags(tilenum, "SFLAG_NVG") end,
spriteshadow = cmd(D)
/ function(tilenum, flags) Cmd.xspriteflags(tilenum, "SFLAG_SHADOW") end,
spriteflags = cmd(D,D), -- also see inner spriteflags = cmd(D,D) -- also see inner
/ function(tilenum, flags) Cmd.xspriteflags(tilenum, flags) end,
--- 4. Game Variables / Arrays --- 4. Game Variables / Arrays
gamevar = cmd(I,D,D) / Cmd.gamevar, gamevar = cmd(I,D,D)
gamearray = cmd(I,D) / Cmd.gamearray, / Cmd.gamevar,
gamearray = cmd(I,D)
/ Cmd.gamearray,
--- 5. Top level commands that are also run-time commands --- 5. Top level commands that are also run-time commands
move = sp1 * tok.identifier * (sp1 * tok.define)^-2 / -- hvel, vvel move = sp1 * tok.identifier * (sp1 * tok.define)^-2 -- hvel, vvel
function(...) do_define_composite(LABEL.MOVE, ...) end, / function(...) do_define_composite(LABEL.MOVE, ...) end,
-- startframe, numframes, viewtype, incval, delay: -- startframe, numframes, viewtype, incval, delay:
action = sp1 * tok.identifier * (sp1 * tok.define)^-5 / action = sp1 * tok.identifier * (sp1 * tok.define)^-5
function(...) do_define_composite(LABEL.ACTION, ...) end, / function(...) do_define_composite(LABEL.ACTION, ...) end,
-- action, move, flags...: -- action, move, flags...:
ai = sp1 * tok.identifier * (sp1 * tok.action * ai = sp1 * tok.identifier * (sp1 * tok.action *
(sp1 * tok.move * (sp1 * tok.define)^0)^-1 (sp1 * tok.move * (sp1 * tok.define)^0)^-1
)^-1 / )^-1
function(...) do_define_composite(LABEL.AI, ...) end, / function(...) do_define_composite(LABEL.AI, ...) end,
--- 6. Deprecated TLCs --- 6. Deprecated TLCs
betaname = newline_term_string, betaname = newline_term_string,
@ -1226,6 +1318,10 @@ local getperxvarcmd = -- get<actor/player>var[<idx>].<varname> <<var>>
local setperxvarcmd = -- set<actor/player>var[<idx>].<<varname>> <var> local setperxvarcmd = -- set<actor/player>var[<idx>].<<varname>> <var>
arraypat * singlememberpat * sp1 * tok.rvar arraypat * singlememberpat * sp1 * tok.rvar
local function thisactor_to_pli(var)
return (var=="_aci") and "_pli" or var
end
-- Function generating code for a struct read/write access. -- Function generating code for a struct read/write access.
local function StructAccess(Structname, writep, index, membertab) local function StructAccess(Structname, writep, index, membertab)
assert(type(membertab)=="table") assert(type(membertab)=="table")
@ -1262,6 +1358,15 @@ local function StructAccess(Structname, writep, index, membertab)
end end
end end
-- THISACTOR special meanings
if (Structname=="player" or Structname=="input") then
index = thisactor_to_pli(index)
elseif (Structname=="sector") then
if (index=="_aci") then
index = SPS".sectnum"
end
end
-- METHOD_MEMBER -- METHOD_MEMBER
local ismethod = (armembcode:find("%%s",1,true)~=nil) local ismethod = (armembcode:find("%%s",1,true)~=nil)
-- If ismethod is true, then the formatted string will now have an "%s" -- If ismethod is true, then the formatted string will now have an "%s"
@ -1278,8 +1383,8 @@ end
function lookup.array_expr(writep, structname, index, membertab) function lookup.array_expr(writep, structname, index, membertab)
if (conl.StructAccessCode[structname] == nil) then if (conl.StructAccessCode[structname] == nil) then
-- Try a gamearray -- Try a gamearray
local ga = (g_gamearray[structname]) and lookup.gamearray(structname) local ganame = g_gamearray[structname] and lookup.gamearray(structname)
if (ga == nil) then if (ganame == nil) then
if (structname=="actorvar") then if (structname=="actorvar") then
-- actorvar[] inline array expr -- actorvar[] inline array expr
-- XXX: kind of CODEDUP with GetOrSetPerxvarCmd() factory -- XXX: kind of CODEDUP with GetOrSetPerxvarCmd() factory
@ -1311,7 +1416,8 @@ function lookup.array_expr(writep, structname, index, membertab)
return "_INVALIDAR" return "_INVALIDAR"
end end
return format("%s[%s]", ga.name, index) assert(type(ganame)=="string")
return format("%s[%s]", ganame, index)
end end
local membercode, ismethod = StructAccess(structname, writep, index, membertab) local membercode, ismethod = StructAccess(structname, writep, index, membertab)
@ -1374,6 +1480,11 @@ local function GetOrSetPerxvarCmd(Setp, Actorp)
errprintf("variable `%s' is not per-%s", perxvarname, Actorp and "actor" or "player") errprintf("variable `%s' is not per-%s", perxvarname, Actorp and "actor" or "player")
end end
if (not Actorp) then
-- THISACTOR -> player index for {g,s}etplayervar
idx = thisactor_to_pli(idx)
end
if (Setp) then if (Setp) then
return format("%s=%s", lookup.gamevar(perxvarname, idx, true), var) return format("%s=%s", lookup.gamevar(perxvarname, idx, true), var)
else else
@ -1396,6 +1507,12 @@ local handle =
errprintf("command `%s' not yet implemented", g_lastkw) errprintf("command `%s' not yet implemented", g_lastkw)
end, end,
dynNYI = function()
-- XXX: what if file name contains a double quote? (Similarly commands below.)
return format([[print("%s:%d: `%s' not yet implemented")]],
g_filename, getlinecol(g_lastkwpos), g_lastkw)
end,
addlog = function() addlog = function()
return format("print('%s:%d: addlog')", g_filename, getlinecol(g_lastkwpos)) return format("print('%s:%d: addlog')", g_filename, getlinecol(g_lastkwpos))
end, end,
@ -1506,7 +1623,7 @@ local Cinner = {
-- We disallow them, recent EDuke32 versions didn't expose them either. -- We disallow them, recent EDuke32 versions didn't expose them either.
getuserdef = GetStructCmd(Access.userdef, userdef_common_pat * tok.wvar), getuserdef = GetStructCmd(Access.userdef, userdef_common_pat * tok.wvar),
getplayervar = GetOrSetPerxvarCmd(false, false), getplayervar = GetOrSetPerxvarCmd(false, false), -- THISACTOR
getactorvar = GetOrSetPerxvarCmd(false, true), getactorvar = GetOrSetPerxvarCmd(false, true),
setsector = SetStructCmd(Access.sector), setsector = SetStructCmd(Access.sector),
@ -1520,7 +1637,7 @@ local Cinner = {
settspr = SetStructCmd(Access.tspr), settspr = SetStructCmd(Access.tspr),
setuserdef = SetStructCmd(Access.userdef, userdef_common_pat * tok.rvar), setuserdef = SetStructCmd(Access.userdef, userdef_common_pat * tok.rvar),
setplayervar = GetOrSetPerxvarCmd(true, false), setplayervar = GetOrSetPerxvarCmd(true, false), -- THISACTOR
setactorvar = GetOrSetPerxvarCmd(true, true), setactorvar = GetOrSetPerxvarCmd(true, true),
setvarvar = varvarop / "%1=%2", setvarvar = varvarop / "%1=%2",
@ -1617,13 +1734,15 @@ local Cinner = {
cmenu = cmd(R) cmenu = cmd(R)
/ handle.NYI, / handle.NYI,
checkavailweapon = cmd(R) -- THISACTOR checkavailweapon = cmd(R) -- THISACTOR
/ handle.NYI, / function(pli)
return format("_con._checkavailweapon(%s)", thisactor_to_pli(pli))
end,
checkavailinven = cmd(R) -- THISACTOR checkavailinven = cmd(R) -- THISACTOR
/ handle.NYI, / function(pli)
return format("_con._selectnextinv(player[%s])", thisactor_to_pli(pli))
end,
guniqhudid = cmd(R) guniqhudid = cmd(R)
/ "_gv._set_guniqhudid(%1)", / "_gv._set_guniqhudid(%1)",
savegamevar = cmd(R),
readgamevar = cmd(R),
echo = cmd(R) echo = cmd(R)
/ "_con._echo(%1)", / "_con._echo(%1)",
activatecheat = cmd(R) activatecheat = cmd(R)
@ -1705,8 +1824,6 @@ local Cinner = {
/ "_con._spawnmany(_aci,1233,%1)", -- TODO: dyntile / "_con._spawnmany(_aci,1233,%1)", -- TODO: dyntile
paper = cmd(D) paper = cmd(D)
/ "_con._spawnmany(_aci,4460,%1)", -- TODO: dyntile / "_con._spawnmany(_aci,4460,%1)", -- TODO: dyntile
savenn = cmd(D),
save = cmd(D),
sleeptime = cmd(D) sleeptime = cmd(D)
/ ACS".timetosleep=%1", / ACS".timetosleep=%1",
@ -1809,7 +1926,7 @@ local Cinner = {
/ "_con._userquote(%1)", / "_con._userquote(%1)",
getkeyname = cmd(R,R,R) getkeyname = cmd(R,R,R)
/ "_con._getkeyname(%1,%2,%3)", / "_con._getkeyname(%1,%2,%3)",
getpname = cmd(R,R) getpname = cmd(R,R) -- THISACTOR
/ handle.NYI, / handle.NYI,
-- array stuff -- array stuff
@ -1821,8 +1938,26 @@ local Cinner = {
/ "%1:resize(%2)", / "%1:resize(%2)",
getarraysize = cmd(GARI,W) getarraysize = cmd(GARI,W)
/ "%2=%1._size", / "%2=%1._size",
readarrayfromfile = cmd(GARI,D), readarrayfromfile = cmd(GARI,D)
writearraytofile = cmd(GARI,D), / "%1:read(%2)",
writearraytofile = cmd(GARI,D)
/ "%1:write(%2)",
-- Persistence
clearmapstate = cmd(R)
/ handle.dynNYI,
loadmapstate = cmd()
/ handle.dynNYI,
savemapstate = cmd()
/ handle.dynNYI,
savegamevar = cmd(R)
/ handle.dynNYI,
readgamevar = cmd(R)
/ handle.dynNYI,
savenn = cmd(D)
/ handle.dynNYI,
save = cmd(D)
/ handle.dynNYI,
addlogvar = cmd(R) addlogvar = cmd(R)
/ handle.addlogvar, / handle.addlogvar,
@ -1898,8 +2033,7 @@ local Cinner = {
/ "_con._activatebysector(%1,%2)", / "_con._activatebysector(%1,%2)",
operateactivators = cmd(R,R) -- THISACTOR operateactivators = cmd(R,R) -- THISACTOR
/ function(tag, pli) / function(tag, pli)
return format("_con._operateactivators(%s,%s)", tag, return format("_con._operateactivators(%s,%s)", tag, thisactor_to_pli(pli))
(pli=="_aci") and "_pli" or pli)
end, end,
operatesectors = cmd(R,R) operatesectors = cmd(R,R)
/ "_con._operatesectors(%1,%2)", / "_con._operatesectors(%1,%2)",
@ -1915,10 +2049,6 @@ local Cinner = {
myospalx = cmd(R,R,R,R,R,R) myospalx = cmd(R,R,R,R,R,R)
/ "_con._myos(%1,%2,32768,%3,%4,%5,%6)", / "_con._myos(%1,%2,32768,%3,%4,%5,%6)",
clearmapstate = cmd(R),
loadmapstate = cmd(),
savemapstate = cmd(),
headspritesect = cmd(W,R) headspritesect = cmd(W,R)
/ "%1=sprite._headspritesect[%2]", / "%1=sprite._headspritesect[%2]",
headspritestat = cmd(W,R) headspritestat = cmd(W,R)

View file

@ -81,7 +81,7 @@ t = os.clock()-t
printf("rotate: %.03fns per call", (1e9)/Nsq) printf("rotate: %.03fns per call", (1e9)/Nsq)
-- Results (helixhorned x86_64) -- Results (helixhorned x86, x86_64)
-- number of points: 10000, testing 100000000 distances -- number of points: 10000, testing 100000000 distances
-- edist: 6.300ns per call, mean=6286.597 -- edist: 6.300ns per call, mean=6286.597
-- ldist: 17.600ns per call, mean=8692.612 -- ldist: 17.600ns per call, mean=8692.612