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/bios…
==============================================================================
--- 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/bios…
==============================================================================
--- 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
{