diff --git a/gtk/configure.ac b/gtk/configure.ac index 0f03e165..d41c84e5 100644 --- a/gtk/configure.ac +++ b/gtk/configure.ac @@ -204,7 +204,7 @@ else fi PKG_CHECK_MODULES([GTK], ["$GTK_VERSION"]) -PKG_CHECK_MODULES([GLIB], [gthread-2.0 >= 2.6 gobject-2.0 >= 2.6]) +PKG_CHECK_MODULES([GLIB], [glib-2.0 > 2.28 gthread-2.0 >= 2.6 gobject-2.0 >= 2.6]) PKG_CHECK_MODULES([LIBXML], [libxml-2.0 >= 2.0]) PKG_CHECK_MODULES([XRANDR], [xrandr]) diff --git a/gtk/src/gtk_config.cpp b/gtk/src/gtk_config.cpp index c4a4c3cd..5b31856d 100644 --- a/gtk/src/gtk_config.cpp +++ b/gtk/src/gtk_config.cpp @@ -413,7 +413,6 @@ Snes9xConfig::save_config_file (void) xml_out_int (xml, "sound_buffer_size", sound_buffer_size); xml_out_int (xml, "sound_driver", sound_driver); xml_out_int (xml, "sound_input_rate", sound_input_rate); - xml_out_int (xml, "sound_sync", Settings.SoundSync); xml_out_int (xml, "dynamic_rate_control", Settings.DynamicRateControl); xml_out_int (xml, "dynamic_rate_limit", Settings.DynamicRateLimit); xml_out_int (xml, "auto_input_rate", auto_input_rate); @@ -653,6 +652,8 @@ Snes9xConfig::set_option (const char *name, const char *value) else if (!strcasecmp (name, "frameskip")) { Settings.SkipFrames = atoi (value); + if (Settings.SkipFrames == THROTTLE_SOUND_SYNC) + Settings.SoundSync = 1; } else if (!strcasecmp (name, "sound_emulation")) { @@ -918,10 +919,6 @@ Snes9xConfig::set_option (const char *name, const char *value) { Settings.UpAndDown = CLAMP (atoi (value), 0, 1); } - else if (!strcasecmp (name, "sound_sync")) - { - Settings.SoundSync = atoi (value) ? 1 : 0; - } else if (!strcasecmp (name, "rewind_buffer_size")) { rewind_buffer_size = CLAMP (atoi (value), 0, 2000); diff --git a/gtk/src/gtk_config.h b/gtk/src/gtk_config.h index 6cf1804a..739b3a14 100644 --- a/gtk/src/gtk_config.h +++ b/gtk/src/gtk_config.h @@ -1,7 +1,6 @@ #ifndef __GTK_CONFIG_H #define __GTK_CONFIG_H -#include #include #include #include @@ -9,17 +8,30 @@ #include "gtk_control.h" #include "snes_ntsc.h" -#define HWA_NONE 0 -#define HWA_OPENGL 1 -#define HWA_XV 2 +enum { + HWA_NONE = 0, + HWA_OPENGL = 1, + HWA_XV = 2 +}; -#define HIRES_MERGE 0 -#define HIRES_NORMAL 1 -#define HIRES_SCALE 2 +enum { + HIRES_MERGE = 0, + HIRES_NORMAL = 1, + HIRES_SCALE = 2 +}; -#define ESC_TOGGLE_MENUBAR 0 -#define ESC_EXIT_FULLSCREEN 1 -#define ESC_EXIT_SNES9X 2 +enum { + ESC_TOGGLE_MENUBAR = 0, + ESC_EXIT_FULLSCREEN = 1, + ESC_EXIT_SNES9X = 2 +}; + +enum { + THROTTLE_TIMER = 0, + THROTTLE_TIMER_FRAMESKIP = 1, + THROTTLE_SOUND_SYNC = 2, + THROTTLE_NONE = 3 +}; class Snes9xConfig { @@ -128,11 +140,11 @@ class Snes9xConfig unsigned char screensaver_needs_reset; int modal_dialogs; - int pointer_is_visible; - struct timeval pointer_timestamp; - - unsigned int rewind_granularity; - unsigned int rewind_buffer_size; + int pointer_is_visible; + gint64 pointer_timestamp; + + unsigned int rewind_granularity; + unsigned int rewind_buffer_size; XRRScreenResources *xrr_screen_resources; XRRCrtcInfo *xrr_crtc_info; diff --git a/gtk/src/gtk_display_driver_opengl.cpp b/gtk/src/gtk_display_driver_opengl.cpp index 2bc30034..aa782915 100644 --- a/gtk/src/gtk_display_driver_opengl.cpp +++ b/gtk/src/gtk_display_driver_opengl.cpp @@ -1,6 +1,4 @@ #include -#include -#include #include #include #include diff --git a/gtk/src/gtk_preferences.cpp b/gtk/src/gtk_preferences.cpp index 0b90154b..0f030e15 100644 --- a/gtk/src/gtk_preferences.cpp +++ b/gtk/src/gtk_preferences.cpp @@ -361,6 +361,23 @@ event_hw_accel_changed (GtkComboBox *widget, gpointer data) return; } +static void +event_frameskip_combo_changed (GtkComboBox *widget, gpointer user_data) +{ + Snes9xPreferences *window = (Snes9xPreferences *) user_data; + + if (window->get_combo ("frameskip_combo") == THROTTLE_SOUND_SYNC) + { + window->set_check ("dynamic_rate_control", 0); + window->enable_widget ("dynamic_rate_control", 0); + } + else + { + window->enable_widget ("dynamic_rate_control", 1); + } +} + + static void event_scale_method_changed (GtkComboBox *widget, gpointer user_data) { @@ -584,6 +601,7 @@ Snes9xPreferences::Snes9xPreferences (Snes9xConfig *config) : { "game_data_clear", G_CALLBACK (event_game_data_clear) }, { "about_clicked", G_CALLBACK (event_about_clicked) }, { "auto_input_rate_toggled", G_CALLBACK (event_auto_input_rate_toggled) }, + { "frameskip_combo_changed", G_CALLBACK (event_frameskip_combo_changed) }, #ifdef USE_JOYSTICK { "calibrate", G_CALLBACK (event_calibrate) }, #endif @@ -711,7 +729,8 @@ Snes9xPreferences::move_settings_to_dialog (void) config->auto_input_rate ? FALSE : TRUE); set_spin ("sound_buffer_size", config->sound_buffer_size); - set_check ("sync_sound", Settings.SoundSync); + if (Settings.SkipFrames == THROTTLE_SOUND_SYNC) + Settings.DynamicRateControl = 0; set_check ("dynamic_rate_control", Settings.DynamicRateControl); set_spin ("dynamic_rate_limit", Settings.DynamicRateLimit / 1000.0); set_spin ("rewind_buffer_size", config->rewind_buffer_size); @@ -762,9 +781,8 @@ Snes9xPreferences::move_settings_to_dialog (void) set_combo ("ntsc_scanline_intensity", config->ntsc_scanline_intensity); set_combo ("scanline_filter_intensity", config->scanline_filter_intensity); - set_combo ("frameskip_combo", - Settings.SkipFrames == AUTO_FRAMERATE ? - 0 : Settings.SkipFrames + 1); + set_combo ("frameskip_combo", Settings.SkipFrames); + enable_widget ("dynamic_rate_control", Settings.SkipFrames != THROTTLE_SOUND_SYNC); set_check ("bilinear_filter", Settings.BilinearFilter); #ifdef USE_OPENGL @@ -806,6 +824,11 @@ Snes9xPreferences::get_settings_from_dialog (void) { int sound_needs_restart = 0; int gfx_needs_restart = 0; + int sound_sync = 0; + + Settings.SkipFrames = get_combo ("frameskip_combo"); + if (Settings.SkipFrames == THROTTLE_SOUND_SYNC) + sound_sync = 1; if ((config->sound_driver != get_combo ("sound_driver")) || (config->mute_sound != get_check ("mute_sound_check")) || @@ -814,7 +837,7 @@ Snes9xPreferences::get_settings_from_dialog (void) (config->sound_playback_rate != (7 - (get_combo ("playback_combo")))) || (config->sound_input_rate != get_slider ("sound_input_rate")) || (config->auto_input_rate != get_check ("auto_input_rate")) || - (Settings.SoundSync != get_check ("sync_sound")) || + (Settings.SoundSync != sound_sync) || (Settings.DynamicRateControl != get_check ("dynamic_rate_control"))) { sound_needs_restart = 1; @@ -858,7 +881,6 @@ Snes9xPreferences::get_settings_from_dialog (void) Settings.AutoSaveDelay = get_entry_value ("save_sram_after_sec"); config->multithreading = get_check ("multithreading"); config->pause_emulation_on_switch = get_check ("pause_emulation_on_switch"); - Settings.SkipFrames = get_combo ("frameskip_combo"); Settings.BlockInvalidVRAMAccessMaster = get_check ("block_invalid_vram_access"); Settings.UpAndDown = get_check ("upanddown"); Settings.SuperFXClockMultiplier = get_spin ("superfx_multiplier"); @@ -868,7 +890,7 @@ Snes9xPreferences::get_settings_from_dialog (void) config->sound_buffer_size = get_spin ("sound_buffer_size"); config->sound_input_rate = get_slider ("sound_input_rate"); config->auto_input_rate = get_check ("auto_input_rate"); - Settings.SoundSync = get_check ("sync_sound"); + Settings.SoundSync = sound_sync; config->mute_sound = get_check ("mute_sound_check"); config->mute_sound_turbo = get_check ("mute_sound_turbo_check"); Settings.DynamicRateControl = get_check ("dynamic_rate_control"); @@ -988,11 +1010,6 @@ Snes9xPreferences::get_settings_from_dialog (void) strncpy (config->sram_directory, safety_sram_directory, PATH_MAX); } - if (Settings.SkipFrames == 0) - Settings.SkipFrames = AUTO_FRAMERATE; - else - Settings.SkipFrames--; - memcpy (config->pad, pad, (sizeof (JoypadBinding)) * NUM_JOYPADS); memcpy (config->shortcut, shortcut, (sizeof (Binding)) * NUM_EMU_LINKS); diff --git a/gtk/src/gtk_s9x.cpp b/gtk/src/gtk_s9x.cpp index 7c1a9622..a5bbfe13 100644 --- a/gtk/src/gtk_s9x.cpp +++ b/gtk/src/gtk_s9x.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #ifdef GDK_WINDOWING_X11 @@ -17,33 +16,26 @@ #include "gtk_netplay.h" #endif -#define IDLE_FUNC_PRIORITY (G_PRIORITY_DEFAULT_IDLE) - -void S9xPostRomInit (void); -void S9xSyncSpeedFinish (void); -static void S9xCheckPointerTimer (void); +void S9xPostRomInit (); +static void S9xThrottle (); +static void S9xCheckPointerTimer (); static gboolean S9xIdleFunc (gpointer data); static gboolean S9xScreenSaverCheckFunc (gpointer data); -Snes9xWindow *top_level; -Snes9xConfig *gui_config; -StateManager stateMan; -static struct timeval next_frame_time = { 0, 0 }; -static struct timeval now; -static int needs_fullscreening = FALSE; -int syncing; -guint idle_func_id; +Snes9xWindow *top_level; +Snes9xConfig *gui_config; +StateManager state_manager; +static int needs_fullscreening = FALSE; +guint idle_func_id; +gint64 frame_clock = -1; +gint64 pointer_timestamp = -1; -void -S9xTerm (int signal) +void S9xTerm (int signal) { S9xExit (); - - return; } -int -main (int argc, char *argv[]) +int main (int argc, char *argv[]) { struct sigaction sig_callback; @@ -118,8 +110,7 @@ main (int argc, char *argv[]) top_level->update_accels (); Settings.Paused = TRUE; - syncing = 0; - idle_func_id = g_idle_add_full (IDLE_FUNC_PRIORITY, + idle_func_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, S9xIdleFunc, NULL, NULL); @@ -160,8 +151,7 @@ main (int argc, char *argv[]) return 0; } -int -S9xOpenROM (const char *rom_filename) +int S9xOpenROM (const char *rom_filename) { uint32 flags; bool8 loaded; @@ -237,7 +227,7 @@ S9xOpenROM (const char *rom_filename) CPU.Flags = flags; - if (stateMan.init (gui_config->rewind_buffer_size * 1024 * 1024)) + if (state_manager.init (gui_config->rewind_buffer_size * 1024 * 1024)) { printf ("Using rewind buffer of %uMB\n", gui_config->rewind_buffer_size); } @@ -247,8 +237,7 @@ S9xOpenROM (const char *rom_filename) return 0; } -void -S9xROMLoaded (void) +void S9xROMLoaded () { gui_config->rom_loaded = TRUE; top_level->configure_widgets (); @@ -260,40 +249,18 @@ S9xROMLoaded (void) } S9xSoundStart (); - - return; } -void -S9xNoROMLoaded (void) +void S9xNoROMLoaded () { S9xSoundStop (); gui_config->rom_loaded = FALSE; S9xDisplayRefresh (-1, -1); top_level->configure_widgets (); top_level->update_statusbar (); - - return; } -/* -static inline void check_messages (void) -{ - static unsigned int current_timeout = 0; - - if (GFX.InfoStringTimeout > current_timeout) - { - top_level->show_status_message (GFX.InfoString); - } - - current_timeout = GFX.InfoStringTimeout; - - return; -} -*/ - -gboolean -S9xPauseFunc (gpointer data) +gboolean S9xPauseFunc (gpointer data) { S9xProcessEvents (TRUE); @@ -325,7 +292,7 @@ S9xPauseFunc (gpointer data) #endif /* Resume high-performance callback */ - idle_func_id = g_idle_add_full (IDLE_FUNC_PRIORITY, + idle_func_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, S9xIdleFunc, NULL, NULL); @@ -336,8 +303,7 @@ S9xPauseFunc (gpointer data) return TRUE; } -gboolean -S9xIdleFunc (gpointer data) +gboolean S9xIdleFunc (gpointer data) { if (needs_fullscreening) { @@ -367,11 +333,8 @@ S9xIdleFunc (gpointer data) return FALSE; } - if (syncing) - S9xSyncSpeedFinish (); - S9xCheckPointerTimer (); - + S9xThrottle (); S9xProcessEvents (TRUE); #ifdef NETPLAY_SUPPORT @@ -385,13 +348,13 @@ S9xIdleFunc (gpointer data) for (int i = 0; i < 8; i++) joypads[i] = MovieGetJoypad(i); - Settings.Rewinding = stateMan.pop(); + Settings.Rewinding = state_manager.pop(); for (int i = 0; i < 8; i++) MovieSetJoypad (i, joypads[i]); } else if(IPPU.TotalEmulatedFrames % gui_config->rewind_granularity == 0) - stateMan.push(); + state_manager.push(); static int muted_from_turbo = FALSE; static int mute_saved_state = FALSE; @@ -419,8 +382,7 @@ S9xIdleFunc (gpointer data) return TRUE; } -gboolean -S9xScreenSaverCheckFunc (gpointer data) +gboolean S9xScreenSaverCheckFunc (gpointer data) { if (!Settings.Paused && @@ -432,18 +394,12 @@ S9xScreenSaverCheckFunc (gpointer data) } /* Snes9x core hooks */ -void -S9xMessage (int type, int number, const char *message) +void S9xMessage (int type, int number, const char *message) { - /* - fprintf (stderr, "%s\n", message); - */ - return; } /* Varies from ParseArgs because this one is for the OS port to handle */ -void -S9xParseArg (char **argv, int &i, int argc) +void S9xParseArg (char **argv, int &i, int argc) { if (!strcasecmp (argv[i], "-filter")) { @@ -511,106 +467,33 @@ S9xParseArg (char **argv, int &i, int argc) { gui_config->mute_sound = TRUE; } - - return; } -#undef TIMER_DIFF -#define TIMER_DIFF(a, b) ((((a).tv_sec - (b).tv_sec) * 1000000) + (a).tv_usec - (b).tv_usec) -/* Finishes syncing by using more accurate system sleep functions*/ -void -S9xSyncSpeedFinish (void) +static void S9xThrottle () { - if (!syncing) - return; - - gettimeofday (&now, NULL); - - if (Settings.SoundSync && !Settings.DynamicRateControl) - { - while (!S9xSyncSound ()) - { - usleep (100); - - gettimeofday (&next_frame_time, NULL); - - /* If we can't sync sound within a second, we're probably deadlocked */ - if (TIMER_DIFF (next_frame_time, now) > 1000000) - { - /* Flush out our sample buffer and give up. */ - S9xClearSamples (); - - break; - } - } - - next_frame_time = now; - return; - } - - if (TIMER_DIFF (next_frame_time, now) < -500000) - { - next_frame_time = now; - } - - while (timercmp (&next_frame_time, &now, >)) - { - int time_left = TIMER_DIFF (next_frame_time, now); - - if (time_left > 500000) - { - next_frame_time = now; - break; - } - - usleep (time_left); - - gettimeofday (&now, NULL); - } - - next_frame_time.tv_usec += Settings.FrameTime; - - if (next_frame_time.tv_usec >= 1000000) - { - next_frame_time.tv_sec += next_frame_time.tv_usec / 1000000; - next_frame_time.tv_usec %= 1000000; - } - - syncing = 0; - - return; -} - -/* SyncSpeed Handles delays between frames, similar to unix.cpp version, - * cleaned up for clarity, adjusted for GUI event loop */ -void -S9xSyncSpeed (void) -{ - unsigned int limit; - int lag; + gint64 now; #ifdef NETPLAY_SUPPORT if (S9xNetplaySyncSpeed ()) return; #endif + now = g_get_monotonic_time (); + if (Settings.HighSpeedSeek > 0) { Settings.HighSpeedSeek--; IPPU.RenderThisFrame = FALSE; IPPU.SkippedFrames = 0; - - gettimeofday (&now, NULL); - next_frame_time = now; - - syncing = 0; + frame_clock = now; return; } - else if (Settings.TurboMode) + if (Settings.TurboMode) { - if ((++IPPU.FrameSkip >= Settings.TurboSkipFrames) + IPPU.FrameSkip++; + if ((IPPU.FrameSkip >= Settings.TurboSkipFrames) && !Settings.HighSpeedSeek) { IPPU.FrameSkip = 0; @@ -623,84 +506,93 @@ S9xSyncSpeed (void) IPPU.RenderThisFrame = FALSE; } + frame_clock = now; + return; } - gettimeofday (&now, NULL); + IPPU.RenderThisFrame = TRUE; - if (next_frame_time.tv_sec == 0) + if (now - frame_clock > 500000) { - next_frame_time = now; - ++next_frame_time.tv_usec; + frame_clock = now; } - if (Settings.SkipFrames == AUTO_FRAMERATE && (!Settings.SoundSync || Settings.DynamicRateControl)) + if (Settings.SkipFrames == THROTTLE_SOUND_SYNC && + !Settings.DynamicRateControl) { - lag = TIMER_DIFF (now, next_frame_time); - - /* We compensate for the frame time by a frame in case it's just a CPU - * discrepancy. We can recover lost time in the next frame anyway. */ - if (lag > (int) (Settings.FrameTime)) + while (!S9xSyncSound ()) { - if (lag > (int) Settings.FrameTime * 10) + usleep (100); + + /* If we can't sync sound within a half-second, we're probably deadlocked */ + if (g_get_monotonic_time () - now > 500000) { - /* Running way too slowly */ - next_frame_time = now; - IPPU.RenderThisFrame = 1; - IPPU.SkippedFrames = 0; + S9xClearSamples (); + break; } - else + } + + frame_clock = now; + IPPU.SkippedFrames = 0; + + return; + } + else if (Settings.SkipFrames == THROTTLE_NONE) + { + frame_clock = now; + } + else // THROTTLE_TIMER or THROTTLE_TIMER_FRAMESKIP + { + if (Settings.SkipFrames == THROTTLE_TIMER_FRAMESKIP) + { + if (now - frame_clock > Settings.FrameTime) { - IPPU.RenderThisFrame = 0; IPPU.SkippedFrames++; + + if (IPPU.SkippedFrames < 8) + { + IPPU.RenderThisFrame = FALSE; + frame_clock += Settings.FrameTime; + return; + } + else + { + frame_clock = now - Settings.FrameTime; + } } } - else + while (now - frame_clock < Settings.FrameTime) { - IPPU.RenderThisFrame = 1; - IPPU.SkippedFrames = 0; + usleep (100); + now = g_get_monotonic_time (); } + + frame_clock += Settings.FrameTime; + IPPU.FrameSkip = 0; + IPPU.SkippedFrames = 0; } - else - { - limit = (Settings.SoundSync && !Settings.DynamicRateControl) ? 1 : Settings.SkipFrames + 1; - - IPPU.SkippedFrames++; - IPPU.RenderThisFrame = 0; - - if (IPPU.SkippedFrames >= limit) - { - IPPU.RenderThisFrame = 1; - IPPU.SkippedFrames = 0; - } - } - - syncing = 1; - - return; } -static void -S9xCheckPointerTimer (void) +void S9xSyncSpeed () +{ +} + +static void S9xCheckPointerTimer () { if (!gui_config->pointer_is_visible) return; - gettimeofday (&now, NULL); - - if (TIMER_DIFF (now, gui_config->pointer_timestamp) > 1000000) + if (g_get_monotonic_time () - gui_config->pointer_timestamp > 1000000) { top_level->hide_mouse_cursor (); gui_config->pointer_is_visible = FALSE; } - - return; } /* Final exit point, issues exit (0) */ -void -S9xExit (void) +void S9xExit () { gui_config->save_config_file (); @@ -726,8 +618,6 @@ S9xExit (void) delete gui_config; exit (0); - - return; } void @@ -808,18 +698,14 @@ S9xPostRomInit (void) case 0x0A: break; //Barcode Battler } } - - return; } -const char * -S9xStringInput(const char *message) +const char *S9xStringInput(const char *message) { return NULL; } -void -S9xExtraUsage (void) +void S9xExtraUsage () { printf ("GTK port options:\n" "-filter [option] Use a filter to scale the image.\n" @@ -827,5 +713,4 @@ S9xExtraUsage (void) " super2xsai hq2x hq3x hq4x 2xbrz 3xbrz 4xbrz epx ntsc\n" "\n" "-mutesound Disables sound output.\n"); - return; } diff --git a/gtk/src/gtk_s9x.h b/gtk/src/gtk_s9x.h index c2ef0134..ab648845 100644 --- a/gtk/src/gtk_s9x.h +++ b/gtk/src/gtk_s9x.h @@ -30,8 +30,8 @@ #define bind_textdomain_codeset(Domain,Codeset) (Codeset) #endif /* ENABLE_NLS */ -#define SNES9X_GTK_AUTHORS "(c) 2007 - 2017 Brandon Wright (bearoso@gmail.com)" -#define SNES9X_GTK_VERSION "85" +#define SNES9X_GTK_AUTHORS "(c) 2007 - 2018 Brandon Wright (bearoso@gmail.com)" +#define SNES9X_GTK_VERSION "86" extern Snes9xWindow *top_level; extern Snes9xConfig *gui_config; @@ -46,7 +46,7 @@ extern Snes9xConfig *gui_config; #endif int S9xOpenROM (const char *filename); -void S9xNoROMLoaded (void); -void S9xROMLoaded (void); +void S9xNoROMLoaded (); +void S9xROMLoaded (); #endif /* __GTK_S9X_H */ diff --git a/gtk/src/gtk_s9xwindow.cpp b/gtk/src/gtk_s9xwindow.cpp index 4e2480ff..be4c3577 100644 --- a/gtk/src/gtk_s9xwindow.cpp +++ b/gtk/src/gtk_s9xwindow.cpp @@ -259,7 +259,7 @@ event_motion_notify (GtkWidget *widget, window->show_mouse_cursor (); } - gettimeofday (&(window->config->pointer_timestamp), NULL); + window->config->pointer_timestamp = g_get_monotonic_time (); return FALSE; } diff --git a/gtk/src/snes9x.ui b/gtk/src/snes9x.ui index f8adb49a..74c4186c 100644 --- a/gtk/src/snes9x.ui +++ b/gtk/src/snes9x.ui @@ -1052,37 +1052,16 @@ - Automatic + Timer-based - 0 + Timer-based with automatic frame-skipping - 1 + Sound buffer synchronization - 2 - - - 3 - - - 4 - - - 5 - - - 6 - - - 7 - - - 8 - - - 9 + No throttling, but can use vsync to control speed @@ -4135,21 +4114,6 @@ 0 - - - Synchronize with sound - True - True - False - Base emulation speed on the rate sound is output - True - - - False - False - 1 - - Automatically adjust input rate to display @@ -4163,7 +4127,7 @@ False False - 2 + 1 @@ -4172,13 +4136,13 @@ True True False - Smoothes out slight hiccups in sound input rate + Smoothes out slight hiccups in sound input rate (can't be used with sound buffer synchronization) True False False - 3 + 2 @@ -4195,7 +4159,7 @@ False False - 4 + 3 @@ -4211,7 +4175,7 @@ False False - 5 + 4 @@ -4227,7 +4191,7 @@ False False - 6 + 5 @@ -4447,7 +4411,7 @@ False True - 7 + 6 @@ -4550,7 +4514,7 @@ True False - Frameskip: + Speed throttle: False @@ -4563,6 +4527,7 @@ True False liststore5 +