HRESULT CProxyDirect3DDevice9::Reset ( D3DPRESENT_PARAMETERS* pPresentationParameters ) { WriteDebugEvent ( "CProxyDirect3DDevice9::Reset" ); GetVideoModeManager ()->PreReset ( pPresentationParameters ); HRESULT hResult; // Call our event handler. CDirect3DEvents9::OnInvalidate ( m_pDevice ); // Call the real reset routine. hResult = m_pDevice->Reset ( pPresentationParameters ); GetVideoModeManager ()->PostReset ( pPresentationParameters ); // Update our data. m_pData->StoreViewport ( 0, 0, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight ); // Call our event handler. CDirect3DEvents9::OnRestore ( m_pDevice ); return hResult; }
HRESULT CProxyDirect3D9::CreateDevice ( UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface ) { HRESULT hResult; WriteDebugEvent ( "CProxyDirect3D9::CreateDevice" ); // Change the window title to MTA: San Andreas #ifdef MTA_DEBUG SetWindowText ( hFocusWindow, "MTA: San Andreas [DEBUG]" ); #else SetWindowText ( hFocusWindow, "MTA: San Andreas" ); #endif // Enable the auto depth stencil parameter pPresentationParameters->EnableAutoDepthStencil = true; GetVideoModeManager ()->PreCreateDevice ( pPresentationParameters ); // Create our object. hResult = m_pDevice->CreateDevice ( Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface ); GetVideoModeManager ()->PostCreateDevice ( *ppReturnedDeviceInterface, pPresentationParameters ); // Pass the device to the core and store the rendering window in the direct 3d data CCore::GetSingleton ().SetRenderDevice ( *ppReturnedDeviceInterface ); CDirect3DData::GetSingleton ().StoreDeviceWindow ( pPresentationParameters->hDeviceWindow ); // Apply input hook CMessageLoopHook::GetSingleton ( ).ApplyHook ( hFocusWindow ); // Make sure the object was created successfully. if ( hResult == D3D_OK ) { // We must first store the presentation values. CDirect3DData::GetSingleton ( ).StoreViewport ( 0, 0, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight ); // Now create the proxy device. *ppReturnedDeviceInterface = new CProxyDirect3DDevice9 ( *ppReturnedDeviceInterface ); } return hResult; }
//////////////////////////////////////////////// // // 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; }
//////////////////////////////////////////////// // // HandleCreateDeviceResult // // Log result and possibly fix everything // //////////////////////////////////////////////// HRESULT HandleCreateDeviceResult(HRESULT hResult, IDirect3D9* pDirect3D, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) { // Log graphic card name D3DADAPTER_IDENTIFIER9 AdapterIdent; pDirect3D->GetAdapterIdentifier(Adapter, 0, &AdapterIdent); WriteDebugEvent(ToString(AdapterIdent)); uint uiCurrentStatus = 0; // 0-unknown 1-fail 2-success after retry 3-success if (hResult == D3D_OK) { // Log success and creation parameters WriteDebugEvent("CreateDevice success"); uiCurrentStatus = CREATE_DEVICE_SUCCESS; WriteDebugEvent(ToString(Adapter, DeviceType, hFocusWindow, BehaviorFlags, *pPresentationParameters)); } if (hResult != D3D_OK) { // Handle failure of initial create device call WriteDebugEvent(SString("CreateDevice failed #0: %08x", hResult)); // Try create device again hResult = DoCreateDevice(pDirect3D, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface); // Handle retry result if (hResult != D3D_OK) { WriteDebugEvent("--CreateDevice failed after retry"); uiCurrentStatus = CREATE_DEVICE_FAIL; } else { WriteDebugEvent("++CreateDevice succeeded after retry"); uiCurrentStatus = CREATE_DEVICE_RETRY_SUCCESS; // Apply input hook CMessageLoopHook::GetSingleton().ApplyHook(hFocusWindow); 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(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")); } } uint uiLastStatus = GetApplicationSettingInt("diagnostics", "createdevice-last-status"); SetApplicationSettingInt("diagnostics", "createdevice-last-status", uiCurrentStatus); // Calc log level to use uint uiDiagnosticLogLevel = 0; if (uiLastStatus == CREATE_DEVICE_FAIL && uiCurrentStatus != CREATE_DEVICE_FAIL) uiDiagnosticLogLevel = 1; // Log and continue - If changing from fail status if (uiCurrentStatus == CREATE_DEVICE_FAIL) uiDiagnosticLogLevel = 2; // Log and wait - If fail status bool bDetectOptimus = (GetModuleHandle("nvd3d9wrap.dll") != NULL); bool bFixCaps = false; if (GetApplicationSettingInt("nvhacks", "optimus") || bDetectOptimus) { bFixCaps = true; if (uiDiagnosticLogLevel == 0) uiDiagnosticLogLevel = 1; } AddCapsReport(Adapter, pDirect3D, *ppReturnedDeviceInterface, bFixCaps); if (uiDiagnosticLogLevel) { // Prevent statup warning in loader WatchDogCompletedSection("L3"); CCore::GetSingleton().GetNetwork()->ResetStub('dia3', *ms_strExtraLogBuffer, uiDiagnosticLogLevel); } ms_strExtraLogBuffer.clear(); if (hResult != D3D_OK) { // Handle fatal error 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; }
HRESULT CProxyDirect3D9::CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) { // Do not change the code at the start of this function. // Some graphic card drivers seem sensitive to the content of the CreateDevice function. HRESULT hResult; WriteDebugEvent("CProxyDirect3D9::CreateDevice"); WriteDebugEvent(SString(" Adapter:%d DeviceType:%d BehaviorFlags:0x%x", Adapter, DeviceType, BehaviorFlags)); // Make sure DirectX Get calls will work BehaviorFlags &= ~D3DCREATE_PUREDEVICE; WriteDebugEvent(SString(" BackBufferWidth:%d Height:%d Format:%d Count:%d", pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight, pPresentationParameters->BackBufferFormat, pPresentationParameters->BackBufferCount)); WriteDebugEvent(SString(" MultiSampleType:%d Quality:%d", pPresentationParameters->MultiSampleType, pPresentationParameters->MultiSampleQuality)); WriteDebugEvent(SString(" SwapEffect:%d Windowed:%d EnableAutoDepthStencil:%d AutoDepthStencilFormat:%d Flags:0x%x", pPresentationParameters->SwapEffect, pPresentationParameters->Windowed, pPresentationParameters->EnableAutoDepthStencil, pPresentationParameters->AutoDepthStencilFormat, pPresentationParameters->Flags)); WriteDebugEvent(SString(" FullScreen_RefreshRateInHz:%d PresentationInterval:0x%08x", pPresentationParameters->FullScreen_RefreshRateInHz, pPresentationParameters->PresentationInterval)); // 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 // Detect if second call to CreateDevice if (CreateDeviceSecondCallCheck(hResult, m_pDevice, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface)) { return hResult; } // Enable the auto depth stencil parameter pPresentationParameters->EnableAutoDepthStencil = true; GetVideoModeManager()->PreCreateDevice(pPresentationParameters); // Create our object. hResult = m_pDevice->CreateDeviceEx(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, NULL, (IDirect3DDevice9Ex**)ppReturnedDeviceInterface); // Store the rendering window in the direct 3d data CDirect3DData::GetSingleton().StoreDeviceWindow(pPresentationParameters->hDeviceWindow); // Make sure the object was created successfully. if (hResult == D3D_OK) { // Apply input hook CMessageLoopHook::GetSingleton().ApplyHook(hFocusWindow); 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(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")); } hResult = HandleCreateDeviceResult(hResult, m_pDevice, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface); return hResult; }
//////////////////////////////////////////////////////////////// // // CRenderItemManager::GetDxStatus // // // //////////////////////////////////////////////////////////////// void CRenderItemManager::GetDxStatus ( SDxStatus& outStatus ) { outStatus.testMode = m_TestMode; // Copy hardware settings outStatus.videoCard.strName = m_strVideoCardName; outStatus.videoCard.iInstalledMemoryKB = m_iVideoCardMemoryKBTotal; outStatus.videoCard.strPSVersion = m_strVideoCardPSVersion; outStatus.videoCard.depthBufferFormat = m_depthBufferFormat; outStatus.videoCard.iMaxAnisotropy = g_pDeviceState->AdapterState.MaxAnisotropicSetting; outStatus.videoCard.iNumSimultaneousRTs = g_pDeviceState->DeviceCaps.NumSimultaneousRTs; // State outStatus.state.iNumShadersUsingReadableDepthBuffer = m_ShadersUsingDepthBuffer.size(); // Memory usage outStatus.videoMemoryKB.iFreeForMTA = m_iMemoryKBFreeForMTA; outStatus.videoMemoryKB.iUsedByFonts = m_iFontMemoryKBUsed; outStatus.videoMemoryKB.iUsedByTextures = m_iTextureMemoryKBUsed; outStatus.videoMemoryKB.iUsedByRenderTargets = m_iRenderTargetMemoryKBUsed; // Option settings CGameSettings* gameSettings = CCore::GetSingleton ().GetGame ()->GetSettings (); outStatus.settings.bWindowed = GetVideoModeManager()->IsDisplayModeWindowed(); outStatus.settings.iFullScreenStyle = GetVideoModeManager()->GetFullScreenStyle(); outStatus.settings.iFXQuality = gameSettings->GetFXQuality(); ; outStatus.settings.iDrawDistance = ( gameSettings->GetDrawDistance () - 0.925f ) / 0.8749f * 100; outStatus.settings.iAntiAliasing = gameSettings->GetAntiAliasing() - 1; outStatus.settings.bVolumetricShadows = false; outStatus.settings.bAllowScreenUpload = true; outStatus.settings.iStreamingMemory = 0; outStatus.settings.bGrassEffect = false; outStatus.settings.bHeatHaze = false; outStatus.settings.iAnisotropicFiltering = 0; outStatus.settings.aspectRatio = gameSettings->GetAspectRatio (); outStatus.settings.bHUDMatchAspectRatio = true; outStatus.settings.fFieldOfView = 70; outStatus.settings.bHighDetailVehicles = false; CVARS_GET ( "streaming_memory", outStatus.settings.iStreamingMemory ); CVARS_GET ( "volumetric_shadows", outStatus.settings.bVolumetricShadows ); CVARS_GET ( "allow_screen_upload", outStatus.settings.bAllowScreenUpload ); CVARS_GET ( "grass", outStatus.settings.bGrassEffect ); CVARS_GET ( "heat_haze", outStatus.settings.bHeatHaze ); CVARS_GET ( "anisotropic", outStatus.settings.iAnisotropicFiltering ); CVARS_GET ( "hud_match_aspect_ratio", outStatus.settings.bHUDMatchAspectRatio ); CVARS_GET ( "fov", outStatus.settings.fFieldOfView ); CVARS_GET ( "high_detail_vehicles", outStatus.settings.bHighDetailVehicles ); if ( outStatus.settings.iFXQuality == 0 ) { // These are always off with low fx quality outStatus.settings.bVolumetricShadows = false; outStatus.settings.bGrassEffect = false; } // Display color depth D3DFORMAT BackBufferFormat = g_pDeviceState->CreationState.PresentationParameters.BackBufferFormat; if ( BackBufferFormat >= D3DFMT_R5G6B5 && BackBufferFormat < D3DFMT_A8R3G3B2 ) outStatus.settings.b32BitColor = 0; else outStatus.settings.b32BitColor = 1; // Modify if using test mode if ( m_TestMode == DX_TEST_MODE_NO_MEM ) outStatus.videoMemoryKB.iFreeForMTA = 0; if ( m_TestMode == DX_TEST_MODE_LOW_MEM ) outStatus.videoMemoryKB.iFreeForMTA = 1; if ( m_TestMode == DX_TEST_MODE_NO_SHADER ) outStatus.videoCard.strPSVersion = "0"; }
LRESULT CALLBACK CMessageLoopHook::ProcessMessage ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { CMessageLoopHook * pThis; // Get a pointer to ourself. pThis = CMessageLoopHook::GetSingletonPtr ( ); if ( pThis ) pThis->m_ProcessMessageTimer.Reset(); // Alternate alt-tab system if ( pThis && hwnd == pThis->GetHookedWindowHandle () ) { if ( uMsg == WM_ACTIVATE && LOWORD(wParam) == WA_ACTIVE ) { GetVideoModeManager()->OnGainFocus(); } if ( uMsg == WM_ACTIVATE && LOWORD(wParam) == WA_INACTIVE ) { GetVideoModeManager()->OnLoseFocus(); } if ( uMsg == WM_PAINT ) { GetVideoModeManager()->OnPaint(); } } // Log our state if ( uMsg == WM_KILLFOCUS || (uMsg == WM_ACTIVATE && LOWORD(wParam) == WA_INACTIVE) ) { CSetCursorPosHook::GetSingleton ().DisableSetCursorPos (); } else if ( uMsg == WM_SETFOCUS || (uMsg == WM_ACTIVATE && LOWORD(wParam) != WA_INACTIVE) ) { if ( !g_pCore->GetLocalGUI ()->InputGoesToGUI () ) CSetCursorPosHook::GetSingleton ().EnableSetCursorPos (); } // Prevent GTA from knowing about kill focuses. Prevents pausing. if ( uMsg == WM_KILLFOCUS || (uMsg == WM_ACTIVATE && LOWORD(wParam) == WA_INACTIVE) ) { return true; } // Disable the system context menu by clicking in the process icon or pressing ALT+SPACE. if ( uMsg == WM_SYSCOMMAND ) { if ( wParam == 0xF093 || wParam == SC_KEYMENU || wParam == SC_MOUSEMENU ) return 0; } // Quit message? if ( uMsg == WM_CLOSE ) { g_pCore->Quit (); } if ( uMsg == WM_COPYDATA ) { PCOPYDATASTRUCT pCDS = (PCOPYDATASTRUCT) lParam; if ( pCDS->dwData == URI_CONNECT ) { LPSTR szConnectInfo = (LPSTR) pCDS->lpData; CCommandFuncs::Connect ( szConnectInfo ); } } // Make sure our pointers are valid. if ( pThis != NULL && hwnd == pThis->GetHookedWindowHandle () && g_pCore->AreModulesLoaded() ) { g_pCore->UpdateIsWindowMinimized (); // Force update of stuff if ( uMsg == WM_TIMER && wParam == IDT_TIMER1 ) g_pCore->WindowsTimerHandler(); // Used for 'minimized before first game' pulses // Handle IME if input is not for the GUI if ( !g_pCore->GetLocalGUI ()->InputGoesToGUI () ) { if ( uMsg == WM_KEYDOWN ) { // Recover virtual key if ( wParam == VK_PROCESSKEY ) wParam = MapVirtualKey ( lParam >> 16, MAPVK_VSC_TO_VK_EX ); } if ( uMsg == WM_IME_STARTCOMPOSITION || uMsg == WM_IME_ENDCOMPOSITION || uMsg == WM_IME_COMPOSITION ) { // Cancel, stop, block and ignore HIMC himc = ImmGetContext ( hwnd ); ImmNotifyIME ( himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0 ); ImmReleaseContext ( hwnd, himc ); return true; } } // Pass escape keyup to onClientKey if ( uMsg == WM_KEYUP && wParam == VK_ESCAPE ) { g_pCore->GetKeyBinds()->TriggerKeyStrokeHandler ( "escape", uMsg == WM_KEYDOWN, true ); return true; } // Suppress auto repeat of escape and console toggle keys if ( ( uMsg == WM_KEYDOWN || uMsg == WM_CHAR ) && ( wParam == VK_ESCAPE || wParam == VK_F8 || wParam == '`' ) ) { bool bFirstHit = ( lParam & 0x40000000 ) ? false:true; if ( !bFirstHit ) return true; } // Slightly hacky way of suppressing escape character when console is closed with escape key if ( uMsg == WM_CHAR && wParam == VK_ESCAPE ) { bool bTemp = ms_bIgnoreNextEscapeCharacter; ms_bIgnoreNextEscapeCharacter = false; if ( bTemp ) return true; } if ( CKeyBinds::IsFakeCtrl_L ( uMsg, wParam, lParam ) ) return true; // See if this is message was caused by our asynchronous sockets if ( uMsg >= WM_ASYNCTRAP && uMsg <= ( WM_ASYNCTRAP + 511 )) { /* ACHTUNG: uMsg - 10? Windows seems to add 10 or there's a bug in the message code. Hack! */ // Let the CTCPManager handle it CTCPManager::GetSingletonPtr ()->HandleEvent ( ( uMsg - WM_ASYNCTRAP ), wParam, lParam ); } bool bWasCaptureKey = false; CMainMenu* pMainMenu = g_pCore->GetLocalGUI ()->GetMainMenu (); if ( pMainMenu ) { CSettings* pSettings = pMainMenu->GetSettingsWindow (); if ( pSettings ) { if ( uMsg == WM_KEYDOWN && wParam == VK_ESCAPE && GetJoystickManager ()->IsCapturingAxis () ) { GetJoystickManager ()->CancelCaptureAxis ( true ); return true; } bWasCaptureKey = ( pSettings->IsCapturingKey () && pSettings->ProcessMessage ( uMsg, wParam, lParam ) ); if ( !bWasCaptureKey ) { // If Escape is pressed and we're playing ingame, we show/hide the menu if ( uMsg == WM_KEYDOWN && wParam == VK_ESCAPE && g_pCore->IsConnected () ) { // Hide the console CConsoleInterface* pConsole = g_pCore->GetConsole (); if ( pConsole->IsVisible () ) { ms_bIgnoreNextEscapeCharacter = true; pConsole->SetVisible ( false ); return true; } // The mainmenu makes sure it isn't hidden if UseIngameButtons == false if ( !CCore::GetSingleton().IsOfflineMod () ) { if ( g_pCore->GetKeyBinds()->TriggerKeyStrokeHandler ( "escape", uMsg == WM_KEYDOWN, true ) ) { // Stop chat input if ( CLocalGUI::GetSingleton ().IsChatBoxInputEnabled () ) { CLocalGUI::GetSingleton ().SetChatBoxInputEnabled ( false ); return true; } CLocalGUI::GetSingleton ().SetMainMenuVisible ( !CLocalGUI::GetSingleton ().IsMainMenuVisible () ); } return true; } } else if ( uMsg == WM_KEYDOWN && wParam == VK_ESCAPE && !g_pCore->IsConnected () ) { // If Escape is pressed and we're not playing ingame, hide certain windows CLocalGUI::GetSingleton ().GetMainMenu ()->OnEscapePressedOffLine (); } // If CTRL and Tab are pressed, Trigger a skip if ( ( uMsg == WM_KEYDOWN && wParam == VK_TAB ) ) { eSystemState systemState = g_pCore->GetGame ()->GetSystemState (); if ( systemState == 7 || systemState == 8 || systemState == 9 ) { short sCtrlState = GetKeyState ( VK_CONTROL ); short sShiftState = GetKeyState ( VK_SHIFT ); if ( sCtrlState & 0x8000 ) { CSettings * pSettings = CLocalGUI::GetSingleton ().GetMainMenu ()->GetSettingsWindow (); CServerBrowser * pServerBrowser = CLocalGUI::GetSingleton ().GetMainMenu ()->GetServerBrowser (); if ( pSettings && pSettings->IsVisible ( ) && pSettings->IsActive ( ) ) { pSettings->TabSkip ( ( sShiftState & 0x8000 ) ? true : false ); } else if ( pServerBrowser && pServerBrowser->IsVisible ( ) && pServerBrowser->IsActive ( ) ) { pServerBrowser->TabSkip ( ( sShiftState & 0x8000 ) ? true : false ); } } } } if ( ( uMsg == WM_KEYDOWN && ( wParam >= VK_1 && wParam <= VK_9 ) ) ) { eSystemState systemState = g_pCore->GetGame ()->GetSystemState (); if ( systemState == 7 || systemState == 8 || systemState == 9 ) { short sCtrlState = GetKeyState ( VK_CONTROL ); if ( sCtrlState & 0x8000 ) { CSettings * pSettings = CLocalGUI::GetSingleton ().GetMainMenu ()->GetSettingsWindow (); CServerBrowser * pServerBrowser = CLocalGUI::GetSingleton ().GetMainMenu ()->GetServerBrowser (); if ( pSettings && pSettings->IsVisible ( ) && pSettings->IsActive ( ) ) { pSettings->SetSelectedIndex ( ( wParam - VK_1 ) - 1 ); } else if ( pServerBrowser && pServerBrowser->IsVisible ( ) && pServerBrowser->IsActive ( ) ) { pServerBrowser->SetSelectedIndex ( ( wParam - VK_1 ) - 1 ); } } } } // If F8 is pressed, we show/hide the console if ( ( uMsg == WM_KEYDOWN && wParam == VK_F8 ) || ( uMsg == WM_CHAR && wParam == '`' ) ) { eSystemState systemState = g_pCore->GetGame ()->GetSystemState (); if ( CLocalGUI::GetSingleton ().IsConsoleVisible () || systemState == 7 || systemState == 8 || systemState == 9 ) /* GS_FRONTEND, GS_INIT_PLAYING_GAME, GS_PLAYING_GAME */ { CLocalGUI::GetSingleton ().SetConsoleVisible ( !CLocalGUI::GetSingleton ().IsConsoleVisible () ); } return true; } // If the console is accepting input, and we pressed down/up, scroll the console history // or if we pressed tab, step through possible autocomplete matches if ( CLocalGUI::GetSingleton ().GetConsole()->IsInputActive() ) { if ( uMsg == WM_KEYDOWN ) { if ( wParam == VK_DOWN ) { CLocalGUI::GetSingleton ().GetConsole ()->SetPreviousHistoryText (); } if ( wParam == VK_UP ) { CLocalGUI::GetSingleton ().GetConsole ()->SetNextHistoryText (); } if ( wParam == VK_TAB ) { CLocalGUI::GetSingleton ().GetConsole ()->SetNextAutoCompleteMatch (); } else { CLocalGUI::GetSingleton ().GetConsole ()->ResetAutoCompleteMatch (); } } } else if ( uMsg == WM_KEYDOWN && CLocalGUI::GetSingleton().GetMainMenu()->GetServerBrowser()->IsAddressBarAwaitingInput() ) { if ( wParam == VK_DOWN ) { CLocalGUI::GetSingleton().GetMainMenu()->GetServerBrowser()->SetNextHistoryText ( true ); } if ( wParam == VK_UP ) { CLocalGUI::GetSingleton().GetMainMenu()->GetServerBrowser()->SetNextHistoryText ( false ); } } } } } if ( !bWasCaptureKey ) { // Store our keydown for backup unicode translation if ( uMsg == WM_KEYDOWN ) { m_LastVirtualKeyCode = wParam; m_LastScanCode = (BYTE)((lParam >> 16) & 0x000F); GetKeyboardState( m_LastKeyboardState ); } // If it was a question mark character, we may have an unprocessed unicode character if ( uMsg == WM_CHAR && wParam == 0x3F ) { wchar_t* wcsUnicode = new wchar_t[1]; ToUnicodeEx ( m_LastVirtualKeyCode, m_LastScanCode, m_LastKeyboardState, wcsUnicode, 1, 0, GetKeyboardLayout(0) ); wParam = (WPARAM)wcsUnicode[0]; delete wcsUnicode; } // Lead the message through the keybinds message processor g_pCore->GetKeyBinds ()->ProcessMessage ( hwnd, uMsg, wParam, lParam ); bool bProcessed = false, bClientProcessed = false; // Check and see if the GUI should process this message bProcessed = CLocalGUI::GetSingleton ().ProcessMessage ( hwnd, uMsg, wParam, lParam ); // Check and see if the Core/mod should process this message if ( !CCore::GetSingleton ().GetGame ()->IsAtMenu() ) { pfnProcessMessage pfnClientMessageProcessor = CCore::GetSingleton ().GetClientMessageProcessor(); if ( pfnClientMessageProcessor ) { bClientProcessed = pfnClientMessageProcessor ( hwnd, uMsg, wParam, lParam ); } } // If GTA can process this key if ( !bProcessed && !bClientProcessed ) { // ALWAYS return true on escape to stop us getting to GTA's menu if ( uMsg == WM_KEYDOWN && wParam == VK_ESCAPE ) { return true; } // Prevent game window auto-minimizing if full screen and: // 1. More than one monitor present // and 2. Minimizing option disabled // or // 1. Starting up (Main menu has not been displayed yet) if ( uMsg == WM_ACTIVATE || uMsg == WM_ACTIVATEAPP || uMsg == WM_NCACTIVATE || uMsg == WM_SETFOCUS || uMsg == WM_KILLFOCUS ) { if ( !GetVideoModeManager ()->IsWindowed () ) { if ( !CLocalGUI::GetSingleton ().GetMainMenu () || !CLocalGUI::GetSingleton ().GetMainMenu ()->HasStarted () ) return true; // No auto-minimize if ( GetVideoModeManager ()->IsMultiMonitor () && !GetVideoModeManager ()->IsMinimizeEnabled () ) return true; // No auto-minimize } } /* // Should not really ever get here, just in case. else if ( uMsg == WM_SIZE ) { if ( wParam == SIZE_MINIMIZED ) { ShowWindow ( pThis->GetHookedWindowHandle(), SW_RESTORE ); return true; } } */ if ( uMsg == WM_SYSCOMMAND && wParam == 0xF012 ) // SC_DRAGMOVE { CMessageLoopHook::GetSingleton().StartWindowMovement (); return true; } // If we handled mouse steering, don't let GTA. //if ( !CCore::GetSingleton ().GetMouseControl()->ProcessMouseMove ( uMsg, wParam, lParam ) ) // Call GTA's window procedure. return CallWindowProcW ( pThis->m_HookedWindowProc, hwnd, uMsg, wParam, lParam ); } // Don't allow DefWindowProc if processed here. (Important for IME) return true; }