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/cloc…
==============================================================================
--- 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/cloc…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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);