C++ Code:
#include <windows.h>#include <iostream>#include <d3d9.h>#include <d3dx9.h>#include <detours.h>#include <thread>#include <cstdint>#include <memory>#include <fstream>#include "Graphics.hxx"#pragma comment(lib, "WS2_32.lib")#pragma comment(lib, "d3d9.lib")#pragma comment(lib, "d3dx9.lib")#pragma comment(lib, "detours.lib")enum D3D9_vTable
{ QUERYINTERFACE
, ADDREF
, RELEASE
, TESTCOOPERATIVELEVEL
, GETAVAILABLETEXTUREMEM
, EVICTMANAGEDRESOURCES
, GETDIRECT3D
, GET_DEVICE_CAPS
, GETDISPLAYMODE
, GETCREATIONPARAMETERS
, SETCURSORPROPERTIES
, SETCURSORPOSITION
, SHOW_CURSOR
, CREATEADDITIONALSWAPCHAIN
, GETSWAPCHAIN
, GETNUMBEROFSWAPCHAINS
, RESET
, PRESENT
, GETBACKBUFFER
, GETRASTERSTATUS
, SETDIALOGBOXMODE
, GETGAMMARAMP
, SETGAMMARAMP
, CREATETEXTURE
, CREATEVOLUMETEXTURE
, CREATECUBETEXTURE
, CREATEVERTEXBUFFER
, CREATEINDEXBUFFER
, CREATERENDERTARGET
, CREATEDEPTHSTENCILSURFACE
, UPDATESURFACE
, UPDATETEXTURE
, GETRENDERTARGETDATA
, GETFRONTBUFFERDATA
, STRETCHRECT
, COLORFILL
, CREATEOFFSCREENPLAINSURFACE
, SETRENDERTARGET
, GETRENDERTARGET
, SETDEPTHSTENCILSURFACE
, GETDEPTHSTENCILSURFACE
, BEGINSCENE
, ENDSCENE
, CLEAR
, SETTRANSFORM
, GETTRANSFORM
, MULTIPLYTRANSFORM
, SETVIEWPORT
, GETVIEWPORT
, SETMATERIAL
, GETMATERIAL
, SETLIGHT
, GETLIGHT
, LIGHTENABLE
, GETLIGHTENABLE
, SETCLIPPLANE
, GETCLIPPLANE
, SETRENDERSTATE
, GETRENDERSTATE
, CREATESTATEBLOCK
, BEGINSTATEBLOCK
, ENDSTATEBLOCK
, SETCLIPSTATUS
, GETCLIPSTATUS
, GETTEXTURE
, SETTEXTURE
, GETTEXTURESTAGESTATE
, SETTEXTURESTAGESTATE
, GETSAMPLERSTATE
, SETSAMPLERSTATE
, VALIDATEDEVICE
, SET_PALETTE_ENTRIES
, GET_PALETTE_ENTRIES
, SETCURRENTTEXTUREPALETTE
, GETCURRENTTEXTUREPALETTE
, SETSCISSORRECT
, GETSCISSORRECT
, SETSOFTWAREVERTEXPROCESSING
, GETSOFTWAREVERTEXPROCESSING
, SETNPATCHMODE
, GETNPATCHMODE
, DRAWPRIMITIVE
, DRAWINDEXEDPRIMITIVE
, DRAWPRIMITIVEUP
, DRAWINDEXEDPRIMITIVEUP
, PROCESSVERTICES
, CREATEVERTEXDECLARATION
, SETVERTEXDECLARATION
, GETVERTEXDECLARATION
, SETFVF
, GETFVF
, CREATEVERTEXSHADER
, SETVERTEXSHADER
, GETVERTEXSHADER
, SETVERTEXSHADERCONSTANTF
, GETVERTEXSHADERCONSTANTF
, SETVERTEXSHADERCONSTANTI
, GETVERTEXSHADERCONSTANTI
, SETVERTEXSHADERCONSTANTB
, GETVERTEXSHADERCONSTANTB
, SETSTREAMSOURCE
, GETSTREAMSOURCE
, SETSTREAMSOURCEFREQ
, GETSTREAMSOURCEFREQ
, SETINDICES
, GETINDICES
, CREATEPIXELSHADER
, SETPIXELSHADER
, GETPIXELSHADER
, SETPIXELSHADERCONSTANTF
, GETPIXELSHADERCONSTANTF
, SETPIXELSHADERCONSTANTI
, GETPIXELSHADERCONSTANTI
, SETPIXELSHADERCONSTANTB
, GETPIXELSHADERCONSTANTB
, DRAWRECTPATCH
, DRAWTRIPATCH
, DELETEPATCH
, CREATEQUERY
, };typedef HRESULT
(__stdcall
*EndScene_t
)(LPDIRECT3DDEVICE9 pDevice
);typedef HRESULT
(__stdcall
*BeginScene_t
)(LPDIRECT3DDEVICE9 pDevice
);typedef HRESULT
(__stdcall
*Reset_t
)(LPDIRECT3DDEVICE9 pDevice
, D3DPRESENT_PARAMETERS
*pPresentationParameters
);typedef HRESULT
(__stdcall
*DrawPrimitive_t
)(LPDIRECT3DDEVICE9 pDevice
, D3DPRIMITIVETYPE PrimitiveType
, UINT StartVertex
, UINT PrimitiveCount
);typedef HRESULT
(__stdcall
*DrawIndexedPrimitive_t
)(LPDIRECT3DDEVICE9 pDevice
, D3DPRIMITIVETYPE PrimitiveType
, INT BaseVertexIndex
, UINT MinVertexIndex
, UINT NumVertices
, UINT startIndex
, UINT primCount
);typedef HRESULT
(__stdcall
*DrawPrimitiveUP_t
)(LPDIRECT3DDEVICE9 pDevice
, D3DPRIMITIVETYPE PrimitiveType
, UINT PrimitiveCount
, CONST
void* pVertexStreamZeroData
, UINT VertexStreamZeroStride
);typedef HRESULT
(__stdcall
*DrawIndexedPrimitiveUP_t
)(LPDIRECT3DDEVICE9 pDevice
, D3DPRIMITIVETYPE PrimitiveType
, UINT MinVertexIndex
, UINT NumVertices
, UINT PrimitiveCount
, CONST
void* pIndexData
, D3DFORMAT IndexDataFormat
, CONST
void* pVertexStreamZeroData
, UINT VertexStreamZeroStride
);typedef HRESULT
(__stdcall
*SetTexture_t
)(LPDIRECT3DDEVICE9 pDevice
, DWORD Sampler
, IDirect3DBaseTexture9
*pTexture
);BeginScene_t o_BeginScene
;EndScene_t o_EndScene
;Reset_t o_Reset
;DrawPrimitive_t o_DrawPrimitive
;DrawIndexedPrimitive_t o_DrawIndexedPrimitive
;DrawPrimitiveUP_t o_DrawPrimitiveUP
;DrawIndexedPrimitiveUP_t o_DrawIndexedPrimitiveUP
;SetTexture_t o_SetTexture
;Font
* font
= NULL
;HRESULT __stdcall DXI_BeginScene
(LPDIRECT3DDEVICE9 pDevice
){ static bool init
= false; if (!init
) { init
= true; font
= new Font
(pDevice
, "Arial", 8); } return o_BeginScene
(pDevice
);}HRESULT __stdcall DXI_EndScene
(LPDIRECT3DDEVICE9 pDevice
){ if (font
) font
->Draw
(50, 50, "HELLO"); return o_EndScene
(pDevice
);}//When the application is minimised, resources are destroyed and rebuilt automatically. It's how d3d works.HRESULT __stdcall DXI_Reset
(LPDIRECT3DDEVICE9 pDevice
, D3DPRESENT_PARAMETERS
*pPresentationParameters
){ if (font
) font
->OnLostDevice
(); HRESULT res
= o_Reset
(pDevice
, pPresentationParameters
); if (font
) font
->OnResetDevice
(); return res
;}HRESULT __stdcall DXI_DrawPrimitive
(LPDIRECT3DDEVICE9 pDevice
, D3DPRIMITIVETYPE PrimitiveType
, UINT StartVertex
, UINT PrimitiveCount
){ IDirect3DBaseTexture9
* tex
= nullptr
; if (SUCCEEDED
(pDevice
->GetTexture
(0, &tex
))) { LPDIRECT3DTEXTURE9 _tex
= (LPDIRECT3DTEXTURE9
)tex
; D3DSURFACE_DESC desc
; if (SUCCEEDED
(_tex
->GetLevelDesc
(0, &desc
))) { if (desc.
Width && desc.
Height) //51 x 51 = mini-map compass. Better to check on the Simba side. 512 x 512 = map. { D3DXMATRIX WVP
; if (SUCCEEDED
(pDevice
->GetVertexShaderConstantF
(0, (float*)&WVP
, 4))) { D3DXMatrixTranspose
(&WVP
, &WVP
); D3DXVECTOR3 out
; D3DXVECTOR3 in
(0, 0, 0); D3DXVec3TransformCoord
(&out
, &in
, &WVP
); D3DVIEWPORT9 viewport
; pDevice
->GetViewport
(&viewport
); out.
x = (out.
x + 1.0f) * viewport.
Width * 0.5f + viewport.
X; out.
y = (1.0f - out.
y) * viewport.
Height * 0.5f + viewport.
Y; if (font
) font
->Draw
(out.
x, out.
y, "Compass(%, %)", desc.
Width, desc.
Height); } } } tex
->Release
(); } return o_DrawPrimitive
(pDevice
, PrimitiveType
, StartVertex
, PrimitiveCount
);}//function in which both textures AND models are drawn. Textures have a primCount of 2 and NumVertices of 4. Basically 2 triangles make up one square/rectangular texture.//models otherwise..HRESULT __stdcall DXI_DrawIndexedPrimitive
(LPDIRECT3DDEVICE9 pDevice
, D3DPRIMITIVETYPE PrimitiveType
, INT BaseVertexIndex
, UINT MinVertexIndex
, UINT NumVertices
, UINT startIndex
, UINT primCount
){ DWORD ID
= GenerateID
(pDevice
, PrimitiveType
, BaseVertexIndex
, MinVertexIndex
, NumVertices
, startIndex
, primCount
); D3DXVECTOR3 out
= WorldToScreen
(pDevice
); //Get the base center point of the model.. For more advanced accuracy, you can use ProcessVerts to get each and every vertex of said model (fingers, eyes, etc..) static bool debug
= false; if (GetAsyncKeyState
(VK_END
) & 1) debug
= !debug
; if (font
&& debug
) font
->Draw
(out.
x, out.
y, 0xFFFF0000, "%", ID
); return o_DrawIndexedPrimitive
(pDevice
, PrimitiveType
, BaseVertexIndex
, MinVertexIndex
, NumVertices
, startIndex
, primCount
);}HRESULT __stdcall DXI_DrawPrimitiveUP
(LPDIRECT3DDEVICE9 pDevice
, D3DPRIMITIVETYPE PrimitiveType
, UINT PrimitiveCount
, CONST
void* pVertexStreamZeroData
, UINT VertexStreamZeroStride
){ return o_DrawPrimitiveUP
(pDevice
, PrimitiveType
, PrimitiveCount
, pVertexStreamZeroData
, VertexStreamZeroStride
);}HRESULT __stdcall DXI_DrawIndexedPrimitiveUP
(LPDIRECT3DDEVICE9 pDevice
, D3DPRIMITIVETYPE PrimitiveType
, UINT MinVertexIndex
, UINT NumVertices
, UINT PrimitiveCount
, CONST
void* pIndexData
, D3DFORMAT IndexDataFormat
, CONST
void* pVertexStreamZeroData
, UINT VertexStreamZeroStride
){ return o_DrawIndexedPrimitiveUP
(pDevice
, PrimitiveType
, MinVertexIndex
, NumVertices
, PrimitiveCount
, pIndexData
, IndexDataFormat
, pVertexStreamZeroData
, VertexStreamZeroStride
);}HRESULT __stdcall DXI_SetTexture
(LPDIRECT3DDEVICE9 pDevice
, DWORD Sampler
, IDirect3DBaseTexture9
*pTexture
){ return o_SetTexture
(pDevice
, Sampler
, pTexture
);}DWORD __stdcall InitialiseHooks
(void* param
);bool __stdcall DllMain
(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
){ switch (fdwReason
) { case DLL_PROCESS_ATTACH
: DisableThreadLibraryCalls
(hinstDLL
); CreateThread
(NULL
, 0, InitialiseHooks
, NULL
, 0, 0); return true; case DLL_PROCESS_DETACH
: break; default: break; } return true;}DWORD FindPattern
(DWORD dwAddress
, DWORD dwLen
, BYTE
*bMask
, const char* szMask
){ auto bCompare
= [](const BYTE
* pData
, const BYTE
* bMask
, const char* szMask
) -> bool
{ for (; *szMask
; ++szMask
, ++pData
, ++bMask
) if (*szMask
== 'x' && *pData
!= *bMask
) return 0; return (*szMask
) == 0; }; for (DWORD i
= 0; i
< dwLen
; ++i
) if (bCompare
(reinterpret_cast
<std
::uint8_t*>(dwAddress
+ i
), bMask
, szMask
)) return static_cast
<DWORD
>(dwAddress
+ i
); return 0;}template
<typename T
, typename U
>void DetourFunction
(T
&OriginalFunction
, U HookFunction
){ DetourTransactionBegin
(); DetourUpdateThread
(GetCurrentThread
()); DetourAttach
(&reinterpret_cast
<void*&>(OriginalFunction
), reinterpret_cast
<void*>(HookFunction
)); DetourTransactionCommit
(); DetourTransactionBegin
(); DetourUpdateThread
(GetCurrentThread
());}DWORD WINAPI VTableRepatch
(void* param
){ while (true) { std
::this_thread::sleep_for(std
::chrono::milliseconds(100)); DetourFunction
(o_BeginScene
, DXI_BeginScene
); DetourFunction
(o_EndScene
, DXI_EndScene
); DetourFunction
(o_Reset
, DXI_Reset
); DetourFunction
(o_DrawPrimitive
, DXI_DrawPrimitive
); DetourFunction
(o_DrawIndexedPrimitive
, DXI_DrawIndexedPrimitive
); DetourFunction
(o_DrawPrimitiveUP
, DXI_DrawPrimitiveUP
); DetourFunction
(o_DrawIndexedPrimitiveUP
, DXI_DrawIndexedPrimitiveUP
); DetourFunction
(o_SetTexture
, DXI_SetTexture
); } return 0;}DWORD __stdcall InitialiseHooks
(void* param
){ while (!GetModuleHandle
("d3d9.dll")) { std
::this_thread::sleep_for(std
::chrono::milliseconds(100)); } DWORD
* VTable
= nullptr
; std
::this_thread::sleep_for(std
::chrono::milliseconds(100)); static std
::uint8_t bMask
[] = { 0xC7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x86, 0x00, 0x00, 0x00, 0x00, 0x89, 0x86 }; DWORD Address
= FindPattern
(reinterpret_cast
<DWORD
>(GetModuleHandle
("d3d9.dll")), 0x128000, bMask
, "xx????xx????xx"); memcpy(&VTable
, reinterpret_cast
<void*>(Address
+ 2), 4); o_BeginScene
= reinterpret_cast
<BeginScene_t
>(VTable
[BEGINSCENE
]); o_EndScene
= reinterpret_cast
<EndScene_t
>(VTable
[ENDSCENE
]); o_Reset
= reinterpret_cast
<Reset_t
>(VTable
[RESET
]); o_DrawPrimitive
= reinterpret_cast
<DrawPrimitive_t
>(VTable
[DRAWPRIMITIVE
]); o_DrawIndexedPrimitive
= reinterpret_cast
<DrawIndexedPrimitive_t
>(VTable
[DRAWINDEXEDPRIMITIVE
]); o_DrawPrimitiveUP
= reinterpret_cast
<DrawPrimitiveUP_t
>(VTable
[DRAWPRIMITIVEUP
]); o_DrawIndexedPrimitiveUP
= reinterpret_cast
<DrawIndexedPrimitiveUP_t
>(VTable
[DRAWINDEXEDPRIMITIVEUP
]); o_SetTexture
= reinterpret_cast
<SetTexture_t
>(VTable
[SETTEXTURE
]); DetourFunction
(o_BeginScene
, DXI_BeginScene
); DetourFunction
(o_EndScene
, DXI_EndScene
); DetourFunction
(o_Reset
, DXI_Reset
); DetourFunction
(o_DrawPrimitive
, DXI_DrawPrimitive
); DetourFunction
(o_DrawIndexedPrimitive
, DXI_DrawIndexedPrimitive
); DetourFunction
(o_DrawPrimitiveUP
, DXI_DrawPrimitiveUP
); DetourFunction
(o_DrawIndexedPrimitiveUP
, DXI_DrawIndexedPrimitiveUP
); DetourFunction
(o_SetTexture
, DXI_SetTexture
); CreateThread
(NULL
, 0, VTableRepatch
, NULL
, 0, 0); return 0;}
ASM Code:
// Parameters:
//
// float4 DistanceFogPlane;
// float4 HeightFogPlane;
// float4x2 TexCoordMatrix;
// float4x4 WVPMatrix;
//
//
// Registers:
//
// Name Reg Size
// ---------------- ----- ----
// WVPMatrix c0 4
// TexCoordMatrix c4 2
// DistanceFogPlane c6 1
// HeightFogPlane c7 1
//
vs_2_0
def c8, 0, 1, 0, 0
dcl_position v0
dcl_texcoord v1
dcl_color v2
dp4 oPos.x, v0, c0
dp4 oPos.y, v0, c1
dp4 oPos.z, v0, c2
dp4 oPos.w, v0, c3
dp4 oT0.x, v1, c4
dp4 oT0.y, v1, c5
dp4 r0.x, v0, c7
max r0.x, r0.x, c8.x
min oT4.x, r0.x, c8.y
dp4 r0.x, v0, c6
max r0.x, r0.x, c8.x
min oT4.y, r0.x, c8.y
mov oD0, v2
mov oT0.zw, c8.x
mov oT1.xyz, c8.x
mov oT2.xyz, c8.y
mov oT3.xyz, c8.x
mov oT5, c8.x
mov oT6.xyz, c8.x
mov oT7, c8.x
// approximately 20 instruction slots used
// Parameters:
//
// sampler2D SpriteSampler;
//
//
// Registers:
//
// Name Reg Size
// ------------- ----- ----
// SpriteSampler s0 1
//
ps_2_0
dcl t0.xy
dcl v0
dcl_2d s0
texld r0, t0, s0
mul r0, r0, v0
mov oC0, r0
// approximately 3 instruction slots used (1 texture, 2 arithmetic)
// Parameters:
//
// sampler2D DiffuseSampler;
// float3 DistanceFogColour;
// float3 HeightFogColour;
//
//
// Registers:
//
// Name Reg Size
// ----------------- ----- ----
// DistanceFogColour c0 1
// HeightFogColour c1 1
// DiffuseSampler s0 1
//
ps_2_0
def c2, 0, 0, 0, 0
dcl v0
dcl t0.xy
dcl t2.xyz
dcl t4.xy
dcl_2d s0
texld r0, t0, s0
mul r0.xyz, r0, v0
mul r1.xyz, r0, t2
mad r0.xyz, r0, -t2, c1
mov r1.w, v0.w
mov r0.w, c2.x
mad r0, t4.x, r0, r1
add r1.xyz, -r0, c0
mov r1.w, c2.x
mad r0, t4.y, r1, r0
mov oC0, r0
// approximately 11 instruction slots used (1 texture, 10 arithmetic)
//...
vs_2_0
dcl_position v0
dcl_texcoord v1
dcl_color v2
mov oPos, v0
mov oT0.xy, v1
mov oD0, v2
// approximately 3 instruction slots used
// Parameters:
//
// float4x2 TexCoordMatrix;
// float4x4 WVPMatrix;
//
//
// Registers:
//
// Name Reg Size
// -------------- ----- ----
// WVPMatrix c0 4
// TexCoordMatrix c4 2
//
vs_2_0
def c6, 0, 0, 0, 0
dcl_position v0
dcl_color v1
dcl_texcoord v2
dp4 oPos.x, v0, c0
dp4 oPos.y, v0, c1
dp4 oPos.z, v0, c2
dp4 oPos.w, v0, c3
dp4 oT0.x, v2, c4
dp4 oT0.y, v2, c5
mov oD0, v1
mov oT1.x, c6.x
// approximately 8 instruction slots used