diff --git a/plugins/Dfusion/luafiles/friendship/friendship.asm b/plugins/Dfusion/luafiles/friendship/friendship.asm index e56fe7f49..b649e38de 100644 --- a/plugins/Dfusion/luafiles/friendship/friendship.asm +++ b/plugins/Dfusion/luafiles/friendship/friendship.asm @@ -66,8 +66,10 @@ mov eax, [edi+0x8c] #jmp compare compare: push ecx +mark_racepointer: mov ebx,0xDEADBEEF #write a pointer to the list of allowed races -mov ecx,2000 #write a number of allowed races +mark_racecount: +mov ecx,0xDEADBEEF #write a number of allowed races loop1: cmp word[ebx+ecx*2],ax jz endok @@ -92,11 +94,13 @@ endfinal: pop ebx pop eax -mov [0xFEEDBEEF],eax #write a pointer to safe location (usually after this) +mark_safeloc1: +mov [0xDEADBEEF],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) +mark_safeloc2: +mov eax,[0xDEADBEEF] #write a pointer to safe location (same as above) ret diff --git a/plugins/Dfusion/luafiles/friendship/friendship.o b/plugins/Dfusion/luafiles/friendship/friendship.o index f956de3e0..c801562db 100644 Binary files a/plugins/Dfusion/luafiles/friendship/friendship.o and b/plugins/Dfusion/luafiles/friendship/friendship.o differ diff --git a/plugins/lua/dfusion/embark.lua b/plugins/lua/dfusion/embark.lua index a674a96d3..578c0b903 100644 --- a/plugins/lua/dfusion/embark.lua +++ b/plugins/lua/dfusion/embark.lua @@ -4,6 +4,8 @@ local ms=require("memscan") local MAX_RACES=100 CustomEmbark=defclass(CustomEmbark,dfu.BinaryPlugin) CustomEmbark.name="CustomEmbark" + +print(t) local myos=dfhack.getOSType() if myos=="windows" then CustomEmbark.ATTRS{filename="hack/lua/plugins/dfusion/embark.o",name="CustomEmbark",race_caste_data=DEFAULT_NIL} diff --git a/plugins/lua/dfusion/friendship.lua b/plugins/lua/dfusion/friendship.lua new file mode 100644 index 000000000..70a1ceea4 --- /dev/null +++ b/plugins/lua/dfusion/friendship.lua @@ -0,0 +1,111 @@ +local _ENV = mkmodule('plugins.dfusion.friendship') +local dfu=require("plugins.dfusion") +local ms=require("memscan") + +local MAX_RACES=100 +local MAX_CODE_DIST=250 +FriendshipRainbow=defclass(FriendshipRainbow,dfu.BinaryPlugin) +FriendshipRainbow.name="FriendshipRainbow" +-- os independant... I think... +FriendshipRainbow.ATTRS{filename="hack/lua/plugins/dfusion/friendship.o",name="FriendshipRainbow",race_data=DEFAULT_NIL} +FriendshipRainbow.class_status="valid, not installed" +function FriendshipRainbow:find_one(codesg,needle,crace) + dfu.concatTables(needle,dfu.dwordToTable(crace)) + return codesg.uint8_t:findall(needle) +end +function FriendshipRainbow:find_all() + local code=ms.get_code_segment() + local locations={} + local _,crace=df.sizeof(df.global.ui:_field("race_id")) + + dfu.concatTables(locations,self:find_one(code,{0x66,0xa1},crace)) --mov ax,[ptr] + dfu.concatTables(locations,self:find_one(code,{0xa1},crace)) --mov ax,[ptr] + local registers= + {0x05, -- (e)ax + 0x1d, --ebx + 0x0d, --ecx + 0x15, --edx + 0x35, --esi + 0x3d, --edi + --0x25, --esp not used? + --0x2d, --ebp not used? + } + for k,reg in ipairs(registers) do + + dfu.concatTables(locations,self:find_one(code,{0x0f,0xbf,reg},crace)) --movsx reg,[ptr] + dfu.concatTables(locations,self:find_one(code,{0x66,0x8b,reg},crace)) --mov reg,[ptr] + end + printall(locations) + return self:filter_locations(code,locations) +end +function FriendshipRainbow:filter_locations(codesg,locations) + local ret={} + local registers={0x80,0x83,0x81,0x82,0x86,0x87, + 0x98,0x9b,0x99,0x9a,0x9e,0x9f, + 0x88,0x8b,0x89,0x8a,0x8e,0x8f, + 0x90,0x93,0x91,0x92,0x96,0x97, + 0xb0,0xb3,0xb1,0xb2,0xb6,0xb7, + 0xb8,0xbb,0xb9,0xba,0xbe,0xbf} + for _,entry in ipairs(locations) do + for _,r in ipairs(registers) do + + local idx,addr=codesg.uint8_t:find({0x39,r,0x8c,0x00,0x00,0x00}, + codesg.uint8_t:addr2idx(entry[2]),codesg.uint8_t:addr2idx(entry[2])+MAX_CODE_DIST) + if addr then + table.insert(ret,{addr,r}) + break + end + idx,addr=codesg.uint8_t:find({0x3b,r,0x8c,0x00,0x00,0x00}, + codesg.uint8_t:addr2idx(entry[2]),codesg.uint8_t:addr2idx(entry[2])+MAX_CODE_DIST) + if addr then + table.insert(ret,{addr,r}) + break + end + end + end + return ret +end +function FriendshipRainbow:patchCalls(target) + local addrs=self:find_all() + local swaps={} + for k,adr in ipairs(addrs) do + local newval=dfu.makeCall(adr[1],target) + table.insert(newval,adr[2]) + for t,val in ipairs(newval) do + swaps[adr[1]+t-1]=val + end + end + dfhack.internal.patchBytes(swaps) +end +function FriendshipRainbow:set_races(arr) + local n_to_id=require("plugins.dfusion.tools").build_race_names() + local ids={} + for k,v in ipairs(self.race_data) do -- to check if all races are valid. + ids[k]=n_to_id[v] + end + for k,v in ipairs(ids) do + arr[k-1]=ids[k] + end +end +function FriendshipRainbow:install(races) + self.race_data=races or self.race_data + if #self.race_data<1 then + error("race count must be bigger than 0") + end + if #self.race_data>MAX_RACES then + error("race count must be less then "..MAX_RACES) + end + local rarr=self:allocate("race_array",'uint16_t',MAX_RACES) + local _,rarr_offset=df.sizeof(rarr) + self:set_marker_dword("racepointer",rarr_offset) + self:set_races(rarr) + self:set_marker_dword("racecount",#self.race_data) + local safe_loc=self:allocate("safe_loc",'uint32_t',1) + local _1,safe_loc_offset=df.sizeof(safe_loc) + self:set_marker_dword("safeloc1",safe_loc_offset) + self:set_marker_dword("safeloc2",safe_loc_offset) + local addr=self:move_to_df() + self:patchCalls(addr) + self.installed=true + end +return _ENV \ No newline at end of file diff --git a/plugins/lua/dfusion/friendship.o b/plugins/lua/dfusion/friendship.o new file mode 100644 index 000000000..c801562db Binary files /dev/null and b/plugins/lua/dfusion/friendship.o differ diff --git a/plugins/lua/dfusion/srcs/compile.bat b/plugins/lua/dfusion/srcs/compile.bat new file mode 100644 index 000000000..e084949f4 --- /dev/null +++ b/plugins/lua/dfusion/srcs/compile.bat @@ -0,0 +1 @@ +as -anl --32 -o friendship.o friendship.asm \ No newline at end of file diff --git a/plugins/lua/dfusion/srcs/embark.asm b/plugins/lua/dfusion/srcs/embark.asm new file mode 100644 index 000000000..d2fa91081 --- /dev/null +++ b/plugins/lua/dfusion/srcs/embark.asm @@ -0,0 +1,7 @@ +.intel_syntax +mov eax , [esp+0x1C] # loop counter +mark_caste: +movsx ecx, word ptr[eax*2+0xdeadbeef] +mark_race: +movzx eax,word ptr [eax*2+0xDEADBEEF] +ret diff --git a/plugins/lua/dfusion/srcs/friendship.asm b/plugins/lua/dfusion/srcs/friendship.asm new file mode 100644 index 000000000..b649e38de --- /dev/null +++ b/plugins/lua/dfusion/srcs/friendship.asm @@ -0,0 +1,106 @@ +.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 +mark_racepointer: +mov ebx,0xDEADBEEF #write a pointer to the list of allowed races +mark_racecount: +mov ecx,0xDEADBEEF #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 +mark_safeloc1: +mov [0xDEADBEEF],eax #write a pointer to safe location (usually after this) +pop eax +pushfd +inc eax #skip one instruction +popfd +push eax +mark_safeloc2: +mov eax,[0xDEADBEEF] #write a pointer to safe location (same as above) +ret