comparison io.c @ 937:9364dad5561a

Added reasonable handling of joystick hotplug
author Michael Pavone <pavone@retrodev.com>
date Tue, 23 Feb 2016 21:17:56 -0800
parents 20c464dbae8f
children 750995b587a0
comparison
equal deleted inserted replaced
936:f1a8124ad881 937:9364dad5561a
88 keybinding bindings[4]; 88 keybinding bindings[4];
89 uint8_t state; 89 uint8_t state;
90 } joydpad; 90 } joydpad;
91 91
92 typedef struct { 92 typedef struct {
93 keybinding *buttons;
94 joydpad *dpads;
95 uint32_t num_buttons; //number of entries in the buttons array, not necessarily the number of buttons on the device
96 uint32_t num_dpads; //number of entries in the dpads array, not necessarily the number of dpads on the device
97 } joystick;
98
99 typedef struct {
93 io_port *motion_port; 100 io_port *motion_port;
94 keybinding buttons[MAX_MOUSE_BUTTONS]; 101 keybinding buttons[MAX_MOUSE_BUTTONS];
95 uint8_t bind_type; 102 uint8_t bind_type;
96 } mousebinding; 103 } mousebinding;
97 104
98 keybinding * bindings[0x10000]; 105 #define DEFAULT_JOYBUTTON_ALLOC 12
99 keybinding * joybindings[MAX_JOYSTICKS]; 106
100 joydpad * joydpads[MAX_JOYSTICKS]; 107 static keybinding * bindings[0x10000];
101 mousebinding mice[MAX_MICE]; 108 static joystick joysticks[MAX_JOYSTICKS];
109 static mousebinding mice[MAX_MICE];
102 const uint8_t dpadbits[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT}; 110 const uint8_t dpadbits[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
103 mouse_modes mouse_mode; 111 static mouse_modes mouse_mode;
104 char mouse_captured; 112 static char mouse_captured;
105 113
106 void bind_key(int keycode, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value) 114 void bind_key(int keycode, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
107 { 115 {
108 int bucket = keycode >> 15 & 0xFFFF; 116 int bucket = keycode >> 15 & 0xFFFF;
109 if (!bindings[bucket]) { 117 if (!bindings[bucket]) {
120 void bind_button(int joystick, int button, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value) 128 void bind_button(int joystick, int button, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
121 { 129 {
122 if (joystick >= MAX_JOYSTICKS) { 130 if (joystick >= MAX_JOYSTICKS) {
123 return; 131 return;
124 } 132 }
125 if (!joybindings[joystick]) { 133 if (!joysticks[joystick].buttons) {
126 int num = render_joystick_num_buttons(joystick); 134 joysticks[joystick].num_buttons = button < DEFAULT_JOYBUTTON_ALLOC ? DEFAULT_JOYBUTTON_ALLOC : button + 1;
127 if (!num) { 135 joysticks[joystick].buttons = calloc(joysticks[joystick].num_buttons, sizeof(keybinding));
128 return; 136 } else if (joysticks[joystick].num_buttons <= button) {
129 } 137 uint32_t old_capacity = joysticks[joystick].num_buttons;
130 joybindings[joystick] = malloc(sizeof(keybinding)*num); 138 joysticks[joystick].num_buttons *= 2;
131 memset(joybindings[joystick], 0, sizeof(keybinding)*num); 139 joysticks[joystick].buttons = realloc(joysticks[joystick].buttons, sizeof(keybinding) * joysticks[joystick].num_buttons);
132 } 140 memset(joysticks[joystick].buttons + old_capacity, 0, joysticks[joystick].num_buttons - old_capacity);
133 joybindings[joystick][button].bind_type = bind_type; 141 }
134 joybindings[joystick][button].subtype_a = subtype_a; 142 joysticks[joystick].buttons[button].bind_type = bind_type;
135 joybindings[joystick][button].subtype_b = subtype_b; 143 joysticks[joystick].buttons[button].subtype_a = subtype_a;
136 joybindings[joystick][button].value = value; 144 joysticks[joystick].buttons[button].subtype_b = subtype_b;
145 joysticks[joystick].buttons[button].value = value;
137 } 146 }
138 147
139 void bind_dpad(int joystick, int dpad, int direction, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value) 148 void bind_dpad(int joystick, int dpad, int direction, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
140 { 149 {
141 if (joystick >= MAX_JOYSTICKS) { 150 if (joystick >= MAX_JOYSTICKS) {
142 return; 151 return;
143 } 152 }
144 if (!joydpads[joystick]) { 153 if (!joysticks[joystick].dpads) {
145 int num = render_joystick_num_hats(joystick); 154 //multiple D-pads hats are not common, so don't allocate any extra space
146 if (!num) { 155 joysticks[joystick].dpads = calloc(dpad+1, sizeof(joydpad));
147 return; 156 joysticks[joystick].num_dpads = dpad+1;
148 } 157 } else if (joysticks[joystick].num_dpads <= dpad) {
149 joydpads[joystick] = malloc(sizeof(joydpad)*num); 158 uint32_t old_capacity = joysticks[joystick].num_dpads;
150 memset(joydpads[joystick], 0, sizeof(joydpad)*num); 159 joysticks[joystick].num_dpads *= 2;
160 joysticks[joystick].dpads = realloc(joysticks[joystick].dpads, sizeof(joydpad) * joysticks[joystick].num_dpads);
161 memset(joysticks[joystick].dpads + old_capacity, 0, joysticks[joystick].num_dpads - old_capacity);
151 } 162 }
152 for (int i = 0; i < 4; i ++) { 163 for (int i = 0; i < 4; i ++) {
153 if (dpadbits[i] & direction) { 164 if (dpadbits[i] & direction) {
154 joydpads[joystick][dpad].bindings[i].bind_type = bind_type; 165 joysticks[joystick].dpads[dpad].bindings[i].bind_type = bind_type;
155 joydpads[joystick][dpad].bindings[i].subtype_a = subtype_a; 166 joysticks[joystick].dpads[dpad].bindings[i].subtype_a = subtype_a;
156 joydpads[joystick][dpad].bindings[i].subtype_b = subtype_b; 167 joysticks[joystick].dpads[dpad].bindings[i].subtype_b = subtype_b;
157 joydpads[joystick][dpad].bindings[i].value = value; 168 joysticks[joystick].dpads[dpad].bindings[i].value = value;
158 break; 169 break;
159 } 170 }
160 } 171 }
161 } 172 }
162 173
256 handle_binding_down(binding); 267 handle_binding_down(binding);
257 } 268 }
258 269
259 void handle_joydown(int joystick, int button) 270 void handle_joydown(int joystick, int button)
260 { 271 {
261 if (!joybindings[joystick]) { 272 if (joystick >= MAX_JOYSTICKS || button >= joysticks[joystick].num_buttons) {
262 return; 273 return;
263 } 274 }
264 keybinding * binding = joybindings[joystick] + button; 275 keybinding * binding = joysticks[joystick].buttons + button;
265 handle_binding_down(binding); 276 handle_binding_down(binding);
266 } 277 }
267 278
268 void handle_mousedown(int mouse, int button) 279 void handle_mousedown(int mouse, int button)
269 { 280 {
390 handle_binding_up(binding); 401 handle_binding_up(binding);
391 } 402 }
392 403
393 void handle_joyup(int joystick, int button) 404 void handle_joyup(int joystick, int button)
394 { 405 {
395 if (!joybindings[joystick]) { 406 if (joystick >= MAX_JOYSTICKS || button >= joysticks[joystick].num_buttons) {
396 return; 407 return;
397 } 408 }
398 keybinding * binding = joybindings[joystick] + button; 409 keybinding * binding = joysticks[joystick].buttons + button;
399 handle_binding_up(binding); 410 handle_binding_up(binding);
400 } 411 }
401 412
402 void handle_joy_dpad(int joystick, int dpadnum, uint8_t value) 413 void handle_joy_dpad(int joystick, int dpadnum, uint8_t value)
403 { 414 {
404 if (!joydpads[joystick]) { 415 if (joystick >= MAX_JOYSTICKS || dpadnum >= joysticks[joystick].num_dpads) {
405 return; 416 return;
406 } 417 }
407 joydpad * dpad = joydpads[joystick] + dpadnum; 418 joydpad * dpad = joysticks[joystick].dpads + dpadnum;
408 uint8_t newdown = (value ^ dpad->state) & value; 419 uint8_t newdown = (value ^ dpad->state) & value;
409 uint8_t newup = ((~value) ^ (~dpad->state)) & (~value); 420 uint8_t newup = ((~value) ^ (~dpad->state)) & (~value);
410 dpad->state = value; 421 dpad->state = value;
411 for (int i = 0; i < 4; i++) { 422 for (int i = 0; i < 4; i++) {
412 if (newdown & dpadbits[i]) { 423 if (newdown & dpadbits[i]) {
929 tern_node * keys = tern_get_node(tern_find_path(config, "bindings\0keys\0")); 940 tern_node * keys = tern_get_node(tern_find_path(config, "bindings\0keys\0"));
930 process_keys(keys, special, padbuttons, mousebuttons, NULL); 941 process_keys(keys, special, padbuttons, mousebuttons, NULL);
931 char numstr[] = "00"; 942 char numstr[] = "00";
932 tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0")); 943 tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0"));
933 if (pads) { 944 if (pads) {
934 for (int i = 0; i < 100 && i < render_num_joysticks(); i++) 945 for (int i = 0; i < MAX_JOYSTICKS; i++)
935 { 946 {
936 947
937 if (i < 10) { 948 if (i < 10) {
938 numstr[0] = i + '0'; 949 numstr[0] = i + '0';
939 numstr[1] = 0; 950 numstr[1] = 0;
943 } 954 }
944 tern_node * pad = tern_find_ptr(pads, numstr); 955 tern_node * pad = tern_find_ptr(pads, numstr);
945 if (pad) { 956 if (pad) {
946 tern_node * dpad_node = tern_find_ptr(pad, "dpads"); 957 tern_node * dpad_node = tern_find_ptr(pad, "dpads");
947 if (dpad_node) { 958 if (dpad_node) {
948 for (int dpad = 0; dpad < 10 && dpad < render_joystick_num_hats(i); dpad++) 959 for (int dpad = 0; dpad < 10; dpad++)
949 { 960 {
950 numstr[0] = dpad + '0'; 961 numstr[0] = dpad + '0';
951 numstr[1] = 0; 962 numstr[1] = 0;
952 tern_node * pad_dpad = tern_find_ptr(dpad_node, numstr); 963 tern_node * pad_dpad = tern_find_ptr(dpad_node, numstr);
953 char * dirs[] = {"up", "down", "left", "right"}; 964 char * dirs[] = {"up", "down", "left", "right"};
966 } 977 }
967 } 978 }
968 } 979 }
969 tern_node *button_node = tern_find_ptr(pad, "buttons"); 980 tern_node *button_node = tern_find_ptr(pad, "buttons");
970 if (button_node) { 981 if (button_node) {
971 for (int but = 0; but < 100 && but < render_joystick_num_buttons(i); but++) 982 for (int but = 0; but < 30; but++)
972 { 983 {
973 if (but < 10) { 984 if (but < 10) {
974 numstr[0] = but + '0'; 985 numstr[0] = but + '0';
975 numstr[1] = 0; 986 numstr[1] = 0;
976 } else { 987 } else {
1021 map_bindings(ports, bindings[bucket], 0x8000); 1032 map_bindings(ports, bindings[bucket], 0x8000);
1022 } 1033 }
1023 } 1034 }
1024 for (int stick = 0; stick < MAX_JOYSTICKS; stick++) 1035 for (int stick = 0; stick < MAX_JOYSTICKS; stick++)
1025 { 1036 {
1026 if (joybindings[stick]) 1037 if (joysticks[stick].buttons) {
1038 map_bindings(ports, joysticks[stick].buttons, joysticks[stick].num_buttons);
1039 }
1040 if (joysticks[stick].dpads)
1027 { 1041 {
1028 int numbuttons = render_joystick_num_buttons(stick); 1042 for (uint32_t i = 0; i < joysticks[stick].num_dpads; i++) {
1029 map_bindings(ports, joybindings[stick], render_joystick_num_buttons(stick)); 1043 map_bindings(ports, joysticks[stick].dpads[i].bindings, 4);
1030 } 1044 }
1031 if (joydpads[stick])
1032 {
1033 map_bindings(ports, joydpads[stick]->bindings, 4);
1034 } 1045 }
1035 } 1046 }
1036 for (int mouse = 0; mouse < MAX_MICE; mouse++) 1047 for (int mouse = 0; mouse < MAX_MICE; mouse++)
1037 { 1048 {
1038 if (mice[mouse].bind_type >= BIND_MOUSE1 && mice[mouse].bind_type <= BIND_MOUSE8) { 1049 if (mice[mouse].bind_type >= BIND_MOUSE1 && mice[mouse].bind_type <= BIND_MOUSE8) {