From 86ec66c0fb69face59182192766b2280dfea5238 Mon Sep 17 00:00:00 2001 From: Warmist Date: Sun, 21 Oct 2012 13:42:55 +0300 Subject: [PATCH] More work on dfusion. Embark anywhere script separated. --- plugins/Dfusion/dfusion.cpp | 20 ++++ plugins/Dfusion/luafiles/embark/init.lua | 137 ++++++++--------------- plugins/devel/CMakeLists.txt | 1 - plugins/lua/dfusion.lua | 113 ++++++++++++------- scripts/dfusion.lua | 2 + scripts/embark.lua | 53 +++++++++ 6 files changed, 196 insertions(+), 130 deletions(-) create mode 100644 scripts/dfusion.lua create mode 100644 scripts/embark.lua diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index daacc0b26..4507f9a15 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -58,8 +58,28 @@ static int loadObjectFile(lua_State* L) lua_setfield(L,table_pos,"symbols"); return 1; } +static int markAsExecutable(lua_State* L) +{ + unsigned addr=luaL_checkunsigned(L,1); + std::vector ranges; + DFHack::Core::getInstance().p->getMemRanges(ranges); + for(size_t i=0;isetPermisions(ranges[i],newperm); + return 0; + } + } + lua_pushlstring(L,"Memory range not found",23); + lua_error(L); + return 0; +} DFHACK_PLUGIN_LUA_COMMANDS { DFHACK_LUA_COMMAND(loadObjectFile), + DFHACK_LUA_COMMAND(markAsExecutable), DFHACK_LUA_END }; DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) diff --git a/plugins/Dfusion/luafiles/embark/init.lua b/plugins/Dfusion/luafiles/embark/init.lua index aa8f2822d..76be00c72 100644 --- a/plugins/Dfusion/luafiles/embark/init.lua +++ b/plugins/Dfusion/luafiles/embark/init.lua @@ -1,108 +1,69 @@ -local dfu=require("dfusion") +local dfu=require("plugins.dfusion") local ms=require("memscan") - +local MAX_RACES=100 CustomEmbark=defclass(CustomEmbark,dfu.BinaryPlugin) CustomEmbark.ATTRS{filename="dfusion/embark/embark.o",name="CustomEmbark",race_caste_data=DEFAULT_NIL} function CustomEmbark:install() local stoff=dfhack.internal.getAddress('start_dwarf_count') + if #self.race_caste_data<7 then + error("caste and race count must be bigger than 6") + end + if #self.race_caste_data>MAX_RACES then + error("caste and race count must be less then "..MAX_RACES) + end if stoff==nil then error("address for start_dwarf_count not found!") end local _,race_id_offset=df.sizeof(df.global.ui:_field("race_id")) - local needle={0x0f,0xb7,0x0d} --movzx,... - add_dword(needle,race_id_offset) -- ...word ptr[] + print(string.format("start=%08x",stoff)) + local needle={0x0f,0xb7,0x0d} --movzx eax,dword ptr [race_id] + local tmp_table=dfu.dwordToTable(race_id_offset) + for k,v in ipairs(tmp_table) do + table.insert(needle,v) + end + local mem=ms.get_code_segment() - local trg_offset=mem.uint8_t.find(needle,stoff)--maybe endoff=stoff+bignumber + print(mem.uint8_t:addr2idx(stoff)) + print(mem.uint8_t:find(needle,mem.uint8_t:addr2idx(stoff))) + local _,trg_offset=mem.uint8_t:find(needle,mem.uint8_t:addr2idx(stoff),nil)--maybe endoff=stoff+bignumber if trg_offset==nil then error("address for race_load not found") end + local call_data={0x90,0x90} + local _,data_offset=df.sizeof(self.data) + dfu.concatTables(call_data,dfu.makeCall(trg_offset+2,data_offset)) + self.call_patch=dfu.BinaryPatch{pre_data=needle,data=call_data,address=trg_offset,name="custom_embark_call_patch"} needle={0x83,0xc8,0xff} -- or eax, 0xFF - local caste_offset=mem.uint8_t.find(needle,trg_offset) + local _,caste_offset=mem.uint8_t:find(needle,mem.uint8_t:addr2idx(trg_offset),nil) if caste_offset==nil or caste_offset-stoff>1000 then error("Caste change code not found or found too far!") end + self.disable_castes=dfu.BinaryPatch{pre_data={0x83,0xc8,0xff},data={0x90,0x90,0x90},address=caste_offset,name="custom_embark_caste_disable"} + self.disable_castes:apply() + self.dwarfcount=dfu.BinaryPatch{pre_data=dfu.dwordToTable(7),data=dfu.dwordToTable(#self.race_caste_data),address=stoff,name="custom_embark_embarkcount"} + self.dwarfcount:apply() + local caste_array=self:allocate("caste_array","uint16_t",#self.race_caste_data) + local race_array=self:allocate("race_array","uint16_t",#self.race_caste_data) + for k,v in ipairs(self.race_caste_data) do + caste_array[k-1]=v[2] + race_array[k-1]=v[1] + end + local race_array_off,caste_array_off + local _ + _,race_array_off=df.sizeof(race_array) + _,caste_array_off=df.sizeof(caste_array) + self:set_marker_dword("race",caste_array_off) --hehe... mixed them up i guess... + self:set_marker_dword("caste",race_array_off) + + self:move_to_df() + self.call_patch:apply() + self.installed=true end -function MakeTable(modpos,modsize,names) - count=0 - castes={} - --print("Making table") - for _,line in pairs(names) do - --print("Line:"..line) - tpos=string.find(line,":") - if tpos~=nil then - --print("Was line:"..line) - table.insert(castes,tonumber(string.sub(line,tpos+1))) - line=string.sub(line,1,tpos-1) - --print("IS line:"..line) - else - table.insert(castes,-1) - end - if RaceTable[line] == nil then - error("Failure, "..line.." not found!") - end - --print("adding:"..line.." id:"..RaceTable[line]) - engine.pokew(modpos+modsize+count*2,RaceTable[line]) -- add race - count = count + 1 - end - i=0 - for _,caste in pairs(castes) do - - engine.pokew(modpos+modsize+count*2+i*2,caste) -- add caste - i= i+1 - end - - engine.poked(stoff,count) - return count -end -function embark(names) - RaceTable=RaceTable or BuildNameTable() - mypos=engine.getmod('Embark') - stoff=VersionInfo.getAddress('start_dwarf_count') - if mypos then --if mod already loaded - print("Mod already loaded @:"..mypos.." just updating") - modpos=mypos - _,modsize=engine.loadobj('dfusion/embark/embark.o') - - count=MakeTable(modpos,modsize,names) --just remake tables - else - - _,tofind=df.sizeof(df.global.ui:_field("race_id")) - - loc=offsets.find(stoff,0x0f,0xb7,0x0d,DWORD_,tofind) --MOVZX ECX,WORD PTR[] - - print(string.format("found:%x",loc)) - if((loc~=0)and(loc-stoff<1000)) then - loc2=offsets.find(loc,0x83,0xc8,0xff) -- or eax, ffffff (for caste) - if loc2== 0 then - error ("Location for caste nulling not found!") - end - engine.pokeb(loc2,0x90) - engine.pokeb(loc2+1,0x90) - engine.pokeb(loc2+2,0x90) - ModData=engine.installMod("dfusion/embark/embark.o","Embark",256) - modpos=ModData.pos - modsize=ModData.size - local castepos=modpos+engine.FindMarker(ModData,"caste") - local racepos=modpos+engine.FindMarker(ModData,"race") - count=MakeTable(modpos,modsize,names) - engine.poked(castepos,modpos+modsize) --fix array start for race - engine.poked(racepos,modpos+modsize+count*2) --fix array start for caste - print("sucess loading mod @:"..modpos) - -- build race vector after module. - - - --finaly poke in the call! - engine.pokeb(loc,0x90) - engine.pokeb(loc+1,0x90) - engine.pokeb(loc+2,0xe8) - engine.poked(loc+3,modpos-loc-7) - --engine.pokeb(loc+5,0x90) - - SetExecute(modpos) - else - error("did not find patch location, failing...") - end - - end +function CustomEmbark:uninstall() + if self.installed then + self.call_patch:remove() + self.disable_castes:remove() + self.dwarfcount:remove() + end end \ No newline at end of file diff --git a/plugins/devel/CMakeLists.txt b/plugins/devel/CMakeLists.txt index f126ae53b..134d5cb67 100644 --- a/plugins/devel/CMakeLists.txt +++ b/plugins/devel/CMakeLists.txt @@ -18,7 +18,6 @@ DFHACK_PLUGIN(stripcaged stripcaged.cpp) DFHACK_PLUGIN(rprobe rprobe.cpp) DFHACK_PLUGIN(nestboxes nestboxes.cpp) DFHACK_PLUGIN(vshook vshook.cpp) -DFHACK_PLUGIN(steam-engine steam-engine.cpp) IF(UNIX) DFHACK_PLUGIN(ref-index ref-index.cpp) ENDIF() diff --git a/plugins/lua/dfusion.lua b/plugins/lua/dfusion.lua index 06128d29b..46f28f78e 100644 --- a/plugins/lua/dfusion.lua +++ b/plugins/lua/dfusion.lua @@ -4,8 +4,23 @@ local _ENV = mkmodule('plugins.dfusion') local ms=require("memscan") local marker={0xDE,0xAD,0xBE,0xEF} -patches={} +--utility functions +function dwordToTable(dword) + local b={bit32.extract(dword,0,8),bit32.extract(dword,8,8),bit32.extract(dword,16,8),bit32.extract(dword,24,8)} + return b +end +function concatTables(t1,t2) + for k,v in pairs(t2) do + table.insert(t1,v) + end +end +function makeCall(from,to) + local ret={0xe8} + concatTables(ret,dwordToTable(to-from-5)) + return ret +end -- A reversable binary patch +patches={} BinaryPatch=defclass(BinaryPatch) BinaryPatch.ATTRS {pre_data=DEFAULT_NIL,data=DEFAULT_NIL,address=DEFAULT_NIL,name=DEFAULT_NIL} function BinaryPatch:init(args) @@ -16,19 +31,8 @@ function BinaryPatch:init(args) if patches[self.name]~=nil then error("Patch already exist") end - self.max_val=0 - for k,v in pairs(args.pre_data) do - if type(k)~="number" then - error("non number key in pre_data") - end - if self.max_val