diff --git a/inc/dd.h b/inc/dd.h index e7ecf2f..5fa56a4 100644 --- a/inc/dd.h +++ b/inc/dd.h @@ -106,6 +106,7 @@ typedef struct cnc_ddraw BOOL nonexclusive; BOOL fixchildwindows; BOOL d3d9linear; + int maxgameticks; BOOL bnet_active; BOOL bnet_was_fullscreen; BOOL bnet_was_upscaled; diff --git a/inc/fps_limiter.h b/inc/fps_limiter.h index 911225b..21cf1de 100644 --- a/inc/fps_limiter.h +++ b/inc/fps_limiter.h @@ -47,12 +47,14 @@ typedef struct fps_limiter D3DKMTOPENADAPTERFROMHDCPROC D3DKMTOpenAdapterFromHdc; D3DKMTCLOSEADAPTERPROC D3DKMTCloseAdapter; BOOL got_adapter; + BOOL initialized; } fps_limiter; extern fps_limiter g_fpsl; void fpsl_init(); BOOL fpsl_wait_for_vblank(); +BOOL fpsl_dwm_flush(); BOOL fpsl_dwm_is_enabled(); void fpsl_frame_start(); void fpsl_frame_end(); diff --git a/src/config.c b/src/config.c index 8202746..8c4e32c 100644 --- a/src/config.c +++ b/src/config.c @@ -81,19 +81,19 @@ void cfg_load() g_fpsl.htimer = CreateWaitableTimer(NULL, TRUE, NULL); //can't fully set it up here due to missing g_ddraw->mode.dmDisplayFrequency - int max_ticks = cfg_get_int("maxgameticks", 0); + g_ddraw->maxgameticks = cfg_get_int("maxgameticks", 0); - if (max_ticks > 0 && max_ticks <= 1000) + if (g_ddraw->maxgameticks > 0 && g_ddraw->maxgameticks <= 1000) { if (g_ddraw->accurate_timers) g_ddraw->ticks_limiter.htimer = CreateWaitableTimer(NULL, TRUE, NULL); - float len = 1000.0f / max_ticks; + float len = 1000.0f / g_ddraw->maxgameticks; g_ddraw->ticks_limiter.tick_length_ns = len * 10000; g_ddraw->ticks_limiter.tick_length = len + 0.5f; } - if (max_ticks >= 0) + if (g_ddraw->maxgameticks >= 0 || g_ddraw->maxgameticks == -2) { //always using 60 fps for flip... if (g_ddraw->accurate_timers) @@ -298,7 +298,7 @@ static void cfg_create_ini() "; Hide WM_ACTIVATEAPP and WM_NCACTIVATE messages to prevent problems on alt+tab\n" "noactivateapp=false\n" "\n" - "; Max game ticks per second, possible values: -1 = disabled, 0 = emulate 60hz vblank, 1-1000 = custom game speed\n" + "; Max game ticks per second, possible values: -1 = disabled, -2 = refresh rate, 0 = emulate 60hz vblank, 1-1000 = custom game speed\n" "; Note: Can be used to slow down a too fast running game, fix flickering or too fast animations\n" "; Note: Usually one of the following values will work: 60 / 30 / 25 / 20 / 15 (lower value = slower game speed)\n" "maxgameticks=0\n" diff --git a/src/dd.c b/src/dd.c index 6b567fd..fd61a1c 100644 --- a/src/dd.c +++ b/src/dd.c @@ -704,6 +704,12 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags) HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE h) { + if (g_ddraw->maxgameticks == -2) + { + if (fpsl_dwm_flush()) + return DD_OK; + } + if (!g_ddraw->flip_limiter.tick_length) return DD_OK; diff --git a/src/fps_limiter.c b/src/fps_limiter.c index 61fd4c0..fa28e8d 100644 --- a/src/fps_limiter.c +++ b/src/fps_limiter.c @@ -27,36 +27,58 @@ void fpsl_init() if (g_fpsl.got_adapter && g_fpsl.D3DKMTCloseAdapter) { + g_fpsl.initialized = FALSE; g_fpsl.got_adapter = FALSE; g_fpsl.close_adapter.hAdapter = g_fpsl.adapter.hAdapter; g_fpsl.D3DKMTCloseAdapter(&g_fpsl.close_adapter); } if (!g_fpsl.gdi32_dll) + { g_fpsl.gdi32_dll = LoadLibraryA("gdi32.dll"); + } if (!g_fpsl.dwmapi_dll) + { g_fpsl.dwmapi_dll = LoadLibraryA("dwmapi.dll"); + } - g_fpsl.DwmFlush = - (DWMFLUSHPROC)GetProcAddress(g_fpsl.dwmapi_dll, "DwmFlush"); + if (!g_fpsl.DwmFlush) + { + g_fpsl.DwmFlush = + (DWMFLUSHPROC)GetProcAddress(g_fpsl.dwmapi_dll, "DwmFlush"); + } - g_fpsl.DwmIsCompositionEnabled = - (DWMISCOMPOSITIONENABLEDPROC)GetProcAddress(g_fpsl.dwmapi_dll, "DwmIsCompositionEnabled"); + if (!g_fpsl.DwmIsCompositionEnabled) + { + g_fpsl.DwmIsCompositionEnabled = + (DWMISCOMPOSITIONENABLEDPROC)GetProcAddress(g_fpsl.dwmapi_dll, "DwmIsCompositionEnabled"); + } - g_fpsl.D3DKMTWaitForVerticalBlankEvent = - (D3DKMTWAITFORVERTICALBLANKEVENTPROC)GetProcAddress(g_fpsl.gdi32_dll, "D3DKMTWaitForVerticalBlankEvent"); + if (!g_fpsl.D3DKMTWaitForVerticalBlankEvent) + { + g_fpsl.D3DKMTWaitForVerticalBlankEvent = + (D3DKMTWAITFORVERTICALBLANKEVENTPROC)GetProcAddress(g_fpsl.gdi32_dll, "D3DKMTWaitForVerticalBlankEvent"); + } - g_fpsl.D3DKMTOpenAdapterFromHdc = - (D3DKMTOPENADAPTERFROMHDCPROC)GetProcAddress(g_fpsl.gdi32_dll, "D3DKMTOpenAdapterFromHdc"); + if (!g_fpsl.D3DKMTOpenAdapterFromHdc) + { + g_fpsl.D3DKMTOpenAdapterFromHdc = + (D3DKMTOPENADAPTERFROMHDCPROC)GetProcAddress(g_fpsl.gdi32_dll, "D3DKMTOpenAdapterFromHdc"); + } - g_fpsl.D3DKMTCloseAdapter = - (D3DKMTCLOSEADAPTERPROC)GetProcAddress(g_fpsl.gdi32_dll, "D3DKMTCloseAdapter"); + if (!g_fpsl.D3DKMTCloseAdapter) + { + g_fpsl.D3DKMTCloseAdapter = + (D3DKMTCLOSEADAPTERPROC)GetProcAddress(g_fpsl.gdi32_dll, "D3DKMTCloseAdapter"); + } + + g_fpsl.initialized = TRUE; } BOOL fpsl_wait_for_vblank() { - if (g_fpsl.D3DKMTOpenAdapterFromHdc && !g_fpsl.got_adapter) + if (g_fpsl.initialized && g_fpsl.D3DKMTOpenAdapterFromHdc && !g_fpsl.got_adapter) { g_fpsl.adapter.hDc = g_ddraw->render.hdc; @@ -75,6 +97,11 @@ BOOL fpsl_wait_for_vblank() return FALSE; } +BOOL fpsl_dwm_flush() +{ + return g_fpsl.initialized && fpsl_dwm_is_enabled() && g_fpsl.DwmFlush && SUCCEEDED(g_fpsl.DwmFlush()); +} + BOOL fpsl_dwm_is_enabled() { BOOL dwm_enabled = FALSE; @@ -95,10 +122,7 @@ void fpsl_frame_end() { if (g_ddraw->render.maxfps < 0 || g_ddraw->vsync) { - if (fpsl_dwm_is_enabled() && g_fpsl.DwmFlush && SUCCEEDED(g_fpsl.DwmFlush())) - return; - - if (fpsl_wait_for_vblank()) + if (fpsl_dwm_flush() || fpsl_wait_for_vblank()) return; }