mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-11 18:50:46 +00:00
Lunatic: prototypical editor binding.
git-svn-id: https://svn.eduke32.com/eduke32@3056 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
fb5d920408
commit
851c6b081d
9 changed files with 592 additions and 403 deletions
|
@ -163,6 +163,8 @@ ifneq (0,$(LUNATIC))
|
||||||
else
|
else
|
||||||
LIBS+= -L/usr/local/lib -lluajit-5.1
|
LIBS+= -L/usr/local/lib -lluajit-5.1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
EDITOROBJS+= $(OBJ)/lunatic_m32.$o
|
||||||
GAMEOBJS+= $(OBJ)/lunatic.$o
|
GAMEOBJS+= $(OBJ)/lunatic.$o
|
||||||
|
|
||||||
GAMEOBJS+= $(OBJ)/../lpeg.$o # TEMP
|
GAMEOBJS+= $(OBJ)/../lpeg.$o # TEMP
|
||||||
|
|
|
@ -49,6 +49,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "m32script.h"
|
#include "m32script.h"
|
||||||
#include "m32def.h"
|
#include "m32def.h"
|
||||||
|
|
||||||
|
#ifdef LUNATIC
|
||||||
|
# include "lunatic_m32.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "rev.h"
|
#include "rev.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -87,6 +91,10 @@ char **g_clipMapFiles = NULL;
|
||||||
int32_t g_clipMapFilesNum = 0;
|
int32_t g_clipMapFilesNum = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LUNATIC
|
||||||
|
Em_State *g_EmState;
|
||||||
|
#endif
|
||||||
|
|
||||||
#pragma pack(push,1)
|
#pragma pack(push,1)
|
||||||
sound_t g_sounds[MAXSOUNDS];
|
sound_t g_sounds[MAXSOUNDS];
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
@ -10492,6 +10500,21 @@ int32_t ExtInit(void)
|
||||||
|
|
||||||
MultiPskyInit();
|
MultiPskyInit();
|
||||||
|
|
||||||
|
#ifdef LUNATIC
|
||||||
|
g_EmState = Em_CreateState();
|
||||||
|
|
||||||
|
if (g_EmState)
|
||||||
|
{
|
||||||
|
i = Em_RunOnce(g_EmState, "defs_m32.ilua");
|
||||||
|
if (i)
|
||||||
|
{
|
||||||
|
initprintf("Lunatic: Error preparing global Lua state (code %d)\n", i);
|
||||||
|
Em_DestroyState(g_EmState);
|
||||||
|
g_EmState = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
signal(SIGINT, m32script_interrupt_handler);
|
signal(SIGINT, m32script_interrupt_handler);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -6,95 +6,25 @@ _EDUKE32_LUNATIC = true
|
||||||
local ffi = require("ffi")
|
local ffi = require("ffi")
|
||||||
local ffiC = ffi.C
|
local ffiC = ffi.C
|
||||||
|
|
||||||
---=== Duke3D engine and game definitions ===---
|
local string = string
|
||||||
ffi.cdef[[
|
local table = table
|
||||||
#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
|
--== First, load the definitions common to the game's and editor's Lua interface.
|
||||||
{
|
|
||||||
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
|
-- 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?
|
||||||
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;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t x, y, z;
|
|
||||||
} vec3_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
vec3_t pos;
|
|
||||||
int16_t sprite, wall, sect;
|
|
||||||
} hitdata_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char r,g,b,f;
|
|
||||||
} palette_t;
|
|
||||||
#pragma pack(pop)
|
|
||||||
]]
|
|
||||||
|
|
||||||
local vec3_ct = ffi.typeof("vec3_t")
|
|
||||||
local hitdata_ct = ffi.typeof("hitdata_t")
|
|
||||||
|
|
||||||
---- engine data and functions ----
|
|
||||||
|
|
||||||
-- GLOBAL gv: provides access to C global *scalars* and safe functions
|
|
||||||
-- XXX: still exposes C library functions etc. contained in ffi.C.
|
|
||||||
-- Is this a problem?
|
|
||||||
local gv_ = {
|
local gv_ = {
|
||||||
-- all non-scalars need to be explicitly listed here and access to them is
|
-- All non-scalars need to be explicitly listed here and access to them is
|
||||||
-- redirected to the dummy empty table...
|
-- redirected to the dummy empty table...
|
||||||
}
|
}
|
||||||
|
|
||||||
local dummy_empty_table = {}
|
local dummy_empty_table = {}
|
||||||
|
|
||||||
-- This is for declarations of arrays or pointers which should not be
|
-- This is for declarations of arrays or pointers which should not be
|
||||||
-- accessible through the gv global.
|
-- accessible through the "gv" global. The "defs_common" module require will
|
||||||
|
-- use this function.
|
||||||
-- NOTE: don't declare multiple pointers on one line (like int32_t *a, *b;)!
|
-- NOTE: don't declare multiple pointers on one line (like int32_t *a, *b;)!
|
||||||
local function decl(str)
|
function decl(str)
|
||||||
for varname in string.gmatch(str, "([%a_][%w_]*)[[(;]") do
|
for varname in string.gmatch(str, "([%a_][%w_]*)[[(;]") do
|
||||||
-- print("protect "..varname)
|
-- print("protect "..varname)
|
||||||
gv_[varname] = dummy_empty_table
|
gv_[varname] = dummy_empty_table
|
||||||
|
@ -103,86 +33,11 @@ local function decl(str)
|
||||||
ffi.cdef(str)
|
ffi.cdef(str)
|
||||||
end
|
end
|
||||||
|
|
||||||
ffi.cdef[[int32_t engine_main_arrays_are_static, engine_v8;]]
|
-- load them!
|
||||||
|
local defs_c = require("defs_common")
|
||||||
|
|
||||||
-- NOTE TO SELF: This is not C, never EVER write
|
|
||||||
-- if (x)
|
|
||||||
-- when checking a C variable x for 'thuthiness'
|
|
||||||
if (ffiC.engine_main_arrays_are_static ~= 0) then
|
|
||||||
decl[[
|
|
||||||
sectortype sector[];
|
|
||||||
walltype wall[];
|
|
||||||
spritetype sprite[];
|
|
||||||
spriteext_t spriteext[];
|
|
||||||
]]
|
|
||||||
else
|
|
||||||
decl[[
|
|
||||||
sectortype *sector;
|
|
||||||
walltype *wall;
|
|
||||||
spritetype *sprite;
|
|
||||||
spriteext_t *spriteext;
|
|
||||||
]]
|
|
||||||
end
|
|
||||||
|
|
||||||
if (ffiC.engine_v8 == 0) then
|
---=== EDuke32 game definitions ===---
|
||||||
-- V7
|
|
||||||
ffi.cdef[[
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
MAXSECTORS = 1024,
|
|
||||||
MAXWALLS = 8192,
|
|
||||||
MAXSPRITES = 4096,
|
|
||||||
}
|
|
||||||
]]
|
|
||||||
else
|
|
||||||
-- V8
|
|
||||||
ffi.cdef[[
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
MAXSECTORS = 4096,
|
|
||||||
MAXWALLS = 16384,
|
|
||||||
MAXSPRITES = 16384,
|
|
||||||
}
|
|
||||||
]]
|
|
||||||
end
|
|
||||||
|
|
||||||
ffi.cdef[[
|
|
||||||
enum {
|
|
||||||
MAXSTATUS = 1024,
|
|
||||||
MAXTILES = 30720,
|
|
||||||
|
|
||||||
MAXBUNCHES = 256,
|
|
||||||
CEILING = 0,
|
|
||||||
FLOOR = 1,
|
|
||||||
|
|
||||||
CLIPMASK0 = (1<<16)+1, // blocking
|
|
||||||
CLIPMASK1 = (256<<16)+64, // hittable
|
|
||||||
};
|
|
||||||
]]
|
|
||||||
|
|
||||||
ffi.cdef[[
|
|
||||||
const int16_t numsectors, numwalls;
|
|
||||||
const int32_t numyaxbunches;
|
|
||||||
const int32_t totalclock;
|
|
||||||
const int32_t xdim, ydim;
|
|
||||||
]]
|
|
||||||
|
|
||||||
decl[[
|
|
||||||
const int16_t headspritesect[MAXSECTORS+1], headspritestat[MAXSTATUS+1];
|
|
||||||
const int16_t prevspritesect[MAXSPRITES], prevspritestat[MAXSPRITES];
|
|
||||||
const int16_t nextspritesect[MAXSPRITES], nextspritestat[MAXSPRITES];
|
|
||||||
|
|
||||||
const int16_t headsectbunch[2][MAXBUNCHES], nextsectbunch[2][MAXSECTORS];
|
|
||||||
|
|
||||||
int16_t yax_getbunch(int16_t i, int16_t cf);
|
|
||||||
|
|
||||||
int32_t hitscan(const vec3_t *sv, int16_t sectnum, int32_t vx, int32_t vy, int32_t vz,
|
|
||||||
hitdata_t *hitinfo, uint32_t cliptype);
|
|
||||||
|
|
||||||
void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
|
|
||||||
int8_t dashade, char dapalnum, int32_t dastat,
|
|
||||||
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2);
|
|
||||||
]]
|
|
||||||
|
|
||||||
-- array -> element flattening inside structs,
|
-- array -> element flattening inside structs,
|
||||||
-- e.g. int32_t a[4] --> int32_t _a0, _a1, _a2, _a3;
|
-- e.g. int32_t a[4] --> int32_t _a0, _a1, _a2, _a3;
|
||||||
|
@ -546,12 +401,7 @@ double rand_jkiss_dbl(rng_jkiss_t *s);
|
||||||
|
|
||||||
void md4once(const unsigned char *block, unsigned int len, unsigned char digest[16]);
|
void md4once(const unsigned char *block, unsigned int len, unsigned char digest[16]);
|
||||||
]]
|
]]
|
||||||
|
-- XXX: "digest" --> dummy?
|
||||||
ffi.cdef[[
|
|
||||||
int32_t ksqrt(uint32_t num);
|
|
||||||
]]
|
|
||||||
|
|
||||||
ffi.cdef "double gethitickms(void);"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -567,9 +417,6 @@ local setmetatable = setmetatable
|
||||||
local setfenv = setfenv
|
local setfenv = setfenv
|
||||||
local type = type
|
local type = type
|
||||||
|
|
||||||
local string = string
|
|
||||||
local table = table
|
|
||||||
|
|
||||||
-- http://lua-users.org/wiki/SandBoxes says "potentially unsafe"
|
-- http://lua-users.org/wiki/SandBoxes says "potentially unsafe"
|
||||||
-- as it allows to see implementations of functions.
|
-- as it allows to see implementations of functions.
|
||||||
--local string_dump = string.dump
|
--local string_dump = string.dump
|
||||||
|
@ -967,46 +814,20 @@ end
|
||||||
|
|
||||||
-- error(..., 2) is to blame the caller and get its line numbers
|
-- error(..., 2) is to blame the caller and get its line numbers
|
||||||
|
|
||||||
-- set metatable and forbid setting it further
|
|
||||||
local function setmtonce(tab, mt)
|
|
||||||
mt.__metatable = true
|
|
||||||
return setmetatable(tab, mt)
|
|
||||||
end
|
|
||||||
|
|
||||||
local tmpmt = {
|
local tmpmt = {
|
||||||
__index = function() error('dummy variable: read access forbidden', 2) end,
|
__index = function() error('dummy variable: read access forbidden', 2) end,
|
||||||
__newindex = function() error('dummy variable: write access forbidden', 2) end,
|
__newindex = function() error('dummy variable: write access forbidden', 2) end,
|
||||||
}
|
}
|
||||||
setmtonce(dummy_empty_table, tmpmt)
|
defs_c.setmtonce(dummy_empty_table, tmpmt)
|
||||||
|
|
||||||
gv = gv_
|
gv = gv_
|
||||||
local tmpmt = {
|
local tmpmt = {
|
||||||
__index = ffiC,
|
__index = ffiC,
|
||||||
__newindex = function() error("cannot create new or write into existing fields of 'gv'", 2) end,
|
__newindex = function() error("cannot create new or write into existing fields of 'gv'", 2) end,
|
||||||
}
|
}
|
||||||
setmtonce(gv, tmpmt)
|
defs_c.setmtonce(gv, tmpmt)
|
||||||
|
|
||||||
---- indirect C array access ----
|
---- indirect C array access ----
|
||||||
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', 2)
|
|
||||||
end,
|
|
||||||
|
|
||||||
__newindex = function(tab, key, val) error('cannot write directly to sector[] struct', 2) end,
|
|
||||||
}
|
|
||||||
sector = setmtonce({}, tmpmt)
|
|
||||||
|
|
||||||
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', 2)
|
|
||||||
end,
|
|
||||||
|
|
||||||
__newindex = function(tab, key, val) error('cannot write directly to wall[] struct', 2) end,
|
|
||||||
}
|
|
||||||
wall = setmtonce({}, tmpmt)
|
|
||||||
|
|
||||||
local tmpmt = {
|
local tmpmt = {
|
||||||
__index = function(tab, key)
|
__index = function(tab, key)
|
||||||
if (key >= 0 and key < ffiC.playerswhenstarted) then
|
if (key >= 0 and key < ffiC.playerswhenstarted) then
|
||||||
|
@ -1017,126 +838,37 @@ local tmpmt = {
|
||||||
|
|
||||||
__newindex = function(tab, key, val) error('cannot write directly to player[] struct', 2) end,
|
__newindex = function(tab, key, val) error('cannot write directly to player[] struct', 2) end,
|
||||||
}
|
}
|
||||||
player = setmtonce({}, tmpmt)
|
player = defs_c.setmtonce({}, tmpmt)
|
||||||
|
|
||||||
-- create a safe indirection for an ffi.C array
|
-- structs
|
||||||
local function creategtab(ctab, maxidx, name)
|
sector = defs_c.sector;
|
||||||
local tab = {}
|
wall = defs_c.wall;
|
||||||
local tmpmt = {
|
sprite = defs_c.sprite
|
||||||
__index = function(tab, key)
|
spriteext = defs_c.spriteext
|
||||||
if (key>=0 and key < maxidx) then
|
|
||||||
return ctab[key]
|
|
||||||
end
|
|
||||||
error('out-of-bounds '..name..' read access', 2)
|
|
||||||
end,
|
|
||||||
__newindex = function(tab, key, val)
|
|
||||||
error('cannot write directly to '..name, 2)
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
return setmtonce(tab, tmpmt)
|
headspritesect = defs_c.headspritesect
|
||||||
end
|
headspritestat = defs_c.headspritestat
|
||||||
|
nextspritesect = defs_c.nextspritesect
|
||||||
|
nextspritestat = defs_c.nextspritestat
|
||||||
|
prevspritesect = defs_c.prevspritesect
|
||||||
|
prevspritestat = defs_c.prevspritestat
|
||||||
|
|
||||||
sprite = creategtab(ffiC.sprite, ffiC.MAXSPRITES, 'sprite[] struct')
|
actor = defs_c.creategtab(ffiC.actor, ffiC.MAXSPRITES, 'actor[]')
|
||||||
spriteext = creategtab(ffiC.spriteext, ffiC.MAXSPRITES, 'spriteext[] struct')
|
|
||||||
headspritesect = creategtab(ffiC.headspritesect, ffiC.MAXSECTORS, 'headspritesect[]')
|
-- functions
|
||||||
-- TODO: allow sprite freelist access via the status list for CON compatibility?
|
spritesofsect = defs_c.spritesofsect
|
||||||
headspritestat = creategtab(ffiC.headspritestat, ffiC.MAXSTATUS, 'headspritestat[]')
|
spritesofstat = defs_c.spritesofstat
|
||||||
nextspritesect = creategtab(ffiC.nextspritesect, ffiC.MAXSPRITES, 'nextspritesect[]')
|
sectorsofbunch = defs_c.sectorsofbunch
|
||||||
nextspritestat = creategtab(ffiC.nextspritestat, ffiC.MAXSPRITES, 'nextspritestat[]')
|
|
||||||
prevspritesect = creategtab(ffiC.prevspritesect, ffiC.MAXSPRITES, 'prevspritesect[]')
|
getbunch = defs_c.getbunch
|
||||||
prevspritestat = creategtab(ffiC.prevspritestat, ffiC.MAXSPRITES, 'prevspritestat[]')
|
|
||||||
|
hitscan = defs_c.hitscan
|
||||||
|
|
||||||
actor = creategtab(ffiC.actor, ffiC.MAXSPRITES, 'actor[]')
|
|
||||||
|
|
||||||
function TEMP_getvollev() -- REMOVE
|
function TEMP_getvollev() -- REMOVE
|
||||||
return ffiC.ud.volume_number+1, ffiC.ud.level_number+1
|
return ffiC.ud.volume_number+1, ffiC.ud.level_number+1
|
||||||
end
|
end
|
||||||
|
|
||||||
---- 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 end
|
|
||||||
end
|
|
||||||
|
|
||||||
function spritesofsect(sect)
|
|
||||||
if (sect < 0 or sect >= ffiC.numsectors) then
|
|
||||||
error("passed invalid sectnum to spritesofsect iterator", 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
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 end
|
|
||||||
end
|
|
||||||
|
|
||||||
function spritesofstat(stat)
|
|
||||||
if (stat < 0 or stat >= ffiC.MAXSTATUS) then
|
|
||||||
error("passed invalid statnum to spritesofstat iterator", 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
return iter_spritesofstat, stat, -1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- TROR iterators
|
|
||||||
local function iter_sectorsofbunch(cf, i)
|
|
||||||
if (i < 0) then
|
|
||||||
i = ffiC.headsectbunch[cf][-i-1];
|
|
||||||
else
|
|
||||||
i = ffiC.nextsectbunch[cf][i];
|
|
||||||
end
|
|
||||||
|
|
||||||
if (i >= 0) then return i end
|
|
||||||
end
|
|
||||||
|
|
||||||
function sectorsofbunch(bunchnum, cf)
|
|
||||||
if (bunchnum < 0 or bunchnum >= ffiC.numyaxbunches) then
|
|
||||||
error("passed invalid bunchnum to sectorsofbunch iterator", 2)
|
|
||||||
end
|
|
||||||
if (cf ~= 0 and cf ~= 1) then
|
|
||||||
error("passed invalid 'cf' to sectorsofbunch iterator, must be 0 or 1", 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
return iter_sectorsofbunch, cf, -bunchnum-1
|
|
||||||
end
|
|
||||||
|
|
||||||
function getbunch(sectnum, cf)
|
|
||||||
if (sectnum < 0 or sectnum >= ffiC.numsectors) then
|
|
||||||
error('passed out-of-bounds sector number'..sectnum, 2)
|
|
||||||
end
|
|
||||||
if (cf ~= 0 and cf ~= 1) then
|
|
||||||
error("passed invalid 'cf' to getbunch, must be 0 or 1", 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
return ffiC.yax_getbunch(sectnum, cf)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
---=== Engine functions, wrapped for Lua convenience ===---
|
|
||||||
-- returns a hitdata_ct
|
|
||||||
function hitscan(x,y,z, sectnum, vx,vy,vz, cliptype)
|
|
||||||
if (sectnum < 0 or sectnum >= ffiC.numsectors) then
|
|
||||||
error('passed out-of-bounds sector number'..sectnum, 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
local vec = vec3_ct(x,y,z)
|
|
||||||
local hitdata = hitdata_ct()
|
|
||||||
|
|
||||||
ffiC.hitscan(vec, sectnum, vx,vy,vz, hitdata, cliptype)
|
|
||||||
return hitdata
|
|
||||||
end
|
|
||||||
|
|
||||||
---=== Game variables ===---
|
---=== Game variables ===---
|
||||||
|
|
||||||
|
|
324
polymer/eduke32/source/lunatic/defs_common.lua
Normal file
324
polymer/eduke32/source/lunatic/defs_common.lua
Normal file
|
@ -0,0 +1,324 @@
|
||||||
|
|
||||||
|
-- This file contains LuaJIT definitions of stuff that's common to the game and
|
||||||
|
-- editor. The 'decl' is expected to be defined in the global environment.
|
||||||
|
|
||||||
|
local ffi = require("ffi")
|
||||||
|
local ffiC = ffi.C
|
||||||
|
|
||||||
|
local error = error
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
|
local decl = decl
|
||||||
|
|
||||||
|
|
||||||
|
module(...)
|
||||||
|
|
||||||
|
|
||||||
|
--== Core engine structs ==--
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t x, y, z;
|
||||||
|
} vec3_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vec3_t pos;
|
||||||
|
int16_t sprite, wall, sect;
|
||||||
|
} hitdata_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char r,g,b,f;
|
||||||
|
} palette_t;
|
||||||
|
#pragma pack(pop)
|
||||||
|
]]
|
||||||
|
|
||||||
|
local vec3_ct = ffi.typeof("vec3_t")
|
||||||
|
local hitdata_ct = ffi.typeof("hitdata_t")
|
||||||
|
|
||||||
|
-- TODO: add 'const'
|
||||||
|
ffi.cdef[[int32_t engine_main_arrays_are_static, engine_v8;]]
|
||||||
|
|
||||||
|
|
||||||
|
--== Engine data and functions ==--
|
||||||
|
|
||||||
|
|
||||||
|
-- NOTE TO SELF: This is not C, never EVER write
|
||||||
|
-- if (x)
|
||||||
|
-- when checking a C variable x for 'thuthiness'
|
||||||
|
if (ffiC.engine_main_arrays_are_static ~= 0) then
|
||||||
|
decl[[
|
||||||
|
sectortype sector[];
|
||||||
|
walltype wall[];
|
||||||
|
spritetype sprite[];
|
||||||
|
spriteext_t spriteext[];
|
||||||
|
]]
|
||||||
|
else
|
||||||
|
decl[[
|
||||||
|
sectortype *sector;
|
||||||
|
walltype *wall;
|
||||||
|
spritetype *sprite;
|
||||||
|
spriteext_t *spriteext;
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
if (ffiC.engine_v8 == 0) then
|
||||||
|
-- V7
|
||||||
|
ffi.cdef[[
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MAXSECTORS = 1024,
|
||||||
|
MAXWALLS = 8192,
|
||||||
|
MAXSPRITES = 4096,
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
else
|
||||||
|
-- V8
|
||||||
|
ffi.cdef[[
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MAXSECTORS = 4096,
|
||||||
|
MAXWALLS = 16384,
|
||||||
|
MAXSPRITES = 16384,
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
ffi.cdef[[
|
||||||
|
enum {
|
||||||
|
MAXSTATUS = 1024,
|
||||||
|
MAXTILES = 30720,
|
||||||
|
|
||||||
|
MAXBUNCHES = 256,
|
||||||
|
CEILING = 0,
|
||||||
|
FLOOR = 1,
|
||||||
|
|
||||||
|
CLIPMASK0 = (1<<16)+1, // blocking
|
||||||
|
CLIPMASK1 = (256<<16)+64, // hittable
|
||||||
|
};
|
||||||
|
]]
|
||||||
|
|
||||||
|
ffi.cdef[[
|
||||||
|
const int16_t numsectors, numwalls;
|
||||||
|
const int32_t numyaxbunches;
|
||||||
|
const int32_t totalclock;
|
||||||
|
const int32_t xdim, ydim;
|
||||||
|
]]
|
||||||
|
|
||||||
|
decl[[
|
||||||
|
const int16_t headspritesect[MAXSECTORS+1], headspritestat[MAXSTATUS+1];
|
||||||
|
const int16_t prevspritesect[MAXSPRITES], prevspritestat[MAXSPRITES];
|
||||||
|
const int16_t nextspritesect[MAXSPRITES], nextspritestat[MAXSPRITES];
|
||||||
|
|
||||||
|
const int16_t headsectbunch[2][MAXBUNCHES], nextsectbunch[2][MAXSECTORS];
|
||||||
|
|
||||||
|
int16_t yax_getbunch(int16_t i, int16_t cf);
|
||||||
|
|
||||||
|
int32_t hitscan(const vec3_t *sv, int16_t sectnum, int32_t vx, int32_t vy, int32_t vz,
|
||||||
|
hitdata_t *hitinfo, uint32_t cliptype);
|
||||||
|
|
||||||
|
void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
|
||||||
|
int8_t dashade, char dapalnum, int32_t dastat,
|
||||||
|
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2);
|
||||||
|
]]
|
||||||
|
|
||||||
|
-- misc. functions
|
||||||
|
ffi.cdef[[
|
||||||
|
int32_t ksqrt(uint32_t num);
|
||||||
|
double gethitickms(void);
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
---=== Restricted access to C variables from Lunatic ===---
|
||||||
|
|
||||||
|
-- set metatable and forbid setting it further
|
||||||
|
function setmtonce(tab, mt)
|
||||||
|
mt.__metatable = true
|
||||||
|
return setmetatable(tab, mt)
|
||||||
|
end
|
||||||
|
|
||||||
|
---- indirect C array access ----
|
||||||
|
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', 2)
|
||||||
|
end,
|
||||||
|
|
||||||
|
__newindex = function(tab, key, val) error('cannot write directly to sector[] struct', 2) end,
|
||||||
|
}
|
||||||
|
sector = setmtonce({}, tmpmt)
|
||||||
|
|
||||||
|
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', 2)
|
||||||
|
end,
|
||||||
|
|
||||||
|
__newindex = function(tab, key, val) error('cannot write directly to wall[] struct', 2) end,
|
||||||
|
}
|
||||||
|
wall = setmtonce({}, tmpmt)
|
||||||
|
|
||||||
|
-- create a safe indirection for an ffi.C array
|
||||||
|
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', 2)
|
||||||
|
end,
|
||||||
|
__newindex = function(tab, key, val)
|
||||||
|
error('cannot write directly to '..name, 2)
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmtonce(tab, tmpmt)
|
||||||
|
end
|
||||||
|
|
||||||
|
sprite = creategtab(ffiC.sprite, ffiC.MAXSPRITES, 'sprite[] struct')
|
||||||
|
spriteext = creategtab(ffiC.spriteext, ffiC.MAXSPRITES, 'spriteext[] struct')
|
||||||
|
headspritesect = creategtab(ffiC.headspritesect, ffiC.MAXSECTORS, 'headspritesect[]')
|
||||||
|
-- TODO: allow sprite freelist access via the status list for CON compatibility?
|
||||||
|
headspritestat = creategtab(ffiC.headspritestat, ffiC.MAXSTATUS, 'headspritestat[]')
|
||||||
|
nextspritesect = creategtab(ffiC.nextspritesect, ffiC.MAXSPRITES, 'nextspritesect[]')
|
||||||
|
nextspritestat = creategtab(ffiC.nextspritestat, ffiC.MAXSPRITES, 'nextspritestat[]')
|
||||||
|
prevspritesect = creategtab(ffiC.prevspritesect, ffiC.MAXSPRITES, 'prevspritesect[]')
|
||||||
|
prevspritestat = creategtab(ffiC.prevspritestat, ffiC.MAXSPRITES, 'prevspritestat[]')
|
||||||
|
|
||||||
|
--== 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 end
|
||||||
|
end
|
||||||
|
|
||||||
|
function spritesofsect(sect)
|
||||||
|
if (sect < 0 or sect >= ffiC.numsectors) then
|
||||||
|
error("passed invalid sectnum to spritesofsect iterator", 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
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 end
|
||||||
|
end
|
||||||
|
|
||||||
|
function spritesofstat(stat)
|
||||||
|
if (stat < 0 or stat >= ffiC.MAXSTATUS) then
|
||||||
|
error("passed invalid statnum to spritesofstat iterator", 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
return iter_spritesofstat, stat, -1
|
||||||
|
end
|
||||||
|
|
||||||
|
--== TROR iterators ==--
|
||||||
|
local function iter_sectorsofbunch(cf, i)
|
||||||
|
if (i < 0) then
|
||||||
|
i = ffiC.headsectbunch[cf][-i-1];
|
||||||
|
else
|
||||||
|
i = ffiC.nextsectbunch[cf][i];
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i >= 0) then return i end
|
||||||
|
end
|
||||||
|
|
||||||
|
function sectorsofbunch(bunchnum, cf)
|
||||||
|
if (bunchnum < 0 or bunchnum >= ffiC.numyaxbunches) then
|
||||||
|
error("passed invalid bunchnum to sectorsofbunch iterator", 2)
|
||||||
|
end
|
||||||
|
if (cf ~= 0 and cf ~= 1) then
|
||||||
|
error("passed invalid 'cf' to sectorsofbunch iterator, must be 0 or 1", 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
return iter_sectorsofbunch, cf, -bunchnum-1
|
||||||
|
end
|
||||||
|
|
||||||
|
function getbunch(sectnum, cf)
|
||||||
|
if (sectnum < 0 or sectnum >= ffiC.numsectors) then
|
||||||
|
error('passed out-of-bounds sector number'..sectnum, 2)
|
||||||
|
end
|
||||||
|
if (cf ~= 0 and cf ~= 1) then
|
||||||
|
error("passed invalid 'cf' to getbunch, must be 0 or 1", 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
return ffiC.yax_getbunch(sectnum, cf)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---=== Engine functions, wrapped for Lua convenience ===---
|
||||||
|
-- returns a hitdata_ct
|
||||||
|
function hitscan(x,y,z, sectnum, vx,vy,vz, cliptype)
|
||||||
|
if (sectnum < 0 or sectnum >= ffiC.numsectors) then
|
||||||
|
error('passed out-of-bounds sector number'..sectnum, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local vec = vec3_ct(x,y,z)
|
||||||
|
local hitdata = hitdata_ct()
|
||||||
|
|
||||||
|
ffiC.hitscan(vec, sectnum, vx,vy,vz, hitdata, cliptype)
|
||||||
|
return hitdata
|
||||||
|
end
|
31
polymer/eduke32/source/lunatic/defs_m32.ilua
Normal file
31
polymer/eduke32/source/lunatic/defs_m32.ilua
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
-- INTERNAL
|
||||||
|
-- definitions of BUILD and game types for the Lunatic Interpreter
|
||||||
|
|
||||||
|
local ffi = require("ffi")
|
||||||
|
local ffiC = ffi.C
|
||||||
|
|
||||||
|
--== First, load the definitions common to the game's and editor's Lua interface.
|
||||||
|
decl = ffi.cdef
|
||||||
|
local defs_c = require("defs_common")
|
||||||
|
|
||||||
|
-- structs
|
||||||
|
sector = defs_c.sector;
|
||||||
|
wall = defs_c.wall;
|
||||||
|
sprite = defs_c.sprite
|
||||||
|
spriteext = defs_c.spriteext
|
||||||
|
|
||||||
|
headspritesect = defs_c.headspritesect
|
||||||
|
headspritestat = defs_c.headspritestat
|
||||||
|
nextspritesect = defs_c.nextspritesect
|
||||||
|
nextspritestat = defs_c.nextspritestat
|
||||||
|
prevspritesect = defs_c.prevspritesect
|
||||||
|
prevspritestat = defs_c.prevspritestat
|
||||||
|
|
||||||
|
-- functions
|
||||||
|
spritesofsect = defs_c.spritesofsect
|
||||||
|
spritesofstat = defs_c.spritesofstat
|
||||||
|
sectorsofbunch = defs_c.sectorsofbunch
|
||||||
|
|
||||||
|
getbunch = defs_c.getbunch
|
||||||
|
|
||||||
|
hitscan = defs_c.hitscan
|
|
@ -11,7 +11,9 @@
|
||||||
|
|
||||||
#include "gameexec.h"
|
#include "gameexec.h"
|
||||||
#include "gamedef.h" // EventNames[], MAXEVENTS
|
#include "gamedef.h" // EventNames[], MAXEVENTS
|
||||||
|
|
||||||
#include "lunatic.h"
|
#include "lunatic.h"
|
||||||
|
#include "lunatic_priv.h"
|
||||||
|
|
||||||
// this serves two purposes:
|
// this serves two purposes:
|
||||||
// the values as booleans and the addresses as keys to the Lua registry
|
// the values as booleans and the addresses as keys to the Lua registry
|
||||||
|
@ -86,16 +88,6 @@ void El_PrintTimes(void)
|
||||||
OSD_Printf(" },\n}\n");
|
OSD_Printf(" },\n}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_and_register_function(lua_State *L, void *keyaddr)
|
|
||||||
{
|
|
||||||
luaL_checktype(L, -1, LUA_TFUNCTION);
|
|
||||||
|
|
||||||
lua_pushlightuserdata(L, keyaddr); // 3, push address
|
|
||||||
lua_pushvalue(L, -2); // 4, push copy of lua function
|
|
||||||
|
|
||||||
lua_settable(L, LUA_REGISTRYINDEX); // "registry[keyaddr] = <lua function>", pop 2
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 0: success, <0: failure
|
// 0: success, <0: failure
|
||||||
int32_t El_CreateState(El_State *estate, const char *name)
|
int32_t El_CreateState(El_State *estate, const char *name)
|
||||||
|
@ -119,12 +111,7 @@ int32_t El_CreateState(El_State *estate, const char *name)
|
||||||
luaopen_lpeg(L);
|
luaopen_lpeg(L);
|
||||||
lua_pop(L, lua_gettop(L)); // pop off whatever lpeg leaves on the stack
|
lua_pop(L, lua_gettop(L)); // pop off whatever lpeg leaves on the stack
|
||||||
|
|
||||||
// get debug.traceback
|
setup_debug_traceback(L);
|
||||||
lua_getglobal(L, "debug");
|
|
||||||
lua_getfield(L, -1, "traceback");
|
|
||||||
Bassert(lua_isfunction(L, -1));
|
|
||||||
check_and_register_function(L, &debug_traceback_key);
|
|
||||||
lua_pop(L, 2);
|
|
||||||
|
|
||||||
// create misc. global functions in the Lua state
|
// create misc. global functions in the Lua state
|
||||||
lua_pushcfunction(L, SetEvent_luacf);
|
lua_pushcfunction(L, SetEvent_luacf);
|
||||||
|
@ -157,88 +144,7 @@ void El_DestroyState(El_State *estate)
|
||||||
// 4: runtime error while executing lua file
|
// 4: runtime error while executing lua file
|
||||||
int32_t El_RunOnce(El_State *estate, const char *fn)
|
int32_t El_RunOnce(El_State *estate, const char *fn)
|
||||||
{
|
{
|
||||||
int32_t fid, flen, i;
|
return lunatic_run_once(estate->L, fn, estate->name);
|
||||||
char *buf;
|
|
||||||
|
|
||||||
lua_State *const L = estate->L;
|
|
||||||
|
|
||||||
fid = kopen4load(fn, 0); // TODO: g_loadFromGroupOnly, kopen4loadfrommod ?
|
|
||||||
|
|
||||||
if (fid < 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
flen = kfilelength(fid);
|
|
||||||
if (flen == 0)
|
|
||||||
return 0; // empty script ...
|
|
||||||
|
|
||||||
buf = Bmalloc(flen+1);
|
|
||||||
if (!buf)
|
|
||||||
{
|
|
||||||
kclose(fid);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = kread(fid, buf, flen);
|
|
||||||
kclose(fid);
|
|
||||||
|
|
||||||
if (i != flen)
|
|
||||||
{
|
|
||||||
Bfree(buf);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[flen] = 0;
|
|
||||||
|
|
||||||
// -- lua --
|
|
||||||
Bassert(lua_gettop(L)==0);
|
|
||||||
|
|
||||||
// get debug.traceback
|
|
||||||
lua_pushlightuserdata(L, &debug_traceback_key);
|
|
||||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
|
||||||
Bassert(lua_isfunction(L, -1));
|
|
||||||
|
|
||||||
i = luaL_loadstring(L, buf);
|
|
||||||
Bassert(lua_gettop(L)==2);
|
|
||||||
Bfree(buf);
|
|
||||||
|
|
||||||
if (i == LUA_ERRMEM)
|
|
||||||
{
|
|
||||||
lua_pop(L, 2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == LUA_ERRSYNTAX)
|
|
||||||
{
|
|
||||||
OSD_Printf("state \"%s\" syntax error: %s\n", estate->name,
|
|
||||||
lua_tostring(L, -1)); // get err msg
|
|
||||||
lua_pop(L, 2); // pop errmsg and debug.traceback
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- call the lua chunk! --
|
|
||||||
|
|
||||||
i = lua_pcall(L, 0, 0, -2);
|
|
||||||
Bassert(lua_gettop(L) == 1+!!i);
|
|
||||||
Bassert(i != LUA_ERRERR); // we expect debug.traceback not to fail
|
|
||||||
|
|
||||||
if (i == LUA_ERRMEM) // XXX: should be more sophisticated. Clean up stack? Do GC?
|
|
||||||
{
|
|
||||||
lua_pop(L, 2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == LUA_ERRRUN)
|
|
||||||
{
|
|
||||||
Bassert(lua_type(L, -1)==LUA_TSTRING);
|
|
||||||
OSD_Printf("state \"%s\" runtime error: %s\n", estate->name,
|
|
||||||
lua_tostring(L, -1)); // get err msg
|
|
||||||
lua_pop(L, 2); // pop errmsg and debug.traceback
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
35
polymer/eduke32/source/lunatic/lunatic_m32.c
Normal file
35
polymer/eduke32/source/lunatic/lunatic_m32.c
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* The Lunatic Interpreter, part of EDuke32/Mapster32 */
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
|
||||||
|
#include "lunatic_m32.h"
|
||||||
|
#include "lunatic_priv.h"
|
||||||
|
|
||||||
|
|
||||||
|
Em_State *Em_CreateState(void)
|
||||||
|
{
|
||||||
|
lua_State *L = luaL_newstate();
|
||||||
|
|
||||||
|
if (L == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
luaL_openlibs(L);
|
||||||
|
setup_debug_traceback(L);
|
||||||
|
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -1: alloc failure
|
||||||
|
// 0: success
|
||||||
|
// 1: didn't find file
|
||||||
|
// 2: couldn't read whole file
|
||||||
|
// 3: syntax error in lua file
|
||||||
|
// 4: runtime error while executing lua file
|
||||||
|
int32_t Em_RunOnce(Em_State *L, const char *fn)
|
||||||
|
{
|
||||||
|
return lunatic_run_once(L, fn, "test");
|
||||||
|
}
|
19
polymer/eduke32/source/lunatic/lunatic_m32.h
Normal file
19
polymer/eduke32/source/lunatic/lunatic_m32.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef EDUKE32_LUNATIC_M32_H_
|
||||||
|
#define EDUKE32_LUNATIC_M32_H_
|
||||||
|
|
||||||
|
#include <lua.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef lua_State Em_State;
|
||||||
|
|
||||||
|
|
||||||
|
Em_State *Em_CreateState(void);
|
||||||
|
|
||||||
|
static inline void Em_DestroyState(Em_State *L)
|
||||||
|
{
|
||||||
|
lua_close(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Em_RunOnce(Em_State *L, const char *fn);
|
||||||
|
|
||||||
|
#endif
|
117
polymer/eduke32/source/lunatic/lunatic_priv.h
Normal file
117
polymer/eduke32/source/lunatic/lunatic_priv.h
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/* Private, game/editor-common Lunatic routines. */
|
||||||
|
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
|
||||||
|
#include "cache1d.h"
|
||||||
|
#include "osd.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Lua-registry key for debug.traceback
|
||||||
|
static uint8_t debug_traceback_key;
|
||||||
|
|
||||||
|
static void check_and_register_function(lua_State *L, void *regkeyaddr)
|
||||||
|
{
|
||||||
|
luaL_checktype(L, -1, LUA_TFUNCTION);
|
||||||
|
|
||||||
|
lua_pushlightuserdata(L, regkeyaddr); // 3, push address
|
||||||
|
lua_pushvalue(L, -2); // 4, push copy of lua function
|
||||||
|
|
||||||
|
lua_settable(L, LUA_REGISTRYINDEX); // "registry[regkeyaddr] = <lua function>", pop 2
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_debug_traceback(lua_State *L)
|
||||||
|
{
|
||||||
|
// get debug.traceback
|
||||||
|
lua_getglobal(L, "debug");
|
||||||
|
lua_getfield(L, -1, "traceback");
|
||||||
|
Bassert(lua_isfunction(L, -1));
|
||||||
|
check_and_register_function(L, &debug_traceback_key);
|
||||||
|
lua_pop(L, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t lunatic_run_once(lua_State *L, const char *fn, const char *statename)
|
||||||
|
{
|
||||||
|
int32_t fid, flen, i;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
fid = kopen4load(fn, 0); // TODO: g_loadFromGroupOnly, kopen4loadfrommod ?
|
||||||
|
|
||||||
|
if (fid < 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
flen = kfilelength(fid);
|
||||||
|
if (flen == 0)
|
||||||
|
return 0; // empty script ...
|
||||||
|
|
||||||
|
buf = Bmalloc(flen+1);
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
kclose(fid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = kread(fid, buf, flen);
|
||||||
|
kclose(fid);
|
||||||
|
|
||||||
|
if (i != flen)
|
||||||
|
{
|
||||||
|
Bfree(buf);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[flen] = 0;
|
||||||
|
|
||||||
|
// -- lua --
|
||||||
|
Bassert(lua_gettop(L)==0);
|
||||||
|
|
||||||
|
// get debug.traceback
|
||||||
|
lua_pushlightuserdata(L, &debug_traceback_key);
|
||||||
|
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||||
|
Bassert(lua_isfunction(L, -1));
|
||||||
|
|
||||||
|
i = luaL_loadstring(L, buf);
|
||||||
|
Bassert(lua_gettop(L)==2);
|
||||||
|
Bfree(buf);
|
||||||
|
|
||||||
|
if (i == LUA_ERRMEM)
|
||||||
|
{
|
||||||
|
lua_pop(L, 2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == LUA_ERRSYNTAX)
|
||||||
|
{
|
||||||
|
OSD_Printf("state \"%s\" syntax error: %s\n", statename,
|
||||||
|
lua_tostring(L, -1)); // get err msg
|
||||||
|
lua_pop(L, 2); // pop errmsg and debug.traceback
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- call the lua chunk! --
|
||||||
|
|
||||||
|
i = lua_pcall(L, 0, 0, -2);
|
||||||
|
Bassert(lua_gettop(L) == 1+!!i);
|
||||||
|
Bassert(i != LUA_ERRERR); // we expect debug.traceback not to fail
|
||||||
|
|
||||||
|
if (i == LUA_ERRMEM) // XXX: should be more sophisticated. Clean up stack? Do GC?
|
||||||
|
{
|
||||||
|
lua_pop(L, 2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == LUA_ERRRUN)
|
||||||
|
{
|
||||||
|
int32_t stringp = (lua_type(L, -1)==LUA_TSTRING);
|
||||||
|
|
||||||
|
// get error message if possible
|
||||||
|
OSD_Printf("state \"%s\" runtime error: %s\n", statename,
|
||||||
|
stringp ? lua_tostring(L, -1) : "??? (errmsg not a string)");
|
||||||
|
lua_pop(L, 2); // pop errmsg and debug.traceback
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue