Lua: Fix type confusion between signed and unsigned
[lsnes.git] / src / core / controller.cpp
blob15e61799200af4b5ff40dcdfdedf8adbc1396bab
1 #include "lsnes.hpp"
3 #include "cmdhelp/button.hpp"
4 #include "cmdhelp/macro.hpp"
5 #include "cmdhelp/buttonmode.hpp"
6 #include "core/command.hpp"
7 #include "core/controller.hpp"
8 #include "core/dispatch.hpp"
9 #include "core/framebuffer.hpp"
10 #include "core/instance.hpp"
11 #include "core/keymapper.hpp"
12 #include "core/mainloop.hpp"
13 #include "core/messages.hpp"
14 #include "core/moviedata.hpp"
15 #include "core/project.hpp"
16 #include "interface/romtype.hpp"
17 #include "library/string.hpp"
18 #include "lua/lua.hpp"
20 #include <map>
21 #include <sstream>
22 #include <string>
24 namespace
26 unsigned next_id_from_map(std::map<std::string, unsigned>& map, const std::string& key, unsigned base)
28 if(!map.count(key))
29 return (map[key] = base);
30 else
31 return ++map[key];
35 button_mapping::button_mapping(controller_state& _controls, keyboard::mapper& _mapper, keyboard::keyboard& _keyboard,
36 emu_framebuffer& _fbuf, emulator_dispatch& _dispatch, lua_state& _lua2, command::group& _cmd)
37 : controls(_controls), mapper(_mapper), keyboard(_keyboard), fbuf(_fbuf), edispatch(_dispatch),
38 lua2(_lua2), cmd(_cmd),
39 button_p(cmd, CBUTTON::p, [this](const std::string& a) { this->do_action(a, 1, 0); }),
40 button_r(cmd, CBUTTON::r, [this](const std::string& a) { this->do_action(a, 0, 0); }),
41 button_h(cmd, CBUTTON::h, [this](const std::string& a) { this->do_action(a, 1, 1); }),
42 button_t(cmd, CBUTTON::t, [this](const std::string& a) { this->do_action(a, 1, 2); }),
43 button_d(cmd, CBUTTON::d, [this](const std::string& a) { this->do_action(a, 0, 3); }),
44 button_ap(cmd, CBUTTON::ap, [this](const std::string& a) { this->do_autofire_action(a, 1); }),
45 button_ar(cmd, CBUTTON::ar, [this](const std::string& a) { this->do_autofire_action(a, 0); }),
46 button_at(cmd, CBUTTON::at, [this](const std::string& a) { this->do_autofire_action(a, -1); }),
47 button_a(cmd, CBUTTON::a, [this](const std::string& a) { this->do_analog_action(a); }),
48 afire_p(cmd, BMODE::afp, [this]() { this->promote_autofire = true; }),
49 afire_n(cmd, BMODE::afn, [this]() { this->promote_autofire = false; }),
50 ahold_p(cmd, BMODE::ahp, [this]() { this->promote_autohold = true; }),
51 ahold_n(cmd, BMODE::ahn, [this]() { this->promote_autohold = false; }),
52 typed_p(cmd, BMODE::atp, [this]() { this->promote_typed = true; }),
53 typed_n(cmd, BMODE::atn, [this]() { this->promote_typed = false; })
55 ncore.set(notify_new_core, [this]() { this->init(); });
58 button_mapping::~button_mapping()
60 cleanup();
63 void button_mapping::reinit()
65 init();
68 void button_mapping::reread()
70 std::map<std::string, unsigned> classnum;
71 active_buttons.clear();
72 for(unsigned i = 0;; i++) {
73 auto x = controls.lcid_to_pcid(i);
74 if(x.first < 0)
75 break;
76 const portctrl::type& pt = controls.get_blank().get_port_type(x.first);
77 const portctrl::controller& ctrl = pt.controller_info->controllers[x.second];
78 if(!classnum.count(ctrl.cclass))
79 classnum[ctrl.cclass] = 1;
80 else
81 classnum[ctrl.cclass]++;
82 for(unsigned j = 0; j < ctrl.buttons.size(); j++) {
83 std::string name = (stringfmt() << ctrl.cclass << "-" << classnum[ctrl.cclass] << "-"
84 << ctrl.buttons[j].name).str();
85 if(all_buttons.count(name)) {
86 button_mapping::active_bind a;
87 a.port = x.first;
88 a.controller = x.second;
89 a.bind = all_buttons[name];
90 active_buttons[name] = a;
93 bool multi = (ctrl.analog_actions() > 1);
94 for(unsigned j = 0; j < ctrl.analog_actions(); j++) {
95 std::string name;
96 if(multi)
97 name = (stringfmt() << "analog" << (j + 1)).str();
98 else
99 name = "analog";
100 std::string cname = (stringfmt() << ctrl.cclass << "-" << classnum[ctrl.cclass] << "-"
101 << name).str();
102 if(all_buttons.count(cname)) {
103 button_mapping::active_bind a;
104 a.port = x.first;
105 a.controller = x.second;
106 a.bind = all_buttons[cname];
107 active_buttons[cname] = a;
113 void button_mapping::load(controller_state& ctrlstate)
115 auto s = ctrlstate.enumerate_macro();
116 for(auto i : s) {
117 if(!macro_binds.count(i)) {
118 //New macro, create inverse bind.
119 macro_binds[i] = new keyboard::invbind(mapper, CMACRO::t.name + (" " + i) , "Macro‣" + i +
120 " (toggle)");
121 macro_binds2[i] = new keyboard::invbind(mapper, CMACRO::p.name + (" " + i) , "Macro‣" +
122 i + " (hold)");
125 for(auto i : macro_binds) {
126 if(!s.count(i.first)) {
127 //Removed macro, delete inverse bind.
128 delete macro_binds[i.first];
129 delete macro_binds2[i.first];
130 macro_binds.erase(i.first);
131 macro_binds2.erase(i.first);
136 void button_mapping::load(controller_state& ctrlstate, project_info& pinfo)
138 for(auto i : pinfo.macros)
139 try {
140 ctrlstate.set_macro(i.first, portctrl::macro(i.second));
141 } catch(std::exception& e) {
142 messages << "Unable to load macro " << i.first << ": " << e.what() << std::endl;
144 for(auto i : ctrlstate.enumerate_macro())
145 if(!pinfo.macros.count(i))
146 ctrlstate.erase_macro(i);
147 load(ctrlstate);
150 void button_mapping::cleanup()
152 for(auto i : added_keys)
153 delete i.second;
154 for(auto i : macro_binds)
155 delete i.second;
156 for(auto i : macro_binds2)
157 delete i.second;
158 added_keys.clear();
159 macro_binds.clear();
160 macro_binds2.clear();
163 std::pair<int, int> button_mapping::byname(const std::string& name)
165 for(auto i : active_buttons) {
166 std::string _name = (stringfmt() << i.second.bind.cclass << "-" << i.second.bind.number).str();
167 if(name != _name)
168 continue;
169 return std::make_pair(i.second.port, i.second.controller);
171 return std::make_pair(-1, -1);
174 void button_mapping::promote_key(keyboard::ctrlrkey& k)
176 std::string name = k.get_command();
177 if(added_keys.count(name)) {
178 //Already exists.
179 delete &k;
180 return;
182 added_keys[name] = &k;
183 if(!button_keys.count(name))
184 return;
185 k.append(button_keys[name]);
186 messages << button_keys[name] << " bound (button) to " << name << std::endl;
187 button_keys.erase(name);
190 void button_mapping::add_button(const std::string& name, const button_mapping::controller_bind& binding)
192 keyboard::ctrlrkey* k;
193 if(binding.mode == 0) {
194 k = new keyboard::ctrlrkey(mapper, (stringfmt() << CBUTTON::p.name << " "
195 << name).str(), (stringfmt() << "Controller‣" << binding.cclass << "‣#"
196 << binding.number << "‣" << binding.name).str());
197 promote_key(*k);
198 k = new keyboard::ctrlrkey(mapper, (stringfmt() << CBUTTON::h.name << " "
199 << name).str(), (stringfmt() << "Controller‣" << binding.cclass << "‣#"
200 << binding.number << "‣" << binding.name << "‣hold").str());
201 promote_key(*k);
202 k = new keyboard::ctrlrkey(mapper, (stringfmt() << CBUTTON::t.name << " "
203 << name).str(), (stringfmt() << "Controller‣" << binding.cclass << "‣#"
204 << binding.number << "‣" << binding.name << "‣type").str());
205 promote_key(*k);
206 k = new keyboard::ctrlrkey(mapper, (stringfmt() << CBUTTON::ap.name << " "
207 << name).str(), (stringfmt() << "Controller‣" << binding.cclass << "‣#"
208 << binding.number << "‣" << binding.name << "‣autofire").str());
209 promote_key(*k);
210 k = new keyboard::ctrlrkey(mapper, (stringfmt() << CBUTTON::at.name << " "
211 << name).str(), (stringfmt() << "Controller‣" << binding.cclass << "‣#"
212 << binding.number << "‣" << binding.name << "‣autofire toggle").str());
213 promote_key(*k);
214 } else if(binding.mode == 1) {
215 k = new keyboard::ctrlrkey(mapper, (stringfmt() << CBUTTON::d.name << " "
216 << name).str(), (stringfmt() << "Controller‣" << binding.cclass << "‣#"
217 << binding.number << "‣" << binding.name).str());
218 promote_key(*k);
219 } else if(binding.mode == 2) {
220 k = new keyboard::ctrlrkey(mapper, (stringfmt() << CBUTTON::a.name << " "
221 << name).str(), (stringfmt() << "Controller‣" << binding.cclass << "‣#"
222 << binding.number << "‣" << binding.name << " (axis)").str(), true);
223 promote_key(*k);
227 //Take specified controller info and process it as specified controller of its class.
228 void button_mapping::process_controller(portctrl::controller& controller, unsigned number)
230 unsigned analog_num = 1;
231 bool multi_analog = (controller.analog_actions() > 1);
232 //This controller might be processed already, but perhaps only partially.
233 for(unsigned i = 0; i < controller.buttons.size(); i++) {
234 if(controller.buttons[i].shadow)
235 continue;
236 if(controller.buttons[i].type != portctrl::button::TYPE_BUTTON)
237 continue;
238 std::string name = (stringfmt() << controller.cclass << "-" << number << "-"
239 << controller.buttons[i].name).str();
240 button_mapping::controller_bind b;
241 b.cclass = controller.cclass;
242 b.number = number;
243 b.name = controller.buttons[i].name;
244 b.mode = 0;
245 b.xrel = b.yrel = false;
246 b.control1 = i;
247 b.control2 = std::numeric_limits<unsigned>::max();
248 if(!all_buttons.count(name)) {
249 all_buttons[name] = b;
250 add_button(name, b);
253 for(unsigned i = 0; i < controller.buttons.size(); i++) {
254 if(controller.buttons[i].shadow)
255 continue;
256 if(!controller.buttons[i].is_analog())
257 continue;
258 std::string name = (stringfmt() << controller.cclass << "-" << number << "-"
259 << controller.buttons[i].name).str();
260 button_mapping::controller_bind b;
261 b.cclass = controller.cclass;
262 b.number = number;
263 b.name = controller.buttons[i].name;
264 b.rmin = controller.buttons[i].rmin;
265 b.rmax = controller.buttons[i].rmax;
266 b.centered = controller.buttons[i].centers;
267 b.mode = 2;
268 b.xrel = b.yrel = false;
269 b.control1 = i;
270 b.control2 = std::numeric_limits<unsigned>::max();
271 if(!all_buttons.count(name)) {
272 all_buttons[name] = b;
273 add_button(name, b);
276 for(unsigned i = 0; i < controller.analog_actions(); i++) {
277 auto g = controller.analog_action(i);
278 auto raxis = portctrl::button::TYPE_RAXIS;
279 std::string name;
280 button_mapping::controller_bind b;
281 if(multi_analog)
282 b.name = (stringfmt() << "analog" << analog_num).str();
283 else
284 b.name = (stringfmt() << "analog").str();
285 name = (stringfmt() << controller.cclass << "-" << number << "-" << b.name).str();
286 analog_num++;
287 b.cclass = controller.cclass;
288 b.number = number;
289 b.mode = 1;
290 b.xrel = (g.first < controller.buttons.size()) &&
291 (controller.buttons[g.first].type == raxis);
292 b.yrel = (g.second < controller.buttons.size()) &&
293 (controller.buttons[g.second].type == raxis);
294 b.control1 = g.first;
295 b.control2 = g.second;
296 if(!all_buttons.count(name))
297 add_button(name, b);
298 if(!all_buttons.count(name) ||
299 ((all_buttons[name].control2 == std::numeric_limits<unsigned>::max()) &&
300 (b.control2 < std::numeric_limits<unsigned>::max()))) {
301 all_buttons[name] = b;
306 //The rules for class number allocations are:
307 //- Different cores allocate numbers independently.
308 //- Within the same core, the allocations for higher port start after the previous port ends.
309 void button_mapping::process_controller(std::map<std::string, unsigned>& allocated,
310 std::map<controller_triple, unsigned>& assigned, portctrl::controller& controller, unsigned port,
311 unsigned number_in_port)
313 controller_triple key;
314 key.cclass = controller.cclass;
315 key.port = port;
316 key.controller = number_in_port;
317 unsigned n;
318 if(!assigned.count(key))
319 assigned[key] = next_id_from_map(allocated, controller.cclass, 1);
320 n = assigned[key];
321 process_controller(controller, n);
324 void button_mapping::process_port(std::map<std::string, unsigned>& allocated,
325 std::map<controller_triple, unsigned>& assigned, unsigned port, portctrl::type& ptype)
327 //What makes this nasty: Separate ports are always processed, but the same controllers can come
328 //multiple times, including with partial reprocessing.
329 std::map<std::string, unsigned> counts;
330 for(unsigned i = 0; i < ptype.controller_info->controllers.size(); i++) {
331 //No, n might not equal i + 1, since some ports have heterogenous controllers (e.g.
332 //gameboy-gambatte system port).
333 unsigned n = next_id_from_map(counts, ptype.controller_info->controllers[i].cclass, 1);
334 process_controller(allocated, assigned, ptype.controller_info->controllers[i], port, n);
338 void button_mapping::init()
340 std::vector<portctrl::type*> ptypes;
341 for(auto k : core_core::all_cores()) {
342 if(cores_done.count(k))
343 continue;
344 std::map<std::string, unsigned> allocated;
345 std::map<button_mapping::controller_triple, unsigned> assigned;
346 auto ptypes = k->get_port_types();
347 for(unsigned i = 0; i < ptypes.size(); i++) {
348 bool any = false;
349 for(unsigned j = 0; j < ptypes.size(); j++) {
350 if(!ptypes[j]->legal(i))
351 continue;
352 any = true;
353 process_port(allocated, assigned, i, *ptypes[j]);
355 if(!any)
356 break;
358 cores_done.insert(k);
362 //Check that button is active.
363 bool button_mapping::check_button_active(const std::string& name)
365 if(active_buttons.count(name))
366 return true;
367 //This isn't active. check if there are any other active buttons on the thingy and don't complain
368 //if there are.
369 bool complain = true;
370 auto ckey = keyboard.get_current_key();
371 if(ckey) {
372 auto cb = mapper.get_controllerkeys_kbdkey(ckey);
373 for(auto i : cb) {
374 regex_results r = regex("[^ \t]+[ \t]+([^ \t]+)([ \t]+.*)?", i->get_command());
375 if(!r)
376 continue;
377 if(active_buttons.count(r[1]))
378 complain = false;
381 if(complain)
382 messages << "No such button " << name << std::endl;
383 return false;
386 //Do button action.
387 void button_mapping::do_button_action(const std::string& name, short newstate, int mode)
389 if(!all_buttons.count(name)) {
390 messages << "No such button " << name << std::endl;
391 return;
393 if(!check_button_active(name))
394 return;
395 auto x = active_buttons[name];
396 if(x.bind.mode != 0)
397 return;
398 if(mode == 0 && newstate == 1 && promote_autofire) {
399 this->do_autofire_action(name, -1);
401 if(mode == 1 || (mode == 0 && promote_autohold && newstate == 1)) {
402 //Autohold.
403 int16_t nstate = controls.autohold2(x.port, x.controller, x.bind.control1) ^ newstate;
404 if(lua2.callback_do_button(x.port, x.controller, x.bind.control1, nstate ? "hold" : "unhold"))
405 return;
406 controls.autohold2(x.port, x.controller, x.bind.control1, nstate);
407 edispatch.autohold_update(x.port, x.controller, x.bind.control1, nstate);
408 if(nstate)
409 messages << "Holding " << name << std::endl;
410 else
411 messages << "Not holding " << name << std::endl;
413 if(mode == 2 || (mode == 0 && promote_typed && newstate == 1)) {
414 //Framehold.
415 bool nstate = controls.framehold2(x.port, x.controller, x.bind.control1) ^ newstate;
416 if(lua2.callback_do_button(x.port, x.controller, x.bind.control1, nstate ? "type" : "untype"))
417 return;
418 controls.framehold2(x.port, x.controller, x.bind.control1, nstate);
419 if(nstate)
420 messages << "Holding " << name << " for the next frame" << std::endl;
421 else
422 messages << "Not holding " << name << " for the next frame" << std::endl;
424 if(mode == 0 && !promote_autohold && !promote_autofire && !promote_typed) {
425 if(lua2.callback_do_button(x.port, x.controller, x.bind.control1, newstate ? "press" :
426 "release"))
427 return;
428 controls.button2(x.port, x.controller, x.bind.control1, newstate);
432 void button_mapping::send_analog(const std::string& name, int32_t x, int32_t y)
434 if(!all_buttons.count(name)) {
435 messages << "No such action " << name << std::endl;
436 return;
438 if(!check_button_active(name))
439 return;
440 auto z = active_buttons[name];
441 if(z.bind.mode != 1) {
442 std::cerr << name << " is not a axis." << std::endl;
443 return;
445 if(lua2.callback_do_button(z.port, z.controller, z.bind.control1, "analog"))
446 return;
447 if(lua2.callback_do_button(z.port, z.controller, z.bind.control2, "analog"))
448 return;
449 auto g2 = fbuf.get_framebuffer_size();
450 x = z.bind.xrel ? (x - g2.first / 2) : (x / 2);
451 y = z.bind.yrel ? (y - g2.second / 2) : (y / 2);
452 if(z.bind.control1 < std::numeric_limits<unsigned>::max())
453 controls.analog(z.port, z.controller, z.bind.control1, x);
454 if(z.bind.control2 < std::numeric_limits<unsigned>::max())
455 controls.analog(z.port, z.controller, z.bind.control2, y);
458 void button_mapping::do_action(const std::string& name, short state, int mode)
460 if(mode < 3)
461 do_button_action(name, state, mode);
462 else if(mode == 3) {
463 keyboard::key* mouse_x = keyboard.try_lookup_key("mouse_x");
464 keyboard::key* mouse_y = keyboard.try_lookup_key("mouse_y");
465 if(!mouse_x || !mouse_y) {
466 messages << "Controller analog function not available without mouse" << std::endl;
467 return;
469 send_analog(name, mouse_x->get_state(), mouse_y->get_state());
473 void button_mapping::do_analog_action(const std::string& a)
475 int _value;
476 regex_results r = regex("([^ \t]+)[ \t]+(-?[0-9]+)[ \t]*", a, "Invalid analog action");
477 std::string name = r[1];
478 int value = parse_value<int>(r[2]);
479 if(!all_buttons.count(name)) {
480 messages << "No such button " << name << std::endl;
481 return;
483 if(!check_button_active(name))
484 return;
485 auto x = active_buttons[name];
486 if(x.bind.mode != 2)
487 return;
488 if(lua2.callback_do_button(x.port, x.controller, x.bind.control1, "analog"))
489 return;
490 int rmin = x.bind.rmin;
491 int rmax = x.bind.rmax;
492 //FIXME: Do something with this?
493 //bool centered = x.bind.centered;
494 int64_t pvalue = value + 32768;
495 _value = pvalue * (rmax - rmin) / 65535 + rmin;
496 controls.analog(x.port, x.controller, x.bind.control1, _value);
499 void button_mapping::do_autofire_action(const std::string& a, int mode)
501 regex_results r = regex("([^ \t]+)(([ \t]+([0-9]+))?[ \t]+([0-9]+))?[ \t]*", a,
502 "Invalid autofire parameters");
503 std::string name = r[1];
504 std::string _duty = r[4];
505 std::string _cyclelen = r[5];
506 if(_duty == "") _duty = "1";
507 if(_cyclelen == "") _cyclelen = "2";
508 uint32_t duty = parse_value<uint32_t>(_duty);
509 uint32_t cyclelen = parse_value<uint32_t>(_cyclelen);
510 if(duty >= cyclelen)
511 throw std::runtime_error("Invalid autofire parameters");
512 if(!all_buttons.count(name)) {
513 messages << "No such button " << name << std::endl;
514 return;
516 if(!check_button_active(name))
517 return;
518 auto z = active_buttons[name];
519 if(z.bind.mode != 0) {
520 std::cerr << name << " is not a button." << std::endl;
521 return;
523 auto afire = controls.autofire2(z.port, z.controller, z.bind.control1);
524 if(mode == 1 || (mode == -1 && afire.first == 0)) {
525 //Turn on.
526 if(lua2.callback_do_button(z.port, z.controller, z.bind.control1, (stringfmt() << "autofire "
527 << duty << " " << cyclelen).str().c_str()))
528 return;
529 controls.autofire2(z.port, z.controller, z.bind.control1, duty, cyclelen);
530 edispatch.autofire_update(z.port, z.controller, z.bind.control1, duty, cyclelen);
531 messages << "Autofiring " << name << " (duty " << duty << "/" << cyclelen << ")" << std::endl;
532 } else if(mode == 0 || (mode == -1 && afire.first != 0)) {
533 //Turn off.
534 if(lua2.callback_do_button(z.port, z.controller, z.bind.control1, "autofire"))
535 return;
536 controls.autofire2(z.port, z.controller, z.bind.control1, 0, 1);
537 edispatch.autofire_update(z.port, z.controller, z.bind.control1, 0, 1);
538 messages << "Not autofiring " << name << std::endl;