diff --git a/polymer/eduke32/Makefile b/polymer/eduke32/Makefile index 93dea7e6f..fd5ab744d 100644 --- a/polymer/eduke32/Makefile +++ b/polymer/eduke32/Makefile @@ -173,6 +173,7 @@ ifneq (0,$(LUNATIC)) $(OBJ)/luaJIT_BC_dis_x86.$o \ $(OBJ)/luaJIT_BC_dis_x64.$o \ $(OBJ)/luaJIT_BC_savegame.$o \ + $(OBJ)/luaJIT_BC_fs.$o \ # TODO: remove debugging modules from release build # now, take care of having the necessary symbols (sector, wall, etc.) in the diff --git a/polymer/eduke32/source/lunatic/defs.ilua b/polymer/eduke32/source/lunatic/defs.ilua index cc9f03531..d3290b274 100644 --- a/polymer/eduke32/source/lunatic/defs.ilua +++ b/polymer/eduke32/source/lunatic/defs.ilua @@ -63,6 +63,8 @@ function decl(str, ...) ffi.cdef(str, ...) end +lprivate.decl = decl + -- Load the definitions common to the game's and editor's Lua interface. local defs_c = require("defs_common") local cansee = defs_c.cansee @@ -1568,6 +1570,7 @@ local allowed_modules = { stat = require("stat"), bitar = require("bitar"), xmath = require("xmath"), + fs = require("fs"), con = con, } @@ -2180,6 +2183,9 @@ G_.actor = actor G_.projectile = projectile G_.g_tile = g_tile +-- A table that can be used for temporary data when debugging from the OSD. +G_.d = {} + ---=== Lunatic translator setup ===--- diff --git a/polymer/eduke32/source/lunatic/doc/lunacon.txt b/polymer/eduke32/source/lunatic/doc/lunacon.txt index 3fd975221..587c63d14 100644 --- a/polymer/eduke32/source/lunatic/doc/lunacon.txt +++ b/polymer/eduke32/source/lunatic/doc/lunacon.txt @@ -330,7 +330,4 @@ predefined constants. Miscellaneous ^^^^^^^^^^^^^ -* gamevar flags 1024 (```NODEFAULT`'') and 131072 (```NORESET`'') are not - handled -* mapstate handling in savegames is not yet implemented * not LunaCON-specific: `EVENT_INIT` is never reached as it runs before Lua state creation diff --git a/polymer/eduke32/source/lunatic/doc/lunatic.txt b/polymer/eduke32/source/lunatic/doc/lunatic.txt index 9ba2f3bcf..f4d37cf6e 100644 --- a/polymer/eduke32/source/lunatic/doc/lunatic.txt +++ b/polymer/eduke32/source/lunatic/doc/lunatic.txt @@ -97,6 +97,11 @@ CAUTION: If an attempt is made to create a new variable in the global environment or to assign any value to an existing variable, the behavior is undefined. +For convenience of debugging from the command line (using the `lua` OSD +command), the global environment contains a table `d` which is initially +empty. It should only be used to temporarily store values of interest in a +debugging session and should never be referenced from actual script code. + Lua functions ~~~~~~~~~~~~~ @@ -1922,6 +1927,16 @@ run afterwards, possibly modifying the sprite. Returns the index of the spawned sprite on success. +The `fs` module -- virtual file system facilities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +[red]*DRAFT* + +===== `files = fs.listpath(path, mask)` + +Lists file names matching a wildcard `mask` which can be found under `path`. + + ///////////////// APPENDICES FOLLOW ///////////////// diff --git a/polymer/eduke32/source/lunatic/dynsymlist b/polymer/eduke32/source/lunatic/dynsymlist index 4326a4c7c..4f2948936 100644 --- a/polymer/eduke32/source/lunatic/dynsymlist +++ b/polymer/eduke32/source/lunatic/dynsymlist @@ -72,6 +72,10 @@ kclose; kread; klseek; +pathsearchmode; +klistfree; +klistpath; + dist; ldist; @@ -184,6 +188,7 @@ luaJIT_BC_dump; luaJIT_BC_dis_x86; luaJIT_BC_dis_x64; luaJIT_BC_savegame; +luaJIT_BC_fs; rand_jkiss_u32; rand_jkiss_dbl; diff --git a/polymer/eduke32/source/lunatic/fs.lua b/polymer/eduke32/source/lunatic/fs.lua new file mode 100644 index 000000000..58737da80 --- /dev/null +++ b/polymer/eduke32/source/lunatic/fs.lua @@ -0,0 +1,84 @@ +-- Virtual file system facilities for Lunatic + +local ffi = require("ffi") +local C = ffi.C + +local decl = require("lprivate").decl + +local assert = assert +local error = error +local type = type + +---------- + +decl[[ +int32_t pathsearchmode; + +typedef struct _CACHE1D_FIND_REC { + char *name; + int32_t type, source; + struct _CACHE1D_FIND_REC *next, *prev, *usera, *userb; +} CACHE1D_FIND_REC; + +void klistfree(CACHE1D_FIND_REC *rec); +CACHE1D_FIND_REC *klistpath(const char *path, const char *mask, int32_t type); +]] + + +-- The API table +local fs = {} + +local CACHE1D = ffi.new[[ +struct { + static const int FIND_FILE = 1; + static const int FIND_DIR = 2; + static const int FIND_DRIVE = 4; + + static const int OPT_NOSTACK = 0x100; + + // the lower the number, the higher the priority + static const int SOURCE_DRIVE = 0; + static const int SOURCE_CURDIR = 1; + static const int SOURCE_PATH = 2; // + path stack depth + static const int SOURCE_ZIP = 0x7ffffffe; + static const int SOURCE_GRP = 0x7fffffff; +} +]] + +-- files = fs.listpath(path, mask) +-- TODO: filter by 'source' (path, zip and/or grp) +-- TODO: directories too, so that one can list them recursively, for example +function fs.listpath(path, mask) + if (path ~= nil and type(path)~="string") then + error("Invalid argument #1: must be nil or a string", 2) + end + + if (type(mask) ~= "string") then + error("Invalid argument #2: must be a string", 2) + end + + local opsm = C.pathsearchmode + C.pathsearchmode = 0 + local rootrec = C.klistpath(path, mask, CACHE1D.FIND_FILE) + C.pathsearchmode = opsm + + if (rootrec == nil) then + -- TODO: discern? + error("out of memory or failed listing path") + end + + local files = {} + + local rec = rootrec + while (rec ~= nil) do + assert(rec.name ~= nil) + files[#files+1] = ffi.string(rec.name) + rec = rec.next + end + + C.klistfree(rootrec) + + return files +end + +return fs