Author: hbelusca Date: Sun Sep 14 00:48:21 2014 New Revision: 64138
URL: http://svn.reactos.org/svn/reactos?rev=64138&view=rev Log: [NTVDM]: Implement few INT 33h (mouse) functions: - For function 0Ah, we don't still support defining hardware cursor. - Implement function 0Ch (define interrupt subroutine params), compatible MSMOUSE v1.0+ - Implement function 14h (exchange interrupt subroutines), compatible MSMOUSE v3.0+ - Implement function 18h (set alternate mouse user handler), that is the same thing as function 0Ch but for a set of maximum 3 handlers, compatible MSMOUSE v6.0+ - Implement function 19h (return user alternate interrupt vector) that returns the handler associated with a call mask, compatible MSMOUSE v6.0+ - Call all those handlers accordingly to their associated call mask, for mouse moves and mouse button presses.
Modified: trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.h
Modified: trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/bios/bios3... ============================================================================== --- trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c [iso-8859-1] Sun Sep 14 00:48:21 2014 @@ -75,6 +75,60 @@ { // TODO: NOT IMPLEMENTED UNIMPLEMENTED; + } +} + +static VOID CallMouseUserHandlers(USHORT CallMask) +{ + USHORT i; + + /* Call handler 0 */ + if ((DriverState.Handler0.CallMask & CallMask) != 0 && + DriverState.Handler0.Callback != (ULONG)NULL) + { + /* + * Set the parameters for the callback. + * NOTE: In text modes, the row and column will be reported + * as a multiple of the cell size, typically 8x8 pixels. + */ + setAX(CallMask); + setBX(DriverState.ButtonState); + setCX(DriverState.Position.X); + setDX(DriverState.Position.Y); + setSI(DriverState.MickeysPerCellHoriz); + setDI(DriverState.MickeysPerCellVert); + + DPRINT1("Calling Handler0 0x%08x with CallMask 0x%04x\n", + DriverState.Handler0.Callback, CallMask); + + /* Call the callback */ + RunCallback16(&BiosContext, DriverState.Handler0.Callback); + } + + for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) + { + /* Call the suitable handlers */ + if ((DriverState.Handlers[i].CallMask & CallMask) != 0 && + DriverState.Handlers[i].Callback != (ULONG)NULL) + { + /* + * Set the parameters for the callback. + * NOTE: In text modes, the row and column will be reported + * as a multiple of the cell size, typically 8x8 pixels. + */ + setAX(CallMask); + setBX(DriverState.ButtonState); + setCX(DriverState.Position.X); + setDX(DriverState.Position.Y); + setSI(DriverState.MickeysPerCellHoriz); + setDI(DriverState.MickeysPerCellVert); + + DPRINT1("Calling Handler[%d] 0x%08x with CallMask 0x%04x\n", + i, DriverState.Handlers[i].Callback, CallMask); + + /* Call the callback */ + RunCallback16(&BiosContext, DriverState.Handlers[i].Callback); + } } }
@@ -176,7 +230,6 @@ setBX(DriverState.ButtonState); setCX(DriverState.Position.X); setDX(DriverState.Position.Y); - break; }
@@ -249,8 +302,26 @@ /* Define Text Cursor */ case 0x0A: { - DriverState.TextCursor.ScreenMask = getCX(); - DriverState.TextCursor.CursorMask = getDX(); + USHORT BX = getBX(); + + if (BX == 0x0000) + { + /* Define software cursor */ + DriverState.TextCursor.ScreenMask = getCX(); + DriverState.TextCursor.CursorMask = getDX(); + } + else if (BX == 0x0001) + { + /* Define hardware cursor */ + DPRINT1("Defining hardware cursor is unimplemented\n"); + UNIMPLEMENTED; + // CX == start scan line + // DX == end scan line + } + else + { + DPRINT1("Invalid BX value 0x%04x\n", BX); + }
break; } @@ -267,11 +338,37 @@ break; }
+ /* Define Interrupt Subroutine Parameters, compatible MS MOUSE v1.0+ */ + case 0x0C: + { + DriverState.Handler0.CallMask = getCX(); + DriverState.Handler0.Callback = MAKELONG(getDX(), getES()); // Far pointer to the callback + DPRINT1("Define callback 0x%04x, 0x%08x\n", + DriverState.Handler0.CallMask, DriverState.Handler0.Callback); + break; + } + /* Define Mickey/Pixel Ratio */ case 0x0F: { DriverState.MickeysPerCellHoriz = getCX(); - DriverState.MickeysPerCellVert = getDX(); + DriverState.MickeysPerCellVert = getDX(); + break; + } + + /* Exchange Interrupt Subroutines, compatible MS MOUSE v3.0+ (see function 0x0C) */ + case 0x14: + { + USHORT OldCallMask = DriverState.Handler0.CallMask; + ULONG OldCallback = DriverState.Handler0.Callback; + + DriverState.Handler0.CallMask = getCX(); + DriverState.Handler0.Callback = MAKELONG(getDX(), getES()); // Far pointer to the callback + + /* Return old callmask in CX and callback vector in ES:DX */ + setCX(OldCallMask); + setES(HIWORD(OldCallback)); + setDX(LOWORD(OldCallback));
break; } @@ -297,6 +394,150 @@ break; }
+ /* Set Alternate Mouse User Handler, compatible MS MOUSE v6.0+ */ + case 0x18: + { + /* + * Up to three handlers can be defined by separate calls to this + * function, each with a different combination of shift states in + * the call mask; calling this function again with a call mask of + * 0000h undefines the specified handler (official documentation); + * specifying the same call mask and an address of 0000h:0000h + * undefines the handler (real life). + * See Ralf Brown: http://www.ctyme.com/intr/rb-5981.htm + * for more information. + */ + + USHORT i; + USHORT CallMask = getCX(); + ULONG Callback = MAKELONG(getDX(), getES()); // Far pointer to the callback + BOOLEAN Success = FALSE; + + DPRINT1("Define v6.0+ callback 0x%04x, 0x%08x\n", + CallMask, Callback); + + if (CallMask == 0x0000) + { + /* + * Find the handler entry corresponding to the given + * callback and undefine it. + */ + for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) + { + if (DriverState.Handlers[i].Callback == Callback) + { + /* Found it, undefine the handler */ + DriverState.Handlers[i].CallMask = 0x0000; + DriverState.Handlers[i].Callback = (ULONG)NULL; + Success = TRUE; + break; + } + } + } + else if (Callback == (ULONG)NULL) + { + /* + * Find the handler entry corresponding to the given + * callmask and undefine it. + */ + for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) + { + if (DriverState.Handlers[i].CallMask == CallMask) + { + /* Found it, undefine the handler */ + DriverState.Handlers[i].CallMask = 0x0000; + DriverState.Handlers[i].Callback = (ULONG)NULL; + Success = TRUE; + break; + } + } + } + else + { + /* + * Try to find a handler entry corresponding to the given + * callmask to redefine it, otherwise find an empty handler + * entry and set the new handler in there. + */ + + USHORT EmptyHandler = 0xFFFF; // Invalid handler + + for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) + { + /* Find the first empty handler */ + if (EmptyHandler == 0xFFFF && + DriverState.Handlers[i].CallMask == 0x0000 && + DriverState.Handlers[i].Callback == (ULONG)NULL) + { + EmptyHandler = i; + } + + if (DriverState.Handlers[i].CallMask == CallMask) + { + /* Found it, redefine the handler */ + DriverState.Handlers[i].CallMask = CallMask; + DriverState.Handlers[i].Callback = Callback; + Success = TRUE; + break; + } + } + + /* + * If we haven't found anything and we found + * an empty handler, set it. + */ + if (!Success && EmptyHandler != 0xFFFF + /* && EmptyHandler < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]) */) + { + DriverState.Handlers[EmptyHandler].CallMask = CallMask; + DriverState.Handlers[EmptyHandler].Callback = Callback; + Success = TRUE; + } + } + + /* If we failed, set error code */ + if (!Success) setAX(0xFFFF); + + break; + } + + /* Return User Alternate Interrupt Vector, compatible MS MOUSE v6.0+ */ + case 0x19: + { + USHORT i; + USHORT CallMask = getCX(); + ULONG Callback; + BOOLEAN Success = FALSE; + + /* + * Find the handler entry corresponding to the given callmask. + */ + for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) + { + if (DriverState.Handlers[i].CallMask == CallMask) + { + /* Found it */ + Callback = DriverState.Handlers[i].Callback; + Success = TRUE; + break; + } + } + + if (Success) + { + /* Return the callback vector in BX:DX */ + setBX(HIWORD(Callback)); + setDX(LOWORD(Callback)); + } + else + { + /* We failed, set error code */ + setCX(0x0000); + } + + break; + } + /* Disable Mouse Driver */ case 0x1F: { @@ -331,19 +572,23 @@ if (!DriverEnabled) return;
DriverState.HorizCount += (DeltaX * (SHORT)DriverState.MickeysPerCellHoriz) / 8; - DriverState.VertCount += (DeltaY * (SHORT)DriverState.MickeysPerCellVert) / 8; - + DriverState.VertCount += (DeltaY * (SHORT)DriverState.MickeysPerCellVert ) / 8; + if (DriverState.ShowCount > 0) { EraseMouseCursor(); DriverState.Position = *NewPosition; PaintMouseCursor(); } + + /* Call the mouse handlers */ + CallMouseUserHandlers(0x0001); // We use MS MOUSE v1.0+ format }
VOID MouseBiosUpdateButtons(WORD ButtonState) { - WORD i; + USHORT i; + USHORT CallMask = 0x0000; // We use MS MOUSE v1.0+ format
if (!DriverEnabled) return;
@@ -357,16 +602,23 @@ /* Mouse press */ DriverState.PressCount[i]++; DriverState.LastPress[i] = DriverState.Position; + + CallMask |= (1 << (2 * i + 1)); } else if (NewState < OldState) { /* Mouse release */ DriverState.ReleaseCount[i]++; DriverState.LastRelease[i] = DriverState.Position; + + CallMask |= (1 << (2 * i + 2)); } }
DriverState.ButtonState = ButtonState; + + /* Call the mouse handlers */ + CallMouseUserHandlers(CallMask); }
BOOLEAN MouseBios32Initialize(VOID)
Modified: trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/bios/bios3... ============================================================================== --- trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.h [iso-8859-1] Sun Sep 14 00:48:21 2014 @@ -25,6 +25,16 @@ NUM_MOUSE_BUTTONS };
+typedef struct _MOUSE_USER_HANDLER +{ + /* + * CallMask format: see table: http://www.ctyme.com/intr/rb-5968.htm#Table3171 + * Alternatively, see table: http://www.ctyme.com/intr/rb-5981.htm#Table3174 + */ + USHORT CallMask; + ULONG Callback; // Far pointer to the callback +} MOUSE_USER_HANDLER, *PMOUSE_USER_HANDLER; + typedef struct _MOUSE_DRIVER_STATE { SHORT ShowCount; @@ -39,6 +49,12 @@ SHORT VertCount; WORD MickeysPerCellHoriz; WORD MickeysPerCellVert; + + /* + * User Subroutine Handlers called on mouse events + */ + MOUSE_USER_HANDLER Handler0; // Handler compatible MS MOUSE v1.0+ + MOUSE_USER_HANDLER Handlers[3]; // Handlers compatible MS MOUSE v6.0+
struct {