// CED3D9Hook.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" using namespace std; map D3D9devices; PD3DHookShared shared=NULL; //set at first present int insidehook; BOOL makeSnapshot=FALSE; //duplicate variable to be used as a hint that one of the devices is making a snapshot. (in case of multiple devices) void DXMessD3D9Handler::PrepareForSnapshot() //just clears the screen { if (!shared->progressiveSnapshot) //if this is true no erasing will be done { if (!shared->alsoClearDepthBuffer) dev->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFF00FF, 0.0f, 0); else dev->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFF00FF, 1.0f, 0); } } void DXMessD3D9Handler::TakeSnapshot(char *functionname) { IDirect3DDevice9 *d=dev; IDirect3DSurface9 *backbuffer; dev->EndScene(); if (SUCCEEDED(d->GetRenderTarget(0, &backbuffer))) { BOOL savethis=FALSE; D3DSURFACE_DESC desc; if (smallSnapshot) { if (SUCCEEDED(backbuffer->GetDesc( &desc))) { IDirect3DSurface9 *backbuffer2=NULL; if (SUCCEEDED(d->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &backbuffer2, NULL))) { if (SUCCEEDED(d->GetRenderTargetData(backbuffer, backbuffer2))) { D3DLOCKED_RECT r; if (SUCCEEDED(backbuffer2->LockRect(&r, NULL, D3DLOCK_READONLY))) { DWORD *color; int xpos, ypos; xpos=(int)floor(desc.Width * smallSnapshotPointRelative.x); ypos=(int)floor(desc.Height * smallSnapshotPointRelative.y); color=(DWORD *)((UINT_PTR)r.pBits+r.Pitch*ypos+xpos*4); if ((*color & 0xffffff)!=0xff00ff) //pixels got changed savethis=TRUE; } backbuffer2->UnlockRect(); } backbuffer2->Release(); } } } else savethis=TRUE; if (savethis) { char s[MAX_PATH]; UINT64 stackbase=0; HANDLE h; int x; DWORD bw; LPD3DXBUFFER dest=NULL; #ifdef _AMD64_ stackbase=(UINT64)&functionname; #else __asm { mov dword ptr [stackbase], ebp //sure, it's a bit too far, but close enough } #endif snapshotCounter++; sprintf_s(s, MAX_PATH, "%ssnapshot%d.ce3dsnapshot", shared->SnapShotDir, snapshotCounter); h=CreateFileA(s, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); x=9; //dx9 WriteFile(h, &x, sizeof(x), &bw, NULL); if (shared->savePNGSeperateAsWell) { switch (shared->snapshotImageFormat) { case 0: strcat_s(s,MAX_PATH, ".BMP"); break; case 1: strcat_s(s,MAX_PATH, ".JPG"); break; case 3: strcat_s(s,MAX_PATH, ".PNG"); break; default: strcat_s(s,MAX_PATH, ".WTF"); break; } D3DXSaveSurfaceToFileA(s, (D3DXIMAGE_FILEFORMAT)shared->snapshotImageFormat, backbuffer, NULL, NULL); } if (SUCCEEDED(D3DXSaveSurfaceToFileInMemory(&dest, (D3DXIMAGE_FILEFORMAT)shared->snapshotImageFormat, backbuffer, NULL, NULL))) { x=shared->snapshotImageFormat; WriteFile(h, &x, sizeof(x), &bw, NULL); x=dest->GetBufferSize(); WriteFile(h, &x, sizeof(x), &bw, NULL); WriteFile(h, dest->GetBufferPointer(), x, &bw, NULL); } else { x=0; WriteFile(h, &x, sizeof(x), &bw, NULL); WriteFile(h, &x, sizeof(x), &bw, NULL); } dest->Release(); WriteFile(h, &stackbase, sizeof(stackbase), &bw, NULL); MEMORY_BASIC_INFORMATION mbi; int stacksize; if (VirtualQuery((void *)stackbase, &mbi, sizeof(mbi))==sizeof(mbi)) { stacksize=min(mbi.RegionSize- ((uintptr_t)stackbase-(uintptr_t)mbi.BaseAddress), 8192); WriteFile(h, &stacksize, sizeof(stacksize), &bw, NULL); WriteFile(h, (void *)stackbase, stacksize, &bw, NULL); } else { stacksize=0; stackbase=0; WriteFile(h, &stacksize, sizeof(stacksize), &bw, NULL); } //no constant buffer { //d->GetVertexDeclaration /* perhaps something could be done with this, but no idea right now IDirect3DVertexShader9 *vs; if (SUCCEEDED(d->GetVertexShader(&vs))) { vs->QueryInterface( vs->Release(); }*/ x=0; WriteFile(h, &x, sizeof(x), &bw, NULL); } if (functionname) { int i=strlen(functionname); WriteFile(h, &i, sizeof(i), &bw, NULL); WriteFile(h, functionname, i, &bw, NULL); } CloseHandle(h); } backbuffer->Release(); } dev->BeginScene(); } void DXMessD3D9Handler::DrawString(D3DXVECTOR3 position, PTextureData9 pFontTexture, char *s, int strlen, float alphablend) /* Render the text using the sprite object (select a texture region and draw that specific character) .Coordinates are in normal x,y coordinates Pre: Sprite must be active */ { int i; D3DXVECTOR3 currentpos = position; float fGlyphSizeY = pFontTexture->DefinedFontMap->charheight; position.z=0; D3DXVECTOR3 scale; D3DXMATRIX m; //calculate the original size of the texture scale.x=1.0f; scale.y=1.0f; scale.z=1.0f; for (i=0; i 127)) continue;//invalid char float offset=pFontTexture->DefinedFontMap->charinfo[s[i]-32].offset; float width=pFontTexture->DefinedFontMap->charinfo[s[i]-32].charwidth; RECT charactertexture; charactertexture.left=(LONG)offset; charactertexture.top=0; charactertexture.bottom=(LONG)fGlyphSizeY; charactertexture.right=(LONG)(offset+width); D3DXMatrixTransformation(&m, NULL, NULL, &scale, NULL, NULL, ¤tpos); sprite->SetTransform(&m); sprite->Draw(pFontTexture->pTexture, &charactertexture, NULL, NULL, D3DCOLOR_ARGB((int)floor(alphablend*255),255,255,255)); currentpos.x+=width; } } void DXMessD3D9Handler::BeforeReset() { if (sprite) sprite->OnLostDevice(); } void DXMessD3D9Handler::AfterReset() { if (sprite) sprite->OnResetDevice(); shared->lastHwnd=0; //reset that } BOOL DXMessD3D9Handler::UpdateTextures() { int i; int newTextureCount; HRESULT hr; WaitForSingleObject((HANDLE)(shared->TextureLock), INFINITE); if (shared->textureCount) { newTextureCount=shared->textureCount; if (shared->textureCount > TextureCount) { //update the textures if needed if (textures==NULL) //initial alloc textures=(TextureData9 *)malloc(sizeof(TextureData9)* shared->textureCount); else //realloc textures=(TextureData9 *)realloc(textures, sizeof(TextureData9)* shared->textureCount); if (textures==NULL) { OutputDebugStringA("Failure allocating memory for texturedata"); SetEvent((HANDLE)(shared->TextureLock)); //unlock return FALSE; } //initialize the new entries to NULL for (i=TextureCount; itextureCount; i++) { textures[i].pTexture=NULL; textures[i].DefinedFontMap=NULL; } TextureCount=shared->textureCount; } for (i=0; iRelease(); textures[i].pTexture=NULL; //should always happen } if (textures[i].DefinedFontMap) { //already has a fontmap. Free the old one free(textures[i].DefinedFontMap); textures[i].DefinedFontMap=NULL; } D3DXIMAGE_INFO imageinfo; ZeroMemory(&imageinfo, sizeof(imageinfo)); hr=D3DXCreateTextureFromFileInMemoryEx(dev, (void *)(tea[i].AddressOfTexture), tea[i].size, D3DX_DEFAULT, D3DX_DEFAULT, 1,0,D3DFMT_UNKNOWN, D3DPOOL_MANAGED,D3DX_FILTER_NONE,D3DX_DEFAULT, 0, &imageinfo, NULL, &textures[i].pTexture); if( FAILED( hr ) ) { char s[255]; //OutputDebugStringA("Fail 1"); hr=D3DXCreateTextureFromFileInMemoryEx(dev, (void *)(tea[i].AddressOfTexture), tea[i].size, D3DX_DEFAULT, D3DX_DEFAULT, 1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, 0, &imageinfo, NULL, &textures[i].pTexture); if (FAILED(hr)) { //OutputDebugStringA("Fail 2"); hr=D3DXCreateTextureFromFileInMemoryEx(dev, (void *)(tea[i].AddressOfTexture), tea[i].size, D3DX_DEFAULT, D3DX_DEFAULT, 1, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_FILTER_NONE, D3DX_DEFAULT, 0, &imageinfo, NULL, &textures[i].pTexture); if (FAILED(hr)) { //OutputDebugStringA("Fail 3"); hr=D3DXCreateTextureFromFileInMemory(dev, (void *)(tea[i].AddressOfTexture), tea[i].size, &textures[i].pTexture); if (FAILED(hr)) { //OutputDebugStringA("Fail 4"); textures[i].pTexture=NULL; sprintf_s(s,254,"Failure creating a texture. (%x) AOT=%p size=%d", hr, (void *)(tea[i].AddressOfTexture), tea[i].size); if (hr==D3DERR_NOTAVAILABLE) sprintf_s(s,254,"%s - D3DERR_NOTAVAILABLE",s); if (hr==D3DERR_OUTOFVIDEOMEMORY) sprintf_s(s,254,"%s - D3DERR_OUTOFVIDEOMEMORY",s); if (hr==D3DERR_INVALIDCALL) sprintf_s(s,254,"%s - D3DERR_INVALIDCALL",s); if (hr==D3DXERR_INVALIDDATA) sprintf_s(s,254,"%s - D3DXERR_INVALIDDATA",s); if (hr==E_OUTOFMEMORY) sprintf_s(s,254,"%s - D3DERR_NOTAVAILABLE",s); OutputDebugStringA(s); SetEvent((HANDLE)(shared->TextureLock)); return hr; } else { //just get the width and height from the texture if (textures[i].pTexture) { D3DSURFACE_DESC d; textures[i].pTexture->GetLevelDesc(0, &d); imageinfo.Width=d.Width; imageinfo.Height=d.Height; } } } } } if (textures[i].pTexture) //should be 100% true here { D3DSURFACE_DESC d; textures[i].pTexture->GetLevelDesc(0, &d); textures[i].width=(float)imageinfo.Width; textures[i].height=(float)imageinfo.Height; if (tea[i].AddressOfFontmap) { int j; float currentOffset=0; textures[i].DefinedFontMap=(PFONTMAP)malloc(sizeof(FONTMAP)); if (textures[i].DefinedFontMap==NULL) { OutputDebugStringA("Failure allocating memory for fontmap"); SetEvent((HANDLE)(shared->TextureLock)); //unlock return FALSE; } //now parse the fontmap provided by ce and fill in the gaps WORD *cefontmap=(WORD *)(tea[i].AddressOfFontmap); textures[i].DefinedFontMap->charheight=(float)cefontmap[0]; for (j=0; j<96; j++) { textures[i].DefinedFontMap->charinfo[j].offset=currentOffset; textures[i].DefinedFontMap->charinfo[j].charwidth=(float)cefontmap[j+1]; currentOffset+=cefontmap[j+1]; } textures[i].DefinedFontMap->fullwidth=currentOffset; } } tea[i].hasBeenUpdated=0; } } else { //It's NULL if (textures[i].pTexture) { textures[i].pTexture->Release(); textures[i].pTexture=NULL; } if (textures[i].DefinedFontMap) { free(textures[i].DefinedFontMap); textures[i].DefinedFontMap=NULL; } } } } if (shared->texturelistHasUpdate) InterlockedExchange((volatile LONG *)&shared->texturelistHasUpdate,0); SetEvent((HANDLE)(shared->TextureLock)); return TRUE; } float tmp=0.01f; void DXMessD3D9Handler::RenderOverlay() { int i; HRESULT hr; D3DVIEWPORT9 vp; POINT clientMousepos; vp.Width=0; clientMousepos.x=-1; clientMousepos.y=-1; if (sprite) { if (shared->lastHwnd==0) { D3DDEVICE_CREATION_PARAMETERS cp; dev->GetCreationParameters(&cp); shared->lastHwnd=(DWORD)cp.hFocusWindow; } if (shared->texturelistHasUpdate) UpdateTextures(); hr=dev->BeginScene(); if (SUCCEEDED(hr)) { hr=sprite->Begin(D3DXSPRITE_ALPHABLEND); if (!SUCCEEDED(hr)) { sprite->OnLostDevice(); sprite->OnResetDevice(); hr=sprite->Begin(D3DXSPRITE_ALPHABLEND); } if (SUCCEEDED(hr)) { BOOL hasLock=FALSE; i=0; if (shared->UseCommandlistLock) hasLock=WaitForSingleObject((HANDLE)shared->CommandlistLock, INFINITE)==WAIT_OBJECT_0; while (shared->RenderCommands[i].Command) { switch (shared->RenderCommands[i].Command) { case rcDrawSprite: { D3DXVECTOR2 scale,position, rotation; D3DXMATRIX m; int tid=shared->RenderCommands[i].sprite.textureid; if ((tidRenderCommands[i].sprite.width==-1) { if (!vp.Width) dev->GetViewport(&vp); scale.x=(float)vp.Width / (float)textures[tid].width; } else scale.x=(float)shared->RenderCommands[i].sprite.width / (float)textures[tid].width; scale.y=(float)shared->RenderCommands[i].sprite.height / (float)textures[tid].height; //set the position //set x if (shared->RenderCommands[i].x==-2) { //mouse position if (clientMousepos.x==-1) { //get the mouse position GetCursorPos(&clientMousepos); ScreenToClient((HWND)shared->lastHwnd, &clientMousepos); } //set x to the x position of the mouse (center is origin) position.x=(float)clientMousepos.x-((float)shared->RenderCommands[i].sprite.width / 2.0f); //make the center of the texture the position of the mouse (to add crosshairs, and normal mousecursors just have to keep that in mind so only render in the bottom left quadrant } else if (shared->RenderCommands[i].x==-1) //center { if (!vp.Width) dev->GetViewport(&vp); position.x=((float)vp.Width / 2.0f) - ((float)shared->RenderCommands[i].sprite.width / 2.0f); } else position.x=shared->RenderCommands[i].x; //set y if (shared->RenderCommands[i].y==-2) { //set to the position of the mouse (center is origin) if (clientMousepos.x==-1) { //get the mouse position GetCursorPos(&clientMousepos); ScreenToClient((HWND)shared->lastHwnd, &clientMousepos); } position.y=(float)clientMousepos.y-((float)shared->RenderCommands[i].sprite.height / 2.0f); } else if (shared->RenderCommands[i].y==-1) { if (!vp.Width) dev->GetViewport(&vp); position.y=((float)vp.Height / 2.0f) - ((float)shared->RenderCommands[i].sprite.height / 2.0f); } else position.y=(float)shared->RenderCommands[i].y; //truncate to a pixel exact position position.x=(float)(int)position.x; position.y=(float)(int)position.y; RECT texturepos; texturepos.left=0; texturepos.top=0; texturepos.bottom=(LONG)textures[tid].height; //shared->RenderCommands[i].sprite.height; texturepos.right=(LONG)textures[tid].width; //shared->RenderCommands[i].sprite.width; rotation.x=shared->RenderCommands[i].centerX; rotation.y=shared->RenderCommands[i].centerY; position.x-=shared->RenderCommands[i].centerX; position.y-=shared->RenderCommands[i].centerY; D3DXMatrixTransformation2D(&m, NULL, NULL, &scale, &rotation, shared->RenderCommands[i].rotation, &position); sprite->SetTransform(&m); hr=sprite->Draw(textures[tid].pTexture, &texturepos, NULL, NULL, D3DCOLOR_ARGB((int)(shared->RenderCommands[i].alphablend*255),255,255,255)); } break; } case rcDrawFont: { int tid=shared->RenderCommands[i].font.fontid; if ((tidGetViewport(&vp); if (!hasLock) hasLock=WaitForSingleObject((HANDLE)shared->CommandlistLock, INFINITE)==WAIT_OBJECT_0; //fonts demand a lock (stringpointer) position.x=(float)shared->RenderCommands[i].x; position.y=(float)shared->RenderCommands[i].y; position.z=0; td=&textures[shared->RenderCommands[i].font.fontid]; s=(char *)shared->RenderCommands[i].font.addressoftext; if (position.x==-1) { //horizontal center //calculate the width float width=0, maxwidth=0; int slen=strlen(s); int j; for (j=0; j=32) && (s[j]<(96+32))) width+=td->DefinedFontMap->charinfo[s[j]-32].charwidth; else if (s[j]=='\n') width=0; if (width>maxwidth) maxwidth=width; } position.x=((float)vp.Width / 2.0f) - ((float)maxwidth / 2.0f); } if (position.y==-1) { //vertical center position.y=((float)vp.Height / 2.0f) - ((float)td->DefinedFontMap->charheight / 2.0f); } position.x=(float)(int)position.x; position.y=(float)(int)position.y; //now draw the string //truncate to a pixel exact position DrawString(position, &textures[tid], s,strlen(s), shared->RenderCommands[i].alphablend); } break; } } i++; } if (hasLock) //release the lock if it was obtained SetEvent((HANDLE)shared->CommandlistLock); hr=sprite->Flush(); hr=sprite->End(); } dev->EndScene(); } } } /* typedef ULONG (__stdcall *RELEASE)(IUnknown *self); typedef ULONG (__stdcall *ADDREF)(IUnknown *self); int careAboutRefcount=1; ADDREF origAddRef; RELEASE origRelease; ULONG __stdcall d3d9devAddRef(IUnknown *self) { int i=0; if (insidehook==0) { i=origAddRef(self); } return i; } ULONG __stdcall d3d9devRelease(IUnknown *self) { int i; if (insidehook) return 1; origAddRef(self); i=origRelease(self); if (i==1) { //free the DXMess handler MessageBoxA(0,"Going to free the handler","FREE Device", MB_OK); } i=origRelease(self); return 0; //i; } */ DXMessD3D9Handler::DXMessD3D9Handler(IDirect3DDevice9 *dev, PD3DHookShared shared) { HRESULT hr; sprite=NULL; snapshotCounter=0; lastSnapshot=0; makeSnapshot=FALSE; smallSnapshot=FALSE; //Failed experiment. For some reason a[1] and a[2] get restored to their original address (which is the main reason why I use the deep hook method) //If it is important, I can add Release and AddRef to the hooklist at a later date /* if (careAboutRefcount) { DWORD old; //hook AddRef and Release for this object uintptr_t *a=(uintptr_t *)*(uintptr_t *)dev; VirtualProtect(dev, 8, PAGE_EXECUTE_READWRITE, &old); origAddRef=(ADDREF)a[1]; origRelease=(RELEASE)a[2]; a[1]=(uintptr_t)&d3d9devAddRef; a[2]=(uintptr_t)&d3d9devRelease; VirtualProtect(dev, 8, old, &old); } */ dev->AddRef(); this->dev=dev; this->shared=shared; textures=NULL; TextureCount=0; tea=(PTextureEntry)((uintptr_t)shared+shared->texturelist); UpdateTextures(); hr=D3DXCreateSprite(dev, &sprite); // if( FAILED( hr ) ) OutputDebugStringA("D3DXCreateSprite FAILED"); } DXMessD3D9Handler::~DXMessD3D9Handler() { D3D9devices[dev]=NULL; } void __stdcall D3D9Hook_Present_imp(IDirect3DDevice9 *device, PD3DHookShared s) { insidehook=1; DXMessD3D9Handler *currenthandler=D3D9devices[device]; if (currenthandler==NULL) { currenthandler=new DXMessD3D9Handler(device, s);//create a new devicehandler D3D9devices[device]=currenthandler; shared=s; } currenthandler->RenderOverlay(); insidehook=0; //check if a snapshot key is down if (currenthandler->makeSnapshot) //possible threading issue if more than one render device { //notify CE that all render operations have completed shared->snapshotcount=currenthandler->snapshotCounter; shared->canDoSnapshot=0; SetEvent((HANDLE)shared->snapshotDone); currenthandler->makeSnapshot=FALSE; } if (shared->canDoSnapshot) { if ((shared->snapshotKey) && (GetTickCount()>currenthandler->lastSnapshot+250)) { SHORT ks=GetAsyncKeyState(shared->snapshotKey); currenthandler->makeSnapshot=((ks & 1) || (ks & (1 << 15))); currenthandler->smallSnapshot=FALSE; if (currenthandler->makeSnapshot) currenthandler->lastSnapshot=GetTickCount(); } if ((currenthandler->makeSnapshot==FALSE) && (shared->smallSnapshotKey) && (GetTickCount()>currenthandler->lastSnapshot+250) && (shared->lastHwnd)) { SHORT ks=GetAsyncKeyState(shared->smallSnapshotKey); currenthandler->makeSnapshot=((ks & 1) || (ks & (1 << 15))); if (currenthandler->makeSnapshot) { POINT p; currenthandler->smallSnapshot=TRUE; currenthandler->lastSnapshot=GetTickCount(); //get the pixel the mouse is hovering over GetCursorPos(&p); ScreenToClient((HWND)shared->lastHwnd, &p); currenthandler->smallSnapshotPoint=p; GetClientRect((HWND)shared->lastHwnd, ¤thandler->smallSnapshotClientRect); //get the relative position (0.00 - 1.00) this position is in for the clientrect currenthandler->smallSnapshotPointRelative.x=(float)currenthandler->smallSnapshotPoint.x/(float)(currenthandler->smallSnapshotClientRect.right-currenthandler->smallSnapshotClientRect.left); currenthandler->smallSnapshotPointRelative.y=(float)currenthandler->smallSnapshotPoint.y/(float)(currenthandler->smallSnapshotClientRect.bottom-currenthandler->smallSnapshotClientRect.top); } } if (currenthandler->makeSnapshot) { makeSnapshot=TRUE; //once true, always true //clear the render target with a specific color currenthandler->dev->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFF00FF, 1.0f, 0); currenthandler->snapshotCounter=0; } } } HRESULT __stdcall D3D9Hook_Reset_imp(D3D9_RESET_ORIGINAL originalfunction, IDirect3DDevice9 *device, D3DPRESENT_PARAMETERS *pPresentationParameters) { HRESULT hr; DXMessD3D9Handler *currenthandler=D3D9devices[device]; if (currenthandler) { currenthandler->BeforeReset(); hr=originalfunction(device, pPresentationParameters); if (SUCCEEDED(hr)) currenthandler->AfterReset(); } return hr; } HRESULT __stdcall D3D9Hook_DrawPrimitive_imp(D3D9_DRAWPRIMITIVE_ORIGINAL originalfunction, IDirect3DDevice9 *device, D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe DWORD oldfillmode; DWORD oldzenable; HRESULT hr,hr2; hr=device->GetRenderState(D3DRS_FILLMODE, &oldfillmode); hr2=device->GetRenderState(D3DRS_ZENABLE, &oldzenable); DXMessD3D9Handler *currentDevice=D3D9devices[device]; if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->PrepareForSnapshot(); if (SUCCEEDED(hr) && SUCCEEDED(hr2)) { device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME); hr=originalfunction(device, PrimitiveType, StartVertex, PrimitiveCount); device->SetRenderState(D3DRS_FILLMODE,oldfillmode); device->SetRenderState(D3DRS_ZENABLE,oldzenable); } else hr=originalfunction(device, PrimitiveType, StartVertex, PrimitiveCount); if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->TakeSnapshot("D3D9Hook_DrawPrimitive_imp"); return hr; } return originalfunction(device, PrimitiveType, StartVertex, PrimitiveCount); } HRESULT __stdcall D3D9Hook_DrawIndexedPrimitive_imp(D3D9_DRAWINDEXEDPRIMITIVE_ORIGINAL originalfunction, IDirect3DDevice9 *device, D3DPRIMITIVETYPE PrimitiveType,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe and/or zbuffer DWORD oldfillmode; DWORD oldzenable; HRESULT hr,hr2; hr=device->GetRenderState(D3DRS_FILLMODE, &oldfillmode); hr2=device->GetRenderState(D3DRS_ZENABLE, &oldzenable); DXMessD3D9Handler *currentDevice=D3D9devices[device]; if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->PrepareForSnapshot(); if (SUCCEEDED(hr) && SUCCEEDED(hr2)) { if (shared->wireframe) device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME); if (shared->disabledzbuffer) device->SetRenderState(D3DRS_ZENABLE,FALSE); hr=originalfunction(device, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount); device->SetRenderState(D3DRS_FILLMODE,oldfillmode); device->SetRenderState(D3DRS_ZENABLE,oldzenable); } else hr=originalfunction(device, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount); if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->TakeSnapshot("D3D9Hook_DrawIndexedPrimitive_imp"); return hr; } return originalfunction(device, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount); } HRESULT __stdcall D3D9Hook_DrawPrimitiveUP_imp(D3D9_DRAWPRIMITIVEUP_ORIGINAL originalfunction, IDirect3DDevice9 *device, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe and/or zbuffer DWORD oldfillmode; DWORD oldzenable; HRESULT hr,hr2; hr=device->GetRenderState(D3DRS_FILLMODE, &oldfillmode); hr2=device->GetRenderState(D3DRS_ZENABLE, &oldzenable); DXMessD3D9Handler *currentDevice=D3D9devices[device]; if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->PrepareForSnapshot(); if (SUCCEEDED(hr) && SUCCEEDED(hr2)) { if (shared->wireframe) device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME); if (shared->disabledzbuffer) device->SetRenderState(D3DRS_ZENABLE,FALSE); hr=originalfunction(device, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride); device->SetRenderState(D3DRS_FILLMODE,oldfillmode); device->SetRenderState(D3DRS_ZENABLE,oldzenable); } else hr=originalfunction(device, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride); if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->TakeSnapshot("D3D9Hook_DrawPrimitiveUP_imp"); return hr; } return originalfunction(device, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride); } HRESULT __stdcall D3D9Hook_DrawIndexedPrimitiveUP_imp(D3D9_DRAWINDEXEDPRIMITIVEUP_ORIGINAL originalfunction, IDirect3DDevice9 *device, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe and/or zbuffer DWORD oldfillmode; DWORD oldzenable; HRESULT hr,hr2; hr=device->GetRenderState(D3DRS_FILLMODE, &oldfillmode); hr2=device->GetRenderState(D3DRS_ZENABLE, &oldzenable); DXMessD3D9Handler *currentDevice=D3D9devices[device]; if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->PrepareForSnapshot(); if (SUCCEEDED(hr) && SUCCEEDED(hr2)) { if (shared->wireframe) device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME); if (shared->disabledzbuffer) device->SetRenderState(D3DRS_ZENABLE,FALSE); hr=originalfunction(device, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride); device->SetRenderState(D3DRS_FILLMODE,oldfillmode); device->SetRenderState(D3DRS_ZENABLE,oldzenable); } else hr=originalfunction(device, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride); if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->TakeSnapshot("D3D9Hook_DrawIndexedPrimitiveUP_imp"); return hr; } return originalfunction(device, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride); } HRESULT __stdcall D3D9Hook_DrawRectPatch_imp(D3D9_DRAWRECTPATCH_ORIGINAL originalfunction, IDirect3DDevice9 *device, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe and/or zbuffer DWORD oldfillmode; DWORD oldzenable; HRESULT hr,hr2; hr=device->GetRenderState(D3DRS_FILLMODE, &oldfillmode); hr2=device->GetRenderState(D3DRS_ZENABLE, &oldzenable); DXMessD3D9Handler *currentDevice=D3D9devices[device]; if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->PrepareForSnapshot(); if (SUCCEEDED(hr) && SUCCEEDED(hr2)) { if (shared->wireframe) device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME); if (shared->disabledzbuffer) device->SetRenderState(D3DRS_ZENABLE,FALSE); hr=originalfunction(device, Handle, pNumSegs, pRectPatchInfo); device->SetRenderState(D3DRS_FILLMODE,oldfillmode); device->SetRenderState(D3DRS_ZENABLE,oldzenable); } else hr=originalfunction(device, Handle, pNumSegs, pRectPatchInfo); if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->TakeSnapshot("D3D9Hook_DrawRectPatch_imp"); return hr; } return originalfunction(device, Handle, pNumSegs, pRectPatchInfo); } HRESULT __stdcall D3D9Hook_DrawTriPatch_imp(D3D9_DRAWTRIPATCH_ORIGINAL originalfunction, IDirect3DDevice9 *device, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe and/or zbuffer DWORD oldfillmode; DWORD oldzenable; HRESULT hr,hr2; hr=device->GetRenderState(D3DRS_FILLMODE, &oldfillmode); hr2=device->GetRenderState(D3DRS_ZENABLE, &oldzenable); DXMessD3D9Handler *currentDevice=D3D9devices[device]; if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->PrepareForSnapshot(); if (SUCCEEDED(hr) && SUCCEEDED(hr2)) { if (shared->wireframe) device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME); if (shared->disabledzbuffer) device->SetRenderState(D3DRS_ZENABLE,FALSE); hr=originalfunction(device, Handle, pNumSegs, pTriPatchInfo); device->SetRenderState(D3DRS_FILLMODE,oldfillmode); device->SetRenderState(D3DRS_ZENABLE,oldzenable); } else hr=originalfunction(device, Handle, pNumSegs, pTriPatchInfo); if ((currentDevice) && (currentDevice->makeSnapshot)) currentDevice->TakeSnapshot("D3D9Hook_DrawTriPatch_imp"); return hr; } return originalfunction(device, Handle, pNumSegs, pTriPatchInfo); } //STDMETHOD(DrawTriPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) PURE;