| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917 |
- #define _CRT_SECURE_NO_WARNINGS
- #include <d3d9.h>
- #include <d3d11.h>
- #include <dxgi.h>
- #include "graphics-hook.h"
- #include "../funchook.h"
- #include "d3d9-patches.hpp"
- typedef HRESULT (STDMETHODCALLTYPE *present_t)(IDirect3DDevice9*,
- CONST RECT*, CONST RECT*, HWND, CONST RGNDATA*);
- typedef HRESULT (STDMETHODCALLTYPE *present_ex_t)(IDirect3DDevice9*,
- CONST RECT*, CONST RECT*, HWND, CONST RGNDATA*, DWORD);
- typedef HRESULT (STDMETHODCALLTYPE *present_swap_t)(IDirect3DSwapChain9*,
- CONST RECT*, CONST RECT*, HWND, CONST RGNDATA*, DWORD);
- typedef HRESULT (STDMETHODCALLTYPE *reset_t)(IDirect3DDevice9*,
- D3DPRESENT_PARAMETERS*);
- typedef HRESULT (STDMETHODCALLTYPE *reset_ex_t)(IDirect3DDevice9*,
- D3DPRESENT_PARAMETERS*, D3DDISPLAYMODEEX*);
- typedef HRESULT (WINAPI *createfactory1_t)(REFIID, void **);
- static struct func_hook present;
- static struct func_hook present_ex;
- static struct func_hook present_swap;
- static struct func_hook reset;
- static struct func_hook reset_ex;
- struct d3d9_data {
- HMODULE d3d9;
- IDirect3DDevice9 *device; /* do not release */
- uint32_t cx;
- uint32_t cy;
- D3DFORMAT d3d9_format;
- DXGI_FORMAT dxgi_format;
- bool using_shtex : 1;
- bool using_scale : 1;
- union {
- /* shared texture */
- struct {
- IDirect3DSurface9 *d3d9_copytex;
- ID3D11Device *d3d11_device;
- ID3D11DeviceContext *d3d11_context;
- ID3D11Resource *d3d11_tex;
- struct shtex_data *shtex_info;
- HANDLE handle;
- int patch;
- };
- /* shared memory */
- struct {
- IDirect3DSurface9 *copy_surfaces[NUM_BUFFERS];
- IDirect3DSurface9 *render_targets[NUM_BUFFERS];
- IDirect3DQuery9 *queries[NUM_BUFFERS];
- struct shmem_data *shmem_info;
- volatile bool issued_queries[NUM_BUFFERS];
- bool texture_mapped[NUM_BUFFERS];
- uint32_t pitch;
- int cur_tex;
- int copy_wait;
- };
- };
- };
- static struct d3d9_data data = {};
- static void d3d9_free()
- {
- capture_free();
- if (data.using_shtex) {
- if (data.d3d11_tex)
- data.d3d11_tex->Release();
- if (data.d3d11_context)
- data.d3d11_context->Release();
- if (data.d3d11_device)
- data.d3d11_device->Release();
- if (data.d3d9_copytex)
- data.d3d9_copytex->Release();
- } else {
- for (size_t i = 0; i < NUM_BUFFERS; i++) {
- if (data.copy_surfaces[i]) {
- if (data.texture_mapped[i])
- data.copy_surfaces[i]->UnlockRect();
- data.copy_surfaces[i]->Release();
- }
- if (data.render_targets[i])
- data.render_targets[i]->Release();
- if (data.queries[i])
- data.queries[i]->Release();
- }
- }
- memset(&data, 0, sizeof(data));
- hlog("----------------- d3d9 capture freed -----------------");
- }
- static DXGI_FORMAT d3d9_to_dxgi_format(D3DFORMAT format)
- {
- switch ((unsigned long)format) {
- case D3DFMT_A2B10G10R10: return DXGI_FORMAT_R10G10B10A2_UNORM;
- case D3DFMT_A8R8G8B8: return DXGI_FORMAT_B8G8R8A8_UNORM;
- case D3DFMT_X8R8G8B8: return DXGI_FORMAT_B8G8R8X8_UNORM;
- }
- return DXGI_FORMAT_UNKNOWN;
- }
- const static D3D_FEATURE_LEVEL feature_levels[] =
- {
- D3D_FEATURE_LEVEL_11_0,
- D3D_FEATURE_LEVEL_10_1,
- D3D_FEATURE_LEVEL_10_0,
- D3D_FEATURE_LEVEL_9_3,
- };
- static inline bool shex_init_d3d11()
- {
- PFN_D3D11_CREATE_DEVICE create_device;
- createfactory1_t create_factory;
- D3D_FEATURE_LEVEL level_used;
- IDXGIFactory *factory;
- IDXGIAdapter *adapter;
- HMODULE d3d11;
- HMODULE dxgi;
- HRESULT hr;
- d3d11 = load_system_library("d3d11.dll");
- if (!d3d11) {
- hlog("d3d9_init: Failed to load D3D11");
- return false;
- }
- dxgi = load_system_library("dxgi.dll");
- if (!dxgi) {
- hlog("d3d9_init: Failed to load DXGI");
- return false;
- }
- create_factory = (createfactory1_t)GetProcAddress(dxgi,
- "CreateDXGIFactory1");
- if (!create_factory) {
- hlog("d3d9_init: Failed to get CreateDXGIFactory1 address");
- return false;
- }
- create_device = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(d3d11,
- "D3D11CreateDevice");
- if (!create_device) {
- hlog("d3d9_init: Failed to get D3D11CreateDevice address");
- return false;
- }
- hr = create_factory(__uuidof(IDXGIFactory1), (void**)&factory);
- if (FAILED(hr)) {
- hlog_hr("d3d9_init: Failed to create factory object", hr);
- return false;
- }
- hr = factory->EnumAdapters(0, &adapter);
- factory->Release();
- if (FAILED(hr)) {
- hlog_hr("d3d9_init: Failed to get adapter", hr);
- return false;
- }
- hr = create_device(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
- 0, feature_levels,
- sizeof(feature_levels) / sizeof(D3D_FEATURE_LEVEL),
- D3D11_SDK_VERSION, &data.d3d11_device, &level_used,
- &data.d3d11_context);
- adapter->Release();
- if (FAILED(hr)) {
- hlog_hr("d3d9_init: Failed to create D3D11 device", hr);
- return false;
- }
- return true;
- }
- static inline bool d3d9_shtex_init_shtex()
- {
- IDXGIResource *res;
- HRESULT hr;
- D3D11_TEXTURE2D_DESC desc = {};
- desc.Width = data.cx;
- desc.Height = data.cy;
- desc.Format = data.dxgi_format;
- desc.MipLevels = 1;
- desc.ArraySize = 1;
- desc.SampleDesc.Count = 1;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
- desc.BindFlags = D3D11_BIND_RENDER_TARGET |
- D3D11_BIND_SHADER_RESOURCE;
- hr = data.d3d11_device->CreateTexture2D(&desc, nullptr,
- (ID3D11Texture2D**)&data.d3d11_tex);
- if (FAILED(hr)) {
- hlog_hr("d3d9_shtex_init_shtex: Failed to create D3D11 texture",
- hr);
- return false;
- }
- hr = data.d3d11_tex->QueryInterface(__uuidof(IDXGIResource),
- (void**)&res);
- if (FAILED(hr)) {
- hlog_hr("d3d9_shtex_init_shtex: Failed to query IDXGIResource",
- hr);
- return false;
- }
- hr = res->GetSharedHandle(&data.handle);
- res->Release();
- if (FAILED(hr)) {
- hlog_hr("d3d9_shtex_init_shtex: Failed to get shared handle",
- hr);
- return false;
- }
- return true;
- }
- static inline bool d3d9_shtex_init_copytex()
- {
- uint8_t *patch_addr = get_d3d9_patch_addr(data.d3d9, data.patch);
- uint8_t saved_data[MAX_PATCH_SIZE];
- size_t patch_size = 0;
- IDirect3DTexture9 *tex;
- DWORD protect_val;
- HRESULT hr;
- if (patch_addr) {
- patch_size = patch[data.patch].size;
- VirtualProtect(patch_addr, patch_size, PAGE_EXECUTE_READWRITE,
- &protect_val);
- memcpy(saved_data, patch_addr, patch_size);
- memcpy(patch_addr, patch[data.patch].data, patch_size);
- }
- hr = data.device->CreateTexture(data.cx, data.cy, 1,
- D3DUSAGE_RENDERTARGET, data.d3d9_format,
- D3DPOOL_DEFAULT, &tex, &data.handle);
- if (patch_addr && patch_size) {
- memcpy(patch_addr, saved_data, patch_size);
- VirtualProtect(patch_addr, patch_size, protect_val,
- &protect_val);
- }
- if (FAILED(hr)) {
- hlog_hr("d3d9_shtex_init_copytex: Failed to create shared texture",
- hr);
- return false;
- }
- hr = tex->GetSurfaceLevel(0, &data.d3d9_copytex);
- tex->Release();
- if (FAILED(hr)) {
- hlog_hr("d3d9_shtex_init_copytex: Failed to get surface level", hr);
- return false;
- }
- return true;
- }
- static bool d3d9_shtex_init(uint32_t cx, uint32_t cy, HWND window)
- {
- data.using_shtex = true;
- if (!shex_init_d3d11()) {
- return false;
- }
- if (!d3d9_shtex_init_shtex()) {
- return false;
- }
- if (!d3d9_shtex_init_copytex()) {
- return false;
- }
- if (!capture_init_shtex(&data.shtex_info, window, cx, cy,
- data.cx, data.cy, data.dxgi_format, false,
- (uintptr_t)data.handle)) {
- return false;
- }
- hlog("d3d9 shared texture capture successful");
- return true;
- }
- static bool d3d9_shmem_init_buffers(size_t buffer)
- {
- HRESULT hr;
- hr = data.device->CreateOffscreenPlainSurface(data.cx, data.cy,
- data.d3d9_format, D3DPOOL_SYSTEMMEM,
- &data.copy_surfaces[buffer], nullptr);
- if (FAILED(hr)) {
- hlog_hr("d3d9_shmem_init_buffers: Failed to create surface",
- hr);
- return false;
- }
- if (buffer == 0) {
- D3DLOCKED_RECT rect;
- hr = data.copy_surfaces[buffer]->LockRect(&rect, nullptr,
- D3DLOCK_READONLY);
- if (FAILED(hr)) {
- hlog_hr("d3d9_shmem_init_buffers: Failed to lock "
- "buffer", hr);
- return false;
- }
- data.pitch = rect.Pitch;
- data.copy_surfaces[buffer]->UnlockRect();
- }
- hr = data.device->CreateRenderTarget(data.cx, data.cy,
- data.d3d9_format, D3DMULTISAMPLE_NONE, 0, false,
- &data.render_targets[buffer], nullptr);
- if (FAILED(hr)) {
- hlog_hr("d3d9_shmem_init_buffers: Failed to create render "
- "target", hr);
- return false;
- }
- hr = data.device->CreateQuery(D3DQUERYTYPE_EVENT,
- &data.queries[buffer]);
- if (FAILED(hr)) {
- hlog_hr("d3d9_shmem_init_buffers: Failed to create query", hr);
- return false;
- }
- return true;
- }
- static bool d3d9_shmem_init(uint32_t cx, uint32_t cy, HWND window)
- {
- data.using_shtex = false;
- for (size_t i = 0; i < NUM_BUFFERS; i++) {
- if (!d3d9_shmem_init_buffers(i)) {
- return false;
- }
- }
- if (!capture_init_shmem(&data.shmem_info, window, cx, cy,
- data.cx, data.cy, data.pitch, data.dxgi_format,
- false)) {
- return false;
- }
- hlog("d3d9 memory capture successful");
- return true;
- }
- static bool d3d9_get_swap_desc(D3DPRESENT_PARAMETERS &pp)
- {
- IDirect3DSwapChain9 *swap = nullptr;
- HRESULT hr;
- hr = data.device->GetSwapChain(0, &swap);
- if (FAILED(hr)) {
- hlog_hr("d3d9_get_swap_desc: Failed to get swap chain", hr);
- return false;
- }
- hr = swap->GetPresentParameters(&pp);
- swap->Release();
- if (FAILED(hr)) {
- hlog_hr("d3d9_get_swap_desc: Failed to get "
- "presentation parameters", hr);
- return false;
- }
- return true;
- }
- static bool d3d9_init_format_backbuffer(uint32_t &cx, uint32_t &cy,
- HWND &window)
- {
- IDirect3DSurface9 *back_buffer = nullptr;
- D3DPRESENT_PARAMETERS pp;
- D3DSURFACE_DESC desc;
- HRESULT hr;
- if (!d3d9_get_swap_desc(pp)) {
- return false;
- }
- hr = data.device->GetRenderTarget(0, &back_buffer);
- if (FAILED(hr)) {
- return false;
- }
- hr = back_buffer->GetDesc(&desc);
- back_buffer->Release();
- if (FAILED(hr)) {
- hlog_hr("d3d9_init_format_backbuffer: Failed to get "
- "backbuffer descriptor", hr);
- return false;
- }
- data.d3d9_format = desc.Format;
- data.dxgi_format = d3d9_to_dxgi_format(desc.Format);
- data.using_scale = global_hook_info->use_scale;
- window = pp.hDeviceWindow;
- cx = desc.Width;
- cy = desc.Height;
- if (data.using_scale) {
- data.cx = global_hook_info->cx;
- data.cy = global_hook_info->cy;
- } else {
- data.cx = desc.Width;
- data.cy = desc.Height;
- }
- return true;
- }
- static bool d3d9_init_format_swapchain(uint32_t &cx, uint32_t &cy, HWND &window)
- {
- D3DPRESENT_PARAMETERS pp;
- if (!d3d9_get_swap_desc(pp)) {
- return false;
- }
- data.dxgi_format = d3d9_to_dxgi_format(pp.BackBufferFormat);
- data.d3d9_format = pp.BackBufferFormat;
- data.using_scale = global_hook_info->use_scale;
- window = pp.hDeviceWindow;
- cx = pp.BackBufferWidth;
- cy = pp.BackBufferHeight;
- if (data.using_scale) {
- data.cx = global_hook_info->cx;
- data.cy = global_hook_info->cy;
- } else {
- data.cx = pp.BackBufferWidth;
- data.cy = pp.BackBufferHeight;
- }
- return true;
- }
- static void d3d9_init(IDirect3DDevice9 *device)
- {
- IDirect3DDevice9Ex *d3d9ex = nullptr;
- bool success;
- uint32_t cx = 0;
- uint32_t cy = 0;
- HWND window = nullptr;
- HRESULT hr;
- data.d3d9 = get_system_module("d3d9.dll");
- data.device = device;
- hr = device->QueryInterface(__uuidof(IDirect3DDevice9Ex),
- (void**)&d3d9ex);
- if (SUCCEEDED(hr)) {
- d3d9ex->Release();
- data.patch = -1;
- } else {
- data.patch = get_d3d9_patch(data.d3d9);
- }
- if (!d3d9_init_format_backbuffer(cx, cy, window)) {
- if (!d3d9_init_format_swapchain(cx, cy, window)) {
- return;
- }
- }
- if (global_hook_info->force_shmem || (!d3d9ex && data.patch == -1)) {
- success = d3d9_shmem_init(cx, cy, window);
- } else {
- success = d3d9_shtex_init(cx, cy, window);
- }
- if (!success)
- d3d9_free();
- }
- static inline HRESULT get_backbuffer(IDirect3DDevice9 *device,
- IDirect3DSurface9 **surface)
- {
- static bool use_backbuffer = false;
- static bool checked_exceptions = false;
- if (!checked_exceptions) {
- if (_strcmpi(get_process_name(), "hotd_ng.exe") == 0)
- use_backbuffer = true;
- checked_exceptions = true;
- }
- if (use_backbuffer) {
- return device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
- surface);
- } else {
- return device->GetRenderTarget(0, surface);
- }
- }
- static inline void d3d9_shtex_capture(IDirect3DSurface9 *backbuffer)
- {
- D3DTEXTUREFILTERTYPE filter;
- HRESULT hr;
- filter = data.using_scale ? D3DTEXF_LINEAR : D3DTEXF_NONE;
- hr = data.device->StretchRect(backbuffer, nullptr, data.d3d9_copytex,
- nullptr, filter);
- if (FAILED(hr))
- hlog_hr("d3d9_shtex_capture: StretchRect failed", hr);
- }
- static inline void d3d9_shmem_capture_queue_copy()
- {
- for (int i = 0; i < NUM_BUFFERS; i++) {
- IDirect3DSurface9 *target = data.copy_surfaces[i];
- D3DLOCKED_RECT rect;
- HRESULT hr;
- if (!data.issued_queries[i]) {
- continue;
- }
- if (data.queries[i]->GetData(0, 0, 0) != S_OK) {
- continue;
- }
- data.issued_queries[i] = false;
- hr = target->LockRect(&rect, nullptr, D3DLOCK_READONLY);
- if (SUCCEEDED(hr)) {
- data.texture_mapped[i] = true;
- shmem_copy_data(i, rect.pBits);
- }
- break;
- }
- }
- static inline void d3d9_shmem_capture(IDirect3DSurface9 *backbuffer)
- {
- D3DTEXTUREFILTERTYPE filter;
- IDirect3DSurface9 *copy;
- int next_tex;
- HRESULT hr;
- d3d9_shmem_capture_queue_copy();
- next_tex = (data.cur_tex == NUM_BUFFERS - 1) ? 0 : data.cur_tex + 1;
- filter = data.using_scale ? D3DTEXF_LINEAR : D3DTEXF_NONE;
- copy = data.render_targets[data.cur_tex];
- hr = data.device->StretchRect(backbuffer, nullptr, copy, nullptr,
- filter);
- if (FAILED(hr)) {
- hlog_hr("d3d9_shmem_capture: StretchRect failed", hr);
- return;
- }
- if (data.copy_wait < NUM_BUFFERS - 1) {
- data.copy_wait++;
- } else {
- IDirect3DSurface9 *src = data.render_targets[next_tex];
- IDirect3DSurface9 *dst = data.copy_surfaces[next_tex];
- if (shmem_texture_data_lock(next_tex)) {
- dst->UnlockRect();
- data.texture_mapped[next_tex] = false;
- shmem_texture_data_unlock(next_tex);
- }
- hr = data.device->GetRenderTargetData(src, dst);
- if (FAILED(hr)) {
- hlog_hr("d3d9_shmem_capture: GetRenderTargetData "
- "failed", hr);
- }
- data.queries[next_tex]->Issue(D3DISSUE_END);
- data.issued_queries[next_tex] = true;
- }
- data.cur_tex = next_tex;
- }
- static void d3d9_capture(IDirect3DDevice9 *device,
- IDirect3DSurface9 *backbuffer)
- {
- if (capture_should_stop()) {
- d3d9_free();
- }
- if (capture_should_init()) {
- d3d9_init(device);
- }
- if (capture_ready()) {
- if (data.using_shtex)
- d3d9_shtex_capture(backbuffer);
- else
- d3d9_shmem_capture(backbuffer);
- }
- }
- /* this is used just in case Present calls PresentEx or vise versa. */
- static int present_recurse = 0;
- static inline void present_begin(IDirect3DDevice9 *device,
- IDirect3DSurface9 *&backbuffer)
- {
- HRESULT hr;
- if (!present_recurse) {
- hr = get_backbuffer(device, &backbuffer);
- if (FAILED(hr)) {
- hlog_hr("d3d9_shmem_capture: Failed to get "
- "backbuffer", hr);
- }
- if (!global_hook_info->capture_overlay) {
- d3d9_capture(device, backbuffer);
- }
- }
- present_recurse++;
- }
- static inline void present_end(IDirect3DDevice9 *device,
- IDirect3DSurface9 *backbuffer)
- {
- present_recurse--;
- if (!present_recurse) {
- if (global_hook_info->capture_overlay) {
- if (!present_recurse)
- d3d9_capture(device, backbuffer);
- }
- if (backbuffer)
- backbuffer->Release();
- }
- }
- static bool hooked_reset = false;
- static void setup_reset_hooks(IDirect3DDevice9 *device);
- static HRESULT STDMETHODCALLTYPE hook_present(IDirect3DDevice9 *device,
- CONST RECT *src_rect, CONST RECT *dst_rect,
- HWND override_window, CONST RGNDATA *dirty_region)
- {
- IDirect3DSurface9 *backbuffer = nullptr;
- HRESULT hr;
- if (!hooked_reset)
- setup_reset_hooks(device);
- present_begin(device, backbuffer);
- unhook(&present);
- present_t call = (present_t)present.call_addr;
- hr = call(device, src_rect, dst_rect, override_window, dirty_region);
- rehook(&present);
- present_end(device, backbuffer);
- return hr;
- }
- static HRESULT STDMETHODCALLTYPE hook_present_ex(IDirect3DDevice9 *device,
- CONST RECT *src_rect, CONST RECT *dst_rect,
- HWND override_window, CONST RGNDATA *dirty_region, DWORD flags)
- {
- IDirect3DSurface9 *backbuffer = nullptr;
- HRESULT hr;
- if (!hooked_reset)
- setup_reset_hooks(device);
- present_begin(device, backbuffer);
- unhook(&present_ex);
- present_ex_t call = (present_ex_t)present_ex.call_addr;
- hr = call(device, src_rect, dst_rect, override_window, dirty_region,
- flags);
- rehook(&present_ex);
- present_end(device, backbuffer);
- return hr;
- }
- static HRESULT STDMETHODCALLTYPE hook_present_swap(IDirect3DSwapChain9 *swap,
- CONST RECT *src_rect, CONST RECT *dst_rect,
- HWND override_window, CONST RGNDATA *dirty_region, DWORD flags)
- {
- IDirect3DSurface9 *backbuffer = nullptr;
- IDirect3DDevice9 *device = nullptr;
- HRESULT hr;
- if (!present_recurse) {
- hr = swap->GetDevice(&device);
- if (SUCCEEDED(hr)) {
- device->Release();
- }
- }
- if (device) {
- if (!hooked_reset)
- setup_reset_hooks(device);
- present_begin(device, backbuffer);
- }
- unhook(&present_swap);
- present_swap_t call = (present_swap_t)present_swap.call_addr;
- hr = call(swap, src_rect, dst_rect, override_window, dirty_region,
- flags);
- rehook(&present_swap);
- if (device)
- present_end(device, backbuffer);
- return hr;
- }
- static HRESULT STDMETHODCALLTYPE hook_reset(IDirect3DDevice9 *device,
- D3DPRESENT_PARAMETERS *params)
- {
- HRESULT hr;
- if (capture_active())
- d3d9_free();
- unhook(&reset);
- reset_t call = (reset_t)reset.call_addr;
- hr = call(device, params);
- rehook(&reset);
- return hr;
- }
- static HRESULT STDMETHODCALLTYPE hook_reset_ex(IDirect3DDevice9 *device,
- D3DPRESENT_PARAMETERS *params, D3DDISPLAYMODEEX *dmex)
- {
- HRESULT hr;
- if (capture_active())
- d3d9_free();
- unhook(&reset_ex);
- reset_ex_t call = (reset_ex_t)reset_ex.call_addr;
- hr = call(device, params, dmex);
- rehook(&reset_ex);
- return hr;
- }
- static void setup_reset_hooks(IDirect3DDevice9 *device)
- {
- IDirect3DDevice9Ex *d3d9ex = nullptr;
- uintptr_t *vtable = *(uintptr_t**)device;
- HRESULT hr;
- hook_init(&reset, (void*)vtable[16], (void*)hook_reset,
- "IDirect3DDevice9::Reset");
- rehook(&reset);
- hr = device->QueryInterface(__uuidof(IDirect3DDevice9Ex),
- (void**)&d3d9ex);
- if (SUCCEEDED(hr)) {
- hook_init(&reset_ex, (void*)vtable[132], (void*)hook_reset_ex,
- "IDirect3DDevice9Ex::ResetEx");
- rehook(&reset_ex);
- d3d9ex->Release();
- }
- hooked_reset = true;
- }
- typedef HRESULT (WINAPI *d3d9create_ex_t)(UINT, IDirect3D9Ex**);
- static bool manually_get_d3d9_addrs(HMODULE d3d9_module,
- void **present_addr,
- void **present_ex_addr,
- void **present_swap_addr)
- {
- d3d9create_ex_t create_ex;
- D3DPRESENT_PARAMETERS pp;
- HRESULT hr;
- IDirect3DDevice9Ex *device;
- IDirect3D9Ex *d3d9ex;
- hlog("D3D9 values invalid, manually obtaining");
- create_ex = (d3d9create_ex_t)GetProcAddress(d3d9_module,
- "Direct3DCreate9Ex");
- if (!create_ex) {
- hlog("Failed to load Direct3DCreate9Ex");
- return false;
- }
- if (FAILED(create_ex(D3D_SDK_VERSION, &d3d9ex))) {
- hlog("Failed to create D3D9 context");
- return false;
- }
- memset(&pp, 0, sizeof(pp));
- pp.Windowed = 1;
- pp.SwapEffect = D3DSWAPEFFECT_FLIP;
- pp.BackBufferFormat = D3DFMT_A8R8G8B8;
- pp.BackBufferCount = 1;
- pp.hDeviceWindow = (HWND)dummy_window;
- pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
- hr = d3d9ex->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
- dummy_window,
- D3DCREATE_HARDWARE_VERTEXPROCESSING |
- D3DCREATE_NOWINDOWCHANGES, &pp, NULL, &device);
- d3d9ex->Release();
- if (SUCCEEDED(hr)) {
- uintptr_t *vtable = *(uintptr_t**)device;
- IDirect3DSwapChain9 *swap;
- *present_addr = (void*)vtable[17];
- *present_ex_addr = (void*)vtable[121];
- hr = device->GetSwapChain(0, &swap);
- if (SUCCEEDED(hr)) {
- vtable = *(uintptr_t**)swap;
- *present_swap_addr = (void*)vtable[3];
- swap->Release();
- }
- device->Release();
- } else {
- hlog("Failed to create D3D9 device");
- return false;
- }
- return true;
- }
- bool hook_d3d9(void)
- {
- HMODULE d3d9_module = get_system_module("d3d9.dll");
- uint32_t d3d9_size;
- void *present_addr = nullptr;
- void *present_ex_addr = nullptr;
- void *present_swap_addr = nullptr;
- if (!d3d9_module) {
- return false;
- }
- d3d9_size = module_size(d3d9_module);
- if (global_hook_info->offsets.d3d9.present < d3d9_size &&
- global_hook_info->offsets.d3d9.present_ex < d3d9_size &&
- global_hook_info->offsets.d3d9.present_swap < d3d9_size) {
- present_addr = get_offset_addr(d3d9_module,
- global_hook_info->offsets.d3d9.present);
- present_ex_addr = get_offset_addr(d3d9_module,
- global_hook_info->offsets.d3d9.present_ex);
- present_swap_addr = get_offset_addr(d3d9_module,
- global_hook_info->offsets.d3d9.present_swap);
- } else {
- if (!dummy_window) {
- return false;
- }
- if (!manually_get_d3d9_addrs(d3d9_module,
- &present_addr,
- &present_ex_addr,
- &present_swap_addr)) {
- hlog("Failed to get D3D9 values");
- return true;
- }
- }
- if (!present_addr && !present_ex_addr && !present_swap_addr) {
- hlog("Invalid D3D9 values");
- return true;
- }
- if (present_swap_addr) {
- hook_init(&present_swap, present_swap_addr,
- (void*)hook_present_swap,
- "IDirect3DSwapChain9::Present");
- rehook(&present_swap);
- }
- if (present_ex_addr) {
- hook_init(&present_ex, present_ex_addr,
- (void*)hook_present_ex,
- "IDirect3DDevice9Ex::PresentEx");
- rehook(&present_ex);
- }
- if (present_addr) {
- hook_init(&present, present_addr,
- (void*)hook_present,
- "IDirect3DDevice9::Present");
- rehook(&present);
- }
- hlog("Hooked D3D9");
- return true;
- }
|