added support for (normal and adaptive) vertical sync (vsync)
[rocksndiamonds.git] / src / screens.c
index 3ffcb48493dcb0b11ae1bd0b2196b08d2b2fc8c2..b339ced690cbe546f406d7702b9800bf8c462978 100644 (file)
 #define SETUP_MODE_CHOOSE_WINDOW_SIZE  19
 #define SETUP_MODE_CHOOSE_SCALING_TYPE 20
 #define SETUP_MODE_CHOOSE_RENDERING    21
-#define SETUP_MODE_CHOOSE_GRAPHICS     22
-#define SETUP_MODE_CHOOSE_SOUNDS       23
-#define SETUP_MODE_CHOOSE_MUSIC                24
-#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE        25
-#define SETUP_MODE_CHOOSE_VOLUME_LOOPS 26
-#define SETUP_MODE_CHOOSE_VOLUME_MUSIC 27
-#define SETUP_MODE_CHOOSE_TOUCH_CONTROL        28
-#define SETUP_MODE_CHOOSE_MOVE_DISTANCE        29
-#define SETUP_MODE_CHOOSE_DROP_DISTANCE        30
-#define SETUP_MODE_CHOOSE_TRANSPARENCY 31
-#define SETUP_MODE_CHOOSE_GRID_XSIZE_0 32
-#define SETUP_MODE_CHOOSE_GRID_YSIZE_0 33
-#define SETUP_MODE_CHOOSE_GRID_XSIZE_1 34
-#define SETUP_MODE_CHOOSE_GRID_YSIZE_1 35
-#define SETUP_MODE_CONFIG_VIRT_BUTTONS 36
-
-#define MAX_SETUP_MODES                        37
+#define SETUP_MODE_CHOOSE_VSYNC                22
+#define SETUP_MODE_CHOOSE_GRAPHICS     23
+#define SETUP_MODE_CHOOSE_SOUNDS       24
+#define SETUP_MODE_CHOOSE_MUSIC                25
+#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE        26
+#define SETUP_MODE_CHOOSE_VOLUME_LOOPS 27
+#define SETUP_MODE_CHOOSE_VOLUME_MUSIC 28
+#define SETUP_MODE_CHOOSE_TOUCH_CONTROL        29
+#define SETUP_MODE_CHOOSE_MOVE_DISTANCE        30
+#define SETUP_MODE_CHOOSE_DROP_DISTANCE        31
+#define SETUP_MODE_CHOOSE_TRANSPARENCY 32
+#define SETUP_MODE_CHOOSE_GRID_XSIZE_0 33
+#define SETUP_MODE_CHOOSE_GRID_YSIZE_0 34
+#define SETUP_MODE_CHOOSE_GRID_XSIZE_1 35
+#define SETUP_MODE_CHOOSE_GRID_YSIZE_1 36
+#define SETUP_MODE_CONFIG_VIRT_BUTTONS 37
+
+#define MAX_SETUP_MODES                        38
 
 #define MAX_MENU_MODES                 MAX(MAX_INFO_MODES, MAX_SETUP_MODES)
 
 #define STR_SETUP_CHOOSE_WINDOW_SIZE   "Window Scaling"
 #define STR_SETUP_CHOOSE_SCALING_TYPE  "Anti-Aliasing"
 #define STR_SETUP_CHOOSE_RENDERING     "Rendering Mode"
+#define STR_SETUP_CHOOSE_VSYNC         "VSync Mode"
 #define STR_SETUP_CHOOSE_VOLUME_SIMPLE "Sound Volume"
 #define STR_SETUP_CHOOSE_VOLUME_LOOPS  "Loops Volume"
 #define STR_SETUP_CHOOSE_VOLUME_MUSIC  "Music Volume"
@@ -221,7 +223,7 @@ static void HandleSetupScreen_Generic(int, int, int, int, int);
 static void HandleSetupScreen_Input(int, int, int, int, int);
 static void CustomizeKeyboard(int);
 static void ConfigureJoystick(int);
-static void ConfigureVirtualButtons();
+static void ConfigureVirtualButtons(void);
 static void execSetupGame(void);
 static void execSetupGraphics(void);
 static void execSetupSound(void);
@@ -265,6 +267,9 @@ static TreeInfo *scaling_type_current = NULL;
 static TreeInfo *rendering_modes = NULL;
 static TreeInfo *rendering_mode_current = NULL;
 
+static TreeInfo *vsync_modes = NULL;
+static TreeInfo *vsync_mode_current = NULL;
+
 static TreeInfo *scroll_delays = NULL;
 static TreeInfo *scroll_delay_current = NULL;
 
@@ -353,6 +358,19 @@ static struct
   {    NULL,                            NULL                            },
 };
 
