develop
commit
fedb6150f4
@ -0,0 +1,126 @@
|
||||
#ifndef OUTFILE_H
|
||||
#define OUTFILE_H
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
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:"<<symbolptr<<"\n";
|
||||
}
|
||||
};
|
||||
struct Section
|
||||
{
|
||||
char name[8];
|
||||
unsigned long Vsize;
|
||||
unsigned long Vstart;
|
||||
unsigned long size;
|
||||
unsigned long start;
|
||||
unsigned long ptrRel;
|
||||
unsigned long ptrLine;
|
||||
unsigned short numRel;
|
||||
unsigned short numLine;
|
||||
unsigned long flags;
|
||||
void PrintData()
|
||||
{
|
||||
std::cout<<name<<" size:"<<size<<" start:"<<start<<"\n";
|
||||
}
|
||||
};
|
||||
struct Symbol
|
||||
{
|
||||
|
||||
std::string name;
|
||||
unsigned long pos;
|
||||
unsigned short sectnumb;
|
||||
unsigned short type;
|
||||
unsigned char storageclass;
|
||||
unsigned char auxsymbs;
|
||||
//char unk2[6];
|
||||
void Read(std::iostream &s,unsigned long strptr)
|
||||
{
|
||||
union
|
||||
{
|
||||
char buf[8];
|
||||
struct
|
||||
{
|
||||
unsigned long zeros;
|
||||
unsigned long strptr;
|
||||
};
|
||||
|
||||
}data;
|
||||
|
||||
s.read((char*)&data,8);
|
||||
s.read((char*)&pos,4);
|
||||
s.read((char*)§numb,2);
|
||||
s.read((char*)&type,2);
|
||||
s.read((char*)&storageclass,1);
|
||||
s.read((char*)&auxsymbs,1);
|
||||
if(data.zeros!=0)
|
||||
{
|
||||
name=data.buf;
|
||||
name=name.substr(0,8);
|
||||
}
|
||||
else
|
||||
{
|
||||
//name="";
|
||||
//std::cout<<"Name in symbol table\n";
|
||||
char buf[256];
|
||||
s.seekg(strptr+data.strptr);
|
||||
s.get(buf,256,'\0');
|
||||
name=buf;
|
||||
}
|
||||
|
||||
//s.seekp(6,std::ios::cur);
|
||||
}
|
||||
void PrintData()
|
||||
{
|
||||
std::cout<<name<<" section:"<<sectnumb<<" pos:"<<pos<<"\n";
|
||||
}
|
||||
};
|
||||
struct Relocation
|
||||
{
|
||||
unsigned long ptr;
|
||||
unsigned long tblIndex;
|
||||
unsigned short type;
|
||||
};
|
||||
typedef std::vector<Symbol> 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<std::string,Section> secMap;
|
||||
|
||||
secMap sections;
|
||||
vSymbol symbols;
|
||||
Section &GetSection(std::string name);
|
||||
|
||||
std::fstream mystream;
|
||||
Header myhead;
|
||||
// Section Text;
|
||||
//Section Data;
|
||||
// Section Bss;
|
||||
};
|
||||
}
|
||||
#endif // OUTFILE_H
|
@ -0,0 +1,37 @@
|
||||
#ifndef HEXSEARCH_H
|
||||
#define HEXSEARCH_H
|
||||
#include <vector>
|
||||
#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<int> 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<uint64_t> FindAll();
|
||||
|
||||
private:
|
||||
bool Compare(int a,int b);
|
||||
void ReparseArgs();
|
||||
SearchArgType args_;
|
||||
uint64_t pos_,startpos_,endpos_;
|
||||
std::vector<int> BadCharShifts,GoodSuffixShift;
|
||||
void PrepareGoodSuffixTable();
|
||||
void PrepareBadCharShift();
|
||||
};
|
||||
|
||||
#endif
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,45 @@
|
||||
#ifndef LUA_MISC_H
|
||||
#define LUA_MISC_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <dfhack/Core.h>
|
||||
#include <dfhack/Process.h>
|
||||
#include "luamain.h"
|
||||
#include "OutFile.h"
|
||||
|
||||
namespace lua
|
||||
{
|
||||
|
||||
typedef std::map<std::string,void *> 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<PlugManager*>(p);
|
||||
};
|
||||
protected:
|
||||
private:
|
||||
PlugManager(){};
|
||||
mapPlugs plugs;
|
||||
};
|
||||
|
||||
void RegisterMisc(lua::state &st);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -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 <string>
|
||||
|
||||
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="<<myref<<"\n";
|
||||
//mytbl->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="<<myref<<"\n";
|
||||
//StackDump(myst);
|
||||
//LOG<<"Tbl preget\n";
|
||||
mytbl->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 <typename T,bool GC=true>
|
||||
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 \""<<T::className<<"\"\n";
|
||||
// fill method table with methods from class T
|
||||
for (RegType *l = T::methods; l->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 \""<<l->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<userdataType*>(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:"<<id<<"stack dump:\n";
|
||||
//lua::StackDump(L);
|
||||
luaL_unref(L,ins,id);
|
||||
}
|
||||
static int index_T(lua_State *L) // calls with (table, key), return value
|
||||
{
|
||||
lua::state st(L);
|
||||
string key=st.as<string>(-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<lua::nil>()) //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_gettop(L)<<"\n";
|
||||
//lua::StackDump(L);
|
||||
if(lua_gettop(L)<1)
|
||||
luaL_error(L,"Member function called without 'self'");
|
||||
//LOG<<"Size of stack after:"<<lua_gettop(L)<<"\n";
|
||||
// stack has userdata, followed by method args
|
||||
T *obj = check(L, 1); // get 'self', or if you prefer, 'this'
|
||||
//T *obj=static_cast<userdataType*>(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<RegType*>(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<userdataType*>(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_gettop(L)<<"\n";
|
||||
//lua::StackDump(L);
|
||||
lua_remove(L, 1); // use classname:new(), instead of classname.new()
|
||||
//lua_newtable(L);
|
||||
int id=RegTable(L);
|
||||
//LOG<<"Registred as:"<<id<<"\n";
|
||||
//int ssize=lua_gettop(L);
|
||||
T *obj = new T(L,id); // call constructor for T objects
|
||||
lua_settop(L,0); //no need for parameters later.
|
||||
//LOG<<"Post build:"<<lua_gettop(L)<<"\t";
|
||||
//lua::StackDump(L);
|
||||
//LOG<<"TSOP\n";
|
||||
|
||||
userdataType *ud =
|
||||
static_cast<userdataType*>(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<class>::RegType methods[];
|
||||
#define DEF_LUNE_NOGC(class) static const char className[];\
|
||||
static Lune<class,false>::RegType methods[];
|
||||
#define IMP_LUNE(class,lua_name) const char class::className[]=#lua_name;
|
||||
#define LUNE_METHODS_START(class) Lune<class>::RegType class::methods[] = {
|
||||
#define LUNE_METHODS_START_NOGC(class) Lune<class,false>::RegType class::methods[] = {
|
||||
#define LUNE_METHODS_END() {0,0}}
|
||||
#endif // LUNE_H
|
@ -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
|
@ -0,0 +1 @@
|
||||
as -a --32 -o embark.o 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
|
Binary file not shown.
@ -0,0 +1,75 @@
|
||||
function MakeTable(modpos,modsize,names)
|
||||
count=0
|
||||
castes={}
|
||||
--print("Making table")
|
||||
for _,line in pairs(names) do
|
||||
--print("Line:"..line)
|
||||
tpos=string.find(line,":")
|
||||
if tpos~=nil then
|
||||
--print("Was line:"..line)
|
||||
table.insert(castes,tonumber(string.sub(line,tpos+1)))
|
||||
line=string.sub(line,1,tpos-1)
|
||||
--print("IS line:"..line)
|
||||
else
|
||||
table.insert(castes,-1)
|
||||
end
|
||||
if RaceTable[line] == nil then
|
||||
error("Failure, "..line.." not found!")
|
||||
end
|
||||
engine.pokew(modpos+modsize+count*2,RaceTable[line]) -- add race
|
||||
count = count + 1
|
||||
end
|
||||
i=0
|
||||
for _,caste in pairs(castes) do
|
||||
|
||||
engine.pokew(modpos+modsize+count*2+i*2,caste) -- add caste
|
||||
i= i+1
|
||||
end
|
||||
|
||||
engine.poked(stoff,count)
|
||||
return count
|
||||
end
|
||||
function embark(names)
|
||||
RaceTable=RaceTable or BuildNameTable()
|
||||
mypos=engine.getmod('Embark')
|
||||
stoff=offsets.getEx('StartDwarfs')
|
||||
if mypos then --if mod already loaded
|
||||
print("Mod already loaded @:"..mypos.." just updating")
|
||||
modpos=mypos
|
||||
_,modsize=engine.loadobj('dfusion/embark/embark.o')
|
||||
|
||||
count=MakeTable(modpos,modsize,names) --just remake tables
|
||||
else
|
||||
|
||||
tofind=offsets.getEx('CurrentRace')
|
||||
|
||||
loc=offsets.find(stoff,0xa1,DWORD_,tofind)
|
||||
|
||||
print("found:"..loc)
|
||||
|
||||
if((loc~=0)and(loc-stoff<1000)) then
|
||||
modpos,modsize=engine.loadmod('dfusion/embark/embark.o','Embark',256)
|
||||
count=MakeTable(modpos,modsize,names)
|
||||
engine.poked(modpos+0x18,modpos+modsize) --fix array start for race
|
||||
engine.poked(modpos+0x08,modpos+modsize+count*2) --fix array start for caste
|
||||
print("sucess loading mod @:"..modpos)
|
||||
-- build race vector after module.
|
||||
|
||||
|
||||
--finaly poke in the call!
|
||||
engine.pokeb(loc,0x6a)
|
||||
engine.pokeb(loc+1,0xFF)
|
||||
engine.pokeb(loc+2,0xe8)
|
||||
engine.poked(loc+3,modpos-loc-7)
|
||||
--engine.pokeb(loc+5,0x90)
|
||||
SetExecute(modpos)
|
||||
else
|
||||
error("did not find patch location, failing...")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
if not(FILE)then
|
||||
names=ParseNames("dfusion/embark/races.txt")--io.open("plugins/embark/races.txt"):lines()
|
||||
embark(names)
|
||||
end
|
@ -0,0 +1,7 @@
|
||||
DWARF:1
|
||||
ELF:0
|
||||
ELF:0
|
||||
DWARF:0
|
||||
DWARF:0
|
||||
HUMAN:0
|
||||
HUMAN:0
|
@ -0,0 +1 @@
|
||||
as -anl --32 -o friendship.o friendship.asm
|
@ -0,0 +1,102 @@
|
||||
.intel_syntax
|
||||
push eax
|
||||
mov eax,[esp+0x04]
|
||||
push ebx
|
||||
pushfd
|
||||
mov eax,[eax] # get a byte after the call this procedure to analyze what register holds cr ptr
|
||||
jmptbl:
|
||||
cmp al,0x81
|
||||
jz regC
|
||||
cmp al,0x82
|
||||
jz regD
|
||||
cmp al,0x83
|
||||
jz regB
|
||||
cmp al,0x85
|
||||
jz regBP
|
||||
cmp al,0x86
|
||||
jz regESI
|
||||
cmp al,0x87
|
||||
jz regEDI
|
||||
cmp al,0x88
|
||||
jz regA
|
||||
cmp al,0x8A
|
||||
jz regD
|
||||
cmp al,0x8B
|
||||
jz regB
|
||||
cmp al,0x8D
|
||||
jz regBP
|
||||
cmp al,0x8E
|
||||
jz regESI
|
||||
cmp al,0x8F
|
||||
jz regEDI
|
||||
cmp al,0x90
|
||||
jz regA
|
||||
cmp al,0x91
|
||||
jz regC
|
||||
cmp al,0x93
|
||||
jz regB
|
||||
cmp al,0x95
|
||||
jz regBP
|
||||
cmp al,0x96
|
||||
jz regESI
|
||||
cmp al,0x97
|
||||
jz regEDI
|
||||
jmp fail
|
||||
regA:
|
||||
mov eax, [esp+0x8]
|
||||
mov eax, [eax+0x8c]
|
||||
jmp compare
|
||||
regC:
|
||||
mov eax, [ecx+0x8c]
|
||||
jmp compare
|
||||
regB:
|
||||
mov eax, [ebx+0x8c]
|
||||
jmp compare
|
||||
regD:
|
||||
mov eax, [edx+0x8c]
|
||||
jmp compare
|
||||
regBP:
|
||||
mov eax, [ebp+0x8c]
|
||||
jmp compare
|
||||
regESI:
|
||||
mov eax, [esi+0x8c]
|
||||
jmp compare
|
||||
regEDI:
|
||||
mov eax, [edi+0x8c]
|
||||
#jmp compare
|
||||
compare:
|
||||
push ecx
|
||||
mov ebx,0xDEADBEEF #write a pointer to the list of allowed races
|
||||
mov ecx,2000 #write a number of allowed races
|
||||
loop1:
|
||||
cmp word[ebx+ecx*2],ax
|
||||
jz endok
|
||||
dec ecx
|
||||
cmp ecx ,-1
|
||||
jnz loop1
|
||||
pop ecx
|
||||
popfd
|
||||
jmp fail
|
||||
endok:
|
||||
pop ecx
|
||||
popfd
|
||||
cmp eax,eax
|
||||
jmp endfinal
|
||||
fail:
|
||||
|
||||
xor ebx,ebx
|
||||
xor eax,eax
|
||||
inc eax
|
||||
cmp eax,ebx
|
||||
endfinal:
|
||||
|
||||
pop ebx
|
||||
pop eax
|
||||
mov [0xFEEDBEEF],eax #write a pointer to safe location (usually after this)
|
||||
pop eax
|
||||
pushfd
|
||||
inc eax #skip one instruction
|
||||
popfd
|
||||
push eax
|
||||
mov eax,[0xFEEDBEEF] #write a pointer to safe location (same as above)
|
||||
ret
|
Binary file not shown.
@ -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
|
@ -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
|
@ -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)
|
||||
print(string.format("Compare at:%x",pos))
|
||||
if pos ==0 then
|
||||
return 0
|
||||
end
|
||||
if(pos-off>0x100) then
|
||||
print(string.format("Distance to cmp:%x",pos-off))
|
||||
pos =offsets.find(off,CALL)
|
||||
print(string.format("Distance to call:%x",pos-off))
|
||||
return 0
|
||||
--return analyzeF(pos)
|
||||
else
|
||||
return pos
|
||||
end
|
||||
end
|
||||
function minEx(...)
|
||||
local imin=arg[1]
|
||||
for _,v in ipairs(arg) do
|
||||
if imin> v and v~=0 then
|
||||
imin=v
|
||||
end
|
||||
end
|
||||
return imin
|
||||
end
|
||||
function signDword(dw)
|
||||
if(dw>0xFFFFFFFF) then
|
||||
return dw-0xFFFFFFFF
|
||||
end
|
||||
return dw
|
||||
end
|
||||
--[[
|
||||
Warning: not all mov's are acounted for. Found one: mov EAX,WORD PTR[EBP+1EF4] WTF??
|
||||
Two more compares are missing. There are calls instead (same function)
|
||||
]]--
|
||||
if not(FILE) then
|
||||
print("race num:"..engine.peekw(offsets.getEx("CurrentRace")))
|
||||
print("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
|
||||
|
@ -0,0 +1,8 @@
|
||||
DWARF
|
||||
GOBLIN
|
||||
ELF
|
||||
HUMAN
|
||||
KOBOLD
|
||||
GREMLIN
|
||||
TIGERMAN
|
||||
ANT_MAN
|
@ -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}
|
@ -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)<i then break end
|
||||
end
|
||||
return T[tonumber(q)]
|
||||
end
|
||||
function items.select_creature(croff)
|
||||
vector=engine.peek(croff,ptr_Creature.itemlist2)
|
||||
print("Vector size:"..vector:size())
|
||||
T={}
|
||||
for i=0,vector:size()-1 do
|
||||
table.insert(T,vector:getval(i)) -- item list is itemptr+location?
|
||||
end
|
||||
print("Items in inventory:")
|
||||
i=1
|
||||
for _,v in pairs(T) do
|
||||
RTI=engine.peek(engine.peekd(v),ptr_item.RTI)
|
||||
print(i..". "..ptr_item.getname(nil,RTI).." locations:"..engine.peekw(v+4).." "..engine.peekw(v+6))
|
||||
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)<i then break end
|
||||
end
|
||||
return engine.peekd(T[tonumber(q)])
|
||||
end
|
||||
function items.edit(itoff)
|
||||
if itoff==nil then
|
||||
itoff=items.select()
|
||||
end
|
||||
print(string.format("Item offset:%x",itoff))
|
||||
print("Type what to edit:")
|
||||
print("1. material")
|
||||
print("2. flags")
|
||||
print("3. covering")
|
||||
Z={}
|
||||
Z[1]=editMaterial
|
||||
Z[2]=editFlags
|
||||
Z[3]=editCovering
|
||||
name=ptr_item.getname(nil,engine.peek(itoff,ptr_item.RTI))
|
||||
if name~=nil and ptr_subitems[name]~=nil then
|
||||
print("4. Item specific edit")
|
||||
--Z[4]=items.fedit[name]
|
||||
Z[4]="dummy"
|
||||
end
|
||||
while true do
|
||||
q=io.stdin:read()
|
||||
if q=='q' then return end
|
||||
if tonumber(q) ~=nil and tonumber(q)<#Z+1 then break end
|
||||
end
|
||||
|
||||
if Z[tonumber(q)]=="dummy" then
|
||||
ModPattern(itoff,ptr_subitems[name])
|
||||
else
|
||||
Z[tonumber(q)](itoff)
|
||||
end
|
||||
end
|
||||
function items.printref()
|
||||
itoff=items.select()
|
||||
vec=engine.peek(itoff,ptr_item.ref)
|
||||
for i=0, vec:size()-1 do
|
||||
toff=vec:getval(i)
|
||||
print(RTTI_GetName(engine.peekd(toff)))
|
||||
end
|
||||
print("Decorations:")
|
||||
vec=engine.peek(itoff,ptr_item.decorations)
|
||||
for i=0, vec:size()-1 do
|
||||
toff=vec:getval(i)
|
||||
print(ptr_decoration_gen.getname(nil,engine.peek(toff,ptr_decoration_gen.RTI)))
|
||||
end
|
||||
end
|
||||
function items.edit_adv()
|
||||
vec=engine.peek(offsets.getEx("CreatureVec"),ptr_vector)
|
||||
items.edit(items.select_creature(vec:getval(0)))
|
||||
end
|
||||
if not(FILE) then -- if not in script mode
|
||||
|
||||
items.menu:add("Destroy all",items.dest)
|
||||
items.menu:add("Hatch eggs",items.eggs)
|
||||
items.menu:add("Edit item",items.edit)
|
||||
items.menu:add("Print ref",items.printref)
|
||||
items.menu:add("Edit adventurer's items",items.edit_adv)
|
||||
items.menu:display()
|
||||
|
||||
end
|
@ -0,0 +1 @@
|
||||
as -anl --32 -o migrants.o 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
|
Binary file not shown.
@ -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
|
@ -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
|
@ -0,0 +1,320 @@
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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)
|
@ -0,0 +1,2 @@
|
||||
offsets.searchoffsets()
|
||||
offsets.save()
|
@ -0,0 +1,104 @@
|
||||
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
|
||||
--print(string.format("Searching (%x->%x)",startoffset,endadr))
|
||||
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")
|
@ -0,0 +1,246 @@
|
||||
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)
|
||||
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)
|
||||
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}
|
@ -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
|
@ -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 r<vector:size() then indx=r else return end
|
||||
end
|
||||
return indx
|
||||
end
|
||||
function tools.change_adv()
|
||||
myoff=offsets.getEx("AdvCreatureVec")
|
||||
vector=engine.peek(myoff,ptr_vector)
|
||||
indx=tools.getCreatureId(vector)
|
||||
print("Swaping, press enter when done or 'q' to stay, 's' to stay with legends id change")
|
||||
tval=vector:getval(0)
|
||||
vector:setval(0,vector:getval(indx))
|
||||
vector:setval(indx,tval)
|
||||
r=io.stdin:read()
|
||||
if r=='q' then
|
||||
return
|
||||
end
|
||||
if r~='s' then
|
||||
tval=vector:getval(0)
|
||||
vector:setval(0,vector:getval(indx))
|
||||
vector:setval(indx,tval)
|
||||
end
|
||||
local lid=tools.getlegendsid(vector:getval(0))
|
||||
if lid~=0 then
|
||||
engine.poked(offsets.getEx("PlayerLegend"),lid)
|
||||
else
|
||||
print("Warning target does not have a valid legends id!")
|
||||
end
|
||||
end
|
||||
tools.menu:add("Change Adventurer",tools.change_adv)
|
||||
|
||||
function tools.MakeFollow()
|
||||
myoff=offsets.getEx("AdvCreatureVec")
|
||||
vector=engine.peek(myoff,ptr_vector)
|
||||
indx=tools.getCreatureId(vector)
|
||||
print(string.format("current creature:%x",vector:getval(indx)))
|
||||
|
||||
trgid=engine.peek(vector:getval(0)+ptr_Creature.ID.off,DWORD)
|
||||
lfollow=engine.peek(vector:getval(indx)+ptr_Creature.followID.off,DWORD)
|
||||
if lfollow ~=0xFFFFFFFF then
|
||||
print("Already following, unfollow? y/N")
|
||||
r=io.stdin:read()
|
||||
if r== "y" then
|
||||
engine.poke(vector:getval(indx)+ptr_Creature.followID.off,DWORD,0)
|
||||
end
|
||||
else
|
||||
engine.poke(vector:getval(indx)+ptr_Creature.followID.off,DWORD,trgid)
|
||||
end
|
||||
end
|
||||
tools.menu:add("Make creature follow",tools.MakeFollow)
|
||||
function tools.runscript(files)
|
||||
if files==nil then
|
||||
files={}
|
||||
table.insert(files,io.stdin:read())
|
||||
end
|
||||
for _,v in pairs(files) do
|
||||
print("Running script:"..v)
|
||||
ParseScript(v)
|
||||
end
|
||||
end
|
||||
function tools.getsite(names)
|
||||
if words==nil then --do once its slow.
|
||||
words,rwords=BuildWordTables()
|
||||
end
|
||||
|
||||
if names==nil then
|
||||
print("Type words that are in the site name, FULLCAPS, no modifiers (lovely->LOVE), 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
|
@ -0,0 +1 @@
|
||||
as -anl --32 -o triggers.o triggers.asm
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
Binary file not shown.
@ -0,0 +1,14 @@
|
||||
.intel_syntax
|
||||
#eax - num of function
|
||||
#ebx -start of data
|
||||
mov ecx,eax
|
||||
mul 10
|
||||
add ebx
|
||||
mov ebx,[eax+4]
|
||||
mov ecx,[eax+8]
|
||||
mov edx,[eax+12]
|
||||
mov esi,[eax+16]
|
||||
mov edi,[eax+20]
|
||||
mov eax,[eax]
|
||||
|
||||
retn
|
@ -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;i<myhead.sectioncount;i++)
|
||||
{
|
||||
Section x;
|
||||
mystream.read((char*)&x,sizeof(Section));
|
||||
sections[x.name]=x;
|
||||
}
|
||||
|
||||
if(mystream)
|
||||
{
|
||||
//std::cout<<"Sizeof:"<<sizeof(Section)<<"\n";
|
||||
/*myhead.PrintData();
|
||||
for(auto it=sections.begin();it!=sections.end();it++)
|
||||
{
|
||||
it->second.PrintData();
|
||||
}*/
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"Error opening file!"<<std::endl;
|
||||
}
|
||||
}
|
||||
Section &File::GetSection(std::string name)
|
||||
{
|
||||
return sections[name];
|
||||
}
|
||||
void File::GetText(char *ptr)
|
||||
{
|
||||
Section &s=GetSection(".text");
|
||||
mystream.seekg(s.start);
|
||||
|
||||
mystream.read(ptr,s.size);
|
||||
}
|
||||
size_t File::GetTextSize()
|
||||
{
|
||||
Section &s=GetSection(".text");
|
||||
return s.size;
|
||||
}
|
||||
void File::PrintRelocations()
|
||||
{
|
||||
for(auto it=sections.begin();it!=sections.end();it++)
|
||||
{
|
||||
std::cout<<it->first<<":\n";
|
||||
for(unsigned i=0;i<it->second.numRel;i++)
|
||||
{
|
||||
Relocation r;
|
||||
mystream.seekg(it->second.ptrRel+10*i);
|
||||
mystream.read((char*)&r,10);
|
||||
std::cout<<r.ptr<<" -- "<<r.tblIndex<<":"<</*symbols[r.tblIndex].name<<*/" type:"<<r.type<<"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
void File::PrintSymbols()
|
||||
{
|
||||
|
||||
std::cout<<"Sizeof symbol:"<<sizeof(Symbol)<<std::endl;
|
||||
std::cout<<"Symbol count:"<<myhead.symbolcount<<std::endl;
|
||||
for(unsigned i=0;i<myhead.symbolcount;i++)
|
||||
{
|
||||
mystream.seekg(myhead.symbolptr+i*18);
|
||||
Symbol s;
|
||||
std::cout<<i<<"\t";
|
||||
s.Read(mystream,myhead.symbolptr+18*myhead.symbolcount);
|
||||
|
||||
//mystream.read((char*)&s,sizeof(Symbol));
|
||||
s.PrintData();
|
||||
symbols.push_back(s);
|
||||
if(s.auxsymbs>0)
|
||||
{
|
||||
i+=s.auxsymbs;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void File::LoadSymbols()
|
||||
{
|
||||
symbols.clear();
|
||||
for(unsigned i=0;i<myhead.symbolcount;i++)
|
||||
{
|
||||
mystream.seekg(myhead.symbolptr+i*18);
|
||||
Symbol s;
|
||||
s.Read(mystream,myhead.symbolptr+18*myhead.symbolcount);
|
||||
symbols.push_back(s);
|
||||
if(s.auxsymbs>0)
|
||||
{
|
||||
i+=s.auxsymbs;
|
||||
}
|
||||
}
|
||||
}
|
||||
File::~File()
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
#include "hexsearch.h"
|
||||
|
||||
|
||||
Hexsearch::Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos)
|
||||
{
|
||||
ReparseArgs();
|
||||
}
|
||||
Hexsearch::~Hexsearch()
|
||||
{
|
||||
|
||||
}
|
||||
inline bool Hexsearch::Compare(int a,int b)
|
||||
{
|
||||
if(b==Hexsearch::ANYBYTE)
|
||||
return true;
|
||||
if(a==b)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
void Hexsearch::ReparseArgs()
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t val;
|
||||
uint8_t bytes[4];
|
||||
}B;
|
||||
SearchArgType targ;
|
||||
targ=args_;
|
||||
args_.clear();
|
||||
for(size_t i=0;i<targ.size();)
|
||||
{
|
||||
if(targ[i]==DWORD_)
|
||||
{
|
||||
i++;
|
||||
B.val=targ[i];
|
||||
for(int j=0;j<4;j++)
|
||||
{
|
||||
args_.push_back(B.bytes[j]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
else if (targ[i]==ANYDWORD)
|
||||
{
|
||||
i++;
|
||||
for(int j=0;j<4;j++)
|
||||
args_.push_back(ANYBYTE);
|
||||
}
|
||||
else
|
||||
{
|
||||
args_.push_back(targ[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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_<endpos_)
|
||||
{
|
||||
bool found=true;
|
||||
p->readByte(pos_,buf[0]);
|
||||
if(Compare(buf[0],args_[0]))
|
||||
{
|
||||
p->read(pos_,args_.size(),buf);
|
||||
for(size_t i=0;i<args_.size();i++)
|
||||
{
|
||||
if(!Compare(buf[i],args_[i]))
|
||||
{
|
||||
pos_+=i;
|
||||
found=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found)
|
||||
{
|
||||
pos_+=args_.size();
|
||||
delete [] buf;
|
||||
return pos_-args_.size();
|
||||
}
|
||||
}
|
||||
pos_++;
|
||||
}
|
||||
delete [] buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint64_t> Hexsearch::FindAll()
|
||||
{
|
||||
std::vector<uint64_t> 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);
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
#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<uint64_t> pos=p->FindAll();
|
||||
st.newtable();
|
||||
for(unsigned i=0;i<pos.size();i++)
|
||||
{
|
||||
st.push(i+1);
|
||||
st.push(pos[i]);
|
||||
st.settable();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
lua::Hexsearch::Hexsearch(lua_State *L,int id):tblid(id)
|
||||
{
|
||||
lua::state st(L);
|
||||
uint64_t start,end;
|
||||
::Hexsearch::SearchArgType args;
|
||||
start=st.as<uint32_t>(1);
|
||||
end=st.as<uint32_t>(2);
|
||||
for(int i=3;i<=st.gettop();i++)
|
||||
{
|
||||
args.push_back(st.as<int>(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();
|
||||
#define __ADDCONST(name) st.push(::Hexsearch:: ## name); st.setglobal(#name)
|
||||
void lua::RegisterHexsearch(lua::state &st)
|
||||
{
|
||||
|
||||
Lune<lua::Hexsearch>::Register(st);
|
||||
__ADDCONST(ANYBYTE);
|
||||
__ADDCONST(ANYDWORD);
|
||||
__ADDCONST(DWORD_);
|
||||
}
|
||||
#undef __ADDCONST
|
@ -0,0 +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;
|
||||
}
|
||||
|
||||
|
||||
static int LoadMod(lua_State *L)
|
||||
{
|
||||
lua::state st(L);
|
||||
std::string modfile=st.as<std::string>(1);
|
||||
std::string modname=st.as<std::string>(2);
|
||||
uint32_t size_add=st.as<uint32_t>(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 @:"<<std::hex<<pos<<"size :"<<size<<std::endl;
|
||||
DFHack::Core::getInstance().p->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<std::string>(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<size_t>(1);
|
||||
unsigned char *p=(unsigned char *)lua_touserdata(L, 2);//st.as<lua::userdata>(2);
|
||||
size_t size=st.as<size_t>(3);
|
||||
size_t start=st.as<size_t>(4);
|
||||
for(size_t i=start;i<size;i++)
|
||||
{
|
||||
bool ok;
|
||||
ok=true;
|
||||
if(p[i]==M.bytes[0])
|
||||
{
|
||||
for(size_t j=0;j<4;j++)
|
||||
{
|
||||
if(p[i+j]!=M.bytes[j])
|
||||
{
|
||||
ok=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ok)
|
||||
{
|
||||
st.push(i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int LoadObjSymbols(lua_State *L)
|
||||
{
|
||||
lua::state st(L);
|
||||
std::string modfile=st.as<std::string>(1);
|
||||
OutFile::File f(modfile);
|
||||
OutFile::vSymbol vec=f.GetSymbols();
|
||||
OutFile::Symbol S;
|
||||
|
||||
st.newtable();
|
||||
for(size_t i=0;i<vec.size();i++)
|
||||
{
|
||||
st.push(i);
|
||||
S=vec[i];
|
||||
st.newtable();
|
||||
st.push(S.name);
|
||||
st.setfield("name");
|
||||
st.push(S.pos);
|
||||
st.setfield("pos");
|
||||
st.settable();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
static int NewMod(lua_State *L)
|
||||
{
|
||||
lua::state st(L);
|
||||
std::string modname=st.as<std::string>(1);
|
||||
size_t size=st.as<size_t>(2);
|
||||
size_t loc=st.as<size_t>(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<std::string>(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<lua::nil>())
|
||||
{
|
||||
st.pop();
|
||||
st.newtable();
|
||||
}
|
||||
lua::RegFunctionsLocal(st, lua_misc_func);
|
||||
st.setglobal("engine");
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
#include "lune.h"
|
||||
lua::object *lua::local_object::mytbl=0;
|
Loading…
Reference in New Issue