From bcd0d80bb537129c2e445e77d4aba2982d768fc2 Mon Sep 17 00:00:00 2001 From: helixhorned Date: Tue, 20 Sep 2011 19:12:24 +0000 Subject: [PATCH] First Lunatic development bits. git-svn-id: https://svn.eduke32.com/eduke32@2034 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/Makefile | 18 +++- polymer/eduke32/Makefile.deps | 2 + polymer/eduke32/source/game.c | 25 +++++ polymer/eduke32/source/lunatic/defs.ilua | 101 +++++++++++++++++++ polymer/eduke32/source/lunatic/dynsymlist | 8 ++ polymer/eduke32/source/lunatic/lunatic.c | 115 ++++++++++++++++++++++ polymer/eduke32/source/lunatic/lunatic.h | 22 +++++ polymer/eduke32/source/lunatic/test.elua | 21 ++++ polymer/eduke32/source/premap.c | 18 ++++ 9 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 polymer/eduke32/source/lunatic/defs.ilua create mode 100644 polymer/eduke32/source/lunatic/dynsymlist create mode 100644 polymer/eduke32/source/lunatic/lunatic.c create mode 100644 polymer/eduke32/source/lunatic/lunatic.h create mode 100644 polymer/eduke32/source/lunatic/test.elua diff --git a/polymer/eduke32/Makefile b/polymer/eduke32/Makefile index e719ca707..8ba192e6a 100644 --- a/polymer/eduke32/Makefile +++ b/polymer/eduke32/Makefile @@ -13,6 +13,8 @@ else #DXROOT=c:/sdks/directx/dx8 endif +# Lunatic development, do not touch! +LUNATIC=0 # Build locations SRC=source @@ -39,6 +41,8 @@ OURCFLAGS=$(BASECFLAGS) \ OURCXXFLAGS=$(BASECXXFLAGS) NASMFLAGS=$(BASEASFLAGS) +MISCLINKOPTS= + JAUDIOLIBDIR=$(SRC)/jaudiolib JAUDIOLIB=libjfaudiolib.a @@ -111,6 +115,15 @@ EDITOROBJS=$(OBJ)/astub.$o \ ifneq ($(USE_LIBVPX),0) GAMEOBJS+= $(OBJ)/animvpx.$o endif + +# Lunatic devel, currently linux-only +ifneq (0,$(LUNATIC)) + OURCFLAGS+= -I/usr/local/include/luajit-2.0 -I$(SRC)/lunatic -DLUNATIC_ENABLE + LIBS+= -L/usr/local/lib -lluajit-5.1 + GAMEOBJS+= $(OBJ)/lunatic.$o + MISCLINKOPTS+= -Wl,--dynamic-list=$(SRC)/lunatic/dynsymlist +endif + # PLATFORM SPECIFIC SETTINGS ifeq ($(PLATFORM),LINUX) @@ -177,7 +190,6 @@ endif OURCFLAGS+= $(BUILDCFLAGS) OURCXXFLAGS+= $(BUILDCFLAGS) -MISCLINKOPTS= ifeq ($(PLATFORM),WINDOWS) MISCLINKOPTS+= -Wl,--large-address-aware endif @@ -270,6 +282,10 @@ $(OBJ)/%.$o: $(SRC)/%.c $(COMPILE_STATUS) if $(CC) $(CFLAGS) $(OURCFLAGS) -c $< -o $@; then $(COMPILE_OK); else $(COMPILE_FAILED); fi +$(OBJ)/%.$o: $(SRC)/lunatic/%.c + $(COMPILE_STATUS) + if $(CC) $(CFLAGS) $(OURCFLAGS) -c $< -o $@; then $(COMPILE_OK); else $(COMPILE_FAILED); fi + $(OBJ)/%.$o: Apple/%.m $(COMPILE_STATUS) if $(CC) $(CFLAGS) $(OURCFLAGS) -c $< -o $@; then $(COMPILE_OK); else $(COMPILE_FAILED); fi diff --git a/polymer/eduke32/Makefile.deps b/polymer/eduke32/Makefile.deps index 099337068..c84994a4b 100644 --- a/polymer/eduke32/Makefile.deps +++ b/polymer/eduke32/Makefile.deps @@ -55,6 +55,8 @@ $(OBJ)/osdcmds.$o: $(SRC)/osdcmds.c $(INC)/osdcmds.h $(EINC)/osd.h $(duke3d_h) $(OBJ)/animvpx.$o: $(SRC)/animvpx.c $(SRC)/animvpx.h $(duke3d_h) $(EINC)/glbuild.h +$(OBJ)/lunatic/lunatic.$o: $(SRC)/lunatic/lunatic.c $(SRC)/lunatic/lunatic.h $(EINC)/cache1d.h $(EINC)/osd.h + # editor objects m32_script_hs=$(EINC)/m32script.h $(SRC)/m32def.h $(OBJ)/astub.$o: $(SRC)/astub.c \ diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index ca8e132e8..1fa0dcd1d 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -52,6 +52,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "anim.h" #include "demo.h" +#ifdef LUNATIC_ENABLE +# include "lunatic.h" +#endif + #define ROTATESPRITE_MAX 2048 #if KRANDDEBUG @@ -130,6 +134,10 @@ int g_scriptModulesNum = 0; char **g_defModules = NULL; int g_defModulesNum = 0; +#ifdef LUNATIC_ENABLE +El_State g_ElState; +#endif + extern int32_t lastvisinc; int32_t g_Shareware = 0; @@ -10221,6 +10229,23 @@ CLEAN_DIRECTORY: OSD_Exec("autoexec.cfg"); +#ifdef LUNATIC_ENABLE + i = El_CreateState(&g_ElState, "test"); + if (i) + { + initprintf("Lunatic: Error initializing global ELua state (code %d)\n", i); + } + else + { + i = El_RunOnce(&g_ElState, "defs.ilua"); + if (i) + { + initprintf("Lunatic: Error preparing global ELua state (code %d)\n", i); + El_DestroyState(&g_ElState); + } + } +#endif + if (g_networkMode != NET_DEDICATED_SERVER) { if (setgamemode(ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP) < 0) diff --git a/polymer/eduke32/source/lunatic/defs.ilua b/polymer/eduke32/source/lunatic/defs.ilua new file mode 100644 index 000000000..0f00221ae --- /dev/null +++ b/polymer/eduke32/source/lunatic/defs.ilua @@ -0,0 +1,101 @@ +-- 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; + int16_t point2, nextwall, nextsector, 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; + int16_t sectnum, statnum; + int16_t ang, owner, xvel, yvel, zvel; + int16_t lotag, hitag, extra; +} spritetype; +#pragma pack(pop) +]] + +ffi.cdef[[ +sectortype *sector; +walltype *wall; +spritetype *sprite; + +const int16_t numsectors, numwalls; +]] + +-- + +sector = {} +local tmpmt = { + __index = function(tab, key) + if (key >= 0 and key < ffi.C.numsectors) then return ffi.C.sector[key] end + error('out-of-bounds sector[] read access') + end, + + __newindex = function(tab, key, val) error('cannot write to sector[] structs directly') end +} +setmetatable(sector, tmpmt) + +wall = {} +local tmpmt = { + __index = function(tab, key) + if (key >= 0 and key < ffi.C.numwalls) then return ffi.C.wall[key] end + error('out-of-bounds wall[] read access') + end, + + __newindex = function(tab, key, val) error('cannot write to wall[] structs directly') end +} +setmetatable(wall, tmpmt) + +sprite = {} +local tmpmt = { + __index = function(tab, key) + -- MAXSPRITES == 16384 + if (key >= 0 and key < 16384) then return ffi.C.sprite[key] end + error('out-of-bounds sprite[] read access') + end, + + __newindex = function(tab, key, val) error('cannot write to sprite[] structs directly') end +} +setmetatable(sprite, tmpmt) + +-- yes, this does export a couple of other stuff that users ought not see, +-- but without the ffi.cdef declarations, they will just sit there and +-- refuse to be accessed. +gv = ffi.C + +-- nope, this would create two numeric variables with their initial values, but +-- certainly not references to numsectors and numwalls like we want: +--numsectors = ffi.C.numsectors +--numwalls = ffi.C.numwalls diff --git a/polymer/eduke32/source/lunatic/dynsymlist b/polymer/eduke32/source/lunatic/dynsymlist new file mode 100644 index 000000000..40799e312 --- /dev/null +++ b/polymer/eduke32/source/lunatic/dynsymlist @@ -0,0 +1,8 @@ +{ +sector; +wall; +sprite; + +numsectors; +numwalls; +}; diff --git a/polymer/eduke32/source/lunatic/lunatic.c b/polymer/eduke32/source/lunatic/lunatic.c new file mode 100644 index 000000000..73b446968 --- /dev/null +++ b/polymer/eduke32/source/lunatic/lunatic.c @@ -0,0 +1,115 @@ +/* The Lunatic Interpreter, part of EDuke32 */ + +#include + +#include +#include +#include + +#include "cache1d.h" +#include "osd.h" + +#include "lunatic.h" + + +// 0: success, -1: failure +int32_t El_CreateState(El_State *estate, const char *name) +{ + estate->name = Bstrdup(name); + if (!estate->name) + return -1; + + estate->L = luaL_newstate(); + + if (!estate->L) + { + Bfree((char *)estate->name); + estate->name = NULL; + return -1; + } + + luaL_openlibs(estate->L); // XXX: only for internal use and testing, obviously + + return 0; +} + +void El_DestroyState(El_State *estate) +{ + if (!estate->L) + return; + + Bfree((char *)estate->name); + estate->name = NULL; + + lua_close(estate->L); + estate->L = NULL; +} + +// -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 El_RunOnce(El_State *estate, const char *fn) +{ + int32_t fid, flen, i; + char *buf; + + fid = kopen4load(fn, 0); + + 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 -- + + i = luaL_loadstring(estate->L, buf); + Bfree(buf); + + if (i == LUA_ERRMEM) + return -1; + + if (i == LUA_ERRSYNTAX) + { + OSD_Printf("state '%s' syntax error: %s\n", estate->name, lua_tostring(estate->L, 1)); // get err msg + lua_pop(estate->L, 1); + return 3; + } + + // -- call the lua chunk! -- + + i = lua_pcall(estate->L, 0, 0, 0); + if (i == LUA_ERRMEM) // XXX: should be more sophisticated. Clean up stack? Do GC? + return -1; + + if (i == LUA_ERRRUN) + { + OSD_Printf("state '%s' runtime error: %s\n", estate->name, lua_tostring(estate->L, 1)); // get err msg + lua_pop(estate->L, 1); + return 4; + } + + return 0; +} diff --git a/polymer/eduke32/source/lunatic/lunatic.h b/polymer/eduke32/source/lunatic/lunatic.h new file mode 100644 index 000000000..119ffa775 --- /dev/null +++ b/polymer/eduke32/source/lunatic/lunatic.h @@ -0,0 +1,22 @@ +/* The Lunatic Interpreter, part of EDuke32 */ + +#ifndef EDUKE32_LUNATIC_H_ +#define EDUKE32_LUNATIC_H_ + +#include + +typedef struct +{ + const char *name; + lua_State *L; +} El_State; + + +// -- functions -- +int32_t El_CreateState(El_State *estate, const char *name); +void El_DestroyState(El_State *estate); +static inline int32_t El_IsInitialized(const El_State *estate) { return (estate->L != NULL); } +int32_t El_RunOnce(El_State *estate, const char *fn); + + +#endif diff --git a/polymer/eduke32/source/lunatic/test.elua b/polymer/eduke32/source/lunatic/test.elua new file mode 100644 index 000000000..08ed9353f --- /dev/null +++ b/polymer/eduke32/source/lunatic/test.elua @@ -0,0 +1,21 @@ +-- test script for ELua/Lunatic Interpreter + +print('--- ELua Test script ---') + +local i + +print('tweaking sector pals') +for i = 0, gv.numsectors/2 do + sector[i].floorpal = 1; + sector[i].ceilingpal = 2; +end + +print(gv.numsectors) +print(gv.numwalls) + +print('--- end test script ---') + +--sector[-1].ceilingpal = 4; -- this must FAIL! +--sector[0].wallnum = 0; -- as must this +--gv.numsectors = 4 -- and this +--sector[4] = sector[6] -- this is forbidden, too diff --git a/polymer/eduke32/source/premap.c b/polymer/eduke32/source/premap.c index f732f18c2..f4dbd60f3 100644 --- a/polymer/eduke32/source/premap.c +++ b/polymer/eduke32/source/premap.c @@ -35,6 +35,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #endif +#ifdef LUNATIC_ENABLE +# include "lunatic.h" +extern El_State g_ElState; +#endif + extern char pow2char[]; static int32_t g_whichPalForPlayer = 9; @@ -1434,6 +1439,19 @@ static inline void prelevel(char g) wall[j].pal = 4; } } + +#ifdef LUNATIC_ENABLE + if (El_IsInitialized(&g_ElState)) + { + i = El_RunOnce(&g_ElState, "test.elua"); + if (i) + OSD_Printf("Error running the test ELua script (code %d)\n", i); + else + initprintf("ELua test script run ok!\n"); + } + else + initprintf("ELua test script: not inited!\n"); +#endif }