Author: aandrejevic Date: Fri Apr 17 00:20:39 2015 New Revision: 67219
URL: http://svn.reactos.org/svn/reactos?rev=67219&view=rev Log: [NTVDM] - Completely rewrite the timing system. Replace hardcoded callbacks with dynamic hardware timers. - Finish implementing the PS/2 mouse. - Fix the DOS mouse driver. Inspired by a patch by Stefano Toncich (Tonix) (see CORE-9166). CORE-9166 #comment A different fix was committed in r67219.
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/moubios32.c trunk/reactos/subsystems/mvdm/ntvdm/clock.c trunk/reactos/subsystems/mvdm/ntvdm/clock.h trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.h trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c trunk/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c trunk/reactos/subsystems/mvdm/ntvdm/dos/mouse32.h trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.h trunk/reactos/subsystems/mvdm/ntvdm/hardware/mouse.c trunk/reactos/subsystems/mvdm/ntvdm/hardware/mouse.h trunk/reactos/subsystems/mvdm/ntvdm/hardware/pit.c trunk/reactos/subsystems/mvdm/ntvdm/hardware/pit.h trunk/reactos/subsystems/mvdm/ntvdm/hardware/ps2.c trunk/reactos/subsystems/mvdm/ntvdm/hardware/ps2.h trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/moubios32.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios/... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/moubios32.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/moubios32.c [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -17,6 +17,7 @@
#include "io.h" #include "hardware/mouse.h" +#include "hardware/ps2.h"
// HACK: For the PS/2 bypass and MOUSE.COM driver direct call #include "dos/mouse32.h" @@ -28,13 +29,6 @@ // Mouse IRQ 12 static VOID WINAPI BiosMouseIrq(LPWORD Stack) { - // HACK!! Call directly the MOUSE.COM driver instead of going - // through the regular interfaces!! - extern COORD DosNewPosition; - extern WORD DosButtonState; - DosMouseUpdatePosition(&DosNewPosition); - DosMouseUpdateButtons(DosButtonState); - PicIRQComplete(Stack); }
@@ -118,6 +112,7 @@ { /* Set up the HW vector interrupts */ EnableHwIRQ(12, BiosMouseIrq); + return TRUE; }
Modified: trunk/reactos/subsystems/mvdm/ntvdm/clock.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/clock... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/clock.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/clock.c [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -14,12 +14,13 @@ #include "emulator.h" #include "cpu/cpu.h"
-// #include "clock.h" +#include "clock.h"
#include "hardware/cmos.h" #include "hardware/ps2.h" #include "hardware/pit.h" #include "hardware/video/vga.h" +#include "hardware/mouse.h"
/* Extra PSDK/NDK Headers */ #include <ndk/kefuncs.h> @@ -28,8 +29,7 @@
/* * Activate IPS_DISPLAY if you want to display the - * number of instructions per second, as well as - * the computed number of ticks for the PIT. + * number of instructions per second. */ // #define IPS_DISPLAY
@@ -38,27 +38,27 @@ */ // #define WORKING_TIMER
- /* Processor speed */ #define STEPS_PER_CYCLE 256 -#define IRQ1_CYCLES 16 -#define IRQ12_CYCLES 16
/* VARIABLES ******************************************************************/
+static LIST_ENTRY Timers; static LARGE_INTEGER StartPerfCount, Frequency; - -static LARGE_INTEGER LastTimerTick, LastRtcTick, Counter; -static LONGLONG TimerTicks; -static DWORD StartTickCount, CurrentTickCount; -static DWORD LastClockUpdate; -static DWORD LastVerticalRefresh; - -static DWORD LastIrq1Tick = 0, LastIrq12Tick = 0; - -#ifdef IPS_DISPLAY - static DWORD LastCyclePrintout; - static ULONGLONG Cycles = 0; +static DWORD StartTickCount; + +#ifdef IPS_DISPLAY +static ULONGLONG Cycles = 0ULL; +#endif + +/* PRIVATE FUNCTIONS **********************************************************/ + +#ifdef IPS_DISPLAY +static VOID FASTCALL IpsDisplayCallback(ULONGLONG ElapsedTime) +{ + DPRINT1("NTVDM: %I64u Instructions Per Second\n", Cycles / ElapsedTime); + Cycles = 0ULL; +} #endif
/* PUBLIC FUNCTIONS ***********************************************************/ @@ -67,112 +67,159 @@ { extern BOOLEAN CpuRunning; UINT i; - // LARGE_INTEGER Counter; + PLIST_ENTRY Entry; + LARGE_INTEGER Counter; + + while (VdmRunning && CpuRunning) + { + /* Get the current number of ticks */ + DWORD CurrentTickCount = GetTickCount();
#ifdef WORKING_TIMER - DWORD PitResolution; -#endif - DWORD RtcFrequency; - - while (VdmRunning && CpuRunning) - { - -#ifdef WORKING_TIMER - PitResolution = PitGetResolution(); -#endif - RtcFrequency = RtcGetTicksPerSecond(); - - /* Get the current number of ticks */ - CurrentTickCount = GetTickCount(); - -#ifdef WORKING_TIMER - if ((PitResolution <= 1000) && (RtcFrequency <= 1000)) - { - /* Calculate the approximate performance counter value instead */ - Counter.QuadPart = StartPerfCount.QuadPart - + (CurrentTickCount - StartTickCount) - * (Frequency.QuadPart / 1000); + if ((PitResolution <= 1000) && (RtcFrequency <= 1000)) + { + /* Calculate the approximate performance counter value instead */ + Counter.QuadPart = StartPerfCount.QuadPart + + ((CurrentTickCount - StartTickCount) + * Frequency.QuadPart) / 1000; + } + else +#endif + { + /* Get the current performance counter value */ + /// DWORD_PTR oldmask = SetThreadAffinityMask(GetCurrentThread(), 0); + NtQueryPerformanceCounter(&Counter, NULL); + /// SetThreadAffinityMask(GetCurrentThread(), oldmask); + } + + /* Continue CPU emulation */ + for (i = 0; VdmRunning && CpuRunning && (i < STEPS_PER_CYCLE); i++) + { + CpuStep(); + +#ifdef IPS_DISPLAY + ++Cycles; +#endif + } + + for (Entry = Timers.Flink; Entry != &Timers; Entry = Entry->Flink) + { + ULONGLONG Ticks = (ULONGLONG)-1; + PHARDWARE_TIMER Timer = CONTAINING_RECORD(Entry, HARDWARE_TIMER, Link); + + ASSERT((Timer->EnableCount > 0) && (Timer->Flags & HARDWARE_TIMER_ENABLED)); + + if (Timer->Delay) + { + if (Timer->Flags & HARDWARE_TIMER_PRECISE) + { + /* Use the performance counter for precise timers */ + if (Counter.QuadPart <= Timer->LastTick.QuadPart) continue; + Ticks = (Counter.QuadPart - Timer->LastTick.QuadPart) / Timer->Delay; + } + else + { + /* Use the regular tick count for normal timers */ + if (CurrentTickCount <= Timer->LastTick.LowPart) continue; + Ticks = (CurrentTickCount - Timer->LastTick.LowPart) / (ULONG)Timer->Delay; + } + + if (Ticks == 0) continue; + } + + Timer->Callback(Ticks); + + if (Timer->Flags & HARDWARE_TIMER_ONESHOT) + { + /* Disable this timer */ + DisableHardwareTimer(Timer); + } + + /* Update the time of the last timer tick */ + Timer->LastTick.QuadPart += Ticks * Timer->Delay; + } + } +} + +PHARDWARE_TIMER CreateHardwareTimer(ULONG Flags, ULONG Delay, PHARDWARE_TIMER_PROC Callback) +{ + PHARDWARE_TIMER Timer; + + Timer = (PHARDWARE_TIMER)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(HARDWARE_TIMER)); + if (Timer == NULL) return NULL; + + Timer->Flags = Flags & ~HARDWARE_TIMER_ENABLED; + Timer->EnableCount = 0; + Timer->Callback = Callback; + SetHardwareTimerDelay(Timer, (ULONGLONG)Delay); + + if (Flags & HARDWARE_TIMER_ENABLED) EnableHardwareTimer(Timer); + return Timer; +} + +VOID EnableHardwareTimer(PHARDWARE_TIMER Timer) +{ + /* Increment the count */ + Timer->EnableCount++; + + /* Check if the count is above 0 but the timer isn't enabled */ + if ((Timer->EnableCount > 0) && !(Timer->Flags & HARDWARE_TIMER_ENABLED)) + { + if (Timer->Flags & HARDWARE_TIMER_PRECISE) + { + NtQueryPerformanceCounter(&Timer->LastTick, NULL); + } + else + { + Timer->LastTick.LowPart = GetTickCount(); + } + + Timer->Flags |= HARDWARE_TIMER_ENABLED; + InsertTailList(&Timers, &Timer->Link); + } +} + +VOID DisableHardwareTimer(PHARDWARE_TIMER Timer) +{ + /* Decrement the count */ + Timer->EnableCount--; + + /* Check if the count is 0 or less but the timer is enabled */ + if ((Timer->EnableCount <= 0) && (Timer->Flags & HARDWARE_TIMER_ENABLED)) + { + /* Disable the timer */ + Timer->Flags &= ~HARDWARE_TIMER_ENABLED; + RemoveEntryList(&Timer->Link); + } +} + +VOID SetHardwareTimerDelay(PHARDWARE_TIMER Timer, ULONGLONG NewDelay) +{ + if (Timer->Flags & HARDWARE_TIMER_PRECISE) + { + /* Convert the delay from nanoseconds to performance counter ticks */ + Timer->Delay = (NewDelay * Frequency.QuadPart + 500000000ULL) / 1000000000ULL; } else -#endif - { - /* Get the current performance counter value */ - /// DWORD_PTR oldmask = SetThreadAffinityMask(GetCurrentThread(), 0); - NtQueryPerformanceCounter(&Counter, NULL); - /// SetThreadAffinityMask(GetCurrentThread(), oldmask); - } - - /* Get the number of PIT ticks that have passed */ - TimerTicks = ((Counter.QuadPart - LastTimerTick.QuadPart) - * PIT_BASE_FREQUENCY) / Frequency.QuadPart; - - /* Update the PIT */ - if (TimerTicks > 0) - { - PitClock(TimerTicks); - LastTimerTick = Counter; - } - - /* Check for RTC update */ - if ((CurrentTickCount - LastClockUpdate) >= 1000) - { - RtcTimeUpdate(); - LastClockUpdate = CurrentTickCount; - } - - /* Check for RTC periodic tick */ - if ((Counter.QuadPart - LastRtcTick.QuadPart) - >= (Frequency.QuadPart / (LONGLONG)RtcFrequency)) - { - RtcPeriodicTick(); - LastRtcTick = Counter; - } - - /* Check for vertical retrace */ - if ((CurrentTickCount - LastVerticalRefresh) >= 15) - { - VgaRefreshDisplay(); - LastVerticalRefresh = CurrentTickCount; - } - - if ((CurrentTickCount - LastIrq1Tick) >= IRQ1_CYCLES) - { - GenerateIrq1(); - LastIrq1Tick = CurrentTickCount; - } - - if ((CurrentTickCount - LastIrq12Tick) >= IRQ12_CYCLES) - { - GenerateIrq12(); - LastIrq12Tick = CurrentTickCount; - } - - /* Horizontal retrace occurs as fast as possible */ - VgaHorizontalRetrace(); - - /* Continue CPU emulation */ - for (i = 0; VdmRunning && CpuRunning && (i < STEPS_PER_CYCLE); i++) - { - CpuStep(); -#ifdef IPS_DISPLAY - ++Cycles; -#endif - } - -#ifdef IPS_DISPLAY - if ((CurrentTickCount - LastCyclePrintout) >= 1000) - { - DPRINT1("NTVDM: %I64u Instructions Per Second; TimerTicks = %I64d\n", Cycles * 1000 / (CurrentTickCount - LastCyclePrintout), TimerTicks); - LastCyclePrintout = CurrentTickCount; - Cycles = 0; - } -#endif - - } + { + Timer->Delay = NewDelay; + } +} + +VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer) +{ + if (Timer->Flags & HARDWARE_TIMER_ENABLED) RemoveEntryList(&Timer->Link); + RtlFreeHeap(RtlGetProcessHeap(), 0, Timer); }
BOOLEAN ClockInitialize(VOID) { +#ifdef IPS_DISPLAY + PHARDWARE_TIMER IpsTimer; +#endif + + InitializeListHead(&Timers); + /* Initialize the performance counter (needed for hardware timers) */ /* Find the starting performance */ NtQueryPerformanceCounter(&StartPerfCount, &Frequency); @@ -185,15 +232,16 @@ /* Find the starting tick count */ StartTickCount = GetTickCount();
- /* Set the different last counts to the starting count */ - LastClockUpdate = LastVerticalRefresh = -#ifdef IPS_DISPLAY - LastCyclePrintout = -#endif - StartTickCount; - - /* Set the last timer ticks to the current time */ - LastTimerTick = LastRtcTick = StartPerfCount; +#ifdef IPS_DISPLAY + + IpsTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, 1000, IpsDisplayCallback); + if (IpsTimer == NULL) + { + wprintf(L"FATAL: Cannot create IPS display timer.\n"); + return FALSE; + } + +#endif
return TRUE; }
Modified: trunk/reactos/subsystems/mvdm/ntvdm/clock.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/clock... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/clock.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/clock.h [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -10,7 +10,38 @@ #ifndef _CLOCK_H_ #define _CLOCK_H_
+#include <ndk/rtlfuncs.h> + +/* DEFINITIONS ****************************************************************/ + +#define HARDWARE_TIMER_ENABLED (1 << 0) +#define HARDWARE_TIMER_ONESHOT (1 << 1) +#define HARDWARE_TIMER_PRECISE (1 << 2) + +typedef VOID (FASTCALL *PHARDWARE_TIMER_PROC)(ULONGLONG ElapsedTime); + +typedef struct _HARDWARE_TIMER +{ + LIST_ENTRY Link; + ULONG Flags; + LONG EnableCount; + ULONGLONG Delay; + PHARDWARE_TIMER_PROC Callback; + LARGE_INTEGER LastTick; +} HARDWARE_TIMER, *PHARDWARE_TIMER; + /* FUNCTIONS ******************************************************************/ + +PHARDWARE_TIMER CreateHardwareTimer +( + ULONG Flags, + ULONG Delay, /* milliseconds for normal timers, nanoseconds for precise timers */ + PHARDWARE_TIMER_PROC Callback +); +VOID EnableHardwareTimer(PHARDWARE_TIMER Timer); +VOID DisableHardwareTimer(PHARDWARE_TIMER Timer); +VOID SetHardwareTimerDelay(PHARDWARE_TIMER Timer, ULONGLONG NewDelay); +VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer);
VOID ClockUpdate(VOID); BOOLEAN ClockInitialize(VOID);
Modified: trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/cpu/c... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.h [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -54,6 +54,8 @@ EMULATOR_EXCEPTION_PAGE_FAULT }; #endif + +extern BOOLEAN CpuRunning; extern FAST486_STATE EmulatorContext;
/* FUNCTIONS ******************************************************************/
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -423,7 +423,7 @@ RegisterBop(BOP_START_DOS, NULL);
/* Load the mouse driver */ - // DosMouseInitialize(); + DosMouseInitialize();
#ifndef STANDALONE
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/m... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -13,36 +13,45 @@ #include "emulator.h" #include "cpu/cpu.h" #include "int32.h" +#include "hardware/mouse.h" +#include "hardware/ps2.h" +#include "hardware/pic.h" +#include "hardware/video/vga.h"
#include "mouse32.h" #include "bios/bios.h" +#include "bios/bios32/bios32p.h"
#include "io.h" #include "dos32krnl/dos.h"
/* PRIVATE VARIABLES **********************************************************/
-static BOOLEAN DriverEnabled = TRUE; +#define MICKEYS_PER_CELL_HORIZ 8 +#define MICKEYS_PER_CELL_VERT 16 + +static MOUSE_PACKET Packet; +static INT ByteCounter = 0; +static BOOLEAN DriverEnabled = FALSE; static MOUSE_DRIVER_STATE DriverState; - -/**/ -COORD DosNewPosition; -WORD DosButtonState; -/**/ +static DWORD OldIrqHandler;
/* PRIVATE FUNCTIONS **********************************************************/
+extern VOID WINAPI BiosMouseIrq(LPWORD Stack); + static VOID PaintMouseCursor(VOID) { if (Bda->VideoMode <= 3) { WORD Character; + WORD CellX = DriverState.Position.X / 8; + WORD CellY = DriverState.Position.Y / 8; DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize);
EmulatorReadMemory(&EmulatorContext, VideoAddress - + (DriverState.Position.Y * Bda->ScreenColumns - + DriverState.Position.X) * sizeof(WORD), + + (CellY * Bda->ScreenColumns + CellX) * sizeof(WORD), (LPVOID)&Character, sizeof(WORD));
@@ -52,8 +61,7 @@
EmulatorWriteMemory(&EmulatorContext, VideoAddress - + (DriverState.Position.Y * Bda->ScreenColumns - + DriverState.Position.X) * sizeof(WORD), + + (CellY * Bda->ScreenColumns + CellX) * sizeof(WORD), (LPVOID)&Character, sizeof(WORD)); } @@ -68,12 +76,13 @@ { if (Bda->VideoMode <= 3) { + WORD CellX = DriverState.Position.X / 8; + WORD CellY = DriverState.Position.Y / 8; DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize);
EmulatorWriteMemory(&EmulatorContext, VideoAddress - + (DriverState.Position.Y * Bda->ScreenColumns - + DriverState.Position.X) * sizeof(WORD), + + (CellY * Bda->ScreenColumns + CellX) * sizeof(WORD), (LPVOID)&DriverState.Character, sizeof(WORD)); } @@ -84,10 +93,45 @@ } }
+static VOID ToMouseCoordinates(PCOORD Position) +{ + COORD Resolution = VgaGetDisplayResolution(); + WORD Width = DriverState.MaxX - DriverState.MinX + 1; + WORD Height = DriverState.MaxY - DriverState.MinY + 1; + + if (!VgaGetDoubleVisionState(NULL, NULL)) + { + Resolution.X *= 8; + Resolution.Y *= 8; + } + + Position->X = DriverState.MinX + ((Position->X * Width) / Resolution.X); + Position->Y = DriverState.MinY + ((Position->Y * Height) / Resolution.Y); +} + +static VOID FromMouseCoordinates(PCOORD Position) +{ + COORD Resolution = VgaGetDisplayResolution(); + WORD Width = DriverState.MaxX - DriverState.MinX + 1; + WORD Height = DriverState.MaxY - DriverState.MinY + 1; + + if (!VgaGetDoubleVisionState(NULL, NULL)) + { + Resolution.X *= 8; + Resolution.Y *= 8; + } + + Position->X = (((Position->X - DriverState.MinX) * Resolution.X) / Width); + Position->Y = (((Position->Y - DriverState.MinY) * Resolution.Y) / Height); +} + static VOID CallMouseUserHandlers(USHORT CallMask) { USHORT i; USHORT AX, BX, CX, DX, SI, DI; + COORD Position = DriverState.Position; + + ToMouseCoordinates(&Position);
/* Call handler 0 */ if ((DriverState.Handler0.CallMask & CallMask) != 0 && @@ -108,10 +152,10 @@
setAX(CallMask); setBX(DriverState.ButtonState); - setCX(DriverState.Position.X); - setDX(DriverState.Position.Y); - setSI(DriverState.MickeysPerCellHoriz); - setDI(DriverState.MickeysPerCellVert); + setCX(Position.X); + setDX(Position.Y); + setSI(MICKEYS_PER_CELL_HORIZ); + setDI(MICKEYS_PER_CELL_VERT);
DPRINT("Calling Handler0 %04X:%04X with CallMask 0x%04X\n", HIWORD(DriverState.Handler0.Callback), @@ -150,10 +194,10 @@
setAX(CallMask); setBX(DriverState.ButtonState); - setCX(DriverState.Position.X); - setDX(DriverState.Position.Y); - setSI(DriverState.MickeysPerCellHoriz); - setDI(DriverState.MickeysPerCellVert); + setCX(Position.X); + setDX(Position.Y); + setSI(MICKEYS_PER_CELL_HORIZ); + setDI(MICKEYS_PER_CELL_VERT);
DPRINT1("Calling Handler[%d] %04X:%04X with CallMask 0x%04X\n", i, @@ -174,6 +218,127 @@ } }
+static inline VOID DosUpdatePosition(PCOORD NewPosition) +{ + COORD Resolution = VgaGetDisplayResolution(); + + /* Check for text mode */ + if (!VgaGetDoubleVisionState(NULL, NULL)) + { + Resolution.X *= 8; + Resolution.Y *= 8; + } + + if (DriverState.ShowCount > 0) EraseMouseCursor(); + DriverState.Position = *NewPosition; + + /* Apply the clipping rectangle */ + if (DriverState.Position.X < DriverState.MinX) DriverState.Position.X = DriverState.MinX; + if (DriverState.Position.X > DriverState.MaxX) DriverState.Position.X = DriverState.MaxX; + if (DriverState.Position.Y < DriverState.MinY) DriverState.Position.Y = DriverState.MinY; + if (DriverState.Position.Y > DriverState.MaxY) DriverState.Position.Y = DriverState.MaxY; + + if (DriverState.ShowCount > 0) PaintMouseCursor(); + + /* Call the mouse handlers */ + CallMouseUserHandlers(0x0001); // We use MS MOUSE v1.0+ format +} + +static inline VOID DosUpdateButtons(BYTE ButtonState) +{ + USHORT i; + USHORT CallMask = 0x0000; // We use MS MOUSE v1.0+ format + + for (i = 0; i < NUM_MOUSE_BUTTONS; i++) + { + BOOLEAN OldState = (DriverState.ButtonState >> i) & 1; + BOOLEAN NewState = (ButtonState >> i) & 1; + + if (NewState > OldState) + { + /* 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); +} + +static VOID WINAPI DosMouseIrq(LPWORD Stack) +{ + COORD Position; + BYTE ButtonState; + + switch (ByteCounter) + { + case 0: + { + Packet.Flags = IOReadB(PS2_DATA_PORT); + break; + } + + case 1: + { + Packet.HorzCounter = IOReadB(PS2_DATA_PORT); + break; + } + + case 2: + { + Packet.VertCounter = IOReadB(PS2_DATA_PORT); + break; + } + + default: + { + /* Shouldn't happen */ + ASSERT(FALSE); + } + } + + if (++ByteCounter == 3) + { + SHORT DeltaX = Packet.HorzCounter; + SHORT DeltaY = Packet.VertCounter; + + /* Adjust the sign */ + if (Packet.Flags & MOUSE_X_SIGN) DeltaX = -DeltaX; + if (Packet.Flags & MOUSE_Y_SIGN) DeltaY = -DeltaY; + + DriverState.HorizCount += DeltaX; + DriverState.VertCount += DeltaY; + + ByteCounter = 0; + } + + /* + * Get the absolute position directly from the mouse, this is the only + * way to perfectly synchronize the host and guest mouse pointer. + */ + MouseGetDataFast(&Position, &ButtonState); + + /* Call the update subroutines */ + DosUpdatePosition(&Position); + DosUpdateButtons(ButtonState); + + /* Complete the IRQ */ + PicIRQComplete(Stack); +} + static VOID WINAPI DosMouseService(LPWORD Stack) { switch (getAX()) @@ -183,9 +348,14 @@ { SHORT i;
- DriverEnabled = TRUE; DriverState.ShowCount = 0; DriverState.ButtonState = 0; + + /* Initialize the default clipping range */ + DriverState.MinX = 0; + DriverState.MaxX = MOUSE_MAX_HORIZ - 1; + DriverState.MinY = 0; + DriverState.MaxY = MOUSE_MAX_VERT - 1;
/* Set the default text cursor */ DriverState.TextCursor.ScreenMask = 0xFFFF; /* Display everything */ @@ -237,10 +407,6 @@ DriverState.PressCount[i] = DriverState.ReleaseCount[i] = 0; }
- /* Initialize the resolution */ - DriverState.MickeysPerCellHoriz = 8; - DriverState.MickeysPerCellVert = 16; - /* Return mouse information */ setAX(0xFFFF); // Hardware & driver installed setBX(NUM_MOUSE_BUTTONS); @@ -252,7 +418,7 @@ case 0x01: { DriverState.ShowCount++; - if (DriverState.ShowCount > 0) PaintMouseCursor(); + if (DriverState.ShowCount == 1) PaintMouseCursor();
break; } @@ -261,7 +427,7 @@ case 0x02: { DriverState.ShowCount--; - if (DriverState.ShowCount <= 0) EraseMouseCursor(); + if (DriverState.ShowCount == 0) EraseMouseCursor();
break; } @@ -269,23 +435,22 @@ /* Return Position And Button Status */ case 0x03: { + COORD Position = DriverState.Position; + ToMouseCoordinates(&Position); + setBX(DriverState.ButtonState); - setCX(DriverState.Position.X); - setDX(DriverState.Position.Y); + setCX(Position.X); + setDX(Position.Y); break; }
/* Position Mouse Cursor */ case 0x04: { - POINT Point; - - Point.x = getCX(); - Point.y = getDX(); - - ClientToScreen(GetConsoleWindow(), &Point); - SetCursorPos(Point.x, Point.y); - + COORD Position = { getCX(), getDX() }; + FromMouseCoordinates(&Position); + + DriverState.Position = Position; break; }
@@ -293,11 +458,13 @@ case 0x05: { WORD Button = getBX(); + COORD LastPress = DriverState.LastPress[Button]; + ToMouseCoordinates(&LastPress);
setAX(DriverState.ButtonState); setBX(DriverState.PressCount[Button]); - setCX(DriverState.LastPress[Button].X); - setDX(DriverState.LastPress[Button].Y); + setCX(LastPress.X); + setDX(LastPress.Y);
/* Reset the counter */ DriverState.PressCount[Button] = 0; @@ -309,17 +476,37 @@ case 0x06: { WORD Button = getBX(); + COORD LastRelease = DriverState.LastRelease[Button]; + ToMouseCoordinates(&LastRelease);
setAX(DriverState.ButtonState); setBX(DriverState.ReleaseCount[Button]); - setCX(DriverState.LastRelease[Button].X); - setDX(DriverState.LastRelease[Button].Y); + setCX(LastRelease.X); + setDX(LastRelease.Y);
/* Reset the counter */ DriverState.ReleaseCount[Button] = 0;
break;
+ } + + /* Define Horizontal Cursor Range */ + case 0x07: + { + DPRINT("Setting mouse horizontal range: %u - %u\n", getCX(), getDX()); + DriverState.MinX = getCX(); + DriverState.MaxX = getDX(); + break; + } + + /* Define Vertical Cursor Range */ + case 0x08: + { + DPRINT("Setting mouse vertical range: %u - %u\n", getCX(), getDX()); + DriverState.MinY = getCX(); + DriverState.MaxY = getDX(); + break; }
/* Define Graphics Cursor */ @@ -395,8 +582,7 @@ /* Define Mickey/Pixel Ratio */ case 0x0F: { - DriverState.MickeysPerCellHoriz = getCX(); - DriverState.MickeysPerCellVert = getDX(); + /* This call should be completely ignored */ break; }
@@ -588,14 +774,14 @@ setES(0x0000); setBX(0x0000);
- DriverEnabled = FALSE; + DosMouseDisable(); break; }
/* Enable Mouse Driver */ case 0x20: { - DriverEnabled = TRUE; + DosMouseEnable(); break; }
@@ -607,6 +793,38 @@ }
/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID DosMouseEnable(VOID) +{ + if (!DriverEnabled) + { + DriverEnabled = TRUE; + + /* Get the old IRQ handler */ + OldIrqHandler = ((PDWORD)BaseAddress)[MOUSE_IRQ_INT]; + + /* Set the IRQ handler */ + RegisterDosInt32(MOUSE_IRQ_INT, DosMouseIrq); + + /* Enable packet reporting */ + IOWriteB(PS2_CONTROL_PORT, 0xD4); + IOWriteB(PS2_DATA_PORT, 0xF4); + + /* Read the mouse ACK reply */ + PS2PortQueueRead(1); + } +} + +VOID DosMouseDisable(VOID) +{ + if (DriverEnabled) + { + /* Restore the old IRQ handler */ + ((PDWORD)BaseAddress)[MOUSE_IRQ_INT] = OldIrqHandler; + + DriverEnabled = FALSE; + } +}
VOID DosMouseUpdatePosition(PCOORD NewPosition) { @@ -615,8 +833,8 @@
if (!DriverEnabled) return;
- DriverState.HorizCount += (DeltaX * (SHORT)DriverState.MickeysPerCellHoriz) / 8; - DriverState.VertCount += (DeltaY * (SHORT)DriverState.MickeysPerCellVert ) / 8; + DriverState.HorizCount += (DeltaX * MICKEYS_PER_CELL_HORIZ) / 8; + DriverState.VertCount += (DeltaY * MICKEYS_PER_CELL_VERT) / 8;
if (DriverState.ShowCount > 0) EraseMouseCursor(); DriverState.Position = *NewPosition; @@ -671,10 +889,12 @@ /* Initialize the interrupt handler */ RegisterDosInt32(DOS_MOUSE_INTERRUPT, DosMouseService);
+ DosMouseEnable(); return TRUE; }
VOID DosMouseCleanup(VOID) { if (DriverState.ShowCount > 0) EraseMouseCursor(); -} + DosMouseDisable(); +}
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/mouse32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/m... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/mouse32.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/mouse32.h [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -16,6 +16,9 @@ /* DEFINES ********************************************************************/
#define DOS_MOUSE_INTERRUPT 0x33 +#define MOUSE_IRQ_INT 0x74 +#define MOUSE_MAX_HORIZ 640 +#define MOUSE_MAX_VERT 200
enum { @@ -47,8 +50,7 @@ COORD LastRelease[NUM_MOUSE_BUTTONS]; SHORT HorizCount; SHORT VertCount; - WORD MickeysPerCellHoriz; - WORD MickeysPerCellVert; + WORD MinX, MaxX, MinY, MaxY;
/* * User Subroutine Handlers called on mouse events @@ -72,9 +74,8 @@
/* FUNCTIONS ******************************************************************/
-VOID DosMouseUpdatePosition(PCOORD NewPosition); -VOID DosMouseUpdateButtons(WORD ButtonStatus); - +VOID DosMouseEnable(VOID); +VOID DosMouseDisable(VOID); BOOLEAN DosMouseInitialize(VOID); VOID DosMouseCleanup(VOID);
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -15,6 +15,7 @@
#include "io.h" #include "pic.h" +#include "clock.h"
/* PRIVATE VARIABLES **********************************************************/
@@ -24,14 +25,82 @@ static BOOLEAN NmiEnabled = TRUE; static CMOS_REGISTERS SelectedRegister = CMOS_REG_STATUS_D;
-/* PUBLIC FUNCTIONS ***********************************************************/ - -BOOLEAN IsNmiEnabled(VOID) -{ - return NmiEnabled; -} - -VOID CmosWriteAddress(BYTE Value) +static PHARDWARE_TIMER ClockTimer; +static PHARDWARE_TIMER PeriodicTimer; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static VOID RtcUpdatePeriodicTimer(VOID) +{ + BYTE RateSelect = CmosMemory.StatusRegA & 0x0F; + + if (RateSelect == 0) + { + /* No periodic interrupt */ + DisableHardwareTimer(PeriodicTimer); + return; + } + + /* 1 and 2 act like 8 and 9 */ + if (RateSelect <= 2) RateSelect += 7; + + SetHardwareTimerDelay(PeriodicTimer, 1000000000ULL / (ULONGLONG)(1 << (16 - RateSelect))); + EnableHardwareTimer(PeriodicTimer); +} + +static VOID FASTCALL RtcPeriodicTick(ULONGLONG ElapsedTime) +{ + UNREFERENCED_PARAMETER(ElapsedTime); + + /* Set PF */ + CmosMemory.StatusRegC |= CMOS_STC_PF; + + /* Check if there should be an interrupt on a periodic timer tick */ + if (CmosMemory.StatusRegB & CMOS_STB_INT_PERIODIC) + { + CmosMemory.StatusRegC |= CMOS_STC_IRQF; + + /* Interrupt! */ + PicInterruptRequest(RTC_IRQ_NUMBER); + } +} + +/* Should be called every second */ +static VOID FASTCALL RtcTimeUpdate(ULONGLONG ElapsedTime) +{ + SYSTEMTIME CurrentTime; + + UNREFERENCED_PARAMETER(ElapsedTime); + + /* Get the current time */ + GetLocalTime(&CurrentTime); + + /* Set UF */ + CmosMemory.StatusRegC |= CMOS_STC_UF; + + /* Check if the time matches the alarm time */ + if ((CurrentTime.wHour == CmosMemory.AlarmHour ) && + (CurrentTime.wMinute == CmosMemory.AlarmMinute) && + (CurrentTime.wSecond == CmosMemory.AlarmSecond)) + { + /* Set the alarm flag */ + CmosMemory.StatusRegC |= CMOS_STC_AF; + + /* Set IRQF if there should be an interrupt */ + if (CmosMemory.StatusRegB & CMOS_STB_INT_ON_ALARM) CmosMemory.StatusRegC |= CMOS_STC_IRQF; + } + + /* Check if there should be an interrupt on update */ + if (CmosMemory.StatusRegB & CMOS_STB_INT_ON_UPDATE) CmosMemory.StatusRegC |= CMOS_STC_IRQF; + + if (CmosMemory.StatusRegC & CMOS_STC_IRQF) + { + /* Interrupt! */ + PicInterruptRequest(RTC_IRQ_NUMBER); + } +} + +static VOID CmosWriteAddress(BYTE Value) { /* Update the NMI enabled flag */ NmiEnabled = !(Value & CMOS_DISABLE_NMI); @@ -51,7 +120,7 @@ } }
-BYTE CmosReadData(VOID) +static BYTE CmosReadData(VOID) { BYTE Value; SYSTEMTIME CurrentTime; @@ -181,7 +250,7 @@ return Value; }
-VOID CmosWriteData(BYTE Value) +static VOID CmosWriteData(BYTE Value) { BOOLEAN ChangeTime = FALSE; SYSTEMTIME CurrentTime; @@ -296,6 +365,7 @@ case CMOS_REG_STATUS_A: { CmosMemory.StatusRegA = Value & 0x7F; // Bit 7 is read-only + RtcUpdatePeriodicTimer(); break; }
@@ -342,13 +412,13 @@ SelectedRegister = CMOS_REG_STATUS_D; }
-BYTE WINAPI CmosReadPort(USHORT Port) +static BYTE WINAPI CmosReadPort(USHORT Port) { ASSERT(Port == CMOS_DATA_PORT); return CmosReadData(); }
-VOID WINAPI CmosWritePort(USHORT Port, BYTE Data) +static VOID WINAPI CmosWritePort(USHORT Port, BYTE Data) { if (Port == CMOS_ADDRESS_PORT) CmosWriteAddress(Data); @@ -356,68 +426,12 @@ CmosWriteData(Data); }
-DWORD RtcGetTicksPerSecond(VOID) -{ - BYTE RateSelect = CmosMemory.StatusRegB & 0x0F; - - if (RateSelect == 0) - { - /* No periodic interrupt */ - return 0; - } - - /* 1 and 2 act like 8 and 9 */ - if (RateSelect <= 2) RateSelect += 7; - - return 1 << (16 - RateSelect); -} - -VOID RtcPeriodicTick(VOID) -{ - /* Set PF */ - CmosMemory.StatusRegC |= CMOS_STC_PF; - - /* Check if there should be an interrupt on a periodic timer tick */ - if (CmosMemory.StatusRegB & CMOS_STB_INT_PERIODIC) - { - CmosMemory.StatusRegC |= CMOS_STC_IRQF; - - /* Interrupt! */ - PicInterruptRequest(RTC_IRQ_NUMBER); - } -} - -/* Should be called every second */ -VOID RtcTimeUpdate(VOID) -{ - SYSTEMTIME CurrentTime; - - /* Get the current time */ - GetLocalTime(&CurrentTime); - - /* Set UF */ - CmosMemory.StatusRegC |= CMOS_STC_UF; - - /* Check if the time matches the alarm time */ - if ((CurrentTime.wHour == CmosMemory.AlarmHour ) && - (CurrentTime.wMinute == CmosMemory.AlarmMinute) && - (CurrentTime.wSecond == CmosMemory.AlarmSecond)) - { - /* Set the alarm flag */ - CmosMemory.StatusRegC |= CMOS_STC_AF; - - /* Set IRQF if there should be an interrupt */ - if (CmosMemory.StatusRegB & CMOS_STB_INT_ON_ALARM) CmosMemory.StatusRegC |= CMOS_STC_IRQF; - } - - /* Check if there should be an interrupt on update */ - if (CmosMemory.StatusRegB & CMOS_STB_INT_ON_UPDATE) CmosMemory.StatusRegC |= CMOS_STC_IRQF; - - if (CmosMemory.StatusRegC & CMOS_STC_IRQF) - { - /* Interrupt! */ - PicInterruptRequest(RTC_IRQ_NUMBER); - } + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN IsNmiEnabled(VOID) +{ + return NmiEnabled; }
VOID CmosInitialize(VOID) @@ -486,6 +500,11 @@ /* Register the I/O Ports */ RegisterIoPort(CMOS_ADDRESS_PORT, NULL , CmosWritePort); RegisterIoPort(CMOS_DATA_PORT , CmosReadPort, CmosWritePort); + + ClockTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, 1000, RtcTimeUpdate); + PeriodicTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED | HARDWARE_TIMER_PRECISE, + 1000000, /* 1,000,000 ns = 1 ms */ + RtcPeriodicTick); }
VOID CmosCleanup(VOID) @@ -493,6 +512,9 @@ DWORD CmosSize = sizeof(CmosMemory);
if (hCmosRam == INVALID_HANDLE_VALUE) return; + + DestroyHardwareTimer(PeriodicTimer); + DestroyHardwareTimer(ClockTimer);
/* Flush the CMOS memory back to the RAM file and close it */ SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN);
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.h [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -128,8 +128,6 @@
BOOLEAN IsNmiEnabled(VOID); DWORD RtcGetTicksPerSecond(VOID); -VOID RtcPeriodicTick(VOID); -VOID RtcTimeUpdate(VOID);
VOID CmosInitialize(VOID); VOID CmosCleanup(VOID);
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/mouse.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/mouse.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/mouse.c [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -12,31 +12,43 @@
#include "mouse.h" #include "ps2.h" -// #include "pic.h" +#include "clock.h" +#include "video/vga.h"
/* PRIVATE VARIABLES **********************************************************/
+static const BYTE ScrollMagic[3] = { 200, 100, 80 }; +static const BYTE ExtraButtonMagic[3] = { 200, 200, 80 }; + +static HANDLE MouseMutex; +static PHARDWARE_TIMER StreamTimer; +static MOUSE_PACKET LastPacket; static MOUSE_MODE Mode, PreviousMode; static COORD Position; -static ULONG WidthMm, HeightMm, WidthPixels, HeightPixels; -static ULONG SampleRate; -static ULONG Resolution; -static BOOLEAN Scaling; +static BYTE Resolution; /* Completely ignored */ +static BOOLEAN Scaling; /* Completely ignored */ static BOOLEAN Reporting; static BYTE MouseId; static ULONG ButtonState; static SHORT HorzCounter; static SHORT VertCounter; static CHAR ScrollCounter; +static BOOLEAN EventsOccurred = FALSE; +static BYTE DataByteWait = 0; +static BYTE ScrollMagicCounter = 0, ExtraButtonMagicCounter = 0;
static BYTE PS2Port = 1;
+/* PUBLIC VARIABLES ***********************************************************/ + +UINT MouseCycles = 10; + /* PRIVATE FUNCTIONS **********************************************************/
static VOID MouseResetConfig(VOID) { /* Reset the configuration to defaults */ - SampleRate = 100; + MouseCycles = 10; Resolution = 4; Scaling = FALSE; Reporting = FALSE; @@ -45,7 +57,7 @@ static VOID MouseResetCounters(VOID) { /* Reset all flags and counters */ - ButtonState = HorzCounter = VertCounter = ScrollCounter = 0; + HorzCounter = VertCounter = ScrollCounter = 0; }
static VOID MouseReset(VOID) @@ -57,41 +69,49 @@ /* Enter streaming mode and the reset the mouse ID */ Mode = MOUSE_STREAMING_MODE; MouseId = 0; + ScrollMagicCounter = ExtraButtonMagicCounter = 0;
/* Send the Basic Assurance Test success code and the device ID */ PS2QueuePush(PS2Port, MOUSE_BAT_SUCCESS); PS2QueuePush(PS2Port, MouseId); }
-#if 0 static VOID MouseGetPacket(PMOUSE_PACKET Packet) { /* Clear the packet */ RtlZeroMemory(Packet, sizeof(*Packet));
+ /* Acquire the mutex */ + WaitForSingleObject(MouseMutex, INFINITE); + Packet->Flags |= MOUSE_ALWAYS_SET;
+ /* Set the sign flags */ + if (HorzCounter < 0) + { + Packet->Flags |= MOUSE_X_SIGN; + HorzCounter = -HorzCounter; + } + + if (VertCounter < 0) + { + Packet->Flags |= MOUSE_Y_SIGN; + VertCounter = -VertCounter; + } + /* Check for horizontal overflows */ - if ((HorzCounter < MOUSE_MIN) || (HorzCounter > MOUSE_MAX)) - { - if (HorzCounter > MOUSE_MAX) HorzCounter = MOUSE_MAX; - if (HorzCounter < MOUSE_MIN) HorzCounter = MOUSE_MIN; - + if (HorzCounter > MOUSE_MAX) + { + HorzCounter = MOUSE_MAX; Packet->Flags |= MOUSE_X_OVERFLOW; }
/* Check for vertical overflows */ - if ((VertCounter < MOUSE_MIN) || (VertCounter > MOUSE_MAX)) - { - if (VertCounter > MOUSE_MIN) VertCounter = MOUSE_MIN; - if (VertCounter < MOUSE_MIN) VertCounter = MOUSE_MIN; - + if (VertCounter > MOUSE_MAX) + { + VertCounter = MOUSE_MAX; Packet->Flags |= MOUSE_Y_OVERFLOW; } - - /* Set the sign flags */ - if (HorzCounter & MOUSE_SIGN_BIT) Packet->Flags |= MOUSE_X_SIGN; - if (HorzCounter & MOUSE_SIGN_BIT) Packet->Flags |= MOUSE_Y_SIGN;
/* Set the button flags */ if (ButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) Packet->Flags |= MOUSE_LEFT_BUTTON; @@ -116,36 +136,94 @@
/* Reset the counters */ MouseResetCounters(); -} -#endif - -/*static*/ VOID MouseUpdatePosition(PCOORD NewPosition) -{ - /* Update the counters */ - HorzCounter += ((NewPosition->X - Position.X) * WidthMm * Resolution) / WidthPixels; - VertCounter += ((NewPosition->Y - Position.Y) * HeightMm * Resolution) / HeightPixels; - - /* Update the position */ - Position = *NewPosition; -} - -/*static*/ VOID MouseUpdateButtons(ULONG NewButtonState) -{ - ButtonState = NewButtonState; -} - -/*static*/ VOID MouseScroll(LONG Direction) -{ - ScrollCounter += Direction; -} - -/*static*/ COORD MouseGetPosition(VOID) -{ - return Position; + + /* Release the mutex */ + ReleaseMutex(MouseMutex); +} + +static VOID MouseDispatchPacket(PMOUSE_PACKET Packet) +{ + PS2QueuePush(PS2Port, Packet->Flags); + PS2QueuePush(PS2Port, Packet->HorzCounter); + PS2QueuePush(PS2Port, Packet->VertCounter); + if (MouseId >= 3) PS2QueuePush(PS2Port, Packet->Extra); }
static VOID WINAPI MouseCommand(LPVOID Param, BYTE Command) { + /* Check if we were waiting for a data byte */ + if (DataByteWait) + { + PS2QueuePush(PS2Port, MOUSE_ACK); + + switch (DataByteWait) + { + /* Set Resolution */ + case 0xE8: + { + Resolution = Command; + break; + } + + /* Set Sample Rate */ + case 0xF3: + { + /* Check for the scroll wheel enabling sequence */ + if (MouseId == 0) + { + if (Command == ScrollMagic[ScrollMagicCounter]) + { + ScrollMagicCounter++; + if (ScrollMagicCounter == 3) MouseId = 3; + } + else + { + ScrollMagicCounter = 0; + } + } + + /* Check for the 5-button enabling sequence */ + if (MouseId == 3) + { + if (Command == ExtraButtonMagic[ExtraButtonMagicCounter]) + { + ExtraButtonMagicCounter++; + if (ExtraButtonMagicCounter == 3) MouseId = 4; + } + else + { + ExtraButtonMagicCounter = 0; + } + } + + MouseCycles = 1000 / (UINT)Command; + break; + } + + default: + { + /* Shouldn't happen */ + ASSERT(FALSE); + } + } + + DataByteWait = 0; + } + + /* Check if we're in wrap mode */ + if (Mode == MOUSE_WRAP_MODE) + { + /* + * In this mode, we just echo whatever byte we get, + * except for the 0xEC and 0xFF commands. + */ + if (Command != 0xEC && Command != 0xFF) + { + PS2QueuePush(PS2Port, Command); + return; + } + } + switch (Command) { /* Set 1:1 Scaling */ @@ -166,17 +244,27 @@
/* Set Resolution */ case 0xE8: - { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + /* Set Sample Rate */ + case 0xF3: + { + PS2QueuePush(PS2Port, MOUSE_ACK); + DataByteWait = Command; break; }
/* Read Status */ case 0xE9: { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + BYTE Status = ButtonState & 7; + PS2QueuePush(PS2Port, MOUSE_ACK); + + if (Scaling) Status |= 1 << 4; + if (Reporting) Status |= 1 << 5; + if (Mode == MOUSE_REMOTE_MODE) Status |= 1 << 6; + + PS2QueuePush(PS2Port, Status); + PS2QueuePush(PS2Port, Resolution); + PS2QueuePush(PS2Port, (BYTE)(1000 / MouseCycles)); break; }
@@ -193,8 +281,9 @@ /* Read Packet */ case 0xEB: { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + PS2QueuePush(PS2Port, MOUSE_ACK); + MouseGetPacket(&LastPacket); + MouseDispatchPacket(&LastPacket); break; }
@@ -247,14 +336,6 @@ break; }
- /* Set Sample Rate */ - case 0xF3: - { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; - break; - } - /* Enable Reporting */ case 0xF4: { @@ -283,8 +364,8 @@ /* Resend */ case 0xFE: { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + PS2QueuePush(PS2Port, MOUSE_ACK); + MouseDispatchPacket(&LastPacket); break; }
@@ -303,50 +384,77 @@ } }
+static VOID FASTCALL MouseStreamingCallback(ULONGLONG ElapsedTime) +{ + UNREFERENCED_PARAMETER(ElapsedTime); + + /* Check if we're not in streaming mode, not reporting, or there's nothing to report */ + if (Mode != MOUSE_STREAMING_MODE || !Reporting || !EventsOccurred) return; + + MouseGetPacket(&LastPacket); + MouseDispatchPacket(&LastPacket); + + EventsOccurred = FALSE; +} + /* PUBLIC FUNCTIONS ***********************************************************/
+VOID MouseGetDataFast(PCOORD CurrentPosition, PBYTE CurrentButtonState) +{ + WaitForSingleObject(MouseMutex, INFINITE); + *CurrentPosition = Position; + *CurrentButtonState = LOBYTE(ButtonState); + ReleaseMutex(MouseMutex); +} + VOID MouseEventHandler(PMOUSE_EVENT_RECORD MouseEvent) { -extern COORD DosNewPosition; -extern WORD DosButtonState; - - // FIXME: Sync our private data - MouseUpdatePosition(&MouseEvent->dwMousePosition); - MouseUpdateButtons(MouseEvent->dwButtonState); - - // HACK: Bypass PS/2 and instead, notify the MOUSE.COM driver directly - DosNewPosition = MouseEvent->dwMousePosition; - DosButtonState = LOWORD(MouseEvent->dwButtonState); - - // PS2QueuePush(PS2Port, Data); + COORD NewPosition = MouseEvent->dwMousePosition; + BOOLEAN DoubleWidth = FALSE, DoubleHeight = FALSE; + + if (!VgaGetDoubleVisionState(&DoubleWidth, &DoubleHeight)) + { + /* Text mode */ + NewPosition.X *= 8; + NewPosition.Y *= 8; + } + + /* Adjust for double vision */ + if (DoubleWidth) NewPosition.X /= 2; + if (DoubleHeight) NewPosition.Y /= 2; + + WaitForSingleObject(MouseMutex, INFINITE); + + /* Update the counters */ + HorzCounter += NewPosition.X - Position.X; + VertCounter += NewPosition.Y - Position.Y; + + /* Update the position */ + Position = NewPosition; + + /* Update the button state */ + ButtonState = MouseEvent->dwButtonState; + + if (MouseEvent->dwEventFlags & MOUSE_WHEELED) + { + ScrollCounter += (SHORT)HIWORD(MouseEvent->dwButtonState); + } + + EventsOccurred = TRUE; + ReleaseMutex(MouseMutex); }
BOOLEAN MouseInit(BYTE PS2Connector) { - HWND hWnd; - HDC hDC; - - /* Get the console window */ - hWnd = GetConsoleWindow(); - if (hWnd == NULL) return FALSE; - - /* Get the console window's device context */ - hDC = GetWindowDC(hWnd); - if (hDC == NULL) return FALSE; - - /* Get the parameters */ - WidthMm = (ULONG)GetDeviceCaps(hDC, HORZSIZE); - HeightMm = (ULONG)GetDeviceCaps(hDC, VERTSIZE); - WidthPixels = (ULONG)GetDeviceCaps(hDC, HORZRES); - HeightPixels = (ULONG)GetDeviceCaps(hDC, VERTRES); - - /* Release the device context */ - ReleaseDC(hWnd, hDC); - /* Finish to plug the mouse to the specified PS/2 port */ PS2Port = PS2Connector; PS2SetDeviceCmdProc(PS2Port, NULL, MouseCommand);
+ MouseMutex = CreateMutex(NULL, FALSE, NULL); + if (MouseMutex == NULL) return FALSE; + + StreamTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, 10, MouseStreamingCallback); + MouseReset(); return TRUE; }
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/mouse.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/mouse.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/mouse.h [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -16,9 +16,7 @@ /* DEFINES ********************************************************************/
/* Mouse packet constants */ -#define MOUSE_MIN -256 #define MOUSE_MAX 255 -#define MOUSE_SIGN_BIT (1 << 8)
/* Mouse packet flags */ #define MOUSE_LEFT_BUTTON (1 << 0) @@ -69,6 +67,7 @@ /* FUNCTIONS ******************************************************************/
VOID MouseEventHandler(PMOUSE_EVENT_RECORD MouseEvent); +VOID MouseGetDataFast(PCOORD CurrentPosition, PBYTE CurrentButtonState); BOOLEAN MouseInit(BYTE PS2Connector);
#endif // _MOUSE_H_
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/pit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/pit.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/pit.c [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -16,10 +16,12 @@ #include "io.h" #include "pit.h" #include "pic.h" +#include "clock.h"
/* PRIVATE VARIABLES **********************************************************/
static PIT_CHANNEL PitChannels[PIT_CHANNELS]; +static PHARDWARE_TIMER MasterClock;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -451,6 +453,17 @@ } }
+static VOID FASTCALL PitClock(ULONGLONG Count) +{ + UCHAR i; + + for (i = 0; i < PIT_CHANNELS; i++) + { + // if (!PitChannels[i].Counting) continue; + PitDecrementCount(&PitChannels[i], Count); + } +} + /* PUBLIC FUNCTIONS ***********************************************************/
VOID PitSetOutFunction(BYTE Channel, LPVOID Param, PIT_OUT_FUNCTION OutFunction) @@ -478,38 +491,6 @@ return 0xFFFF; else return PitChannels[Channel].ReloadValue; -} - -DWORD PitGetResolution(VOID) -{ - UCHAR i; - DWORD MinReloadValue = 65536; - - for (i = 0; i < PIT_CHANNELS; i++) - { - DWORD ReloadValue = PitChannels[i].ReloadValue; - - /* 0 means 65536 */ - if (ReloadValue == 0) ReloadValue = 65536; - - if (ReloadValue < MinReloadValue) MinReloadValue = ReloadValue; - } - - /* Return the frequency resolution */ - return PIT_BASE_FREQUENCY / MinReloadValue; -} - -VOID PitClock(DWORD Count) -{ - UCHAR i; - - if (Count == 0) return; - - for (i = 0; i < PIT_CHANNELS; i++) - { - // if (!PitChannels[i].Counting) continue; - PitDecrementCount(&PitChannels[i], Count); - } }
VOID PitInitialize(VOID) @@ -527,6 +508,11 @@ RegisterIoPort(PIT_DATA_PORT(0), PitReadPort, PitWritePort); RegisterIoPort(PIT_DATA_PORT(1), PitReadPort, PitWritePort); RegisterIoPort(PIT_DATA_PORT(2), PitReadPort, PitWritePort); + + /* Register the hardware timer */ + MasterClock = CreateHardwareTimer(HARDWARE_TIMER_ENABLED | HARDWARE_TIMER_PRECISE, + 1000000000ULL / PIT_BASE_FREQUENCY, + PitClock); }
/* EOF */
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/pit.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/pit.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/pit.h [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -79,9 +79,6 @@ VOID PitSetGate(BYTE Channel, BOOLEAN State); WORD PitGetReloadValue(BYTE Channel);
-DWORD PitGetResolution(VOID); -VOID PitClock(DWORD Count); - VOID PitInitialize(VOID);
#endif // _PIT_H_
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/ps2.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/ps2.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/ps2.c [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -15,6 +15,7 @@ #include "io.h" #include "ps2.h" #include "pic.h" +#include "clock.h"
/* PRIVATE VARIABLES **********************************************************/
@@ -48,6 +49,8 @@ static BYTE StatusRegister = 0x00; // static BYTE InputBuffer = 0x00; // PS/2 Input Buffer static BYTE OutputBuffer = 0x00; // PS/2 Output Buffer + +static PHARDWARE_TIMER IrqTimer = NULL;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -262,7 +265,30 @@ } }
-static BOOLEAN PS2PortQueueRead(BYTE PS2Port) +static VOID FASTCALL GeneratePS2Irq(ULONGLONG ElapsedTime) +{ + UNREFERENCED_PARAMETER(ElapsedTime); + + /* Generate an IRQ 1 if there is data ready in the output queue */ + if (PS2PortQueueRead(0)) + { + /* Generate an interrupt if interrupts for the first PS/2 port are enabled */ + if (ControllerConfig & 0x01) PicInterruptRequest(1); + return; + } + + /* Generate an IRQ 12 if there is data ready in the output queue */ + if (PS2PortQueueRead(1)) + { + /* Generate an interrupt if interrupts for the second PS/2 port are enabled */ + if (ControllerConfig & 0x02) PicInterruptRequest(12); + return; + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN PS2PortQueueRead(BYTE PS2Port) { BOOLEAN Result = TRUE; PPS2_PORT Port; @@ -316,8 +342,6 @@ return Result; }
-/* PUBLIC FUNCTIONS ***********************************************************/ - VOID PS2SetDeviceCmdProc(BYTE PS2Port, LPVOID Param, PS2_DEVICE_CMDPROC DeviceCommand) { if (PS2Port >= PS2_PORTS) return; @@ -354,41 +378,12 @@ /* The queue is not empty anymore */ Port->QueueEmpty = FALSE;
-/* - // Get the data - OutputBuffer = Port->Queue[Port->QueueStart]; - StatusRegister |= (1 << 0); // There is something to read - // FIXME: Sometimes StatusRegister |= (1 << 5); for the second PS/2 port - - if (PS2Port == 0) - PicInterruptRequest(1); - else if (PS2Port == 1) - PicInterruptRequest(12); -*/ + /* Schedule the IRQ */ + EnableHardwareTimer(IrqTimer);
Done: ReleaseMutex(Port->QueueMutex); return Result; -} - -VOID GenerateIrq1(VOID) -{ - /* Generate an interrupt if interrupts for the first PS/2 port are enabled */ - if (ControllerConfig & 0x01) - { - /* Generate an IRQ 1 if there is data ready in the output queue */ - if (PS2PortQueueRead(0)) PicInterruptRequest(1); - } -} - -VOID GenerateIrq12(VOID) -{ - /* Generate an interrupt if interrupts for the second PS/2 port are enabled */ - if (ControllerConfig & 0x02) - { - /* Generate an IRQ 12 if there is data ready in the output queue */ - if (PS2PortQueueRead(1)) PicInterruptRequest(12); - } }
BOOLEAN PS2Initialize(VOID) @@ -410,11 +405,15 @@ RegisterIoPort(PS2_CONTROL_PORT, PS2ReadPort, PS2WritePort); RegisterIoPort(PS2_DATA_PORT , PS2ReadPort, PS2WritePort);
+ IrqTimer = CreateHardwareTimer(HARDWARE_TIMER_ONESHOT, 20, GeneratePS2Irq); + return TRUE; }
VOID PS2Cleanup(VOID) { + DestroyHardwareTimer(IrqTimer); + CloseHandle(Ports[1].QueueMutex); CloseHandle(Ports[0].QueueMutex); }
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/ps2.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/ps2.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/ps2.h [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -26,9 +26,7 @@ VOID PS2SetDeviceCmdProc(BYTE PS2Port, LPVOID Param, PS2_DEVICE_CMDPROC DeviceCommand);
BOOLEAN PS2QueuePush(BYTE PS2Port, BYTE Data); - -VOID GenerateIrq1(VOID); -VOID GenerateIrq12(VOID); +BOOLEAN PS2PortQueueRead(BYTE PS2Port);
BOOLEAN PS2Initialize(VOID); VOID PS2Cleanup(VOID);
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -16,6 +16,7 @@
#include "memory.h" #include "io.h" +#include "clock.h"
/* PRIVATE VARIABLES **********************************************************/
@@ -245,6 +246,9 @@ static BOOLEAN DoubleWidth = FALSE; static BOOLEAN DoubleHeight = FALSE;
+static PHARDWARE_TIMER VSyncTimer; +static PHARDWARE_TIMER HSyncTimer; + /* * VGA Hardware */ @@ -1754,59 +1758,11 @@ } }
-/* PUBLIC FUNCTIONS ***********************************************************/ - -COORD VgaGetDisplayResolution(VOID) -{ - COORD Resolution; - BYTE MaximumScanLine = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F); - - /* The low 8 bits are in the display registers */ - Resolution.X = VgaCrtcRegisters[VGA_CRTC_END_HORZ_DISP_REG]; - Resolution.Y = VgaCrtcRegisters[VGA_CRTC_VERT_DISP_END_REG]; - - /* Set the top bits from the overflow register */ - if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE8) - { - Resolution.Y |= 1 << 8; - } - if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE9) - { - Resolution.Y |= 1 << 9; - } - - /* Increase the values by 1 */ - Resolution.X++; - Resolution.Y++; - - if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) - { - /* Multiply the horizontal resolution by the 9/8 dot mode */ - Resolution.X *= (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & VGA_SEQ_CLOCK_98DM) - ? 8 : 9; - - /* The horizontal resolution is halved in 8-bit mode */ - if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) Resolution.X /= 2; - } - - if (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & VGA_CRTC_MAXSCANLINE_DOUBLE) - { - /* Halve the vertical resolution */ - Resolution.Y >>= 1; - } - else - { - /* Divide the vertical resolution by the maximum scan line (== font size in text mode) */ - Resolution.Y /= MaximumScanLine; - } - - /* Return the resolution */ - return Resolution; -} - -VOID VgaRefreshDisplay(VOID) +static VOID FASTCALL VgaVerticalRetrace(ULONGLONG ElapsedTime) { HANDLE ConsoleBufferHandle = NULL; + + UNREFERENCED_PARAMETER(ElapsedTime);
/* Set the vertical retrace flag */ InVerticalRetrace = TRUE; @@ -1876,10 +1832,75 @@ NeedsUpdate = FALSE; }
-VOID VgaHorizontalRetrace(VOID) -{ +static VOID FASTCALL VgaHorizontalRetrace(ULONGLONG ElapsedTime) +{ + UNREFERENCED_PARAMETER(ElapsedTime); + /* Set the flag */ InHorizontalRetrace = TRUE; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +COORD VgaGetDisplayResolution(VOID) +{ + COORD Resolution; + BYTE MaximumScanLine = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F); + + /* The low 8 bits are in the display registers */ + Resolution.X = VgaCrtcRegisters[VGA_CRTC_END_HORZ_DISP_REG]; + Resolution.Y = VgaCrtcRegisters[VGA_CRTC_VERT_DISP_END_REG]; + + /* Set the top bits from the overflow register */ + if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE8) + { + Resolution.Y |= 1 << 8; + } + if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE9) + { + Resolution.Y |= 1 << 9; + } + + /* Increase the values by 1 */ + Resolution.X++; + Resolution.Y++; + + if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) + { + /* Multiply the horizontal resolution by the 9/8 dot mode */ + Resolution.X *= (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & VGA_SEQ_CLOCK_98DM) + ? 8 : 9; + + /* The horizontal resolution is halved in 8-bit mode */ + if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) Resolution.X /= 2; + } + + if (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & VGA_CRTC_MAXSCANLINE_DOUBLE) + { + /* Halve the vertical resolution */ + Resolution.Y >>= 1; + } + else + { + /* Divide the vertical resolution by the maximum scan line (== font size in text mode) */ + Resolution.Y /= MaximumScanLine; + } + + /* Return the resolution */ + return Resolution; +} + +BOOLEAN VgaGetDoubleVisionState(PBOOLEAN Vertical, PBOOLEAN Horizontal) +{ + if (GraphicsConsoleBuffer == NULL) return FALSE; + if (Vertical) *Vertical = DoubleWidth; + if (Horizontal) *Horizontal = DoubleHeight; + return TRUE; +} + +VOID VgaRefreshDisplay(VOID) +{ + VgaVerticalRetrace(0); }
VOID NTAPI VgaReadMemory(ULONG Address, PVOID Buffer, ULONG Size) @@ -2106,12 +2127,18 @@ RegisterIoPort(0x3D8, VgaReadPort, VgaWritePort); // CGA_MODE_CTRL_REG RegisterIoPort(0x3D9, VgaReadPort, VgaWritePort); // CGA_PAL_CTRL_REG
+ HSyncTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, 0, VgaHorizontalRetrace); + VSyncTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, 16, VgaVerticalRetrace); + /* Return success */ return TRUE; }
VOID VgaCleanup(VOID) { + DestroyHardwareTimer(VSyncTimer); + DestroyHardwareTimer(HSyncTimer); + if (ScreenMode == GRAPHICS_MODE) { /* Leave the current graphics mode */
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h [iso-8859-1] Fri Apr 17 00:20:39 2015 @@ -260,9 +260,9 @@
COORD VgaGetDisplayResolution(VOID); VOID VgaRefreshDisplay(VOID); -VOID VgaHorizontalRetrace(VOID); VOID VgaWriteFont(UINT FontNumber, CONST UCHAR *FontData, UINT Height); VOID VgaClearMemory(VOID); +BOOLEAN VgaGetDoubleVisionState(PBOOLEAN Vertical, PBOOLEAN Horizontal);
BOOLEAN VgaInitialize(HANDLE TextHandle); VOID VgaCleanup(VOID);