fix a buffer overflow
[libpicofe.git] / menu.c
diff --git a/menu.c b/menu.c
index 3acab62..2447bce 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -1,10 +1,11 @@
 /*\r
- * (C) Gražvydas "notaz" Ignotas, 2006-2011\r
+ * (C) Gražvydas "notaz" Ignotas, 2006-2012\r
  *\r
  * This work is licensed under the terms of any of these licenses\r
  * (at your option):\r
  *  - GNU GPL, version 2 or later.\r
  *  - GNU LGPL, version 2.1 or later.\r
+ *  - MAME license.\r
  * See the COPYING file in the top-level directory.\r
  */\r
 \r
@@ -30,13 +31,13 @@ void *g_menuscreen_ptr;
 void *g_menubg_src_ptr;\r
 void *g_menubg_ptr;\r
 \r
-#if !MSCREEN_SIZE_FIXED\r
 int g_menuscreen_w;\r
 int g_menuscreen_h;\r
-#endif\r
+\r
+int g_autostateld_opt;\r
 \r
 static unsigned char *menu_font_data = NULL;\r
-static int menu_text_color = 0xffff; // default to white\r
+static int menu_text_color = 0xfffe; // default to white\r
 static int menu_sel_color = -1; // disabled\r
 \r
 /* note: these might become non-constant in future */\r
@@ -48,6 +49,10 @@ static const int me_mfont_w = 8, me_mfont_h = 10;
 static const int me_sfont_w = 6, me_sfont_h = 10;\r
 #endif\r
 \r
+static int g_menu_filter_off;\r
+static int g_border_style;\r
+static int border_left, border_right, border_top, border_bottom;\r
+\r
 // draws text to current bbp16 screen\r
 static void text_out16_(int x, int y, const char *text, int color)\r
 {\r
@@ -106,6 +111,15 @@ static void text_out16_(int x, int y, const char *text, int color)
                }\r
                dest += me_mfont_w;\r
        }\r
+\r
+       if (x < border_left)\r
+               border_left = x;\r
+       if (x + i * me_mfont_w > border_right)\r
+               border_right = x + i * me_mfont_w;\r
+       if (y < border_top)\r
+               border_top = y;\r
+       if (y + me_mfont_h > border_bottom)\r
+               border_bottom = y + me_mfont_h;\r
 }\r
 \r
 void text_out16(int x, int y, const char *texto, ...)\r
@@ -223,9 +237,9 @@ static char tolower_simple(char c)
        return c;\r
 }\r
 \r
