diff options
| author | Javier <dev.git@javispedro.com> | 2022-04-08 02:17:46 +0200 | 
|---|---|---|
| committer | Javier <dev.git@javispedro.com> | 2022-04-08 02:17:46 +0200 | 
| commit | 98a343355c3459b892792585788069bac3bc40e7 (patch) | |
| tree | 1ff4674815775c323822e03c3c0f05c49204a549 | |
| parent | db308ca65b8f0ddb61969e7e4b4fb2145d8a27c2 (diff) | |
| download | vbados-98a343355c3459b892792585788069bac3bc40e7.tar.gz vbados-98a343355c3459b892792585788069bac3bc40e7.zip  | |
try to detect video mode changes
| -rw-r--r-- | dostsr.c | 112 | ||||
| -rw-r--r-- | dostsr.h | 6 | ||||
| -rw-r--r-- | int10vga.h | 1 | ||||
| -rw-r--r-- | int33.h | 28 | ||||
| -rw-r--r-- | utils.h | 3 | ||||
| -rw-r--r-- | w16mouse.c | 15 | 
6 files changed, 126 insertions, 39 deletions
@@ -467,21 +467,9 @@ static void load_cursor(void)  #endif  } -/** Refreshes the information about the current video mode. */ -static void refresh_video_info(void) +/** Reloads the information about the current video mode. */ +static void reload_video_info(void)  { -	uint8_t cur_mode = bda_get_video_mode() & ~0x80; -	bool mode_change = cur_mode != data.video_mode.mode; - -	if (mode_change && data.cursor_visible) { -		// Assume cursor is lost -		data.cursor_visible = false; -	} - -	dlog_print("Current video mode="); -	dlog_printx(cur_mode); -	dlog_endline(); -  	get_current_video_mode_info(&data.video_mode);  	data.screen_max.x = data.video_mode.pixels_width - 1; @@ -496,6 +484,53 @@ static void refresh_video_info(void)  		data.screen_max.x = 640 - 1;  		data.screen_scale.x = 640 / 320;  	} + +	dlog_print("Current video mode="); +	dlog_printx(data.video_mode.mode); +	dlog_print(" screen_max="); +	dlog_printd(data.screen_max.x); +	dlog_putc(','); +	dlog_printd(data.screen_max.y); +	dlog_endline(); +} + +/** True if the current video is different from what we have stored + *  and we probably need to recompute video mode info. */ +static inline bool video_mode_changed(void) +{ +	uint8_t cur_mode = bda_get_video_mode() & ~0x80; + +	if (cur_mode != data.video_mode.mode) +		return true; + +	if (data.video_mode.type == VIDEO_TEXT) { +		// Also check to see if the font size was changed.. +		return data.video_mode.pixels_height != (bda_get_last_row()+1) * 8; +	} else { +		return false; +	} +} + +/** Checks if the video mode has changed and if so + *  refreshes the information about the current video mode.  */ +static void refresh_video_info(void) +{ +	if (video_mode_changed()) { +		if (data.cursor_visible) { +			// Assume cursor is lost with no way to restore prev contents +			data.cursor_visible = false; +		} + +		reload_video_info(); + +		if (data.video_mode.type != VIDEO_UNKNOWN) { +			// If we know the screen size for this mode, then reset the window to it +			data.min.x = 0; +			data.min.y = 0; +			data.max.x = data.screen_max.x; +			data.max.y = data.screen_max.y; +		} +	}  }  /** Calls the application-registered event handler. */ @@ -569,10 +604,14 @@ static void handle_mouse_event(uint16_t buttons, bool absolute, int x, int y, in  			// Programs that expect relative movement data  			// will almost never set a mickeyPerPixel value.  			// So all we can do is guess. -			data.delta.x += (x - data.pos.x) * 8; -			data.delta.y += (y - data.pos.y) * 8; +			if (data.abs_pos.x >= 0 && data.abs_pos.y >= 0) { +				data.delta.x += (x - data.abs_pos.x) * 8; +				data.delta.y += (y - data.abs_pos.y) * 8; +			} +			data.abs_pos.x = x; +			data.abs_pos.y = y; -			// Store the new absolute position +			// Set the new absolute position  			data.pos.x = x;  			data.pos.y = y;  			data.pos_frac.x = 0; @@ -603,6 +642,8 @@ static void handle_mouse_event(uint16_t buttons, bool absolute, int x, int y, in  		data.delta.y += y;  		data.delta_frac.x = 0;  		data.delta_frac.y = 0; +		data.abs_pos.x = -1; +		data.abs_pos.y = -1;  		// Convert mickeys into pixels  		data.pos.x += scalei_rem(x, data.mickeysPerLine.x, 8, &data.pos_frac.x); @@ -704,6 +745,7 @@ static void ps2_mouse_handler(uint16_t word1, uint16_t word2, uint16_t word3, ui  		if ((vbox_get_mouse(&data.vb, &abs, &vbx, &vby) == 0) && abs) {  			// VirtualBox gives unsigned coordinates from 0...0xFFFFU,  			// scale to 0..screen_size (in pixels). +			refresh_video_info();  			// If the user is using a window larger than the screen, use it.  			x = scaleu(vbx, 0xFFFFU, MAX(data.max.x, data.screen_max.x));  			y = scaleu(vby, 0xFFFFU, MAX(data.max.y, data.screen_max.y)); @@ -757,10 +799,12 @@ static void ps2_mouse_handler(uint16_t word1, uint16_t word2, uint16_t word3, ui  				z = (int8_t) (uint8_t) vmw.z;  			} else {  				abs = true; +				// Scale to screen coordinates +				refresh_video_info();  				x = scaleu(vmw.x & 0xFFFFU, 0xFFFFU, -				            MAX(data.max.x, data.screen_max.x)); +				           MAX(data.max.x, data.screen_max.x));  				y = scaleu(vmw.y & 0xFFFFU, 0xFFFFU, -				            MAX(data.max.y, data.screen_max.y)); +				           MAX(data.max.y, data.screen_max.y));  				z = (int8_t) (uint8_t) vmw.z;  			} @@ -924,6 +968,8 @@ static void reset_mouse_state()  	data.delta.y = 0;  	data.delta_frac.x = 0;  	data.delta_frac.y = 0; +	data.abs_pos.x = -1; +	data.abs_pos.y = -1;  	data.buttons = 0;  	for (i = 0; i < NUM_BUTTONS; i++) {  		data.button[i].pressed.count = 0; @@ -968,7 +1014,7 @@ static void int33_handler(union INTPACK r)  	switch (r.x.ax) {  	case INT33_RESET_MOUSE:  		dlog_puts("Mouse reset"); -		refresh_video_info(); +		reload_video_info();  		reset_mouse_settings();  		reset_mouse_hardware();  		reset_mouse_state(); @@ -984,6 +1030,9 @@ static void int33_handler(union INTPACK r)  		refresh_cursor();  		break;  	case INT33_GET_MOUSE_POSITION: +#if TRACE_EVENTS +		dlog_puts("Mouse get position"); +#endif  		r.x.cx = data.pos.x;  		r.x.dx = data.pos.y;  		r.x.bx = data.buttons; @@ -993,6 +1042,9 @@ static void int33_handler(union INTPACK r)  		}  		break;  	case INT33_SET_MOUSE_POSITION: +#if TRACE_EVENTS +		dlog_puts("Mouse set position"); +#endif  		data.pos.x = r.x.cx;  		data.pos.y = r.x.dx;  		data.pos_frac.x = 0; @@ -1073,14 +1125,13 @@ static void int33_handler(union INTPACK r)  		refresh_cursor();  		break;  	case INT33_GET_MOUSE_MOTION: +#if TRACE_EVENTS +		dlog_puts("Mouse get motion"); +#endif  		r.x.cx = data.delta.x;  		r.x.dx = data.delta.y;  		data.delta.x = 0;  		data.delta.y = 0; -#if USE_VIRTUALBOX -		// Likely this means we need a relative mouse, or we will get out of sync -		//if (data.vbabs) enable_vbox_absolute(false); -#endif  		break;  	case INT33_SET_EVENT_HANDLER:  		dlog_puts("Mouse set event handler"); @@ -1143,7 +1194,7 @@ static void int33_handler(union INTPACK r)  		break;  	case INT33_RESET_SETTINGS:  		dlog_puts("Mouse reset settings"); -		refresh_video_info(); +		reload_video_info();  		reset_mouse_settings();  		reset_mouse_state();  		r.x.ax = INT33_MOUSE_FOUND; @@ -1160,8 +1211,9 @@ static void int33_handler(union INTPACK r)  		r.h.cl = 0;  		break;  	case INT33_GET_MAX_COORDINATES: -		r.x.cx = data.screen_max.x; -		r.x.dx = data.screen_max.y; +		r.x.bx = 0; +		r.x.cx = MAX(data.screen_max.x, data.max.x); +		r.x.dx = MAX(data.screen_max.y, data.max.y);  		break;  	case INT33_GET_WINDOW:  		r.x.ax = data.min.x; @@ -1169,11 +1221,15 @@ static void int33_handler(union INTPACK r)  		r.x.cx = data.max.x;  		r.x.dx = data.max.y;  		break; +#if USE_WHEEL +	// Wheel API extensions:  	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; +#endif +	// Our internal API extensions:  	case INT33_GET_TSR_DATA:  		dlog_puts("Get TSR data");  		r.x.es = FP_SEG(&data); @@ -1333,7 +1389,7 @@ static LPTSRDATA int33_get_tsr_data(void);  	"xor ax, ax" \  	"mov es, ax" \  	"mov di, ax" \ -	"mov ax, 0x7f" \ +	"mov ax, 0x73" \  	"int 0x33"   \  	__value [es di] \  	__modify [ax] @@ -53,8 +53,8 @@  #define VERSION_MAJOR 0  #define VERSION_MINOR 4 -#define REPORTED_VERSION_MAJOR 8 -#define REPORTED_VERSION_MINOR 0x20 +#define REPORTED_VERSION_MAJOR 6 +#define REPORTED_VERSION_MINOR 0x30  #if USE_VIRTUALBOX  #include "vbox.h" @@ -121,6 +121,8 @@ typedef struct tsrdata {  	/** Current remainder of delta movement that does not yet translate to an entire mickey  	 *  Usually only when mickeysPerLine is not a multiple of 8. */  	struct point delta_frac; +	/** Last absolute position (to compute a delta for relative motion emulation). Using -1 for "none". */ +	struct point abs_pos;  	/** Total mickeys moved in the last second. */  	uint16_t total_motion;  	/** Ticks when the above value was last reset. */ @@ -28,6 +28,7 @@ static inline uint8_t bda_get_byte(unsigned int offset) {  #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_char_height()     bda_get_word(0x85)  #define bda_get_tick_count()      bda_get_dword(0x6c)  #define bda_get_tick_count_lo()   bda_get_word(0x6c) @@ -134,12 +134,18 @@ enum INT33_API {  	 *  @return ax min_x, bx min_y, cx max_x, d max_y. */  	INT33_GET_WINDOW = 0x31, +	/** Get pointer to driver's copyright string in es:di. */ +	INT33_GET_COPYRIGHT_STRING = 0x4D, + +	/** Get pointer to driver's version string in es:di. */ +	INT33_GET_VERSION_STRING = 0x6D, +  	// Wheel API Extensions:  	INT33_GET_CAPABILITIES = 0x11,  	// Our internal API functions: -	/** Obtains a pointer to the driver's data. */ -	INT33_GET_TSR_DATA = 0x7f +	/** Obtains a pointer to the driver's data in es:di. */ +	INT33_GET_TSR_DATA = 0x73,  };  enum INT33_CAPABILITY_BITS { @@ -183,7 +189,7 @@ enum INT33_EVENT_MASK {  	INT33_EVENT_MASK_ALL                    = 0xFFFF  }; -#pragma aux INT33_CB far loadds parm [ax] [bx] [cx] [dx] [si] [di] +#pragma aux INT33_CB far loadds parm [ax] [bx] [cx] [dx] [si] [di] modify []  static uint16_t int33_reset(void);  #pragma aux int33_reset = \ @@ -226,4 +232,20 @@ static uint16_t int33_get_driver_version(void);  	__value [bx] \  	__modify [ax bx cx dx] +static bool int33_get_max_coordinates(int16_t *x, int16_t *y); +#pragma aux int33_get_max_coordinates = \ +	"mov ax, 0x26" \ +	"mov bx, -1" \ +	"int 0x33" \ +	"xor ax, ax" \ +	"test bx, bx" \ +	"jnz error" \ +	"mov [si], cx" \ +	"mov [di], dx" \ +	"mov al, 1" \ +	"error:" \ +	__parm [si] [di] \ +	__value [al] \ +	__modify [ax bx cx dx] +  #endif /* INT33_H */ @@ -14,6 +14,9 @@ static inline void breakpoint(void);  static inline __segment get_cs(void);  #pragma aux get_cs = "mov ax, cs" value [ax] modify exact []; +static inline __segment get_ds(void); +#pragma aux get_ds = "mov ax, ds" value [ax] modify exact []; +  /** Map x linearly from range [0, srcmax] to [0, dstmax].   *  Equivalent of (x * dstmax) / srcmax but with 32-bit unsigned precision. */  static unsigned scaleu(unsigned x, unsigned srcmax, unsigned dstmax); @@ -18,6 +18,7 @@   */  #include <windows.h> +#include <limits.h>  #include "utils.h"  #include "int33.h" @@ -52,7 +53,7 @@ static void FAR int33_mouse_callback(uint16_t events, uint16_t buttons, int16_t  {  	int status = 0; -#if TRACE_EVENTS_IN +#if TRACE_EVENTS  	dlog_print("w16mouse: events=");  	dlog_printx(events);  	dlog_print(" buttons="); @@ -84,7 +85,7 @@ static void FAR int33_mouse_callback(uint16_t events, uint16_t buttons, int16_t  		x = (uint16_t)(x) * 2;  		y = (uint16_t)(y) * 2;  	} else { -		// Use mickeys for relative motion +		// Prefer to use mickeys for relative motion if we don't have absolute data  		x = delta_x - prev_delta_x;  		y = delta_y - prev_delta_y; @@ -99,13 +100,15 @@ static void FAR int33_mouse_callback(uint16_t events, uint16_t buttons, int16_t  	dlog_print("w16mouse: event status=");  	dlog_printx(status);  	dlog_print(" x="); -	dlog_printd(x); +	if (status & SF_ABSOLUTE) dlog_printu(x); +	                     else dlog_printd(x);  	dlog_print(" y="); -	dlog_printd(y); +	if (status & SF_ABSOLUTE) dlog_printu(y); +	                     else dlog_printd(y);  	dlog_endline();  #endif -	send_event(status, x, (uint16_t)(y), MOUSE_NUM_BUTTONS, 0, 0); +	send_event(status, x, y, MOUSE_NUM_BUTTONS, 0, 0);  }  #pragma code_seg () @@ -172,7 +175,7 @@ VOID FAR PASCAL Enable(LPFN_MOUSEEVENT lpEventProc)  VOID FAR PASCAL Disable(VOID)  {  	if (enabled) { -		int33_reset(); // This removes our handler and removes all other settings +		int33_reset(); // This removes our handler and all other settings  		enabled = false;  	}  }  | 
