Refactor Lua support
[lsnes.git] / src / lua / input.cpp
bloba27a8cf55235b218b7fc6654431878bae85a0ad3
1 #include "core/keymapper.hpp"
2 #include "lua/internal.hpp"
3 #include "core/movie.hpp"
4 #include "core/emucore.hpp"
5 #include "core/moviedata.hpp"
6 #include "core/controller.hpp"
7 #include <iostream>
9 namespace
11 int input_set(lua_state& L, unsigned port, unsigned controller, unsigned index, short value)
13 if(!lua_input_controllerdata)
14 return 0;
15 lua_input_controllerdata->axis3(port, controller, index, value);
16 return 0;
19 int input_get(lua_state& L, unsigned port, unsigned controller, unsigned index)
21 if(!lua_input_controllerdata)
22 return 0;
23 L.pushnumber(lua_input_controllerdata->axis3(port, controller, index));
24 return 1;
27 int input_controllertype(lua_state& L, unsigned port, unsigned controller)
29 auto& m = get_movie();
30 controller_frame f = m.read_subframe(m.get_current_frame(), 0);
31 const port_type& p = f.get_port_type(port);
32 if(p.controllers <= controller)
33 L.pushnil();
34 else if(p.ctrlname == "")
35 L.pushnil();
36 else
37 L.pushstring(p.ctrlname.c_str());
38 return 1;
41 int input_seta(lua_state& L, unsigned port, unsigned controller, int base, const char* fname)
43 if(!lua_input_controllerdata)
44 return 0;
45 short val;
46 if(port >= lua_input_controllerdata->get_port_count())
47 return 0;
48 const port_type& pt = lua_input_controllerdata->get_port_type(port);
49 if(controller >= pt.controllers)
50 return 0;
51 for(unsigned i = 0; i < pt.controller_indices[controller]; i++) {
52 val = (base >> i) & 1;
53 L.get_numeric_argument<short>(i + base, val, fname);
54 lua_input_controllerdata->axis3(port, controller, i, val);
56 return 0;
59 int input_geta(lua_state& L, unsigned port, unsigned controller)
61 if(!lua_input_controllerdata)
62 return 0;
63 if(port >= lua_input_controllerdata->get_port_count())
64 return 0;
65 const port_type& pt = lua_input_controllerdata->get_port_type(port);
66 if(controller >= pt.controllers)
67 return 0;
68 uint64_t fret = 0;
69 for(unsigned i = 0; i < pt.controller_indices[controller]; i++)
70 if(lua_input_controllerdata->axis3(port, controller, i))
71 fret |= (1ULL << i);
72 L.pushnumber(fret);
73 for(unsigned i = 0; i < pt.controller_indices[controller]; i++)
74 L.pushnumber(lua_input_controllerdata->axis3(port, controller, i));
75 return pt.controller_indices[controller] + 1;
78 function_ptr_luafun iset(LS, "input.set", [](lua_state& L, const std::string& fname) -> int {
79 unsigned controller = L.get_numeric_argument<unsigned>(1, fname.c_str());
80 unsigned index = L.get_numeric_argument<unsigned>(2, fname.c_str());
81 short value = L.get_numeric_argument<short>(3, fname.c_str());
82 return input_set(L, controller / 4 + 1, controller % 4, index, value);
83 });
85 function_ptr_luafun iset2(LS, "input.set2", [](lua_state& L, const std::string& fname) -> int {
86 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
87 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
88 unsigned index = L.get_numeric_argument<unsigned>(3, fname.c_str());
89 short value = L.get_numeric_argument<short>(4, fname.c_str());
90 return input_set(L, port, controller, index, value);
91 });
93 function_ptr_luafun iget(LS, "input.get", [](lua_state& L, const std::string& fname) -> int {
94 unsigned controller = L.get_numeric_argument<unsigned>(1, fname.c_str());
95 unsigned index = L.get_numeric_argument<unsigned>(2, fname.c_str());
96 return input_get(L, controller / 4 + 1, controller % 4, index);
97 });
99 function_ptr_luafun iget2(LS, "input.get2", [](lua_state& L, const std::string& fname) -> int {
100 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
101 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
102 unsigned index = L.get_numeric_argument<unsigned>(3, fname.c_str());
103 return input_get(L, port, controller, index);
106 function_ptr_luafun iseta(LS, "input.seta", [](lua_state& L, const std::string& fname) -> int {
107 unsigned controller = L.get_numeric_argument<unsigned>(1, fname.c_str());
108 uint64_t base = L.get_numeric_argument<uint64_t>(2, fname.c_str());
109 return input_seta(L, controller / 4 + 1, controller % 4, 3, fname.c_str());
112 function_ptr_luafun iseta2(LS, "input.seta2", [](lua_state& L, const std::string& fname) -> int {
113 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
114 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
115 uint64_t base = L.get_numeric_argument<uint64_t>(3, fname.c_str());
116 return input_seta(L, port, controller, 4, fname.c_str());
119 function_ptr_luafun igeta(LS, "input.geta", [](lua_state& L, const std::string& fname) -> int {
120 unsigned controller = L.get_numeric_argument<unsigned>(1, fname.c_str());
121 return input_geta(L, controller / 4 + 1, controller % 4);
124 function_ptr_luafun igeta2(LS, "input.geta2", [](lua_state& L, const std::string& fname) -> int {
125 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
126 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
127 return input_geta(L, port, controller);
130 function_ptr_luafun igett(LS, "input.controllertype", [](lua_state& L, const std::string& fname) -> int {
131 unsigned controller = L.get_numeric_argument<unsigned>(1, fname.c_str());
132 return input_controllertype(L, controller / 4 + 1, controller % 4);
135 function_ptr_luafun igett2(LS, "input.controllertype2", [](lua_state& L, const std::string& fname) -> int {
136 unsigned port = L.get_numeric_argument<unsigned>(1, fname.c_str());
137 unsigned controller = L.get_numeric_argument<unsigned>(2, fname.c_str());
138 return input_controllertype(L, port, controller);
141 function_ptr_luafun ireset(LS, "input.reset", [](lua_state& L, const std::string& fname) -> int {
142 if(!lua_input_controllerdata)
143 return 0;
144 long cycles = 0;
145 L.get_numeric_argument(1, cycles, fname.c_str());
146 if(cycles < 0)
147 return 0;
148 short lo = cycles % 10000;
149 short hi = cycles / 10000;
150 lua_input_controllerdata->axis3(0, 0, 1, 1);
151 lua_input_controllerdata->axis3(0, 0, 2, hi);
152 lua_input_controllerdata->axis3(0, 0, 3, lo);
153 return 0;
156 function_ptr_luafun iraw(LS, "input.raw", [](lua_state& L, const std::string& fname) -> int {
157 auto s = keygroup::get_all_parameters();
158 L.newtable();
159 for(auto i : s) {
160 L.pushstring(i.first.c_str());
161 push_keygroup_parameters(L, i.second);
162 L.settable(-3);
164 return 1;
167 function_ptr_luafun ireq(LS, "input.keyhook", [](lua_state& L, const std::string& fname) -> int {
168 struct keygroup* k;
169 bool state;
170 std::string x = L.get_string(1, fname.c_str());
171 state = L.get_bool(2, fname.c_str());
172 k = keygroup::lookup_by_name(x);
173 if(!k) {
174 L.pushstring("Invalid key name");
175 L.error();
176 return 0;
178 k->request_hook_callback(state);
179 return 0;
182 function_ptr_luafun ijget(LS, "input.joyget", [](lua_state& L, const std::string& fname) -> int {
183 unsigned lcid = L.get_numeric_argument<unsigned>(1, fname.c_str());
184 if(!lua_input_controllerdata)
185 return 0;
186 auto pcid = controls.lcid_to_pcid(lcid - 1);
187 if(pcid.first < 0) {
188 L.pushstring("Invalid controller for input.joyget");
189 L.error();
190 return 0;
192 L.newtable();
193 unsigned lcnt = get_core_logical_controller_limits().second;
194 for(unsigned i = 0; i < lcnt; i++) {
195 std::string n = get_logical_button_name(i);
196 int y = lua_input_controllerdata->button_id(pcid.first, pcid.second, i);
197 if(y < 0)
198 continue;
199 L.pushstring(n.c_str());
200 L.pushboolean(lua_input_controllerdata->axis3(pcid.first, pcid.second, y) != 0);
201 L.settable(-3);
203 if(lua_input_controllerdata->is_analog(pcid.first, pcid.second)) {
204 L.pushstring("xaxis");
205 L.pushnumber(lua_input_controllerdata->axis3(pcid.first, pcid.second, 0));
206 L.settable(-3);
207 L.pushstring("yaxis");
208 L.pushnumber(lua_input_controllerdata->axis3(pcid.first, pcid.second, 1));
209 L.settable(-3);
211 return 1;
214 function_ptr_luafun ijset(LS, "input.joyset", [](lua_state& L, const std::string& fname) -> int {
215 unsigned lcid = L.get_numeric_argument<unsigned>(1, fname.c_str());
216 if(L.type(2) != LUA_TTABLE) {
217 L.pushstring("Invalid type for input.joyset");
218 L.error();
219 return 0;
221 if(!lua_input_controllerdata)
222 return 0;
223 auto pcid = controls.lcid_to_pcid(lcid - 1);
224 if(pcid.first < 0) {
225 L.pushstring("Invalid controller for input.joyset");
226 L.error();
227 return 0;
229 unsigned lcnt = get_core_logical_controller_limits().second;
230 for(unsigned i = 0; i < lcnt; i++) {
231 std::string n = get_logical_button_name(i);
232 int y = lua_input_controllerdata->button_id(pcid.first, pcid.second, i);
233 if(y < 0)
234 continue;
235 L.pushstring(n.c_str());
236 L.gettable(2);
237 int s = L.toboolean(-1) ? 1 : 0;
238 lua_input_controllerdata->axis3(pcid.first, pcid.second, y, s);
239 L.pop(1);
241 if(lua_input_controllerdata->is_analog(pcid.first, pcid.second)) {
242 L.pushstring("xaxis");
243 L.gettable(2);
244 int s = L.tonumber(-1);
245 lua_input_controllerdata->axis3(pcid.first, pcid.second, 0, s);
246 L.pop(1);
247 L.pushstring("yaxis");
248 L.gettable(2);
249 s = L.tonumber(-1);
250 lua_input_controllerdata->axis3(pcid.first, pcid.second, 1, s);
251 L.pop(1);
253 return 0;
256 function_ptr_luafun ijlcid_to_pcid(LS, "input.lcid_to_pcid", [](lua_state& L, const std::string& fname) ->
257 int {
258 unsigned lcid = L.get_numeric_argument<unsigned>(1, fname.c_str());
259 auto pcid = controls.lcid_to_pcid(lcid - 1);
260 if(pcid.first < 0)
261 return 0;
262 L.pushnumber((pcid.first - 1) * 4 + pcid.second);
263 L.pushnumber(pcid.first);
264 L.pushnumber(pcid.second);
265 return 3;