News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Vista Woes

Started by Jimg, April 28, 2009, 05:46:46 PM

Previous topic - Next topic

Jimg

Thank you Bruce, I appreciate it.

Slugsnack

using server 2008 which is pretty similar to vista and both run okay

Mark Jones

No Vista here, but if I had it, I would test your code Jim. (Frankly, Vista is just too damn large to consider installing. If Win7 is better I might consider that, but Vista is not likely for my toolbox.)
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Jimg

I agree Mark.  If I had it, I'd probably in the 50% for which the program works.  Wish I knew what was causing the problem.

Jimg

Well, I think I finally got it all worked out.   Apparently when using Vista on some recent Dell laptops (and probably others, this is the only one I know for sure), the scan lines returned by directdraw are not consistant.  If I wait for the first one after the vertical retrace/blanking interval, it is often somewhere in the 200's, rather than 1 like the vast majority of machines.  In fact, sometimes I would have to step through a dozen frames before I received any indication of vertical retrace at all.  So I rewrote the code (much of which I originally stole from MichaelW) that waits for a particular scan line that will minimize the screen tearing.

;--------code to get vertical blanking to prevent flicker from MichaelW------------

DDO_GetScanLine EQU 64
DDERR_VERTICALBLANKINPROGRESS EQU ((1 shl 31)or(876h shl 16)or(537))

.data
align 4
lpdd     dd 0   ; address of direct draw object
scanLine dd 0   ; returned from DDGetScanLine
VblankOk dd 0 ; flag that it is ok to wait for vertical blanking
WantLine dd 1
.data?
align 4
MaxLine dd ?    ; largest scan line number (outside vertical blanking region)
minline dd ?    ; minimum scan line number (outside vertical blanking region)
LastScan dd ?
.data
align 8
t1000 dq 1000
DD_OK equ 0

.code

StartDD proc
    local framecount
    invoke DirectDrawCreate,0,addr lpdd,0 ; Create a default DirectDraw object.
    or eax,eax
    jnz DDNoGood
    mov minline,99999
    mov MaxLine,0
    .repeat
        call DDGetScanLine ; Make sure DDGetScanLine doesn't have any obvious problems.
    .until eax != DDERR_VERTICALBLANKINPROGRESS
    or eax,eax  ; it better be DD_OK
    jnz DDNoGood
mov VblankOk,1 ; ok to use
    mov framecount,0
    mov LastScan,edx
    .repeat
        .if edx<minline
            mov minline,edx
        .endif
        sif edx>MaxLine
            mov MaxLine,edx
        .endif
        call DDGetScanLine
        .if eax || edx < LastScan
            inc framecount ; some hardware (e.g. my daughters brand new Dell laptop) is flakey and doesn't cycle smoothly
            .break .if framecount>2
            .repeat
                call DDGetScanLine
            .until eax==0
        .endif             
    .until 0
    mov eax,WantLine    ; as set by ini file
.if sdword ptr eax > MaxLine || sdword ptr eax < 1
   m2m WantLine,minline
.endif
mov eax,MaxLine
sub eax,minline
sif eax < 200
   mov VblankOk,0  ; no good, not enough to manipulate
.endif
DDNoGood:
    if PrintLog
        printx mbuff," *** Min ScanLine=",dd minline," Max ScanLine=",dd MaxLine," DD ok=",dd VblankOk
        pmsg mbuff
    endif 
ret
StartDD EndP

DDGetScanLine proc  ; return eax=0 or eax=DDERR_VERTICALBLANKINPROGRESS, edx=scan line
    push offset scanLine
    push lpdd
    mov  eax, lpdd
    mov  eax, [eax]
    call DWORD PTR[eax+DDO_GetScanLine]
    mov edx,scanLine
    ret
DDGetScanLine endp

WaitForScanLine proc
    mov LastScan,0 ; last scan line found
    .repeat
        call DDGetScanLine
        .break .if eax!=0  ; in retrace, go wait for non retrace
        .if edx==WantLine
            ret  ;optimal case, no stack frame, so just return
        .endif
        .break .if edx < LastScan  ; scan line number recycled, but we missed retrace
        mov LastScan,edx   ; save to check for missed retrace
    .until 0
    .repeat
        call DDGetScanLine  ; until we get a non-retrace
    .until eax==0
    mov LastScan,0   
    .repeat
        .if edx>=WantLine
            ret ; where we want to be
        .elseif edx<LastScan
            ret ; missed it again, give up
        .endif
        mov LastScan,edx   ; save to check for missed retrace
        call DDGetScanLine
    .until eax  ; exit if we hit another retrace
    .repeat
        call DDGetScanLine  ; total failure, wait until we get a non-retrace
    .until eax==0
ret
WaitForScanLine endp


Seems to be rock solid now.