+/* 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;
+
+ *combo_keys = *combo_acts = 0;
+ for (act = 0; act < sizeof(binds[0]) * 8; act++)
+ {
+ int keyc = 0;
+ for (u = 0; u <= last_key; u++)
+ 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[IN_BIND_OFFS(u, IN_BINDTYPE_EMU)] & (1 << act)) {
+ *combo_keys |= 1 << u;
+ *combo_acts |= 1 << act;
+ }
+ }
+ }
+ }
+}
+
+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, acts_c, u;
+
+ if (!(keys & (1 << i)))
+ continue;
+
+ acts = binds[IN_BIND_OFFS(i, IN_BINDTYPE_EMU)];
+ if (!acts)
+ continue;
+
+ 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;
+}
+