lsnes/controllerdata.hpp
Ilari Liusvaara e0a4bfa510 Get rid of fieldsplitter
It was used more before, now it was just used to split author names
into component parts. This can be much better done with a dedicated
function.
2011-09-17 10:15:35 +03:00

421 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.
*/
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