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