-void menu_init(void)\r
+void menu_init_base(void)\r
 {\r
-       int i, c, l;\r
+       int i, c, l, pos;\r
        unsigned char *fd, *fds;\r
        char buff[256];\r
        FILE *f;\r
@@ -238,7 +252,7 @@ void menu_init(void)
                return;\r
 \r
        // generate default 8x10 font from fontdata8x8\r
-       for (c = 0, fd = menu_font_data; c < 256; c++)\r
+       for (c = 0, fd = menu_font_data; c < 128; c++)\r
        {\r
                for (l = 0; l < 8; l++)\r
                {\r
@@ -280,17 +294,18 @@ void menu_init(void)
        }\r
 \r
        // load custom font and selector (stored as 1st symbol in font table)\r
-       emu_make_path(buff, "skin/font.png", sizeof(buff));\r
+       pos = plat_get_skin_dir(buff, sizeof(buff));\r
+       strcpy(buff + pos, "font.png");\r
        readpng(menu_font_data, buff, READPNG_FONT,\r
                MENU_X2 ? 256 : 128, MENU_X2 ? 320 : 160);\r
        // default selector symbol is '>'\r
        memcpy(menu_font_data, menu_font_data + ((int)'>') * me_mfont_w * me_mfont_h / 2,\r
                me_mfont_w * me_mfont_h / 2);\r
-       emu_make_path(buff, "skin/selector.png", sizeof(buff));\r
+       strcpy(buff + pos, "selector.png");\r
        readpng(menu_font_data, buff, READPNG_SELECTOR, me_mfont_w, me_mfont_h);\r
 \r
        // load custom colors\r
-       emu_make_path(buff, "skin/skin.txt", sizeof(buff));\r
+       strcpy(buff + pos, "skin.txt");\r
        f = fopen(buff, "r");\r
        if (f != NULL)\r
        {\r
@@ -323,18 +338,6 @@ void menu_init(void)
        setlocale(LC_TIME, "");\r
 }\r
 \r
-static void menu_draw_begin(int need_bg)\r
-{\r
-       plat_video_menu_begin();\r
-       if (need_bg)\r
-               memcpy(g_menuscreen_ptr, g_menubg_ptr, g_menuscreen_w * g_menuscreen_h * 2);\r
-}\r
-\r
-static void menu_draw_end(void)\r
-{\r
-       plat_video_menu_end();\r
-}\r
-\r
 static void menu_darken_bg(void *dst, void *src, int pixels, int darker)\r
 {\r
        unsigned int *dest = dst;\r
@@ -358,6 +361,88 @@ static void menu_darken_bg(void *dst, void *src, int pixels, int darker)
        }\r
 }\r
 \r
+static void menu_darken_text_bg(void)\r
+{\r
+       int x, y, xmin, xmax, ymax, ls;\r
+       unsigned short *screen = g_menuscreen_ptr;\r
+\r
+       xmin = border_left - 3;\r
+       if (xmin < 0)\r
+               xmin = 0;\r
+       xmax = border_right + 2;\r
+       if (xmax > g_menuscreen_w - 1)\r
+               xmax = g_menuscreen_w - 1;\r
+\r
+       y = border_top - 3;\r
+       if (y < 0)\r
+               y = 0;\r
+       ymax = border_bottom + 2;\r
+       if (ymax > g_menuscreen_h - 1)\r
+               ymax = g_menuscreen_h - 1;\r
+\r
+       for (x = xmin; x <= xmax; x++)\r
+               screen[y * g_menuscreen_w + x] = 0xa514;\r
+       for (y++; y < ymax; y++)\r
+       {\r
+               ls = y * g_menuscreen_w;\r
+               screen[ls + xmin] = 0xffff;\r
+               for (x = xmin + 1; x < xmax; x++)\r
+               {\r
+                       unsigned int p = screen[ls + x];\r
+                       if (p != menu_text_color)\r
+                               screen[ls + x] = ((p&0xf79e)>>1) - ((p&0xc618)>>3);\r
+               }\r
+               screen[ls + xmax] = 0xffff;\r
+       }\r
+       ls = y * g_menuscreen_w;\r
+       for (x = xmin; x <= xmax; x++)\r
+               screen[ls + x] = 0xffff;\r
+}\r
+\r
+static int borders_pending;\r
+\r
+static void menu_reset_borders(void)\r
+{\r
+       border_left = g_menuscreen_w;\r
+       border_right = 0;\r
+       border_top = g_menuscreen_h;\r
+       border_bottom = 0;\r
+}\r
+\r
+static void menu_draw_begin(int need_bg, int no_borders)\r
+{\r
+       plat_video_menu_begin();\r
+\r
+       menu_reset_borders();\r
+       borders_pending = g_border_style && !no_borders;\r
+\r
+       if (need_bg) {\r
+               if (g_border_style && no_borders) {\r
+                       menu_darken_bg(g_menuscreen_ptr, g_menubg_ptr,\r
+                               g_menuscreen_w * g_menuscreen_h, 1);\r
+               }\r
+               else {\r
+                       memcpy(g_menuscreen_ptr, g_menubg_ptr,\r
+                               g_menuscreen_w * g_menuscreen_h * 2);\r
+               }\r
+       }\r
+}\r
+\r
+static void menu_draw_end(void)\r
+{\r
+       if (borders_pending)\r
+               menu_darken_text_bg();\r
+       plat_video_menu_end();\r
+}\r
+\r
+static void menu_separation(void)\r
+{\r
+       if (borders_pending) {\r
+               menu_darken_text_bg();\r
+               menu_reset_borders();\r
+       }\r
+}\r
+\r
 static int me_id2offset(const menu_entry *ent, menu_id id)\r
 {\r
        int i;\r
@@ -487,7 +572,7 @@ static void me_draw(const menu_entry *entries, int sel, void (*draw_more)(void))
 #endif\r
 \r
        /* draw */\r
-       menu_draw_begin(1);\r
+       menu_draw_begin(1, 0);\r
        menu_draw_selection(x, y + vi_sel_ln * me_mfont_h, w);\r
        x += me_mfont_w * 2;\r
 \r
@@ -548,6 +633,8 @@ static void me_draw(const menu_entry *entries, int sel, void (*draw_more)(void))
                y += me_mfont_h;\r
        }\r
 \r
+       menu_separation();\r
+\r
        /* display help or message if we have one */\r
        h = (g_menuscreen_h - h) / 2; // bottom area height\r
        if (menu_error_msg[0] != 0) {\r
@@ -569,6 +656,8 @@ static void me_draw(const menu_entry *entries, int sel, void (*draw_more)(void))
                                smalltext_out16(5, g_menuscreen_h - (l * me_sfont_h + 4), tmp, 0xffff);\r
        }\r
 \r
+       menu_separation();\r
+\r
        if (draw_more != NULL)\r
                draw_more();\r
 \r
@@ -710,7 +799,7 @@ static void draw_menu_message(const char *msg, void (*draw_more)(void))
        if (x < 0) x = 0;\r
        if (y < 0) y = 0;\r
 \r
-       menu_draw_begin(1);\r
+       menu_draw_begin(1, 0);\r
 \r
        for (p = msg; *p != 0 && y <= g_menuscreen_h - me_mfont_h; y += me_mfont_h) {\r
                text_out16(x, y, p);\r
@@ -721,6 +810,8 @@ static void draw_menu_message(const char *msg, void (*draw_more)(void))
                        p++;\r
        }\r
 \r
+       menu_separation();\r
+\r
        if (draw_more != NULL)\r
                draw_more();\r
 \r
@@ -735,7 +826,7 @@ static void do_delete(const char *fpath, const char *fname)
        const char *nm;\r
        char tmp[64];\r
 \r
-       menu_draw_begin(1);\r
+       menu_draw_begin(1, 0);\r
 \r
        len = strlen(fname);\r
        if (len > g_menuscreen_w / me_sfont_w)\r
@@ -764,16 +855,18 @@ static void do_delete(const char *fpath, const char *fname)
 \r
 // -------------- ROM selector --------------\r
 \r
-static void draw_dirlist(char *curdir, struct dirent **namelist, int n, int sel)\r
+static void draw_dirlist(char *curdir, struct dirent **namelist,\r
+       int n, int sel, int show_help)\r
 {\r
        int max_cnt, start, i, x, pos;\r
        void *darken_ptr;\r
+       char buff[64];\r
 \r
        max_cnt = g_menuscreen_h / me_sfont_h;\r
        start = max_cnt / 2 - sel;\r
        n--; // exclude current dir (".")\r
 \r
-       menu_draw_begin(1);\r
+       menu_draw_begin(1, 1);\r
 \r
 //     if (!rom_loaded)\r
 //             menu_darken_bg(gp2x_screen, 320*240, 0);\r
@@ -797,6 +890,28 @@ static void draw_dirlist(char *curdir, struct dirent **namelist, int n, int sel)
                }\r
        }\r
        smalltext_out16(5, max_cnt/2 * me_sfont_h, ">", 0xffff);\r
