2011-09-16 06:13:33 +03:00
|
|
|
#include "lsnes.hpp"
|
|
|
|
#include <snes/snes.hpp>
|
|
|
|
#include <ui-libsnes/libsnes.hpp>
|
2011-11-08 21:22:30 +02:00
|
|
|
|
2011-11-06 14:41:41 +02:00
|
|
|
#include "core/command.hpp"
|
|
|
|
#include "core/controller.hpp"
|
2011-11-08 21:22:30 +02:00
|
|
|
#include "core/dispatch.hpp"
|
2011-11-06 14:41:41 +02:00
|
|
|
#include "core/framebuffer.hpp"
|
|
|
|
#include "core/mainloop.hpp"
|
2011-11-08 21:22:30 +02:00
|
|
|
#include "core/misc.hpp"
|
2011-11-06 14:41:41 +02:00
|
|
|
#include "core/window.hpp"
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <sstream>
|
2011-09-16 06:13:33 +03:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2011-10-05 02:24:34 +03:00
|
|
|
std::map<std::string, std::pair<unsigned, unsigned>> buttonmap;
|
|
|
|
|
|
|
|
void init_buttonmap()
|
|
|
|
{
|
|
|
|
static int done = 0;
|
|
|
|
if(done)
|
|
|
|
return;
|
|
|
|
for(unsigned i = 0; i < 8; i++)
|
2012-01-11 23:07:31 +02:00
|
|
|
for(unsigned j = 0; j < MAX_LOGICAL_BUTTONS; j++) {
|
2011-10-05 02:24:34 +03:00
|
|
|
std::ostringstream x;
|
2012-01-11 23:07:31 +02:00
|
|
|
x << (i + 1) << get_logical_button_name(j);
|
2011-10-05 02:24:34 +03:00
|
|
|
buttonmap[x.str()] = std::make_pair(i, j);
|
|
|
|
}
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Do button action.
|
2012-01-11 23:07:31 +02:00
|
|
|
void do_button_action(unsigned ui_id, unsigned button, short newstate, bool autoh)
|
2011-10-05 02:24:34 +03:00
|
|
|
{
|
2012-01-11 23:07:31 +02:00
|
|
|
int x = controls.lcid_to_pcid(ui_id);
|
|
|
|
if(x < 0) {
|
2011-11-08 21:22:30 +02:00
|
|
|
messages << "No such controller #" << (ui_id + 1) << std::endl;
|
2011-10-05 02:24:34 +03:00
|
|
|
return;
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
int bid = controls.button_id(x, button);
|
|
|
|
if(bid < 0) {
|
|
|
|
messages << "Invalid button for controller type" << std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(autoh) {
|
|
|
|
controls.autohold(x, bid, controls.autohold(x, bid) ^ newstate);
|
|
|
|
information_dispatch::do_autohold_update(x, bid, controls.autohold(x, bid));
|
2011-11-05 00:37:32 +02:00
|
|
|
} else
|
2012-01-11 23:07:31 +02:00
|
|
|
controls.button(x, bid, newstate);
|
2011-10-05 02:24:34 +03:00
|
|
|
}
|
|
|
|
|
2012-01-17 23:48:13 +02:00
|
|
|
void send_analog(unsigned lcid, int32_t x, int32_t y)
|
|
|
|
{
|
|
|
|
int pcid = controls.lcid_to_pcid(lcid);
|
|
|
|
if(pcid < 0) {
|
|
|
|
messages << "Controller #" << (lcid + 1) << " not present" << std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(controls.is_analog(pcid) < 0) {
|
|
|
|
messages << "Controller #" << (lcid + 1) << " is not analog" << std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto g2 = get_framebuffer_size();
|
|
|
|
if(controls.is_mouse(pcid)) {
|
|
|
|
controls.analog(pcid, x - g2.first / 2, y - g2.second / 2);
|
|
|
|
} else
|
|
|
|
controls.analog(pcid, x / 2 , y / 2);
|
|
|
|
}
|
|
|
|
|
2011-10-05 02:24:34 +03:00
|
|
|
function_ptr_command<tokensplitter&> autofire("autofire", "Set autofire pattern",
|
|
|
|
"Syntax: autofire <buttons|->...\nSet autofire pattern\n",
|
|
|
|
[](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
|
|
|
|
if(!t)
|
|
|
|
throw std::runtime_error("Need at least one frame for autofire");
|
2012-01-09 21:55:55 +02:00
|
|
|
std::vector<controller_frame> new_autofire_pattern;
|
2011-10-05 02:24:34 +03:00
|
|
|
init_buttonmap();
|
|
|
|
while(t) {
|
|
|
|
std::string fpattern = t;
|
|
|
|
if(fpattern == "-")
|
2012-01-11 23:07:31 +02:00
|
|
|
new_autofire_pattern.push_back(controls.get_blank());
|
2011-10-05 02:24:34 +03:00
|
|
|
else {
|
2012-01-11 23:07:31 +02:00
|
|
|
controller_frame c(controls.get_blank());
|
2011-10-05 02:24:34 +03:00
|
|
|
while(fpattern != "") {
|
|
|
|
size_t split = fpattern.find_first_of(",");
|
|
|
|
std::string button = fpattern;
|
|
|
|
std::string rest;
|
|
|
|
if(split < fpattern.length()) {
|
|
|
|
button = fpattern.substr(0, split);
|
|
|
|
rest = fpattern.substr(split + 1);
|
|
|
|
}
|
|
|
|
if(!buttonmap.count(button)) {
|
|
|
|
std::ostringstream x;
|
|
|
|
x << "Invalid button '" << button << "'";
|
|
|
|
throw std::runtime_error(x.str());
|
|
|
|
}
|
|
|
|
auto g = buttonmap[button];
|
2012-01-11 23:07:31 +02:00
|
|
|
int x = controls.lcid_to_pcid(g.first);
|
|
|
|
if(x < 0) {
|
|
|
|
std::ostringstream x;
|
|
|
|
x << "No such controller #" << (g.first + 1) << std::endl;
|
|
|
|
throw std::runtime_error(x.str());
|
|
|
|
}
|
|
|
|
int bid = controls.button_id(x, g.second);
|
|
|
|
if(bid < 0) {
|
|
|
|
std::ostringstream x;
|
|
|
|
x << "Invalid button for controller type" << std::endl;
|
|
|
|
throw std::runtime_error(x.str());
|
|
|
|
}
|
|
|
|
c.axis(x, bid, true);
|
2011-10-05 02:24:34 +03:00
|
|
|
fpattern = rest;
|
|
|
|
}
|
|
|
|
new_autofire_pattern.push_back(c);
|
|
|
|
}
|
|
|
|
}
|
2012-01-11 23:07:31 +02:00
|
|
|
controls.autofire(new_autofire_pattern);
|
2011-10-05 02:24:34 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
class button_action : public command
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
button_action(const std::string& cmd, int _type, unsigned _controller, std::string _button)
|
|
|
|
throw(std::bad_alloc)
|
|
|
|
: command(cmd)
|
|
|
|
{
|
|
|
|
commandn = cmd;
|
|
|
|
type = _type;
|
|
|
|
controller = _controller;
|
|
|
|
button = _button;
|
|
|
|
}
|
|
|
|
~button_action() throw() {}
|
|
|
|
void invoke(const std::string& args) throw(std::bad_alloc, std::runtime_error)
|
|
|
|
{
|
|
|
|
if(args != "")
|
|
|
|
throw std::runtime_error("This command does not take parameters");
|
|
|
|
init_buttonmap();
|
|
|
|
if(!buttonmap.count(button))
|
|
|
|
return;
|
|
|
|
auto i = buttonmap[button];
|
|
|
|
do_button_action(i.first, i.second, (type != 1) ? 1 : 0, (type == 2));
|
|
|
|
update_movie_state();
|
2011-11-15 05:10:12 +02:00
|
|
|
information_dispatch::do_status_update();
|
2011-10-05 02:24:34 +03:00
|
|
|
}
|
|
|
|
std::string get_short_help() throw(std::bad_alloc)
|
|
|
|
{
|
|
|
|
return "Press/Unpress button";
|
|
|
|
}
|
|
|
|
std::string get_long_help() throw(std::bad_alloc)
|
|
|
|
{
|
|
|
|
return "Syntax: " + commandn + "\n"
|
|
|
|
"Presses/Unpresses button\n";
|
|
|
|
}
|
|
|
|
std::string commandn;
|
|
|
|
unsigned controller;
|
|
|
|
int type;
|
|
|
|
std::string button;
|
|
|
|
};
|
|
|
|
|
2012-01-17 23:48:13 +02:00
|
|
|
class analog_action : public command
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
analog_action(const std::string& cmd, unsigned _controller)
|
|
|
|
throw(std::bad_alloc)
|
|
|
|
: command(cmd)
|
|
|
|
{
|
|
|
|
controller = _controller;
|
|
|
|
}
|
|
|
|
~analog_action() throw() {}
|
|
|
|
void invoke(const std::string& args) throw(std::bad_alloc, std::runtime_error)
|
|
|
|
{
|
|
|
|
if(args != "")
|
|
|
|
throw std::runtime_error("This command does not take parameters");
|
|
|
|
keygroup* mouse_x = keygroup::lookup_by_name("mouse_x");
|
|
|
|
keygroup* mouse_y = keygroup::lookup_by_name("mouse_y");
|
|
|
|
if(!mouse_x || !mouse_y) {
|
|
|
|
messages << "Controller analog function not available without mouse" << std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
send_analog(controller, mouse_x->get_value(), mouse_y->get_value());
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
unsigned controller;
|
|
|
|
};
|
|
|
|
|
2011-10-05 02:24:34 +03:00
|
|
|
class button_action_helper
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
button_action_helper()
|
|
|
|
{
|
2012-01-11 23:07:31 +02:00
|
|
|
for(size_t i = 0; i < MAX_LOGICAL_BUTTONS; ++i)
|
2011-10-05 02:24:34 +03:00
|
|
|
for(int j = 0; j < 3; ++j)
|
|
|
|
for(unsigned k = 0; k < 8; ++k) {
|
2012-01-10 01:12:17 +02:00
|
|
|
std::string x, y;
|
|
|
|
char cstr[2] = {0, 0};
|
|
|
|
cstr[0] = 49 + k;
|
2011-10-05 02:24:34 +03:00
|
|
|
switch(j) {
|
|
|
|
case 0:
|
2012-01-10 01:12:17 +02:00
|
|
|
x = "+controller";
|
2011-10-05 02:24:34 +03:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-01-10 01:12:17 +02:00
|
|
|
x = "-controller";
|
2011-10-05 02:24:34 +03:00
|
|
|
break;
|
|
|
|
case 2:
|
2012-01-10 01:12:17 +02:00
|
|
|
x = "controllerh";
|
2011-10-05 02:24:34 +03:00
|
|
|
break;
|
|
|
|
};
|
2012-01-11 23:07:31 +02:00
|
|
|
x = x + cstr + get_logical_button_name(i);
|
|
|
|
y = cstr + get_logical_button_name(i);
|
2012-01-10 01:12:17 +02:00
|
|
|
our_commands.insert(new button_action(x, j, k, y));
|
2011-10-05 02:24:34 +03:00
|
|
|
}
|
2012-01-17 23:48:13 +02:00
|
|
|
for(unsigned k = 0; k < 8; ++k) {
|
|
|
|
std::string x = "controllerXanalog";
|
|
|
|
x[10] = 49 + k;
|
|
|
|
our_commands.insert(new analog_action(x, k));
|
|
|
|
}
|
2011-10-05 02:24:34 +03:00
|
|
|
}
|
2012-01-10 01:12:17 +02:00
|
|
|
~button_action_helper()
|
|
|
|
{
|
|
|
|
for(auto i : our_commands)
|
|
|
|
delete i;
|
|
|
|
our_commands.clear();
|
|
|
|
}
|
|
|
|
std::set<command*> our_commands;
|
2011-10-05 02:24:34 +03:00
|
|
|
} bah;
|
2011-09-16 06:13:33 +03:00
|
|
|
}
|
|
|
|
|
2012-01-11 23:07:31 +02:00
|
|
|
controller_state controls;
|