Hooking DirectX and screenshots

Started by
4 comments, last by Evil Steve 15 years, 3 months ago
I need to hook a DirectX based game and take a screenshot using C# in a similar way to FRAPS. I'm guessing it would look something like this: DirectX game -> C++ based dll -> C# program I have seen ways of hooking DirectX (here and here) although i'm unsure how to capture a screenshot (when requested from the C# app) and get the data back. C++ really isn't my thing so sample code would be appreciated.
Advertisement
Quote:Original post by DanCake
I need to hook a DirectX based game and take a screenshot using C# in a similar way to FRAPS.

I'm guessing it would look something like this:
DirectX game -> C++ based dll -> C# program

I have seen ways of hooking DirectX (here and here) although i'm unsure how to capture a screenshot (when requested from the C# app) and get the data back.

C++ really isn't my thing so sample code would be appreciated.
I've used the proxy DLL version quite a few times.
To take a screenshot with that method, you can just call IDirect3DDevice9::GetFrontBufferData after Present(), and then send that data to your C# program through a socket or named pipe or some other method of IPC.
Thanks for that, it was very helpful and i've successfully captured the front buffer to a file and managed to get sockets working in both c++ and c#.

What is the best way to extract the color values from each pixel? The following code works although once it reaches a certain pixel, I get the following:
"Unhandled exception at 0x1004407a (d3d9.dll) in test.exe: 0xC0000005: Access violation reading location 0x00134000."

void myIDirect3DDevice9::CaptureScreenshot(void){	LPDIRECT3DSURFACE9 FrontBuff;	D3DSURFACE_DESC SurfaceDesc;	D3DDISPLAYMODE DisplayMode;	D3DLOCKED_RECT Rect;	myIDirect3DDevice9::GetDisplayMode(D3DADAPTER_DEFAULT, &DisplayMode);	m_pIDirect3DDevice9->CreateOffscreenPlainSurface(DisplayMode.Width, DisplayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &FrontBuff, NULL);	m_pIDirect3DDevice9->GetFrontBufferData(D3DADAPTER_DEFAULT, FrontBuff);	//D3DXSaveSurfaceToFile( "c:\\screenshot.jpg", D3DXIFF_JPG, pFrontBuff, NULL, NULL);	FrontBuff->GetDesc(&SurfaceDesc);		FrontBuff->LockRect(&Rect,0,D3DLOCK_READONLY);	DWORD *imageData = (DWORD*)&Rect.pBits;	int r,g,b;	for(int i = 0; i < DisplayMode.Height; i++) {		for(int j = 0; j < DisplayMode.Width; j++) {			D3DXCOLOR PixelColor(imageData); <span class="cpp-comment">//Causes the access violation</span><br>			<br>			r = PixelColor.r;<br>			g = PixelColor.g;<br>			b = PixelColor.b;<br>			<br>			ProcessPixel(r, g, b, i, j);<br>		}<br>	} <br>	<br>	pFrontBuff-&gt;UnlockRect();<br>	pFrontBuff-&gt;Release();<br><br>		<br>}<br><br><br></pre></div><!–ENDSCRIPT–> 
DWORD *imageData = (DWORD*)&Rect.pBits
should be:
DWORD *imageData = (DWORD*)Rect.pBits;

Otherwise you're taking the address of the variable on the stack, instead of copying the pointer.
I've changed that and now i'm getting the following:
"Unhandled exception at 0x100440f7 (d3d9.dll) in test.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd."

Edit: Ignore that, the UnlockRect() and Release() lines are wrong.

Thanks for all the help!

[Edited by - DanCake on January 1, 2009 9:12:45 AM]
Quote:Original post by DanCake
I've changed that and now i'm getting the following:
"Unhandled exception at 0x100440f7 (d3d9.dll) in test.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd."

Edit: Ignore that, the UnlockRect() and Release() lines are wrong.

Thanks for all the help!
Even though you've solved the problem, you must check the return values for all D3D functions that return any pointer or data you rely on. If you don't, you can expect your app to give those lovely "The application has encountered an error and will be closed" messages when run on various other hardware. I can count 3 points in your code that could cause a crash.

This topic is closed to new replies.

Advertisement