Skip to content

Commit 51f3d89

Browse files
authored
Supports automatic detection of monitor refresh rate (#4403)
Implements #4393
1 parent 148b360 commit 51f3d89

File tree

10 files changed

+120
-31
lines changed

10 files changed

+120
-31
lines changed

config/keeperfx.cfg

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,11 @@ DELTA_TIME=ON
5959
; Run the game faster or slower than it is meant to be played. Default value is 20.
6060
TURNS_PER_SECOND=20
6161

62-
; The maximum frame rate for drawing. Default value is 0.
62+
; The maximum frame rate for drawing. Default value is "AUTO 0".
63+
; Config format is "<main> [secondary]". secondary is optional, only used when main is set to AUTO and detection fails.
64+
; AUTO = auto detect monitor’s refresh rate.
6365
; 0 = unlimited (uses 100% of one CPU core). Suggested value: your monitor’s refresh rate.
64-
FRAMES_PER_SECOND=0
66+
FRAMES_PER_SECOND=AUTO 0
6567

6668
; The maximum distance you can zoom out the camera [0 - 100].
6769
; A value of 0 is equal to the original game's max distance.

src/bflib_inputctrl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ static void process_event(const SDL_Event *ev)
355355
{
356356
mute_audio(false);
357357
}
358+
redetect_screen_refresh_rate_for_draw();
358359
break;
359360
}
360361
case SDL_WINDOWEVENT_FOCUS_LOST:
@@ -387,6 +388,11 @@ static void process_event(const SDL_Event *ev)
387388
isMouseActive = false;
388389
break;
389390
}
391+
case SDL_WINDOWEVENT_MOVED:
392+
{
393+
redetect_screen_refresh_rate_for_draw();
394+
break;
395+
}
390396
default: break;
391397
}
392398
/* else if (ev->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {

src/bflib_video.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include "bflib_sprfnt.h"
2727
#include "bflib_vidsurface.h"
2828

29+
#include "keeperfx.hpp"
30+
2931
#include <SDL2/SDL.h>
3032
#include <SDL2/SDL_syswm.h>
3133
#include <math.h>
@@ -644,6 +646,9 @@ TbResult LbScreenSetup(TbScreenMode mode, TbScreenCoord width, TbScreenCoord hei
644646
}
645647

646648
reset_bflib_render();
649+
650+
redetect_screen_refresh_rate_for_draw();
651+
647652
SYNCDBG(8,"Finished");
648653
return Lb_SUCCESS;
649654
}

src/config_keeperfx.c

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -876,19 +876,11 @@ static void load_file_configuration(const char *fname, const char *sname, const
876876
}
877877
break;
878878
case 39: // FRAMES_PER_SECOND
879-
if (get_conf_parameter_single(buf, &pos, len, word_buf, sizeof(word_buf)) > 0)
880-
{
881-
i = atoi(word_buf);
882-
}
883-
if ((i >= 0) && (i <= INT32_MAX))
879+
if (!start_params.overrides[Clo_FramesPerSecond] && get_conf_parameter_whole(buf, &pos, len, word_buf, sizeof(word_buf)) > 0)
884880
{
885-
if (!start_params.overrides[Clo_FramesPerSecond])
886-
{
887-
start_params.num_fps_draw = i;
888-
}
889-
}
890-
else {
891-
CONFWRNLOG("Couldn't recognize \"%s\" command parameter in %s file.", COMMAND_TEXT(cmd_num), config_textname);
881+
i = parse_draw_fps_config_val(word_buf, &start_params.num_fps_draw_main, &start_params.num_fps_draw_secondary);
882+
if (i <= 0)
883+
CONFWRNLOG("Couldn't recognize \"%s\" command parameter in %s file.", COMMAND_TEXT(cmd_num), config_textname);
892884
}
893885
break;
894886
case 40: // TAG_MODE_TOGGLING
@@ -1069,4 +1061,54 @@ void process_cmdline_overrides(void)
10691061
}
10701062
}
10711063

1064+
int parse_draw_fps_config_val(const char *arg, long *fps_draw_main, long *fps_draw_secondary)
1065+
{
1066+
int cnt = 0, val1 = 0, val2 = 0;
1067+
long len = strlen(arg);
1068+
int32_t pos = 0;
1069+
char word_buf[32];
1070+
for (int i=0; i<2; i++)
1071+
{
1072+
if (get_conf_parameter_single(arg,&pos,len,word_buf,sizeof(word_buf)) <= 0)
1073+
break;
1074+
1075+
switch (i)
1076+
{
1077+
case 0:
1078+
if (strcasecmp(word_buf, "auto") == 0) {
1079+
val1=-1;
1080+
cnt++;
1081+
} else {
1082+
val1 = atoi(word_buf);
1083+
if (val1 >= 0){
1084+
cnt++;
1085+
} else {
1086+
i=2; // jump out for loop
1087+
break;
1088+
}
1089+
}
1090+
break;
1091+
case 1:
1092+
val2 = atoi(word_buf);
1093+
if (val2 >= 0){
1094+
cnt++;
1095+
} else {
1096+
i=2; // jump out for loop
1097+
break;
1098+
}
1099+
break;
1100+
}
1101+
}
1102+
1103+
if (cnt > 0) {
1104+
*fps_draw_main = val1;
1105+
}
1106+
if (cnt > 1) {
1107+
*fps_draw_secondary = val2;
1108+
}
1109+
1110+
return cnt;
1111+
}
1112+
1113+
10721114
/******************************************************************************/

