diff --git a/.gitattributes b/.gitattributes index e69de29bb..1003d3bd2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -0,0 +1 @@ +* !text !filter !merge !diff diff --git a/MediaWindows64.arc b/MediaWindows64.arc new file mode 100644 index 000000000..1e388818e Binary files /dev/null and b/MediaWindows64.arc differ diff --git a/Minecraft.Client/Common/App_enums.h b/Minecraft.Client/Common/App_enums.h index 15a179787..18dff99d3 100644 --- a/Minecraft.Client/Common/App_enums.h +++ b/Minecraft.Client/Common/App_enums.h @@ -133,6 +133,8 @@ enum eGameSetting { eGameSetting_MusicVolume=0, eGameSetting_SoundFXVolume, + eGameSetting_FpsCap, + eGameSetting_VSync, eGameSetting_RenderDistance, eGameSetting_Gamma, eGameSetting_FOV, @@ -157,32 +159,24 @@ enum eGameSetting eGameSetting_InviteOnly, eGameSetting_FriendsOfFriends, eGameSetting_DisplayUpdateMessage, - // TU6 eGameSetting_BedrockFog, eGameSetting_DisplayHUD, eGameSetting_DisplayHand, - // TU7 eGameSetting_CustomSkinAnim, - // TU9 eGameSetting_DeathMessages, eGameSetting_UISize, eGameSetting_UISizeSplitscreen, eGameSetting_AnimatedCharacter, - // PS3 eGameSetting_PS3_EULA_Read, - // PSVita eGameSetting_PSVita_NetworkModeAdhoc, - - }; - enum eGameMode { eMode_Singleplayer, diff --git a/Minecraft.Client/Common/App_structs.h b/Minecraft.Client/Common/App_structs.h index 6a6e03546..62c6c9987 100644 --- a/Minecraft.Client/Common/App_structs.h +++ b/Minecraft.Client/Common/App_structs.h @@ -67,6 +67,8 @@ typedef struct unsigned char ucInterfaceOpacity; unsigned char ucPad02; // 1 byte padding unsigned char ucFov; + unsigned char ucFpsCap; + unsigned char ucVSync; // Adding another bitmask flag for more settings for 1.8.2 unsigned int uiBitmaskValues; // 0x00000001 - eGameSetting_Clouds - on diff --git a/Minecraft.Client/Common/Consoles_App.cpp b/Minecraft.Client/Common/Consoles_App.cpp index c3a623d5f..2abf4a8b7 100644 --- a/Minecraft.Client/Common/Consoles_App.cpp +++ b/Minecraft.Client/Common/Consoles_App.cpp @@ -771,6 +771,7 @@ static void Win64_GetSettingsPath(char *outPath, DWORD size) static void Win64_SaveSettings(GAME_SETTINGS *gs) { if (!gs) return; + printf("[DEBUG] Win64_SaveSettings: VSync=%d before save\n", gs->ucVSync); char filePath[MAX_PATH] = {}; Win64_GetSettingsPath(filePath, MAX_PATH); FILE *f = nullptr; @@ -778,6 +779,11 @@ static void Win64_SaveSettings(GAME_SETTINGS *gs) { fwrite(gs, sizeof(GAME_SETTINGS), 1, f); fclose(f); + printf("[DEBUG] Win64_SaveSettings: Settings saved to %s\n", filePath); + } + else + { + printf("[DEBUG] Win64_SaveSettings: Failed to open file %s\n", filePath); } } static void Win64_LoadSettings(GAME_SETTINGS *gs) @@ -790,8 +796,16 @@ static void Win64_LoadSettings(GAME_SETTINGS *gs) { GAME_SETTINGS temp = {}; if (fread(&temp, sizeof(GAME_SETTINGS), 1, f) == 1) + { memcpy(gs, &temp, sizeof(GAME_SETTINGS)); + printf("[DEBUG] Win64_LoadSettings: VSync=%d after load\n", gs->ucVSync); + } fclose(f); + printf("[DEBUG] Win64_LoadSettings: Settings loaded from %s\n", filePath); + } + else + { + printf("[DEBUG] Win64_LoadSettings: Failed to open file %s, using defaults\n", filePath); } } #endif @@ -838,6 +852,9 @@ int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,con SetGameSettings(iPad,eGameSetting_RenderDistance,16); SetGameSettings(iPad,eGameSetting_Gamma,50); SetGameSettings(iPad,eGameSetting_FOV,0); + SetGameSettings(iPad,eGameSetting_FpsCap,1); + SetGameSettings(iPad,eGameSetting_VSync,0); + printf("[DEBUG] VSync initialized to OFF (0) for pad %d\n", iPad); // 4J-PB - Don't reset the difficult level if we're in-game if(Minecraft::GetInstance()->level==nullptr) @@ -1411,6 +1428,10 @@ void CMinecraftApp::ActionGameSettings(int iPad,eGameSetting eVal) pMinecraft->options->set(Options::Option::FOV, (float)GameSettingsA[iPad]->ucFov / 100.0f); } break; + case eGameSetting_FpsCap: + break; + case eGameSetting_VSync: + break; case eGameSetting_Difficulty: if(iPad==ProfileManager.GetPrimaryPad()) { @@ -1890,6 +1911,22 @@ void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucV GameSettingsA[iPad]->bSettingsChanged=true; } break; + case eGameSetting_FpsCap: + if(GameSettingsA[iPad]->ucFpsCap!=ucVal) + { + GameSettingsA[iPad]->ucFpsCap=ucVal; + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_VSync: + printf("[DEBUG] SetGameSettings VSync: pad=%d, old=%d, new=%d\n", iPad, GameSettingsA[iPad]->ucVSync, ucVal); + if(GameSettingsA[iPad]->ucVSync!=ucVal) + { + GameSettingsA[iPad]->ucVSync=ucVal; + GameSettingsA[iPad]->bSettingsChanged=true; + printf("[DEBUG] VSync setting updated to: %d\n", ucVal); + } + break; case eGameSetting_Difficulty: if((GameSettingsA[iPad]->usBitmaskValues&0x03)!=(ucVal&0x03)) { @@ -2442,6 +2479,13 @@ unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal) case eGameSetting_PSVita_NetworkModeAdhoc: return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)>>17; + case eGameSetting_FpsCap: + return GameSettingsA[iPad]->ucFpsCap; + + case eGameSetting_VSync: + printf("[DEBUG] GetGameSettings VSync: pad=%d, value=%d\n", iPad, GameSettingsA[iPad]->ucVSync); + return GameSettingsA[iPad]->ucVSync; + } return 0; } diff --git a/Minecraft.Client/Common/Media/MediaWindows64.arc b/Minecraft.Client/Common/Media/MediaWindows64.arc index 6ce552c53..1e388818e 100644 Binary files a/Minecraft.Client/Common/Media/MediaWindows64.arc and b/Minecraft.Client/Common/Media/MediaWindows64.arc differ diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp index b258d8c31..31bdb7d8e 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp @@ -10,6 +10,15 @@ namespace constexpr int FOV_MIN = 70; constexpr int FOV_MAX = 110; constexpr int FOV_SLIDER_MAX = 100; + constexpr int fpsCaps[] = { 30, 60, 120, 0 }; + + void formatFpsCapLabel(WCHAR* buf, int idx) + { + if (fpsCaps[idx] == 0) + swprintf(buf, 256, L"Max Framerate: Unlimited"); + else + swprintf(buf, 256, L"Max Framerate: %d", fpsCaps[idx]); + } int ClampFov(int value) { @@ -62,8 +71,10 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD m_checkboxClouds.init(app.GetString(IDS_CHECKBOX_RENDER_CLOUDS),eControl_Clouds,(app.GetGameSettings(m_iPad,eGameSetting_Clouds)!=0)); m_checkboxBedrockFog.init(app.GetString(IDS_CHECKBOX_RENDER_BEDROCKFOG),eControl_BedrockFog,(app.GetGameSettings(m_iPad,eGameSetting_BedrockFog)!=0)); m_checkboxCustomSkinAnim.init(app.GetString(IDS_CHECKBOX_CUSTOM_SKIN_ANIM),eControl_CustomSkinAnim,(app.GetGameSettings(m_iPad,eGameSetting_CustomSkinAnim)!=0)); + m_checkboxVSync.init(L"VSync",eControl_VSync,(app.GetGameSettings(m_iPad,eGameSetting_VSync)!=0)); + WCHAR TempString[256]; swprintf(TempString, 256, L"Render Distance: %d",app.GetGameSettings(m_iPad,eGameSetting_RenderDistance)); @@ -80,6 +91,11 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD swprintf( TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_INTERFACEOPACITY ),app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity)); m_sliderInterfaceOpacity.init(TempString,eControl_InterfaceOpacity,0,100,app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity)); + int fpsCapIndex = (int)app.GetGameSettings(m_iPad, eGameSetting_FpsCap); + if (fpsCapIndex < 0 || fpsCapIndex > 3) fpsCapIndex = 1; + formatFpsCapLabel(TempString, fpsCapIndex); + m_sliderFpsCap.init(TempString, eControl_FpsCap, 0, 3, fpsCapIndex); + doHorizontalResizeCheck(); const bool bInGame=(Minecraft::GetInstance()->level!=nullptr); @@ -165,6 +181,7 @@ void UIScene_SettingsGraphicsMenu::handleInput(int iPad, int key, bool repeat, b app.SetGameSettings(m_iPad,eGameSetting_Clouds,m_checkboxClouds.IsChecked()?1:0); app.SetGameSettings(m_iPad,eGameSetting_BedrockFog,m_checkboxBedrockFog.IsChecked()?1:0); app.SetGameSettings(m_iPad,eGameSetting_CustomSkinAnim,m_checkboxCustomSkinAnim.IsChecked()?1:0); + app.SetGameSettings(m_iPad,eGameSetting_VSync,m_checkboxVSync.IsChecked()?1:0); navigateBack(); handled = true; @@ -236,5 +253,17 @@ void UIScene_SettingsGraphicsMenu::handleSliderMove(F64 sliderId, F64 currentVal m_sliderInterfaceOpacity.setLabel(TempString); break; + + case eControl_FpsCap: + { + int idx = value; + if (idx < 0) idx = 0; + if (idx > 3) idx = 3; + m_sliderFpsCap.handleSliderMove(idx); + app.SetGameSettings(m_iPad, eGameSetting_FpsCap, idx); + formatFpsCapLabel(TempString, idx); + m_sliderFpsCap.setLabel(TempString); + } + break; } } diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h index 99022c83f..22b1ef0ce 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h @@ -15,19 +15,23 @@ class UIScene_SettingsGraphicsMenu : public UIScene eControl_RenderDistance, eControl_Gamma, eControl_FOV, - eControl_InterfaceOpacity + eControl_InterfaceOpacity, + eControl_FpsCap, + eControl_VSync }; - UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim; // Checkboxes - UIControl_Slider m_sliderRenderDistance, m_sliderGamma, m_sliderFOV, m_sliderInterfaceOpacity; // Sliders + UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim, m_checkboxVSync; + UIControl_Slider m_sliderRenderDistance, m_sliderGamma, m_sliderFOV, m_sliderInterfaceOpacity, m_sliderFpsCap; UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) UI_MAP_ELEMENT( m_checkboxClouds, "Clouds") UI_MAP_ELEMENT( m_checkboxBedrockFog, "BedrockFog") UI_MAP_ELEMENT( m_checkboxCustomSkinAnim, "CustomSkinAnim") + UI_MAP_ELEMENT( m_checkboxVSync, "VSync") UI_MAP_ELEMENT( m_sliderRenderDistance, "RenderDistance") UI_MAP_ELEMENT( m_sliderGamma, "Gamma") UI_MAP_ELEMENT(m_sliderFOV, "FOV") UI_MAP_ELEMENT( m_sliderInterfaceOpacity, "InterfaceOpacity") + UI_MAP_ELEMENT( m_sliderFpsCap, "FpsCap") UI_END_MAP_ELEMENTS_AND_NAMES() bool m_bNotInGame; diff --git a/Minecraft.Client/GameRenderer.cpp b/Minecraft.Client/GameRenderer.cpp index 73b39529c..f8ed3f154 100644 --- a/Minecraft.Client/GameRenderer.cpp +++ b/Minecraft.Client/GameRenderer.cpp @@ -2240,13 +2240,13 @@ FloatBuffer *GameRenderer::getBuffer(float a, float b, float c, float d) int GameRenderer::getFpsCap(int option) { - int maxFps = 200; - if (option == 1) maxFps = 120; - if (option == 2) maxFps = 35; - return maxFps; + static const int fpsCaps[] = {30, 60, 120, 0}; + if (option < 0 || option > 3) return 0; + return fpsCaps[option]; } + void GameRenderer::updateAllChunks() { // mc->levelRenderer->updateDirtyChunks(mc->cameraTargetPlayer, true); -} +} \ No newline at end of file diff --git a/Minecraft.Client/GameRenderer.h b/Minecraft.Client/GameRenderer.h index c379106e0..a2856e1f3 100644 --- a/Minecraft.Client/GameRenderer.h +++ b/Minecraft.Client/GameRenderer.h @@ -163,8 +163,8 @@ class GameRenderer void setupFog(int i, float alpha); FloatBuffer *getBuffer(float a, float b, float c, float d); - static int getFpsCap(int option); public: + static int getFpsCap(int option); void updateAllChunks(); #ifdef MULTITHREAD_ENABLE diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index 70aeb22bf..a6de636a9 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -1959,8 +1959,29 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, RenderManager.Set_matrixDirty(); #endif + { + int maxFps = GameRenderer::getFpsCap(app.GetGameSettings(0, eGameSetting_FpsCap)); + if (maxFps > 0) + { + static LONGLONG lastTime = 0; + LARGE_INTEGER freq, now; + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&now); + LONGLONG targetInterval = freq.QuadPart / maxFps; + LONGLONG elapsed = now.QuadPart - lastTime; + if (elapsed < targetInterval) + { + DWORD sleepMs = (DWORD)((targetInterval - elapsed) * 1000 / freq.QuadPart); + if (sleepMs > 0) Sleep(sleepMs); + } + QueryPerformanceCounter(&now); + lastTime = now.QuadPart; + } + } // Present the frame. - RenderManager.Present(); + int vsyncSetting = app.GetGameSettings(ProfileManager.GetPrimaryPad(), eGameSetting_VSync); + printf("[DEBUG] VSync setting: %d (0=OFF, 1=ON)\n", vsyncSetting); + g_pSwapChain->Present(vsyncSetting ? 1 : 0, 0); ui.CheckMenuDisplayed();