JSON-based controller descriptions
[lsnes.git] / src / core / controller.cpp
blob4e318138175dd657d9b9bfc494a0294909111fa3
1 #include "lsnes.hpp"
3 #include "core/command.hpp"
4 #include "core/controller.hpp"
5 #include "core/dispatch.hpp"
6 #include "core/framebuffer.hpp"
7 #include "core/mainloop.hpp"
8 #include "core/misc.hpp"
9 #include "core/moviedata.hpp"
10 #include "core/window.hpp"
11 #include "interface/romtype.hpp"
12 #include "library/string.hpp"
14 #include <map>
15 #include <sstream>
16 #include <string>
18 namespace
20 struct controller_bind
22 std::string cclass;
23 unsigned number;
24 std::string name;
25 int mode; //0 => Button, 1 => Axis pair, 2 => Single axis.
26 bool xrel;
27 bool yrel;
28 unsigned control1;
29 unsigned control2; //Axis only, UINT_MAX if not valid.
30 int16_t rmin;
31 int16_t rmax;
32 bool centered;
35 struct active_bind
37 unsigned port;
38 unsigned controller;
39 struct controller_bind bind;
42 struct controller_triple
44 std::string cclass;
45 unsigned port;
46 unsigned controller;
47 bool operator<(const struct controller_triple& t) const throw()
49 if(cclass < t.cclass) return true;
50 if(cclass > t.cclass) return false;
51 if(port < t.port) return true;
52 if(port > t.port) return false;
53 if(controller < t.controller) return true;
54 if(controller > t.controller) return false;
55 return false;
57 bool operator==(const struct controller_triple& t) const throw()
59 return (cclass == t.cclass && port == t.port && controller == t.controller);
63 std::map<std::string, inverse_bind*> macro_binds;
64 std::map<std::string, inverse_bind*> macro_binds2;
65 std::map<std::string, controller_bind> all_buttons;
66 std::map<std::string, active_bind> active_buttons;
67 std::map<std::string, controller_key*> added_keys;
69 //Promote stored key to active key.
70 void promote_key(controller_key& k)
72 std::string name = k.get_command();
73 if(added_keys.count(name)) {
74 //Already exists.
75 delete &k;
76 return;
78 added_keys[name] = &k;
79 if(!button_keys.count(name))
80 return;
81 k.append(button_keys[name]);
82 messages << button_keys[name] << " bound (button) to " << name << std::endl;
83 button_keys.erase(name);
86 //Allocate controller keys for specified button.
87 void add_button(const std::string& name, const controller_bind& binding)
89 controller_key* k;
90 if(binding.mode == 0) {
91 k = new controller_key(lsnes_mapper, (stringfmt() << "+controller " << name).str(),
92 (stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << "‣"
93 << binding.name).str());
94 promote_key(*k);
95 k = new controller_key(lsnes_mapper, (stringfmt() << "hold-controller " << name).str(),
96 (stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << "‣"
97 << binding.name << "‣hold").str());
98 promote_key(*k);
99 k = new controller_key(lsnes_mapper, (stringfmt() << "type-controller " << name).str(),
100 (stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << "‣"
101 << binding.name << "‣type").str());
102 promote_key(*k);
103 k = new controller_key(lsnes_mapper, (stringfmt() << "+autofire-controller " << name).str(),
104 (stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << "‣"
105 << binding.name << "‣autofire").str());
106 promote_key(*k);
107 k = new controller_key(lsnes_mapper, (stringfmt() << "autofire-controller " << name).str(),
108 (stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << "‣"
109 << binding.name << "‣autofire toggle").str());
110 promote_key(*k);
111 } else if(binding.mode == 1) {
112 k = new controller_key(lsnes_mapper, (stringfmt() << "designate-position " << name).str(),
113 (stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << "‣"
114 << binding.name).str());
115 promote_key(*k);
116 } else if(binding.mode == 2) {
117 k = new controller_key(lsnes_mapper, (stringfmt() << "controller-analog " << name).str(),
118 (stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << "‣"
119 << binding.name << " (axis)").str(), true);
120 promote_key(*k);
124 //Take specified controller info and process it as specified controller of its class.
125 void process_controller(port_controller& controller, unsigned number)
127 unsigned analog_num = 1;
128 bool multi_analog = (controller.analog_actions() > 1);
129 //This controller might be processed already, but perhaps only partially.
130 for(unsigned i = 0; i < controller.buttons.size(); i++) {
131 if(controller.buttons[i].shadow)
132 continue;
133 if(controller.buttons[i].type != port_controller_button::TYPE_BUTTON)
134 continue;
135 std::string name = (stringfmt() << controller.cclass << "-" << number << "-"
136 << controller.buttons[i].name).str();
137 controller_bind b;
138 b.cclass = controller.cclass;
139 b.number = number;
140 b.name = controller.buttons[i].name;
141 b.mode = 0;
142 b.xrel = b.yrel = false;
143 b.control1 = i;
144 b.control2 = std::numeric_limits<unsigned>::max();
145 if(!all_buttons.count(name)) {
146 all_buttons[name] = b;
147 add_button(name, b);
150 for(unsigned i = 0; i < controller.buttons.size(); i++) {
151 if(controller.buttons[i].shadow)
152 continue;
153 if(!controller.buttons[i].is_analog())
154 continue;
155 std::string name = (stringfmt() << controller.cclass << "-" << number << "-"
156 << controller.buttons[i].name).str();
157 controller_bind b;
158 b.cclass = controller.cclass;
159 b.number = number;
160 b.name = controller.buttons[i].name;
161 b.rmin = controller.buttons[i].rmin;
162 b.rmax = controller.buttons[i].rmax;
163 b.centered = controller.buttons[i].centers;
164 b.mode = 2;
165 b.xrel = b.yrel = false;
166 b.control1 = i;
167 b.control2 = std::numeric_limits<unsigned>::max();
168 if(!all_buttons.count(name)) {
169 all_buttons[name] = b;
170 add_button(name, b);
173 for(unsigned i = 0; i < controller.analog_actions(); i++) {
174 auto g = controller.analog_action(i);
175 auto raxis = port_controller_button::TYPE_RAXIS;
176 std::string name;
177 controller_bind b;
178 if(multi_analog)
179 b.name = (stringfmt() << "analog" << analog_num).str();
180 else
181 b.name = (stringfmt() << "analog").str();
182 name = (stringfmt() << controller.cclass << "-" << number << "-" << b.name).str();
183 analog_num++;
184 b.cclass = controller.cclass;
185 b.number = number;
186 b.mode = 1;
187 b.xrel = (g.first < controller.buttons.size()) &&
188 (controller.buttons[g.first].type == raxis);
189 b.yrel = (g.second < controller.buttons.size()) &&
190 (controller.buttons[g.second].type == raxis);
191 b.control1 = g.first;
192 b.control2 = g.second;
193 if(!all_buttons.count(name))
194 add_button(name, b);
195 if(!all_buttons.count(name) ||
196 ((all_buttons[name].control2 == std::numeric_limits<unsigned>::max()) &&
197 (b.control2 < std::numeric_limits<unsigned>::max()))) {
198 all_buttons[name] = b;
203 unsigned next_id_from_map(std::map<std::string, unsigned>& map, const std::string& key, unsigned base)
205 if(!map.count(key))
206 return (map[key] = base);
207 else
208 return ++map[key];
211 //The rules for class number allocations are:
212 //- Different cores allocate numbers independently.
213 //- Within the same core, the allocations for higher port start after the previous port ends.
216 void process_controller(std::map<std::string, unsigned>& allocated,
217 std::map<controller_triple, unsigned>& assigned, port_controller& controller, unsigned port,
218 unsigned number_in_port)
220 controller_triple key;
221 key.cclass = controller.cclass;
222 key.port = port;
223 key.controller = number_in_port;
224 unsigned n;
225 if(!assigned.count(key))
226 assigned[key] = next_id_from_map(allocated, controller.cclass, 1);
227 n = assigned[key];
228 process_controller(controller, n);
231 void process_port(std::map<std::string, unsigned>& allocated,
232 std::map<controller_triple, unsigned>& assigned, unsigned port, port_type& ptype)
234 //What makes this nasty: Separate ports are always processed, but the same controllers can come
235 //multiple times, including with partial reprocessing.
236 std::map<std::string, unsigned> counts;
237 for(unsigned i = 0; i < ptype.controller_info->controllers.size(); i++) {
238 //No, n might not equal i + 1, since some ports have heterogenous controllers (e.g.
239 //gameboy-gambatte system port).
240 unsigned n = next_id_from_map(counts, ptype.controller_info->controllers[i].cclass, 1);
241 process_controller(allocated, assigned, ptype.controller_info->controllers[i], port, n);
245 void init_buttonmap()
247 static std::set<core_core*> done;
248 std::vector<port_type*> ptypes;
249 for(auto k : core_core::all_cores()) {
250 if(done.count(k))
251 continue;
252 std::map<std::string, unsigned> allocated;
253 std::map<controller_triple, unsigned> assigned;
254 auto ptypes = k->get_port_types();
255 for(unsigned i = 0; i < ptypes.size(); i++) {
256 bool any = false;
257 for(unsigned j = 0; j < ptypes.size(); j++) {
258 if(!ptypes[j]->legal(i))
259 continue;
260 any = true;
261 process_port(allocated, assigned, i, *ptypes[j]);
263 if(!any)
264 break;
266 done.insert(k);
270 //Check that button is active.
271 bool check_button_active(const std::string& name)
273 if(active_buttons.count(name))
274 return true;
275 //This isn't active. check if there are any other active buttons on the thingy and don't complain
276 //if there are.
277 bool complain = true;
278 auto ckey = lsnes_kbd.get_current_key();
279 if(ckey) {
280 auto cb = lsnes_mapper.get_controllerkeys_kbdkey(ckey);
281 for(auto i : cb) {
282 regex_results r = regex("[^ \t]+[ \t]+([^ \t]+)([ \t]+.*)?", i->get_command());
283 if(!r)
284 continue;
285 if(active_buttons.count(r[1]))
286 complain = false;
289 if(complain)
290 messages << "No such button " << name << std::endl;
291 return false;
294 //Do button action.
295 void do_button_action(const std::string& name, short newstate, int mode)
297 if(!all_buttons.count(name)) {
298 messages << "No such button " << name << std::endl;
299 return;
301 if(!check_button_active(name))
302 return;
303 auto x = active_buttons[name];
304 if(x.bind.mode != 0)
305 return;
306 if(mode == 1) {
307 //Autohold.
308 int16_t nstate = controls.autohold2(x.port, x.controller, x.bind.control1) ^ newstate;
309 if(lua_callback_do_button(x.port, x.controller, x.bind.control1, nstate ? "hold" : "unhold"))
310 return;
311 controls.autohold2(x.port, x.controller, x.bind.control1, nstate);
312 notify_autohold_update(x.port, x.controller, x.bind.control1, nstate);
313 } else if(mode == 2) {
314 //Framehold.
315 bool nstate = controls.framehold2(x.port, x.controller, x.bind.control1) ^ newstate;
316 if(lua_callback_do_button(x.port, x.controller, x.bind.control1, nstate ? "type" : "untype"))
317 return;
318 controls.framehold2(x.port, x.controller, x.bind.control1, nstate);
319 if(nstate)
320 messages << "Holding " << name << " for the next frame" << std::endl;
321 else
322 messages << "Not holding " << name << " for the next frame" << std::endl;
323 } else {
324 if(lua_callback_do_button(x.port, x.controller, x.bind.control1, newstate ? "press" :
325 "release"))
326 return;
327 controls.button2(x.port, x.controller, x.bind.control1, newstate);
331 void send_analog(const std::string& name, int32_t x, int32_t y)
333 if(!all_buttons.count(name)) {
334 messages << "No such action " << name << std::endl;
335 return;
337 if(!check_button_active(name))
338 return;
339 auto z = active_buttons[name];
340 if(z.bind.mode != 1) {
341 std::cerr << name << " is not a axis." << std::endl;
342 return;
344 if(lua_callback_do_button(z.port, z.controller, z.bind.control1, "analog"))
345 return;
346 if(lua_callback_do_button(z.port, z.controller, z.bind.control2, "analog"))
347 return;
348 auto g2 = get_framebuffer_size();
349 x = z.bind.xrel ? (x - g2.first / 2) : (x / 2);
350 y = z.bind.yrel ? (y - g2.second / 2) : (y / 2);
351 if(z.bind.control1 < std::numeric_limits<unsigned>::max())
352 controls.analog(z.port, z.controller, z.bind.control1, x);
353 if(z.bind.control2 < std::numeric_limits<unsigned>::max())
354 controls.analog(z.port, z.controller, z.bind.control2, y);
357 void do_action(const std::string& name, short state, int mode)
359 if(mode < 3)
360 do_button_action(name, state, mode);
361 else if(mode == 3) {
362 keyboard_key* mouse_x = lsnes_kbd.try_lookup_key("mouse_x");
363 keyboard_key* mouse_y = lsnes_kbd.try_lookup_key("mouse_y");
364 if(!mouse_x || !mouse_y) {
365 messages << "Controller analog function not available without mouse" << std::endl;
366 return;
368 send_analog(name, mouse_x->get_state(), mouse_y->get_state());
372 void do_analog_action(const std::string& a)
374 int _value;
375 regex_results r = regex("([^ \t]+)[ \t]+(-?[0-9]+)[ \t]*", a, "Invalid analog action");
376 std::string name = r[1];
377 int value = parse_value<int>(r[2]);
378 if(!all_buttons.count(name)) {
379 messages << "No such button " << name << std::endl;
380 return;
382 if(!check_button_active(name))
383 return;
384 auto x = active_buttons[name];
385 if(x.bind.mode != 2)
386 return;
387 if(lua_callback_do_button(x.port, x.controller, x.bind.control1, "analog"))
388 return;
389 int rmin = x.bind.rmin;
390 int rmax = x.bind.rmax;
391 bool centered = x.bind.centered;
392 int64_t pvalue = value + 32768;
393 _value = pvalue * (rmax - rmin) / 65535 + rmin;
394 controls.analog(x.port, x.controller, x.bind.control1, _value);
397 void do_autofire_action(const std::string& a, int mode)
399 regex_results r = regex("([^ \t]+)(([ \t]+([0-9]+))?[ \t]+([0-9]+))?[ \t]*", a,
400 "Invalid autofire parameters");
401 std::string name = r[1];
402 std::string _duty = r[4];
403 std::string _cyclelen = r[5];
404 if(_duty == "") _duty = "1";
405 if(_cyclelen == "") _cyclelen = "2";
406 uint32_t duty = parse_value<uint32_t>(_duty);
407 uint32_t cyclelen = parse_value<uint32_t>(_cyclelen);
408 if(duty >= cyclelen)
409 throw std::runtime_error("Invalid autofire parameters");
410 if(!all_buttons.count(name)) {
411 messages << "No such button " << name << std::endl;
412 return;
414 if(!check_button_active(name))
415 return;
416 auto z = active_buttons[name];
417 if(z.bind.mode != 0) {
418 std::cerr << name << " is not a button." << std::endl;
419 return;
421 auto afire = controls.autofire2(z.port, z.controller, z.bind.control1);
422 if(mode == 1 || (mode == -1 && afire.first == 0)) {
423 //Turn on.
424 if(lua_callback_do_button(z.port, z.controller, z.bind.control1, (stringfmt() << "autofire "
425 << duty << " " << cyclelen).str().c_str()))
426 return;
427 controls.autofire2(z.port, z.controller, z.bind.control1, duty, cyclelen);
428 notify_autofire_update(z.port, z.controller, z.bind.control1, duty,
429 cyclelen);
430 } else if(mode == 0 || (mode == -1 && afire.first != 0)) {
431 //Turn off.
432 if(lua_callback_do_button(z.port, z.controller, z.bind.control1, "autofire"))
433 return;
434 controls.autofire2(z.port, z.controller, z.bind.control1, 0, 1);
435 notify_autofire_update(z.port, z.controller, z.bind.control1, 0, 1);
439 function_ptr_command<const std::string&> button_p(lsnes_cmd, "+controller", "Press a button",
440 "Syntax: +controller<button>...\nPress a button\n",
441 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
442 do_action(a, 1, 0);
445 function_ptr_command<const std::string&> button_r(lsnes_cmd, "-controller", "Release a button",
446 "Syntax: -controller<button>...\nRelease a button\n",
447 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
448 do_action(a, 0, 0);
451 function_ptr_command<const std::string&> button_h(lsnes_cmd, "hold-controller", "Autohold a button",
452 "Syntax: hold-controller<button>...\nAutohold a button\n",
453 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
454 do_action(a, 1, 1);
457 function_ptr_command<const std::string&> button_t(lsnes_cmd, "type-controller", "Type a button",
458 "Syntax: type-controller<button>...\nType a button\n",
459 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
460 do_action(a, 1, 2);
463 function_ptr_command<const std::string&> button_d(lsnes_cmd, "designate-position", "Set postion",
464 "Syntax: designate-position <button>...\nDesignate position for an axis\n",
465 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
466 do_action(a, 0, 3);
469 function_ptr_command<const std::string&> button_ap(lsnes_cmd, "+autofire-controller", "Start autofire",
470 "Syntax: +autofire-controller<button> [[<duty> ]<cyclelen>]...\nAutofire a button\n",
471 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
472 do_autofire_action(a, 1);
475 function_ptr_command<const std::string&> button_an(lsnes_cmd, "-autofire-controller", "End autofire",
476 "Syntax: -autofire-controller<button> [[<duty> ]<cyclelen>]...\nEnd Autofire on a button\n",
477 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
478 do_autofire_action(a, 0);
481 function_ptr_command<const std::string&> button_at(lsnes_cmd, "autofire-controller", "Toggle autofire",
482 "Syntax: autofire-controller<button> [[<duty> ]<cyclelen>]...\nToggle Autofire on a button\n",
483 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
484 do_autofire_action(a, -1);
487 function_ptr_command<const std::string&> button_a(lsnes_cmd, "controller-analog", "Analog action",
488 "Syntax: controller-analog <button> <axis>\nAnalog action\n",
489 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
490 do_analog_action(a);
493 function_ptr_command<const std::string&> macro_t(lsnes_cmd, "macro", "Toggle a macro",
494 "Syntax: macro <macroname>\nToggle a macro.\n",
495 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
496 controls.do_macro(a, 7);
499 function_ptr_command<const std::string&> macro_e(lsnes_cmd, "+macro", "Enable a macro",
500 "Syntax: +macro <macroname>\nEnable a macro.\n",
501 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
502 controls.do_macro(a, 5);
505 function_ptr_command<const std::string&> macro_d(lsnes_cmd, "-macro", "Disable a macro",
506 "Syntax: -macro <macroname>\nDisable a macro.\n",
507 [](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
508 controls.do_macro(a, 2);
511 class new_core_snoop
513 public:
514 new_core_snoop()
516 ncore.set(notify_new_core, []() { init_buttonmap(); });
518 struct dispatch_target<> ncore;
519 } coresnoop;
522 void reinitialize_buttonmap()
524 init_buttonmap();
527 void reread_active_buttons()
529 std::map<std::string, unsigned> classnum;
530 active_buttons.clear();
531 for(unsigned i = 0;; i++) {
532 auto x = controls.lcid_to_pcid(i);
533 if(x.first < 0)
534 break;
535 const port_type& pt = controls.get_blank().get_port_type(x.first);
536 const port_controller& ctrl = pt.controller_info->controllers[x.second];
537 if(!classnum.count(ctrl.cclass))
538 classnum[ctrl.cclass] = 1;
539 else
540 classnum[ctrl.cclass]++;
541 for(unsigned j = 0; j < ctrl.buttons.size(); j++) {
542 std::string name = (stringfmt() << ctrl.cclass << "-" << classnum[ctrl.cclass] << "-"
543 << ctrl.buttons[j].name).str();
544 if(all_buttons.count(name)) {
545 active_bind a;
546 a.port = x.first;
547 a.controller = x.second;
548 a.bind = all_buttons[name];
549 active_buttons[name] = a;
552 bool multi = (ctrl.analog_actions() > 1);
553 for(unsigned j = 0; j < ctrl.analog_actions(); j++) {
554 std::string name;
555 if(multi)
556 name = (stringfmt() << "analog" << (j + 1)).str();
557 else
558 name = "analog";
559 std::string cname = (stringfmt() << ctrl.cclass << "-" << classnum[ctrl.cclass] << "-"
560 << name).str();
561 if(all_buttons.count(cname)) {
562 active_bind a;
563 a.port = x.first;
564 a.controller = x.second;
565 a.bind = all_buttons[cname];
566 active_buttons[cname] = a;
572 void load_macros(controller_state& ctrlstate)
574 auto s = ctrlstate.enumerate_macro();
575 for(auto i : s) {
576 if(!macro_binds.count(i)) {
577 //New macro, create inverse bind.
578 macro_binds[i] = new inverse_bind(lsnes_mapper, "macro " + i , "Macro‣" + i + " (toggle)");
579 macro_binds2[i] = new inverse_bind(lsnes_mapper, "+macro " + i , "Macro‣" + i + " (hold)");
582 for(auto i : macro_binds) {
583 if(!s.count(i.first)) {
584 //Removed macro, delete inverse bind.
585 delete macro_binds[i.first];
586 delete macro_binds2[i.first];
587 macro_binds.erase(i.first);
588 macro_binds2.erase(i.first);
593 void load_project_macros(controller_state& ctrlstate, project_info& pinfo)
595 for(auto i : pinfo.macros)
596 try {
597 ctrlstate.set_macro(i.first, controller_macro(i.second));
598 } catch(std::exception& e) {
599 messages << "Unable to load macro " << i.first << ": " << e.what() << std::endl;
601 for(auto i : ctrlstate.enumerate_macro())
602 if(!pinfo.macros.count(i))
603 ctrlstate.erase_macro(i);
604 load_macros(ctrlstate);
607 void cleanup_all_keys()
609 for(auto i : added_keys)
610 delete i.second;
613 std::pair<int, int> controller_by_name(const std::string& name)
615 for(auto i : active_buttons) {
616 std::string _name = (stringfmt() << i.second.bind.cclass << "-" << i.second.bind.number).str();
617 if(name != _name)
618 continue;
619 return std::make_pair(i.second.port, i.second.controller);
621 return std::make_pair(-1, -1);
624 controller_state controls;
625 std::map<std::string, std::string> button_keys;