static void keys_write(FILE *fn, const char *bind_str, int dev_id, const int *binds, int no_defaults)
{
char act[48];
- int key_count, t, i;
+ int key_count, k, i;
const int *def_binds;
key_count = in_get_dev_info(dev_id, IN_INFO_BIND_COUNT);
def_binds = in_get_dev_def_binds(dev_id);
- for (t = 0; t < key_count; t++)
+ for (k = 0; k < key_count; k++)
{
const char *name;
+ int t, mask;
act[0] = act[31] = 0;
- if (no_defaults && binds[t] == def_binds[t])
- continue;
+ for (t = 0; t < IN_BINDTYPE_COUNT; t++)
+ if (binds[IN_BIND_OFFS(k, t)] != def_binds[IN_BIND_OFFS(k, t)])
+ break;
- name = in_get_key_name(dev_id, t);
-#ifdef __GP2X__
- if (strcmp(name, "SELECT") == 0) continue;
-#endif
+ if (no_defaults && t == IN_BINDTYPE_COUNT)
+ continue; /* no change from defaults */
+
+ name = in_get_key_name(dev_id, k);
- if (binds[t] == 0 && def_binds[t] != 0) {
+ for (t = 0; t < IN_BINDTYPE_COUNT; t++)
+ if (binds[IN_BIND_OFFS(k, t)] != 0 || def_binds[IN_BIND_OFFS(k, t)] == 0)
+ break;
+
+ if (t == IN_BINDTYPE_COUNT) {
+ /* key has default bind removed */
fprintf(fn, "%s %s =" NL, bind_str, name);
continue;
}
for (i = 0; i < sizeof(me_ctrl_actions) / sizeof(me_ctrl_actions[0]); i++) {
- if (me_ctrl_actions[i].mask & binds[t]) {
+ mask = me_ctrl_actions[i].mask;
+ if (mask & binds[IN_BIND_OFFS(k, IN_BINDTYPE_PLAYER12)]) {
+ strncpy(act, me_ctrl_actions[i].name, 31);
+ fprintf(fn, "%s %s = player1 %s" NL, bind_str, name, mystrip(act));
+ }
+ mask = me_ctrl_actions[i].mask << 16;
+ if (mask & binds[IN_BIND_OFFS(k, IN_BINDTYPE_PLAYER12)]) {
strncpy(act, me_ctrl_actions[i].name, 31);
- fprintf(fn, "%s %s = player%i %s" NL, bind_str, name,
- ((binds[t]>>16)&1)+1, mystrip(act));
+ fprintf(fn, "%s %s = player2 %s" NL, bind_str, name, mystrip(act));
}
}
for (i = 0; emuctrl_actions[i].name != NULL; i++) {
- if (emuctrl_actions[i].mask & binds[t]) {
+ mask = emuctrl_actions[i].mask;
+ if (mask & binds[IN_BIND_OFFS(k, IN_BINDTYPE_EMU)]) {
strncpy(act, emuctrl_actions[i].name, 31);
fprintf(fn, "%s %s = %s" NL, bind_str, name, mystrip(act));
}
static unsigned int keys_encountered = 0;
-static int parse_bind_val(const char *val)
+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)
{
- unsigned int player;
+ int player, shift = 0;
player = atoi(val + 6) - 1;
+
if (player > 1)
return -1;
+ if (player == 1)
+ shift = 16;
+ *type = IN_BINDTYPE_PLAYER12;
for (i = 0; i < sizeof(me_ctrl_actions) / sizeof(me_ctrl_actions[0]); i++) {
if (strncasecmp(me_ctrl_actions[i].name, val + 8, strlen(val + 8)) == 0)
- return me_ctrl_actions[i].mask | (player<<16);
+ 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)
+ if (strncasecmp(emuctrl_actions[i].name, val, strlen(val)) == 0) {
+ *type = IN_BINDTYPE_EMU;
return emuctrl_actions[i].mask;
+ }
}
return -1;
static void keys_parse(const char *key, const char *val, int dev_id)
{
- int binds;
+ int acts, type;
- binds = parse_bind_val(val);
- if (binds == -1) {
+ acts = parse_bind_val(val, &type);
+ if (acts == -1) {
lprintf("config: unhandled action \"%s\"\n", val);
return;
}
- in_config_bind_key(dev_id, key, binds);
+ in_config_bind_key(dev_id, key, acts, type);
}
static int get_numvar_num(const char *var)
\r
void emu_update_input(void)\r
{\r
- unsigned int allActions[2] = { 0, 0 }, events;\r
- static unsigned int prevEvents = 0;\r
+ static int prev_events = 0;\r
+ int actions[IN_BINDTYPE_COUNT] = { 0, };\r
+ int pl_actions[2];\r
+ int events;\r
\r
- /* FIXME: player2 */\r
- allActions[0] = in_update();\r
+ in_update(actions);\r
\r
- PicoPad[0] = allActions[0] & 0xfff;\r
- PicoPad[1] = allActions[1] & 0xfff;\r
+ pl_actions[0] = actions[IN_BINDTYPE_PLAYER12];\r
+ pl_actions[1] = actions[IN_BINDTYPE_PLAYER12] >> 16;\r
\r
- if (allActions[0] & 0x7000) do_turbo(&PicoPad[0], allActions[0]);\r
- if (allActions[1] & 0x7000) do_turbo(&PicoPad[1], allActions[1]);\r
+ PicoPad[0] = pl_actions[0] & 0xfff;\r
+ PicoPad[1] = pl_actions[1] & 0xfff;\r
\r
- events = (allActions[0] | allActions[1]) & PEV_MASK;\r
+ if (pl_actions[0] & 0x7000)\r
+ do_turbo(&PicoPad[0], pl_actions[0]);\r
+ if (pl_actions[1] & 0x7000)\r
+ do_turbo(&PicoPad[1], pl_actions[1]);\r
+\r
+ events = actions[IN_BINDTYPE_EMU] & PEV_MASK;\r
\r
// volume is treated in special way and triggered every frame\r
if (events & (PEV_VOL_DOWN|PEV_VOL_UP))\r
plat_update_volume(1, events & PEV_VOL_UP);\r
\r
- if ((events ^ prevEvents) & PEV_FF) {\r
+ if ((events ^ prev_events) & PEV_FF) {\r
emu_set_fastforward(events & PEV_FF);\r
plat_update_volume(0, 0);\r
reset_timing = 1;\r
}\r
\r
- events &= ~prevEvents;\r
+ events &= ~prev_events;\r
\r
if (PicoAHW == PAHW_PICO)\r
run_events_pico(events);\r
if (movie_data)\r
update_movie();\r
\r
- prevEvents = (allActions[0] | allActions[1]) & PEV_MASK;\r
+ prev_events = actions[IN_BINDTYPE_EMU] & PEV_MASK;\r
}\r
\r
static void mkdir_path(char *path_with_reserve, int pos, const char *name)\r
int drv_fd_hnd;
void *drv_data;
char *name;
- int *binds;
+ int key_count;
+ int *binds; /* total = key_count * bindtypes * 2 */
int probed:1;
int does_combos:1;
} in_dev_t;
#define DRV(id) in_drivers[(unsigned)(id) < IN_DRVID_COUNT ? (id) : 0]
-static int in_bind_count(int drv_id)
-{
- int count = DRV(drv_id).get_bind_count();
- if (count <= 0)
- printf("input: failed to get bind count for drv %d\n", drv_id);
-
- return count;
-}
-
-static int *in_alloc_binds(int drv_id)
+static int *in_alloc_binds(int drv_id, int key_count)
{
- int count, *binds;
-
- count = in_bind_count(drv_id);
- if (count <= 0)
- return NULL;
+ int *binds;
- binds = calloc(count * 2, sizeof(binds[0]));
+ binds = calloc(key_count * IN_BINDTYPE_COUNT * 2, sizeof(binds[0]));
if (binds == NULL)
return NULL;
- DRV(drv_id).get_def_binds(binds + count);
- memcpy(binds, binds + count, count * sizeof(binds[0]));
+ DRV(drv_id).get_def_binds(binds + key_count * IN_BINDTYPE_COUNT);
+ memcpy(binds, binds + key_count * IN_BINDTYPE_COUNT,
+ sizeof(binds[0]) * key_count * IN_BINDTYPE_COUNT);
return binds;
}
/* to be called by drivers
* async devices must set drv_fd_hnd to -1 */
-void in_register(const char *nname, int drv_id, int drv_fd_hnd, void *drv_data, int combos)
+void in_register(const char *nname, int drv_id, int drv_fd_hnd, void *drv_data,
+ int key_count, int combos)
{
int i, ret, dupe_count = 0, *binds;
char name[256], *name_end, *tmp;
if (tmp == NULL)
return;
- binds = in_alloc_binds(drv_id);
+ binds = in_alloc_binds(drv_id, key_count);
if (binds == NULL) {
free(tmp);
return;
in_devices[i].name = tmp;
in_devices[i].binds = binds;
+ in_devices[i].key_count = key_count;
if (i + 1 > in_dev_count)
in_dev_count = i + 1;
in_devices[i].drv_data = drv_data;
if (in_devices[i].binds != NULL) {
- ret = DRV(drv_id).clean_binds(drv_data, in_devices[i].binds);
+ ret = DRV(drv_id).clean_binds(drv_data, in_devices[i].binds,
+ in_devices[i].binds + key_count * IN_BINDTYPE_COUNT);
if (ret == 0) {
/* no useable binds */
free(in_devices[i].binds);
}
}
-/* key combo handling, to be called by drivers that support it */
-void in_combos_find(int *binds, int last_key, int *combo_keys, int *combo_acts)
+/* key combo handling, to be called by drivers that support it.
+ * Only care about IN_BINDTYPE_EMU */
+void in_combos_find(const int *binds, int last_key, int *combo_keys, int *combo_acts)
{
int act, u;
{
int keyc = 0;
for (u = 0; u <= last_key; u++)
- if (binds[u] & (1 << act))
+ if (binds[IN_BIND_OFFS(u, IN_BINDTYPE_EMU)] & (1 << act))
keyc++;
if (keyc > 1)
// loop again and mark those keys and actions as combo
for (u = 0; u <= last_key; u++)
{
- if (binds[u] & (1 << act)) {
+ if (binds[IN_BIND_OFFS(u, IN_BINDTYPE_EMU)] & (1 << act)) {
*combo_keys |= 1 << u;
*combo_acts |= 1 << act;
}
}
}
-int in_combos_do(int keys, int *binds, int last_key, int combo_keys, int combo_acts)
+int in_combos_do(int keys, const int *binds, int last_key, int combo_keys, int combo_acts)
{
int i, ret = 0;
for (i = 0; i <= last_key; i++)
{
- int acts;
+ int acts, acts_c, u;
+
if (!(keys & (1 << i)))
continue;
- acts = binds[i];
+ acts = binds[IN_BIND_OFFS(i, IN_BINDTYPE_EMU)];
if (!acts)
continue;
- if (combo_keys & (1 << i))
- {
- int acts_c = acts & combo_acts;
- int u = last_key;
- if (acts_c) {
- // let's try to find the other one
- for (u = i + 1; u <= last_key; u++)
- if ( (keys & (1 << u)) && (binds[u] & acts_c) ) {
- ret |= acts_c & binds[u];
- keys &= ~((1 << i) | (1 << u));
- break;
- }
- }
- // add non-combo actions if combo ones were not found
- if (u >= last_key)
- ret |= acts & ~combo_acts;
- } else
+ if (!(combo_keys & (1 << i))) {
ret |= acts;
+ continue;
+ }
+
+ acts_c = acts & combo_acts;
+ u = last_key;
+ if (acts_c) {
+ // let's try to find the other one
+ for (u = i + 1; u <= last_key; u++)
+ if ( (keys & (1 << u)) && (binds[IN_BIND_OFFS(u, IN_BINDTYPE_EMU)] & acts_c) ) {
+ ret |= acts_c & binds[IN_BIND_OFFS(u, IN_BINDTYPE_EMU)];
+ keys &= ~((1 << i) | (1 << u));
+ break;
+ }
+ }
+ // add non-combo actions if combo ones were not found
+ if (u >= last_key)
+ ret |= acts & ~combo_acts;
}
return ret;
}
/* async update */
-int in_update(void)
+int in_update(int *result)
{
- int i, result = 0;
+ int i, ret = 0;
for (i = 0; i < in_dev_count; i++) {
in_dev_t *dev = &in_devices[i];
switch (dev->drv_id) {
#ifdef IN_EVDEV
case IN_DRVID_EVDEV:
- result |= in_evdev_update(dev->drv_data, dev->binds);
+ ret |= in_evdev_update(dev->drv_data, dev->binds, result);
break;
#endif
#ifdef IN_GP2X
case IN_DRVID_GP2X:
- result |= in_gp2x_update(dev->drv_data, dev->binds);
+ ret |= in_gp2x_update(dev->drv_data, dev->binds, result);
break;
#endif
}
}
}
- return result;
+ return ret;
}
void in_set_blocking(int is_blocking)
const int *in_get_dev_def_binds(int dev_id)
{
- int count;
-
if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
return NULL;
- count = in_bind_count(in_devices[dev_id].drv_id);
- return in_devices[dev_id].binds + count;
+ return in_devices[dev_id].binds + in_devices[dev_id].key_count * IN_BINDTYPE_COUNT;
}
int in_get_dev_info(int dev_id, int what)
switch (what) {
case IN_INFO_BIND_COUNT:
- return in_bind_count(in_devices[dev_id].drv_id);
+ return in_devices[dev_id].key_count;
case IN_INFO_DOES_COMBOS:
return in_devices[dev_id].does_combos;
}
return xname;
}
-int in_bind_key(int dev_id, int keycode, int mask, int force_unbind)
+int in_bind_key(int dev_id, int keycode, int bind_type, int mask, int force_unbind)
{
int ret, count;
in_dev_t *dev;
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
+ if (dev_id < 0 || dev_id >= IN_MAX_DEVS || bind_type >= IN_BINDTYPE_COUNT)
return -1;
+
dev = &in_devices[dev_id];
+ count = dev->key_count;
if (dev->binds == NULL) {
if (force_unbind)
return 0;
- dev->binds = in_alloc_binds(dev->drv_id);
+ dev->binds = in_alloc_binds(dev->drv_id, count);
if (dev->binds == NULL)
return -1;
}
- count = in_bind_count(dev->drv_id);
if (keycode < 0 || keycode >= count)
return -1;
if (force_unbind)
- dev->binds[keycode] &= ~mask;
+ dev->binds[IN_BIND_OFFS(keycode, bind_type)] &= ~mask;
else
- dev->binds[keycode] ^= mask;
+ dev->binds[IN_BIND_OFFS(keycode, bind_type)] ^= mask;
- ret = DRV(dev->drv_id).clean_binds(dev->drv_data, dev->binds);
+ ret = DRV(dev->drv_id).clean_binds(dev->drv_data, dev->binds,
+ dev->binds + count * IN_BINDTYPE_COUNT);
if (ret == 0) {
free(dev->binds);
dev->binds = NULL;
if (in_devices[i].name == NULL)
return -1;
+ in_devices[i].key_count = DRV(drv_id).get_bind_count();
+ in_devices[i].drv_id = drv_id;
+
if (i + 1 > in_dev_count)
in_dev_count = i + 1;
- in_devices[i].drv_id = drv_id;
return i;
}
if (binds == NULL)
continue;
- count = in_bind_count(in_devices[i].drv_id);
- def_binds = binds + count;
+ count = in_devices[i].key_count;
+ def_binds = binds + count * IN_BINDTYPE_COUNT;
- for (n = 0; n < count; n++)
+ for (n = 0; n < count * IN_BINDTYPE_COUNT; n++)
if (binds[n] == def_binds[n])
binds[n] = -1;
}
}
-int in_config_bind_key(int dev_id, const char *key, int binds)
+int in_config_bind_key(int dev_id, const char *key, int acts, int bind_type)
{
- int count, kc;
in_dev_t *dev;
+ int i, offs, kc;
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
+ if (dev_id < 0 || dev_id >= IN_MAX_DEVS || bind_type >= IN_BINDTYPE_COUNT)
return -1;
dev = &in_devices[dev_id];
- count = in_bind_count(dev->drv_id);
-
/* maybe a raw code? */
if (key[0] == '\\' && key[1] == 'x') {
char *p = NULL;
else {
/* device specific key name */
if (dev->binds == NULL) {
- dev->binds = in_alloc_binds(dev->drv_id);
+ dev->binds = in_alloc_binds(dev->drv_id, dev->key_count);
if (dev->binds == NULL)
return -1;
in_config_start();
}
}
- if (kc < 0 || kc >= count) {
+ if (kc < 0 || kc >= dev->key_count) {
printf("input: bad key: %s\n", key);
return -1;
}
- if (dev->binds[kc] == -1)
- dev->binds[kc] = 0;
- dev->binds[kc] |= binds;
+ if (bind_type == IN_BINDTYPE_NONE) {
+ for (i = 0; i < IN_BINDTYPE_COUNT; i++)
+ dev->binds[IN_BIND_OFFS(kc, i)] = 0;
+ return 0;
+ }
+ offs = IN_BIND_OFFS(kc, bind_type);
+ if (dev->binds[offs] == -1)
+ dev->binds[offs] = 0;
+ dev->binds[offs] |= acts;
return 0;
}
if (dev->binds == NULL)
continue;
- count = in_bind_count(dev->drv_id);
+ count = dev->key_count;
binds = dev->binds;
- def_binds = binds + count;
+ def_binds = binds + count * IN_BINDTYPE_COUNT;
- for (n = 0; n < count; n++)
+ for (n = 0; n < count * IN_BINDTYPE_COUNT; n++)
if (binds[n] == -1)
binds[n] = def_binds[n];
if (dev->drv_data == NULL)
continue;
- ret = DRV(dev->drv_id).clean_binds(dev->drv_data, binds);
+ ret = DRV(dev->drv_id).clean_binds(dev->drv_data, binds, def_binds);
if (ret == 0) {
/* no useable binds */
free(dev->binds);
static void in_def_free(void *drv_data) {}
static int in_def_get_bind_count(void) { return 0; }
static void in_def_get_def_binds(int *binds) {}
-static int in_def_clean_binds(void *drv_data, int *binds) { return 0; }
+static int in_def_clean_binds(void *drv_data, int *b, int *db) { return 0; }
static void in_def_set_blocking(void *data, int y) {}
static int in_def_update_keycode(void *drv_data, int *is_down) { return 0; }
static int in_def_menu_translate(int keycode) { return keycode; }
IN_INFO_DOES_COMBOS,
};
+enum {
+ IN_BINDTYPE_NONE = -1,
+ IN_BINDTYPE_EMU = 0,
+ IN_BINDTYPE_PLAYER12,
+ IN_BINDTYPE_COUNT
+};
+
+#define IN_BIND_OFFS(key, btype) \
+ ((key) * IN_BINDTYPE_COUNT + (btype))
+
typedef struct {
const char *prefix;
void (*probe)(void);
void (*free)(void *drv_data);
int (*get_bind_count)(void);
void (*get_def_binds)(int *binds);
- int (*clean_binds)(void *drv_data, int *binds);
+ int (*clean_binds)(void *drv_data, int *binds, int *def_finds);
void (*set_blocking)(void *data, int y);
int (*update_keycode)(void *drv_data, int *is_down);
int (*menu_translate)(int keycode);
/* to be called by drivers */
-void in_register(const char *nname, int drv_id, int fd_hnd, void *drv_data, int combos);
-void in_combos_find(int *binds, int last_key, int *combo_keys, int *combo_acts);
-int in_combos_do(int keys, int *binds, int last_key, int combo_keys, int combo_acts);
+void in_register(const char *nname, int drv_id, int drv_fd_hnd, void *drv_data,
+ int key_count, int combos);
+void in_combos_find(const int *binds, int last_key, int *combo_keys, int *combo_acts);
+int in_combos_do(int keys, const int *binds, int last_key, int combo_keys, int combo_acts);
void in_init(void);
void in_probe(void);
-int in_update(void);
+int in_update(int *result);
void in_set_blocking(int is_blocking);
int in_update_keycode(int *dev_id, int *is_down, int timeout_ms);
int in_menu_wait_any(int timeout_ms);
int in_get_dev_info(int dev_id, int what);
void in_config_start(void);
int in_config_parse_dev(const char *dev_name);
-int in_config_bind_key(int dev_id, const char *key, int mask);
+int in_config_bind_key(int dev_id, const char *key, int binds, int bind_type);
void in_config_end(void);
-int in_bind_key(int dev_id, int keycode, int mask, int force_unbind);
+int in_bind_key(int dev_id, int keycode, int bind_type, int mask, int force_unbind);
void in_debug_dump(void);
const int *in_get_dev_binds(int dev_id);
{\r
const menu_entry *ent;\r
int x, y, w = 0, h = 0;\r
- int offs, opt_offs = 27 * me_mfont_w;\r
+ int offs, col2_offs = 27 * me_mfont_w;\r
const char *name;\r
int asel = 0;\r
int i, n;\r
\r
if (ent->beh != MB_NONE)\r
{\r
- if (wt > opt_offs)\r
- opt_offs = wt + me_mfont_w;\r
- wt = opt_offs;\r
+ if (wt > col2_offs)\r
+ col2_offs = wt + me_mfont_w;\r
+ wt = col2_offs;\r
\r
switch (ent->beh) {\r
case MB_NONE: break;\r
case MB_NONE:\r
break;\r
case MB_OPT_ONOFF:\r
- text_out16(x + opt_offs, y, (*(int *)ent->var & ent->mask) ? "ON" : "OFF");\r
+ text_out16(x + col2_offs, y, (*(int *)ent->var & ent->mask) ? "ON" : "OFF");\r
break;\r
case MB_OPT_RANGE:\r
- text_out16(x + opt_offs, y, "%i", *(int *)ent->var);\r
+ text_out16(x + col2_offs, y, "%i", *(int *)ent->var);\r
break;\r
case MB_OPT_CUSTOM:\r
case MB_OPT_CUSTONOFF:\r
if (ent->generate_name)\r
name = ent->generate_name(ent->id, &offs);\r
if (name != NULL)\r
- text_out16(x + opt_offs + offs * me_mfont_w, y, "%s", name);\r
+ text_out16(x + col2_offs + offs * me_mfont_w, y, "%s", name);\r
break;\r
}\r
\r
\r
static char *action_binds(int player_idx, int action_mask, int dev_id)\r
{\r
+ int k, count, can_combo, type;\r
const int *binds;\r
- int k, count;\r
\r
static_buff[0] = 0;\r
\r
return static_buff;\r
\r
count = in_get_dev_info(dev_id, IN_INFO_BIND_COUNT);\r
+ can_combo = in_get_dev_info(dev_id, IN_INFO_DOES_COMBOS);\r
+\r
+ type = IN_BINDTYPE_EMU;\r
+ if (player_idx >= 0) {\r
+ can_combo = 0;\r
+ type = IN_BINDTYPE_PLAYER12;\r
+ }\r
+ 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 (!(binds[k] & action_mask))\r
- continue;\r
\r
- if (player_idx >= 0 && ((binds[k] >> 16) & 3) != player_idx)\r
+ if (!(binds[IN_BIND_OFFS(k, type)] & action_mask))\r
continue;\r
\r
xname = in_get_key_name(dev_id, k);\r
len = strlen(static_buff);\r
if (len) {\r
- strncat(static_buff, " + ", sizeof(static_buff) - len - 1);\r
- len += 3;\r
+ strncat(static_buff, can_combo ? " + " : ", ",\r
+ sizeof(static_buff) - len - 1);\r
+ len += can_combo ? 3 : 2;\r
}\r
strncat(static_buff, xname, sizeof(static_buff) - len - 1);\r
}\r
return static_buff;\r
}\r
\r
-static int count_bound_keys(int dev_id, int action_mask, int player_idx)\r
+static int count_bound_keys(int dev_id, int action_mask, int bindtype)\r
{\r
const int *binds;\r
int k, keys = 0;\r
count = in_get_dev_info(dev_id, IN_INFO_BIND_COUNT);\r
for (k = 0; k < count; k++)\r
{\r
- if (!(binds[k] & action_mask))\r
- continue;\r
-\r
- if (player_idx >= 0 && ((binds[k] >> 16) & 3) != player_idx)\r
- continue;\r
-\r
- keys++;\r
+ if (binds[IN_BIND_OFFS(k, bindtype)] & action_mask)\r
+ keys++;\r
}\r
\r
return keys;\r
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;\r
- int dev_id, dev_count, kc, is_down, mkey, unbind;\r
+ int dev_id, dev_count, kc, is_down, mkey;\r
+ int unbind, bindtype, mask;\r
\r
for (i = 0, dev_id = -1, dev_count = 0; i < IN_MAX_DEVS; i++) {\r
if (in_get_dev_name(i, 1, 0) != NULL) {\r
for (is_down = 1; is_down; )\r
kc = in_update_keycode(&dev_id, &is_down, -1);\r
\r
- i = count_bound_keys(dev_id, opts[sel].mask, player_idx);\r
+ bindtype = player_idx >= 0 ? IN_BINDTYPE_PLAYER12 : IN_BINDTYPE_EMU;\r
+ mask = opts[sel].mask;\r
+ if (player_idx == 1)\r
+ mask <<= 16;\r
+\r
+ i = count_bound_keys(dev_id, mask, bindtype);\r
unbind = (i > 0);\r
\r
/* allow combos if device supports them */\r
- if (i == 1 && in_get_dev_info(dev_id, IN_INFO_DOES_COMBOS))\r
+ if (i == 1 && bindtype == IN_BINDTYPE_EMU &&\r
+ in_get_dev_info(dev_id, IN_INFO_DOES_COMBOS))\r
unbind = 0;\r
\r
- in_bind_key(dev_id, kc, opts[sel].mask, unbind);\r
- if (player_idx >= 0) {\r
- /* FIXME */\r
- in_bind_key(dev_id, kc, 3 << 16, 1);\r
- in_bind_key(dev_id, kc, player_idx << 16, 0);\r
- }\r
+ in_bind_key(dev_id, kc, bindtype, mask, unbind);\r
}\r
}\r
\r
{ "Z ", 0x0100 }\r
};\r
\r
-// player2_flag, reserved, ?, ?,\r
-// ?, ?, fast forward, menu\r
-// "NEXT SAVE SLOT", "PREV SAVE SLOT", "SWITCH RENDERER", "SAVE STATE",\r
-// "LOAD STATE", "VOLUME UP", "VOLUME DOWN", "DONE"\r
me_bind_action emuctrl_actions[] =\r
{\r
{ "Load State ", PEV_STATE_LOAD },\r
return;
}
- in_register(IN_PREFIX "GP2X pad", IN_DRVID_GP2X, -1, (void *)1, 1);
+ in_register(IN_PREFIX "GP2X pad", IN_DRVID_GP2X, -1, (void *)1,
+ IN_GP2X_NBUTTONS, 1);
}
static void in_gp2x_free(void *drv_data)
return IN_GP2X_NBUTTONS;
}
-/* returns bitfield of binds of pressed buttons */
-int in_gp2x_update(void *drv_data, int *binds)
+/* ORs result with pressed buttons */
+int in_gp2x_update(void *drv_data, const int *binds, int *result)
{
- int i, keys, ret = 0;
+ int type_start = 0;
+ int i, t, keys;
keys = in_gp2x_get_bits();
- if (keys & in_gp2x_combo_keys)
- return in_combos_do(keys, binds, BTN_PUSH, in_gp2x_combo_keys, in_gp2x_combo_acts);
+ if (keys & in_gp2x_combo_keys) {
+ result[IN_BINDTYPE_EMU] = in_combos_do(keys, binds, BTN_PUSH,
+ in_gp2x_combo_keys, in_gp2x_combo_acts);
+ type_start = IN_BINDTYPE_PLAYER12;
+ }
+
+ for (i = 0; keys; i++, keys >>= 1) {
+ if (!(keys & 1))
+ continue;
- for (i = 0; keys; i++) {
- if (keys & 1)
- ret |= binds[i];
- keys >>= 1;
+ for (t = type_start; t < IN_BINDTYPE_COUNT; t++)
+ result[t] |= binds[IN_BIND_OFFS(i, t)];
}
- return ret;
+ return 0;
}
int in_gp2x_update_keycode(void *data, int *is_down)
static const struct {
short code;
- short bit;
+ char btype;
+ char bit;
} in_gp2x_def_binds[] =
{
/* MXYZ SACB RLDU */
- { BTN_UP, 0 },
- { BTN_DOWN, 1 },
- { BTN_LEFT, 2 },
- { BTN_RIGHT, 3 },
- { BTN_X, 4 }, /* B */
- { BTN_B, 5 }, /* C */
- { BTN_A, 6 }, /* A */
- { BTN_START, 7 },
- { BTN_SELECT, 23 }, /* menu */
- { BTN_Y, 26 }, /* switch rend */
- { BTN_L, 27 }, /* save state */
- { BTN_R, 28 }, /* load state */
- { BTN_VOL_UP, 29 }, /* vol up */
- { BTN_VOL_DOWN, 30 }, /* vol down */
+ { BTN_UP, IN_BINDTYPE_PLAYER12, 0 },
+ { BTN_DOWN, IN_BINDTYPE_PLAYER12, 1 },
+ { BTN_LEFT, IN_BINDTYPE_PLAYER12, 2 },
+ { BTN_RIGHT, IN_BINDTYPE_PLAYER12, 3 },
+ { BTN_X, IN_BINDTYPE_PLAYER12, 4 }, /* B */
+ { BTN_B, IN_BINDTYPE_PLAYER12, 5 }, /* C */
+ { BTN_A, IN_BINDTYPE_PLAYER12, 6 }, /* A */
+ { BTN_START, IN_BINDTYPE_PLAYER12, 7 },
+ { BTN_SELECT, IN_BINDTYPE_EMU, PEVB_MENU },
+ { BTN_Y, IN_BINDTYPE_EMU, PEVB_SWITCH_RND },
+ { BTN_L, IN_BINDTYPE_EMU, PEVB_STATE_SAVE },
+ { BTN_R, IN_BINDTYPE_EMU, PEVB_STATE_LOAD },
+ { BTN_VOL_UP, IN_BINDTYPE_EMU, PEVB_VOL_UP },
+ { BTN_VOL_DOWN, IN_BINDTYPE_EMU, PEVB_VOL_DOWN },
};
#define DEF_BIND_COUNT (sizeof(in_gp2x_def_binds) / sizeof(in_gp2x_def_binds[0]))
int i;
for (i = 0; i < DEF_BIND_COUNT; i++)
- binds[in_gp2x_def_binds[i].code] = 1 << in_gp2x_def_binds[i].bit;
+ binds[IN_BIND_OFFS(in_gp2x_def_binds[i].code, in_gp2x_def_binds[i].btype)] =
+ 1 << in_gp2x_def_binds[i].bit;
}
/* remove binds of missing keys, count remaining ones */
-static int in_gp2x_clean_binds(void *drv_data, int *binds)
+static int in_gp2x_clean_binds(void *drv_data, int *binds, int *def_binds)
{
int i, count = 0, have_vol = 0, have_menu = 0;
for (i = 0; i < IN_GP2X_NBUTTONS; i++) {
- if (in_gp2x_keys[i] == NULL)
- binds[i] = binds[i + IN_GP2X_NBUTTONS] = 0;
- if (binds[i]) {
- count++;
- if (binds[i] & ((1 << 29)|(1 << 30)))
- have_vol = 1;
- if (binds[i] & (1 << 23))
- have_menu = 1;
+ int t, eb, offs;
+ for (t = 0; t < IN_BINDTYPE_COUNT; t++) {
+ offs = IN_BIND_OFFS(i, t);
+ if (in_gp2x_keys[i] == NULL)
+ binds[offs] = def_binds[offs] = 0;
+ if (binds[offs])
+ count++;
}
+ eb = binds[IN_BIND_OFFS(i, IN_BINDTYPE_EMU)];
+ if (eb & (PEV_VOL_DOWN|PEV_VOL_UP))
+ have_vol = 1;
+ if (eb & PEV_MENU)
+ have_menu = 1;
}
/* autobind some important keys, if they are unbound */
if (!have_vol && binds[BTN_VOL_UP] == 0 && binds[BTN_VOL_DOWN] == 0) {
- binds[BTN_VOL_UP] = 1 << 29;
- binds[BTN_VOL_DOWN] = 1 << 30;
+ binds[IN_BIND_OFFS(BTN_VOL_UP, IN_BINDTYPE_EMU)] = PEV_VOL_UP;
+ binds[IN_BIND_OFFS(BTN_VOL_DOWN, IN_BINDTYPE_EMU)] = PEV_VOL_DOWN;
+ count += 2;
}
- if (!have_menu && binds[BTN_SELECT] == 0)
- binds[BTN_SELECT] = 1 << 23;
+ if (!have_menu) {
+ binds[IN_BIND_OFFS(BTN_SELECT, IN_BINDTYPE_EMU)] = PEV_MENU;
+ count++;
+ }
in_combos_find(binds, BTN_PUSH, &in_gp2x_combo_keys, &in_gp2x_combo_acts);
return count;
-
}
void in_gp2x_init(void *vdrv)
void in_gp2x_init(void *vdrv);
-int in_gp2x_update(void *drv_data, int *binds);
+int in_gp2x_update(void *drv_data, const int *binds, int *result);
typedef struct {
int fd;
- int prev_update;
int abs_lzone;
int abs_rzone;
int abs_tzone;
int abs_lasty;
} in_evdev_t;
+#ifndef KEY_CNT
+#define KEY_CNT (KEY_MAX + 1)
+#endif
+
#define KEYBITS_BIT(x) (keybits[(x)/sizeof(keybits[0])/8] & \
(1 << ((x) & (sizeof(keybits[0])*8-1))))
(1 << ((x) & (sizeof(keybits[0])*8-1))))
static const char * const in_evdev_prefix = "evdev:";
-static const char * const in_evdev_keys[KEY_MAX + 1] = {
+static const char * const in_evdev_keys[KEY_CNT] = {
[0 ... KEY_MAX] = NULL,
[KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
[KEY_1] = "1", [KEY_2] = "2",
for (i = 0;; i++)
{
- int keybits[(KEY_MAX+1)/sizeof(int)], absbits[(ABS_MAX+1)/sizeof(int)];
+ int keybits[KEY_CNT / sizeof(int)], absbits[(ABS_MAX+1)/sizeof(int)];
int support = 0, count = 0;
in_evdev_t *dev;
int u, ret, fd;
snprintf(name, sizeof(name), "/dev/input/event%d", i);
fd = open(name, O_RDONLY|O_NONBLOCK);
- if (fd == -1)
+ if (fd == -1) {
+ if (errno == EACCES)
+ continue; /* maybe we can access next one */
break;
+ }
/* check supported events */
ret = ioctl(fd, EVIOCGBIT(0, sizeof(support)), &support);
}
/* check for interesting keys */
- for (u = 0; u < KEY_MAX + 1; u++) {
+ for (u = 0; u < KEY_CNT; u++) {
if (KEYBITS_BIT(u) && u != KEY_POWER && u != KEY_SLEEP)
count++;
}
ioctl(fd, EVIOCGNAME(sizeof(name)-6), name+6);
printf("in_evdev: found \"%s\" with %d events (type %08x)\n",
name+6, count, support);
- in_register(name, IN_DRVID_EVDEV, fd, dev, 0);
+ in_register(name, IN_DRVID_EVDEV, fd, dev, KEY_CNT, 0);
continue;
skip:
static int in_evdev_get_bind_count(void)
{
- return KEY_MAX + 1;
+ return KEY_CNT;
}
-/* returns bitfield of binds of pressed buttons */
-int in_evdev_update(void *drv_data, int *binds)
+static void or_binds(const int *binds, int key, int *result)
+{
+ int t;
+ for (t = 0; t < IN_BINDTYPE_COUNT; t++)
+ result[t] |= binds[IN_BIND_OFFS(key, t)];
+}
+
+/* ORs result with binds of pressed buttons
+ * XXX: should measure performance hit of this func, might need to optimize */
+int in_evdev_update(void *drv_data, const int *binds, int *result)
{
struct input_event ev[16];
struct input_absinfo ainfo;
- int keybits[(KEY_MAX+1)/sizeof(int)];
+ int keybits[KEY_CNT / sizeof(int)];
in_evdev_t *dev = drv_data;
- int result = 0, changed = 0;
int rd, ret, u;
while (1) {
perror("in_evdev: read failed");
break;
}
-
- changed = 1;
}
- if (!changed)
- return dev->prev_update;
-
ret = ioctl(dev->fd, EVIOCGKEY(sizeof(keybits)), keybits);
if (ret == -1) {
perror("in_evdev: ioctl failed");
- return 0;
+ return -1;
}
- for (u = 0; u < KEY_MAX + 1; u++) {
- if (KEYBITS_BIT(u)) {
- result |= binds[u];
- }
+ for (u = 0; u < KEY_CNT; u++) {
+ if (KEYBITS_BIT(u))
+ or_binds(binds, u, result);
}
/* map X and Y absolute to UDLR */
if (dev->abs_lzone != 0) {
ret = ioctl(dev->fd, EVIOCGABS(ABS_X), &ainfo);
if (ret != -1) {
- if (ainfo.value < dev->abs_lzone) result |= binds[KEY_LEFT];
- if (ainfo.value > dev->abs_rzone) result |= binds[KEY_RIGHT];
+ if (ainfo.value < dev->abs_lzone) or_binds(binds, KEY_LEFT, result);
+ if (ainfo.value > dev->abs_rzone) or_binds(binds, KEY_RIGHT, result);
}
}
if (dev->abs_tzone != 0) {
ret = ioctl(dev->fd, EVIOCGABS(ABS_Y), &ainfo);
if (ret != -1) {
- if (ainfo.value < dev->abs_tzone) result |= binds[KEY_UP];
- if (ainfo.value > dev->abs_bzone) result |= binds[KEY_DOWN];
+ if (ainfo.value < dev->abs_tzone) or_binds(binds, KEY_UP, result);
+ if (ainfo.value > dev->abs_bzone) or_binds(binds, KEY_DOWN, result);
}
}
- dev->prev_update = result;
- return result;
+ return 0;
}
static void in_evdev_set_blocking(void *drv_data, int y)
long flags;
int ret;
- dev->prev_update = 0;
-
flags = (long)fcntl(dev->fd, F_GETFL);
if ((int)flags == -1) {
perror("in_evdev: F_GETFL fcntl failed");
{
int i;
- for (i = 0; i < KEY_MAX + 1; i++) {
+ for (i = 0; i < KEY_CNT; i++) {
const char *k = in_evdev_keys[i];
if (k != NULL && strcasecmp(k, key_name) == 0)
return i;
static const struct {
short code;
- short bit;
+ char btype;
+ char bit;
} in_evdev_def_binds[] =
{
/* MXYZ SACB RLDU */
- { KEY_UP, 0 },
- { KEY_DOWN, 1 },
- { KEY_LEFT, 2 },
- { KEY_RIGHT, 3 },
- { KEY_S, 4 }, /* B */
- { BTN_B, 4 },
- { KEY_D, 5 }, /* C */
- { BTN_A, 5 },
- { KEY_A, 6 }, /* A */
- { BTN_Y, 6 },
- { KEY_ENTER, 7 },
- { BTN_START, 7 },
- { BTN_TL, PEVB_STATE_LOAD },
- { BTN_TR, PEVB_STATE_SAVE },
+ { KEY_UP, IN_BINDTYPE_PLAYER12, 0 },
+ { KEY_DOWN, IN_BINDTYPE_PLAYER12, 1 },
+ { KEY_LEFT, IN_BINDTYPE_PLAYER12, 2 },
+ { KEY_RIGHT, IN_BINDTYPE_PLAYER12, 3 },
+ { KEY_S, IN_BINDTYPE_PLAYER12, 4 }, /* B */
+ { BTN_B, IN_BINDTYPE_PLAYER12, 4 },
+ { KEY_D, IN_BINDTYPE_PLAYER12, 5 }, /* C */
+ { BTN_A, IN_BINDTYPE_PLAYER12, 5 },
+ { KEY_A, IN_BINDTYPE_PLAYER12, 6 }, /* A */
+ { BTN_Y, IN_BINDTYPE_PLAYER12, 6 },
+ { KEY_ENTER, IN_BINDTYPE_PLAYER12, 7 },
+ { BTN_START, IN_BINDTYPE_PLAYER12, 7 },
+ { BTN_TL, IN_BINDTYPE_EMU, PEVB_STATE_LOAD },
+ { BTN_TR, IN_BINDTYPE_EMU, PEVB_STATE_SAVE },
};
#define DEF_BIND_COUNT (sizeof(in_evdev_def_binds) / sizeof(in_evdev_def_binds[0]))
int i;
for (i = 0; i < DEF_BIND_COUNT; i++)
- binds[in_evdev_def_binds[i].code] = 1 << in_evdev_def_binds[i].bit;
+ binds[IN_BIND_OFFS(in_evdev_def_binds[i].code, in_evdev_def_binds[i].btype)] =
+ 1 << in_evdev_def_binds[i].bit;
}
/* remove binds of missing keys, count remaining ones */
-static int in_evdev_clean_binds(void *drv_data, int *binds)
+static int in_evdev_clean_binds(void *drv_data, int *binds, int *def_binds)
{
- int keybits[(KEY_MAX+1)/sizeof(int)];
+ int keybits[KEY_CNT / sizeof(int)];
in_evdev_t *dev = drv_data;
- int i, ret, count = 0;
+ int i, t, ret, offs, count = 0;
ret = ioctl(dev->fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits);
if (ret == -1) {
KEYBITS_BIT_SET(KEY_DOWN);
}
- for (i = 0; i < KEY_MAX + 1; i++) {
- if (!KEYBITS_BIT(i))
- binds[i] = binds[i + KEY_MAX + 1] = 0;
- if (binds[i])
- count++;
+ for (i = 0; i < KEY_CNT; i++) {
+ for (t = 0; t < IN_BINDTYPE_COUNT; t++) {
+ offs = IN_BIND_OFFS(i, t);
+ if (!KEYBITS_BIT(i))
+ binds[offs] = def_binds[offs] = 0;
+ if (binds[offs])
+ count++;
+ }
}
return count;
void in_evdev_init(void *vdrv);
-int in_evdev_update(void *drv_data, int *binds);
+int in_evdev_update(void *drv_data, const int *binds, int *result);
#define SIMPLE_WRITE_SOUND 0
#define mix_32_to_16l_stereo_lvl mix_32_to_16l_stereo
-#define EL_LOGMASK (EL_ANOMALY|EL_STATUS|EL_SRAMIO|EL_EEPROM|EL_UIO|EL_IDLE)//|EL_VDPDMA|EL_HVCNT|EL_ASVDP)//|EL_SVP)
+#define EL_LOGMASK (EL_ANOMALY|EL_STATUS|EL_UIO|EL_IDLE)//|EL_VDPDMA|EL_HVCNT|EL_ASVDP)//|EL_SVP)
// EL_VDPDMA|EL_ASVDP|EL_SR) // |EL_BUSREQ|EL_Z80BNK)
//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__)