跳转至

为 Reset() 编写钩子

在生产中使用 Direct3D 钩子时,你会做各种任务,比如绘制自定义文本、显示与机器人相关的图像,以及与游戏中的函数调用交互。这些任务要求你创建绑定到游戏设备的自有 Direct3D 对象,这可能是个问题。游戏有时会通过 Reset() 函数完全重置设备。设备重置时,你需要用它们的 OnLostDevice()成员函数更新你为设备创建的任何对象(最常见的是字体和精灵)。

由于 Reset() 从设备的 VF 表调用,你可以用它的钩子告诉你设备何时被重置。Reset() 接受两个参数,位于 VF 表索引 16。你可以把这段代码添加到清单 8-14 的 placeHooks() 中,钩住 Reset() 函数:

auto ret = hookVF((DWORD)discoveredDevice, 16, 
(DWORD)&myReset);
if (ret != (DWORD)&myReset)
    origReset = (_reset)ret;

这是用于 origReset 的声明:

typedef HRESULT (WINAPI* _reset)(
    LPDIRECT3DDEVICE9 pDevice,
    D3DPRESENT_PARAMETERS* pPresentationParameters);
_reset origReset = NULL;

重置成功时,原始函数返回 D3D_OK。你的钩子函数识别这一点,并相应调用 OnLostDevice():

HRESULT WINAPI myReset(
    LPDIRECT3DDEVICE9 pDevice,
    D3DPRESENT_PARAMETERS* pPresentationParameters)
{
    auto result = origReset(pDevice, 
pPresentationParameters);
    if (result == D3D_OK) {
        // 为你所有的对象调用 onLostDevice()
    }
    return result;
}

一旦你填好 if() 语句的内容,你所有的对象就都可以再次使用了。