/*************************************************************************** inptport.h Handle input ports and mappings. Copyright Nicola Salmoria and the MAME Team. Visit http://mamedev.org for licensing and usage restrictions. ***************************************************************************/ #pragma once #ifndef __EMU_H__ #error Dont include this file directly; include emu.h instead. #endif #ifndef __INPTPORT_H__ #define __INPTPORT_H__ #include /*************************************************************************** CONSTANTS ***************************************************************************/ #define MAX_PLAYERS 8 #define IP_ACTIVE_HIGH 0x00000000 #define IP_ACTIVE_LOW 0xffffffff /* flags for input_field_configs */ #define FIELD_FLAG_UNUSED 0x01 /* set if this field is unused but relevant to other games on the same hw */ #define FIELD_FLAG_COCKTAIL 0x02 /* set if this field is relevant only for cocktail cabinets */ #define FIELD_FLAG_TOGGLE 0x04 /* set if this field should behave as a toggle */ #define FIELD_FLAG_ROTATED 0x08 /* set if this field represents a rotated control */ #define ANALOG_FLAG_REVERSE 0x10 /* analog only: reverse the sense of the axis */ #define ANALOG_FLAG_RESET 0x20 /* analog only: always preload in->default for relative axes, returning only deltas */ #define ANALOG_FLAG_WRAPS 0x40 /* analog only: positional count wraps around */ #define ANALOG_FLAG_INVERT 0x80 /* analog only: bitwise invert bits */ /* INP file information */ #define INP_HEADER_SIZE 64 #define INP_HEADER_MAJVERSION 3 #define INP_HEADER_MINVERSION 0 /* sequence types for input_port_seq() call */ enum _input_seq_type { SEQ_TYPE_STANDARD = 0, SEQ_TYPE_INCREMENT, SEQ_TYPE_DECREMENT, SEQ_TYPE_TOTAL }; typedef enum _input_seq_type input_seq_type; DECLARE_ENUM_OPERATORS(input_seq_type) /* conditions for DIP switches */ enum { PORTCOND_ALWAYS = 0, PORTCOND_EQUALS, PORTCOND_NOTEQUALS, PORTCOND_GREATERTHAN, PORTCOND_NOTGREATERTHAN, PORTCOND_LESSTHAN, PORTCOND_NOTLESSTHAN }; /* crosshair types */ enum { CROSSHAIR_AXIS_NONE = 0, CROSSHAIR_AXIS_X, CROSSHAIR_AXIS_Y }; /* groups for input ports */ enum ioport_group { IPG_UI = 0, IPG_PLAYER1, IPG_PLAYER2, IPG_PLAYER3, IPG_PLAYER4, IPG_PLAYER5, IPG_PLAYER6, IPG_PLAYER7, IPG_PLAYER8, IPG_OTHER, IPG_TOTAL_GROUPS, IPG_INVALID }; /* various input port types */ enum { /* pseudo-port types */ IPT_INVALID = 0, IPT_UNUSED, IPT_END, IPT_UNKNOWN, IPT_PORT, IPT_DIPSWITCH, IPT_VBLANK, IPT_CONFIG, IPT_CATEGORY, /* MESS only */ /* start buttons */ IPT_START1, IPT_START2, IPT_START3, IPT_START4, IPT_START5, IPT_START6, IPT_START7, IPT_START8, /* coin slots */ IPT_COIN1, IPT_COIN2, IPT_COIN3, IPT_COIN4, IPT_COIN5, IPT_COIN6, IPT_COIN7, IPT_COIN8, IPT_COIN9, IPT_COIN10, IPT_COIN11, IPT_COIN12, IPT_BILL1, /* service coin */ IPT_SERVICE1, IPT_SERVICE2, IPT_SERVICE3, IPT_SERVICE4, /* tilt inputs */ IPT_TILT1, IPT_TILT2, IPT_TILT3, IPT_TILT4, /* misc other digital inputs */ IPT_SERVICE, IPT_TILT, IPT_INTERLOCK, IPT_VOLUME_UP, IPT_VOLUME_DOWN, IPT_START, /* MESS only */ IPT_SELECT, /* MESS only */ IPT_KEYPAD, /* MESS only */ IPT_KEYBOARD, /* MESS only */ #define __ipt_digital_joystick_start IPT_JOYSTICK_UP /* use IPT_JOYSTICK for panels where the player has one single joystick */ IPT_JOYSTICK_UP, IPT_JOYSTICK_DOWN, IPT_JOYSTICK_LEFT, IPT_JOYSTICK_RIGHT, /* use IPT_JOYSTICKLEFT and IPT_JOYSTICKRIGHT for dual joystick panels */ IPT_JOYSTICKRIGHT_UP, IPT_JOYSTICKRIGHT_DOWN, IPT_JOYSTICKRIGHT_LEFT, IPT_JOYSTICKRIGHT_RIGHT, IPT_JOYSTICKLEFT_UP, IPT_JOYSTICKLEFT_DOWN, IPT_JOYSTICKLEFT_LEFT, IPT_JOYSTICKLEFT_RIGHT, #define __ipt_digital_joystick_end IPT_JOYSTICKLEFT_RIGHT /* action buttons */ IPT_BUTTON1, IPT_BUTTON2, IPT_BUTTON3, IPT_BUTTON4, IPT_BUTTON5, IPT_BUTTON6, IPT_BUTTON7, IPT_BUTTON8, IPT_BUTTON9, IPT_BUTTON10, IPT_BUTTON11, IPT_BUTTON12, IPT_BUTTON13, IPT_BUTTON14, IPT_BUTTON15, IPT_BUTTON16, /* mahjong inputs */ IPT_MAHJONG_A, IPT_MAHJONG_B, IPT_MAHJONG_C, IPT_MAHJONG_D, IPT_MAHJONG_E, IPT_MAHJONG_F, IPT_MAHJONG_G, IPT_MAHJONG_H, IPT_MAHJONG_I, IPT_MAHJONG_J, IPT_MAHJONG_K, IPT_MAHJONG_L, IPT_MAHJONG_M, IPT_MAHJONG_N, IPT_MAHJONG_O, IPT_MAHJONG_P, IPT_MAHJONG_Q, IPT_MAHJONG_KAN, IPT_MAHJONG_PON, IPT_MAHJONG_CHI, IPT_MAHJONG_REACH, IPT_MAHJONG_RON, IPT_MAHJONG_BET, IPT_MAHJONG_LAST_CHANCE, IPT_MAHJONG_SCORE, IPT_MAHJONG_DOUBLE_UP, IPT_MAHJONG_FLIP_FLOP, IPT_MAHJONG_BIG, IPT_MAHJONG_SMALL, /* hanafuda inputs */ IPT_HANAFUDA_A, IPT_HANAFUDA_B, IPT_HANAFUDA_C, IPT_HANAFUDA_D, IPT_HANAFUDA_E, IPT_HANAFUDA_F, IPT_HANAFUDA_G, IPT_HANAFUDA_H, IPT_HANAFUDA_YES, IPT_HANAFUDA_NO, /* gambling inputs */ IPT_GAMBLE_HIGH, IPT_GAMBLE_LOW, IPT_GAMBLE_HALF, IPT_GAMBLE_DEAL, IPT_GAMBLE_D_UP, IPT_GAMBLE_TAKE, IPT_GAMBLE_STAND, IPT_GAMBLE_BET, IPT_GAMBLE_KEYIN, IPT_GAMBLE_KEYOUT, IPT_GAMBLE_PAYOUT, IPT_GAMBLE_DOOR, IPT_GAMBLE_SERVICE, IPT_GAMBLE_BOOK, /* poker-specific inputs */ IPT_POKER_HOLD1, IPT_POKER_HOLD2, IPT_POKER_HOLD3, IPT_POKER_HOLD4, IPT_POKER_HOLD5, IPT_POKER_CANCEL, IPT_POKER_BET, /* slot-specific inputs */ IPT_SLOT_STOP1, IPT_SLOT_STOP2, IPT_SLOT_STOP3, IPT_SLOT_STOP4, IPT_SLOT_STOP_ALL, /* analog inputs */ #define __ipt_analog_start IPT_PADDLE #define __ipt_analog_absolute_start IPT_PADDLE IPT_PADDLE, /* absolute */ IPT_PADDLE_V, /* absolute */ IPT_AD_STICK_X, /* absolute */ IPT_AD_STICK_Y, /* absolute */ IPT_AD_STICK_Z, /* absolute */ IPT_LIGHTGUN_X, /* absolute */ IPT_LIGHTGUN_Y, /* absolute */ IPT_PEDAL, /* absolute */ IPT_PEDAL2, /* absolute */ IPT_PEDAL3, /* absolute */ IPT_POSITIONAL, /* absolute */ IPT_POSITIONAL_V, /* absolute */ #define __ipt_analog_absolute_end IPT_POSITIONAL_V IPT_DIAL, /* relative */ IPT_DIAL_V, /* relative */ IPT_TRACKBALL_X, /* relative */ IPT_TRACKBALL_Y, /* relative */ IPT_MOUSE_X, /* relative */ IPT_MOUSE_Y, /* relative */ #define __ipt_analog_end IPT_MOUSE_Y /* analog adjuster support */ IPT_ADJUSTER, /* the following are special codes for user interface handling - not to be used by drivers! */ #define __ipt_ui_start IPT_UI_CONFIGURE IPT_UI_CONFIGURE, IPT_UI_ON_SCREEN_DISPLAY, IPT_UI_DEBUG_BREAK, IPT_UI_PAUSE, IPT_UI_RESET_MACHINE, IPT_UI_SOFT_RESET, IPT_UI_SHOW_GFX, IPT_UI_FRAMESKIP_DEC, IPT_UI_FRAMESKIP_INC, IPT_UI_THROTTLE, IPT_UI_FAST_FORWARD, IPT_UI_SHOW_FPS, IPT_UI_SNAPSHOT, IPT_UI_RECORD_MOVIE, IPT_UI_TOGGLE_CHEAT, IPT_UI_UP, IPT_UI_DOWN, IPT_UI_LEFT, IPT_UI_RIGHT, IPT_UI_HOME, IPT_UI_END, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, IPT_UI_SELECT, IPT_UI_CANCEL, IPT_UI_DISPLAY_COMMENT, IPT_UI_CLEAR, IPT_UI_ZOOM_IN, IPT_UI_ZOOM_OUT, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, IPT_UI_ROTATE, IPT_UI_SHOW_PROFILER, IPT_UI_TOGGLE_UI, IPT_UI_TOGGLE_DEBUG, IPT_UI_PASTE, IPT_UI_SAVE_STATE, IPT_UI_LOAD_STATE, /* additional OSD-specified UI port types (up to 16) */ IPT_OSD_1, IPT_OSD_2, IPT_OSD_3, IPT_OSD_4, IPT_OSD_5, IPT_OSD_6, IPT_OSD_7, IPT_OSD_8, IPT_OSD_9, IPT_OSD_10, IPT_OSD_11, IPT_OSD_12, IPT_OSD_13, IPT_OSD_14, IPT_OSD_15, IPT_OSD_16, #define __ipt_ui_end IPT_OSD_16 /* other meaning not mapped to standard defaults */ IPT_OTHER, /* special meaning handled by custom code */ IPT_SPECIAL, IPT_OUTPUT, __ipt_max }; /* default strings used in port definitions */ enum { INPUT_STRING_Off = 1, INPUT_STRING_On, INPUT_STRING_No, INPUT_STRING_Yes, INPUT_STRING_Lives, INPUT_STRING_Bonus_Life, INPUT_STRING_Difficulty, INPUT_STRING_Demo_Sounds, INPUT_STRING_Coinage, INPUT_STRING_Coin_A, INPUT_STRING_Coin_B, INPUT_STRING_9C_1C, INPUT_STRING_8C_1C, INPUT_STRING_7C_1C, INPUT_STRING_6C_1C, INPUT_STRING_5C_1C, INPUT_STRING_4C_1C, INPUT_STRING_3C_1C, INPUT_STRING_8C_3C, INPUT_STRING_4C_2C, INPUT_STRING_2C_1C, INPUT_STRING_5C_3C, INPUT_STRING_3C_2C, INPUT_STRING_4C_3C, INPUT_STRING_4C_4C, INPUT_STRING_3C_3C, INPUT_STRING_2C_2C, INPUT_STRING_1C_1C, INPUT_STRING_4C_5C, INPUT_STRING_3C_4C, INPUT_STRING_2C_3C, INPUT_STRING_4C_7C, INPUT_STRING_2C_4C, INPUT_STRING_1C_2C, INPUT_STRING_2C_5C, INPUT_STRING_2C_6C, INPUT_STRING_1C_3C, INPUT_STRING_2C_7C, INPUT_STRING_2C_8C, INPUT_STRING_1C_4C, INPUT_STRING_1C_5C, INPUT_STRING_1C_6C, INPUT_STRING_1C_7C, INPUT_STRING_1C_8C, INPUT_STRING_1C_9C, INPUT_STRING_Free_Play, INPUT_STRING_Cabinet, INPUT_STRING_Upright, INPUT_STRING_Cocktail, INPUT_STRING_Flip_Screen, INPUT_STRING_Service_Mode, INPUT_STRING_Pause, INPUT_STRING_Test, INPUT_STRING_Tilt, INPUT_STRING_Version, INPUT_STRING_Region, INPUT_STRING_International, INPUT_STRING_Japan, INPUT_STRING_USA, INPUT_STRING_Europe, INPUT_STRING_Asia, INPUT_STRING_World, INPUT_STRING_Hispanic, INPUT_STRING_Language, INPUT_STRING_English, INPUT_STRING_Japanese, INPUT_STRING_German, INPUT_STRING_French, INPUT_STRING_Italian, INPUT_STRING_Spanish, INPUT_STRING_Very_Easy, INPUT_STRING_Easiest, INPUT_STRING_Easier, INPUT_STRING_Easy, INPUT_STRING_Medium_Easy, INPUT_STRING_Normal, INPUT_STRING_Medium, INPUT_STRING_Medium_Hard, INPUT_STRING_Hard, INPUT_STRING_Harder, INPUT_STRING_Hardest, INPUT_STRING_Very_Hard, INPUT_STRING_Medium_Difficult, INPUT_STRING_Difficult, INPUT_STRING_More_Difficult, INPUT_STRING_Most_Difficult, INPUT_STRING_Very_Difficult, INPUT_STRING_Very_Low, INPUT_STRING_Low, INPUT_STRING_High, INPUT_STRING_Higher, INPUT_STRING_Highest, INPUT_STRING_Very_High, INPUT_STRING_Players, INPUT_STRING_Controls, INPUT_STRING_Dual, INPUT_STRING_Single, INPUT_STRING_Game_Time, INPUT_STRING_Continue_Price, INPUT_STRING_Controller, INPUT_STRING_Light_Gun, INPUT_STRING_Joystick, INPUT_STRING_Trackball, INPUT_STRING_Continues, INPUT_STRING_Allow_Continue, INPUT_STRING_Level_Select, INPUT_STRING_Infinite, INPUT_STRING_Stereo, INPUT_STRING_Mono, INPUT_STRING_Unused, INPUT_STRING_Unknown, INPUT_STRING_Standard, INPUT_STRING_Reverse, INPUT_STRING_Alternate, INPUT_STRING_None, INPUT_STRING_COUNT }; /* input classes */ enum { INPUT_CLASS_INTERNAL, INPUT_CLASS_KEYBOARD, INPUT_CLASS_CONTROLLER, INPUT_CLASS_CONFIG, INPUT_CLASS_DIPSWITCH, INPUT_CLASS_CATEGORIZED, INPUT_CLASS_MISC }; #define UCHAR_PRIVATE (0x100000) #define UCHAR_SHIFT_1 (UCHAR_PRIVATE + 0) #define UCHAR_SHIFT_2 (UCHAR_PRIVATE + 1) #define UCHAR_MAMEKEY_BEGIN (UCHAR_PRIVATE + 2) #define UCHAR_MAMEKEY(code) (UCHAR_MAMEKEY_BEGIN + ITEM_ID_##code) #define UCHAR_SHIFT_BEGIN (UCHAR_SHIFT_1) #define UCHAR_SHIFT_END (UCHAR_SHIFT_2) /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ /* input ports support up to 32 bits each */ typedef UINT32 input_port_value; /* opaque types pointing to live state */ typedef struct _input_port_state input_port_state; typedef struct _input_field_state input_field_state; /* forward declarations */ class input_port_config; class input_field_config; /* template specializations */ typedef tagged_list ioport_list; /* read input port callback function */ typedef delegate input_field_read_delegate; /* input port write callback function */ typedef delegate input_field_write_delegate; /* crosshair mapping function */ typedef delegate input_field_crossmap_delegate; /* encapsulates a condition on a port field or setting */ typedef struct _input_condition input_condition; struct _input_condition { const char * tag; /* tag of port whose condition is to be tested */ input_port_value mask; /* mask to apply to the port */ input_port_value value; /* value to compare against */ UINT8 condition; /* condition to use */ }; /* a single setting for a configuration or DIP switch */ class input_setting_config { DISABLE_COPYING(input_setting_config); friend class simple_list; public: input_setting_config(input_field_config &field, input_port_value value, const char *name); input_setting_config *next() const { return m_next; } input_port_value value; /* value of the bits in this setting */ input_condition condition; /* condition under which this setting is valid */ const char * name; /* user-friendly name to display */ UINT16 category; /* (MESS-specific) category */ private: input_field_config & m_field; /* pointer back to the field that owns us */ input_setting_config * m_next; /* pointer to next setting in sequence */ }; /* a mapping from a bit to a physical DIP switch description */ class input_field_diplocation { DISABLE_COPYING(input_field_diplocation); friend class simple_list; public: input_field_diplocation(const char *string, UINT8 swnum, bool invert); input_field_diplocation *next() const { return m_next; } astring swname; /* name of the physical DIP switch */ UINT8 swnum; /* physical switch number */ bool invert; /* is this an active-high DIP? */ private: input_field_diplocation * m_next; /* pointer to the next bit */ }; /* a single bitfield within an input port */ class input_field_config { DISABLE_COPYING(input_field_config); friend class simple_list; public: input_field_config(input_port_config &port, int type, input_port_value defvalue, input_port_value maskbits, const char *name = NULL); input_field_config *next() const { return m_next; } input_port_config &port() const { return m_port; } running_machine &machine() const; simple_list &settinglist() { return m_settinglist; } const simple_list &settinglist() const { return m_settinglist; } simple_list &diploclist() { return m_diploclist; } int modcount() const { return m_modcount; } /* generally-applicable data */ input_port_value mask; /* mask of bits belonging to the field */ input_port_value defvalue; /* default value of these bits */ input_condition condition; /* condition under which this field is relevant */ UINT32 type; /* IPT_* type for this port */ UINT8 player; /* player number (0-based) */ UINT16 category; /* (MESS-specific) category */ UINT32 flags; /* combination of FIELD_FLAG_* and ANALOG_FLAG_* above */ UINT8 impulse; /* number of frames before reverting to defvalue */ const char * name; /* user-friendly name to display */ input_seq seq[SEQ_TYPE_TOTAL];/* sequences of all types */ input_field_read_delegate read; /* read callback routine */ void * read_param; /* parameter for read callback routine */ const char * read_device; /* parameter for read callback routine */ input_field_write_delegate write; /* write callback routine */ void * write_param; /* parameter for write callback routine */ const char * write_device; /* parameter for write callback routine */ /* data relevant to analog control types */ INT32 min; /* minimum value for absolute axes */ INT32 max; /* maximum value for absolute axes */ INT32 sensitivity; /* sensitivity (100=normal) */ INT32 delta; /* delta to apply each frame a digital inc/dec key is pressed */ INT32 centerdelta; /* delta to apply each frame no digital inputs are pressed */ UINT8 crossaxis; /* crosshair axis */ double crossscale; /* crosshair scale */ double crossoffset; /* crosshair offset */ double crossaltaxis; /* crosshair alternate axis value */ input_field_crossmap_delegate crossmapper; /* crosshair mapping function */ const char * crossmapper_device; /* parameter for write callback routine */ UINT16 full_turn_count;/* number of optical counts for 1 full turn of the original control */ const input_port_value * remap_table; /* pointer to an array that remaps the port value */ /* data relevant to other specific types */ UINT8 way; /* digital joystick 2/4/8-way descriptions */ unicode_char chars[3]; /* (MESS-specific) unicode key data */ /* this field is only valid if the device is live */ input_field_state * state; /* live state of field (NULL if not live) */ private: input_field_config * m_next; /* pointer to next field in sequence */ input_port_config & m_port; /* pointer back to the port that owns us */ int m_modcount; simple_list m_settinglist; /* list of input_setting_configs */ simple_list m_diploclist; /* list of locations for various bits */ }; /* user-controllable settings for a field */ typedef struct _input_field_user_settings input_field_user_settings; struct _input_field_user_settings { input_port_value value; /* for DIP switches */ input_seq seq[SEQ_TYPE_TOTAL];/* sequences of all types */ INT32 sensitivity; /* for analog controls */ INT32 delta; /* for analog controls */ INT32 centerdelta; /* for analog controls */ UINT8 reverse; /* for analog controls */ }; /* device defined default input settings */ typedef struct _input_device_default input_device_default; struct _input_device_default { const char * tag; /* tag of port to update */ input_port_value mask; /* mask to apply to the port */ input_port_value defvalue; /* new default value */ }; /* a single input port configuration */ class input_port_config { DISABLE_COPYING(input_port_config); friend class simple_list; public: // construction/destruction input_port_config(device_t &owner, const char *tag); // getters input_port_config *next() const { return m_next; } device_t &owner() const { return m_owner; } running_machine &machine() const; input_field_config *first_field() const { return m_fieldlist.first(); } simple_list &fieldlist() { return m_fieldlist; } const char *tag() const { return m_tag; } int modcount() const { return m_modcount; } void bump_modcount() { m_modcount++; } void collapse_fields(astring &errorbuf); /* these fields are only valid if the port is live */ input_port_state * state; /* live state of port (NULL if not live) */ input_port_value active; /* mask of active bits in the port */ private: input_port_config * m_next; /* pointer to next port */ device_t & m_owner; /* associated device, when appropriate */ simple_list m_fieldlist; /* list of input_field_configs */ astring m_tag; /* pointer to this port's tag */ int m_modcount; }; /* describes a fundamental input type, including default input sequences */ class input_type_entry { friend class simple_list; public: input_type_entry(UINT32 type, ioport_group group, int player, const char *token, const char *name, input_seq standard); input_type_entry(UINT32 type, ioport_group group, int player, const char *token, const char *name, input_seq standard, input_seq decrement, input_seq increment); input_type_entry *next() const { return m_next; } UINT32 type; /* IPT_* for this entry */ ioport_group group; /* which group the port belongs to */ UINT8 player; /* player number (0 is player 1) */ const char * token; /* token used to store settings */ const char * name; /* user-friendly name */ input_seq defseq[SEQ_TYPE_TOTAL];/* default input sequence */ input_seq seq[SEQ_TYPE_TOTAL];/* currently configured sequences */ private: input_type_entry * m_next; /* next description in the list */ }; /* header at the front of INP files */ typedef struct _inp_header inp_header; struct _inp_header { char header[8]; /* +00: 8 byte header - must be "MAMEINP\0" */ UINT64 basetime; /* +08: base time of recording */ UINT8 majversion; /* +10: major INP version */ UINT8 minversion; /* +11: minor INP version */ UINT8 reserved[2]; /* +12: must be zero */ char gamename[12]; /* +14: game name string, NULL-terminated */ char version[32]; /* +20: system version string, NULL-terminated */ }; /*************************************************************************** MACROS ***************************************************************************/ /* macro for a read callback function (PORT_CUSTOM) */ #define CUSTOM_INPUT(name) input_port_value name(device_t &device, const input_field_config &field, void *param) #define CUSTOM_INPUT_MEMBER(name) input_port_value name(const input_field_config &field, void *param) #define DECLARE_CUSTOM_INPUT_MEMBER(name) input_port_value name(const input_field_config &field, void *param) /* macro for port write callback functions (PORT_CHANGED) */ #define INPUT_CHANGED(name) void name(device_t &device, const input_field_config &field, void *param, input_port_value oldval, input_port_value newval) #define INPUT_CHANGED_MEMBER(name) void name(const input_field_config &field, void *param, input_port_value oldval, input_port_value newval) #define DECLARE_INPUT_CHANGED_MEMBER(name) void name(const input_field_config &field, void *param, input_port_value oldval, input_port_value newval) /* macro for port changed callback functions (PORT_CROSSHAIR_MAPPER) */ #define CROSSHAIR_MAPPER(name) float name(device_t &device, const input_field_config &field, float linear_value) #define CROSSHAIR_MAPPER_MEMBER(name) float name(const input_field_config &field, float linear_value) #define DECLARE_CROSSHAIR_MAPPER_MEMBER(name) float name(const input_field_config &field, float linear_value) /* macro for wrapping a default string */ #define DEF_STR(str_num) ((const char *)INPUT_STRING_##str_num) template input_port_value ioport_read_line_wrapper(device_t &device, const input_field_config &field, void *param) { return (*_FunctionPointer)(&device); } template input_port_value ioport_read_line_wrapper(_FunctionClass &device, const input_field_config &field, void *param) { return (device.*_FunctionPointer)(); } template void ioport_write_line_wrapper(device_t &device, const input_field_config &field, void *param, input_port_value oldval, input_port_value newval) { return (*_FunctionPointer)(&device, newval); } template void ioport_write_line_wrapper(_FunctionClass &device, const input_field_config &field, void *param, input_port_value oldval, input_port_value newval) { return (device.*_FunctionPointer)(newval); } /*************************************************************************** MACROS FOR BUILDING INPUT PORTS ***************************************************************************/ typedef void (*ioport_constructor)(device_t &owner, ioport_list &portlist, astring &errorbuf); /* so that "0" can be used for unneeded input ports */ #define construct_ioport_0 NULL /* name of table */ #define INPUT_PORTS_NAME(_name) construct_ioport_##_name /* start of table */ #define INPUT_PORTS_START(_name) \ void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, astring &errorbuf) \ { \ astring fulltag; \ input_setting_config *cursetting = NULL; \ input_field_config *curfield = NULL; \ input_port_config *curport = NULL; \ input_port_value maskbits = 0; \ (void)cursetting; (void)curfield; (void)curport; (void)maskbits; \ /* end of table */ #define INPUT_PORTS_END \ } /* aliasing */ #define INPUT_PORTS_EXTERN(_name) \ extern void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, astring &errorbuf) /* including */ #define PORT_INCLUDE(_name) \ INPUT_PORTS_NAME(_name)(owner, portlist, errorbuf); \ /* start of a new input port (with included tag) */ #define PORT_START(_tag) \ curport = ioconfig_alloc_port(portlist, owner, _tag); \ curfield = NULL; \ cursetting = NULL; \ maskbits = 0; \ /* modify an existing port */ #define PORT_MODIFY(_tag) \ curport = ioconfig_modify_port(portlist, owner, _tag); \ curfield = NULL; \ cursetting = NULL; \ maskbits = 0; \ /* input bit definition */ #define PORT_BIT(_mask, _default, _type) \ curfield = ioconfig_alloc_field(*curport, (_type), (_default), (_mask)); \ cursetting = NULL; #define PORT_SPECIAL_ONOFF(_mask, _default, _strindex) PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, _strindex, NULL) #define PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, _strindex, _diploc) \ curfield = ioconfig_alloc_onoff(*curport, DEF_STR(_strindex), _default, _mask, _diploc, errorbuf); \ cursetting = NULL; /* append a code */ #define PORT_CODE(_code) \ ioconfig_add_code(*curfield, SEQ_TYPE_STANDARD, _code); #define PORT_CODE_DEC(_code) \ ioconfig_add_code(*curfield, SEQ_TYPE_DECREMENT, _code); #define PORT_CODE_INC(_code) \ ioconfig_add_code(*curfield, SEQ_TYPE_INCREMENT, _code); /* joystick flags */ #define PORT_2WAY \ curfield->way = 2; #define PORT_4WAY \ curfield->way = 4; #define PORT_8WAY \ curfield->way = 8; #define PORT_16WAY \ curfield->way = 16; #define PORT_ROTATED \ curfield->flags |= FIELD_FLAG_ROTATED /* general flags */ #define PORT_NAME(_name) \ curfield->name = input_port_string_from_token(_name); #define PORT_PLAYER(_player) \ curfield->player = (_player) - 1; #define PORT_COCKTAIL \ curfield->flags |= FIELD_FLAG_COCKTAIL; \ curfield->player = 1; #define PORT_TOGGLE \ curfield->flags |= FIELD_FLAG_TOGGLE; #define PORT_IMPULSE(_duration) \ curfield->impulse = _duration; #define PORT_REVERSE \ curfield->flags |= ANALOG_FLAG_REVERSE; #define PORT_RESET \ curfield->flags |= ANALOG_FLAG_RESET; #define PORT_UNUSED \ curfield->flags |= FIELD_FLAG_UNUSED; /* analog settings */ /* if this macro is not used, the minimum defaluts to 0 and maximum defaults to the mask value */ #define PORT_MINMAX(_min, _max) \ curfield->min = _min; \ curfield->max = _max; #define PORT_SENSITIVITY(_sensitivity) \ curfield->sensitivity = _sensitivity; #define PORT_KEYDELTA(_delta) \ curfield->delta = curfield->centerdelta = _delta; /* note that PORT_CENTERDELTA must appear after PORT_KEYDELTA */ #define PORT_CENTERDELTA(_delta) \ curfield->centerdelta = _delta; #define PORT_CROSSHAIR(axis, scale, offset, altaxis) \ curfield->crossaxis = CROSSHAIR_AXIS_##axis; \ curfield->crossaltaxis = altaxis; \ curfield->crossscale = scale; \ curfield->crossoffset = offset; #define PORT_CROSSHAIR_MAPPER(_callback) \ curfield->crossmapper = input_field_crossmap_delegate(_callback, #_callback, (device_t *)NULL); \ curfield->crossmapper_device = DEVICE_SELF; #define PORT_CROSSHAIR_MAPPER_MEMBER(_device, _class, _member) \ curfield->crossmapper = input_field_crossmap_delegate(&_class::_member, #_class "::" #_member, (_class *)NULL); \ curfield->crossmapper_device = _device; /* how many optical counts for 1 full turn of the control */ #define PORT_FULL_TURN_COUNT(_count) \ curfield->full_turn_count = _count; /* positional controls can be binary or 1 of X */ /* 1 of X not completed yet */ /* if it is specified as PORT_REMAP_TABLE then it is binary, but remapped */ /* otherwise it is binary */ #define PORT_POSITIONS(_positions) \ curfield->max = _positions; /* positional control wraps at min/max */ #define PORT_WRAPS \ curfield->flags |= ANALOG_FLAG_WRAPS; /* positional control uses this remap table */ #define PORT_REMAP_TABLE(_table) \ curfield->remap_table = _table; /* positional control bits are active low */ #define PORT_INVERT \ curfield->flags |= ANALOG_FLAG_INVERT; /* read callbacks */ #define PORT_CUSTOM(_callback, _param) \ curfield->read = input_field_read_delegate(_callback, #_callback, (device_t *)NULL); \ curfield->read_param = (void *)(_param); \ curfield->read_device = DEVICE_SELF; #define PORT_CUSTOM_MEMBER(_device, _class, _member, _param) \ curfield->read = input_field_read_delegate(&_class::_member, #_class "::" #_member, (_class *)NULL); \ curfield->read_param = (void *)(_param); \ curfield->read_device = (_device); /* write callbacks */ #define PORT_CHANGED(_callback, _param) \ curfield->write = input_field_write_delegate(_callback, #_callback, (device_t *)NULL); \ curfield->write_param = (void *)(_param); \ curfield->write_device = DEVICE_SELF; #define PORT_CHANGED_MEMBER(_device, _class, _member, _param) \ curfield->write = input_field_write_delegate(&_class::_member, #_class "::" #_member, (_class *)NULL); \ curfield->write_param = (void *)(_param); \ curfield->write_device = (_device); /* input device handler */ #define PORT_READ_LINE_DEVICE(_device, _read_line_device) \ curfield->read = input_field_read_delegate(&ioport_read_line_wrapper<_read_line_device>, #_read_line_device, (device_t *)NULL); \ curfield->read_param = NULL; \ curfield->read_device = _device; #define PORT_READ_LINE_DEVICE_MEMBER(_device, _class, _member) \ curfield->read = input_field_read_delegate(&ioport_read_line_wrapper<_class, &_class::_member>, #_class "::" #_member, (_class *)NULL); \ curfield->read_param = NULL; \ curfield->read_device = _device; /* output device handler */ #define PORT_WRITE_LINE_DEVICE(_device, _write_line_device) \ curfield->write = input_field_write_delegate(&ioport_write_line_wrapper<_write_line_device>, #_write_line_device, (device_t *)NULL); \ curfield->write_param = NULL; \ curfield->write_device = _device; #define PORT_WRITE_LINE_DEVICE_MEMBER(_device, _class, _member) \ curfield->write = input_field_write_delegate(&ioport_write_line_wrapper<_class, &_class::_member>, #_class "::" #_member, (_class *)NULL); \ curfield->write_param = NULL; \ curfield->write_device = _device; /* dip switch definition */ #define PORT_DIPNAME(_mask, _default, _name) \ curfield = ioconfig_alloc_field(*curport, IPT_DIPSWITCH, (_default), (_mask), (_name)); \ cursetting = NULL; #define PORT_DIPSETTING(_default, _name) \ cursetting = ioconfig_alloc_setting(*curfield, (_default) & curfield->mask, (_name)); /* physical location, of the form: name:[!]sw,[name:][!]sw,... */ /* note that these are specified LSB-first */ #define PORT_DIPLOCATION(_location) \ diplocation_list_alloc(*curfield, _location, errorbuf); /* conditionals for dip switch settings */ #define PORT_CONDITION(_tag, _mask, _condition, _value) \ { \ input_condition &condition = (cursetting != NULL) ? cursetting->condition : curfield->condition; \ condition.tag = (_tag); \ condition.mask = (_mask); \ condition.condition = (_condition); \ condition.value = (_value); \ } /* analog adjuster definition */ #define PORT_ADJUSTER(_default, _name) \ curfield = ioconfig_alloc_field(*curport, IPT_ADJUSTER, (_default), 0xff, (_name)); \ cursetting = NULL; \ /* config definition */ #define PORT_CONFNAME(_mask, _default, _name) \ curfield = ioconfig_alloc_field(*curport, IPT_CONFIG, (_default), (_mask), (_name)); \ cursetting = NULL; \ #define PORT_CONFSETTING(_default, _name) \ cursetting = ioconfig_alloc_setting(*curfield, (_default) & curfield->mask, (_name)); /* keyboard chars */ #define PORT_CHAR(_ch) \ ioconfig_field_add_char(*curfield, _ch, errorbuf); /* categories */ #define PORT_CATEGORY(_category) \ curfield->category = (_category); #define PORT_CATEGORY_CLASS(_mask, _default, _name) \ curfield = ioconfig_alloc_field(*curport, IPT_CATEGORY, (_default), (_mask), (_name)); \ cursetting = NULL; #define PORT_CATEGORY_ITEM(_default, _name, _category) \ cursetting = ioconfig_alloc_setting(*curfield, (_default) & curfield->mask, (_name)); \ cursetting->category = (_category); /* name of table */ #define DEVICE_INPUT_DEFAULTS_NAME(_name) device_iptdef_##_name /* start of table */ #define DEVICE_INPUT_DEFAULTS_START(_name) \ const input_device_default DEVICE_INPUT_DEFAULTS_NAME(_name)[] = { /* end of table */ #define DEVICE_INPUT_DEFAULTS(_tag,_mask,_defval) \ { _tag ,_mask, _defval }, \ /* end of table */ #define DEVICE_INPUT_DEFAULTS_END \ {NULL,0,0} }; /*************************************************************************** HELPER MACROS ***************************************************************************/ #define PORT_DIPUNUSED_DIPLOC(_mask, _default, _diploc) \ PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, Unused, _diploc) #define PORT_DIPUNUSED(_mask, _default) \ PORT_SPECIAL_ONOFF(_mask, _default, Unused) #define PORT_DIPUNKNOWN_DIPLOC(_mask, _default, _diploc) \ PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, Unknown, _diploc) #define PORT_DIPUNKNOWN(_mask, _default) \ PORT_SPECIAL_ONOFF(_mask, _default, Unknown) #define PORT_SERVICE_DIPLOC(_mask, _default, _diploc) \ PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, Service_Mode, _diploc) #define PORT_SERVICE(_mask, _default) \ PORT_SPECIAL_ONOFF(_mask, _default, Service_Mode) #define PORT_SERVICE_NO_TOGGLE(_mask, _default) \ PORT_BIT( _mask, _mask & _default, IPT_SERVICE ) PORT_NAME( DEF_STR( Service_Mode )) /*************************************************************************** FUNCTION PROTOTYPES ***************************************************************************/ /* ----- core system management ----- */ /* initialize the input ports, processing the given token list */ time_t input_port_init(running_machine &machine); /* ----- port configurations ----- */ /* initialize an input port list structure and allocate ports according to the given tokens */ void input_port_list_init(device_t &device, ioport_list &portlist, astring &errorbuf); /* return the field that matches the given tag and mask */ const input_field_config *input_field_by_tag_and_mask(const ioport_list &portlist, const char *tag, input_port_value mask); /* ----- accessors for input types ----- */ /* return TRUE if the given type represents an analog control */ int input_type_is_analog(int type); /* return the name for the given type/player */ const char *input_type_name(running_machine &machine, int type, int player); /* return the group for the given type/player */ int input_type_group(running_machine &machine, int type, int player); /* return the global input mapping sequence for the given type/player */ const input_seq &input_type_seq(running_machine &machine, int type, int player, input_seq_type seqtype); /* change the global input sequence for the given type/player */ void input_type_set_seq(running_machine &machine, int type, int player, input_seq_type seqtype, const input_seq *newseq); /* return TRUE if the sequence for the given input type/player is pressed */ int input_type_pressed(running_machine &machine, int type, int player); /* return the list of default mappings */ const simple_list &input_type_list(running_machine &machine); /* ----- accessors for input fields ----- */ /* return the expanded string name of the field */ const char *input_field_name(const input_field_config *field); /* return the input sequence for the given input field */ const input_seq &input_field_seq(const input_field_config *field, input_seq_type seqtype); /* return the current settings for the given input field */ void input_field_get_user_settings(const input_field_config *field, input_field_user_settings *settings); /* modify the current settings for the given input field */ void input_field_set_user_settings(const input_field_config *field, const input_field_user_settings *settings); /* return the expanded setting name for a field */ const char *input_field_setting_name(const input_field_config *field); /* return TRUE if the given field has a "previous" setting */ int input_field_has_previous_setting(const input_field_config *field); /* select the previous item for a DIP switch or configuration field */ void input_field_select_previous_setting(const input_field_config *field); /* return TRUE if the given field has a "next" setting */ int input_field_has_next_setting(const input_field_config *field); /* select the next item for a DIP switch or configuration field */ void input_field_select_next_setting(const input_field_config *field); /* ----- port checking ----- */ /* return whether an input port exists */ bool input_port_exists(running_machine &machine, const char *tag); /* return a bitmask of which bits of an input port are active (i.e. not unused or unknown) */ input_port_value input_port_active(running_machine &machine, const char *tag); /* return a bitmask of which bits of an input port are active (i.e. not unused or unknown), or a default value if the port does not exist */ input_port_value input_port_active_safe(running_machine &machine, const char *tag, input_port_value defvalue); /* ----- port reading ----- */ /* return the value of an input port */ input_port_value input_port_read_direct(const input_port_config *port); /* return the value of an input port specified by tag */ input_port_value input_port_read(running_machine &machine, const char *tag); /* return the value of a device input port specified by tag */ input_port_value input_port_read(device_t *device, const char *tag); /* return the value of an input port specified by tag, or a default value if the port does not exist */ input_port_value input_port_read_safe(running_machine &machine, const char *tag, input_port_value defvalue); /* return the extracted crosshair values for the given player */ int input_port_get_crosshair_position(running_machine &machine, int player, float *x, float *y); /* force an update to the input port values based on current conditions */ void input_port_update_defaults(running_machine &machine); /* ----- port writing ----- */ /* write a value to a port */ void input_port_write_direct(const input_port_config *port, input_port_value value, input_port_value mask); /* write a value to a port specified by tag */ void input_port_write(running_machine &machine, const char *tag, input_port_value value, input_port_value mask); /* write a value to a port, ignore if the port does not exist */ void input_port_write_safe(running_machine &machine, const char *tag, input_port_value value, input_port_value mask); /* ----- misc helper functions ----- */ /* return the TRUE if the given condition attached is true */ int input_condition_true(running_machine &machine, const input_condition *condition); /* convert an input_port_token to a default string */ const char *input_port_string_from_token(const char *token); /* return TRUE if machine use full keyboard emulation */ int input_machine_has_keyboard(running_machine &machine); /* these are called by the core; they should not be called from FEs */ void inputx_init(running_machine &machine); /* called by drivers to setup natural keyboard support */ void inputx_setup_natural_keyboard(running_machine &machine, int (*queue_chars)(running_machine &machine, const unicode_char *text, size_t text_len), int (*accept_char)(running_machine &machine, unicode_char ch), int (*charqueue_empty)(running_machine &machine)); /* validity checks */ int validate_natural_keyboard_statics(void); /* these can be called from FEs */ int inputx_can_post(running_machine &machine); /* various posting functions; can be called from FEs */ void inputx_postc(running_machine &machine, unicode_char ch); void inputx_post_utf8(running_machine &machine, const char *text); void inputx_post_utf8_rate(running_machine &machine, const char *text, attotime rate); int inputx_is_posting(running_machine &machine); /* miscellaneous functions */ int input_classify_port(const input_field_config *field); int input_has_input_class(running_machine &machine, int inputclass); int input_player_number(const input_field_config *field); int input_count_players(running_machine &machine); int input_category_active(running_machine &machine, int category); inline running_machine &input_field_config::machine() const { return m_port.machine(); } // temporary construction helpers void field_config_insert(input_field_config &newfield, input_port_value &disallowedbits, astring &errorbuf); void diplocation_list_alloc(input_field_config &field, const char *location, astring &errorbuf); input_port_config *ioconfig_alloc_port(ioport_list &portlist, device_t &device, const char *tag); input_port_config *ioconfig_modify_port(ioport_list &portlist, device_t &device, const char *tag); input_field_config *ioconfig_alloc_field(input_port_config &port, int type, input_port_value defval, input_port_value mask, const char *name = NULL); input_field_config *ioconfig_alloc_onoff(input_port_config &port, const char *name, input_port_value defval, input_port_value mask, const char *diplocation, astring &errorbuf); input_setting_config *ioconfig_alloc_setting(input_field_config &field, input_port_value value, const char *name); void ioconfig_field_add_char(input_field_config &field, unicode_char ch, astring &errorbuf); void ioconfig_add_code(input_field_config &field, int which, input_code code); #endif /* __INPTPORT_H__ */