// CED3D11Hook.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" using namespace std; map D3D11devices; DXMessD3D11Handler *lastdevice=NULL; int insidehook=0; PD3DHookShared shared; BOOL makeSnapshot; //definitions struct SpriteVertex{ XMFLOAT3 Pos; XMFLOAT2 Tex; }; struct ConstantBuffer { XMMATRIX rotation; XMFLOAT2 originpoint; XMFLOAT2 translation; XMFLOAT2 scaling; FLOAT transparency; FLOAT garbage; //16 byte alignment crap }; BOOL test=TRUE; ID3D11DeviceContext *DXMessD3D11Handler::PrepareForSnapshot(ID3D11DeviceContext *dc) //just clears the screen { ID3D11DeviceContext *drawdc=dc; EnterCriticalSection(&cs); if ((test) && (dc->GetType()!=D3D11_DEVICE_CONTEXT_IMMEDIATE)) { //If necesary create my own immeadiate context if (RenderContext==NULL) dev->GetImmediateContext(&RenderContext); //get all the data from all the stages (this will be SLOOOOW) /* drawdc=RenderContext; //get IA { ID3D11Buffer *IndexBuffer; ID3D11InputLayout *InputLayout; D3D11_PRIMITIVE_TOPOLOGY Topology; DXGI_FORMAT format; UINT offset; ID3D11Buffer *vertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; UINT strides[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; UINT offsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; dc->IAGetIndexBuffer(&IndexBuffer, &format, &offset); dc->IAGetInputLayout(&InputLayout); dc->IAGetPrimitiveTopology(&Topology); dc->IAGetVertexBuffers(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, vertexBuffers, strides, offsets); drawdc->IASetIndexBuffer(IndexBuffer, format, offset); drawdc->IASetInputLayout(InputLayout); drawdc->IASetPrimitiveTopology(Topology); drawdc->IASetVertexBuffers(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, vertexBuffers, strides, offsets); if (IndexBuffer) IndexBuffer->Release(); if (InputLayout) InputLayout->Release(); for (i=0; iRelease(); } //get VS { ID3D11Buffer *ConstantBuffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; ID3D11SamplerState *Samplers[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; ID3D11VertexShader *VertexShader=NULL; ID3D11ClassInstance **ClassInstances=NULL; ID3D11ClassInstance *Bla[10]; ID3D11ShaderResourceView *ShaderResourceViews[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; UINT NumClassInstances=0; dc->VSGetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, ConstantBuffers); dc->VSGetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, Samplers); NumClassInstances=10; dc->VSGetShader(&VertexShader, Bla, &NumClassInstances); if (NumClassInstances) { if (VertexShader) VertexShader->Release(); ClassInstances=(ID3D11ClassInstance **)malloc(NumClassInstances*sizeof(ID3D11ClassInstance *)); dc->VSGetShader(&VertexShader, ClassInstances, &NumClassInstances); } dc->VSGetShaderResources(0,D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, ShaderResourceViews); drawdc->VSSetShader(VertexShader, ClassInstances, NumClassInstances); drawdc->VSSetConstantBuffers(0,D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, ConstantBuffers); drawdc->VSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, Samplers); drawdc->VSSetShaderResources(0,D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, ShaderResourceViews); for (i=0; iRelease(); for (i=0; iRelease(); if (VertexShader) //for some reason the game tends to crash if I release the vertex shader here. Seems like refcount is 0 (I thought VSSetShader would increase it with 1) VertexShader->Release(); if (ClassInstances) { for (i=0; iRelease(); free(ClassInstances); } for (i=0; iRelease(); } } //get HS (Hull shader) { ID3D11Buffer *ConstantBuffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; ID3D11SamplerState *Samplers[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; ID3D11HullShader *HullShader=NULL; ID3D11ClassInstance **ClassInstances=NULL; ID3D11ShaderResourceView *ShaderResourceViews[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; UINT NumClassInstances=0; dc->HSGetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, ConstantBuffers); dc->HSGetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, Samplers); dc->HSGetShader(&HullShader, NULL, &NumClassInstances); if (NumClassInstances) { if (HullShader) HullShader->Release(); ClassInstances=(ID3D11ClassInstance **)malloc(NumClassInstances*sizeof(ID3D11ClassInstance *)); dc->HSGetShader(&HullShader, ClassInstances, &NumClassInstances); } dc->HSGetShaderResources(0,D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, ShaderResourceViews); drawdc->HSSetShader(HullShader, ClassInstances, NumClassInstances); drawdc->HSSetConstantBuffers(0,D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, ConstantBuffers); drawdc->HSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, Samplers); drawdc->HSSetShaderResources(0,D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, ShaderResourceViews); if (ClassInstances) { free(ClassInstances); } } //get DS (Domain shader) { ID3D11Buffer *ConstantBuffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; ID3D11SamplerState *Samplers[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; ID3D11DomainShader *DomainShader=NULL; ID3D11ClassInstance **ClassInstances=NULL; ID3D11ShaderResourceView *ShaderResourceViews[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; UINT NumClassInstances=0; dc->DSGetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, ConstantBuffers); dc->DSGetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, Samplers); dc->DSGetShader(&DomainShader, NULL, &NumClassInstances); if (NumClassInstances) { if (DomainShader) DomainShader->Release(); ClassInstances=(ID3D11ClassInstance **)malloc(NumClassInstances*sizeof(ID3D11ClassInstance *)); dc->DSGetShader(&DomainShader, ClassInstances, &NumClassInstances); } dc->DSGetShaderResources(0,D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, ShaderResourceViews); drawdc->DSSetShader(DomainShader, ClassInstances, NumClassInstances); drawdc->DSSetConstantBuffers(0,D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, ConstantBuffers); drawdc->DSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, Samplers); drawdc->DSSetShaderResources(0,D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, ShaderResourceViews); if (ClassInstances) { free(ClassInstances); } } //get GS { ID3D11Buffer *ConstantBuffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; ID3D11SamplerState *Samplers[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; UINT NumClassInstances=0; ID3D11GeometryShader *GeometryShader=NULL; ID3D11ClassInstance **ClassInstances=NULL; ID3D11ShaderResourceView *ShaderResourceViews[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; dc->GSGetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, ConstantBuffers); dc->GSGetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, Samplers); dc->GSGetShader(&GeometryShader, NULL, &NumClassInstances); if (NumClassInstances) { if (GeometryShader) GeometryShader->Release(); ClassInstances=(ID3D11ClassInstance **)malloc(NumClassInstances*sizeof(ID3D11ClassInstance *)); dc->GSGetShader(&GeometryShader, ClassInstances, &NumClassInstances); } dc->GSGetShaderResources(0,D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, ShaderResourceViews); drawdc->GSSetShader(GeometryShader, ClassInstances, NumClassInstances); drawdc->GSSetConstantBuffers(0,D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, ConstantBuffers); drawdc->GSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, Samplers); drawdc->GSSetShaderResources(0,D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, ShaderResourceViews); for (i=0; iRelease(); for (i=0; iRelease(); if (GeometryShader) GeometryShader->Release(); if (ClassInstances) { for (i=0; iRelease(); free(ClassInstances); } for (i=0; iRelease(); } } //get SO { ID3D11Buffer *SOTarget[D3D11_SO_BUFFER_SLOT_COUNT]; UINT offsets[D3D11_SO_BUFFER_SLOT_COUNT]; for (i=0; iSOGetTargets(D3D11_SO_BUFFER_SLOT_COUNT, SOTarget); drawdc->SOSetTargets(D3D11_SO_BUFFER_SLOT_COUNT, SOTarget, offsets); for (i=0; iRelease(); } //get RS { D3D11_RECT rects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; UINT rectcount=D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; D3D11_VIEWPORT viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; UINT viewportcount= D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ID3D11RasterizerState *RasterizerState; dc->RSGetScissorRects(&rectcount, NULL); dc->RSGetScissorRects(&rectcount, rects); dc->RSGetState(&RasterizerState); dc->RSGetViewports(&viewportcount, NULL); dc->RSGetViewports(&viewportcount, viewports); drawdc->RSSetScissorRects(rectcount, rects); drawdc->RSSetState(RasterizerState); drawdc->RSSetViewports(viewportcount, viewports); if (RasterizerState) RasterizerState->Release(); } //get PS { ID3D11Buffer *ConstantBuffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; ID3D11SamplerState *Samplers[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; UINT NumClassInstances=0; ID3D11PixelShader *PixelShader=NULL; ID3D11ClassInstance **ClassInstances=NULL; ID3D11ShaderResourceView *ShaderResourceViews[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; dc->PSGetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, ConstantBuffers); dc->PSGetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, Samplers); dc->PSGetShader(&PixelShader, NULL, &NumClassInstances); if (NumClassInstances) { if (PixelShader) PixelShader->Release(); ClassInstances=(ID3D11ClassInstance **)malloc(NumClassInstances*sizeof(ID3D11ClassInstance *)); dc->PSGetShader(&PixelShader, ClassInstances, &NumClassInstances); } dc->PSGetShaderResources(0,D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, ShaderResourceViews); drawdc->PSSetShader(NULL, NULL, 0); drawdc->PSSetShader(PixelShader, ClassInstances, NumClassInstances); drawdc->PSSetConstantBuffers(0,D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, ConstantBuffers); drawdc->PSSetSamplers(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, Samplers); drawdc->PSSetShaderResources(0,D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, ShaderResourceViews); for (i=0; iRelease(); for (i=0; iRelease(); if (PixelShader) PixelShader->Release(); if (ClassInstances) { for (i=0; iRelease(); free(ClassInstances); } for (i=0; iRelease(); } } //get OM { ID3D11BlendState* BlendState; ID3D11DepthStencilState *DepthStencilState; ID3D11RenderTargetView *RenderTargets[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; ID3D11DepthStencilView *DepthStencilView; FLOAT BlendFactor[4]; UINT SampleMask; UINT StencilRef; dc->OMGetBlendState( &BlendState, BlendFactor, &SampleMask); dc->OMGetDepthStencilState(&DepthStencilState, &StencilRef); dc->OMGetRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, RenderTargets, &DepthStencilView); //drawdc->OMGetRenderTargetsAndUnorderedAccessViews drawdc->OMSetBlendState(BlendState, BlendFactor, SampleMask); drawdc->OMSetDepthStencilState(DepthStencilState, StencilRef); drawdc->OMSetRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, RenderTargets, DepthStencilView); for (i=0; iRelease(); if (DepthStencilView) DepthStencilView->Release(); if (BlendState) BlendState->Release(); if (DepthStencilState) DepthStencilState->Release(); } */ //OutputDebugStringA("Defered"); } if (makeSnapshot) { if (!shared->progressiveSnapshot) //if this is true no erasing will be done { ID3D11RenderTargetView *currentrt=NULL; ID3D11DepthStencilView* currentds=NULL; FLOAT f[]={1.0f,0.0f,1.0f,1.0f}; //dc->OMSetRenderTargets(1, &ExtraRenderTarget, NULL); if (!shared->alsoClearDepthBuffer) drawdc->OMGetRenderTargets(1, ¤trt, NULL); else drawdc->OMGetRenderTargets(1, ¤trt, ¤tds); if (currentrt) { drawdc->ClearRenderTargetView(currentrt, f); currentrt->Release(); } if (currentds) { drawdc->ClearDepthStencilView(currentds, D3D11_CLEAR_DEPTH, 1.0, 0); currentds->Release(); } } } return drawdc; } void DXMessD3D11Handler::TakeSnapshot(ID3D11DeviceContext *dc, char* functionname) { ID3D11DeviceContext *drawdc=dc; ID3D11RenderTargetView *currentrt=NULL ; if (makeSnapshot) { dc->OMGetRenderTargets(1, ¤trt, NULL); if (dc->GetType()!=D3D11_DEVICE_CONTEXT_IMMEDIATE) { ID3D11CommandList *cl; if (SUCCEEDED(dc->FinishCommandList(TRUE, &cl))) { dev->GetImmediateContext(&dc); dc->ExecuteCommandList(cl, TRUE); } else dev->GetImmediateContext(&dc); } if (currentrt) { ID3D11Texture2D *backbuffer=NULL; D3D11_TEXTURE2D_DESC texDesc; D3D11_RENDER_TARGET_VIEW_DESC backbufferdesc; ID3D11Resource *r=NULL; currentrt->GetDesc(&backbufferdesc); texDesc.Format=backbufferdesc.Format; currentrt->GetResource(&r); if (r) { BOOL isMultiSampled=FALSE; if (SUCCEEDED(r->QueryInterface(__uuidof(ID3D11Texture2D), (void **)&backbuffer))) { backbuffer->GetDesc(&texDesc); isMultiSampled=texDesc.SampleDesc.Count>1; texDesc.SampleDesc.Count=1; texDesc.SampleDesc.Quality=0; if (smallSnapshot && (isMultiSampled==FALSE)) { texDesc.BindFlags = 0; //D3D11_BIND_UNORDERED_ACCESS;//0; texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; texDesc.Usage = D3D11_USAGE_STAGING; } else { texDesc.CPUAccessFlags = 0; texDesc.Usage = D3D11_USAGE_DEFAULT; } //figure out a good format ID3D11Texture2D *texture; if (SUCCEEDED(dev->CreateTexture2D(&texDesc, 0, &texture))) { BOOL savethis=FALSE; if (isMultiSampled) { dc->ResolveSubresource(texture, 0, r, 0, texDesc.Format); if (smallSnapshot) { ID3D11Texture2D *texture2; //temp storage for the new texture texDesc.BindFlags = 0; texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; texDesc.Usage = D3D11_USAGE_STAGING; if (SUCCEEDED(dev->CreateTexture2D(&texDesc, 0, &texture2))) { dc->CopyResource(texture2, texture); texture->Release(); //release the old one texture=texture2; } } } else dc->CopyResource(texture, r); if (smallSnapshot) { D3D11_MAPPED_SUBRESOURCE mappedtexture; if (SUCCEEDED(dc->Map(texture, 0, D3D11_MAP_READ, 0, &mappedtexture))) { PVOID color; int xpos, ypos; int pixelsize=4; xpos=(int)floor(texDesc.Width * smallSnapshotPointRelative.x); ypos=(int)floor(texDesc.Height * smallSnapshotPointRelative.y); //check if the pixel at xpos,ypos is not 0xffff00ff //use texDesc.Format to figure out where the pixel is located (size) and what format is equivalent to 1,0,1 if ((texDesc.Format>=DXGI_FORMAT_R32G32B32A32_TYPELESS) && (texDesc.Format<=DXGI_FORMAT_R32G32B32_SINT)) pixelsize=16; else if ((texDesc.Format>=DXGI_FORMAT_R16G16B16A16_TYPELESS) && (texDesc.Format<=DXGI_FORMAT_X32_TYPELESS_G8X24_UINT )) pixelsize=8; else if ((texDesc.Format>=DXGI_FORMAT_R10G10B10A2_TYPELESS ) && (texDesc.Format<=DXGI_FORMAT_X24_TYPELESS_G8_UINT )) pixelsize=4; else pixelsize=-1; //too small, compressed or unknown. Either way, don't use it if (pixelsize!=-1) { color=(PVOID)((UINT_PTR)mappedtexture.pData+mappedtexture.RowPitch*ypos+xpos*pixelsize); switch (pixelsize) { case 16: { if (texDesc.Format==DXGI_FORMAT_R32G32B32A32_FLOAT) { typedef struct { FLOAT c1; FLOAT c2; FLOAT c3; FLOAT c4; } *PC128; PC128 c=(PC128)color; savethis=((c->c1!=1.0f) || (c->c2!=0.0f) || (c->c3!=1.0f)); } else { typedef struct { DWORD c1; DWORD c2; DWORD c3; DWORD c4; } *PC128; PC128 c=(PC128)color; savethis=((c->c1!=0xffffffff) || (c->c2!=0x00000000) || (c->c3!=0xffffffff)); } break; } case 8: { if (texDesc.Format==DXGI_FORMAT_R16G16B16A16_FLOAT) { typedef struct { WORD c1; WORD c2; WORD c3; WORD c4; } *PC64; PC64 c=(PC64)color; savethis=((c->c1!=0x3c00) || (c->c2!=0x0000) || (c->c3!=0x3c00)); } else { typedef struct { WORD c1; WORD c2; WORD c3; WORD c4; } *PC64; PC64 c=(PC64)color; savethis=((c->c1!=0xffff) || (c->c2!=0x0000) || (c->c3!=0xffff)); } break; } case 4: { typedef struct { BYTE c1; BYTE c2; BYTE c3; BYTE c4; } *PC32; PC32 c=(PC32)color; savethis=((c->c1!=0xff) || (c->c2!=0x00) || (c->c3!=0xff)); break; } default: savethis=FALSE; } } dc->Unmap(texture, 0); } } else savethis=TRUE; if (savethis) { char s[MAX_PATH]; HANDLE h; DWORD bw; int x; UINT64 stackbase=0; #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=11; //dx11 WriteFile(h, &x, sizeof(x), &bw, NULL); ID3D10Blob *dest=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; } D3DX11SaveTextureToFileA(dc, texture, (D3DX11_IMAGE_FILE_FORMAT)shared->snapshotImageFormat, s); } if (SUCCEEDED(D3DX11SaveTextureToMemory(dc, texture, (D3DX11_IMAGE_FILE_FORMAT)shared->snapshotImageFormat, &dest, 0))) //weird. PNG has some information loss on certain things like text { 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); dest->Release(); } else { x=0; WriteFile(h, &x, sizeof(x), &bw, NULL); WriteFile(h, &x, sizeof(x), &bw, NULL); } 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); } ID3D11Buffer* c=NULL; //save the VS Constant buffers drawdc->VSGetConstantBuffers(0, 1, &c); int nocb=1; //if getting the constantbuffers fail this notifies that it has a length of 0 if (c) { ID3D11Buffer* c2=NULL; D3D11_BUFFER_DESC desc; c->GetDesc(&desc); desc.CPUAccessFlags=D3D11_CPU_ACCESS_READ; desc.BindFlags=0; desc.Usage=D3D11_USAGE_STAGING; dev->CreateBuffer(&desc, NULL, &c2); if (c2) { D3D11_MAPPED_SUBRESOURCE buf; dc->CopyResource(c2, c); if (SUCCEEDED(dc->Map(c2, 0, D3D11_MAP_READ, 0, &buf))) { int i=desc.ByteWidth; WriteFile(h, &i, sizeof(i), &bw, NULL); WriteFile(h, buf.pData, desc.ByteWidth, &bw, NULL); nocb=0; dc->Unmap(c2,0); } c2->Release(); } c->Release(); } if (nocb) { int i=0; WriteFile(h, &i, sizeof(i), &bw, NULL); } if (functionname) { int i=strlen(functionname); WriteFile(h, &i, sizeof(i), &bw, NULL); WriteFile(h, functionname, i, &bw, NULL); } //perhaps also save the vertex buffers? CloseHandle(h); } texture->Release(); } backbuffer->Release(); } r->Release(); } currentrt->Release(); } } LeaveCriticalSection(&cs); } void DXMessD3D11Handler::SetupFontVertexBuffer(int count) { if (currentMaxCharacterCountRelease(); pFontVB=NULL; } ZeroMemory( &bd2d, sizeof(bd2d) ); bd2d.Usage = D3D11_USAGE_DYNAMIC; bd2d.ByteWidth = sizeof( SpriteVertex ) * 6 * count; //size of a vertex*verticel per char*charcount bd2d.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd2d.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; hr = dev->CreateBuffer( &bd2d, NULL, &pFontVB ); if (SUCCEEDED(hr)) { currentMaxCharacterCount=count; } } } void DXMessD3D11Handler::DrawString(D3D11_VIEWPORT vp, PTextureData11 pFontTexture, char *s, int strlen) { if (pFontTexture) { ID3D11DeviceContext *dc; dev->GetImmediateContext(&dc); SetupFontVertexBuffer(strlen); if (currentMaxCharacterCountDefinedFontMap->charheight*2) / vp.Height; float fRectLeft = 0; float fRectTop = 1.0f; fRectLeft = fRectLeft * 2.0f - 1.0f; fRectTop = fRectTop * 2.0f - 1.0f; float fOriginalLeft = fRectLeft; //0*2.0f-1.0f=-1.0f float fTexTop = 0.0f; float fTexBottom = 1.0f; //fill the FontVB with the sizes and texture coordinates D3D11_MAPPED_SUBRESOURCE sr; if (SUCCEEDED(dc->Map(pFontVB,0, D3D11_MAP_WRITE_DISCARD, 0, &sr))) { int i,j; SpriteVertex *vertices=(SpriteVertex *)sr.pData; for (j=0, i=0; i 127)) continue;//invalid char float fGlyphSizeX = (pFontTexture->DefinedFontMap->charinfo[s[i]-32].charwidth*2) / vp.Width; float fCharTexSizeX = pFontTexture->DefinedFontMap->charinfo[s[i]-32].charwidth / (pFontTexture->DefinedFontMap->fullwidth); //0.010526315f; float fRectRight = fRectLeft + fGlyphSizeX; float fRectBottom = fRectTop - fGlyphSizeY; float fTexLeft = pFontTexture->DefinedFontMap->charinfo[s[i]-32].offset / pFontTexture->DefinedFontMap->fullwidth; float fTexRight = fTexLeft + fCharTexSizeX; vertices[j*6+0].Pos=XMFLOAT3( fRectLeft, fRectTop, 1.0f ); vertices[j*6+0].Tex=XMFLOAT2( fTexLeft, fTexTop ); vertices[j*6+1].Pos=XMFLOAT3( fRectRight, fRectTop, 1.0f ); vertices[j*6+1].Tex=XMFLOAT2( fTexRight, fTexTop ); vertices[j*6+2].Pos=XMFLOAT3( fRectLeft, fRectBottom, 1.0f ); vertices[j*6+2].Tex=XMFLOAT2( fTexLeft, fTexBottom ); vertices[j*6+3].Pos=XMFLOAT3( fRectRight, fRectTop, 1.0f); vertices[j*6+3].Tex=XMFLOAT2( fTexRight, fTexTop ); vertices[j*6+4].Pos=XMFLOAT3( fRectRight, fRectBottom, 1.0f); vertices[j*6+4].Tex=XMFLOAT2( fTexRight, fTexBottom ); vertices[j*6+5].Pos=XMFLOAT3( fRectLeft, fRectBottom, 1.0f); vertices[j*6+5].Tex=XMFLOAT2( fTexLeft, fTexBottom ); j++; fRectLeft += fGlyphSizeX; } dc->Unmap(pFontVB, 0); } //then render UINT stride = sizeof( SpriteVertex ); UINT offset = 0; dc->IASetVertexBuffers( 0, 1, &pFontVB, &stride, &offset ); dc->PSSetShaderResources( 0, 1, &pFontTexture->pTexture ); dc->Draw(6*strlen,0); dc->Release(); } } BOOL DXMessD3D11Handler::UpdateTextures() { //call this each time the resolution changes (when the buffer changes) HRESULT hr; ID3D11Resource *test; ID3D11Texture2D *texturex; DXGI_SWAP_CHAIN_DESC desc; int i; int newTextureCount; WaitForSingleObject((HANDLE)(shared->TextureLock), INFINITE); if (shared->textureCount) { ZeroMemory(&desc, sizeof(desc)); hr=swapchain->GetDesc(&desc); if (FAILED(hr)) return hr; newTextureCount=shared->textureCount; if (shared->textureCount > TextureCount) { //update the textures if needed if (textures==NULL) //initial alloc textures=(TextureData11 *)malloc(sizeof(TextureData11)* shared->textureCount); else //realloc textures=(TextureData11 *)realloc(textures, sizeof(TextureData11)* shared->textureCount); //initialize the new entries to NULL for (i=TextureCount; itextureCount; i++) { textures[i].pTexture=NULL; textures[i].DefinedFontMap=NULL; } } 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; } hr=D3DX11CreateTextureFromMemory(dev, (void *)(tea[i].AddressOfTexture), tea[i].size, NULL, NULL, &test, NULL); if( FAILED( hr ) ) { OutputDebugStringA("Failure creating a texture"); return hr; } hr=test->QueryInterface(__uuidof(ID3D11Texture2D), (void **)(&texturex)); hr=dev->CreateShaderResourceView(test, NULL, &textures[i].pTexture); if( FAILED( hr ) ) return hr; test->Release(); texturex->Release(); if (tea[i].AddressOfFontmap) { int j; float currentOffset=0; textures[i].DefinedFontMap=(PFONTMAP)malloc(sizeof(FONTMAP)); //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 (cleanup) if (textures[i].pTexture) { textures[i].pTexture->Release(); textures[i].pTexture=NULL; } if (textures[i].DefinedFontMap) { free(textures[i].DefinedFontMap); textures[i].DefinedFontMap=NULL; } } } TextureCount=newTextureCount; } if (shared->texturelistHasUpdate) InterlockedExchange((volatile LONG *)&shared->texturelistHasUpdate,0); SetEvent((HANDLE)(shared->TextureLock)); return TRUE; } DXMessD3D11Handler::~DXMessD3D11Handler() { if (textures) { int i; for (i=0; iRelease(); } free(textures); } if (pFontVB) pFontVB->Release(); if (pSpriteVB) pSpriteVB->Release(); if (pPixelShaderNormal) pPixelShaderNormal->Release(); if (pVertexShader) pVertexShader->Release(); if (pVertexLayout) pVertexLayout->Release(); if (pSamplerLinear) pSamplerLinear->Release(); if (pSpriteRasterizer) pSpriteRasterizer->Release(); if (pTransparency) pTransparency->Release(); if (pDepthStencil) pDepthStencil->Release(); if (pRenderTargetView) pRenderTargetView->Release(); if (pDepthStencilView) pDepthStencilView->Release(); if (pConstantBuffer) pConstantBuffer->Release(); if (pWireframeRasterizer) pWireframeRasterizer->Release(); if (pDisabledDepthStencilState) pDisabledDepthStencilState->Release(); /*if (dc) dc->Release();*/ if (dev) dev->Release(); if (swapchain) swapchain->Release(); } DXMessD3D11Handler::DXMessD3D11Handler(ID3D11Device *dev, IDXGISwapChain *sc, PD3DHookShared shared) { HRESULT hr; InitializeCriticalSection(&cs); //initialize the critical section used for snapshots RenderContext=NULL; snapshotCounter=0; lastSnapshot=0; makeSnapshot=FALSE; smallSnapshot=FALSE; pPixelShaderNormal=NULL; pVertexShader=NULL; pVertexLayout=NULL; pSamplerLinear=NULL; pSpriteRasterizer=NULL; pTransparency=NULL; pDepthStencil=NULL; pRenderTargetView=NULL; pDepthStencilView=NULL; pConstantBuffer=NULL; pWireframeRasterizer=NULL; pDisabledDepthStencilState=NULL; pSpriteVB=NULL; pFontVB=NULL; TextureCount=0; textures=NULL; tea=NULL; Valid=FALSE; this->shared=shared; this->dev=dev; this->swapchain=sc; dev->AddRef(); sc->AddRef(); // dc=NULL; // dev->GetImmediateContext(&dc); //increases the reference count D3D11_BUFFER_DESC bd2d; D3D11_SUBRESOURCE_DATA InitData2d; //create the shaders ID3DBlob* pBlob = NULL; ID3DBlob* pErrorBlob = NULL; char filename[MAX_PATH]; sprintf_s(filename,MAX_PATH, "%s%s", shared->CheatEngineDir,"overlay.fx"); //load the "normal" pixel shader pBlob = NULL; pErrorBlob = NULL; hr=D3DX11CompileFromFileA( filename, NULL, NULL, "PSNormal", "ps_4_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, NULL, &pBlob, &pErrorBlob, NULL ); if (pErrorBlob) pErrorBlob->Release(); if( FAILED( hr ) ) { OutputDebugStringA("pixelshader compilation failed\n"); return; } hr = dev->CreatePixelShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &pPixelShaderNormal ); pBlob->Release(); if( FAILED( hr ) ) { OutputDebugStringA("CreatePixelShader failed\n"); return; } pBlob = NULL; pErrorBlob = NULL; hr=D3DX11CompileFromFileA( filename, NULL, NULL, "VS", "vs_4_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, NULL, &pBlob, &pErrorBlob, NULL ); if (pErrorBlob) pErrorBlob->Release(); if( FAILED( hr ) ) { OutputDebugStringA("vertexshader compilation failed\n"); return; } hr = dev->CreateVertexShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &pVertexShader ); if( FAILED( hr ) ) { pBlob->Release(); OutputDebugStringA("CreateVertexShader failed\n"); return; } D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = ARRAYSIZE( layout ); // Create the input layout hr = dev->CreateInputLayout( layout, numElements, pBlob->GetBufferPointer(), pBlob->GetBufferSize(), &pVertexLayout ); pBlob->Release(); //create rectangular vertex buffer for sprites SpriteVertex spriteVertices[] ={ {XMFLOAT3( 1.0f, 1.0f, 1.0f), XMFLOAT2( 1.0f, 0.0f ) }, {XMFLOAT3( 1.0f, -1.0f, 1.0f), XMFLOAT2( 1.0f, 1.0f )}, {XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT2( 0.0f, 1.0f )}, {XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT2( 0.0f, 1.0f )}, {XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT2( 0.0f, 0.0f )}, {XMFLOAT3( 1.0f, 1.0f, 1.0f), XMFLOAT2( 1.0f, 0.0f )}, }; ZeroMemory( &bd2d, sizeof(bd2d) ); bd2d.Usage = D3D11_USAGE_IMMUTABLE; bd2d.ByteWidth = sizeof( SpriteVertex ) * 6; bd2d.BindFlags = D3D11_BIND_VERTEX_BUFFER; //bd2d.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; ZeroMemory( &InitData2d, sizeof(InitData2d) ); InitData2d.pSysMem = spriteVertices; hr = dev->CreateBuffer( &bd2d, &InitData2d, &pSpriteVB ); if( FAILED( hr ) ) { OutputDebugStringA("Vertexbuffer creation failed\n"); return; } D3D11_SAMPLER_DESC sampDesc; ZeroMemory( &sampDesc, sizeof(sampDesc) ); sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampDesc.MinLOD = 0; sampDesc.MaxLOD = D3D11_FLOAT32_MAX; hr = dev->CreateSamplerState( &sampDesc, &pSamplerLinear ); if( FAILED( hr ) ) return; //rasterizer D3D11_RASTERIZER_DESC rasterizerdesc; ZeroMemory(&rasterizerdesc, sizeof(rasterizerdesc)); rasterizerdesc.FillMode = D3D11_FILL_SOLID; rasterizerdesc.CullMode = D3D11_CULL_NONE; rasterizerdesc.FrontCounterClockwise = false; rasterizerdesc.DepthBias = 0; rasterizerdesc.DepthBiasClamp = 0.0f; rasterizerdesc.DepthClipEnable = false; rasterizerdesc.AntialiasedLineEnable = false; rasterizerdesc.MultisampleEnable = false; rasterizerdesc.ScissorEnable = false; rasterizerdesc.SlopeScaledDepthBias = 0.0f; hr=dev->CreateRasterizerState(&rasterizerdesc, &pSpriteRasterizer); if( FAILED( hr ) ) return; rasterizerdesc.FillMode = D3D11_FILL_WIREFRAME; hr=dev->CreateRasterizerState(&rasterizerdesc, &pWireframeRasterizer); if( FAILED( hr ) ) pWireframeRasterizer=NULL; //no biggie D3D11_DEPTH_STENCIL_DESC dsDesc; ZeroMemory(&dsDesc, sizeof(dsDesc)); //everything 0, including DepthEnable hr= dev->CreateDepthStencilState(&dsDesc, &pDisabledDepthStencilState); if( FAILED( hr ) ) pDisabledDepthStencilState=NULL; D3D11_BLEND_DESC blend; D3D11_RENDER_TARGET_BLEND_DESC rtbd; ZeroMemory( &rtbd, sizeof(rtbd) ); ZeroMemory( &blend, sizeof(blend) ); rtbd.BlendEnable = true; rtbd.SrcBlend = D3D11_BLEND_SRC_ALPHA; rtbd.DestBlend = D3D11_BLEND_INV_SRC_ALPHA; rtbd.BlendOp = D3D11_BLEND_OP_ADD; rtbd.SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; rtbd.DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; rtbd.BlendOpAlpha = D3D11_BLEND_OP_ADD; rtbd.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; blend.AlphaToCoverageEnable=false; blend.IndependentBlendEnable=false; //true; blend.RenderTarget[0]=rtbd; hr=dev->CreateBlendState(&blend, &pTransparency); if( FAILED( hr ) ) return; //create a rendertarget ID3D11Texture2D* pBackBuffer = NULL; hr = sc->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer ); if( FAILED( hr ) ) return; hr = dev->CreateRenderTargetView( pBackBuffer, NULL, &pRenderTargetView ); pBackBuffer->Release(); DXGI_SWAP_CHAIN_DESC scd; if (SUCCEEDED(sc->GetDesc(&scd))) { D3D11_TEXTURE2D_DESC texdesc; texdesc.ArraySize=1; texdesc.BindFlags=D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; texdesc.CPUAccessFlags=0; texdesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM; texdesc.Height=scd.BufferDesc.Height; texdesc.Width=scd.BufferDesc.Width; texdesc.MipLevels=1; texdesc.MiscFlags=0; texdesc.SampleDesc.Count=1; texdesc.SampleDesc.Quality=0; texdesc.Usage=D3D11_USAGE_DEFAULT; if (SUCCEEDED(dev->CreateTexture2D(&texdesc, NULL, &ExtraRenderTargetTexture))) { ExtraRenderTarget=NULL; dev->CreateRenderTargetView(ExtraRenderTargetTexture, NULL, &ExtraRenderTarget); } } if( FAILED( hr ) ) return; DXGI_SWAP_CHAIN_DESC scdesc; ZeroMemory(&scdesc,sizeof(scdesc)); sc->GetDesc(&scdesc); // Create depth stencil texture D3D11_TEXTURE2D_DESC descDepth; ZeroMemory( &descDepth, sizeof(descDepth) ); descDepth.Width = scdesc.BufferDesc.Width; descDepth.Height = scdesc.BufferDesc.Height; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; descDepth.SampleDesc.Count = 1; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D11_USAGE_DEFAULT; descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = 0; descDepth.MiscFlags = 0; hr = dev->CreateTexture2D( &descDepth, NULL, &pDepthStencil ); if( FAILED( hr ) ) return; // Create the depth stencil view D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; ZeroMemory( &descDSV, sizeof(descDSV) ); descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; hr = dev->CreateDepthStencilView( pDepthStencil, &descDSV, &pDepthStencilView ); if( FAILED( hr ) ) return; //now load the textures tea=(PTextureEntry)((uintptr_t)shared+shared->texturelist); UpdateTextures(); // Create the constant buffer D3D11_BUFFER_DESC bd; ZeroMemory(&bd, sizeof(bd)); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof(ConstantBuffer); bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = 0; hr = dev->CreateBuffer( &bd, NULL, &pConstantBuffer ); if( FAILED( hr ) ) return; //create a vertexbuffer to hold the characters currentMaxCharacterCount=0; SetupFontVertexBuffer(32); //init to 32 chars Valid=TRUE; } void DXMessD3D11Handler::RenderOverlay() { int i; if (Valid) { //render the overlay BOOL hasLock=FALSE; POINT clientMousepos; ID3D11DeviceContext *dc; dev->GetImmediateContext(&dc); clientMousepos.x=-1; clientMousepos.y=-1; //check if the overlay has an update //if so, first update the texture DXGI_SWAP_CHAIN_DESC desc; swapchain->GetDesc(&desc); shared->lastHwnd=(DWORD)desc.OutputWindow; if (shared->texturelistHasUpdate) UpdateTextures(); UINT stride = sizeof( SpriteVertex ); UINT offset = 0; float blendFactor[] = {0.1f, 1.0f, 1.0f, 0.1f}; ID3D11VertexShader *oldvs=NULL; ID3D11ClassInstance **oldvsinstances=NULL; UINT vci_count=0; ID3D11PixelShader *oldps=NULL; ID3D11ClassInstance **oldpsinstances=NULL; UINT pci_count=0; ID3D11GeometryShader *oldgs=NULL; ID3D11ClassInstance **oldgsinstances=NULL; UINT gci_count=0; ID3D11SamplerState *oldPSSampler=NULL; ID3D11ShaderResourceView *oldPSShaderResource=NULL; ID3D11BlendState *oldBlendState=NULL; float oldblendFactor[4]; UINT oldblendsamplemask; ID3D11DepthStencilState *oldDepthStencilState=NULL; UINT oldstencilref; D3D11_PRIMITIVE_TOPOLOGY oldPrimitiveTopology; ID3D11InputLayout *oldInputLayout=NULL; ID3D11Buffer *oldIndexBuffer=NULL; DXGI_FORMAT oldIndexBufferFormat; UINT oldIndexBufferOffset; ID3D11Buffer *oldVertexBuffer=NULL; UINT oldVertexBufferStrides; UINT oldVertexBufferOffset; ID3D11RasterizerState *oldRastersizerState=NULL; ID3D11RenderTargetView *oldRenderTarget; ID3D11DepthStencilView *oldDepthStencilView=NULL; ID3D11Buffer *oldConstantBuffersVS=NULL; ID3D11Buffer *oldConstantBuffersPS=NULL; //save state dc->VSGetConstantBuffers(0,1, &oldConstantBuffersVS); dc->VSGetShader( &oldvs, NULL, &vci_count); if (vci_count) { if (oldvs) oldvs->Release(); oldvsinstances=new ID3D11ClassInstance*[vci_count]; dc->VSGetShader( &oldvs, oldvsinstances, &vci_count); } dc->GSGetShader( &oldgs, NULL, &gci_count); if (gci_count) { if (oldgs) oldgs->Release(); oldgsinstances=new ID3D11ClassInstance*[gci_count]; dc->GSGetShader( &oldgs, oldgsinstances, &gci_count); } dc->PSGetConstantBuffers(0,1, &oldConstantBuffersPS); dc->PSGetShader( &oldps, NULL, &pci_count); if (pci_count) { if (oldps) oldps->Release(); oldpsinstances=new ID3D11ClassInstance*[pci_count]; dc->PSGetShader( &oldps, oldpsinstances, &pci_count); } dc->PSGetSamplers(0,1, &oldPSSampler); dc->PSGetShaderResources(0,1, &oldPSShaderResource); dc->OMGetRenderTargets(1, &oldRenderTarget, &oldDepthStencilView); dc->OMGetBlendState( &oldBlendState, oldblendFactor, &oldblendsamplemask); dc->OMGetDepthStencilState( &oldDepthStencilState, &oldstencilref); dc->IAGetPrimitiveTopology(&oldPrimitiveTopology); dc->IAGetInputLayout(&oldInputLayout); dc->IAGetIndexBuffer( &oldIndexBuffer, &oldIndexBufferFormat, &oldIndexBufferOffset); dc->IAGetVertexBuffers(0,1,&oldVertexBuffer, &oldVertexBufferStrides, &oldVertexBufferOffset); //I just need to save 1 dc->RSGetState(&oldRastersizerState); UINT oldviewports=0; D3D11_VIEWPORT viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; dc->RSGetViewports(&oldviewports, NULL); dc->RSGetViewports(&oldviewports, viewports); //change state dc->GSSetShader(NULL,NULL,0); dc->VSSetShader( pVertexShader, NULL, 0 ); dc->PSSetSamplers( 0, 1, &pSamplerLinear ); D3D11_VIEWPORT vp; vp.Width = (float)desc.BufferDesc.Width; vp.Height = (float)desc.BufferDesc.Height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; dc->RSSetViewports( 1, &vp ); dc->OMSetRenderTargetsAndUnorderedAccessViews(0,NULL,NULL,0,0,NULL,NULL); dc->OMSetRenderTargets(1, &pRenderTargetView, pDepthStencilView); dc->ClearDepthStencilView( pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0 ); dc->OMSetBlendState(pTransparency, blendFactor, 0xffffffff); dc->OMSetDepthStencilState(pDisabledDepthStencilState,0); dc->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); dc->IASetInputLayout( pVertexLayout ); dc->IASetIndexBuffer( NULL, DXGI_FORMAT_R16_UINT, 0 ); dc->RSSetState(pSpriteRasterizer); if (shared->UseCommandlistLock) hasLock=WaitForSingleObject((HANDLE)shared->CommandlistLock, INFINITE)==WAIT_OBJECT_0; i=0; while (shared->RenderCommands[i].Command) { switch (shared->RenderCommands[i].Command) { case rcDrawSprite: { if (shared->RenderCommands[i].sprite.textureidIASetVertexBuffers( 0, 1, &pSpriteVB, &stride, &offset ); dc->PSSetShader( pPixelShaderNormal, NULL, 0); dc->PSSetSamplers( 0, 1, &pSamplerLinear ); dc->PSSetShaderResources( 0, 1, &textures[shared->RenderCommands[i].sprite.textureid].pTexture ); if (shared->RenderCommands[i].x==-1) //center { position.x=((float)vp.Width / 2.0f) - ((float)shared->RenderCommands[i].sprite.width / 2.0f); } else if (shared->RenderCommands[i].x==-2) //mouse { if (clientMousepos.x==-1) { //get the mouse position GetCursorPos(&clientMousepos); ScreenToClient((HWND)shared->lastHwnd, &clientMousepos); } position.x=(float)clientMousepos.x-((float)shared->RenderCommands[i].sprite.width / 2.0f); } else position.x=(float)shared->RenderCommands[i].x; if (shared->RenderCommands[i].y==-1) //center { position.y=((float)vp.Height / 2.0f) - ((float)shared->RenderCommands[i].sprite.height / 2.0f); } else if (shared->RenderCommands[i].y==-2) //mouse { if (clientMousepos.y==-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 position.y=(float)shared->RenderCommands[i].y; //truncate the position to an exact pixel position.x=(float)(int)position.x; position.y=(float)(int)position.y; ConstantBuffer cb; cb.transparency=shared->RenderCommands[i].alphablend; if (shared->RenderCommands[i].sprite.width==-1) cb.scaling.x=(float)vp.Width/(float)vp.Width; else cb.scaling.x=(float)shared->RenderCommands[i].sprite.width/(float)vp.Width; cb.scaling.y=(float)shared->RenderCommands[i].sprite.height/(float)vp.Height; cb.originpoint.x=-1.0f+((float)shared->RenderCommands[i].centerX * 2)/(float)shared->RenderCommands[i].sprite.width; cb.originpoint.y=-1.0f+((float)shared->RenderCommands[i].centerY * 2)/(float)shared->RenderCommands[i].sprite.height; cb.rotation=XMMatrixRotationZ(shared->RenderCommands[i].rotation); cb.translation.x=-1.0f+((float)(((float)position.x-(float)shared->RenderCommands[i].centerX) * 2)/(float)vp.Width); cb.translation.y=-1.0f+((float)(((float)position.y-(float)shared->RenderCommands[i].centerY) * 2)/(float)vp.Height); dc->UpdateSubresource( pConstantBuffer, 0, NULL, &cb, 0, 0 ); dc->VSSetConstantBuffers(0,1, &pConstantBuffer); dc->PSSetConstantBuffers(0,1, &pConstantBuffer); dc->Draw(6,0); } break; } case rcDrawFont: { int tid=shared->RenderCommands[i].font.fontid; if ((tidCommandlistLock, INFINITE)==WAIT_OBJECT_0; //fonts demand a lock (stringpointer) position.x=(float)shared->RenderCommands[i].x; position.y=(float)shared->RenderCommands[i].y; td=&textures[tid]; s=(char *)shared->RenderCommands[i].font.addressoftext; if (position.x==-1) { //horizontal center //calculate the width float maxwidth=0, width=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); } //truncate the position to an exact pixel position.x=(float)(int)position.x; position.y=(float)(int)position.y; dc->PSSetShader( pPixelShaderNormal, NULL, 0); dc->PSSetSamplers( 0, 1, &pSamplerLinear ); ConstantBuffer cb; cb.transparency=shared->RenderCommands[i].alphablend; cb.scaling.x=1.0f; cb.scaling.y=1.0f;//if you wish a bigger font, use a bigger font, don't scale (ugly) cb.originpoint.x=-1.0f; cb.originpoint.y=-1.0f; cb.rotation=XMMatrixRotationZ(shared->RenderCommands[i].rotation); cb.translation.x=-1.0f+((float)((float)position.x * 2)/(float)vp.Width); cb.translation.y=-1.0f+((float)((float)position.y * 2)/(float)vp.Height); dc->UpdateSubresource( pConstantBuffer, 0, NULL, &cb, 0, 0 ); dc->VSSetConstantBuffers(0,1, &pConstantBuffer); dc->PSSetConstantBuffers(0,1, &pConstantBuffer); DrawString(vp, &textures[tid], s,strlen(s)); } break; } } i++; } if (hasLock) //release the lock if it was obtained SetEvent((HANDLE)shared->CommandlistLock); //restore dc->GSSetShader(oldgs, oldgsinstances, gci_count); if (oldgs) oldgs->Release(); if (oldgsinstances) { for (UINT j=0; jRelease(); delete [] oldgsinstances; } dc->VSSetShader(oldvs, oldvsinstances, vci_count); if (oldvs) oldvs->Release(); if (oldvsinstances) { for (UINT j=0; jRelease(); delete [] oldvsinstances; } dc->PSSetShader(oldps, oldpsinstances, pci_count); if (oldps) oldps->Release(); if (oldpsinstances) { for (UINT j=0; jRelease(); delete [] oldpsinstances; } dc->PSSetSamplers(0, 1, &oldPSSampler); if (oldPSSampler) oldPSSampler->Release(); dc->PSSetShaderResources(0,1, &oldPSShaderResource); if (oldPSShaderResource) oldPSShaderResource->Release(); dc->VSSetConstantBuffers(0,1, &oldConstantBuffersVS); if (oldConstantBuffersVS) oldConstantBuffersVS->Release(); dc->PSSetConstantBuffers(0,1, &oldConstantBuffersPS); if (oldConstantBuffersPS) oldConstantBuffersPS->Release(); dc->OMSetRenderTargets(1, &oldRenderTarget, oldDepthStencilView); if (oldRenderTarget) oldRenderTarget->Release(); if (oldDepthStencilView) oldDepthStencilView->Release(); dc->OMSetBlendState(oldBlendState, oldblendFactor, oldblendsamplemask); if (oldBlendState) oldBlendState->Release(); dc->OMSetDepthStencilState(oldDepthStencilState, oldstencilref); if (oldDepthStencilState) oldDepthStencilState->Release(); dc->IASetPrimitiveTopology(oldPrimitiveTopology); dc->IASetInputLayout(oldInputLayout); if (oldInputLayout) oldInputLayout->Release(); dc->IASetIndexBuffer(oldIndexBuffer, oldIndexBufferFormat, oldIndexBufferOffset); if (oldIndexBuffer) oldIndexBuffer->Release(); dc->IASetVertexBuffers(0,1,&oldVertexBuffer, &oldVertexBufferStrides, &oldVertexBufferOffset); if (oldVertexBuffer) oldVertexBuffer->Release(); dc->RSSetState(oldRastersizerState); if (oldRastersizerState) oldRastersizerState->Release(); dc->RSSetViewports(oldviewports, viewports); //check if the overlay texture needs to be updated, if so, getdc, update, continue } } void __stdcall D3D11Hook_SwapChain_ResizeBuffers_imp(IDXGISwapChain *swapchain, ID3D11Device *device, PD3DHookShared s) { DXMessD3D11Handler *currentDevice=D3D11devices[device]; if (currentDevice) { D3D11devices[device]=NULL; lastdevice=NULL; //currentDevice->dc->ClearState(); delete(currentDevice); } } void __stdcall D3D11Hook_SwapChain_Present_imp(IDXGISwapChain *swapchain, ID3D11Device *device, PD3DHookShared s) { //look up the controller class for this device DXMessD3D11Handler *currenthandler=D3D11devices[device]; if (currenthandler==NULL) { //OutputDebugStringA("New\n"); //D3D11devices[dev]=1; currenthandler=new DXMessD3D11Handler(device, swapchain, s);//create a new devicehandler //add to the map D3D11devices[device]=currenthandler; shared=s; } insidehook=1; D3D11devices[device]->RenderOverlay(); insidehook=0; lastdevice=currenthandler; //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) { ID3D11DeviceContext *dc; ID3D11RenderTargetView *rt=NULL; device->GetImmediateContext(&dc); makeSnapshot=TRUE; //once true, always true dc->OMGetRenderTargets(1, &rt, NULL); //currenthandler->dc->OMSetRenderTargets(1, ¤thandler->ExtraRenderTarget, NULL); //clear the render target with a specific color if (rt) { FLOAT f[]={1.0f,0.0f,1.0f,1.0f}; dc->ClearRenderTargetView(currenthandler->ExtraRenderTarget, f); rt->Release(); } currenthandler->snapshotCounter=0; } } } HRESULT __stdcall D3D11Hook_DrawIndexed_imp(D3D11_DRAWINDEXED_ORIGINAL originalfunction, ID3D11DeviceContext *dc, UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe and/or zbuffer HRESULT hr; ID3D11Device *device=NULL; dc->GetDevice(&device); DXMessD3D11Handler *currentDevice=D3D11devices[device]; if (currentDevice==NULL) //this can happen in some situations when there is a layer inbetween currentDevice=lastdevice; if (currentDevice) { ID3D11DeviceContext *drawdc; ID3D11DepthStencilState *oldDepthStencilState; ID3D11RasterizerState *oldRasterizerState; UINT stencilref=0; dc->OMGetDepthStencilState(&oldDepthStencilState,&stencilref); dc->RSGetState(&oldRasterizerState); if (shared->wireframe) dc->RSSetState(currentDevice->pWireframeRasterizer); if (shared->disabledzbuffer) dc->OMSetDepthStencilState(currentDevice->pDisabledDepthStencilState, 0); if (currentDevice->makeSnapshot) drawdc=currentDevice->PrepareForSnapshot(dc); else drawdc=dc; hr=originalfunction(drawdc, IndexCount, StartIndexLocation, BaseVertexLocation); if (currentDevice->makeSnapshot) currentDevice->TakeSnapshot(drawdc, "D3D11Hook_DrawIndexed_imp"); dc->RSSetState(oldRasterizerState); dc->OMSetDepthStencilState(oldDepthStencilState, stencilref); if (oldRasterizerState) oldRasterizerState->Release(); if (oldDepthStencilState) oldDepthStencilState->Release(); return hr; } } return originalfunction(dc, IndexCount, StartIndexLocation, BaseVertexLocation); } HRESULT __stdcall D3D11Hook_Draw_imp(D3D11_DRAW_ORIGINAL originalfunction, ID3D11DeviceContext *dc, UINT VertexCount, UINT StartVertexLocation) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe and/or zbuffer HRESULT hr; ID3D11Device *device=NULL; dc->GetDevice(&device); DXMessD3D11Handler *currentDevice=D3D11devices[device]; device->Release(); if (currentDevice==NULL) //this can happen in some situations when there is a layer inbetween currentDevice=lastdevice; if (currentDevice) { ID3D11DeviceContext *drawdc; ID3D11DepthStencilState *oldDepthStencilState; ID3D11RasterizerState *oldRasterizerState; UINT stencilref=0; dc->OMGetDepthStencilState(&oldDepthStencilState,&stencilref); dc->RSGetState(&oldRasterizerState); if (shared->wireframe) dc->RSSetState(currentDevice->pWireframeRasterizer); if (shared->disabledzbuffer) dc->OMSetDepthStencilState(currentDevice->pDisabledDepthStencilState, 0);; if (currentDevice->makeSnapshot) drawdc=currentDevice->PrepareForSnapshot(dc); else drawdc=dc; hr=originalfunction(drawdc, VertexCount, StartVertexLocation); if (currentDevice->makeSnapshot) currentDevice->TakeSnapshot(drawdc, "D3D11Hook_Draw_imp"); dc->RSSetState(oldRasterizerState); dc->OMSetDepthStencilState(oldDepthStencilState, stencilref); if (oldRasterizerState) oldRasterizerState->Release(); if (oldDepthStencilState) oldDepthStencilState->Release(); return hr; } } return originalfunction(dc, VertexCount, StartVertexLocation); } HRESULT __stdcall D3D11Hook_DrawIndexedInstanced_imp(D3D11_DRAWINDEXEDINSTANCED_ORIGINAL originalfunction, ID3D11DeviceContext *dc, UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation, INT BaseVertexLocation, UINT StartInstanceLocation) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe and/or zbuffer HRESULT hr; ID3D11DeviceContext *drawdc; ID3D11Device *device=NULL; dc->GetDevice(&device); DXMessD3D11Handler *currentDevice=D3D11devices[device]; device->Release(); if (currentDevice==NULL) //this can happen in some situations when there is a layer inbetween currentDevice=lastdevice; if (currentDevice) { ID3D11DepthStencilState *oldDepthStencilState; ID3D11RasterizerState *oldRasterizerState; UINT stencilref=0; dc->OMGetDepthStencilState(&oldDepthStencilState,&stencilref); dc->RSGetState(&oldRasterizerState); if (shared->wireframe) dc->RSSetState(currentDevice->pWireframeRasterizer); if (shared->disabledzbuffer) dc->OMSetDepthStencilState(currentDevice->pDisabledDepthStencilState, 0);; if (currentDevice->makeSnapshot) drawdc=currentDevice->PrepareForSnapshot(dc); else drawdc=dc; hr=originalfunction(drawdc, IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation); if (currentDevice->makeSnapshot) currentDevice->TakeSnapshot(drawdc, "D3D11Hook_DrawIndexedInstanced_imp"); dc->RSSetState(oldRasterizerState); dc->OMSetDepthStencilState(oldDepthStencilState, stencilref); if (oldRasterizerState) oldRasterizerState->Release(); if (oldDepthStencilState) oldDepthStencilState->Release(); return hr; } } return originalfunction(dc, IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation); } HRESULT __stdcall D3D11Hook_DrawInstanced_imp(D3D11_DRAWINSTANCED_ORIGINAL originalfunction, ID3D11DeviceContext *dc, UINT VertexCountPerInstance, UINT InstanceCount, UINT StartVertexLocation, UINT StartInstanceLocation) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe and/or zbuffer HRESULT hr; ID3D11DeviceContext *drawdc; ID3D11Device *device=NULL; dc->GetDevice(&device); DXMessD3D11Handler *currentDevice=D3D11devices[device]; device->Release(); if (currentDevice==NULL) //this can happen in some situations when there is a layer inbetween currentDevice=lastdevice; if (currentDevice) { ID3D11DepthStencilState *oldDepthStencilState; ID3D11RasterizerState *oldRasterizerState; UINT stencilref=0; dc->OMGetDepthStencilState(&oldDepthStencilState, &stencilref); dc->RSGetState(&oldRasterizerState); if (shared->wireframe) dc->RSSetState(currentDevice->pWireframeRasterizer); if (shared->disabledzbuffer) dc->OMSetDepthStencilState(currentDevice->pDisabledDepthStencilState, 0);; if (currentDevice->makeSnapshot) drawdc=currentDevice->PrepareForSnapshot(dc); else drawdc=dc; hr=originalfunction(drawdc, VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation); if (currentDevice->makeSnapshot) currentDevice->TakeSnapshot(drawdc, "D3D11Hook_DrawInstanced_imp"); dc->RSSetState(oldRasterizerState); dc->OMSetDepthStencilState(oldDepthStencilState, stencilref); if (oldRasterizerState) oldRasterizerState->Release(); if (oldDepthStencilState) oldDepthStencilState->Release(); return hr; } } return originalfunction(dc, VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation); } HRESULT __stdcall D3D11Hook_DrawAuto_imp(D3D11_DRAWAUTO_ORIGINAL originalfunction, ID3D11DeviceContext *dc) { if (((shared) && ((shared->wireframe) || (shared->disabledzbuffer) || (makeSnapshot) ) && (insidehook==0))) { //setup for wireframe and/or zbuffer HRESULT hr; ID3D11DeviceContext *drawdc; ID3D11Device *device=NULL; dc->GetDevice(&device); DXMessD3D11Handler *currentDevice=D3D11devices[device]; device->Release(); if (currentDevice==NULL) //this can happen in some situations when there is a layer inbetween currentDevice=lastdevice; if (currentDevice) { ID3D11DepthStencilState *oldDepthStencilState; ID3D11RasterizerState *oldRasterizerState; UINT stencilref=0; dc->OMGetDepthStencilState(&oldDepthStencilState, &stencilref); dc->RSGetState(&oldRasterizerState); if (shared->wireframe) dc->RSSetState(currentDevice->pWireframeRasterizer); if (shared->disabledzbuffer) dc->OMSetDepthStencilState(currentDevice->pDisabledDepthStencilState, 0);; if (currentDevice->makeSnapshot) drawdc=currentDevice->PrepareForSnapshot(dc); else drawdc=dc; hr=originalfunction(drawdc); if (currentDevice->makeSnapshot) currentDevice->TakeSnapshot(drawdc, "D3D11Hook_DrawAuto_imp"); dc->RSSetState(oldRasterizerState); dc->OMSetDepthStencilState(oldDepthStencilState, stencilref); if (oldRasterizerState) oldRasterizerState->Release(); if (oldDepthStencilState) oldDepthStencilState->Release(); return hr; } } return originalfunction(dc); }