bool CDirect3DHook9::RemoveHook ( ) { if ( UsingAltD3DSetup() ) return true; m_bDirect3DCreate9Suspended = true; WriteDebugEvent ( "Direct3D9 hook suspended." ); return true; }
bool CDirect3DHook9::ApplyHook ( ) { if ( UsingAltD3DSetup() ) return true; // Hook Direct3DCreate9. if ( !m_pfnDirect3DCreate9 ) { m_pfnDirect3DCreate9 = reinterpret_cast < pDirect3DCreate > ( DetourFunction ( DetourFindFunction ( "D3D9.DLL", "Direct3DCreate9" ), reinterpret_cast < PBYTE > ( API_Direct3DCreate9 ) ) ); WriteDebugEvent ( SString( "Direct3D9 hook applied %08x", m_pfnDirect3DCreate9 ) ); } else { WriteDebugEvent ( "Direct3D9 hook resumed." ); m_bDirect3DCreate9Suspended = false; } return true; }
//////////////////////////////////////////////// // // Hook CCore::OnPreCreateDevice // // Modify paramters // //////////////////////////////////////////////// void CCore::OnPreCreateDevice(IDirect3D9* pDirect3D, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD& BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters) { assert(0); if (!UsingAltD3DSetup()) return; WriteDebugEvent("CCore::OnPreCreateDevice"); uint uiPrevResult = GetApplicationSettingInt("diagnostics", "last-create-device-result"); if (uiPrevResult) { // Failed last time, so as a test for logging, try a create device with no modifications WriteDebugEvent(SString("Previous CreateDevice failed with: %08x", uiPrevResult)); WriteDebugEvent(" Test unmodified:"); WriteDebugEvent(ToString(Adapter, DeviceType, hFocusWindow, BehaviorFlags, *pPresentationParameters)); IDirect3DDevice9* pReturnedDeviceInterface = NULL; HRESULT hResult = pDirect3D->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, &pReturnedDeviceInterface); SAFE_RELEASE(pReturnedDeviceInterface); WriteDebugEvent(SString(" Unmodified result is: %08x", hResult)); } // Save original values for later BehaviorFlagsOrig = BehaviorFlags; presentationParametersOrig = *pPresentationParameters; WriteDebugEvent(" Original paramters:"); WriteDebugEvent(ToString(Adapter, DeviceType, hFocusWindow, BehaviorFlags, *pPresentationParameters)); // Make sure DirectX Get...() calls will work BehaviorFlags &= ~D3DCREATE_PUREDEVICE; // Enable the auto depth stencil parameter pPresentationParameters->EnableAutoDepthStencil = true; GetVideoModeManager()->PreCreateDevice(pPresentationParameters); WriteDebugEvent(" Modified paramters:"); WriteDebugEvent(ToString(Adapter, DeviceType, hFocusWindow, BehaviorFlags, *pPresentationParameters)); }
//////////////////////////////////////////////// // // Hook CCore::OnPostCreateDevice // // Wrap device or log failure // //////////////////////////////////////////////// HRESULT CCore::OnPostCreateDevice(HRESULT hResult, IDirect3D9* pDirect3D, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) { if (!UsingAltD3DSetup()) return D3D_OK; // // - Allow create device with no changes // - Check caps and report diff with GTA caps // - Release device // WriteDebugEvent("CCore::OnPostCreateDevice - Alt startup used"); if (hResult != D3D_OK) WriteDebugEvent(SString("Initial CreateDevice failed: %08x", hResult)); else WriteDebugEvent("Initial CreateDevice succeeded"); AddCapsReport(Adapter, pDirect3D, *ppReturnedDeviceInterface, false); SAFE_RELEASE(*ppReturnedDeviceInterface); // // - Create device with required changes // - Check caps and report diff with GTA caps // - Fix GTA caps if needed // // Save original values for later BehaviorFlagsOrig = BehaviorFlags; presentationParametersOrig = *pPresentationParameters; WriteDebugEvent(" Original paramters:"); WriteDebugEvent(ToString(Adapter, DeviceType, hFocusWindow, BehaviorFlags, *pPresentationParameters)); // Make sure DirectX Get...() calls will work BehaviorFlags &= ~D3DCREATE_PUREDEVICE; // Enable the auto depth stencil parameter pPresentationParameters->EnableAutoDepthStencil = true; GetVideoModeManager()->PreCreateDevice(pPresentationParameters); WriteDebugEvent(" Modified paramters:"); WriteDebugEvent(ToString(Adapter, DeviceType, hFocusWindow, BehaviorFlags, *pPresentationParameters)); hResult = CreateDeviceInsist(2, 1000, pDirect3D, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface); if (hResult != D3D_OK) WriteDebugEvent(SString("MTA CreateDevice failed: %08x", hResult)); else WriteDebugEvent("MTA CreateDevice succeeded"); AddCapsReport(Adapter, pDirect3D, *ppReturnedDeviceInterface, true); // Change the window title to MTA: San Andreas #ifdef MTA_DEBUG SetWindowTextW(hFocusWindow, MbUTF8ToUTF16("MTA: San Andreas [DEBUG]").c_str()); #else SetWindowTextW(hFocusWindow, MbUTF8ToUTF16("MTA: San Andreas").c_str()); #endif // Log graphic card name D3DADAPTER_IDENTIFIER9 AdapterIdent; pDirect3D->GetAdapterIdentifier(Adapter, 0, &AdapterIdent); WriteDebugEvent(ToString(AdapterIdent)); // Store the rendering window in the direct 3d data CDirect3DData::GetSingleton().StoreDeviceWindow(pPresentationParameters->hDeviceWindow); // Apply input hook CMessageLoopHook::GetSingleton().ApplyHook(hFocusWindow); // Make sure the object was created successfully. if (hResult == D3D_OK) { WriteDebugEvent("CreateDevice succeeded"); GetVideoModeManager()->PostCreateDevice(*ppReturnedDeviceInterface, pPresentationParameters); // We must first store the presentation values. CDirect3DData::GetSingleton().StoreViewport(0, 0, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight); // Calc and store readable depth format for shader use ERenderFormat ReadableDepthFormat = CDirect3DEvents9::DiscoverReadableDepthFormat(*ppReturnedDeviceInterface, pPresentationParameters->MultiSampleType, pPresentationParameters->Windowed != 0); CGraphics::GetSingleton().GetRenderItemManager()->SetDepthBufferFormat(ReadableDepthFormat); // Now create the proxy device. *ppReturnedDeviceInterface = new CProxyDirect3DDevice9(*ppReturnedDeviceInterface); // Debug output D3DDEVICE_CREATION_PARAMETERS parameters; (*ppReturnedDeviceInterface)->GetCreationParameters(¶meters); WriteDebugEvent(" Used creation parameters:"); WriteDebugEvent(SString(" Adapter:%d DeviceType:%d BehaviorFlags:0x%x ReadableDepth:%s", parameters.AdapterOrdinal, parameters.DeviceType, parameters.BehaviorFlags, ReadableDepthFormat ? std::string((char*)&ReadableDepthFormat, 4).c_str() : "None")); } bool bDetectOptimus = (GetModuleHandle("nvd3d9wrap.dll") != NULL); // Calc log level to use uint uiDiagnosticLogLevel = 0; if (GetApplicationSettingInt("nvhacks", "optimus") || bDetectOptimus) uiDiagnosticLogLevel = 1; // Log and continue if (hResult != D3D_OK) uiDiagnosticLogLevel = 2; // Log and wait - If fail status // Do diagnostic log now if needed if (uiDiagnosticLogLevel) { // Prevent statup warning in loader WatchDogCompletedSection("L3"); // Run diagnostic CCore::GetSingleton().GetNetwork()->ResetStub('dia3', *ms_strExtraLogBuffer, uiDiagnosticLogLevel); } ms_strExtraLogBuffer.clear(); // Handle fatal error if (hResult != D3D_OK) { // Inform user SString strMessage; strMessage += "There was a problem starting MTA:SA\n\n"; strMessage += SString("Direct3D CreateDevice error: %08x", hResult); BrowseToSolution("d3dcreatedevice-fail", EXIT_GAME_FIRST | ASK_GO_ONLINE, strMessage); } return hResult; }