-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/inputmap.cpp",
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.h",
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()
{
// read the axis
// read the axis and check for changes
const int new_m = m_mousexy[AXIS]->read();
// did it change?
int diff = new_m - m_last[AXIS];
// check for wrap
if (diff > 0x80)
diff = 0x100 - diff;
if (diff < -0x80)
diff = -0x100 - diff;
diff -= 0x100;
else if (diff < -0x80)
diff += 0x100;
m_count[AXIS] += diff;
m_last[AXIS] = new_m;

View File

@ -1696,7 +1696,8 @@ time_t ioport_manager::initialize()
for (ioport_field &field : port.second->fields())
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);
}
}
@ -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_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++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)
{
// 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
for (auto &port : m_portlist)
for (ioport_field &field : port.second->fields())

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
// copyright-holders:Aaron Giles,Vas Crabb
/***************************************************************************
natkeyboard.cpp
@ -12,6 +12,9 @@
#include "natkeyboard.h"
#include "emuopts.h"
#include <algorithm>
#include <cstring>
//**************************************************************************
// DEBUGGING
@ -330,8 +333,8 @@ natural_keyboard::natural_keyboard(running_machine &machine)
, m_charqueue_empty()
{
// try building a list of keycodes; if none are available, don't bother
build_codes(machine.ioport());
if (!m_keycode_map.empty())
build_codes();
if (m_have_charkeys)
{
m_buffer.resize(KEY_BUFFER_SIZE);
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);
// lock out (or unlock) all keyboard inputs
for (auto &port : machine().ioport().ports())
for (ioport_field &field : port.second->fields())
if (field.type() == IPT_KEYBOARD)
for (kbd_dev_info &devinfo : m_keyboards)
{
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
if (!usage)
if (is_keyboard && !usage)
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>");
}
// can we post this key in the queue directly?
if (can_post_directly(ch))
{
// can post this key in the queue directly
internal_post(ch);
// can we post this key with an alternate representation?
}
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);
const char *altstring = info->alternate;
while (*altstring != 0)
char const *altstring = info->alternate;
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);
}
}
@ -601,15 +611,59 @@ void natural_keyboard::paste()
// chars
//-------------------------------------------------
void natural_keyboard::build_codes(ioport_manager &manager)
void natural_keyboard::build_codes()
{
// find all shift keys
unsigned mask = 0;
std::array<ioport_field *, SHIFT_COUNT> shift;
std::fill(std::begin(shift), std::end(shift), nullptr);
ioport_manager &manager(machine().ioport());
// find all the devices with keyboard or keypad inputs
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())
{
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)
{
@ -624,13 +678,11 @@ void natural_keyboard::build_codes(ioport_manager &manager)
}
}
}
}
// iterate over ports and fields
for (auto const &port : manager.ports())
{
for (ioport_field &field : port.second->fields())
// iterate over keyboard/keypad fields
for (ioport_field &field : devinfo.keyfields)
{
field.live().lockout = !devinfo.enabled;
if (field.type() == IPT_KEYBOARD)
{
// 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))
{
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;
std::fill(std::begin(newcode.field), std::end(newcode.field), nullptr);
newcode.shift = curshift;
newcode.condition = field.condition();
unsigned fieldnum = 0;
unsigned fieldnum(0);
for (unsigned i = 0, bits = curshift; (i < SHIFT_COUNT) && bits; ++i, bits >>= 1)
{
if (BIT(bits, 0))
@ -658,11 +711,11 @@ void natural_keyboard::build_codes(ioport_manager &manager)
}
newcode.field[fieldnum] = &field;
if (m_keycode_map.end() == found)
if (devinfo.codemap.end() == found)
{
keycode_map_entries entries;
entries.emplace_back(newcode);
m_keycode_map.emplace(code, std::move(entries));
devinfo.codemap.emplace(code, std::move(entries));
}
else
found->second.emplace_back(newcode);
@ -670,8 +723,7 @@ void natural_keyboard::build_codes(ioport_manager &manager)
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());
}
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
for (auto &mapping : m_keycode_map)
for (auto &mapping : devinfo.codemap)
{
std::sort(
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; });
}
}
}
//-------------------------------------------------
// 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
// 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;
if (code)
if (m_current_code)
{
keycode_map_entry const code(*m_current_code);
do
{
ioport_field *const field = code->field[m_fieldnum];
ioport_field *const field = code.field[m_fieldnum];
if (field)
{
// special handling for toggle fields
@ -817,8 +888,8 @@ void natural_keyboard::timer(void *ptr, int param)
field->set_value(!field->digital_value());
}
}
while (code->field[m_fieldnum] && (++m_fieldnum < code->field.size()) && m_status_keydown);
advance = (m_fieldnum >= code->field.size()) || !code->field[m_fieldnum];
while (code.field[m_fieldnum] && (++m_fieldnum < code.field.size()) && m_status_keydown);
advance = (m_fieldnum >= code.field.size()) || !code.field[m_fieldnum];
}
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
{
keycode_map::const_iterator const found(m_keycode_map.find(ch));
if (m_keycode_map.end() == found)
return nullptr;
for (kbd_dev_info const &devinfo : m_keyboards)
{
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)
{
if (entry.condition.eval())
return &entry;
}
}
}
}
return nullptr;
}
@ -908,9 +986,26 @@ void natural_keyboard::dump(std::ostream &str) const
{
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
bool first(true);
for (auto &code : m_keycode_map)
bool firstkey(true);
for (auto &code : devinfo.codemap)
{
// describe the character code
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
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
str << '\n';
first = false;
firstkey = false;
}
}
}
}

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
// copyright-holders:Aaron Giles,Vas Crabb
/***************************************************************************
natkeyboard.h
@ -12,8 +12,12 @@
#pragma once
#include <array>
#include <functional>
#include <iosfwd>
#include <string>
#include <unordered_map>
#include <vector>
//**************************************************************************
@ -21,9 +25,9 @@
//**************************************************************************
// keyboard helper function delegates
typedef delegate<int (const char32_t *, size_t)> ioport_queue_chars_delegate;
typedef delegate<bool (char32_t)> ioport_accept_char_delegate;
typedef delegate<bool ()> ioport_charqueue_empty_delegate;
using ioport_queue_chars_delegate = delegate<int (const char32_t *, size_t)>;
using ioport_accept_char_delegate = delegate<bool (char32_t)>;
using ioport_charqueue_empty_delegate = delegate<bool ()>;
// ======================> natural_keyboard
@ -41,13 +45,18 @@ public:
running_machine &machine() const { return m_machine; }
bool empty() const { return (m_bufbegin == m_bufend); }
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 in_use() const { return m_in_use; }
// configuration
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);
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
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::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
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_alternate(char32_t ch);
attotime choose_delay(char32_t ch);
@ -90,11 +113,14 @@ private:
const keycode_map_entry *find_code(char32_t ch) const;
// internal state
std::vector<kbd_dev_info> m_keyboards; // info on keyboard devices in system
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?
u32 m_bufbegin; // index of starting character
u32 m_bufend; // index of ending character
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
bool m_status_keydown; // current keydown status
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_accept_char_delegate m_accept_char; // accept character 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.is_optional = false;
item.name = entry.name();
item.owner_name = nullptr;
item.owner = nullptr;
// stop after one, unless we're analog
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.is_optional = field.optional();
item.name = field.name();
item.owner_name = field.device().tag();
item.owner = &field.device();
// stop after one, unless we're analog
if (item.type == INPUT_TYPE_DIGITAL)
@ -180,7 +180,7 @@ void menu_input_specific::populate(float &customtop, float &custombottom)
data.end(),
[] (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)
return true;
if (cmp > 0)
@ -431,21 +431,24 @@ void menu_input::populate_sorted(float &customtop, float &custombottom)
// build the menu
std::string text, subtext;
std::string prev_owner;
const device_t *prev_owner = nullptr;
bool first_entry = true;
for (input_item_data &item : data)
{
// generate the name of the item itself, based off the base name and the type
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)
first_entry = false;
else
item_append(menu_item_type::SEPARATOR);
item_append(string_format("[root%s]", item.owner_name), "", 0, nullptr);
prev_owner.assign(item.owner_name);
if (item.owner->owner())
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);

View File

@ -55,7 +55,7 @@ protected:
input_seq seq; // copy of the live 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 * 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
uint8_t type = 0U; // type of port
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/inifile.h"
#include "ui/inputmap.h"
#include "ui/keyboard.h"
#include "ui/miscmenu.h"
#include "ui/pluginopt.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)
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(_("Slider Controls"), "", 0, (void *)SLIDERS);

View File

@ -23,7 +23,6 @@
#include "mameopts.h"
#include "pluginopts.h"
#include "drivenum.h"
#include "natkeyboard.h"
#include "romload.h"
#include "uiinput.h"
@ -40,42 +39,6 @@ namespace ui {
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
bios selection menu

View File

@ -7,7 +7,6 @@
Internal MAME menus for the user interface.
***************************************************************************/
#ifndef MAME_FRONTEND_UI_MISCMENU_H
#define MAME_FRONTEND_UI_MISCMENU_H
@ -24,17 +23,6 @@
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
{
public:

View File

@ -141,7 +141,7 @@ void menu_video_options::handle()
// process the menu
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))
{

View File

@ -246,11 +246,8 @@ private:
uint32_t m_overlay;
int m_irq_count, m_ca1_data, m_ca2_data;
int m_mouse_bit_x;
int m_mouse_bit_y;
int last_mx, last_my;
int count_x, count_y;
int m_last_was_x;
uint8_t m_mouse_bit[2], m_mouse_last[2];
int16_t m_mouse_last_m[2], m_mouse_count[2];
int m_screen_buffer;
emu_timer *m_scan_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_ca1_data));
save_item(NAME(m_ca2_data));
save_item(NAME(m_mouse_bit_x));
save_item(NAME(m_mouse_bit_y));
save_item(NAME(last_mx));
save_item(NAME(last_my));
save_item(NAME(count_x));
save_item(NAME(count_y));
save_item(NAME(m_last_was_x));
save_item(NAME(m_mouse_bit));
save_item(NAME(m_mouse_last));
save_item(NAME(m_mouse_last_m));
save_item(NAME(m_mouse_count));
save_item(NAME(m_screen_buffer));
save_item(NAME(m_scc_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_drive_select));
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()
@ -314,7 +311,6 @@ void mac128_state::machine_reset()
m_last_taken_interrupt = -1;
m_overlay = 1;
m_screen_buffer = 1;
m_mouse_bit_x = m_mouse_bit_y = 0;
m_last_taken_interrupt = 0;
m_snd_enable = false;
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)
{
static int lasty = 0;
static int lastx = 0;
// 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 == 2)
m_scc->dcda_w(m_mouse_last[0] ? 1 : 0);
if (x < 0)
{
if(lastx)
{
m_scc->dcda_w(1);
m_mouse_bit_x = 0;
m_mouse_bit[0] = m_mouse_last[0] ? 0 : 1;
}
else
{
m_scc->dcda_w(0);
m_mouse_bit_x = 1;
m_mouse_bit[0] = m_mouse_last[0] ? 1 : 0;
}
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
{
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_mouse_bit[1] = m_mouse_last[1] ? 1 : 0;
}
m_mouse_last[1] = !m_mouse_last[1];
}
}
@ -748,12 +639,9 @@ uint8_t mac128_state::mac_via_in_b()
{
int val = 0x40;
if (m_mouse_bit_y) /* Mouse Y2 */
val |= 0x20;
if (m_mouse_bit_x) /* Mouse X2 */
val |= 0x10;
if ((m_mouse0->read() & 0x01) == 0)
val |= 0x08;
val |= m_mouse_bit[1] << 5; // Mouse Y2
val |= m_mouse_bit[0] << 4; // Mouse X2
val |= BIT(~m_mouse0->read(), 0) << 3;
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()
{
int new_mx, new_my;
int x_needs_update = 0, y_needs_update = 0;
new_mx = m_mouse1->read();
new_my = m_mouse2->read();
/* see if it moved in the x coord */
if (new_mx != last_mx)
// see if it moved in the x coord
const int new_mx = m_mouse1->read();
if (new_mx != m_mouse_last_m[0])
{
int diff = new_mx - last_mx;
int diff = new_mx - m_mouse_last_m[0];
/* check for wrap */
// check for wrap
if (diff > 0x80)
diff = 0x100-diff;
if (diff < -0x80)
diff = -0x100-diff;
diff -= 0x100;
else if (diff < -0x80)
diff += 0x100;
count_x += diff;
last_mx = new_mx;
m_mouse_count[0] += diff;
m_mouse_last_m[0] = 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)
diff = 0x100-diff;
if (diff < -0x80)
diff = -0x100-diff;
diff -= 0x100;
else if (diff < -0x80)
diff += 0x100;
count_y += diff;
last_my = new_my;
m_mouse_count[1] += diff;
m_mouse_last_m[1] = new_my;
}
/* update any remaining count and then return */
if (count_x)
// update any remaining count and then return
int x_needs_update = 0;
if (m_mouse_count[0] < 0)
{
if (count_x < 0)
{
count_x++;
m_mouse_bit_x = 0;
x_needs_update = 2;
m_mouse_count[0]++;
x_needs_update = -1;
}
else
else if (m_mouse_count[0])
{
count_x--;
m_mouse_bit_x = 1;
m_mouse_count[0]--;
x_needs_update = 1;
}
}
else if (count_y)
int y_needs_update = 0;
if (m_mouse_count[1] < 0)
{
if (count_y < 0)
{
count_y++;
m_mouse_bit_y = 1;
m_mouse_count[1]++;
y_needs_update = 1;
}
else
else if (m_mouse_count[1])
{
count_y--;
m_mouse_bit_y = 0;
y_needs_update = 2;
}
m_mouse_count[1]--;
y_needs_update = -1;
}
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);
}
}
@ -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_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_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
static INPUT_PORTS_START( macadb )