cli: better FPS limiting

Simplify and make the fps limit behave better.

From: Thomas Jones <thomas.jones@utoronto.ca>

[rm: remove fps_limiter_frame_period now unused and fixup whitespace]
This commit is contained in:
riccardom 2011-03-09 21:55:48 +00:00
parent 9d0c383e93
commit 18349689c8
1 changed files with 10 additions and 68 deletions

View File

@ -71,8 +71,7 @@ static float nds_screen_size_ratio = 1.0f;
#define NUM_FRAMES_TO_TIME 60 #define NUM_FRAMES_TO_TIME 60
#endif #endif
#define FPS_LIMITER_FPS 60
#define FPS_LIMITER_FRAME_PERIOD 8
static SDL_Surface * surface; static SDL_Surface * surface;
@ -129,7 +128,6 @@ class configured_features : public CommandLine
public: public:
int auto_pause; int auto_pause;
int frameskip; int frameskip;
int fps_limiter_frame_period;
int engine_3d; int engine_3d;
int savetype; int savetype;
@ -147,7 +145,6 @@ init_config( class configured_features *config) {
config->auto_pause = 0; config->auto_pause = 0;
config->frameskip = 0; config->frameskip = 0;
config->fps_limiter_frame_period = FPS_LIMITER_FRAME_PERIOD;
config->engine_3d = 1; config->engine_3d = 1;
config->savetype = 0; config->savetype = 0;
@ -168,7 +165,6 @@ fill_config( class configured_features *config,
GOptionEntry options[] = { GOptionEntry options[] = {
{ "auto-pause", 0, 0, G_OPTION_ARG_NONE, &config->auto_pause, "Pause emulation if focus is lost", NULL}, { "auto-pause", 0, 0, G_OPTION_ARG_NONE, &config->auto_pause, "Pause emulation if focus is lost", NULL},
{ "frameskip", 0, 0, G_OPTION_ARG_INT, &config->frameskip, "Set frameskip", "FRAMESKIP"}, { "frameskip", 0, 0, G_OPTION_ARG_INT, &config->frameskip, "Set frameskip", "FRAMESKIP"},
{ "limiter-period", 0, 0, G_OPTION_ARG_INT, &config->fps_limiter_frame_period, "Set frame period of the fps limiter", "LIMITER"},
{ "3d-engine", 0, 0, G_OPTION_ARG_INT, &config->engine_3d, "Select 3d rendering engine. Available engines:\n" { "3d-engine", 0, 0, G_OPTION_ARG_INT, &config->engine_3d, "Select 3d rendering engine. Available engines:\n"
"\t\t\t\t\t\t 0 = 3d disabled\n" "\t\t\t\t\t\t 0 = 3d disabled\n"
"\t\t\t\t\t\t 1 = internal rasterizer (default)\n" "\t\t\t\t\t\t 1 = internal rasterizer (default)\n"
@ -225,11 +221,6 @@ fill_config( class configured_features *config,
goto error; goto error;
} }
if (config->fps_limiter_frame_period < 0 || config->fps_limiter_frame_period > 30) {
g_printerr("FPS limiter period must be >= 0 and <= 30.\n");
goto error;
}
if (config->nds_file == "") { if (config->nds_file == "") {
g_printerr("Need to specify file to load.\n"); g_printerr("Need to specify file to load.\n");
goto error; goto error;
@ -275,30 +266,6 @@ joinThread_gdb( void *thread_handle) {
} }
#endif #endif
/**
* A SDL timer callback function. Signals the supplied SDL semaphore
* if its value is small.
*
* @param interval The interval since the last call (in ms)
* @param param The pointer to the semaphore.
*
* @return The interval to the next call (required by SDL)
*/
static Uint32
fps_limiter_fn( Uint32 interval, void *param) {
SDL_sem *sdl_semaphore = (SDL_sem *)param;
/* signal the semaphore if it is getting low */
if ( SDL_SemValue( sdl_semaphore) < 4) {
SDL_SemPost( sdl_semaphore);
}
return interval;
}
#ifdef INCLUDE_OPENGL_2D #ifdef INCLUDE_OPENGL_2D
/* initialization openGL function */ /* initialization openGL function */
static int static int
@ -518,8 +485,7 @@ int main(int argc, char ** argv) {
#endif #endif
int limiter_frame_counter = 0; int limiter_frame_counter = 0;
SDL_sem *fps_limiter_semaphore = NULL; int limiter_tick0 = 0;
SDL_TimerID limiter_timer = NULL;
int error; int error;
GKeyFile *keyfile; GKeyFile *keyfile;
@ -726,27 +692,6 @@ int main(int argc, char ** argv) {
/* Since gtk has a different mapping the keys stop to work with the saved configuration :| */ /* Since gtk has a different mapping the keys stop to work with the saved configuration :| */
load_default_config(cli_kb_cfg); load_default_config(cli_kb_cfg);
if ( !my_config.disable_limiter) {
/* create the semaphore used for fps limiting */
fps_limiter_semaphore = SDL_CreateSemaphore( 1);
/* start a SDL timer for every FPS_LIMITER_FRAME_PERIOD frames to keep us at 60 fps */
if ( fps_limiter_semaphore != NULL) {
limiter_timer = SDL_AddTimer( 16 * my_config.fps_limiter_frame_period,
fps_limiter_fn, fps_limiter_semaphore);
}
if ( limiter_timer == NULL) {
fprintf( stderr, "Error trying to start FPS limiter timer: %s\n",
SDL_GetError());
if ( fps_limiter_semaphore != NULL) {
SDL_DestroySemaphore( fps_limiter_semaphore);
fps_limiter_semaphore = NULL;
}
return 1;
}
}
if(my_config.load_slot != -1){ if(my_config.load_slot != -1){
loadstate_slot(my_config.load_slot); loadstate_slot(my_config.load_slot);
} }
@ -786,14 +731,17 @@ int main(int argc, char ** argv) {
} }
if ( !my_config.disable_limiter && !ctrls_cfg.boost) { if ( !my_config.disable_limiter && !ctrls_cfg.boost) {
limiter_frame_counter += 1 + my_config.frameskip; int now = SDL_GetTicks();
if ( limiter_frame_counter >= my_config.fps_limiter_frame_period) { int delay = (limiter_tick0 + limiter_frame_counter*1000/FPS_LIMITER_FPS) - now;
if (delay > 0) {
SDL_Delay(delay);
} else if (delay < -500) { // reset if we fall too far behind don't want to run super fast until we catch up
limiter_tick0 = now;
limiter_frame_counter = 0; limiter_frame_counter = 0;
/* wait for the timer to expire */
SDL_SemWait( fps_limiter_semaphore);
} }
} }
// always count frames, we'll mess up if the limiter gets turned on later otherwise
limiter_frame_counter += 1 + my_config.frameskip;
#ifdef DISPLAY_FPS #ifdef DISPLAY_FPS
fps_frame_counter += 1; fps_frame_counter += 1;
@ -818,12 +766,6 @@ int main(int argc, char ** argv) {
/* Unload joystick */ /* Unload joystick */
uninit_joy(); uninit_joy();
if ( !my_config.disable_limiter) {
/* tidy up the FPS limiter timer and semaphore */
SDL_RemoveTimer( limiter_timer);
SDL_DestroySemaphore( fps_limiter_semaphore);
}
SDL_Quit(); SDL_Quit();
NDS_DeInit(); NDS_DeInit();