rnd-20020330-1-src
authorHolger Schemel <info@artsoft.org>
Sat, 30 Mar 2002 01:11:52 +0000 (02:11 +0100)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:36:34 +0000 (10:36 +0200)
src/game.c
src/libgame/setup.c
src/libgame/setup.h
src/screens.c

index fcfeb740e3afd3230aa60028092df703164bbb15..c0d43b8bf432636e9960977340fedff96188d52f 100644 (file)
@@ -173,10 +173,10 @@ void GetPlayerConfig()
     setup.sound = FALSE;
 
   if (!audio.loops_available)
-  {
     setup.sound_loops = FALSE;
+
+  if (!audio.music_available)
     setup.sound_music = FALSE;
-  }
 
   if (!video.fullscreen_available)
     setup.fullscreen = FALSE;
@@ -6515,7 +6515,7 @@ static void HandleGameButtons(struct GadgetInfo *gi)
        setup.sound_music = FALSE;
        FadeMusic();
       }
-      else if (audio.loops_available)
+      else if (audio.music_available)
       { 
        setup.sound = setup.sound_music = TRUE;
        if (num_bg_loops)
index def8fa9e715bad821e011abc843893996707b3d1..240fe67f928bd47524ae85afcc7a3113a5598752 100644 (file)
@@ -1007,16 +1007,16 @@ static struct LevelDirInfo ldi;
 static struct TokenInfo levelinfo_tokens[] =
 {
   /* level directory info */
-  { TYPE_STRING,  &ldi.name,           "name"                          },
-  { TYPE_STRING,  &ldi.name_short,     "name_short"                    },
-  { TYPE_STRING,  &ldi.name_sorting,   "name_sorting"                  },
-  { TYPE_STRING,  &ldi.author,         "author"                        },
-  { TYPE_STRING,  &ldi.imported_from,  "imported_from"                 },
-  { TYPE_INTEGER, &ldi.levels,         "levels"                        },
-  { TYPE_INTEGER, &ldi.first_level,    "first_level"                   },
-  { TYPE_INTEGER, &ldi.sort_priority,  "sort_priority"                 },
-  { TYPE_BOOLEAN, &ldi.level_group,    "level_group"                   },
-  { TYPE_BOOLEAN, &ldi.readonly,       "readonly"                      }
+  { TYPE_STRING,  &ldi.name,           "name"          },
+  { TYPE_STRING,  &ldi.name_short,     "name_short"    },
+  { TYPE_STRING,  &ldi.name_sorting,   "name_sorting"  },
+  { TYPE_STRING,  &ldi.author,         "author"        },
+  { TYPE_STRING,  &ldi.imported_from,  "imported_from" },
+  { TYPE_INTEGER, &ldi.levels,         "levels"        },
+  { TYPE_INTEGER, &ldi.first_level,    "first_level"   },
+  { TYPE_INTEGER, &ldi.sort_priority,  "sort_priority" },
+  { TYPE_BOOLEAN, &ldi.level_group,    "level_group"   },
+  { TYPE_BOOLEAN, &ldi.readonly,       "readonly"      }
 };
 
 static void setLevelDirInfoToDefaults(struct LevelDirInfo *ldi)
@@ -1384,66 +1384,78 @@ static void SaveUserLevelInfo()
   SetFilePermissions(filename, PERMS_PRIVATE);
 }
 
-char *getSetupLine(struct TokenInfo *token_info, char *prefix, int token_nr)
+char *getSetupValue(int type, void *value)
 {
-  int i;
-  static char entry[MAX_LINE_LEN];
-  int token_type = token_info[token_nr].type;
-  void *setup_value = token_info[token_nr].value;
-  char *token_text = token_info[token_nr].text;
-
-  /* start with the prefix, token and some spaces to format output line */
-  sprintf(entry, "%s%s:", prefix, token_text);
-  for (i=strlen(entry); i<TOKEN_VALUE_POSITION; i++)
-    strcat(entry, " ");
+  static char value_string[MAX_LINE_LEN];
 
-  /* continue with the token's value (which can have different types) */
-  switch (token_type)
+  switch (type)
   {
     case TYPE_BOOLEAN:
-      strcat(entry, (*(boolean *)setup_value ? "true" : "false"));
+      strcpy(value_string, (*(boolean *)value ? "true" : "false"));
       break;
 
     case TYPE_SWITCH:
-      strcat(entry, (*(boolean *)setup_value ? "on" : "off"));
+      strcpy(value_string, (*(boolean *)value ? "on" : "off"));
+      break;
+
+    case TYPE_YES_NO:
+      strcpy(value_string, (*(boolean *)value ? "yes" : "no"));
       break;
 
     case TYPE_KEY:
-      {
-       Key key = *(Key *)setup_value;
-       char *keyname = getKeyNameFromKey(key);
-
-       strcat(entry, getX11KeyNameFromKey(key));
-       for (i=strlen(entry); i<50; i++)
-         strcat(entry, " ");
-
-       /* add comment, if useful */
-       if (strcmp(keyname, "(undefined)") != 0 &&
-           strcmp(keyname, "(unknown)") != 0)
-       {
-         strcat(entry, "# ");
-         strcat(entry, keyname);
-       }
-      }
+      strcpy(value_string, getX11KeyNameFromKey(*(Key *)value));
       break;
 
     case TYPE_INTEGER:
-      {
-       char buffer[MAX_LINE_LEN];
-
-       sprintf(buffer, "%d", *(int *)setup_value);
-       strcat(entry, buffer);
-      }
+      sprintf(value_string, "%d", *(int *)value);
       break;
 
     case TYPE_STRING:
-      strcat(entry, *(char **)setup_value);
+      strcpy(value_string, *(char **)value);
       break;
 
     default:
+      value_string[0] = '\0';
       break;
   }
 
+  return value_string;
+}
+
+char *getSetupLine(struct TokenInfo *token_info, char *prefix, int token_nr)
+{
+  int i;
+  static char entry[MAX_LINE_LEN];
+  int token_type = token_info[token_nr].type;
+  void *setup_value = token_info[token_nr].value;
+  char *token_text = token_info[token_nr].text;
+  char *value_string = getSetupValue(token_type, setup_value);
+
+  /* start with the prefix, token and some spaces to format output line */
+  sprintf(entry, "%s%s:", prefix, token_text);
+  for (i=strlen(entry); i<TOKEN_VALUE_POSITION; i++)
+    strcat(entry, " ");
+
+  /* continue with the token's value (which can have different types) */
+  strcat(entry, value_string);
+
+  if (token_type == TYPE_KEY)
+  {
+    Key key = *(Key *)setup_value;
+    char *keyname = getKeyNameFromKey(key);
+
+    /* add comment, if useful */
+    if (strcmp(keyname, "(undefined)") != 0 &&
+       strcmp(keyname, "(unknown)") != 0)
+    {
+      for (i=strlen(entry); i<50; i++)
+       strcat(entry, " ");
+
+      strcat(entry, "# ");
+      strcat(entry, keyname);
+    }
+  }
+
   return entry;
 }
 
