Mercurial > repos > blastem
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) { |