+\r
+       if (show_help) {\r
+               darken_ptr = (short *)g_menuscreen_ptr\r
+                       + g_menuscreen_w * (g_menuscreen_h - me_sfont_h * 5 / 2);\r
+               menu_darken_bg(darken_ptr, darken_ptr,\r
+                       g_menuscreen_w * (me_sfont_h * 5 / 2), 1);\r
+\r
+               snprintf(buff, sizeof(buff), "%s - select, %s - back",\r
+                       in_get_key_name(-1, -PBTN_MOK), in_get_key_name(-1, -PBTN_MBACK));\r
+               smalltext_out16(x, g_menuscreen_h - me_sfont_h * 3 - 2, buff, 0xe78c);\r
+\r
+               snprintf(buff, sizeof(buff), g_menu_filter_off ?\r
+                        "%s - hide unknown files" : "%s - show all files",\r
+                       in_get_key_name(-1, -PBTN_MA3));\r
+               smalltext_out16(x, g_menuscreen_h - me_sfont_h * 2 - 2, buff, 0xe78c);\r
+\r
+               snprintf(buff, sizeof(buff), g_autostateld_opt ?\r
+                        "%s - autoload save is ON" : "%s - autoload save is OFF",\r
+                       in_get_key_name(-1, -PBTN_MA2));\r
+               smalltext_out16(x, g_menuscreen_h - me_sfont_h * 1 - 2, buff, 0xe78c);\r
+       }\r
+\r
        menu_draw_end();\r
 }\r
 \r
