rm/rmnimbus.cpp: Allow choice of HLE mouse processing (#11890)

This commit is contained in:
Robin Sergeant 2024-01-25 22:03:30 +00:00 committed by GitHub
parent 9bbc99137f
commit 62419d27b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 116 additions and 13 deletions

View File

@ -68,6 +68,11 @@ void rmnimbus_state::nimbus_io(address_map &map)
static INPUT_PORTS_START( nimbus )
PORT_START("config")
PORT_CONFNAME( 0x01, 0x00, "Mouse emulation mode" )
PORT_CONFSETTING( 0x00, "Real" )
PORT_CONFSETTING( 0x01, "HLE" )
PORT_START(JOYSTICK0_TAG)
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_8WAY

View File

@ -77,6 +77,7 @@ public:
m_fdc(*this, FDC_TAG),
m_z80sio(*this, Z80SIO_TAG),
m_screen(*this, "screen"),
m_io_config(*this, "config"),
m_io_joysticks(*this, JOYSTICK_TAG_BASE "%u", 0),
m_io_mouse_button(*this, MOUSE_BUTTON_TAG),
m_io_mousex(*this, MOUSEX_TAG),
@ -104,6 +105,7 @@ private:
required_device<wd2793_device> m_fdc;
required_device<z80sio_device> m_z80sio;
required_device<screen_device> m_screen;
required_ioport m_io_config;
required_ioport_array<2> m_io_joysticks;
required_ioport m_io_mouse_button;
required_ioport m_io_mousex;
@ -227,6 +229,13 @@ private:
/* Mouse */
struct
{
uint16_t xpos_loc = 0;
uint16_t ypos_loc = 0;
uint16_t xmin_loc = 0;
uint16_t ymin_loc = 0;
uint16_t xmax_loc = 0;
uint16_t ymax_loc = 0;
uint8_t m_mouse_x = 0;
uint8_t m_mouse_y = 0;
@ -263,6 +272,8 @@ private:
offs_t dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer &params);
TIMER_CALLBACK_MEMBER(do_mouse);
void do_mouse_real(int8_t xdiff, int8_t ydiff);
void do_mouse_hle(int8_t xdiff, int8_t ydiff);
};
#endif // MAME_RM_RMNIMBUS_H

View File

