summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/ioport.h
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/ioport.h')
-rw-r--r--trunk/src/emu/ioport.h1713
1 files changed, 1713 insertions, 0 deletions
diff --git a/trunk/src/emu/ioport.h b/trunk/src/emu/ioport.h
new file mode 100644
index 00000000000..6a3655b542b
--- /dev/null
+++ b/trunk/src/emu/ioport.h
@@ -0,0 +1,1713 @@
+/***************************************************************************
+
+ 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__ */