|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name: USNF97.cpp
Abstract:
USNF '97 synchronizes it's video playback with cli/sti combinations. This fails on NT, so we have to make sure they aren't bltting during the refresh. Note that each time a cli/sti is hit, it makes only 1 blt synchronize with the refresh. After the intro has played, cli/sti is no longer used and so the blts don't incur extra overhead.
Notes:
This is an app specific shim.
History:
02/10/2000 linstev Created
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(USNF97) #include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN APIHOOK_ENUM_ENTRY_DIRECTX_COMSERVER() APIHOOK_ENUM_ENTRY(GetStartupInfoA) APIHOOK_ENUM_END
IMPLEMENT_DIRECTX_COMSERVER_HOOKS()
LPDIRECTDRAW g_lpDirectDraw = NULL; BOOL bFixBlt = FALSE;
/*++
Hook create surface so we can be sure we're being called.
--*/
HRESULT COMHOOK(IDirectDraw, CreateSurface)( PVOID pThis, LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE* lplpDDSurface, IUnknown* pUnkOuter ) { HRESULT hReturn; _pfn_IDirectDraw_CreateSurface pfnOld = ORIGINAL_COM(IDirectDraw, CreateSurface, pThis);
if (SUCCEEDED(hReturn = (*pfnOld)( pThis, lpDDSurfaceDesc, lplpDDSurface, pUnkOuter))) { HookObject( NULL, IID_IDirectDrawSurface, (PVOID*)lplpDDSurface, NULL, FALSE); }
g_lpDirectDraw = (LPDIRECTDRAW)pThis;
return hReturn; }
/*++
Synchronize the blt with the refresh if a cli/sti has just been called.
--*/
HRESULT COMHOOK(IDirectDrawSurface, Blt)( LPDIRECTDRAWSURFACE lpDDDestSurface, LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFX ) { // Original Blt
_pfn_IDirectDrawSurface_Blt pfnOld = ORIGINAL_COM(IDirectDrawSurface, Blt, (LPVOID) lpDDDestSurface);
if (bFixBlt) { // Make sure we're in the blank.
DWORD dwScanLine = 0; while (dwScanLine<480) { g_lpDirectDraw->GetScanLine(&dwScanLine); } bFixBlt = FALSE; } return (*pfnOld)( lpDDDestSurface, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFX); }
/*++
Custom exception handler to filter the cli/sti instructions. Handle out of range idivs.
--*/
LONG USNF97_ExceptionFilter( struct _EXCEPTION_POINTERS *ExceptionInfo ) { CONTEXT *lpContext = ExceptionInfo->ContextRecord; LONG lRet = EXCEPTION_CONTINUE_SEARCH;
if ((*((LPBYTE)lpContext->Eip) == 0xFA) || (*((LPBYTE)lpContext->Eip) == 0xFB)) { bFixBlt = TRUE; lpContext->Eip++; lRet = EXCEPTION_CONTINUE_EXECUTION; } else if ((*((LPBYTE)lpContext->Eip) == 0xF7) || // Handle idiv
(*((LPBYTE)lpContext->Eip+1) == 0xF7)) // Handle 16 bit idiv
{ DPFN( eDbgLevelWarning, "Detected 'idiv' overflow: validating edx:eax"); lpContext->Edx=0; if ((LONG)lpContext->Eax < 0) { lpContext->Eax = (DWORD)(-(LONG)lpContext->Eax); } lRet = EXCEPTION_CONTINUE_EXECUTION; }
return lRet; }
/*++
Hook the exception handler.
--*/
VOID APIHOOK(GetStartupInfoA)( LPSTARTUPINFOA lpStartupInfo ) { SetUnhandledExceptionFilter(USNF97_ExceptionFilter); ORIGINAL_API(GetStartupInfoA)(lpStartupInfo); }
/*++
Register hooked functions
--*/
HOOK_BEGIN
APIHOOK_ENTRY(KERNEL32.DLL, GetStartupInfoA)
APIHOOK_ENTRY_DIRECTX_COMSERVER() COMHOOK_ENTRY(DirectDraw, IDirectDraw, CreateSurface, 6) COMHOOK_ENTRY(DirectDraw, IDirectDrawSurface, Blt, 5)
HOOK_END
IMPLEMENT_SHIM_END
|