Lots of changes, including hexsearch and wrapper for lua, also LUNE - an object oriented lua wrapper

develop
Warmist 2011-08-03 16:07:57 +03:00
parent ff4d545ae7
commit f4179652fa
13 changed files with 927 additions and 27 deletions

@ -14,6 +14,7 @@
#include "luamain.h" #include "luamain.h"
#include "lua_Console.h" #include "lua_Console.h"
#include "lua_Process.h" #include "lua_Process.h"
#include "lua_Hexsearch.h"
#include "functioncall.h" #include "functioncall.h"
using std::vector; using std::vector;
@ -37,6 +38,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
//maybe remake it to run automaticaly //maybe remake it to run automaticaly
lua::RegisterConsole(lua::glua::Get(),&c->con); lua::RegisterConsole(lua::glua::Get(),&c->con);
lua::RegisterProcess(lua::glua::Get(),c->p); lua::RegisterProcess(lua::glua::Get(),c->p);
lua::RegisterHexsearch(lua::glua::Get());
commands.push_back(PluginCommand("dfusion","Init dfusion system.",dfusion)); commands.push_back(PluginCommand("dfusion","Init dfusion system.",dfusion));
commands.push_back(PluginCommand("lua", "Run interactive interpreter.\ commands.push_back(PluginCommand("lua", "Run interactive interpreter.\
\n Options: <filename> = run <filename> instead",lua_run)); \n Options: <filename> = run <filename> instead",lua_run));

@ -0,0 +1,35 @@
#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:
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);//TODO remake into OO oriented thing
}
#endif

@ -11,7 +11,7 @@ extern "C" {
#include "lualib.h" #include "lualib.h"
} }
//#include "lune.h" #include "lune.h"
#include "luaxx.hpp" #include "luaxx.hpp"
namespace lua namespace lua

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

@ -17,7 +17,7 @@ offsets.load = function ()
end end
end end
offsets.load() offsets.load()
function unlockDF() function GetTextRegion()
local ranges=Process.getMemRanges() local ranges=Process.getMemRanges()
for k,v in pairs(ranges) do for k,v in pairs(ranges) do
--for k2,v2 in pairs(v) do --for k2,v2 in pairs(v) do
@ -30,32 +30,27 @@ function unlockDF()
--if(v["execute"]) then num=num+100 end --if(v["execute"]) then num=num+100 end
--print(string.format("%d %x->%x %s %d",k,v["start"],v["end"],v.name,num)) --print(string.format("%d %x->%x %s %d",k,v["start"],v["end"],v.name,num))
local pos=string.find(v.name,".text") local pos=string.find(v.name,".text")
if pos~=nil then if(pos~=nil) then
v["write"]=true return v;
Process.setPermisions(v,v)
end end
end end
return nil
end
function unlockDF()
local reg=GetTextRegion()
reg["write"]=true
Process.setPermisions(reg,reg)
end end
function lockDF() function lockDF()
local ranges=Process.getMemRanges() local reg=GetTextRegion()
for k,v in pairs(ranges) do reg["write"]=false
--for k2,v2 in pairs(v) do Process.setPermisions(reg,reg)
-- print(string.format("%d %s->%s",k,tostring(k2),tostring(v2)))
--end
--local num
--num=0
--if(v["read"])then num=num+1 end
--if(v["write"])then num=num+10 end
--if(v["execute"]) then num=num+100 end
--print(string.format("%d %x->%x %s %d",k,v["start"],v["end"],v.name,num))
local pos=string.find(v.name,".text")
if pos~=nil then
v["write"]=false
Process.setPermisions(v,v)
end
end
end end
-- engine bindings -- engine bindings
engine=engine or {} engine=engine or {}
engine.peekd=Process.readDWord engine.peekd=Process.readDWord
engine.poked=Process.writeDWord engine.poked=Process.writeDWord
dofile("dfusion/patterns.lua")
dofile("dfusion/patterns2.lua")
dofile("dfusion/itempatterns.lua")

@ -15,10 +15,17 @@ dofile("dfusion/common.lua")
print("Unlocking Df .text section...") print("Unlocking Df .text section...")
unlockDF() unlockDF()
print("Done unlock") print("Done unlock")
lockDF() text=GetTextRegion()
dofile("dfusion/simple_embark/plugin.lua") h=hexsearch(text.start,text["end"],0x73,0x02,0x8b,0xce,0x53,0x6a,0x01,0x6a,0x06)
print("hello world") pos=h:findall()
Console.print("Hello world in console!\n") for k,v in pairs(pos) do
print(k..v)
end
--hexsearch.delete(h)
lockDF() --DOES NOT WORK?!
--dofile("dfusion/simple_embark/plugin.lua")
--print("hello world")
--Console.print("Hello world in console!\n")
--name=Console.lineedit("Enter name:") --name=Console.lineedit("Enter name:")
--Console.print("Your name is:"..name) --Console.print("Your name is:"..name)

