parent
4b9786f8af
commit
835581e5d3
@ -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,EOL)
|
||||||
|
print(string.format("Compare at:%x",pos))
|
||||||
|
if pos ==0 then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if(pos-off>0x100) then
|
||||||
|
print(string.format("Distance to cmp:%x",pos-off))
|
||||||
|
pos =offsets.find(off,CALL,EOL)
|
||||||
|
print(string.format("Distance to call:%x",pos-off))
|
||||||
|
return 0
|
||||||
|
--return analyzeF(pos)
|
||||||
|
else
|
||||||
|
return pos
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function minEx(...)
|
||||||
|
local imin=arg[1]
|
||||||
|
for _,v in ipairs(arg) do
|
||||||
|
if imin> v and v~=0 then
|
||||||
|
imin=v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return imin
|
||||||
|
end
|
||||||
|
function signDword(dw)
|
||||||
|
if(dw>0xFFFFFFFF) then
|
||||||
|
return dw-0xFFFFFFFF
|
||||||
|
end
|
||||||
|
return dw
|
||||||
|
end
|
||||||
|
--[[
|
||||||
|
Warning: not all mov's are acounted for. Found one: mov EAX,WORD PTR[EBP+1EF4] WTF??
|
||||||
|
Two more compares are missing. There are calls instead (same function)
|
||||||
|
]]--
|
||||||
|
if not(FILE) then
|
||||||
|
print("race num:"..engine.peekw(offsets.getEx("CurrentRace")))
|
||||||
|
print("Your current race is:"..GetRaceToken(engine.peekw(offsets.getEx('CurrentRace'))))
|
||||||
|
print("If this is wrong please quit now (by ctrl+c)")
|
||||||
|
io.stdin:read()
|
||||||
|
end
|
||||||
|
friendship_in={}
|
||||||
|
dofile("dfusion/friendship/install.lua")
|
||||||
|
dofile("dfusion/friendship/patch.lua")
|
||||||
|
if not(FILE) then
|
||||||
|
names=ParseNames("dfusion/friendship/races.txt")--io.open("plugins/friendship/races.txt"):lines()
|
||||||
|
friendship_in.install(names)
|
||||||
|
friendship_in.patch()
|
||||||
|
end
|
||||||
|
function friendship(names)
|
||||||
|
friendship_in.install(names)
|
||||||
|
friendship_in.patch()
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
DWARF
|
||||||
|
GOBLIN
|
||||||
|
ELF
|
||||||
|
HUMAN
|
||||||
|
KOBOLD
|
||||||
|
GREMLIN
|
||||||
|
TIGERMAN
|
||||||
|
ANT_MAN
|
@ -1,3 +1,152 @@
|
|||||||
#include "lua_Misc.h"
|
#include "lua_Misc.h"
|
||||||
|
uint32_t lua::PlugManager::AddNewPlug(std::string name,uint32_t size,uint32_t loc)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
if(size!=0)
|
||||||
|
p=new unsigned char[size];
|
||||||
|
else
|
||||||
|
p=(void*)loc;
|
||||||
|
plugs[name]=p;
|
||||||
|
return (uint32_t)p;
|
||||||
|
}
|
||||||
|
uint32_t lua::PlugManager::FindPlugin(std::string name)
|
||||||
|
{
|
||||||
|
mapPlugs::iterator it=plugs.find(name);
|
||||||
|
if(it!=plugs.end())
|
||||||
|
return (uint32_t)it->second;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void lua::RegisterMisc(lua::state &st);
|
|
||||||
|
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");
|
||||||
|
}
|
Loading…
Reference in New Issue