mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
Fixed framerate limit and vsync logic
This commit is contained in:
parent
86c7b57272
commit
320e4eac44
|
|
@ -67,6 +67,8 @@ typedef struct
|
||||||
unsigned char ucInterfaceOpacity;
|
unsigned char ucInterfaceOpacity;
|
||||||
unsigned char ucPad02; // 1 byte padding
|
unsigned char ucPad02; // 1 byte padding
|
||||||
unsigned char ucFov;
|
unsigned char ucFov;
|
||||||
|
unsigned char ucFpsCap;
|
||||||
|
unsigned char ucVSync;
|
||||||
|
|
||||||
// Adding another bitmask flag for more settings for 1.8.2
|
// Adding another bitmask flag for more settings for 1.8.2
|
||||||
unsigned int uiBitmaskValues; // 0x00000001 - eGameSetting_Clouds - on
|
unsigned int uiBitmaskValues; // 0x00000001 - eGameSetting_Clouds - on
|
||||||
|
|
|
||||||
|
|
@ -771,6 +771,7 @@ static void Win64_GetSettingsPath(char *outPath, DWORD size)
|
||||||
static void Win64_SaveSettings(GAME_SETTINGS *gs)
|
static void Win64_SaveSettings(GAME_SETTINGS *gs)
|
||||||
{
|
{
|
||||||
if (!gs) return;
|
if (!gs) return;
|
||||||
|
printf("[DEBUG] Win64_SaveSettings: VSync=%d before save\n", gs->ucVSync);
|
||||||
char filePath[MAX_PATH] = {};
|
char filePath[MAX_PATH] = {};
|
||||||
Win64_GetSettingsPath(filePath, MAX_PATH);
|
Win64_GetSettingsPath(filePath, MAX_PATH);
|
||||||
FILE *f = nullptr;
|
FILE *f = nullptr;
|
||||||
|
|
@ -778,6 +779,11 @@ static void Win64_SaveSettings(GAME_SETTINGS *gs)
|
||||||
{
|
{
|
||||||
fwrite(gs, sizeof(GAME_SETTINGS), 1, f);
|
fwrite(gs, sizeof(GAME_SETTINGS), 1, f);
|
||||||
fclose(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)
|
static void Win64_LoadSettings(GAME_SETTINGS *gs)
|
||||||
|
|
@ -790,8 +796,16 @@ static void Win64_LoadSettings(GAME_SETTINGS *gs)
|
||||||
{
|
{
|
||||||
GAME_SETTINGS temp = {};
|
GAME_SETTINGS temp = {};
|
||||||
if (fread(&temp, sizeof(GAME_SETTINGS), 1, f) == 1)
|
if (fread(&temp, sizeof(GAME_SETTINGS), 1, f) == 1)
|
||||||
|
{
|
||||||
memcpy(gs, &temp, sizeof(GAME_SETTINGS));
|
memcpy(gs, &temp, sizeof(GAME_SETTINGS));
|
||||||
|
printf("[DEBUG] Win64_LoadSettings: VSync=%d after load\n", gs->ucVSync);
|
||||||
|
}
|
||||||
fclose(f);
|
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
|
#endif
|
||||||
|
|
@ -838,6 +852,9 @@ int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,con
|
||||||
SetGameSettings(iPad,eGameSetting_RenderDistance,16);
|
SetGameSettings(iPad,eGameSetting_RenderDistance,16);
|
||||||
SetGameSettings(iPad,eGameSetting_Gamma,50);
|
SetGameSettings(iPad,eGameSetting_Gamma,50);
|
||||||
SetGameSettings(iPad,eGameSetting_FOV,0);
|
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
|
// 4J-PB - Don't reset the difficult level if we're in-game
|
||||||
if(Minecraft::GetInstance()->level==nullptr)
|
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);
|
pMinecraft->options->set(Options::Option::FOV, (float)GameSettingsA[iPad]->ucFov / 100.0f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case eGameSetting_FpsCap:
|
||||||
|
break;
|
||||||
|
case eGameSetting_VSync:
|
||||||
|
break;
|
||||||
case eGameSetting_Difficulty:
|
case eGameSetting_Difficulty:
|
||||||
if(iPad==ProfileManager.GetPrimaryPad())
|
if(iPad==ProfileManager.GetPrimaryPad())
|
||||||
{
|
{
|
||||||
|
|
@ -1890,6 +1911,22 @@ void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucV
|
||||||
GameSettingsA[iPad]->bSettingsChanged=true;
|
GameSettingsA[iPad]->bSettingsChanged=true;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case eGameSetting_Difficulty:
|
||||||
if((GameSettingsA[iPad]->usBitmaskValues&0x03)!=(ucVal&0x03))
|
if((GameSettingsA[iPad]->usBitmaskValues&0x03)!=(ucVal&0x03))
|
||||||
{
|
{
|
||||||
|
|
@ -2442,6 +2479,13 @@ unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal)
|
||||||
case eGameSetting_PSVita_NetworkModeAdhoc:
|
case eGameSetting_PSVita_NetworkModeAdhoc:
|
||||||
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)>>17;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -954,70 +954,91 @@ float GameRenderer::ComputeGammaFromSlider(float slider0to100)
|
||||||
|
|
||||||
void GameRenderer::CachePlayerGammas()
|
void GameRenderer::CachePlayerGammas()
|
||||||
{
|
{
|
||||||
const float slider = app.GetGameSettings(ProfileManager.GetPrimaryPad(), eGameSetting_Gamma);
|
|
||||||
const float gamma = ComputeGammaFromSlider(slider);
|
|
||||||
|
|
||||||
for (int j = 0; j < XUSER_MAX_COUNT && j < NUM_LIGHT_TEXTURES; ++j)
|
for (int j = 0; j < XUSER_MAX_COUNT && j < NUM_LIGHT_TEXTURES; ++j)
|
||||||
m_cachedGammaPerPlayer[j] = gamma;
|
{
|
||||||
|
std::shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[j];
|
||||||
|
if (!player)
|
||||||
|
{
|
||||||
|
m_cachedGammaPerPlayer[j] = 1.0f;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float slider = app.GetGameSettings(j, eGameSetting_Gamma); // 0..100
|
||||||
|
m_cachedGammaPerPlayer[j] = ComputeGammaFromSlider(slider);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameRenderer::ComputeViewportForPlayer(int j, D3D11_VIEWPORT &outViewport) const
|
bool GameRenderer::ComputeViewportForPlayer(int j, D3D11_VIEWPORT &outViewport) const
|
||||||
{
|
{
|
||||||
|
// Use the actual backbuffer dimensions so viewports adapt to window resize.
|
||||||
extern int g_rScreenWidth;
|
extern int g_rScreenWidth;
|
||||||
extern int g_rScreenHeight;
|
extern int g_rScreenHeight;
|
||||||
|
|
||||||
std::shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[j];
|
int active = 0;
|
||||||
if (!player)
|
int indexMap[NUM_LIGHT_TEXTURES] = {-1, -1, -1, -1};
|
||||||
|
for (int i = 0; i < XUSER_MAX_COUNT && i < NUM_LIGHT_TEXTURES; ++i)
|
||||||
|
{
|
||||||
|
if (Minecraft::GetInstance()->localplayers[i])
|
||||||
|
indexMap[active++] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active <= 1)
|
||||||
|
{
|
||||||
|
outViewport.TopLeftX = 0.0f;
|
||||||
|
outViewport.TopLeftY = 0.0f;
|
||||||
|
outViewport.Width = static_cast<FLOAT>(g_rScreenWidth);
|
||||||
|
outViewport.Height = static_cast<FLOAT>(g_rScreenHeight);
|
||||||
|
outViewport.MinDepth = 0.0f;
|
||||||
|
outViewport.MaxDepth = 1.0f;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int k = -1;
|
||||||
|
for (int ord = 0; ord < active; ++ord)
|
||||||
|
if (indexMap[ord] == j)
|
||||||
|
{
|
||||||
|
k = ord;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (k < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const float w = static_cast<float>(g_rScreenWidth);
|
const float width = static_cast<float>(g_rScreenWidth);
|
||||||
const float h = static_cast<float>(g_rScreenHeight);
|
const float height = static_cast<float>(g_rScreenHeight);
|
||||||
const float halfW = w * 0.5f;
|
|
||||||
const float halfH = h * 0.5f;
|
|
||||||
|
|
||||||
outViewport.MinDepth = 0.0f;
|
if (active == 2)
|
||||||
outViewport.MaxDepth = 1.0f;
|
|
||||||
|
|
||||||
switch (static_cast<C4JRender::eViewportType>(player->m_iScreenSection))
|
|
||||||
{
|
{
|
||||||
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
|
const float halfH = height * 0.5f;
|
||||||
outViewport.TopLeftX = 0; outViewport.TopLeftY = 0;
|
outViewport.TopLeftX = 0.0f;
|
||||||
outViewport.Width = w; outViewport.Height = halfH;
|
outViewport.Width = width;
|
||||||
break;
|
outViewport.MinDepth = 0.0f;
|
||||||
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
|
outViewport.MaxDepth = 1.0f;
|
||||||
outViewport.TopLeftX = 0; outViewport.TopLeftY = halfH;
|
if (k == 0)
|
||||||
outViewport.Width = w; outViewport.Height = halfH;
|
{
|
||||||
break;
|
outViewport.TopLeftY = 0.0f;
|
||||||
case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
|
outViewport.Height = halfH;
|
||||||
outViewport.TopLeftX = 0; outViewport.TopLeftY = 0;
|
}
|
||||||
outViewport.Width = halfW; outViewport.Height = h;
|
else
|
||||||
break;
|
{
|
||||||
case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
|
outViewport.TopLeftY = halfH;
|
||||||
outViewport.TopLeftX = halfW; outViewport.TopLeftY = 0;
|
outViewport.Height = halfH;
|
||||||
outViewport.Width = halfW; outViewport.Height = h;
|
}
|
||||||
break;
|
return true;
|
||||||
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
|
}
|
||||||
outViewport.TopLeftX = 0; outViewport.TopLeftY = 0;
|
else
|
||||||
outViewport.Width = halfW; outViewport.Height = halfH;
|
{
|
||||||
break;
|
const float halfW = width * 0.5f;
|
||||||
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
|
const float halfH = height * 0.5f;
|
||||||
outViewport.TopLeftX = halfW; outViewport.TopLeftY = 0;
|
const int row = (k >= 2) ? 1 : 0;
|
||||||
outViewport.Width = halfW; outViewport.Height = halfH;
|
const int col = (k % 2);
|
||||||
break;
|
outViewport.TopLeftX = col ? halfW : 0.0f;
|
||||||
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
|
outViewport.TopLeftY = row ? halfH : 0.0f;
|
||||||
outViewport.TopLeftX = 0; outViewport.TopLeftY = halfH;
|
outViewport.Width = halfW;
|
||||||
outViewport.Width = halfW; outViewport.Height = halfH;
|
outViewport.Height = halfH;
|
||||||
break;
|
outViewport.MinDepth = 0.0f;
|
||||||
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
|
outViewport.MaxDepth = 1.0f;
|
||||||
outViewport.TopLeftX = halfW; outViewport.TopLeftY = halfH;
|
return true;
|
||||||
outViewport.Width = halfW; outViewport.Height = halfH;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
outViewport.TopLeftX = 0; outViewport.TopLeftY = 0;
|
|
||||||
outViewport.Width = w; outViewport.Height = h;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GameRenderer::BuildPlayerViewports(D3D11_VIEWPORT *outViewports, float *outGammas, UINT maxCount) const
|
uint32_t GameRenderer::BuildPlayerViewports(D3D11_VIEWPORT *outViewports, float *outGammas, UINT maxCount) const
|
||||||
|
|
@ -1169,19 +1190,11 @@ void GameRenderer::render(float a, bool bFirst)
|
||||||
const int xMouse = Mouse::getX() * screenWidth / mc->width;
|
const int xMouse = Mouse::getX() * screenWidth / mc->width;
|
||||||
const int yMouse = screenHeight - Mouse::getY() * screenHeight / mc->height - 1;
|
const int yMouse = screenHeight - Mouse::getY() * screenHeight / mc->height - 1;
|
||||||
|
|
||||||
const int maxFps = getFpsCap(mc->options->framerateLimit);
|
const int maxFps = getFpsCap(app.GetGameSettings(0, eGameSetting_FpsCap));
|
||||||
|
|
||||||
if (mc->level != nullptr)
|
if (mc->level != nullptr)
|
||||||
{
|
{
|
||||||
if (mc->options->framerateLimit == 0)
|
renderLevel(a, 0);
|
||||||
{
|
|
||||||
renderLevel(a, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
renderLevel(a, lastNsTime + 1000000000 / maxFps);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastNsTime = System::nanoTime();
|
lastNsTime = System::nanoTime();
|
||||||
|
|
||||||
if (!mc->options->hideGui || mc->screen != nullptr)
|
if (!mc->options->hideGui || mc->screen != nullptr)
|
||||||
|
|
@ -2240,10 +2253,9 @@ FloatBuffer *GameRenderer::getBuffer(float a, float b, float c, float d)
|
||||||
|
|
||||||
int GameRenderer::getFpsCap(int option)
|
int GameRenderer::getFpsCap(int option)
|
||||||
{
|
{
|
||||||
int maxFps = 200;
|
static const int fpsCaps[] = {30, 60, 120, 0};
|
||||||
if (option == 1) maxFps = 120;
|
if (option < 0 || option > 3) return 0;
|
||||||
if (option == 2) maxFps = 35;
|
return fpsCaps[option];
|
||||||
return maxFps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::updateAllChunks()
|
void GameRenderer::updateAllChunks()
|
||||||
|
|
|
||||||
|
|
@ -163,8 +163,8 @@ private:
|
||||||
|
|
||||||
void setupFog(int i, float alpha);
|
void setupFog(int i, float alpha);
|
||||||
FloatBuffer *getBuffer(float a, float b, float c, float d);
|
FloatBuffer *getBuffer(float a, float b, float c, float d);
|
||||||
static int getFpsCap(int option);
|
|
||||||
public:
|
public:
|
||||||
|
static int getFpsCap(int option);
|
||||||
void updateAllChunks();
|
void updateAllChunks();
|
||||||
|
|
||||||
#ifdef MULTITHREAD_ENABLE
|
#ifdef MULTITHREAD_ENABLE
|
||||||
|
|
|
||||||
|
|
@ -1959,8 +1959,29 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
||||||
|
|
||||||
RenderManager.Set_matrixDirty();
|
RenderManager.Set_matrixDirty();
|
||||||
#endif
|
#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.
|
// 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();
|
ui.CheckMenuDisplayed();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue