aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2022-04-08 02:17:46 +0200
committerJavier <dev.git@javispedro.com>2022-04-08 02:17:46 +0200
commit98a343355c3459b892792585788069bac3bc40e7 (patch)
tree1ff4674815775c323822e03c3c0f05c49204a549
parentdb308ca65b8f0ddb61969e7e4b4fb2145d8a27c2 (diff)
downloadvbados-98a343355c3459b892792585788069bac3bc40e7.tar.gz
vbados-98a343355c3459b892792585788069bac3bc40e7.zip
try to detect video mode changes
-rw-r--r--dostsr.c112
-rw-r--r--dostsr.h6
-rw-r--r--int10vga.h1
-rw-r--r--int33.h28
-rw-r--r--utils.h3
-rw-r--r--w16mouse.c15
6 files changed, 126 insertions, 39 deletions
diff --git a/dostsr.c b/dostsr.c
index 8f6bf04..f0dc0ca 100644
--- a/dostsr.c
+++ b/dostsr.c
@@ -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]
diff --git a/dostsr.h b/dostsr.h
index 5aae98c..50d4441 100644
--- a/dostsr.h
+++ b/dostsr.h
@@ -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. */
diff --git a/int10vga.h b/int10vga.h
index a7f6b8f..ec19a21 100644
--- a/int10vga.h
+++ b/int10vga.h
@@ -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)
diff --git a/int33.h b/int33.h
index 13d5eea..bb975a3 100644
--- a/int33.h
+++ b/int33.h
@@ -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 */
diff --git a/utils.h b/utils.h
index 6cc74da..05b4e36 100644
--- a/utils.h
+++ b/utils.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);
diff --git a/w16mouse.c b/w16mouse.c
index 5660b81..910358f 100644
--- a/w16mouse.c
+++ b/w16mouse.c
@@ -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;
}
}