HOOKFUNC BOOL WINAPI MyStretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop) { bool isFrameBoundary = false; if (!usingSDLOrDD /*&& !inPauseHandler*/ && !redrawingScreen) { if (dwRop == SRCCOPY) { HWND hwnd = WindowFromDC(hdcDest); if (hwnd /*&& !hwndRespondingToPaintMessage[hwnd]*/) { if ((/*s_gdiPhaseDetector.AdvanceAndCheckCycleBoundary(MAKELONG(nXOriginDest,nYOriginDest)) ||*/ tls.peekedMessage) && VerifyIsTrustedCaller(!tls.callerisuntrusted)) { if ((nWidthSrc >= gdiFrameBigEnoughWidth && nHeightSrc >= gdiFrameBigEnoughHeight) || HDCSizeBigEnoughForFrameBoundary(hdcSrc)) { isFrameBoundary = true; } } } } } ENTER(); BOOL rv = TRUE; if (!ShouldSkipDrawing(false, WindowFromDC(hdcDest) != 0)) { if (s_gdiPendingRefresh && !redrawingScreen) { redrawingScreen = true; RedrawScreenGDI(); redrawingScreen = false; } rv = StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, dwRop); } else s_gdiPendingRefresh = true; if (isFrameBoundary) { tls.peekedMessage = FALSE; if (!(tasflags.aviMode & 1)) FrameBoundary(NULL, CAPTUREINFO_TYPE_NONE); else FrameBoundaryHDCtoAVI(hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc); s_hdcSrcSaved = hdcSrc; s_hdcDstSaved = hdcDest; } return rv; }
static HRESULT STDMETHODCALLTYPE MyClear(IDirect3DDeviceN* pThis, DWORD a,LPD3DRECT b,DWORD c,D3DCOLOR d,D3DVALUE e,DWORD f) { d3ddebugprintf(__FUNCTION__ "(0x%X) called.\n", pThis); if(ShouldSkipDrawing(false, true)) return D3D_OK; HRESULT rv = Clear(pThis,a,b,c,d,e,f); return rv; }
static HRESULT STDMETHODCALLTYPE MyEnd(IDirect3DDeviceN* pThis, DWORD a) { d3ddebugprintf(__FUNCTION__ "(0x%X) called.\n", pThis); if(ShouldSkipDrawing(false, true)) return D3D_OK; HRESULT rv = End(pThis, a); return rv; }
static HRESULT STDMETHODCALLTYPE MyBeginIndexed(IDirect3DDeviceN* pThis, D3DPRIMITIVETYPE a, D3DVERTEXTYPE b, LPVOID c, DWORD d, DWORD e) { d3ddebugprintf(__FUNCTION__ "(0x%X) called.\n", pThis); if(ShouldSkipDrawing(false, true)) return D3D_OK; HRESULT rv = BeginIndexed(pThis, a, b, c, d, e); return rv; }
static HRESULT STDMETHODCALLTYPE MyDrawIndexedPrimitiveVB(IDirect3DDeviceN* pThis, D3DPRIMITIVETYPE a, LPDIRECT3DVERTEXBUFFERN b, DWORD c, DWORD d, LPWORD e, DWORD f, DWORD g) { d3ddebugprintf(__FUNCTION__ "(0x%X) called.\n", pThis); if(ShouldSkipDrawing(false, true)) return D3D_OK; HRESULT rv = DrawIndexedPrimitiveVB(pThis, a, b, c, d, e, f, g); return rv; }
static HRESULT STDMETHODCALLTYPE MyDrawIndexedPrimitiveStrided(IDirect3DDeviceN* pThis, D3DPRIMITIVETYPE a, DWORD b, LPD3DDRAWPRIMITIVESTRIDEDDATA c, DWORD d, LPWORD e, DWORD f, DWORD g) { d3ddebugprintf(__FUNCTION__ "(0x%X) called.\n", pThis); if(ShouldSkipDrawing(false, true)) return D3D_OK; HRESULT rv = DrawIndexedPrimitiveStrided(pThis, a, b, c, d, e, f, g); return rv; }
HOOKFUNC void SDLCALL MySDL_UpdateRects(SDL_Surface* screen, int numrects, SDL_Rect* rects) { debuglog(LCF_SDL|LCF_FRAME, __FUNCTION__ "(0x%X, %d, 0x%X) called.\n", screen, numrects, rects); usingSDLOrDD = true; if(!ShouldSkipDrawing(true, true)) SDL_UpdateRects(screen, numrects, rects); // used_sdl_flip check needed for eversion, not needed for ? if(!used_sdl_flip) SDLFrameBoundary(screen); }
HOOKFUNC void SDLCALL MySDL_UpdateRect(SDL_Surface* screen, int x, int y, int w, int h) { usingSDLOrDD = true; bool isEntireScreen = !x && !y && !w && !h; debuglog(LCF_SDL|(isEntireScreen?LCF_FRAME:0), __FUNCTION__ "(0x%X, %d,%d,%d,%d) called.\n", screen, x,y,w,h); if(!ShouldSkipDrawing(isEntireScreen, /*!isEntireScreen*/false)) // eversion crashes sometimes if the second param is true SDL_UpdateRect(screen, x,y,w,h); // used_sdl_flip check needed for eversion, not needed for ? if(!used_sdl_flip && isEntireScreen) SDLFrameBoundary(screen); }
HOOKFUNC int SDLCALL MySDL_Flip(SDL_Surface* screen) { debuglog(LCF_SDL|LCF_FRAME, __FUNCTION__ " called.\n"); used_sdl_flip = true; usingSDLOrDD = true; int prevFrameCount = framecount; int rv; if(!ShouldSkipDrawing(true, false)) rv = SDL_Flip(screen); else rv = 0; if(prevFrameCount == framecount) SDLFrameBoundary(screen); return rv; }
HOOKFUNC BOOL WINAPI MyBitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop) { bool isFrameBoundary = false; if (!usingSDLOrDD /*&& !inPauseHandler*/ && !redrawingScreen) { if (dwRop == SRCCOPY) { HWND hwnd = WindowFromDC(hdcDest); if (hwnd /*&& !hwndRespondingToPaintMessage[hwnd]*/) { if ((/*s_gdiPhaseDetector.AdvanceAndCheckCycleBoundary(MAKELONG(nXDest,nYDest)) ||*/ tls.peekedMessage) && VerifyIsTrustedCaller(!tls.callerisuntrusted)) { if ((nWidth >= gdiFrameBigEnoughWidth && nHeight >= gdiFrameBigEnoughHeight) || HDCSizeBigEnoughForFrameBoundary(hdcSrc)) { isFrameBoundary = true; } } } } } ENTER(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop); BOOL rv = TRUE; if (!ShouldSkipDrawing(false, WindowFromDC(hdcDest) != 0)) { if (s_gdiPendingRefresh && !redrawingScreen) { redrawingScreen = true; RedrawScreenGDI(); redrawingScreen = false; } if (!fakeDisplayValid) { rv = BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop); } else { HWND hwnd = WindowFromDC(hdcDest); RECT realRect; if (!GetClientRect(hwnd, &realRect) || (realRect.right == fakeDisplayWidth && realRect.bottom == fakeDisplayHeight)) { rv = BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop); } else { // support resized fake-fullscreen windows in games like Lyle in Cube Sector // a little iffy: sprites leave pixels behind occasionally at non-integral scales HDC hdcTemp = 0; HDC hdc = hdcDest; if (realRect.right > fakeDisplayWidth || realRect.bottom > fakeDisplayHeight) { // sidestep clip region (it can't be expanded without switching HDCs) hdcTemp = GetDC(hwnd); hdc = hdcTemp; } // FIXME this feature actually broke, it's drawing at 100% size again no matter the window size, // it probably broke because of extra hooking of functions like GetClientRect. RECT dstRect = { nXDest, nYDest, nXDest + nWidth, nYDest + nHeight }; RECT fakeRect = { 0, 0, fakeDisplayWidth, fakeDisplayHeight }; RescaleRect(dstRect, fakeRect, realRect); rv = StretchBlt(hdc, dstRect.left, dstRect.top, dstRect.right - dstRect.left, dstRect.bottom - dstRect.top, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, dwRop); if (hdcTemp) ReleaseDC(hwnd, hdcTemp); } } } else s_gdiPendingRefresh = true; if (isFrameBoundary) { tls.peekedMessage = FALSE; if (!(tasflags.aviMode & 1)) FrameBoundary(NULL, CAPTUREINFO_TYPE_NONE); else FrameBoundaryHDCtoAVI(hdcSrc, nXSrc, nYSrc, nWidth, nHeight); s_hdcSrcSaved = hdcSrc; s_hdcDstSaved = hdcDest; } return rv; }