+static struct
+{
+  char *value;
+  char *text;
+} vsync_modes_list[] =
+{
+  {    STR_VSYNC_MODE_OFF,             "Off"           },
+  {    STR_VSYNC_MODE_NORMAL,          "Normal"        },
+  {    STR_VSYNC_MODE_ADAPTIVE,        "Adaptive"      },
+
+  {    NULL,                            NULL           },
+};
+
 static struct
 {
   int value;
@@ -1085,7 +1103,7 @@ static boolean visibleTextPos(struct TextPosInfo *pos)
   return (pos != NULL && pos->x != -1 && pos->y != -1);
 }
 
-static void InitializeMainControls()
+static void InitializeMainControls(void)
 {
   boolean local_team_mode = (!network.enabled && setup.team_mode);
   int i;
@@ -1361,7 +1379,7 @@ static void AdjustChooseTreeScrollbar(int id, int first_entry, TreeInfo *ti)
                  first_entry);
 }
 
-static void clearMenuListArea()
+static void clearMenuListArea(void)
 {
   int scrollbar_xpos = mSX + SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset;
 
@@ -1415,13 +1433,13 @@ static void drawChooseTreeCursor(int ypos, boolean active)
   drawCursorExt(0, ypos, active, -1);
 }
 
-void DrawHeadline()
+static void DrawHeadline(void)
 {
   DrawTextSCentered(MENU_TITLE1_YPOS, FONT_TITLE_1, main_text_title_1);
   DrawTextSCentered(MENU_TITLE2_YPOS, FONT_TITLE_2, main_text_title_2);
 }
 
-void DrawTitleScreenImage(int nr, boolean initial)
+static void DrawTitleScreenImage(int nr, boolean initial)
 {
   int graphic = getTitleScreenGraphic(nr, initial);
   Bitmap *bitmap = graphic_info[graphic].bitmap;
@@ -1465,7 +1483,7 @@ void DrawTitleScreenImage(int nr, boolean initial)
   redraw_mask = REDRAW_ALL;
 }
 
-void DrawTitleScreenMessage(int nr, boolean initial)
+static void DrawTitleScreenMessage(int nr, boolean initial)
 {
   char *filename = getLevelSetTitleMessageFilename(nr, initial);
   struct TitleMessageInfo *tmi = getTitleMessageInfo(nr, initial);
@@ -1516,14 +1534,14 @@ void DrawTitleScreenMessage(int nr, boolean initial)
   ResetFontStatus();
 }
 
-void DrawTitleScreen()
+static void DrawTitleScreen(void)
 {
   KeyboardAutoRepeatOff();
 
   HandleTitleScreen(0, 0, 0, 0, MB_MENU_INITIALIZE);
 }
 
-boolean CheckTitleScreen(boolean levelset_has_changed)
+static boolean CheckTitleScreen(boolean levelset_has_changed)
 {
   static boolean show_title_initial = TRUE;
   boolean show_titlescreen = FALSE;
@@ -1540,7 +1558,7 @@ boolean CheckTitleScreen(boolean levelset_has_changed)
   return (show_titlescreen && num_title_screens > 0);
 }
 
-void DrawMainMenu()
+void DrawMainMenu(void)
 {
   static LevelDirTree *leveldir_last_valid = NULL;
   boolean levelset_has_changed = FALSE;
@@ -1642,6 +1660,7 @@ void DrawMainMenu()
 
   DrawCursorAndText_Main(-1, FALSE, FALSE);
   DrawPreviewLevelInitial();
+  DrawNetworkPlayers();
 
   HandleMainMenu(0, 0, 0, 0, MB_MENU_INITIALIZE);
 
@@ -1685,7 +1704,7 @@ void DrawMainMenu()
   OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2);
 }
 
-static void gotoTopLevelDir()
+static void gotoTopLevelDir(void)
 {
   /* move upwards until inside (but not above) top level directory */
   while (leveldir_current->node_parent &&
@@ -1886,7 +1905,8 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
   }
 }
 
