diff --git a/reactos/subsystems/ntvdm/CMakeLists.txt b/reactos/subsystems/ntvdm/CMakeLists.txt index 7f480dc8f82..43ac966013d 100644 --- a/reactos/subsystems/ntvdm/CMakeLists.txt +++ b/reactos/subsystems/ntvdm/CMakeLists.txt @@ -9,6 +9,7 @@ list(APPEND SOURCE bios/bios32/bios32.c bios/bios32/kbdbios32.c bios/bios32/vidbios32.c + bios/bios32/moubios32.c bios/bios.c bios/kbdbios.c bios/rom.c diff --git a/reactos/subsystems/ntvdm/bios/bios32/bios32.c b/reactos/subsystems/ntvdm/bios/bios32/bios32.c index 34f6b61d6f3..7bf9a83daf0 100644 --- a/reactos/subsystems/ntvdm/bios/bios32/bios32.c +++ b/reactos/subsystems/ntvdm/bios/bios32/bios32.c @@ -20,6 +20,7 @@ #include "bios32p.h" #include "kbdbios32.h" #include "vidbios32.h" +#include "moubios32.h" #include "io.h" #include "hardware/cmos.h" @@ -412,7 +413,7 @@ BOOLEAN Bios32Initialize(VOID) BiosHwSetup(); /* Initialize the Keyboard and Video BIOS */ - if (!KbdBios32Initialize() || !VidBios32Initialize()) return FALSE; + if (!KbdBios32Initialize() || !VidBios32Initialize() || !MouseBios32Initialize()) return FALSE; ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! ///////////////////// @@ -428,6 +429,7 @@ BOOLEAN Bios32Initialize(VOID) VOID Bios32Cleanup(VOID) { + MouseBios32Cleanup(); VidBios32Cleanup(); KbdBios32Cleanup(); } diff --git a/reactos/subsystems/ntvdm/bios/bios32/moubios32.c b/reactos/subsystems/ntvdm/bios/bios32/moubios32.c new file mode 100644 index 00000000000..5a7b62e223d --- /dev/null +++ b/reactos/subsystems/ntvdm/bios/bios32/moubios32.c @@ -0,0 +1,250 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: moubios32.c + * PURPOSE: VDM Mouse 32-bit BIOS + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" + +#include "moubios32.h" +#include "bios32p.h" + +#include "io.h" +#include "hardware/mouse.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static BOOLEAN DriverEnabled = TRUE; +static MOUSE_DRIVER_STATE DriverState; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static VOID PaintMouseCursor(VOID) +{ + if (Bda->VideoMode <= 3) + { + WORD Character; + DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize); + + EmulatorReadMemory(&EmulatorContext, + VideoAddress + + (DriverState.Position.Y * Bda->ScreenColumns + + DriverState.Position.X) * sizeof(WORD), + (LPVOID)&Character, + sizeof(WORD)); + + DriverState.Character = Character; + Character &= DriverState.TextCursor.ScreenMask; + Character ^= DriverState.TextCursor.CursorMask; + + EmulatorWriteMemory(&EmulatorContext, + VideoAddress + + (DriverState.Position.Y * Bda->ScreenColumns + + DriverState.Position.X) * sizeof(WORD), + (LPVOID)&Character, + sizeof(WORD)); + } + else + { + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + } +} + +static VOID EraseMouseCursor(VOID) +{ + if (Bda->VideoMode <= 3) + { + DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize); + + EmulatorWriteMemory(&EmulatorContext, + VideoAddress + + (DriverState.Position.Y * Bda->ScreenColumns + + DriverState.Position.X) * sizeof(WORD), + (LPVOID)&DriverState.Character, + sizeof(WORD)); + } + else + { + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + } +} + +static VOID WINAPI BiosMouseService(LPWORD Stack) +{ + switch (getAX()) + { + /* Reset Driver */ + case 0x00: + { + DriverEnabled = TRUE; + DriverState.ShowCount = 0; + + /* Set the default text cursor */ + DriverState.TextCursor.ScreenMask = 0xFFFF; /* Display everything */ + DriverState.TextCursor.CursorMask = 0xFF00; /* ... but with inverted attributes */ + + /* Set the default graphics cursor */ + DriverState.GraphicsCursor.HotSpot.X = 3; + DriverState.GraphicsCursor.HotSpot.Y = 1; + + DriverState.GraphicsCursor.ScreenMask[0] = 0xC3FF; // 1100001111111111 + DriverState.GraphicsCursor.ScreenMask[1] = 0xC0FF; // 1100000011111111 + DriverState.GraphicsCursor.ScreenMask[2] = 0xC07F; // 1100000001111111 + DriverState.GraphicsCursor.ScreenMask[3] = 0xC01F; // 1100000000011111 + DriverState.GraphicsCursor.ScreenMask[4] = 0xC00F; // 1100000000001111 + DriverState.GraphicsCursor.ScreenMask[5] = 0xC007; // 1100000000000111 + DriverState.GraphicsCursor.ScreenMask[6] = 0xC003; // 1100000000000011 + DriverState.GraphicsCursor.ScreenMask[7] = 0xC007; // 1100000000000111 + DriverState.GraphicsCursor.ScreenMask[8] = 0xC01F; // 1100000000011111 + DriverState.GraphicsCursor.ScreenMask[9] = 0xC01F; // 1100000000011111 + DriverState.GraphicsCursor.ScreenMask[10] = 0xC00F; // 1100000000001111 + DriverState.GraphicsCursor.ScreenMask[11] = 0xC60F; // 1100011000001111 + DriverState.GraphicsCursor.ScreenMask[12] = 0xFF07; // 1111111100000111 + DriverState.GraphicsCursor.ScreenMask[13] = 0xFF07; // 1111111100000111 + DriverState.GraphicsCursor.ScreenMask[14] = 0xFF87; // 1111111110000111 + DriverState.GraphicsCursor.ScreenMask[15] = 0xFFCF; // 1111111111001111 + + DriverState.GraphicsCursor.CursorMask[0] = 0x0000; // 0000000000000000 + DriverState.GraphicsCursor.CursorMask[1] = 0x1C00; // 0001110000000000 + DriverState.GraphicsCursor.CursorMask[2] = 0x1F00; // 0001111100000000 + DriverState.GraphicsCursor.CursorMask[3] = 0x1F80; // 0001111110000000 + DriverState.GraphicsCursor.CursorMask[4] = 0x1FE0; // 0001111111100000 + DriverState.GraphicsCursor.CursorMask[5] = 0x1FF0; // 0001111111110000 + DriverState.GraphicsCursor.CursorMask[6] = 0x1FF8; // 0001111111111000 + DriverState.GraphicsCursor.CursorMask[7] = 0x1FE0; // 0001111111100000 + DriverState.GraphicsCursor.CursorMask[8] = 0x1FC0; // 0001111111000000 + DriverState.GraphicsCursor.CursorMask[9] = 0x1FC0; // 0001111111000000 + DriverState.GraphicsCursor.CursorMask[10] = 0x19E0; // 0001100111100000 + DriverState.GraphicsCursor.CursorMask[11] = 0x00E0; // 0000000011100000 + DriverState.GraphicsCursor.CursorMask[12] = 0x0070; // 0000000001110000 + DriverState.GraphicsCursor.CursorMask[13] = 0x0070; // 0000000001110000 + DriverState.GraphicsCursor.CursorMask[14] = 0x0030; // 0000000000110000 + DriverState.GraphicsCursor.CursorMask[15] = 0x0000; // 0000000000000000 + + break; + } + + /* Show Mouse Cursor */ + case 0x01: + { + DriverState.ShowCount++; + if (DriverState.ShowCount > 0) PaintMouseCursor(); + + break; + } + + /* Hide Mouse Cursor */ + case 0x02: + { + DriverState.ShowCount--; + if (DriverState.ShowCount <= 0) EraseMouseCursor(); + + break; + } + + /* Define Graphics Cursor */ + case 0x09: + { + PWORD MaskBitmap = (PWORD)SEG_OFF_TO_PTR(getES(), getDX()); + + DriverState.GraphicsCursor.HotSpot.X = getBX(); + DriverState.GraphicsCursor.HotSpot.Y = getCX(); + + RtlMoveMemory(DriverState.GraphicsCursor.ScreenMask, + MaskBitmap, + sizeof(DriverState.GraphicsCursor.ScreenMask)); + + RtlMoveMemory(DriverState.GraphicsCursor.CursorMask, + &MaskBitmap[16], + sizeof(DriverState.GraphicsCursor.CursorMask)); + + break; + } + + /* Define Text Cursor */ + case 0x0A: + { + DriverState.TextCursor.ScreenMask = getCX(); + DriverState.TextCursor.CursorMask = getDX(); + + break; + } + + /* Return Driver Storage Requirements */ + case 0x15: + { + setBX(sizeof(MOUSE_DRIVER_STATE)); + break; + } + + /* Save Driver State */ + case 0x16: + { + *((PMOUSE_DRIVER_STATE)SEG_OFF_TO_PTR(getES(), getDX())) = DriverState; + break; + } + + /* Restore Driver State */ + case 0x17: + { + DriverState = *((PMOUSE_DRIVER_STATE)SEG_OFF_TO_PTR(getES(), getDX())); + break; + } + + /* Disable Mouse Driver */ + case 0x1F: + { + DriverEnabled = FALSE; + break; + } + + /* Enable Mouse Driver */ + case 0x20: + { + DriverEnabled = TRUE; + break; + } + + default: + { + DPRINT1("BIOS Function INT 33h, AX = 0x%04X NOT IMPLEMENTED\n", getAX()); + } + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID MouseBiosUpdatePosition(PCOORD NewPosition) +{ + if (DriverEnabled && (DriverState.ShowCount > 0)) + { + EraseMouseCursor(); + DriverState.Position = *NewPosition; + PaintMouseCursor(); + } +} + +BOOLEAN MouseBios32Initialize(VOID) +{ + /* Clear the state */ + ZeroMemory(&DriverState, sizeof(DriverState)); + + /* Initialize the interrupt handler */ + RegisterBiosInt32(BIOS_MOUSE_INTERRUPT, BiosMouseService); + + return TRUE; +} + +VOID MouseBios32Cleanup(VOID) +{ + if (DriverState.ShowCount > 0) EraseMouseCursor(); +} diff --git a/reactos/subsystems/ntvdm/bios/bios32/moubios32.h b/reactos/subsystems/ntvdm/bios/bios32/moubios32.h new file mode 100644 index 00000000000..f5aa951ac40 --- /dev/null +++ b/reactos/subsystems/ntvdm/bios/bios32/moubios32.h @@ -0,0 +1,48 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: moubios32.h + * PURPOSE: VDM Mouse 32-bit BIOS + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _MOUBIOS32_H_ +#define _MOUBIOS32_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define BIOS_MOUSE_INTERRUPT 0x33 + +typedef struct _MOUSE_DRIVER_STATE +{ + SHORT ShowCount; + COORD Position; + WORD Character; + + struct + { + WORD ScreenMask; + WORD CursorMask; + } TextCursor; + + struct + { + COORD HotSpot; + WORD ScreenMask[16]; + WORD CursorMask[16]; + } GraphicsCursor; +} MOUSE_DRIVER_STATE, *PMOUSE_DRIVER_STATE; + +/* FUNCTIONS ******************************************************************/ + +VOID MouseBiosUpdatePosition(PCOORD NewPosition); +BOOLEAN MouseBios32Initialize(VOID); +VOID MouseBios32Cleanup(VOID); + +#endif // _MOUBIOS32_H_ + +/* EOF */ diff --git a/reactos/subsystems/ntvdm/hardware/ps2.c b/reactos/subsystems/ntvdm/hardware/ps2.c index d2f27bba649..7c1ed6d4472 100644 --- a/reactos/subsystems/ntvdm/hardware/ps2.c +++ b/reactos/subsystems/ntvdm/hardware/ps2.c @@ -15,6 +15,7 @@ #include "ps2.h" #include "pic.h" #include "mouse.h" +#include "../bios/bios32/moubios32.h" /* PRIVATE VARIABLES **********************************************************/ @@ -307,8 +308,11 @@ VOID PS2Dispatch(PINPUT_RECORD InputRecord) case MOUSE_EVENT: { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + /* Notify the BIOS driver */ + MouseBiosUpdatePosition(&InputRecord->Event.MouseEvent.dwMousePosition); + + // TODO: PS/2, other stuff + break; } @@ -326,9 +330,7 @@ VOID GenerateKeyboardInterrupts(VOID) BOOLEAN PS2Initialize(HANDLE ConsoleInput) { -#if 0 DWORD ConInMode; -#endif /* Create the mutex */ QueueMutex = CreateMutex(NULL, FALSE, NULL); @@ -337,23 +339,25 @@ BOOLEAN PS2Initialize(HANDLE ConsoleInput) RegisterIoPort(PS2_CONTROL_PORT, PS2ReadPort, PS2WritePort); RegisterIoPort(PS2_DATA_PORT , PS2ReadPort, PS2WritePort); -#if 0 if (GetConsoleMode(ConsoleInput, &ConInMode)) { +#if 0 if (MousePresent) { +#endif /* Support mouse input events if there is a mouse on the system */ ConInMode |= ENABLE_MOUSE_INPUT; +#if 0 } else { /* Do not support mouse input events if there is no mouse on the system */ ConInMode &= ~ENABLE_MOUSE_INPUT; } +#endif SetConsoleMode(ConsoleInput, ConInMode); } -#endif return TRUE; }