diff options
| author | Timothy Collett | 2012-09-10 09:18:24 -0400 |
|---|---|---|
| committer | Timothy Collett | 2012-09-10 09:18:24 -0400 |
| commit | 270351f510db516811117ab746a563560102c14b (patch) | |
| tree | 40f05ca4e5c9aac7fd24071436921ca4748b8e47 /library | |
| parent | d5ae1fc4f217589d0a34c116237740475accb267 (diff) | |
| parent | 45456b2230bd87bacc4bcd32515f530baafa8c04 (diff) | |
| download | dfhack-270351f510db516811117ab746a563560102c14b.tar.gz dfhack-270351f510db516811117ab746a563560102c14b.tar.bz2 dfhack-270351f510db516811117ab746a563560102c14b.tar.xz | |
Merge branch 'master' of https://github.com/danaris/dfhack
Diffstat (limited to 'library')
| -rw-r--r-- | library/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | library/Core.cpp | 73 | ||||
| -rw-r--r-- | library/Hooks-darwin.cpp | 26 | ||||
| -rw-r--r-- | library/LuaApi.cpp | 9 | ||||
| -rw-r--r-- | library/LuaTools.cpp | 83 | ||||
| -rw-r--r-- | library/PluginManager.cpp | 8 | ||||
| -rw-r--r-- | library/Process-windows.cpp | 136 | ||||
| -rw-r--r-- | library/include/ColorText.h | 2 | ||||
| -rw-r--r-- | library/include/Core.h | 7 | ||||
| -rw-r--r-- | library/include/Hooks.h | 6 | ||||
| -rw-r--r-- | library/include/PluginManager.h | 2 | ||||
| -rw-r--r-- | library/lua/dfhack.lua | 6 | ||||
| -rw-r--r-- | library/lua/memscan.lua | 46 | ||||
| -rw-r--r-- | library/lua/utils.lua | 2 |
14 files changed, 331 insertions, 77 deletions
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 73f6c9ec..75485ff2 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -8,8 +8,8 @@ IF(UNIX) OPTION(CONSOLE_NO_CATCH "Make the console not catch 'CTRL+C' events for easier debugging." OFF) ENDIF() -include_directories (include) include_directories (proto) +include_directories (include) SET(PERL_EXECUTABLE "perl" CACHE FILEPATH "This is the perl executable to run in the codegen step. Tweak it if you need to run a specific one.") diff --git a/library/Core.cpp b/library/Core.cpp index f30e19c2..09344135 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -204,7 +204,7 @@ struct sortable }; }; -static std::string getLuaHelp(std::string path) +static std::string getScriptHelp(std::string path, std::string helpprefix) { ifstream script(path.c_str()); @@ -212,14 +212,14 @@ static std::string getLuaHelp(std::string path) { std::string help; if (getline(script, help) && - help.substr(0,3) == "-- ") - return help.substr(3); + help.substr(0,helpprefix.length()) == helpprefix) + return help.substr(helpprefix.length()); } - return "Lua script."; + return "No help available."; } -static std::map<string,string> listLuaScripts(std::string path) +static std::map<string,string> listScripts(PluginManager *plug_mgr, std::string path) { std::vector<string> files; getdir(path, files); @@ -229,10 +229,16 @@ static std::map<string,string> listLuaScripts(std::string path) { if (hasEnding(files[i], ".lua")) { - std::string help = getLuaHelp(path + files[i]); + std::string help = getScriptHelp(path + files[i], "-- "); pset[files[i].substr(0, files[i].size()-4)] = help; } + else if (plug_mgr->eval_ruby && hasEnding(files[i], ".rb")) + { + std::string help = getScriptHelp(path + files[i], "# "); + + pset[files[i].substr(0, files[i].size()-3)] = help; + } } return pset; } @@ -275,31 +281,34 @@ static command_result runLuaScript(color_ostream &out, std::string name, vector< return ok ? CR_OK : CR_FAILURE; } +static command_result runRubyScript(PluginManager *plug_mgr, std::string name, vector<string> &args) +{ + std::string rbcmd = "$script_args = ["; + for (size_t i = 0; i < args.size(); i++) + rbcmd += "'" + args[i] + "', "; + rbcmd += "]\n"; + + rbcmd += "load './hack/scripts/" + name + ".rb'"; + + return plug_mgr->eval_ruby(rbcmd.c_str()); +} + command_result Core::runCommand(color_ostream &out, const std::string &command) { - //fprintf(stderr,"Inside runCommand"); - //fprintf(stderr," with command %s\n",command.c_str()); if (!command.empty()) { - //fprintf(stderr,"Command is not empty, tokenizing\n"); vector <string> parts; Core::cheap_tokenise(command,parts); - //fprintf(stderr,"Tokenized, got %d parts\n",parts.size()); if(parts.size() == 0) return CR_NOT_IMPLEMENTED; string first = parts[0]; - //fprintf(stderr,"Erasing beginning\n"); parts.erase(parts.begin()); - - //fprintf(stderr,"I think we're about there\n"); if (first[0] == '#') return CR_OK; cerr << "Invoking: " << command << endl; - - //fprintf(stderr,"Returning with the next recursion\n"); return runCommand(out, first, parts); } else @@ -357,10 +366,16 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve return CR_OK; } } - auto filename = getHackPath() + "scripts/" + parts[0] + ".lua"; - if (fileExists(filename)) + auto filename = getHackPath() + "scripts/" + parts[0]; + if (fileExists(filename + ".lua")) + { + string help = getScriptHelp(filename + ".lua", "-- "); + con.print("%s: %s\n", parts[0].c_str(), help.c_str()); + return CR_OK; + } + if (plug_mgr->eval_ruby && fileExists(filename + ".rb")) { - string help = getLuaHelp(filename); + string help = getScriptHelp(filename + ".rb", "# "); con.print("%s: %s\n", parts[0].c_str(), help.c_str()); return CR_OK; } @@ -508,7 +523,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve con.print(" %-22s- %s\n",(*iter).name.c_str(), (*iter).description.c_str()); con.reset_color(); } - auto scripts = listLuaScripts(getHackPath() + "scripts/"); + auto scripts = listScripts(plug_mgr, getHackPath() + "scripts/"); if (!scripts.empty()) { con.print("\nscripts:\n"); @@ -613,9 +628,11 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve command_result res = plug_mgr->InvokeCommand(con, first, parts); if(res == CR_NOT_IMPLEMENTED) { - auto filename = getHackPath() + "scripts/" + first + ".lua"; - if (fileExists(filename)) + auto filename = getHackPath() + "scripts/" + first; + if (fileExists(filename + ".lua")) res = runLuaScript(con, first, parts); + else if (plug_mgr->eval_ruby && fileExists(filename + ".rb")) + res = runRubyScript(plug_mgr, first, parts); else con.printerr("%s is not a recognized command.\n", first.c_str()); } @@ -680,7 +697,7 @@ void fIOthread(void * iodata) { string command = ""; int ret = con.lineedit("[DFHack]# ",command, main_history); - //fprintf(stderr,"Command: [%s]\n",command.c_str()); + fprintf(stderr,"Command: [%s]\n",command.c_str()); if(ret == -2) { cerr << "Console is shutting down properly." << endl; @@ -694,13 +711,13 @@ void fIOthread(void * iodata) else if(ret) { // a proper, non-empty command was entered - //fprintf(stderr,"Adding command to history\n"); + fprintf(stderr,"Adding command to history\n"); main_history.add(command); - //fprintf(stderr,"Saving history\n"); + fprintf(stderr,"Saving history\n"); main_history.save("dfhack.history"); } - //fprintf(stderr,"Running command\n"); + fprintf(stderr,"Running command\n"); auto rv = core->runCommand(con, command); @@ -1207,7 +1224,8 @@ bool Core::ncurses_wgetch(int in, int & out) { df::viewscreen * ws = Gui::GetCurrentScreen(); if (strict_virtual_cast<df::viewscreen_dwarfmodest>(ws) && - df::global::ui->main.mode != ui_sidebar_mode::Hotkeys) + df::global::ui->main.mode != ui_sidebar_mode::Hotkeys && + df::global::ui->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None) { setHotkeyCmd(df::global::ui->main.hotkeys[idx].name); return false; @@ -1355,7 +1373,8 @@ bool Core::SelectHotkey(int sym, int modifiers) idx += 8; if (strict_virtual_cast<df::viewscreen_dwarfmodest>(screen) && - df::global::ui->main.mode != ui_sidebar_mode::Hotkeys) + df::global::ui->main.mode != ui_sidebar_mode::Hotkeys && + df::global::ui->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None) { cmd = df::global::ui->main.hotkeys[idx].name; } diff --git a/library/Hooks-darwin.cpp b/library/Hooks-darwin.cpp index ef89105d..190616b8 100644 --- a/library/Hooks-darwin.cpp +++ b/library/Hooks-darwin.cpp @@ -38,11 +38,11 @@ distribution. #include <string> #include <map> -/*typedef struct interpose_s +typedef struct interpose_s { void *new_func; void *orig_func; -} interpose_t;*/ +} interpose_t; #include "DFHack.h" #include "Core.h" @@ -58,11 +58,18 @@ distribution. };*/ +#define DYLD_INTERPOSE(_replacment,_replacee) __attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee __attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee }; + +DYLD_INTERPOSE(DFH_SDL_Init,SDL_Init); +DYLD_INTERPOSE(DFH_SDL_PollEvent,SDL_PollEvent); +DYLD_INTERPOSE(DFH_SDL_Quit,SDL_Quit); +DYLD_INTERPOSE(DFH_SDL_NumJoysticks,SDL_NumJoysticks); + /******************************************************************************* * SDL part starts here * *******************************************************************************/ // hook - called for each game tick (or more often) -DFhackCExport int SDL_NumJoysticks(void) +DFhackCExport int DFH_SDL_NumJoysticks(void) { DFHack::Core & c = DFHack::Core::getInstance(); return c.Update(); @@ -70,7 +77,7 @@ DFhackCExport int SDL_NumJoysticks(void) // hook - called at program exit static void (*_SDL_Quit)(void) = 0; -DFhackCExport void SDL_Quit(void) +DFhackCExport void DFH_SDL_Quit(void) { DFHack::Core & c = DFHack::Core::getInstance(); c.Shutdown(); @@ -79,16 +86,16 @@ DFhackCExport void SDL_Quit(void) _SDL_Quit(); }*/ - _SDL_Quit(); + SDL_Quit(); } // called by DF to check input events static int (*_SDL_PollEvent)(SDL::Event* event) = 0; -DFhackCExport int SDL_PollEvent(SDL::Event* event) +DFhackCExport int DFH_SDL_PollEvent(SDL::Event* event) { pollevent_again: // if SDL returns 0 here, it means there are no more events. return 0 - int orig_return = _SDL_PollEvent(event); + int orig_return = SDL_PollEvent(event); if(!orig_return) return 0; // otherwise we have an event to filter @@ -128,7 +135,7 @@ DFhackCExport int wgetch(WINDOW *win) // hook - called at program start, initialize some stuffs we'll use later static int (*_SDL_Init)(uint32_t flags) = 0; -DFhackCExport int SDL_Init(uint32_t flags) +DFhackCExport int DFH_SDL_Init(uint32_t flags) { // reroute stderr fprintf(stderr,"dfhack: attempting to hook in\n"); @@ -158,6 +165,7 @@ DFhackCExport int SDL_Init(uint32_t flags) DFHack::Core & c = DFHack::Core::getInstance(); //c.Init(); - int ret = _SDL_Init(flags); + //int ret = _SDL_Init(flags); + int ret = SDL_Init(flags); return ret; }
\ No newline at end of file diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 631b3c49..b0a085ec 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1036,10 +1036,10 @@ static void *checkaddr(lua_State *L, int idx, bool allow_null = false) return rv; } -static uint32_t getBase() { return Core::getInstance().p->getBase(); } +static int getRebaseDelta() { return Core::getInstance().vinfo->getRebaseDelta(); } static const LuaWrapper::FunctionReg dfhack_internal_module[] = { - WRAP(getBase), + WRAP(getRebaseDelta), { NULL, NULL } }; @@ -1074,8 +1074,9 @@ static int internal_setAddress(lua_State *L) } // 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); + uint32_t iaddr = addr - Core::getInstance().vinfo->getRebaseDelta(); + fprintf(stderr, "Setting global '%s' to %x (%x)\n", name.c_str(), addr, iaddr); + fflush(stderr); return 1; } diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp index 752c341b..28571a0f 100644 --- a/library/LuaTools.cpp +++ b/library/LuaTools.cpp @@ -256,8 +256,11 @@ static int lua_dfhack_color(lua_State *S) luaL_argerror(S, 1, "invalid color value"); color_ostream *out = Lua::GetOutput(S); - if (out) + if (out) { + lua_pushinteger(S, (int)out->color()); out->color(color_ostream::color_value(cv)); + return 1; + } return 0; } @@ -423,10 +426,12 @@ static bool convert_to_exception(lua_State *L, int slevel, lua_State *thread = N // Create a new exception for this thread lua_newtable(L); - luaL_where(L, 1); + luaL_where(L, slevel); + lua_setfield(L, -2, "where"); lua_pushstring(L, "coroutine resume failed"); - lua_concat(L, 2); lua_setfield(L, -2, "message"); + lua_getfield(L, -2, "verbose"); + lua_setfield(L, -2, "verbose"); lua_swap(L); lua_setfield(L, -2, "cause"); } @@ -480,12 +485,57 @@ static int dfhack_onerror(lua_State *L) return 1; } +static int dfhack_error(lua_State *L) +{ + luaL_checkany(L, 1); + lua_settop(L, 3); + int level = std::max(1, luaL_optint(L, 2, 1)); + + lua_pushvalue(L, 1); + + if (convert_to_exception(L, level)) + { + luaL_where(L, level); + lua_setfield(L, -2, "where"); + + if (!lua_isnil(L, 3)) + { + lua_pushvalue(L, 3); + lua_setfield(L, -2, "verbose"); + } + } + + return lua_error(L); +} + static int dfhack_exception_tostring(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); + + if (lua_isnil(L, 2)) + { + lua_rawgetp(L, LUA_REGISTRYINDEX, &DFHACK_EXCEPTION_META_TOKEN); + lua_getfield(L, -1, "verbose"); + lua_insert(L, 2); + lua_settop(L, 2); + } + + lua_getfield(L, 1, "verbose"); + + bool verbose = + lua_toboolean(L, 2) || lua_toboolean(L, 3) || + (lua_isnil(L, 2) && lua_isnil(L, 3)); int base = lua_gettop(L); + if (verbose || lua_isnil(L, 3)) + { + lua_getfield(L, 1, "where"); + if (!lua_isstring(L, -1)) + lua_pop(L, 1); + } + lua_getfield(L, 1, "message"); if (!lua_isstring(L, -1)) { @@ -493,15 +543,26 @@ static int dfhack_exception_tostring(lua_State *L) lua_pushstring(L, "(error message is not a string)"); } - lua_pushstring(L, "\n"); - lua_getfield(L, 1, "stacktrace"); - if (!lua_isstring(L, -1)) - lua_pop(L, 2); + if (verbose) + { + lua_pushstring(L, "\n"); + lua_getfield(L, 1, "stacktrace"); + if (!lua_isstring(L, -1)) + lua_pop(L, 2); + } lua_pushstring(L, "\ncaused by:\n"); lua_getfield(L, 1, "cause"); if (lua_isnil(L, -1)) lua_pop(L, 2); + else if (lua_istable(L, -1)) + { + lua_pushcfunction(L, dfhack_exception_tostring); + lua_swap(L); + lua_pushvalue(L, 2); + if (lua_pcall(L, 2, 1, 0) != LUA_OK) + error_tostring(L); + } else error_tostring(L); @@ -652,7 +713,12 @@ static int dfhack_coauxwrap (lua_State *L) { if (Lua::IsSuccess(r)) return lua_gettop(L); else + { + if (lua_checkstack(L, LUA_MINSTACK)) + convert_to_exception(L, 1); + return lua_error(L); + } } static int dfhack_cowrap (lua_State *L) { @@ -1159,6 +1225,7 @@ static const luaL_Reg dfhack_funcs[] = { { "safecall", dfhack_safecall }, { "saferesume", dfhack_saferesume }, { "onerror", dfhack_onerror }, + { "error", dfhack_error }, { "call_with_finalizer", dfhack_call_with_finalizer }, { "with_suspend", lua_dfhack_with_suspend }, { "open_plugin", dfhack_open_plugin }, @@ -1359,6 +1426,8 @@ lua_State *DFHack::Lua::Open(color_ostream &out, lua_State *state) lua_newtable(state); lua_pushcfunction(state, dfhack_exception_tostring); lua_setfield(state, -2, "__tostring"); + lua_pushcfunction(state, dfhack_exception_tostring); + lua_setfield(state, -2, "tostring"); lua_dup(state); lua_rawsetp(state, LUA_REGISTRYINDEX, &DFHACK_EXCEPTION_META_TOKEN); lua_setfield(state, -2, "exception"); diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp index ae8cc755..a314883e 100644 --- a/library/PluginManager.cpp +++ b/library/PluginManager.cpp @@ -188,6 +188,7 @@ bool Plugin::load(color_ostream &con) plugin_shutdown = (command_result (*)(color_ostream &)) LookupPlugin(plug, "plugin_shutdown"); plugin_onstatechange = (command_result (*)(color_ostream &, state_change_event)) LookupPlugin(plug, "plugin_onstatechange"); plugin_rpcconnect = (RPCService* (*)(color_ostream &)) LookupPlugin(plug, "plugin_rpcconnect"); + plugin_eval_ruby = (command_result (*)(const char*)) LookupPlugin(plug, "plugin_eval_ruby"); index_lua(plug); this->name = *plug_name; plugin_lib = plug; @@ -538,6 +539,7 @@ PluginManager::PluginManager(Core * core) const string searchstr = ".plug.dll"; #endif cmdlist_mutex = new mutex(); + eval_ruby = NULL; vector <string> filez; getdir(path, filez); for(size_t i = 0; i < filez.size();i++) @@ -620,6 +622,8 @@ void PluginManager::registerCommands( Plugin * p ) { belongs[cmds[i].name] = p; } + if (p->plugin_eval_ruby) + eval_ruby = p->plugin_eval_ruby; cmdlist_mutex->unlock(); } @@ -632,5 +636,7 @@ void PluginManager::unregisterCommands( Plugin * p ) { belongs.erase(cmds[i].name); } + if (p->plugin_eval_ruby) + eval_ruby = NULL; cmdlist_mutex->unlock(); -}
\ No newline at end of file +} diff --git a/library/Process-windows.cpp b/library/Process-windows.cpp index 944a773c..7eb6ff5f 100644 --- a/library/Process-windows.cpp +++ b/library/Process-windows.cpp @@ -233,19 +233,55 @@ struct HeapBlock ULONG reserved; }; */ -// FIXME: NEEDS TESTING! -// FIXME: <warmist> i noticed that if you enumerate it twice, second time it returns wrong .text region size + +static void GetDosNames(std::map<string, string> &table) +{ + // Partially based on example from msdn: + // Translate path with device name to drive letters. + TCHAR szTemp[512]; + szTemp[0] = '\0'; + + if (GetLogicalDriveStrings(sizeof(szTemp)-1, szTemp)) + { + TCHAR szName[MAX_PATH]; + TCHAR szDrive[3] = " :"; + BOOL bFound = FALSE; + TCHAR* p = szTemp; + + do + { + // Copy the drive letter to the template string + *szDrive = *p; + + // Look up each device name + if (QueryDosDevice(szDrive, szName, MAX_PATH)) + table[szName] = szDrive; + + // Go to the next NULL character. + while (*p++); + } while (*p); // end of string + } +} + void Process::getMemRanges( vector<t_memrange> & ranges ) { MEMORY_BASIC_INFORMATION MBI; //map<char *, unsigned int> heaps; uint64_t movingStart = 0; + PVOID LastAllocationBase = 0; map <char *, string> nameMap; + map <string,string> dosDrives; // get page size SYSTEM_INFO si; GetSystemInfo(&si); uint64_t PageSize = si.dwPageSize; + + // get dos drive names + GetDosNames(dosDrives); + + ranges.clear(); + // enumerate heaps // HeapNodes(d->my_pid, heaps); // go through all the VM regions, convert them to our internal format @@ -254,52 +290,106 @@ void Process::getMemRanges( vector<t_memrange> & ranges ) movingStart = ((uint64_t)MBI.BaseAddress + MBI.RegionSize); if(movingStart % PageSize != 0) movingStart = (movingStart / PageSize + 1) * PageSize; - // skip empty regions and regions we share with other processes (DLLs) - if( !(MBI.State & MEM_COMMIT) /*|| !(MBI.Type & MEM_PRIVATE)*/ ) + + // Skip unallocated address space + if (MBI.State & MEM_FREE) continue; + + // Find range and permissions t_memrange temp; + memset(&temp, 0, sizeof(temp)); + temp.start = (char *) MBI.BaseAddress; temp.end = ((char *)MBI.BaseAddress + (uint64_t)MBI.RegionSize); - temp.read = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READONLY || MBI.Protect & PAGE_READWRITE; - temp.write = MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READWRITE; - temp.execute = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_EXECUTE; - temp.valid = true; - if(!GetModuleBaseName(d->my_handle, (HMODULE) temp.start, temp.name, 1024)) + temp.valid = true; + + if (!(MBI.State & MEM_COMMIT)) + temp.valid = false; // reserved address space + else if (MBI.Protect & PAGE_EXECUTE) + temp.execute = true; + else if (MBI.Protect & PAGE_EXECUTE_READ) + temp.execute = temp.read = true; + else if (MBI.Protect & PAGE_EXECUTE_READWRITE) + temp.execute = temp.read = temp.write = true; + else if (MBI.Protect & PAGE_EXECUTE_WRITECOPY) + temp.execute = temp.read = temp.write = true; + else if (MBI.Protect & PAGE_READONLY) + temp.read = true; + else if (MBI.Protect & PAGE_READWRITE) + temp.read = temp.write = true; + else if (MBI.Protect & PAGE_WRITECOPY) + temp.read = temp.write = true; + + // Merge areas with the same properties + if (!ranges.empty() && LastAllocationBase == MBI.AllocationBase) { - if(nameMap.count((char *)temp.start)) + auto &last = ranges.back(); + + if (last.end == temp.start && + last.valid == temp.valid && last.execute == temp.execute && + last.read == temp.read && last.write == temp.write) { - // potential buffer overflow... - strcpy(temp.name, nameMap[(char *)temp.start].c_str()); + last.end = temp.end; + continue; } - else + } + +#if 1 + // Find the mapped file name + if (GetMappedFileName(d->my_handle, temp.start, temp.name, 1024)) + { + int vsize = strlen(temp.name); + + // Translate NT name to DOS name + for (auto it = dosDrives.begin(); it != dosDrives.end(); ++it) { - // filter away shared segments without a name. - if( !(MBI.Type & MEM_PRIVATE) ) + int ksize = it->first.size(); + if (strncmp(temp.name, it->first.data(), ksize) != 0) continue; - else - temp.name[0]=0; + + memcpy(temp.name, it->second.data(), it->second.size()); + memmove(temp.name + it->second.size(), temp.name + ksize, vsize + 1 - ksize); + break; } } else + temp.name[0] = 0; +#else + // Find the executable name + char *base = (char*)MBI.AllocationBase; + + if(nameMap.count(base)) + { + strncpy(temp.name, nameMap[base].c_str(), 1023); + } + else if(GetModuleBaseName(d->my_handle, (HMODULE)base, temp.name, 1024)) { + std::string nm(temp.name); + + nameMap[base] = nm; + // this is our executable! (could be generalized to pull segments from libs, but whatever) - if(d->base == temp.start) + if(d->base == base) { for(int i = 0; i < d->pe_header.FileHeader.NumberOfSections; i++) { - char sectionName[9]; + /*char sectionName[9]; memcpy(sectionName,d->sections[i].Name,8); sectionName[8] = 0; string nm; nm.append(temp.name); nm.append(" : "); - nm.append(sectionName); - nameMap[(char *)temp.start + d->sections[i].VirtualAddress] = nm; + nm.append(sectionName);*/ + nameMap[base + d->sections[i].VirtualAddress] = nm; } } - else - continue; } + else + temp.name[0] = 0; +#endif + + // Push the entry + LastAllocationBase = MBI.AllocationBase; ranges.push_back(temp); } } diff --git a/library/include/ColorText.h b/library/include/ColorText.h index 105832ef..0cc286dc 100644 --- a/library/include/ColorText.h +++ b/library/include/ColorText.h @@ -111,6 +111,8 @@ namespace DFHack void printerr(const char *format, ...); void vprinterr(const char *format, va_list args); + /// Get color + color_value color() { return cur_color; } /// Set color (ANSI color number) void color(color_value c); /// Reset color to default diff --git a/library/include/Core.h b/library/include/Core.h index e4d1080d..653298d8 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -83,10 +83,17 @@ namespace DFHack // Better than tracking some weird variables all over the place. class DFHACK_EXPORT Core { +#ifdef _DARWIN + friend int ::DFH_SDL_NumJoysticks(void); + friend void ::DFH_SDL_Quit(void); + friend int ::DFH_SDL_PollEvent(SDL::Event *); + friend int ::DFH_SDL_Init(uint32_t flags); +#else friend int ::SDL_NumJoysticks(void); friend void ::SDL_Quit(void); friend int ::SDL_PollEvent(SDL::Event *); friend int ::SDL_Init(uint32_t flags); +#endif friend int ::wgetch(WINDOW * w); friend int ::egg_init(void); friend int ::egg_shutdown(void); diff --git a/library/include/Hooks.h b/library/include/Hooks.h index 418a5ce3..325af43e 100644 --- a/library/include/Hooks.h +++ b/library/include/Hooks.h @@ -44,6 +44,12 @@ namespace SDL // these functions are here because they call into DFHack::Core and therefore need to // be declared as friend functions/known +#ifdef _DARWIN +DFhackCExport int DFH_SDL_NumJoysticks(void); +DFhackCExport void DFH_SDL_Quit(void); +DFhackCExport int DFH_SDL_PollEvent(SDL::Event* event); +DFhackCExport int DFH_SDL_Init(uint32_t flags); +#endif DFhackCExport int SDL_NumJoysticks(void); DFhackCExport void SDL_Quit(void); DFhackCExport int SDL_PollEvent(SDL::Event* event); diff --git a/library/include/PluginManager.h b/library/include/PluginManager.h index b76df437..5da9fc92 100644 --- a/library/include/PluginManager.h +++ b/library/include/PluginManager.h @@ -209,6 +209,7 @@ namespace DFHack command_result (*plugin_onupdate)(color_ostream &); command_result (*plugin_onstatechange)(color_ostream &, state_change_event); RPCService* (*plugin_rpcconnect)(color_ostream &); + command_result (*plugin_eval_ruby)(const char*); }; class DFHACK_EXPORT PluginManager { @@ -237,6 +238,7 @@ namespace DFHack { return all_plugins.size(); } + command_result (*eval_ruby)(const char*); // DATA private: tthread::mutex * cmdlist_mutex; diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index 4cdb4c95..d56d4df6 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -49,6 +49,10 @@ function dfhack.pcall(f, ...) return xpcall(f, dfhack.onerror, ...) end +function qerror(msg, level) + dfhack.error(msg, (level or 1) + 1, false) +end + function dfhack.with_finalize(...) return dfhack.call_with_finalizer(0,true,...) end @@ -64,6 +68,8 @@ function dfhack.with_temp_object(obj,fn,...) return dfhack.call_with_finalizer(1,true,call_delete,obj,fn,obj,...) end +dfhack.exception.__index = dfhack.exception + -- Module loading function mkmodule(module,env) diff --git a/library/lua/memscan.lua b/library/lua/memscan.lua index 95b9197b..970f821c 100644 --- a/library/lua/memscan.lua +++ b/library/lua/memscan.lua @@ -154,7 +154,8 @@ function MemoryArea.new(astart, aend) int16_t = CheckedArray.new('int16_t',astart,aend), uint16_t = CheckedArray.new('uint16_t',astart,aend), int32_t = CheckedArray.new('int32_t',astart,aend), - uint32_t = CheckedArray.new('uint32_t',astart,aend) + uint32_t = CheckedArray.new('uint32_t',astart,aend), + float = CheckedArray.new('float',astart,aend) } setmetatable(obj, MemoryArea) return obj @@ -168,7 +169,7 @@ function MemoryArea:__tostring() return string.format('<MemoryArea: %x..%x>', self.start_addr, self.end_addr) end function MemoryArea:contains_range(start,size) - return start >= self.start_addr and (start+size) <= self.end_addr + return size >= 0 and start >= self.start_addr and (start+size) <= self.end_addr end function MemoryArea:contains_obj(obj,count) local size, base = df.sizeof(obj) @@ -208,7 +209,8 @@ local function find_data_segment() end elseif mem.read and mem.write and (string.match(mem.name,'/dwarfort%.exe$') - or string.match(mem.name,'/Dwarf_Fortress$')) + or string.match(mem.name,'/Dwarf_Fortress$') + or string.match(mem.name,'Dwarf Fortress%.exe')) then data_start = mem.start_addr data_end = mem.end_addr @@ -233,7 +235,7 @@ function found_offset(name,val) if not val then print('Could not find offset '..name) if not cval and not utils.prompt_yes_no('Continue with the script?') then - error('User quit') + qerror('User quit') end return end @@ -250,6 +252,16 @@ function found_offset(name,val) end else dfhack.internal.setAddress(name, val) + + local ival = val - dfhack.internal.getRebaseDelta() + local entry = string.format("<global-address name='%s' value='0x%x'/>\n", name, ival) + + local ccolor = dfhack.color(COLOR_LIGHTGREEN) + dfhack.print(entry) + dfhack.color(ccolor) + + io.stdout:write(entry) + io.stdout:flush() end end @@ -452,4 +464,30 @@ function DiffSearcher:find_counter(prompt,data_type,delta,action_prompt) ) end +-- Screen size + +function get_screen_size() + -- Use already known globals + if dfhack.internal.getAddress('init') then + local d = df.global.init.display + return d.grid_x, d.grid_y + end + if dfhack.internal.getAddress('gps') then + local g = df.global.gps + return g.dimx, g.dimy + end + + -- Parse stdout.log for resize notifications + io.stdout:flush() + + local w,h = 80,25 + for line in io.lines('stdout.log') do + local cw, ch = string.match(line, '^Resizing grid to (%d+)x(%d+)$') + if cw and ch then + w, h = tonumber(cw), tonumber(ch) + end + end + return w,h +end + return _ENV diff --git a/library/lua/utils.lua b/library/lua/utils.lua index 93ee840c..f303091d 100644 --- a/library/lua/utils.lua +++ b/library/lua/utils.lua @@ -379,7 +379,7 @@ function prompt_yes_no(msg,default) elseif string.match(rv,'^[Nn]') then return false elseif rv == 'abort' then - error('User abort in utils.prompt_yes_no()') + qerror('User abort in utils.prompt_yes_no()') elseif rv == '' and default ~= nil then return default end |
