Natural keyboard improvements

- NUL is no longer a reserved character, and PORT_CHAR(0) is meaningful now. The ioport_field structure now uses a reserved Unicode character rather than 0 as a filler.
- PORT_CHAR() with no arguments (formerly illegal) may be used to skip over shift positions that produce no useful codes.

* ioport.h: Use the empty string rather than nullptr as default tag for ioport_condition. (ioport_condition::operator== was blindly passing the null pointers to strcmp.)
This commit is contained in:
AJR 2024-12-04 09:15:16 -05:00
parent 076147c601
commit 43d61833e4
5 changed files with 28 additions and 24 deletions

View File

@ -740,8 +740,8 @@ ioport_field::ioport_field(ioport_port &port, ioport_type type, ioport_value def
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
m_seq[seqtype].set_default();
for (int i = 0; i < std::size(m_chars); i++)
std::fill(std::begin(m_chars[i]), std::end(m_chars[i]), char32_t(0));
for (auto &chars : m_chars)
std::fill(std::begin(chars), std::end(chars), UCHAR_INVALID);
// for DIP switches and configs, look for a default value from the owner
if (type == IPT_DIPSWITCH || type == IPT_CONFIG)
@ -909,11 +909,8 @@ std::vector<char32_t> ioport_field::keyboard_codes(int which) const
if (which >= std::size(m_chars))
throw emu_fatalerror("Tried to access keyboard_code with out-of-range index %d\n", which);
std::vector<char32_t> result;
for (int i = 0; i < std::size(m_chars[which]) && m_chars[which][i] != 0; i++)
result.push_back(m_chars[which][i]);
return result;
auto &chars = m_chars[which];
return std::vector<char32_t>(std::begin(chars), std::find(std::begin(chars), std::end(chars), UCHAR_INVALID));
}
@ -3289,7 +3286,8 @@ ioport_configurer::ioport_configurer(device_t &owner, ioport_list &portlist, std
m_errorbuf(errorbuf),
m_curport(nullptr),
m_curfield(nullptr),
m_cursetting(nullptr)
m_cursetting(nullptr),
m_curshift(0)
{
}
@ -3394,6 +3392,7 @@ ioport_configurer& ioport_configurer::field_alloc(ioport_type type, ioport_value
// reset the current setting
m_cursetting = nullptr;
m_curshift = 0;
return *this;
}
@ -3404,16 +3403,17 @@ ioport_configurer& ioport_configurer::field_alloc(ioport_type type, ioport_value
ioport_configurer& ioport_configurer::field_add_char(std::initializer_list<char32_t> charlist)
{
for (int index = 0; index < std::size(m_curfield->m_chars); index++)
if (m_curfield->m_chars[index][0] == 0)
{
const size_t char_count = std::size(m_curfield->m_chars[index]);
assert(charlist.size() > 0 && charlist.size() <= char_count);
if (m_curshift < std::size(m_curfield->m_chars))
{
auto &chars = m_curfield->m_chars[m_curshift++];
assert(chars[0] == UCHAR_INVALID);
assert(charlist.size() <= std::size(chars));
for (size_t i = 0; i < char_count; i++)
m_curfield->m_chars[index][i] = i < charlist.size() ? *(charlist.begin() + i) : 0;
return *this;
}
std::copy(charlist.begin(), charlist.end(), std::begin(chars));
std::fill(std::begin(chars) + charlist.size(), std::end(chars), UCHAR_INVALID);
return *this;
}
std::ostringstream s;
bool is_first = true;

View File

@ -46,12 +46,13 @@ constexpr ioport_value IP_ACTIVE_LOW = 0xffffffff;
constexpr int MAX_PLAYERS = 10;
// unicode constants
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_PRIVATE + 2;
constexpr char32_t UCHAR_MAMEKEY_BEGIN = UCHAR_SHIFT_END + 1;
// crosshair types
@ -473,7 +474,7 @@ 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;
@ -488,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
@ -1091,6 +1092,7 @@ private:
ioport_port * m_curport;
ioport_field * m_curfield;
ioport_setting * m_cursetting;
int m_curshift;
};

View File

@ -678,11 +678,11 @@ void natural_keyboard::build_codes()
{
if (!(curshift & ~mask))
{
// fetch the code, ignoring 0 and shifters
// fetch the code, ignoring shifters
std::vector<char32_t> const codes = field.keyboard_codes(curshift);
for (char32_t code : codes)
{
if (((code < UCHAR_SHIFT_BEGIN) || (code > UCHAR_SHIFT_END)) && (code != 0))
if ((code < UCHAR_SHIFT_BEGIN) || (code > UCHAR_SHIFT_END))
{
m_have_charkeys = true;
keycode_map::iterator const found(devinfo.codemap.find(code));

View File

@ -223,7 +223,7 @@ static INPUT_PORTS_START(tim011_keyboard)
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) // excluded from scan
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ret") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x20) PORT_CODE(KEYCODE_SPACE)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CHAR(0x20) PORT_CHAR() PORT_CHAR(0x00) PORT_CODE(KEYCODE_SPACE)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x02) PORT_CODE(KEYCODE_B)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x07) PORT_CODE(KEYCODE_G)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x19) PORT_CODE(KEYCODE_Y)

View File

@ -508,7 +508,9 @@ void sdl_osd_interface::process_events()
}
else if (m_modifier_keys & MODIFIER_KEY_SHIFT)
{
if (event.key.keysym.sym == SDLK_6) // Ctrl-^ (RS)
if (event.key.keysym.sym == SDLK_2) // Ctrl-@ (NUL)
machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), 0x00);
else if (event.key.keysym.sym == SDLK_6) // Ctrl-^ (RS)
machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), 0x1e);
else if (event.key.keysym.sym == SDLK_MINUS) // Ctrl-_ (US)
machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), 0x1f);