From f4179652fa97cde183872aeb1ac26ffbb65a699d Mon Sep 17 00:00:00 2001 From: Warmist Date: Wed, 3 Aug 2011 16:07:57 +0300 Subject: [PATCH 01/10] Lots of changes, including hexsearch and wrapper for lua, also LUNE - an object oriented lua wrapper --- plugins/Dfusion/dfusion.cpp | 2 + plugins/Dfusion/include/hexsearch.h | 35 +++ plugins/Dfusion/include/lua_Hexsearch.h | 33 ++ plugins/Dfusion/include/luamain.h | 2 +- plugins/Dfusion/include/lune.h | 361 ++++++++++++++++++++++ plugins/Dfusion/luafiles/common.lua | 39 +-- plugins/Dfusion/luafiles/init.lua | 15 +- plugins/Dfusion/luafiles/itempatterns.lua | 62 ++++ plugins/Dfusion/luafiles/patterns.lua | 243 +++++++++++++++ plugins/Dfusion/luafiles/patterns2.lua | 29 ++ plugins/Dfusion/src/hexsearch.cpp | 74 +++++ plugins/Dfusion/src/lua_Hexsearch.cpp | 57 ++++ plugins/Dfusion/src/lune.cpp | 2 + 13 files changed, 927 insertions(+), 27 deletions(-) create mode 100644 plugins/Dfusion/include/hexsearch.h create mode 100644 plugins/Dfusion/include/lua_Hexsearch.h create mode 100644 plugins/Dfusion/include/lune.h create mode 100644 plugins/Dfusion/luafiles/itempatterns.lua create mode 100644 plugins/Dfusion/luafiles/patterns.lua create mode 100644 plugins/Dfusion/luafiles/patterns2.lua create mode 100644 plugins/Dfusion/src/hexsearch.cpp create mode 100644 plugins/Dfusion/src/lua_Hexsearch.cpp create mode 100644 plugins/Dfusion/src/lune.cpp diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index 4b6a33710..45aa3c687 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -14,6 +14,7 @@ #include "luamain.h" #include "lua_Console.h" #include "lua_Process.h" +#include "lua_Hexsearch.h" #include "functioncall.h" using std::vector; @@ -37,6 +38,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector //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()); commands.push_back(PluginCommand("dfusion","Init dfusion system.",dfusion)); commands.push_back(PluginCommand("lua", "Run interactive interpreter.\ \n Options: = run instead",lua_run)); diff --git a/plugins/Dfusion/include/hexsearch.h b/plugins/Dfusion/include/hexsearch.h new file mode 100644 index 000000000..335bfebde --- /dev/null +++ b/plugins/Dfusion/include/hexsearch.h @@ -0,0 +1,35 @@ +#ifndef HEXSEARCH_H +#define HEXSEARCH_H +#include +#include "dfhack/Core.h" //for some reason process.h needs core +#include "dfhack/Process.h" + +//(not yet)implemented using Boyer-Moore algorithm + +class Hexsearch +{ +public: + typedef std::vector SearchArgType; + enum SearchConst //TODO add more + { + ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS + }; + + Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos); + ~Hexsearch(); + + void Reset(){pos_=startpos_;}; + void SetStart(uint64_t pos){pos_=pos;}; + + uint64_t FindNext(); + std::vector FindAll(); + +private: + SearchArgType args_; + uint64_t pos_,startpos_,endpos_; + std::vector BadCharShifts,GoodSuffixShift; + void PrepareGoodSuffixTable(); + void PrepareBadCharShift(); +}; + +#endif \ No newline at end of file diff --git a/plugins/Dfusion/include/lua_Hexsearch.h b/plugins/Dfusion/include/lua_Hexsearch.h new file mode 100644 index 000000000..030db079e --- /dev/null +++ b/plugins/Dfusion/include/lua_Hexsearch.h @@ -0,0 +1,33 @@ +#ifndef LUA_HEXSEARCH_H +#define LUA_HEXSEARCH_H +#include "hexsearch.h" + +#include "luamain.h" + + + +namespace lua +{ + +class Hexsearch +{ + int tblid; + ::Hexsearch *p; +public: + Hexsearch(lua_State *L,int id); + ~Hexsearch(); + + int GetTableId(){return tblid;}; + + int find(lua_State *L); + int findall(lua_State *L); + int reset(lua_State *L); + + DEF_LUNE(Hexsearch); +}; +void RegisterHexsearch(lua::state &st);//TODO remake into OO oriented thing + +} + + +#endif \ No newline at end of file diff --git a/plugins/Dfusion/include/luamain.h b/plugins/Dfusion/include/luamain.h index aee073729..89524a52d 100644 --- a/plugins/Dfusion/include/luamain.h +++ b/plugins/Dfusion/include/luamain.h @@ -11,7 +11,7 @@ extern "C" { #include "lualib.h" } -//#include "lune.h" +#include "lune.h" #include "luaxx.hpp" namespace lua diff --git a/plugins/Dfusion/include/lune.h b/plugins/Dfusion/include/lune.h new file mode 100644 index 000000000..9acd80cc2 --- /dev/null +++ b/plugins/Dfusion/include/lune.h @@ -0,0 +1,361 @@ +#ifndef LUNE_H +#define LUNE_H + +extern "C" { +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#include "luaxx.hpp" +#include + +namespace lua +{ + class object + { + state &myst; + int myref; + public: + object(state &myst):myst(myst) + { + myref=luaL_ref(myst,LUA_REGISTRYINDEX); + } + ~object() + { + luaL_unref(myst,LUA_REGISTRYINDEX,myref); + } + void Get() + { + lua_rawgeti(myst,LUA_REGISTRYINDEX,myref); + } + state &GetState(){return myst;}; + }; + + class local_object + { + state myst; + int myref; + static object *mytbl; + public: + local_object(lua_State *L) + { + + myst=state(L); + //LOG<<"Creating local object...\n"; + //StackDump(L); + if(!mytbl) + { + //LOG<<" Metable...\n"; + myst.newtable(); //2 + if(myst.newmetatable("WEAKTABLE"))//3 + { + //StackDump(L); + myst.push("kv"); //4 + myst.setfield("__mode");//3 + //LOG<<" Setting Metable...\n"; + //StackDump(L); + } + //LOG<<" Attaching to holder...\n"; + + //myst.setfield("__metatable");//2 + lua_setmetatable(myst,-1); + mytbl=new object(myst); + //StackDump(L); + //LOG<<" Done Metatable...\n"; + } + //StackDump(L); + mytbl->Get(); + //LOG<<" Got my table...\n"; + //StackDump(L); + myst.insert(-2); + myref=luaL_ref(myst,-2); + //LOG<<"Before pop:"; + //StackDump(L); + myst.pop(1); + GetTable(); + //LOG<<"========Done...\n"<<"Ref="<Get(); + //StackDump(L); + //LOG<<"===========================\n"; + } + ~local_object() + { + //LOG<<"Deleting local object...\n"; + ReleaseTable(); + } + void ReleaseTable() + { + mytbl->Get(); + int pos=myst.gettop(); + luaL_unref(myst,pos,myref); + myst.remove(pos); + } + state GetState(){return myst;} + void GetTable() + { + //LOG<<"Getting ref="<Get(); + int pos=myst.gettop(); + //StackDump(myst); + //LOG<<"Tbl get\n"; + //int pos=myst.gettop(); + lua_rawgeti(myst,pos,myref); + //StackDump(myst); + //LOG<<"Done\n"; + myst.remove(pos); + } + protected: + + }; +}; + +template +class Lune +{ +public: + typedef struct + { + T *pT; + int tableref; + } userdataType; + + typedef int (T::*mfp)(lua_State *L); + typedef struct + { + const char *name; + mfp mfunc; + } RegType; + + static void Register(lua_State *L) + { + lua_newtable(L); + int methods = lua_gettop(L); + + luaL_newmetatable(L, T::className); + int metatable = lua_gettop(L); + + // store method table in globals so that + // scripts can add functions written in Lua. + lua_pushstring(L, T::className); + lua_pushvalue(L, methods); + lua_settable(L, LUA_GLOBALSINDEX); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methods); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, index_T); + lua_settable(L, metatable); + + //lua_pushliteral(L, "__name"); + //lua_pushstring(L, T::className); + //lua_settable(L, metatable); + + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, newindex_T); + lua_settable(L, metatable); + + lua_pushliteral(L, "__instances"); + lua_newtable(L); + lua_settable(L, metatable); + if(GC) + { + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_T); + lua_settable(L, metatable); + } + + + lua_newtable(L); // metatable for method table + int mt = lua_gettop(L); + lua_pushliteral(L, "__call"); + lua_pushcfunction(L, new_T); + lua_pushliteral(L, "new"); + lua_pushvalue(L, -2); // dup new_T function + lua_settable(L, methods); // add new_T to method table + lua_settable(L, mt); // mt.__call = new_T + lua_setmetatable(L, methods); + //LOG<<"lune: registered class \""<name; l++) + { + /* edited by Snaily: shouldn't it be const RegType *l ... ? */ + lua_pushstring(L, l->name); + lua_pushlightuserdata(L, (void*)l); + lua_pushcclosure(L, thunk, 1); + lua_settable(L, methods); + //LOG<<"lune: method \""<name<<"\"\n"; + } + + lua_pop(L, 2); // drop metatable and method table + }; + static void GetTable(lua_State *L,T *p) + { + GetTableEx(L,p->GetTableId()); + } + static void GetTableEx(lua_State *L,int id) + { + lua::state s(L); + s.getmetatable(T::className); + s.getfield("__instances"); + int ins=s.gettop(); + lua_rawgeti(L, ins, id); + s.insert(-3); + s.pop(2); + } + static T *check(lua_State *L, int narg) + { + userdataType *ud = + static_cast(luaL_checkudata(L, narg, T::className)); //TODO FIX THIs.. + //(lua_touserdata(L, narg));// + if(!ud) luaL_typerror(L, narg, T::className); + return ud->pT; // pointer to T object + } +protected: +private: + + static int RegTable(lua_State *L) + { + // LOG<<"Regging....\n"; + //lua::StackDump(L); + + lua::state s(L); + int ssize=s.gettop(); + //s.getglobal(T::className); + s.getmetatable(T::className); + s.getfield("__instances"); + int ins=s.gettop(); + s.newtable(); + int id=luaL_ref(L,ins); + //LOG<<"After reg:\n"; + //lua::StackDump(L); + s.settop(ssize); + return id; + } + static void UnregTable(lua_State *L,int id) + { + lua::state s(L); + s.getmetatable(T::className); + s.getfield("__instances"); + int ins=s.gettop(); + //LOG<<"Unreg table id:"<(-1); + T *p=check(L,1); + GetTable(L,p); + st.insert(-2); + //LOG<<"Index:\n"; + //lua::StackDump(L); + lua_rawget(L,-2); //try getting from normal table + if(st.is()) //failed + { + st.pop(2); + st.getglobal(T::className); //try class tables then + st.push(key); + st.gettable(); + } + return 1; + } + static int newindex_T(lua_State *L) + { + //LOG<<"New index....\n"; + //lua::StackDump(L); + + lua::state st(L); + T *p=check(L,1); + GetTable(L,p); + //st.insert(-3); + //LOG<<"Before set:\n"; + st.insert(-3); + //lua::StackDump(L); + lua_rawset(L,-3); + return 0; + } + static int thunk(lua_State *L) + { + //LOG<<"Size of stack:"<(lua_touserdata(L,1))->pT; + lua_remove(L, 1); // remove self so member function args start at index 1 + // get member function from upvalue + RegType *l = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + return (obj->*(l->mfunc))(L); // call member function + } + static int gc_T(lua_State *L) + { + //lua_getfield(L,,"__ud"); + //LOG<<"Garbage collecting.\n"; + //lua::StackDump(L); + userdataType *ud = static_cast(lua_touserdata(L, 1)); + T *obj = ud->pT; + + delete obj; // call destructor for T objects + UnregTable(L,ud->tableref); + return 0; + } + static int new_T(lua_State *L) + { + //LOG<<"Pre build:"<(lua_newuserdata(L, sizeof(userdataType))); + //lua::StackDump(L); + luaL_getmetatable(L, T::className); // lookup metatable in Lua registry + lua_setmetatable(L,-2); + //LOG<<"metatable set\n"; + + //lua::StackDump(L); + GetTable(L,obj); + lua_pushliteral(L,"__obj"); + lua_pushvalue(L,-3); + lua_settable(L,-3); + lua_pop(L,1); + //LOG<<"Object referenced\n"; + //lua::StackDump(L); + //T *p = new(ud) T(L); // call constructor for T objects + //lua::StackDump(L); + ud->pT = obj; // store pointer to object in userdata + ud->tableref=id; + //luaL_getmetatable(L, T::className); // lookup metatable in Lua registry + //lua_setmetatable(L, tableindex); + //lua::StackDump(L); + //LOG<<"Push done\n"; + return 1; // userdata containing pointer to T object + } + Lune() {}; //non constructable... +}; +#define method(class, name) {#name, &class::name} +#define DEF_LUNE(class) static const char className[];\ + static Lune::RegType methods[]; +#define DEF_LUNE_NOGC(class) static const char className[];\ + static Lune::RegType methods[]; +#define IMP_LUNE(class,lua_name) const char class::className[]=#lua_name; +#define LUNE_METHODS_START(class) Lune::RegType class::methods[] = { +#define LUNE_METHODS_START_NOGC(class) Lune::RegType class::methods[] = { +#define LUNE_METHODS_END() {0,0}} +#endif // LUNE_H diff --git a/plugins/Dfusion/luafiles/common.lua b/plugins/Dfusion/luafiles/common.lua index aeca0a820..b80f70e3e 100644 --- a/plugins/Dfusion/luafiles/common.lua +++ b/plugins/Dfusion/luafiles/common.lua @@ -17,7 +17,7 @@ offsets.load = function () end end offsets.load() -function unlockDF() +function GetTextRegion() local ranges=Process.getMemRanges() for k,v in pairs(ranges) do --for k2,v2 in pairs(v) do @@ -30,32 +30,27 @@ function unlockDF() --if(v["execute"]) then num=num+100 end --print(string.format("%d %x->%x %s %d",k,v["start"],v["end"],v.name,num)) local pos=string.find(v.name,".text") - if pos~=nil then - v["write"]=true - Process.setPermisions(v,v) + if(pos~=nil) then + return v; end end + return nil +end +function unlockDF() + local reg=GetTextRegion() + reg["write"]=true + Process.setPermisions(reg,reg) end function lockDF() - local 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))) - --end - --local num - --num=0 - --if(v["read"])then num=num+1 end - --if(v["write"])then num=num+10 end - --if(v["execute"]) then num=num+100 end - --print(string.format("%d %x->%x %s %d",k,v["start"],v["end"],v.name,num)) - local pos=string.find(v.name,".text") - if pos~=nil then - v["write"]=false - Process.setPermisions(v,v) - end - end + local reg=GetTextRegion() + reg["write"]=false + Process.setPermisions(reg,reg) end -- engine bindings engine=engine or {} engine.peekd=Process.readDWord -engine.poked=Process.writeDWord \ No newline at end of file +engine.poked=Process.writeDWord + +dofile("dfusion/patterns.lua") +dofile("dfusion/patterns2.lua") +dofile("dfusion/itempatterns.lua") \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/init.lua b/plugins/Dfusion/luafiles/init.lua index 4056da046..0cd34cc5c 100644 --- a/plugins/Dfusion/luafiles/init.lua +++ b/plugins/Dfusion/luafiles/init.lua @@ -15,10 +15,17 @@ dofile("dfusion/common.lua") print("Unlocking Df .text section...") unlockDF() print("Done unlock") -lockDF() -dofile("dfusion/simple_embark/plugin.lua") -print("hello world") -Console.print("Hello world in console!\n") +text=GetTextRegion() +h=hexsearch(text.start,text["end"],0x73,0x02,0x8b,0xce,0x53,0x6a,0x01,0x6a,0x06) +pos=h:findall() +for k,v in pairs(pos) do + print(k..v) +end +--hexsearch.delete(h) +lockDF() --DOES NOT WORK?! +--dofile("dfusion/simple_embark/plugin.lua") +--print("hello world") +--Console.print("Hello world in console!\n") --name=Console.lineedit("Enter name:") --Console.print("Your name is:"..name) diff --git a/plugins/Dfusion/luafiles/itempatterns.lua b/plugins/Dfusion/luafiles/itempatterns.lua new file mode 100644 index 000000000..da62c26d2 --- /dev/null +++ b/plugins/Dfusion/luafiles/itempatterns.lua @@ -0,0 +1,62 @@ +--dofile("patterns2.lua") moved to common.lua +ptr_item={} +ptr_item.RTI={off=0,rtype=DWORD} +ptr_item.x={off=4,rtype=WORD} +ptr_item.y={off=6,rtype=WORD} +ptr_item.z={off=8,rtype=WORD} +ptr_item.ref={off=0x28,rtype=ptr_vector} + +ptr_item.mat={off=0x78,rtype=WORD} +ptr_item.submat={off=0x7A,rtype=WORD} +ptr_item.submat2={off=0x7C,rtype=DWORD} +ptr_item.legendid={off=0x80,rtype=DWORD} -- i don't remember writing this... +ptr_item.decorations={off=0x90,rtype=ptr_vector} +ptr_item.flags={off=0xC,rtype=ptt_dfflag.new(8)} +ptr_item.ptr_covering={off=0x64,rtype=DWORD} +ptr_item.stack={off=0x58,rtype=WORD} +function ptr_item.getname(self,RTI) + if RTI == nil then + return string.sub(RTTI_GetName(self.RTI),5,-3) + else + return string.sub(RTTI_GetName(RTI),5,-3) + end +end +ptr_subitems={} +ptr_subitems["item_slabst"]={} +ptr_subitems["item_slabst"].msgptr={off=0xA0,rtype=ptt_dfstring} +ptr_subitems["item_slabst"].signtype={off=0xC0,rtype=DWORD} + +ptr_subitems["item_fisthst"]={} +ptr_subitems["item_fisthst"].fisthtype={off=0x78,rtype=WORD} + +ptr_subitems["item_eggst"]={} +ptr_subitems["item_eggst"].race={off=0x78,rtype=DWORD} +ptr_subitems["item_eggst"].isfertile={off=0xa0,rtype=DWORD} --0 or 1 +ptr_subitems["item_eggst"].hatchtime={off=0xa4,rtype=DWORD} + +ptr_decoration_gen={} +ptr_decoration_gen.RTI={off=0,rtype=DWORD} +ptr_decoration_gen.material={off=0x04,rtype=WORD} -- same for all? +ptr_decoration_gen.submat={off=0x08,rtype=DWORD} +function ptr_decoration_gen.getname(self,RTI) + if RTI == nil then + return string.sub(RTTI_GetName(self.RTI),21,-5) + else + return string.sub(RTTI_GetName(RTI),21,-5) + end +end +ptr_decoration={} +ptr_decoration["covered"]={} +ptr_decoration["covered"].material={off=0x04,rtype=WORD} +ptr_decoration["covered"].submat={off=0x08,rtype=DWORD} +ptr_decoration["art_image"]={} +ptr_decoration["art_image"].material={off=0x04,rtype=WORD} +ptr_decoration["art_image"].submat={off=0x08,rtype=DWORD} +ptr_decoration["art_image"].image={off=0x24,rtype=DWORD} +ptr_decoration["bands"]={} +ptr_decoration["bands"].material={off=0x04,rtype=WORD} +ptr_decoration["bands"].submat={off=0x08,rtype=DWORD} +ptr_cover={} --covering of various types (blood, water, etc) +ptr_cover.mat={off=0,rtype=WORD} +ptr_cover.submat={off=4,rtype=DWORD} +ptr_cover.state={off=8,rtype=WORD} \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/patterns.lua b/plugins/Dfusion/luafiles/patterns.lua new file mode 100644 index 000000000..f7c37da0d --- /dev/null +++ b/plugins/Dfusion/luafiles/patterns.lua @@ -0,0 +1,243 @@ +ptt_dfstring={} +if(COMPATMODE) then +ptt_dfstring.ptr={off=4,rtype=DWORD} +ptt_dfstring.size={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 + --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 +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) + + 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) + 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 +end + +--if(COMPATMODE) then +--ptr_vector={} +--ptr_vector.st={off=4,rtype=DWORD} +--ptr_vector.en={off=8,rtype=DWORD} +--else +ptr_vector={} +ptr_vector.st={off=0,rtype=DWORD} +ptr_vector.en={off=4,rtype=DWORD} +ptr_vector.alloc={off=8,rtype=DWORD} +--end +function ptr_vector:clone(settype) + local ret={} + for k,v in pairs(self) do + ret[k]=v + end + ret.type=settype + return ret +end +function ptr_vector:size() + return (self.en-self.st)/engine.sizeof(self.type) +end +ptr_vector.type=DWORD +function ptr_vector:getval(num) + return engine.peek(self.st+engine.sizeof(self.type)*num,self.type) +end +function ptr_vector:setval(num,val) + return engine.poke(self.st+engine.sizeof(self.type)*num,self.type,val) +end +function ptr_vector:append(val) + if self.alloc - self.en > 0 then + local num=self:size() + self.en=self.en+engine.sizeof(self.type) + self:setval(val,num) + else + error("larger than allocated arrays not implemented yet") + local num=self:size() + local ptr=Allocate(num*2) + + end +end +ptt_dfflag={} +function ptt_dfflag.flip(self,num) --flip one bit in flags + local of=math.floor (num/8); + + self[of]=bit.bxor(self[of],bit.lshift(1,num%8)) +end + +function ptt_dfflag.get(self,num) -- get one bit in flags + local of=math.floor (num/8); + + if bit.band(self[of],bit.lshift(1,num%8))~=0 then + return true + else + return false + end +end +function ptt_dfflag.set(self,num,val) --set to on or off one bit in flags + if (self:get(num)~=val) then + self:flip(num) + end +end +function ptt_dfflag.new(size) -- create new flag pattern of size(in bytes) + local ret={} + for i=0,size-1 do + ret[i]={off=i,rtype=BYTE}; + end + ret.flip=ptt_dfflag.flip --change to metatable stuff... + ret.get=ptt_dfflag.get + ret.set=ptt_dfflag.set + return ret; +end +--[[ + Creature: + 0 name (df_string) 28 + 28 nick (df_string) 56 + 56 surname- namearray(7*dword(4)) 84 ... + 140 race (dword) 144 + 224 flags + 264 civ (dword) + 252 ID + 592 following ID + 904 bleed vector? hurt vector or sth... + 0x790 legends id? + 2128 known names? or knowledge? + flags: + 0 Can the dwarf move or are they waiting for their movement timer + 1 Dead (might also be set for incoming/leaving critters that are alive) + 2 Currently in mood + 3 Had a mood + 4 "marauder" -- wide class of invader/inside creature attackers + 5 Drowning + 6 Active merchant + 7 "forest" (used for units no longer linked to merchant/diplomacy, they just try to leave mostly) + 8 Left (left the map) + 9 Rider + 10 Incoming + 11 Diplomat + 12 Zombie + 13 Skeleton + 14 Can swap tiles during movement (prevents multiple swaps) + 15 On the ground (can be conscious) + 16 Projectile + 17 Active invader (for organized ones) + 18 Hidden in ambush + 19 Invader origin (could be inactive and fleeing) + 20 Will flee if invasion turns around + 21 Active marauder/invader moving inward + 22 Marauder resident/invader moving in all the way + 23 Check against flows next time you get a chance + 24 Ridden + 25 Caged + 26 Tame + 27 Chained + 28 Royal guard + 29 Fortress guard + 30 Suppress wield for beatings/etc + 31 Is an important historical figure + 32 swiming + +]]-- +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)} +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 +ptr_Creature.race={off=140,rtype=DWORD} --ok +ptr_Creature.civ={off=264,rtype=DWORD} +ptr_Creature.legends={off=344,rtype=ptr_vector} --ok +ptr_Creature.hurt1={off=0x308,rtype=ptr_vector:clone(BYTE)} --byte vector... +ptr_Creature.hurt2={off=0x338,rtype=ptr_vector} +ptr_Creature.wounds={off=0x388,rtype=ptr_vector} +ptr_Creature.itemlist1={off=0x1D0,rtype=ptr_vector} +ptr_Creature.itemlist2={off=0x288,rtype=ptr_vector} +ptr_Creature.bloodlvl={off=0x490,rtype=DWORD} +ptr_Creature.bleedlvl={off=0x494,rtype=DWORD} + +ptr_CrGloss={} +ptr_CrGloss.token={off=0,rtype=ptt_dfstring} +ptr_CrGloss.castes={off=296,rtype=ptr_vector} + +ptr_CrCaste={} +ptr_CrCaste.name={off=0,rtype=ptt_dfstring} +ptr_CrCaste.flags_ptr={off=0x524,rtype=DWORD} --size 17? +--[=[ + Flags: + 57 - is sentient (allows setting labours) +--]=] +ptr_LEntry={} -- all size 256 +ptr_LEntry.name={off=36,rtype=ptt_dfstring} +ptr_LEntry.id1={off=160,rtype=DWORD} +ptr_LEntry.id2={off=164,rtype=DWORD} +ptr_LEntry.somlist={off=220,rtype=DWORD} + +ptr_dfname={} +for i=0,6 do +ptr_dfname[i]={off=i*4,rtype=DWORD} +end +--[[ + Site docs: + 0x38 name struct todo... + 0x78 type: + 0 - mountain halls (yours) + 1 - dark fort + 2 - cave + 3 - mountain hall (other) + 4 - forest + 5 - hamlet + 6 - imp location + 7 - lair + 8 - fort + 9 - camp + 0x7a some sort of id? + 0x84 some vec (ids) + 0x94 some other vec (ids) + 0xa4 some vec (prts) + 0x118 ptr to sth + + 0x14c ptr to mapdata +]]-- + + +ptr_site={} +ptr_site.type={off=0x78,rtype=WORD} +ptr_site.id={off=0x7a,rtype=DWORD} +ptr_site.name={off=0x38,rtype=ptr_dfname} +ptr_site.flagptr={off=0x118,rtype=DWORD} + +ptr_legends2={} +ptr_legends2.id={off=0,rtype=DWORD} +ptr_legends2.follow={off=0x18,rtype=DWORD} + +ptr_material={} +ptr_material.token={off=0,rtype=ptt_dfstring} diff --git a/plugins/Dfusion/luafiles/patterns2.lua b/plugins/Dfusion/luafiles/patterns2.lua new file mode 100644 index 000000000..09a3b0db8 --- /dev/null +++ b/plugins/Dfusion/luafiles/patterns2.lua @@ -0,0 +1,29 @@ +ptr_COL={} -- complete object locator... +ptr_COL.sig={off=0,rtype=DWORD} +ptr_COL.offset={off=4,rtype=DWORD} --offset of this vtable in the complete class +ptr_COL.cdoffset={off=8,rtype=DWORD} -- constructor displacement +ptr_COL.typePointer={off=12,rtype=DWORD} +ptr_COL.hierarchyPointer={off=16,rtype=DWORD} + +ptr_RTTI_Type={} +ptr_RTTI_Type.vftPointer={off=0,rtype=DWORD} +ptr_RTTI_Type.name={off=8,rtype=STD_STRING} + +function RTTI_GetName(vtable) + local COLoff=engine.peek(vtable-4,DWORD) + --print(string.format("Look:%x vtable:%x",vtable,engine.peek(vtable-4,DWORD))) + COL=engine.peek(COLoff,ptr_COL) + --print(string.format("COL:%x Typeptr:%x Type:%s",COLoff,COL.typePointer,engine.peek(COL.typePointer,ptr_RTTI_Type.name))) + return engine.peek(COL.typePointer,ptr_RTTI_Type.name) +end +ptr_RTTI_Hierarchy={} +ptr_RTTI_Hierarchy.sig={off=0,rtype=DWORD} +ptr_RTTI_Hierarchy.attributes={off=4,rtype=DWORD} +ptr_RTTI_Hierarchy.numBaseClasses={off=8,rtype=DWORD} +ptr_RTTI_Hierarchy.ptrBases={off=12,rtype=DWORD} + +ptr_RTTI_BaseClass={} +ptr_RTTI_BaseClass.typePointer={off=0,rtype=DWORD} +ptr_RTTI_BaseClass.numContained={off=4,rtype=DWORD} +--todo PMD +--todo flags \ No newline at end of file diff --git a/plugins/Dfusion/src/hexsearch.cpp b/plugins/Dfusion/src/hexsearch.cpp new file mode 100644 index 000000000..dda04c9ab --- /dev/null +++ b/plugins/Dfusion/src/hexsearch.cpp @@ -0,0 +1,74 @@ +#include "hexsearch.h" + + +Hexsearch::Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos):args_(args),pos_(startpos_),startpos_(startpos),endpos_(endpos) +{ + +} +Hexsearch::~Hexsearch() +{ + +} + +uint64_t Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm +{ + DFHack::Core &inst=DFHack::Core::getInstance(); + DFHack::Process *p=inst.p; + uint8_t *buf; + buf=new uint8_t[args_.size()]; + while(pos_readByte(pos_,buf[0]); + if(buf[0]==args_[0]) //TODO make a comparator + { + p->read(pos_,args_.size(),buf); + for(size_t i=0;i Hexsearch::FindAll() +{ + std::vector ret; + uint64_t cpos=pos_; + while(cpos!=0) + { + cpos=FindNext(); + if(cpos!=0) + ret.push_back(cpos); + } + return ret; +} +void Hexsearch::PrepareBadCharShift() +{ + BadCharShifts.resize(256,-1); + int i=0; + for(SearchArgType::reverse_iterator it=args_.rbegin();it!=args_.rend();it++) + { + BadCharShifts[*it]=i; + i++; + } +} +void Hexsearch::PrepareGoodSuffixTable() +{ + GoodSuffixShift.resize(args_.size()+1,0); + +} \ No newline at end of file diff --git a/plugins/Dfusion/src/lua_Hexsearch.cpp b/plugins/Dfusion/src/lua_Hexsearch.cpp new file mode 100644 index 000000000..a4e5e9ea5 --- /dev/null +++ b/plugins/Dfusion/src/lua_Hexsearch.cpp @@ -0,0 +1,57 @@ +#include "lua_Hexsearch.h" +int lua::Hexsearch::find(lua_State *L) +{ + lua::state st(L); + uint64_t pos=p->FindNext(); + st.push(pos); + return 1; +} +int lua::Hexsearch::findall(lua_State *L) +{ + lua::state st(L); + std::vector pos=p->FindAll(); + st.newtable(); + for(int i=0;i(2); + end=st.as(3); + for(int i=4;i(i)); + } + p=new ::Hexsearch(args,start,end); +} +lua::Hexsearch::~Hexsearch() +{ + delete p; +} +int lua::Hexsearch::reset(lua_State *L) +{ + lua::state st(L); + p->Reset(); + return 0; +} + +IMP_LUNE(lua::Hexsearch,hexsearch); +LUNE_METHODS_START(lua::Hexsearch) + method(lua::Hexsearch,find), + method(lua::Hexsearch,findall), + method(lua::Hexsearch,reset), +LUNE_METHODS_END(); +void lua::RegisterHexsearch(lua::state &st) +{ + + Lune::Register(st); + +} \ No newline at end of file diff --git a/plugins/Dfusion/src/lune.cpp b/plugins/Dfusion/src/lune.cpp new file mode 100644 index 000000000..186f56fb5 --- /dev/null +++ b/plugins/Dfusion/src/lune.cpp @@ -0,0 +1,2 @@ +#include "lune.h" +lua::object *lua::local_object::mytbl=0; From e98e4a51115bb78fb5ec9915cc8fefe5971fa1ce Mon Sep 17 00:00:00 2001 From: Warmist Date: Wed, 3 Aug 2011 16:27:04 +0300 Subject: [PATCH 02/10] Fixes to hexsearch Signed-off-by: Warmist --- plugins/Dfusion/include/lua_Hexsearch.h | 2 +- plugins/Dfusion/luafiles/init.lua | 2 +- plugins/Dfusion/src/hexsearch.cpp | 4 ++-- plugins/Dfusion/src/lua_Hexsearch.cpp | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/Dfusion/include/lua_Hexsearch.h b/plugins/Dfusion/include/lua_Hexsearch.h index 030db079e..2dfa78af8 100644 --- a/plugins/Dfusion/include/lua_Hexsearch.h +++ b/plugins/Dfusion/include/lua_Hexsearch.h @@ -25,7 +25,7 @@ public: DEF_LUNE(Hexsearch); }; -void RegisterHexsearch(lua::state &st);//TODO remake into OO oriented thing +void RegisterHexsearch(lua::state &st); } diff --git a/plugins/Dfusion/luafiles/init.lua b/plugins/Dfusion/luafiles/init.lua index 0cd34cc5c..fd345397c 100644 --- a/plugins/Dfusion/luafiles/init.lua +++ b/plugins/Dfusion/luafiles/init.lua @@ -13,7 +13,7 @@ end dofile("dfusion/common.lua") print("Unlocking Df .text section...") -unlockDF() +--unlockDF() print("Done unlock") text=GetTextRegion() h=hexsearch(text.start,text["end"],0x73,0x02,0x8b,0xce,0x53,0x6a,0x01,0x6a,0x06) diff --git a/plugins/Dfusion/src/hexsearch.cpp b/plugins/Dfusion/src/hexsearch.cpp index dda04c9ab..c8b1fd67a 100644 --- a/plugins/Dfusion/src/hexsearch.cpp +++ b/plugins/Dfusion/src/hexsearch.cpp @@ -1,7 +1,7 @@ #include "hexsearch.h" -Hexsearch::Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos):args_(args),pos_(startpos_),startpos_(startpos),endpos_(endpos) +Hexsearch::Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos) { } @@ -36,7 +36,7 @@ uint64_t Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm { pos_+=args_.size(); delete [] buf; - return pos_; + return pos_-args_.size(); } } pos_++; diff --git a/plugins/Dfusion/src/lua_Hexsearch.cpp b/plugins/Dfusion/src/lua_Hexsearch.cpp index a4e5e9ea5..08d571c50 100644 --- a/plugins/Dfusion/src/lua_Hexsearch.cpp +++ b/plugins/Dfusion/src/lua_Hexsearch.cpp @@ -24,9 +24,9 @@ lua::Hexsearch::Hexsearch(lua_State *L,int id):tblid(id) lua::state st(L); uint64_t start,end; ::Hexsearch::SearchArgType args; - start=st.as(2); - end=st.as(3); - for(int i=4;i(1); + end=st.as(2); + for(int i=3;i<=st.gettop();i++) { args.push_back(st.as(i)); } From ef4a45921457e3133d530f1438a7d26fc6144811 Mon Sep 17 00:00:00 2001 From: Warmist Date: Wed, 3 Aug 2011 17:59:06 +0300 Subject: [PATCH 03/10] Ported items plugin with more stuff --- plugins/Dfusion/include/hexsearch.h | 2 + plugins/Dfusion/luafiles/common.lua | 358 ++++++++++++++++++++++ plugins/Dfusion/luafiles/init.lua | 49 ++- plugins/Dfusion/luafiles/items/plugin.lua | 212 +++++++++++++ plugins/Dfusion/readme.txt | 23 +- plugins/Dfusion/src/hexsearch.cpp | 43 ++- plugins/Dfusion/src/lua_Hexsearch.cpp | 10 +- 7 files changed, 665 insertions(+), 32 deletions(-) create mode 100644 plugins/Dfusion/luafiles/items/plugin.lua diff --git a/plugins/Dfusion/include/hexsearch.h b/plugins/Dfusion/include/hexsearch.h index 335bfebde..b4ffb84d8 100644 --- a/plugins/Dfusion/include/hexsearch.h +++ b/plugins/Dfusion/include/hexsearch.h @@ -25,6 +25,8 @@ public: std::vector FindAll(); private: + bool Compare(int a,int b); + void ReparseArgs(); SearchArgType args_; uint64_t pos_,startpos_,endpos_; std::vector BadCharShifts,GoodSuffixShift; diff --git a/plugins/Dfusion/luafiles/common.lua b/plugins/Dfusion/luafiles/common.lua index b80f70e3e..ca84b4f4f 100644 --- a/plugins/Dfusion/luafiles/common.lua +++ b/plugins/Dfusion/luafiles/common.lua @@ -17,6 +17,12 @@ offsets.load = function () end end offsets.load() + +STD_STRING=0 +DWORD=1 +WORD=2 +BYTE=3 + function GetTextRegion() local ranges=Process.getMemRanges() for k,v in pairs(ranges) do @@ -50,6 +56,358 @@ end engine=engine or {} engine.peekd=Process.readDWord engine.poked=Process.writeDWord +engine.peekb=Process.readByte +engine.pokeb=Process.writeByte +engine.peekw=Process.readWord +engine.pokew=Process.writeWord +engine.peekstr=Process.readCString +--engine.pokestr=Process.readCString +engine.peekarb=Process.read +engine.pokearb=Process.write + + +function engine.peek(offset,rtype) + if type(rtype)=="table" then + if rtype.off ==nil then + return engine.peekpattern(offset,rtype) + else + return engine.peek(rtype.off+offset,rtype.rtype) + end + end + if rtype==STD_STRING then + return engine.peekstr(offset) + elseif rtype==DWORD then + return engine.peekd(offset) + elseif rtype==WORD then + return engine.peekw(offset) + elseif rtype==BYTE then + return engine.peekb(offset) + else + error("Invalid peek type") + return + end +end +function engine.poke(offset,rtype,val) + if type(rtype)=="table" then + if rtype.off ==nil then + return engine.pokepattern(offset,rtype,val) + else + return engine.poke(rtype.off+offset,rtype.rtype,val) + end + end + if rtype==STD_STRING then + return engine.pokestr(offset,val) + elseif rtype==DWORD then + return engine.poked(offset,val) + elseif rtype==WORD then + return engine.pokew(offset,val) + elseif rtype==BYTE then + return engine.pokeb(offset,val) + else + error("Invalid poke type:"..tostring(rtype)) + return + end +end +function engine.sizeof(rtype) + if rtype==STD_STRING then + error("String has no constant size") + return + elseif rtype==DWORD then + return 4; + elseif rtype==WORD then + return 2; + elseif rtype==BYTE then + return 1; + else + error("Invalid sizeof type") + return + end +end +function engine.peekpattern(offset,pattern) + local ret={} + for k,v in pairs(pattern) do + --print("k:"..k.." v:"..type(v)) + if type(v)=="table" then + ret[k]=engine.peek(offset+v.off,v.rtype) + --print(k.." peeked:"..offset+v.off) + else + ret[k]=v + end + end + ret.__offset=offset + return ret +end +function engine.pokepattern(offset,pattern,val) + for k,v in pairs(pattern) do + --print("k:"..k.." v:"..type(v)) + if type(v)=="table" then + engine.poke(offset+v.off,v.rtype,val[k]) + end + end +end + + +it_menu={} +it_menu.__index=it_menu +function it_menu:add(name,func) + table.insert(self.items,{func,name}) +end +function it_menu:display() + print("Select choice (q exits):") + for p,c in pairs(self.items) do + print(p..")."..c[2]) + end + local ans + repeat + local r + r=io.stdin:read() + if r=='q' then return end + ans=tonumber(r) + + if ans==nil or not(ans<=table.maxn(self.items) and ans>0) then + print("incorrect choice") + end + + until ans~=nil and (ans<=table.maxn(self.items) and ans>0) + self.items[ans][1]() +end +function MakeMenu() + local ret={} + ret.items={} + setmetatable(ret,it_menu) + return ret +end + +function PrintPattern(loadedpattern) + for k,v in pairs(loadedpattern) do + if type(v)== "string" then + print(k.." "..v) + else + print(string.format("%s %d inhex:%x",k,v,v)) + end + end +end + +function printPattern(pattern) + local i=0; + local names={} + names[STD_STRING]="std_string (STD_STRING)" + names[DWORD]= "Double word (DWORD)" + names[WORD]= "Word (WORD)" + names[STD_STRING]="Byte (BYTE)" + ret={} + for k,v in pairs(pattern) do + if type(v)=="table" and v.off~=nil then + + if names[v.rtype]~=nil then + lname=names[v.rtype] + else + if type(v.rtype)=="table" then + lname="Table (prob subpattern)" + else + lname="Other" + end + end + print(string.format("%d. %s is %s with offset %x",i,k,lname,v.off)) + table.insert(ret,k) + else + print(string.format("%d. %s",i,k)) + end + i=i+1 + end + return ret; +end +function editPattern(offset,pattern,name) + if type(pattern[name].rtype)=="table" then + if pattern[name].rtype.setval~=nil then + print(string.format("%x",offset+pattern[name].off)) + local t=engine.peek(offset+pattern[name].off,pattern[name].rtype) + print("Value is now:"..t:getval()) + print("Enter new value:") + val=io.stdin:read() + t:setval(val) + else + ModPattern(offset+pattern[name].off,pattern[name].rtype) + end + return + end + val=engine.peek(offset,pattern[name]) + print("Value is now:"..val) + print("Enter new value:") + if pattern[name].rtype==STD_STRING then + val=io.stdin:read() + else + val=tonumber(io.stdin:read()) + end + engine.poke(offset,pattern[name],val) +end +function ModPattern(itemoffset,pattern) + print("Select what to edit:") + nm=printPattern(pattern) + q=tonumber(io.stdin:read()) + if q~=nil and q<#nm then + editPattern(itemoffset,pattern,nm[q+1]) + end +end + +function findVectors() + local text=GetTextRegion() + local h=hexsearch(text.start,text["end"],0x8b,ANYBYTE,ANYDWORD,0x8b,ANYBYTE,ANYDWORD,0x2b,ANYBYTE) + local pos=h:findall() + local T={} + for k,v in pairs(pos) do + local loc1,loc2 + loc1=engine.peekd(v+2) + loc2=engine.peekd(v+8) + --print(string.format("%x - %x=%x",loc1,loc2,loc1-loc2)) + if(math.abs(loc1-loc2)==4) then + if T[loc1-4]~=nil then + T[loc1-4]=T[loc1-4]+1 + else + T[loc1-4]=1 + end + end + end + return T +end + +function GetRaceToken(p) --actually gets token... + local vec=engine.peek(offsets.getEx('CreatureGloss'),ptr_vector) + local off=vec:getval(p) + local crgloss=engine.peek(off,ptr_CrGloss) + return crgloss.token:getval() +end +function BuildNameTable() + local rtbl={} + local vec=engine.peek(offsets.getEx('CreatureGloss'),ptr_vector) + --print(string.format("Vector start:%x",vec.st)) + --print(string.format("Vector end:%x",vec.en)) + --local i=0 + for p=0,vec:size()-1 do + local off=vec:getval(p) + --print("First member:"..off) + local name=engine.peek(off,ptt_dfstring) + --print("Loading:"..p.."="..name:getval()) + rtbl[name:getval()]=p + --i=i+1 + --if i>100 then + -- io.stdin:read() + -- i=0 + --end + end + return rtbl; +end +function BuildMaterialTable() + local rtbl={} + local vec=engine.peek(offsets.getEx('Materials'),ptr_vector) + --print(string.format("Vector start:%x",vec.st)) + --print(string.format("Vector end:%x",vec.en)) + --local i=0 + for p=0,vec:size()-1 do + local off=vec:getval(p) + --print("First member:"..off) + local name=engine.peek(off,ptt_dfstring) + --print("Loading:"..p.."="..name:getval()) + rtbl[name:getval()]=p + --i=i+1 + --if i>100 then + -- io.stdin:read() + -- i=0 + --end + end + return rtbl; +end +function BuildWordTables() + local names={} + local rnames={} + local vector=engine.peek(offsets.getEx('WordVec'),ptr_vector) +for i =0,vector:size()-1 do + local off=vector:getval(i) + local n=engine.peekstr(off) + names[i]=n + rnames[n]=i +end + return names,rnames +end +function ParseScript(file) + + io.input(file) + f="" + first=0 + nobraces=0 + function updFunction() + if f~="" then + first=0 + if nobraces==0 then + f=f.."}" + end + nobraces=0 + print("Doing:"..f) + assert(loadstring(f))() + + f="" + end + end + while true do + + local line = io.read("*line") + if line == nil then break end + if string.sub(line,1,2)==">>" then + updFunction() + if string.find(line,"%b()") then + f=string.sub(line,3) + nobraces=1 + else + f=string.sub(line,3).."{" + end + --print(string.sub(line,3)..) + else + if first~=0 then + f=f.."," + else + first=1 + end + f=f..string.format('%q',line) + + end + + end + updFunction() +end +function ParseNames(path) + local ret={} + local ff=io.open(path) + for n in ff:lines() do + table.insert(ret,n) + end + return ret +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 + -- 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 + local z=engine.peekd(off+8) --next is 8 from start + --print("Pointer @:"..x..","..y..","..z) + return x,y,z -- return the coords +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 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) + local cz=engine.peek(curoff,ptr_Creature.z) + if cx==x and cy==y and cz==z then --compare them + return i --return index + end + end + print("Creature not found!") + return -1 + +end dofile("dfusion/patterns.lua") dofile("dfusion/patterns2.lua") diff --git a/plugins/Dfusion/luafiles/init.lua b/plugins/Dfusion/luafiles/init.lua index fd345397c..ff088daa4 100644 --- a/plugins/Dfusion/luafiles/init.lua +++ b/plugins/Dfusion/luafiles/init.lua @@ -10,31 +10,30 @@ function dofile(filename) --safer dofile, with traceback (very usefull) print(perr) end end -dofile("dfusion/common.lua") - -print("Unlocking Df .text section...") ---unlockDF() -print("Done unlock") -text=GetTextRegion() -h=hexsearch(text.start,text["end"],0x73,0x02,0x8b,0xce,0x53,0x6a,0x01,0x6a,0x06) -pos=h:findall() -for k,v in pairs(pos) do - print(k..v) -end ---hexsearch.delete(h) -lockDF() --DOES NOT WORK?! ---dofile("dfusion/simple_embark/plugin.lua") ---print("hello world") ---Console.print("Hello world in console!\n") ---name=Console.lineedit("Enter name:") ---Console.print("Your name is:"..name) -function OnTick() -- floods the console - r=Console.get_rows() - c=Console.get_columns() +function mainmenu(t1) Console.clear() - Console.gotoxy(math.random(1,r),math.random(1,2)) - Console.color(math.random(0,15)) - Console.print("*") + 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])) + end + local q=Console.lineedit("Select plugin to run (q to quit):") + if q=='q' then return end + q=tonumber(q) + if q~=nil then + if q>=1 and q<=#t1 then + dofile("dfusion/"..t1[q][1].."/plugin.lua") + + end + end + end end -OnTick=nil \ No newline at end of file +dofile("dfusion/common.lua") +unlockDF() +plugins={} +table.insert(plugins,{"simple_embark","A simple embark dwarf count editor"}) +table.insert(plugins,{"items","A collection of item hacking tools"}) + +mainmenu(plugins) + diff --git a/plugins/Dfusion/luafiles/items/plugin.lua b/plugins/Dfusion/luafiles/items/plugin.lua new file mode 100644 index 000000000..8b92785bd --- /dev/null +++ b/plugins/Dfusion/luafiles/items/plugin.lua @@ -0,0 +1,212 @@ +items={} --> first lets make a menu table +items.menu=MakeMenu() + + +function items.dest() + myoff=offsets.getEx("Items") -- first find out where "item vector" is + vector=engine.peek(myoff,ptr_vector) -- get list of items + for i=0,vector:size()-1 do --look at each item + flg=engine.peek(vector:getval(i),ptr_item.flags) + flg:set(17,1) + engine.poke(vector:getval(i),ptr_item.flags,flg) + end +end +function items.eggs() + myoff=offsets.getEx("Items") -- first find out where "item vector" is + vector=engine.peek(myoff,ptr_vector) -- get list of items + for i=0,vector:size()-1 do --look at each item + rti=engine.peek(vector:getval(i),ptr_item.RTI) + if ptr_item.getname(nil,rti)=="item_eggst" then + egg=engine.peek(vector:getval(i),ptr_subitems["item_eggst"]) + egg.isfertile=1 + egg.hatchtime=0xffffff + --egg.race=123 -- change race for fun times + engine.poke(vector:getval(i),ptr_subitems["item_eggst"],egg) + end + end +end +function editFlags(offset) + while true do + flags=engine.peek(offset,ptr_item.flags) + for i=0,8*8-1 do + if flags:get(i) then + print(i.." is true") + else + print(i.." is false") + end + end + print(" enter number to switch flag or not a number to quit:") + q=tonumber(io.stdin:read()) + if q==nil then return end + flags:flip(q) + engine.poke(offset,ptr_item.flags,flags) + end +end +function editCovering(offset) + off=engine.peek(offset,ptr_item.ptr_covering) + if off == 0 then + print("No coverings found.") + end + vec=engine.peek(off,ptr_vector) + print("Covering list:") + for i=0,vec:size()-1 do + cov=engine.peek(vec:getval(i),ptr_cover) + print(string.format("%d. mat=%d submat=%d state=%d",i,cov.mat,cov.submat,cov.state)) + end + print("To edit type number:") + q=tonumber(io.stdin:read()) + if q==nil then return end + if q>=vec:size() or q<0 then return end + off=vec:getval(q) + cov=engine.peek(off,ptr_cover) + print("Enter mat:") + q=tonumber(io.stdin:read()) + if q==nil then q=0xffff end + print("Enter submat:") + v=tonumber(io.stdin:read()) + if v==nil then v=0xffff end + print("Enter state:") + y=tonumber(io.stdin:read()) + if y==nil then y=0 end + cov.mat=q + cov.submat=v + cov.state=y + engine.poke(off,ptr_cover,cov) +end +function editMaterial(offset) + print("Mat id 0 to 18 is in normal materials (inorganic, amber etc...) after that creature mat (with submat2 being race)") + print("from 219 with submat2=0xffffffff (type not a number) it reads legends id, from 419 submat2 means plant id") + print("Probably submat is not used :? ") + mat=engine.peek(offset,ptr_item.mat) + submat=engine.peek(offset,ptr_item.submat) + submat2=engine.peek(offset,ptr_item.submat2) + lid=engine.peek(offset,ptr_item.legendid) + print(string.format("Now is mat=%d, submat=%d submat2=%d legend id=%d",mat,submat,submat2,lid)) + print("Enter mat:") + q=tonumber(io.stdin:read()) + if q==nil then return end + print("Enter submat:") + v=tonumber(io.stdin:read()) + if v==nil then v=0xffff end + print("Enter submat2:") + z=tonumber(io.stdin:read()) + if z==nil then z=0xffffffff end + print("Enter legendid:") + y=tonumber(io.stdin:read()) + if y==nil then y=0xffffffff end + engine.poke(offset,ptr_item.mat,q) + engine.poke(offset,ptr_item.submat,v) + engine.poke(offset,ptr_item.legendid,y) + engine.poke(offset,ptr_item.submat2,z) + print("Done") +end +function items.select() + myoff=offsets.getEx("Items") + vector=engine.peek(myoff,ptr_vector) + tx,ty,tz=getxyz() + T={} + for i=0,vector:size()-1 do --this finds all item offsets that are on pointer + itoff=vector:getval(i) + x=engine.peek(itoff,ptr_item.x) + y=engine.peek(itoff,ptr_item.y) + z=engine.peek(itoff,ptr_item.z) + if x==tx and y==ty and z==tz then + table.insert(T,itoff) + end + end + print("Items under cursor:") + i=1 + for _,v in pairs(T) do + RTI=engine.peek(v,ptr_item.RTI) + print(i..". "..ptr_item.getname(nil,RTI)) + i=i+1 + end + print("Type number to edit or 'q' to exit") + while true do + q=io.stdin:read() + if q=='q' then return end + if tonumber(q) ~=nil and tonumber(q)readByte(pos_,buf[0]); - if(buf[0]==args_[0]) //TODO make a comparator + if(Compare(buf[0],args_[0])) { p->read(pos_,args_.size(),buf); for(size_t i=0;i pos=p->FindAll(); st.newtable(); - for(int i=0;i::Register(st); - -} \ No newline at end of file + __ADDCONST(ANYBYTE); + __ADDCONST(ANYDWORD); + __ADDCONST(DWORD_); +} +#undef __ADDCONST \ No newline at end of file From e7174e6736decc5d8861c1527a27a0e3b09c8af7 Mon Sep 17 00:00:00 2001 From: Warmist Date: Wed, 3 Aug 2011 18:15:58 +0300 Subject: [PATCH 04/10] DWORD_ fix, not sure if correct --- plugins/Dfusion/src/hexsearch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/Dfusion/src/hexsearch.cpp b/plugins/Dfusion/src/hexsearch.cpp index 0ee71c69a..ec0abb4f0 100644 --- a/plugins/Dfusion/src/hexsearch.cpp +++ b/plugins/Dfusion/src/hexsearch.cpp @@ -29,10 +29,10 @@ void Hexsearch::ReparseArgs() i++; for(int j=0;j<4;j++) { - args_.push_back(targ[i+4-j]); + args_.push_back((targ[i]&(0xff<>i);//TODO is this correct??? } - i+=4; + i++; } else if (targ[i]==ANYDWORD) { From e66a03e6542cfa2252f236a754a463958dedb2e2 Mon Sep 17 00:00:00 2001 From: Warmist Date: Thu, 4 Aug 2011 20:57:53 +0300 Subject: [PATCH 05/10] Beggining of auto-offset finder port. (not working yet) Signed-off-by: Warmist --- plugins/Dfusion/luafiles/common.lua | 41 ++- plugins/Dfusion/luafiles/init.lua | 2 +- plugins/Dfusion/luafiles/offsets.lua | 310 ++++++++++++++++++++ plugins/Dfusion/luafiles/offsets/plugin.lua | 2 + plugins/Dfusion/luafiles/offsets_misc.lua | 103 +++++++ plugins/Dfusion/luafiles/patterns.lua | 1 + 6 files changed, 437 insertions(+), 22 deletions(-) create mode 100644 plugins/Dfusion/luafiles/offsets.lua create mode 100644 plugins/Dfusion/luafiles/offsets/plugin.lua create mode 100644 plugins/Dfusion/luafiles/offsets_misc.lua diff --git a/plugins/Dfusion/luafiles/common.lua b/plugins/Dfusion/luafiles/common.lua index ca84b4f4f..e9b5421d8 100644 --- a/plugins/Dfusion/luafiles/common.lua +++ b/plugins/Dfusion/luafiles/common.lua @@ -1,23 +1,4 @@ -offsets=offsets or {} -offsets._toff={} -offsets.get = function (name) - return offsets._toff[name] -end -offsets.getEx = function (name) - return offsets._toff[name]+Process.getBase() -end -offsets.load = function () - local f=io.open("dfusion/offsets.txt") - local line=f:read() - while line~=nil do - --print(line) - local sppliter=string.find(line,":") - offsets._toff[string.sub(line,1,sppliter-2)]=tonumber(string.sub(line,sppliter+2)) - line=f:read() - end -end -offsets.load() - +dofile("dfusion/offsets_misc.lua") STD_STRING=0 DWORD=1 WORD=2 @@ -42,6 +23,24 @@ function GetTextRegion() end return nil end +function GetRegionIn(pos) + local 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))) + --end + --local num + --num=0 + --if(v["read"])then num=num+1 end + --if(v["write"])then num=num+10 end + --if(v["execute"]) then num=num+100 end + --print(string.format("%d %x->%x %s %d",k,v["start"],v["end"],v.name,num)) + if pos>=v.start and pos<=v["end"] then + return v + end + end + return nil +end function unlockDF() local reg=GetTextRegion() reg["write"]=true @@ -260,7 +259,7 @@ function findVectors() loc1=engine.peekd(v+2) loc2=engine.peekd(v+8) --print(string.format("%x - %x=%x",loc1,loc2,loc1-loc2)) - if(math.abs(loc1-loc2)==4) then + if(loc1-loc2==4) then if T[loc1-4]~=nil then T[loc1-4]=T[loc1-4]+1 else diff --git a/plugins/Dfusion/luafiles/init.lua b/plugins/Dfusion/luafiles/init.lua index ff088daa4..1202fb534 100644 --- a/plugins/Dfusion/luafiles/init.lua +++ b/plugins/Dfusion/luafiles/init.lua @@ -34,6 +34,6 @@ unlockDF() plugins={} table.insert(plugins,{"simple_embark","A simple embark dwarf count editor"}) table.insert(plugins,{"items","A collection of item hacking tools"}) - +table.insert(plugins,{"offsets","Find all offsets"}) mainmenu(plugins) diff --git a/plugins/Dfusion/luafiles/offsets.lua b/plugins/Dfusion/luafiles/offsets.lua new file mode 100644 index 000000000..c88602e96 --- /dev/null +++ b/plugins/Dfusion/luafiles/offsets.lua @@ -0,0 +1,310 @@ + + +function f_dwarves() + pos=offsets.find(0,0x24,0x14,0x07,0,0,0,0xeb,0x08,0x8d) --search pattern + if pos~=0 then + return pos+2-offsets.base(); + else + return 0; + end +end +offsets.new("StartDwarfs",f_dwarves) -- finds the starting dwarf count +function f_creatures() + --01C48034-base=0x1258034 + local val=0 + --print("Enter creature count:"); + --local r=io.stdin:read() + for k,v in pairs(offsets.getvectors()) do + if (v>60) and (v<100) then --used count changed some time ago... two hits second one is the right one. Maybe some smarter way could be better? + --new version first one is right?? needs more testing thou... + val= k-offsets.base() + print(string.format("%x",val)) + break; + end + --vec=engine.peek(k,ptr_vector); + + --[[if(vec:size()==tonumber(r)) then + val=k-offsets.base() + print(string.format("off:%x",k)) + end--]] + end + offsets.new("AdvCreatureVec",val) + return val +end +offsets.new("CreatureVec",f_creatures) +function f_words() + local val=0 + for k,v in pairs(offsets.getvectors()) do + local toff=engine.peekd(engine.peekd(k)) + if(engine.peekstr(toff)=="ABBEY") then + val=k-offsets.base() + end + end + return val +end +offsets.newlazy("WordVec",f_words) +function f_creatureptr() --a creature number under the pointer + pos=offsets.find(0,0xa1,ANYDWORD,0x83,0xf8,0xff,0x75) + print("Offset="..pos) + if pos~=0 then + pos=engine.peekd(pos+1) + return pos-offsets.base() + else + return 0 + end +end +offsets.new("CreaturePtr",f_creatureptr) + +function f_creaturegloss() --creature race vector + for k,v in pairs(offsets.getvectors()) do + if k~=0 then + --print("Looking into:"..string.format("%x",k).." used:"..v) + + local vec=engine.peek(k,ptr_vector) + if vec:size()>0 and vec:size()<100000 and vec:getval(0)~=0 then + --print("\tval:"..string.format("%x",vec:getval(0))) + local token=engine.peek(vec:getval(0),ptt_dfstring) + --print("\t\tval:".. token:getval()) + if token:getval()=="TOAD" then -- more offsets could be found this way + return k-offsets.base() + end + end + end + end + return 0 +end +offsets.new("CreatureGloss",f_creaturegloss) +--reaction vec: search for TAN_A_HIDE +function f_racevec() --current race + --find all movsx anyreg,address + local den={} + local pos=offsets.findall(0,0x0f,0xbf,ANYBYTE,ADDRESS) + for k,v in pairs(pos) do + local add + if v~=0 then + add=engine.peekd(v+3) + if den[add]~=nil then + den[add]= den[add]+1 + else + den[add]=1 + end + end + + end + + for k,v in pairs(den) do + if v <60 then + den[k]=nil + end + + end + for k,v in pairs(den) do + print("Looking into:"..string.format("%x",k).." used:"..v.." Race:"..engine.peekw(k)) + if engine.peekw(k) >0 and engine.peekw(k)<1000 then + + return k-offsets.base() + end + end + + + return 0 +end +offsets.new("CurrentRace",f_racevec) +function f_pointer() --adventure (not only?) pointer x,y,z + print("\n") + local den={} + local pos=0 + repeat + pos=offsets.find(pos+3,0x0f,0xb7,ANYBYTE,ADDRESS) + local add=engine.peekd(pos+3) + local add2=engine.peekd(pos+13) + local add3=engine.peekd(pos+23) + if( math.abs(add-add2)==4 or math.abs(add-add3)==4) then + + if den[add]~=nil then + den[add]= den[add]+1 + else + den[add]=1 + end + end + until pos==0 + for k,v in pairs(den) do + print("Looking into:"..string.format("%x",k).." used:"..v) + return k-offsets.base()-4 + end + return 0 +end +offsets.new("Xpointer",f_pointer) +function f_adventure() + RaceTable=RaceTable or BuildNameTable() -- this gets all the races' numbers + --[[print("input chars race:") + repeat + r=io.stdin:read() + if RaceTable[r]==nil then print("Incorrect race...") end + until RaceTable[r]~=nil -- query till correct race is inputed + rnum=RaceTable[r] --get its num + print("Race:"..rnum)]]-- + myoff=0 + print("input player's creature's name (lowercaps):") + r=io.stdin:read() + + for k,v in pairs(offsets.getvectors()) do -- now lets look through all vector offsets + off=engine.peekd(k) --get vector start + off=engine.peekd(off) --get 0 element (or first) in adventurer mode its our hero + name=engine.peekstr(off) + if(name==r) then + --if engine.peek(off+140)==rnum then -- creature start+140 is the place where race is kept + print(string.format("%x race:%x",k,engine.peekw(off+140))) + myoff=k -- ok found it + break + end + end + if myoff~=0 then + crvec=engine.peek(myoff,ptr_vector) + print(string.format("player offset:%x",crvec:getval(0))) + local legidVec=engine.peek(crvec:getval(0),ptr_Creature.legends) + print(string.format("legends offset:%x",legidVec:getval(0))) + local vtable=engine.peekd(legidVec:getval(0)) + print(string.format("vtable offset:%x",vtable)) + offsets.new("vtableLegends",vtable-offsets.base()) + return myoff-offsets.base() --save the offset for laters + else + return 0 --indicate failure + end +end +offsets.newlazy("AdvCreatureVec",f_adventure) -- register a way to find this offset +--7127F0 +function f_legends() + pos=1 + T={} + repeat + pos=offsets.find(pos+1,0x50,0xb8,ANYDWORD,0xe8,ANYDWORD,0x8b,0xf0) + off=engine.peekd(pos+2) + vec=engine.peek(off,ptr_vector) + if vec:size()~=0 then + if T[off]~=nil then + T[off].c=T[off].c+1 + else + T[off]={c=1,vsize=vec:size()} + end + + end + + until pos==0 + for k,v in pairs(T) do + vec=engine.peek(k,ptr_vector) + print(string.format("off:%x used:%i size:%d",k,v.c,v.vsize)) + print(string.format("fith elements id:%d",engine.peekd(vec:getval(5)))) + if engine.peekd(vec:getval(5))==5 then + --if v.c==2 and v.vsize>1000 then + return k-offsets.base() + end + end + return 0 +end +offsets.newlazy("Legends",f_legends) +function f_playerlegendid() + local off=offsets.getEx("Legends") + local pos=1 + repeat + pos=offsets.find(pos+1,0xa1,DWORD_,off+4,0x2b,0x05,DWORD_,off) + val=engine.peekd(pos+16) + if engine.peekd(val)~=0 then + --if val >offsets.base() then + return val-offsets.base() + end + --print(string.format("%x",val)) + until pos==0 + return 0 +end +offsets.newlazy("PlayerLegend",f_playerlegendid) + +function f_world() + local pos=offsets.base() + T={} + while pos~=0 do + --pos=offsets.find(pos+6,0xa1,DWORD_,mapoffset,0x8b,0x4c,0x88,0xFC) + pos=offsets.find(pos+6,0x8b,0x35,ANYDWORD,0x85,0xf6)--,0x8b,0x4c,0x88,0xFC) + --pos2=offsets.find(pos,0x8b,0x34,0x88) + + if pos~=0 then + add=engine.peekd(pos+2); + --if pos2 ~=0 and pos2-pos<25 then + -- print(string.format("Address:%x dist:%d Map:%x",pos2,pos2-pos,add)) + -- + --end + if add~=0 then + if T[add]~=nil then + T[add]=T[add]+1 + else + T[add]=1 + end + end + end + + end + local kk,vv + vv=0 + for k,v in pairs(T) do + if v>vv then + vv=v + kk=k + end + --print(string.format("Address:%x, times used:%d",k,v)) + end + return kk-offsets.base() +end +offsets.new("WorldData",f_world) + +function f_sites() + local pos=offsets.base() + T={} + while pos~=0 do + + pos=offsets.find(pos+17,0xA1,ANYDWORD, --mov eax, ptr to some biger thing + 0x8B,0x90,0x24,0x01,0x00,0x00, --mov edx [eax+0x124] + 0x2b,0x90,0x20,0x01,0x00,0x00, --sub edx [eax+0x120] + EOL) + if pos~=0 then + add=engine.peekd(pos+1) + return add-offsets.base() + + end + + end + return 0 +end +offsets.newlazy("SiteData",f_sites) --actually has a lot more data... +function f_items() + local pos=offsets.base() + while pos~= 0 do + pos=offsets.find(pos+17,0x8b,0x0d,ANYDWORD, --mov eax, ptr to some biger thing + 0x8B,0x54,0x24,0x34) + if pos~=0 then + --print(string.format("%x",engine.peekd(pos+2))) + local ret=engine.peekd(pos+2)-offsets.base() + return ret + end + end + return 0 +end +offsets.new("Items",f_items) +function f_materials() + for k,v in pairs(offsets.getvectors()) do + --print("Looking into:"..string.format("%x",k).." used:"..v) + local vec=engine.peek(k,ptr_vector) + if vec:getval(0)~=0 then + --print("\tval:"..string.format("%x",vec:getval(0))) + local token=engine.peek(vec:getval(0),ptt_dfstring) + if token:getval()~=""then + --print("\t\tval:".. token:getval()) + if token:getval()=="IRON" then + --print("Found:"..string.format("%x",k).." used:"..v) + return k-offsets.base() + end + end + end + end + return 0 +end +offsets.new("Materials",f_materials) \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/offsets/plugin.lua b/plugins/Dfusion/luafiles/offsets/plugin.lua new file mode 100644 index 000000000..b9e2fc441 --- /dev/null +++ b/plugins/Dfusion/luafiles/offsets/plugin.lua @@ -0,0 +1,2 @@ +offsets.searchoffsets() +offsets.save() \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/offsets_misc.lua b/plugins/Dfusion/luafiles/offsets_misc.lua new file mode 100644 index 000000000..7f13f4b8d --- /dev/null +++ b/plugins/Dfusion/luafiles/offsets_misc.lua @@ -0,0 +1,103 @@ +offsets=offsets or {} +offsets._toff={} +offsets._foff={} +offsets.get = function (name) + if offsets._toff[name] == nil then + offsets.searchoffset(name,true) + end + return offsets._toff[name] +end +offsets.getEx = function (name) + --return offsets._toff[name]+Process.getBase() + return offsets.get(name)+Process.getBase() +end +offsets.load = function () + local f=io.open("dfusion/offsets.txt") + local line=f:read() + while line~=nil do + --print(line) + local sppliter=string.find(line,":") + offsets._toff[string.sub(line,1,sppliter-2)]=tonumber(string.sub(line,sppliter+2)) + line=f:read() + end +end +offsets.save = function () + local f=io.open("dfusion/offsets.txt","w") + for k,v in pairs(offsets._toff) do + + f:write(string.format("%s : 0x%x\n",k,v)) + end + f:close() +end +function offsets.new(name, func) + if type(func)=="function" then + table.insert(offsets._foff,{name,func,false}) + else + offsets._toff[name]=func + end + --offsets._foff[name]={func,false} +end +function offsets.newlazy(name, func) + table.insert(offsets._foff,{name,func,true}) + --offsets._foff[name]={func,true} +end +function offsets.searchoffset(num,forcelazy) + v=offsets._foff[num] + print("Finding offset:"..v[1]) + if (v[3] and focelazy) or not v[3] then + local pos=v[2]() + if pos== 0 then + error("Offset not found for:"..v[1]) + else + offsets._toff[v[1]]=pos + end + end +end +function offsets.searchoffsets(forcelazy) + for k,v in pairs(offsets._foff) do + offsets.searchoffset(k,forcelazy) + end +end +function offsets.find(startoffset,...) + local endadr; + if startoffset== 0 then + local text=GetTextRegion() + --print("searching in:"..text.name) + startoffset=text.start + endadr=text["end"] + else + local reg=GetRegionIn(startoffset) + --print("searching in:"..reg.name) + endadr=reg["end"] + end + local h=hexsearch(startoffset,endadr,...) + local pos=h:find() + h=nil + return pos +end +function offsets.findall(startoffset,...) + local endadr; + if startoffset== 0 then + local text=GetTextRegion() + --print("searching in:"..text.name) + startoffset=text.start + endadr=text["end"] + else + local reg=GetRegionIn(startoffset) + --print("searching in:"..reg.name) + endadr=reg["end"] + end + local h=hexsearch(startoffset,endadr,...) + local pos=h:findall() + h=nil + return pos +end +function offsets.base() + return Process.getBase() +end +function offsets.getvectors() + return findVectors() +end +offsets.load() +ADDRESS=ANYDWORD +dofile("dfusion/offsets.lua") \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/patterns.lua b/plugins/Dfusion/luafiles/patterns.lua index f7c37da0d..92713d6c6 100644 --- a/plugins/Dfusion/luafiles/patterns.lua +++ b/plugins/Dfusion/luafiles/patterns.lua @@ -68,6 +68,7 @@ function ptr_vector:size() end ptr_vector.type=DWORD function ptr_vector:getval(num) + if self.st==0 then return 0 end return engine.peek(self.st+engine.sizeof(self.type)*num,self.type) end function ptr_vector:setval(num,val) From 89c1dba6377e69cb91130efbe7777165b6912ddc Mon Sep 17 00:00:00 2001 From: Warmist Date: Thu, 4 Aug 2011 21:52:22 +0300 Subject: [PATCH 06/10] .o file reader source files --- plugins/Dfusion/include/OutFile.h | 126 +++++++++++++++++++++++++++ plugins/Dfusion/include/lua_Misc.h | 13 +++ plugins/Dfusion/luafiles/common.lua | 28 ++++-- plugins/Dfusion/luafiles/offsets.lua | 26 ++++-- plugins/Dfusion/src/OutFile.cpp | 100 +++++++++++++++++++++ plugins/Dfusion/src/lua_Misc.cpp | 3 + 6 files changed, 283 insertions(+), 13 deletions(-) create mode 100644 plugins/Dfusion/include/OutFile.h create mode 100644 plugins/Dfusion/include/lua_Misc.h create mode 100644 plugins/Dfusion/src/OutFile.cpp create mode 100644 plugins/Dfusion/src/lua_Misc.cpp diff --git a/plugins/Dfusion/include/OutFile.h b/plugins/Dfusion/include/OutFile.h new file mode 100644 index 000000000..665a1e132 --- /dev/null +++ b/plugins/Dfusion/include/OutFile.h @@ -0,0 +1,126 @@ +#ifndef OUTFILE_H +#define OUTFILE_H +#include +#include +#include +#include +#include +namespace OutFile +{ +struct Header +{ + unsigned short machinetype; + unsigned short sectioncount; + unsigned long time; + unsigned long symbolptr; + unsigned long symbolcount; + unsigned short opthead; + unsigned short flags; + void PrintData() + { + std::cout<<"Symbol start:"< vSymbol; +class File +{ +public: + File(std::string path); + virtual ~File(); + + void GetText(char *ptr); + size_t GetTextSize(); + void LoadSymbols(); + vSymbol GetSymbols(){LoadSymbols();return symbols;}; + void PrintSymbols(); + void PrintRelocations(); +protected: +private: + typedef std::map secMap; + + secMap sections; + vSymbol symbols; + Section &GetSection(std::string name); + + std::fstream mystream; + Header myhead; + // Section Text; + //Section Data; + // Section Bss; +}; +} +#endif // OUTFILE_H diff --git a/plugins/Dfusion/include/lua_Misc.h b/plugins/Dfusion/include/lua_Misc.h new file mode 100644 index 000000000..6859bd0ef --- /dev/null +++ b/plugins/Dfusion/include/lua_Misc.h @@ -0,0 +1,13 @@ +#ifndef LUA_MISC_H +#define LUA_MISC_H + +#include "luamain.h" + +namespace lua +{ + +void RegisterMisc(lua::state &st); + +} + +#endif \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/common.lua b/plugins/Dfusion/luafiles/common.lua index e9b5421d8..ec3463440 100644 --- a/plugins/Dfusion/luafiles/common.lua +++ b/plugins/Dfusion/luafiles/common.lua @@ -5,8 +5,8 @@ WORD=2 BYTE=3 function GetTextRegion() - local ranges=Process.getMemRanges() - for k,v in pairs(ranges) do + ranges__=ranges__ or 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))) --end @@ -24,8 +24,8 @@ function GetTextRegion() return nil end function GetRegionIn(pos) - local ranges=Process.getMemRanges() - for k,v in pairs(ranges) do + ranges__=ranges__ or 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))) --end @@ -34,13 +34,31 @@ function GetRegionIn(pos) --if(v["read"])then num=num+1 end --if(v["write"])then num=num+10 end --if(v["execute"]) then num=num+100 end - --print(string.format("%d %x->%x %s %d",k,v["start"],v["end"],v.name,num)) + print(string.format("%d %x->%x %s %x",k,v["start"],v["end"],v.name,pos)) if pos>=v.start and pos<=v["end"] then return v end end return nil end +function ValidOffset(pos) + ranges__=ranges__ or 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))) + --end + --local num + --num=0 + --if(v["read"])then num=num+1 end + --if(v["write"])then num=num+10 end + --if(v["execute"]) then num=num+100 end + --print(string.format("%d %x->%x %s %d",k,v["start"],v["end"],v.name,num)) + if pos>=v.start and pos<=v["end"] then + return true + end + end + return false +end function unlockDF() local reg=GetTextRegion() reg["write"]=true diff --git a/plugins/Dfusion/luafiles/offsets.lua b/plugins/Dfusion/luafiles/offsets.lua index c88602e96..4d5321534 100644 --- a/plugins/Dfusion/luafiles/offsets.lua +++ b/plugins/Dfusion/luafiles/offsets.lua @@ -57,16 +57,26 @@ offsets.new("CreaturePtr",f_creatureptr) function f_creaturegloss() --creature race vector for k,v in pairs(offsets.getvectors()) do - if k~=0 then - --print("Looking into:"..string.format("%x",k).." used:"..v) - + local reg + reg=GetRegionIn(k) + if reg ~=nil then + print(string.format("looking into %x wich is in %s",k,reg.name or "")) + else + print(string.format("looking into %x in nil region",k)) + end + if ValidOffset(k) then + print("Looking into:"..string.format("%x",k).." used:"..v) + local vec=engine.peek(k,ptr_vector) if vec:size()>0 and vec:size()<100000 and vec:getval(0)~=0 then - --print("\tval:"..string.format("%x",vec:getval(0))) - local token=engine.peek(vec:getval(0),ptt_dfstring) - --print("\t\tval:".. token:getval()) - if token:getval()=="TOAD" then -- more offsets could be found this way - return k-offsets.base() + local toff=vec:getval(0) + if ValidOffset(toff) then + print("\tval:"..string.format("%x",vec:getval(0))) + local token=engine.peek(toff,ptt_dfstring) + --print("\t\tval:".. token:getval()) + if token:getval()=="TOAD" then -- more offsets could be found this way + return k-offsets.base() + end end end end diff --git a/plugins/Dfusion/src/OutFile.cpp b/plugins/Dfusion/src/OutFile.cpp new file mode 100644 index 000000000..2d8399b03 --- /dev/null +++ b/plugins/Dfusion/src/OutFile.cpp @@ -0,0 +1,100 @@ +#include "OutFile.h" +using namespace OutFile; +File::File(std::string path) +{ + //mystream.exceptions ( std::fstream::eofbit | std::fstream::failbit | std::fstream::badbit ); + mystream.open(path.c_str(),std::fstream::binary|std::ios::in|std::ios::out); + mystream.read((char*)&myhead,sizeof(myhead)); + for(unsigned i=0;isecond.PrintData(); + }*/ + + } + else + { + std::cout<<"Error opening file!"<first<<":\n"; + for(unsigned i=0;isecond.numRel;i++) + { + Relocation r; + mystream.seekg(it->second.ptrRel+10*i); + mystream.read((char*)&r,10); + std::cout<0) + { + i+=s.auxsymbs; + } + } + +} +void File::LoadSymbols() +{ + symbols.clear(); + for(unsigned i=0;i0) + { + i+=s.auxsymbs; + } + } +} +File::~File() +{ + +} diff --git a/plugins/Dfusion/src/lua_Misc.cpp b/plugins/Dfusion/src/lua_Misc.cpp new file mode 100644 index 000000000..e9b7dd1e9 --- /dev/null +++ b/plugins/Dfusion/src/lua_Misc.cpp @@ -0,0 +1,3 @@ +#include "lua_Misc.h" + +void lua::RegisterMisc(lua::state &st); \ No newline at end of file From 9985b5de0fc41bc9c41adfadc363ec66c7611e03 Mon Sep 17 00:00:00 2001 From: Warmist Date: Thu, 4 Aug 2011 22:00:21 +0300 Subject: [PATCH 07/10] DFHack::Core modification: added a way to share void* between plugins and/or plugin unloads. --- library/Core.cpp | 13 +++++++++++++ library/include/dfhack/Core.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/library/Core.cpp b/library/Core.cpp index e3f0263a7..bf9b9fa2f 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -469,6 +469,19 @@ std::string Core::getHotkeyCmd( void ) return returner; } +void Core::RegisterData(void *p,std::string key) +{ + misc_data_map[key]=p; +} + +void *Core::GetData(std::string key) +{ + std::map::iterator it=misc_data_map.find(key); + if (it!=misc_data_map.end()) + return misc_data_map[key]; + else + return 0;// or throw an error. +} void Core::Suspend() { diff --git a/library/include/dfhack/Core.h b/library/include/dfhack/Core.h index 9d5b1fe5a..dab39f858 100644 --- a/library/include/dfhack/Core.h +++ b/library/include/dfhack/Core.h @@ -126,6 +126,11 @@ namespace DFHack /// removes the hotkey command and gives it to the caller thread std::string getHotkeyCmd( void ); + /// adds a named pointer (for later or between plugins) + void RegisterData(void *p,std::string key); + /// returns a named pointer. + void *GetData(std::string key); + DFHack::Process * p; DFHack::VersionInfo * vinfo; DFHack::Console con; @@ -174,5 +179,7 @@ namespace DFHack tthread::condition_variable * HotkeyCond; // Very important! bool started; + + std::map misc_data_map; }; } From 4b9786f8afcc091fe672b11bf8054bc373db3877 Mon Sep 17 00:00:00 2001 From: Warmist Date: Thu, 4 Aug 2011 22:33:54 +0300 Subject: [PATCH 08/10] Thread safety for void* sharing part of DFHack::Core --- library/Core.cpp | 15 ++++++++++++++- library/include/dfhack/Core.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/library/Core.cpp b/library/Core.cpp index bf9b9fa2f..e3fcc2329 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -383,6 +383,7 @@ Core::Core() hotkey_set = false; HotkeyMutex = 0; HotkeyCond = 0; + misc_data_mutex=0; }; bool Core::Init() @@ -437,6 +438,7 @@ bool Core::Init() HotkeyMutex = new mutex(); HotkeyCond = new condition_variable(); thread * HK = new thread(fHKthread, (void *) temp); + misc_data_mutex=new mutex(); started = true; return true; } @@ -471,16 +473,27 @@ std::string Core::getHotkeyCmd( void ) void Core::RegisterData(void *p,std::string key) { + misc_data_mutex->lock(); misc_data_map[key]=p; + misc_data_mutex->unlock(); } void *Core::GetData(std::string key) { + misc_data_mutex->lock(); std::map::iterator it=misc_data_map.find(key); + if (it!=misc_data_map.end()) - return misc_data_map[key]; + { + void *p=it->second; + misc_data_mutex->unlock(); + return p; + } else + { + misc_data_mutex->unlock(); return 0;// or throw an error. + } } void Core::Suspend() diff --git a/library/include/dfhack/Core.h b/library/include/dfhack/Core.h index dab39f858..2cc9ff149 100644 --- a/library/include/dfhack/Core.h +++ b/library/include/dfhack/Core.h @@ -180,6 +180,7 @@ namespace DFHack // Very important! bool started; + tthread::mutex * misc_data_mutex; std::map misc_data_map; }; } From 835581e5d3e5e93d06e3d68f18eb4c2b6d52ca81 Mon Sep 17 00:00:00 2001 From: Warmist Date: Fri, 5 Aug 2011 00:22:25 +0300 Subject: [PATCH 09/10] Embark and friendship working Signed-off-by: Warmist --- plugins/Dfusion/dfusion.cpp | 6 + plugins/Dfusion/include/lua_Misc.h | 32 ++++ plugins/Dfusion/luafiles/common.lua | 35 +++- plugins/Dfusion/luafiles/embark/a.out | 0 plugins/Dfusion/luafiles/embark/build.bat | 1 + plugins/Dfusion/luafiles/embark/embark.asm | 9 ++ plugins/Dfusion/luafiles/embark/embark.o | Bin 0 -> 356 bytes plugins/Dfusion/luafiles/embark/plugin.lua | 75 +++++++++ plugins/Dfusion/luafiles/embark/races.txt | 7 + .../Dfusion/luafiles/friendship/compile.bat | 1 + .../luafiles/friendship/friendship.asm | 102 ++++++++++++ .../Dfusion/luafiles/friendship/friendship.o | Bin 0 -> 722 bytes .../Dfusion/luafiles/friendship/install.lua | 35 ++++ plugins/Dfusion/luafiles/friendship/patch.lua | 56 +++++++ .../Dfusion/luafiles/friendship/plugin.lua | 60 +++++++ plugins/Dfusion/luafiles/friendship/races.txt | 8 + plugins/Dfusion/luafiles/init.lua | 2 + plugins/Dfusion/luafiles/offsets_misc.lua | 1 + plugins/Dfusion/luafiles/patterns.lua | 4 +- plugins/Dfusion/src/hexsearch.cpp | 9 +- plugins/Dfusion/src/lua_Misc.cpp | 151 +++++++++++++++++- 21 files changed, 589 insertions(+), 5 deletions(-) create mode 100644 plugins/Dfusion/luafiles/embark/a.out create mode 100644 plugins/Dfusion/luafiles/embark/build.bat create mode 100644 plugins/Dfusion/luafiles/embark/embark.asm create mode 100644 plugins/Dfusion/luafiles/embark/embark.o create mode 100644 plugins/Dfusion/luafiles/embark/plugin.lua create mode 100644 plugins/Dfusion/luafiles/embark/races.txt create mode 100644 plugins/Dfusion/luafiles/friendship/compile.bat create mode 100644 plugins/Dfusion/luafiles/friendship/friendship.asm create mode 100644 plugins/Dfusion/luafiles/friendship/friendship.o create mode 100644 plugins/Dfusion/luafiles/friendship/install.lua create mode 100644 plugins/Dfusion/luafiles/friendship/patch.lua create mode 100644 plugins/Dfusion/luafiles/friendship/plugin.lua create mode 100644 plugins/Dfusion/luafiles/friendship/races.txt diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index 45aa3c687..79b8f1f94 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -15,6 +15,7 @@ #include "lua_Console.h" #include "lua_Process.h" #include "lua_Hexsearch.h" +#include "lua_Misc.h" #include "functioncall.h" using std::vector; @@ -39,6 +40,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector lua::RegisterConsole(lua::glua::Get(),&c->con); lua::RegisterProcess(lua::glua::Get(),c->p); lua::RegisterHexsearch(lua::glua::Get()); + lua::RegisterMisc(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)); @@ -73,6 +75,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) catch(lua::exception &e) { c->con.printerr("Error OnTick:%s\n",e.what()); + c->con.printerr("%s",lua::DebugDump(lua::glua::Get())); c->con.msleep(1000); } } @@ -99,6 +102,7 @@ void InterpreterLoop(Core* c) catch(lua::exception &e) { con.printerr("Error:%s\n",e.what()); + c->con.printerr("%s",lua::DebugDump(lua::glua::Get())); s.settop(0); } con.lineedit(">>",curline); @@ -119,6 +123,7 @@ DFhackCExport command_result lua_run (Core * c, vector & parameters) catch(lua::exception &e) { con.printerr("Error:%s\n",e.what()); + c->con.printerr("%s",lua::DebugDump(lua::glua::Get())); } } else @@ -143,6 +148,7 @@ DFhackCExport command_result dfusion (Core * c, vector & parameters) catch(lua::exception &e) { con.printerr("Error:%s\n",e.what()); + c->con.printerr("%s",lua::DebugDump(lua::glua::Get())); } s.settop(0);// clean up mymutex->unlock(); diff --git a/plugins/Dfusion/include/lua_Misc.h b/plugins/Dfusion/include/lua_Misc.h index 6859bd0ef..6f1416257 100644 --- a/plugins/Dfusion/include/lua_Misc.h +++ b/plugins/Dfusion/include/lua_Misc.h @@ -1,11 +1,43 @@ #ifndef LUA_MISC_H #define LUA_MISC_H +#include + +#include +#include #include "luamain.h" +#include "OutFile.h" namespace lua { +typedef std::map mapPlugs; + +class PlugManager +{ + public: + + mapPlugs GetList(){return plugs;}; + uint32_t AddNewPlug(std::string name,uint32_t size,uint32_t loc=0); + uint32_t FindPlugin(std::string name); + + static PlugManager &GetInst() + { + void *p; + p=DFHack::Core::getInstance().GetData("dfusion_manager"); + if(p==0) + { + p=new PlugManager; + DFHack::Core::getInstance().RegisterData(p,"dfusion_manager"); + } + return *static_cast(p); + }; + protected: + private: + PlugManager(){}; + mapPlugs plugs; +}; + void RegisterMisc(lua::state &st); } diff --git a/plugins/Dfusion/luafiles/common.lua b/plugins/Dfusion/luafiles/common.lua index ec3463440..ca26e56b2 100644 --- a/plugins/Dfusion/luafiles/common.lua +++ b/plugins/Dfusion/luafiles/common.lua @@ -34,7 +34,7 @@ function GetRegionIn(pos) --if(v["read"])then num=num+1 end --if(v["write"])then num=num+10 end --if(v["execute"]) then num=num+100 end - print(string.format("%d %x->%x %s %x",k,v["start"],v["end"],v.name,pos)) + --print(string.format("%d %x->%x %s %x",k,v["start"],v["end"],v.name,pos)) if pos>=v.start and pos<=v["end"] then return v end @@ -69,6 +69,11 @@ function lockDF() reg["write"]=false Process.setPermisions(reg,reg) end +function SetExecute(pos) + local reg=GetRegionIn(pos) + reg.execute=true + Process.setPermisions(reg,reg) -- TODO maybe make a page with only execute permisions or sth +end -- engine bindings engine=engine or {} engine.peekd=Process.readDWord @@ -163,6 +168,31 @@ function engine.pokepattern(offset,pattern,val) end end +function engine.LoadModData(file) + local T2={} + T2.symbols={} + T2.data,T2.size=engine.loadobj(file) + data,modsize=engine.loadobj(file) + local T=engine.loadobjsymbols(file) + for k,v in pairs(T) do + + if v.pos~=0 then + T2.symbols[v.name]=v.pos + end + end + return T2 +end +function engine.FindMarker(moddata,name) + if moddata.symbols[name] ~=nil then + return engine.findmarker(0xDEADBEEF,moddata.data,moddata.size,moddata.symbols[name]) + end +end +function engine.installMod(file,name,bonussize) + local T=engine.LoadModData(file) + local modpos,modsize=engine.loadmod(file,name,bonussize) + T.pos=modpos + return T +end it_menu={} it_menu.__index=it_menu @@ -290,8 +320,11 @@ end function GetRaceToken(p) --actually gets token... local vec=engine.peek(offsets.getEx('CreatureGloss'),ptr_vector) + --print("Vector ok") local off=vec:getval(p) + --print("Offset:"..off) local crgloss=engine.peek(off,ptr_CrGloss) + --print("Peek ok") return crgloss.token:getval() end function BuildNameTable() diff --git a/plugins/Dfusion/luafiles/embark/a.out b/plugins/Dfusion/luafiles/embark/a.out new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/Dfusion/luafiles/embark/build.bat b/plugins/Dfusion/luafiles/embark/build.bat new file mode 100644 index 000000000..51eeb8140 --- /dev/null +++ b/plugins/Dfusion/luafiles/embark/build.bat @@ -0,0 +1 @@ +as -a --32 -o embark.o embark.asm \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/embark/embark.asm b/plugins/Dfusion/luafiles/embark/embark.asm new file mode 100644 index 000000000..fc3245983 --- /dev/null +++ b/plugins/Dfusion/luafiles/embark/embark.asm @@ -0,0 +1,9 @@ +.intel_syntax +mov eax , [esp+0x1C] +caste: +movsx eax, word ptr[eax*2+0xdeadbeef] +mov [esp+0x04],eax +mov eax , [esp+0x1C] +race: +movzx eax,word ptr [eax*2+0xDEADBEEF] +ret diff --git a/plugins/Dfusion/luafiles/embark/embark.o b/plugins/Dfusion/luafiles/embark/embark.o new file mode 100644 index 0000000000000000000000000000000000000000..ec19c9dcfe645c21058d2a00d1a155304eed9e7a GIT binary patch literal 356 zcmeZaWM%+?H9*V-X0bBrm84dbfY}g20Z8>A@j*-l27?5>l*E!mG;wsU1B1Z_@WI%8U5HcS92 zo}5@*0uo{YVn!flV<<{Y2CET)iy-?Cq=uPM7D%E3WWO;1rII3a0tG+rTticRPp<-2Hyv+Iu@Murn~ES-N;Lm2i1B|NLM2Idbl6w#d1b z2VS!q-ZnhoV0j}tV)6TZZ~sNiahMyh5X3sHmzJ563iaT>{|pT2jA@D4FafA|R&GH_ zQVs(HCy);edImOzqSSO}kYqfvhzm$0A6di+B$AFI5&-0tBa65OdonQ8qlmZwMcR=? z9Dy8$V7N$HVkXcv3=HexBFXu=1&Kwe483rXoc#O(Lm+PkTqHFwB|jU;TZt@^mYJ8B nvkfkSoSHyBWo87WCscr(l9+%}%piqm067(b(kwPLEI@Gp^f!o8 literal 0 HcmV?d00001 diff --git a/plugins/Dfusion/luafiles/friendship/install.lua b/plugins/Dfusion/luafiles/friendship/install.lua new file mode 100644 index 000000000..aa0653c7f --- /dev/null +++ b/plugins/Dfusion/luafiles/friendship/install.lua @@ -0,0 +1,35 @@ + +function friendship_in.install(names) +RaceTable=RaceTable or BuildNameTable() +mypos=engine.getmod("Friendship") +if mypos then +modpos=mypos +_,modsize=engine.loadobj("dfusion/friendship/friendship.o") +_=nil +else +modpos,modsize=engine.loadmod("dfusion/friendship/friendship.o","Friendship",1024) +print(string.format("Loaded module @:%x",modpos)) +end +count=0 +for _,v in pairs(names) do + if RaceTable[v] == nil then + --print("Failure, "..v.." not found!") + error("Failure, "..v.." not found!") + --break --maybe some indication of failure? and cleanup? + end + engine.pokew(modpos+modsize+count*2+4+2,RaceTable[v]) -- for some reason it compiled strangely + -- cmp word[ebx+ecx*2],ax -> cmp word[ebx+ecx*2+2],ax + count = count + 1 +end +engine.poked(modpos+0x8f,modpos+modsize+4) -- set ptr to creatures +engine.poked(modpos+0x94,count) -- set count of creatures +engine.poked(modpos+0xb9,modpos+modsize) -- set safe location +engine.poked(modpos+0xc3,modpos+modsize) -- set safe location +SetExecute(modpos) +end +function pokeCall(off) + engine.pokeb(off,0xe8) + b=engine.peekb(off+1) + engine.poked(off+1,modpos-off-5) + engine.pokeb(off+5,b) +end \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/friendship/patch.lua b/plugins/Dfusion/luafiles/friendship/patch.lua new file mode 100644 index 000000000..b11ad41da --- /dev/null +++ b/plugins/Dfusion/luafiles/friendship/patch.lua @@ -0,0 +1,56 @@ +function friendship_in.patch() + pos=GetTextRegion().start + local crace=offsets.getEx("CurrentRace") + hits={} + i=1 + repeat + --todo make something better/smarter... + pos1=offsets.find(pos+7,0x0f,0xBF,ANYBYTE,DWORD_,crace) -- movsx + pos2=offsets.find(pos+7,0x66,0xa1,DWORD_,crace) -- mov ax,[ptr] + pos3=offsets.find(pos+7,0xa1,DWORD_,crace) -- mov eax,[ptr] + pos4=offsets.find(pos+7,0x66,0x8b,ANYBYTE,DWORD_,crace) -- mov ANYREG,[ptr] + --pos5=offsets.find(pos+7,0x66,0x8b,0x15,DWORD_,crace) -- mov dx,[ptr] + + pos=minEx(pos1,pos2,pos3,pos4) + if pos ~=0 then + hits[i]=pos + i=i+1 + print(string.format("Found at %x",pos)) + end + until pos==0 + print("=======================================") + for _,p in pairs(hits) do + myp=p + repeat + + --print(string.format("Analyzing %x...",p)) + pos1=offsets.find(myp,0x39,ANYBYTE,0x8c,00,00,00) -- compare [reg+08c] (creature race) with any reg + pos2=offsets.find(myp,0x3b,ANYBYTE,0x8c,00,00,00) -- compare any reg with [reg+08c] (creature race) + pos=minEx(pos1,pos2) + if pos ~=0 then + + if(pos-p>250) then + --this here does not work yet... + --[[pos =offsets.find(p,CALL) + print(string.format("Distance to call:%x",pos-p)) + print(string.format("Call: %x",signDword(engine.peekd(pos+1)+pos))) + pos=analyzeF(signDword(signDword(engine.peekd(pos+1)+pos))) + + print(string.format("Cmp @:%x",pos))]]-- + print(string.format("skipping %x... Cmp too far away (dist=%i)",p,pos-p)) + else + --print(string.format("Found at %x, simple compare",pos)) + --print(string.format("Distance =%x",pos-p)) + --patch compares + + pokeCall(pos) + end + else + break + end + myp=myp+pos+6 + if myp-p >250 then break end + until false + + end +end \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/friendship/plugin.lua b/plugins/Dfusion/luafiles/friendship/plugin.lua new file mode 100644 index 000000000..b3c5ea50f --- /dev/null +++ b/plugins/Dfusion/luafiles/friendship/plugin.lua @@ -0,0 +1,60 @@ +--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,EOL) + 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,EOL) + 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("Your current race is:"..GetRaceToken(engine.peekw(offsets.getEx('CurrentRace')))) +print("If this is wrong please quit now (by ctrl+c)") +io.stdin:read() +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 + diff --git a/plugins/Dfusion/luafiles/friendship/races.txt b/plugins/Dfusion/luafiles/friendship/races.txt new file mode 100644 index 000000000..e4ed7c5a6 --- /dev/null +++ b/plugins/Dfusion/luafiles/friendship/races.txt @@ -0,0 +1,8 @@ +DWARF +GOBLIN +ELF +HUMAN +KOBOLD +GREMLIN +TIGERMAN +ANT_MAN \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/init.lua b/plugins/Dfusion/luafiles/init.lua index 1202fb534..92ef5f195 100644 --- a/plugins/Dfusion/luafiles/init.lua +++ b/plugins/Dfusion/luafiles/init.lua @@ -35,5 +35,7 @@ plugins={} table.insert(plugins,{"simple_embark","A simple embark dwarf count editor"}) table.insert(plugins,{"items","A collection of item hacking tools"}) table.insert(plugins,{"offsets","Find all offsets"}) +table.insert(plugins,{"friendship","Multi race fort enabler"}) +table.insert(plugins,{"embark","Multi race embark"}) mainmenu(plugins) diff --git a/plugins/Dfusion/luafiles/offsets_misc.lua b/plugins/Dfusion/luafiles/offsets_misc.lua index 7f13f4b8d..80f420baa 100644 --- a/plugins/Dfusion/luafiles/offsets_misc.lua +++ b/plugins/Dfusion/luafiles/offsets_misc.lua @@ -70,6 +70,7 @@ function offsets.find(startoffset,...) --print("searching in:"..reg.name) endadr=reg["end"] end + --print(string.format("Searching (%x->%x)",startoffset,endadr)) local h=hexsearch(startoffset,endadr,...) local pos=h:find() h=nil diff --git a/plugins/Dfusion/luafiles/patterns.lua b/plugins/Dfusion/luafiles/patterns.lua index 92713d6c6..f4ac43650 100644 --- a/plugins/Dfusion/luafiles/patterns.lua +++ b/plugins/Dfusion/luafiles/patterns.lua @@ -68,7 +68,9 @@ function ptr_vector:size() end ptr_vector.type=DWORD function ptr_vector:getval(num) - if self.st==0 then return 0 end + if self.st==0 then return error("Vector empty.") end + --print("Wants:"..num.." size:"..self:size()) + if num>=self:size() then error("Index out of bounds in vector.") end return engine.peek(self.st+engine.sizeof(self.type)*num,self.type) end function ptr_vector:setval(num,val) diff --git a/plugins/Dfusion/src/hexsearch.cpp b/plugins/Dfusion/src/hexsearch.cpp index ec0abb4f0..1958086ce 100644 --- a/plugins/Dfusion/src/hexsearch.cpp +++ b/plugins/Dfusion/src/hexsearch.cpp @@ -19,6 +19,11 @@ inline bool Hexsearch::Compare(int a,int b) } void Hexsearch::ReparseArgs() { + union + { + uint32_t val; + uint8_t bytes[4]; + }B; SearchArgType targ; targ=args_; args_.clear(); @@ -27,10 +32,10 @@ void Hexsearch::ReparseArgs() if(targ[i]==DWORD_) { i++; + B.val=targ[i]; for(int j=0;j<4;j++) { - args_.push_back((targ[i]&(0xff<>i);//TODO is this correct??? - + args_.push_back(B.bytes[j]); } i++; } diff --git a/plugins/Dfusion/src/lua_Misc.cpp b/plugins/Dfusion/src/lua_Misc.cpp index e9b7dd1e9..aacf65e2b 100644 --- a/plugins/Dfusion/src/lua_Misc.cpp +++ b/plugins/Dfusion/src/lua_Misc.cpp @@ -1,3 +1,152 @@ #include "lua_Misc.h" +uint32_t lua::PlugManager::AddNewPlug(std::string name,uint32_t size,uint32_t loc) +{ + void *p; + if(size!=0) + p=new unsigned char[size]; + else + p=(void*)loc; + plugs[name]=p; + return (uint32_t)p; +} +uint32_t lua::PlugManager::FindPlugin(std::string name) +{ + mapPlugs::iterator it=plugs.find(name); + if(it!=plugs.end()) + return (uint32_t)it->second; + else + return 0; +} -void lua::RegisterMisc(lua::state &st); \ No newline at end of file + +static int LoadMod(lua_State *L) +{ + lua::state st(L); + std::string modfile=st.as(1); + std::string modname=st.as(2); + uint32_t size_add=st.as(0,3); + OutFile::File f(modfile); + uint32_t size=f.GetTextSize(); + uint32_t pos=lua::PlugManager::GetInst().AddNewPlug(modname,size+size_add); + char *buf; + buf=new char[size]; + f.GetText(buf); + //std::cout<<"poking @:"<write(pos,size,(uint8_t*)buf); + delete [] buf; + st.push(pos); + st.push(size); + return 2; +} +static int LoadObj(lua_State *L) +{ + lua::state st(L); + std::string modfile=st.as(1); + OutFile::File f(modfile); + size_t s=f.GetTextSize(); + void *p=st.newuserdata(s); //TODO does it leak memory?? + f.GetText((char*)p); + st.push(s); + return 2; +} +static int FindMarker(lua_State *L) // marker, void ptr, size, start +{ + lua::state st(L); + union + { + unsigned char bytes[4]; + size_t mark; + }M; + M.mark=st.as(1); + unsigned char *p=(unsigned char *)lua_touserdata(L, 2);//st.as(2); + size_t size=st.as(3); + size_t start=st.as(4); + for(size_t i=start;i(1); + OutFile::File f(modfile); + OutFile::vSymbol vec=f.GetSymbols(); + OutFile::Symbol S; + + st.newtable(); + for(size_t i=0;i(1); + size_t size=st.as(2); + size_t loc=st.as(3,0); + uint32_t pos=lua::PlugManager::GetInst().AddNewPlug(modname,size,loc); + st.push(pos); + return 1; +} +static int GetMod(lua_State *L) +{ + lua::state st(L); + std::string modname=st.as(1); + uint32_t pos=lua::PlugManager::GetInst().FindPlugin(modname); + if(pos==0) + st.push(); + else + st.push(pos); + return 1; +} +const luaL_Reg lua_misc_func[]= +{ + {"loadmod",LoadMod}, + {"getmod",GetMod}, + {"loadobj",LoadObj}, + {"loadobjsymbols",LoadObjSymbols}, + {"findmarker",FindMarker}, + {"newmod",NewMod}, + {NULL,NULL} +}; +void lua::RegisterMisc(lua::state &st) +{ + st.getglobal("engine"); + if(st.is()) + { + st.pop(); + st.newtable(); + } + lua::RegFunctionsLocal(st, lua_misc_func); + st.setglobal("engine"); +} \ No newline at end of file From f2b8ff12809120d250c2a6c5db722071dbdc163e Mon Sep 17 00:00:00 2001 From: Warmist Date: Fri, 5 Aug 2011 00:44:56 +0300 Subject: [PATCH 10/10] All plugins added, triggers not working yet other +- work Signed-off-by: Warmist --- plugins/Dfusion/luafiles/adv_tools/plugin.lua | 87 +++ plugins/Dfusion/luafiles/common.lua | 13 +- .../Dfusion/luafiles/friendship/plugin.lua | 4 +- plugins/Dfusion/luafiles/init.lua | 4 + plugins/Dfusion/luafiles/migrants/compile.bat | 1 + .../Dfusion/luafiles/migrants/migrants.asm | 20 + plugins/Dfusion/luafiles/migrants/migrants.o | Bin 0 -> 336 bytes plugins/Dfusion/luafiles/migrants/plugin.lua | 65 +++ plugins/Dfusion/luafiles/migrants/races.txt | 29 + plugins/Dfusion/luafiles/tools/plugin.lua | 529 ++++++++++++++++++ plugins/Dfusion/luafiles/triggers/compile.bat | 1 + .../Dfusion/luafiles/triggers/functions.lua | 20 + .../luafiles/triggers/functions_menu.lua | 12 + plugins/Dfusion/luafiles/triggers/plugin.lua | 107 ++++ .../Dfusion/luafiles/triggers/triggers.asm | 68 +++ plugins/Dfusion/luafiles/triggers/triggers.o | Bin 0 -> 720 bytes .../luafiles/triggers/universalfunc.asm | 14 + 17 files changed, 971 insertions(+), 3 deletions(-) create mode 100644 plugins/Dfusion/luafiles/adv_tools/plugin.lua create mode 100644 plugins/Dfusion/luafiles/migrants/compile.bat create mode 100644 plugins/Dfusion/luafiles/migrants/migrants.asm create mode 100644 plugins/Dfusion/luafiles/migrants/migrants.o create mode 100644 plugins/Dfusion/luafiles/migrants/plugin.lua create mode 100644 plugins/Dfusion/luafiles/migrants/races.txt create mode 100644 plugins/Dfusion/luafiles/tools/plugin.lua create mode 100644 plugins/Dfusion/luafiles/triggers/compile.bat create mode 100644 plugins/Dfusion/luafiles/triggers/functions.lua create mode 100644 plugins/Dfusion/luafiles/triggers/functions_menu.lua create mode 100644 plugins/Dfusion/luafiles/triggers/plugin.lua create mode 100644 plugins/Dfusion/luafiles/triggers/triggers.asm create mode 100644 plugins/Dfusion/luafiles/triggers/triggers.o create mode 100644 plugins/Dfusion/luafiles/triggers/universalfunc.asm diff --git a/plugins/Dfusion/luafiles/adv_tools/plugin.lua b/plugins/Dfusion/luafiles/adv_tools/plugin.lua new file mode 100644 index 000000000..7ad4726d7 --- /dev/null +++ b/plugins/Dfusion/luafiles/adv_tools/plugin.lua @@ -0,0 +1,87 @@ +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. + 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 ca26e56b2..200621b82 100644 --- a/plugins/Dfusion/luafiles/common.lua +++ b/plugins/Dfusion/luafiles/common.lua @@ -458,7 +458,18 @@ function GetCreatureAtPos(x,y,z) -- gets the creature index @ x,y,z coord return -1 end - +function Allocate(size) + local ptr=engine.getmod('General_Space') + if ptr==nil then + ptr=engine.newmod("General_Space",4096) -- some time later maybe make some more space + engine.poked(ptr,4) + end + + local curptr=engine.peekd(ptr) + curptr=curptr+size + engine.poked(ptr,curptr) + return curptr-size+ptr +end dofile("dfusion/patterns.lua") dofile("dfusion/patterns2.lua") dofile("dfusion/itempatterns.lua") \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/friendship/plugin.lua b/plugins/Dfusion/luafiles/friendship/plugin.lua index b3c5ea50f..2a317afe0 100644 --- a/plugins/Dfusion/luafiles/friendship/plugin.lua +++ b/plugins/Dfusion/luafiles/friendship/plugin.lua @@ -5,14 +5,14 @@ --end function analyzeF(off) - pos=offsets.find(off,0x39,ANYBYTE,0x8c,00,00,00,EOL) + 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,EOL) + pos =offsets.find(off,CALL) print(string.format("Distance to call:%x",pos-off)) return 0 --return analyzeF(pos) diff --git a/plugins/Dfusion/luafiles/init.lua b/plugins/Dfusion/luafiles/init.lua index 92ef5f195..9eb595641 100644 --- a/plugins/Dfusion/luafiles/init.lua +++ b/plugins/Dfusion/luafiles/init.lua @@ -37,5 +37,9 @@ table.insert(plugins,{"items","A collection of item hacking tools"}) table.insert(plugins,{"offsets","Find all offsets"}) table.insert(plugins,{"friendship","Multi race fort enabler"}) table.insert(plugins,{"embark","Multi race embark"}) +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"}) mainmenu(plugins) diff --git a/plugins/Dfusion/luafiles/migrants/compile.bat b/plugins/Dfusion/luafiles/migrants/compile.bat new file mode 100644 index 000000000..4d226851d --- /dev/null +++ b/plugins/Dfusion/luafiles/migrants/compile.bat @@ -0,0 +1 @@ +as -anl --32 -o migrants.o migrants.asm \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/migrants/migrants.asm b/plugins/Dfusion/luafiles/migrants/migrants.asm new file mode 100644 index 000000000..646497665 --- /dev/null +++ b/plugins/Dfusion/luafiles/migrants/migrants.asm @@ -0,0 +1,20 @@ +.intel_syntax +pushfd +push ebx +push edx +mov eax,[0xdeadbeef] # get old seed +mov ebx,1103515245 +#mul 1103515245 +mul ebx +add eax,12345 +mov [0xdeadbeef],eax #put seed back...thus generation rnd is complete + +xor edx,edx +mov ebx,2000 #put size of array here +div ebx #why oh why there is no div const? compiler prob makes some xor/add magic +movzx eax,word ptr[0xdeadbeef+edx*2] +pop edx +pop ebx + +popfd +ret diff --git a/plugins/Dfusion/luafiles/migrants/migrants.o b/plugins/Dfusion/luafiles/migrants/migrants.o new file mode 100644 index 0000000000000000000000000000000000000000..30b5b14f03cd8e110b91123e0631f8e0b3378ed0 GIT binary patch literal 336 zcmeZaWM%+?JwVI>X0bBrm84dbfY}hj07&&9@j*-l27?5>l*E!mG;wsU1B1Zh*T58Y}8WPdP$)nF)LK=uPD#F#;bp#c^k F9{~H9FI)fs literal 0 HcmV?d00001 diff --git a/plugins/Dfusion/luafiles/migrants/plugin.lua b/plugins/Dfusion/luafiles/migrants/plugin.lua new file mode 100644 index 000000000..0e1e46160 --- /dev/null +++ b/plugins/Dfusion/luafiles/migrants/plugin.lua @@ -0,0 +1,65 @@ +--install part +function migrants(names) +RaceTable=RaceTable or BuildNameTable() +mypos=engine.getmod("Migrants") +if mypos then + print("Migrant mod is running already @:"..mypos) + modpos=mypos + _,modsize=engine.loadobj("dfusion/migrants/migrants.o") + count=0 + for _,v in pairs(names) do + if RaceTable[v] == nil then + print("Failure, "..v.." not found!") + break --maybe some indication of failure? and cleanup? + end + engine.pokew(modpos+modsize+count*2+4,RaceTable[v]) + count = count + 1 + end + seedpos=modpos+modsize + engine.poked(seedpos,math.random(1234567)) -- seed the generator :) + engine.poked(modpos+0x1c,count) --max size for div + +else + modpos,modsize=engine.loadmod("dfusion/migrants/migrants.o","Migrants") + print(string.format("Loaded module @:%x",modpos)) + count=0 + for _,v in pairs(names) do + if RaceTable[v] == nil then + print("Failure, "..v.." not found!") + break --maybe some indication of failure? and cleanup? + end + engine.pokew(modpos+modsize+count*2+4,RaceTable[v]) + + count = count + 1 + end + + seedpos=modpos+modsize + engine.poked(modpos+0x04,seedpos) + engine.poked(modpos+0x15,seedpos) + + engine.poked(seedpos,math.random(1234567)) -- seed the generator :) + engine.poked(modpos+0x1c,count) --max size for div + + engine.poked(modpos+0x26,seedpos+4) --start of array + + --patch part + --pos=62873C+DF + -- pattern: A1,DWORD_,"CURRENTRACE",56,89,ANYBYTE,ANYBYTE,34,e8 + pos=offsets.find(offsets.base(),0xa1,DWORD_,offsets.getEx("CurrentRace"),0x56,0x89,ANYBYTE,ANYBYTE,0x34,0xe8) + function pokeCall(off) + engine.pokeb(off,0xe8) + engine.poked(off+1,modpos-off-5) + end + if pos~=0 then + print(string.format("Found @:%x",pos)) + pokeCall(pos) + else + print("Not found patch location!!!") + end + end + +end +if not(FILE) then + names=ParseNames("dfusion/migrants/races.txt")--io.open("plugins/migrants/races.txt"):lines() + migrants(names) +end \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/migrants/races.txt b/plugins/Dfusion/luafiles/migrants/races.txt new file mode 100644 index 000000000..9a3fa6cf6 --- /dev/null +++ b/plugins/Dfusion/luafiles/migrants/races.txt @@ -0,0 +1,29 @@ +DWARF +DWARF +DWARF +DWARF +DWARF +DWARF +DWARF +DWARF +DWARF +ELF +HUMAN +DWARF +GREMLIN +KOBOLD +DWARF +DWARF +DWARF +DWARF +DWARF +DWARF +DWARF +DWARF +DWARF +ELF +HUMAN +DWARF +GREMLIN +KOBOLD +DEMON_13 \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/tools/plugin.lua b/plugins/Dfusion/luafiles/tools/plugin.lua new file mode 100644 index 000000000..0a7bbc872 --- /dev/null +++ b/plugins/Dfusion/luafiles/tools/plugin.lua @@ -0,0 +1,529 @@ +--local bit = require("bit") +tools={} +tools.menu=MakeMenu() +function tools.setrace() + RaceTable=RaceTable or BuildNameTable() --slow.If loaded don't load again + print("Your current race is:"..GetRaceToken(engine.peekw(offsets.getEx('CurrentRace')))) + print("Type new race's token name in full caps:") + repeat + entry=io.stdin:read() + id=RaceTable[entry] + until id~=nil + engine.pokew(offsets.getEx('CurrentRace'),id) +end +tools.menu:add("Set current race",tools.setrace) +function tools.GiveSentience(names) --TODO make pattern... + RaceTable=RaceTable or BuildNameTable() --slow.If loaded don't load again + if names ==nil then + ids={} + print("Type race's token name in full caps to give sentience to:") + repeat + entry=io.stdin:read() + id=RaceTable[entry] + until id~=nil + table.insert(ids,id) + else + ids={} + for _,name in pairs(names) do + id=RaceTable[name] + table.insert(ids,id) + end + end + for _,id in pairs(ids) do + local off=offsets.getEx('CreatureGloss') + local races=engine.peek(off,ptr_vector) + --print("Vector start:"..off) + + off=races:getval(id) + print(string.format("race location:%x",off)) + local castes=engine.peek(off,ptr_CrGloss.castes) + print(string.format("Caste count:%i",castes:size())) + local flagPattern=ptt_dfflag.new(17) + for i =0,castes:size()-1 do + local offCaste=castes:getval(i) + print("Caste name:"..engine.peek(offCaste,ptr_CrCaste.name):getval().."...") + local flagoffset=engine.peek(offCaste,ptr_CrCaste.flags_ptr) + local flags=engine.peek(flagoffset,flagPattern) + --print(string.format("%x",flagoffset)) + if flags:get(57) then + print("\tis sentient.") + else + print("\tnon sentient. Allocating IQ...") + flags:set(57,1) + engine.poke(flagoffset,flagPattern,flags) + end + end + end +end +tools.menu:add("Give Sentience",tools.GiveSentience) +function tools.embark() + off=offsets.find(0,0x66, 0x83, 0x7F ,0x1A ,0xFF,0x74,0x04) + if off~=0 then + engine.pokeb(off+5,0x90) + engine.pokeb(off+6,0x90) + print("Found and patched") + else + print("not found") + end +end +tools.menu:add("Embark anywhere",tools.embark) +function tools.getlegendsid(croff) + local vec=engine.peek(croff,ptr_Creature.legends) + if vec:size()==0 then + return 0 + end + for i =0,vector:size()-1 do + --if engine.peekd(vec:getval(i))~=0 then + -- print(string.format("%x",engine.peekd(vec:getval(i))-offsets.base())) + --end + if(engine.peekd(vec:getval(i))==offsets.getEx("vtableLegends")) then --easy to get.. just copy from player's-base + return engine.peekd(vec:getval(i)+4) + end + end + return 0 +end +function tools.getCreatureId(vector) + + tnames={} + rnames={} + --[[print("vector1 size:"..vector:size()) + print("vector2 size:"..vector2:size())]]-- + for i=0,vector:size()-1 do + --print(string.format("%x",vector:getval(i))) + + local name=engine.peek(vector:getval(i),ptt_dfstring):getval() + local lid= tools.getlegendsid(vector:getval(i)) + if lid ~=0 then + print(i..")*Creature Name:"..name.." race="..engine.peekw(vector:getval(i)+ptr_Creature.race.off).." legendid="..lid) + else + print(i..") Creature Name:"..name.." race="..engine.peekw(vector:getval(i)+ptr_Creature.race.off)) + end + if name ~="" and name~=nil then + tnames[i]=name + rnames[name]=i + end + end + print("=====================================") + print("type in name or number:") + r=io.stdin:read() + if tonumber(r) ==nil then + indx=rnames[r] + if indx==nil then return end + else + r=tonumber(r) + if rLOVE), q to quit:") + names={} + repeat + w=io.stdin:read(); + + if rwords[w]~=nil then + table.insert(names,w) + print("--added--") + end + + until w=='q' + end + + tnames={} + for _,v in pairs(names) do + if rwords[v] ~=nil then + table.insert(tnames,rwords[v]) --get word numbers + end + end + + local offsites=engine.peekd(offsets.getEx("SiteData"))+0x120 + snames={" pfort"," dfort"," cave","mohall","forest","hamlet","imploc"," lair"," fort"," camp"} + vector=engine.peek(offsites,ptr_vector) + print("Number of sites:"..vector:size()) + print("List of hits:") + for i =0,vector:size()-1 do + off=vector:getval(i) + + good=true + r="" + hits=0 + sname=engine.peek(off,ptr_site.name) + for k=0,6 do + vnum=sname[k]--engine.peekd(off+0x38+k*4) + tgood=false + + if vnum~=0xFFFFFFFF then + --print(string.format("%x",vnum)) + if names[vnum]~=nil then + r=r..names[vnum].." " + end + for _,v in pairs(tnames) do + if vnum==v then + tgood=true + --print("Match") + hits=hits+1 + break + end + end + if not tgood then + good=false + end + end + end + + if(good) and (hits>0)then + --if true then + --print("=====================") + typ=engine.peek(off,ptr_site.type)--engine.peekw(off+0x78) + flg=engine.peekd(engine.peek(off,ptr_site.flagptr)) + --flg=engine.peekd(off+224) + --flg2=engine.peekw(off) + --tv=engine.peek(off+0x84,ptr_vector) + --tv2=engine.peek(off+0xA4,ptr_vector) + + print(string.format("%d)%s off=%x type=%s\t flags=%x",i,r,off,snames[typ+1],flg)) + + if i%100==99 then + r=io.stdin:read() + end + + end + end + print("Type which to change (q cancels):") + repeat + r=io.stdin:read() + n=tonumber(r) + if(r=='q') then return end + until n~=nil + return vector:getval(n) +end +function tools.changesite(names) + off=tools.getsite(names) + snames={"Mountain halls (yours)","Dark fort","Cave","Mountain hall (NPC)","Forest retreat","Hamlet","Important location","Lair","Fort","Camp"} + + print("Type in the site type (q cancels):") + for k,v in pairs(snames) do + print((k-1).."->"..v) + end + repeat + r=io.stdin:read() + n2=tonumber(r) + if(r=='q') then return end + until n2~=nil + --off=vector:getval(n) + print(string.format("%x->%d",off,n2)) + engine.poke(off,ptr_site.type,n2) +end +function tools.changeflags(names) + myflag_pattern=ptt_dfflag.new(3*8) + off=tools.getsite(names) + offflgs=engine.peek(off,ptr_site.flagptr) + q='' + print(string.format("Site offset %x flags offset %x",off,offflgs)) + repeat + print("flags:") + + --off=vector:getval(n) + flg=engine.peek(offflgs,myflag_pattern) + r="" + for i=0,3*8-1 do + if flg:get(i)==1 then + r=r.."x" + else + r=r.."o" + end + if i%8==7 then + print(i-7 .."->"..r) + r="" + end + end + print("Type number to flip, or 'q' to quit.") + q=io.stdin:read() + n2=tonumber(q) + if n2~=nil then + + flg:flip(n2) + engine.poke(offflgs,myflag_pattern,flg) + end + until q=='q' +end +function tools.hostilate() + vector=engine.peek(offsets.getEx("CreatureVec"),ptr_vector) + id=engine.peekd(offsets.getEx("CreaturePtr")) + print(string.format("Vec:%d cr:%d",vector:size(),id)) + off=vector:getval(id) + crciv=engine.peek(off,ptr_Creature.civ) + print("Creatures civ:"..crciv) + curciv=engine.peekd(offsets.getEx("CurrentRace")-12) + print("My civ:"..curciv) + 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,0) + print("flag 51:"..tostring(flg:get(51))) + 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,1) + flg:set(19,0) + engine.poke(off,ptr_Creature.flags,flg) + end +end +function tools.mouseBlock() + local xs,ys,zs + xs,ys,zs=getxyz() + xs=math.floor(xs/16) + ys=math.floor(ys/16) + print("Mouse block is:"..xs.." "..ys.." "..zs) +end +function tools.protectsite() + local mapoffset=offsets.getEx("WorldData")--0x131C128+offsets.base() + local x=engine.peek(mapoffset+24,DWORD) + local y=engine.peek(mapoffset+28,DWORD) + local z=engine.peek(mapoffset+32,DWORD) + --vec=engine.peek(mapoffset,ptr_vector) + + print("Blocks loaded:"..x.." "..y.." "..z) + print("Select type:") + print("1. All (SLOW)") + print("2. range (x0 x1 y0 y1 z0 z1)") + print("3. One block around pointer") + print("anything else- quit") + q=io.stdin:read() + n2=tonumber(q) + if n2==nil then return end + if n2>3 or n2<1 then return end + local xs,xe,ys,ye,zs,ze + if n2==1 then + xs=0 + xe=x-1 + ys=0 + ye=y-1 + zs=0 + ze=z-1 + elseif n2==2 then + print("enter x0:") + xs=tonumber(io.stdin:read()) + print("enter x1:") + xe=tonumber(io.stdin:read()) + print("enter y0:") + ys=tonumber(io.stdin:read()) + print("enter y1:") + ye=tonumber(io.stdin:read()) + print("enter z0:") + zs=tonumber(io.stdin:read()) + print("enter z1:") + ze=tonumber(io.stdin:read()) + function clamp(t,vmin,vmax) + if t> vmax then return vmax end + if t< vmin then return vmin end + return t + end + xs=clamp(xs,0,x-1) + ys=clamp(ys,0,y-1) + zs=clamp(zs,0,z-1) + xe=clamp(xe,xs,x-1) + ye=clamp(ye,ys,y-1) + ze=clamp(ze,zs,z-1) + else + xs,ys,zs=getxyz() + xs=math.floor(xs/16) + ys=math.floor(ys/16) + xe=xs + ye=ys + ze=zs + end + local xblocks=engine.peek(mapoffset,DWORD) + local flg=bit.lshift(1,14) + for xx=xs,xe do + local yblocks=engine.peek(xblocks+xx*4,DWORD) + for yy=ys,ye do + local zblocks=engine.peek(yblocks+yy*4,DWORD) + for zz=zs,ze do + + + + local myblock=engine.peek(zblocks+zz*4,DWORD) + if myblock~=0 then + for i=0,255 do + local ff=engine.peek(myblock+0x67c+i*4,DWORD) + ff=bit.bor(ff,flg) --set 14 flag to 1 + engine.poke(myblock+0x67c+i*4,DWORD,ff) + end + end + end + print("Blocks done:"..xx.." "..yy) + end + end +end +function tools.fixwarp() + local mapoffset=offsets.getEx("WorldData")--0x131C128+offsets.base() + local x=engine.peek(mapoffset+24,DWORD) + local y=engine.peek(mapoffset+28,DWORD) + local z=engine.peek(mapoffset+32,DWORD) + --vec=engine.peek(mapoffset,ptr_vector) + + print("Blocks loaded:"..x.." "..y.." "..z) + print("Select type:") + print("1. All (SLOW)") + print("2. range (x0 x1 y0 y1 z0 z1)") + print("3. One block around pointer") + print("anything else- quit") + q=io.stdin:read() + n2=tonumber(q) + if n2==nil then return end + if n2>3 or n2<1 then return end + local xs,xe,ys,ye,zs,ze + if n2==1 then + xs=0 + xe=x-1 + ys=0 + ye=y-1 + zs=0 + ze=z-1 + elseif n2==2 then + print("enter x0:") + xs=tonumber(io.stdin:read()) + print("enter x1:") + xe=tonumber(io.stdin:read()) + print("enter y0:") + ys=tonumber(io.stdin:read()) + print("enter y1:") + ye=tonumber(io.stdin:read()) + print("enter z0:") + zs=tonumber(io.stdin:read()) + print("enter z1:") + ze=tonumber(io.stdin:read()) + function clamp(t,vmin,vmax) + if t> vmax then return vmax end + if t< vmin then return vmin end + return t + end + xs=clamp(xs,0,x-1) + ys=clamp(ys,0,y-1) + zs=clamp(zs,0,z-1) + xe=clamp(xe,xs,x-1) + ye=clamp(ye,ys,y-1) + ze=clamp(ze,zs,z-1) + else + xs,ys,zs=getxyz() + xs=math.floor(xs/16) + ys=math.floor(ys/16) + xe=xs + ye=ys + ze=zs + end + local xblocks=engine.peek(mapoffset,DWORD) + local flg=bit.bnot(bit.lshift(1,3)) + for xx=xs,xe do + local yblocks=engine.peek(xblocks+xx*4,DWORD) + for yy=ys,ye do + local zblocks=engine.peek(yblocks+yy*4,DWORD) + for zz=zs,ze do + local myblock=engine.peek(zblocks+zz*4,DWORD) + if myblock~=0 then + for i=0,255 do + local ff=engine.peek(myblock+0x67c+i*4,DWORD) + ff=bit.band(ff,flg) --set 14 flag to 1 + engine.poke(myblock+0x67c+i*4,DWORD,ff) + end + end + end + print("Blocks done:"..xx.." "..yy) + end + end +end +if not(FILE) then + tools.menu:add("Change site type",tools.changesite) + tools.menu:add("Change site flags",tools.changeflags) + tools.menu:add("Run script file",tools.runscript) + tools.menu:add("Hostilate creature",tools.hostilate) + tools.menu:add("Protect site from item scattering",tools.protectsite) + tools.menu:add("Print current mouse block",tools.mouseBlock) + --tools.menu:add("XXX",tools.fixwarp) + tools.menu:display() + + --[[choices={ + {tools.setrace,"Change race"}, + {tools.GiveSentience,"Give Sentience"}, + {tools.embark,"Embark anywhere"}, + {tools.change_adv,"Change Adventurer"}, + {tools.changesite,"Change site type"}, + {tools.runscript,"Run script file"}, + {tools.MakeFollow,"Make creature follow"}, + {function () return end,"Quit"}} + print("Select choice:") + for p,c in pairs(choices) do + print(p..")."..c[2]) + end + repeat + ans=tonumber(io.stdin:read()) + if ans==nil or not(ans<=table.maxn(choices) and ans>0) then + print("incorrect choice") + end + until ans~=nil and (ans<=table.maxn(tdir) and ans>0) + choices[ans][1]()]]-- +end \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/triggers/compile.bat b/plugins/Dfusion/luafiles/triggers/compile.bat new file mode 100644 index 000000000..3b0fec1a2 --- /dev/null +++ b/plugins/Dfusion/luafiles/triggers/compile.bat @@ -0,0 +1 @@ +as -anl --32 -o triggers.o triggers.asm \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/triggers/functions.lua b/plugins/Dfusion/luafiles/triggers/functions.lua new file mode 100644 index 000000000..d5fca0773 --- /dev/null +++ b/plugins/Dfusion/luafiles/triggers/functions.lua @@ -0,0 +1,20 @@ +function func.Find_Print() + pos=offsets.find(offsets.base(),0x73,0x02,0x8b,0xce,0x53,0x6a,0x01,0x6a,0x06,CALL) -- a hack for now... + return engine.peekd(pos+10)+pos+14-offsets.base() +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)) + debuger.suspend() + d=NewCallTable() -- make a call table + t=Allocate(string.len(msg)) + engine.pokestr(t,msg) + --print(string.format("Message location:%x",t)) + d["ECX"]=t --set ecx to message location + d["STACK5"]=color1 -- push to stack color1 + d["STACK4"]=color2 -- push to stack color2 + d["STACK3"]=0 -- this is usually 0 maybe a struct pointing to location of this message? + PushFunction(func.f_print_pos+offsets.base(),d) -- prep to call function + -- was 0x27F030 + debuger.resume() +end diff --git a/plugins/Dfusion/luafiles/triggers/functions_menu.lua b/plugins/Dfusion/luafiles/triggers/functions_menu.lua new file mode 100644 index 000000000..3256c6117 --- /dev/null +++ b/plugins/Dfusion/luafiles/triggers/functions_menu.lua @@ -0,0 +1,12 @@ +func={} +dofile("dfusion/triggers/functions.lua") +func.menu=MakeMenu() +function func.PrintMessage_() + print("Type a message:") + msg=io.stdin:read() + func.PrintMessage(msg,6,1) +end +if not(FILE) then -- if not in script mode + func.menu:add("Print message",func.PrintMessage_) + func.menu:display() +end \ No newline at end of file diff --git a/plugins/Dfusion/luafiles/triggers/plugin.lua b/plugins/Dfusion/luafiles/triggers/plugin.lua new file mode 100644 index 000000000..e8f31eac1 --- /dev/null +++ b/plugins/Dfusion/luafiles/triggers/plugin.lua @@ -0,0 +1,107 @@ +if FILE then + return +end +callinfo={} +callinfo.regs={} +callinfo.regs["EAX"]=0 +callinfo.regs["EBX"]=1 +callinfo.regs["ECX"]=2 +callinfo.regs["EDX"]=3 +callinfo.regs["ESI"]=4 +callinfo.regs["EDI"]=5 +callinfo.regs["STACK1"]=6 +callinfo.regs["STACK2"]=7 +callinfo.regs["STACK3"]=8 +callinfo.regs["STACK4"]=9 +callinfo.regs["STACK5"]=10 + +mypos=engine.getmod("triggers_main") + +function GetCount() + return engine.peek(0,triggers.count) +end +function SetCount(val) + engine.poke(0,triggers.count,val) +end +function NewCallTable(tbl) + ret=tbl or {} + for k,v in pairs(callinfo.regs) do + ret[k]=0 + end + return ret +end +function PushFunction(off,data) + local i=GetCount() + engine.poked(triggers.table.off+i*44,off) -- add function to table + engine.poked(triggers.data.off+0,data["EAX"]) --set register data... + engine.poked(triggers.data.off+4,data["EBX"]) + engine.poked(triggers.data.off+8,data["ECX"]) + engine.poked(triggers.data.off+12,data["EDX"]) + engine.poked(triggers.data.off+16,data["ESI"]) + engine.poked(triggers.data.off+20,data["EDI"]) + engine.poked(triggers.data.off+24,data["STACK1"]) + engine.poked(triggers.data.off+28,data["STACK2"]) + engine.poked(triggers.data.off+32,data["STACK3"]) + engine.poked(triggers.data.off+36,data["STACK4"]) + engine.poked(triggers.data.off+40,data["STACK5"]) + SetCount(i+1) +end +function loadTriggers() + if triggers then return end + triggers={} + p=engine.getmod("triggerdata") + triggers.count={off=engine.peekd(p),rtype=DWORD} + triggers.table={off=engine.peekd(p+4),rtype=DWORD} + triggers.ret={off=engine.peekd(p+8),rtype=DWORD} + triggers.data={off=engine.peekd(p+12),rtype=DWORD} +end +if mypos then + loadTriggers() + dofile("dfusion/triggers/functions_menu.lua") + --return +else + triggers={} + + off=0x56D345+offsets.base() + print(string.format("Function start %x",off)) + ModData=engine.installMod("dfusion/triggers/triggers.o","triggers_main") + print("installed") + modpos=ModData.pos + modsize=ModData.size + fdata=engine.newmod("function_body",256) + + + engine.poked(modpos+engine.FindMarker(ModData,"trigercount"),modpos+modsize) -- count of functions + engine.poked(modpos+engine.FindMarker(ModData,"f_loc"),modpos+modsize+4) -- function table start + engine.poked(modpos+engine.FindMarker(ModData,"f_data"),fdata) -- function data start + + engine.poked(modpos+engine.FindMarker(ModData,"saveplace31"),modpos+modsize+260) -- save function loc + engine.poked(modpos+engine.FindMarker(ModData,"saveplace32"),modpos+modsize+260) -- save function loc + engine.poked(modpos+engine.FindMarker(ModData,"saveplace33"),modpos+modsize+260) -- save function loc + engine.poked(modpos+engine.FindMarker(ModData,"saveplace"),modpos+modsize+256) -- save function loc + engine.poked(modpos+engine.FindMarker(ModData,"trigcount2"),modpos+modsize) -- count of functions (for zeroing) + engine.poked(modpos+engine.FindMarker(ModData,"saveplace2"),modpos+modsize+256) -- save function loc + engine.poked(modpos+engine.FindMarker(ModData,"results"),modpos+modsize+256) --overwrite function call with results + + triggers.count={off=modpos+modsize,rtype=DWORD} + triggers.table={off=modpos+modsize+4,rtype=DWORD} + triggers.ret={off=modpos+modsize+256,rtype=DWORD} + triggers.data={off=fdata,rtype=DWORD} + pp=Allocate(4*4) + engine.poked(pp,triggers.count.off) + engine.poked(pp+4,triggers.table.off) + engine.poked(pp+8,triggers.ret.off) + engine.poked(pp+12,triggers.data.off) + engine.newmod("triggerdata",0,pp) + function pokeCall(off) + engine.pokeb(off,0xe8) + --b=engine.peekb(off+1) + engine.poked(off+1,modpos-off-5) + --engine.pokeb(off+5,b) + end + print(string.format("Mod @:%x",modpos)) + dat=engine.peekarb(off,5) + engine.pokearb(modpos,dat,5) + pokeCall(off) +end + diff --git a/plugins/Dfusion/luafiles/triggers/triggers.asm b/plugins/Dfusion/luafiles/triggers/triggers.asm new file mode 100644 index 000000000..58b9e5f61 --- /dev/null +++ b/plugins/Dfusion/luafiles/triggers/triggers.asm @@ -0,0 +1,68 @@ +.intel_syntax +nop #5 nops for instruction thats replaced by call +nop +nop +nop +nop +pushad +pushfd +saveplace31: +mov [0xDEADBEEF], esp +trigercount: +mov eax, [0xDEADBEEF] #mov count of triggers. +f_loc: +mov esi, 0xdeadbeef #mov location of functions. +f_data: +mov ebx, 0xDEADBEEF #mov a start of function data +test eax,eax +jz lend +lstart: +dec eax +push ebx +push eax + +mov eax,[esi+eax*4] +saveplace: +mov [0xDEADBEEF],eax #save function for later +pop eax +push eax +mov edx,44 +mul edx +add eax,ebx +#stack preparation +mov ebx,[eax+24] +push ebx +mov ebx,[eax+28] +push ebx +mov ebx,[eax+32] +push ebx +mov ebx,[eax+36] +push ebx +mov ebx,[eax+40] +push ebx +mov ebx,[eax+4] +mov ecx,[eax+8] +mov edx,[eax+12] +mov esi,[eax+16] +mov edi,[eax+20] +mov eax,[eax] +saveplace2: +call [0xdeadbeef] #same save loc +results: +mov [0xDEADBEEF],eax #get result +saveplace33: +mov esp, [0xDEADBEEF] +add esp, -8 +pop eax +pop ebx +cmp eax,0 +jnz lstart +lend: +xor eax,eax +trigcount2: +mov dword ptr [0xDEADBEEF], eax # zero triggers +saveplace32: +mov esp, [0xDEADBEEF] +popfd +popad +ret diff --git a/plugins/Dfusion/luafiles/triggers/triggers.o b/plugins/Dfusion/luafiles/triggers/triggers.o new file mode 100644 index 0000000000000000000000000000000000000000..5a47daa69bb4ac4f86773a23f66d5a73c8b6d7b0 GIT binary patch literal 720 zcmeZaWM%*X5k?>evsfARN>VFIz-$Q70i=46_#mbNgF%8`N@7VOnm9Vwfx+N_UQ%%} zx;Q$&0jO>Q2qetuRDHj1?Y)H{Vjqau4I)|(l!SQ%2XwQvEe3HT0(R*DjrjhE@kV!q zL~wV63=k^-u?i4t05MCq2S;}RPj`VpcZEnd!+%kbF0j^au<^}Dendn!|6nLxWq1Hd zcy8k12@~|vGILU)4*d6@fgznSEioG=faGu%Ae$YCfkDT>1{N0plDu${wD_F-WFSun zNdyvP;&73i)VvfRhoKB1Qe2W)1Pp!!xCoHJAOpl|C?X(UG+d-8wYW5=q?iE|9|-pt z0(ogDBDO$Y1&W9VkXH*AL5_QnIn0c0KoS)o$2${HiW#I34IsxkD1~8D69N=3PAp3; n$Vp62H8x}@DauSwElSQW%_~8OBUnZVrm-