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; } } |