Petr Mrázek 2011-08-23 13:47:04 +02:00
commit 8ab5697f4a
21 changed files with 516 additions and 214 deletions

@ -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))

@ -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)

@ -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)

@ -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 <string> & parameters);
@ -37,15 +38,23 @@ DFhackCExport const char * plugin_name ( void )
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &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: <filename> = run <filename> 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 <filename>' to run <filename> 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 <string> & parameters)
mymutex->unlock();
return CR_OK;
}
DFhackCExport command_result dfusion (Core * c, vector <string> & parameters)
void RunDfusion(void *p)
{
Console &con=c->con;
Console &con=static_cast<Core*>(p)->con;
mymutex->lock();
lua::state s=lua::glua::Get();
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 <string> & 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 <string> & 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;
}

@ -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

@ -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

@ -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)

@ -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

@ -1,45 +1,5 @@
--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
--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")
@ -49,17 +9,11 @@ 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

@ -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")
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

@ -1,6 +1,8 @@
function f_dwarves()
--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))

@ -0,0 +1 @@
as -anl --32 -o functions.o 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]

@ -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

@ -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

@ -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

@ -1,13 +1,9 @@
ptt_dfstring={}
if(COMPATMODE) then
ptt_dfstring.ptr={off=4,rtype=DWORD}
ptt_dfstring.size={off=20,rtype=DWORD}
else
if WINDOWS then
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
@ -44,7 +40,12 @@ function ptt_dfstring:setval(newstring)
engine.poked(self.__offset,loc)
end
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

@ -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))

@ -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<lua::nil>())
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<uint32_t>();
}
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)

@ -0,0 +1,114 @@
#include <dfhack/Core.h>
#include <dfhack/Console.h>
#include <dfhack/PluginManager.h>
#include <dfhack/Process.h>
#include <dfhack/extra/stopwatch.h>
#include <string>
#include <vector>
#include <sstream>
using std::vector;
using std::string;
using namespace DFHack;
DFhackCExport command_result memview (Core * c, vector <string> & parameters);
DFhackCExport const char * plugin_name ( void )
{
return "memview";
}
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &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<<std::hex;
conv<<p;
conv>>ret;
return ret;
}
bool isAddr(uint32_t *trg,vector<t_memrange> & ranges)
{
if(trg[0]%4==0)
for(size_t i=0;i<ranges.size();i++)
if(ranges[i].isInRange(trg[0]))
return true;
return false;
}
void outputHex(uint8_t *buf,uint8_t *lbuf,size_t len,size_t start,Console &con,vector<t_memrange> & ranges)
{
con.clear();
const size_t page_size=16;
for(size_t i=0;i<len;i+=page_size)
{
con.print("%8x ",i+start);
for(size_t j=0;(j<page_size) && (i+j<len);j++)
{
if(j%4==0)
{
con.reset_color();
if(isAddr((uint32_t *)(buf+j+i),ranges))
con.color(Console::COLOR_LIGHTRED);
}
if(lbuf[j+i]!=buf[j+i])
con.print("*%2x",buf[j+i]);
else
con.print(" %2x",buf[j+i]);
}
con.reset_color();
con.print(" | ");
for(size_t j=0;(j<page_size) && (i+j<len);j++)
if(buf[j+i]>20)
con.print("%c",buf[j+i]);
else
con.print(".");
con.print("\n");
}
}
DFhackCExport command_result memview (Core * c, vector <string> & 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<t_memrange> 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(delta<refresh)
continue;
timeLast = time2;
c->p->read(addr,len,buf);
outputHex(buf,lbuf,len,addr,con,ranges);
if(refresh==0)
break;
memcpy(lbuf, buf, len);
}
delete[] buf;
delete[] lbuf;
}