index d702ef1f461ea619a94a5f21d54c1c3538365d56..a644642021f9ccf075ca73af4f347490143a9b83 100644 (file)
 
 
 /* values for setup file handling */
-#define TYPE_BOOLEAN                   1
-#define TYPE_SWITCH                    2
-#define TYPE_KEY                       3
-#define TYPE_INTEGER                   4
-#define TYPE_STRING                    5
-
+#define TYPE_BOOLEAN                   (1 << 0)
+#define TYPE_SWITCH                    (1 << 1)
+#define TYPE_YES_NO                    (1 << 2)
+#define TYPE_KEY                       (1 << 3)
+#define TYPE_INTEGER                   (1 << 4)
+#define TYPE_STRING                    (1 << 5)
+
+#define TYPE_BOOLEAN_STYLE             (TYPE_BOOLEAN | \
+                                        TYPE_SWITCH  | \
+                                        TYPE_YES_NO)
+
+/* additional values for setup screen */
+#define TYPE_ENTER_MENU                        (1 << 6)
+#define TYPE_LEAVE_MENU                        (1 << 7)
+#define TYPE_EMPTY                     (1 << 8)
+#define TYPE_GHOSTED                   (1 << 9)
+
+#define TYPE_ENTER_OR_LEAVE_MENU       (TYPE_ENTER_MENU | TYPE_LEAVE_MENU)
+
+/* cookie token for file identifier and version number */
 #define TOKEN_STR_FILE_IDENTIFIER      "file_identifier"
 
 /* structures for setup file handling */
@@ -111,6 +125,7 @@ char *getTapeFilename(int);
 char *getScoreFilename(int);
 char *getSetupFilename(void);
 char *getImageFilename(char *);
+char *getCustomImageFilename(char *);
 
 void InitTapeDirectory(char *);
 void InitScoreDirectory(char *);
@@ -150,6 +165,7 @@ char *getTokenValue(struct SetupFileList *, char *);
 struct SetupFileList *loadSetupFileList(char *);
 void checkSetupFileListIdentifier(struct SetupFileList *, char *);
 void setSetupInfo(struct TokenInfo *, int, char *);
+char *getSetupValue(int, void *);
 char *getSetupLine(struct TokenInfo *, char *, int);
 
 void LoadLevelInfo(void);
index 99cbd2eafe450e464fa46e9bdb3e38511aeb6ead..ac3eaef20929d8f7147cab5b174c6e7ed3c05fce 100644 (file)
 #include "init.h"
 
 /* for DrawSetupScreen(), HandleSetupScreen() */
-#define SETUP_SCREEN_POS_START         2
-#define SETUP_SCREEN_POS_END           (SCR_FIELDY - 1)
+#define SETUP_SCREEN_POS_START         0
+#define SETUP_SCREEN_POS_END           (SCR_FIELDY - 3)
 #define SETUP_SCREEN_POS_EMPTY1                (SETUP_SCREEN_POS_END - 2)
 #define SETUP_SCREEN_POS_EMPTY2                (SETUP_SCREEN_POS_END - 2)
 
 /* for HandleSetupInputScreen() */
-#define SETUPINPUT_SCREEN_POS_START    2
-#define SETUPINPUT_SCREEN_POS_END      (SCR_FIELDY - 2)
+#define SETUPINPUT_SCREEN_POS_START    0
+#define SETUPINPUT_SCREEN_POS_END      (SCR_FIELDY - 4)
 #define SETUPINPUT_SCREEN_POS_EMPTY1   (SETUPINPUT_SCREEN_POS_START + 3)
 #define SETUPINPUT_SCREEN_POS_EMPTY2   (SETUPINPUT_SCREEN_POS_END - 1)
 
 /* for HandleChooseLevel() */
-#define MAX_LEVEL_SERIES_ON_SCREEN     (SCR_FIELDY - 2)
+#define MAX_MENU_ENTRIES_ON_SCREEN     (SCR_FIELDY - 2)
+#define MENU_SCREEN_START_YPOS         2
+#define MENU_SCREEN_VALUE_XPOS         14
 
 /* buttons and scrollbars identifiers */
 #define SCREEN_CTRL_ID_SCROLL_UP       0
@@ -203,13 +205,13 @@ static void gotoTopLevelDir()
       int num_page_entries;
       int cl_first, cl_cursor;
 
-      if (num_leveldirs <= MAX_LEVEL_SERIES_ON_SCREEN)
+      if (num_leveldirs <= MAX_MENU_ENTRIES_ON_SCREEN)
        num_page_entries = num_leveldirs;
       else
-       num_page_entries = MAX_LEVEL_SERIES_ON_SCREEN - 1;
+       num_page_entries = MAX_MENU_ENTRIES_ON_SCREEN - 1;
 
       cl_first = MAX(0, leveldir_pos - num_page_entries + 1);
-      cl_cursor = leveldir_pos - cl_first + 3;
+      cl_cursor = leveldir_pos - cl_first + 1;
 
       leveldir_current->node_parent->node_group->cl_first = cl_first;
       leveldir_current->node_parent->node_group->cl_cursor = cl_cursor;
@@ -896,31 +898,31 @@ void HandleTypeName(int newxpos, Key key)
   BackToFront();
 }
 
