lsnes rr2-β24
[lsnes.git] / src / lua / input.cpp
blob83b78dab46672dd9a76c97ef181526ca5f439a61
1 #include "core/keymapper.hpp"
2 #include "lua/internal.hpp"
3 #include "core/instance.hpp"
4 #include "core/moviedata.hpp"
5 #include "core/controller.hpp"
6 #include "interface/romtype.hpp"
7 #include <iostream>
9 namespace
11 int input_set(lua::state& L, unsigned port, unsigned controller, unsigned index, short value)
13 auto& core = CORE();
14 if(!core.lua2->input_controllerdata)
15 return 0;
16 core.lua2->input_controllerdata->axis3(port, controller, index, value);
17 return 0;
20 int input_get(lua::state& L, unsigned port, unsigned controller, unsigned index)
22 auto& core = CORE();
23 if(!core.lua2->input_controllerdata)
24 return 0;
25 L.pushnumber(core.lua2->input_controllerdata->axis3(port, controller, index));
26 return 1;
29 int input_controllertype(lua::state& L, unsigned port, unsigned controller)
31 auto& core = CORE();
32 auto& m = core.mlogic->get_movie();
33 portctrl::frame f = m.read_subframe(m.get_current_frame(), 0);
34 if(port >= f.get_port_count()) {
35 L.pushnil();
36 return 1;
38 const portctrl::type& p = f.get_port_type(port);
39 if(controller >= p.controller_info->controllers.size())
40 L.pushnil();
41 else
42 L.pushlstring(p.controller_info->controllers[controller].type);
43 return 1;
46 int input_seta(lua::state& L, unsigned port, unsigned controller, uint64_t base, lua::parameters& P)
48 auto& core = CORE();
49 if(!core.lua2->input_controllerdata)
50 return 0;
51 short val;
52 if(port >= core.lua2->input_controllerdata->get_port_count())
53 return 0;
54 const portctrl::type& pt = core.lua2->input_controllerdata->get_port_type(port);
55 if(controller >= pt.controller_info->controllers.size())
56 return 0;
57 for(unsigned i = 0; i < pt.controller_info->controllers[controller].buttons.size(); i++) {
58 val = (base >> i) & 1;
59 P(P.optional(val, val));
60 core.lua2->input_controllerdata->axis3(port, controller, i, val);
62 return 0;
65 int input_geta(lua::state& L, unsigned port, unsigned controller)
67 auto& core = CORE();
68 if(!core.lua2->input_controllerdata)
69 return 0;
70 if(port >= core.lua2->input_controllerdata->get_port_count())
71 return 0;
72 const portctrl::type& pt = core.lua2->input_controllerdata->get_port_type(port);
73 if(controller >= pt.controller_info->controllers.size())
74 return 0;
75 uint64_t fret = 0;
76 for(unsigned i = 0; i < pt.controller_info->controllers[controller].buttons.size(); i++)
77 if(core.lua2->input_controllerdata->axis3(port, controller, i))
78 fret |= (1ULL << i);
79 L.pushnumber(fret);
80 for(unsigned i = 0; i < pt.controller_info->controllers[controller].buttons.size(); i++)
81 L.pushnumber(core.lua2->input_controllerdata->axis3(port, controller, i));
82 return pt.controller_info->controllers[controller].buttons.size() + 1;
85 class _keyhook_listener : public keyboard::event_listener
87 void on_key_event(keyboard::modifier_set& modifiers, keyboard::key& key, keyboard::event& event)
89 auto& core = CORE();
90 core.lua2->callback_keyhook(key.get_name(), key);
92 } S_keyhook_listener;
94 const portctrl::controller_set* lookup_ps(unsigned port)
96 auto& core = CORE();
97 auto& m = core.mlogic->get_movie();
98 portctrl::frame f = m.read_subframe(m.get_current_frame(), 0);
99 if(port >= f.get_port_count())
100 return NULL; //Port does not exist.
101 const portctrl::type& p = f.get_port_type(port);
102 return p.controller_info;
105 int set(lua::state& L, lua::parameters& P)
107 auto& core = CORE();
108 unsigned controller, index, value;
110 if(!core.lua2->input_controllerdata) return 0;
112 P(controller, index, value);
114 auto _controller = core.lua2->input_controllerdata->porttypes().legacy_pcid_to_pair(controller);
115 return input_set(L, _controller.first, _controller.second, index, value);
118 int set2(lua::state& L, lua::parameters& P)
120 unsigned port, controller, index;
121 short value;
123 P(port, controller, index, value);
125 return input_set(L, port, controller, index, value);
128 int get(lua::state& L, lua::parameters& P)
130 auto& core = CORE();
131 unsigned controller, index;
133 if(!core.lua2->input_controllerdata) return 0;
135 P(controller, index);
137 auto _controller = core.lua2->input_controllerdata->porttypes().legacy_pcid_to_pair(controller);
138 return input_get(L, _controller.first, _controller.second, index);
141 int get2(lua::state& L, lua::parameters& P)
143 unsigned port, controller, index;
145 P(port, controller, index);
147 return input_get(L, port, controller, index);
150 int seta(lua::state& L, lua::parameters& P)
152 auto& core = CORE();
153 unsigned controller;
154 uint64_t base;
156 if(!core.lua2->input_controllerdata) return 0;
158 P(controller, base);
160 auto _controller = core.lua2->input_controllerdata->porttypes().legacy_pcid_to_pair(controller);
161 return input_seta(L, _controller.first, _controller.second, base, P);
164 int seta2(lua::state& L, lua::parameters& P)
166 unsigned port, controller;
167 uint64_t base;
169 P(port, controller, base);
171 return input_seta(L, port, controller, base, P);
174 int geta(lua::state& L, lua::parameters& P)
176 auto& core = CORE();
177 unsigned controller;
179 if(!core.lua2->input_controllerdata) return 0;
181 P(controller);
183 auto _controller = core.lua2->input_controllerdata->porttypes().legacy_pcid_to_pair(controller);
184 return input_geta(L, _controller.first, _controller.second);
187 int geta2(lua::state& L, lua::parameters& P)
189 unsigned port, controller;
191 P(port, controller);
193 return input_geta(L, port, controller);
196 int controllertype(lua::state& L, lua::parameters& P)
198 auto& core = CORE();
199 unsigned controller;
201 P(controller);
203 auto& m = core.mlogic->get_movie();
204 const portctrl::type_set& s = m.read_subframe(m.get_current_frame(), 0).porttypes();
205 auto _controller = s.legacy_pcid_to_pair(controller);
206 return input_controllertype(L, _controller.first, _controller.second);
209 int controllertype2(lua::state& L, lua::parameters& P)
211 unsigned port, controller;
213 P(port, controller);
215 return input_controllertype(L, port, controller);
218 int reset(lua::state& L, lua::parameters& P)
220 auto& core = CORE();
221 long cycles;
223 if(!core.lua2->input_controllerdata) return 0;
225 P(P.optional(cycles, 0));
227 if(cycles < 0)
228 return 0;
229 short lo = cycles % 10000;
230 short hi = cycles / 10000;
231 core.lua2->input_controllerdata->axis3(0, 0, 1, 1);
232 core.lua2->input_controllerdata->axis3(0, 0, 2, hi);
233 core.lua2->input_controllerdata->axis3(0, 0, 3, lo);
234 return 0;
237 int raw(lua::state& L, lua::parameters& P)
239 auto& core = CORE();
240 L.newtable();
241 for(auto i : core.keyboard->all_keys()) {
242 L.pushlstring(i->get_name());
243 push_keygroup_parameters(L, *i);
244 L.settable(-3);
246 return 1;
249 int keyhook(lua::state& L, lua::parameters& P)
251 auto& core = CORE();
252 std::string x;
253 bool state;
255 P(x, state);
257 keyboard::key* key = core.keyboard->try_lookup_key(x);
258 if(!key)
259 throw std::runtime_error("Invalid key name");
260 bool ostate = core.lua2->hooked_keys.count(x) > 0;
261 if(ostate == state)
262 return 0;
263 if(state) {
264 core.lua2->hooked_keys.insert(x);
265 key->add_listener(S_keyhook_listener, true);
266 } else {
267 core.lua2->hooked_keys.erase(x);
268 key->remove_listener(S_keyhook_listener);
270 return 0;
273 int joyget(lua::state& L, lua::parameters& P)
275 auto& core = CORE();
276 unsigned lcid;
278 P(lcid);
280 if(!core.lua2->input_controllerdata)
281 return 0;
282 auto pcid = core.controls->lcid_to_pcid(lcid - 1);
283 if(pcid.first < 0)
284 throw std::runtime_error("Invalid controller for input.joyget");
285 L.newtable();
286 const portctrl::type& pt = core.lua2->input_controllerdata->get_port_type(pcid.first);
287 const portctrl::controller& ctrl = pt.controller_info->controllers[pcid.second];
288 unsigned lcnt = ctrl.buttons.size();
289 for(unsigned i = 0; i < lcnt; i++) {
290 if(ctrl.buttons[i].type == portctrl::button::TYPE_NULL)
291 continue;
292 L.pushlstring(ctrl.buttons[i].name);
293 if(ctrl.buttons[i].is_analog())
294 L.pushnumber(core.lua2->input_controllerdata->axis3(pcid.first, pcid.second, i));
295 else if(ctrl.buttons[i].type == portctrl::button::TYPE_BUTTON)
296 L.pushboolean(core.lua2->input_controllerdata->axis3(pcid.first, pcid.second, i) !=
298 L.settable(-3);
300 return 1;
303 int joyset(lua::state& L, lua::parameters& P)
305 auto& core = CORE();
306 unsigned lcid;
307 int ltbl;
309 P(lcid, P.table(ltbl));
311 if(!core.lua2->input_controllerdata)
312 return 0;
313 auto pcid = core.controls->lcid_to_pcid(lcid - 1);
314 if(pcid.first < 0)
315 throw std::runtime_error("Invalid controller for input.joyset");
316 const portctrl::type& pt = core.lua2->input_controllerdata->get_port_type(pcid.first);
317 const portctrl::controller& ctrl = pt.controller_info->controllers[pcid.second];
318 unsigned lcnt = ctrl.buttons.size();
319 for(unsigned i = 0; i < lcnt; i++) {
320 if(ctrl.buttons[i].type == portctrl::button::TYPE_NULL)
321 continue;
322 L.pushlstring(ctrl.buttons[i].name);
323 L.gettable(ltbl);
324 int s;
325 if(ctrl.buttons[i].is_analog()) {
326 if(L.type(-1) == LUA_TNIL)
327 s = core.lua2->input_controllerdata->axis3(pcid.first, pcid.second, i);
328 else
329 s = L.tonumber(-1);
330 } else {
331 if(L.type(-1) == LUA_TNIL)
332 s = core.lua2->input_controllerdata->axis3(pcid.first, pcid.second, i);
333 else if(L.type(-1) == LUA_TSTRING)
334 s = core.lua2->input_controllerdata->axis3(pcid.first, pcid.second, i) ^ 1;
335 else
336 s = L.toboolean(-1) ? 1 : 0;
338 core.lua2->input_controllerdata->axis3(pcid.first, pcid.second, i, s);
339 L.pop(1);
341 return 0;
344 int lcid_to_pcid(lua::state& L, lua::parameters& P)
346 auto& core = CORE();
347 unsigned lcid;
349 P(lcid);
351 auto pcid = core.controls->lcid_to_pcid(lcid - 1);
352 if(pcid.first < 0)
353 return 0;
354 int legacy_pcid = -1;
355 for(unsigned i = 0;; i++)
356 try {
357 auto p = core.controls->legacy_pcid_to_pair(i);
358 if(p.first == pcid.first && p.second == pcid.second) {
359 legacy_pcid = i;
360 break;
362 } catch(...) {
363 break;
365 if(legacy_pcid >= 0)
366 L.pushnumber(legacy_pcid);
367 else
368 L.pushboolean(false);
369 L.pushnumber(pcid.first);
370 L.pushnumber(pcid.second);
371 return 3;
374 int lcid_to_pcid2(lua::state& L, lua::parameters& P)
376 auto& core = CORE();
377 unsigned lcid;
379 P(lcid);
381 auto pcid = core.controls->lcid_to_pcid(lcid - 1);
382 if(pcid.first < 0)
383 return 0;
384 L.pushnumber(pcid.first);
385 L.pushnumber(pcid.second);
386 return 2;
389 int _port_type(lua::state& L, lua::parameters& P)
391 auto& core = CORE();
392 unsigned port;
394 P(port);
396 auto& m = core.mlogic->get_movie();
397 const portctrl::type_set& s = m.read_subframe(m.get_current_frame(), 0).porttypes();
398 try {
399 const portctrl::type& p = s.port_type(port);
400 L.pushlstring(p.name);
401 } catch(...) {
402 return 0;
404 return 1;
407 int veto_button(lua::state& L, lua::parameters& P)
409 auto& core = CORE();
410 if(core.lua2->veto_flag) *core.lua2->veto_flag = true;
411 return 0;
414 int controller_info(lua::state& L, lua::parameters& P)
416 auto& core = CORE();
417 unsigned port, controller;
419 P(port, controller);
421 const portctrl::controller_set* ps;
422 unsigned lcid = 0;
423 unsigned classnum = 1;
424 ps = lookup_ps(port);
425 if(!ps || ps->controllers.size() <= controller)
426 return 0;
427 for(unsigned i = 0; i < 8; i++) {
428 auto pcid = core.controls->lcid_to_pcid(i);
429 if(pcid.first < 0)
430 continue;
431 if(pcid.first == (int)port && pcid.second == (int)controller) {
432 lcid = i + 1;
433 break;
435 const portctrl::controller_set* ps2 = lookup_ps(pcid.first);
436 if(ps->controllers[controller].cclass == ps2->controllers[pcid.second].cclass)
437 classnum++;
439 const portctrl::controller& cs = ps->controllers[controller];
440 L.newtable();
441 L.pushstring("type");
442 L.pushlstring(cs.type);
443 L.rawset(-3);
444 L.pushstring("class");
445 L.pushlstring(cs.cclass);
446 L.rawset(-3);
447 L.pushstring("classnum");
448 L.pushnumber(classnum);
449 L.rawset(-3);
450 L.pushstring("lcid");
451 L.pushnumber(lcid);
452 L.rawset(-3);
453 L.pushstring("button_count");
454 L.pushnumber(cs.buttons.size());
455 L.rawset(-3);
456 L.pushstring("buttons");
457 L.newtable();
458 //Push the buttons.
459 for(unsigned i = 0; i < cs.buttons.size(); i++) {
460 L.pushnumber(i + 1);
461 L.newtable();
462 L.pushstring("type");
463 switch(cs.buttons[i].type) {
464 case portctrl::button::TYPE_NULL: L.pushstring("null"); break;
465 case portctrl::button::TYPE_BUTTON: L.pushstring("button"); break;
466 case portctrl::button::TYPE_AXIS: L.pushstring("axis"); break;
467 case portctrl::button::TYPE_RAXIS: L.pushstring("raxis"); break;
468 case portctrl::button::TYPE_TAXIS: L.pushstring("axis"); break;
469 case portctrl::button::TYPE_LIGHTGUN: L.pushstring("lightgun"); break;
471 L.rawset(-3);
472 if(cs.buttons[i].symbol) {
473 L.pushstring("symbol");
474 L.pushlstring(&cs.buttons[i].symbol, 1);
475 L.rawset(-3);
477 if(cs.buttons[i].macro != "") {
478 L.pushstring("macro");
479 L.pushlstring(cs.buttons[i].macro);
480 L.rawset(-3);
482 if(cs.buttons[i].is_analog()) {
483 L.pushstring("rmin");
484 L.pushnumber(cs.buttons[i].rmin);
485 L.rawset(-3);
486 L.pushstring("rmax");
487 L.pushnumber(cs.buttons[i].rmax);
488 L.rawset(-3);
490 L.pushstring("name");
491 L.pushlstring(cs.buttons[i].name);
492 L.rawset(-3);
493 L.pushstring("hidden");
494 L.pushboolean(cs.buttons[i].shadow);
495 L.rawset(-3);
496 L.rawset(-3);
498 L.rawset(-3);
499 return 1;
502 lua::functions LUA_input_fns(lua_func_misc, "input", {
503 {"set", set},
504 {"set2", set2},
505 {"get", get},
506 {"get2", get2},
507 {"seta", seta},
508 {"seta2", seta2},
509 {"geta", geta},
510 {"geta2", geta2},
511 {"controllertype", controllertype},
512 {"controllertype2", controllertype2},
513 {"reset", reset},
514 {"raw", raw},
515 {"keyhook", keyhook},
516 {"joyget", joyget},
517 {"joyset", joyset},
518 {"lcid_to_pcid", lcid_to_pcid},
519 {"lcid_to_pcid2", lcid_to_pcid2},
520 {"port_type", _port_type},
521 {"veto_button", veto_button},
522 {"controller_info", controller_info},