src/config_keeperfx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ extern TbBool IMPRISON_BUTTON_DEFAULT;
126126
void load_configuration_for_mod_all(void);
127127
short load_configuration(void);
128128
void process_cmdline_overrides(void);
129+
int parse_draw_fps_config_val(const char *arg, long *fps_draw_main, long *fps_draw_secondary);
129130
/******************************************************************************/
130131
TbBool is_feature_on(unsigned long feature);
131132
void set_skip_heart_zoom_feature(TbBool enable);

src/console_cmd.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "bflib_sound.h"
2626
#include "bflib_sndlib.h"
2727
#include "config.h"
28+
#include "config_keeperfx.h"
2829
#include "config_campaigns.h"
2930
#include "config_effects.h"
3031
#include "config_magic.h"
@@ -290,7 +291,7 @@ static TbBool cmd_magic_instance(PlayerNumber plyr_idx, char * args)
290291

291292
TbBool cmd_stats(PlayerNumber plyr_idx, char * args)
292293
{
293-
targeted_message_add(MsgType_Player, plyr_idx, plyr_idx, GUI_MESSAGES_DELAY, "turn fps is %ld, draw fps is %ld", game_num_fps, game_num_fps_draw);
294+
targeted_message_add(MsgType_Player, plyr_idx, plyr_idx, GUI_MESSAGES_DELAY, "turn fps is %ld, draw fps is %ld", game_num_fps, game_num_fps_draw_current);
294295
return true;
295296
}
296297

@@ -308,13 +309,8 @@ TbBool cmd_fps_turn(PlayerNumber plyr_idx, char * args)
308309

309310
TbBool cmd_fps_draw(PlayerNumber plyr_idx, char * args)
310311
{
311-
char * pr2str = strsep(&args, " ");
312-
if (pr2str == NULL) {
313-
game_num_fps_draw = start_params.num_fps_draw;
314-
targeted_message_add(MsgType_Player, plyr_idx, plyr_idx, GUI_MESSAGES_DELAY, "Drawrate is %ld fps", game_num_fps_draw);
315-
} else {
316-
game_num_fps_draw = atoi(pr2str);
317-
}
312+
parse_draw_fps_config_val(args, &game_num_fps_draw_main, &game_num_fps_draw_secondary);
313+
redetect_screen_refresh_rate_for_draw();
318314
return true;
319315
}
320316

src/game_legacy.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,11 @@ struct Game {
382382
/******************************************************************************/
383383
extern struct Game game;
384384
extern long game_num_fps;
385-
extern long game_num_fps_draw;
385+
386+
extern long game_num_fps_draw_current;
387+
extern long game_num_fps_draw_main;
388+
extern long game_num_fps_draw_secondary;
389+
386390
/******************************************************************************/
387391
#ifdef __cplusplus
388392
}

