Author: aandrejevic
Date: Sat Aug 27 17:10:08 2016
New Revision: 72474
URL:
http://svn.reactos.org/svn/reactos?rev=72474&view=rev
Log:
[NTVDM:SVGA]
Properly implement the vertical retrace interval. The starting address and the
scanline size are calculated at the start, and the actual update is performed at
the end. This allows software to change the pixel panning and some other
parameters during the vertical retrace.
Also, normalize the CRTC register names.
Modified:
trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c
trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c
trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c
trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c [iso-8859-1] Sat Aug 27 17:10:08
2016
@@ -210,11 +210,11 @@
/* Unlock CRTC registers 0-7 */
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG);
IOWriteB(VGA_CRTC_DATA , IOReadB(VGA_CRTC_DATA) | 0x80);
- IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_VERT_RETRACE_END_REG);
+ IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_VERT_RETRACE_REG);
IOWriteB(VGA_CRTC_DATA , IOReadB(VGA_CRTC_DATA) & ~0x80);
// Make sure they remain unlocked
Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80;
- Registers->CRT[VGA_CRTC_VERT_RETRACE_END_REG] &= ~0x80;
+ Registers->CRT[VGA_CRTC_END_VERT_RETRACE_REG] &= ~0x80;
/* Write the CRTC registers */
for (i = 0; i < SVGA_CRTC_MAX_REG; i++)
@@ -564,7 +564,7 @@
default:
{
- DPRINT("VESA INT 0x10, AH = 0x05, Unknown subfunction:
%02X", getBH());
+ DPRINT("VESA INT 0x10, AL = 0x05, Unknown subfunction:
%02X", getBH());
}
}
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c [iso-8859-1] Sat Aug 27 17:10:08
2016
@@ -2195,11 +2195,11 @@
/* Unlock CRTC registers 0-7 */
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG);
IOWriteB(VGA_CRTC_DATA , IOReadB(VGA_CRTC_DATA) | 0x80);
- IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_VERT_RETRACE_END_REG);
+ IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_VERT_RETRACE_REG);
IOWriteB(VGA_CRTC_DATA , IOReadB(VGA_CRTC_DATA) & ~0x80);
// Make sure they remain unlocked
Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80;
- Registers->CRT[VGA_CRTC_VERT_RETRACE_END_REG] &= ~0x80;
+ Registers->CRT[VGA_CRTC_END_VERT_RETRACE_REG] &= ~0x80;
/* Write the CRTC registers */
for (i = 0; i < VGA_CRTC_MAX_REG; i++)
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hard…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c [iso-8859-1] Sat Aug 27
17:10:08 2016
@@ -272,10 +272,11 @@
// static VGA_REGISTERS VgaRegisters;
-static ULONGLONG VerticalRetraceCycle = 0ULL;
static ULONGLONG HorizontalRetraceCycle = 0ULL;
-static PHARDWARE_TIMER VSyncTimer;
static PHARDWARE_TIMER HSyncTimer;
+static DWORD ScanlineCounter = 0;
+static DWORD StartAddressLatch = 0;
+static DWORD ScanlineSizeLatch = 0;
static BOOLEAN NeedsUpdate = FALSE;
static BOOLEAN ModeChanged = FALSE;
@@ -731,17 +732,8 @@
{
SHORT i, j, k;
DWORD AddressSize = VgaGetAddressSize();
- DWORD ScanlineSize = ((DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG]
- + (((DWORD)VgaCrtcRegisters[SVGA_CRTC_EXT_DISPLAY_REG] &
SVGA_CRTC_EXT_OFFSET_BIT8) << 4)) * 2;
- BYTE PresetRowScan = VgaCrtcRegisters[VGA_CRTC_PRESET_ROW_SCAN_REG] & 0x1F;
+ DWORD Address = StartAddressLatch;
BYTE BytePanning = (VgaCrtcRegisters[VGA_CRTC_PRESET_ROW_SCAN_REG] >> 5) &
3;
- DWORD Address = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_START_ADDR_LOW_REG],
- VgaCrtcRegisters[VGA_CRTC_START_ADDR_HIGH_REG])
- + ((VgaCrtcRegisters[SVGA_CRTC_EXT_DISPLAY_REG] &
SVGA_CRTC_EXT_ADDR_BIT16) << 16)
- + ((VgaCrtcRegisters[SVGA_CRTC_EXT_DISPLAY_REG] &
SVGA_CRTC_EXT_ADDR_BITS1718) << 15)
- + ((VgaCrtcRegisters[SVGA_CRTC_OVERLAY_REG] &
SVGA_CRTC_EXT_ADDR_BIT19) << 12)
- + PresetRowScan * ScanlineSize
- + BytePanning;
WORD LineCompare = VgaCrtcRegisters[VGA_CRTC_LINE_COMPARE_REG]
| ((VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] &
VGA_CRTC_OVERFLOW_LC8) << 4);
BYTE PixelShift = VgaAcRegisters[VGA_AC_HORZ_PANNING_REG] & 0x0F;
@@ -816,11 +808,11 @@
/* Apply horizontal pixel panning */
if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
{
- X = j + (PixelShift >> 1);
+ X = j + ((PixelShift >> 1) & 0x03);
}
else
{
- X = j + PixelShift;
+ X = j + ((PixelShift < 8) ? PixelShift : -1);
}
/* Check the shifting mode */
@@ -1014,7 +1006,7 @@
if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_OE) || (i & 1))
{
/* Move to the next scanline */
- Address += ScanlineSize;
+ Address += ScanlineSizeLatch;
}
}
@@ -1064,7 +1056,7 @@
}
/* Move to the next scanline */
- Address += ScanlineSize;
+ Address += ScanlineSizeLatch;
}
}
}
@@ -1116,16 +1108,15 @@
ULONG CyclesPerMicrosecond = (ULONG)((GetCycleSpeed() + 500000ULL) /
1000000ULL);
ULONG Dots = (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & 1) ? 9 : 8;
ULONG Clock = VgaGetClockFrequency() / 1000000;
- 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;
+ ULONG HblankStart, HblankEnd;
+ ULONG HblankDuration;
+ ULONG VerticalRetraceStart =
VgaCrtcRegisters[VGA_CRTC_START_VERT_RETRACE_REG];
+ ULONG VerticalRetraceEnd;
+
+ VerticalRetraceStart |= (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] &
VGA_CRTC_OVERFLOW_VRS8) << 6;
+ VerticalRetraceStart |= (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] &
VGA_CRTC_OVERFLOW_VRS9) << 2;
+
+ VerticalRetraceEnd = VerticalRetraceStart +
(VgaCrtcRegisters[VGA_CRTC_END_VERT_RETRACE_REG] & 0x0F);
/* Calculate the horizontal blanking duration in cycles */
HblankStart = VgaCrtcRegisters[VGA_CRTC_START_HORZ_BLANKING_REG] & 0x1F;
@@ -1134,15 +1125,11 @@
HblankDuration = ((HblankEnd - HblankStart) * Dots
* CyclesPerMicrosecond + (Clock >> 1)) / Clock;
- Vsync = (Cycles - VerticalRetraceCycle) < (ULONGLONG)VblankDuration;
+ Vsync = ScanlineCounter >= VerticalRetraceStart && ScanlineCounter
<= VerticalRetraceEnd;
Hsync = (Cycles - HorizontalRetraceCycle) < (ULONGLONG)HblankDuration;
/* Reset the AC latch */
VgaAcLatch = FALSE;
-
- /* Reverse the polarity, if needed */
- if (VgaMiscRegister & VGA_MISC_VSYNCP) Vsync = !Vsync;
- if (VgaMiscRegister & VGA_MISC_HSYNCP) Hsync = !Hsync;
/* Set a flag if there is a vertical or horizontal retrace */
if (Vsync || Hsync) Result |= VGA_STAT_DD;
@@ -1591,13 +1578,8 @@
SvgaHdrCounter = 0;
}
-static VOID FASTCALL VgaVerticalRetrace(ULONGLONG ElapsedTime)
-{
- UNREFERENCED_PARAMETER(ElapsedTime);
-
- /* Set the vertical retrace cycle */
- VerticalRetraceCycle = GetCycleCount();
-
+static inline VOID VgaVerticalRetrace(VOID)
+{
/* If nothing has changed, just return */
// if (!ModeChanged && !CursorChanged && !PaletteChanged &&
!NeedsUpdate)
// return;
@@ -1640,10 +1622,61 @@
static VOID FASTCALL VgaHorizontalRetrace(ULONGLONG ElapsedTime)
{
+ ULONG VerticalTotal = VgaCrtcRegisters[VGA_CRTC_VERT_TOTAL_REG];
+ ULONG VerticalRetraceStart = VgaCrtcRegisters[VGA_CRTC_START_VERT_RETRACE_REG];
+ ULONG VerticalRetraceEnd;
+ BOOLEAN BeforeVSyncStart, BeforeVSyncEnd;
+ ULONG CurrentCycleCount = GetCycleCount();
+ ULONG ElapsedCycles = CurrentCycleCount - HorizontalRetraceCycle;
+ ULONG Dots = (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & 1) ? 9 : 8;
+ ULONG HorizTotalDots = ((ULONG)VgaCrtcRegisters[VGA_CRTC_HORZ_TOTAL_REG] + 5) *
Dots;
+ ULONG HSyncsPerSecond = VgaGetClockFrequency() / HorizTotalDots;
+ ULONG HSyncs = (ElapsedCycles * HSyncsPerSecond) / GetCycleSpeed();
+
UNREFERENCED_PARAMETER(ElapsedTime);
+ if (HSyncs == 0) HSyncs = 1;
+
+ VerticalTotal |= (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] &
VGA_CRTC_OVERFLOW_VT8) << 8;
+ VerticalTotal |= (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] &
VGA_CRTC_OVERFLOW_VT9) << 4;
+
+ VerticalRetraceStart |= (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] &
VGA_CRTC_OVERFLOW_VRS8) << 6;
+ VerticalRetraceStart |= (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] &
VGA_CRTC_OVERFLOW_VRS9) << 2;
+
+ VerticalRetraceEnd = VerticalRetraceStart +
(VgaCrtcRegisters[VGA_CRTC_END_VERT_RETRACE_REG] & 0x0F);
/* Set the cycle */
- HorizontalRetraceCycle = GetCycleCount();
+ HorizontalRetraceCycle = CurrentCycleCount;
+
+ /* Increment the scanline counter, but make sure we don't skip any part of the
vertical retrace */
+ BeforeVSyncStart = (ScanlineCounter < VerticalRetraceStart);
+ BeforeVSyncEnd = (ScanlineCounter < VerticalRetraceEnd);
+ ScanlineCounter += HSyncs;
+ if (BeforeVSyncStart && ScanlineCounter >= VerticalRetraceStart)
ScanlineCounter = VerticalRetraceStart;
+ else if (BeforeVSyncEnd && ScanlineCounter >= VerticalRetraceEnd)
ScanlineCounter = VerticalRetraceEnd;
+
+ /* The scanline counter wraps around */
+ ScanlineCounter %= VerticalTotal;
+
+ if (ScanlineCounter == VerticalRetraceStart)
+ {
+ /* Save the scanline size */
+ ScanlineSizeLatch = ((DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG]
+ + (((DWORD)VgaCrtcRegisters[SVGA_CRTC_EXT_DISPLAY_REG] &
SVGA_CRTC_EXT_OFFSET_BIT8) << 4)) * 2;
+
+ /* Save the starting address */
+ StartAddressLatch = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_START_ADDR_LOW_REG],
+ VgaCrtcRegisters[VGA_CRTC_START_ADDR_HIGH_REG])
+ + ((VgaCrtcRegisters[SVGA_CRTC_EXT_DISPLAY_REG] &
SVGA_CRTC_EXT_ADDR_BIT16) << 16)
+ + ((VgaCrtcRegisters[SVGA_CRTC_EXT_DISPLAY_REG] &
SVGA_CRTC_EXT_ADDR_BITS1718) << 15)
+ + ((VgaCrtcRegisters[SVGA_CRTC_OVERLAY_REG] &
SVGA_CRTC_EXT_ADDR_BIT19) << 12)
+ + (VgaCrtcRegisters[VGA_CRTC_PRESET_ROW_SCAN_REG] & 0x1F)
* ScanlineSizeLatch
+ + ((VgaCrtcRegisters[VGA_CRTC_PRESET_ROW_SCAN_REG] >>
5) & 3);
+ }
+
+ if (ScanlineCounter == VerticalRetraceEnd)
+ {
+ VgaVerticalRetrace();
+ }
}
/* PUBLIC FUNCTIONS ***********************************************************/
@@ -1706,7 +1739,7 @@
VOID VgaRefreshDisplay(VOID)
{
- VgaVerticalRetrace(0);
+ VgaVerticalRetrace();
}
VOID FASTCALL VgaReadMemory(ULONG Address, PVOID Buffer, ULONG Size)
@@ -1803,13 +1836,11 @@
/*
* These values can also be computed in the following way, but using the table
seems to be faster:
*
- * ColorCompareBytes = VgaGcRegisters[VGA_GC_COLOR_COMPARE_REG];
- * ColorCompareBytes |= (ColorCompareBytes << 7) | (ColorCompareBytes
<< 14) | (ColorCompareBytes << 21);
+ * ColorCompareBytes = VgaGcRegisters[VGA_GC_COLOR_COMPARE_REG] * 0x000204081;
* ColorCompareBytes &= 0x01010101;
* ColorCompareBytes = (ColorCompareBytes << 8) - ColorCompareBytes;
*
- * ColorIgnoreBytes = VgaGcRegisters[VGA_GC_COLOR_IGNORE_REG];
- * ColorIgnoreBytes |= (ColorIgnoreBytes << 7) | (ColorIgnoreBytes <<
14) | (ColorIgnoreBytes << 21);
+ * ColorIgnoreBytes = VgaGcRegisters[VGA_GC_COLOR_IGNORE_REG] * 0x000204081;
* ColorIgnoreBytes &= 0x01010101;
* ColorIgnoreBytes = (ColorIgnoreBytes << 8) - ColorIgnoreBytes;
*/
@@ -1959,7 +1990,6 @@
RegisterIoPort(0x3D9, VgaReadPort, VgaWritePort); // CGA_PAL_CTRL_REG
HSyncTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(31469),
VgaHorizontalRetrace);
- VSyncTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(60),
VgaVerticalRetrace);
/* Return success */
return TRUE;
@@ -1970,7 +2000,6 @@
/* Do a final display refresh */
VgaRefreshDisplay();
- DestroyHardwareTimer(VSyncTimer);
DestroyHardwareTimer(HSyncTimer);
/* Leave the current video mode */
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hard…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h [iso-8859-1] Sat Aug 27
17:10:08 2016
@@ -215,8 +215,8 @@
VGA_CRTC_START_ADDR_LOW_REG,
VGA_CRTC_CURSOR_LOC_HIGH_REG,
VGA_CRTC_CURSOR_LOC_LOW_REG,
- VGA_CRTC_VERT_RETRACE_START_REG,
- VGA_CRTC_VERT_RETRACE_END_REG,
+ VGA_CRTC_START_VERT_RETRACE_REG,
+ VGA_CRTC_END_VERT_RETRACE_REG,
VGA_CRTC_VERT_DISP_END_REG,
VGA_CRTC_OFFSET_REG,
VGA_CRTC_UNDERLINE_REG,