为 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() 语句的内容,你所有的对象就都可以再次使用了。