lsnes/include/core/controllerdata.hpp
2011-11-06 14:41:41 +02:00

427 lines
12 KiB
C++

#ifndef _controllerdata__hpp__included__
#define _controllerdata__hpp__included__
#include <vector>
#include <stdexcept>
#define ENCODE_SPECIAL_NO_OUTPUT 0xFFFFFFFFU
/**
* What version to write as control version?
*/
#define WRITE_CONTROL_VERSION 0
/**
* System control: Frame sync flag
*/
#define CONTROL_FRAME_SYNC 0
/**
* System control: System reset button
*/
#define CONTROL_SYSTEM_RESET 1
/**
* High part of cycle count for system reset (multiplier 10000).
*/
#define CONTROL_SYSTEM_RESET_CYCLES_HI 2
/**
* Low part of cycle count for system reset (multiplier 1).
*/
#define CONTROL_SYSTEM_RESET_CYCLES_LO 3
/**
* Number of system controls.
*/
#define MAX_SYSTEM_CONTROLS 4
/**
* SNES has 2 controller ports.
*/
#define MAX_PORTS 2
/**
* Multitap can connect 4 controllers to a single port.
*/
#define MAX_CONTROLLERS_PER_PORT 4
/**
* Ordinary gamepad has 12 buttons/axis total (more than anything else supported).
*/
#define CONTROLLER_CONTROLS 12
/**
* The total number of controls (currently 100).
*/
#define TOTAL_CONTROLS (MAX_SYSTEM_CONTROLS + MAX_PORTS * CONTROLLER_CONTROLS * MAX_CONTROLLERS_PER_PORT)
struct controls_t;
/**
* Decoders
*/
class cdecode
{
public:
/**
* This is type of functions that perform decoding of port fields.
*
* parameter port: The number of port to decode.
* parameter line: The line to decode from.
* parameter pos: Position on the line to start from.
* parameter controls: Buffer to place the read controls to.
* returns: End of fields (end of string or on '|') or start of next field (otherwise).
* throws std::bad_alloc: Not enough memory.
* throws std::runtime_error: Bad input.
*/
typedef size_t (*fn_t)(unsigned port, const std::string& line, size_t pos, short* controls);
/**
* This is a decoder for the system field. Note that this is not compatible with fn_t as parameters are diffrent.
*
* parameter port: The number of port to decode.
* parameter line: The line to decode from.
* parameter pos: Position on the line to start from.
* parameter controls: Buffer to place the read controls to.
* parameter version: The version of control structure to read.
* returns: End of fields or start of next field.
* throws std::bad_alloc: Not enough memory.
* throws std::runtime_error: Bad input.
*/
static size_t system(const std::string& line, size_t pos, short* controls, unsigned version)
throw(std::bad_alloc, std::runtime_error);
/**
* This is a port decoder for port type none (see fn_t).
*/
static size_t none(unsigned port, const std::string& line, size_t pos, short* controls)
throw(std::bad_alloc, std::runtime_error);
/**
* This is a port decoder for port type gamepad (see fn_t).
*/
static size_t gamepad(unsigned port, const std::string& line, size_t pos, short* controls)
throw(std::bad_alloc, std::runtime_error);
/**
* This is a port decoder for port type multitap (see fn_t).
*/
static size_t multitap(unsigned port, const std::string& line, size_t pos, short* controls)
throw(std::bad_alloc, std::runtime_error);
/**
* This is a port decoder for port type mouse (see fn_t).
*/
static size_t mouse(unsigned port, const std::string& line, size_t pos, short* controls)
throw(std::bad_alloc, std::runtime_error);
/**
* This is a port decoder for port type superscope (see fn_t).
*/
static size_t superscope(unsigned port, const std::string& line, size_t pos, short* controls)
throw(std::bad_alloc, std::runtime_error);
/**
* This is a port decoder for port type justifier (see fn_t).
*/
static size_t justifier(unsigned port, const std::string& line, size_t pos, short* controls)
throw(std::bad_alloc, std::runtime_error);
/**
* This is a port decoder for port type justifiers (see fn_t).
*/
static size_t justifiers(unsigned port, const std::string& line, size_t pos, short* controls)
throw(std::bad_alloc, std::runtime_error);
};
/**
* Encoders
*/
class cencode
{
public:
/**
* This is the type of functions that perform encoding of port fields.
*
* parameter port: To number of port to encode.
* parameter buffer: Buffer to store the encoded data to.
* parameter pos: Position to start writing to.
* parameter controls: Buffer to read the controls from.
* returns: Position after written data, or ENCODE_SPECIAL_NO_OUTPUT if one wants no output, suppressing even the
* field terminator.
* throws std::bad_alloc: Not enough memory.
*/
typedef size_t (*fn_t)(unsigned port, char* buffer, size_t pos, const short* controls);
/**
* This is encoder for the system field. Note that the parameters are bit diffrent and this can't be put into fn_t.
*
* parameter buffer: Buffer to store the encoded data to.
* parameter pos: Position to start writing to.
* parameter controls: Buffer to read the controls from.
* returns: Position after written data, or ENCODE_SPECIAL_NO_OUTPUT if one wants no output, suppressing even the
* field terminator.
* throws std::bad_alloc: Not enough memory.
*/
static size_t system(char* buffer, size_t pos, const short* controls) throw(std::bad_alloc);
/**
* This is a port encoder for port type none. See fn_t.
*/
static size_t none(unsigned port, char* buffer, size_t pos, const short* controls) throw(std::bad_alloc);
/**
* This is a port encoder for port type gamepad. See fn_t.
*/
static size_t gamepad(unsigned port, char* buffer, size_t pos, const short* controls) throw(std::bad_alloc);
/**
* This is a port encoder for port type multitap. See fn_t.
*/
static size_t multitap(unsigned port, char* buffer, size_t pos, const short* controls) throw(std::bad_alloc);
/**
* This is a port encoder for port type mouse. See fn_t.
*/
static size_t mouse(unsigned port, char* buffer, size_t pos, const short* controls) throw(std::bad_alloc);
/**
* This is a port encoder for port type superscope. See fn_t.
*/
static size_t superscope(unsigned port, char* buffer, size_t pos, const short* controls) throw(std::bad_alloc);
/**
* This is a port encoder for port type justifier. See fn_t.
*/
static size_t justifier(unsigned port, char* buffer, size_t pos, const short* controls) throw(std::bad_alloc);
/**
* This is a port encoder for port type justifiers. See fn_t.
*/
static size_t justifiers(unsigned port, char* buffer, size_t pos, const short* controls) throw(std::bad_alloc);
};
/**
* This structure holds controls for single (sub)frame or instant of time.
*/
struct controls_t
{
/**
* Creates new controls structure. All buttons are released and all axes are 0 (neutral).
*
* parameter sync: If true, write 1 (pressed) to frame sync subfield, else write 0 (released). Default false.
*/
explicit controls_t(bool sync = false) throw();
/**
* This constructor takes in a line of input, port decoders and system field version and decodes the controls.
*
* parameter line: The line to decode.
* parameter decoders: The decoders for each port.
* parameter version: Version for the system field.
* throws std::bad_alloc: Not enough memory.
* throws std::runtime_error: Invalid input line.
*/
controls_t(const std::string& line, const std::vector<cdecode::fn_t>& decoders, unsigned version)
throw(std::bad_alloc, std::runtime_error);
/**
* This method takes in port encoders and encodes the controls.
*
* parameter encoders: The encoders for each port.
* returns: The encoded controls.
* throws std::bad_alloc: Not enough memory.
*/
std::string tostring(const std::vector<cencode::fn_t>& encoders) const throw(std::bad_alloc);
/**
* This method takes in controller (port, controller, control) tuple and returns reference to the value of that
* control.
*
* parameter port: The port number
* parameter controller: The controller number within that port.
* parameter control: The control number within that controller.
* returns: Reference to control value.
* throws std::logic_error: port, controller or control is invalid.
*/
const short& operator()(unsigned port, unsigned controller, unsigned control) const throw(std::logic_error);
/**
* This method takes in control index and returns reference to the value of that control.
*
* parameter control: The control index number.
* returns: Reference to control value.
* throws std::logic_error: control index is invalid.
*/
const short& operator()(unsigned control) const throw(std::logic_error);
/**
* This method takes in controller (port, controller, control) tuple and returns reference to the value of that
* control.
*
* parameter port: The port number
* parameter controller: The controller number within that port.
* parameter control: The control number within that controller.
* returns: Reference to control value.
* throws std::logic_error: port, controller or control is invalid.
*/
short& operator()(unsigned port, unsigned controller, unsigned control) throw(std::logic_error);
/**
* This method takes in control index and returns reference to the value of that control.
*
* parameter control: The control index number.
* returns: Reference to control value.
* throws std::logic_error: control index is invalid.
*/
short& operator()(unsigned control) throw(std::logic_error);
/**
* Perform XOR per-control.
*
* parameter other: The othe field to XOR with.
* returns: The XOR result.
*/
controls_t operator^(controls_t other) throw();
/**
* This field contains the raw controller data. Avoid manipulating directly.
*/
short controls[TOTAL_CONTROLS];
/**
* Equality
*/
bool operator==(const controls_t& c) const throw();
};
/**
* This enumeration gives the type of port.
*/
enum porttype_t
{
/**
* No device
*/
PT_NONE = 0, //Nothing connected to port.
/**
* Gamepad
*/
PT_GAMEPAD = 1,
/**
* Multitap (with 4 gamepads connected)
*/
PT_MULTITAP = 2,
/**
* Mouse
*/
PT_MOUSE = 3,
/**
* Superscope (only allowed for port 2).
*/
PT_SUPERSCOPE = 4,
/**
* Justifier (only allowed for port 2).
*/
PT_JUSTIFIER = 5,
/**
* 2 Justifiers (only allowed for port 2).
*/
PT_JUSTIFIERS = 6,
/**
* Number of controller types.
*/
PT_LAST_CTYPE = 6,
/**
* Invalid controller type.
*/
PT_INVALID = PT_LAST_CTYPE + 1
};
/**
* This enumeration gives the type of device.
*/
enum devicetype_t
{
/**
* No device
*/
DT_NONE = 0,
/**
* Gamepad (note that multitap controllers are gamepads)
*/
DT_GAMEPAD = 1,
/**
* Mouse
*/
DT_MOUSE = 3,
/**
* Superscope
*/
DT_SUPERSCOPE = 4,
/**
* Justifier (note that justifiers is two of these).
*/
DT_JUSTIFIER = 5
};
/**
* Information about port type.
*/
struct port_type
{
/**
* Name of type.
*/
const char* name;
/**
* Decoder function.
*/
cdecode::fn_t decoder;
/**
* Encoder function.
*/
cencode::fn_t encoder;
/**
* Port type value.
*/
porttype_t ptype;
/**
* Number of devices.
*/
unsigned devices;
/**
* Type of each connected device.
*/
devicetype_t dtype;
/**
* True if valid for port1&2, false if valid for only for port 2.
*/
bool valid_port1;
/**
* BSNES controller type ID.
*/
unsigned bsnes_type;
/**
* Lookup port type by name.
*
* parameter name: Name of the port type to look up.
* parameter port2: True if controller is for port 2, false if for port 1.
* returns: The port type structure
* throws std::bad_alloc: Not enough memory.
* throws std::runtime_error: Invalid port type.
*/
static const port_type& lookup(const std::string& name, bool port2 = true) throw(std::bad_alloc,
std::runtime_error);
};
/**
* Information about port types, index by port type value (porttype_t).
*/
extern port_type port_types[];
/**
* This method takes in controller (port, controller, control) tuple and returns the system index corresponding to
* that control.
*
* parameter port: The port number
* parameter controller: The controller number within that port.
* parameter control: The control number within that controller.
* returns: The control index.
* throws std::logic_error: port, controller or control is invalid.
*/
unsigned ccindex2(unsigned port, unsigned controller, unsigned control) throw(std::logic_error);
#endif