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