aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dlog.h3
-rw-r--r--int33.h33
-rw-r--r--makefile13
-rw-r--r--moustest.c335
4 files changed, 382 insertions, 2 deletions
diff --git a/dlog.h b/dlog.h
index ebeb01c..112254e 100644
--- a/dlog.h
+++ b/dlog.h
@@ -280,6 +280,9 @@ static void dprintf(const char *fmt, ...)
: va_arg(va, const char *),
precision);
break;
+ case 'c':
+ dputc(va_arg(va, char));
+ break;
case '%':
dputc('%');
break;
diff --git a/int33.h b/int33.h
index f7a469d..2755379 100644
--- a/int33.h
+++ b/int33.h
@@ -214,6 +214,29 @@ static uint16_t int33_reset(void);
__value [ax] \
__modify [ax bx]
+static bool int33_reset_get_buttons(uint16_t *num_buttons);
+#pragma aux int33_reset_get_buttons = \
+ "mov ax, 0x0" \
+ "int 0x33" \
+ "mov [di], bx" \
+ "cmp ax, 0xFFFF" \
+ "sete ah" \
+ __parm [di] \
+ __value [ah] \
+ __modify [ax bx]
+
+static void int33_show_cursor(void);
+#pragma aux int33_show_cursor = \
+ "mov ax, 0x1" \
+ "int 0x33" \
+ __modify [ax]
+
+static void int33_hide_cursor(void);
+#pragma aux int33_hide_cursor = \
+ "mov ax, 0x2" \
+ "int 0x33" \
+ __modify [ax]
+
static void int33_set_horizontal_window(int16_t min, int16_t max);
#pragma aux int33_set_horizontal_window = \
"mov ax, 0x7" \
@@ -309,4 +332,14 @@ static uint16_t int33_get_capabilities(void);
__value [cx] \
__modify [ax bx cx]
+static const char __far * int33_get_version_string(void);
+#pragma aux int33_get_version_string = \
+ "xor ax, ax" \
+ "mov di, ax" \
+ "mov es, ax" \
+ "mov ax, 0x6d" \
+ "int 0x33" \
+ __value [es di] \
+ __modify [ax]
+
#endif /* INT33_H */
diff --git a/makefile b/makefile
index 907a8e5..c6dc7e5 100644
--- a/makefile
+++ b/makefile
@@ -2,7 +2,7 @@
# Assuming you have sourced `owsetenv` beforehand.
# All binaries to build
-bins = vbmouse.exe vbsf.exe vbmouse.drv
+bins = vbmouse.exe vbsf.exe vbmouse.drv moustest.exe
# Inf files
infs = oemsetup.inf
@@ -16,7 +16,7 @@ sfdos_objs = sftsr.obj sfmain.obj kitten.obj vbox.obj
# Compiler arguments for DOS
dos_cflags = -bt=dos -ms -6 -osi -w3 -wcd=202
-# -ms to use small memory model (though sometimes ss != ds...)
+# -ms to use small memory model (this assumes ss == ds)
# -osi to optimize for size, put intrinsics inline (to avoid runtime calls)
# -w3 enables warnings
# -wcd=202 disables the unreferenced function warning (e.g., for inline functions in headers)
@@ -78,6 +78,15 @@ vbox.obj: vbox.c .AUTODEPEND
kitten.obj: kitten.c .AUTODEPEND
$(compile_dos)
+# Test programs
+moustest_objs = moustest.obj
+
+moustest.exe: moustest.obj
+ *wlink system dos name $@ file { $(moustest_objs) }
+
+moustest.obj: moustest.c .AUTODEPEND
+ $(compile_dos) -mc -zu
+
# Other targets
clean: .SYMBOLIC
rm -f vbmouse.exe vbmouse.drv vbsf.exe vbados.flp *.obj *.map
diff --git a/moustest.c b/moustest.c
new file mode 100644
index 0000000..97e554b
--- /dev/null
+++ b/moustest.c
@@ -0,0 +1,335 @@
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <dos.h>
+#include <conio.h>
+#include <graph.h>
+
+#include "int33.h"
+#include "utils.h"
+#include "dlog.h"
+
+#define DPREFIX "moustest: "
+
+bool exiting = false;
+
+uint16_t driver_caps;
+uint16_t num_buttons;
+uint16_t num_wheels;
+
+struct videoconfig vidconf;
+
+short ctexttop, ctextbot, ctextleft, ctextright;
+struct rccoord ctextpos;
+const short ctextcolor = 7;
+const long ctextbg = _BLACK;
+
+void gui_printf(const char *format, ...)
+{
+ va_list arglist;
+ char buffer[120];
+
+ va_start(arglist, format);
+ vsprintf(buffer, format, arglist);
+ va_end(arglist);
+
+ _outtext(buffer);
+}
+
+void gui_draw_textwindow(int top, int left, int bottom, int right, grcolor fg, long bg)
+{
+ _settextwindow(top, left, bottom, right);
+ _setbkcolor(bg);
+ _settextcolor(fg);
+ _clearscreen(_GWINDOW);
+}
+
+void gui_draw_title()
+{
+ const int cols = vidconf.numtextcols;
+
+ gui_draw_textwindow(1, 1, 1, cols, 0, _WHITE);
+ _outtext("MOUSTEST ESC to exit, 'r' reset, 's' show, 'h' hide");
+}
+
+void gui_draw_status()
+{
+ const int statusrow = vidconf.numtextrows;
+ const int cols = vidconf.numtextcols;
+
+ gui_draw_textwindow(statusrow, 1, statusrow, cols, 0, _WHITE);
+}
+
+void gui_draw_console()
+{
+ const int rows = vidconf.numtextrows, cols = vidconf.numtextcols;
+ ctexttop = 3;
+ ctextbot = rows - 2;
+ ctextleft = 1;
+ ctextright = cols;
+ gui_draw_textwindow(ctexttop, ctextleft, ctextbot, ctextright,
+ ctextcolor, ctextbg);
+}
+
+void gui_init()
+{
+ _setbkcolor(_BLACK);
+ _clearscreen(_GCLEARSCREEN);
+
+ gui_draw_title();
+
+ gui_draw_status();
+
+ gui_draw_console();
+}
+
+void console_enter()
+{
+ _settextwindow(ctexttop, ctextleft, ctextbot, ctextright);
+ _settextposition(ctextpos.row, ctextpos.col);
+ _setbkcolor(ctextbg);
+ _settextcolor(ctextcolor);
+}
+
+void console_leave()
+{
+ ctextpos = _gettextposition();
+}
+
+void console_print(char __far *str)
+{
+ _disable();
+ int33_hide_cursor();
+ console_enter();
+ _outtext(str);
+ console_leave();
+ int33_show_cursor();
+ _enable();
+}
+
+void console_printf(const char *format, ...)
+{
+ va_list arglist;
+ char buffer[120];
+
+ va_start(arglist, format);
+ vsprintf(buffer, format, arglist);
+ va_end(arglist);
+
+ console_print(buffer);
+}
+
+/** Called by the int33 mouse driver. */
+void __far mouse_callback(uint16_t events, uint16_t buttons, int16_t x, int16_t y, int16_t delta_x, int16_t delta_y)
+#pragma aux (INT33_CB) mouse_callback
+{
+ int8_t z = buttons >> 8;
+
+#if 1
+ dprintf(DPREFIX "mouse_callback events=0x%x buttons=0x%x x=%d y=%d dx=%d dy=%d\n",
+ events, buttons, x, y, delta_x, delta_y);
+#endif
+
+ // Update the status bar
+ _disable();
+ gui_draw_status();
+
+ gui_printf(" %3s %4u , %4u |",
+ events & INT33_EVENT_MASK_ABSOLUTE ? "ABS" : "REL", x, y);
+
+ if (num_buttons <= 2) {
+ gui_printf(" [%5s] [%5s] ",
+ buttons & INT33_BUTTON_MASK_LEFT ? "LEFT" : "",
+ buttons & INT33_BUTTON_MASK_RIGHT ? "RIGHT" : "");
+ } else {
+ gui_printf(" [%5s] [%5s] [%5s] ",
+ buttons & INT33_BUTTON_MASK_LEFT ? "LEFT" : "",
+ buttons & INT33_BUTTON_MASK_CENTER ? "MID " : "",
+ buttons & INT33_BUTTON_MASK_RIGHT ? "RIGHT" : "");
+ if (num_buttons > 3) {
+ gui_printf(" [%3s] [%3s] ",
+ buttons & INT33_BUTTON_MASK_4TH ? "4TH" : "",
+ buttons & INT33_BUTTON_MASK_5TH ? "5TH" : "");
+ }
+ }
+
+ if (num_wheels > 0) {
+ char c = ' ';
+ if (events & INT33_EVENT_MASK_WHEEL_MOVEMENT) {
+ c = z > 0 ? 0x19 : 0x18;
+ } else if (events & INT33_EVENT_MASK_HORIZ_WHEEL_MOVEMENT) {
+ c = z > 0 ? 0x1A : 0x1B;
+ }
+ gui_printf("| %c", c);
+ }
+
+ _settextposition(1, 1);
+ _enable();
+
+ // Log the events
+ if (events & INT33_EVENT_MASK_LEFT_BUTTON_PRESSED) {
+ console_printf("Left button pressed\n");
+ }
+ if (events & INT33_EVENT_MASK_LEFT_BUTTON_RELEASED) {
+ console_printf("Left button released\n");
+ }
+ if (events & INT33_EVENT_MASK_CENTER_BUTTON_PRESSED) {
+ console_printf("Middle button pressed\n");
+ }
+ if (events & INT33_EVENT_MASK_CENTER_BUTTON_RELEASED) {
+ console_printf("Middle button released\n");
+ }
+ if (events & INT33_EVENT_MASK_RIGHT_BUTTON_PRESSED) {
+ console_printf("Right button pressed\n");
+ }
+ if (events & INT33_EVENT_MASK_RIGHT_BUTTON_RELEASED) {
+ console_printf("Right button released\n");
+ }
+ if (events & INT33_EVENT_MASK_4TH_BUTTON_PRESSED) {
+ console_printf("4th button pressed\n");
+ }
+ if (events & INT33_EVENT_MASK_4TH_BUTTON_RELEASED) {
+ console_printf("4th button released\n");
+ }
+ if (events & INT33_EVENT_MASK_5TH_BUTTON_PRESSED) {
+ console_printf("5th button pressed\n");
+ }
+ if (events & INT33_EVENT_MASK_5TH_BUTTON_RELEASED) {
+ console_printf("5th button released\n");
+ }
+
+ if (events & INT33_EVENT_MASK_WHEEL_MOVEMENT) {
+ console_printf("Wheel %s %d\n", z > 0 ? "down" : "up", z);
+ }
+ if (events & INT33_EVENT_MASK_HORIZ_WHEEL_MOVEMENT) {
+ console_printf("Wheel %s %d\n", z > 0 ? "right" : "left", z);
+ }
+}
+
+bool mouse_reset()
+{
+ if (!int33_reset_get_buttons(&num_buttons)) {
+ puts("Mouse not installed");
+ return false;
+ }
+
+ driver_caps = int33_get_capabilities();
+ num_wheels = 0;
+ if (driver_caps & INT33_CAPABILITY_WHEEL_API) {
+ num_wheels = 1;
+ }
+ if (driver_caps & INT33_CAPABILITY_WHEEL2_API) {
+ num_wheels = 2;
+ }
+
+ int33_set_event_handler(INT33_EVENT_MASK_ALL, mouse_callback);
+
+ return true;
+}
+
+void mouse_report()
+{
+ const char __far *fstr;
+
+ if (driver_caps != 0) {
+ console_printf("Driver capabilities bits: 0x%x %s %s\n", driver_caps,
+ driver_caps & INT33_CAPABILITY_WHEEL_API ? "<wheel API>" : "",
+ driver_caps & INT33_CAPABILITY_WHEEL2_API ? "<wheel API v2>" : "");
+ }
+
+ fstr = int33_get_version_string();
+ if (fstr) {
+ console_printf("Driver version string: %Fs\n", fstr);
+ }
+
+ console_printf("Number of buttons: %u\n", num_buttons);
+ console_printf("Number of wheels: %u\n", num_wheels);
+
+}
+
+void mouse_quit()
+{
+ int33_reset();
+}
+
+void mouse_debug()
+{
+ // TODO ?
+ union REGS in, out;
+ in.x.ax = INT33_GET_MOUSE_POSITION;
+ in.x.bx = 0x4567;
+ in.x.cx = 0x7845;
+ in.x.dx = 0x9AAC;
+ in.x.si = 0xAAAA;
+ in.x.di = 0xBBBB;
+
+ int86(0x33, &in, &out);
+
+ console_printf("IN ax 0x%04x bx 0x%04x cx 0x%04x dx 0x%04x si 0x%04x di 0x%04x\n",
+ in.x.ax, in.x.bx, in.x.cx, in.x.dx, in.x.si, in.x.di);
+ console_printf("OUT ax 0x%04x bx 0x%04x cx 0x%04x dx 0x%04x si 0x%04x di 0x%04x\n",
+ out.x.ax, out.x.bx, out.x.cx, out.x.dx, out.x.si, out.x.di);
+}
+
+int main(int argc, const char *argv[])
+{
+ int c;
+
+ (void)argc;
+ (void)argv;
+
+ if (!mouse_reset()) {
+ return EXIT_FAILURE;
+ }
+
+ _setvideomode(_TEXTC80);
+ _getvideoconfig(&vidconf);
+
+ gui_init();
+
+ mouse_report();
+
+ int33_show_cursor();
+
+ while (!exiting) {
+ int c;
+
+ c = getch();
+
+ dprintf(DPREFIX "getch returns %d\n", c);
+
+ if (c == 0) {
+ // Extended key
+ c = getch();
+ console_printf("Keyboard extended key %d\n", c);
+ } else {
+ console_printf("Keyboard key %d '%c'\n", c, c);
+ switch (c) {
+ case 27: // Escape
+ exiting = true;
+ break;
+ case 'r':
+ console_printf("Reset mouse driver\n");
+ mouse_reset();
+ mouse_report();
+ break;
+ case 's':
+ int33_show_cursor();
+ break;
+ case 'h':
+ int33_hide_cursor();
+ break;
+ case 'd':
+ mouse_debug();
+ break;
+ }
+ }
+ }
+
+ mouse_quit();
+ _setvideomode(_DEFAULTMODE);
+
+ return EXIT_SUCCESS;
+}