-void HandleMainMenu_SelectLevel(int step, int direction, int selected_level_nr)
+static void HandleMainMenu_SelectLevel(int step, int direction,
+                                      int selected_level_nr)
 {
   int old_level_nr = level_nr;
   int new_level_nr;
@@ -2136,56 +2156,56 @@ static struct TokenInfo *info_info;
 static int num_info_info;      /* number of info entries shown on screen */
 static int max_info_info;      /* total number of info entries in list */
 
-static void execInfoTitleScreen()
+static void execInfoTitleScreen(void)
 {
   info_mode = INFO_MODE_TITLE;
 
   DrawInfoScreen();
 }
 
-static void execInfoElements()
+static void execInfoElements(void)
 {
   info_mode = INFO_MODE_ELEMENTS;
 
   DrawInfoScreen();
 }
 
-static void execInfoMusic()
+static void execInfoMusic(void)
 {
   info_mode = INFO_MODE_MUSIC;
 
   DrawInfoScreen();
 }
 
-static void execInfoCredits()
+static void execInfoCredits(void)
 {
   info_mode = INFO_MODE_CREDITS;
 
   DrawInfoScreen();
 }
 
-static void execInfoProgram()
+static void execInfoProgram(void)
 {
   info_mode = INFO_MODE_PROGRAM;
 
   DrawInfoScreen();
 }
 
-static void execInfoVersion()
+static void execInfoVersion(void)
 {
   info_mode = INFO_MODE_VERSION;
 
   DrawInfoScreen();
 }
 
-static void execInfoLevelSet()
+static void execInfoLevelSet(void)
 {
   info_mode = INFO_MODE_LEVELSET;
 
   DrawInfoScreen();
 }
 
-static void execExitInfo()
+static void execExitInfo(void)
 {
   SetGameStatus(GAME_MODE_MAIN);
 
@@ -2306,7 +2326,7 @@ static void drawMenuInfoList(int first_entry, int num_page_entries,
   }
 }
 
-static void DrawInfoScreen_Main()
+static void DrawInfoScreen_Main(void)
 {
   int fade_mask = REDRAW_FIELD;
   int i;
@@ -2366,8 +2386,9 @@ static void DrawInfoScreen_Main()
 
 static void changeSetupValue(int, int, int);
 
-void HandleMenuScreen(int mx, int my, int dx, int dy, int button,
-                     int mode, int num_page_entries, int max_page_entries)
+static void HandleMenuScreen(int mx, int my, int dx, int dy, int button,
+                            int mode, int num_page_entries,
+                            int max_page_entries)
 {
   static int num_page_entries_all_last[NUM_SPECIAL_GFX_ARGS][MAX_MENU_MODES];
   static int choice_stores[NUM_SPECIAL_GFX_ARGS][MAX_MENU_MODES];
@@ -2884,7 +2905,7 @@ void DrawInfoScreen_HelpText(int element, int action, int direction, int ypos)
                 TRUE, FALSE, FALSE);
 }
 
-void DrawInfoScreen_TitleScreen()
+static void DrawInfoScreen_TitleScreen(void)
 {
   SetGameStatus(GAME_MODE_TITLE);
 
@@ -2896,7 +2917,7 @@ void HandleInfoScreen_TitleScreen(int button)
   HandleTitleScreen(0, 0, 0, 0, button);
 }
 
-void DrawInfoScreen_Elements()
+static void DrawInfoScreen_Elements(void)
 {
   SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_ELEMENTS);
 
@@ -2989,7 +3010,7 @@ void HandleInfoScreen_Elements(int button)
   }
 }
 
-void DrawInfoScreen_Music()
+static void DrawInfoScreen_Music(void)
 {
   SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_MUSIC);
 
@@ -3095,7 +3116,12 @@ void HandleInfoScreen_Music(int button)
     }
     else
     {
-      PlayMusic(list->music);
+      int music = list->music;
+
+      if (music_info[music].loop)
+       PlayMusicLoop(music);
+      else
+       PlayMusic(music);
 
       DrawTextSCentered(ystart, font_title, "The Game Background Music:");
     }
@@ -3395,7 +3421,7 @@ static void DrawInfoScreen_CreditsScreen(int screen_nr)
                    "Press any key or button for next page");
 }
 
-void DrawInfoScreen_Credits()
+static void DrawInfoScreen_Credits(void)
 {
   SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_CREDITS);
 
@@ -3465,7 +3491,7 @@ void HandleInfoScreen_Credits(int button)
   }
 }
 
-void DrawInfoScreen_Program()
+static void DrawInfoScreen_Program(void)
 {
   int font_title = MENU_INFO_FONT_TITLE;
   int font_head  = MENU_INFO_FONT_HEAD;
@@ -3550,7 +3576,7 @@ void HandleInfoScreen_Program(int button)
   }
 }
 
-void DrawInfoScreen_Version()
+static void DrawInfoScreen_Version(void)
 {
   int font_title = MENU_INFO_FONT_TITLE;
   int font_head  = MENU_INFO_FONT_HEAD;
@@ -3747,7 +3773,7 @@ void HandleInfoScreen_Version(int button)
   }
 }
 
-void DrawInfoScreen_LevelSet()
+static void DrawInfoScreen_LevelSet(void)
 {
   struct TitleMessageInfo *tmi = &readme;
   char *filename = getLevelSetInfoFilename();
@@ -3809,7 +3835,7 @@ void DrawInfoScreen_LevelSet()
   FadeIn(REDRAW_FIELD);
 }
 
