From d850afa60589d2b53e009f61bf4f41b98948e901 Mon Sep 17 00:00:00 2001 From: Nathan Woods Date: Sat, 2 Sep 2017 15:40:33 -0400 Subject: Added support for multiple PORT_CHAR() bindings, and adopted in the CoCo driver (addresses MT#2618) --- src/emu/ioport.cpp | 42 ++++++++++++++++++++--------- src/emu/ioport.h | 10 +++---- src/emu/natkeyboard.cpp | 64 +++++++++++++++++++++++++-------------------- src/emu/validity.cpp | 15 ++++++----- src/mame/drivers/coco12.cpp | 8 +++--- src/mame/drivers/coco3.cpp | 8 +++--- 6 files changed, 87 insertions(+), 60 deletions(-) diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp index bf241f30b57..4ee034a10d0 100644 --- a/src/emu/ioport.cpp +++ b/src/emu/ioport.cpp @@ -616,7 +616,9 @@ ioport_field::ioport_field(ioport_port &port, ioport_type type, ioport_value def // reset sequences and chars for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype) m_seq[seqtype].set_default(); - std::fill(std::begin(m_chars), std::end(m_chars), char32_t(0)); + + for (int i = 0; i < ARRAY_LENGTH(m_chars); i++) + std::fill(std::begin(m_chars[i]), std::end(m_chars[i]), char32_t(0)); // for DIP switches and configs, look for a default value from the owner if (type == IPT_DIPSWITCH || type == IPT_CONFIG) @@ -755,16 +757,20 @@ ioport_type_class ioport_field::type_class() const //------------------------------------------------- -// keyboard_code - accesses a particular keyboard -// code +// keyboard_codes - accesses a particular keyboard +// code list //------------------------------------------------- -char32_t ioport_field::keyboard_code(int which) const +std::vector ioport_field::keyboard_codes(int which) const { if (which >= ARRAY_LENGTH(m_chars)) throw emu_fatalerror("Tried to access keyboard_code with out-of-range index %d\n", which); - return m_chars[which]; + std::vector result; + for (int i = 0; i < ARRAY_LENGTH(m_chars[which]) && m_chars[which] != 0; i++) + result.push_back(m_chars[which][i]); + + return result; } @@ -774,7 +780,8 @@ char32_t ioport_field::keyboard_code(int which) const std::string ioport_field::key_name(int which) const { - char32_t ch = keyboard_code(which); + std::vector codes = keyboard_codes(which); + char32_t ch = codes.empty() ? 0 : codes[0]; // attempt to get the string from the character info table switch (ch) @@ -1373,8 +1380,8 @@ ioport_field_live::ioport_field_live(ioport_field &field, analog_field *analog) // loop through each character on the field for (int which = 0; which < 4; which++) { - char32_t const ch = field.keyboard_code(which); - if (ch == 0) + std::vector const codes = field.keyboard_codes(which); + if (codes.empty()) break; name.append(string_format("%-*s ", std::max(SPACE_COUNT - 1, 0), field.key_name(which))); } @@ -3059,16 +3066,27 @@ ioport_configurer& ioport_configurer::field_alloc(ioport_type type, ioport_value // field_add_char - add a character to a field //------------------------------------------------- -ioport_configurer& ioport_configurer::field_add_char(char32_t ch) +ioport_configurer& ioport_configurer::field_add_char(std::initializer_list charlist) { for (int index = 0; index < ARRAY_LENGTH(m_curfield->m_chars); index++) - if (m_curfield->m_chars[index] == 0) + if (m_curfield->m_chars[index][0] == 0) { - m_curfield->m_chars[index] = ch; + const size_t char_count = ARRAY_LENGTH(m_curfield->m_chars[index]); + assert(charlist.size() > 0 && charlist.size() <= char_count); + + for (size_t i = 0; i < char_count; i++) + m_curfield->m_chars[index][i] = i < charlist.size() ? *(charlist.begin() + i) : 0; return *this; } - throw emu_fatalerror("PORT_CHAR(%d) could not be added - maximum amount exceeded\n", ch); + std::ostringstream s; + bool is_first = true; + for (char32_t ch : charlist) + { + util::stream_format(s, "%s%d", is_first ? "" : ",", (int)ch); + is_first = false; + } + throw emu_fatalerror("PORT_CHAR(%s) could not be added - maximum amount exceeded\n", s.str().c_str()); } diff --git a/src/emu/ioport.h b/src/emu/ioport.h index a391492a906..a61a694dbb8 100644 --- a/src/emu/ioport.h +++ b/src/emu/ioport.h @@ -1058,7 +1058,7 @@ public: const ioport_value *remap_table() const { return m_remap_table; } u8 way() const { return m_way; } - char32_t keyboard_code(int which) const; + std::vector keyboard_codes(int which) const; std::string key_name(int which) const; ioport_field_live &live() const { assert(m_live != nullptr); return *m_live; } @@ -1144,7 +1144,7 @@ private: // data relevant to other specific types u8 m_way; // digital joystick 2/4/8-way descriptions - char32_t m_chars[1 << (UCHAR_SHIFT_END - UCHAR_SHIFT_BEGIN + 1)]; // unicode key data + char32_t m_chars[1 << (UCHAR_SHIFT_END - UCHAR_SHIFT_BEGIN + 1)][2]; // unicode key data }; @@ -1496,7 +1496,7 @@ public: // field helpers ioport_configurer& field_alloc(ioport_type type, ioport_value defval, ioport_value mask, const char *name = nullptr); - ioport_configurer& field_add_char(char32_t ch); + ioport_configurer& field_add_char(std::initializer_list charlist); ioport_configurer& field_add_code(input_seq_type which, input_code code); ioport_configurer& field_set_way(int way) { m_curfield->m_way = way; return *this; } ioport_configurer& field_set_rotated() { m_curfield->m_flags |= ioport_field::FIELD_FLAG_ROTATED; return *this; } @@ -1741,8 +1741,8 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, s configurer.setting_alloc((_default), (_name)); // keyboard chars -#define PORT_CHAR(_ch) \ - configurer.field_add_char(_ch); +#define PORT_CHAR(...) \ + configurer.field_add_char({ __VA_ARGS__ }); // name of table diff --git a/src/emu/natkeyboard.cpp b/src/emu/natkeyboard.cpp index 9defa2f0fa1..2c579b6b894 100644 --- a/src/emu/natkeyboard.cpp +++ b/src/emu/natkeyboard.cpp @@ -580,11 +580,14 @@ void natural_keyboard::build_codes(ioport_manager &manager) { if (field.type() == IPT_KEYBOARD) { - char32_t const code = field.keyboard_code(0); - if ((code >= UCHAR_SHIFT_BEGIN) && (code <= UCHAR_SHIFT_END)) + std::vector const codes = field.keyboard_codes(0); + for (char32_t code : codes) { - mask |= 1U << (code - UCHAR_SHIFT_BEGIN); - shift[code - UCHAR_SHIFT_BEGIN] = &field; + if ((code >= UCHAR_SHIFT_BEGIN) && (code <= UCHAR_SHIFT_END)) + { + mask |= 1U << (code - UCHAR_SHIFT_BEGIN); + shift[code - UCHAR_SHIFT_BEGIN] = &field; + } } } } @@ -603,35 +606,38 @@ void natural_keyboard::build_codes(ioport_manager &manager) if (!(curshift & ~mask)) { // fetch the code, ignoring 0 and shiters - char32_t const code = field.keyboard_code(curshift); - if (((code < UCHAR_SHIFT_BEGIN) || (code > UCHAR_SHIFT_END)) && (code != 0)) + std::vector const codes = field.keyboard_codes(curshift); + for (char32_t code : codes) { - // prefer lowest shift state - keycode_map::iterator const found(m_keycode_map.find(code)); - if ((m_keycode_map.end() == found) || (found->second.shift > curshift)) + if (((code < UCHAR_SHIFT_BEGIN) || (code > UCHAR_SHIFT_END)) && (code != 0)) { - keycode_map_entry newcode; - std::fill(std::begin(newcode.field), std::end(newcode.field), nullptr); - newcode.shift = curshift; - - unsigned fieldnum = 0; - for (unsigned i = 0, bits = curshift; (i < SHIFT_COUNT) && bits; ++i, bits >>= 1) - { - if (BIT(bits, 0)) - newcode.field[fieldnum++] = shift[i]; - } - - assert(fieldnum < ARRAY_LENGTH(newcode.field)); - newcode.field[fieldnum] = &field; - if (m_keycode_map.end() == found) - m_keycode_map.emplace(code, newcode); - else - found->second = newcode; - - if (LOG_NATURAL_KEYBOARD) + // prefer lowest shift state + keycode_map::iterator const found(m_keycode_map.find(code)); + if ((m_keycode_map.end() == found) || (found->second.shift > curshift)) { - machine().logerror("natural_keyboard: code=%u (%s) port=%p field.name='%s'\n", + keycode_map_entry newcode; + std::fill(std::begin(newcode.field), std::end(newcode.field), nullptr); + newcode.shift = curshift; + + unsigned fieldnum = 0; + for (unsigned i = 0, bits = curshift; (i < SHIFT_COUNT) && bits; ++i, bits >>= 1) + { + if (BIT(bits, 0)) + newcode.field[fieldnum++] = shift[i]; + } + + assert(fieldnum < ARRAY_LENGTH(newcode.field)); + newcode.field[fieldnum] = &field; + if (m_keycode_map.end() == found) + m_keycode_map.emplace(code, newcode); + else + found->second = newcode; + + if (LOG_NATURAL_KEYBOARD) + { + machine().logerror("natural_keyboard: code=%u (%s) port=%p field.name='%s'\n", code, unicode_to_string(code), (void *)&port, field.name()); + } } } } diff --git a/src/emu/validity.cpp b/src/emu/validity.cpp index 618214970c2..0ded5f781cf 100644 --- a/src/emu/validity.cpp +++ b/src/emu/validity.cpp @@ -1836,13 +1836,16 @@ void validity_checker::validate_inputs() // verify natural keyboard codes for (int which = 0; which < 1 << (UCHAR_SHIFT_END - UCHAR_SHIFT_BEGIN + 1); which++) { - char32_t code = field.keyboard_code(which); - if (code && !uchar_isvalid(code)) + std::vector codes = field.keyboard_codes(which); + for (char32_t code : codes) { - osd_printf_error("Field '%s' has non-character U+%04X in PORT_CHAR(%d)\n", - name, - (unsigned)code, - (int)code); + if (!uchar_isvalid(code)) + { + osd_printf_error("Field '%s' has non-character U+%04X in PORT_CHAR(%d)\n", + name, + (unsigned)code, + (int)code); + } } } } diff --git a/src/mame/drivers/coco12.cpp b/src/mame/drivers/coco12.cpp index b83f419dfad..b9c6157d741 100644 --- a/src/mame/drivers/coco12.cpp +++ b/src/mame/drivers/coco12.cpp @@ -181,10 +181,10 @@ static INPUT_PORTS_START( coco_keyboard ) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP), '^') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN), 10) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(UCHAR_MAMEKEY(LEFT), 8) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT), 9) PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco12_state, coco_state::keyboard_changed, nullptr) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_START("row4") diff --git a/src/mame/drivers/coco3.cpp b/src/mame/drivers/coco3.cpp index 9af64d7a6bf..6c9ef01b2cb 100644 --- a/src/mame/drivers/coco3.cpp +++ b/src/mame/drivers/coco3.cpp @@ -111,10 +111,10 @@ static INPUT_PORTS_START( coco3_keyboard ) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP), '^') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN), 10) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(UCHAR_MAMEKEY(LEFT), 8) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT), 9) PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, coco3_state, coco_state::keyboard_changed, nullptr) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_START("row4") -- cgit v1.2.3