diff options
Diffstat (limited to 'src/emu/ioport.h')
-rw-r--r-- | src/emu/ioport.h | 973 |
1 files changed, 312 insertions, 661 deletions
diff --git a/src/emu/ioport.h b/src/emu/ioport.h index df7d2ad026b..8e8009ffce6 100644 --- a/src/emu/ioport.h +++ b/src/emu/ioport.h @@ -17,44 +17,42 @@ #ifndef MAME_EMU_IOPORT_H #define MAME_EMU_IOPORT_H +#include "inpttype.h" + +#include "ioprocs.h" + +#include <array> #include <cstdint> #include <cstring> -#include <time.h> +#include <ctime> +#include <functional> +#include <iosfwd> +#include <initializer_list> +#include <list> +#include <memory> +#include <string_view> +#include <vector> //************************************************************************** // CONSTANTS //************************************************************************** -// input ports support up to 32 bits each -typedef u32 ioport_value; - // active high/low values for input ports -const ioport_value IP_ACTIVE_HIGH = 0x00000000; -const ioport_value IP_ACTIVE_LOW = 0xffffffff; +constexpr ioport_value IP_ACTIVE_HIGH = 0x00000000; +constexpr ioport_value IP_ACTIVE_LOW = 0xffffffff; // maximum number of players supported -const int MAX_PLAYERS = 10; +constexpr int MAX_PLAYERS = 10; // unicode constants -const char32_t UCHAR_PRIVATE = 0x100000; -const char32_t UCHAR_SHIFT_1 = UCHAR_PRIVATE + 0; -const char32_t UCHAR_SHIFT_2 = UCHAR_PRIVATE + 1; -const char32_t UCHAR_SHIFT_BEGIN = UCHAR_SHIFT_1; -const char32_t UCHAR_SHIFT_END = UCHAR_SHIFT_2; -const char32_t 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_INCDEC_OPERATORS(input_seq_type) +constexpr char32_t UCHAR_INVALID = 0xffff; +constexpr char32_t UCHAR_PRIVATE = 0x100000; +constexpr char32_t UCHAR_SHIFT_1 = UCHAR_PRIVATE + 0; +constexpr char32_t UCHAR_SHIFT_2 = UCHAR_PRIVATE + 1; +constexpr char32_t UCHAR_SHIFT_BEGIN = UCHAR_SHIFT_1; +constexpr char32_t UCHAR_SHIFT_END = UCHAR_SHIFT_2; +constexpr char32_t UCHAR_MAMEKEY_BEGIN = UCHAR_SHIFT_END + 1; // crosshair types @@ -86,326 +84,6 @@ enum ioport_group }; -// 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, - IPT_START9, - IPT_START10, - - // 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_POWER_ON, - IPT_POWER_OFF, - IPT_SERVICE, - IPT_TILT, - IPT_INTERLOCK, - IPT_MEMORY_RESET, - IPT_VOLUME_UP, - IPT_VOLUME_DOWN, - IPT_START, // use the numbered start button(s) for coin-ops - IPT_SELECT, - IPT_KEYPAD, - IPT_KEYBOARD, - - // 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_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 - - // 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_PAUSE_SINGLE, - IPT_UI_REWIND_SINGLE, - 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_TIMECODE, - IPT_UI_RECORD_MNG, - IPT_UI_RECORD_AVI, - 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_FOCUS_NEXT, - IPT_UI_FOCUS_PREV, - 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, - IPT_UI_TAPE_START, - IPT_UI_TAPE_STOP, - IPT_UI_DATS, - IPT_UI_FAVORITES, - IPT_UI_EXPORT, - IPT_UI_AUDIT_FAST, - IPT_UI_AUDIT_ALL, - IPT_UI_TOGGLE_AUTOFIRE, - - // 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, - - IPT_OTHER, // not mapped to standard defaults - - IPT_SPECIAL, // uninterpreted characters - IPT_CUSTOM, // handled by custom code - IPT_OUTPUT, - - IPT_COUNT -}; -DECLARE_ENUM_INCDEC_OPERATORS(ioport_type) -// aliases for some types -#define IPT_PADDLE_H IPT_PADDLE -#define IPT_PEDAL1 IPT_PEDAL -#define IPT_POSITIONAL_H IPT_POSITIONAL -#define IPT_DIAL_H IPT_DIAL - - // input type classes enum ioport_type_class { @@ -452,13 +130,13 @@ enum 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_5C_2C, // 0.500000 INPUT_STRING_2C_1C, // 0.500000 // INPUT_STRING_9C_5C, // 0.555556 // INPUT_STRING_7C_4C, // 0.571429 @@ -496,6 +174,7 @@ enum // INPUT_STRING_6C_7C, // 1.166667 // INPUT_STRING_5C_6C, // 1.200000 // INPUT_STRING_8C_10C, // 1.250000 + INPUT_STRING_3C_5C, // 1.250000 INPUT_STRING_4C_5C, // 1.250000 // INPUT_STRING_7C_9C, // 1.285714 // INPUT_STRING_6C_8C, // 1.333333 @@ -650,7 +329,7 @@ enum //************************************************************************** // constructor function pointer -typedef void(*ioport_constructor)(device_t &owner, ioport_list &portlist, std::string &errorbuf); +typedef void(*ioport_constructor)(device_t &owner, ioport_list &portlist, std::ostream &errorbuf); // I/O port callback function delegates typedef device_delegate<ioport_value ()> ioport_field_read_delegate; @@ -658,116 +337,6 @@ typedef device_delegate<void (ioport_field &, u32, ioport_value, ioport_value)> typedef device_delegate<float (float)> ioport_field_crossmap_delegate; -// ======================> inp_header - -// header at the front of INP files -class inp_header -{ -public: - // parameters - static constexpr unsigned MAJVERSION = 3; - static constexpr unsigned MINVERSION = 0; - - bool read(emu_file &f) - { - return f.read(m_data, sizeof(m_data)) == sizeof(m_data); - } - bool write(emu_file &f) const - { - return f.write(m_data, sizeof(m_data)) == sizeof(m_data); - } - - bool check_magic() const - { - return 0 == std::memcmp(MAGIC, m_data + OFFS_MAGIC, OFFS_BASETIME - OFFS_MAGIC); - } - u64 get_basetime() const - { - return - (u64(m_data[OFFS_BASETIME + 0]) << (0 * 8)) | - (u64(m_data[OFFS_BASETIME + 1]) << (1 * 8)) | - (u64(m_data[OFFS_BASETIME + 2]) << (2 * 8)) | - (u64(m_data[OFFS_BASETIME + 3]) << (3 * 8)) | - (u64(m_data[OFFS_BASETIME + 4]) << (4 * 8)) | - (u64(m_data[OFFS_BASETIME + 5]) << (5 * 8)) | - (u64(m_data[OFFS_BASETIME + 6]) << (6 * 8)) | - (u64(m_data[OFFS_BASETIME + 7]) << (7 * 8)); - } - unsigned get_majversion() const - { - return m_data[OFFS_MAJVERSION]; - } - unsigned get_minversion() const - { - return m_data[OFFS_MINVERSION]; - } - std::string get_sysname() const - { - return get_string<OFFS_SYSNAME, OFFS_APPDESC>(); - } - std::string get_appdesc() const - { - return get_string<OFFS_APPDESC, OFFS_END>(); - } - - void set_magic() - { - std::memcpy(m_data + OFFS_MAGIC, MAGIC, OFFS_BASETIME - OFFS_MAGIC); - } - void set_basetime(u64 time) - { - m_data[OFFS_BASETIME + 0] = u8((time >> (0 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 1] = u8((time >> (1 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 2] = u8((time >> (2 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 3] = u8((time >> (3 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 4] = u8((time >> (4 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 5] = u8((time >> (5 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 6] = u8((time >> (6 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 7] = u8((time >> (7 * 8)) & 0x00ff); - } - void set_version() - { - m_data[OFFS_MAJVERSION] = MAJVERSION; - m_data[OFFS_MINVERSION] = MINVERSION; - } - void set_sysname(std::string const &name) - { - set_string<OFFS_SYSNAME, OFFS_APPDESC>(name); - } - void set_appdesc(std::string const &desc) - { - set_string<OFFS_APPDESC, OFFS_END>(desc); - } - -private: - template <std::size_t BEGIN, std::size_t END> void set_string(std::string const &str) - { - std::size_t const used = (std::min<std::size_t>)(str.size() + 1, END - BEGIN); - std::memcpy(m_data + BEGIN, str.c_str(), used); - if ((END - BEGIN) > used) - std::memset(m_data + BEGIN + used, 0, (END - BEGIN) - used); - } - template <std::size_t BEGIN, std::size_t END> std::string get_string() const - { - char const *const begin = reinterpret_cast<char const *>(m_data + BEGIN); - return std::string(begin, std::find(begin, reinterpret_cast<char const *>(m_data + END), '\0')); - } - - static constexpr std::size_t OFFS_MAGIC = 0x00; // 0x08 bytes - static constexpr std::size_t OFFS_BASETIME = 0x08; // 0x08 bytes (little-endian binary integer) - static constexpr std::size_t OFFS_MAJVERSION = 0x10; // 0x01 bytes (binary integer) - static constexpr std::size_t OFFS_MINVERSION = 0x11; // 0x01 bytes (binary integer) - // 0x02 bytes reserved - static constexpr std::size_t OFFS_SYSNAME = 0x14; // 0x0c bytes (ASCII) - static constexpr std::size_t OFFS_APPDESC = 0x20; // 0x20 bytes (ASCII) - static constexpr std::size_t OFFS_END = 0x40; - - static u8 const MAGIC[OFFS_BASETIME - OFFS_MAGIC]; - - u8 m_data[OFFS_END]; -}; - - // ======================> input_device_default // device defined default input settings @@ -784,38 +353,39 @@ struct input_device_default // 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); + input_type_entry(ioport_type type, ioport_group group, int player, const char *token, const char *name, input_seq standard) noexcept; + 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) noexcept; // getters - input_type_entry *next() const { return m_next; } - ioport_type type() const { return m_type; } - ioport_group group() const { return m_group; } - u8 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]; } - void restore_default_seq(); + ioport_type type() const noexcept { return m_type; } + ioport_group group() const noexcept { return m_group; } + u8 player() const noexcept { return m_player; } + const char *token() const noexcept { return m_token; } + std::string name() const; + input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) noexcept { return m_defseq[seqtype]; } + const input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept { return m_defseq[seqtype]; } + const input_seq &seq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept { return m_seq[seqtype]; } + const std::string &cfg(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept { return m_cfg[seqtype]; } // setters - void configure_osd(const char *token, const char *name); + void restore_default_seq() noexcept; + void set_seq(input_seq_type seqtype, const input_seq &seq) noexcept { m_seq[seqtype] = seq; } + template <typename... T> void set_cfg(input_seq_type seqtype, T &&... cfg) { m_cfg[seqtype].assign(std::forward<T>(cfg)...); } + void replace_code(input_code oldcode, input_code newcode) noexcept; + void configure_osd(const char *token, const char *name) noexcept; 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 - u8 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 + ioport_type m_type; // IPT_* for this entry + ioport_group m_group; // which group the port belongs to + u8 m_player; // player number (0 is player 1) + const char * m_token; // token used to store settings + const char * m_name; // user-friendly name + std::array<input_seq, SEQ_TYPE_TOTAL> m_defseq; // default input sequence + std::array<input_seq, SEQ_TYPE_TOTAL> m_seq; // currently configured sequences + std::array<std::string, SEQ_TYPE_TOTAL> m_cfg; // configuration strings }; @@ -825,7 +395,6 @@ private: class digital_joystick { DISABLE_COPYING(digital_joystick); - friend class simple_list<digital_joystick>; public: // directions @@ -848,11 +417,10 @@ public: 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; } - u8 current() const { return m_current; } - u8 current4way() const { return m_current4way; } + int player() const noexcept { return m_player; } + int number() const noexcept { return m_number; } + u8 current() const noexcept { return m_current; } + u8 current4way() const noexcept { return m_current4way; } // configuration direction_t add_axis(ioport_field &field); @@ -862,10 +430,9 @@ public: private: // internal state - digital_joystick * m_next; // next joystick in the list int m_player; // player number represented int m_number; // joystick number represented - simple_list<simple_list_wrapper<ioport_field> > m_field[JOYDIR_COUNT]; // potential input fields for each direction + std::forward_list<std::reference_wrapper<ioport_field> > m_field[JOYDIR_COUNT]; // potential input fields for each direction u8 m_current; // current value u8 m_current4way; // current 4-way value u8 m_previous; // previous value @@ -907,11 +474,12 @@ public: bool none() const { return (m_condition == ALWAYS); } // configuration - void reset() { set(ALWAYS, nullptr, 0, 0); } + void reset() { set(ALWAYS, "", 0, 0); } void set(condition_t condition, const char *tag, ioport_value mask, ioport_value value) { m_condition = condition; m_tag = tag; + m_port = nullptr; m_mask = mask; m_value = value; } @@ -921,7 +489,7 @@ public: private: // internal state condition_t m_condition; // condition to use - const char * m_tag; // tag of port whose condition is to be tested + const char * m_tag; // tag of port whose condition is to be tested (must never be nullptr) ioport_port * m_port; // reference to the port to be tested ioport_value m_mask; // mask to apply to the port ioport_value m_value; // value to compare against @@ -933,15 +501,11 @@ private: // 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; @@ -951,15 +515,14 @@ public: const char *name() const { return m_name; } // helpers - bool enabled() { return m_condition.eval(); } + bool enabled() const { return m_condition.eval(); } 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_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 }; @@ -968,24 +531,19 @@ private: // 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, u8 swnum, bool invert); + ioport_diplocation(std::string_view name, u8 swnum, bool invert); // getters - ioport_diplocation *next() const { return m_next; } const char *name() const { return m_name.c_str(); } u8 number() const { return m_number; } bool inverted() const { return m_invert; } private: - ioport_diplocation * m_next; // pointer to the next bit - std::string m_name; // name of the physical DIP switch - u8 m_number; // physical switch number - bool m_invert; // is this an active-high DIP? + std::string m_name; // name of the physical DIP switch + u8 m_number; // physical switch number + bool m_invert; // is this an active-high DIP? }; @@ -996,18 +554,19 @@ class ioport_field { DISABLE_COPYING(ioport_field); friend class simple_list<ioport_field>; + friend class ioport_manager; friend class ioport_configurer; friend class dynamic_field; // flags for ioport_fields - static const int FIELD_FLAG_OPTIONAL = 0x0001; // set if this field is not required but recognized by hw - static const int FIELD_FLAG_COCKTAIL = 0x0002; // set if this field is relevant only for cocktail cabinets - static const int FIELD_FLAG_TOGGLE = 0x0004; // set if this field should behave as a toggle - static const int FIELD_FLAG_ROTATED = 0x0008; // set if this field represents a rotated control - static const int ANALOG_FLAG_REVERSE = 0x0010; // analog only: reverse the sense of the axis - static const int ANALOG_FLAG_RESET = 0x0020; // analog only: always preload in->default for relative axes, returning only deltas - static const int ANALOG_FLAG_WRAPS = 0x0040; // analog only: positional count wraps around - static const int ANALOG_FLAG_INVERT = 0x0080; // analog only: bitwise invert bits + static inline constexpr u32 FIELD_FLAG_OPTIONAL = 0x0001; // set if this field is not required but recognized by hw + static inline constexpr u32 FIELD_FLAG_COCKTAIL = 0x0002; // set if this field is relevant only for cocktail cabinets + static inline constexpr u32 FIELD_FLAG_TOGGLE = 0x0004; // set if this field should behave as a toggle + static inline constexpr u32 FIELD_FLAG_ROTATED = 0x0008; // set if this field represents a rotated control + static inline constexpr u32 ANALOG_FLAG_REVERSE = 0x0010; // analog only: reverse the sense of the axis + static inline constexpr u32 ANALOG_FLAG_RESET = 0x0020; // analog only: always preload in->default for relative axes, returning only deltas + static inline constexpr u32 ANALOG_FLAG_WRAPS = 0x0040; // analog only: positional count wraps around + static inline constexpr u32 ANALOG_FLAG_INVERT = 0x0080; // analog only: bitwise invert bits public: // construction/destruction @@ -1021,8 +580,8 @@ public: ioport_manager &manager() const; running_machine &machine() const; int modcount() const { return m_modcount; } - const simple_list<ioport_setting> &settings() const { return m_settinglist; } - const simple_list<ioport_diplocation> &diplocations() const { return m_diploclist; } + const std::vector<ioport_setting> &settings() const { return m_settinglist; } + const std::vector<ioport_diplocation> &diplocations() const { return m_diploclist; } ioport_value mask() const { return m_mask; } ioport_value defvalue() const { return m_defvalue; } @@ -1032,6 +591,7 @@ public: u8 player() const { return m_player; } bool digital_value() const { return m_digital_value; } void set_value(ioport_value value); + void clear_value(); bool optional() const { return ((m_flags & FIELD_FLAG_OPTIONAL) != 0); } bool cocktail() const { return ((m_flags & FIELD_FLAG_COCKTAIL) != 0); } @@ -1042,42 +602,43 @@ public: bool analog_wraps() const { return ((m_flags & ANALOG_FLAG_WRAPS) != 0); } bool analog_invert() const { return ((m_flags & ANALOG_FLAG_INVERT) != 0); } - u8 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]; } - void set_defseq(const input_seq &newseq) { set_defseq(SEQ_TYPE_STANDARD, newseq); } + u8 impulse() const noexcept { return m_impulse; } + std::string name() const; + const char *specific_name() const noexcept { return m_name; } + const input_seq &seq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept; + const input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept; + const input_seq &defseq_unresolved(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept { return m_seq[seqtype]; } + void set_defseq(const input_seq &newseq) noexcept { set_defseq(SEQ_TYPE_STANDARD, newseq); } void set_defseq(input_seq_type seqtype, const input_seq &newseq); 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; } - s32 sensitivity() const { return m_sensitivity; } - s32 delta() const { return m_delta; } - s32 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; } - u16 full_turn_count() const { return m_full_turn_count; } - const ioport_value *remap_table() const { return m_remap_table; } - - u8 way() const { return m_way; } + ioport_value minval() const noexcept { return m_min; } + ioport_value maxval() const noexcept { return m_max; } + s32 sensitivity() const noexcept { return m_sensitivity; } + s32 delta() const noexcept { return m_delta; } + s32 centerdelta() const noexcept { return m_centerdelta; } + crosshair_axis_t crosshair_axis() const noexcept { return m_crosshair_axis; } + float crosshair_scale() const noexcept { return m_crosshair_scale; } + float crosshair_offset() const noexcept { return m_crosshair_offset; } + float crosshair_altaxis() const noexcept { return m_crosshair_altaxis; } + u16 full_turn_count() const noexcept { return m_full_turn_count; } + const ioport_value *remap_table() const noexcept { return m_remap_table; } + + u8 way() const noexcept { return m_way; } std::vector<char32_t> keyboard_codes(int which) const; std::string key_name(int which) const; ioport_field_live &live() const { assert(m_live != nullptr); return *m_live; } // setters - void set_crosshair_scale(double scale) { m_crosshair_scale = scale; } - void set_crosshair_offset(double offset) { m_crosshair_offset = offset; } + void set_crosshair_scale(float scale) { m_crosshair_scale = scale; } + void set_crosshair_offset(float offset) { m_crosshair_offset = offset; } void set_player(u8 player) { m_player = player; } // 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); } + ioport_type_class type_class() const noexcept; + bool is_analog() const noexcept { return (m_type > IPT_ANALOG_FIRST && m_type < IPT_ANALOG_LAST); } + bool is_digital_joystick() const noexcept { return (m_type > IPT_DIGITAL_JOYSTICK_FIRST && m_type < IPT_DIGITAL_JOYSTICK_LAST); } // additional operations bool enabled() const { return m_condition.eval(); } @@ -1086,7 +647,7 @@ public: void select_previous_setting(); bool has_next_setting() const; void select_next_setting(); - void crosshair_position(float &x, float &y, bool &gotx, bool &goty); + float crosshair_read() const; void init_live_state(analog_field *analog); void frame_update(ioport_value &result); void reduce_mask(ioport_value bits_to_remove) { m_mask &= ~bits_to_remove; } @@ -1094,28 +655,28 @@ public: // user-controllable settings for a field struct user_settings { - ioport_value value; // for DIP switches - bool autofire; // for autofire settings + ioport_value value = 0; // for DIP switches input_seq seq[SEQ_TYPE_TOTAL]; // sequences of all types - s32 sensitivity; // for analog controls - s32 delta; // for analog controls - s32 centerdelta; // for analog controls - bool reverse; // for analog controls - bool toggle; // for non-analog controls + std::string cfg[SEQ_TYPE_TOTAL]; // configuration strings of all types + s32 sensitivity = 0; // for analog controls + s32 delta = 0; // for analog controls + s32 centerdelta = 0; // for analog controls + bool reverse = false; // for analog controls + bool toggle = false; // for non-analog controls }; - void get_user_settings(user_settings &settings); + void get_user_settings(user_settings &settings) const; void set_user_settings(const user_settings &settings); private: - void expand_diplocation(const char *location, std::string &errorbuf); + void expand_diplocation(const char *location, std::ostream &errorbuf); // internal state ioport_field * m_next; // pointer to next field in sequence ioport_port & m_port; // reference to the port that owns us - std::unique_ptr<ioport_field_live> m_live; // live state of field (nullptr if not live) + std::unique_ptr<ioport_field_live> m_live; // live state of field (nullptr 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 + std::vector<ioport_setting> m_settinglist; // list of input_setting_configs + std::vector<ioport_diplocation> m_diploclist; // list of locations for various bits // generally-applicable data ioport_value m_mask; // mask of bits belonging to the field @@ -1141,9 +702,9 @@ private: s32 m_delta; // delta to apply each frame a digital inc/dec key is pressed s32 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 + float m_crosshair_scale; // crosshair scale + float m_crosshair_offset; // crosshair offset + float m_crosshair_altaxis;// crosshair alternate axis value ioport_field_crossmap_delegate m_crosshair_mapper; // crosshair mapping function u16 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 @@ -1171,10 +732,9 @@ struct ioport_field_live bool last; // were we pressed last time? bool toggle; // current toggle setting digital_joystick::direction_t joydir; // digital joystick direction index - bool autofire; // autofire - int autopressed; // autofire status bool lockout; // user lockout std::string name; // overridden name + std::string cfg[SEQ_TYPE_TOTAL];// configuration strings }; @@ -1188,7 +748,7 @@ class ioport_list : public std::map<std::string, std::unique_ptr<ioport_port>> public: ioport_list() { } - void append(device_t &device, std::string &errorbuf); + void append(device_t &device, std::ostream &errorbuf); }; @@ -1223,13 +783,13 @@ public: // other operations ioport_field *field(ioport_value mask) const; - void collapse_fields(std::string &errorbuf); + void collapse_fields(std::ostream &errorbuf); void frame_update(); void init_live_state(); void update_defvalue(bool flush_defaults); private: - void insert_field(ioport_field &newfield, ioport_value &disallowedbits, std::string &errorbuf); + void insert_field(ioport_field &newfield, ioport_value &disallowedbits, std::ostream &errorbuf); // internal state ioport_port * m_next; // pointer to next port @@ -1248,7 +808,6 @@ private: // live analog field information class analog_field { - friend class simple_list<analog_field>; friend class ioport_manager; friend void ioport_field::set_user_settings(const ioport_field::user_settings &settings); @@ -1257,19 +816,22 @@ public: analog_field(ioport_field &field); // getters - analog_field *next() const { return m_next; } - ioport_manager &manager() const { return m_field.manager(); } - ioport_field &field() const { return m_field; } - s32 sensitivity() const { return m_sensitivity; } - bool reverse() const { return m_reverse; } - s32 delta() const { return m_delta; } - s32 centerdelta() const { return m_centerdelta; } + ioport_manager &manager() const noexcept { return m_field.manager(); } + ioport_field &field() const noexcept { return m_field; } + s32 sensitivity() const noexcept { return m_sensitivity; } + bool reverse() const noexcept { return m_reverse; } + s32 delta() const noexcept { return m_delta; } + s32 centerdelta() const noexcept { return m_centerdelta; } // readers void read(ioport_value &value); float crosshair_read(); void frame_update(running_machine &machine); + // programmatic override (for script bindings) + void set_value(s32 value); + void clear_value(); + private: // helpers s32 apply_min_max(s32 value) const; @@ -1278,14 +840,14 @@ private: s32 apply_inverse_sensitivity(s32 value) const; // internal state - analog_field * m_next; // link to the next analog state for this port ioport_field & m_field; // pointer to the input field referenced // adjusted values (right-justified and tweaked) - u8 m_shift; // shift to align final value in the port - s32 m_adjdefvalue; // adjusted default value from the config + u8 const m_shift; // shift to align final value in the port + s32 const m_adjdefvalue; // adjusted default value from the config s32 m_adjmin; // adjusted minimum value from the config s32 m_adjmax; // adjusted maximum value from the config + s32 m_adjoverride; // programmatically set adjusted value // live values of configurable parameters s32 m_sensitivity; // current live sensitivity (100=normal) @@ -1318,6 +880,7 @@ private: bool m_single_scale; // scale joystick differently if default is between min/max bool m_interpolate; // should we do linear interpolation for mid-frame reads? bool m_lastdigital; // was the last modification caused by a digital form? + bool m_use_adjoverride; // override what will be read from the field }; @@ -1326,14 +889,11 @@ private: // live device field information class dynamic_field { - friend class simple_list<dynamic_field>; - public: // construction/destruction dynamic_field(ioport_field &field); // getters - dynamic_field *next() const { return m_next; } ioport_field &field() const { return m_field; } // read/write @@ -1342,7 +902,6 @@ public: private: // internal state - dynamic_field * m_next; // linked list of info for this port ioport_field & m_field; // reference to the input field u8 m_shift; // shift to apply to the final result ioport_value m_oldval; // last value @@ -1358,9 +917,9 @@ struct ioport_port_live ioport_port_live(ioport_port &port); // public state - simple_list<analog_field> analoglist; // list of analog port info - simple_list<dynamic_field> readlist; // list of dynamic read fields - simple_list<dynamic_field> writelist; // list of dynamic write fields + std::list<analog_field> analoglist; // list of analog port info + std::vector<dynamic_field> readlist; // list of dynamic read fields + std::vector<dynamic_field> writelist; // list of dynamic write fields ioport_value defvalue; // combined default value across the port ioport_value digital; // current value from all digital inputs ioport_value outputvalue; // current value for outputs @@ -1383,104 +942,91 @@ public: ~ioport_manager(); // getters - running_machine &machine() const { return m_machine; } - const ioport_list &ports() const { return m_portlist; } - bool safe_to_read() const { return m_safe_to_read; } - natural_keyboard &natkeyboard() { assert(m_natkeyboard != nullptr); return *m_natkeyboard; } + running_machine &machine() const noexcept { return m_machine; } + const ioport_list &ports() const noexcept { return m_portlist; } + bool safe_to_read() const noexcept { return m_safe_to_read; } // type helpers - const simple_list<input_type_entry> &types() const { return m_typelist; } + const std::vector<input_type_entry> &types() const noexcept { return m_typelist; } bool type_pressed(ioport_type type, int player = 0); - const char *type_name(ioport_type type, u8 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); + std::string type_name(ioport_type type, u8 player) const; + ioport_group type_group(ioport_type type, int player) const noexcept; + const input_seq &type_seq(ioport_type type, int player = 0, input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept; + void set_type_seq(ioport_type type, int player, input_seq_type seqtype, const input_seq &newseq) noexcept; + static constexpr bool type_is_analog(ioport_type type) noexcept { return (type > IPT_ANALOG_FIRST && type < IPT_ANALOG_LAST); } + bool type_class_present(ioport_type_class inputclass) const noexcept; // other helpers digital_joystick &digjoystick(int player, int joysticknum); - int count_players() const; - bool crosshair_position(int player, float &x, float &y); + int count_players() const noexcept; s32 frame_interpolate(s32 oldval, s32 newval); ioport_type token_to_input_type(const char *string, int &player) const; std::string input_type_to_token(ioport_type type, int player); - // autofire - bool get_autofire_toggle() { return m_autofire_toggle; } - void set_autofire_toggle(bool toggle) { m_autofire_toggle = toggle; } - int get_autofire_delay() { return m_autofire_delay; } - void set_autofire_delay(int delay) { m_autofire_delay = delay; } - private: // internal helpers void init_port_types(); - void init_autoselect_devices(int type1, int type2, int type3, const char *option, const char *ananame); + void init_autoselect_devices(std::initializer_list<ioport_type> types, std::string_view option, std::string_view ananame); void frame_update_callback(); void frame_update(); - ioport_port *port(const char *tag) const { if (tag) { auto search = m_portlist.find(tag); if (search != m_portlist.end()) return search->second.get(); else return nullptr; } else return nullptr; } + ioport_port *port(const std::string &tag) const { auto search = m_portlist.find(tag); if (search != m_portlist.end()) return search->second.get(); else return nullptr; } void exit(); input_seq_type token_to_seq_type(const char *string); static const char *const seqtypestrings[]; - void load_config(config_type cfg_type, util::xml::data_node const *parentnode); - void load_remap_table(util::xml::data_node const *parentnode); - bool load_default_config(util::xml::data_node const *portnode, int type, int player, const input_seq *newseq); - bool load_game_config(util::xml::data_node const *portnode, int type, int player, const input_seq *newseq); + void load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode); + void load_remap_table(util::xml::data_node const &parentnode); + bool load_default_config(int type, int player, const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL]); + bool load_controller_config(util::xml::data_node const &portnode, int type, int player, const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL]); + void load_system_config(util::xml::data_node const &portnode, int type, int player, const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL]); + void apply_device_defaults(); void save_config(config_type cfg_type, util::xml::data_node *parentnode); - void save_sequence(util::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(util::xml::data_node &parentnode); void save_game_inputs(util::xml::data_node &parentnode); - template<typename _Type> _Type playback_read(_Type &result); + template<typename Type> Type playback_read(Type &result); time_t playback_init(); void playback_end(const char *message = nullptr); void playback_frame(const attotime &curtime); void playback_port(ioport_port &port); - template<typename _Type> void record_write(_Type value); + template<typename Type> void record_write(Type value); void record_init(); void record_end(const char *message = nullptr); void record_frame(const attotime &curtime); void record_port(ioport_port &port); - template<typename _Type> void timecode_write(_Type value); - void timecode_init(); - void timecode_end(const char *message = nullptr); - // 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 + std::vector<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 - std::unique_ptr<natural_keyboard> m_natkeyboard; // natural keyboard support + std::list<digital_joystick> m_joystick_list; // list of digital joysticks // 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 (nullptr if not recording) - emu_file m_playback_file; // playback file (nullptr if not recording) + std::unique_ptr<emu_file> m_record_file; // recording file (nullptr if not recording) + std::unique_ptr<emu_file> m_playback_file; // playback file (nullptr if not recording) + util::write_stream::ptr m_record_stream; // recording stream (nullptr if not recording) + util::read_stream::ptr m_playback_stream; // playback stream (nullptr if not recording) u64 m_playback_accumulated_speed; // accumulated speed during playback u32 m_playback_accumulated_frames; // accumulated frames during playback - emu_file m_timecode_file; // timecode/frames playback file (nullptr if not recording) - int m_timecode_count; - attotime m_timecode_last_time; - // autofire - bool m_autofire_toggle; // autofire toggle - int m_autofire_delay; // autofire delay + // storage for inactive configuration + std::unique_ptr<util::xml::file> m_deselected_card_config; + bool m_applied_device_defaults; }; @@ -1491,7 +1037,7 @@ class ioport_configurer { public: // construction/destruction - ioport_configurer(device_t &owner, ioport_list &portlist, std::string &errorbuf); + ioport_configurer(device_t &owner, ioport_list &portlist, std::ostream &errorbuf); // static helpers static const char *string_from_token(const char *string); @@ -1512,6 +1058,7 @@ public: ioport_configurer& field_set_toggle() { m_curfield->m_flags |= ioport_field::FIELD_FLAG_TOGGLE; return *this; } ioport_configurer& field_set_impulse(u8 impulse) { m_curfield->m_impulse = impulse; return *this; } ioport_configurer& field_set_analog_reverse() { m_curfield->m_flags |= ioport_field::ANALOG_FLAG_REVERSE; return *this; } + [[deprecated("PORT_RESET is deprecated; manage counter state explicitly")]] ioport_configurer& field_set_analog_reset() { m_curfield->m_flags |= ioport_field::ANALOG_FLAG_RESET; return *this; } ioport_configurer& field_set_optional() { m_curfield->m_flags |= ioport_field::FIELD_FLAG_OPTIONAL; return *this; } ioport_configurer& field_set_min_max(ioport_value minval, ioport_value maxval) { m_curfield->m_min = minval; m_curfield->m_max = maxval; return *this; } @@ -1527,6 +1074,7 @@ public: ioport_configurer& field_set_dynamic_read(ioport_field_read_delegate delegate) { m_curfield->m_read = delegate; return *this; } ioport_configurer& field_set_dynamic_write(ioport_field_write_delegate delegate, u32 param = 0) { m_curfield->m_write = delegate; m_curfield->m_write_param = param; return *this; } ioport_configurer& field_set_diplocation(const char *location) { m_curfield->expand_diplocation(location, m_errorbuf); return *this; } + ioport_configurer& field_set_gm_note(u8 note); // setting helpers ioport_configurer& setting_alloc(ioport_value value, const char *name); @@ -1539,11 +1087,12 @@ private: // internal state device_t & m_owner; ioport_list & m_portlist; - std::string & m_errorbuf; + std::ostream & m_errorbuf; ioport_port * m_curport; ioport_field * m_curfield; ioport_setting * m_cursetting; + int m_curshift; }; @@ -1554,10 +1103,6 @@ private: #define UCHAR_MAMEKEY(code) (UCHAR_MAMEKEY_BEGIN + ITEM_ID_##code) -// macro for a read callback function (PORT_CUSTOM) -#define CUSTOM_INPUT_MEMBER(name) ioport_value name() -#define DECLARE_CUSTOM_INPUT_MEMBER(name) ioport_value name() - // macro for port write callback functions (PORT_CHANGED) #define INPUT_CHANGED_MEMBER(name) void name(ioport_field &field, u32 param, ioport_value oldval, ioport_value newval) #define DECLARE_INPUT_CHANGED_MEMBER(name) void name(ioport_field &field, u32 param, ioport_value oldval, ioport_value newval) @@ -1583,7 +1128,7 @@ private: // start of table #define INPUT_PORTS_START(_name) \ -ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, std::string &errorbuf) \ +ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, std::ostream &errorbuf) \ { \ ioport_configurer configurer(owner, portlist, errorbuf); // end of table @@ -1592,7 +1137,7 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, s // aliasing #define INPUT_PORTS_EXTERN(_name) \ - extern void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, std::string &errorbuf) + extern void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, std::ostream &errorbuf) // including #define PORT_INCLUDE(_name) \ @@ -1662,6 +1207,9 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, s #define PORT_OPTIONAL \ configurer.field_set_optional(); +#define PORT_GM_NOTE(_id) \ + configurer.field_set_gm_note(_id); + // analog settings // if this macro is not used, the minimum defaults to 0 and maximum defaults to the mask value #define PORT_MINMAX(_min, _max) \ @@ -1679,11 +1227,10 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, s #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 *)nullptr)); - -#define PORT_CROSSHAIR_MAPPER_MEMBER(_device, _class, _member) \ - configurer.field_set_crossmapper(ioport_field_crossmap_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)nullptr)); +#define PORT_CROSSHAIR_MAPPER_MEMBER_IMPL(_device, _funcptr, _name) \ + configurer.field_set_crossmapper(ioport_field_crossmap_delegate(owner, _device, _funcptr, _name)); +#define PORT_CROSSHAIR_MAPPER_DEVICE_MEMBER(...) PORT_CROSSHAIR_MAPPER_MEMBER_IMPL(__VA_ARGS__) +#define PORT_CROSSHAIR_MAPPER_MEMBER(...) PORT_CROSSHAIR_MAPPER_MEMBER_IMPL(DEVICE_SELF, __VA_ARGS__) // how many optical counts for 1 full turn of the control #define PORT_FULL_TURN_COUNT(_count) \ @@ -1709,28 +1256,41 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, s configurer.field_set_analog_invert(); // read callbacks -#define PORT_CUSTOM_MEMBER(_class, _member) \ - configurer.field_set_dynamic_read(ioport_field_read_delegate(&_class::_member, #_class "::" #_member, DEVICE_SELF, (_class *)nullptr)); -#define PORT_CUSTOM_DEVICE_MEMBER(_device, _class, _member) \ - configurer.field_set_dynamic_read(ioport_field_read_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)nullptr)); +#define PORT_CUSTOM_MEMBER_IMPL(_device, _funcptr, _name) \ + configurer.field_set_dynamic_read(ioport_field_read_delegate(owner, _device, _funcptr, _name)); +#define PORT_CUSTOM_DEVICE_MEMBER(...) PORT_CUSTOM_MEMBER_IMPL(__VA_ARGS__) +#define PORT_CUSTOM_MEMBER(...) PORT_CUSTOM_MEMBER_IMPL(DEVICE_SELF, __VA_ARGS__); // write callbacks -#define PORT_CHANGED_MEMBER(_device, _class, _member, _param) \ - configurer.field_set_dynamic_write(ioport_field_write_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)nullptr), (_param)); +#define PORT_CHANGED_MEMBER_IMPL(_device, _funcptr, _name, _param) \ + configurer.field_set_dynamic_write(ioport_field_write_delegate(owner, _device, _funcptr, _name), (_param)); +#define PORT_CHANGED_MEMBER(...) PORT_CHANGED_MEMBER_IMPL(__VA_ARGS__) // input device handler -#define PORT_READ_LINE_MEMBER(_class, _member) \ - configurer.field_set_dynamic_read(ioport_field_read_delegate([](_class &device)->ioport_value { return (device._member() & 1) ? ~ioport_value(0) : 0; } , #_class "::" #_member, DEVICE_SELF, (_class *)nullptr)); -#define PORT_READ_LINE_DEVICE_MEMBER(_device, _class, _member) \ - configurer.field_set_dynamic_read(ioport_field_read_delegate([](_class &device)->ioport_value { return (device._member() & 1) ? ~ioport_value(0) : 0; } , #_class "::" #_member, _device, (_class *)nullptr)); +#define PORT_READ_LINE_MEMBER_IMPL(_device, _funcptr, _name) \ + configurer.field_set_dynamic_read( \ + ioport_field_read_delegate( \ + owner, \ + _device, \ + static_cast<ioport_value (*)(emu::detail::rw_delegate_device_class_t<decltype(_funcptr)> &)>( \ + [] (auto &device) -> ioport_value { return (std::invoke(_funcptr, device) & 1) ? ~ioport_value(0) : 0; }), \ + _name)); +#define PORT_READ_LINE_DEVICE_MEMBER(...) PORT_READ_LINE_MEMBER_IMPL(__VA_ARGS__) +#define PORT_READ_LINE_MEMBER(...) PORT_READ_LINE_MEMBER_IMPL(DEVICE_SELF, __VA_ARGS__) // output device handler -#define PORT_WRITE_LINE_MEMBER(_class, _member) \ - configurer.field_set_dynamic_write(ioport_field_write_delegate([](_class &device, ioport_field &field, u32 param, ioport_value oldval, ioport_value newval) { device._member(newval); }, #_class "::" #_member, DEVICE_SELF, (_class *)nullptr)); -#define PORT_WRITE_LINE_DEVICE_MEMBER(_device, _class, _member) \ - configurer.field_set_dynamic_write(ioport_field_write_delegate([](_class &device, ioport_field &field, u32 param, ioport_value oldval, ioport_value newval) { device._member(newval); }, #_class "::" #_member, _device, (_class *)nullptr)); - -// dip switch definition +#define PORT_WRITE_LINE_MEMBER_IMPL(_device, _funcptr, _name) \ + configurer.field_set_dynamic_write( \ + ioport_field_write_delegate( \ + owner, \ + _device, \ + static_cast<void (*)(emu::detail::rw_delegate_device_class_t<decltype(_funcptr)> &, ioport_field &, u32, ioport_value, ioport_value)>( \ + [] (auto &device, ioport_field &field, u32 param, ioport_value oldval, ioport_value newval) { std::invoke(_funcptr, device, newval); }), \ + _name)); +#define PORT_WRITE_LINE_DEVICE_MEMBER(...) PORT_WRITE_LINE_MEMBER_IMPL(__VA_ARGS__) +#define PORT_WRITE_LINE_MEMBER(...) PORT_WRITE_LINE_MEMBER_IMPL(DEVICE_SELF, __VA_ARGS__) + +// DIP switch definition #define PORT_DIPNAME(_mask, _default, _name) \ configurer.field_alloc(IPT_DIPSWITCH, (_default), (_mask), (_name)); #define PORT_DIPSETTING(_default, _name) \ @@ -1739,7 +1299,7 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, s // note that these are specified LSB-first #define PORT_DIPLOCATION(_location) \ configurer.field_set_diplocation(_location); -// conditionals for dip switch settings +// conditionals for DIP switch settings #define PORT_CONDITION(_tag, _mask, _condition, _value) \ configurer.set_condition(ioport_condition::_condition, _tag, _mask, _value); // analog adjuster definition @@ -1756,6 +1316,103 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, s #define PORT_CHAR(...) \ configurer.field_add_char({ __VA_ARGS__ }); +// General-midi derived piano notes +#define PORT_GM_A0 PORT_GM_NOTE( 21) // Start of 88-key keyboard +#define PORT_GM_AS0 PORT_GM_NOTE( 22) +#define PORT_GM_B0 PORT_GM_NOTE( 23) + +#define PORT_GM_C1 PORT_GM_NOTE( 24) +#define PORT_GM_CS1 PORT_GM_NOTE( 25) +#define PORT_GM_D1 PORT_GM_NOTE( 26) +#define PORT_GM_DS1 PORT_GM_NOTE( 27) +#define PORT_GM_E1 PORT_GM_NOTE( 28) // Start of 76-key keyboard +#define PORT_GM_F1 PORT_GM_NOTE( 29) +#define PORT_GM_FS1 PORT_GM_NOTE( 30) +#define PORT_GM_G1 PORT_GM_NOTE( 31) +#define PORT_GM_GS1 PORT_GM_NOTE( 32) +#define PORT_GM_A1 PORT_GM_NOTE( 33) +#define PORT_GM_AS1 PORT_GM_NOTE( 34) +#define PORT_GM_B1 PORT_GM_NOTE( 35) + +#define PORT_GM_C2 PORT_GM_NOTE( 36) // Start of 49 and 61-key keyboards +#define PORT_GM_CS2 PORT_GM_NOTE( 37) +#define PORT_GM_D2 PORT_GM_NOTE( 38) +#define PORT_GM_DS2 PORT_GM_NOTE( 39) +#define PORT_GM_E2 PORT_GM_NOTE( 40) +#define PORT_GM_F2 PORT_GM_NOTE( 41) +#define PORT_GM_FS2 PORT_GM_NOTE( 42) +#define PORT_GM_G2 PORT_GM_NOTE( 43) +#define PORT_GM_GS2 PORT_GM_NOTE( 44) +#define PORT_GM_A2 PORT_GM_NOTE( 45) +#define PORT_GM_AS2 PORT_GM_NOTE( 46) +#define PORT_GM_B2 PORT_GM_NOTE( 47) + +#define PORT_GM_C3 PORT_GM_NOTE( 48) +#define PORT_GM_CS3 PORT_GM_NOTE( 49) +#define PORT_GM_D3 PORT_GM_NOTE( 50) +#define PORT_GM_DS3 PORT_GM_NOTE( 51) +#define PORT_GM_E3 PORT_GM_NOTE( 52) +#define PORT_GM_F3 PORT_GM_NOTE( 53) +#define PORT_GM_FS3 PORT_GM_NOTE( 54) +#define PORT_GM_G3 PORT_GM_NOTE( 55) +#define PORT_GM_GS3 PORT_GM_NOTE( 56) +#define PORT_GM_A3 PORT_GM_NOTE( 57) +#define PORT_GM_AS3 PORT_GM_NOTE( 58) +#define PORT_GM_B3 PORT_GM_NOTE( 59) + +#define PORT_GM_C4 PORT_GM_NOTE( 60) // Middle C +#define PORT_GM_CS4 PORT_GM_NOTE( 61) +#define PORT_GM_D4 PORT_GM_NOTE( 62) +#define PORT_GM_DS4 PORT_GM_NOTE( 63) +#define PORT_GM_E4 PORT_GM_NOTE( 64) +#define PORT_GM_F4 PORT_GM_NOTE( 65) +#define PORT_GM_FS4 PORT_GM_NOTE( 66) +#define PORT_GM_G4 PORT_GM_NOTE( 67) +#define PORT_GM_GS4 PORT_GM_NOTE( 68) +#define PORT_GM_A4 PORT_GM_NOTE( 69) +#define PORT_GM_AS4 PORT_GM_NOTE( 70) +#define PORT_GM_B4 PORT_GM_NOTE( 71) + +#define PORT_GM_C5 PORT_GM_NOTE( 72) +#define PORT_GM_CS5 PORT_GM_NOTE( 73) +#define PORT_GM_D5 PORT_GM_NOTE( 74) +#define PORT_GM_DS5 PORT_GM_NOTE( 75) +#define PORT_GM_E5 PORT_GM_NOTE( 76) +#define PORT_GM_F5 PORT_GM_NOTE( 77) +#define PORT_GM_FS5 PORT_GM_NOTE( 78) +#define PORT_GM_G5 PORT_GM_NOTE( 79) +#define PORT_GM_GS5 PORT_GM_NOTE( 80) +#define PORT_GM_A5 PORT_GM_NOTE( 81) +#define PORT_GM_AS5 PORT_GM_NOTE( 82) +#define PORT_GM_B5 PORT_GM_NOTE( 83) + +#define PORT_GM_C6 PORT_GM_NOTE( 84) // End of 49-key keyboard +#define PORT_GM_CS6 PORT_GM_NOTE( 85) +#define PORT_GM_D6 PORT_GM_NOTE( 86) +#define PORT_GM_DS6 PORT_GM_NOTE( 87) +#define PORT_GM_E6 PORT_GM_NOTE( 88) +#define PORT_GM_F6 PORT_GM_NOTE( 89) +#define PORT_GM_FS6 PORT_GM_NOTE( 90) +#define PORT_GM_G6 PORT_GM_NOTE( 91) +#define PORT_GM_GS6 PORT_GM_NOTE( 92) +#define PORT_GM_A6 PORT_GM_NOTE( 93) +#define PORT_GM_AS6 PORT_GM_NOTE( 94) +#define PORT_GM_B6 PORT_GM_NOTE( 95) + +#define PORT_GM_C7 PORT_GM_NOTE( 96) // End of 61-key keyboard +#define PORT_GM_CS7 PORT_GM_NOTE( 97) +#define PORT_GM_D7 PORT_GM_NOTE( 98) +#define PORT_GM_DS7 PORT_GM_NOTE( 99) +#define PORT_GM_E7 PORT_GM_NOTE(100) +#define PORT_GM_F7 PORT_GM_NOTE(101) +#define PORT_GM_FS7 PORT_GM_NOTE(102) +#define PORT_GM_G7 PORT_GM_NOTE(103) // End of 76-key keyboard +#define PORT_GM_GS7 PORT_GM_NOTE(104) +#define PORT_GM_A7 PORT_GM_NOTE(105) +#define PORT_GM_AS7 PORT_GM_NOTE(106) +#define PORT_GM_B7 PORT_GM_NOTE(107) + +#define PORT_GM_C8 PORT_GM_NOTE(108) // End of 88-key keyboard // name of table #define DEVICE_INPUT_DEFAULTS_NAME(_name) device_iptdef_##_name @@ -1799,12 +1456,6 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, s #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) - -#define PORT_HBLANK(_screen) \ - PORT_READ_LINE_DEVICE_MEMBER(_screen, screen_device, hblank) - //************************************************************************** // INLINE FUNCTIONS //************************************************************************** |