From f3c5b91037f1834c387d3fbf84aedca779c63c0b Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Tue, 9 Jun 2015 19:22:52 +0000 Subject: [PATCH] [NTVDM] Implement cycle-based timing for VGA. svn path=/trunk/; revision=68095 --- reactos/subsystems/mvdm/ntvdm/clock.c | 41 ++++++++++-------- reactos/subsystems/mvdm/ntvdm/clock.h | 3 ++ .../mvdm/ntvdm/hardware/video/vga.c | 42 ++++++++++++++----- .../mvdm/ntvdm/hardware/video/vga.h | 2 +- 4 files changed, 58 insertions(+), 30 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/clock.c b/reactos/subsystems/mvdm/ntvdm/clock.c index c89da7e8fac..bcb0148e259 100644 --- a/reactos/subsystems/mvdm/ntvdm/clock.c +++ b/reactos/subsystems/mvdm/ntvdm/clock.c @@ -36,26 +36,28 @@ /* VARIABLES ******************************************************************/ static LIST_ENTRY Timers; +static ULONGLONG Cycles = 0ULL; +static ULONGLONG CurrentIps = 20000000ULL; // 20 MIPS is a good estimate static LARGE_INTEGER StartPerfCount, Frequency; // static ULONG StartTickCount; static LARGE_INTEGER Counter; static ULONG CurrentTickCount; - -#ifdef IPS_DISPLAY +static ULONGLONG LastCycles = 0ULL; static PHARDWARE_TIMER IpsTimer; -static ULONGLONG Cycles = 0ULL; -#endif /* PRIVATE FUNCTIONS **********************************************************/ -#ifdef IPS_DISPLAY -static VOID FASTCALL IpsDisplayCallback(ULONGLONG ElapsedTime) +static VOID FASTCALL IpsCallback(ULONGLONG ElapsedTime) { - DPRINT1("NTVDM: %I64u Instructions Per Second\n", Cycles / ElapsedTime); - Cycles = 0ULL; -} + CurrentIps = (Cycles - LastCycles) / ElapsedTime; + +#ifdef IPS_DISPLAY + DPRINT1("NTVDM: %I64u Instructions Per Second\n", CurrentIps); #endif + LastCycles = Cycles; +} + /* PUBLIC FUNCTIONS ***********************************************************/ VOID ClockUpdate(VOID) @@ -76,10 +78,7 @@ VOID ClockUpdate(VOID) 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) @@ -199,6 +198,16 @@ VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer) } } +ULONGLONG GetCycleCount(VOID) +{ + return Cycles; +} + +ULONGLONG GetCycleSpeed(VOID) +{ + return CurrentIps; +} + BOOLEAN ClockInitialize(VOID) { InitializeListHead(&Timers); @@ -215,16 +224,12 @@ BOOLEAN ClockInitialize(VOID) /* Find the starting tick count */ // StartTickCount = GetTickCount(); -#ifdef IPS_DISPLAY - - IpsTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(1), IpsDisplayCallback); + IpsTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(1), IpsCallback); if (IpsTimer == NULL) { - wprintf(L"FATAL: Cannot create IPS display timer.\n"); + wprintf(L"FATAL: Cannot create IPS timer.\n"); return FALSE; } -#endif - return TRUE; } diff --git a/reactos/subsystems/mvdm/ntvdm/clock.h b/reactos/subsystems/mvdm/ntvdm/clock.h index 65fa32258f9..bc0c3bd5d68 100644 --- a/reactos/subsystems/mvdm/ntvdm/clock.h +++ b/reactos/subsystems/mvdm/ntvdm/clock.h @@ -44,6 +44,9 @@ VOID DisableHardwareTimer(PHARDWARE_TIMER Timer); VOID SetHardwareTimerDelay(PHARDWARE_TIMER Timer, ULONGLONG NewDelay); VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer); +ULONGLONG GetCycleCount(VOID); +ULONGLONG GetCycleSpeed(VOID); + VOID ClockUpdate(VOID); BOOLEAN ClockInitialize(VOID); diff --git a/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c b/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c index 871397208d7..f11d1a691aa 100644 --- a/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c +++ b/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c @@ -282,8 +282,8 @@ static BYTE VgaDacRegisters[VGA_PALETTE_SIZE]; // static VGA_REGISTERS VgaRegisters; -static BOOLEAN InVerticalRetrace = FALSE; -static BOOLEAN InHorizontalRetrace = FALSE; +static ULONGLONG VerticalRetraceCycle = 0ULL; +static ULONGLONG HorizontalRetraceCycle = 0ULL; static BOOLEAN NeedsUpdate = FALSE; static BOOLEAN ModeChanged = FALSE; @@ -1413,8 +1413,31 @@ static BYTE WINAPI VgaReadPort(USHORT Port) case VGA_INSTAT1_READ_COLOR: { BYTE Result = 0; - BOOLEAN Vsync = InVerticalRetrace; - BOOLEAN Hsync = InHorizontalRetrace; + BOOLEAN Vsync, Hsync; + ULONGLONG Cycles = GetCycleCount(); + ULONG CyclesPerMicrosecond = (ULONG)((GetCycleSpeed() + 500000ULL) / 1000000ULL); + ULONG Dots = (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & 1) ? 9 : 8; + ULONG Clock = ((VgaMiscRegister >> 2) & 1) ? 28 : 25; + ULONG HorizTotalDots = ((ULONG)VgaCrtcRegisters[VGA_CRTC_HORZ_TOTAL_REG] + 5) * Dots; + ULONG VblankStart, VblankEnd, HblankStart, HblankEnd; + ULONG HblankDuration, VblankDuration; + + /* Calculate the vertical blanking duration in cycles */ + VblankStart = VgaCrtcRegisters[VGA_CRTC_START_VERT_BLANKING_REG] & 0x7F; + VblankEnd = VgaCrtcRegisters[VGA_CRTC_END_VERT_BLANKING_REG] & 0x7F; + if (VblankEnd < VblankStart) VblankEnd |= 0x80; + VblankDuration = ((VblankEnd - VblankStart) * HorizTotalDots + * CyclesPerMicrosecond + (Clock >> 1)) / Clock; + + /* Calculate the horizontal blanking duration in cycles */ + HblankStart = VgaCrtcRegisters[VGA_CRTC_START_HORZ_BLANKING_REG] & 0x1F; + HblankEnd = VgaCrtcRegisters[VGA_CRTC_END_HORZ_BLANKING_REG] & 0x1F; + if (HblankEnd < HblankStart) HblankEnd |= 0x20; + HblankDuration = ((HblankEnd - HblankStart) * Dots + * CyclesPerMicrosecond + (Clock >> 1)) / Clock; + + Vsync = (Cycles - VerticalRetraceCycle) < (ULONGLONG)VblankDuration; + Hsync = (Cycles - HorizontalRetraceCycle) < (ULONGLONG)HblankDuration; /* Reset the AC latch */ VgaAcLatch = FALSE; @@ -1429,9 +1452,6 @@ static BYTE WINAPI VgaReadPort(USHORT Port) /* Set an additional flag if there was a vertical retrace */ if (Vsync) Result |= VGA_STAT_VRETRACE; - /* Clear the flags */ - InHorizontalRetrace = InVerticalRetrace = FALSE; - return Result; } @@ -1787,8 +1807,8 @@ static VOID FASTCALL VgaVerticalRetrace(ULONGLONG ElapsedTime) UNREFERENCED_PARAMETER(ElapsedTime); - /* Set the vertical retrace flag */ - InVerticalRetrace = TRUE; + /* Set the vertical retrace cycle */ + VerticalRetraceCycle = GetCycleCount(); /* If nothing has changed, just return */ // if (!ModeChanged && !CursorChanged && !PaletteChanged && !NeedsUpdate) @@ -1859,8 +1879,8 @@ static VOID FASTCALL VgaHorizontalRetrace(ULONGLONG ElapsedTime) { UNREFERENCED_PARAMETER(ElapsedTime); - /* Set the flag */ - InHorizontalRetrace = TRUE; + /* Set the cycle */ + HorizontalRetraceCycle = GetCycleCount(); } /* PUBLIC FUNCTIONS ***********************************************************/ diff --git a/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h b/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h index 445f700cb5e..083f807ff3d 100644 --- a/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h +++ b/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h @@ -161,7 +161,7 @@ enum VGA_CRTC_OFFSET_REG, VGA_CRTC_UNDERLINE_REG, VGA_CRTC_START_VERT_BLANKING_REG, - VGA_CRTC_END_VERT_BLANKING, + VGA_CRTC_END_VERT_BLANKING_REG, VGA_CRTC_MODE_CONTROL_REG, VGA_CRTC_LINE_COMPARE_REG, VGA_CRTC_MAX_REG