frontend: key config: save it and make more intuitive
authornotaz <notasas@gmail.com>
Sun, 6 Feb 2011 22:49:40 +0000 (00:49 +0200)
committernotaz <notasas@gmail.com>
Thu, 10 Feb 2011 00:07:54 +0000 (02:07 +0200)
frontend/common/input.c
frontend/common/menu.c
frontend/menu.c
frontend/pandora.c

index 7bbb39c..5250535 100644 (file)
@@ -677,22 +677,39 @@ int in_bind_key(int dev_id, int keycode, int mask, int bind_type, int force_unbi
        return 0;
 }
 
-void in_unbind_all(int dev_id, int act_mask, int bind_type)
+/*
+ * Unbind act_mask on binds with type bind_type
+ * - if dev_id_ < 0, affects all devices
+ *   else only affects dev_id_
+ * - if act_mask == -1, unbind all keys
+ *   else only actions in mask
+ */
+void in_unbind_all(int dev_id_, int act_mask, int bind_type)
 {
+       int dev_id = 0, dev_last = IN_MAX_DEVS - 1;
        int i, count;
        in_dev_t *dev;
 
-       if (dev_id < 0 || dev_id >= IN_MAX_DEVS || bind_type >= IN_BINDTYPE_COUNT)
+       if (dev_id_ >= 0)
+               dev_id = dev_last = dev_id_;
+
+       if (bind_type >= IN_BINDTYPE_COUNT)
                return;
 
-       dev = &in_devices[dev_id];
-       count = dev->key_count;
+       for (; dev_id <= dev_last; dev_id++) {
+               dev = &in_devices[dev_id];
+               count = dev->key_count;
 
-       if (dev->binds == NULL)
-               return;
+               if (dev->binds == NULL)
+                       continue;
 
-       for (i = 0; i < count; i++)
-               dev->binds[IN_BIND_OFFS(i, bind_type)] &= ~act_mask;
+               if (act_mask != -1) {
+                       for (i = 0; i < count; i++)
+                               dev->binds[IN_BIND_OFFS(i, bind_type)] &= ~act_mask;
+               }
+               else
+                       memset(dev->binds, 0, sizeof(dev->binds[0]) * count * IN_BINDTYPE_COUNT);
+       }
 }
 
 /* returns device id, or -1 on error */
