From a2aaf8a11f318f4f1dda9c5f15cf2257a3c73f9a Mon Sep 17 00:00:00 2001 From: Javier Date: Wed, 20 Apr 2022 02:45:41 +0200 Subject: add back support for using ps/2 bios with 3-byte packets apparently some BIOSes and DOSBox don't support 1-byte streaming mode, and neither does win386 without a special vkd --- int15ps2.h | 13 ++++++----- int2fwin.h | 2 ++ mousetsr.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- mousetsr.h | 8 +++++-- mousmain.c | 2 +- 5 files changed, 80 insertions(+), 23 deletions(-) diff --git a/int15ps2.h b/int15ps2.h index 95bedf7..438dfd8 100644 --- a/int15ps2.h +++ b/int15ps2.h @@ -31,10 +31,10 @@ typedef uint8_t ps2m_err; enum ps2m_errors { PS2M_ERR_INVALID_FUNCTION = 1, - PSM2_ERR_INVALID_INPUT = 2, - PSM2_ERR_INTERFACE_ERROR = 3, - PSM2_ERR_RESEND = 4, - PSM2_ERR_NO_CALLBACK = 5, + PS2M_ERR_INVALID_INPUT = 2, + PS2M_ERR_INTERFACE_ERROR = 3, + PS2M_ERR_RESEND = 4, + PS2M_ERR_NO_CALLBACK = 5, }; enum ps2m_status { @@ -48,8 +48,9 @@ enum ps2m_status { }; enum ps2m_packet_size { - PS2M_PACKET_SIZE_PLAIN = 3, - PS2M_PACKET_SIZE_EXT = 4, + PS2M_PACKET_SIZE_STREAMING = 1, + PS2M_PACKET_SIZE_PLAIN = 3, + PS2M_PACKET_SIZE_EXT = 4, }; enum ps2m_device_ids { diff --git a/int2fwin.h b/int2fwin.h index 255cdd7..abd5f2e 100644 --- a/int2fwin.h +++ b/int2fwin.h @@ -45,6 +45,8 @@ enum int2f_functions { /** Notification sent when Windows386 is starting up. */ INT2F_NOTIFY_WIN386_STARTUP = 0x1605, + /** Notification sent when Windows386 is terminating. */ + INT2F_NOTIFY_WIN386_SHUTDOWN = 0x1606, /** Notification sent by a VxD that wants to invoke a function in a real-mode driver. */ INT2F_NOTIFY_DEVICE_CALLOUT = 0x1607, diff --git a/mousetsr.c b/mousetsr.c index 406727b..3acbda1 100644 --- a/mousetsr.c +++ b/mousetsr.c @@ -846,19 +846,34 @@ static void handle_ps2_packet(void) /** PS/2 BIOS calls this routine to notify mouse events. * In our case, each time we receive a byte from the mouse. */ -static void ps2_mouse_handler(unsigned byte) +static void ps2_mouse_handler(uint16_t word0, uint16_t word1, uint16_t word2, uint16_t word3) { -#pragma aux ps2_mouse_handler "*" parm caller [ax] modify [ax bx cx dx si di es fs gs] +#pragma aux ps2_mouse_handler "*" parm caller [ax] [bx] [cx] [dx] modify [ax bx cx dx si di es fs gs] uint16_t ticks = bda_get_tick_count_lo(); + // Are we using the BIOS in 3-packet mode directly? + if (data.bios_packet_size == PS2M_PACKET_SIZE_PLAIN) { + // Just forward it to the full packet handler. + data.ps2_packet[0] = word0; + data.ps2_packet[1] = word1; + data.ps2_packet[2] = word2; + (void) word3; + handle_ps2_packet(); + return; + } + + // Otherwise we are using the BIOS in 1-packet size mode, + // receiving one byte at a time. + // We have to compute synchronization ourselves. + #if TRACE_EVENTS dlog_print("ps2 callback byte "); dlog_printd(1 + data.cur_packet_bytes); dlog_putc('/'); dlog_printd(data.packet_size); dlog_putc('='); - dlog_printx(byte & 0xFF); + dlog_printx(word0 & 0xFF); dlog_endline(); #endif /* TRACE_EVENTS */ @@ -876,10 +891,10 @@ static void ps2_mouse_handler(unsigned byte) data.cur_packet_ticks = ticks; } - data.ps2_packet[data.cur_packet_bytes] = byte; + data.ps2_packet[data.cur_packet_bytes] = word0; data.cur_packet_bytes++; - if (data.cur_packet_bytes == data.packet_size) { + if (data.cur_packet_bytes >= data.packet_size) { handle_ps2_packet(); data.cur_packet_bytes = 0; } @@ -904,9 +919,9 @@ void __declspec(naked) __far ps2_mouse_callback() pop ds mov ax,[bp+28+6] ; Status - ; mov bx,[bp+28+4] ; X - ; mov cx,[bp+28+2] ; Y - ; mov dx,[bp+28+0] ; Z + mov bx,[bp+28+4] ; X + mov cx,[bp+28+2] ; Y + mov dx,[bp+28+0] ; Z call ps2_mouse_handler @@ -959,24 +974,53 @@ static void set_absolute(bool enable) static void reset_mouse_hardware() { + int err; + // Stop receiving bytes... ps2m_enable(false); - // Let the BIOS know we want every packet separately - // This also resets the mouse - ps2m_init(1); - + data.bios_packet_size = PS2M_PACKET_SIZE_STREAMING; // Default to use the BIOS in streaming mode data.packet_size = PS2M_PACKET_SIZE_PLAIN; data.cur_packet_bytes = 0; data.cur_packet_ticks = 0; +#if USE_WIN386 + if (data.haswin386) { + uint8_t device_id; + // Normally, win386 does not support anything except PS2M_PACKET_SIZE_PLAIN + // However, if we detect our special wheelvkd driver is running... + err = ps2m_get_device_id(&device_id); + if (err || device_id != PS2M_DEVICE_ID_IMPS2) { + // Our special driver is not running... + dlog_puts("Windows running, using plain packet size"); + data.bios_packet_size = PS2M_PACKET_SIZE_PLAIN; + } + } +#endif + + // Try to init PS/2 BIOS with desired packet size / streaming mode + err = ps2m_init(data.bios_packet_size); + + if (err && data.bios_packet_size != PS2M_PACKET_SIZE_PLAIN) { + // However, if there is an error, drop down to plain packet size + // Emulators like DOSBox don't support anything but plain packet size + dlog_puts("BIOS didn't support streaming mode, using plain packet size"); + data.bios_packet_size = PS2M_PACKET_SIZE_PLAIN; + err = ps2m_init(data.bios_packet_size); + } + if (err) { + dlog_puts("error on ps2m_init during reset, ignoring"); + } + #if USE_WHEEL - if (data.usewheel && ps2m_detect_wheel()) { + if (data.usewheel + && data.bios_packet_size == PS2M_PACKET_SIZE_STREAMING + && ps2m_detect_wheel()) { dlog_puts("PS/2 wheel detected"); data.haswheel = true; data.packet_size = PS2M_PACKET_SIZE_EXT; } else { - dlog_puts("PS/2 wheel NOT detected"); + if (data.usewheel) dlog_puts("PS/2 wheel NOT detected"); data.haswheel = false; } #endif @@ -1422,6 +1466,12 @@ static void int2f_handler(union INTPACK r) data.w386_instance[1].size = 0; r.x.es = FP_SEG(&data.w386_startup); r.x.bx = FP_OFF(&data.w386_startup); + data.haswin386 = true; + break; + case INT2F_NOTIFY_WIN386_SHUTDOWN: + dlog_puts("Windows is stopping"); + data.haswin386 = false; + data.w386cursor = false; break; case INT2F_NOTIFY_DEVICE_CALLOUT: switch (r.x.bx) { diff --git a/mousetsr.h b/mousetsr.h index 5e10afa..68377ab 100644 --- a/mousetsr.h +++ b/mousetsr.h @@ -110,9 +110,11 @@ typedef struct tsrdata { /** Whether the current mouse has a wheel (and support is enabled). */ bool haswheel; #endif - /** Packet size that we are currently using. */ + /** Packet size that the BIOS is currently using. Either 1 (streaming) or 3 (plain). */ + uint8_t bios_packet_size; + /** Packet size that we are currently expecting internally. Usually 3 (plain) or 4 (with wheel). */ uint8_t packet_size; - /** Number of bytes received so far (< packet_size). */ + /** For streaming mode: number of bytes received so far (< packet_size). */ uint8_t cur_packet_bytes; /** Stores the bytes received so far (cur_bytes). */ uint8_t ps2_packet[MAX_PS2_PACKET_SIZE]; @@ -195,6 +197,8 @@ typedef struct tsrdata { /** Information that we pass to Windows 386 on startup. */ win386_startup_info w386_startup; win386_instance_item w386_instance[2]; + /** Whether Windows 386 is running. */ + bool haswin386 : 1; /** Whether Windows 386 is rendering the cursor for us, * and therefore we should hide our own. */ bool w386cursor : 1; diff --git a/mousmain.c b/mousmain.c index 72b5b09..90e5e5c 100644 --- a/mousmain.c +++ b/mousmain.c @@ -246,7 +246,7 @@ static int configure_driver(LPTSRDATA data) dlog_init(); // Check for PS/2 mouse BIOS availability - if ((err = ps2m_init(1))) { + if ((err = ps2m_init(PS2M_PACKET_SIZE_PLAIN))) { fprintf(stderr, "Cannot init PS/2 mouse BIOS, err=%d\n", err); // Can't do anything without PS/2 return err; -- cgit v1.2.3