Lua: Fix type confusion between signed and unsigned
[lsnes.git] / src / core / controllerframe.cpp
blob3b80d50bf0f1c32afa2e1478daa59dc23e71cda5
1 #include "cmdhelp/macro.hpp"
2 #include "core/command.hpp"
3 #include "core/controllerframe.hpp"
4 #include "core/controller.hpp"
5 #include "core/dispatch.hpp"
6 #include "core/instance.hpp"
7 #include "core/messages.hpp"
8 #include "core/moviedata.hpp"
9 #include "core/project.hpp"
10 #include "interface/romtype.hpp"
12 #include <cstdio>
13 #include <iostream>
15 namespace
17 portctrl::type_set dummytypes;
19 command::fnptr<const std::string&> macro_test(lsnes_cmds, CMACRO::test,
20 [](const std::string& args) throw(std::bad_alloc, std::runtime_error) {
21 auto& core = CORE();
22 regex_results r = regex("([0-9]+)[ \t](.*)", args);
23 if(!r) {
24 messages << "Bad syntax" << std::endl;
25 return;
27 unsigned ctrl = parse_value<unsigned>(r[1]);
28 auto pcid = core.controls->lcid_to_pcid(ctrl);
29 if(pcid.first < 0) {
30 messages << "Bad controller" << std::endl;
31 return;
33 try {
34 const portctrl::controller* _ctrl =
35 core.controls->get_blank().porttypes().port_type(pcid.first).
36 controller_info->get(pcid.second);
37 if(!_ctrl) {
38 messages << "No controller data for controller" << std::endl;
39 return;
41 portctrl::macro_data mdata(r[2].c_str(),
42 portctrl::macro_data::make_descriptor(*_ctrl), 0);
43 messages << "Macro: " << mdata.dump(*_ctrl) << std::endl;
44 } catch(std::exception& e) {
45 messages << "Exception: " << e.what() << std::endl;
47 });
51 controller_state::controller_state(project_state& _project, movie_logic& _mlogic, button_mapping& _buttons,
52 emulator_dispatch& _dispatch, status_updater& _supdater, command::group& _cmd) throw()
53 : project(_project), mlogic(_mlogic), buttons(_buttons), edispatch(_dispatch), supdater(_supdater),
54 cmd(_cmd),
55 macro_p(cmd, CMACRO::p, [this](const std::string& a) { this->do_macro(a, 5); }),
56 macro_r(cmd, CMACRO::r, [this](const std::string& a) { this->do_macro(a, 2); }),
57 macro_t(cmd, CMACRO::t, [this](const std::string& a) { this->do_macro(a, 7); })
59 types = &dummytypes;
60 tasinput_enaged = false;
63 std::pair<int,int> controller_state::lcid_to_pcid(unsigned lcid) throw()
65 if(lcid >= types->number_of_controllers())
66 return std::make_pair(-1, -1);
67 auto k = types->lcid_to_pcid(lcid);
68 return std::make_pair(k.first, k.second);
71 std::pair<int, int> controller_state::legacy_pcid_to_pair(unsigned pcid) throw()
73 if(pcid >= types->number_of_legacy_pcids())
74 return std::make_pair(-1, -1);
75 auto k = types->legacy_pcid_to_pair(pcid);
76 return std::make_pair(k.first, k.second);
80 portctrl::frame controller_state::get(uint64_t framenum) throw()
82 portctrl::frame tmp = _input ^ _framehold ^ _autohold;
83 for(auto i : _autofire)
84 if(i.second.eval_at(framenum))
85 tmp.axis2(i.first, tmp.axis2(i.first) ^ 1);
86 if(tasinput_enaged)
87 for(auto i : _tasinput) {
88 if(i.second.mode == 0 && i.second.state)
89 tmp.axis2(i.first, tmp.axis2(i.first) ^ 1);
90 else if(i.second.mode == 1)
91 tmp.axis2(i.first, i.second.state);
93 apply_macro(tmp);
94 return tmp;
97 void controller_state::analog(unsigned port, unsigned controller, unsigned control, short x) throw()
99 _input.axis3(port, controller, control, x);
102 void controller_state::autohold2(unsigned port, unsigned controller, unsigned pbid, bool newstate) throw()
104 _autohold.axis3(port, controller, pbid, newstate ? 1 : 0);
105 edispatch.autohold_update(port, controller, pbid, newstate);
108 bool controller_state::autohold2(unsigned port, unsigned controller, unsigned pbid) throw()
110 return (_autohold.axis3(port, controller, pbid) != 0);
113 void controller_state::autofire2(unsigned port, unsigned controller, unsigned pbid, unsigned duty, unsigned cyclelen)
114 throw()
116 unsigned idx = _input.porttypes().triple_to_index(port, controller, pbid);
117 if(duty) {
118 _autofire[idx].first_frame = mlogic.get_movie().get_current_frame();
119 _autofire[idx].duty = duty;
120 _autofire[idx].cyclelen = cyclelen;
121 } else
122 _autofire.erase(idx);
125 std::pair<unsigned, unsigned> controller_state::autofire2(unsigned port, unsigned controller, unsigned pbid) throw()
127 unsigned idx = _input.porttypes().triple_to_index(port, controller, pbid);
128 if(!_autofire.count(idx))
129 return std::make_pair(0, 1);
130 else
131 return std::make_pair(_autofire[idx].duty, _autofire[idx].cyclelen);
134 bool controller_state::autofire_info::eval_at(uint64_t frame)
136 if(frame < first_frame) {
137 uint64_t diff = first_frame - frame;
138 frame += ((diff / cyclelen) + 1) * cyclelen;
140 return frame % cyclelen < duty;
143 void controller_state::reset_framehold() throw()
145 _framehold = _framehold.blank_frame();
148 void controller_state::framehold2(unsigned port, unsigned controller, unsigned pbid, bool newstate) throw()
150 _framehold.axis3(port, controller, pbid, newstate ? 1 : 0);
153 bool controller_state::framehold2(unsigned port, unsigned controller, unsigned pbid) throw()
155 return (_framehold.axis3(port, controller, pbid) != 0);
158 void controller_state::button2(unsigned port, unsigned controller, unsigned pbid, bool newstate) throw()
160 _input.axis3(port, controller, pbid, newstate ? 1 : 0);
163 bool controller_state::button2(unsigned port, unsigned controller, unsigned pbid) throw()
165 return (_input.axis3(port, controller, pbid) != 0);
168 void controller_state::tasinput(unsigned port, unsigned controller, unsigned pbid, int16_t state) throw()
170 unsigned idx = _input.porttypes().triple_to_index(port, controller, pbid);
171 if(!_tasinput.count(idx))
172 _tasinput[idx].mode = 0; //Just to be sure.
173 _tasinput[idx].state = state;
176 int16_t controller_state::tasinput(unsigned port, unsigned controller, unsigned pbid) throw()
178 unsigned idx = _input.porttypes().triple_to_index(port, controller, pbid);
179 return _tasinput.count(idx) ? _tasinput[idx].state : 0;
182 void controller_state::tasinput_enable(bool enabled)
184 tasinput_enaged = enabled;
187 void controller_state::reread_tasinput_mode(const portctrl::type_set& ptype)
189 unsigned indices = ptype.indices();
190 _tasinput.clear();
191 for(unsigned i = 0; i < indices; i++) {
192 auto t = ptype.index_to_triple(i);
193 if(!t.valid)
194 continue;
195 //See what the heck that is...
196 const portctrl::type& pt = ptype.port_type(t.port);
197 const portctrl::controller_set& pci = *(pt.controller_info);
198 if(pci.controllers.size() <= t.controller)
199 continue;
200 const portctrl::controller& pc = pci.controllers[t.controller];
201 if(pc.buttons.size() <= t.control)
202 continue;
203 const portctrl::button& pcb = pc.buttons[t.control];
204 if(pcb.shadow)
205 continue;
206 if(pcb.type == portctrl::button::TYPE_BUTTON)
207 _tasinput[i].mode = 0;
208 else
209 _tasinput[i].mode = 1;
210 _tasinput[i].state = 0;
214 void controller_state::set_ports(const portctrl::type_set& ptype) throw(std::runtime_error)
216 const portctrl::type_set* oldtype = types;
217 types = &ptype;
218 if(oldtype != types) {
219 _input.set_types(ptype);
220 _autohold.set_types(ptype);
221 _committed.set_types(ptype);
222 _framehold.set_types(ptype);
223 //The old autofire pattern no longer applies.
224 _autofire.clear();
225 reread_tasinput_mode(ptype);
226 _autohold = _autohold.blank_frame();
227 buttons.reread();
228 edispatch.autohold_reconfigure();
232 portctrl::frame controller_state::get_blank() throw()
234 return _input.blank_frame();
237 portctrl::frame controller_state::get_committed() throw()
239 return _committed;
242 void controller_state::commit(portctrl::frame controls) throw()
244 _committed = controls;
247 bool controller_state::is_present(unsigned port, unsigned controller) throw()
249 return _input.is_present(port, controller);
252 void controller_state::erase_macro(const std::string& macro)
255 threads::alock h(macro_lock);
256 if(!all_macros.count(macro))
257 return;
258 auto m = &all_macros[macro];
259 for(auto i = active_macros.begin(); i != active_macros.end(); i++) {
260 if(i->second == m) {
261 active_macros.erase(i);
262 break;
265 all_macros.erase(macro);
266 project_info* p = project.get();
267 if(p) {
268 p->macros.erase(macro);
269 p->flush();
272 buttons.load(*this);
275 std::set<std::string> controller_state::enumerate_macro()
277 threads::alock h(macro_lock);
278 std::set<std::string> r;
279 for(auto i : all_macros)
280 r.insert(i.first);
281 return r;
284 portctrl::macro& controller_state::get_macro(const std::string& macro)
286 threads::alock h(macro_lock);
287 if(!all_macros.count(macro))
288 throw std::runtime_error("No such macro");
289 return all_macros[macro];
292 void controller_state::set_macro(const std::string& macro, const portctrl::macro& m)
295 threads::alock h(macro_lock);
296 portctrl::macro* old = NULL;
297 if(all_macros.count(macro))
298 old = &all_macros[macro];
299 all_macros[macro] = m;
300 for(auto i = active_macros.begin(); i != active_macros.end(); i++) {
301 if(i->second == old) {
302 i->second = &all_macros[macro];
303 break;
306 project_info* p = project.get();
307 if(p) {
308 p->macros[macro] = all_macros[macro].serialize();
309 p->flush();
312 buttons.load(*this);
315 void controller_state::apply_macro(portctrl::frame& f)
317 threads::alock h(macro_lock);
318 for(auto i : active_macros)
319 i.second->write(f, i.first);
322 void controller_state::advance_macros()
324 threads::alock h(macro_lock);
325 for(auto& i : active_macros)
326 i.first++;
329 std::map<std::string, uint64_t> controller_state::get_macro_frames()
331 threads::alock h(macro_lock);
332 std::map<std::string, uint64_t> r;
333 for(auto i : active_macros) {
334 for(auto& j : all_macros)
335 if(i.second == &j.second) {
336 r[j.first] = i.first;
339 return r;
342 void controller_state::set_macro_frames(const std::map<std::string, uint64_t>& f)
344 threads::alock h(macro_lock);
345 std::list<std::pair<uint64_t, portctrl::macro*>> new_active_macros;
346 for(auto i : f)
347 if(all_macros.count(i.first))
348 new_active_macros.push_back(std::make_pair(i.second, &all_macros[i.first]));
349 else
350 messages << "Warning: Can't find defintion for '" << i.first << "'" << std::endl;
351 std::swap(active_macros, new_active_macros);
354 void controller_state::rename_macro(const std::string& old, const std::string& newn)
357 threads::alock h(macro_lock);
358 if(!all_macros.count(old))
359 throw std::runtime_error("Old macro doesn't exist");
360 if(all_macros.count(newn))
361 throw std::runtime_error("Target name already exists");
362 if(old == newn)
363 return;
364 all_macros[newn] = all_macros[old];
365 portctrl::macro* _old = &all_macros[old];
366 all_macros.erase(old);
367 for(auto i = active_macros.begin(); i != active_macros.end(); i++) {
368 if(i->second == _old) {
369 i->second = &all_macros[newn];
370 break;
373 project_info* p = project.get();
374 if(p) {
375 p->macros[newn] = p->macros[old];
376 p->macros.erase(old);
379 buttons.load(*this);
382 void controller_state::do_macro(const std::string& a, int mode) {
384 threads::alock h(macro_lock);
385 if(!all_macros.count(a)) {
386 if(mode & 1) messages << "No such macro '" << a << "'" << std::endl;
387 return;
389 portctrl::macro* m = &all_macros[a];
390 for(auto i = active_macros.begin(); i != active_macros.end(); i++) {
391 if(i->second == m) {
392 if(mode & 2) active_macros.erase(i);
393 goto end;
396 if(mode & 4) active_macros.push_back(std::make_pair(0, m));
398 end:
399 supdater.update();
400 edispatch.status_update();
403 std::set<std::string> controller_state::active_macro_set()
405 threads::alock h(macro_lock);
406 std::set<std::string> r;
407 for(auto i : active_macros) {
408 for(auto& j : all_macros)
409 if(i.second == &j.second) {
410 r.insert(j.first);
413 return r;