-static void drawCursorExt(int ypos, int color, int graphic)
+static void drawCursorExt(int pos, int color, int graphic)
 {
   static int cursor_array[SCR_FIELDY];
 
   if (graphic)
-    cursor_array[ypos] = graphic;
+    cursor_array[pos] = graphic;
 
-  graphic = cursor_array[ypos];
+  graphic = cursor_array[pos];
 
   if (color == FC_RED)
     graphic = (graphic == GFX_ARROW_BLUE_LEFT  ? GFX_ARROW_RED_LEFT  :
               graphic == GFX_ARROW_BLUE_RIGHT ? GFX_ARROW_RED_RIGHT :
               GFX_KUGEL_ROT);
 
-  DrawGraphic(0, ypos, graphic);
+  DrawGraphic(0, MENU_SCREEN_START_YPOS + pos, graphic);
 }
 
-static void initCursor(int ypos, int graphic)
+static void initCursor(int pos, int graphic)
 {
-  drawCursorExt(ypos, FC_BLUE, graphic);
+  drawCursorExt(pos, FC_BLUE, graphic);
 }
 
-static void drawCursor(int ypos, int color)
+static void drawCursor(int pos, int color)
 {
-  drawCursorExt(ypos, color, 0);
+  drawCursorExt(pos, color, 0);
 }
 
 void DrawChooseLevel()
@@ -942,7 +944,7 @@ static void AdjustChooseLevelScrollbar(int id, int first_entry)
   int items_max, items_visible, item_position;
 
   items_max = numLevelDirInfoInGroup(leveldir_current);
-  items_visible = MAX_LEVEL_SERIES_ON_SCREEN - 1;
+  items_visible = MAX_MENU_ENTRIES_ON_SCREEN - 1;
   item_position = first_entry;
 
   if (item_position > items_max - items_visible)
@@ -968,7 +970,7 @@ static void drawChooseLevelList(int first_entry, int num_page_entries)
   {
     struct LevelDirInfo *node, *node_first;
     int leveldir_pos = first_entry + i;
-    int ypos = i + 2;
+    int ypos = MENU_SCREEN_START_YPOS + i;
 
     node_first = getLevelDirInfoFirstGroupEntry(leveldir_current);
     node = getLevelDirInfoFromPos(node_first, leveldir_pos);
@@ -979,18 +981,18 @@ static void drawChooseLevelList(int first_entry, int num_page_entries)
     DrawText(SX + 32, SY + ypos * 32, buffer, FS_MEDIUM, node->color);
 
     if (node->parent_link)
-      initCursor(ypos, GFX_ARROW_BLUE_LEFT);
+      initCursor(i, GFX_ARROW_BLUE_LEFT);
     else if (node->level_group)
-      initCursor(ypos, GFX_ARROW_BLUE_RIGHT);
+      initCursor(i, GFX_ARROW_BLUE_RIGHT);
     else
-      initCursor(ypos, GFX_KUGEL_BLAU);
+      initCursor(i, GFX_KUGEL_BLAU);
   }
 
   if (first_entry > 0)
     DrawGraphic(0, 1, GFX_ARROW_BLUE_UP);
 
   if (first_entry + num_page_entries < num_leveldirs)
-    DrawGraphic(0, MAX_LEVEL_SERIES_ON_SCREEN + 1, GFX_ARROW_BLUE_DOWN);
+    DrawGraphic(0, MAX_MENU_ENTRIES_ON_SCREEN + 1, GFX_ARROW_BLUE_DOWN);
 }
 
 static void drawChooseLevelInfo(int leveldir_pos)
@@ -1021,15 +1023,16 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
 {
   static unsigned long choose_delay = 0;
   static int redraw = TRUE;
-  int x = (mx + 32 - SX) / 32, y = (my + 32 - SY) / 32;
+  int x = (mx + 32 - SX) / 32;
+  int y = (my + 32 - SY) / 32 - MENU_SCREEN_START_YPOS;
   int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
   int num_leveldirs = numLevelDirInfoInGroup(leveldir_current);
   int num_page_entries;
 
-  if (num_leveldirs <= MAX_LEVEL_SERIES_ON_SCREEN)
+  if (num_leveldirs <= MAX_MENU_ENTRIES_ON_SCREEN)
     num_page_entries = num_leveldirs;
   else
-    num_page_entries = MAX_LEVEL_SERIES_ON_SCREEN - 1;
+    num_page_entries = MAX_MENU_ENTRIES_ON_SCREEN - 1;
 
   if (button == MB_MENU_INITIALIZE)
   {
@@ -1039,7 +1042,7 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
     {
       leveldir_current->cl_first = MAX(0, leveldir_pos - num_page_entries + 1);
       leveldir_current->cl_cursor =
-       leveldir_pos - leveldir_current->cl_first + 3;
+       leveldir_pos - leveldir_current->cl_first + 1;
     }
 
     if (dx == 999)     /* first entry is set by scrollbar position */
@@ -1050,7 +1053,7 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
 
     drawChooseLevelList(leveldir_current->cl_first, num_page_entries);
     drawChooseLevelInfo(leveldir_current->cl_first +
-                       leveldir_current->cl_cursor - 3);
+                       leveldir_current->cl_cursor - 1);
     redraw = TRUE;
   }
 
@@ -1078,11 +1081,11 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
       dy = SIGN(dy);
       step = num_page_entries - 1;
       x = 1;
-      y = (dy < 0 ? 2 : num_page_entries + 3);
+      y = (dy < 0 ? 0 : num_page_entries + 1);
     }
   }
 
-  if (x == 1 && y == 2)
+  if (x == 1 && y == 0)
   {
     if (leveldir_current->cl_first > 0 &&
        (dy || DelayReached(&choose_delay, GADGET_FRAME_DELAY)))
@@ -1093,14 +1096,14 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
 
       drawChooseLevelList(leveldir_current->cl_first, num_page_entries);
       drawChooseLevelInfo(leveldir_current->cl_first +
-                         leveldir_current->cl_cursor - 3);
+                         leveldir_current->cl_cursor - 1);
       drawCursor(leveldir_current->cl_cursor - 1, FC_RED);
       AdjustChooseLevelScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL,
                                 leveldir_current->cl_first);
       return;
     }
   }
