aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2022-04-03 00:03:15 +0200
committerJavier <dev.git@javispedro.com>2022-04-03 00:03:15 +0200
commit7d93442564b57c2d292df7f823c2115d3e0b8c12 (patch)
tree6a7e31e172ced11dde78f1b0a1f38fa2ab252697
parent3ca7b6c9cc23e118968b49a79f2b64fe4a3b73b3 (diff)
downloadvbados-7d93442564b57c2d292df7f823c2115d3e0b8c12.tar.gz
vbados-7d93442564b57c2d292df7f823c2115d3e0b8c12.zip
complete wheel support
-rw-r--r--dosmain.c43
-rw-r--r--dostsr.c52
-rw-r--r--dostsr.h4
-rw-r--r--int10vga.h1
-rw-r--r--int33.h31
-rw-r--r--w16mouse.c20
6 files changed, 124 insertions, 27 deletions
diff --git a/dosmain.c b/dosmain.c
index ee6389c..c35975e 100644
--- a/dosmain.c
+++ b/dosmain.c
@@ -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) {
diff --git a/dostsr.c b/dostsr.c
index 57ec089..7d881e2 100644
--- a/dostsr.c
+++ b/dostsr.c
@@ -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);
diff --git a/dostsr.h b/dostsr.h
index b9a5b73..e64c93e 100644
--- a/dostsr.h
+++ b/dostsr.h
@@ -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. */
diff --git a/int10vga.h b/int10vga.h
index e254e3f..a2a20a0 100644
--- a/int10vga.h
+++ b/int10vga.h
@@ -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)
diff --git a/int33.h b/int33.h
index f97ba21..44f61f9 100644
--- a/int33.h
+++ b/int33.h
@@ -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
diff --git a/w16mouse.c b/w16mouse.c
index 2faefbf..f4c16a9 100644
--- a/w16mouse.c
+++ b/w16mouse.c
@@ -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;
}
}