diff options
| author | Javier <dev.git@javispedro.com> | 2022-04-02 03:57:55 +0200 | 
|---|---|---|
| committer | Javier <dev.git@javispedro.com> | 2022-04-02 03:57:55 +0200 | 
| commit | aade1f47d34594216500f26ed0d21b23a1d1f4f1 (patch) | |
| tree | b8cf37b6fa99dd77104662da206060a1fd622a5b | |
| parent | 3e39df4a4185f947d1af564aca265c0f6b51c9ec (diff) | |
| download | vbados-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.c | 7 | ||||
| -rw-r--r-- | dostsr.c | 122 | ||||
| -rw-r--r-- | dostsr.h | 20 | ||||
| -rw-r--r-- | int2fwin.h | 35 | ||||
| -rw-r--r-- | w16mouse.c | 137 | 
5 files changed, 165 insertions, 156 deletions
@@ -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) { @@ -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 @@ -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 @@ -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, @@ -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;  } -  | 