-void HandleInfoScreen_LevelSet(int button)
+static void HandleInfoScreen_LevelSet(int button)
 {
   if (button == MB_MENU_LEAVE)
   {
@@ -3835,7 +3861,7 @@ void HandleInfoScreen_LevelSet(int button)
   }
 }
 
-static void DrawInfoScreen()
+static void DrawInfoScreen(void)
 {
   if (info_mode == INFO_MODE_TITLE)
     DrawInfoScreen_TitleScreen();
@@ -4160,7 +4186,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
        execSetupGame();
       else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE ||
               setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE ||
-              setup_mode == SETUP_MODE_CHOOSE_RENDERING)
+              setup_mode == SETUP_MODE_CHOOSE_RENDERING ||
+              setup_mode == SETUP_MODE_CHOOSE_VSYNC)
        execSetupGraphics();
       else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE ||
               setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS ||
@@ -4317,7 +4344,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
            execSetupGame();
          else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE ||
                   setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE ||
-                  setup_mode == SETUP_MODE_CHOOSE_RENDERING)
+                  setup_mode == SETUP_MODE_CHOOSE_RENDERING ||
+                  setup_mode == SETUP_MODE_CHOOSE_VSYNC)
            execSetupGraphics();
          else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE ||
                   setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS ||
@@ -4388,7 +4416,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
            execSetupGame();
          else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE ||
                   setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE ||
-                  setup_mode == SETUP_MODE_CHOOSE_RENDERING)
+                  setup_mode == SETUP_MODE_CHOOSE_RENDERING ||
+                  setup_mode == SETUP_MODE_CHOOSE_VSYNC)
            execSetupGraphics();
          else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE ||
                   setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS ||
@@ -4424,7 +4453,7 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
   }
 }
 
-void DrawChooseLevelSet()
+void DrawChooseLevelSet(void)
 {
   FadeMenuSoundsAndMusic();
 
@@ -4438,7 +4467,7 @@ void HandleChooseLevelSet(int mx, int my, int dx, int dy, int button)
   HandleChooseTree(mx, my, dx, dy, button, &leveldir_current);
 }
 
-void DrawChooseLevelNr()
+void DrawChooseLevelNr(void)
 {
   int i;
 
@@ -4531,14 +4560,15 @@ void DrawHallOfFame(int level_nr, int highlight_position)
 
   OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
 
-  HandleHallOfFame(highlight_position, 0, 0, 0, MB_MENU_INITIALIZE);
+  HandleHallOfFame(level_nr, highlight_position, 0, 0, MB_MENU_INITIALIZE);
 
   DrawMaskedBorder(fade_mask);
 
   FadeIn(fade_mask);
 }
 
-static void drawHallOfFameList(int first_entry, int highlight_position)
+static void drawHallOfFameList(int level_nr, int first_entry,
+                              int highlight_position)
 {
   int i, j;
 
@@ -4581,15 +4611,18 @@ static void drawHallOfFameList(int first_entry, int highlight_position)
 
 void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
 {
+  static int level_nr = 0;
   static int first_entry = 0;
   static int highlight_position = 0;
   int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
 
   if (button == MB_MENU_INITIALIZE)
   {
+    level_nr = mx;
     first_entry = 0;
-    highlight_position = mx;
-    drawHallOfFameList(first_entry, highlight_position);
+    highlight_position = my;
+
+    drawHallOfFameList(level_nr, first_entry, highlight_position);
 
     return;
   }
@@ -4605,7 +4638,7 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
       if (first_entry < 0)
        first_entry = 0;
 
-      drawHallOfFameList(first_entry, highlight_position);
+      drawHallOfFameList(level_nr, first_entry, highlight_position);
     }
   }
   else if (dy > 0)
@@ -4616,7 +4649,7 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
       if (first_entry + NUM_MENU_ENTRIES_ON_SCREEN > MAX_SCORE_ENTRIES)
        first_entry = MAX(0, MAX_SCORE_ENTRIES - NUM_MENU_ENTRIES_ON_SCREEN);
 
-      drawHallOfFameList(first_entry, highlight_position);
+      drawHallOfFameList(level_nr, first_entry, highlight_position);
     }
   }
   else if (button == MB_MENU_LEAVE || button == MB_MENU_CHOICE)
@@ -4625,16 +4658,17 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
 
     FadeSound(SND_BACKGROUND_SCORES);
 
