From 05c487733790cb848b0b916bac77a86cec9eda7f Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Sat, 4 Apr 2020 17:17:42 +0700 Subject: [PATCH] news_r3k: mouse support (nw) --- src/mame/drivers/news_r3k.cpp | 40 ++++----- src/mame/machine/news_kbd.cpp | 152 ++++++++++++++++++++++++++++------ src/mame/machine/news_kbd.h | 41 +++++++-- 3 files changed, 172 insertions(+), 61 deletions(-) diff --git a/src/mame/drivers/news_r3k.cpp b/src/mame/drivers/news_r3k.cpp index 99dc92cc617..e86eaeab9e5 100644 --- a/src/mame/drivers/news_r3k.cpp +++ b/src/mame/drivers/news_r3k.cpp @@ -8,7 +8,6 @@ * * TODO * - sound - * - mouse */ #include "emu.h" @@ -61,7 +60,7 @@ public: , m_net(*this, "net") , m_fdc(*this, "fdc") , m_lcd(*this, "lcd") - , m_kbd(*this, "kbd") + , m_hid(*this, "hid") , m_scsi(*this, "scsi:7:cxd1185") , m_serial(*this, "serial%u", 0U) , m_scsibus(*this, "scsi") @@ -119,7 +118,6 @@ protected: u32 bus_error(); void itimer_w(u8 data); void itimer(void *ptr, s32 param); - void kbd_irq(int state); u8 debug_r() { return m_debug; } void debug_w(u8 data); @@ -135,7 +133,7 @@ protected: required_device m_fdc; required_device m_lcd; - required_device m_kbd; + required_device m_hid; required_device m_scsi; required_device_array m_serial; @@ -150,7 +148,6 @@ protected: u16 m_inten; u16 m_intst; - u8 m_kbd_status; u8 m_debug; static unsigned const NUM_INT = 4; @@ -171,8 +168,6 @@ void news_r3k_state::machine_start() for (bool &int_state : m_int_state) int_state = false; - - m_kbd_status = 0; } void news_r3k_state::machine_reset() @@ -207,24 +202,28 @@ void news_r3k_state::cpu_map(address_map &map) // 0x18500000 lcdc? map(0x18600000, 0x186fffff).r(FUNC(news_r3k_state::bus_error)); // ?? map(0x18780000, 0x18780003).r(FUNC(news_r3k_state::bus_error)); // nwb-225 - map(0x18c30000, 0x18c30003).r(FUNC(news_r3k_state::bus_error)); // second lance + map(0x18c30000, 0x18c30003).r(FUNC(news_r3k_state::bus_error)); // second lance (ram at 18c20000, id at 18c38000) map(0x18c40000, 0x18c40003).r(FUNC(news_r3k_state::bus_error)); // second scc map(0x18c40004, 0x18c40007).r(FUNC(news_r3k_state::bus_error)); // third scc - map(0x18c70000, 0x18c70003).r(FUNC(news_r3k_state::bus_error)); // third lance + //map(0x18c40100, 0x18c40118); // scc #1-#4 port/status + map(0x18c70000, 0x18c70003).r(FUNC(news_r3k_state::bus_error)); // third lance (ram at 18c60000, id at 18c78000) map(0x18e00000, 0x18e00003).r(FUNC(news_r3k_state::bus_error)); // nwb-252/nwb-253 crt map(0x18ff0000, 0x18ff0003).r(FUNC(news_r3k_state::bus_error)); // nwb-252/nwb-253 ctrl map(0x1fc00000, 0x1fc1ffff).rom().region("eprom", 0); //map(0x1fc40004, 0x1fc40004).w().umask32(0xff); ?? + // 1fc40007 // powreb? map(0x1fc80000, 0x1fc80001).rw(FUNC(news_r3k_state::inten_r), FUNC(news_r3k_state::inten_w)); map(0x1fc80002, 0x1fc80003).r(FUNC(news_r3k_state::intst_r)); map(0x1fc80004, 0x1fc80005).w(FUNC(news_r3k_state::intclr_w)); map(0x1fc80006, 0x1fc80006).w(FUNC(news_r3k_state::itimer_w)); - map(0x1fcc0003, 0x1fcc0003).rw(FUNC(news_r3k_state::debug_r), FUNC(news_r3k_state::debug_w)); - map(0x1fd00000, 0x1fd00000).r(m_kbd, FUNC(news_hle_kbd_device::data_r)); - map(0x1fd00001, 0x1fd00001).lr8([this]() { return m_kbd_status; }, "kbd_status_r"); - map(0x1fd00002, 0x1fd00002).lw8([this](u8 data) { m_kbd->reset(); }, "kbd_reset_w"); + // 1fcc0000 // cstrobe? + // 1fcc0002 // sccstatus0? + map(0x1fcc0003, 0x1fcc0003).rw(FUNC(news_r3k_state::debug_r), FUNC(news_r3k_state::debug_w)); + // 1fcc0007 // sccvect? + + map(0x1fd00000, 0x1fd00007).m(m_hid, FUNC(news_hid_hle_device::map)); map(0x1fd40000, 0x1fd40003).noprw().umask32(0xffff); // FIXME: ignore buzzer for now map(0x1fe00000, 0x1fe0000f).m(m_dma, FUNC(dmac_0448_device::map)); @@ -360,16 +359,6 @@ void news_r3k_state::itimer(void *ptr, s32 param) irq_w(ASSERT_LINE); } -void news_r3k_state::kbd_irq(int state) -{ - if (state) - m_kbd_status |= 2; - else - m_kbd_status &= ~2; - - irq_w(state); -} - void news_r3k_state::debug_w(u8 data) { LOG("debug_w 0x%02x (%s)\n", data, machine().describe_context()); @@ -477,8 +466,9 @@ void news_r3k_state::common(machine_config &config) m_lcd->set_raw(47185920, 1024, 0, 1024, 768, 0, 768); m_lcd->set_screen_update(FUNC(news_r3k_state::screen_update)); - NEWS_HLE_KBD(config, m_kbd); - m_kbd->irq_out().set(*this, FUNC(news_r3k_state::kbd_irq)); + NEWS_HID_HLE(config, m_hid); + m_hid->irq_out().set(FUNC(news_r3k_state::irq_w)); + m_hid->irq_out().set(FUNC(news_r3k_state::irq_w)); } void news_r3k_state::nws3260(machine_config &config) diff --git a/src/mame/machine/news_kbd.cpp b/src/mame/machine/news_kbd.cpp index 6efd7bc5cbb..d87bd6af2e7 100644 --- a/src/mame/machine/news_kbd.cpp +++ b/src/mame/machine/news_kbd.cpp @@ -2,11 +2,13 @@ // copyright-holders:Patrick Mackinlay /* - * Sony NEWS keyboard (high-level emulation). + * Sony NEWS keyboard and mouse (high-level emulation). * * Sources: * - * https://github.com/NetBSD/src/blob/trunk/sys/dev/news/newskeymap.c + * - https://github.com/tmk/tmk_keyboard/tree/master/converter/news_usb + * - https://github.com/NetBSD/src/blob/trunk/sys/dev/news/newskeymap.c + * - https://github.com/NetBSD/src/blob/trunk/sys/arch/newsmips/dev/ms_hb.c * * TODO: * - other languages (esp. Japanese) @@ -22,73 +24,157 @@ #define VERBOSE 0 #include "logmacro.h" -DEFINE_DEVICE_TYPE(NEWS_HLE_KBD, news_hle_kbd_device, "news_kbd_hle", "Sony NEWS Keyboard (HLE)") +DEFINE_DEVICE_TYPE(NEWS_HID_HLE, news_hid_hle_device, "news_hid_hle", "Sony NEWS Keyboard and Mouse (HLE)") -news_hle_kbd_device::news_hle_kbd_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) - : device_t(mconfig, NEWS_HLE_KBD, tag, owner, clock) +news_hid_hle_device::news_hid_hle_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) + : device_t(mconfig, NEWS_HID_HLE, tag, owner, clock) , device_matrix_keyboard_interface(mconfig, *this, "ROW0", "ROW1", "ROW2", "ROW3", "ROW4", "ROW5", "ROW6", "ROW7") + , m_mouse_x_axis(*this, "mouse_x_axis") + , m_mouse_y_axis(*this, "mouse_y_axis") + , m_mouse_buttons(*this, "mouse_buttons") , m_irq_out_cb(*this) { } -void news_hle_kbd_device::device_start() +void news_hid_hle_device::map(address_map &map) { - m_irq_out_cb.resolve_safe(); + map(0x0, 0x0).r(FUNC(news_hid_hle_device::data_r)); + map(0x1, 0x1).r(FUNC(news_hid_hle_device::status_r)); + map(0x2, 0x2).w(FUNC(news_hid_hle_device::reset_w)); + map(0x3, 0x3).w(FUNC(news_hid_hle_device::init_w)); + map(0x4, 0x4).r(FUNC(news_hid_hle_device::data_r)); + map(0x5, 0x5).r(FUNC(news_hid_hle_device::status_r)); + map(0x6, 0x6).w(FUNC(news_hid_hle_device::reset_w)); + map(0x7, 0x7).w(FUNC(news_hid_hle_device::init_w)); } -void news_hle_kbd_device::device_reset() +void news_hid_hle_device::device_start() { - m_fifo.clear(); - out_irq(false); + m_irq_out_cb.resolve_all_safe(); + + //save_item(NAME(m_fifo)); + save_item(NAME(m_irq_out_state)); + + save_item(NAME(m_mouse_x)); + save_item(NAME(m_mouse_y)); + save_item(NAME(m_mouse_b)); + save_item(NAME(m_mouse_enable)); +} + +void news_hid_hle_device::device_reset() +{ + m_fifo[KEYBOARD].clear(); + m_fifo[MOUSE].clear(); + + out_irq(false); + out_irq(false); + + m_mouse_enable = false; reset_key_state(); start_processing(attotime::from_hz(1'200)); } -void news_hle_kbd_device::key_make(u8 row, u8 column) +void news_hid_hle_device::key_make(u8 row, u8 column) { LOG("key_make row %d col %d\n", row, column); push_key((row << 4) | column); } -void news_hle_kbd_device::key_break(u8 row, u8 column) +void news_hid_hle_device::key_break(u8 row, u8 column) { LOG("key_break row %d col %d\n", row, column); push_key(0x80 | (row << 4) | column); } -void news_hle_kbd_device::push_key(u8 code) +void news_hid_hle_device::push_key(u8 code) { - m_fifo.enqueue(code); + m_fifo[KEYBOARD].enqueue(code); - out_irq(true); + out_irq(true); } -void news_hle_kbd_device::out_irq(bool state) +// HACK: abuse the keyboard row scanner to sample the mouse too +void news_hid_hle_device::scan_complete() { - if (m_irq_out_state != state) + if (!m_mouse_enable) + return; + + // read mouse state + s16 const x = m_mouse_x_axis->read(); + s16 const y = m_mouse_y_axis->read(); + u8 const b = m_mouse_buttons->read(); + + // compute delta + s8 const dx = x - m_mouse_x; + s8 const dy = y - m_mouse_y; + u8 const db = b ^ m_mouse_b; + + // report if fifo has room and position or buttons changed + if ((m_fifo[MOUSE].queue_length() < 6) && (dx || dy || db)) { - m_irq_out_state = state; - m_irq_out_cb(state); + LOG("mouse dx %d dy %d db %d\n", dx, dy, db); + + // compute sign + u8 const sx = (dx < 0) ? 0x08 : 0x00; + u8 const sy = (dy < 0) ? 0x10 : 0x00; + + // transmit data + m_fifo[MOUSE].enqueue(0x80 | sy | sx | b); + m_fifo[MOUSE].enqueue(dx & 0x7f); + m_fifo[MOUSE].enqueue(dy & 0x7f); + + // update mouse state + m_mouse_x = x; + m_mouse_y = y; + m_mouse_b = b; + + out_irq(true); } } -u8 news_hle_kbd_device::data_r() +template void news_hid_hle_device::out_irq(bool state) { - if (m_fifo.empty()) + if (m_irq_out_state[Device] != state) + { + m_irq_out_state[Device] = state; + m_irq_out_cb[Device](state); + } +} + +template u8 news_hid_hle_device::data_r() +{ + if (m_fifo[Device].empty()) return 0; - u8 const data = m_fifo.dequeue(); + u8 const data = m_fifo[Device].dequeue(); - if (m_fifo.empty()) - out_irq(false); + if (m_fifo[Device].empty()) + out_irq(false); return data; } -INPUT_PORTS_START(news_hle_kbd_device) +template void news_hid_hle_device::reset_w(u8 data) +{ + LOG("reset_w<%d> 0x%02x\n", Device, data); + m_fifo[Device].clear(); + + out_irq(false); +} + +template void news_hid_hle_device::init_w(u8 data) +{ + LOG("init_w<%d> 0x%02x\n", Device, data); + + // HACK: prevent unexpected mouse activity from crashing NEWS-OS + if (Device == MOUSE) + m_mouse_enable = bool(data); +} + +INPUT_PORTS_START(news_hid_hle_device) PORT_START("ROW0") PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) @@ -232,9 +318,21 @@ INPUT_PORTS_START(news_hle_kbd_device) PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_UNUSED) + + PORT_START("mouse_x_axis") + PORT_BIT(0xffff, 0, IPT_MOUSE_X) PORT_SENSITIVITY(100) + + PORT_START("mouse_y_axis") + PORT_BIT(0xffff, 0, IPT_MOUSE_Y) PORT_SENSITIVITY(100) + + PORT_START("mouse_buttons") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("Left Button") + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_CODE(MOUSECODE_BUTTON2) PORT_NAME("Right Button") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_CODE(MOUSECODE_BUTTON3) PORT_NAME("Middle Button") + PORT_BIT(0xf8, IP_ACTIVE_HIGH, IPT_UNUSED) INPUT_PORTS_END -ioport_constructor news_hle_kbd_device::device_input_ports() const +ioport_constructor news_hid_hle_device::device_input_ports() const { - return INPUT_PORTS_NAME(news_hle_kbd_device); + return INPUT_PORTS_NAME(news_hid_hle_device); } diff --git a/src/mame/machine/news_kbd.h b/src/mame/machine/news_kbd.h index 9b478902363..1f8382a82be 100644 --- a/src/mame/machine/news_kbd.h +++ b/src/mame/machine/news_kbd.h @@ -8,15 +8,21 @@ #include "machine/keyboard.h" -class news_hle_kbd_device +class news_hid_hle_device : public device_t , public device_matrix_keyboard_interface<8U> { public: - news_hle_kbd_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0); + news_hid_hle_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0); - auto irq_out() { return m_irq_out_cb.bind(); } - u8 data_r(); + enum news_hid_device : unsigned + { + KEYBOARD = 0, + MOUSE = 1, + }; + template auto irq_out() { return m_irq_out_cb[Device].bind(); } + + void map(address_map &map); protected: // device_t overrides @@ -27,17 +33,34 @@ protected: // device_matrix_keyboard_interface overrides virtual void key_make(u8 row, u8 column) override; virtual void key_break(u8 row, u8 column) override; + virtual void scan_complete() override; private: void push_key(u8 code); - void out_irq(bool state); - devcb_write_line m_irq_out_cb; + template void out_irq(bool state); - util::fifo m_fifo; - bool m_irq_out_state; + template u8 status_r() { return (!m_fifo[Device].empty() ? 2 : 0) | (m_fifo[Device].full() ? 1 : 0); } + template u8 data_r(); + template void reset_w(u8 data); + template void init_w(u8 data); + + required_ioport m_mouse_x_axis; + required_ioport m_mouse_y_axis; + required_ioport m_mouse_buttons; + + devcb_write_line::array<2> m_irq_out_cb; + + util::fifo m_fifo[2]; + bool m_irq_out_state[2]; + + // mouse state + s16 m_mouse_x; + s16 m_mouse_y; + u8 m_mouse_b; + bool m_mouse_enable; }; -DECLARE_DEVICE_TYPE(NEWS_HLE_KBD, news_hle_kbd_device) +DECLARE_DEVICE_TYPE(NEWS_HID_HLE, news_hid_hle_device) #endif // MAME_MACHINE_NEWS_KBD_H