diff --git a/lua/include/luaconf.h b/lua/include/luaconf.h index ba9e833bb..660793356 100644 --- a/lua/include/luaconf.h +++ b/lua/include/luaconf.h @@ -520,7 +520,11 @@ */ #define LUA_NUMBER_SCAN "%lf" #define LUA_NUMBER_FMT "%.14g" +#ifdef WIN32 //More specifically MSVC, but did not work, either way only MSVC is used in windows build +#define lua_number2str(s,n) sprintf_s((s),32, LUA_NUMBER_FMT, (n)) +#else #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#endif #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ #define lua_str2number(s,p) strtod((s), (p)) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 9946ef427..0d3bb57e6 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -118,3 +118,5 @@ DFHACK_PLUGIN(autodump autodump.cpp) DFHACK_PLUGIN(cleanowned cleanowned.cpp) DFHACK_PLUGIN(deramp deramp.cpp) DFHACK_PLUGIN(flows flows.cpp) +DFHACK_PLUGIN(memview memview.cpp) + diff --git a/plugins/Dfusion/CMakeLists.txt b/plugins/Dfusion/CMakeLists.txt index d17e66a23..7b6724dde 100644 --- a/plugins/Dfusion/CMakeLists.txt +++ b/plugins/Dfusion/CMakeLists.txt @@ -4,6 +4,7 @@ FILE(GLOB DFUSION_CPPS src/*.c*) set( DFUSION_CPPS_ALL dfusion.cpp + ${dfhack_SOURCE_DIR}/library/depends/tthread/tinythread.cpp ${DFUSION_CPPS} ) DFHACK_PLUGIN(dfusion ${DFUSION_CPPS_ALL} LINK_LIBRARIES lua) diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index f75ce69b2..514a5509d 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -24,6 +24,7 @@ using std::string; using namespace DFHack; static tthread::mutex* mymutex=0; +static tthread::thread* thread_dfusion=0; uint64_t timeLast=0; DFhackCExport command_result dfusion (Core * c, vector & parameters); @@ -37,15 +38,23 @@ DFhackCExport const char * plugin_name ( void ) DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) { commands.clear(); + lua::state st=lua::glua::Get(); //maybe remake it to run automaticaly - lua::RegisterConsole(lua::glua::Get(),&c->con); - lua::RegisterProcess(lua::glua::Get(),c->p); - lua::RegisterHexsearch(lua::glua::Get()); - lua::RegisterMisc(lua::glua::Get()); - lua::RegisterVersionInfo(lua::glua::Get()); - commands.push_back(PluginCommand("dfusion","Init dfusion system.",dfusion)); - commands.push_back(PluginCommand("lua", "Run interactive interpreter.\ -\n Options: = run instead",lua_run)); + lua::RegisterConsole(st,&c->con); + lua::RegisterProcess(st,c->p); + lua::RegisterHexsearch(st); + lua::RegisterMisc(st); + lua::RegisterVersionInfo(st); + #ifdef LINUX_BUILD + st.push(1); + st.setglobal("LINUX"); + #else + st.push(1); + st.setglobal("WINDOWS"); + #endif + + commands.push_back(PluginCommand("dfusion","Init dfusion system. Use 'dfusion thready' to spawn a different thread.",dfusion)); + commands.push_back(PluginCommand("lua", "Run interactive interpreter. Use 'lua ' to run instead.",lua_run)); mymutex=new tthread::mutex; return CR_OK; @@ -55,11 +64,13 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) { // shutdown stuff + if(thread_dfusion) + delete thread_dfusion; delete mymutex; return CR_OK; } -DFhackCExport command_result plugin_onupdate ( Core * c ) +DFhackCExport command_result plugin_onupdate_DISABLED ( Core * c ) { uint64_t time2 = GetTimeMs64(); uint64_t delta = time2-timeLast; @@ -137,13 +148,12 @@ DFhackCExport command_result lua_run (Core * c, vector & parameters) mymutex->unlock(); return CR_OK; } -DFhackCExport command_result dfusion (Core * c, vector & parameters) +void RunDfusion(void *p) { - - Console &con=c->con; + Console &con=static_cast(p)->con; mymutex->lock(); + lua::state s=lua::glua::Get(); - try{ s.loadfile("dfusion/init.lua"); //load script s.pcall(0,0);// run it @@ -151,9 +161,20 @@ DFhackCExport command_result dfusion (Core * c, vector & parameters) catch(lua::exception &e) { con.printerr("Error:%s\n",e.what()); - c->con.printerr("%s\n",lua::DebugDump(lua::glua::Get()).c_str()); + con.printerr("%s\n",lua::DebugDump(lua::glua::Get()).c_str()); } s.settop(0);// clean up mymutex->unlock(); +} +DFhackCExport command_result dfusion (Core * c, vector & parameters) +{ + if(thread_dfusion==0) + thread_dfusion=new tthread::thread(RunDfusion,c); + if(parameters[0]!="thready") + { + thread_dfusion->join(); + delete thread_dfusion; + thread_dfusion=0; + } return CR_OK; } diff --git a/plugins/Dfusion/luafiles/adv_tools/init.lua b/plugins/Dfusion/luafiles/adv_tools/init.lua new file mode 100644 index 000000000..d8317f7ab --- /dev/null +++ b/plugins/Dfusion/luafiles/adv_tools/init.lua @@ -0,0 +1,89 @@ +adv_tools=adv_tools or {} +adv_tools.menu=adv_tools.menu or MakeMenu() +function adv_tools.ressurect() + myoff=offsets.getEx("AdvCreatureVec") + vector=engine.peek(myoff,ptr_vector) + indx=GetCreatureAtPos(getxyz()) + if indx<0 then indx=0 end + --print(string.format("%x",vector:getval(indx))) + v2=engine.peek(vector:getval(indx),ptr_Creature.hurt1) + for i=0,v2:size()-1 do + v2:setval(i,0) + end + v2=engine.peek(vector:getval(indx),ptr_Creature.hurt2) + v2.type=DWORD + for i=0,v2:size()-1 do + v2:setval(i,0) + end + engine.poke(vector:getval(indx),ptr_Creature.bloodlvl,60000) --give blood + engine.poke(vector:getval(indx),ptr_Creature.bleedlvl,0) --stop some bleeding... + local flg=engine.peek(vector:getval(indx),ptr_Creature.flags) + flg:set(1,false) --ALIVE + flg:set(39,false) -- leave body yet again + flg:set(37,false) -- something todo with wounds- lets you walk again. + flg:set(58,true) -- makes them able to breathe + flg:set(61,true) -- gives them sight + engine.poke(vector:getval(indx),ptr_Creature.flags,flg) +end + +function adv_tools.wagonmode() --by rumrusher + --first three lines same as before (because we will need an offset of creature at location x,y,z) + myoff=offsets.getEx("AdvCreatureVec") + vector=engine.peek(myoff,ptr_vector) + indx=GetCreatureAtPos(getxyz()) + --indx=0 + --print(string.format("%x",vector:getval(indx))) + flg=engine.peek(vector:getval(indx),ptr_Creature.flags) --get flags + flg:set(1,false) + flg:set(74,false) + engine.poke(vector:getval(indx),ptr_Creature.flags,flg) + print("To stay normal press y, else hit Enter turn Wagon mode on.") + r=io.stdin:read() -- repeat for it too work... also creature will be dead. + if r== "y" then + flg=engine.peek(vector:getval(indx),ptr_Creature.flags) + flg:set(1,false) + engine.poke(vector:getval(indx),ptr_Creature.flags,flg) + else + flg=engine.peek(vector:getval(indx),ptr_Creature.flags) + flg:set(1,false) + flg:flip(74) + engine.poke(vector:getval(indx),ptr_Creature.flags,flg) + end +end +function selectall() + local retvec={} --return vector (or a list) + myoff=offsets.getEx("AdvCreatureVec") + vector=engine.peek(myoff,ptr_vector) --standart start + for i=0,vector:size()-1 do --check all creatures + local off + off=vector:getval(i) + local flags=engine.peek(off,ptr_Creature.flags) + if flags:get(1)==true then --if dead ... + table.insert(retvec,off)--... add it to return vector + end + end + return retvec --return the "return vector" :) +end +function adv_tools.hostilate() + vector=engine.peek(offsets.getEx("AdvCreatureVec"),ptr_vector) + id=GetCreatureAtPos(getxyz()) + print(string.format("Vec:%d cr:%d",vector:size(),id)) + off=vector:getval(id) + crciv=engine.peek(vector:getval(id),ptr_Creature.civ) + curciv=engine.peek(vector:getval(0),ptr_Creature.civ) + + if curciv==crciv then + print("Friendly-making enemy") + engine.poke(off,ptr_Creature.civ,-1) + flg=engine.peek(off,ptr_Creature.flags) + flg:set(17,true) + engine.poke(off,ptr_Creature.flags,flg) + else + print("Enemy- making friendly") + engine.poke(off,ptr_Creature.civ,curciv) + flg=engine.peek(off,ptr_Creature.flags) + flg:set(17,false) + flg:set(19,false) + engine.poke(off,ptr_Creature.flags,flg) + end +end diff --git a/plugins/Dfusion/luafiles/adv_tools/plugin.lua b/plugins/Dfusion/luafiles/adv_tools/plugin.lua index d8317f7ab..e69de29bb 100644 --- a/plugins/Dfusion/luafiles/adv_tools/plugin.lua +++ b/plugins/Dfusion/luafiles/adv_tools/plugin.lua @@ -1,89 +0,0 @@ -adv_tools=adv_tools or {} -adv_tools.menu=adv_tools.menu or MakeMenu() -function adv_tools.ressurect() - myoff=offsets.getEx("AdvCreatureVec") - vector=engine.peek(myoff,ptr_vector) - indx=GetCreatureAtPos(getxyz()) - if indx<0 then indx=0 end - --print(string.format("%x",vector:getval(indx))) - v2=engine.peek(vector:getval(indx),ptr_Creature.hurt1) - for i=0,v2:size()-1 do - v2:setval(i,0) - end - v2=engine.peek(vector:getval(indx),ptr_Creature.hurt2) - v2.type=DWORD - for i=0,v2:size()-1 do - v2:setval(i,0) - end - engine.poke(vector:getval(indx),ptr_Creature.bloodlvl,60000) --give blood - engine.poke(vector:getval(indx),ptr_Creature.bleedlvl,0) --stop some bleeding... - local flg=engine.peek(vector:getval(indx),ptr_Creature.flags) - flg:set(1,false) --ALIVE - flg:set(39,false) -- leave body yet again - flg:set(37,false) -- something todo with wounds- lets you walk again. - flg:set(58,true) -- makes them able to breathe - flg:set(61,true) -- gives them sight - engine.poke(vector:getval(indx),ptr_Creature.flags,flg) -end - -function adv_tools.wagonmode() --by rumrusher - --first three lines same as before (because we will need an offset of creature at location x,y,z) - myoff=offsets.getEx("AdvCreatureVec") - vector=engine.peek(myoff,ptr_vector) - indx=GetCreatureAtPos(getxyz()) - --indx=0 - --print(string.format("%x",vector:getval(indx))) - flg=engine.peek(vector:getval(indx),ptr_Creature.flags) --get flags - flg:set(1,false) - flg:set(74,false) - engine.poke(vector:getval(indx),ptr_Creature.flags,flg) - print("To stay normal press y, else hit Enter turn Wagon mode on.") - r=io.stdin:read() -- repeat for it too work... also creature will be dead. - if r== "y" then - flg=engine.peek(vector:getval(indx),ptr_Creature.flags) - flg:set(1,false) - engine.poke(vector:getval(indx),ptr_Creature.flags,flg) - else - flg=engine.peek(vector:getval(indx),ptr_Creature.flags) - flg:set(1,false) - flg:flip(74) - engine.poke(vector:getval(indx),ptr_Creature.flags,flg) - end -end -function selectall() - local retvec={} --return vector (or a list) - myoff=offsets.getEx("AdvCreatureVec") - vector=engine.peek(myoff,ptr_vector) --standart start - for i=0,vector:size()-1 do --check all creatures - local off - off=vector:getval(i) - local flags=engine.peek(off,ptr_Creature.flags) - if flags:get(1)==true then --if dead ... - table.insert(retvec,off)--... add it to return vector - end - end - return retvec --return the "return vector" :) -end -function adv_tools.hostilate() - vector=engine.peek(offsets.getEx("AdvCreatureVec"),ptr_vector) - id=GetCreatureAtPos(getxyz()) - print(string.format("Vec:%d cr:%d",vector:size(),id)) - off=vector:getval(id) - crciv=engine.peek(vector:getval(id),ptr_Creature.civ) - curciv=engine.peek(vector:getval(0),ptr_Creature.civ) - - if curciv==crciv then - print("Friendly-making enemy") - engine.poke(off,ptr_Creature.civ,-1) - flg=engine.peek(off,ptr_Creature.flags) - flg:set(17,true) - engine.poke(off,ptr_Creature.flags,flg) - else - print("Enemy- making friendly") - engine.poke(off,ptr_Creature.civ,curciv) - flg=engine.peek(off,ptr_Creature.flags) - flg:set(17,false) - flg:set(19,false) - engine.poke(off,ptr_Creature.flags,flg) - end -end diff --git a/plugins/Dfusion/luafiles/common.lua b/plugins/Dfusion/luafiles/common.lua index 912862d56..55c3793f2 100644 --- a/plugins/Dfusion/luafiles/common.lua +++ b/plugins/Dfusion/luafiles/common.lua @@ -26,7 +26,7 @@ function GetTextRegion() return nil end function GetRegionIn(pos) - ranges__=ranges__ or Process.getMemRanges() + ranges__= Process.getMemRanges() for k,v in pairs(ranges__) do --for k2,v2 in pairs(v) do -- print(string.format("%d %s->%s",k,tostring(k2),tostring(v2))) @@ -84,6 +84,8 @@ engine.peekb=Process.readByte engine.pokeb=Process.writeByte engine.peekw=Process.readWord engine.pokew=Process.writeWord +engine.peekstr_stl=Process.readSTLString +engine.pokestr_stl=Process.writeSTLString engine.peekstr=Process.readCString --engine.pokestr=Process.readCString engine.peekarb=Process.read @@ -204,7 +206,7 @@ end function it_menu:display() print("Select choice (q exits):") for p,c in pairs(self.items) do - print(p..")."..c[2]) + print(string.format("%3d).%s",p,c[2])) end local ans repeat @@ -438,7 +440,7 @@ function ParseNames(path) end function getxyz() -- this will return pointers x,y and z coordinates. - local off=offsets.getEx("Xpointer") -- lets find where in memory its being held + local off=VersionInfo.getGroup("Position"):getAddress("cursor_xyz") -- lets find where in memory its being held -- now lets read them (they are double words (or unsigned longs or 4 bits each) and go in sucesion local x=engine.peekd(off) local y=engine.peekd(off+4) --next is 4 from start @@ -448,8 +450,8 @@ function getxyz() -- this will return pointers x,y and z coordinates. end function GetCreatureAtPos(x,y,z) -- gets the creature index @ x,y,z coord --local x,y,z=getxyz() --get 'X' coords - local vector=engine.peek(offsets.getEx("AdvCreatureVec"),ptr_vector) -- load all creatures - for i = 0, vector:size() do -- look into all creatures offsets + local vector=engine.peek(VersionInfo.getGroup("Creatures"):getAddress("vector"),ptr_vector) -- load all creatures + for i = 0, vector:size()-1 do -- look into all creatures offsets local curoff=vector:getval(i) -- get i-th creatures offset local cx=engine.peek(curoff,ptr_Creature.x) --get its coordinates local cy=engine.peek(curoff,ptr_Creature.y) diff --git a/plugins/Dfusion/luafiles/friendship/init.lua b/plugins/Dfusion/luafiles/friendship/init.lua new file mode 100644 index 000000000..12981d166 --- /dev/null +++ b/plugins/Dfusion/luafiles/friendship/init.lua @@ -0,0 +1,45 @@ +function analyzeF(off) + pos=offsets.find(off,0x39,ANYBYTE,0x8c,00,00,00) + print(string.format("Compare at:%x",pos)) + if pos ==0 then + return 0 + end + if(pos-off>0x100) then + print(string.format("Distance to cmp:%x",pos-off)) + pos =offsets.find(off,CALL) + print(string.format("Distance to call:%x",pos-off)) + return 0 + --return analyzeF(pos) + else + return pos + end +end +function minEx(...) + local imin=arg[1] + for _,v in ipairs(arg) do + if imin> v and v~=0 then + imin=v + end + end + return imin +end +function signDword(dw) + if(dw>0xFFFFFFFF) then + return dw-0xFFFFFFFF + end + return dw +end +--[[ + Warning: not all mov's are acounted for. Found one: mov EAX,WORD PTR[EBP+1EF4] WTF?? + Two more compares are missing. There are calls instead (same function) +]]-- + +friendship_in={} +dofile("dfusion/friendship/install.lua") +dofile("dfusion/friendship/patch.lua") + +function friendship(names) + friendship_in.install(names) + friendship_in.patch() +end + diff --git a/plugins/Dfusion/luafiles/friendship/plugin.lua b/plugins/Dfusion/luafiles/friendship/plugin.lua index e820a0ccd..633b30239 100644 --- a/plugins/Dfusion/luafiles/friendship/plugin.lua +++ b/plugins/Dfusion/luafiles/friendship/plugin.lua @@ -1,65 +1,19 @@ ---if(mypos~=0) then ---print("plugin already active") ---maybe set options for reinit? ---return ---end - -function analyzeF(off) - pos=offsets.find(off,0x39,ANYBYTE,0x8c,00,00,00) - print(string.format("Compare at:%x",pos)) - if pos ==0 then - return 0 - end - if(pos-off>0x100) then - print(string.format("Distance to cmp:%x",pos-off)) - pos =offsets.find(off,CALL) - print(string.format("Distance to call:%x",pos-off)) - return 0 - --return analyzeF(pos) - else - return pos - end -end -function minEx(...) - local imin=arg[1] - for _,v in ipairs(arg) do - if imin> v and v~=0 then - imin=v - end - end - return imin -end -function signDword(dw) - if(dw>0xFFFFFFFF) then - return dw-0xFFFFFFFF - end - return dw -end ---[[ - Warning: not all mov's are acounted for. Found one: mov EAX,WORD PTR[EBP+1EF4] WTF?? - Two more compares are missing. There are calls instead (same function) -]]-- if not(FILE) then ---print("race num:"..engine.peekw(offsets.getEx("CurrentRace"))) ---print(string.format("%x vs %x",offsets.getEx("CurrentRace"),VersionInfo.getGroup("Creatures"):getAddress("current_race"))) -add_race=VersionInfo.getGroup("Creatures"):getAddress("current_race") -print("Race num:"..engine.peekw(add_race)) -print("Your current race is:"..GetRaceToken(engine.peekw(add_race))) -print("If this is wrong please type 'q'") -if(io.stdin:read()=='q') then - return -end + --sanity test + --print("race num:"..engine.peekw(offsets.getEx("CurrentRace"))) + --print(string.format("%x vs %x",offsets.getEx("CurrentRace"),VersionInfo.getGroup("Creatures"):getAddress("current_race"))) + add_race=VersionInfo.getGroup("Creatures"):getAddress("current_race") + print("Race num:"..engine.peekw(add_race)) + print("Your current race is:"..GetRaceToken(engine.peekw(add_race))) + print("If this is wrong please type 'q'") + if(io.stdin:read()=='q') then + return + end + end -friendship_in={} -dofile("dfusion/friendship/install.lua") -dofile("dfusion/friendship/patch.lua") + if not(FILE) then names=ParseNames("dfusion/friendship/races.txt")--io.open("plugins/friendship/races.txt"):lines() friendship_in.install(names) friendship_in.patch() -end -function friendship(names) - friendship_in.install(names) - friendship_in.patch() -end - +end \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/init.lua b/plugins/Dfusion/luafiles/init.lua index d8307eaab..d5d067ea6 100644 --- a/plugins/Dfusion/luafiles/init.lua +++ b/plugins/Dfusion/luafiles/init.lua @@ -13,13 +13,23 @@ function dofile(filename) --safer dofile, with traceback (very usefull) print(perr) end end - +function dofile_silent(filename) --safer dofile, with traceback, no file not found error + f,perr=loadfile(filename) + if f~=nil then + return xpcall(f,err) + end +end +function loadall(t1) --loads all non interactive plugin parts, so that later they could be used + for k,v in pairs(t1) do + dofile_silent("dfusion/"..v[1].."/init.lua") + end +end function mainmenu(t1) Console.clear() while true do - print("No. Name Desc") + print("No. Name Desc") for k,v in pairs(t1) do - print(string.format("%d %s %s",k,v[1],v[2])) + print(string.format("%3d %15s %s",k,v[1],v[2])) end local q=Console.lineedit("Select plugin to run (q to quit):") if q=='q' then return end @@ -44,5 +54,9 @@ table.insert(plugins,{"adv_tools","some tools for (mainly) advneturer hacking"}) table.insert(plugins,{"tools","some misc tools"}) table.insert(plugins,{"triggers","a function calling plug (discontinued...)"}) table.insert(plugins,{"migrants","multi race imigrations"}) +table.insert(plugins,{"onfunction","run lua on some df function"}) +loadall(plugins) +if not INIT then mainmenu(plugins) +end diff --git a/plugins/Dfusion/luafiles/offsets.lua b/plugins/Dfusion/luafiles/offsets.lua index 9d684b62a..8349f73e3 100644 --- a/plugins/Dfusion/luafiles/offsets.lua +++ b/plugins/Dfusion/luafiles/offsets.lua @@ -1,7 +1,9 @@ function f_dwarves() - pos_=offsets.findall(0,0x24,0x14,0x07,0,0,0) --search pattern + --mov DWORD PTR [ESP+14],7 + --jmp +0x08 + pos_=offsets.findall(0,0x24,0x14,0x07,0,0,0) --search pattern for _,v in pairs(pos_) do print(string.format("Possible hit:%x",v)) end diff --git a/plugins/Dfusion/luafiles/onfunction/compile.bat b/plugins/Dfusion/luafiles/onfunction/compile.bat new file mode 100644 index 000000000..f06fb8c4c --- /dev/null +++ b/plugins/Dfusion/luafiles/onfunction/compile.bat @@ -0,0 +1 @@ +as -anl --32 -o functions.o functions.asm \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/onfunction/functions.asm b/plugins/Dfusion/luafiles/onfunction/functions.asm new file mode 100644 index 000000000..13ef23191 --- /dev/null +++ b/plugins/Dfusion/luafiles/onfunction/functions.asm @@ -0,0 +1,23 @@ +.intel_syntax +push eax +push ebp +push esp +push esi +push edi +push edx +push ecx +push ebx +push eax +mov eax,[esp+36] +push eax +function: +call 0xdeadbee0 +function2: +mov [0xdeadbeef],eax +pop eax +function3: +jmp [0xdeadbeef] + + + + diff --git a/plugins/Dfusion/luafiles/onfunction/functions.o b/plugins/Dfusion/luafiles/onfunction/functions.o new file mode 100644 index 000000000..7b7d4a33f Binary files /dev/null and b/plugins/Dfusion/luafiles/onfunction/functions.o differ diff --git a/plugins/Dfusion/luafiles/onfunction/init.lua b/plugins/Dfusion/luafiles/onfunction/init.lua new file mode 100644 index 000000000..52620ad10 --- /dev/null +++ b/plugins/Dfusion/luafiles/onfunction/init.lua @@ -0,0 +1,61 @@ +onfunction=onfunction or {} +function onfunction.install() + ModData=engine.installMod("dfusion/onfunction/functions.o","functions",4) + modpos=ModData.pos + modsize=ModData.size + onfunction.pos=modpos + trgpos=engine.getpushvalue() + print(string.format("Function installed in:%x function to call is: %x",modpos,trgpos)) + local firstpos=modpos+engine.FindMarker(ModData,"function") + engine.poked(firstpos,trgpos-firstpos-4) --call Lua-Onfunction + onfunction.fpos=modpos+engine.FindMarker(ModData,"function3") + engine.poked(modpos+engine.FindMarker(ModData,"function2"),modpos+modsize) + engine.poked(onfunction.fpos,modpos+modsize) + SetExecute(modpos) + onfunction.calls={} + onfunction.functions={} + onfunction.names={} + onfunction.hints={} +end +function OnFunction(values) + --[=[print("Onfunction called!") + print("Data:") + for k,v in pairs(values) do + print(string.format("%s=%x",k,v)) + end + print("stack:") + for i=0,3 do + print(string.format("%d %x",i,engine.peekd(values.esp+i*4))) + end + --]=] + if onfunction.functions[values.ret] ~=nil then + onfunction.functions[values.ret](values) + end + + return onfunction.calls[values.ret] --returns real function to call +end +function onfunction.patch(addr) + + if(engine.peekb(addr)~=0xe8) then + error("Incorrect address, not a function call") + else + + onfunction.calls[addr+5]=addr+engine.peekd(addr+1)+5 --adds real function to call + engine.poked(addr+1,engine.getmod("functions")-addr-5) + end +end +function onfunction.AddFunction(addr,name,hints) + onfunction.patch(addr) + onfunction.names[name]=addr+5 + if hints~=nil then + onfunction.hints[name]=hints + end +end +function onfunction.SetCallback(name,func) + if onfunction.names[name]==nil then + error("No such function:"..name) + else + onfunction.functions[onfunction.names[name]]=func + end +end + diff --git a/plugins/Dfusion/luafiles/onfunction/locations.lua b/plugins/Dfusion/luafiles/onfunction/locations.lua new file mode 100644 index 000000000..2f6e4d80c --- /dev/null +++ b/plugins/Dfusion/luafiles/onfunction/locations.lua @@ -0,0 +1,7 @@ +if WINDOWS then --windows function defintions + onfunction.AddFunction(0x55499D+offsets.base(),"Move") --on creature move found with "watch mem=xcoord" + onfunction.AddFunction(0x275933+offsets.base(),"Die",{creature="edi"}) --on creature death? found by watching dead flag then stepping until new function +else --linux + onfunction.AddFunction(0x899befe+offsets.base(),"Move") -- found out by attaching watch... + onfunction.AddFunction(0x850eecd+offsets.base(),"Die",{creature="ebx"}) -- same +end diff --git a/plugins/Dfusion/luafiles/onfunction/plugin.lua b/plugins/Dfusion/luafiles/onfunction/plugin.lua new file mode 100644 index 000000000..7c76af122 --- /dev/null +++ b/plugins/Dfusion/luafiles/onfunction/plugin.lua @@ -0,0 +1,14 @@ +mypos=engine.getmod("functions") +function DeathMsg(values) + local name + name=engine.peek(values[onfunction.hints["Die"].creature],ptt_dfstring) + print(name:getval().." died") +end +if mypos then + print("Onfunction already installed") + --onfunction.patch(0x189dd6+offsets.base()) +else + onfunction.install() + dofile("dfusion/onfunction/locations.lua") + onfunction.SetCallback("Die",DeathMsg) +end diff --git a/plugins/Dfusion/luafiles/patterns.lua b/plugins/Dfusion/luafiles/patterns.lua index f4ac43650..1d15741eb 100644 --- a/plugins/Dfusion/luafiles/patterns.lua +++ b/plugins/Dfusion/luafiles/patterns.lua @@ -1,50 +1,51 @@ ptt_dfstring={} -if(COMPATMODE) then -ptt_dfstring.ptr={off=4,rtype=DWORD} -ptt_dfstring.size={off=20,rtype=DWORD} +if WINDOWS then + ptt_dfstring.ptr={off=0,rtype=DWORD} + ptt_dfstring.size={off=16,rtype=DWORD} + ptt_dfstring.alloc={off=20,rtype=DWORD} -else -ptt_dfstring.ptr={off=0,rtype=DWORD} -ptt_dfstring.size={off=16,rtype=DWORD} -ptt_dfstring.alloc={off=20,rtype=DWORD} -end -function ptt_dfstring:getval() - --print(string.format("GETTING FROM:%x",self.__offset)) - if self.size<16 then + function ptt_dfstring:getval() --print(string.format("GETTING FROM:%x",self.__offset)) - return string.sub(engine.peekstr(self.__offset),1,self.size) - else - --print(string.format("GETTING FROM:%x",self.ptr)) - return string.sub(engine.peekstr(self.ptr),1,self.size) + if self.size<16 then + --print(string.format("GETTING FROM:%x",self.__offset)) + return string.sub(engine.peekstr(self.__offset),1,self.size) + else + --print(string.format("GETTING FROM:%x",self.ptr)) + return string.sub(engine.peekstr(self.ptr),1,self.size) + end end -end -function ptt_dfstring:setval(newstring) - local offset=self.__offset - local strl=string.len(newstring) - if strl<16 then - --print(string.format("GETTING FROM:%x",self.__offset)) + function ptt_dfstring:setval(newstring) + local offset=self.__offset + local strl=string.len(newstring) + if strl<16 then + --print(string.format("GETTING FROM:%x",self.__offset)) - engine.poked(offset+ptt_dfstring.size.off,strl) - engine.poked(offset+ptt_dfstring.alloc.off,15) - engine.pokestr(offset,newstring) + engine.poked(offset+ptt_dfstring.size.off,strl) + engine.poked(offset+ptt_dfstring.alloc.off,15) + engine.pokestr(offset,newstring) - else - local loc - if engine.peekd(offset+ptt_dfstring.alloc.off) > strl then - loc=engine.peekd(offset) - print("Will fit:"..loc.." len:"..strl) else - loc=Allocate(strl+1) - engine.poked(offset+ptt_dfstring.alloc.off,strl) - print("Will not fit:"..loc.." len:"..strl) + local loc + if engine.peekd(offset+ptt_dfstring.alloc.off) > strl then + loc=engine.peekd(offset) + print("Will fit:"..loc.." len:"..strl) + else + loc=Allocate(strl+1) + engine.poked(offset+ptt_dfstring.alloc.off,strl) + print("Will not fit:"..loc.." len:"..strl) + end + --print(string.format("GETTING FROM:%x",self.ptr)) + engine.poked(self.__offset+ptt_dfstring.size.off,strl) + engine.pokestr(loc,newstring) + engine.poked(self.__offset,loc) end - --print(string.format("GETTING FROM:%x",self.ptr)) - engine.poked(self.__offset+ptt_dfstring.size.off,strl) - engine.pokestr(loc,newstring) - engine.poked(self.__offset,loc) + end +else + --ptt_dfstring.ptr={off=0,rtype=DWORD} + function ptt_dfstring:getval() + return engine.peekstr_stl(self.__offset) end end - --if(COMPATMODE) then --ptr_vector={} --ptr_vector.st={off=4,rtype=DWORD} @@ -169,10 +170,11 @@ end ]]-- ptr_Creature={} -ptr_Creature.x={off=144,rtype=WORD} --ok -ptr_Creature.y={off=146,rtype=WORD} --ok -ptr_Creature.z={off=148,rtype=WORD} --ok -ptr_Creature.flags={off=224,rtype=ptt_dfflag.new(10)} +local posoff=VersionInfo.getGroup("Creatures"):getGroup("creature"):getOffset("position") +ptr_Creature.x={off=posoff,rtype=WORD} --ok +ptr_Creature.y={off=posoff+2,rtype=WORD} --ok +ptr_Creature.z={off=posoff+4,rtype=WORD} --ok +ptr_Creature.flags={off=VersionInfo.getGroup("Creatures"):getGroup("creature"):getOffset("flags1"),rtype=ptt_dfflag.new(10)} ptr_Creature.name={off=0,rtype=ptt_dfstring} ptr_Creature.ID={off=252,rtype=DWORD} --ok i guess ptr_Creature.followID={off=592,rtype=DWORD} --ok diff --git a/plugins/Dfusion/luafiles/triggers/functions.lua b/plugins/Dfusion/luafiles/triggers/functions.lua index d5fca0773..e6c3a62c9 100644 --- a/plugins/Dfusion/luafiles/triggers/functions.lua +++ b/plugins/Dfusion/luafiles/triggers/functions.lua @@ -4,7 +4,7 @@ function func.Find_Print() end function func.PrintMessage(msg,color1,color2) func.f_print_pos= func.f_print_pos or func.Find_Print() - --print(string.format("%x",func.f_print_pos)) + print(string.format("Print @:%x",func.f_print_pos)) debuger.suspend() d=NewCallTable() -- make a call table t=Allocate(string.len(msg)) diff --git a/plugins/Dfusion/src/lua_Misc.cpp b/plugins/Dfusion/src/lua_Misc.cpp index aacf65e2b..be1de4a24 100644 --- a/plugins/Dfusion/src/lua_Misc.cpp +++ b/plugins/Dfusion/src/lua_Misc.cpp @@ -129,6 +129,40 @@ static int GetMod(lua_State *L) st.push(pos); return 1; } +static size_t __attribute__((stdcall)) PushValue(size_t ret,uint32_t eax,uint32_t ebx,uint32_t ecx,uint32_t edx,uint32_t edi,uint32_t esi,uint32_t esp,uint32_t ebp) +{ + lua::state st=lua::glua::Get(); + st.getglobal("OnFunction"); + if(st.is()) + return 0; + st.newtable(); + st.push(eax); + st.setfield("eax"); + st.push(ebx); + st.setfield("ebx"); + st.push(ecx); + st.setfield("ecx"); + st.push(edx); + st.setfield("edx"); + st.push(edi); + st.setfield("edi"); + st.push(esi); + st.setfield("esi"); + st.push(esp); + st.setfield("esp"); + st.push(ebp); + st.setfield("ebp"); + st.push(ret); + st.setfield("ret"); + st.pcall(1,1); + return st.as(); +} +static int Get_PushValue(lua_State *L) +{ + lua::state st(L); + st.push((uint32_t)&PushValue); + return 1; +} const luaL_Reg lua_misc_func[]= { {"loadmod",LoadMod}, @@ -137,6 +171,7 @@ const luaL_Reg lua_misc_func[]= {"loadobjsymbols",LoadObjSymbols}, {"findmarker",FindMarker}, {"newmod",NewMod}, + {"getpushvalue",Get_PushValue}, {NULL,NULL} }; void lua::RegisterMisc(lua::state &st) @@ -149,4 +184,4 @@ void lua::RegisterMisc(lua::state &st) } lua::RegFunctionsLocal(st, lua_misc_func); st.setglobal("engine"); -} \ No newline at end of file +} diff --git a/plugins/memview.cpp b/plugins/memview.cpp new file mode 100644 index 000000000..7c57d010a --- /dev/null +++ b/plugins/memview.cpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; +using std::string; +using namespace DFHack; + +DFhackCExport command_result memview (Core * c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "memview"; +} + +DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate.",memview)); + return CR_OK; +} +size_t convert(const std::string& p,bool ishex=false) +{ + size_t ret; + std::stringstream conv; + if(ishex) + conv<>ret; + return ret; +} +bool isAddr(uint32_t *trg,vector & ranges) +{ + if(trg[0]%4==0) + for(size_t i=0;i & ranges) +{ + + con.clear(); + const size_t page_size=16; + for(size_t i=0;i20) + con.print("%c",buf[j+i]); + else + con.print("."); + con.print("\n"); + } +} +DFhackCExport command_result memview (Core * c, vector & parameters) +{ + size_t addr=convert(parameters[0],true); + size_t len; + if(parameters.size()>1) + len=convert(parameters[1]); + else + len=20*16; + size_t refresh; + if(parameters.size()>2) + refresh=convert(parameters[2]); + else + refresh=0; + Console &con=c->con; + uint8_t *buf,*lbuf; + buf=new uint8_t[len]; + lbuf=new uint8_t[len]; + uint64_t timeLast=0; + vector ranges; + c->p->getMemRanges(ranges); + while(true)//TODO add some sort of way to exit loop??!! + { + uint64_t time2 = GetTimeMs64(); + uint64_t delta = time2-timeLast; + if(refresh!=0) + if(deltap->read(addr,len,buf); + outputHex(buf,lbuf,len,addr,con,ranges); + if(refresh==0) + break; + memcpy(lbuf, buf, len); + } + delete[] buf; + delete[] lbuf; +}