diff options
author | Javier <dev.git@javispedro.com> | 2022-04-03 00:03:15 +0200 |
---|---|---|
committer | Javier <dev.git@javispedro.com> | 2022-04-03 00:03:15 +0200 |
commit | 7d93442564b57c2d292df7f823c2115d3e0b8c12 (patch) | |
tree | 6a7e31e172ced11dde78f1b0a1f38fa2ab252697 | |
parent | 3ca7b6c9cc23e118968b49a79f2b64fe4a3b73b3 (diff) | |
download | vbados-7d93442564b57c2d292df7f823c2115d3e0b8c12.tar.gz vbados-7d93442564b57c2d292df7f823c2115d3e0b8c12.zip |
complete wheel support
-rw-r--r-- | dosmain.c | 43 | ||||
-rw-r--r-- | dostsr.c | 52 | ||||
-rw-r--r-- | dostsr.h | 4 | ||||
-rw-r--r-- | int10vga.h | 1 | ||||
-rw-r--r-- | int33.h | 31 | ||||
-rw-r--r-- | w16mouse.c | 20 |
6 files changed, 124 insertions, 27 deletions
@@ -28,6 +28,24 @@ #include "vbox.h" #include "dostsr.h" +static int set_wheel(LPTSRDATA data, bool enable) +{ + printf("Setting wheel support to %s\n", enable ? "enabled" : "disabled"); + data->usewheel = enable; + + if (data->usewheel) { + // Do a quick check for a mouse wheel here. + // The TSR will do its own check when it is reset anyway + if (data->haswheel = ps2m_detect_wheel()) { + printf("Wheel mouse found and enabled\n"); + } + } else { + data->haswheel = false; + } + + return 0; +} + #if USE_VIRTUALBOX static int set_integration(LPTSRDATA data, bool enable) { @@ -99,15 +117,7 @@ static int configure_driver(LPTSRDATA data) } // Let's utilize the wheel by default - data->usewheel = true; - - if (data->usewheel) { - // Do a quick check for a mouse wheel here. - // The TSR will do its own check when it is reset anyway - if (data->haswheel = ps2m_detect_wheel()) { - printf("Wheel mouse found and enabled\n"); - } - } + set_wheel(data, true); #if USE_VIRTUALBOX // Assume initially that we want integration and host cursor @@ -232,6 +242,7 @@ static void print_help(void) "Supported actions:\n" "\tinstall install the driver (default)\n" "\tuninstall uninstall the driver from memory\n" + "\twheel <ON|OFF> enable/disable wheel API support\n" #if USE_VIRTUALBOX "\tinteg <ON|OFF> enable/disable virtualbox integration\n" "\thostcur <ON|OFF> enable/disable mouse cursor rendering in host\n" @@ -289,6 +300,17 @@ int main(int argc, const char *argv[]) return EXIT_FAILURE; } return uninstall_driver(data); + } else if (stricmp(argv[argi], "wheel") == 0) { + bool enable = true; + + if (!data) return driver_not_found(); + + argi++; + if (argi < argc) { + if (is_false(argv[argi])) enable = false; + } + + return set_wheel(data, enable); #if USE_VIRTUALBOX } else if (stricmp(argv[argi], "integ") == 0) { bool enable = true; @@ -311,6 +333,9 @@ int main(int argc, const char *argv[]) if (is_false(argv[argi])) enable = false; } + // Reset before changing this to ensure the cursor is not drawn + int33_reset(); + return set_host_cursor(data, enable); #endif } else if (stricmp(argv[argi], "reset") == 0) { @@ -384,7 +384,6 @@ static void load_cursor(void) /** Refreshes the information about the current video mode. */ static void refresh_video_info(void) { - uint8_t screen_columns = bda_get_num_columns(); uint8_t mode = bda_get_video_mode() & ~0x80; bool mode_change = mode != data.screen_mode; @@ -396,7 +395,9 @@ static void refresh_video_info(void) dlog_print("Current video mode="); dlog_printx(mode); dlog_print(" with cols="); - dlog_printd(screen_columns); + dlog_printd(bda_get_num_columns()); + dlog_print(" lastrow="); + dlog_printd(bda_get_last_row()); dlog_endline(); data.screen_mode = mode; @@ -412,8 +413,8 @@ static void refresh_video_info(void) case 2: case 3: // CGA text modes with 25 rows and variable columns case 7: // MDA Mono text mode - data.screen_max.x = (screen_columns * 8) - 1; - data.screen_max.y = (25 * 8) - 1; + data.screen_max.x = (bda_get_num_columns() * 8) - 1; + data.screen_max.y = ( 25 * 8) - 1; break; case 4: @@ -736,6 +737,7 @@ static void reset_mouse_state() data.button[i].released.last.x = 0; data.button[i].released.last.y = 0; } + data.wheel_delta = 0; data.cursor_visible = false; data.cursor_pos.x = 0; data.cursor_pos.y = 0; @@ -743,6 +745,16 @@ static void reset_mouse_state() bzero(data.cursor_prev_graphic, sizeof(data.cursor_prev_graphic)); } +static void return_clear_wheel_counter(union INTPACK __far *r) +{ + r->x.cx = data.wheel_last.x; + r->x.dx = data.wheel_last.y; + r->x.bx = data.wheel_delta; + data.wheel_last.x = 0; + data.wheel_last.y = 0; + data.wheel_delta = 0; +} + static void return_clear_button_counter(union INTPACK __far *r, struct buttoncounter *c) { r->x.cx = c->last.x; @@ -778,6 +790,10 @@ static void int33_handler(union INTPACK r) r.x.cx = data.pos.x; r.x.dx = data.pos.y; r.x.bx = data.buttons; + if (data.haswheel) { + r.h.bh = data.wheel_delta; + data.wheel_delta = 0; + } break; case INT33_SET_MOUSE_POSITION: data.pos.x = r.x.cx; @@ -792,11 +808,30 @@ static void int33_handler(union INTPACK r) break; case INT33_GET_BUTTON_PRESSED_COUNTER: r.x.ax = data.buttons; - return_clear_button_counter(&r, &data.button[MIN(r.x.bx, NUM_BUTTONS - 1)].pressed); + if (data.haswheel) { + r.h.bh = data.wheel_delta; + } + 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); + } break; case INT33_GET_BUTTON_RELEASED_COUNTER: r.x.ax = data.buttons; - return_clear_button_counter(&r, &data.button[MIN(r.x.bx, NUM_BUTTONS - 1)].released); + if (data.haswheel) { + r.h.bh = data.wheel_delta; + } + 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); + } break; case INT33_SET_HORIZONTAL_WINDOW: dlog_print("Mouse set horizontal window ["); @@ -937,6 +972,11 @@ static void int33_handler(union INTPACK r) r.x.cx = data.max.x; r.x.dx = data.max.y; break; + case INT33_GET_CAPABILITIES: + 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; + break; case INT33_GET_TSR_DATA: dlog_puts("Get TSR data"); r.x.es = FP_SEG(&data); @@ -114,6 +114,10 @@ typedef struct tsrdata { uint16_t count; } pressed, released; } button[NUM_BUTTONS]; + /** Total delta movement of the wheel since the last wheel report. */ + int16_t wheel_delta; + /** Last position where the wheel was moved. */ + struct point wheel_last; // Cursor information /** Whether the cursor is currently displayed or not. */ @@ -38,6 +38,7 @@ static inline uint8_t bda_get_byte(unsigned int offset) { #define bda_get_num_columns() bda_get_word(0x4a) #define bda_get_video_page_size() bda_get_word(0x4c) #define bda_get_cur_video_page() bda_get_word(0x62) +#define bda_get_last_row() bda_get_byte(0x84) #define bda_get_tick_count() bda_get_dword(0x6c) #define bda_get_tick_count_lo() bda_get_word(0x6c) @@ -129,16 +129,22 @@ enum INT33_API { /** Gets the current window coordinates (set by INT33_SET_HORIZONTAL_WINDOW). * @return ax min_x, bx min_y, cx max_x, d max_y. */ INT33_GET_WINDOW = 0x31, -}; -enum INT33_API_INTERNAL { + // Wheel API Extensions: + INT33_GET_CAPABILITIES = 0x11, + + // Our internal API functions: + /** Obtains a pointer to the driver's data. */ INT33_GET_TSR_DATA = 0x7f }; -enum { - INT33_MOUSE_FOUND = 0xFFFF +enum INT33_CAPABILITY_BITS { + INT33_CAPABILITY_MOUSE_API = 1 << 0 }; +#define INT33_WHEEL_API_MAGIC 'WM' +#define INT33_MOUSE_FOUND 0xFFFF + enum INT33_MOUSE_TYPE { INT33_MOUSE_TYPE_BUS = 1, INT33_MOUSE_TYPE_SERIAL = 2, @@ -181,14 +187,14 @@ static uint16_t int33_reset(void); "int 0x33" \ __value [ax] -static void int33_set_horizontal_window(uint16_t min, uint16_t max); +static void int33_set_horizontal_window(int16_t min, int16_t max); #pragma aux int33_set_horizontal_window = \ "mov ax, 0x7" \ "int 0x33" \ __parm [cx] [dx] \ __modify [ax] -static void int33_set_vertical_window(uint16_t min, uint16_t max); +static void int33_set_vertical_window(int16_t min, int16_t max); #pragma aux int33_set_vertical_window = \ "mov ax, 0x8" \ "int 0x33" \ @@ -202,4 +208,17 @@ static void int33_set_event_handler(uint16_t event_mask, void (__far *handler)() __parm [cx] [es dx] \ __modify [ax] +static uint16_t int33_get_driver_version(void); +#pragma aux int33_get_driver_version = \ + "mov bx, 0" \ + "mov ax, 0x24" \ + "int 0x33" \ + "cmp ax, -1" \ + "jne end" \ + "error:" \ + "mov bx, 0" \ + "end:" \ + __value [bx] \ + __modify [ax bx cx dx] + #endif @@ -116,13 +116,18 @@ static void FAR int33_mouse_callback(uint16_t events, uint16_t buttons, int16_t * The initialization routine should check whether a mouse exists. * @return nonzero value indicates a mouse exists. */ -#pragma off (unreferenced); +#pragma off (unreferenced) BOOL FAR PASCAL LibMain(HINSTANCE hInstance, WORD wDataSegment, WORD wHeapSize, LPSTR lpszCmdLine) -#pragma pop (unreferenced); +#pragma pop (unreferenced) { - // We are not going to bother checking whether the int33 driver exists - // and just assume it does. + uint16_t version = int33_get_driver_version(); + + // For now we just check for the presence of any int33 driver version + if (version <= 0) { + // This will cause a "can't load .drv" message from Windows + return 0; + } return 1; } @@ -149,6 +154,10 @@ VOID FAR PASCAL Enable(LPFN_MOUSEEVENT lpEventProc) if (!enabled) { int33_reset(); + // Since the mouse driver will likely not know the Windows resolution, + // let's manually set up a large window of coordinates so as to have + // as much precision as possible. + // We use 0x7FFF instead of 0xFFFF because this parameter is officially a signed value. int33_set_horizontal_window(0, 0x7FFF); int33_set_vertical_window(0, 0x7FFF); @@ -162,8 +171,7 @@ VOID FAR PASCAL Enable(LPFN_MOUSEEVENT lpEventProc) VOID FAR PASCAL Disable(VOID) { if (enabled) { - int33_reset(); - + int33_reset(); // This removes our handler and removes all other settings enabled = false; } } |