views:

187

answers:

4

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?

A: 

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.

George Phillips
A: 

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
raven
+1  A: 

This is best achieved using the DirectX API WaitForVerticalBlank, part of DirectDraw from v7 onward, I believe. Much simpler than rooting around in RasterStatus.

Jim Mack
A: 

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.

Kris Erickson