comparison io.c @ 1194:1ad0ec7e3939

Make gamepad "semantic" mapping play nice with hotplug support
author Michael Pavone <pavone@retrodev.com>
date Tue, 24 Jan 2017 20:53:10 -0800
parents 6a4503fad67e
children 9bc78bd89567
comparison
equal deleted inserted replaced
1193:0e69409634f3 1194:1ad0ec7e3939
169 joysticks[joystick].dpads[dpad].bindings[i].bind_type = bind_type; 169 joysticks[joystick].dpads[dpad].bindings[i].bind_type = bind_type;
170 joysticks[joystick].dpads[dpad].bindings[i].subtype_a = subtype_a; 170 joysticks[joystick].dpads[dpad].bindings[i].subtype_a = subtype_a;
171 joysticks[joystick].dpads[dpad].bindings[i].subtype_b = subtype_b; 171 joysticks[joystick].dpads[dpad].bindings[i].subtype_b = subtype_b;
172 joysticks[joystick].dpads[dpad].bindings[i].value = value; 172 joysticks[joystick].dpads[dpad].bindings[i].value = value;
173 break; 173 break;
174 }
175 }
176 }
177
178 void reset_joystick_bindings(int joystick)
179 {
180 if (joystick >= MAX_JOYSTICKS) {
181 return;
182 }
183 if (joysticks[joystick].buttons) {
184 for (int i = 0; i < joysticks[joystick].num_buttons; i++)
185 {
186 joysticks[joystick].buttons[i].bind_type = BIND_NONE;
187 }
188 }
189 if (joysticks[joystick].dpads) {
190 for (int i = 0; i < joysticks[joystick].num_dpads; i++)
191 {
192 for (int dir = 0; dir < 4; dir++)
193 {
194 joysticks[joystick].dpads[i].bindings[dir].bind_type = BIND_NONE;
195 }
174 } 196 }
175 } 197 }
176 } 198 }
177 199
178 #define GAMEPAD_BUTTON(PRI_SLOT, SEC_SLOT, VALUE) (PRI_SLOT << 12 | SEC_SLOT << 8 | VALUE) 200 #define GAMEPAD_BUTTON(PRI_SLOT, SEC_SLOT, VALUE) (PRI_SLOT << 12 | SEC_SLOT << 8 | VALUE)
962 if (bindtype == BIND_GAMEPAD1) { 984 if (bindtype == BIND_GAMEPAD1) {
963 bind_button_gamepad(hostpadnum, hostbutton, padnum, button); 985 bind_button_gamepad(hostpadnum, hostbutton, padnum, button);
964 } else if (bindtype == BIND_UI) { 986 } else if (bindtype == BIND_UI) {
965 bind_button_ui(hostpadnum, hostbutton, ui_func, button); 987 bind_button_ui(hostpadnum, hostbutton, ui_func, button);
966 } 988 }
989 }
990
991 static tern_node *get_pad_buttons()
992 {
993 static tern_node *padbuttons;
994 if (!padbuttons) {
995 padbuttons = tern_insert_int(NULL, ".up", DPAD_UP);
996 padbuttons = tern_insert_int(padbuttons, ".down", DPAD_DOWN);
997 padbuttons = tern_insert_int(padbuttons, ".left", DPAD_LEFT);
998 padbuttons = tern_insert_int(padbuttons, ".right", DPAD_RIGHT);
999 padbuttons = tern_insert_int(padbuttons, ".a", BUTTON_A);
1000 padbuttons = tern_insert_int(padbuttons, ".b", BUTTON_B);
1001 padbuttons = tern_insert_int(padbuttons, ".c", BUTTON_C);
1002 padbuttons = tern_insert_int(padbuttons, ".x", BUTTON_X);
1003 padbuttons = tern_insert_int(padbuttons, ".y", BUTTON_Y);
1004 padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z);
1005 padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START);
1006 padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE);
1007 }
1008 return padbuttons;
1009 }
1010
1011 static tern_node *get_mouse_buttons()
1012 {
1013 static tern_node *mousebuttons;
1014 if (!mousebuttons) {
1015 mousebuttons = tern_insert_int(NULL, ".left", MOUSE_LEFT);
1016 mousebuttons = tern_insert_int(mousebuttons, ".middle", MOUSE_MIDDLE);
1017 mousebuttons = tern_insert_int(mousebuttons, ".right", MOUSE_RIGHT);
1018 mousebuttons = tern_insert_int(mousebuttons, ".start", MOUSE_START);
1019 mousebuttons = tern_insert_int(mousebuttons, ".motion", PSEUDO_BUTTON_MOTION);
1020 }
1021 return mousebuttons;
1022 }
1023
1024 void handle_joy_added(int joystick)
1025 {
1026 if (joystick > MAX_JOYSTICKS) {
1027 return;
1028 }
1029 tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0"));
1030 if (pads) {
1031 char numstr[11];
1032 sprintf(numstr, "%d", joystick);
1033 tern_node * pad = tern_find_ptr(pads, numstr);
1034 if (pad) {
1035 tern_node * dpad_node = tern_find_ptr(pad, "dpads");
1036 if (dpad_node) {
1037 for (int dpad = 0; dpad < 10; dpad++)
1038 {
1039 numstr[0] = dpad + '0';
1040 numstr[1] = 0;
1041 tern_node * pad_dpad = tern_find_ptr(dpad_node, numstr);
1042 char * dirs[] = {"up", "down", "left", "right"};
1043 int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
1044 for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) {
1045 char * target = tern_find_ptr(pad_dpad, dirs[dir]);
1046 if (target) {
1047 int ui_func, padnum, button;
1048 int bindtype = parse_binding_target(target, get_pad_buttons(), get_mouse_buttons(), &ui_func, &padnum, &button);
1049 if (bindtype == BIND_GAMEPAD1) {
1050 bind_dpad_gamepad(joystick, dpad, dirnums[dir], padnum, button);
1051 } else if (bindtype == BIND_UI) {
1052 bind_dpad_ui(joystick, dpad, dirnums[dir], ui_func, button);
1053 }
1054 }
1055 }
1056 }
1057 }
1058 tern_node *button_node = tern_find_ptr(pad, "buttons");
1059 if (button_node) {
1060 pad_button_state state = {
1061 .padnum = joystick,
1062 .padbuttons = get_pad_buttons(),
1063 .mousebuttons = get_mouse_buttons()
1064 };
1065 tern_foreach(button_node, process_pad_button, &state);
1066 }
1067 if (current_io) {
1068 if (joysticks[joystick].buttons) {
1069 map_bindings(current_io->ports, joysticks[joystick].buttons, joysticks[joystick].num_buttons);
1070 }
1071 if (joysticks[joystick].dpads)
1072 {
1073 for (uint32_t i = 0; i < joysticks[joystick].num_dpads; i++) {
1074 map_bindings(current_io->ports, joysticks[joystick].dpads[i].bindings, 4);
1075 }
1076 }
1077 }
1078 }
1079 }
1080
967 } 1081 }
968 1082
969 void set_keybindings(sega_io *io) 1083 void set_keybindings(sega_io *io)
970 { 1084 {
971 static uint8_t already_done; 1085 static uint8_t already_done;
1010 special = tern_insert_int(special, "select", RENDERKEY_SELECT); 1124 special = tern_insert_int(special, "select", RENDERKEY_SELECT);
1011 special = tern_insert_int(special, "play", RENDERKEY_PLAY); 1125 special = tern_insert_int(special, "play", RENDERKEY_PLAY);
1012 special = tern_insert_int(special, "search", RENDERKEY_SEARCH); 1126 special = tern_insert_int(special, "search", RENDERKEY_SEARCH);
1013 special = tern_insert_int(special, "back", RENDERKEY_BACK); 1127 special = tern_insert_int(special, "back", RENDERKEY_BACK);
1014 1128
1015 tern_node * padbuttons = tern_insert_int(NULL, ".up", DPAD_UP); 1129 tern_node *padbuttons = get_pad_buttons();
1016 padbuttons = tern_insert_int(padbuttons, ".down", DPAD_DOWN); 1130
1017 padbuttons = tern_insert_int(padbuttons, ".left", DPAD_LEFT); 1131 tern_node *mousebuttons = get_mouse_buttons();
1018 padbuttons = tern_insert_int(padbuttons, ".right", DPAD_RIGHT);
1019 padbuttons = tern_insert_int(padbuttons, ".a", BUTTON_A);
1020 padbuttons = tern_insert_int(padbuttons, ".b", BUTTON_B);
1021 padbuttons = tern_insert_int(padbuttons, ".c", BUTTON_C);
1022 padbuttons = tern_insert_int(padbuttons, ".x", BUTTON_X);
1023 padbuttons = tern_insert_int(padbuttons, ".y", BUTTON_Y);
1024 padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z);
1025 padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START);
1026 padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE);
1027
1028 tern_node *mousebuttons = tern_insert_int(NULL, ".left", MOUSE_LEFT);
1029 mousebuttons = tern_insert_int(mousebuttons, ".middle", MOUSE_MIDDLE);
1030 mousebuttons = tern_insert_int(mousebuttons, ".right", MOUSE_RIGHT);
1031 mousebuttons = tern_insert_int(mousebuttons, ".start", MOUSE_START);
1032 mousebuttons = tern_insert_int(mousebuttons, ".motion", PSEUDO_BUTTON_MOTION);
1033
1034 //pump event loop, so initial joystick insertion events are processed
1035 process_events();
1036 1132
1037 tern_node * keys = tern_get_node(tern_find_path(config, "bindings\0keys\0")); 1133 tern_node * keys = tern_get_node(tern_find_path(config, "bindings\0keys\0"));
1038 process_keys(keys, special, padbuttons, mousebuttons, NULL); 1134 process_keys(keys, special, padbuttons, mousebuttons, NULL);
1039 char numstr[] = "00"; 1135 char numstr[] = "00";
1040 tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0")); 1136 tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0"));
1047 numstr[1] = 0; 1143 numstr[1] = 0;
1048 } else { 1144 } else {
1049 numstr[0] = i/10 + '0'; 1145 numstr[0] = i/10 + '0';
1050 numstr[1] = i%10 + '0'; 1146 numstr[1] = i%10 + '0';
1051 } 1147 }
1052 tern_node * pad = tern_find_ptr(pads, numstr); 1148
1053 if (pad) {
1054 tern_node * dpad_node = tern_find_ptr(pad, "dpads");
1055 if (dpad_node) {
1056 for (int dpad = 0; dpad < 10; dpad++)
1057 {
1058 numstr[0] = dpad + '0';
1059 numstr[1] = 0;
1060 tern_node * pad_dpad = tern_find_ptr(dpad_node, numstr);
1061 char * dirs[] = {"up", "down", "left", "right"};
1062 int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
1063 for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) {
1064 char * target = tern_find_ptr(pad_dpad, dirs[dir]);
1065 if (target) {
1066 int ui_func, padnum, button;
1067 int bindtype = parse_binding_target(target, padbuttons, mousebuttons, &ui_func, &padnum, &button);
1068 if (bindtype == BIND_GAMEPAD1) {
1069 bind_dpad_gamepad(i, dpad, dirnums[dir], padnum, button);
1070 } else if (bindtype == BIND_UI) {
1071 bind_dpad_ui(i, dpad, dirnums[dir], ui_func, button);
1072 }
1073 }
1074 }
1075 }
1076 }
1077 tern_node *button_node = tern_find_ptr(pad, "buttons");
1078 if (button_node) {
1079 pad_button_state state = {
1080 .padnum = i,
1081 .padbuttons = padbuttons,
1082 .mousebuttons = mousebuttons
1083 };
1084 tern_foreach(button_node, process_pad_button, &state);
1085
1086 }
1087 }
1088 } 1149 }
1089 } 1150 }
1090 memset(mice, 0, sizeof(mice)); 1151 memset(mice, 0, sizeof(mice));
1091 tern_node * mice = tern_get_node(tern_find_path(config, "bindings\0mice\0")); 1152 tern_node * mice = tern_get_node(tern_find_path(config, "bindings\0mice\0"));
1092 if (mice) { 1153 if (mice) {