mirror of
https://github.com/holub/mame
synced 2025-05-23 14:19:01 +03:00
1714 lines
56 KiB
C++
1714 lines
56 KiB
C++
/***************************************************************************
|
|
|
|
ioport.h
|
|
|
|
Input/output port handling.
|
|
|
|
****************************************************************************
|
|
|
|
Copyright Aaron Giles
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in
|
|
the documentation and/or other materials provided with the
|
|
distribution.
|
|
* Neither the name 'MAME' nor the names of its contributors may be
|
|
used to endorse or promote products derived from this software
|
|
without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
|
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
***************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#ifndef __EMU_H__
|
|
#error Dont include this file directly; include emu.h instead.
|
|
#endif
|
|
|
|
#ifndef __INPTPORT_H__
|
|
#define __INPTPORT_H__
|
|
|
|
#include <time.h>
|
|
|
|
|
|
//**************************************************************************
|
|
// CONSTANTS
|
|
//**************************************************************************
|
|
|
|
// input ports support up to 32 bits each
|
|
typedef UINT32 ioport_value;
|
|
|
|
// active high/low values for input ports
|
|
const ioport_value IP_ACTIVE_HIGH = 0x00000000;
|
|
const ioport_value IP_ACTIVE_LOW = 0xffffffff;
|
|
|
|
// maximum number of players supported
|
|
const int MAX_PLAYERS = 8;
|
|
|
|
// INP file parameters
|
|
const UINT32 INP_HEADER_SIZE = 64;
|
|
const UINT32 INP_HEADER_MAJVERSION = 3;
|
|
const UINT32 INP_HEADER_MINVERSION = 0;
|
|
|
|
// unicode constants
|
|
const unicode_char UCHAR_PRIVATE = 0x100000;
|
|
const unicode_char UCHAR_SHIFT_1 = UCHAR_PRIVATE + 0;
|
|
const unicode_char UCHAR_SHIFT_2 = UCHAR_PRIVATE + 1;
|
|
const unicode_char UCHAR_SHIFT_BEGIN = UCHAR_SHIFT_1;
|
|
const unicode_char UCHAR_SHIFT_END = UCHAR_SHIFT_2;
|
|
const unicode_char UCHAR_MAMEKEY_BEGIN = UCHAR_PRIVATE + 2;
|
|
|
|
|
|
// sequence types for input_port_seq() call
|
|
enum input_seq_type
|
|
{
|
|
SEQ_TYPE_INVALID = -1,
|
|
SEQ_TYPE_STANDARD = 0,
|
|
SEQ_TYPE_INCREMENT,
|
|
SEQ_TYPE_DECREMENT,
|
|
SEQ_TYPE_TOTAL
|
|
};
|
|
DECLARE_ENUM_OPERATORS(input_seq_type)
|
|
|
|
|
|
// crosshair types
|
|
enum crosshair_axis_t
|
|
{
|
|
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 ioport_type
|
|
{
|
|
// pseudo-port types
|
|
IPT_INVALID = 0,
|
|
IPT_UNUSED,
|
|
IPT_END,
|
|
IPT_UNKNOWN,
|
|
IPT_PORT,
|
|
IPT_DIPSWITCH,
|
|
IPT_CONFIG,
|
|
|
|
// 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
|
|
|
|
// digital joystick inputs
|
|
IPT_DIGITAL_JOYSTICK_FIRST,
|
|
|
|
// 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,
|
|
|
|
IPT_DIGITAL_JOYSTICK_LAST,
|
|
|
|
// 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_FIRST,
|
|
|
|
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_RIICHI, // REACH is Japanglish
|
|
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,
|
|
|
|
IPT_MAHJONG_LAST,
|
|
|
|
// hanafuda inputs
|
|
IPT_HANAFUDA_FIRST,
|
|
|
|
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,
|
|
|
|
IPT_HANAFUDA_LAST,
|
|
|
|
// gambling inputs
|
|
IPT_GAMBLING_FIRST,
|
|
|
|
IPT_GAMBLE_KEYIN, // attendant
|
|
IPT_GAMBLE_KEYOUT, // attendant
|
|
IPT_GAMBLE_SERVICE, // attendant
|
|
IPT_GAMBLE_BOOK, // attendant
|
|
IPT_GAMBLE_DOOR, // attendant
|
|
// IPT_GAMBLE_DOOR2, // many gambling games have several doors.
|
|
// IPT_GAMBLE_DOOR3,
|
|
// IPT_GAMBLE_DOOR4,
|
|
// IPT_GAMBLE_DOOR5,
|
|
|
|
IPT_GAMBLE_HIGH, // player
|
|
IPT_GAMBLE_LOW, // player
|
|
IPT_GAMBLE_HALF, // player
|
|
IPT_GAMBLE_DEAL, // player
|
|
IPT_GAMBLE_D_UP, // player
|
|
IPT_GAMBLE_TAKE, // player
|
|
IPT_GAMBLE_STAND, // player
|
|
IPT_GAMBLE_BET, // player
|
|
IPT_GAMBLE_PAYOUT, // player
|
|
// IPT_GAMBLE_BUTTON1, // player
|
|
// IPT_GAMBLE_BUTTON2, // many many gambling games have multi-games and/or multi-function-buttons
|
|
// IPT_GAMBLE_BUTTON3, // I suggest to eliminate specific names
|
|
// IPT_GAMBLE_BUTTON4,
|
|
// IPT_GAMBLE_BUTTON5,
|
|
// IPT_GAMBLE_BUTTON6,
|
|
// IPT_GAMBLE_BUTTON7,
|
|
// IPT_GAMBLE_BUTTON8,
|
|
// IPT_GAMBLE_BUTTON9,
|
|
// IPT_GAMBLE_BUTTON10,
|
|
// IPT_GAMBLE_BUTTON11,
|
|
// IPT_GAMBLE_BUTTON12,
|
|
// IPT_GAMBLE_BUTTON13,
|
|
// IPT_GAMBLE_BUTTON14,
|
|
// IPT_GAMBLE_BUTTON15,
|
|
// IPT_GAMBLE_BUTTON16,
|
|
|
|
// 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,
|
|
|
|
IPT_GAMBLING_LAST,
|
|
|
|
// analog inputs
|
|
IPT_ANALOG_FIRST,
|
|
|
|
IPT_ANALOG_ABSOLUTE_FIRST,
|
|
|
|
IPT_AD_STICK_X, // absolute // autocenter
|
|
IPT_AD_STICK_Y, // absolute // autocenter
|
|
IPT_AD_STICK_Z, // absolute // autocenter
|
|
IPT_PADDLE, // absolute // autocenter
|
|
IPT_PADDLE_V, // absolute // autocenter
|
|
IPT_PEDAL, // absolute // autocenter
|
|
IPT_PEDAL2, // absolute // autocenter
|
|
IPT_PEDAL3, // absolute // autocenter
|
|
IPT_LIGHTGUN_X, // absolute
|
|
IPT_LIGHTGUN_Y, // absolute
|
|
IPT_POSITIONAL, // absolute // autocenter if not wraps
|
|
IPT_POSITIONAL_V, // absolute // autocenter if not wraps
|
|
|
|
IPT_ANALOG_ABSOLUTE_LAST,
|
|
|
|
IPT_DIAL, // relative
|
|
IPT_DIAL_V, // relative
|
|
IPT_TRACKBALL_X, // relative
|
|
IPT_TRACKBALL_Y, // relative
|
|
IPT_MOUSE_X, // relative
|
|
IPT_MOUSE_Y, // relative
|
|
|
|
IPT_ANALOG_LAST,
|
|
|
|
// analog adjuster support
|
|
IPT_ADJUSTER,
|
|
|
|
// the following are special codes for user interface handling - not to be used by drivers!
|
|
IPT_UI_FIRST,
|
|
|
|
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,
|
|
|
|
IPT_UI_LAST,
|
|
|
|
// other meaning not mapped to standard defaults
|
|
IPT_OTHER,
|
|
|
|
// special meaning handled by custom code
|
|
IPT_SPECIAL,
|
|
IPT_CUSTOM,
|
|
IPT_OUTPUT,
|
|
|
|
IPT_COUNT
|
|
};
|
|
DECLARE_ENUM_OPERATORS(ioport_type)
|
|
|
|
|
|
// input type classes
|
|
enum ioport_type_class
|
|
{
|
|
INPUT_CLASS_INTERNAL,
|
|
INPUT_CLASS_KEYBOARD,
|
|
INPUT_CLASS_CONTROLLER,
|
|
INPUT_CLASS_CONFIG,
|
|
INPUT_CLASS_DIPSWITCH,
|
|
INPUT_CLASS_MISC
|
|
};
|
|
|
|
|
|
// 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_20C_1C, // 0.050000
|
|
// INPUT_STRING_15C_1C, // 0.066667
|
|
// INPUT_STRING_10C_1C, // 0.100000
|
|
#define __input_string_coinage_start INPUT_STRING_9C_1C
|
|
INPUT_STRING_9C_1C, // 0.111111
|
|
INPUT_STRING_8C_1C, // 0.125000
|
|
INPUT_STRING_7C_1C, // 0.142857
|
|
INPUT_STRING_6C_1C, // 0.166667
|
|
// INPUT_STRING_10C_2C, // 0.200000
|
|
INPUT_STRING_5C_1C, // 0.200000
|
|
// INPUT_STRING_9C_2C, // 0.222222
|
|
// INPUT_STRING_8C_2C, // 0.250000
|
|
INPUT_STRING_4C_1C, // 0.250000
|
|
// INPUT_STRING_7C_2C, // 0.285714
|
|
// INPUT_STRING_10C_3C, // 0.300000
|
|
// INPUT_STRING_9C_3C, // 0.333333
|
|
// INPUT_STRING_6C_2C, // 0.333333
|
|
INPUT_STRING_3C_1C, // 0.333333
|
|
INPUT_STRING_8C_3C, // 0.375000
|
|
// INPUT_STRING_10C_4C, // 0.400000
|
|
// INPUT_STRING_5C_2C, // 0.400000
|
|
// INPUT_STRING_7C_3C, // 0.428571
|
|
// INPUT_STRING_9C_4C, // 0.444444
|
|
// INPUT_STRING_10C_5C, // 0.500000
|
|
// INPUT_STRING_8C_4C, // 0.500000
|
|
// INPUT_STRING_6C_3C, // 0.500000
|
|
INPUT_STRING_4C_2C, // 0.500000
|
|
INPUT_STRING_2C_1C, // 0.500000
|
|
// INPUT_STRING_9C_5C, // 0.555556
|
|
// INPUT_STRING_7C_4C, // 0.571429
|
|
// INPUT_STRING_10C_6C, // 0.600000
|
|
INPUT_STRING_5C_3C, // 0.600000
|
|
// INPUT_STRING_8C_5C, // 0.625000
|
|
// INPUT_STRING_9C_6C, // 0.666667
|
|
// INPUT_STRING_6C_4C, // 0.666667
|
|
INPUT_STRING_3C_2C, // 0.666667
|
|
// INPUT_STRING_10C_7C, // 0.700000
|
|
// INPUT_STRING_7C_5C, // 0.714286
|
|
// INPUT_STRING_8C_6C, // 0.750000
|
|
INPUT_STRING_4C_3C, // 0.750000
|
|
// INPUT_STRING_9C_7C, // 0.777778
|
|
// INPUT_STRING_10C_8C, // 0.800000
|
|
// INPUT_STRING_5C_4C, // 0.800000
|
|
// INPUT_STRING_6C_5C, // 0.833333
|
|
// INPUT_STRING_7C_6C, // 0.857143
|
|
// INPUT_STRING_8C_7C, // 0.875000
|
|
// INPUT_STRING_9C_8C, // 0.888889
|
|
// INPUT_STRING_10C_9C, // 0.900000
|
|
// INPUT_STRING_10C_10C, // 1.000000
|
|
// INPUT_STRING_9C_9C, // 1.000000
|
|
// INPUT_STRING_8C_8C, // 1.000000
|
|
// INPUT_STRING_7C_7C, // 1.000000
|
|
// INPUT_STRING_6C_6C, // 1.000000
|
|
// INPUT_STRING_5C_5C, // 1.000000
|
|
INPUT_STRING_4C_4C, // 1.000000
|
|
INPUT_STRING_3C_3C, // 1.000000
|
|
INPUT_STRING_2C_2C, // 1.000000
|
|
INPUT_STRING_1C_1C, // 1.000000
|
|
// INPUT_STRING_9C_10C, // 1.111111
|
|
// INPUT_STRING_8C_9C, // 1.125000
|
|
// INPUT_STRING_7C_8C, // 1.142857
|
|
// INPUT_STRING_6C_7C, // 1.166667
|
|
// INPUT_STRING_5C_6C, // 1.200000
|
|
// INPUT_STRING_8C_10C, // 1.250000
|
|
INPUT_STRING_4C_5C, // 1.250000
|
|
// INPUT_STRING_7C_9C, // 1.285714
|
|
// INPUT_STRING_6C_8C, // 1.333333
|
|
INPUT_STRING_3C_4C, // 1.333333
|
|
// INPUT_STRING_5C_7C, // 1.400000
|
|
// INPUT_STRING_7C_10C, // 1.428571
|
|
// INPUT_STRING_6C_9C, // 1.500000
|
|
// INPUT_STRING_4C_6C, // 1.500000
|
|
INPUT_STRING_2C_3C, // 1.500000
|
|
// INPUT_STRING_5C_8C, // 1.600000
|
|
// INPUT_STRING_6C_10C, // 1.666667
|
|
// INPUT_STRING_3C_5C, // 1.666667
|
|
INPUT_STRING_4C_7C, // 1.750000
|
|
// INPUT_STRING_5C_9C, // 1.800000
|
|
// INPUT_STRING_5C_10C, // 2.000000
|
|
// INPUT_STRING_4C_8C, // 2.000000
|
|
// INPUT_STRING_3C_6C, // 2.000000
|
|
INPUT_STRING_2C_4C, // 2.000000
|
|
INPUT_STRING_1C_2C, // 2.000000
|
|
// INPUT_STRING_4C_9C, // 2.250000
|
|
// INPUT_STRING_3C_7C, // 2.333333
|
|
// INPUT_STRING_4C_10C, // 2.500000
|
|
INPUT_STRING_2C_5C, // 2.500000
|
|
// INPUT_STRING_3C_8C, // 2.666667
|
|
// INPUT_STRING_3C_9C, // 3.000000
|
|
INPUT_STRING_2C_6C, // 3.000000
|
|
INPUT_STRING_1C_3C, // 3.000000
|
|
// INPUT_STRING_3C_10C, // 3.333333
|
|
INPUT_STRING_2C_7C, // 3.500000
|
|
INPUT_STRING_2C_8C, // 4.000000
|
|
INPUT_STRING_1C_4C, // 4.000000
|
|
// INPUT_STRING_2C_9C, // 4.500000
|
|
// INPUT_STRING_2C_10C, // 5.000000
|
|
INPUT_STRING_1C_5C, // 5.000000
|
|
INPUT_STRING_1C_6C, // 6.000000
|
|
INPUT_STRING_1C_7C, // 7.000000
|
|
INPUT_STRING_1C_8C, // 8.000000
|
|
INPUT_STRING_1C_9C, // 9.000000
|
|
#define __input_string_coinage_end INPUT_STRING_1C_9C
|
|
// INPUT_STRING_1C_10C, // 10.000000
|
|
// INPUT_STRING_1C_11C, // 11.000000
|
|
// INPUT_STRING_1C_12C, // 12.000000
|
|
// INPUT_STRING_1C_13C, // 13.000000
|
|
// INPUT_STRING_1C_14C, // 14.000000
|
|
// INPUT_STRING_1C_15C, // 15.000000
|
|
// INPUT_STRING_1C_20C, // 20.000000
|
|
// INPUT_STRING_1C_25C, // 25.000000
|
|
// INPUT_STRING_1C_30C, // 30.000000
|
|
// INPUT_STRING_1C_40C, // 40.000000
|
|
// INPUT_STRING_1C_50C, // 50.000000
|
|
// INPUT_STRING_1C_99C, // 99.000000
|
|
// INPUT_STRING_1C_100C, // 100.000000
|
|
// INPUT_STRING_1C_120C, // 120.000000
|
|
// INPUT_STRING_1C_125C, // 125.000000
|
|
// INPUT_STRING_1C_150C, // 150.000000
|
|
// INPUT_STRING_1C_200C, // 200.000000
|
|
// INPUT_STRING_1C_250C, // 250.000000
|
|
// INPUT_STRING_1C_500C, // 500.000000
|
|
// INPUT_STRING_1C_1000C, // 1000.000000
|
|
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_China,
|
|
INPUT_STRING_Hong_Kong,
|
|
INPUT_STRING_Korea,
|
|
INPUT_STRING_Southeast_Asia,
|
|
INPUT_STRING_Taiwan,
|
|
INPUT_STRING_World,
|
|
INPUT_STRING_Language,
|
|
INPUT_STRING_English,
|
|
INPUT_STRING_Japanese,
|
|
INPUT_STRING_Chinese,
|
|
INPUT_STRING_French,
|
|
INPUT_STRING_German,
|
|
INPUT_STRING_Italian,
|
|
INPUT_STRING_Korean,
|
|
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_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_Allow,
|
|
// INPUT_STRING_Forbid,
|
|
// INPUT_STRING_Enable,
|
|
// INPUT_STRING_Disable,
|
|
INPUT_STRING_Infinite,
|
|
// INPUT_STRING_Invincibility,
|
|
// INPUT_STRING_Invulnerability,
|
|
INPUT_STRING_Stereo,
|
|
INPUT_STRING_Mono,
|
|
INPUT_STRING_Unused,
|
|
INPUT_STRING_Unknown,
|
|
// INPUT_STRING_Undefined,
|
|
INPUT_STRING_Standard,
|
|
INPUT_STRING_Reverse,
|
|
INPUT_STRING_Alternate,
|
|
// INPUT_STRING_Reserve,
|
|
// INPUT_STRING_Spare,
|
|
// INPUT_STRING_Invalid,
|
|
INPUT_STRING_None,
|
|
|
|
INPUT_STRING_COUNT
|
|
};
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// TYPE DEFINITIONS
|
|
//**************************************************************************
|
|
|
|
// opaque types pointing to live state
|
|
struct input_port_state;
|
|
struct input_field_state;
|
|
|
|
// forward declarations
|
|
class ioport_list;
|
|
class ioport_port;
|
|
struct ioport_port_live;
|
|
class ioport_field;
|
|
struct ioport_field_live;
|
|
class ioport_manager;
|
|
class emu_timer;
|
|
typedef struct _xml_data_node xml_data_node;
|
|
class analog_field;
|
|
|
|
// constructor function pointer
|
|
typedef void (*ioport_constructor)(device_t &owner, ioport_list &portlist, astring &errorbuf);
|
|
|
|
// I/O port callback function delegates
|
|
typedef device_delegate<ioport_value (ioport_field &, void *)> ioport_field_read_delegate;
|
|
typedef device_delegate<void (ioport_field &, void *, ioport_value, ioport_value)> ioport_field_write_delegate;
|
|
typedef device_delegate<float (ioport_field &, float)> ioport_field_crossmap_delegate;
|
|
|
|
// keyboard helper function delegates
|
|
typedef delegate<int (const unicode_char *, size_t)> ioport_queue_chars_delegate;
|
|
typedef delegate<bool (unicode_char)> ioport_accept_char_delegate;
|
|
typedef delegate<bool ()> ioport_charqueue_empty_delegate;
|
|
|
|
|
|
// ======================> inp_header
|
|
|
|
// header at the front of INP files
|
|
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
|
|
};
|
|
|
|
|
|
// ======================> input_device_default
|
|
|
|
// device defined default input settings
|
|
struct input_device_default
|
|
{
|
|
const char * tag; // tag of port to update
|
|
ioport_value mask; // mask to apply to the port
|
|
ioport_value defvalue; // new default value
|
|
};
|
|
|
|
|
|
// ======================> input_type_entry
|
|
|
|
// describes a fundamental input type, including default input sequences
|
|
class input_type_entry
|
|
{
|
|
friend class simple_list<input_type_entry>;
|
|
friend class ioport_manager;
|
|
|
|
public:
|
|
// construction/destruction
|
|
input_type_entry(ioport_type type, ioport_group group, int player, const char *token, const char *name, input_seq standard);
|
|
input_type_entry(ioport_type type, ioport_group group, int player, const char *token, const char *name, input_seq standard, input_seq decrement, input_seq increment);
|
|
|
|
// getters
|
|
input_type_entry *next() const { return m_next; }
|
|
ioport_type type() const { return m_type; }
|
|
ioport_group group() const { return m_group; }
|
|
UINT8 player() const { return m_player; }
|
|
const char *token() const { return m_token; }
|
|
const char *name() const { return m_name; }
|
|
input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) { return m_defseq[seqtype]; }
|
|
const input_seq &seq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const { return m_seq[seqtype]; }
|
|
|
|
// setters
|
|
void configure_osd(const char *token, const char *name);
|
|
|
|
private:
|
|
// internal state
|
|
input_type_entry * m_next; // next description in the list
|
|
ioport_type m_type; // IPT_* for this entry
|
|
ioport_group m_group; // which group the port belongs to
|
|
UINT8 m_player; // player number (0 is player 1)
|
|
const char * m_token; // token used to store settings
|
|
const char * m_name; // user-friendly name
|
|
input_seq m_defseq[SEQ_TYPE_TOTAL];// default input sequence
|
|
input_seq m_seq[SEQ_TYPE_TOTAL];// currently configured sequences
|
|
};
|
|
|
|
|
|
// ======================> digital_joystick
|
|
|
|
// tracking information about a digital joystick input
|
|
class digital_joystick
|
|
{
|
|
DISABLE_COPYING(digital_joystick);
|
|
friend class simple_list<digital_joystick>;
|
|
|
|
public:
|
|
// directions
|
|
enum direction_t
|
|
{
|
|
JOYDIR_UP,
|
|
JOYDIR_DOWN,
|
|
JOYDIR_LEFT,
|
|
JOYDIR_RIGHT,
|
|
JOYDIR_COUNT
|
|
};
|
|
|
|
// bit constants
|
|
static const UINT8 UP_BIT = 1 << JOYDIR_UP;
|
|
static const UINT8 DOWN_BIT = 1 << JOYDIR_DOWN;
|
|
static const UINT8 LEFT_BIT = 1 << JOYDIR_LEFT;
|
|
static const UINT8 RIGHT_BIT = 1 << JOYDIR_RIGHT;
|
|
|
|
// construction/destruction
|
|
digital_joystick(int player, int number);
|
|
|
|
// getters
|
|
digital_joystick *next() const { return m_next; }
|
|
int player() const { return m_player; }
|
|
int number() const { return m_number; }
|
|
UINT8 current() const { return m_current; }
|
|
UINT8 current4way() const { return m_current4way; }
|
|
|
|
// configuration
|
|
direction_t set_axis(ioport_field &field);
|
|
|
|
// updates
|
|
void frame_update();
|
|
|
|
private:
|
|
// internal state
|
|
digital_joystick * m_next; // next joystick in the list
|
|
int m_player; // player number represented
|
|
int m_number; // joystick number represented
|
|
ioport_field * m_field[JOYDIR_COUNT]; // input field for each direction
|
|
UINT8 m_current; // current value
|
|
UINT8 m_current4way; // current 4-way value
|
|
UINT8 m_previous; // previous value
|
|
};
|
|
DECLARE_ENUM_OPERATORS(digital_joystick::direction_t)
|
|
|
|
|
|
// ======================> natural_keyboard
|
|
|
|
// buffer to handle copy/paste/insert of keys
|
|
class natural_keyboard
|
|
{
|
|
DISABLE_COPYING(natural_keyboard);
|
|
|
|
public:
|
|
// construction/destruction
|
|
natural_keyboard(running_machine &machine);
|
|
|
|
void initialize();
|
|
|
|
// getters and queries
|
|
running_machine &machine() const { return m_machine; }
|
|
bool empty() const { return (m_bufbegin == m_bufend); }
|
|
bool full() const { return ((m_bufend + 1) % m_buffer.count()) == m_bufbegin; }
|
|
bool can_post() const { return (!m_queue_chars.isnull() || m_keycode_map.count() != 0); }
|
|
bool is_posting() const { return (!empty() || (!m_charqueue_empty.isnull() && !m_charqueue_empty())); }
|
|
|
|
// configuration
|
|
void configure(ioport_queue_chars_delegate queue_chars, ioport_accept_char_delegate accept_char, ioport_charqueue_empty_delegate charqueue_empty);
|
|
|
|
// posting
|
|
void post(unicode_char ch);
|
|
void post(const unicode_char *text, size_t length = 0, attotime rate = attotime::zero);
|
|
void post_utf8(const char *text, size_t length = 0, attotime rate = attotime::zero);
|
|
void post_coded(const char *text, size_t length = 0, attotime rate = attotime::zero);
|
|
|
|
void frame_update(ioport_port &port, ioport_value &digital);
|
|
const char *key_name(astring &string, unicode_char ch);
|
|
|
|
private:
|
|
// internal keyboard code information
|
|
struct keycode_map_entry
|
|
{
|
|
unicode_char ch;
|
|
ioport_field * field[UCHAR_SHIFT_END + 1 - UCHAR_SHIFT_BEGIN];
|
|
};
|
|
|
|
// internal helpers
|
|
void build_codes(ioport_manager &manager);
|
|
bool can_post_directly(unicode_char ch);
|
|
bool can_post_alternate(unicode_char ch);
|
|
attotime choose_delay(unicode_char ch);
|
|
void internal_post(unicode_char ch);
|
|
void timer(void *ptr, int param);
|
|
const char *unicode_to_string(astring &buffer, unicode_char ch);
|
|
const keycode_map_entry *find_code(unicode_char ch) const;
|
|
|
|
// debugger helpers
|
|
static void execute_input(running_machine &machine, int ref, int params, const char *param[]);
|
|
static void execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[]);
|
|
|
|
// internal state
|
|
running_machine & m_machine; // reference to our machine
|
|
UINT32 m_bufbegin; // index of starting character
|
|
UINT32 m_bufend; // index of ending character
|
|
dynamic_array<unicode_char> m_buffer; // actual buffer
|
|
bool m_status_keydown; // current keydown status
|
|
bool m_last_cr; // was the last char a CR?
|
|
emu_timer * m_timer; // timer for posting characters
|
|
attotime m_current_rate; // current rate for posting
|
|
ioport_queue_chars_delegate m_queue_chars; // queue characters callback
|
|
ioport_accept_char_delegate m_accept_char; // accept character callback
|
|
ioport_charqueue_empty_delegate m_charqueue_empty; // character queue empty callback
|
|
dynamic_array<keycode_map_entry> m_keycode_map; // keycode map
|
|
};
|
|
|
|
|
|
// ======================> ioport_condition
|
|
|
|
// encapsulates a condition on a port field or setting
|
|
class ioport_condition
|
|
{
|
|
public:
|
|
// condition types
|
|
enum condition_t
|
|
{
|
|
ALWAYS = 0,
|
|
EQUALS,
|
|
NOTEQUALS,
|
|
GREATERTHAN,
|
|
NOTGREATERTHAN,
|
|
LESSTHAN,
|
|
NOTLESSTHAN
|
|
};
|
|
|
|
// construction/destruction
|
|
ioport_condition() { reset(); }
|
|
ioport_condition(condition_t condition, const char *tag, ioport_value mask, ioport_value value) { set(condition, tag, mask, value); }
|
|
|
|
// getters
|
|
const char *tag() const { return m_tag; }
|
|
|
|
// operators
|
|
bool operator==(const ioport_condition &rhs) const { return (m_mask == rhs.m_mask && m_value == rhs.m_value && m_condition == rhs.m_condition && strcmp(m_tag, rhs.m_tag) == 0); }
|
|
bool eval(device_t &device) const;
|
|
bool none() const { return (m_condition == ALWAYS); }
|
|
|
|
// configuration
|
|
void reset() { set(ALWAYS, NULL, 0, 0); }
|
|
void set(condition_t condition, const char *tag, ioport_value mask, ioport_value value)
|
|
{
|
|
m_condition = condition;
|
|
m_tag = tag;
|
|
m_mask = mask;
|
|
m_value = value;
|
|
}
|
|
|
|
private:
|
|
// internal state
|
|
condition_t m_condition; // condition to use
|
|
const char * m_tag; // tag of port whose condition is to be tested
|
|
ioport_value m_mask; // mask to apply to the port
|
|
ioport_value m_value; // value to compare against
|
|
};
|
|
|
|
|
|
// ======================> ioport_setting
|
|
|
|
// a single setting for a configuration or DIP switch
|
|
class ioport_setting
|
|
{
|
|
DISABLE_COPYING(ioport_setting);
|
|
friend class simple_list<ioport_setting>;
|
|
|
|
public:
|
|
// construction/destruction
|
|
ioport_setting(ioport_field &field, ioport_value value, const char *name);
|
|
|
|
// getters
|
|
ioport_setting *next() const { return m_next; }
|
|
ioport_field &field() const { return m_field; }
|
|
device_t &device() const;
|
|
running_machine &machine() const;
|
|
ioport_value value() const { return m_value; }
|
|
ioport_condition &condition() { return m_condition; }
|
|
const char *name() const { return m_name; }
|
|
|
|
// helpers
|
|
bool enabled() { return m_condition.eval(device()); }
|
|
|
|
private:
|
|
// internal state
|
|
ioport_setting * m_next; // pointer to next setting in sequence
|
|
ioport_field & m_field; // pointer back to the field that owns us
|
|
ioport_value m_value; // value of the bits in this setting
|
|
const char * m_name; // user-friendly name to display
|
|
ioport_condition m_condition; // condition under which this setting is valid
|
|
};
|
|
|
|
|
|
// ======================> ioport_diplocation
|
|
|
|
// a mapping from a bit to a physical DIP switch description
|
|
class ioport_diplocation
|
|
{
|
|
DISABLE_COPYING(ioport_diplocation);
|
|
friend class simple_list<ioport_diplocation>;
|
|
|
|
public:
|
|
// construction/destruction
|
|
ioport_diplocation(const char *name, UINT8 swnum, bool invert);
|
|
|
|
// getters
|
|
ioport_diplocation *next() const { return m_next; }
|
|
const char *name() const { return m_name; }
|
|
UINT8 number() const { return m_number; }
|
|
bool inverted() const { return m_invert; }
|
|
|
|
private:
|
|
ioport_diplocation * m_next; // pointer to the next bit
|
|
astring m_name; // name of the physical DIP switch
|
|
UINT8 m_number; // physical switch number
|
|
bool m_invert; // is this an active-high DIP?
|
|
};
|
|
|
|
|
|
// ======================> ioport_field
|
|
|
|
// a single bitfield within an input port
|
|
class ioport_field
|
|
{
|
|
DISABLE_COPYING(ioport_field);
|
|
friend class simple_list<ioport_field>;
|
|
friend class ioport_configurer;
|
|
friend class dynamic_field;
|
|
|
|
// flags for ioport_fields
|
|
static const int FIELD_FLAG_UNUSED = 0x01; // set if this field is unused but relevant to other games on the same hw
|
|
static const int FIELD_FLAG_COCKTAIL = 0x02; // set if this field is relevant only for cocktail cabinets
|
|
static const int FIELD_FLAG_TOGGLE = 0x04; // set if this field should behave as a toggle
|
|
static const int FIELD_FLAG_ROTATED = 0x08; // set if this field represents a rotated control
|
|
static const int ANALOG_FLAG_REVERSE = 0x10; // analog only: reverse the sense of the axis
|
|
static const int ANALOG_FLAG_RESET = 0x20; // analog only: always preload in->default for relative axes, returning only deltas
|
|
static const int ANALOG_FLAG_WRAPS = 0x40; // analog only: positional count wraps around
|
|
static const int ANALOG_FLAG_INVERT = 0x80; // analog only: bitwise invert bits
|
|
|
|
public:
|
|
// construction/destruction
|
|
ioport_field(ioport_port &port, ioport_type type, ioport_value defvalue, ioport_value maskbits, const char *name = NULL);
|
|
~ioport_field();
|
|
|
|
// getters
|
|
ioport_field *next() const { return m_next; }
|
|
ioport_port &port() const { return m_port; }
|
|
device_t &device() const;
|
|
ioport_manager &manager() const;
|
|
running_machine &machine() const;
|
|
int modcount() const { return m_modcount; }
|
|
ioport_setting *first_setting() const { return m_settinglist.first(); }
|
|
ioport_diplocation *first_diplocation() const { return m_diploclist.first(); }
|
|
|
|
ioport_value mask() const { return m_mask; }
|
|
ioport_value defvalue() const { return m_defvalue; }
|
|
ioport_condition &condition() { return m_condition; }
|
|
ioport_type type() const { return m_type; }
|
|
UINT8 player() const { return m_player; }
|
|
|
|
bool unused() const { return ((m_flags & FIELD_FLAG_UNUSED) != 0); }
|
|
bool cocktail() const { return ((m_flags & FIELD_FLAG_COCKTAIL) != 0); }
|
|
bool toggle() const { return ((m_flags & FIELD_FLAG_TOGGLE) != 0); }
|
|
bool rotated() const { return ((m_flags & FIELD_FLAG_ROTATED) != 0); }
|
|
bool analog_reverse() const { return ((m_flags & ANALOG_FLAG_REVERSE) != 0); }
|
|
bool analog_reset() const { return ((m_flags & ANALOG_FLAG_RESET) != 0); }
|
|
bool analog_wraps() const { return ((m_flags & ANALOG_FLAG_WRAPS) != 0); }
|
|
bool analog_invert() const { return ((m_flags & ANALOG_FLAG_INVERT) != 0); }
|
|
|
|
UINT8 impulse() const { return m_impulse; }
|
|
const char *name() const;
|
|
const char *specific_name() const { return m_name; }
|
|
const input_seq &seq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const;
|
|
const input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const;
|
|
const input_seq &defseq_unresolved(input_seq_type seqtype = SEQ_TYPE_STANDARD) const { return m_seq[seqtype]; }
|
|
bool has_dynamic_read() const { return !m_read.isnull(); }
|
|
bool has_dynamic_write() const { return !m_write.isnull(); }
|
|
|
|
ioport_value minval() const { return m_min; }
|
|
ioport_value maxval() const { return m_max; }
|
|
INT32 sensitivity() const { return m_sensitivity; }
|
|
INT32 delta() const { return m_delta; }
|
|
INT32 centerdelta() const { return m_centerdelta; }
|
|
crosshair_axis_t crosshair_axis() const { return m_crosshair_axis; }
|
|
double crosshair_scale() const { return m_crosshair_scale; }
|
|
double crosshair_offset() const { return m_crosshair_offset; }
|
|
UINT16 full_turn_count() const { return m_full_turn_count; }
|
|
const ioport_value *remap_table() const { return m_remap_table; }
|
|
|
|
UINT8 way() const { return m_way; }
|
|
unicode_char keyboard_code(int which) const;
|
|
ioport_field_live &live() const { assert(m_live != NULL); return *m_live; }
|
|
|
|
// setters
|
|
void set_crosshair_scale(double scale) { m_crosshair_scale = scale; }
|
|
void set_crosshair_offset(double offset) { m_crosshair_offset = offset; }
|
|
|
|
// derived getters
|
|
ioport_type_class type_class() const;
|
|
bool is_analog() const { return (m_type > IPT_ANALOG_FIRST && m_type < IPT_ANALOG_LAST); }
|
|
bool is_digital_joystick() const { return (m_type > IPT_DIGITAL_JOYSTICK_FIRST && m_type < IPT_DIGITAL_JOYSTICK_LAST); }
|
|
|
|
// additional operations
|
|
bool enabled() const { return m_condition.eval(device()); }
|
|
const char *setting_name() const;
|
|
bool has_previous_setting() const;
|
|
void select_previous_setting();
|
|
bool has_next_setting() const;
|
|
void select_next_setting();
|
|
void crosshair_position(float &x, float &y, bool &gotx, bool &goty);
|
|
void init_live_state(analog_field *analog);
|
|
void frame_update(ioport_value &result, bool mouse_down);
|
|
void reduce_mask(ioport_value bits_to_remove) { m_mask &= ~bits_to_remove; }
|
|
|
|
// user-controllable settings for a field
|
|
struct user_settings
|
|
{
|
|
ioport_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
|
|
bool reverse; // for analog controls
|
|
};
|
|
void get_user_settings(user_settings &settings);
|
|
void set_user_settings(const user_settings &settings);
|
|
|
|
private:
|
|
void expand_diplocation(const char *location, astring &errorbuf);
|
|
|
|
// internal state
|
|
ioport_field * m_next; // pointer to next field in sequence
|
|
ioport_port & m_port; // reference to the port that owns us
|
|
ioport_field_live * m_live; // live state of field (NULL if not live)
|
|
int m_modcount; // modification count
|
|
simple_list<ioport_setting> m_settinglist; // list of input_setting_configs
|
|
simple_list<ioport_diplocation> m_diploclist; // list of locations for various bits
|
|
|
|
// generally-applicable data
|
|
ioport_value m_mask; // mask of bits belonging to the field
|
|
ioport_value m_defvalue; // default value of these bits
|
|
ioport_condition m_condition; // condition under which this field is relevant
|
|
ioport_type m_type; // IPT_* type for this port
|
|
UINT8 m_player; // player number (0-based)
|
|
UINT32 m_flags; // combination of FIELD_FLAG_* and ANALOG_FLAG_* above
|
|
UINT8 m_impulse; // number of frames before reverting to defvalue
|
|
const char * m_name; // user-friendly name to display
|
|
input_seq m_seq[SEQ_TYPE_TOTAL];// sequences of all types
|
|
ioport_field_read_delegate m_read; // read callback routine
|
|
void * m_read_param; // parameter for read callback routine
|
|
ioport_field_write_delegate m_write; // write callback routine
|
|
void * m_write_param; // parameter for write callback routine
|
|
|
|
// data relevant to analog control types
|
|
ioport_value m_min; // minimum value for absolute axes
|
|
ioport_value m_max; // maximum value for absolute axes
|
|
INT32 m_sensitivity; // sensitivity (100=normal)
|
|
INT32 m_delta; // delta to apply each frame a digital inc/dec key is pressed
|
|
INT32 m_centerdelta; // delta to apply each frame no digital inputs are pressed
|
|
crosshair_axis_t m_crosshair_axis; // crosshair axis
|
|
double m_crosshair_scale; // crosshair scale
|
|
double m_crosshair_offset; // crosshair offset
|
|
double m_crosshair_altaxis;// crosshair alternate axis value
|
|
ioport_field_crossmap_delegate m_crosshair_mapper; // crosshair mapping function
|
|
UINT16 m_full_turn_count; // number of optical counts for 1 full turn of the original control
|
|
const ioport_value * m_remap_table; // pointer to an array that remaps the port value
|
|
|
|
// data relevant to other specific types
|
|
UINT8 m_way; // digital joystick 2/4/8-way descriptions
|
|
unicode_char m_chars[4]; // unicode key data
|
|
};
|
|
|
|
|
|
// ======================> ioport_list
|
|
|
|
// class that holds a list of I/O ports
|
|
class ioport_list : public tagged_list<ioport_port>
|
|
{
|
|
DISABLE_COPYING(ioport_list);
|
|
|
|
public:
|
|
// construction/destruction
|
|
ioport_list(resource_pool &pool = global_resource_pool())
|
|
: tagged_list<ioport_port>(pool) { }
|
|
|
|
using tagged_list<ioport_port>::append;
|
|
void append(device_t &device, astring &errorbuf);
|
|
};
|
|
|
|
|
|
// ======================> ioport_port
|
|
|
|
// a single input port configuration
|
|
class ioport_port
|
|
{
|
|
DISABLE_COPYING(ioport_port);
|
|
friend class simple_list<ioport_port>;
|
|
friend class ioport_configurer;
|
|
|
|
public:
|
|
// construction/destruction
|
|
ioport_port(device_t &owner, const char *tag);
|
|
~ioport_port();
|
|
|
|
// getters
|
|
ioport_port *next() const { return m_next; }
|
|
ioport_manager &manager() const;
|
|
device_t &device() const { return m_device; }
|
|
running_machine &machine() const;
|
|
ioport_field *first_field() const { return m_fieldlist.first(); }
|
|
const char *tag() const { return m_tag; }
|
|
int modcount() const { return m_modcount; }
|
|
ioport_value active() const { return m_active; }
|
|
ioport_value active_safe(ioport_value defval) const { return (this == NULL) ? defval : active(); }
|
|
ioport_port_live &live() const { assert(m_live != NULL); return *m_live; }
|
|
|
|
// read/write to the port
|
|
ioport_value read();
|
|
ioport_value read_safe(ioport_value defval) { return (this == NULL) ? defval : read(); }
|
|
void write(ioport_value value, ioport_value mask = ~0);
|
|
void write_safe(ioport_value value, ioport_value mask = ~0) { if (this != NULL) write(value, mask); }
|
|
|
|
// other operations
|
|
ioport_field *field(ioport_value mask);
|
|
void collapse_fields(astring &errorbuf);
|
|
void frame_update(ioport_field *mouse_field);
|
|
void init_live_state();
|
|
|
|
private:
|
|
void insert_field(ioport_field &newfield, ioport_value &disallowedbits, astring &errorbuf);
|
|
|
|
// internal state
|
|
ioport_port * m_next; // pointer to next port
|
|
device_t & m_device; // associated device
|
|
simple_list<ioport_field> m_fieldlist; // list of ioport_fields
|
|
astring m_tag; // copy of this port's tag
|
|
int m_modcount; // modification count
|
|
ioport_value m_active; // mask of active bits in the port
|
|
ioport_port_live * m_live; // live state of port (NULL if not live)
|
|
};
|
|
|
|
|
|
// ======================> ioport_manager
|
|
|
|
// private input port state
|
|
class ioport_manager
|
|
{
|
|
DISABLE_COPYING(ioport_manager);
|
|
friend class device_t;
|
|
friend class ioport_configurer;
|
|
|
|
public:
|
|
// construction/destruction
|
|
ioport_manager(running_machine &machine);
|
|
time_t initialize();
|
|
|
|
// getters
|
|
running_machine &machine() const { return m_machine; }
|
|
ioport_port *first_port() const { return m_portlist.first(); }
|
|
bool safe_to_read() const { return m_safe_to_read; }
|
|
natural_keyboard &natkeyboard() { return m_natkeyboard; }
|
|
|
|
// type helpers
|
|
input_type_entry *first_type() const { return m_typelist.first(); }
|
|
bool type_pressed(ioport_type type, int player = 0);
|
|
const char *type_name(ioport_type type, UINT8 player);
|
|
ioport_group type_group(ioport_type type, int player);
|
|
const input_seq &type_seq(ioport_type type, int player = 0, input_seq_type seqtype = SEQ_TYPE_STANDARD);
|
|
void set_type_seq(ioport_type type, int player, input_seq_type seqtype, const input_seq &newseq);
|
|
static bool type_is_analog(ioport_type type) { return (type > IPT_ANALOG_FIRST && type < IPT_ANALOG_LAST); }
|
|
bool type_class_present(ioport_type_class inputclass);
|
|
|
|
// other helpers
|
|
digital_joystick &digjoystick(int player, int joysticknum);
|
|
int count_players() const;
|
|
bool crosshair_position(int player, float &x, float &y);
|
|
bool has_keyboard() const;
|
|
void setup_natural_keyboard(ioport_queue_chars_delegate queue_chars, ioport_accept_char_delegate accept_char, ioport_charqueue_empty_delegate charqueue_empty);
|
|
INT32 frame_interpolate(INT32 oldval, INT32 newval);
|
|
ioport_type token_to_input_type(const char *string, int &player) const;
|
|
const char *input_type_to_token(astring &string, ioport_type type, int player);
|
|
|
|
private:
|
|
// internal helpers
|
|
void init_port_types();
|
|
void init_autoselect_devices(int type1, int type2, int type3, const char *option, const char *ananame);
|
|
|
|
void frame_update_callback();
|
|
void frame_update();
|
|
|
|
ioport_port *port(const char *tag) const { return m_portlist.find(tag); }
|
|
void exit();
|
|
input_seq_type token_to_seq_type(const char *string);
|
|
void update_defaults();
|
|
|
|
void load_config(int config_type, xml_data_node *parentnode);
|
|
void load_remap_table(xml_data_node *parentnode);
|
|
bool load_default_config(xml_data_node *portnode, int type, int player, const input_seq *newseq);
|
|
bool load_game_config(xml_data_node *portnode, int type, int player, const input_seq *newseq);
|
|
|
|
void save_config(int config_type, xml_data_node *parentnode);
|
|
void save_sequence(xml_data_node *parentnode, input_seq_type type, ioport_type porttype, const input_seq &seq);
|
|
bool save_this_input_field_type(ioport_type type);
|
|
void save_default_inputs(xml_data_node *parentnode);
|
|
void save_game_inputs(xml_data_node *parentnode);
|
|
|
|
template<typename _Type> _Type playback_read(_Type &result);
|
|
time_t playback_init();
|
|
void playback_end(const char *message = NULL);
|
|
void playback_frame(attotime curtime);
|
|
void playback_port(ioport_port &port);
|
|
|
|
template<typename _Type> void record_write(_Type value);
|
|
void record_init();
|
|
void record_end(const char *message = NULL);
|
|
void record_frame(attotime curtime);
|
|
void record_port(ioport_port &port);
|
|
|
|
// internal state
|
|
running_machine & m_machine; // reference to owning machine
|
|
bool m_safe_to_read; // clear at start; set after state is loaded
|
|
ioport_list m_portlist; // list of input port configurations
|
|
|
|
// types
|
|
simple_list<input_type_entry> m_typelist; // list of live type states
|
|
input_type_entry * m_type_to_entry[IPT_COUNT][MAX_PLAYERS]; // map from type/player to type state
|
|
|
|
// specific special global input states
|
|
simple_list<digital_joystick> m_joystick_list; // list of digital joysticks
|
|
natural_keyboard m_natkeyboard; // natural keyboard support
|
|
|
|
// frame time tracking
|
|
attotime m_last_frame_time; // time of the last frame callback
|
|
attoseconds_t m_last_delta_nsec; // nanoseconds that passed since the previous callback
|
|
|
|
// playback/record information
|
|
emu_file m_record_file; // recording file (NULL if not recording)
|
|
emu_file m_playback_file; // playback file (NULL if not recording)
|
|
UINT64 m_playback_accumulated_speed; // accumulated speed during playback
|
|
UINT32 m_playback_accumulated_frames; // accumulated frames during playback
|
|
};
|
|
|
|
|
|
// ======================> ioport_configurer
|
|
|
|
// class to wrap helper functions
|
|
class ioport_configurer
|
|
{
|
|
public:
|
|
// construction/destruction
|
|
ioport_configurer(device_t &owner, ioport_list &portlist, astring &errorbuf);
|
|
|
|
// static helpers
|
|
static const char *string_from_token(const char *string);
|
|
|
|
// port helpers
|
|
void port_alloc(const char *tag);
|
|
void port_modify(const char *tag);
|
|
|
|
// field helpers
|
|
void field_alloc(ioport_type type, ioport_value defval, ioport_value mask, const char *name = NULL);
|
|
void field_add_char(unicode_char ch);
|
|
void field_add_code(input_seq_type which, input_code code);
|
|
void field_set_way(int way) const { m_curfield->m_way = way; }
|
|
void field_set_rotated() const { m_curfield->m_flags |= ioport_field::FIELD_FLAG_ROTATED; }
|
|
void field_set_name(const char *name) const { m_curfield->m_name = string_from_token(name); }
|
|
void field_set_player(int player) const { m_curfield->m_player = player - 1; }
|
|
void field_set_cocktail() const { m_curfield->m_flags |= ioport_field::FIELD_FLAG_COCKTAIL; field_set_player(2); }
|
|
void field_set_toggle() const { m_curfield->m_flags |= ioport_field::FIELD_FLAG_TOGGLE; }
|
|
void field_set_impulse(UINT8 impulse) const { m_curfield->m_impulse = impulse; }
|
|
void field_set_analog_reverse() const { m_curfield->m_flags |= ioport_field::ANALOG_FLAG_REVERSE; }
|
|
void field_set_analog_reset() const { m_curfield->m_flags |= ioport_field::ANALOG_FLAG_RESET; }
|
|
void field_set_unused() const { m_curfield->m_flags |= ioport_field::FIELD_FLAG_UNUSED; }
|
|
void field_set_min_max(ioport_value minval, ioport_value maxval) const { m_curfield->m_min = minval; m_curfield->m_max = maxval; }
|
|
void field_set_sensitivity(INT32 sensitivity) const { m_curfield->m_sensitivity = sensitivity; }
|
|
void field_set_delta(INT32 delta) const { m_curfield->m_centerdelta = m_curfield->m_delta = delta; }
|
|
void field_set_centerdelta(INT32 delta) const { m_curfield->m_centerdelta = delta; }
|
|
void field_set_crosshair(crosshair_axis_t axis, double altaxis, double scale, double offset) const { m_curfield->m_crosshair_axis = axis; m_curfield->m_crosshair_altaxis = altaxis; m_curfield->m_crosshair_scale = scale; m_curfield->m_crosshair_offset = offset; }
|
|
void field_set_crossmapper(ioport_field_crossmap_delegate callback) const { m_curfield->m_crosshair_mapper = callback; }
|
|
void field_set_full_turn_count(UINT16 count) const { m_curfield->m_full_turn_count = count; }
|
|
void field_set_analog_wraps() const { m_curfield->m_flags |= ioport_field::ANALOG_FLAG_WRAPS; }
|
|
void field_set_remap_table(const ioport_value *table) { m_curfield->m_remap_table = table; }
|
|
void field_set_analog_invert() const { m_curfield->m_flags |= ioport_field::ANALOG_FLAG_INVERT; }
|
|
void field_set_dynamic_read(ioport_field_read_delegate delegate, void *param = NULL) const { m_curfield->m_read = delegate; m_curfield->m_read_param = param; }
|
|
void field_set_dynamic_write(ioport_field_write_delegate delegate, void *param = NULL) const { m_curfield->m_write = delegate; m_curfield->m_write_param = param; }
|
|
void field_set_diplocation(const char *location) const { m_curfield->expand_diplocation(location, m_errorbuf); }
|
|
|
|
// setting helpers
|
|
void setting_alloc(ioport_value value, const char *name);
|
|
|
|
// misc helpers
|
|
void set_condition(ioport_condition::condition_t condition, const char *tag, ioport_value mask, ioport_value value);
|
|
void onoff_alloc(const char *name, ioport_value defval, ioport_value mask, const char *diplocation);
|
|
|
|
private:
|
|
// internal state
|
|
device_t & m_owner;
|
|
ioport_list & m_portlist;
|
|
astring & m_errorbuf;
|
|
|
|
ioport_port * m_curport;
|
|
ioport_field * m_curfield;
|
|
ioport_setting * m_cursetting;
|
|
};
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// MACROS
|
|
//**************************************************************************
|
|
|
|
#define UCHAR_MAMEKEY(code) (UCHAR_MAMEKEY_BEGIN + ITEM_ID_##code)
|
|
|
|
// macro for a read callback function (PORT_CUSTOM)
|
|
#define CUSTOM_INPUT(name) ioport_value name(device_t &device, ioport_field &field, void *param)
|
|
#define CUSTOM_INPUT_MEMBER(name) ioport_value name(ioport_field &field, void *param)
|
|
#define DECLARE_CUSTOM_INPUT_MEMBER(name) ioport_value name(ioport_field &field, void *param)
|
|
|
|
// macro for port write callback functions (PORT_CHANGED)
|
|
#define INPUT_CHANGED(name) void name(device_t &device, ioport_field &field, void *param, ioport_value oldval, ioport_value newval)
|
|
#define INPUT_CHANGED_MEMBER(name) void name(ioport_field &field, void *param, ioport_value oldval, ioport_value newval)
|
|
#define DECLARE_INPUT_CHANGED_MEMBER(name) void name(ioport_field &field, void *param, ioport_value oldval, ioport_value newval)
|
|
|
|
// macro for port changed callback functions (PORT_CROSSHAIR_MAPPER)
|
|
#define CROSSHAIR_MAPPER(name) float name(device_t &device, ioport_field &field, float linear_value)
|
|
#define CROSSHAIR_MAPPER_MEMBER(name) float name(ioport_field &field, float linear_value)
|
|
#define DECLARE_CROSSHAIR_MAPPER_MEMBER(name) float name(ioport_field &field, float linear_value)
|
|
|
|
// macro for wrapping a default string
|
|
#define DEF_STR(str_num) ((const char *)INPUT_STRING_##str_num)
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// MACROS FOR BUILDING INPUT PORTS
|
|
//**************************************************************************
|
|
|
|
// 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) \
|
|
ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, astring &errorbuf) \
|
|
{ \
|
|
ioport_configurer configurer(owner, portlist, errorbuf); \
|
|
|
|
// 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) \
|
|
configurer.port_alloc(_tag); \
|
|
|
|
// modify an existing port
|
|
#define PORT_MODIFY(_tag) \
|
|
configurer.port_modify(_tag); \
|
|
|
|
// input bit definition
|
|
#define PORT_BIT(_mask, _default, _type) \
|
|
configurer.field_alloc((_type), (_default), (_mask)); \
|
|
|
|
#define PORT_SPECIAL_ONOFF(_mask, _default, _strindex) \
|
|
PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, _strindex, NULL)
|
|
|
|
#define PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, _strindex, _diploc) \
|
|
configurer.onoff_alloc(DEF_STR(_strindex), _default, _mask, _diploc); \
|
|
|
|
// append a code
|
|
#define PORT_CODE(_code) \
|
|
configurer.field_add_code(SEQ_TYPE_STANDARD, _code);
|
|
|
|
#define PORT_CODE_DEC(_code) \
|
|
configurer.field_add_code(SEQ_TYPE_DECREMENT, _code);
|
|
|
|
#define PORT_CODE_INC(_code) \
|
|
configurer.field_add_code(SEQ_TYPE_INCREMENT, _code);
|
|
|
|
// joystick flags
|
|
#define PORT_2WAY \
|
|
configurer.field_set_way(2);
|
|
|
|
#define PORT_4WAY \
|
|
configurer.field_set_way(4);
|
|
|
|
#define PORT_8WAY \
|
|
configurer.field_set_way(8);
|
|
|
|
#define PORT_16WAY \
|
|
configurer.field_set_way(16);
|
|
|
|
#define PORT_ROTATED \
|
|
configurer.field_set_rotated();
|
|
|
|
// general flags
|
|
#define PORT_NAME(_name) \
|
|
configurer.field_set_name(_name);
|
|
|
|
#define PORT_PLAYER(_player) \
|
|
configurer.field_set_player(_player);
|
|
|
|
#define PORT_COCKTAIL \
|
|
configurer.field_set_cocktail();
|
|
|
|
#define PORT_TOGGLE \
|
|
configurer.field_set_toggle();
|
|
|
|
#define PORT_IMPULSE(_duration) \
|
|
configurer.field_set_impulse(_duration);
|
|
|
|
#define PORT_REVERSE \
|
|
configurer.field_set_analog_reverse();
|
|
|
|
#define PORT_RESET \
|
|
configurer.field_set_analog_reset();
|
|
|
|
#define PORT_UNUSED \
|
|
configurer.field_set_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) \
|
|
configurer.field_set_min_max(_min, _max);
|
|
|
|
#define PORT_SENSITIVITY(_sensitivity) \
|
|
configurer.field_set_sensitivity(_sensitivity);
|
|
|
|
#define PORT_KEYDELTA(_delta) \
|
|
configurer.field_set_delta(_delta); \
|
|
|
|
// note that PORT_CENTERDELTA must appear after PORT_KEYDELTA
|
|
#define PORT_CENTERDELTA(_delta) \
|
|
configurer.field_set_centerdelta(_delta);
|
|
|
|
#define PORT_CROSSHAIR(axis, scale, offset, altaxis) \
|
|
configurer.field_set_crosshair(CROSSHAIR_AXIS_##axis, altaxis, scale, offset);
|
|
|
|
#define PORT_CROSSHAIR_MAPPER(_callback) \
|
|
configurer.field_set_crossmapper(ioport_field_crossmap_delegate(_callback, #_callback, DEVICE_SELF, (device_t *)NULL));
|
|
|
|
#define PORT_CROSSHAIR_MAPPER_MEMBER(_device, _class, _member) \
|
|
configurer.field_set_crossmapper(ioport_field_crossmap_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)NULL));
|
|
|
|
// how many optical counts for 1 full turn of the control
|
|
#define PORT_FULL_TURN_COUNT(_count) \
|
|
configurer.field_set_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) \
|
|
configurer.field_set_min_max(0, _positions);
|
|
|
|
// positional control wraps at min/max
|
|
#define PORT_WRAPS \
|
|
configurer.field_set_analog_wraps();
|
|
|
|
// positional control uses this remap table
|
|
#define PORT_REMAP_TABLE(_table) \
|
|
configurer.field_set_remap_table(_table);
|
|
|
|
// positional control bits are active low
|
|
#define PORT_INVERT \
|
|
configurer.field_set_analog_invert();
|
|
|
|
// read callbacks
|
|
#define PORT_CUSTOM(_callback, _param) \
|
|
configurer.field_set_dynamic_read(ioport_field_read_delegate(_callback, #_callback, DEVICE_SELF, (device_t *)NULL), (void *)(_param));
|
|
|
|
#define PORT_CUSTOM_MEMBER(_device, _class, _member, _param) \
|
|
configurer.field_set_dynamic_read(ioport_field_read_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)NULL), (void *)(_param));
|
|
|
|
// write callbacks
|
|
#define PORT_CHANGED(_callback, _param) \
|
|
configurer.field_set_dynamic_write(ioport_field_write_delegate(_callback, #_callback, DEVICE_SELF, (device_t *)NULL), (void *)(_param));
|
|
|
|
#define PORT_CHANGED_MEMBER(_device, _class, _member, _param) \
|
|
configurer.field_set_dynamic_write(ioport_field_write_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)NULL), (void *)(_param));
|
|
|
|
// input device handler
|
|
#define PORT_READ_LINE_DEVICE(_device, _read_line_device) \
|
|
configurer.field_set_dynamic_read(ioport_field_read_delegate(&ioport_read_line_wrapper<_read_line_device>, #_read_line_device, _device, (device_t *)NULL));
|
|
|
|
#define PORT_READ_LINE_DEVICE_MEMBER(_device, _class, _member) \
|
|
configurer.field_set_dynamic_read(ioport_field_read_delegate(&ioport_read_line_wrapper<_class, &_class::_member>, #_class "::" #_member, _device, (_class *)NULL));
|
|
|
|
// output device handler
|
|
#define PORT_WRITE_LINE_DEVICE(_device, _write_line_device) \
|
|
configurer.field_set_dynamic_write(ioport_field_write_delegate(&ioport_write_line_wrapper<_write_line_device>, #_write_line_device, _device, (device_t *)NULL));
|
|
|
|
#define PORT_WRITE_LINE_DEVICE_MEMBER(_device, _class, _member) \
|
|
configurer.field_set_dynamic_write(ioport_field_write_delegate(&ioport_write_line_wrapper<_class, &_class::_member>, #_class "::" #_member, _device, (_class *)NULL));
|
|
|
|
// dip switch definition
|
|
#define PORT_DIPNAME(_mask, _default, _name) \
|
|
configurer.field_alloc(IPT_DIPSWITCH, (_default), (_mask), (_name)); \
|
|
|
|
#define PORT_DIPSETTING(_default, _name) \
|
|
configurer.setting_alloc((_default), (_name)); \
|
|
|
|
// physical location, of the form: name:[!]sw,[name:][!]sw,...
|
|
// note that these are specified LSB-first
|
|
#define PORT_DIPLOCATION(_location) \
|
|
configurer.field_set_diplocation(_location); \
|
|
|
|
// conditionals for dip switch settings
|
|
#define PORT_CONDITION(_tag, _mask, _condition, _value) \
|
|
configurer.set_condition(ioport_condition::_condition, _tag, _mask, _value); \
|
|
|
|
// analog adjuster definition
|
|
#define PORT_ADJUSTER(_default, _name) \
|
|
configurer.field_alloc(IPT_ADJUSTER, (_default), 0xff, (_name)); \
|
|
|
|
// config definition
|
|
#define PORT_CONFNAME(_mask, _default, _name) \
|
|
configurer.field_alloc(IPT_CONFIG, (_default), (_mask), (_name)); \
|
|
|
|
#define PORT_CONFSETTING(_default, _name) \
|
|
configurer.setting_alloc((_default), (_name));
|
|
|
|
// keyboard chars
|
|
#define PORT_CHAR(_ch) \
|
|
configurer.field_add_char(_ch);
|
|
|
|
|
|
// name of table
|
|
#define DEVICE_INPUT_DEFAULTS_NAME(_name) device_iptdef_##_name
|
|
|
|
#define device_iptdef_0 NULL
|
|
#define device_iptdef___null NULL
|
|
|
|
// 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 ))
|
|
|
|
#define PORT_VBLANK(_screen) \
|
|
PORT_READ_LINE_DEVICE_MEMBER(_screen, screen_device, vblank_port_read)
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// INLINE TEMPLATES
|
|
//**************************************************************************
|
|
|
|
template<int (*_FunctionPointer)(device_t *)>
|
|
ioport_value ioport_read_line_wrapper(device_t &device, ioport_field &field, void *param)
|
|
{
|
|
return (*_FunctionPointer)(&device);
|
|
}
|
|
|
|
template<class _FunctionClass, int (_FunctionClass::*_FunctionPointer)()>
|
|
ioport_value ioport_read_line_wrapper(_FunctionClass &device, ioport_field &field, void *param)
|
|
{
|
|
return (device.*_FunctionPointer)();
|
|
}
|
|
|
|
template<void (*_FunctionPointer)(device_t *, int)>
|
|
void ioport_write_line_wrapper(device_t &device, ioport_field &field, void *param, ioport_value oldval, ioport_value newval)
|
|
{
|
|
return (*_FunctionPointer)(&device, newval);
|
|
}
|
|
|
|
template<class _FunctionClass, void (_FunctionClass::*_FunctionPointer)(int)>
|
|
void ioport_write_line_wrapper(_FunctionClass &device, ioport_field &field, void *param, ioport_value oldval, ioport_value newval)
|
|
{
|
|
return (device.*_FunctionPointer)(newval);
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// INLINE FUNCITONS
|
|
//**************************************************************************
|
|
|
|
inline ioport_manager &ioport_field::manager() const { return m_port.manager(); }
|
|
inline device_t &ioport_field::device() const { return m_port.device(); }
|
|
inline running_machine &ioport_field::machine() const { return m_port.machine(); }
|
|
|
|
inline device_t &ioport_setting::device() const { return m_field.device(); }
|
|
inline running_machine &ioport_setting::machine() const { return m_field.machine(); }
|
|
|
|
|
|
#endif // __INPTPORT_H__ */
|