@@ -814,21 +929,30 @@ static int scandir_cmp(const void *p1, const void *p2)
        return alphasort(d1, d2);\r
 }\r
 \r
+static const char **filter_exts_internal;\r
+\r
 static int scandir_filter(const struct dirent *ent)\r
 {\r
-       const char *p;\r
+       const char **filter = filter_exts_internal;\r
+       const char *ext;\r
        int i;\r
 \r
-       if (ent == NULL || ent->d_name == NULL) return 0;\r
-       if (strlen(ent->d_name) < 5) return 1;\r
+       if (ent == NULL || ent->d_name == NULL)\r
+               return 0;\r
 \r
-       p = ent->d_name + strlen(ent->d_name) - 4;\r
+       if (ent->d_type == DT_DIR)\r
+               return 1;\r
 \r
-       for (i = 0; i < array_size(filter_exts); i++)\r
-               if (strcmp(p, filter_exts[i]) == 0)\r
-                       return 0;\r
+       ext = strrchr(ent->d_name, '.');\r
+       if (ext == NULL)\r
+               return 0;\r
+\r
+       ext++;\r
+       for (i = 0; filter[i] != NULL; i++)\r
+               if (strcasecmp(ext, filter[i]) == 0)\r
+                       return 1;\r
 \r
-       return 1;\r
+       return 0;\r
 }\r
 \r
 static int dirent_seek_char(struct dirent **namelist, int len, int sel, char c)\r
@@ -836,9 +960,11 @@ static int dirent_seek_char(struct dirent **namelist, int len, int sel, char c)
        int i;\r
 \r
        sel++;\r