-    if (game_status_last_screen != GAME_MODE_PLAYING ||
-       !setup.auto_play_next_level || !setup.increment_levels)
+    if (game_status_last_screen == GAME_MODE_PLAYING &&
+       setup.auto_play_next_level && setup.increment_levels &&
+       !network_playing)
     {
-      SetGameStatus(GAME_MODE_MAIN);
-
-      DrawMainMenu();
+      StartGameActions(network.enabled, setup.autorecord, level.random_seed);
     }
     else
     {
-      StartGameActions(network.enabled, setup.autorecord, level.random_seed);
+      SetGameStatus(GAME_MODE_MAIN);
+
+      DrawMainMenu();
     }
   }
 
@@ -4654,6 +4688,7 @@ static int max_setup_info;        /* total number of setup entries in list */
 static char *window_size_text;
 static char *scaling_type_text;
 static char *rendering_mode_text;
+static char *vsync_mode_text;
 static char *scroll_delay_text;
 static char *snapshot_mode_text;
 static char *game_speed_text;
@@ -4669,14 +4704,14 @@ static char *drop_distance_text;
 static char *transparency_text;
 static char *grid_size_text[2][2];
 
-static void execSetupMain()
+static void execSetupMain(void)
 {
   setup_mode = SETUP_MODE_MAIN;
 
   DrawSetupScreen();
 }
 