-  else if (x == 1 && y > num_page_entries + 2)
+  else if (x == 1 && y > num_page_entries)
   {
     if (leveldir_current->cl_first + num_page_entries < num_leveldirs &&
        (dy || DelayReached(&choose_delay, GADGET_FRAME_DELAY)))
@@ -1111,7 +1114,7 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
 
       drawChooseLevelList(leveldir_current->cl_first, num_page_entries);
       drawChooseLevelInfo(leveldir_current->cl_first +
-                         leveldir_current->cl_cursor - 3);
+                         leveldir_current->cl_cursor - 1);
       drawCursor(leveldir_current->cl_cursor - 1, FC_RED);
       AdjustChooseLevelScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL,
                                 leveldir_current->cl_first);
@@ -1129,7 +1132,7 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
   {
     struct LevelDirInfo *node_first, *node_cursor;
     int leveldir_pos =
-      leveldir_current->cl_first + leveldir_current->cl_cursor - 3;
+      leveldir_current->cl_first + leveldir_current->cl_cursor - 1;
 
     node_first = getLevelDirInfoFirstGroupEntry(leveldir_current);
     node_cursor = getLevelDirInfoFromPos(node_first, leveldir_pos);
@@ -1148,7 +1151,7 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
     DrawChooseLevel();
   }
 