-       for (i = sel + 1; i != sel; i++) {\r
+       for (i = sel + 1; ; i++) {\r
                if (i >= len)\r
                        i = 1;\r
+               if (i == sel)\r
+                       break;\r
 \r
                if (tolower_simple(namelist[i]->d_name[0]) == c)\r
                        break;\r
@@ -847,24 +973,49 @@ static int dirent_seek_char(struct dirent **namelist, int len, int sel, char c)
        return i - 1;\r
 }\r
 \r
-static char *menu_loop_romsel(char *curr_path, int len)\r
+static const char *menu_loop_romsel(char *curr_path, int len,\r
+       const char **filter_exts,\r
+       int (*extra_filter)(struct dirent **namelist, int count,\r
+                           const char *basedir))\r
 {\r
-       struct dirent **namelist;\r
-       int n, inp, sel = 0;\r
-       char *ret = NULL, *fname = NULL;\r
+       static char rom_fname_reload[256]; // used for return\r
+       char sel_fname[256];\r
+       int (*filter)(const struct dirent *);\r
+       struct dirent **namelist = NULL;\r
+       int n = 0, inp = 0, sel = 0, show_help = 0;\r
+       char *curr_path_restore = NULL;\r
+       const char *ret = NULL;\r
        char cinp;\r
 \r
-rescan:\r
+       filter_exts_internal = filter_exts;\r
+       sel_fname[0] = 0;\r
+\r
        // is this a dir or a full path?\r
        if (!plat_is_dir(curr_path)) {\r
-               char *p = curr_path + strlen(curr_path) - 1;\r
-               for (; p > curr_path && *p != '/'; p--)\r
-                       ;\r
-               *p = 0;\r
-               fname = p+1;\r
+               char *p = strrchr(curr_path, '/');\r
+               if (p != NULL) {\r
+                       *p = 0;\r
+                       curr_path_restore = p;\r
+                       snprintf(sel_fname, sizeof(sel_fname), "%s", p + 1);\r
+               }\r
+\r
+               if (rom_fname_reload[0] == 0)\r
+                       show_help = 2;\r
+       }\r
+\r
+rescan:\r
+       if (namelist != NULL) {\r
+               while (n-- > 0)\r
+                       free(namelist[n]);\r
+               free(namelist);\r
+               namelist = NULL;\r
        }\r
 \r
-       n = scandir(curr_path, &namelist, scandir_filter, (void *)scandir_cmp);\r
+       filter = NULL;\r
+       if (!g_menu_filter_off)\r
+               filter = scandir_filter;\r
+\r
+       n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp);\r
        if (n < 0) {\r
                char *t;\r
                lprintf("menu_loop_romsel failed, dir: %s\n", curr_path);\r
@@ -873,7 +1024,7 @@ rescan:
                t = getcwd(curr_path, len);\r
                if (t == NULL)\r
                        plat_get_root_dir(curr_path, len);\r
-               n = scandir(curr_path, &namelist, scandir_filter, (void *)scandir_cmp);\r
+               n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp);\r
                if (n < 0) {\r
                        // oops, we failed\r
                        lprintf("menu_loop_romsel failed, dir: %s\n", curr_path);\r
@@ -881,13 +1032,17 @@ rescan:
                }\r
        }\r
 \r
-       // try to find sel\r
+       if (!g_menu_filter_off && extra_filter != NULL)\r
+               n = extra_filter(namelist, n, curr_path);\r
+\r
+       // try to find selected file\r
        // note: we don't show '.' so sel is namelist index - 1\r
