-emu/natkeyboard.cpp: Allow keyboard devices to be enabled/disabled.

This fixes the "typing on all keyboards at once" issue.  You can now
enable and disable keyboard/keypad inputs per device in the Keyboard
Mode menu.  Default is to enable the first device with keyboard inputs,
and all device with keypad inputs but no keyboard inputs.  The settings
are saved in the CFG file for the machine.

Typing in natural keyboard mode only ever types on one keyboard at a
time, but now you can control which keyboard it types on, as it will be
the first enabled keyboard.

You can easily try this out with something like:
mame64d zorba -rs232 terminal cpm

-ui/inputmap.cpp: Show device descriptions as well as tag paths.

-mac128.cpp: Fixed mouse axis wrap compensation, cleaned up mouse code,
eliminated static variables for mouse input state.

You could see the issue with wrap detection easily enough just by
running mac128k/mac512k/macplus and tapping the arrow keys to move the
mouse one pixel at a time.  As you moved past the point where the axis
count wrapped, it would move one pixel in the opposite direction.

There were two function static variables related to mouse input state,
probably still lurking from when the code was initially made to use a
driver state class.  This obviously messes with save states and prevents
multiple instances.

- bus/a2bus/mouse.cpp: Fixed mouse axis wrap compensation.

This device had the same bug with wrap compensation as mac128k.cpp.
This commit is contained in:
Vas Crabb 2020-10-11 02:58:46 +11:00
parent 9e971ab36e
commit c751a5348a
14 changed files with 452 additions and 338 deletions

View File