-  if (x == 1 && y >= 3 && y <= num_page_entries + 2)
+  if (x == 1 && y > 0 && y <= num_page_entries)
   {
     if (button)
     {
@@ -1156,14 +1159,14 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
       {
        drawCursor(y - 1, FC_RED);
        drawCursor(leveldir_current->cl_cursor - 1, FC_BLUE);
-       drawChooseLevelInfo(leveldir_current->cl_first + y - 3);
+       drawChooseLevelInfo(leveldir_current->cl_first + y - 1);
        leveldir_current->cl_cursor = y;
       }
     }
     else
     {
       struct LevelDirInfo *node_first, *node_cursor;
-      int leveldir_pos = leveldir_current->cl_first + y - 3;
+      int leveldir_pos = leveldir_current->cl_first + y - 1;
 
       node_first = getLevelDirInfoFirstGroupEntry(leveldir_current);
       node_cursor = getLevelDirInfoFromPos(node_first, leveldir_pos);
@@ -1229,7 +1232,7 @@ static void drawHallOfFameList(int first_entry, int highlight_position)
   DrawText(SX + 80, SY + 8, "Hall Of Fame", FS_BIG, FC_YELLOW);
   DrawTextFCentered(46, FC_RED, "HighScores of Level %d", level_nr);
 
-  for(i=0; i<MAX_LEVEL_SERIES_ON_SCREEN; i++)
+  for(i=0; i<MAX_MENU_ENTRIES_ON_SCREEN; i++)
   {
     int entry = first_entry + i;
     int color = (entry == highlight_position ? FC_RED : FC_GREEN);
@@ -1267,7 +1270,7 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
   }
 
   if (ABS(dy) == SCR_FIELDY)   /* handle KSYM_Page_Up, KSYM_Page_Down */
-    step = MAX_LEVEL_SERIES_ON_SCREEN - 1;
+    step = MAX_MENU_ENTRIES_ON_SCREEN - 1;
 
   if (dy < 0)
   {
@@ -1283,11 +1286,11 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
   }
   else if (dy > 0)
   {
-    if (first_entry + MAX_LEVEL_SERIES_ON_SCREEN < MAX_SCORE_ENTRIES)
+    if (first_entry + MAX_MENU_ENTRIES_ON_SCREEN < MAX_SCORE_ENTRIES)
     {
       first_entry += step;
-      if (first_entry + MAX_LEVEL_SERIES_ON_SCREEN > MAX_SCORE_ENTRIES)
-       first_entry = MAX(0, MAX_SCORE_ENTRIES - MAX_LEVEL_SERIES_ON_SCREEN);
+      if (first_entry + MAX_MENU_ENTRIES_ON_SCREEN > MAX_SCORE_ENTRIES)
+       first_entry = MAX(0, MAX_SCORE_ENTRIES - MAX_MENU_ENTRIES_ON_SCREEN);
 
       drawHallOfFameList(first_entry, highlight_position);
       return;
@@ -1307,38 +1310,79 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
     DoAnimation();
 }
 
-void DrawSetupScreen()
+static void execSetupInput()
 {
-  int i;
-  static struct setup
-  {
-    boolean *value;
-    char *text;
-  } setup_info[] =
-  {
-    { &setup.sound,            "Sound:",       },
-    { &setup.sound_loops,      " Sound Loops:" },
-    { &setup.sound_music,      " Game Music:"  },
+  game_status = SETUPINPUT;
+  DrawSetupInputScreen();
+}
+
+static void execExitSetup()
+{
+  game_status = MAINMENU;
+  DrawMainMenu();
+}
+
+static void execSaveAndExitSetup()
+{
+  SaveSetup();
+  execExitSetup();
+}
+
+static struct TokenInfo setup_info[] =
+{
+  { TYPE_SWITCH,       &setup.sound,           "Sound:",       },
+  { TYPE_SWITCH,       &setup.sound_loops,     " Sound Loops:" },
+  { TYPE_SWITCH,       &setup.sound_music,     " Game Music:"  },
 #if 0
-    { &setup.toons,            "Toons:"        },
-    { &setup.double_buffering, "Buffered gfx:" },
+  { TYPE_SWITCH,       &setup.toons,           "Toons:"        },
+  { TYPE_SWITCH,       &setup.double_buffering,"Buffered gfx:" },
 #endif
-    { &setup.scroll_delay,     "Scroll Delay:" },
-    { &setup.soft_scrolling,   "Soft Scroll.:" },
+  { TYPE_SWITCH,       &setup.scroll_delay,    "Scroll Delay:" },
+  { TYPE_SWITCH,       &setup.soft_scrolling,  "Soft Scroll.:" },
 #if 0
-    { &setup.fading,           "Fading:"       },
+  { TYPE_SWITCH,       &setup.fading,          "Fading:"       },
 #endif
-    { &setup.fullscreen,       "Fullscreen:"   },
-    { &setup.quick_doors,      "Quick Doors:"  },
-    { &setup.autorecord,       "Auto-Record:"  },
-    { &setup.team_mode,                "Team-Mode:"    },
-    { &setup.handicap,         "Handicap:"     },
-    { &setup.time_limit,       "Timelimit:"    },
-    { NULL,                    "Input Devices" },
-    { NULL,                    ""              },
-    { NULL,                    "Exit"          },
-    { NULL,                    "Save and exit" }
-  };
+  { TYPE_SWITCH,       &setup.fullscreen,      "Fullscreen:"   },
+  { TYPE_SWITCH,       &setup.quick_doors,     "Quick Doors:"  },
+  { TYPE_SWITCH,       &setup.autorecord,      "Auto-Record:"  },
+  { TYPE_SWITCH,       &setup.team_mode,       "Team-Mode:"    },
+  { TYPE_SWITCH,       &setup.handicap,        "Handicap:"     },
+  { TYPE_SWITCH,       &setup.time_limit,      "Timelimit:"    },
+  { TYPE_ENTER_MENU,   execSetupInput,         "Input Devices" },
+  { TYPE_EMPTY,                NULL,                   ""              },
+  { TYPE_LEAVE_MENU,   execExitSetup,          "Exit"          },
+  { TYPE_LEAVE_MENU,   execSaveAndExitSetup,   "Save and exit" },
+  { 0,                 NULL,                   NULL            }
+};
+static int num_setup_info = 0;
+
+static void drawSetupValue(struct TokenInfo *si, int pos)
+{
+  int xpos = MENU_SCREEN_VALUE_XPOS;
+  int ypos = MENU_SCREEN_START_YPOS + pos;
+  int value_color = FC_YELLOW;
+  char *value_string = getSetupValue(si[pos].type & ~TYPE_GHOSTED,
+                                    si[pos].value);
+
+  if (si[pos].type & TYPE_SWITCH ||
+      si[pos].type & TYPE_YES_NO)
+  {
+    boolean value = *(boolean *)(si[pos].value);
+    int value_length = 3;
+
+    if (!value)
+      value_color = FC_BLUE;
+
+    if (strlen(value_string) < value_length)
+      strcat(value_string, " ");
+  }
+
+  DrawText(SX + xpos * 32, SY + ypos * 32, value_string, FS_BIG, value_color);
+}
+
+void DrawSetupScreen()
+{
+  int i;
 
   UnmapAllGadgets();
   CloseDoor(DOOR_CLOSE_2);
@@ -1346,27 +1390,32 @@ void DrawSetupScreen()
 
   DrawText(SX + 16, SY + 16, "SETUP",FS_BIG,FC_YELLOW);
 
-  for(i=SETUP_SCREEN_POS_START;i<=SETUP_SCREEN_POS_END;i++)
+  for(i=0; setup_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++)
   {
-    int base = i - SETUP_SCREEN_POS_START;
+    void *value_ptr = setup_info[i].value;
+    int ypos = MENU_SCREEN_START_YPOS + i;
 
-    if (!(i >= SETUP_SCREEN_POS_EMPTY1 && i <= SETUP_SCREEN_POS_EMPTY2))
-    {
-      DrawText(SX+32,SY+i*32, setup_info[base].text, FS_BIG,FC_GREEN);
+    /* set some entries to "unchangeable" according to other variables */
+    if ((value_ptr == &setup.sound       && !audio.sound_available) ||
+       (value_ptr == &setup.sound_loops && !audio.loops_available) ||
+       (value_ptr == &setup.sound_music && !audio.music_available) ||
+       (value_ptr == &setup.sound_music && !audio.music_available) ||
+       (value_ptr == &setup.fullscreen  && !video.fullscreen_available))
+      setup_info[i].type |= TYPE_GHOSTED;
 
-      if (strcmp(setup_info[base].text, "Input Devices") == 0)
+    DrawText(SX + 32, SY + ypos * 32, setup_info[i].text, FS_BIG, FC_GREEN);
+
+    if (setup_info[i].type & TYPE_ENTER_MENU)
        initCursor(i, GFX_ARROW_BLUE_RIGHT);
-      else
-       initCursor(i, GFX_KUGEL_BLAU);
-    }
+    else if (setup_info[i].type & TYPE_LEAVE_MENU)
+       initCursor(i, GFX_ARROW_BLUE_LEFT);
+    else if (setup_info[i].type != TYPE_EMPTY)
+      initCursor(i, GFX_KUGEL_BLAU);
 
-    if (setup_info[base].value)
-    {
-      int setting_value = *setup_info[base].value;
+    if (setup_info[i].type & TYPE_BOOLEAN_STYLE)
+      drawSetupValue(setup_info, i);
 
-      DrawText(SX+14*32, SY+i*32, (setting_value ? "on" : "off"),
-              FS_BIG, (setting_value ? FC_YELLOW : FC_BLUE));
-    }
+    num_setup_info++;
   }
 
   FadeToFront();
@@ -1374,22 +1423,305 @@ void DrawSetupScreen()
   HandleSetupScreen(0,0,0,0,MB_MENU_INITIALIZE);
 }
 
+
+#if 1
+
 void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
 {
-  static int choice = 3;
+  static int choice = 0;
+  static int redraw = TRUE;
+  int x = (mx - SX) / 32;
+  int y = (my - SY) / 32 - MENU_SCREEN_START_YPOS;
+  int pos_start  = SETUP_SCREEN_POS_START;
+  int pos_empty1 = SETUP_SCREEN_POS_EMPTY1;
+  int pos_empty2 = SETUP_SCREEN_POS_EMPTY2;
+  int pos_end    = SETUP_SCREEN_POS_END;
+
+  if (button == MB_MENU_INITIALIZE)
+    redraw = TRUE;
+
+  if (redraw)
+  {
+    drawCursor(choice, FC_RED);
+    redraw = FALSE;
+  }
+
+  if (button == MB_MENU_INITIALIZE)
+    return;
+
+  if (dx || dy)
+  {
+    x = 0;
+    y = choice;
+
+    if (dx)
+    {
+      int type = (dx < 0 ? TYPE_LEAVE_MENU : TYPE_ENTER_MENU);
+
+      if (!(setup_info[choice].type & TYPE_ENTER_OR_LEAVE_MENU) ||
+         setup_info[choice].type == type)
+       button = MB_MENU_CHOICE;
+    }
+    else if (dy)
+      y = choice + dy;
+
+    /* stay in valid range */
+    if (y < 0)
+      y = 0;
+    else if (y > num_setup_info - 1)
+      y = num_setup_info - 1;
+
+    /* jump to next non-empty menu entry (up or down) */
+    if (setup_info[y].type == TYPE_EMPTY)
+      while (y > 0 && y < num_setup_info - 1 &&
+            setup_info[y].type == TYPE_EMPTY)
+       y += dy;
+  }
+
+  if (!mx && !my && !dx && !dy)
+  {
+    x = 0;
+    y = choice;
+  }
+
+  if (x == 0 && y >= 0 && y < num_setup_info &&
+      setup_info[y].type != TYPE_EMPTY)
+  {
+    if (button)
+    {
+      if (y != choice)
+      {
+       drawCursor(y, FC_RED);
+       drawCursor(choice, FC_BLUE);
+       choice = y;
+      }
+    }
+    else if (!(setup_info[y].type & TYPE_GHOSTED))
+    {
+      if (setup_info[y].type & TYPE_BOOLEAN_STYLE)
+      {
+       boolean new_value = !*(boolean *)(setup_info[y].value);
+
+       *(boolean *)setup_info[y].value = new_value;
+
+       drawSetupValue(setup_info, y);
+      }
+      else if (setup_info[y].type & TYPE_ENTER_OR_LEAVE_MENU)
+      {
+       void (*menu_callback_function)(void) = setup_info[choice].value;
+
+       menu_callback_function();
+       redraw = TRUE;
+      }
+    }
+  }
+
+  BackToFront();
+
+  if (game_status == SETUP)
+    DoAnimation();
+
+  return;
+
+
+
+  if (x == 0 && y >= pos_start && y <= pos_end &&
+      !(y >= pos_empty1 && y <= pos_empty2))
+  {
+    if (button)
+    {
+      if (y != choice)
+      {
+       drawCursor(y, FC_RED);
+       drawCursor(choice, FC_BLUE);
+      }
+      choice = y;
+    }
+    else
+    {
+      int yy = MENU_SCREEN_START_YPOS + y;
+
+      if (y == 0 && audio.sound_available)
+      {
+       if (setup.sound)
+       {
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+         DrawText(SX+14*32, SY+(yy+1)*32,"off",FS_BIG,FC_BLUE);
+         DrawText(SX+14*32, SY+(yy+2)*32,"off",FS_BIG,FC_BLUE);
+         setup.sound_loops = FALSE;
+         setup.sound_music = FALSE;
+       }
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.sound = !setup.sound;
+      }
+      else if (y == 1 && audio.loops_available)
+      {
+       if (setup.sound_loops)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+       {
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+         DrawText(SX+14*32, SY+(yy-1)*32,"on ",FS_BIG,FC_YELLOW);
+         setup.sound = TRUE;
+       }
+       setup.sound_loops = !setup.sound_loops;
+      }
+      else if (y == 2 && audio.loops_available)
+      {
+       if (setup.sound_music)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+       {
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+         DrawText(SX+14*32, SY+(yy-2)*32,"on ",FS_BIG,FC_YELLOW);
+         setup.sound = TRUE;
+       }
+       setup.sound_music = !setup.sound_music;
+      }
+
+#if 0
+      else if (y == 3)
+      {
+       if (setup.toons)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.toons = !setup.toons;
+      }
+      else if (y == 4)
+      {
+#if 0
+       if (setup.double_buffering)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.double_buffering = !setup.double_buffering;
+       setup.direct_draw = !setup.double_buffering;
+#else
+       DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.double_buffering = TRUE;
+       setup.direct_draw = !setup.double_buffering;
+#endif
+      }
+#endif
+
+      else if (y == 3)
+      {
+       if (setup.scroll_delay)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.scroll_delay = !setup.scroll_delay;
+      }
+      else if (y == 4)
+      {
+       if (setup.soft_scrolling)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.soft_scrolling = !setup.soft_scrolling;
+      }
+#if 0
+      else if (y == 5)
+      {
+       if (setup.fading)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.fading = !setup.fading;
+      }
+#endif
+      else if (y == 5 && video.fullscreen_available)
+      {
+       if (setup.fullscreen)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.fullscreen = !setup.fullscreen;
+      }
+      else if (y == 6)
+      {
+       if (setup.quick_doors)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.quick_doors = !setup.quick_doors;
+      }
+      else if (y == 7)
+      {
+       if (setup.autorecord)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.autorecord = !setup.autorecord;
+      }
+      else if (y == 8)
+      {
+       if (setup.team_mode)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.team_mode = !setup.team_mode;
+      }
+      else if (y == 9)
+      {
+       if (setup.handicap)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.handicap = !setup.handicap;
+      }
+      else if (y == 10)
+      {
+       if (setup.time_limit)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.time_limit = !setup.time_limit;
+      }
+      else if (y == 11)
+      {
+       game_status = SETUPINPUT;
+       DrawSetupInputScreen();
+       redraw = TRUE;
+      }
+      else if (y == pos_end - 1 || y == pos_end)
+      {
+        if (y == pos_end)
+         SaveSetup();
+
+       game_status = MAINMENU;
+       DrawMainMenu();
+       redraw = TRUE;
+      }
+    }
+  }
+  BackToFront();
+
+  if (game_status==SETUP)
+    DoAnimation();
+}
+
+#else
+
+void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
+{
+  static int choice = 0;
   static int redraw = TRUE;
-  int x = (mx+32-SX)/32, y = (my+32-SY)/32;
-  int pos_start  = SETUP_SCREEN_POS_START  + 1;
-  int pos_empty1 = SETUP_SCREEN_POS_EMPTY1 + 1;
-  int pos_empty2 = SETUP_SCREEN_POS_EMPTY2 + 1;
-  int pos_end    = SETUP_SCREEN_POS_END    + 1;
+  int x = (mx - SX) / 32;
+  int y = (my - SY) / 32 - MENU_SCREEN_START_YPOS;
+  int pos_start  = SETUP_SCREEN_POS_START;
+  int pos_empty1 = SETUP_SCREEN_POS_EMPTY1;
+  int pos_empty2 = SETUP_SCREEN_POS_EMPTY2;
+  int pos_end    = SETUP_SCREEN_POS_END;
 
   if (button == MB_MENU_INITIALIZE)
     redraw = TRUE;
 
   if (redraw)
   {
-    drawCursor(choice - 1, FC_RED);
+    drawCursor(choice, FC_RED);
     redraw = FALSE;
   }
 
@@ -1400,11 +1732,11 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
   {
     if (dy)
     {
-      x = 1;
-      y = choice+dy;
+      x = 0;
+      y = choice + dy;
     }
     else
-      x = y = 0;
+      x = y = -1;
 
     if (y >= pos_empty1 && y <= pos_empty2)
       y = (dy > 0 ? pos_empty2 + 1 : pos_empty1 - 1);
@@ -1417,34 +1749,34 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
 
   if (!mx && !my && !dx && !dy)
   {
-    x = 1;
+    x = 0;
     y = choice;
   }
 
-  if (dx == 1 && choice == 14)
+  if (dx == 1 && choice == 11)
   {
     game_status = SETUPINPUT;
     DrawSetupInputScreen();
     redraw = TRUE;
   }
 
-  if (x==1 && y >= pos_start && y <= pos_end &&
+  if (x == 0 && y >= pos_start && y <= pos_end &&
       !(y >= pos_empty1 && y <= pos_empty2))
   {
     if (button)
     {
-      if (y!=choice)
+      if (y != choice)
       {
-       drawCursor(y - 1, FC_RED);
-       drawCursor(choice - 1, FC_BLUE);
+       drawCursor(y, FC_RED);
+       drawCursor(choice, FC_BLUE);
       }
       choice = y;
     }
     else
     {
-      int yy = y-1;
+      int yy = MENU_SCREEN_START_YPOS + y;
 
-      if (y == 3 && audio.sound_available)
+      if (y == 0 && audio.sound_available)
       {
        if (setup.sound)
        {
@@ -1458,7 +1790,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.sound = !setup.sound;
       }
-      else if (y == 4 && audio.loops_available)
+      else if (y == 1 && audio.loops_available)
       {
        if (setup.sound_loops)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1470,7 +1802,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
        }
        setup.sound_loops = !setup.sound_loops;
       }
-      else if (y == 5 && audio.loops_available)
+      else if (y == 2 && audio.loops_available)
       {
        if (setup.sound_music)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1484,7 +1816,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
       }
 
 #if 0
-      else if (y == 6)
+      else if (y == 3)
       {
        if (setup.toons)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1492,7 +1824,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.toons = !setup.toons;
       }
-      else if (y == 7)
+      else if (y == 4)
       {
 #if 0
        if (setup.double_buffering)
@@ -1509,7 +1841,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
       }
 #endif
 
-      else if (y == 6)
+      else if (y == 3)
       {
        if (setup.scroll_delay)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1517,7 +1849,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.scroll_delay = !setup.scroll_delay;
       }
-      else if (y == 7)
+      else if (y == 4)
       {
        if (setup.soft_scrolling)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1526,7 +1858,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
        setup.soft_scrolling = !setup.soft_scrolling;
       }
 #if 0
-      else if (y == 8)
+      else if (y == 5)
       {
        if (setup.fading)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1535,7 +1867,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
        setup.fading = !setup.fading;
       }
 #endif
-      else if (y == 8 && video.fullscreen_available)
+      else if (y == 5 && video.fullscreen_available)
       {
        if (setup.fullscreen)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1543,7 +1875,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.fullscreen = !setup.fullscreen;
       }
-      else if (y == 9)
+      else if (y == 6)
       {
        if (setup.quick_doors)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1551,7 +1883,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.quick_doors = !setup.quick_doors;
       }
-      else if (y == 10)
+      else if (y == 7)
       {
        if (setup.autorecord)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1559,7 +1891,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.autorecord = !setup.autorecord;
       }
-      else if (y == 11)
+      else if (y == 8)
       {
        if (setup.team_mode)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1567,7 +1899,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.team_mode = !setup.team_mode;
       }
-      else if (y == 12)
+      else if (y == 9)
       {
        if (setup.handicap)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1575,7 +1907,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.handicap = !setup.handicap;
       }
-      else if (y == 13)
+      else if (y == 10)
       {
        if (setup.time_limit)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1583,7 +1915,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.time_limit = !setup.time_limit;
       }
-      else if (y == 14)
+      else if (y == 11)
       {
        game_status = SETUPINPUT;
        DrawSetupInputScreen();
@@ -1606,18 +1938,21 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
     DoAnimation();
 }
 
+#endif
+
+
 void DrawSetupInputScreen()
 {
   ClearWindow();
   DrawText(SX+16, SY+16, "SETUP INPUT", FS_BIG, FC_YELLOW);
 
-  initCursor(2, GFX_KUGEL_BLAU);
-  initCursor(3, GFX_KUGEL_BLAU);
-  initCursor(4, GFX_ARROW_BLUE_RIGHT);
-  initCursor(15, GFX_KUGEL_BLAU);
+  initCursor(0, GFX_KUGEL_BLAU);
+  initCursor(1, GFX_KUGEL_BLAU);
+  initCursor(2, GFX_ARROW_BLUE_RIGHT);
+  initCursor(13, GFX_KUGEL_BLAU);
 
-  DrawGraphic(10, 2, GFX_ARROW_BLUE_LEFT);
-  DrawGraphic(12, 2, GFX_ARROW_BLUE_RIGHT);
+  DrawGraphic(10, MENU_SCREEN_START_YPOS, GFX_ARROW_BLUE_LEFT);
+  DrawGraphic(12, MENU_SCREEN_START_YPOS, GFX_ARROW_BLUE_RIGHT);
 
   DrawText(SX+32, SY+2*32, "Player:", FS_BIG, FC_GREEN);
   DrawText(SX+32, SY+3*32, "Device:", FS_BIG, FC_GREEN);
@@ -1726,14 +2061,15 @@ static void drawPlayerSetupInputInfo(int player_nr)
 
 void HandleSetupInputScreen(int mx, int my, int dx, int dy, int button)
 {
-  static int choice = 3;
+  static int choice = 0;
   static int player_nr = 0;
   static int redraw = TRUE;
-  int x = (mx+32-SX)/32, y = (my+32-SY)/32;
-  int pos_start  = SETUPINPUT_SCREEN_POS_START  + 1;
-  int pos_empty1 = SETUPINPUT_SCREEN_POS_EMPTY1 + 1;
-  int pos_empty2 = SETUPINPUT_SCREEN_POS_EMPTY2 + 1;
-  int pos_end    = SETUPINPUT_SCREEN_POS_END    + 1;
+  int x = (mx - SX) / 32;
+  int y = (my - SY) / 32 - MENU_SCREEN_START_YPOS;
+  int pos_start  = SETUPINPUT_SCREEN_POS_START;
+  int pos_empty1 = SETUPINPUT_SCREEN_POS_EMPTY1;
+  int pos_empty2 = SETUPINPUT_SCREEN_POS_EMPTY2;
+  int pos_end    = SETUPINPUT_SCREEN_POS_END;
 
   if (button == MB_MENU_INITIALIZE)
   {
@@ -1743,7 +2079,7 @@ void HandleSetupInputScreen(int mx, int my, int dx, int dy, int button)
 
   if (redraw)
   {
-    drawCursor(choice - 1, FC_RED);
+    drawCursor(choice, FC_RED);
     redraw = FALSE;
   }
 
@@ -1752,24 +2088,24 @@ void HandleSetupInputScreen(int mx, int my, int dx, int dy, int button)
 
   if (dx || dy)
   {
-    if (dx && choice == 3)
+    if (dx && choice == 0)
     {
-      x = (dx < 0 ? 11 : 13);
-      y = 3;
+      x = (dx < 0 ? 10 : 12);
+      y = 0;
     }
-    else if (dx && choice == 4)
+    else if (dx && choice == 1)
     {
       button = MB_MENU_CHOICE;
-      x = 1;
-      y = 4;
+      x = 0;
+      y = 1;
     }
     else if (dy)
     {
-      x = 1;
+      x = 0;
       y = choice + dy;
     }
     else
-      x = y = 0;
+      x = y = -1;
 
     if (y >= pos_empty1 && y <= pos_empty2)
       y = (dy > 0 ? pos_empty2 + 1 : pos_empty1 - 1);
@@ -1782,36 +2118,36 @@ void HandleSetupInputScreen(int mx, int my, int dx, int dy, int button)
 
   if (!mx && !my && !dx && !dy)
   {
-    x = 1;
+    x = 0;
     y = choice;
   }
 
-  if (y == 3 && ((x == 1 && !button) || ((x == 11 || x == 13) && button)))
+  if (y == 0 && ((x == 0 && !button) || ((x == 10 || x == 12) && button)))
   {
     static unsigned long delay = 0;
 
     if (!DelayReached(&delay, GADGET_FRAME_DELAY))
       goto out;
 
-    player_nr = (player_nr + (x == 11 ? -1 : +1) + MAX_PLAYERS) % MAX_PLAYERS;
+    player_nr = (player_nr + (x == 10 ? -1 : +1) + MAX_PLAYERS) % MAX_PLAYERS;
 
     drawPlayerSetupInputInfo(player_nr);
   }
-  else if (x==1 && y >= pos_start && y <= pos_end &&
+  else if (x == 0 && y >= pos_start && y <= pos_end &&
           !(y >= pos_empty1 && y <= pos_empty2))
   {
     if (button)
     {
       if (y != choice)
       {
-       drawCursor(y - 1, FC_RED);
-       drawCursor(choice - 1, FC_BLUE);
+       drawCursor(y, FC_RED);
+       drawCursor(choice, FC_BLUE);
       }
       choice = y;
     }
     else
     {
-      if (y == 4)
+      if (y == 1)
       {
        char *device_name = setup.input[player_nr].joy.device_name;
 
@@ -1835,7 +2171,7 @@ void HandleSetupInputScreen(int mx, int my, int dx, int dy, int button)
 
        drawPlayerSetupInputInfo(player_nr);
       }
-      else if (y == 5)
+      else if (y == 2)
       {
        if (setup.input[player_nr].use_joystick)
        {
@@ -2335,13 +2671,13 @@ static void CreateScreenScrollbars()
     struct GadgetInfo *gi;
     int items_max, items_visible, item_position;
     unsigned long event_mask;
-    int num_page_entries = MAX_LEVEL_SERIES_ON_SCREEN - 1;
+    int num_page_entries = MAX_MENU_ENTRIES_ON_SCREEN - 1;
 
 #if 0
-    if (num_leveldirs <= MAX_LEVEL_SERIES_ON_SCREEN)
+    if (num_leveldirs <= MAX_MENU_ENTRIES_ON_SCREEN)
       num_page_entries = num_leveldirs;
     else
-      num_page_entries = MAX_LEVEL_SERIES_ON_SCREEN - 1;
+      num_page_entries = MAX_MENU_ENTRIES_ON_SCREEN - 1;
 
     items_max = MAX(num_leveldirs, num_page_entries);
     items_visible = num_page_entries;
@@ -2396,7 +2732,7 @@ void MapChooseLevelGadgets()
   int num_leveldirs = numLevelDirInfoInGroup(leveldir_current);
   int i;
 
-  if (num_leveldirs <= MAX_LEVEL_SERIES_ON_SCREEN)
+  if (num_leveldirs <= MAX_MENU_ENTRIES_ON_SCREEN)
     return;
 
   for (i=0; i<NUM_SCREEN_GADGETS; i++)