@ -980,6 +980,29 @@ TIMER_CALLBACK_MEMBER(rmnimbus_state::do_mouse)
int8_t xdiff; // Difference from previous X and Y
int8_t ydiff;
// Read mose positions and calculate difference from previous value
mouse_x = m_io_mousex->read();
mouse_y = m_io_mousey->read();
xdiff = m_nimbus_mouse.m_mouse_x - mouse_x;
ydiff = m_nimbus_mouse.m_mouse_y - mouse_y;
if (m_io_config->read() & 0x01)
{
do_mouse_hle(xdiff, ydiff);
}
else
{
do_mouse_real(xdiff, ydiff);
}
// Update current mouse position
m_nimbus_mouse.m_mouse_x = mouse_x;
m_nimbus_mouse.m_mouse_y = mouse_y;
}
void rmnimbus_state::do_mouse_real(int8_t xdiff, int8_t ydiff)
{
uint8_t intstate_x; // Used to calculate if we should trigger interrupt
uint8_t intstate_y;
int xint; // X and Y interrupts to trigger
@ -990,13 +1013,6 @@ TIMER_CALLBACK_MEMBER(rmnimbus_state::do_mouse)
uint8_t mya;
uint8_t myb;
// Read mose positions and calculate difference from previous value
mouse_x = m_io_mousex->read();
mouse_y = m_io_mousey->read();
xdiff = m_nimbus_mouse.m_mouse_x - mouse_x;
ydiff = m_nimbus_mouse.m_mouse_y - mouse_y;
// convert movement into emulated movement of quadrature encoder in mouse.
if (xdiff < 0)
m_nimbus_mouse.m_mouse_pcx++;
@ -1049,17 +1065,78 @@ TIMER_CALLBACK_MEMBER(rmnimbus_state::do_mouse)
m_nimbus_mouse.m_reg0a4 |= ( myb & 0x01) << 0; // YB
}
// Update current mouse position
m_nimbus_mouse.m_mouse_x = mouse_x;
m_nimbus_mouse.m_mouse_y = mouse_y;
// and interrupt state
m_nimbus_mouse.m_intstate_x=intstate_x;
m_nimbus_mouse.m_intstate_y=intstate_y;
}
void rmnimbus_state::do_mouse_hle(int8_t xdiff, int8_t ydiff)
{
if (MOUSE_INT_ENABLED(this))
{
// bypass bios ISR and update mouse cursor position locations directly
address_space &space = m_maincpu->space(AS_PROGRAM);
if (xdiff)
{
uint16_t x = space.read_word_unaligned(m_nimbus_mouse.xpos_loc);
if ((xdiff < 0) && (x != space.read_word_unaligned(m_nimbus_mouse.xmax_loc)))
{
x++;
}
else if (x != space.read_word_unaligned(m_nimbus_mouse.xmin_loc))
{
x--;
}
space.write_word_unaligned(m_nimbus_mouse.xpos_loc, x);
}
if (ydiff)
{
uint16_t y = space.read_word_unaligned(m_nimbus_mouse.ypos_loc);
if ((ydiff < 0) && (y != space.read_word_unaligned(m_nimbus_mouse.ymin_loc)))
{
y--;
}
else if (y != space.read_word_unaligned(m_nimbus_mouse.ymax_loc))
{
y++;
}
space.write_word_unaligned(m_nimbus_mouse.ypos_loc, y);
}
}
else
{
// store status to support polling operation of mouse
// (not tested as no software seems to use this method!)
if (xdiff || ydiff)
{
m_nimbus_mouse.m_reg0a4 = 0;
}
if (xdiff < 0)
{
m_nimbus_mouse.m_reg0a4 |= CONTROLLER_RIGHT;
}
else if (xdiff > 0)
{
m_nimbus_mouse.m_reg0a4 |= CONTROLLER_LEFT;
}
if (ydiff < 0)
{
m_nimbus_mouse.m_reg0a4 |= CONTROLLER_DOWN;
}
else if (ydiff > 0)
{
m_nimbus_mouse.m_reg0a4 |= CONTROLLER_UP;
}
}
}
void rmnimbus_state::mouse_js_reset()
{
constexpr uint16_t bios_addresses[] = { 0x18cd, 0x196d, 0x196d, 0x1a6d, 0x1a6d, 0x1a77 };
m_nimbus_mouse.m_mouse_x=128;
m_nimbus_mouse.m_mouse_y=128;
m_nimbus_mouse.m_mouse_pcx=0;
@ -1068,6 +1145,15 @@ void rmnimbus_state::mouse_js_reset()
m_nimbus_mouse.m_intstate_y=0;
m_nimbus_mouse.m_reg0a4=0xC0;
// calculate addresses for mouse related variable used by the bios mouse ISR
auto bios_base = bios_addresses[system_bios() - 1];
m_nimbus_mouse.xpos_loc = bios_base + 8;
m_nimbus_mouse.ypos_loc = bios_base + 10;
m_nimbus_mouse.xmin_loc = bios_base;
m_nimbus_mouse.ymin_loc = bios_base + 4;
m_nimbus_mouse.xmax_loc = bios_base + 2;
m_nimbus_mouse.ymax_loc = bios_base + 6;
// Setup timer to poll the mouse
m_nimbus_mouse.m_mouse_timer->adjust(attotime::zero, 0, attotime::from_hz(MOUSE_POLL_FREQUENCY));
@ -1078,8 +1164,9 @@ uint8_t rmnimbus_state::nimbus_joystick_r()
{
/* Only the joystick drection data is read from this port
(which corresponds to the the low nibble of the selected joystick port).
The joystick buttons are read from the mouse data port instead. */
uint8_t result = m_io_joysticks[m_selected_js_idx]->read() & 0x0f;
The joystick buttons are read from the mouse data port instead.
Unused bits are set to 1. */
uint8_t result = m_io_joysticks[m_selected_js_idx]->read() | 0xf0;
if (result & CONTROLLER_RIGHT)
{