@ -121,6 +121,8 @@ files {
MAME_DIR .. "src/frontend/mame/ui/inifile.h", MAME_DIR .. "src/frontend/mame/ui/inifile.h",
MAME_DIR .. "src/frontend/mame/ui/inputmap.cpp", MAME_DIR .. "src/frontend/mame/ui/inputmap.cpp",
MAME_DIR .. "src/frontend/mame/ui/inputmap.h", MAME_DIR .. "src/frontend/mame/ui/inputmap.h",
MAME_DIR .. "src/frontend/mame/ui/keyboard.cpp",
MAME_DIR .. "src/frontend/mame/ui/keyboard.h",
MAME_DIR .. "src/frontend/mame/ui/mainmenu.cpp", MAME_DIR .. "src/frontend/mame/ui/mainmenu.cpp",
MAME_DIR .. "src/frontend/mame/ui/mainmenu.h", MAME_DIR .. "src/frontend/mame/ui/mainmenu.h",
MAME_DIR .. "src/frontend/mame/ui/menu.cpp", MAME_DIR .. "src/frontend/mame/ui/menu.cpp",

View File

@ -299,17 +299,15 @@ void a2bus_mouse_device::mcu_port_c_w(uint8_t data)
template <unsigned AXIS, u8 DIR, u8 CLK> void a2bus_mouse_device::update_axis() template <unsigned AXIS, u8 DIR, u8 CLK> void a2bus_mouse_device::update_axis()
{ {
// read the axis // read the axis and check for changes
const int new_m = m_mousexy[AXIS]->read(); const int new_m = m_mousexy[AXIS]->read();
// did it change?
int diff = new_m - m_last[AXIS]; int diff = new_m - m_last[AXIS];
// check for wrap // check for wrap
if (diff > 0x80) if (diff > 0x80)
diff = 0x100 - diff; diff -= 0x100;
if (diff < -0x80) else if (diff < -0x80)
diff = -0x100 - diff; diff += 0x100;
m_count[AXIS] += diff; m_count[AXIS] += diff;
m_last[AXIS] = new_m; m_last[AXIS] = new_m;

View File

@ -1696,7 +1696,8 @@ time_t ioport_manager::initialize()
for (ioport_field &field : port.second->fields()) for (ioport_field &field : port.second->fields())
if (field.type_class() == INPUT_CLASS_CONTROLLER) if (field.type_class() == INPUT_CLASS_CONTROLLER)
{ {
if (players < field.player() + 1) players = field.player() + 1; if (players < field.player() + 1)
players = field.player() + 1;
field.set_player(field.player() + player_offset); field.set_player(field.player() + player_offset);
} }
} }
@ -2120,6 +2121,29 @@ void ioport_manager::load_config(config_type cfg_type, util::xml::data_node cons
for (input_type_entry &entry : m_typelist) for (input_type_entry &entry : m_typelist)
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype) for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
entry.defseq(seqtype) = entry.seq(seqtype); entry.defseq(seqtype) = entry.seq(seqtype);
// load keyboard enable/disable state
if (cfg_type == config_type::GAME)
{
for (util::xml::data_node const *kbdnode = parentnode->get_child("keyboard"); kbdnode; kbdnode = kbdnode->get_next_sibling("keyboard"))
{
char const *const tag = kbdnode->get_attribute_string("tag", nullptr);
int const enabled = kbdnode->get_attribute_int("enabled", -1);
if (tag && (0 <= enabled))
{
for (size_t i = 0; natkeyboard().keyboard_count() > i; ++i)
{
if (!strcmp(natkeyboard().keyboard_device(i).tag(), tag))
{
if (enabled)
natkeyboard().enable_keyboard(i);
else
natkeyboard().disable_keyboard(i);
}
}
}
}
}
} }
@ -2358,6 +2382,14 @@ void ioport_manager::save_default_inputs(util::xml::data_node &parentnode)
void ioport_manager::save_game_inputs(util::xml::data_node &parentnode) void ioport_manager::save_game_inputs(util::xml::data_node &parentnode)
{ {
// save keyboard enable/disable state
for (size_t i = 0; natkeyboard().keyboard_count() > i; ++i)
{
util::xml::data_node *const kbdnode = parentnode.add_child("keyboard", nullptr);
kbdnode->set_attribute("tag", natkeyboard().keyboard_device(i).tag());
kbdnode->set_attribute_int("enabled", natkeyboard().keyboard_enabled(i));
}
// iterate over ports // iterate over ports
for (auto &port : m_portlist) for (auto &port : m_portlist)
for (ioport_field &field : port.second->fields()) for (ioport_field &field : port.second->fields())

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Aaron Giles // copyright-holders:Aaron Giles,Vas Crabb
/*************************************************************************** /***************************************************************************
natkeyboard.cpp natkeyboard.cpp
@ -12,6 +12,9 @@
#include "natkeyboard.h" #include "natkeyboard.h"
#include "emuopts.h" #include "emuopts.h"
#include <algorithm>
#include <cstring>
//************************************************************************** //**************************************************************************
// DEBUGGING // DEBUGGING
@ -330,8 +333,8 @@ natural_keyboard::natural_keyboard(running_machine &machine)
, m_charqueue_empty() , m_charqueue_empty()
{ {
// try building a list of keycodes; if none are available, don't bother // try building a list of keycodes; if none are available, don't bother
build_codes(machine.ioport()); build_codes();
if (!m_keycode_map.empty()) if (m_have_charkeys)
{ {
m_buffer.resize(KEY_BUFFER_SIZE); m_buffer.resize(KEY_BUFFER_SIZE);
m_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(natural_keyboard::timer), this)); m_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(natural_keyboard::timer), this));
@ -370,18 +373,20 @@ void natural_keyboard::set_in_use(bool usage)
machine().options().set_value(OPTION_NATURAL_KEYBOARD, usage, OPTION_PRIORITY_CMDLINE); machine().options().set_value(OPTION_NATURAL_KEYBOARD, usage, OPTION_PRIORITY_CMDLINE);
// lock out (or unlock) all keyboard inputs // lock out (or unlock) all keyboard inputs
for (auto &port : machine().ioport().ports()) for (kbd_dev_info &devinfo : m_keyboards)
for (ioport_field &field : port.second->fields())
if (field.type() == IPT_KEYBOARD)
{ {
field.live().lockout = usage; for (ioport_field &field : devinfo.keyfields)
{
bool const is_keyboard(field.type() == IPT_KEYBOARD);
field.live().lockout = !devinfo.enabled || (is_keyboard && usage);
// clear pressed status when going out of use // clear pressed status when going out of use
if (!usage) if (is_keyboard && !usage)
field.set_value(0); field.set_value(0);
} }
} }
} }
}
//------------------------------------------------- //-------------------------------------------------
@ -413,19 +418,24 @@ void natural_keyboard::post_char(char32_t ch, bool normalize_crlf)
machine().logerror("natural_keyboard::post_char(): code=%i (%s) field.name='%s'\n", int(ch), unicode_to_string(ch).c_str(), (code != nullptr && code->field[0] != nullptr) ? code->field[0]->name() : "<null>"); machine().logerror("natural_keyboard::post_char(): code=%i (%s) field.name='%s'\n", int(ch), unicode_to_string(ch).c_str(), (code != nullptr && code->field[0] != nullptr) ? code->field[0]->name() : "<null>");
} }
// can we post this key in the queue directly?
if (can_post_directly(ch)) if (can_post_directly(ch))
{
// can post this key in the queue directly
internal_post(ch); internal_post(ch);
}
// can we post this key with an alternate representation?
else if (can_post_alternate(ch)) else if (can_post_alternate(ch))
{ {
const char_info *info = char_info::find(ch); // can post this key with an alternate representation
char_info const *const info = char_info::find(ch);
assert(info != nullptr && info->alternate != nullptr); assert(info != nullptr && info->alternate != nullptr);
const char *altstring = info->alternate; char const *altstring = info->alternate;
while (*altstring != 0) unsigned remain(std::strlen(altstring));
while (remain)
{ {
altstring += uchar_from_utf8(&ch, altstring, strlen(altstring)); int const used(uchar_from_utf8(&ch, altstring, remain));
assert(0 < used);
altstring += used;
remain -= used;
internal_post(ch); internal_post(ch);
} }
} }
@ -601,15 +611,59 @@ void natural_keyboard::paste()
// chars // chars
//------------------------------------------------- //-------------------------------------------------
void natural_keyboard::build_codes(ioport_manager &manager) void natural_keyboard::build_codes()
{ {
// find all shift keys ioport_manager &manager(machine().ioport());
unsigned mask = 0;
std::array<ioport_field *, SHIFT_COUNT> shift; // find all the devices with keyboard or keypad inputs
std::fill(std::begin(shift), std::end(shift), nullptr);
for (auto const &port : manager.ports()) for (auto const &port : manager.ports())
{ {
auto devinfo(
std::find_if(
m_keyboards.begin(),
m_keyboards.end(),
[&port] (kbd_dev_info const &info)
{
return &port.second->device() == &info.device.get();
}));
for (ioport_field &field : port.second->fields()) for (ioport_field &field : port.second->fields())
{
bool const is_keyboard(field.type() == IPT_KEYBOARD);
if (is_keyboard || (field.type() == IPT_KEYPAD))
{
if (m_keyboards.end() == devinfo)
devinfo = m_keyboards.emplace(devinfo, port.second->device());
devinfo->keyfields.emplace_back(field);
if (is_keyboard)
devinfo->keyboard = true;
else
devinfo->keypad = true;
}
}
}
std::sort(
std::begin(m_keyboards),
std::end(m_keyboards),
[] (kbd_dev_info const &l, kbd_dev_info const &r)
{
return 0 > std::strcmp(l.device.get().tag(), r.device.get().tag());
});
// set up key mappings for each keyboard
std::array<ioport_field *, SHIFT_COUNT> shift;
unsigned mask;
bool have_keyboard(false);
for (kbd_dev_info &devinfo : m_keyboards)
{
// enable all pure keypads and the first keyboard
if (!devinfo.keyboard || !have_keyboard)
devinfo.enabled = true;
have_keyboard = have_keyboard || devinfo.keyboard;
// find all shift keys
std::fill(std::begin(shift), std::end(shift), nullptr);
mask = 0;
for (ioport_field &field : devinfo.keyfields)
{ {
if (field.type() == IPT_KEYBOARD) if (field.type() == IPT_KEYBOARD)
{ {
@ -624,13 +678,11 @@ void natural_keyboard::build_codes(ioport_manager &manager)
} }
} }
} }
}
// iterate over ports and fields // iterate over keyboard/keypad fields
for (auto const &port : manager.ports()) for (ioport_field &field : devinfo.keyfields)
{
for (ioport_field &field : port.second->fields())
{ {
field.live().lockout = !devinfo.enabled;
if (field.type() == IPT_KEYBOARD) if (field.type() == IPT_KEYBOARD)
{ {
// iterate over all shift states // iterate over all shift states
@ -644,13 +696,14 @@ void natural_keyboard::build_codes(ioport_manager &manager)
{ {
if (((code < UCHAR_SHIFT_BEGIN) || (code > UCHAR_SHIFT_END)) && (code != 0)) if (((code < UCHAR_SHIFT_BEGIN) || (code > UCHAR_SHIFT_END)) && (code != 0))
{ {
keycode_map::iterator const found(m_keycode_map.find(code)); m_have_charkeys = true;
keycode_map::iterator const found(devinfo.codemap.find(code));
keycode_map_entry newcode; keycode_map_entry newcode;
std::fill(std::begin(newcode.field), std::end(newcode.field), nullptr); std::fill(std::begin(newcode.field), std::end(newcode.field), nullptr);
newcode.shift = curshift; newcode.shift = curshift;
newcode.condition = field.condition(); newcode.condition = field.condition();
unsigned fieldnum = 0; unsigned fieldnum(0);
for (unsigned i = 0, bits = curshift; (i < SHIFT_COUNT) && bits; ++i, bits >>= 1) for (unsigned i = 0, bits = curshift; (i < SHIFT_COUNT) && bits; ++i, bits >>= 1)
{ {
if (BIT(bits, 0)) if (BIT(bits, 0))
@ -658,11 +711,11 @@ void natural_keyboard::build_codes(ioport_manager &manager)
} }
newcode.field[fieldnum] = &field; newcode.field[fieldnum] = &field;
if (m_keycode_map.end() == found) if (devinfo.codemap.end() == found)
{ {
keycode_map_entries entries; keycode_map_entries entries;
entries.emplace_back(newcode); entries.emplace_back(newcode);
m_keycode_map.emplace(code, std::move(entries)); devinfo.codemap.emplace(code, std::move(entries));
} }
else else
found->second.emplace_back(newcode); found->second.emplace_back(newcode);
@ -670,8 +723,7 @@ void natural_keyboard::build_codes(ioport_manager &manager)
if (LOG_NATURAL_KEYBOARD) if (LOG_NATURAL_KEYBOARD)
{ {
machine().logerror("natural_keyboard: code=%u (%s) port=%p field.name='%s'\n", machine().logerror("natural_keyboard: code=%u (%s) port=%p field.name='%s'\n",
code, unicode_to_string(code), (void *)&port, field.name()); code, unicode_to_string(code), (void *)&field.port(), field.name());
}
} }
} }
} }
@ -681,7 +733,7 @@ void natural_keyboard::build_codes(ioport_manager &manager)
} }
// sort mapping entries by shift state // sort mapping entries by shift state
for (auto &mapping : m_keycode_map) for (auto &mapping : devinfo.codemap)
{ {
std::sort( std::sort(
mapping.second.begin(), mapping.second.begin(),
@ -689,6 +741,23 @@ void natural_keyboard::build_codes(ioport_manager &manager)
[] (keycode_map_entry const &x, keycode_map_entry const &y) { return x.shift < y.shift; }); [] (keycode_map_entry const &x, keycode_map_entry const &y) { return x.shift < y.shift; });
} }
} }
}
//-------------------------------------------------
// set_keyboard_enabled - enable or disable a
// device with key inputs
//-------------------------------------------------
void natural_keyboard::set_keyboard_enabled(size_t n, bool enable)
{
if (enable != m_keyboards[n].enabled)
{
m_keyboards[n].enabled = enable;
for (ioport_field &field : m_keyboards[n].keyfields)
field.live().lockout = !enable || ((field.type() == IPT_KEYBOARD) && in_use());
}
}
//------------------------------------------------- //-------------------------------------------------
@ -801,13 +870,15 @@ void natural_keyboard::timer(void *ptr, int param)
// the driver does not have a queue_chars handler // the driver does not have a queue_chars handler
// loop through this character's component codes // loop through this character's component codes
const keycode_map_entry *const code = find_code(m_buffer[m_bufbegin]); if (!m_fieldnum)
m_current_code = find_code(m_buffer[m_bufbegin]);
bool advance; bool advance;
if (code) if (m_current_code)
{ {
keycode_map_entry const code(*m_current_code);
do do
{ {
ioport_field *const field = code->field[m_fieldnum]; ioport_field *const field = code.field[m_fieldnum];
if (field) if (field)
{ {
// special handling for toggle fields // special handling for toggle fields
@ -817,8 +888,8 @@ void natural_keyboard::timer(void *ptr, int param)
field->set_value(!field->digital_value()); field->set_value(!field->digital_value());
} }
} }
while (code->field[m_fieldnum] && (++m_fieldnum < code->field.size()) && m_status_keydown); while (code.field[m_fieldnum] && (++m_fieldnum < code.field.size()) && m_status_keydown);
advance = (m_fieldnum >= code->field.size()) || !code->field[m_fieldnum]; advance = (m_fieldnum >= code.field.size()) || !code.field[m_fieldnum];
} }
else else
{ {
@ -888,14 +959,21 @@ std::string natural_keyboard::unicode_to_string(char32_t ch) const
const natural_keyboard::keycode_map_entry *natural_keyboard::find_code(char32_t ch) const const natural_keyboard::keycode_map_entry *natural_keyboard::find_code(char32_t ch) const
{ {
keycode_map::const_iterator const found(m_keycode_map.find(ch)); for (kbd_dev_info const &devinfo : m_keyboards)
if (m_keycode_map.end() == found) {
return nullptr; if (devinfo.enabled)
{
keycode_map::const_iterator const found(devinfo.codemap.find(ch));
if (devinfo.codemap.end() != found)
{
for (keycode_map_entry const &entry : found->second) for (keycode_map_entry const &entry : found->second)
{ {
if (entry.condition.eval()) if (entry.condition.eval())
return &entry; return &entry;
} }
}
}
}
return nullptr; return nullptr;
} }
@ -908,9 +986,26 @@ void natural_keyboard::dump(std::ostream &str) const
{ {
constexpr size_t left_column_width = 24; constexpr size_t left_column_width = 24;
// loop through all devices
bool firstdev(true);
for (kbd_dev_info const &devinfo : m_keyboards)
{
if (!firstdev)
str << '\n';
util::stream_format(
str,
"%s(%s) - %s%s%s %sabled\n",
devinfo.device.get().type().shortname(),
devinfo.device.get().tag(),
devinfo.keyboard ? "keyboard" : "",
(devinfo.keyboard && devinfo.keypad) ? "/" : "",
devinfo.keypad ? "keypad" : "",
devinfo.enabled ? "en" : "dis");
firstdev = false;
// loop through all codes // loop through all codes
bool first(true); bool firstkey(true);
for (auto &code : m_keycode_map) for (auto &code : devinfo.codemap)
{ {
// describe the character code // describe the character code
std::string const description(string_format("%08X (%s) ", code.first, unicode_to_string(code.first))); std::string const description(string_format("%08X (%s) ", code.first, unicode_to_string(code.first)));
@ -922,11 +1017,12 @@ void natural_keyboard::dump(std::ostream &str) const
{ {
// identify the keys used // identify the keys used
for (std::size_t field = 0; (entry.field.size() > field) && entry.field[field]; ++field) for (std::size_t field = 0; (entry.field.size() > field) && entry.field[field]; ++field)
util::stream_format(str, "%s'%s'", first ? "" : ", ", entry.field[field]->name()); util::stream_format(str, "%s'%s'", firstkey ? "" : ", ", entry.field[field]->name());
// carriage return // carriage return
str << '\n'; str << '\n';
first = false; firstkey = false;
}
} }
} }
} }

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Aaron Giles // copyright-holders:Aaron Giles,Vas Crabb
/*************************************************************************** /***************************************************************************
natkeyboard.h natkeyboard.h
@ -12,8 +12,12 @@
#pragma once #pragma once
#include <array>
#include <functional>
#include <iosfwd> #include <iosfwd>
#include <string>
#include <unordered_map> #include <unordered_map>
#include <vector>
//************************************************************************** //**************************************************************************
@ -21,9 +25,9 @@
//************************************************************************** //**************************************************************************
// keyboard helper function delegates // keyboard helper function delegates
typedef delegate<int (const char32_t *, size_t)> ioport_queue_chars_delegate; using ioport_queue_chars_delegate = delegate<int (const char32_t *, size_t)>;
typedef delegate<bool (char32_t)> ioport_accept_char_delegate; using ioport_accept_char_delegate = delegate<bool (char32_t)>;
typedef delegate<bool ()> ioport_charqueue_empty_delegate; using ioport_charqueue_empty_delegate = delegate<bool ()>;
// ======================> natural_keyboard // ======================> natural_keyboard
@ -41,13 +45,18 @@ public:
running_machine &machine() const { return m_machine; } running_machine &machine() const { return m_machine; }
bool empty() const { return (m_bufbegin == m_bufend); } bool empty() const { return (m_bufbegin == m_bufend); }
bool full() const { return ((m_bufend + 1) % m_buffer.size()) == m_bufbegin; } bool full() const { return ((m_bufend + 1) % m_buffer.size()) == m_bufbegin; }
bool can_post() const { return (!m_queue_chars.isnull() || !m_keycode_map.empty()); } bool can_post() const { return m_have_charkeys || !m_queue_chars.isnull(); }
bool is_posting() const { return (!empty() || (!m_charqueue_empty.isnull() && !m_charqueue_empty())); } bool is_posting() const { return (!empty() || (!m_charqueue_empty.isnull() && !m_charqueue_empty())); }
bool in_use() const { return m_in_use; } bool in_use() const { return m_in_use; }
// configuration // configuration
void configure(ioport_queue_chars_delegate queue_chars, ioport_accept_char_delegate accept_char, ioport_charqueue_empty_delegate charqueue_empty); void configure(ioport_queue_chars_delegate queue_chars, ioport_accept_char_delegate accept_char, ioport_charqueue_empty_delegate charqueue_empty);
void set_in_use(bool usage); void set_in_use(bool usage);
size_t keyboard_count() const { return m_keyboards.size(); }
device_t &keyboard_device(size_t n) { return m_keyboards[n].device; }
bool keyboard_enabled(size_t n) { return m_keyboards[n].enabled; }
void enable_keyboard(size_t n) { set_keyboard_enabled(n, true); }
void disable_keyboard(size_t n) { set_keyboard_enabled(n, false); }
// posting // posting
void post_char(char32_t ch, bool normalize_crlf = false); void post_char(char32_t ch, bool normalize_crlf = false);
@ -79,8 +88,22 @@ private:
typedef std::vector<keycode_map_entry> keycode_map_entries; typedef std::vector<keycode_map_entry> keycode_map_entries;
typedef std::unordered_map<char32_t, keycode_map_entries> keycode_map; typedef std::unordered_map<char32_t, keycode_map_entries> keycode_map;
// per-device character-to-key mapping
struct kbd_dev_info
{
kbd_dev_info(device_t &dev) : device(dev) { }
std::reference_wrapper<device_t> device;
std::vector<std::reference_wrapper<ioport_field> > keyfields;
keycode_map codemap;
bool keyboard = false;
bool keypad = false;
bool enabled = false;
};
// internal helpers // internal helpers
void build_codes(ioport_manager &manager); void build_codes();
void set_keyboard_enabled(size_t n, bool enable);
bool can_post_directly(char32_t ch); bool can_post_directly(char32_t ch);
bool can_post_alternate(char32_t ch); bool can_post_alternate(char32_t ch);
attotime choose_delay(char32_t ch); attotime choose_delay(char32_t ch);
@ -90,11 +113,14 @@ private:
const keycode_map_entry *find_code(char32_t ch) const; const keycode_map_entry *find_code(char32_t ch) const;
// internal state // internal state
std::vector<kbd_dev_info> m_keyboards; // info on keyboard devices in system
running_machine & m_machine; // reference to our machine running_machine & m_machine; // reference to our machine
bool m_have_charkeys; // are there keys with character?
bool m_in_use; // is natural keyboard in use? bool m_in_use; // is natural keyboard in use?
u32 m_bufbegin; // index of starting character u32 m_bufbegin; // index of starting character
u32 m_bufend; // index of ending character u32 m_bufend; // index of ending character
std::vector<char32_t> m_buffer; // actual buffer std::vector<char32_t> m_buffer; // actual buffer
keycode_map_entry const * m_current_code; // current code being typed
unsigned m_fieldnum; // current step in multi-key sequence unsigned m_fieldnum; // current step in multi-key sequence
bool m_status_keydown; // current keydown status bool m_status_keydown; // current keydown status
bool m_last_cr; // was the last char a CR? bool m_last_cr; // was the last char a CR?
@ -103,7 +129,6 @@ private:
ioport_queue_chars_delegate m_queue_chars; // queue characters callback ioport_queue_chars_delegate m_queue_chars; // queue characters callback
ioport_accept_char_delegate m_accept_char; // accept character callback ioport_accept_char_delegate m_accept_char; // accept character callback
ioport_charqueue_empty_delegate m_charqueue_empty; // character queue empty callback ioport_charqueue_empty_delegate m_charqueue_empty; // character queue empty callback
keycode_map m_keycode_map; // keycode map
}; };

View File

@ -93,7 +93,7 @@ void menu_input_general::populate(float &customtop, float &custombottom)
item.type = ioport_manager::type_is_analog(entry.type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; item.type = ioport_manager::type_is_analog(entry.type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
item.is_optional = false; item.is_optional = false;
item.name = entry.name(); item.name = entry.name();
item.owner_name = nullptr; item.owner = nullptr;
// stop after one, unless we're analog // stop after one, unless we're analog
if (item.type == INPUT_TYPE_DIGITAL) if (item.type == INPUT_TYPE_DIGITAL)
@ -164,7 +164,7 @@ void menu_input_specific::populate(float &customtop, float &custombottom)
item.type = field.is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; item.type = field.is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
item.is_optional = field.optional(); item.is_optional = field.optional();
item.name = field.name(); item.name = field.name();
item.owner_name = field.device().tag(); item.owner = &field.device();
// stop after one, unless we're analog // stop after one, unless we're analog
if (item.type == INPUT_TYPE_DIGITAL) if (item.type == INPUT_TYPE_DIGITAL)
@ -180,7 +180,7 @@ void menu_input_specific::populate(float &customtop, float &custombottom)
data.end(), data.end(),
[] (const input_item_data &i1, const input_item_data &i2) [] (const input_item_data &i1, const input_item_data &i2)
{ {
int cmp = strcmp(i1.owner_name, i2.owner_name); int cmp = strcmp(i1.owner->tag(), i2.owner->tag());
if (cmp < 0) if (cmp < 0)
return true; return true;
if (cmp > 0) if (cmp > 0)
@ -431,21 +431,24 @@ void menu_input::populate_sorted(float &customtop, float &custombottom)
// build the menu // build the menu
std::string text, subtext; std::string text, subtext;
std::string prev_owner; const device_t *prev_owner = nullptr;
bool first_entry = true; bool first_entry = true;
for (input_item_data &item : data) for (input_item_data &item : data)
{ {
// generate the name of the item itself, based off the base name and the type // generate the name of the item itself, based off the base name and the type
assert(nameformat[item.type] != nullptr); assert(nameformat[item.type] != nullptr);
if (item.owner_name && strcmp(item.owner_name, prev_owner.c_str()) != 0) if (item.owner && (item.owner != prev_owner))
{ {
if (first_entry) if (first_entry)
first_entry = false; first_entry = false;
else else
item_append(menu_item_type::SEPARATOR); item_append(menu_item_type::SEPARATOR);
item_append(string_format("[root%s]", item.owner_name), "", 0, nullptr); if (item.owner->owner())
prev_owner.assign(item.owner_name); item_append(string_format(_("%1$s [root%2$s]"), item.owner->type().fullname(), item.owner->tag()), "", 0, nullptr);
else
item_append(string_format(_("[root%1$s]"), item.owner->tag()), "", 0, nullptr);
prev_owner = item.owner;
} }
text = string_format(nameformat[item.type], item.name); text = string_format(nameformat[item.type], item.name);

View File

@ -55,7 +55,7 @@ protected:
input_seq seq; // copy of the live sequence input_seq seq; // copy of the live sequence
const input_seq * defseq = nullptr; // pointer to the default sequence const input_seq * defseq = nullptr; // pointer to the default sequence
const char * name = nullptr; // pointer to the base name of the item const char * name = nullptr; // pointer to the base name of the item
const char * owner_name = nullptr; // pointer to the name of the owner of the item const device_t * owner = nullptr; // pointer to the owner of the item
ioport_group group = IPG_INVALID; // group type ioport_group group = IPG_INVALID; // group type
uint8_t type = 0U; // type of port uint8_t type = 0U; // type of port
bool is_optional = false; // true if this input is considered optional bool is_optional = false; // true if this input is considered optional

View File

@ -0,0 +1,98 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/***************************************************************************
ui/keyboard.cpp
Keyboard mode menu.
***************************************************************************/
#include "emu.h"
#include "ui/keyboard.h"
#include "natkeyboard.h"
namespace ui {
namespace {
constexpr uintptr_t ITEM_KBMODE = 0x00000100;
constexpr uintptr_t ITEM_KBDEV_FIRST = 0x00000200;
} // anonymous namespace
menu_keyboard_mode::menu_keyboard_mode(mame_ui_manager &mui, render_container &container) : menu(mui, container)
{
}
void menu_keyboard_mode::populate(float &customtop, float &custombottom)
{
natural_keyboard &natkbd(machine().ioport().natkeyboard());
if (natkbd.can_post())
{
bool const natmode(natkbd.in_use());
item_append(
_("Keyboard Mode"),
natmode ? _("Natural") : _("Emulated"),
natmode ? FLAG_LEFT_ARROW : FLAG_RIGHT_ARROW,
reinterpret_cast<void *>(ITEM_KBMODE));
item_append(menu_item_type::SEPARATOR);
}
uintptr_t ref(ITEM_KBDEV_FIRST);
for (size_t i = 0; natkbd.keyboard_count() > i; ++i, ++ref)
{
device_t &kbddev(natkbd.keyboard_device(i));
bool const enabled(natkbd.keyboard_enabled(i));
item_append(
util::string_format(
kbddev.owner() ? _("%1$s [root%2$s]") : _("[root%2$s"),
kbddev.type().fullname(),
kbddev.tag()),
enabled ? _("Enabled") : _("Disabled"),
enabled ? FLAG_LEFT_ARROW : FLAG_RIGHT_ARROW,
reinterpret_cast<void *>(ref));
}
item_append(menu_item_type::SEPARATOR);
}
menu_keyboard_mode::~menu_keyboard_mode()
{
}
void menu_keyboard_mode::handle()
{
event const *const menu_event(process(0));
if (menu_event && uintptr_t(menu_event->itemref))
{
natural_keyboard &natkbd(machine().ioport().natkeyboard());
uintptr_t const ref(uintptr_t(menu_event->itemref));
bool const left(IPT_UI_LEFT == menu_event->iptkey);
bool const right(IPT_UI_RIGHT == menu_event->iptkey);
if (ITEM_KBMODE == ref)
{
if ((left || right) && (natkbd.in_use() != right))
{
natkbd.set_in_use(right);
reset(reset_options::REMEMBER_REF);
}
}
else if (ITEM_KBDEV_FIRST <= ref)
{
if ((left || right) && (natkbd.keyboard_enabled(ref - ITEM_KBDEV_FIRST) != right))
{
if (right)
natkbd.enable_keyboard(ref - ITEM_KBDEV_FIRST);
else
natkbd.disable_keyboard(ref - ITEM_KBDEV_FIRST);
reset(reset_options::REMEMBER_REF);
}
}
}
}
} // namespace ui

View File

@ -0,0 +1,33 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/***************************************************************************
ui/keyboard.h
Keyboard mode menu.
***************************************************************************/
#ifndef MAME_FRONTEND_UI_KEYBOARD_H
#define MAME_FRONTEND_UI_KEYBOARD_H
#pragma once
#include "ui/menu.h"
namespace ui {
class menu_keyboard_mode : public menu
{
public:
menu_keyboard_mode(mame_ui_manager &mui, render_container &container);
virtual ~menu_keyboard_mode();
private:
virtual void populate(float &customtop, float &custombottom) override;
virtual void handle() override;
};
} // namespace ui
#endif // MAME_FRONTEND_UI_KEYBOARD_H

View File

@ -22,6 +22,7 @@
#include "ui/info_pty.h" #include "ui/info_pty.h"
#include "ui/inifile.h" #include "ui/inifile.h"
#include "ui/inputmap.h" #include "ui/inputmap.h"
#include "ui/keyboard.h"
#include "ui/miscmenu.h" #include "ui/miscmenu.h"
#include "ui/pluginopt.h" #include "ui/pluginopt.h"
#include "ui/selgame.h" #include "ui/selgame.h"
@ -108,7 +109,7 @@ void menu_main::populate(float &customtop, float &custombottom)
if (network_interface_iterator(machine().root_device()).first() != nullptr) if (network_interface_iterator(machine().root_device()).first() != nullptr)
item_append(_("Network Devices"), "", 0, (void*)NETWORK_DEVICES); item_append(_("Network Devices"), "", 0, (void*)NETWORK_DEVICES);
if (ui().machine_info().has_keyboard() && machine().ioport().natkeyboard().can_post()) if (machine().ioport().natkeyboard().keyboard_count())
item_append(_("Keyboard Mode"), "", 0, (void *)KEYBOARD_MODE); item_append(_("Keyboard Mode"), "", 0, (void *)KEYBOARD_MODE);
item_append(_("Slider Controls"), "", 0, (void *)SLIDERS); item_append(_("Slider Controls"), "", 0, (void *)SLIDERS);

View File

@ -23,7 +23,6 @@
#include "mameopts.h" #include "mameopts.h"
#include "pluginopts.h" #include "pluginopts.h"
#include "drivenum.h" #include "drivenum.h"
#include "natkeyboard.h"
#include "romload.h" #include "romload.h"
#include "uiinput.h" #include "uiinput.h"
@ -40,42 +39,6 @@ namespace ui {
MENU HANDLERS MENU HANDLERS
***************************************************************************/ ***************************************************************************/
/*-------------------------------------------------
menu_keyboard_mode - menu that
-------------------------------------------------*/
menu_keyboard_mode::menu_keyboard_mode(mame_ui_manager &mui, render_container &container) : menu(mui, container)
{
}
void menu_keyboard_mode::populate(float &customtop, float &custombottom)
{
bool natural = machine().ioport().natkeyboard().in_use();
item_append(_("Keyboard Mode:"), natural ? _("Natural") : _("Emulated"), natural ? FLAG_LEFT_ARROW : FLAG_RIGHT_ARROW, nullptr);
}
menu_keyboard_mode::~menu_keyboard_mode()
{
}
void menu_keyboard_mode::handle()
{
bool natural = machine().ioport().natkeyboard().in_use();
/* process the menu */
const event *menu_event = process(0);
if (menu_event != nullptr)
{
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
{
machine().ioport().natkeyboard().set_in_use(!natural);
reset(reset_options::REMEMBER_REF);
}
}
}
/*------------------------------------------------- /*-------------------------------------------------
menu_bios_selection - populates the main menu_bios_selection - populates the main
bios selection menu bios selection menu

View File

@ -7,7 +7,6 @@
Internal MAME menus for the user interface. Internal MAME menus for the user interface.
***************************************************************************/ ***************************************************************************/
#ifndef MAME_FRONTEND_UI_MISCMENU_H #ifndef MAME_FRONTEND_UI_MISCMENU_H
#define MAME_FRONTEND_UI_MISCMENU_H #define MAME_FRONTEND_UI_MISCMENU_H
@ -24,17 +23,6 @@
namespace ui { namespace ui {
class menu_keyboard_mode : public menu
{
public:
menu_keyboard_mode(mame_ui_manager &mui, render_container &container);
virtual ~menu_keyboard_mode();
private:
virtual void populate(float &customtop, float &custombottom) override;
virtual void handle() override;
};
class menu_network_devices : public menu class menu_network_devices : public menu
{ {
public: public:

View File

@ -141,7 +141,7 @@ void menu_video_options::handle()
// process the menu // process the menu
event const *const menu_event(process(0)); event const *const menu_event(process(0));
if (menu_event && menu_event->itemref) if (menu_event && uintptr_t(menu_event->itemref))
{ {
switch (reinterpret_cast<uintptr_t>(menu_event->itemref)) switch (reinterpret_cast<uintptr_t>(menu_event->itemref))
{ {

View File

@ -246,11 +246,8 @@ private:
uint32_t m_overlay; uint32_t m_overlay;
int m_irq_count, m_ca1_data, m_ca2_data; int m_irq_count, m_ca1_data, m_ca2_data;
int m_mouse_bit_x; uint8_t m_mouse_bit[2], m_mouse_last[2];
int m_mouse_bit_y; int16_t m_mouse_last_m[2], m_mouse_count[2];
int last_mx, last_my;
int count_x, count_y;
int m_last_was_x;
int m_screen_buffer; int m_screen_buffer;
emu_timer *m_scan_timer; emu_timer *m_scan_timer;
emu_timer *m_hblank_timer; emu_timer *m_hblank_timer;
@ -288,13 +285,10 @@ void mac128_state::machine_start()
save_item(NAME(m_irq_count)); save_item(NAME(m_irq_count));
save_item(NAME(m_ca1_data)); save_item(NAME(m_ca1_data));
save_item(NAME(m_ca2_data)); save_item(NAME(m_ca2_data));
save_item(NAME(m_mouse_bit_x)); save_item(NAME(m_mouse_bit));
save_item(NAME(m_mouse_bit_y)); save_item(NAME(m_mouse_last));
save_item(NAME(last_mx)); save_item(NAME(m_mouse_last_m));
save_item(NAME(last_my)); save_item(NAME(m_mouse_count));
save_item(NAME(count_x));
save_item(NAME(count_y));
save_item(NAME(m_last_was_x));
save_item(NAME(m_screen_buffer)); save_item(NAME(m_screen_buffer));
save_item(NAME(m_scc_interrupt)); save_item(NAME(m_scc_interrupt));
save_item(NAME(m_via_interrupt)); save_item(NAME(m_via_interrupt));
@ -306,6 +300,9 @@ void mac128_state::machine_start()
save_item(NAME(m_adb_irq_pending)); save_item(NAME(m_adb_irq_pending));
save_item(NAME(m_drive_select)); save_item(NAME(m_drive_select));
save_item(NAME(m_scsiirq_enable)); save_item(NAME(m_scsiirq_enable));
m_mouse_bit[0] = m_mouse_bit[1] = 0;
m_mouse_last[0] = m_mouse_last[1] = 0;
} }
void mac128_state::machine_reset() void mac128_state::machine_reset()
@ -314,7 +311,6 @@ void mac128_state::machine_reset()
m_last_taken_interrupt = -1; m_last_taken_interrupt = -1;
m_overlay = 1; m_overlay = 1;
m_screen_buffer = 1; m_screen_buffer = 1;
m_mouse_bit_x = m_mouse_bit_y = 0;
m_last_taken_interrupt = 0; m_last_taken_interrupt = 0;
m_snd_enable = false; m_snd_enable = false;
m_main_buffer = true; m_main_buffer = true;
@ -518,137 +514,32 @@ void mac128_state::macplus_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mas
void mac128_state::scc_mouse_irq(int x, int y) void mac128_state::scc_mouse_irq(int x, int y)
{ {
static int lasty = 0;
static int lastx = 0;
// DCD lines are active low in hardware but active high to software // DCD lines are active low in hardware but active high to software
if (x && y)
{
if (m_last_was_x)
{
if(x == 2)
{
if(lastx)
{
m_scc->dcda_w(1);
m_mouse_bit_x = 0;
}
else
{
m_scc->dcda_w(0);
m_mouse_bit_x = 1;
}
}
else
{
if(lastx)
{
m_scc->dcda_w(1);
m_mouse_bit_x = 1;
}
else
{
m_scc->dcda_w(0);
m_mouse_bit_x = 0;
}
}
lastx = !lastx;
}
else
{
if(y == 2)
{
if(lasty)
{
m_scc->dcdb_w(1);
m_mouse_bit_y = 0;
}
else
{
m_scc->dcdb_w(0);
m_mouse_bit_y = 1;
}
}
else
{
if(lasty)
{
m_scc->dcdb_w(1);
m_mouse_bit_y = 1;
}
else
{
m_scc->dcdb_w(0);
m_mouse_bit_y = 0;
}
}
lasty = !lasty;
}
m_last_was_x ^= 1;
}
else
{
if (x) if (x)
{ {
if(x == 2) m_scc->dcda_w(m_mouse_last[0] ? 1 : 0);
if (x < 0)
{ {
if(lastx) m_mouse_bit[0] = m_mouse_last[0] ? 0 : 1;
{
m_scc->dcda_w(1);
m_mouse_bit_x = 0;
} }
else else
{ {
m_scc->dcda_w(0); m_mouse_bit[0] = m_mouse_last[0] ? 1 : 0;
m_mouse_bit_x = 1;
} }
m_mouse_last[0] = !m_mouse_last[0];
}
if (y)
{
m_scc->dcdb_w(m_mouse_last[1] ? 1 : 0);
if (y < 0)
{
m_mouse_bit[1] = m_mouse_last[1] ? 0 : 1;
} }
else else
{ {
if(lastx) m_mouse_bit[1] = m_mouse_last[1] ? 1 : 0;
{
m_scc->dcda_w(1);
m_mouse_bit_x = 1;
}
else
{
m_scc->dcda_w(0);
m_mouse_bit_x = 0;
}
}
lastx = !lastx;
}
else
{
if(y == 2)
{
if(lasty)
{
m_scc->dcdb_w(1);
m_mouse_bit_y = 0;
}
else
{
m_scc->dcdb_w(0);
m_mouse_bit_y = 1;
}
}
else
{
if(lasty)
{
m_scc->dcdb_w(1);
m_mouse_bit_y = 1;
}
else
{
m_scc->dcdb_w(0);
m_mouse_bit_y = 0;
}
}
lasty = !lasty;
} }
m_mouse_last[1] = !m_mouse_last[1];
} }
} }
@ -748,12 +639,9 @@ uint8_t mac128_state::mac_via_in_b()
{ {
int val = 0x40; int val = 0x40;
if (m_mouse_bit_y) /* Mouse Y2 */ val |= m_mouse_bit[1] << 5; // Mouse Y2
val |= 0x20; val |= m_mouse_bit[0] << 4; // Mouse X2
if (m_mouse_bit_x) /* Mouse X2 */ val |= BIT(~m_mouse0->read(), 0) << 3;
val |= 0x10;
if ((m_mouse0->read() & 0x01) == 0)
val |= 0x08;
val |= m_rtc->data_r(); val |= m_rtc->data_r();
@ -849,78 +737,65 @@ void mac128_state::mac_via_out_b_se(uint8_t data)
void mac128_state::mouse_callback() void mac128_state::mouse_callback()
{ {
int new_mx, new_my; // see if it moved in the x coord
int x_needs_update = 0, y_needs_update = 0; const int new_mx = m_mouse1->read();
if (new_mx != m_mouse_last_m[0])
new_mx = m_mouse1->read();
new_my = m_mouse2->read();
/* see if it moved in the x coord */
if (new_mx != last_mx)
{ {
int diff = new_mx - last_mx; int diff = new_mx - m_mouse_last_m[0];
/* check for wrap */ // check for wrap
if (diff > 0x80) if (diff > 0x80)
diff = 0x100-diff; diff -= 0x100;
if (diff < -0x80) else if (diff < -0x80)
diff = -0x100-diff; diff += 0x100;
count_x += diff; m_mouse_count[0] += diff;
m_mouse_last_m[0] = new_mx;
last_mx = new_mx;
} }
/* see if it moved in the y coord */
if (new_my != last_my)
{
int diff = new_my - last_my;
/* check for wrap */ // see if it moved in the y coord
const int new_my = m_mouse2->read();
if (new_my != m_mouse_last_m[1])
{
int diff = new_my - m_mouse_last_m[1];
// check for wrap
if (diff > 0x80) if (diff > 0x80)
diff = 0x100-diff; diff -= 0x100;
if (diff < -0x80) else if (diff < -0x80)
diff = -0x100-diff; diff += 0x100;
count_y += diff; m_mouse_count[1] += diff;
m_mouse_last_m[1] = new_my;
last_my = new_my;
} }
/* update any remaining count and then return */ // update any remaining count and then return
if (count_x) int x_needs_update = 0;
if (m_mouse_count[0] < 0)
{ {
if (count_x < 0) m_mouse_count[0]++;
{ x_needs_update = -1;
count_x++;
m_mouse_bit_x = 0;
x_needs_update = 2;
} }
else else if (m_mouse_count[0])
{ {
count_x--; m_mouse_count[0]--;
m_mouse_bit_x = 1;
x_needs_update = 1; x_needs_update = 1;
} }
} int y_needs_update = 0;
else if (count_y) if (m_mouse_count[1] < 0)
{ {
if (count_y < 0) m_mouse_count[1]++;
{
count_y++;
m_mouse_bit_y = 1;
y_needs_update = 1; y_needs_update = 1;
} }
else else if (m_mouse_count[1])
{ {
count_y--; m_mouse_count[1]--;
m_mouse_bit_y = 0; y_needs_update = -1;
y_needs_update = 2;
}
} }
if (x_needs_update || y_needs_update) if (x_needs_update || y_needs_update)
{ {
/* assert Port B External Interrupt on the SCC */ // assert Port B External Interrupt on the SCC
scc_mouse_irq(x_needs_update, y_needs_update); scc_mouse_irq(x_needs_update, y_needs_update);
} }
} }
@ -1164,10 +1039,10 @@ static INPUT_PORTS_START( macplus )
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Button") PORT_CODE(MOUSECODE_BUTTON1)
PORT_START("MOUSE1") /* Mouse - X AXIS */ PORT_START("MOUSE1") /* Mouse - X AXIS */
PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0)
PORT_START("MOUSE2") /* Mouse - Y AXIS */ PORT_START("MOUSE2") /* Mouse - Y AXIS */
PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0)
INPUT_PORTS_END INPUT_PORTS_END
static INPUT_PORTS_START( macadb ) static INPUT_PORTS_START( macadb )