Completely reworked mouse handling - should now be smoother due to there no longer being a multi-layered game of telephone going on with all the various interim coordinate counters, also rewritten the serial mouse emulation ground ground up.
This commit is contained in:
@@ -19,7 +19,9 @@
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017-2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@@ -37,17 +39,22 @@ typedef struct mouse_t {
|
||||
} mouse_t;
|
||||
|
||||
int mouse_type = 0;
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
int mouse_z;
|
||||
int mouse_buttons;
|
||||
atomic_int mouse_x;
|
||||
atomic_int mouse_y;
|
||||
atomic_int mouse_z;
|
||||
atomic_int mouse_buttons;
|
||||
int mouse_mode;
|
||||
int mouse_timed = 1;
|
||||
int mouse_tablet_in_proximity = 0;
|
||||
int tablet_tool_type = 1; /* 0 = Puck/Cursor, 1 = Pen */
|
||||
|
||||
double mouse_x_abs;
|
||||
double mouse_y_abs;
|
||||
|
||||
double mouse_sensitivity = 1.0;
|
||||
double mouse_x_error = 0.0;
|
||||
double mouse_y_error = 0.0;
|
||||
|
||||
pc_timer_t mouse_timer; /* mouse event timer */
|
||||
|
||||
static const device_t mouse_none_device = {
|
||||
@@ -155,22 +162,81 @@ mouse_close(void)
|
||||
static void
|
||||
mouse_timer_poll(UNUSED(void *priv))
|
||||
{
|
||||
/* Poll at 255 Hz, maximum supported by PS/2 mic. */
|
||||
/* Poll at the specified sample rate. */
|
||||
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
|
||||
|
||||
#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */
|
||||
if (gdbstub_step == GDBSTUB_EXEC)
|
||||
if (gdbstub_step == GDBSTUB_EXEC) {
|
||||
#endif
|
||||
mouse_process();
|
||||
if (mouse_timed)
|
||||
mouse_process();
|
||||
#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
mouse_scale(int x, int y)
|
||||
{
|
||||
pclog("mouse_scale()\n");
|
||||
double scaled_x = (((double) x) * mouse_sensitivity) + mouse_x_error;
|
||||
double scaled_y = (((double) y) * mouse_sensitivity) + mouse_y_error;
|
||||
|
||||
mouse_x += (int) scaled_x;
|
||||
mouse_y += (int) scaled_y;
|
||||
|
||||
mouse_x_error = scaled_x - floor(scaled_x);
|
||||
mouse_y_error = scaled_y - floor(scaled_y);
|
||||
}
|
||||
|
||||
void
|
||||
mouse_scale_x(int x)
|
||||
{
|
||||
double scaled_x = ((double) x) * mouse_sensitivity + mouse_x_error;
|
||||
|
||||
mouse_x += (int) scaled_x;
|
||||
|
||||
mouse_x_error = scaled_x - ((double) mouse_x);
|
||||
}
|
||||
|
||||
void
|
||||
mouse_scale_y(int y)
|
||||
{
|
||||
double scaled_y = ((double) y) * mouse_sensitivity + mouse_y_error;
|
||||
|
||||
mouse_y += (int) scaled_y;
|
||||
|
||||
mouse_y_error = scaled_y - ((double) mouse_y);
|
||||
}
|
||||
|
||||
void
|
||||
mouse_set_z(int z)
|
||||
{
|
||||
mouse_z += z;
|
||||
}
|
||||
|
||||
void
|
||||
mouse_set_buttons_ex(int b)
|
||||
{
|
||||
mouse_buttons = b;
|
||||
}
|
||||
|
||||
int
|
||||
mouse_get_buttons_ex(void)
|
||||
{
|
||||
return mouse_buttons;
|
||||
}
|
||||
|
||||
void
|
||||
mouse_set_sample_rate(double new_rate)
|
||||
{
|
||||
mouse_timed = (new_rate > 0.0);
|
||||
|
||||
timer_stop(&mouse_timer);
|
||||
|
||||
sample_rate = new_rate;
|
||||
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
|
||||
if (mouse_timed)
|
||||
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -186,6 +252,9 @@ mouse_reset(void)
|
||||
mouse_x = mouse_y = mouse_z = 0;
|
||||
mouse_buttons = 0x00;
|
||||
mouse_mode = 0;
|
||||
mouse_timed = 1;
|
||||
|
||||
mouse_x_error = mouse_y_error = 0.0;
|
||||
|
||||
/* If no mouse configured, we're done. */
|
||||
if (mouse_type == 0)
|
||||
@@ -222,19 +291,14 @@ mouse_process(void)
|
||||
if (mouse_curr == NULL)
|
||||
return;
|
||||
|
||||
if (mouse_poll_ex)
|
||||
if ((mouse_mode >= 1) && mouse_poll_ex)
|
||||
mouse_poll_ex();
|
||||
else
|
||||
mouse_poll();
|
||||
|
||||
if ((mouse_dev_poll != NULL) || (mouse_curr->poll != NULL)) {
|
||||
if (mouse_curr->poll != NULL)
|
||||
mouse_curr->poll(mouse_x, mouse_y, mouse_z, mouse_buttons, mouse_x_abs, mouse_y_abs, mouse_priv);
|
||||
else
|
||||
mouse_dev_poll(mouse_x, mouse_y, mouse_z, mouse_buttons, mouse_priv);
|
||||
|
||||
/* Reset mouse deltas. */
|
||||
mouse_x = mouse_y = mouse_z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@@ -80,6 +81,7 @@
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mouse.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/plat_unused.h>
|
||||
#include <86box/random.h>
|
||||
|
||||
@@ -147,8 +149,6 @@ typedef struct mouse {
|
||||
int irq;
|
||||
int bn;
|
||||
int flags;
|
||||
int mouse_delayed_dx;
|
||||
int mouse_delayed_dy;
|
||||
int mouse_buttons;
|
||||
int mouse_buttons_last;
|
||||
int toggle_counter;
|
||||
@@ -480,10 +480,13 @@ bm_poll(int x, int y, UNUSED(int z), int b, UNUSED(double abs_x), UNUSED(double
|
||||
mouse_t *dev = (mouse_t *) priv;
|
||||
int xor ;
|
||||
|
||||
if (!mouse_capture && !video_fullscreen)
|
||||
return 1;
|
||||
|
||||
if (!(dev->flags & FLAG_ENABLED))
|
||||
return 1; /* Mouse is disabled, do nothing. */
|
||||
|
||||
if (!x && !y && !((b ^ dev->mouse_buttons_last) & 0x07)) {
|
||||
if (!mouse_x && !mouse_y && !((b ^ dev->mouse_buttons_last) & 0x07)) {
|
||||
dev->mouse_buttons_last = b;
|
||||
return 1; /* State has not changed, do nothing. */
|
||||
}
|
||||
@@ -498,7 +501,7 @@ bm_poll(int x, int y, UNUSED(int z), int b, UNUSED(double abs_x), UNUSED(double
|
||||
so update bits 6-3 here. */
|
||||
|
||||
/* If the mouse has moved, set bit 6. */
|
||||
if (x || y)
|
||||
if (mouse_x || mouse_y)
|
||||
dev->mouse_buttons |= 0x40;
|
||||
|
||||
/* Set bits 3-5 according to button state changes. */
|
||||
@@ -508,26 +511,30 @@ bm_poll(int x, int y, UNUSED(int z), int b, UNUSED(double abs_x), UNUSED(double
|
||||
|
||||
dev->mouse_buttons_last = b;
|
||||
|
||||
/* Clamp x and y to between -128 and 127 (int8_t range). */
|
||||
if (x > 127)
|
||||
x = 127;
|
||||
if (x < -128)
|
||||
x = -128;
|
||||
|
||||
if (y > 127)
|
||||
y = 127;
|
||||
if (y < -128)
|
||||
y = -128;
|
||||
|
||||
if (dev->timer_enabled) {
|
||||
/* Update delayed coordinates. */
|
||||
dev->mouse_delayed_dx += x;
|
||||
dev->mouse_delayed_dy += y;
|
||||
} else {
|
||||
if (!dev->timer_enabled) {
|
||||
/* If the counters are not frozen, update them. */
|
||||
if (!(dev->flags & FLAG_HOLD)) {
|
||||
dev->current_x = (int8_t) x;
|
||||
dev->current_y = (int8_t) y;
|
||||
if (mouse_x > 127) {
|
||||
dev->current_x = 127;
|
||||
mouse_x -= 127;
|
||||
} else if (mouse_x < 1-128) {
|
||||
dev->current_x = -128;
|
||||
mouse_x += 128;
|
||||
} else {
|
||||
dev->current_x = mouse_x;
|
||||
mouse_x = 0;
|
||||
}
|
||||
|
||||
if (mouse_y > 127) {
|
||||
dev->current_y = 127;
|
||||
mouse_y -= 127;
|
||||
} else if (mouse_y < 1-128) {
|
||||
dev->current_y = -128;
|
||||
mouse_y += 128;
|
||||
} else {
|
||||
dev->current_y = mouse_y;
|
||||
mouse_y = 0;
|
||||
}
|
||||
|
||||
dev->current_b = dev->mouse_buttons;
|
||||
}
|
||||
@@ -538,6 +545,7 @@ bm_poll(int x, int y, UNUSED(int z), int b, UNUSED(double abs_x), UNUSED(double
|
||||
bm_log("DEBUG: Data Interrupt Fired...\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -548,31 +556,31 @@ bm_update_data(mouse_t *dev)
|
||||
{
|
||||
int delta_x;
|
||||
int delta_y;
|
||||
int xor ;
|
||||
int xor;
|
||||
|
||||
/* If the counters are not frozen, update them. */
|
||||
if (!(dev->flags & FLAG_HOLD)) {
|
||||
if ((mouse_capture || video_fullscreen) && !(dev->flags & FLAG_HOLD)) {
|
||||
/* Update the deltas and the delays. */
|
||||
if (dev->mouse_delayed_dx > 127) {
|
||||
if (mouse_x > 127) {
|
||||
delta_x = 127;
|
||||
dev->mouse_delayed_dx -= 127;
|
||||
} else if (dev->mouse_delayed_dx < -128) {
|
||||
mouse_x -= 127;
|
||||
} else if (mouse_x < -128) {
|
||||
delta_x = -128;
|
||||
dev->mouse_delayed_dx += 128;
|
||||
mouse_x += 128;
|
||||
} else {
|
||||
delta_x = dev->mouse_delayed_dx;
|
||||
dev->mouse_delayed_dx = 0;
|
||||
delta_x = mouse_x;
|
||||
mouse_x = 0;
|
||||
}
|
||||
|
||||
if (dev->mouse_delayed_dy > 127) {
|
||||
if (mouse_y > 127) {
|
||||
delta_y = 127;
|
||||
dev->mouse_delayed_dy -= 127;
|
||||
} else if (dev->mouse_delayed_dy < -128) {
|
||||
mouse_y -= 127;
|
||||
} else if (mouse_y < -128) {
|
||||
delta_y = -128;
|
||||
dev->mouse_delayed_dy += 128;
|
||||
mouse_y += 128;
|
||||
} else {
|
||||
delta_y = dev->mouse_delayed_dy;
|
||||
dev->mouse_delayed_dy = 0;
|
||||
delta_y = mouse_y;
|
||||
mouse_y = 0;
|
||||
}
|
||||
|
||||
dev->current_x = (int8_t) delta_x;
|
||||
@@ -659,8 +667,6 @@ bm_init(const device_t *info)
|
||||
}
|
||||
mouse_set_buttons(dev->bn);
|
||||
|
||||
dev->mouse_delayed_dx = 0;
|
||||
dev->mouse_delayed_dy = 0;
|
||||
dev->mouse_buttons = 0;
|
||||
dev->mouse_buttons_last = 0;
|
||||
dev->sig_val = 0; /* the signature port value */
|
||||
@@ -707,6 +713,8 @@ bm_init(const device_t *info)
|
||||
else
|
||||
bm_log("Standard MS/Logitech BusMouse initialized\n");
|
||||
|
||||
mouse_set_sample_rate(0.0);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@@ -23,6 +24,7 @@
|
||||
#include <86box/device.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/mouse.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
enum {
|
||||
@@ -75,40 +77,51 @@ ps2_report_coordinates(atkbc_dev_t *dev, int main)
|
||||
uint8_t buff[3] = { 0x08, 0x00, 0x00 };
|
||||
int temp_z;
|
||||
|
||||
if (dev->x > 255) {
|
||||
dev->x = 255;
|
||||
if (mouse_x > 255) {
|
||||
buff[0] |= 0x40;
|
||||
buff[1] = 255;
|
||||
mouse_x -= 255;
|
||||
} else if (mouse_x < -256) {
|
||||
buff[0] |= (0x40 | 0x10);
|
||||
mouse_x += 256;
|
||||
} else {
|
||||
if (mouse_x < 0)
|
||||
buff[0] |= 0x10;
|
||||
buff[1] = mouse_x;
|
||||
mouse_x = 0;
|
||||
}
|
||||
if (dev->x < -256) {
|
||||
dev->x = -256;
|
||||
buff[0] |= 0x40;
|
||||
}
|
||||
if (dev->y > 255) {
|
||||
dev->y = 255;
|
||||
buff[0] |= 0x80;
|
||||
}
|
||||
if (dev->y < -256) {
|
||||
dev->y = -256;
|
||||
buff[0] |= 0x80;
|
||||
}
|
||||
if (dev->z < -8)
|
||||
dev->z = -8;
|
||||
if (dev->z > 7)
|
||||
dev->z = 7;
|
||||
|
||||
if (dev->x < 0)
|
||||
buff[0] |= 0x10;
|
||||
if (dev->y < 0)
|
||||
buff[0] |= 0x20;
|
||||
buff[0] |= (dev->b & ((dev->flags & FLAG_INTELLI) ? 0x07 : 0x03));
|
||||
buff[1] = (dev->x & 0xff);
|
||||
buff[2] = (dev->y & 0xff);
|
||||
if (mouse_y < -255) {
|
||||
buff[0] |= 0x80;
|
||||
buff[2] = 255;
|
||||
mouse_y += 255;
|
||||
} else if (mouse_y > 256) {
|
||||
buff[0] |= (0x80 | 0x20);
|
||||
mouse_y -= 256;
|
||||
} else {
|
||||
if (mouse_y > 0)
|
||||
buff[0] |= 0x20;
|
||||
buff[2] = -mouse_y;
|
||||
mouse_y = 0;
|
||||
}
|
||||
|
||||
if (dev->z < -7) {
|
||||
temp_z = 7;
|
||||
temp_z += 7;
|
||||
} else if (mouse_z > 8) {
|
||||
temp_z = (-8) & 0x0f;
|
||||
mouse_z -= 8;
|
||||
} else {
|
||||
temp_z = (-mouse_y) & 0x0f;
|
||||
mouse_z = 0;
|
||||
}
|
||||
|
||||
buff[0] |= (mouse_buttons & ((dev->flags & FLAG_INTELLI) ? 0x07 : 0x03));
|
||||
|
||||
kbc_at_dev_queue_add(dev, buff[0], main);
|
||||
kbc_at_dev_queue_add(dev, buff[1], main);
|
||||
kbc_at_dev_queue_add(dev, buff[2], main);
|
||||
if (dev->flags & FLAG_INTMODE) {
|
||||
temp_z = dev->z & 0x0f;
|
||||
if (dev->flags & FLAG_5BTN) {
|
||||
if (mouse_buttons & 8)
|
||||
temp_z |= 0x10;
|
||||
@@ -121,8 +134,6 @@ ps2_report_coordinates(atkbc_dev_t *dev, int main)
|
||||
}
|
||||
kbc_at_dev_queue_add(dev, temp_z, main);
|
||||
}
|
||||
|
||||
dev->x = dev->y = dev->z = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -132,7 +143,7 @@ ps2_set_defaults(atkbc_dev_t *dev)
|
||||
dev->rate = 100;
|
||||
mouse_set_sample_rate(100.0);
|
||||
dev->resolution = 2;
|
||||
dev->flags &= 0x88;
|
||||
dev->flags &= 0x188;
|
||||
mouse_scan = 0;
|
||||
}
|
||||
|
||||
@@ -316,25 +327,17 @@ ps2_poll(int x, int y, int z, int b, UNUSED(double abs_x), UNUSED(double abs_y),
|
||||
atkbc_dev_t *dev = (atkbc_dev_t *) priv;
|
||||
int packet_size = (dev->flags & FLAG_INTMODE) ? 4 : 3;
|
||||
|
||||
if (!mouse_scan || (!x && !y && !z && (b == dev->b)))
|
||||
return 0xff;
|
||||
int cond = (!mouse_capture && !video_fullscreen) || (!mouse_scan || (!x && !y && !z && (b == dev->b))) ||
|
||||
((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) >= (FIFO_SIZE - packet_size)));
|
||||
|
||||
if ((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) < (FIFO_SIZE - packet_size))) {
|
||||
dev->x = x;
|
||||
dev->y = -y;
|
||||
dev->z = -z;
|
||||
dev->b = b;
|
||||
} else {
|
||||
dev->x += x;
|
||||
dev->y -= y;
|
||||
dev->z -= z;
|
||||
if (!cond) {
|
||||
dev->b = b;
|
||||
|
||||
if (dev->mode == MODE_STREAM)
|
||||
ps2_report_coordinates(dev, 1);
|
||||
}
|
||||
|
||||
if ((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) < (FIFO_SIZE - packet_size)))
|
||||
ps2_report_coordinates(dev, 1);
|
||||
|
||||
return 0;
|
||||
return cond;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user