aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2022-04-02 03:57:55 +0200
committerJavier <dev.git@javispedro.com>2022-04-02 03:57:55 +0200
commitaade1f47d34594216500f26ed0d21b23a1d1f4f1 (patch)
treeb8cf37b6fa99dd77104662da206060a1fd622a5b
parent3e39df4a4185f947d1af564aca265c0f6b51c9ec (diff)
downloadvbados-aade1f47d34594216500f26ed0d21b23a1d1f4f1.tar.gz
vbados-aade1f47d34594216500f26ed0d21b23a1d1f4f1.zip
complete support for the win386 hooks in dos mouse side, and further simplify w16 driver
-rw-r--r--dosmain.c7
-rw-r--r--dostsr.c122
-rw-r--r--dostsr.h20
-rw-r--r--int2fwin.h35
-rw-r--r--w16mouse.c137
5 files changed, 165 insertions, 156 deletions
diff --git a/dosmain.c b/dosmain.c
index 646a03a..f1c2291 100644
--- a/dosmain.c
+++ b/dosmain.c
@@ -28,11 +28,6 @@
#include "vbox.h"
#include "dostsr.h"
-static unsigned get_resident_size(void)
-{
- return FP_OFF(&resident_end);
-}
-
#if USE_VIRTUALBOX
static int set_integration(LPTSRDATA data, bool enable)
{
@@ -268,7 +263,7 @@ int main(int argc, const char *argv[])
LPTSRDATA data = get_tsr_data(true);
int err, argi = 1;
- printf("\nVBMouse 0.x (MSMOUSE %x.%x)\n", REPORTED_VERSION_MAJOR, REPORTED_VERSION_MINOR);
+ printf("\nVBMouse %x.%x (like MSMOUSE %x.%x)\n", VERSION_MAJOR, VERSION_MINOR, REPORTED_VERSION_MAJOR, REPORTED_VERSION_MINOR);
if (argi >= argc || stricmp(argv[argi], "install") == 0) {
if (data) {
diff --git a/dostsr.c b/dostsr.c
index 4ec9975..aab2855 100644
--- a/dostsr.c
+++ b/dostsr.c
@@ -22,6 +22,7 @@
#include "dlog.h"
#include "ps2.h"
#include "int10vga.h"
+#include "int2fwin.h"
#include "int33.h"
#include "dostsr.h"
@@ -247,6 +248,12 @@ static void refresh_cursor(void)
{
bool should_show = data.visible_count >= 0;
+#if USE_INT2F
+ // Windows 386 is already rendering the cursor for us.
+ // Hide our own.
+ if (data.w386cursor) should_show = false;
+#endif
+
#if USE_VIRTUALBOX
if (data.vbwantcursor) {
int err = 0;
@@ -305,6 +312,8 @@ static void hide_cursor(void)
}
}
+/** Loads the current graphic cursor,
+ * which in this case means uploading it to the host. */
static void load_cursor(void)
{
#if USE_VIRTUALBOX
@@ -372,6 +381,7 @@ static void load_cursor(void)
#endif
}
+/** Refreshes the information about the current video mode. */
static void refresh_video_info(void)
{
uint8_t screen_columns = bda_get_num_columns();
@@ -442,11 +452,12 @@ static void refresh_video_info(void)
}
}
+/** Calls the application-registered event handler. */
static void call_event_handler(void (__far *handler)(), uint16_t events,
uint16_t buttons, int16_t x, int16_t y,
int16_t delta_x, int16_t delta_y)
{
-#if TRACE_EVENT
+#if TRACE_EVENTS
dlog_print("calling event handler events=");
dlog_printx(events);
dlog_print(" buttons=");
@@ -474,12 +485,19 @@ static void call_event_handler(void (__far *handler)(), uint16_t events,
}
}
+/** Process a mouse event internally.
+ * @param buttons currently pressed buttons as a bitfield
+ * @param absolute whether mouse coordinates are an absolute value
+ * @param x y if absolute, then absolute coordinates in screen pixels
+ * if relative, then relative coordinates in mickeys
+ * @param z relative wheel mouse movement
+ */
static void handle_mouse_event(uint16_t buttons, bool absolute, int x, int y, int z)
{
uint16_t events = 0;
int i;
-#if TRACE_EVENT
+#if TRACE_EVENTS
dlog_print("handle mouse event");
if (absolute) dlog_print(" absolute");
dlog_print(" buttons=");
@@ -592,7 +610,7 @@ static void __far ps2_mouse_callback(uint8_t status, uint8_t x, uint8_t y, uint8
int sz = z;
bool abs = false;
-#if TRACE_EVENT
+#if TRACE_EVENTS
dlog_print("ps2 callback status=");
dlog_printx(status);
dlog_print(" sx=");
@@ -958,18 +976,94 @@ void __declspec(naked) __far int33_isr(void)
}
#if USE_INT2F
+static void windows_mouse_handler(int action, int x, int y, int buttons, int events)
+#pragma aux windows_mouse_handler "*" parm [ax] [bx] [cx] [dx] [si] modify [ax bx cx dx es]
+{
+ switch (action) {
+ case VMD_ACTION_MOUSE_EVENT:
+ handle_mouse_event(buttons, true, x, y, 0);
+ break;
+ case VMD_ACTION_HIDE_CURSOR:
+ dlog_puts("VMD_ACTION_HIDE_CURSOR");
+ data.w386cursor = true;
+ refresh_cursor();
+ break;
+ case VMD_ACTION_SHOW_CURSOR:
+ dlog_puts("VMD_ACTION_SHOW_CURSOR");
+ data.w386cursor = false;
+ refresh_cursor();
+ break;
+ }
+}
+
+void __declspec(naked) __far windows_mouse_callback()
+{
+ __asm {
+ pusha
+ push ds
+ push es
+ push fs
+ push gs
+
+ mov bp, sp
+ push cs
+ pop ds
+
+ call windows_mouse_handler
+
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ popa
+
+ retf
+ }
+}
+
static void int2f_handler(union INTPACK r)
#pragma aux int2f_handler "*" parm caller [] modify [ax bx cx dx es]
{
+ switch (r.x.ax) {
+ case INT2F_NOTIFY_WIN386_STARTUP:
+ dlog_print("Windows is starting, version=");
+ dlog_printx(r.x.di);
+ dlog_endline();
+ data.w386_startup.version = 3;
+ data.w386_startup.next = MK_FP(r.x.es, r.x.bx);
+ data.w386_startup.device_driver = 0;
+ data.w386_startup.device_driver_data = 0;
+ data.w386_startup.instance_data = &data.w386_instance;
+ data.w386_instance[0].ptr = &data;
+ data.w386_instance[0].size = sizeof(data);
+ data.w386_instance[1].ptr = 0;
+ data.w386_instance[1].size = 0;
+ r.x.es = FP_SEG(&data.w386_startup);
+ r.x.bx = FP_OFF(&data.w386_startup);
+ break;
+ case INT2F_NOTIFY_DEVICE_CALLOUT:
+ switch (r.x.bx) {
+ case VMD_DEVICE_ID:
+ switch (r.x.cx) {
+ case VMD_CALLOUT_TEST:
+ r.x.cx = 1; // Yes, we are here!
+ break;
+ case VMD_CALLOUT_GET_DOS_MOUSE_API:
+ // Windows is asking our mouse driver for the hook function address
+ r.x.ds = FP_SEG(windows_mouse_callback);
+ r.x.si = FP_OFF(windows_mouse_callback);
+ r.x.ax = 0; // Yes, we are here!
+ break;
+ }
+ break;
+ }
+ break;
+ }
}
void __declspec(naked) __far int2f_isr(void)
{
__asm {
- ; Space for the pointer to the next ISR in the chain
- push dword ptr 0
-
- ; Save all registers (also acts as the INTPACK paramenter later)
pusha
push ds
push es
@@ -980,16 +1074,6 @@ void __declspec(naked) __far int2f_isr(void)
push cs
pop ds
- ; Load the address of the next ISR in the chain
- ; Stack looks like sp+0: gs, fs, es, ds (4*2bytes)
- ; sp+8: pusha (8 * 2bytes)
- ; sp+24: dword ptr (the space we reserved to store the next ISR)
- mov ax, word ptr [data + 4] ; i.e. data.prev_int2f_handler -- Watcom doesn't support structs
- mov [bp + 24], ax
- mov ax, word ptr [data + 6] ; i.e. data.prev_int2f_handler[2]
- mov [bp + 26], ax
-
- ; Now call our handler
call int2f_handler
pop gs
@@ -998,8 +1082,8 @@ void __declspec(naked) __far int2f_isr(void)
pop ds
popa
- ; This will jump to the address of the next ISR we loaded before
- retf
+ ; Jump to the next handler in the chain
+ jmp dword ptr cs:[data + 4] ; wasm doesn't support structs, this is data.prev_int2f_handler
}
}
#endif
diff --git a/dostsr.h b/dostsr.h
index d7c8183..268b2aa 100644
--- a/dostsr.h
+++ b/dostsr.h
@@ -24,16 +24,19 @@
#include <stdint.h>
#include "vbox.h"
+#include "int2fwin.h"
#define USE_VIRTUALBOX 1
#define USE_INT2F 1
-#define TRACE_EVENT 1
+#define TRACE_EVENTS 0
#define NUM_BUTTONS 3
#define GRAPHIC_CURSOR_WIDTH 16
#define GRAPHIC_CURSOR_HEIGHT 16
+#define VERSION_MAJOR 0
+#define VERSION_MINOR 3
#define REPORTED_VERSION_MAJOR 8
#define REPORTED_VERSION_MINOR 0x20
@@ -129,6 +132,15 @@ typedef struct tsrdata {
/** Events for which we should call the event handler. */
uint16_t event_mask;
+#if USE_INT2F
+ /** Information that we pass to Windows 386 on startup. */
+ win386_startup_info w386_startup;
+ win386_instance_item w386_instance[2];
+ /** Whether Windows 386 is rendering the cursor for us,
+ * and therefore we should hide our own. */
+ bool w386cursor : 1;
+#endif
+
#if USE_VIRTUALBOX
/** VirtualBox is available. */
bool vbavail : 1;
@@ -151,4 +163,10 @@ extern LPTSRDATA __far get_tsr_data(bool installed);
extern int resident_end;
+/** This is not just data, but the entire segment. */
+static inline unsigned get_resident_size(void)
+{
+ return FP_OFF(&resident_end);
+}
+
#endif
diff --git a/int2fwin.h b/int2fwin.h
index e8540dc..255cdd7 100644
--- a/int2fwin.h
+++ b/int2fwin.h
@@ -24,26 +24,29 @@
#include <stdint.h>
#include <dos.h>
-struct win386_instance_item
+typedef _Packed struct win386_instance_item
{
void __far * ptr;
uint16_t size;
-};
+} win386_instance_item;
-struct win386_startup_info
+typedef _Packed struct win386_startup_info
{
uint16_t version;
struct win386_startup_info __far * next;
char __far * device_driver;
void __far * device_driver_data;
- struct win386_instance_item __far *instance_data;
-};
+ struct win386_instance_item __far * instance_data;
+} win386_startup_info;
typedef void (__far *LPFN)(void);
enum int2f_functions
{
- INT2F_NOTIFY_WIN386_STARTUP = 0x1605,
+ /** Notification sent when Windows386 is starting up. */
+ INT2F_NOTIFY_WIN386_STARTUP = 0x1605,
+ /** Notification sent by a VxD that wants to invoke a function in a real-mode driver. */
+ INT2F_NOTIFY_DEVICE_CALLOUT = 0x1607,
INT2F_NOTIFY_BACKGROUND_SWITCH = 0x4001,
INT2F_NOTIFY_FOREGROUND_SWITCH = 0x4002
@@ -78,6 +81,26 @@ enum vmd_apis {
VMD_SET_MOUSE_TYPE = 0x100,
};
+enum vmd_callouts
+{
+ /** VMD emits this to know if there is a "win386 aware" DOS mouse driver installed.
+ * If there is, and the driver responds with CX!=0, VMD will assume
+ * the driver is taking care of its own instancing
+ * (which we do, through win386_startup_info)
+ * and not try to hack around our internals. */
+ VMD_CALLOUT_TEST = 0,
+ /** VMD emits this to know the entrypoint for the API of a "win386 aware"
+ * DOS mouse driver. */
+ VMD_CALLOUT_GET_DOS_MOUSE_API = 0x1
+};
+
+enum vmd_dos_mouse_api_actions
+{
+ VMD_ACTION_MOUSE_EVENT = 1,
+ VMD_ACTION_HIDE_CURSOR = 2,
+ VMD_ACTION_SHOW_CURSOR = 3
+};
+
enum vmd_mouse_type {
VMD_TYPE_UNDEFINED = 0,
VMD_TYPE_BUS = 1,
diff --git a/w16mouse.c b/w16mouse.c
index f1ca962..2faefbf 100644
--- a/w16mouse.c
+++ b/w16mouse.c
@@ -24,27 +24,16 @@
#include "int2fwin.h"
#include "w16mouse.h"
-#define TRACE_EVENT 1
-
-/** If 1, hook int2f to detect fullscreen DOSBoxes and auto-disable this driver. */
-#define HOOK_INT2F 0
+#define TRACE_EVENTS 0
#define MOUSE_NUM_BUTTONS 2
/** The routine Windows gave us which we should use to report events. */
static LPFN_MOUSEEVENT eventproc;
-/** Current status of the mouse driver (see MOUSEFLAGS_*). */
-static struct mouseflags {
- bool enabled : 1;
- bool haswin386 : 1;
- bool int2f_hooked : 1;
-} flags;
+/** Current status of the mouse driver. */
+static bool enabled;
/** Previous deltaX, deltaY from the int33 mouse callback (for relative motion) */
static short prev_delta_x, prev_delta_y;
-#if HOOK_INT2F
-/** Existing interrupt2f handler. */
-static LPFN prev_int2f_handler;
-#endif
/* This is how events are delivered to Windows */
@@ -52,6 +41,8 @@ static void send_event(unsigned short Status, short deltaX, short deltaY, short
#pragma aux (MOUSEEVENTPROC) send_event = \
"call dword ptr [eventproc]"
+/* Our "CALLBACKS" segment which is fixed and non-relocatable. */
+
#pragma code_seg ( "CALLBACKS" )
#include "dlog.h"
@@ -61,7 +52,7 @@ static void FAR int33_mouse_callback(uint16_t events, uint16_t buttons, int16_t
{
int status = 0;
-#if TRACE_EVENT_IN
+#if TRACE_EVENTS_IN
dlog_print("w16mouse: events=");
dlog_printx(events);
dlog_print(" buttons=");
@@ -104,7 +95,7 @@ static void FAR int33_mouse_callback(uint16_t events, uint16_t buttons, int16_t
// Unused
(void) buttons;
-#if TRACE_EVENT
+#if TRACE_EVENTS
dlog_print("w16mouse: event status=");
dlog_printx(status);
dlog_print(" x=");
@@ -117,72 +108,6 @@ static void FAR int33_mouse_callback(uint16_t events, uint16_t buttons, int16_t
send_event(status, x, (uint16_t)(y), MOUSE_NUM_BUTTONS, 0, 0);
}
-#if HOOK_INT2F
-
-static void display_switch_handler(int function)
-#pragma aux display_switch_handler parm caller [ax] modify [ax bx cx dx si di]
-{
- if (!flags.enabled) {
- return;
- }
-
- switch (function) {
- case INT2F_NOTIFY_BACKGROUND_SWITCH:
- dlog_puts("Going background\n");
- break;
- case INT2F_NOTIFY_FOREGROUND_SWITCH:
- dlog_puts("Going foreground\n");
- break;
- }
-}
-
-/** Interrupt 2F handler, which will be called on some Windows 386 mode events.
- * This is more complicated than it should be becaused we have to fetch our DS
- * without clobbering any registers whatsoever, and chain back to the previous handler.
- * @todo OpenWatcom 2.x insists on calling GETDS from a different code segment, so we can't use __interrupt. */
-static void __declspec(naked) __far int2f_handler(void)
-{
- _asm {
- ; Preserve data segment
- push ds
-
- ; Load our data segment
- push ax
- mov ax, SEG prev_int2f_handler ; Let's hope that Windows relocates segments with interrupts disabled
- mov ds, ax
- pop ax
-
- ; Check functions we are interested in hooking
- cmp ax, 0x4001 ; Notify Background Switch
- je handle_it
- cmp ax, 0x4002 ; Notify Foreground Switch
- je handle_it
-
- ; Otherwise directly jump to next handler
- jmp next_handler
-
- handle_it:
- pushad ; Save and restore 32-bit registers, we may clobber them from C
- call display_switch_handler
- popad
-
- next_handler:
- ; Store the address of the previous handler
- push dword ptr [prev_int2f_handler]
-
- ; Restore original data segment without touching the stack,
- ; since we want to keep the prev handler address at the top
- push bp
- mov bp, sp
- mov ds, [bp + 6] ; Stack looks like 0: bp, 2: prev_int2f_handler, 6: ds
- pop bp
-
- retf 2
- }
-}
-
-#endif /* HOOK_INT2F */
-
#pragma code_seg ()
/* Driver exported functions. */
@@ -196,25 +121,8 @@ BOOL FAR PASCAL LibMain(HINSTANCE hInstance, WORD wDataSegment,
WORD wHeapSize, LPSTR lpszCmdLine)
#pragma pop (unreferenced);
{
- // We are not going to bother checking whether a PS2 mouse exists and just assume it does
-
-#if HOOK_INT2F
- // Check now whether we are running under protected mode windows
- if (windows_386_enhanced_mode()) {
- flags.haswin386 = true;
- }
-#endif
-
-#if 0
- // When running under protected mode Windows, let's tell VMD (the mouse virtualizer)
- // what type of mouse we are going to be using
- if (flags.haswin386) {
- LPFN vmd_entry = win_get_vxd_api_entry(VMD_DEVICE_ID);
- if (vmd_entry) {
- vmd_set_mouse_type(&vmd_entry, VMD_TYPE_PS2, 0x33, 0);
- }
- }
-#endif
+ // We are not going to bother checking whether the int33 driver exists
+ // and just assume it does.
return 1;
}
@@ -238,7 +146,7 @@ VOID FAR PASCAL Enable(LPFN_MOUSEEVENT lpEventProc)
eventproc = lpEventProc;
sti();
- if (!flags.enabled) {
+ if (!enabled) {
int33_reset();
int33_set_horizontal_window(0, 0x7FFF);
@@ -246,35 +154,17 @@ VOID FAR PASCAL Enable(LPFN_MOUSEEVENT lpEventProc)
int33_set_event_handler(INT33_EVENT_MASK_ALL, int33_mouse_callback);
- flags.enabled = true;
-
-#if HOOK_INT2F
- if (flags.haswin386) {
- cli();
- hook_int2f(&prev_int2f_handler, int2f_handler);
- sti();
- flags.int2f_hooked = true;
- }
-#endif
+ enabled = true;
}
}
/** Called by Windows to disable the mouse driver. */
VOID FAR PASCAL Disable(VOID)
{
- if (flags.enabled) {
-#if HOOK_INT2F
- if (flags.int2f_hooked) {
- cli();
- unhook_int2f(prev_int2f_handler);
- sti();
- flags.int2f_hooked = false;
- }
-#endif
-
+ if (enabled) {
int33_reset();
- flags.enabled = false;
+ enabled = false;
}
}
@@ -283,4 +173,3 @@ int FAR PASCAL MouseGetIntVect(VOID)
{
return 0x33;
}
-