@ -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,243 @@
ptt_dfstring={}
if(COMPATMODE) then
ptt_dfstring.ptr={off=4,rtype=DWORD}
ptt_dfstring.size={off=20,rtype=DWORD}
else
ptt_dfstring.ptr={off=0,rtype=DWORD}
ptt_dfstring.size={off=16,rtype=DWORD}
ptt_dfstring.alloc={off=20,rtype=DWORD}
end
function ptt_dfstring:getval()
--print(string.format("GETTING FROM:%x",self.__offset))
if self.size<16 then
--print(string.format("GETTING FROM:%x",self.__offset))
return string.sub(engine.peekstr(self.__offset),1,self.size)
else
--print(string.format("GETTING FROM:%x",self.ptr))
return string.sub(engine.peekstr(self.ptr),1,self.size)
end
end
function ptt_dfstring:setval(newstring)
local offset=self.__offset
local strl=string.len(newstring)
if strl<16 then
--print(string.format("GETTING FROM:%x",self.__offset))
engine.poked(offset+ptt_dfstring.size.off,strl)
engine.poked(offset+ptt_dfstring.alloc.off,15)
engine.pokestr(offset,newstring)
else
local loc
if engine.peekd(offset+ptt_dfstring.alloc.off) > strl then
loc=engine.peekd(offset)
print("Will fit:"..loc.." len:"..strl)
else
loc=Allocate(strl+1)
engine.poked(offset+ptt_dfstring.alloc.off,strl)
print("Will not fit:"..loc.." len:"..strl)
end
--print(string.format("GETTING FROM:%x",self.ptr))
engine.poked(self.__offset+ptt_dfstring.size.off,strl)
engine.pokestr(loc,newstring)
engine.poked(self.__offset,loc)
end
end
--if(COMPATMODE) then
--ptr_vector={}
--ptr_vector.st={off=4,rtype=DWORD}
--ptr_vector.en={off=8,rtype=DWORD}
--else
ptr_vector={}
ptr_vector.st={off=0,rtype=DWORD}
ptr_vector.en={off=4,rtype=DWORD}
ptr_vector.alloc={off=8,rtype=DWORD}
--end
function ptr_vector:clone(settype)
local ret={}
for k,v in pairs(self) do
ret[k]=v
end
ret.type=settype
return ret
end
function ptr_vector:size()
return (self.en-self.st)/engine.sizeof(self.type)
end
ptr_vector.type=DWORD
function ptr_vector:getval(num)
return engine.peek(self.st+engine.sizeof(self.type)*num,self.type)
end
function ptr_vector:setval(num,val)
return engine.poke(self.st+engine.sizeof(self.type)*num,self.type,val)
end
function ptr_vector:append(val)
if self.alloc - self.en > 0 then
local num=self:size()
self.en=self.en+engine.sizeof(self.type)
self:setval(val,num)
else
error("larger than allocated arrays not implemented yet")
local num=self:size()
local ptr=Allocate(num*2)
end
end
ptt_dfflag={}
function ptt_dfflag.flip(self,num) --flip one bit in flags
local of=math.floor (num/8);
self[of]=bit.bxor(self[of],bit.lshift(1,num%8))
end
function ptt_dfflag.get(self,num) -- get one bit in flags
local of=math.floor (num/8);
if bit.band(self[of],bit.lshift(1,num%8))~=0 then
return true
else
return false
end
end
function ptt_dfflag.set(self,num,val) --set to on or off one bit in flags
if (self:get(num)~=val) then
self:flip(num)
end
end
function ptt_dfflag.new(size) -- create new flag pattern of size(in bytes)
local ret={}
for i=0,size-1 do
ret[i]={off=i,rtype=BYTE};
end
ret.flip=ptt_dfflag.flip --change to metatable stuff...
ret.get=ptt_dfflag.get
ret.set=ptt_dfflag.set
return ret;
end
--[[
Creature:
0 name (df_string) 28
28 nick (df_string) 56
56 surname- namearray(7*dword(4)) 84 ...
140 race (dword) 144
224 flags
264 civ (dword)
252 ID
592 following ID
904 bleed vector? hurt vector or sth...
0x790 legends id?
2128 known names? or knowledge?
flags:
0 Can the dwarf move or are they waiting for their movement timer
1 Dead (might also be set for incoming/leaving critters that are alive)
2 Currently in mood
3 Had a mood
4 "marauder" -- wide class of invader/inside creature attackers
5 Drowning
6 Active merchant
7 "forest" (used for units no longer linked to merchant/diplomacy, they just try to leave mostly)
8 Left (left the map)
9 Rider
10 Incoming
11 Diplomat
12 Zombie
13 Skeleton
14 Can swap tiles during movement (prevents multiple swaps)
15 On the ground (can be conscious)
16 Projectile
17 Active invader (for organized ones)
18 Hidden in ambush
19 Invader origin (could be inactive and fleeing)
20 Will flee if invasion turns around
21 Active marauder/invader moving inward
22 Marauder resident/invader moving in all the way
23 Check against flows next time you get a chance
24 Ridden
25 Caged
26 Tame
27 Chained
28 Royal guard
29 Fortress guard
30 Suppress wield for beatings/etc
31 Is an important historical figure
32 swiming
]]--
ptr_Creature={}
ptr_Creature.x={off=144,rtype=WORD} --ok
ptr_Creature.y={off=146,rtype=WORD} --ok
ptr_Creature.z={off=148,rtype=WORD} --ok
ptr_Creature.flags={off=224,rtype=ptt_dfflag.new(10)}
ptr_Creature.name={off=0,rtype=ptt_dfstring}
ptr_Creature.ID={off=252,rtype=DWORD} --ok i guess
ptr_Creature.followID={off=592,rtype=DWORD} --ok
ptr_Creature.race={off=140,rtype=DWORD} --ok
ptr_Creature.civ={off=264,rtype=DWORD}
ptr_Creature.legends={off=344,rtype=ptr_vector} --ok
ptr_Creature.hurt1={off=0x308,rtype=ptr_vector:clone(BYTE)} --byte vector...
ptr_Creature.hurt2={off=0x338,rtype=ptr_vector}
ptr_Creature.wounds={off=0x388,rtype=ptr_vector}
ptr_Creature.itemlist1={off=0x1D0,rtype=ptr_vector}
ptr_Creature.itemlist2={off=0x288,rtype=ptr_vector}
ptr_Creature.bloodlvl={off=0x490,rtype=DWORD}
ptr_Creature.bleedlvl={off=0x494,rtype=DWORD}
ptr_CrGloss={}
ptr_CrGloss.token={off=0,rtype=ptt_dfstring}
ptr_CrGloss.castes={off=296,rtype=ptr_vector}
ptr_CrCaste={}
ptr_CrCaste.name={off=0,rtype=ptt_dfstring}
ptr_CrCaste.flags_ptr={off=0x524,rtype=DWORD} --size 17?
--[=[
Flags:
57 - is sentient (allows setting labours)
--]=]
ptr_LEntry={} -- all size 256
ptr_LEntry.name={off=36,rtype=ptt_dfstring}
ptr_LEntry.id1={off=160,rtype=DWORD}
ptr_LEntry.id2={off=164,rtype=DWORD}
ptr_LEntry.somlist={off=220,rtype=DWORD}
ptr_dfname={}
for i=0,6 do
ptr_dfname[i]={off=i*4,rtype=DWORD}
end
--[[
Site docs:
0x38 name struct todo...
0x78 type:
0 - mountain halls (yours)
1 - dark fort
2 - cave
3 - mountain hall (other)
4 - forest
5 - hamlet
6 - imp location
7 - lair
8 - fort
9 - camp
0x7a some sort of id?
0x84 some vec (ids)
0x94 some other vec (ids)
0xa4 some vec (prts)
0x118 ptr to sth
0x14c ptr to mapdata
]]--
ptr_site={}
ptr_site.type={off=0x78,rtype=WORD}
ptr_site.id={off=0x7a,rtype=DWORD}
ptr_site.name={off=0x38,rtype=ptr_dfname}
ptr_site.flagptr={off=0x118,rtype=DWORD}
ptr_legends2={}
ptr_legends2.id={off=0,rtype=DWORD}
ptr_legends2.follow={off=0x18,rtype=DWORD}
ptr_material={}
ptr_material.token={off=0,rtype=ptt_dfstring}

