aboutsummaryrefslogtreecommitdiff
path: root/mousetsr.c
diff options
context:
space:
mode:
Diffstat (limited to 'mousetsr.c')
-rw-r--r--mousetsr.c114
1 files changed, 77 insertions, 37 deletions
diff --git a/mousetsr.c b/mousetsr.c
index 8990e4d..1e33dc2 100644
--- a/mousetsr.c
+++ b/mousetsr.c
@@ -60,6 +60,24 @@ static void bound_position_to_window(void)
if (data.pos.y > data.max.y) data.pos.y = data.max.y;
}
+/** Apply sensitivity to a raw mouse delta.
+ * @param sens value [5..100] given to set_mouse_sensitivity.
+ * @param x mouse delta in mickeys
+ * @return mouse delta scaled by sensitivity
+ *
+ * Note this is not acceleration, we are still multiplying the delta by a
+ * linear factor supposedly derived from the sensivitity [5..100] value.
+ * Every mouse driver seems to use their own formula for computing this factor.
+ * I am going with f(x) = x(x+32)/4096 since it looks round and fits decently,
+ * even with integer math (we don't divide by 4096 until after multiplying by delta).
+ * @see INT33_SET_MOUSE_SENSITIVITY for what the factor should look like. */
+int16_t apply_sensitivity(int16_t x, uint8_t sens, int16_t *rem)
+{
+ uint16_t factor = (sens * (sens + 32));
+ // TODO Actually use a shift instead of division
+ return scalei_rem(x, 4096, factor, rem);
+}
+
/** Constraints coordinate value to the desired granularity,
* which must be a power of two. */
static inline int16_t snap_to_grid(int16_t val, int16_t granularity)
@@ -72,7 +90,8 @@ static void hide_text_cursor(void)
{
// Restore the character under the old position of the cursor
uint16_t __far *ch = get_video_char(&data.video_mode,
- data.cursor_pos.x / 8, data.cursor_pos.y / 8);
+ data.cursor_pos.x / (data.screen_scale.x * 8),
+ data.cursor_pos.y / (data.screen_scale.y * 8));
*ch = data.cursor_prev_char;
data.cursor_visible = false;
}
@@ -80,7 +99,8 @@ static void hide_text_cursor(void)
static void show_text_cursor(void)
{
uint16_t __far *ch = get_video_char(&data.video_mode,
- data.pos.x / 8, data.pos.y / 8);
+ data.pos.x / (data.screen_scale.x * 8),
+ data.pos.y / (data.screen_scale.y * 8));
data.cursor_prev_char = *ch;
data.cursor_pos = data.pos;
*ch = (*ch & data.cursor_text_and_mask) ^ data.cursor_text_xor_mask;
@@ -624,40 +644,54 @@ static void handle_mouse_event(uint16_t buttons, bool absolute, int x, int y, ch
// Set the new absolute position
data.pos.x = x;
data.pos.y = y;
- data.pos_frac.x = 0;
- data.pos_frac.y = 0;
+ data.pos_pixel_frac.x = 0;
+ data.pos_pixel_frac.y = 0;
+ data.pos_sens_frac.x = 0;
+ data.pos_sens_frac.y = 0;
}
} else if (x || y) {
// Relative movement: x,y are in mickeys
- uint16_t ticks = bda_get_tick_count_lo();
+ uint16_t cur_ticks = bda_get_tick_count_lo();
unsigned ax = abs(x), ay = abs(y);
events |= INT33_EVENT_MASK_MOVEMENT;
- // Check if around one second has passed
- if ((ticks - data.last_motion_ticks) >= 18) {
+ // Check if a tick has passed, if so update speed
+ if (data.last_motion_ticks != cur_ticks) {
+ uint16_t elapsed_ticks = cur_ticks - data.last_motion_ticks;
+ data.cur_speed = (data.total_motion / elapsed_ticks) * 18; // Extrapolate speed from movement in this tick
+#if TRACE_EVENTS
+ dprintf("mouse speed = %u / threshold = %u total_motion in last %u ticks = %u\n", data.cur_speed, data.doubleSpeedThreshold * data.doubleSpeedThreshold, elapsed_ticks, data.total_motion);
+#endif
data.total_motion = 0;
- data.last_motion_ticks = ticks;
+ data.last_motion_ticks = cur_ticks;
}
-
- // If more than the double speed threshold has been moved in the last second,
- // double the speed
data.total_motion += ax * ax + ay * ay;
- if (data.total_motion > data.doubleSpeedThreshold * data.doubleSpeedThreshold) {
- x *= 2;
- y *= 2;
- }
+ // Apply sensitivity now, since unlike acceleration/speed, it affects the raw mickey counters
+ x = apply_sensitivity(x, data.sensitivity_x, &data.pos_sens_frac.x);
+ y = apply_sensitivity(y, data.sensitivity_y, &data.pos_sens_frac.y);
+
+ // Update the raw mickey counters
data.delta.x += x;
data.delta.y += y;
- data.delta_frac.x = 0;
- data.delta_frac.y = 0;
+
+ // Invalidate last abs position
data.abs_pos.x = -1;
data.abs_pos.y = -1;
- // Convert mickeys into pixels
- data.pos.x += scalei_rem(x, data.mickeysPerLine.x, 8, &data.pos_frac.x);
- data.pos.y += scalei_rem(y, data.mickeysPerLine.y, 8, &data.pos_frac.y);
+ // Convert mickeys into pixels, applying speed and acceleration
+
+ // If more than the double speed threshold has been moved in the last second,
+ // double the speed
+ if (data.cur_speed > data.double_speed_threshold * data.double_speed_threshold) {
+ x *= 2;
+ y *= 2;
+ }
+
+ // Apply mickeysPerLine. Keep the fractional part for the next movement!
+ data.pos.x += scalei_rem(x, data.mickeysPerLine.x, 8, &data.pos_pixel_frac.x);
+ data.pos.y += scalei_rem(y, data.mickeysPerLine.y, 8, &data.pos_pixel_frac.y);
}
bound_position_to_window();
@@ -1164,7 +1198,7 @@ static void reset_mouse_settings()
data.mickeysPerLine.x = 8;
data.mickeysPerLine.y = 16;
- data.doubleSpeedThreshold = 64;
+ data.double_speed_threshold = 64;
data.min.x = 0;
data.max.x = data.screen_max.x;
data.min.y = 0;
@@ -1177,6 +1211,10 @@ static void reset_mouse_settings()
data.cursor_hotspot.y = 0;
memcpy(data.cursor_graphic, default_cursor_graphic, sizeof(data.cursor_graphic));
+ // Sensitivity is persisted through resets, but ensure we init it with 50 if 0.
+ if (data.sensitivity_x == 0) data.sensitivity_x = 50;
+ if (data.sensitivity_y == 0) data.sensitivity_y = 50;
+
refresh_cursor(); // This will hide the cursor and update data.cursor_visible
}
@@ -1186,15 +1224,18 @@ static void reset_mouse_state()
int i;
data.pos.x = data.min.x + (data.max.x - data.min.x) / 2;
data.pos.y = data.min.y + (data.max.y - data.min.y) / 2;
- data.pos_frac.x = 0;
- data.pos_frac.y = 0;
+ data.pos_pixel_frac.x = 0;
+ data.pos_pixel_frac.y = 0;
+ data.pos_sens_frac.x = 0;
+ data.pos_sens_frac.y = 0;
data.delta.x = 0;
data.delta.y = 0;
- data.delta_frac.x = 0;
- data.delta_frac.y = 0;
data.abs_pos.x = -1;
data.abs_pos.y = -1;
data.buttons = 0;
+ data.cur_speed = 0;
+ data.total_motion = 0;
+ data.last_motion_ticks = bda_get_tick_count_lo();
for (i = 0; i < MAX_BUTTONS; i++) {
data.button[i].pressed.count = 0;
data.button[i].pressed.last.x = 0;
@@ -1307,12 +1348,12 @@ static void int33_handler(union INTPACK r)
#endif
data.pos.x = r.w.cx;
data.pos.y = r.w.dx;
- data.pos_frac.x = 0;
- data.pos_frac.y = 0;
+ data.pos_pixel_frac.x = 0;
+ data.pos_pixel_frac.y = 0;
+ data.pos_sens_frac.x = 0;
+ data.pos_sens_frac.y = 0;
data.delta.x = 0;
data.delta.y = 0;
- data.delta_frac.x = 0;
- data.delta_frac.y = 0;
bound_position_to_window();
break;
case INT33_GET_BUTTON_PRESSED_COUNTER:
@@ -1407,7 +1448,7 @@ static void int33_handler(union INTPACK r)
break;
case INT33_SET_SPEED_DOUBLE_THRESHOLD:
dprintf("Mouse set speed double threshold=%d\n", r.w.dx);
- data.doubleSpeedThreshold = r.w.dx;
+ data.double_speed_threshold = r.w.dx;
break;
case INT33_EXCHANGE_EVENT_HANDLER:
dputs("Mouse exchange event handler");
@@ -1439,15 +1480,14 @@ static void int33_handler(union INTPACK r)
case INT33_SET_MOUSE_SENSITIVITY:
dprintf("Mouse set sensitivity x=%d y=%d threshold=%d\n",
r.w.bx, r.w.cx, r.w.dx);
- // TODO According to cutemouse, sensitivity != mickeysPerLine
- data.mickeysPerLine.x = r.w.bx;
- data.mickeysPerLine.y = r.w.cx;
- data.doubleSpeedThreshold = r.w.dx;
+ data.sensitivity_x = BOUND(r.w.bx, 1, 100);
+ data.sensitivity_y = BOUND(r.w.cx, 1, 100);
+ data.double_speed_threshold = r.w.dx;
break;
case INT33_GET_MOUSE_SENSITIVITY:
- r.w.bx = data.mickeysPerLine.x;
- r.w.cx = data.mickeysPerLine.y;
- r.w.dx = data.doubleSpeedThreshold;
+ r.w.bx = data.sensitivity_x;
+ r.w.cx = data.sensitivity_y;
+ r.w.dx = data.double_speed_threshold;
break;
case INT33_RESET_SETTINGS:
dputs("Mouse reset settings");