-static void execSetupGame_setGameSpeeds()
+static void execSetupGame_setGameSpeeds(void)
 {
   if (game_speeds == NULL)
   {
@@ -4726,7 +4761,7 @@ static void execSetupGame_setGameSpeeds()
   game_speed_text = game_speed_current->name;
 }
 
-static void execSetupGame_setScrollDelays()
+static void execSetupGame_setScrollDelays(void)
 {
   if (scroll_delays == NULL)
   {
@@ -4776,7 +4811,7 @@ static void execSetupGame_setScrollDelays()
   scroll_delay_text = scroll_delay_current->name;
 }
 
-static void execSetupGame_setSnapshotModes()
+static void execSetupGame_setSnapshotModes(void)
 {
   if (snapshot_modes == NULL)
   {
@@ -4826,7 +4861,7 @@ static void execSetupGame_setSnapshotModes()
   snapshot_mode_text = snapshot_mode_current->name;
 }
 
-static void execSetupGame()
+static void execSetupGame(void)
 {
   execSetupGame_setGameSpeeds();
   execSetupGame_setScrollDelays();
@@ -4837,28 +4872,28 @@ static void execSetupGame()
   DrawSetupScreen();
 }
 
-static void execSetupChooseGameSpeed()
+static void execSetupChooseGameSpeed(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_GAME_SPEED;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseScrollDelay()
+static void execSetupChooseScrollDelay(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_SCROLL_DELAY;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseSnapshotMode()
+static void execSetupChooseSnapshotMode(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_SNAPSHOT_MODE;
 
   DrawSetupScreen();
 }
 
-static void execSetupEditor()
+static void execSetupEditor(void)
 {
   setup_mode = SETUP_MODE_EDITOR;
 
@@ -4950,7 +4985,7 @@ static void execSetupGraphics_setWindowSizes(boolean update_list)
   window_size_text = window_size_current->name;
 }
 
-static void execSetupGraphics_setScalingTypes()
+static void execSetupGraphics_setScalingTypes(void)
 {
   if (scaling_types == NULL)
   {
@@ -5000,7 +5035,7 @@ static void execSetupGraphics_setScalingTypes()
   scaling_type_text = scaling_type_current->name;
 }
 
-static void execSetupGraphics_setRenderingModes()
+static void execSetupGraphics_setRenderingModes(void)
 {
   if (rendering_modes == NULL)
   {
@@ -5051,7 +5086,57 @@ static void execSetupGraphics_setRenderingModes()
   rendering_mode_text = rendering_mode_current->name;
 }
 
-static void execSetupGraphics()
+static void execSetupGraphics_setVsyncModes(void)
+{
+  if (vsync_modes == NULL)
+  {
+    int i;
+
+    for (i = 0; vsync_modes_list[i].value != NULL; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      char *value = vsync_modes_list[i].value;
+      char *text = vsync_modes_list[i].text;
+
+      ti->node_top = &vsync_modes;
+      ti->sort_priority = i;
+
+      sprintf(identifier, "%s", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, STR_SETUP_CHOOSE_VSYNC);
+
+      pushTreeInfo(&vsync_modes, ti);
+    }
+
+    /* sort vsync mode values to start with lowest vsync mode value */
+    sortTreeInfo(&vsync_modes);
+
+    /* set current vsync mode value to configured vsync mode value */
+    vsync_mode_current =
+      getTreeInfoFromIdentifier(vsync_modes, setup.vsync_mode);
+
+    /* if that fails, set current vsync mode to reliable default value */
+    if (vsync_mode_current == NULL)
+      vsync_mode_current =
+       getTreeInfoFromIdentifier(vsync_modes, STR_VSYNC_MODE_DEFAULT);
+
+    /* if that also fails, set current vsync mode to first available one */
+    if (vsync_mode_current == NULL)
+      vsync_mode_current = vsync_modes;
+  }
+
+  setup.vsync_mode = vsync_mode_current->identifier;
+
+  /* needed for displaying vsync mode text instead of identifier */
+  vsync_mode_text = vsync_mode_current->name;
+}
+
+static void execSetupGraphics(void)
 {
   // update "setup.window_scaling_percent" from list selection
   // (in this case, window scaling was changed on setup screen)
@@ -5064,6 +5149,7 @@ static void execSetupGraphics()
 
   execSetupGraphics_setScalingTypes();
   execSetupGraphics_setRenderingModes();
+  execSetupGraphics_setVsyncModes();
 
   setup_mode = SETUP_MODE_GRAPHICS;
 
@@ -5079,52 +5165,62 @@ static void execSetupGraphics()
 
   // screen rendering mode may have changed at this point
   SDLSetScreenRenderingMode(setup.screen_rendering_mode);
+
+  // screen vsync mode may have changed at this point
+  SDLSetScreenVsyncMode(setup.vsync_mode);
 #endif
 }
 
-static void execSetupChooseWindowSize()
+static void execSetupChooseWindowSize(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_WINDOW_SIZE;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseScalingType()
+static void execSetupChooseScalingType(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_SCALING_TYPE;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseRenderingMode()
+static void execSetupChooseRenderingMode(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_RENDERING;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseVolumeSimple()
+static void execSetupChooseVsyncMode(void)
+{
+  setup_mode = SETUP_MODE_CHOOSE_VSYNC;
+
+  DrawSetupScreen();
+}
+
+static void execSetupChooseVolumeSimple(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_VOLUME_SIMPLE;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseVolumeLoops()
+static void execSetupChooseVolumeLoops(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_VOLUME_LOOPS;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseVolumeMusic()
+static void execSetupChooseVolumeMusic(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_VOLUME_MUSIC;
 
   DrawSetupScreen();
 }
 
-static void execSetupSound()
+static void execSetupSound(void)
 {
   if (volumes_simple == NULL)
   {
@@ -5344,63 +5440,63 @@ static void execSetupSound()
   DrawSetupScreen();
 }
 
-static void execSetupChooseTouchControls()
+static void execSetupChooseTouchControls(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_TOUCH_CONTROL;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseMoveDistance()
+static void execSetupChooseMoveDistance(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_MOVE_DISTANCE;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseDropDistance()
+static void execSetupChooseDropDistance(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_DROP_DISTANCE;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseTransparency()
+static void execSetupChooseTransparency(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_TRANSPARENCY;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseGridXSize_0()
+static void execSetupChooseGridXSize_0(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_GRID_XSIZE_0;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseGridYSize_0()
+static void execSetupChooseGridYSize_0(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_GRID_YSIZE_0;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseGridXSize_1()
+static void execSetupChooseGridXSize_1(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_GRID_XSIZE_1;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseGridYSize_1()
+static void execSetupChooseGridYSize_1(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_GRID_YSIZE_1;
 
   DrawSetupScreen();
 }
 
-static void execSetupConfigureVirtualButtons()
+static void execSetupConfigureVirtualButtons(void)
 {
   setup_mode = SETUP_MODE_CONFIG_VIRT_BUTTONS;
 
@@ -5411,7 +5507,7 @@ static void execSetupConfigureVirtualButtons()
   DrawSetupScreen();
 }
 
-static void execSetupTouch()
+static void execSetupTouch(void)
 {
   int i, j, k;
 
@@ -5672,7 +5768,7 @@ static void execSetupTouch()
   DrawSetupScreen();
 }
 
-static void execSetupArtwork()
+static void execSetupArtwork(void)
 {
 #if 0
   printf("::: '%s', '%s', '%s'\n",
@@ -5698,84 +5794,84 @@ static void execSetupArtwork()
   DrawSetupScreen();
 }
 
-static void execSetupChooseGraphics()
+static void execSetupChooseGraphics(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_GRAPHICS;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseSounds()
+static void execSetupChooseSounds(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_SOUNDS;
 
   DrawSetupScreen();
 }
 
-static void execSetupChooseMusic()
+static void execSetupChooseMusic(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_MUSIC;
 
   DrawSetupScreen();
 }
 
-static void execSetupInput()
+static void execSetupInput(void)
 {
   setup_mode = SETUP_MODE_INPUT;
 
   DrawSetupScreen();
 }
 
-static void execSetupShortcuts()
+static void execSetupShortcuts(void)
 {
   setup_mode = SETUP_MODE_SHORTCUTS;
 
   DrawSetupScreen();
 }
 
-static void execSetupShortcuts1()
+static void execSetupShortcuts1(void)
 {
   setup_mode = SETUP_MODE_SHORTCUTS_1;
 
   DrawSetupScreen();
 }
 
-static void execSetupShortcuts2()
+static void execSetupShortcuts2(void)
 {
   setup_mode = SETUP_MODE_SHORTCUTS_2;
 
   DrawSetupScreen();
 }
 
-static void execSetupShortcuts3()
+static void execSetupShortcuts3(void)
 {
   setup_mode = SETUP_MODE_SHORTCUTS_3;
 
   DrawSetupScreen();
 }
 
-static void execSetupShortcuts4()
+static void execSetupShortcuts4(void)
 {
   setup_mode = SETUP_MODE_SHORTCUTS_4;
 
   DrawSetupScreen();
 }
 
-static void execSetupShortcuts5()
+static void execSetupShortcuts5(void)
 {
   setup_mode = SETUP_MODE_SHORTCUTS_5;
 
   DrawSetupScreen();
 }
 
-static void execExitSetup()
+static void execExitSetup(void)
 {
   SetGameStatus(GAME_MODE_MAIN);
 
   DrawMainMenu();
 }
 
-static void execSaveAndExitSetup()
+static void execSaveAndExitSetup(void)
 {
   SaveSetup();
   execExitSetup();
@@ -5805,6 +5901,9 @@ static struct
   { &setup.screen_rendering_mode,      execSetupChooseRenderingMode    },
   { &setup.screen_rendering_mode,      &rendering_mode_text            },
 
+  { &setup.vsync_mode,                 execSetupChooseVsyncMode        },
+  { &setup.vsync_mode,                 &vsync_mode_text                },
+
   { &setup.graphics_set,               execSetupChooseGraphics         },
   { &setup.graphics_set,               &graphics_set_name              },
 
@@ -5850,7 +5949,7 @@ static struct
   { NULL,                              NULL                            }
 };
 
-void setHideRelatedSetupEntries()
+void setHideRelatedSetupEntries(void)
 {
   int i;
 
@@ -5953,6 +6052,8 @@ static struct TokenInfo setup_info_graphics[] =
   { TYPE_ENTER_LIST,   execSetupChooseScrollDelay, "Scroll Delay:"     },
   { TYPE_STRING,       &scroll_delay_text,     ""                      },
 #endif
+  { TYPE_ENTER_LIST,   execSetupChooseVsyncMode, "Vertical Sync (VSync):" },
+  { TYPE_STRING,       &vsync_mode_text,       ""                      },
   { TYPE_SWITCH,       &setup.fade_screens,    "Fade Screens:"         },
   { TYPE_SWITCH,       &setup.quick_switch,    "Quick Player Focus Switch:" },
   { TYPE_SWITCH,       &setup.quick_doors,     "Quick Menu Doors:"     },
@@ -6194,7 +6295,7 @@ static struct TokenInfo setup_info_shortcuts_5[] =
   { 0,                 NULL,                   NULL                    }
 };
 
-static Key getSetupKey()
+static Key getSetupKey(void)
 {
   Key key = KSYM_UNDEFINED;
   boolean got_key_event = FALSE;
@@ -6449,12 +6550,9 @@ static void changeSetupValue(int screen_pos, int setup_info_pos_raw, int dx)
   {
     network.enabled = setup.network_mode;
 
-    SetGameStatus(GAME_MODE_LOADING);
-    SetDrawBackgroundMask(REDRAW_NONE);
-
     FadeOut(REDRAW_ALL);
 
-    ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
+    ClearField();
 
     FadeIn(REDRAW_ALL);
 
@@ -6463,11 +6561,6 @@ static void changeSetupValue(int screen_pos, int setup_info_pos_raw, int dx)
     else
       DisconnectFromNetworkServer();
 
-    SetGameStatus(GAME_MODE_SETUP);
-    SetDrawBackgroundMask(REDRAW_FIELD);
-
-    redraw_mask = REDRAW_ALL;
-
     DrawSetupScreen();
   }
 }
@@ -6504,7 +6597,7 @@ static struct TokenInfo *getSetupInfoFinal(struct TokenInfo *setup_info_orig)
   return setup_info_final;
 }
 
-static void DrawSetupScreen_Generic()
+static void DrawSetupScreen_Generic(void)
 {
   int fade_mask = REDRAW_FIELD;
   boolean redraw_all = FALSE;
@@ -6640,7 +6733,7 @@ void HandleSetupScreen_Generic(int mx, int my, int dx, int dy, int button)
                   setup_mode, num_setup_info, max_setup_info);
 }
 
-void DrawSetupScreen_Input()
+static void DrawSetupScreen_Input(void)
 {
   int i;
 
@@ -6794,7 +6887,7 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active)
 
 static int input_player_nr = 0;
 
-void HandleSetupScreen_Input_Player(int step, int direction)
+static void HandleSetupScreen_Input_Player(int step, int direction)
 {
   int old_player_nr = input_player_nr;
   int new_player_nr;
@@ -7548,7 +7641,7 @@ void ConfigureJoystick(int player_nr)
   DrawSetupScreen_Input();
 }
 
-boolean ConfigureVirtualButtonsMain()
+static boolean ConfigureVirtualButtonsMain(void)
 {
   static char *customize_step_text[] =
   {
@@ -7785,7 +7878,7 @@ boolean ConfigureVirtualButtonsMain()
   return success;
 }
 
-void ConfigureVirtualButtons()
+void ConfigureVirtualButtons(void)
 {
   boolean success = ConfigureVirtualButtonsMain();
 
@@ -7812,7 +7905,7 @@ void ConfigureVirtualButtons()
   }
 }
 
-void DrawSetupScreen()
+void DrawSetupScreen(void)
 {
   if (setup_mode == SETUP_MODE_INPUT)
     DrawSetupScreen_Input();
@@ -7828,6 +7921,8 @@ void DrawSetupScreen()
     DrawChooseTree(&scaling_type_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_RENDERING)
     DrawChooseTree(&rendering_mode_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_VSYNC)
+    DrawChooseTree(&vsync_mode_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_GRAPHICS)
     DrawChooseTree(&artwork.gfx_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_SOUNDS)
@@ -7862,7 +7957,7 @@ void DrawSetupScreen()
   PlayMenuSoundsAndMusic();
 }
 
-void RedrawSetupScreenAfterFullscreenToggle()
+void RedrawSetupScreenAfterFullscreenToggle(void)
 {
   if (setup_mode == SETUP_MODE_GRAPHICS ||
       setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE)
@@ -7908,6 +8003,8 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
     HandleChooseTree(mx, my, dx, dy, button, &scaling_type_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_RENDERING)
     HandleChooseTree(mx, my, dx, dy, button, &rendering_mode_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_VSYNC)
+    HandleChooseTree(mx, my, dx, dy, button, &vsync_mode_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_GRAPHICS)
     HandleChooseTree(mx, my, dx, dy, button, &artwork.gfx_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_SOUNDS)
@@ -7940,7 +8037,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
     HandleSetupScreen_Generic(mx, my, dx, dy, button);
 }
 
-void HandleGameActions()
+void HandleGameActions(void)
 {
   if (game.restart_game_message != NULL)
     RequestRestartGame(game.restart_game_message);
@@ -8091,7 +8188,7 @@ static struct
   }
 };
 
-static void CreateScreenMenubuttons()
+static void CreateScreenMenubuttons(void)
 {
   struct GadgetInfo *gi;
   unsigned int event_mask;
@@ -8156,7 +8253,7 @@ static void CreateScreenMenubuttons()
   }
 }
 
-static void CreateScreenScrollbuttons()
+static void CreateScreenScrollbuttons(void)
 {
   struct GadgetInfo *gi;
   unsigned int event_mask;
@@ -8224,7 +8321,7 @@ static void CreateScreenScrollbuttons()
   }
 }
 
-static void CreateScreenScrollbars()
+static void CreateScreenScrollbars(void)
 {
   int i;
 
@@ -8305,7 +8402,7 @@ static void CreateScreenScrollbars()
   }
 }
 
-void CreateScreenGadgets()
+void CreateScreenGadgets(void)
 {
   CreateScreenMenubuttons();
 
@@ -8313,7 +8410,7 @@ void CreateScreenGadgets()
   CreateScreenScrollbars();
 }
 
-void FreeScreenGadgets()
+void FreeScreenGadgets(void)
 {
   int i;
 
@@ -8330,7 +8427,7 @@ void MapScreenMenuGadgets(int screen_mask)
       MapGadget(screen_gadget[menubutton_info[i].gadget_id]);
 }
 
-void UnmapScreenMenuGadgets(int screen_mask)
+static void UnmapScreenMenuGadgets(int screen_mask)
 {
   int i;
 
@@ -8448,7 +8545,7 @@ static void HandleScreenGadgets(struct GadgetInfo *gi)
   }
 }
 
-void DumpScreenIdentifiers()
+void DumpScreenIdentifiers(void)
 {
   int i;