diff options
Diffstat (limited to 'library/LuaApi.cpp')
| -rw-r--r-- | library/LuaApi.cpp | 233 |
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); } |