src/keeperfx.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ struct StartupParameters {
131131
unsigned char debug_flags;
132132
unsigned short computer_chat_flags;
133133
long num_fps;
134-
long num_fps_draw;
134+
long num_fps_draw_main; // -1 if auto
135+
long num_fps_draw_secondary;
135136
TbBool packet_save_enable;
136137
TbBool packet_load_enable;
137138
char packet_fname[150];
@@ -298,11 +299,13 @@ long get_foot_creature_has_down(struct Thing *thing);
298299
void process_keeper_spell_aura(struct Thing *thing);
299300
void init_seeds();
300301

302+
301303
TbPixel get_player_path_colour(unsigned short owner);
302304

303305
void startup_saved_packet_game(void);
304306
void faststartup_saved_packet_game(void);
305307
void reinit_level_after_load(void);
308+
void redetect_screen_refresh_rate_for_draw();
306309
void update_time(void);
307310
extern TbClockMSec timerstarttime;
308311
struct TimerTime {

src/main.cpp

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,11 @@ struct StartupParameters start_params;
145145
char autostart_multiplayer_campaign[80] = "";
146146
int autostart_multiplayer_level = 0;
147147
long game_num_fps;
148-
long game_num_fps_draw = 0;
148+
149+
long game_num_fps_draw_current = 0;
150+
long game_num_fps_draw_main = 0; // -1 if auto
151+
long game_num_fps_draw_secondary = 0;
152+
149153

150154
unsigned char *blue_palette;
151155
unsigned char *red_palette;
@@ -1122,6 +1126,7 @@ short setup_game(void)
11221126
}
11231127

11241128
game.frame_skip = start_params.frame_skip;
1129+
redetect_screen_refresh_rate_for_draw();
11251130

11261131
// Intro problems shouldn't force the game to quit,
11271132
// so we're re-setting the result flag
@@ -3327,10 +3332,10 @@ TbBool keeper_wait_for_next_turn(void)
33273332
TbBool keeper_wait_for_next_draw(void)
33283333
{
33293334
// fps.draw is currently unable to work properly with frame_skip
3330-
if (game_num_fps_draw > 0 && is_feature_on(Ft_DeltaTime) == true && game.frame_skip == 0)
3335+
if (game_num_fps_draw_current > 0 && is_feature_on(Ft_DeltaTime) == true && game.frame_skip == 0)
33313336
{
33323337
const long double tick_ns_one_sec = 1000000000.0;
3333-
const long double tick_ns_one_frame = tick_ns_one_sec/game_num_fps_draw;
3338+
const long double tick_ns_one_frame = tick_ns_one_sec/game_num_fps_draw_current;
33343339

33353340
static long double tick_ns_last_draw = 0;
33363341
long double tick_ns_cur = get_time_tick_ns();
@@ -3350,6 +3355,29 @@ TbBool keeper_wait_for_next_draw(void)
33503355
return false;
33513356
}
33523357

3358+
void redetect_screen_refresh_rate_for_draw()
3359+
{
3360+
game_num_fps_draw_current = 0;
3361+
3362+
if (game_num_fps_draw_main == -1) {
3363+
if (game_num_fps_draw_secondary > 0)
3364+
game_num_fps_draw_current = game_num_fps_draw_secondary;
3365+
3366+
if (lbWindow != NULL) {
3367+
int display_index = SDL_GetWindowDisplayIndex(lbWindow);
3368+
if (display_index >= 0) {
3369+
SDL_DisplayMode mode;
3370+
if (SDL_GetCurrentDisplayMode(display_index, &mode) == 0 && mode.refresh_rate > 0) {
3371+
game_num_fps_draw_current = mode.refresh_rate;
3372+
}
3373+
}
3374+
}
3375+
3376+
} else if (game_num_fps_draw_main > 0) {
3377+
game_num_fps_draw_current = game_num_fps_draw_main;
3378+
}
3379+
}
3380+
33533381
TbBool keeper_wait_for_screen_focus(void)
33543382
{
33553383
do {
@@ -3492,7 +3520,7 @@ void gameplay_loop_timestep()
34923520
exit_keeper = 1;
34933521
}
34943522

3495-
if (game_num_fps_draw > 0 && is_feature_on(Ft_DeltaTime) == true) {
3523+
if (game_num_fps_draw_current > 0 && is_feature_on(Ft_DeltaTime) == true) {
34963524
keeper_wait_for_next_draw();
34973525

34983526
if (game.turns_packetoff == game.play_gameturn) {
@@ -4058,8 +4086,8 @@ short process_command_line(unsigned short argc, char *argv[])
40584086
if (strcasecmp(parstr, "fps_draw") == 0)
40594087
{
40604088
narg++;
4061-
start_params.num_fps_draw = atoi(pr2str);
4062-
start_params.overrides[Clo_FramesPerSecond] = true;
4089+
if (parse_draw_fps_config_val(pr2str, &start_params.num_fps_draw_main, &start_params.num_fps_draw_secondary) > 0)
4090+
start_params.overrides[Clo_FramesPerSecond] = true;
40634091
} else
40644092
if (strcasecmp(parstr, "human") == 0)
40654093
{

src/main_game.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,9 @@ void clear_complete_game(void)
467467
else
468468
set_selected_level_number(first_singleplayer_level());
469469
game_num_fps = start_params.num_fps;
470-
game_num_fps_draw = start_params.num_fps_draw;
470+
game_num_fps_draw_current = 0;
471+
game_num_fps_draw_main = start_params.num_fps_draw_main;
472+
game_num_fps_draw_secondary = start_params.num_fps_draw_secondary;
471473
game.mode_flags = start_params.mode_flags;
472474
game.easter_eggs_enabled = start_params.easter_egg;
473475
set_flag_value(game.system_flags, GSF_AllowOnePlayer, start_params.one_player);

0 commit comments

Comments
 (0)