東方紅魔郷
東方紅魔郷では、以後の作品のように、低速移動の際に当たり判定を示すマーカーを表示することができません。
そこで、DirectXをフックすることで、マーカーの表示を実現してみます*1。
DirectXのフック
ここでは、偽のd3dx8.dllを東方紅魔郷.exeと同じディレクトリから読み込ませ、IAT*2を書き換えることで、自作関数を呼び出すというアプローチをとります。
以下をフックします。
- IDirect3DDevice8
- IDirect3D8
それぞれをどう置き換えるか示します。なお、呼び出し規約にしたがって__stdcallを付けておく必要があります。これがないとフリーズしてしまいました。
IDirect3DDevice8
myIDirect3DDevice8::myIDirect3DDevice8(IDirect3DDevice8* pOriginal)
{
m_pIDirect3DDevice8 = pOriginal; // ポインタを保存
draw = false;
hit_marker_texture = NULL;
focused_time = 255;
count = 0;
frame_count = 0;
}
クラスも用意しておきます。
class myIDirect3DDevice8 : public IDirect3DDevice8
{
private:
IDirect3DTexture8* hitbox_texture;
unsigned int count;
int focused_time;
bool draw;
unsigned int frame_count;
IDirect3DDevice8 *m_pIDirect3DDevice8;
public:myIDirect3DDevice8(IDirect3DDevice8* pOriginal);
virtual ~myIDirect3DDevice8();HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj);
ULONG __stdcall AddRef(void);
ULONG __stdcall Release(void);
HRESULT __stdcall TestCooperativeLevel(void);
UINT __stdcall GetAvailableTextureMem(void);
HRESULT __stdcall ResourceManagerDiscardBytes(DWORD Bytes);
HRESULT __stdcall GetDirect3D(IDirect3D8** ppD3D8);
HRESULT __stdcall GetDeviceCaps(D3DCAPS8* pCaps);
HRESULT __stdcall GetDisplayMode(D3DDISPLAYMODE* pMode);
HRESULT __stdcall GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *pParameters);
HRESULT __stdcall SetCursorProperties(UINT XHotSpot,UINT YHotSpot,IDirect3DSurface8* pCursorBitmap);
void __stdcall SetCursorPosition(UINT XScreenSpace,UINT YScreenSpace,DWORD Flags);
BOOL __stdcall ShowCursor(BOOL bShow);
HRESULT __stdcall CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DSwapChain8** pSwapChain);
HRESULT __stdcall Reset(D3DPRESENT_PARAMETERS* pPresentationParameters);
HRESULT __stdcall Present(CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion);
HRESULT __stdcall GetBackBuffer(UINT BackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface8** ppBackBuffer);
HRESULT __stdcall GetRasterStatus(D3DRASTER_STATUS* pRasterStatus);
void __stdcall SetGammaRamp(DWORD Flags,CONST D3DGAMMARAMP* pRamp);
void __stdcall GetGammaRamp(D3DGAMMARAMP* pRamp);
HRESULT __stdcall CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture8** ppTexture);
HRESULT __stdcall CreateVolumeTexture(UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture8** ppVolumeTexture);
HRESULT __stdcall CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture8** ppCubeTexture);
HRESULT __stdcall CreateVertexBuffer(UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer8** ppVertexBuffer);
HRESULT __stdcall CreateIndexBuffer(UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer8** ppIndexBuffer);
HRESULT __stdcall CreateRenderTarget(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,BOOL Lockable,IDirect3DSurface8** ppSurface);
HRESULT __stdcall CreateDepthStencilSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,IDirect3DSurface8** ppSurface);
HRESULT __stdcall CreateImageSurface(UINT Width,UINT Height,D3DFORMAT Format,IDirect3DSurface8** ppSurface);
HRESULT __stdcall CopyRects(IDirect3DSurface8* pSourceSurface,CONST RECT* pSourceRectsArray,UINT cRects,IDirect3DSurface8* pDestinationSurface,CONST POINT* pDestPointsArray);
HRESULT __stdcall UpdateTexture(IDirect3DBaseTexture8* pSourceTexture,IDirect3DBaseTexture8* pDestinationTexture);
HRESULT __stdcall GetFrontBuffer(IDirect3DSurface8* pDestSurface);
HRESULT __stdcall SetRenderTarget(IDirect3DSurface8* pRenderTarget,IDirect3DSurface8* pNewZStencil);
HRESULT __stdcall GetRenderTarget(IDirect3DSurface8** ppRenderTarget);
HRESULT __stdcall GetDepthStencilSurface(IDirect3DSurface8** ppZStencilSurface);
HRESULT __stdcall BeginScene(THIS);
HRESULT __stdcall EndScene(THIS);
HRESULT __stdcall Clear(DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil);
HRESULT __stdcall SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix);
HRESULT __stdcall GetTransform(D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix);
HRESULT __stdcall MultiplyTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix);
HRESULT __stdcall SetViewport(CONST D3DVIEWPORT8* pViewport);
HRESULT __stdcall GetViewport(D3DVIEWPORT8* pViewport);
HRESULT __stdcall SetMaterial(CONST D3DMATERIAL8* pMaterial);
HRESULT __stdcall GetMaterial(D3DMATERIAL8* pMaterial);
HRESULT __stdcall SetLight(DWORD Index,CONST D3DLIGHT8* pLight);
HRESULT __stdcall GetLight(DWORD Index,D3DLIGHT8* pLight);
HRESULT __stdcall LightEnable(DWORD Index,BOOL Enable);
HRESULT __stdcall GetLightEnable(DWORD Index,BOOL* pEnable);
HRESULT __stdcall SetClipPlane(DWORD Index,CONST float* pPlane);
HRESULT __stdcall GetClipPlane(DWORD Index,float* pPlane);
HRESULT __stdcall SetRenderState(D3DRENDERSTATETYPE State,DWORD Value);
HRESULT __stdcall GetRenderState(D3DRENDERSTATETYPE State,DWORD* pValue);
HRESULT __stdcall BeginStateBlock(THIS);
HRESULT __stdcall EndStateBlock(DWORD* pToken);
HRESULT __stdcall ApplyStateBlock(DWORD Token);
HRESULT __stdcall CaptureStateBlock(DWORD Token);
HRESULT __stdcall DeleteStateBlock(DWORD Token);
HRESULT __stdcall CreateStateBlock(D3DSTATEBLOCKTYPE Type,DWORD* pToken);
HRESULT __stdcall SetClipStatus(CONST D3DCLIPSTATUS8* pClipStatus);
HRESULT __stdcall GetClipStatus(D3DCLIPSTATUS8* pClipStatus);
HRESULT __stdcall GetTexture(DWORD Stage,IDirect3DBaseTexture8** ppTexture);
HRESULT __stdcall SetTexture(DWORD Stage,IDirect3DBaseTexture8* pTexture);
HRESULT __stdcall GetTextureStageState(DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue);
HRESULT __stdcall SetTextureStageState(DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value);
HRESULT __stdcall ValidateDevice(DWORD* pNumPasses);
HRESULT __stdcall GetInfo(DWORD DevInfoID,void* pDevInfoStruct,DWORD DevInfoStructSize);
HRESULT __stdcall SetPaletteEntries(UINT PaletteNumber,CONST PALETTEENTRY* pEntries);
HRESULT __stdcall GetPaletteEntries(UINT PaletteNumber,PALETTEENTRY* pEntries);
HRESULT __stdcall SetCurrentTexturePalette(UINT PaletteNumber);
HRESULT __stdcall GetCurrentTexturePalette(UINT *PaletteNumber);
HRESULT __stdcall DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount);
HRESULT __stdcall DrawIndexedPrimitive(D3DPRIMITIVETYPE Type,UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount);
HRESULT __stdcall DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride);
HRESULT __stdcall DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride);
HRESULT __stdcall ProcessVertices(UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags);
HRESULT __stdcall CreateVertexShader(CONST DWORD* pDeclaration,CONST DWORD* pFunction,DWORD* pHandle,DWORD Usage);
HRESULT __stdcall SetVertexShader(DWORD Handle);
HRESULT __stdcall GetVertexShader(DWORD* pHandle);
HRESULT __stdcall DeleteVertexShader(DWORD Handle);
HRESULT __stdcall SetVertexShaderConstant(DWORD Register,CONST void* pConstantData,DWORD ConstantCount);
HRESULT __stdcall GetVertexShaderConstant(DWORD Register,void* pConstantData,DWORD ConstantCount);
HRESULT __stdcall GetVertexShaderDeclaration(DWORD Handle,void* pData,DWORD* pSizeOfData);
HRESULT __stdcall GetVertexShaderFunction(DWORD Handle,void* pData,DWORD* pSizeOfData);
HRESULT __stdcall SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride);
HRESULT __stdcall GetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer8** ppStreamData,UINT* pStride);
HRESULT __stdcall SetIndices(IDirect3DIndexBuffer8* pIndexData,UINT BaseVertexIndex);
HRESULT __stdcall GetIndices(IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex);
HRESULT __stdcall CreatePixelShader(CONST DWORD* pFunction,DWORD* pHandle);
HRESULT __stdcall SetPixelShader(DWORD Handle);
HRESULT __stdcall GetPixelShader(DWORD* pHandle);
HRESULT __stdcall DeletePixelShader(DWORD Handle);
HRESULT __stdcall SetPixelShaderConstant(DWORD Register,CONST void* pConstantData,DWORD ConstantCount);
HRESULT __stdcall GetPixelShaderConstant(DWORD Register,void* pConstantData,DWORD ConstantCount);
HRESULT __stdcall GetPixelShaderFunction(DWORD Handle,void* pData,DWORD* pSizeOfData);
HRESULT __stdcall DrawRectPatch(UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo);
HRESULT __stdcall DrawTriPatch(UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo);
HRESULT __stdcall DeletePatch(UINT Handle);};
以下のようにメソッドを書き換えていきます。
IDirect3DDevice8::QueryInterface
HRESULT __stdcall myIDirect3DDevice8::QueryInterface(REFIID riid, void** ppvObj)
{
*ppvObj = NULL;HRESULT hRes = m_pIDirect3DDevice8->QueryInterface(riid, ppvObj);
if (hRes == NOERROR)
{
*ppvObj = this;
}
return hRes;
}
IDirect3DDevice8::Release
ULONG __stdcall myIDirect3DDevice8::Release(void)
{
extern myIDirect3DDevice8* gl_pmyIDirect3DDevice8;if(hit_marker_texture)
hit_marker_texture->Release();
ULONG count = m_pIDirect3DDevice8->Release();
gl_pmyIDirect3DDevice8 = NULL;
delete(this);return (count);
}
IDirect3DDevice8::EndScene
HRESULT __stdcall myIDirect3DDevice8::EndScene(void)
{
if(!hit_marker_texture) {
D3DXCreateTextureFromFileEx(m_pIDirect3DDevice8, "hit_marker.png", 0, 0, 9, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &hit_marker_texture);
}
if(draw && hit_marker_texture) {
bool focused = *( (unsigned char*) 0x006CB00B);
int paused = *( (unsigned char*) 0x00481B44);
if(paused == 0) {
if(focused) {
focused_time = max(0, focused_time - 256 / 32);float half_hit_marker_size = 32.5f * (1.0f - .9f*(focused_time / 255.0f));
float x_border = 32.0;
float y_border = 16.0;float player_sprite_center_x = *( (float*)0x006CAA80) + x_border + 1.5f;
float player_sprite_center_y = *( (float*)0x006CAA84) + y_border + 1.5f;float x = player_sprite_center_x;
float y = player_sprite_center_y;
float radians = PI * (count / 128.0f);
count++;DWORD state_token;
m_pIDirect3DDevice8->CreateStateBlock(D3DSBT_ALL, &state_token);
m_pIDirect3DDevice8->CaptureStateBlock(state_token);D3DVIEWPORT8 vp; vp.X = 32; vp.Y = 16; vp.Width = 384; vp.Height = 448; vp.MinZ = 0.0; vp.MaxZ = 1.0;
lvert verts[4];
verts[0].x = x + (-half_hit_marker_size * cosf(radians) + -half_hit_marker_size * -sinf(radians)); verts[0].y = y + (-half_hit_marker_size * sinf(radians) + -half_hit_marker_size * cosf(radians)); verts[0].z = 0.0045f; verts[0].q = 1.0f; verts[0].tu = 0.0f; verts[0].tv = 0.0f;
verts[1].x = x + (-half_hit_marker_size * cosf(radians) + half_hit_marker_size * -sinf(radians)); verts[1].y = y + (-half_hit_marker_size * sinf(radians) + half_hit_marker_size * cosf(radians)); verts[1].z = 0.0045f; verts[1].q = 1.0f; verts[1].tu = 0.0f; verts[1].tv = 1.0f;
verts[2].x = x + ( half_hit_marker_size * cosf(radians) + -half_hit_marker_size * -sinf(radians)); verts[2].y = y + ( half_hit_marker_size * sinf(radians) + -half_hit_marker_size * cosf(radians)); verts[2].z = 0.0045f; verts[2].q = 1.0f; verts[2].tu = 1.0f; verts[2].tv = 0.0f;
verts[3].x = x + ( half_hit_marker_size * cosf(radians) + half_hit_marker_size * -sinf(radians)); verts[3].y = y + ( half_hit_marker_size * sinf(radians) + half_hit_marker_size * cosf(radians)); verts[3].z = 0.0045f; verts[3].q = 1.0f; verts[3].tu = 1.0f; verts[3].tv = 1.0f;
verts[0].diffuse = verts[1].diffuse = verts[2].diffuse = verts[3].diffuse = D3DCOLOR_ARGB(focused_time,0x00,0x00,0x00);
m_pIDirect3DDevice8->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
m_pIDirect3DDevice8->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SUBTRACT);
m_pIDirect3DDevice8->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pIDirect3DDevice8->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
m_pIDirect3DDevice8->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
m_pIDirect3DDevice8->SetTexture(0, hit_marker_texture);
m_pIDirect3DDevice8->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
m_pIDirect3DDevice8->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
m_pIDirect3DDevice8->SetVertexShader(0x144);
m_pIDirect3DDevice8->SetViewport(&vp);
m_pIDirect3DDevice8->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pIDirect3DDevice8->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pIDirect3DDevice8->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pIDirect3DDevice8->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
m_pIDirect3DDevice8->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
m_pIDirect3DDevice8->SetRenderState(D3DRS_TEXTUREFACTOR, 0x00000000);
m_pIDirect3DDevice8->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, &verts, 28);
m_pIDirect3DDevice8->ApplyStateBlock(state_token);
m_pIDirect3DDevice8->DeleteStateBlock(state_token);
}
else {
focused_time = min(focused_time + 256 / 32, 255);
}
}
}draw = false;
return (m_pIDirect3DDevice8->EndScene() );
}
当たり判定マーカーの画像を読み込んで自機に描画しています。
IDirect3D8
IDirect3D8も書き換えましょう。
myIDirect3D8::myIDirect3D8(IDirect3D8 *pOriginal)
{
m_pIDirect3D8 = pOriginal; // ポインタを保存
}
例によってクラスです。
class myIDirect3D8 : public IDirect3D8
{
private:
IDirect3D8 * m_pIDirect3D8;
public:myIDirect3D8(IDirect3D8 *pOriginal);
virtual ~myIDirect3D8();HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj);
ULONG __stdcall AddRef(void);
ULONG __stdcall Release(void);
HRESULT __stdcall RegisterSoftwareDevice(void* pInitializeFunction);
UINT __stdcall GetAdapterCount(void);
HRESULT __stdcall GetAdapterIdentifier(UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER8* pIdentifier);
UINT __stdcall GetAdapterModeCount(UINT Adapter);
HRESULT __stdcall EnumAdapterModes(UINT Adapter,UINT Mode,D3DDISPLAYMODE* pMode);
HRESULT __stdcall GetAdapterDisplayMode( UINT Adapter,D3DDISPLAYMODE* pMode);
HRESULT __stdcall CheckDeviceType(UINT Adapter,D3DDEVTYPE CheckType,D3DFORMAT DisplayFormat,D3DFORMAT BackBufferFormat,BOOL Windowed);
HRESULT __stdcall CheckDeviceFormat(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat);
HRESULT __stdcall CheckDeviceMultiSampleType(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType);
HRESULT __stdcall CheckDepthStencilMatch(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat);
HRESULT __stdcall GetDeviceCaps(UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS8* pCaps);
HMONITOR __stdcall GetAdapterMonitor(UINT Adapter);
HRESULT __stdcall CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice8** ppReturnedDeviceInterface);};
それでは、メソッドを書き換えていきます。
IDirect3D8::QueryInterface
HRESULT __stdcall myIDirect3D8::QueryInterface(REFIID riid, void** ppvObj)
{
*ppvObj = NULL;HRESULT hRes = m_pIDirect3D8->QueryInterface(riid, ppvObj);
if (hRes == NOERROR)
{
*ppvObj = this;
}
return hRes;
}
IDirect3D8::Release
ULONG __stdcall myIDirect3D8::Release()
{
extern myIDirect3D8* gl_pmyIDirect3D8;ULONG count = m_pIDirect3D8->Release();
if (count == 0)
{
gl_pmyIDirect3D8 = NULL;
delete(this);
}return(count);
}
IDirect3D8::CreateDevice
HRESULT __stdcall myIDirect3D8::CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice8** ppReturnedDeviceInterface)
{
extern myIDirect3DDevice8* gl_pmyIDirect3DDevice8;HRESULT hres = m_pIDirect3D8->CreateDevice( Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
gl_pmyIDirect3DDevice8 = new myIDirect3DDevice8(*ppReturnedDeviceInterface);
*ppReturnedDeviceInterface = gl_pmyIDirect3DDevice8;return(hres);
}
これら以外は本来のポインタを返すようにします。
IAT
フックを行うために、DLL_PROCESS_ATTACHの際、IATを書き換えなければなりません。
以下のようなコードでIATを書き換えられます。
BOOL HookIAT(char *szModule,char *szImportName,void *DummyFunc)
{
HMODULE base = GetModuleHandle(NULL);
DWORD size;
PIMAGE_IMPORT_DESCRIPTOR imgDesc = (PIMAGE_IMPORT_DESCRIPTOR)(ImageDirectoryEntryToData(base, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size));
while(imgDesc->Name) {
char* module = (char*)( (DWORD)(base) + imgDesc->Name);
if(!lstrcmp(module, szModule)) {
break;
}
++imgDesc;
}if(imgDesc->Name) {
PIMAGE_THUNK_DATA pIAT,pINT;
pIAT = reinterpret_cast(reinterpret_cast (base) + imgDesc->FirstThunk);
pINT = reinterpret_cast(reinterpret_cast (base) + imgDesc->OriginalFirstThunk);
while(pIAT->u1.Function) {
if(IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal)) {
continue;
}
PIMAGE_IMPORT_BY_NAME pImportName = reinterpret_cast(reinterpret_cast (base)+pINT->u1.AddressOfData); if(!lstrcmp(reinterpret_cast
(pImportName->Name), szImportName)) {
DWORD oldProtect;
VirtualProtect(&pIAT->u1.Function, sizeof(DWORD), PAGE_READWRITE, &oldProtect);
pIAT->u1.Function = reinterpret_cast(DummyFunc);
VirtualProtect(&pIAT->u1.Function,sizeof(DWORD),oldProtect,&oldProtect);
}++pIAT;
++pINT;
}
}return TRUE;
}
この関数を以下のように呼び出すことで、IDirect3DDevice8の呼び出し時にmyIDirect3DDevice8を、IDirect3D8呼び出し時にmyIDirect3D8を呼び出すことができます。
HookIAT("d3d8.dll","IDirect3DDevice8",(void *)myIDirect3DDevice8);
HookIAT("d3d8.dll","IDirect3D8",(void *)myIDirect3D8);
おわりに
こうして、東方紅魔郷の自機に当たり判定のマーカーを表示することができました。
DirectXのフックはネトゲのWallHackにも使われている*3技術です。
応用するといろいろな楽しいことができるのではないでしょうか。
参考
久々の以下略
Direct3D8 API-Hooking