summaryrefslogtreecommitdiff
path: root/library/LuaApi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'library/LuaApi.cpp')
-rw-r--r--library/LuaApi.cpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index 6a550db8..631b3c49 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -84,6 +84,8 @@ distribution.
using namespace DFHack;
using namespace DFHack::LuaWrapper;
+void dfhack_printerr(lua_State *S, const std::string &str);
+
void Lua::Push(lua_State *state, const Units::NoblePosition &pos)
{
lua_createtable(state, 0, 3);
@@ -640,10 +642,37 @@ static void OpenModule(lua_State *state, const char *mname,
/***** DFHack module *****/
+static std::string getOSType()
+{
+ switch (Core::getInstance().vinfo->getOS())
+ {
+ case OS_WINDOWS:
+ return "windows";
+
+ case OS_LINUX:
+ return "linux";
+
+ case OS_APPLE:
+ return "darwin";
+
+ default:
+ return "unknown";
+ }
+}
+
+static std::string getDFVersion() { return Core::getInstance().vinfo->getVersion(); }
+
+static std::string getDFPath() { return Core::getInstance().p->getPath(); }
+static std::string getHackPath() { return Core::getInstance().getHackPath(); }
+
static bool isWorldLoaded() { return Core::getInstance().isWorldLoaded(); }
static bool isMapLoaded() { return Core::getInstance().isMapLoaded(); }
static const LuaWrapper::FunctionReg dfhack_module[] = {
+ WRAP(getOSType),
+ WRAP(getDFVersion),
+ WRAP(getDFPath),
+ WRAP(getHackPath),
WRAP(isWorldLoaded),
WRAP(isMapLoaded),
WRAPM(Translation, TranslateName),
@@ -715,6 +744,8 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, isDead),
WRAPM(Units, isAlive),
WRAPM(Units, isSane),
+ WRAPM(Units, isDwarf),
+ WRAPM(Units, isCitizen),
WRAPM(Units, getAge),
WRAPM(Units, getProfessionName),
WRAPM(Units, getCasteProfessionName),
@@ -988,6 +1019,207 @@ static const luaL_Reg dfhack_constructions_funcs[] = {
{ NULL, NULL }
};
+/***** Internal module *****/
+
+static void *checkaddr(lua_State *L, int idx, bool allow_null = false)
+{
+ luaL_checkany(L, idx);
+ void *rv;
+ if (lua_isnil(L, idx))
+ rv = NULL;
+ else if (lua_type(L, idx) == LUA_TNUMBER)
+ rv = (void*)lua_tounsigned(L, idx);
+ else
+ rv = Lua::CheckDFObject(L, NULL, idx);
+ if (!rv && !allow_null)
+ luaL_argerror(L, idx, "null pointer");
+ return rv;
+}
+
+static uint32_t getBase() { return Core::getInstance().p->getBase(); }
+
+static const LuaWrapper::FunctionReg dfhack_internal_module[] = {
+ WRAP(getBase),
+ { NULL, NULL }
+};
+
+static int internal_getAddress(lua_State *L)
+{
+ const char *name = luaL_checkstring(L, 1);
+ uint32_t addr = Core::getInstance().vinfo->getAddress(name);
+ if (addr)
+ lua_pushnumber(L, addr);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+static int internal_setAddress(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+ uint32_t addr = (uint32_t)checkaddr(L, 2, true);
+ internal_getAddress(L);
+
+ // Set the address
+ Core::getInstance().vinfo->setAddress(name, addr);
+
+ auto fields = df::global::_identity.getFields();
+
+ for (int i = 0; fields && fields[i].mode != struct_field_info::END; ++i)
+ {
+ if (fields[i].name != name)
+ continue;
+
+ *(void**)fields[i].offset = (void*)addr;
+ }
+
+ // Print via printerr, so that it is definitely logged to stderr.log.
+ std::string msg = stl_sprintf("<global-address name='%s' value='0x%x'/>", name.c_str(), addr);
+ dfhack_printerr(L, msg);
+
+ return 1;
+}
+
+static int internal_getVTable(lua_State *L)
+{
+ const char *name = luaL_checkstring(L, 1);
+ uint32_t addr = (uint32_t)Core::getInstance().vinfo->getVTable(name);
+ if (addr)
+ lua_pushnumber(L, addr);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+static int internal_getMemRanges(lua_State *L)
+{
+ std::vector<DFHack::t_memrange> ranges;
+ Core::getInstance().p->getMemRanges(ranges);
+
+ lua_newtable(L);
+
+ for(size_t i = 0; i < ranges.size(); i++)
+ {
+ lua_newtable(L);
+ lua_pushnumber(L, (uint32_t)ranges[i].start);
+ lua_setfield(L, -2, "start_addr");
+ lua_pushnumber(L, (uint32_t)ranges[i].end);
+ lua_setfield(L, -2, "end_addr");
+ lua_pushstring(L, ranges[i].name);
+ lua_setfield(L, -2, "name");
+ lua_pushboolean(L, ranges[i].read);
+ lua_setfield(L, -2, "read");
+ lua_pushboolean(L, ranges[i].write);
+ lua_setfield(L, -2, "write");
+ lua_pushboolean(L, ranges[i].execute);
+ lua_setfield(L, -2, "execute");
+ lua_pushboolean(L, ranges[i].shared);
+ lua_setfield(L, -2, "shared");
+ lua_pushboolean(L, ranges[i].valid);
+ lua_setfield(L, -2, "valid");
+ lua_rawseti(L, -2, i+1);
+ }
+
+ return 1;
+}
+
+static int internal_memmove(lua_State *L)
+{
+ void *dest = checkaddr(L, 1);
+ void *src = checkaddr(L, 2);
+ int size = luaL_checkint(L, 3);
+ if (size < 0) luaL_argerror(L, 1, "negative size");
+ memmove(dest, src, size);
+ return 0;
+}
+
+static int internal_memcmp(lua_State *L)
+{
+ void *dest = checkaddr(L, 1);
+ void *src = checkaddr(L, 2);
+ int size = luaL_checkint(L, 3);
+ if (size < 0) luaL_argerror(L, 1, "negative size");
+ lua_pushinteger(L, memcmp(dest, src, size));
+ return 1;
+}
+
+static int internal_memscan(lua_State *L)
+{
+ uint8_t *haystack = (uint8_t*)checkaddr(L, 1);
+ int hcount = luaL_checkint(L, 2);
+ int hstep = luaL_checkint(L, 3);
+ if (hstep == 0) luaL_argerror(L, 3, "zero step");
+ void *needle = checkaddr(L, 4);
+ int nsize = luaL_checkint(L, 5);
+ if (nsize < 0) luaL_argerror(L, 5, "negative size");
+
+ for (int i = 0; i <= hcount; i++)
+ {
+ uint8_t *p = haystack + i*hstep;
+ if (memcmp(p, needle, nsize) == 0) {
+ lua_pushinteger(L, i);
+ lua_pushinteger(L, (lua_Integer)p);
+ return 2;
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int internal_diffscan(lua_State *L)
+{
+ lua_settop(L, 8);
+ void *old_data = checkaddr(L, 1);
+ void *new_data = checkaddr(L, 2);
+ int start_idx = luaL_checkint(L, 3);
+ int end_idx = luaL_checkint(L, 4);
+ int eltsize = luaL_checkint(L, 5);
+ bool has_oldv = !lua_isnil(L, 6);
+ bool has_newv = !lua_isnil(L, 7);
+ bool has_diffv = !lua_isnil(L, 8);
+
+#define LOOP(esz, etype) \
+ case esz: { \
+ etype *pold = (etype*)old_data; \
+ etype *pnew = (etype*)new_data; \
+ etype oldv = (etype)luaL_optint(L, 6, 0); \
+ etype newv = (etype)luaL_optint(L, 7, 0); \
+ etype diffv = (etype)luaL_optint(L, 8, 0); \
+ for (int i = start_idx; i < end_idx; i++) { \
+ if (pold[i] == pnew[i]) continue; \
+ if (has_oldv && pold[i] != oldv) continue; \
+ if (has_newv && pnew[i] != newv) continue; \
+ if (has_diffv && etype(pnew[i]-pold[i]) != diffv) continue; \
+ lua_pushinteger(L, i); return 1; \
+ } \
+ break; \
+ }
+ switch (eltsize) {
+ LOOP(1, uint8_t);
+ LOOP(2, uint16_t);
+ LOOP(4, uint32_t);
+ default:
+ luaL_argerror(L, 5, "invalid element size");
+ }
+#undef LOOP
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static const luaL_Reg dfhack_internal_funcs[] = {
+ { "getAddress", internal_getAddress },
+ { "setAddress", internal_setAddress },
+ { "getVTable", internal_getVTable },
+ { "getMemRanges", internal_getMemRanges },
+ { "memmove", internal_memmove },
+ { "memcmp", internal_memcmp },
+ { "memscan", internal_memscan },
+ { "diffscan", internal_diffscan },
+ { NULL, NULL }
+};
+
/************************
* Main Open function *
@@ -1007,4 +1239,5 @@ void OpenDFHackApi(lua_State *state)
OpenModule(state, "burrows", dfhack_burrows_module, dfhack_burrows_funcs);
OpenModule(state, "buildings", dfhack_buildings_module, dfhack_buildings_funcs);
OpenModule(state, "constructions", dfhack_constructions_module);
+ OpenModule(state, "internal", dfhack_internal_module, dfhack_internal_funcs);
}