-       if (fname != NULL) {\r
+       sel = 0;\r
+       if (sel_fname[0] != 0) {\r
                int i;\r
                for (i = 1; i < n; i++) {\r
                        char *dname = namelist[i]->d_name;\r
-                       if (dname[0] == fname[0] && strcmp(dname, fname) == 0) {\r
+                       if (dname[0] == sel_fname[0] && strcmp(dname, sel_fname) == 0) {\r
                                sel = i - 1;\r
                                break;\r
                        }\r
@@ -895,39 +1050,41 @@ rescan:
        }\r
 \r
        /* make sure action buttons are not pressed on entering menu */\r
-       draw_dirlist(curr_path, namelist, n, sel);\r
+       draw_dirlist(curr_path, namelist, n, sel, show_help);\r
        while (in_menu_wait_any(NULL, 50) & (PBTN_MOK|PBTN_MBACK|PBTN_MENU))\r
                ;\r
 \r
        for (;;)\r
        {\r
-               draw_dirlist(curr_path, namelist, n, sel);\r
-               inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|\r
-                       PBTN_L|PBTN_R|PBTN_MA2|PBTN_MOK|PBTN_MBACK|PBTN_MENU|PBTN_CHAR, &cinp, 33);\r
+               draw_dirlist(curr_path, namelist, n, sel, show_help);\r
+               inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT\r
+                       | PBTN_L|PBTN_R|PBTN_MA2|PBTN_MA3|PBTN_MOK|PBTN_MBACK\r
+                       | PBTN_MENU|PBTN_CHAR, &cinp, 33);\r
+               if (inp & PBTN_MA3)   {\r
+                       g_menu_filter_off = !g_menu_filter_off;\r
+                       snprintf(sel_fname, sizeof(sel_fname), "%s",\r
+                               namelist[sel+1]->d_name);\r
+                       goto rescan;\r
+               }\r
                if (inp & PBTN_UP  )  { sel--;   if (sel < 0)   sel = n-2; }\r
                if (inp & PBTN_DOWN)  { sel++;   if (sel > n-2) sel = 0; }\r
                if (inp & PBTN_LEFT)  { sel-=10; if (sel < 0)   sel = 0; }\r
                if (inp & PBTN_L)     { sel-=24; if (sel < 0)   sel = 0; }\r
                if (inp & PBTN_RIGHT) { sel+=10; if (sel > n-2) sel = n-2; }\r
                if (inp & PBTN_R)     { sel+=24; if (sel > n-2) sel = n-2; }\r
-               if (inp & PBTN_CHAR)  sel = dirent_seek_char(namelist, n, sel, cinp);\r
+\r
                if ((inp & PBTN_MOK) || (inp & (PBTN_MENU|PBTN_MA2)) == (PBTN_MENU|PBTN_MA2))\r
                {\r
                        again:\r
                        if (namelist[sel+1]->d_type == DT_REG)\r
                        {\r
-                               strcpy(rom_fname_reload, curr_path);\r
-                               strcat(rom_fname_reload, "/");\r
-                               strcat(rom_fname_reload, namelist[sel+1]->d_name);\r
+                               snprintf(rom_fname_reload, sizeof(rom_fname_reload),\r
+                                       "%s/%s", curr_path, namelist[sel+1]->d_name);\r
                                if (inp & PBTN_MOK) { // return sel\r
                                        ret = rom_fname_reload;\r
                                        break;\r
                                }\r
                                do_delete(rom_fname_reload, namelist[sel+1]->d_name);\r
-                               if (n > 0) {\r
-                                       while (n--) free(namelist[n]);\r
-                                       free(namelist);\r
-                               }\r
                                goto rescan;\r
                        }\r
                        else if (namelist[sel+1]->d_type == DT_DIR)\r
@@ -954,7 +1111,7 @@ rescan:
                                        strcat(newdir, "/");\r
                                        strcat(newdir, namelist[sel+1]->d_name);\r
                                }\r
-                               ret = menu_loop_romsel(newdir, newlen);\r
+                               ret = menu_loop_romsel(newdir, newlen, filter_exts, extra_filter);\r
                                free(newdir);\r
                                break;\r
                        }\r
@@ -962,9 +1119,8 @@ rescan:
                        {\r
                                // unknown file type, happens on NTFS mounts. Try to guess.\r
                                FILE *tstf; int tmp;\r
-                               strcpy(rom_fname_reload, curr_path);\r
-                               strcat(rom_fname_reload, "/");\r
-                               strcat(rom_fname_reload, namelist[sel+1]->d_name);\r
+                               snprintf(rom_fname_reload, sizeof(rom_fname_reload),\r
+                                       "%s/%s", curr_path, namelist[sel+1]->d_name);\r
                                tstf = fopen(rom_fname_reload, "rb");\r
                                if (tstf != NULL)\r
                                {\r
@@ -976,21 +1132,31 @@ rescan:
                                }\r
                        }\r
                }\r
+               else if (inp & PBTN_MA2) {\r
+                       g_autostateld_opt = !g_autostateld_opt;\r
+                       show_help = 3;\r
+               }\r
+               else if (inp & PBTN_CHAR) {\r
+                       // must be last\r
+                       sel = dirent_seek_char(namelist, n, sel, cinp);\r
+               }\r
+\r
                if (inp & PBTN_MBACK)\r
                        break;\r
