dfhack/plugins/Dfusion/luafiles/embark/init.lua

108 lines
3.3 KiB
Lua

local dfu=require("dfusion")
local ms=require("memscan")
CustomEmbark=defclass(CustomEmbark,dfu.BinaryPlugin)
CustomEmbark.ATTRS{filename="dfusion/embark/embark.o",name="CustomEmbark",race_caste_data=DEFAULT_NIL}
function CustomEmbark:install()
local stoff=dfhack.internal.getAddress('start_dwarf_count')
if stoff==nil then
error("address for start_dwarf_count not found!")
end
local _,race_id_offset=df.sizeof(df.global.ui:_field("race_id"))
local needle={0x0f,0xb7,0x0d} --movzx,...
add_dword(needle,race_id_offset) -- ...word ptr[]
local mem=ms.get_code_segment()
local trg_offset=mem.uint8_t.find(needle,stoff)--maybe endoff=stoff+bignumber
if trg_offset==nil then
error("address for race_load not found")
end
needle={0x83,0xc8,0xff} -- or eax, 0xFF
local caste_offset=mem.uint8_t.find(needle,trg_offset)
if caste_offset==nil or caste_offset-stoff>1000 then
error("Caste change code not found or found too far!")
end
end
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
--print("adding:"..line.." id:"..RaceTable[line])
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=VersionInfo.getAddress('start_dwarf_count')
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=df.sizeof(df.global.ui:_field("race_id"))
loc=offsets.find(stoff,0x0f,0xb7,0x0d,DWORD_,tofind) --MOVZX ECX,WORD PTR[]
print(string.format("found:%x",loc))
if((loc~=0)and(loc-stoff<1000)) then
loc2=offsets.find(loc,0x83,0xc8,0xff) -- or eax, ffffff (for caste)
if loc2== 0 then
error ("Location for caste nulling not found!")
end
engine.pokeb(loc2,0x90)
engine.pokeb(loc2+1,0x90)
engine.pokeb(loc2+2,0x90)
ModData=engine.installMod("dfusion/embark/embark.o","Embark",256)
modpos=ModData.pos
modsize=ModData.size
local castepos=modpos+engine.FindMarker(ModData,"caste")
local racepos=modpos+engine.FindMarker(ModData,"race")
count=MakeTable(modpos,modsize,names)
engine.poked(castepos,modpos+modsize) --fix array start for race
engine.poked(racepos,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,0x90)
engine.pokeb(loc+1,0x90)
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