aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2022-04-09 00:04:39 +0200
committerJavier <dev.git@javispedro.com>2022-04-09 00:04:39 +0200
commit90cecec048ee29a4971b8bda571da2a2b9613024 (patch)
tree5aa8e9c6a8f8694f12972ab89e215dfcfed65db2
parent0f6414cb3f8afa2012f6567e2fbfe844b8bd4b78 (diff)
downloadvbados-90cecec048ee29a4971b8bda571da2a2b9613024.tar.gz
vbados-90cecec048ee29a4971b8bda571da2a2b9613024.zip
support generating a keystroke on wheel movement
-rw-r--r--dosmain.c90
-rw-r--r--dostsr.c75
-rw-r--r--dostsr.h11
-rw-r--r--int16kbd.h12
4 files changed, 148 insertions, 40 deletions
diff --git a/dosmain.c b/dosmain.c
index 18120a8..a95908a 100644
--- a/dosmain.c
+++ b/dosmain.c
@@ -31,6 +31,7 @@
#include "vmware.h"
#include "dostsr.h"
+#if USE_WHEEL
static void detect_wheel(LPTSRDATA data)
{
// Do a quick check for a mouse wheel here.
@@ -54,6 +55,34 @@ static int set_wheel(LPTSRDATA data, bool enable)
return 0;
}
+static int set_wheel_key(LPTSRDATA data, const char *keyname)
+{
+ if (!data->usewheel || !data->haswheel) {
+ fprintf(stderr, "Wheel not detected or support not enabled\n");
+ return EXIT_FAILURE;
+ }
+ if (keyname) {
+ if (stricmp(keyname, "updn") == 0) {
+ data->wheel_up_key = 0x4800;
+ data->wheel_down_key = 0x5000;
+ printf("Generate Up Arrow / Down Arrow key presses on wheel movement");
+ } else if (stricmp(keyname, "pageupdn") == 0) {
+ data->wheel_up_key = 0x4900;
+ data->wheel_down_key = 0x5100;
+ printf("Generate PageUp / PageDown key presses on wheel movement");
+ } else {
+ fprintf(stderr, "Unknown key '%s'\n", keyname);
+ return EXIT_FAILURE;
+ }
+ } else {
+ printf("Disabling wheel keystroke generation\n");
+ data->wheel_up_key = 0;
+ data->wheel_down_key = 0;
+ }
+ return EXIT_SUCCESS;
+}
+#endif /* USE_WHEEL */
+
#if USE_VIRTUALBOX
static int set_virtualbox_integration(LPTSRDATA data, bool enable)
{
@@ -224,9 +253,9 @@ static int configure_driver(LPTSRDATA data)
#if USE_WHEEL
// Let's utilize the wheel by default
data->usewheel = true;
+ data->wheel_up_key = 0;
+ data->wheel_down_key = 0;
detect_wheel(data);
-#else
- data->usewheel = false;
#endif
#if USE_INTEGRATION
@@ -383,21 +412,21 @@ static __declspec(aborts) int install_driver(LPTSRDATA data, bool high)
static bool check_if_driver_uninstallable(LPTSRDATA data)
{
void (__interrupt __far *cur_int33_handler)() = _dos_getvect(0x33);
- void (__interrupt __far *our_int33_handler)() = data:>int33_isr;
- if (cur_int33_handler != our_int33_handler) {
- fprintf(stderr, "INT33 has been hooked by someone else, removing anyway\n");
- return true;
+ // Compare the segment of the installed handler to see if its ours
+ // or someone else's
+ if (FP_SEG(cur_int33_handler) != FP_SEG(data)) {
+ fprintf(stderr, "INT33 has been hooked by someone else, cannot safely remove\n");
+ return false;
}
#if USE_WIN386
{
void (__interrupt __far *cur_int2f_handler)() = _dos_getvect(0x2f);
- void (__interrupt __far *our_int2f_handler)() = data:>int2f_isr;
- if (cur_int2f_handler != our_int2f_handler) {
- fprintf(stderr, "INT2F has been hooked by someone else, removing anyway\n");
- return true;
+ if (FP_SEG(cur_int2f_handler) != FP_SEG(data)) {
+ fprintf(stderr, "INT2F has been hooked by someone else, cannot safely remove\n");
+ return false;
}
}
#endif
@@ -452,17 +481,19 @@ static void print_help(void)
"Usage: \n"
" VBMOUSE <ACTION> <ARGS..>\n\n"
"Supported actions:\n"
- " install install the driver (default)\n"
- " low install in conventional memory (otherwise UMB)\n"
- " uninstall uninstall the driver from memory\n"
+ " install install the driver (default)\n"
+ " low install in conventional memory (otherwise UMB)\n"
+ " uninstall uninstall the driver from memory\n"
#if USE_WHEEL
- " wheel <ON|OFF> enable/disable wheel API support\n"
+ " wheel <ON|OFF> enable/disable wheel API support\n"
+ " wheelkey <KEY|OFF> emulate a specific keystroke on wheel scroll\n"
+ " supported keys: updn, pageupdn\n"
#endif
#if USE_INTEGRATION
- " integ <ON|OFF> enable/disable virtualbox integration\n"
- " hostcur <ON|OFF> enable/disable mouse cursor rendering in host\n"
+ " integ <ON|OFF> enable/disable virtualbox integration\n"
+ " hostcur <ON|OFF> enable/disable mouse cursor rendering in host\n"
#endif
- " reset reset mouse driver settings\n"
+ " reset reset mouse driver settings\n"
);
}
@@ -473,6 +504,13 @@ static int invalid_arg(const char *s)
return EXIT_FAILURE;
}
+static int arg_required(const char *s)
+{
+ fprintf(stderr, "Argument required for '%s'", s);
+ print_help();
+ return EXIT_FAILURE;
+}
+
static bool is_true(const char *s)
{
return stricmp(s, "yes") == 0
@@ -553,6 +591,24 @@ int main(int argc, const char *argv[])
}
return set_wheel(data, enable);
+ } else if (stricmp(argv[argi], "wheelkey") == 0) {
+ bool enable = true;
+ const char *key = 0;
+
+ if (!data) return driver_not_found();
+
+ argi++;
+ if (argi < argc) {
+ if (is_false(argv[argi])) enable = false;
+ else key = argv[argi];
+ }
+
+ if (enable) {
+ if (!key) return arg_required("wheelkey");
+ return set_wheel_key(data, key);
+ } else {
+ return set_wheel_key(data, 0);
+ }
#endif
#if USE_INTEGRATION
} else if (stricmp(argv[argi], "integ") == 0) {
diff --git a/dostsr.c b/dostsr.c
index f3d199e..a9319d3 100644
--- a/dostsr.c
+++ b/dostsr.c
@@ -24,6 +24,7 @@
#include "dlog.h"
#include "ps2.h"
#include "int10vga.h"
+#include "int16kbd.h"
#include "int2fwin.h"
#include "int33.h"
#include "vbox.h"
@@ -670,15 +671,30 @@ static void handle_mouse_event(uint16_t buttons, bool absolute, int x, int y, in
bound_position_to_window();
+#if USE_WHEEL
if (data.haswheel && z) {
- events |= INT33_EVENT_MASK_WHEEL_MOVEMENT;
- // Higher byte of buttons contains wheel movement
- buttons |= (z & 0xFF) << 8;
- // Accumulate delta wheel movement
- data.wheel_delta += z;
- data.wheel_last.x = data.pos.x;
- data.wheel_last.y = data.pos.y;
+ if (!data.usewheelapi && (data.wheel_up_key || data.wheel_down_key)) {
+ // Emulate keystrokes on wheel movement
+ if (z < 0 && data.wheel_up_key) {
+ for (; z < 0; z++) {
+ int16_store_keystroke(data.wheel_up_key);
+ }
+ } else if (z > 0 && data.wheel_up_key) {
+ for (; z > 0; z--) {
+ int16_store_keystroke(data.wheel_down_key);
+ }
+ }
+ } else {
+ events |= INT33_EVENT_MASK_WHEEL_MOVEMENT;
+ // Higher byte of buttons contains wheel movement
+ buttons |= (z & 0xFF) << 8;
+ // Accumulate delta wheel movement
+ data.wheel_delta += z;
+ data.wheel_last.x = data.pos.x;
+ data.wheel_last.y = data.pos.y;
+ }
}
+#endif
// Update button status
for (i = 0; i < NUM_BUTTONS; ++i) {
@@ -782,12 +798,14 @@ static void ps2_mouse_handler(uint16_t word1, uint16_t word2, uint16_t word3, ui
// Rely on PS/2 relative coordinates.
}
+#if USE_WHEEL
// VirtualBox/Bochs BIOS does not pass wheel data to the callback,
// so we will fetch it directly from the BIOS data segment.
if (data.haswheel) {
int8_t __far * mouse_packet = MK_FP(bda_get_ebda_segment(), 0x28);
z = mouse_packet[3];
}
+#endif
}
#endif /* USE_VIRTUALBOX */
@@ -937,7 +955,6 @@ static void reset_mouse_hardware()
ps2m_init(PS2M_PACKET_SIZE_PLAIN);
}
#else
- data.haswheel = false;
ps2m_init(PS2M_PACKET_SIZE_PLAIN);
#endif
@@ -978,6 +995,10 @@ static void reset_mouse_settings()
data.cursor_hotspot.y = 0;
memcpy(data.cursor_graphic, default_cursor_graphic, sizeof(data.cursor_graphic));
+#if USE_WHEEL
+ data.usewheelapi = false;
+#endif
+
refresh_cursor(); // This will hide the cursor and update data.cursor_visible
}
@@ -1061,10 +1082,12 @@ static void int33_handler(union INTPACK r)
r.x.cx = snap_to_grid(data.pos.x, data.screen_granularity.x);
r.x.dx = snap_to_grid(data.pos.y, data.screen_granularity.y);
r.x.bx = data.buttons;
+#if USE_WHEEL
if (data.haswheel) {
r.h.bh = data.wheel_delta;
data.wheel_delta = 0;
}
+#endif
break;
case INT33_SET_MOUSE_POSITION:
#if TRACE_EVENTS
@@ -1082,30 +1105,34 @@ static void int33_handler(union INTPACK r)
break;
case INT33_GET_BUTTON_PRESSED_COUNTER:
r.x.ax = data.buttons;
+#if USE_WHEEL
if (data.haswheel) {
r.h.bh = data.wheel_delta;
+ if (r.x.bx == -1) {
+ // Asked for wheel information
+ return_clear_wheel_counter(&r);
+ break;
+ }
}
- if (data.haswheel && r.x.bx == -1) {
- // Wheel information
- return_clear_wheel_counter(&r);
- } else {
- // Regular button information
- int btn = MIN(r.x.bx, NUM_BUTTONS - 1);
- return_clear_button_counter(&r, &data.button[btn].pressed);
- }
+#endif
+ // Regular button information
+ return_clear_button_counter(&r,
+ &data.button[MIN(r.x.bx, NUM_BUTTONS - 1)].pressed);
break;
case INT33_GET_BUTTON_RELEASED_COUNTER:
r.x.ax = data.buttons;
+#if USE_WHEEL
if (data.haswheel) {
r.h.bh = data.wheel_delta;
+ if (r.x.bx == -1) {
+ // Asked for wheel information
+ return_clear_wheel_counter(&r);
+ break;
+ }
}
- if (data.haswheel && r.x.bx == -1) {
- // Wheel information
- return_clear_wheel_counter(&r);
- } else {
- int btn = MIN(r.x.bx, NUM_BUTTONS - 1);
- return_clear_button_counter(&r, &data.button[btn].released);
- }
+#endif
+ return_clear_button_counter(&r,
+ &data.button[MIN(r.x.bx, NUM_BUTTONS - 1)].released);
break;
case INT33_SET_HORIZONTAL_WINDOW:
dlog_print("Mouse set horizontal window [");
@@ -1249,9 +1276,11 @@ static void int33_handler(union INTPACK r)
#if USE_WHEEL
// Wheel API extensions:
case INT33_GET_CAPABILITIES:
+ dlog_puts("Mouse get capabitilies");
r.x.ax = INT33_WHEEL_API_MAGIC; // Driver supports wheel API
r.x.bx = 0;
r.x.cx = data.haswheel ? INT33_CAPABILITY_MOUSE_API : 0;
+ data.usewheelapi = true; // Someone calling this function likely wants to use wheel API
break;
#endif
// Our internal API extensions:
diff --git a/dostsr.h b/dostsr.h
index b3a5b3c..a025c92 100644
--- a/dostsr.h
+++ b/dostsr.h
@@ -71,8 +71,12 @@ typedef struct tsrdata {
#if USE_WIN386
void (__interrupt __far *prev_int2f_handler)();
#endif
+#if USE_WHEEL
/** Whether to enable & use wheel mouse. */
bool usewheel;
+ /** Key (scancode) to generate on wheel scroll up/down, or 0 for none. */
+ uint16_t wheel_up_key, wheel_down_key;
+#endif
// Video settings
/** Information of the current video mode. */
@@ -90,8 +94,10 @@ typedef struct tsrdata {
struct point screen_granularity;
// Detected mouse hardware
+#if USE_WHEEL
/** Whether the current mouse has a wheel (and support is enabled). */
bool haswheel;
+#endif
// Current mouse settings
/** Mouse sensitivity/speed. */
@@ -112,6 +118,11 @@ typedef struct tsrdata {
struct point cursor_hotspot;
/** Masks for the graphic cursor. */
uint16_t cursor_graphic[GRAPHIC_CURSOR_DATA_LEN/sizeof(uint16_t)];
+#if USE_WHEEL
+ /** Whether someone asked for the int33 wheel API, in which case we
+ * should send them wheel movement rather than fake keypresses. */
+ bool usewheelapi;
+#endif
// Current mouse status
/** Current cursor position (in pixels). */
diff --git a/int16kbd.h b/int16kbd.h
new file mode 100644
index 0000000..45db8ef
--- /dev/null
+++ b/int16kbd.h
@@ -0,0 +1,12 @@
+#ifndef INT16KBD_H
+#define INT16KBD_H
+
+static bool int16_store_keystroke(uint16_t scancode);
+#pragma aux int16_store_keystroke = \
+ "mov ah, 0x05" \
+ "int 0x16" \
+ __parm [cx] \
+ __value [al] \
+ __modify [ax]
+
+#endif // INT16KBD_H