index aa76e43..31522f7 100644 (file)
@@ -1039,18 +1039,11 @@ static int menu_loop_savestate(int is_loading)
 \r
 static char *action_binds(int player_idx, int action_mask, int dev_id)\r
 {\r
-       int k, count = 0, can_combo = 0, type;\r
-       const int *binds;\r
+       int dev = 0, dev_last = IN_MAX_DEVS - 1;\r
+       int can_combo = 1, type;\r
 \r
        static_buff[0] = 0;\r
 \r
-       binds = in_get_dev_binds(dev_id);\r
-       if (binds == NULL)\r
-               return static_buff;\r
-\r
-       in_get_config(dev_id, IN_CFG_BIND_COUNT, &count);\r
-       in_get_config(dev_id, IN_CFG_DOES_COMBOS, &can_combo);\r
-\r
        type = IN_BINDTYPE_EMU;\r
        if (player_idx >= 0) {\r
                can_combo = 0;\r
@@ -1059,22 +1052,37 @@ static char *action_binds(int player_idx, int action_mask, int dev_id)
        if (player_idx == 1)\r
                action_mask <<= 16;\r
 \r
-       for (k = 0; k < count; k++)\r
-       {\r
-               const char *xname;\r
-               int len;\r
+       if (dev_id >= 0)\r
+               dev = dev_last = dev_id;\r
+\r
+       for (; dev <= dev_last; dev++) {\r
+               int k, count = 0, combo = 0;\r
+               const int *binds;\r
 \r
-               if (!(binds[IN_BIND_OFFS(k, type)] & action_mask))\r
+               binds = in_get_dev_binds(dev);\r
+               if (binds == NULL)\r
                        continue;\r
 \r
-               xname = in_get_key_name(dev_id, k);\r
-               len = strlen(static_buff);\r
-               if (len) {\r
-                       strncat(static_buff, can_combo ? " + " : ", ",\r
-                               sizeof(static_buff) - len - 1);\r
-                       len += can_combo ? 3 : 2;\r
+               in_get_config(dev, IN_CFG_BIND_COUNT, &count);\r
+               in_get_config(dev, IN_CFG_DOES_COMBOS, &combo);\r
+               combo = combo && can_combo;\r
+\r
+               for (k = 0; k < count; k++) {\r
+                       const char *xname;\r
+                       int len;\r
+\r
+                       if (!(binds[IN_BIND_OFFS(k, type)] & action_mask))\r
+                               continue;\r
+\r
+                       xname = in_get_key_name(dev, k);\r
+                       len = strlen(static_buff);\r
+                       if (len) {\r
+                               strncat(static_buff, combo ? " + " : ", ",\r
+                                       sizeof(static_buff) - len - 1);\r
+                               len += combo ? 3 : 2;\r
+                       }\r
+                       strncat(static_buff, xname, sizeof(static_buff) - len - 1);\r
                }\r
-               strncat(static_buff, xname, sizeof(static_buff) - len - 1);\r
        }\r
 \r
        return static_buff;\r
@@ -1126,7 +1134,10 @@ 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
-       dev_name = in_get_dev_name(dev_id, 1, 1);\r
+       if (dev_id < 0)\r
+               dev_name = "(all devices)";\r
+       else\r
+               dev_name = in_get_dev_name(dev_id, 1, 1);\r
        w = strlen(dev_name) * me_mfont_w;\r
        if (w < 30 * me_mfont_w)\r
                w = 30 * me_mfont_w;\r
@@ -1155,7 +1166,7 @@ static void draw_key_config(const me_bind_action *opts, int opt_cnt, int player_
 static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_idx)\r
 {\r
        int i, sel = 0, menu_sel_max = opt_cnt - 1, does_combos = 0;\r
-       int dev_id, dev_count, kc, is_down, mkey;\r
+       int dev_id, bind_dev_id, dev_count, kc, is_down, mkey;\r
        int unbind, bindtype, mask_shift;\r
 \r
        for (i = 0, dev_id = -1, dev_count = 0; i < IN_MAX_DEVS; i++) {\r
@@ -1171,6 +1182,7 @@ static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_
                return;\r
        }\r
 \r
+       dev_id = -1; // show all\r
        mask_shift = 0;\r
        if (player_idx == 1)\r
                mask_shift = 16;\r
@@ -1184,18 +1196,18 @@ static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_
                        case PBTN_UP:   sel--; if (sel < 0) sel = menu_sel_max; continue;\r
                        case PBTN_DOWN: sel++; if (sel > menu_sel_max) sel = 0; continue;\r
                        case PBTN_LEFT:\r
-                               for (i = 0, dev_id--; i < IN_MAX_DEVS; i++, dev_id--) {\r
-                                       if (dev_id < 0)\r
+                               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 (in_get_dev_name(dev_id, 1, 0) != NULL)\r
+                                       if (dev_id == -1 || in_get_dev_name(dev_id, 1, 0) != NULL)\r
                                                break;\r
                                }\r
                                continue;\r
                        case PBTN_RIGHT:\r
                                for (i = 0, dev_id++; i < IN_MAX_DEVS; i++, dev_id++) {\r
                                        if (dev_id >= IN_MAX_DEVS)\r
-                                               dev_id = 0;\r
-                                       if (in_get_dev_name(dev_id, 1, 0) != NULL)\r
+                                               dev_id = -1;\r
+                                       if (dev_id == -1 || in_get_dev_name(dev_id, 1, 0) != NULL)\r
                                                break;\r
                                }\r
                                continue;\r
@@ -1217,20 +1229,20 @@ static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_
 \r
                /* wait for some up event */\r
                for (is_down = 1; is_down; )\r
-                       kc = in_update_keycode(&dev_id, &is_down, -1);\r
+                       kc = in_update_keycode(&bind_dev_id, &is_down, -1);\r
 \r
-               i = count_bound_keys(dev_id, opts[sel].mask << mask_shift, bindtype);\r
+               i = count_bound_keys(bind_dev_id, opts[sel].mask << mask_shift, bindtype);\r
                unbind = (i > 0);\r
 \r
                /* allow combos if device supports them */\r
-               in_get_config(dev_id, IN_CFG_DOES_COMBOS, &does_combos);\r
+               in_get_config(bind_dev_id, IN_CFG_DOES_COMBOS, &does_combos);\r
                if (i == 1 && bindtype == IN_BINDTYPE_EMU && does_combos)\r
                        unbind = 0;\r
 \r
                if (unbind)\r
-                       in_unbind_all(dev_id, opts[sel].mask << mask_shift, bindtype);\r
+                       in_unbind_all(bind_dev_id, opts[sel].mask << mask_shift, bindtype);\r
 \r
-               in_bind_key(dev_id, kc, opts[sel].mask << mask_shift, bindtype, 0);\r
+               in_bind_key(bind_dev_id, kc, opts[sel].mask << mask_shift, bindtype, 0);\r
        }\r
 }\r
 \r
index 0a4c271..e7d20ff 100644 (file)
@@ -251,6 +251,8 @@ static void make_cfg_fname(char *buf, size_t size, int is_game)
                snprintf(buf, size, "." PCSX_DOT_DIR "%s", cfgfile_basename);
 }
 
+static void keys_write_all(FILE *f);
+
 static int menu_write_config(int is_game)
 {
        char cfgfile[MAXPATHLEN];
@@ -289,7 +291,9 @@ static int menu_write_config(int is_game)
        if (!is_game)
                fprintf(f, "lastcdimg = %s\n", last_selected_fname);
 
+       keys_write_all(f);
        fclose(f);
+
        return 0;
 }
 
@@ -305,6 +309,8 @@ static void parse_str_val(char *cval, const char *src)
                *tmp = 0;
 }
 
+static void keys_load_all(const char *cfg);
+
 static int menu_load_config(int is_game)
 {
        char cfgfile[MAXPATHLEN];
@@ -400,6 +406,7 @@ static int menu_load_config(int is_game)
                if (strcmp(Config.Spu, spu_plugins[i]) == 0)
                        { spu_plugsel = i; break; }
 
+       keys_load_all(cfg);
        ret = 0;
 fail_read:
        free(cfg);
@@ -647,6 +654,8 @@ me_bind_action me_ctrl_actions[] =
        { "R1      ", 1 << DKEY_R1 },
        { "L2      ", 1 << DKEY_L2 },
        { "R2      ", 1 << DKEY_R2 },
+       { "L3      ", 1 << DKEY_L3 },
+       { "R3      ", 1 << DKEY_R3 },
        { "START   ", 1 << DKEY_START },
        { "SELECT  ", 1 << DKEY_SELECT },
        { NULL,       0 }
@@ -664,6 +673,177 @@ me_bind_action emuctrl_actions[] =
        { NULL,                0 }
 };
 
+static char *mystrip(char *str)
+{
+       int i, len;
+
+       len = strlen(str);
+       for (i = 0; i < len; i++)
+               if (str[i] != ' ') break;
+       if (i > 0) memmove(str, str + i, len - i + 1);
+
+       len = strlen(str);
+       for (i = len - 1; i >= 0; i--)
+               if (str[i] != ' ') break;
+       str[i+1] = 0;
+
+       return str;
+}
+
+static void get_line(char *d, size_t size, const char *s)
+{
+       const char *pe;
+       size_t len;
+
+       for (pe = s; *pe != '\r' && *pe != '\n' && *pe != 0; pe++)
+               ;
+       len = pe - s;
+       if (len > size - 1)
+               len = size - 1;
+       strncpy(d, s, len);
+       d[len] = 0;
+
+       mystrip(d);
+}
+
+static void keys_write_all(FILE *f)
+{
+       int d;
+
+       for (d = 0; d < IN_MAX_DEVS; d++)
+       {
+               const int *binds = in_get_dev_binds(d);
+               const char *name = in_get_dev_name(d, 0, 0);
+               int k, count = 0;
+
+               if (binds == NULL || name == NULL)
+                       continue;
+
+               fprintf(f, "binddev = %s\n", name);
+               in_get_config(d, IN_CFG_BIND_COUNT, &count);
+
+               for (k = 0; k < count; k++)
+               {
+                       int i, kbinds, mask;
+                       char act[32];
+
+                       act[0] = act[31] = 0;
+                       name = in_get_key_name(d, k);
+
+                       kbinds = binds[IN_BIND_OFFS(k, IN_BINDTYPE_PLAYER12)];
+                       for (i = 0; kbinds && i < ARRAY_SIZE(me_ctrl_actions) - 1; i++) {
+                               mask = me_ctrl_actions[i].mask;
+                               if (mask & kbinds) {
+                                       strncpy(act, me_ctrl_actions[i].name, 31);
+                                       fprintf(f, "bind %s = player1 %s\n", name, mystrip(act));
+                                       kbinds &= ~mask;
+                               }
+                               mask = me_ctrl_actions[i].mask << 16;
+                               if (mask & kbinds) {
+                                       strncpy(act, me_ctrl_actions[i].name, 31);
+                                       fprintf(f, "bind %s = player2 %s\n", name, mystrip(act));
+                                       kbinds &= ~mask;
+                               }
+                       }
+
+                       kbinds = binds[IN_BIND_OFFS(k, IN_BINDTYPE_EMU)];
+                       for (i = 0; kbinds && i < ARRAY_SIZE(emuctrl_actions) - 1; i++) {
+                               mask = emuctrl_actions[i].mask;
+                               if (mask & kbinds) {
+                                       strncpy(act, emuctrl_actions[i].name, 31);
+                                       fprintf(f, "bind %s = %s\n", name, mystrip(act));
+                                       kbinds &= ~mask;
+                               }
+                       }
+               }
+       }
+}
+
+static int parse_bind_val(const char *val, int *type)
+{
+       int i;
+
+       *type = IN_BINDTYPE_NONE;
+       if (val[0] == 0)
+               return 0;
+       
+       if (strncasecmp(val, "player", 6) == 0)
+       {
+               int player, shift = 0;
+               player = atoi(val + 6) - 1;
+
+               if ((unsigned int)player > 1)
+                       return -1;
+               if (player == 1)
+                       shift = 16;
+
+               *type = IN_BINDTYPE_PLAYER12;
+               for (i = 0; me_ctrl_actions[i].name != NULL; i++) {
+                       if (strncasecmp(me_ctrl_actions[i].name, val + 8, strlen(val + 8)) == 0)
+                               return me_ctrl_actions[i].mask << shift;
+               }
+       }
+       for (i = 0; emuctrl_actions[i].name != NULL; i++) {
+               if (strncasecmp(emuctrl_actions[i].name, val, strlen(val)) == 0) {
+                       *type = IN_BINDTYPE_EMU;
+                       return emuctrl_actions[i].mask;
+               }
+       }
+
+       return -1;
+}
+
+static void keys_load_all(const char *cfg)
+{
+       char dev[256], key[128], *act;
+       const char *p;
+       int bind, bindtype;
+       int dev_id;
+
+       p = cfg;
+       while (p != NULL && (p = strstr(p, "binddev = ")) != NULL) {
+               p += 10;
+
+               get_line(dev, sizeof(dev), p);
+               dev_id = in_config_parse_dev(dev);
+               if (dev_id < 0) {
+                       printf("input: can't handle dev: %s\n", dev);
+                       continue;
+               }
+
+               in_unbind_all(dev_id, -1, -1);
+               while ((p = strstr(p, "bind"))) {
+                       if (strncmp(p, "binddev = ", 10) == 0)
+                               break;
+
+                       p += 4;
+                       if (*p != ' ') {
+                               printf("input: parse error: %16s..\n", p);
+                               continue;
+                       }
+
+                       get_line(key, sizeof(key), p);
+                       act = strchr(key, '=');
+                       if (act == NULL) {
+                               printf("parse failed: %16s..\n", p);
+                               continue;
+                       }
+                       *act = 0;
+                       act++;
+                       mystrip(key);
+                       mystrip(act);
+
+                       bind = parse_bind_val(act, &bindtype);
+                       if (bind != -1 && bind != 0) {
+                               printf("bind #%d '%s' %08x (%s)\n", dev_id, key, bind, act);
+                               in_config_bind_key(dev_id, key, bind, bindtype);
+                       }
+                       else
+                               lprintf("config: unhandled action \"%s\"\n", act);
+               }
+       }
+}
+
 static int key_config_loop_wrap(int id, int keys)
 {
        switch (id) {
index 8eacabb..cd50728 100644 (file)
@@ -27,12 +27,12 @@ static const char * const pandora_gpio_keys[KEY_MAX + 1] = {
        [KEY_LEFT]      = "Left",
        [KEY_RIGHT]     = "Right",
        [KEY_DOWN]      = "Down",
-       [KEY_HOME]      = "A",
-       [KEY_PAGEDOWN]  = "X",
-       [KEY_END]       = "B",
-       [KEY_PAGEUP]    = "Y",
-       [KEY_RIGHTSHIFT]= "L",
-       [KEY_RIGHTCTRL] = "R",
+       [KEY_HOME]      = "(A)",
+       [KEY_PAGEDOWN]  = "(X)",
+       [KEY_END]       = "(B)",
+       [KEY_PAGEUP]    = "(Y)",
+       [KEY_RIGHTSHIFT]= "(L)",
+       [KEY_RIGHTCTRL] = "(R)",
        [KEY_LEFTALT]   = "Start",
        [KEY_LEFTCTRL]  = "Select",
        [KEY_MENU]      = "Pandora",