mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
[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. svn path=/trunk/; revision=64138
This commit is contained in:
parent
fe68098da9
commit
76a416c915
2 changed files with 275 additions and 7 deletions
|
@ -78,6 +78,60 @@ static VOID EraseMouseCursor(VOID)
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VOID WINAPI BiosMouseService(LPWORD Stack)
|
||||
{
|
||||
switch (getAX())
|
||||
|
@ -176,7 +230,6 @@ static VOID WINAPI BiosMouseService(LPWORD Stack)
|
|||
setBX(DriverState.ButtonState);
|
||||
setCX(DriverState.Position.X);
|
||||
setDX(DriverState.Position.Y);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -249,8 +302,26 @@ static VOID WINAPI BiosMouseService(LPWORD Stack)
|
|||
/* 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 @@ static VOID WINAPI BiosMouseService(LPWORD Stack)
|
|||
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 @@ static VOID WINAPI BiosMouseService(LPWORD Stack)
|
|||
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 @@ VOID MouseBiosUpdatePosition(PCOORD NewPosition)
|
|||
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 @@ VOID MouseBiosUpdateButtons(WORD ButtonState)
|
|||
/* 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)
|
||||
|
|
|
@ -25,6 +25,16 @@ enum
|
|||
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;
|
||||
|
@ -40,6 +50,12 @@ typedef struct _MOUSE_DRIVER_STATE
|
|||
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
|
||||
{
|
||||
WORD ScreenMask;
|
||||
|
|
Loading…
Reference in a new issue