diff options
author | 2017-02-05 12:02:53 +1100 | |
---|---|---|
committer | 2017-02-05 12:04:35 +1100 | |
commit | fb8b69545f9ad073c73e57cf200b9877b4b6aea3 (patch) | |
tree | c9360b883fd9e94507c0e56940036087eaadd565 /src/emu/natkeyboard.cpp | |
parent | aed1d8afeeaa5d7d727edba8c05217c47e33ec98 (diff) |
Amiga keyboard updates:
* Fixed Shift-Alt combinations with natural keyboard
* Fixed crash on keyboard inputs with four characters
* Corrected polarity of KB_DATA from Amiga to keyboard
* Completely rewrote 68HC05CxA-based A1200 keyboard device, now working
* Fixed KB_DATA mixing in A500 keyboard
* Made A500 keyboard caps lock LED output name consistent with A1200
* Added Alt- and Alt-Shift- characters to A500 US keyboard
* Fixed natural keyboard modifiers with LLE keyboards
Diffstat (limited to 'src/emu/natkeyboard.cpp')
-rw-r--r-- | src/emu/natkeyboard.cpp | 154 |
1 files changed, 93 insertions, 61 deletions
diff --git a/src/emu/natkeyboard.cpp b/src/emu/natkeyboard.cpp index a5d856a20e9..e1921b7a21d 100644 --- a/src/emu/natkeyboard.cpp +++ b/src/emu/natkeyboard.cpp @@ -314,17 +314,18 @@ const char_info charinfo[] = //------------------------------------------------- natural_keyboard::natural_keyboard(running_machine &machine) - : m_machine(machine), - m_in_use(false), - m_bufbegin(0), - m_bufend(0), - m_status_keydown(false), - m_last_cr(false), - m_timer(nullptr), - m_current_rate(attotime::zero), - m_queue_chars(), - m_accept_char(), - m_charqueue_empty() + : m_machine(machine) + , m_in_use(false) + , m_bufbegin(0) + , m_bufend(0) + , m_fieldnum(0) + , m_status_keydown(false) + , m_last_cr(false) + , m_timer(nullptr) + , m_current_rate(attotime::zero) + , m_queue_chars() + , m_accept_char() + , m_charqueue_empty() { // try building a list of keycodes; if none are available, don't bother build_codes(machine.ioport()); @@ -571,48 +572,68 @@ void natural_keyboard::post_coded(const char *text, size_t length, const attotim void natural_keyboard::build_codes(ioport_manager &manager) { - // iterate over shift keys - ioport_field *shift[UCHAR_SHIFT_END + 1 - UCHAR_SHIFT_BEGIN] = { nullptr }; - for (int curshift = 0; curshift <= ARRAY_LENGTH(shift); curshift++) - if (curshift == 0 || shift[curshift - 1] != nullptr) - - // iterate over ports and fields - for (auto &port : manager.ports()) - for (ioport_field &field : port.second->fields()) - if (field.type() == IPT_KEYBOARD) - { - // fetch the code, ignoring 0 - char32_t code = field.keyboard_code(curshift); - if (code == 0) - continue; - - // is this a shifter key? - if (code >= UCHAR_SHIFT_BEGIN && code <= UCHAR_SHIFT_END) - shift[code - UCHAR_SHIFT_BEGIN] = &field; + // find all shfit keys + unsigned mask = 0; + ioport_field *shift[SHIFT_COUNT]; + std::fill(std::begin(shift), std::end(shift), nullptr); + for (auto const &port : manager.ports()) + { + for (ioport_field &field : port.second->fields()) + { + if (field.type() == IPT_KEYBOARD) + { + char32_t const code = field.keyboard_code(0); + if ((code >= UCHAR_SHIFT_BEGIN) && (code <= UCHAR_SHIFT_END)) + { + mask |= 1U << (code - UCHAR_SHIFT_BEGIN); + shift[code - UCHAR_SHIFT_BEGIN] = &field; + } + } + } + } - // not a shifter key; record normally - else + // iterate over ports and fields + for (auto const &port : manager.ports()) + { + for (ioport_field &field : port.second->fields()) + { + if (field.type() == IPT_KEYBOARD) + { + // iterate over all shift states + for (unsigned curshift = 0; curshift < SHIFT_STATES; ++curshift) + { + 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)) { keycode_map_entry newcode; - if (curshift == 0) - { - newcode.field[0] = &field; - newcode.field[1] = nullptr; - } - else + newcode.ch = code; + std::fill(std::begin(newcode.field), std::end(newcode.field), nullptr); + + unsigned fieldnum = 0; + for (unsigned i = 0, bits = curshift; (i < SHIFT_COUNT) && bits; ++i, bits >>= 1) { - newcode.field[0] = shift[curshift - 1]; - newcode.field[1] = &field; + if (BIT(bits, 0)) + newcode.field[fieldnum++] = shift[i]; } - newcode.ch = code; - m_keycode_map.push_back(newcode); + + assert(fieldnum < ARRAY_LENGTH(newcode.field)); + newcode.field[fieldnum] = &field; + m_keycode_map.push_back(std::move(newcode)); if (LOG_NATURAL_KEYBOARD) { - machine().logerror("natural_keyboard: code=%i (%s) port=%p field.name='%s'\n", int(code), unicode_to_string(code).c_str(), (void *)&port, field.name()); + machine().logerror("natural_keyboard: code=%u (%s) port=%p field.name='%s'\n", + code, unicode_to_string(code), (void *)&port, field.name()); } } } + } + } + } + } } @@ -692,7 +713,8 @@ void natural_keyboard::internal_post(char32_t ch) if (empty()) { m_timer->adjust(choose_delay(ch)); - m_status_keydown = 0; + m_fieldnum = 0; + m_status_keydown = false; } // add to the buffer, resizing if necessary @@ -710,9 +732,9 @@ void natural_keyboard::internal_post(char32_t ch) void natural_keyboard::timer(void *ptr, int param) { - // the driver has a queue_chars handler if (!m_queue_chars.isnull()) { + // the driver has a queue_chars handler while (!empty() && m_queue_chars(&m_buffer[m_bufbegin], 1)) { m_bufbegin = (m_bufbegin + 1) % m_buffer.size(); @@ -720,36 +742,46 @@ void natural_keyboard::timer(void *ptr, int param) break; } } - - // the driver does not have a queue_chars handler else { + // the driver does not have a queue_chars handler + // loop through this character's component codes - const bool new_keydown = !m_status_keydown; const keycode_map_entry *const code = find_code(m_buffer[m_bufbegin]); - if (code != nullptr) + bool advance; + if (code) { - for (int fieldnum = 0; fieldnum < ARRAY_LENGTH(code->field); fieldnum++) + do { - ioport_field *const field = code->field[fieldnum]; - if (field == nullptr) - break; + assert(m_fieldnum < ARRAY_LENGTH(code->field)); - // special handling for toggle fields - if (field->live().toggle) + ioport_field *const field = code->field[m_fieldnum]; + if (field) { - if (new_keydown) + // special handling for toggle fields + if (!field->live().toggle) + field->set_value(!m_status_keydown); + else if (!m_status_keydown) field->set_value(!field->digital_value()); } - else - field->set_value(new_keydown); } + while (code->field[m_fieldnum] && (++m_fieldnum < ARRAY_LENGTH(code->field)) && m_status_keydown); + advance = (m_fieldnum >= ARRAY_LENGTH(code->field)) || !code->field[m_fieldnum]; + } + else + { + advance = true; } - // proceed to next character when keydown expires - if (!new_keydown) - m_bufbegin = (m_bufbegin + 1) % m_buffer.size(); - m_status_keydown = new_keydown; + if (advance) + { + m_fieldnum = 0; + m_status_keydown = !m_status_keydown; + + // proceed to next character when keydown expires + if (!m_status_keydown) + m_bufbegin = (m_bufbegin + 1) % m_buffer.size(); + } } // need to make sure timerproc is called again if buffer not empty |