mirror of
https://github.com/holub/mame
synced 2025-04-24 01:11:11 +03:00
Merge pull request #2672 from npwoods/multiple_natural_keyboard_bindings
Added support for multiple PORT_CHAR() bindings, and adopted in the CoCo driver (addresses MT#2618)
This commit is contained in:
commit
dc2b6e95eb
@ -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<char32_t> 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<char32_t> 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<char32_t> 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<char32_t> 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<char32_t> 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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -1063,7 +1063,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<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; }
|
||||
|
||||
@ -1149,7 +1149,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
|
||||
};
|
||||
|
||||
|
||||
@ -1501,7 +1501,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<char32_t> 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; }
|
||||
@ -1746,8 +1746,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
|
||||
|
@ -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<char32_t> 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<char32_t> 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)
|
||||
// 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 (BIT(bits, 0))
|
||||
newcode.field[fieldnum++] = shift[i];
|
||||
}
|
||||
keycode_map_entry newcode;
|
||||
std::fill(std::begin(newcode.field), std::end(newcode.field), nullptr);
|
||||
newcode.shift = curshift;
|
||||
|
||||
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;
|
||||
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];
|
||||
}
|
||||
|
||||
if (LOG_NATURAL_KEYBOARD)
|
||||
{
|
||||
machine().logerror("natural_keyboard: code=%u (%s) port=%p field.name='%s'\n",
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1876,13 +1876,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<char32_t> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user