2012-06-30 12:42:29 +03:00
|
|
|
#include "core/emucore.hpp"
|
2012-02-23 16:48:56 +02:00
|
|
|
|
2012-01-09 21:55:55 +02:00
|
|
|
#include "core/controllerframe.hpp"
|
2012-01-11 23:07:31 +02:00
|
|
|
#include "core/dispatch.hpp"
|
|
|
|
#include "core/misc.hpp"
|
2012-01-09 21:55:55 +02:00
|
|
|
|
2012-01-11 17:31:25 +02:00
|
|
|
#include <cstdio>
|
2012-01-10 01:11:53 +02:00
|
|
|
#include <iostream>
|
|
|
|
|
2012-01-09 21:55:55 +02:00
|
|
|
namespace
|
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
port_type_set dummytypes;
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
controller_state::controller_state() throw()
|
|
|
|
{
|
|
|
|
for(size_t i = 0; i < MAX_ANALOG; i++) {
|
2012-10-11 20:06:40 +03:00
|
|
|
analog_indices[i] = std::make_pair(-1, -1);
|
2012-01-11 23:07:31 +02:00
|
|
|
analog_mouse[i] = false;
|
|
|
|
}
|
2012-10-11 20:06:40 +03:00
|
|
|
types = &dummytypes;
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
std::pair<int,int> controller_state::lcid_to_pcid(unsigned lcid) throw()
|
2012-01-11 23:07:31 +02:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
unsigned base = 0;
|
|
|
|
//Port 0 is system and never has logical controllers.
|
|
|
|
//First scan high-priority.
|
|
|
|
for(unsigned i = 1; i < types->ports(); i++) {
|
|
|
|
if(!types->port_type(i).controllers)
|
|
|
|
break;
|
|
|
|
if(base == lcid)
|
|
|
|
return std::make_pair(i, 0);
|
|
|
|
if(!types->port_type(i).priority && lcid < base + types->port_type(i).controllers)
|
|
|
|
return std::make_pair(i, lcid - base);
|
|
|
|
base += types->port_type(i).priority ? 1 : types->port_type(i).controllers;
|
|
|
|
}
|
|
|
|
//Then scan low-priority.
|
|
|
|
for(unsigned i = 1; i < types->ports(); i++) {
|
|
|
|
if(!types->port_type(i).controllers || !types->port_type(i).priority)
|
|
|
|
break;
|
|
|
|
if(lcid < base + types->port_type(i).controllers)
|
|
|
|
return std::make_pair(i, lcid - base - 1);
|
|
|
|
base += types->port_type(i).priority ? (types->port_type(i).controllers - 1) : 0;
|
|
|
|
}
|
|
|
|
return std::make_pair(-1, -1);
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
std::pair<int,int> controller_state::acid_to_pcid(unsigned acid) throw()
|
2012-01-11 23:07:31 +02:00
|
|
|
{
|
|
|
|
if(acid > MAX_ANALOG)
|
2012-10-11 20:06:40 +03:00
|
|
|
return std::make_pair(-1, -1);
|
2012-01-11 23:07:31 +02:00
|
|
|
return analog_indices[acid];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool controller_state::acid_is_mouse(unsigned acid) throw()
|
|
|
|
{
|
|
|
|
if(acid > MAX_ANALOG)
|
|
|
|
return -1;
|
|
|
|
return analog_mouse[acid];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
controller_frame controller_state::get(uint64_t framenum) throw()
|
|
|
|
{
|
|
|
|
if(_autofire.size())
|
2012-05-11 19:37:06 +03:00
|
|
|
return _input ^ _framehold ^ _autohold ^ _autofire[framenum % _autofire.size()];
|
2012-01-11 23:07:31 +02:00
|
|
|
else
|
2012-05-11 19:37:06 +03:00
|
|
|
return _input ^ _framehold ^ _autohold;
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
void controller_state::analog(unsigned port, unsigned controller, int x, int y) throw()
|
2012-01-11 23:07:31 +02:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
_input.axis3(port, controller, 0, x);
|
|
|
|
_input.axis3(port, controller, 1, y);
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void controller_state::reset(int32_t delay) throw()
|
|
|
|
{
|
|
|
|
if(delay >= 0) {
|
2012-10-11 20:06:40 +03:00
|
|
|
_input.axis3(0, 0, 1, 1);
|
|
|
|
_input.axis3(0, 0, 2, delay / 10000);
|
|
|
|
_input.axis3(0, 0, 3, delay % 10000);
|
2012-01-11 23:07:31 +02:00
|
|
|
} else {
|
2012-10-11 20:06:40 +03:00
|
|
|
_input.axis3(0, 0, 1, 0);
|
|
|
|
_input.axis3(0, 0, 2, 0);
|
|
|
|
_input.axis3(0, 0, 3, 0);
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
void controller_state::autohold2(unsigned port, unsigned controller, unsigned pbid, bool newstate) throw()
|
2012-01-11 23:07:31 +02:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
_autohold.axis3(port, controller, pbid, newstate ? 1 : 0);
|
|
|
|
information_dispatch::do_autohold_update(port, controller, pbid, newstate);
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
bool controller_state::autohold2(unsigned port, unsigned controller, unsigned pbid) throw()
|
2012-01-11 23:07:31 +02:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
return (_autohold.axis3(port, controller, pbid) != 0);
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
|
2012-05-11 19:37:06 +03:00
|
|
|
void controller_state::reset_framehold() throw()
|
|
|
|
{
|
|
|
|
_framehold = _framehold.blank_frame();
|
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
void controller_state::framehold2(unsigned port, unsigned controller, unsigned pbid, bool newstate) throw()
|
2012-05-11 19:37:06 +03:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
_framehold.axis3(port, controller, pbid, newstate ? 1 : 0);
|
2012-05-11 19:37:06 +03:00
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
bool controller_state::framehold2(unsigned port, unsigned controller, unsigned pbid) throw()
|
2012-05-11 19:37:06 +03:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
return (_framehold.axis3(port, controller, pbid) != 0);
|
2012-05-11 19:37:06 +03:00
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
void controller_state::button2(unsigned port, unsigned controller, unsigned pbid, bool newstate) throw()
|
2012-01-11 23:07:31 +02:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
_input.axis3(port, controller, pbid, newstate ? 1 : 0);
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
bool controller_state::button2(unsigned port, unsigned controller, unsigned pbid) throw()
|
2012-01-11 23:07:31 +02:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
return (_input.axis3(port, controller, pbid) != 0);
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void controller_state::autofire(std::vector<controller_frame> pattern) throw(std::bad_alloc)
|
|
|
|
{
|
|
|
|
_autofire = pattern;
|
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
int controller_state::button_id(unsigned port, unsigned controller, unsigned lbid) throw()
|
2012-01-11 23:07:31 +02:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
if(port >= types->ports())
|
2012-01-11 23:07:31 +02:00
|
|
|
return -1;
|
2012-10-11 20:06:40 +03:00
|
|
|
return types->port_type(port).button_id(controller, lbid);
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
void controller_state::set_ports(const port_type_set& ptype, bool set_core) throw(std::runtime_error)
|
2012-01-11 23:07:31 +02:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
const port_type_set* oldtype = types;
|
|
|
|
types = &ptype;
|
|
|
|
if(set_core) {
|
|
|
|
for(unsigned i = 1; i < types->ports(); i++)
|
|
|
|
types->port_type(i).set_core_controller(i);
|
|
|
|
}
|
|
|
|
if(oldtype != types) {
|
|
|
|
_input.set_types(ptype);
|
|
|
|
_autohold.set_types(ptype);
|
|
|
|
_committed.set_types(ptype);
|
|
|
|
_framehold.set_types(ptype);
|
2012-01-11 23:07:31 +02:00
|
|
|
//The old autofire pattern no longer applies.
|
|
|
|
_autofire.clear();
|
|
|
|
}
|
|
|
|
int i = 0;
|
|
|
|
for(unsigned j = 0; j < MAX_ANALOG; j++)
|
2012-10-11 20:06:40 +03:00
|
|
|
analog_indices[j] = std::make_pair(-1, -1);
|
|
|
|
for(unsigned j = 0; j < types->ports(); j++) {
|
|
|
|
for(unsigned k = 0; k < types->port_type(j).controllers; k++) {
|
|
|
|
if(types->port_type(j).is_mouse(k)) {
|
|
|
|
analog_mouse[i] = true;
|
|
|
|
analog_indices[i++] = std::make_pair(j, k);
|
|
|
|
} else if(types->port_type(j).is_analog(k)) {
|
|
|
|
analog_mouse[i] = false;
|
|
|
|
analog_indices[i++] = std::make_pair(j, k);
|
|
|
|
}
|
|
|
|
if(i == MAX_ANALOG)
|
|
|
|
break;
|
2012-01-11 23:07:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
information_dispatch::do_autohold_reconfigure();
|
|
|
|
}
|
|
|
|
|
|
|
|
controller_frame controller_state::get_blank() throw()
|
|
|
|
{
|
|
|
|
return _input.blank_frame();
|
|
|
|
}
|
|
|
|
|
2012-01-13 06:51:47 +02:00
|
|
|
controller_frame controller_state::commit(uint64_t framenum) throw()
|
|
|
|
{
|
|
|
|
controller_frame f = get(framenum);
|
|
|
|
_committed = f;
|
|
|
|
return _committed;
|
|
|
|
}
|
|
|
|
|
|
|
|
controller_frame controller_state::get_committed() throw()
|
|
|
|
{
|
|
|
|
return _committed;
|
|
|
|
}
|
|
|
|
|
|
|
|
controller_frame controller_state::commit(controller_frame controls) throw()
|
|
|
|
{
|
|
|
|
_committed = controls;
|
|
|
|
return _committed;
|
|
|
|
}
|
2012-01-17 23:48:13 +02:00
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
bool controller_state::is_present(unsigned port, unsigned controller) throw()
|
2012-07-08 12:57:22 +03:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
return _input.is_present(port, controller);
|
2012-07-08 12:57:22 +03:00
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
bool controller_state::is_analog(unsigned port, unsigned controller) throw()
|
2012-01-17 23:48:13 +02:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
return _input.is_analog(port, controller);
|
2012-01-17 23:48:13 +02:00
|
|
|
}
|
|
|
|
|
2012-10-11 20:06:40 +03:00
|
|
|
bool controller_state::is_mouse(unsigned port, unsigned controller) throw()
|
2012-01-17 23:48:13 +02:00
|
|
|
{
|
2012-10-11 20:06:40 +03:00
|
|
|
return _input.is_mouse(port, controller);
|
2012-01-17 23:48:13 +02:00
|
|
|
}
|