diff options
-rw-r--r-- | dosmain.c | 90 | ||||
-rw-r--r-- | dostsr.c | 75 | ||||
-rw-r--r-- | dostsr.h | 11 | ||||
-rw-r--r-- | int16kbd.h | 12 |
4 files changed, 148 insertions, 40 deletions
@@ -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) { @@ -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: @@ -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 |