VB6 Vertical Sync for Emulator
-
12-09-2019 - |
Question
This is maybe an oblique question:
I'm writing an emulator in VB6 (silly me). For smooth window refreshing in the emulator itself, I would like to grab the vertical sync of the monitor. Are there any Windows API calls I can use? Or is this an impossible request?
Solution
This is best achieved using the DirectX API WaitForVerticalBlank, part of DirectDraw from v7 onward, I believe. Much simpler than rooting around in RasterStatus.
OTHER TIPS
There are WPF facilities which function on XP but only work properly on Vista. You can bring in open GL but that may not be supported by all video cards.
The only effective solution is to use Direct3D, but you don't have to use it for your rendering. Just piggyback its capabilities. Looks like IDirect3DDevice9::GetRasterStatus() is just the thing. Your first order solution can poll that until it reports InVBlank TRUE. Then you can do a second order solution where you poll it through one frame to determine vsync rate and relative timing. Then use a timer to keep in sync. Perhaps waking up every half frame and verify that you're hitting about the same scan line when out of vsync. That way you can adjust the timing to keep in sync.
I've got my own pet emulator that could use this functionality. If I code up a solution I'll post more details here.
You are asking for the "vertical sync of the monitor". Vertical sync is a graphics card setting that locks the frame rendering rate to the monitor refresh rate. According to NVida, "This improves image quality by eliminating horizontal tearing effects in the 3D image." Do you want to know whether vertical sync is on or off or were you looking for the refresh rate of the monitor? I don't know how to do the former, but you can get the latter this way:
Private Const CCHDEVICENAME = 32
Private Const CCHFORMNAME = 32
Private Type DEVMODE
dmDeviceName As String * CCHDEVICENAME
dmSpecVersion As Integer
dmDriverVersion As Integer
dmSize As Integer
dmDriverExtra As Integer
dmFields As Long
dmOrientation As Integer
dmPaperSize As Integer
dmPaperLength As Integer
dmPaperWidth As Integer
dmScale As Integer
dmCopies As Integer
dmDefaultSource As Integer
dmPrintQuality As Integer
dmColor As Integer
dmDuplex As Integer
dmYResolution As Integer
dmTTOption As Integer
dmCollate As Integer
dmFormName As String * CCHFORMNAME
dmUnusedPadding As Integer
dmBitsPerPel As Long
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
End Type
Private Declare Function EnumDisplaySettings Lib "user32.dll" Alias _
"EnumDisplaySettingsA" (ByVal lpszDeviceName As String, _
ByVal iModeNum As Long, ByRef lpDevMode As DEVMODE) As Long
Private Function GetRefreshRate() As Long
Dim dm As DEVMODE
dm.dmSize = Len(dm)
EnumDisplaySettings vbNullString, ENUM_CURRENT_SETTINGS, dm
GetRefreshRate = dm.dmDisplayFrequency
End Function
If you really want to do this in VB6, you are going to have to look at DirectX. Here is a good starting ground for how to do DirectX in Vb6. Planet Source Code and CDVG have some more tutorials.