+\r
+               if (show_help > 0)\r
+                       show_help--;\r
        }\r
 \r
        if (n > 0) {\r
-               while (n--) free(namelist[n]);\r
+               while (n-- > 0)\r
+                       free(namelist[n]);\r
                free(namelist);\r
        }\r
 \r
        // restore curr_path\r
-       if (fname != NULL) {\r
-               n = strlen(curr_path);\r
-               if (curr_path + n + 1 == fname)\r
-                       curr_path[n] = '/';\r
-       }\r
+       if (curr_path_restore != NULL)\r
+               *curr_path_restore = '/';\r
 \r
        return ret;\r
 }\r
@@ -1036,7 +1202,7 @@ static void draw_savestate_menu(int menu_sel, int is_loading)
                x = 12 + me_mfont_w * 2;\r
 #endif\r
 \r
-       menu_draw_begin(1);\r
+       menu_draw_begin(1, 1);\r
 \r
        text_out16(x, y, is_loading ? "Load state" : "Save state");\r
        y += 3 * me_mfont_h;\r
@@ -1098,7 +1264,7 @@ static int menu_loop_savestate(int is_loading)
                        if (menu_sel < STATE_SLOT_COUNT) {\r
                                state_slot = menu_sel;\r
                                if (emu_save_load_game(is_loading, 0)) {\r
-                                       me_update_msg(is_loading ? "Load failed" : "Save failed");\r
+                                       menu_update_msg(is_loading ? "Load failed" : "Save failed");\r
                                        break;\r
                                }\r
                                ret = 1;\r
@@ -1199,7 +1365,7 @@ static void draw_key_config(const me_bind_action *opts, int opt_cnt, int player_
        if (x < me_mfont_w * 2)\r
                x = me_mfont_w * 2;\r
 \r
-       menu_draw_begin(1);\r
+       menu_draw_begin(1, 0);\r
        if (player_idx >= 0)\r
                text_out16(x, y, "Player %i controls", player_idx + 1);\r
        else\r
@@ -1212,10 +1378,12 @@ static void draw_key_config(const me_bind_action *opts, int opt_cnt, int player_
                text_out16(x, y, "%s : %s", opts[i].name,\r
                        action_binds(player_idx, opts[i].mask, dev_id));\r
 \r
+       menu_separation();\r
+\r
        if (dev_id < 0)\r
                dev_name = "(all devices)";\r
        else\r
-               dev_name = in_get_dev_name(dev_id, 1, 1);\r
+               dev_name = in_get_dev_name(dev_id, 0, 1);\r
        w = strlen(dev_name) * me_mfont_w;\r
        if (w < 30 * me_mfont_w)\r
                w = 30 * me_mfont_w;\r
@@ -1278,7 +1446,7 @@ static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_
                                for (i = 0, dev_id--; i < IN_MAX_DEVS + 1; i++, dev_id--) {\r
                                        if (dev_id < -1)\r
                                                dev_id = IN_MAX_DEVS - 1;\r
-                                       if (dev_id == -1 || in_get_dev_name(dev_id, 1, 0) != NULL)\r
+                                       if (dev_id == -1 || in_get_dev_name(dev_id, 0, 0) != NULL)\r
                                                break;\r
                                }\r
                                continue;\r
@@ -1286,7 +1454,7 @@ static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_
                                for (i = 0, dev_id++; i < IN_MAX_DEVS; i++, dev_id++) {\r
                                        if (dev_id >= IN_MAX_DEVS)\r
                                                dev_id = -1;\r
-                                       if (dev_id == -1 || in_get_dev_name(dev_id, 1, 0) != NULL)\r
+                                       if (dev_id == -1 || in_get_dev_name(dev_id, 0, 0) != NULL)\r
                                                break;\r
                                }\r
                                continue;\r