Upload UI
[lsnes.git] / src / lua / input.cpp
blob74d75a0b32b41d53462dc2b3b42a54eaf6c42643
1 #include "core/keymapper.hpp"
2 #include "lua/internal.hpp"
3 #include "core/movie.hpp"
4 #include "core/moviedata.hpp"
5 #include "core/controller.hpp"
6 #include "interface/romtype.hpp"
7 #include <iostream>
9 extern bool* lua_veto_flag;
11 namespace
13 int input_set(lua_state& L, unsigned port, unsigned controller, unsigned index, short value)
15 if(!lua_input_controllerdata)
16 return 0;
17 lua_input_controllerdata->axis3(port, controller, index, value);
18 return 0;
21 int input_get(lua_state& L, unsigned port, unsigned controller, unsigned index)
23 if(!lua_input_controllerdata)
24 return 0;
25 L.pushnumber(lua_input_controllerdata->axis3(port, controller, index));
26 return 1;
29 int input_controllertype(lua_state& L, unsigned port, unsigned controller)
31 auto& m = get_movie();
32 controller_frame f = m.read_subframe(m.get_current_frame(), 0);
33 if(port >= f.get_port_count()) {
34 L.pushnil();
35 return 1;
37 const port_type& p = f.get_port_type(port);
38 if(controller >= p.controller_info->controllers.size())
39 L.pushnil();
40 else
41 L.pushlstring(p.controller_info->controllers[controller].type);
42 return 1;
45 int input_seta(lua_state& L, unsigned port, unsigned controller, uint64_t base, const char* fname)
47 if(!lua_input_controllerdata)
48 return 0;
49 short val;
50 if(port >= lua_input_controllerdata->get_port_count())
51 return 0;
52 const port_type& pt = lua_input_controllerdata->get_port_type(port);
53 if(controller >= pt.controller_info->controllers.size())
54 return 0;
55 for(unsigned i = 0; i < pt.controller_info->controllers[controller].buttons.size(); i++) {
56 val = (base >> i) & 1;
57 L.get_numeric_argument<short>(i + base, val, fname);
58 lua_input_controllerdata->axis3(port, controller, i, val);
60 return 0;
63 int input_geta(lua_state& L, unsigned port, unsigned controller)
65 if(!lua_input_controllerdata)
66 return 0;
67 if(port >= lua_input_controllerdata->get_port_count())
68 return 0;
69 const port_type& pt = lua_input_controllerdata->get_port_type(port);
70 if(controller >= pt.controller_info->controllers.size())
71 return 0;
72 uint64_t fret = 0;
73 for(unsigned i = 0; i < pt.controller_info->controllers[controller].buttons.size(); i++)
74 if(lua_input_controllerdata->axis3(port, controller, i))
75 fret |= (1ULL << i);
76 L.pushnumber(fret);
77 for(unsigned i = 0; i < pt.controller_info->controllers[controller].buttons.size(); i++)
78 L.pushnumber(lua_input_controllerdata->axis3(port, controller, i));
79 return pt.controller_info->controllers[controller].buttons.size() + 1;
82 function_ptr_luafun iset(lua_func_misc, "input.set", [](lua_state& L, const std::string& fname) -> int {
83 if(!lua_input_controllerdata)
84 return 0;
85 unsigned controller = L.get_numeric_argument<unsigned>(1, fname.c_str());
86 unsigned index = L.get_numeric_argument<unsigned>(2, fname.c_str());
87 short value = L.get_numeric_argument<short>(3, fname.c_str());
88 auto _controller = lua_input_controllerdata->porttypes().legacy_pcid_to_pair(controller);
89 return input_set(L, _controller.first, _controller.second, index, value);
90 });
92 function_ptr_luafun iset2(lua_func_misc, "input.set2", [](lua_state& L, const std::string& fname) -> int {
93 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
94 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
95 unsigned index = L.get_numeric_argument<unsigned>(3, fname.c_str());
96 short value = L.get_numeric_argument<short>(4, fname.c_str());
97 return input_set(L, port, controller, index, value);
98 });
100 function_ptr_luafun iget(lua_func_misc, "input.get", [](lua_state& L, const std::string& fname) -> int {
101 if(!lua_input_controllerdata)
102 return 0;
103 unsigned controller = L.get_numeric_argument<unsigned>(1, fname.c_str());
104 unsigned index = L.get_numeric_argument<unsigned>(2, fname.c_str());
105 auto _controller = lua_input_controllerdata->porttypes().legacy_pcid_to_pair(controller);
106 return input_get(L, _controller.first, _controller.second, index);
109 function_ptr_luafun iget2(lua_func_misc, "input.get2", [](lua_state& L, const std::string& fname) -> int {
110 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
111 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
112 unsigned index = L.get_numeric_argument<unsigned>(3, fname.c_str());
113 return input_get(L, port, controller, index);
116 function_ptr_luafun iseta(lua_func_misc, "input.seta", [](lua_state& L, const std::string& fname) -> int {
117 if(!lua_input_controllerdata)
118 return 0;
119 unsigned controller = L.get_numeric_argument<unsigned>(1, fname.c_str());
120 uint64_t base = L.get_numeric_argument<uint64_t>(2, fname.c_str());
121 auto _controller = lua_input_controllerdata->porttypes().legacy_pcid_to_pair(controller);
122 return input_seta(L, _controller.first, _controller.second, base, fname.c_str());
125 function_ptr_luafun iseta2(lua_func_misc, "input.seta2", [](lua_state& L, const std::string& fname) -> int {
126 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
127 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
128 uint64_t base = L.get_numeric_argument<uint64_t>(3, fname.c_str());
129 return input_seta(L, port, controller, base, fname.c_str());
132 function_ptr_luafun igeta(lua_func_misc, "input.geta", [](lua_state& L, const std::string& fname) -> int {
133 if(!lua_input_controllerdata)
134 return 0;
135 unsigned controller = L.get_numeric_argument<unsigned>(1, fname.c_str());
136 auto _controller = lua_input_controllerdata->porttypes().legacy_pcid_to_pair(controller);
137 return input_geta(L, _controller.first, _controller.second);
140 function_ptr_luafun igeta2(lua_func_misc, "input.geta2", [](lua_state& L, const std::string& fname) -> int {
141 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
142 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
143 return input_geta(L, port, controller);
146 function_ptr_luafun igett(lua_func_misc, "input.controllertype", [](lua_state& L, const std::string& fname)
147 -> int {
148 unsigned controller = L.get_numeric_argument<unsigned>(1, fname.c_str());
149 auto& m = get_movie();
150 const port_type_set& s = m.read_subframe(m.get_current_frame(), 0).porttypes();
151 auto _controller = s.legacy_pcid_to_pair(controller);
152 return input_controllertype(L, _controller.first, _controller.second);
155 function_ptr_luafun igett2(lua_func_misc, "input.controllertype2", [](lua_state& L, const std::string& fname)
156 -> int {
157 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
158 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
159 return input_controllertype(L, port, controller);
162 function_ptr_luafun ireset(lua_func_misc, "input.reset", [](lua_state& L, const std::string& fname) -> int {
163 if(!lua_input_controllerdata)
164 return 0;
165 long cycles = 0;
166 L.get_numeric_argument(1, cycles, fname.c_str());
167 if(cycles < 0)
168 return 0;
169 short lo = cycles % 10000;
170 short hi = cycles / 10000;
171 lua_input_controllerdata->axis3(0, 0, 1, 1);
172 lua_input_controllerdata->axis3(0, 0, 2, hi);
173 lua_input_controllerdata->axis3(0, 0, 3, lo);
174 return 0;
177 function_ptr_luafun iraw(lua_func_misc, "input.raw", [](lua_state& L, const std::string& fname) -> int {
178 L.newtable();
179 for(auto i : lsnes_kbd.all_keys()) {
180 L.pushlstring(i->get_name());
181 push_keygroup_parameters(L, *i);
182 L.settable(-3);
184 return 1;
187 class _keyhook_listener : public keyboard_event_listener
189 void on_key_event(keyboard_modifier_set& modifiers, keyboard_key& key, keyboard_event& event)
191 lua_callback_keyhook(key.get_name(), key);
193 } keyhook_listener;
194 std::set<std::string> hooked;
196 function_ptr_luafun ireq(lua_func_misc, "input.keyhook", [](lua_state& L, const std::string& fname) -> int {
197 bool state;
198 std::string x = L.get_string(1, fname.c_str());
199 state = L.get_bool(2, fname.c_str());
200 keyboard_key* key = lsnes_kbd.try_lookup_key(x);
201 if(!key)
202 throw std::runtime_error("Invalid key name");
203 bool ostate = hooked.count(x) > 0;
204 if(ostate == state)
205 return 0;
206 if(state) {
207 hooked.insert(x);
208 key->add_listener(keyhook_listener, true);
209 } else {
210 hooked.erase(x);
211 key->remove_listener(keyhook_listener);
213 return 0;
216 function_ptr_luafun ijget(lua_func_misc, "input.joyget", [](lua_state& L, const std::string& fname) -> int {
217 unsigned lcid = L.get_numeric_argument<unsigned>(1, fname.c_str());
218 if(!lua_input_controllerdata)
219 return 0;
220 auto pcid = controls.lcid_to_pcid(lcid - 1);
221 if(pcid.first < 0)
222 throw std::runtime_error("Invalid controller for input.joyget");
223 L.newtable();
224 const port_type& pt = lua_input_controllerdata->get_port_type(pcid.first);
225 const port_controller& ctrl = pt.controller_info->controllers[pcid.second];
226 unsigned lcnt = ctrl.buttons.size();
227 for(unsigned i = 0; i < lcnt; i++) {
228 if(ctrl.buttons[i].type == port_controller_button::TYPE_NULL)
229 continue;
230 L.pushlstring(ctrl.buttons[i].name);
231 if(ctrl.buttons[i].is_analog())
232 L.pushnumber(lua_input_controllerdata->axis3(pcid.first, pcid.second, i));
233 else if(ctrl.buttons[i].type == port_controller_button::TYPE_BUTTON)
234 L.pushboolean(lua_input_controllerdata->axis3(pcid.first, pcid.second, i) != 0);
235 L.settable(-3);
237 return 1;
240 function_ptr_luafun ijset(lua_func_misc, "input.joyset", [](lua_state& L, const std::string& fname) -> int {
241 unsigned lcid = L.get_numeric_argument<unsigned>(1, fname.c_str());
242 if(L.type(2) != LUA_TTABLE)
243 throw std::runtime_error("Invalid type for input.joyset");
244 if(!lua_input_controllerdata)
245 return 0;
246 auto pcid = controls.lcid_to_pcid(lcid - 1);
247 if(pcid.first < 0)
248 throw std::runtime_error("Invalid controller for input.joyset");
249 const port_type& pt = lua_input_controllerdata->get_port_type(pcid.first);
250 const port_controller& ctrl = pt.controller_info->controllers[pcid.second];
251 unsigned lcnt = ctrl.buttons.size();
252 for(unsigned i = 0; i < lcnt; i++) {
253 if(ctrl.buttons[i].type == port_controller_button::TYPE_NULL)
254 continue;
255 L.pushlstring(ctrl.buttons[i].name);
256 L.gettable(2);
257 int s;
258 if(ctrl.buttons[i].is_analog()) {
259 if(L.type(-1) == LUA_TNIL)
260 s = lua_input_controllerdata->axis3(pcid.first, pcid.second, i);
261 else
262 s = L.tonumber(-1);
263 } else {
264 if(L.type(-1) == LUA_TNIL)
265 s = lua_input_controllerdata->axis3(pcid.first, pcid.second, i);
266 else if(L.type(-1) == LUA_TSTRING)
267 s = lua_input_controllerdata->axis3(pcid.first, pcid.second, i) ^ 1;
268 else
269 s = L.toboolean(-1) ? 1 : 0;
271 lua_input_controllerdata->axis3(pcid.first, pcid.second, i, s);
272 L.pop(1);
274 return 0;
277 function_ptr_luafun ijlcid_to_pcid(lua_func_misc, "input.lcid_to_pcid", [](lua_state& L,
278 const std::string& fname) -> int {
279 unsigned lcid = L.get_numeric_argument<unsigned>(1, fname.c_str());
280 auto pcid = controls.lcid_to_pcid(lcid - 1);
281 if(pcid.first < 0)
282 return 0;
283 int legacy_pcid = -1;
284 for(unsigned i = 0;; i++)
285 try {
286 auto p = controls.legacy_pcid_to_pair(i);
287 if(p.first == pcid.first && p.second == pcid.second) {
288 legacy_pcid = i;
289 break;
291 } catch(...) {
292 break;
294 if(legacy_pcid >= 0)
295 L.pushnumber(legacy_pcid);
296 else
297 L.pushboolean(false);
298 L.pushnumber(pcid.first);
299 L.pushnumber(pcid.second);
300 return 3;
303 //THE NEW API.
305 function_ptr_luafun ijlcid_to_pcid2(lua_func_misc, "input.lcid_to_pcid2", [](lua_state& L,
306 const std::string& fname) -> int {
307 unsigned lcid = L.get_numeric_argument<unsigned>(1, fname.c_str());
308 auto pcid = controls.lcid_to_pcid(lcid - 1);
309 if(pcid.first < 0)
310 return 0;
311 L.pushnumber(pcid.first);
312 L.pushnumber(pcid.second);
313 return 2;
316 function_ptr_luafun iporttype(lua_func_misc, "input.port_type", [](lua_state& L, const std::string& fname)
317 -> int {
318 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
319 auto& m = get_movie();
320 const port_type_set& s = m.read_subframe(m.get_current_frame(), 0).porttypes();
321 try {
322 const port_type& p = s.port_type(port);
323 L.pushlstring(p.name);
324 } catch(...) {
325 return 0;
327 return 1;
330 const port_controller_set* lookup_ps(unsigned port)
332 auto& m = get_movie();
333 controller_frame f = m.read_subframe(m.get_current_frame(), 0);
334 const port_type& p = f.get_port_type(port);
335 return p.controller_info;
338 function_ptr_luafun iveto(lua_func_misc, "input.veto_button", [](lua_state& L, const std::string& fname)
339 -> int {
340 if(lua_veto_flag) *lua_veto_flag = true;
341 return 0;
344 function_ptr_luafun ictrlinfo(lua_func_misc, "input.controller_info", [](lua_state& L,
345 const std::string& fname) -> int {
346 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
347 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
348 const port_controller_set* ps;
349 unsigned lcid = 0;
350 unsigned classnum = 1;
351 ps = lookup_ps(port);
352 if(!ps || ps->controllers.size() <= controller)
353 return 0;
354 for(unsigned i = 0; i < 8; i++) {
355 auto pcid = controls.lcid_to_pcid(i);
356 if(pcid.first < 0)
357 continue;
358 if(pcid.first == port && pcid.second == controller) {
359 lcid = i + 1;
360 break;
362 const port_controller_set* ps2 = lookup_ps(pcid.first);
363 if(ps->controllers[controller].cclass == ps2->controllers[pcid.second].cclass)
364 classnum++;
366 const port_controller& cs = ps->controllers[controller];
367 L.newtable();
368 L.pushstring("type");
369 L.pushlstring(cs.type);
370 L.rawset(-3);
371 L.pushstring("class");
372 L.pushlstring(cs.cclass);
373 L.rawset(-3);
374 L.pushstring("classnum");
375 L.pushnumber(classnum);
376 L.rawset(-3);
377 L.pushstring("lcid");
378 L.pushnumber(lcid);
379 L.rawset(-3);
380 L.pushstring("button_count");
381 L.pushnumber(cs.buttons.size());
382 L.rawset(-3);
383 L.pushstring("buttons");
384 L.newtable();
385 //Push the buttons.
386 for(unsigned i = 0; i < cs.buttons.size(); i++) {
387 L.pushnumber(i + 1);
388 L.newtable();
389 L.pushstring("type");
390 switch(cs.buttons[i].type) {
391 case port_controller_button::TYPE_NULL: L.pushstring("null"); break;
392 case port_controller_button::TYPE_BUTTON: L.pushstring("button"); break;
393 case port_controller_button::TYPE_AXIS: L.pushstring("axis"); break;
394 case port_controller_button::TYPE_RAXIS: L.pushstring("raxis"); break;
395 case port_controller_button::TYPE_TAXIS: L.pushstring("axis"); break;
396 case port_controller_button::TYPE_LIGHTGUN: L.pushstring("lightgun"); break;
398 L.rawset(-3);
399 if(cs.buttons[i].symbol) {
400 L.pushstring("symbol");
401 L.pushlstring(&cs.buttons[i].symbol, 1);
402 L.rawset(-3);
404 if(cs.buttons[i].macro != "") {
405 L.pushstring("macro");
406 L.pushlstring(cs.buttons[i].macro);
407 L.rawset(-3);
409 if(cs.buttons[i].is_analog()) {
410 L.pushstring("rmin");
411 L.pushnumber(cs.buttons[i].rmin);
412 L.rawset(-3);
413 L.pushstring("rmax");
414 L.pushnumber(cs.buttons[i].rmax);
415 L.rawset(-3);
417 L.pushstring("name");
418 L.pushlstring(cs.buttons[i].name);
419 L.rawset(-3);
420 L.pushstring("hidden");
421 L.pushboolean(cs.buttons[i].shadow);
422 L.rawset(-3);
423 L.rawset(-3);
425 L.rawset(-3);
426 return 1;