@ -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,74 @@
#include "hexsearch.h"
Hexsearch::Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos):args_(args),pos_(startpos_),startpos_(startpos),endpos_(endpos)
{
}
Hexsearch::~Hexsearch()
{
}
uint64_t Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm
{
DFHack::Core &inst=DFHack::Core::getInstance();
DFHack::Process *p=inst.p;
uint8_t *buf;
buf=new uint8_t[args_.size()];
while(pos_<endpos_)
{
bool found=true;
p->readByte(pos_,buf[0]);
if(buf[0]==args_[0]) //TODO make a comparator
{
p->read(pos_,args_.size(),buf);
for(size_t i=0;i<args_.size();i++)
{
if(buf[i]!=args_[i])
{
pos_+=i;
found=false;
break;
}
}
if(found)
{
pos_+=args_.size();
delete [] buf;
return pos_;
}
}
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,57 @@
#include "lua_Hexsearch.h"
int lua::Hexsearch::find(lua_State *L)
{
lua::state st(L);
uint64_t pos=p->FindNext();
st.push(pos);
return 1;
}
int lua::Hexsearch::findall(lua_State *L)
{
lua::state st(L);
std::vector<uint64_t> pos=p->FindAll();
st.newtable();
for(int 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>(2);
end=st.as<uint32_t>(3);
for(int i=4;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();
void lua::RegisterHexsearch(lua::state &st)
{
Lune<lua::Hexsearch>::Register(st);
}

@ -0,0 +1,2 @@
#include "lune.h"
lua::object *lua::local_object::mytbl=0;