news_r3k: mouse support (nw)

This commit is contained in:
Patrick Mackinlay 2020-04-04 17:17:42 +07:00
parent 6ae7508bc3
commit 05c4877337
3 changed files with 172 additions and 61 deletions

View File

@ -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<upd72067_device> m_fdc;
required_device<screen_device> m_lcd;
required_device<news_hle_kbd_device> m_kbd;
required_device<news_hid_hle_device> m_hid;
required_device<cxd1185_device> m_scsi;
required_device_array<rs232_port_device, 2> 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<TIMER>(ASSERT_LINE);
}
void news_r3k_state::kbd_irq(int state)
{
if (state)
m_kbd_status |= 2;
else
m_kbd_status &= ~2;
irq_w<KBD>(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<news_hid_hle_device::KEYBOARD>().set(FUNC(news_r3k_state::irq_w<KBD>));
m_hid->irq_out<news_hid_hle_device::MOUSE>().set(FUNC(news_r3k_state::irq_w<MOUSE>));
}
void news_r3k_state::nws3260(machine_config &config)

View File

@ -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<KEYBOARD>));
map(0x1, 0x1).r(FUNC(news_hid_hle_device::status_r<KEYBOARD>));
map(0x2, 0x2).w(FUNC(news_hid_hle_device::reset_w<KEYBOARD>));
map(0x3, 0x3).w(FUNC(news_hid_hle_device::init_w<KEYBOARD>));
map(0x4, 0x4).r(FUNC(news_hid_hle_device::data_r<MOUSE>));
map(0x5, 0x5).r(FUNC(news_hid_hle_device::status_r<MOUSE>));
map(0x6, 0x6).w(FUNC(news_hid_hle_device::reset_w<MOUSE>));
map(0x7, 0x7).w(FUNC(news_hid_hle_device::init_w<MOUSE>));
}
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<KEYBOARD>(false);
out_irq<MOUSE>(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<KEYBOARD>(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<MOUSE>(true);
}
}
u8 news_hle_kbd_device::data_r()
template <news_hid_hle_device::news_hid_device Device> 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 <news_hid_hle_device::news_hid_device Device> 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<Device>(false);
return data;
}
INPUT_PORTS_START(news_hle_kbd_device)
template <news_hid_hle_device::news_hid_device Device> void news_hid_hle_device::reset_w(u8 data)
{
LOG("reset_w<%d> 0x%02x\n", Device, data);
m_fifo[Device].clear();
out_irq<Device>(false);
}
template <news_hid_hle_device::news_hid_device Device> 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);
}

View File

@ -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 <news_hid_device Device> 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 <news_hid_device Device> void out_irq(bool state);
util::fifo<u8, 8> m_fifo;
bool m_irq_out_state;
template <news_hid_device Device> u8 status_r() { return (!m_fifo[Device].empty() ? 2 : 0) | (m_fifo[Device].full() ? 1 : 0); }
template <news_hid_device Device> u8 data_r();
template <news_hid_device Device> void reset_w(u8 data);
template <news_hid_device Device> 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<u8, 8> 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