diff --git a/Client/core/CClientVariables.cpp b/Client/core/CClientVariables.cpp index ce823f0763..00ac9ab942 100644 --- a/Client/core/CClientVariables.cpp +++ b/Client/core/CClientVariables.cpp @@ -398,6 +398,7 @@ void CClientVariables::LoadDefaults() DEFAULT("browser_enable_gpu", true); // Enable GPU in CEF? (allows stuff like WebGL to function) DEFAULT("browser_enable_video_acceleration", true); // Enable hardware video decoding in CEF? DEFAULT("process_cpu_affinity", true); // Set CPU 0 affinity to improve game performance and fix the known issue in single-threaded games + DEFAULT("img_file_caching", false); // Preserve GTA's original IMG read behavior unless caching is explicitly enabled DEFAULT("ask_before_disconnect", true); // Ask before disconnecting from a server DEFAULT("allow_steam_client", false); // Allow connecting with the local Steam client (to set GTA:SA ingame status) DEFAULT("use_mouse_sensitivity_for_aiming", diff --git a/Client/core/CSettings.cpp b/Client/core/CSettings.cpp index d956181d5c..9fe1826e10 100644 --- a/Client/core/CSettings.cpp +++ b/Client/core/CSettings.cpp @@ -1720,7 +1720,7 @@ void CSettings::CreateGUI() vecTemp = CVector2D(12.f, 12.f); float fComboWidth = 170.f; float fHeaderHeight = 20; - float fLineHeight = 27; + float fLineHeight = 25; // Misc section label m_pAdvancedMiscLabel = reinterpret_cast(pManager->CreateLabel(pTabAdvanced, _("Misc"))); @@ -1906,6 +1906,15 @@ void CSettings::CreateGUI() m_pProcessAffinityCheckbox->AutoSize(nullptr, 20.0f); vecTemp.fY += fLineHeight; + // Let users opt into Windows caching while preserving GTA's original IMG reads by default. + m_pIMGFileCachingCheckbox = + reinterpret_cast(pManager->CreateCheckBox(pTabAdvanced, _("Enable Windows file caching for IMG archives"), false)); + m_pIMGFileCachingCheckbox->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY)); + m_pIMGFileCachingCheckbox->AutoSize(nullptr, 20.0f); + m_pIMGFileCachingCheckbox->SetMouseEnterHandler(GUI_CALLBACK(&CSettings::OnShowAdvancedSettingDescription, this)); + m_pIMGFileCachingCheckbox->SetMouseLeaveHandler(GUI_CALLBACK(&CSettings::OnHideAdvancedSettingDescription, this)); + vecTemp.fY += fLineHeight; + // Auto updater section label m_pAdvancedUpdaterLabel = reinterpret_cast(pManager->CreateLabel(pTabAdvanced, _("Auto updater"))); m_pAdvancedUpdaterLabel->SetPosition(CVector2D(vecTemp.fX - 10.0f, vecTemp.fY)); @@ -1957,11 +1966,11 @@ void CSettings::CreateGUI() vecTemp.fX -= fComboWidth + 15; // Description label - vecTemp.fY += 15.0f; + vecTemp.fY += 2.0f; m_pAdvancedSettingDescriptionLabel = reinterpret_cast(pManager->CreateLabel(pTabAdvanced, "")); - m_pAdvancedSettingDescriptionLabel->SetPosition(CVector2D(vecTemp.fX + 10.f, vecTemp.fY)); - m_pAdvancedSettingDescriptionLabel->SetFont("default-bold-small"); - m_pAdvancedSettingDescriptionLabel->SetSize(CVector2D(500.0f, 95.0f)); + m_pAdvancedSettingDescriptionLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY)); + m_pAdvancedSettingDescriptionLabel->SetFont("default"); + m_pAdvancedSettingDescriptionLabel->SetSize(CVector2D(std::max(1.0f, tabPanelSize.fX - 2.0f * vecTemp.fX), 95.0f)); m_pAdvancedSettingDescriptionLabel->SetHorizontalAlign(CGUI_ALIGN_HORIZONTALCENTER_WORDWRAP); // Set up the events @@ -4162,6 +4171,9 @@ void CSettings::LoadData() CVARS_GET("photosaving", bVar); m_pPhotoSavingCheckbox->SetSelected(bVar); + CVARS_GET("img_file_caching", bVar); + m_pIMGFileCachingCheckbox->SetSelected(bVar); + // Process CPU Affinity CVARS_GET("process_cpu_affinity", bVar); m_pProcessAffinityCheckbox->SetSelected(bVar); @@ -4606,6 +4618,11 @@ void CSettings::SaveData() CVARS_SET("photosaving", photoSaving); CScreenShot::SetPhotoSavingInsideDocuments(photoSaving); + // Archive handles retain their opening flags, so save the preference and request a restart. + const bool bIMGFileCaching = m_pIMGFileCachingCheckbox->GetSelected(); + const bool bIMGFileCachingChanged = bIMGFileCaching != CVARS_GET_VALUE("img_file_caching"); + CVARS_SET("img_file_caching", bIMGFileCaching); + // Process CPU Affinity bool affinity = m_pProcessAffinityCheckbox->GetSelected(); CVARS_SET("process_cpu_affinity", affinity); @@ -4794,7 +4811,7 @@ void CSettings::SaveData() // Ask to restart? if (bIsVideoModeChanged || bIsAntiAliasingChanged || bIsCustomizedSAFilesChanged || processsDPIAwareChanged || bBrowserGPUSettingChanged || - bBrowserVideoAccelSettingChanged) + bBrowserVideoAccelSettingChanged || bIMGFileCachingChanged) ShowRestartQuestion(); else if (CModManager::GetSingleton().IsLoaded() && bBrowserSettingChanged) ShowDisconnectQuestion(); @@ -6122,6 +6139,10 @@ bool CSettings::OnShowAdvancedSettingDescription(CGUIElement* pElement) strText = std::string(_("Auto updater:")) + " " + std::string(_("Select default to automatically install important updates.")); else if (pCheckBox && pCheckBox == m_pProcessAffinityCheckbox) strText = std::string(_("CPU affinity:")) + " " + std::string(_("Only change if you're having stability issues.")); + else if (pCheckBox && pCheckBox == m_pIMGFileCachingCheckbox) + strText = + _("Off by default to preserve GTA's original behavior. When enabled, removes FILE_FLAG_NO_BUFFERING so Windows can cache IMG game archives in RAM. " + "This may reduce disk reads and loading stutter on SSDs and HDDs. Try turning it off if performance worsens. Requires restarting MTA."); if (strText != "") m_pAdvancedSettingDescriptionLabel->SetText(strText.c_str()); diff --git a/Client/core/CSettings.h b/Client/core/CSettings.h index 864feadb72..cbe6ce9778 100644 --- a/Client/core/CSettings.h +++ b/Client/core/CSettings.h @@ -240,6 +240,7 @@ class CSettings CGUICheckBox* m_pPhotoSavingCheckbox; CGUICheckBox* m_pCheckBoxAskBeforeDisconnect; CGUICheckBox* m_pProcessAffinityCheckbox; + CGUICheckBox* m_pIMGFileCachingCheckbox; CGUILabel* m_pUpdateBuildTypeLabel; CGUIComboBox* m_pUpdateBuildTypeCombo; CGUILabel* m_pUpdateAutoInstallLabel; diff --git a/Client/game_sa/gamesa_init.cpp b/Client/game_sa/gamesa_init.cpp index f071433a34..366cc95f46 100644 --- a/Client/game_sa/gamesa_init.cpp +++ b/Client/game_sa/gamesa_init.cpp @@ -36,6 +36,12 @@ MTAEXPORT CGame* GetGameInterface(CCoreInterface* pCore) pGame = new CGameSA; g_pCore = pCore; + // Remove FILE_FLAG_NO_BUFFERING to let Windows cache IMG reads and reduce disk I/O. + // Apply this before CdStreamInit opens archives; existing handles require a restart to change their flags. + bool bIMGFileCaching = false; + pCore->GetCVars()->Get("img_file_caching", bIMGFileCaching); + MemPut(0x406BC6, bIMGFileCaching ? 0xEB : 0x77); + return (CGame*)pGame; }