The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Farabi on June 17, 2005, 01:50:07 PM

Title: Flicker
Post by: Farabi on June 17, 2005, 01:50:07 PM
I use double buffer but still it flicker. Can it posible because bitblt is slow? I did saw about set thread priority function or something, can it maybe solve the problem?

What is the function name? Set thread priority? I forgot. Last time I use that function my computer smells like burn. But im not sure.

[attachment deleted by admin]
Title: Re: Flicker
Post by: MichaelW on June 17, 2005, 07:34:42 PM
I think the problem is what used to be called "tearing". It is normally caused by the buffer update and screen refresh being out of sync. This page explains the problem and demonstrates a method of avoiding it, without having your code waste time in a polling loop. If you manage to create an ASM version of this code, I would be interested in seeing it. I saved the link so I could experiment with it, but I have never found the time to do so:

http://www.codeproject.com/gdi/tearingfreedrawing.asp

MSDN: SetPriorityClass (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/setpriorityclass.asp)

Title: Re: Flicker
Post by: Farabi on June 18, 2005, 02:35:09 AM
Sure. After I finish the problem I will send the source. And also what function do you suggest for this? WaitForVerticalRetrace? But it is not available on GDI function.
Title: Re: Flicker
Post by: MichaelW on June 19, 2005, 05:31:03 AM
This demonstrates a minimal solution that I think should work for most systems.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
    include \masm32\include\ddraw.inc
    includelib \masm32\lib\ddraw.lib

    DD_OK EQU 0

    DDO_GetScanLine EQU 64
   
    DDERR_INVALIDPARAMS EQU E_INVALIDARG
    DDERR_UNSUPPORTED   EQU E_NOTIMPL
    DDERR_INVALIDOBJECT EQU ((1 shl 31) or (876h shl 16) or ( 130 ))
    DDERR_VERTICALBLANKINPROGRESS EQU ((1 shl 31)or(876h shl 16)or(537))

    DDGetScanLine PROTO scanLine:DWORD
    WaitForVerticalBlank PROTO

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
        lpdd_1      dd 0
        scanLine    dd 0
        maxScanLine dd 0
        vbStart     dd 0
        vbEnd       dd 0
        temp        dd 0
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    ; ------------------------------------
    ; Create a default DirectDraw object.
    ; ------------------------------------
    invoke DirectDrawCreate,NULL,ADDR lpdd_1,NULL
    .IF (eax)
        print "DirectDrawCreate failed",13,10
        jmp   fini
    .ENDIF

    ; -----------------------------------------------------------
    ; Make sure DDGetScanLine doesn't have any obvious problems.
    ; -----------------------------------------------------------
    invoke DDGetScanLine, ADDR scanLine
    .IF (eax != DD_OK)
        SWITCH (eax)
          CASE DDERR_INVALIDPARAMS
            print "DDERR_INVALIDPARAMS",13,10
          CASE DDERR_UNSUPPORTED
            print "DDERR_UNSUPPORTED",13,10
          CASE DDERR_INVALIDOBJECT
            print "DDERR_INVALIDOBJECT",13,10
        ENDSW
        jmp   fini
    .ENDIF

    ; ---------------------------------------------------
    ; Set HIGH_PRIORITY_CLASS to miminize interruptions.
    ; ---------------------------------------------------
    invoke GetCurrentProcess
    invoke SetPriorityClass, eax, HIGH_PRIORITY_CLASS

    ; ----------------------------------------------------
    ; Determine the maximum scan line, which will be the
    ; value of the scan line counter at the bottom of the
    ; top border, immediately above the first visible
    ; scan line (scan line 0).
    ; ----------------------------------------------------
    mov   ebx, 100000
    .WHILE (ebx)
        invoke DDGetScanLine, ADDR scanLine
        .IF (eax == DD_OK)
            mov   eax, scanLine
            .IF (eax > maxScanLine)
                mov   maxScanLine, eax
            .ENDIF
        .ENDIF
        dec   ebx
    .ENDW
    print "maximum scan line = "
    print ustr$(maxScanLine),13,10

    ; ----------------------------------------
    ; Determine the scan lines where vertical
    ; blank starts and ends.
    ; ----------------------------------------
    invoke DDGetScanLine, ADDR scanLine
    .WHILE (scanLine)
        invoke DDGetScanLine, ADDR scanLine
    .ENDW
    .WHILE (TRUE)
        invoke DDGetScanLine, ADDR scanLine
        .IF (eax != DDERR_VERTICALBLANKINPROGRESS)
            m2m   vbStart, scanLine
            inc   vbStart
        .ELSE
            .WHILE (eax == DDERR_VERTICALBLANKINPROGRESS)
                invoke DDGetScanLine, ADDR scanLine
            .ENDW
            m2m   vbEnd, scanLine
            .BREAK
        .ENDIF
    .ENDW
    print "vertical blank start = "
    print ustr$(vbStart),13,10
    print "vertical blank end = "
    print ustr$(vbEnd),13,10

    ; ----------------------------------------
    ; Determine the approximate refresh rate.
    ; ----------------------------------------
    invoke GetTickCount
    mov   ebx, eax
    .WHILE (eax == ebx)
        invoke GetTickCount
    .ENDW
    mov   temp, eax
    mov   ebx, 200
    .WHILE (ebx)
        invoke WaitForVerticalBlank
        dec   ebx
    .ENDW
    invoke GetTickCount
    sub   eax, temp
    mov   temp, eax
    fld8  200000.0
    fild  temp
    fdiv
    fistp temp
    print chr$("approximate refresh rate = ")
    print ustr$(temp),'Hz',13,10

    invoke GetCurrentProcess
    invoke SetPriorityClass, eax, NORMAL_PRIORITY_CLASS

  fini:   

    mov   eax, input(13,10,"Press enter to exit...")
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

DDGetScanLine proc lpScanLine:DWORD

    push  lpScanLine
    push  lpdd_1
    mov   eax, lpdd_1
    mov   eax, [eax]
    call  DWORD PTR[eax+DDO_GetScanLine]
    ret

DDGetScanLine endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

WaitForVerticalBlank proc

    LOCAL localScanLine:DWORD

    invoke DDGetScanLine, ADDR localScanLine
    ; -------------------------------
    ; Wait until not vertical blank.
    ; -------------------------------
    .WHILE (eax == DDERR_VERTICALBLANKINPROGRESS)
        invoke DDGetScanLine, ADDR localScanLine
    .ENDW
    ; ---------------------------
    ; Wait until vertical blank.
    ; ---------------------------
    .WHILE (eax != DDERR_VERTICALBLANKINPROGRESS)
        invoke DDGetScanLine, ADDR localScanLine
    .ENDW   

    ret

WaitForVerticalBlank endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

Title: Re: Flicker
Post by: Farabi on June 19, 2005, 10:38:29 AM
Hai. Please test this, I heard it was crashes. Is this crashes on your computer?

http://www.geocities.com/realvampire2001/Contoh_program.zip
Title: Re: Flicker
Post by: Mark Jones on June 19, 2005, 01:42:14 PM
Both work fine for me on AMD XP SP2. :)
Title: Re: Flicker
Post by: brixton on June 19, 2005, 06:28:59 PM
Both crash for me, Win2k  :eek
Title: Re: Flicker
Post by: MichaelW on June 19, 2005, 06:47:40 PM
Both work OK for me: P3, Windows 2000 SP4, default version of DirectX (8.1), default drivers for Matrox G200.


Title: Re: Flicker
Post by: brixton on June 19, 2005, 09:29:24 PM
Oops, my bad, didn't extract the sound!  :lol

Both work fine now  :U
Title: Re: Flicker
Post by: Farabi on June 20, 2005, 12:11:41 AM
Thank you very much for testing it. I will upload the source soon.

Brixton:
So in Win2k if the music did not extracted it crash. Thanks for let me know about it.
Title: Re: Flicker
Post by: brixton on June 20, 2005, 01:09:24 AM
Quote from: Farabi on June 20, 2005, 12:11:41 AMBrixton:
So in Win2k if the music did not extracted it crash. Thanks for let me know about it.
Yes.  They both crashed at slightly different stages though.  :eek
Title: Re: Flicker
Post by: Farabi on June 20, 2005, 08:37:55 AM
About the source I cannot post it. The size is above 256 Kbytes.
Title: Re: Flicker
Post by: Farabi on June 20, 2005, 12:58:00 PM
Here is the old source. Its disneat I hope you can understand it. Its free for you to modify or recreate it for commercial or non commercial purpose.

[attachment deleted by admin]
Title: Re: Flicker
Post by: Farabi on June 20, 2005, 01:05:31 PM
Here is a screen shot

(http://www.geocities.com/realvampire2001/Clipboard.jpg)

I cannot send the code rigth now because it still under development. It still big.

Here is the very basic function to made a circle. Unfortunately FPU is very slow. Im still find another way to make it fast and this is what I know to make it fast.

*Note: The clock information on this code is wrong*

If this code

push eax
fld dword ptr[esp]
pop eax
fimul delta
fistp r_cos

replaced with this code

; xor edx,edx
; mov ecx,delta
; mul ecx
; mov ecx,1000
; div ecx
; mov eax,r_cos

I can save time until 15 times on 1.7 GHz celeron machine. I tried it but it crashed. I dont know what causing it. When I debug it with ollydbg, it stop at this function.


GetSin proc uses esi deg:dword ; 3 Clock cycle

mov esi,SCTbl ; 1 Clock cycle
mov ecx,deg ; 1 Clock cycle
mov eax,dword ptr[esi+ecx*4] ; 1 Clock cycle

ret
GetSin endp


Ecx register on GetSin procedure point to a wrong place and reported access violation. Maybe someone here understand and can solve this?


Phase1 proc uses esi ; 28.8 Kbyte needed
LOCAL deg,sin,cos,tan:dword


invoke GlobalAlloc,LMEM_DISCARDABLE,28800+14400 + 16*10000 +768
invoke GlobalLock,eax
mov SCTbl,eax


mov esi,eax ; 1 Clock cycle
xor ecx,ecx ; 1 Clock cycle
mov deg,ecx ; 1 Clock cycle

mov edx,3600 ; 1 Clock cycle
shl edx,2 ; 2 Clock cycle


@@:
finit ; 17 Clock cycle
pushad
invoke Deg2Rad,deg ; 104 Clock cycle
popad
fsincos ; 365 Clock cycle
fstp sin ; 8 Clock cycle
fstp cos ; 8 Clock cycle

; push 1000
; fimul dword ptr[esp]
; fistp sin
; pop eax
; push 1000
; fimul dword ptr[esp]
; fistp cos
; pop eax

mov eax,sin ; 1 Clock cycle
mov dword ptr[esi],eax ; 1 Clock cycle
mov eax,cos ; 1 Clock cycle
mov dword ptr[esi+edx],eax ; 1 Clock cycle

add deg,1 ; 3 Clock cycle
add esi,4 ; 1 Clock cycle
add ecx,4 ; 1 Clock cycle
cmp deg,3600 ; 2 Clock cycle
jl @b ; 3 Clock cycle
; 513 Clock cycle Each loop
; 1846800 Clock cycle total loop
; 1846806 Clock cycle
mov esi,SCTbl
add esi,28800
;Tan
mov edx,3600 ; 1 Clock cycle
shl edx,2 ; 2 Clock cycle

xor ecx,ecx
mov deg,ecx

@@:
finit ; 17 Clock cycle
pushad
invoke Deg2Rad,deg ; 104 Clock cycle
popad
fptan ; 273 Clock cycle
fstp tan
; push 1000
; fimul dword ptr[esp]
; fistp tan
; pop eax
;
push tan
pop [esi]
add deg,1 ; 3 Clock cycle
add esi,4 ; 1 Clock cycle
add ecx,4 ; 1 Clock cycle
cmp deg,3600 ; 2 Clock cycle
jl @b ; 3 Clock cycle


mov esi,SCTbl
add esi,28800+14400
mov Line_Table,esi
mov eax,16*10000
mov nLLimit,eax
mov nLPtr,0

add esi,eax
mov SCR_TBL,esi

mov ecx,768
xor eax,eax
xor edx,edx
@@:
mov [esi+edx*4],eax
add eax,1024
dec ecx
jnz @b

ret
Phase1 endp


UMGetPosRound proc uses esi delta:dword,deg:dword ; 138 Clock cycle
LOCAL r_sin,r_cos:dword


cmp deg,3600
jl @f
sub deg,3600
@@:
invoke GetSin,deg
push eax
fld dword ptr[esp]
pop eax
fimul delta
fistp r_sin

; xor edx,edx
; mov ecx,delta
; mul ecx
; mov ecx,1000
; div ecx
; mov eax,r_sin

invoke GetCos,deg
push eax
fld dword ptr[esp]
pop eax
fimul delta
fistp r_cos

; xor edx,edx
; mov ecx,delta
; mul ecx
; mov ecx,1000
; div ecx
; mov eax,r_cos

mov edx,r_sin
mov eax,r_cos


ret
UMGetPosRound endp

GetSin proc uses esi deg:dword ; 3 Clock cycle

mov esi,SCTbl ; 1 Clock cycle
mov ecx,deg ; 1 Clock cycle
mov eax,dword ptr[esi+ecx*4] ; 1 Clock cycle

ret
GetSin endp

GetCos proc uses esi deg:dword ; 4 Clock cycle

mov esi,SCTbl ; 1 Clock cycle
add esi,14400 ; 1 Clock cycle
mov ecx,deg ; 1 Clock cycle
mov eax,dword ptr[esi+ecx*4] ; 1 Clock cycle

ret
GetCos endp

GetTan proc uses esi deg:dword ; 4 Clock cycle

mov esi,SCTbl ; 1 Clock cycle
add esi,28800 ; 1 Clock cycle
mov ecx,deg ; 1 Clock cycle
mov eax,dword ptr[esi+ecx*4] ; 1 Clock cycle

ret
GetTan endp




[attachment deleted by admin]
Title: Re: Flicker
Post by: daydreamer on June 20, 2005, 04:56:29 PM
why not use bresenhams circlealgo instead?
Title: Re: Flicker
Post by: RuiLoureiro on June 20, 2005, 10:52:51 PM
Hi Farabi, i dont know if i am able to help you!
           Here are some topics about the case. I am trying to understand the problem itself, so

1.    sin(x + 360) = sin(x), cos(x + 360) = cos(x) , tan(x + 360) = tan(x)

2.    Here, why    «add ecx, 4     ; 1 Clock cycle»  ?

add deg,1 ; 3 Clock cycle
add esi,4 ; 1 Clock cycle
add ecx,4 ; 1 Clock cycle
cmp deg,3600 ; 2 Clock cycle
jl  @b ; 3 Clock cycle

ECX is not used between @@ and jl @B (i thk it is not used, but ...):

@@:   finit
      ...
      cmp  deg, 3600
      jl   @B
;-------------------------------------------------------
3.     mov    edx, 3600
       shl    edx, 2
could be           
       mov   edx, 14 400
;--------------------------------------------------------
4.     The proc  Phase1  create a table of functions SIN(deg), COS(deg) and
       TAN(deg) ( deg is the angle in degrees ) in this way:

SCTbl      dd  sin 0         <- Address = SCTbl             SCTblSin
           dd  sin 1
           ...
           dd  sin 3 599      ; 3 600 dwords = 14 400 bytes
           ;
           dd  cos 0                <- Address = SCTbl + 14 400   SCTblCos 
           dd  cos 1
           ...
           dd  cos 3 599
           ;
           dd  tan 0                <- Address = SCTbl + 28 800   SCTblTan
           dd  tan 1
           ...
           dd  tan 3 599
           ;
                                   <- Address = SCTbl + 43 200 

where you have
           mov   SCTbl, eax
would be
           mov   SCTblSin, eax
           add   eax, 14 400
           mov   SCTblCos, eax
           add   eax, 14 400
           mov   SCTblTan, eax
implying


GetSin proc uses esi deg:dword
mov esi, SCTblSin
mov ecx,deg
mov eax,dword ptr[esi+ecx*4]
ret
GetSin endp
;...................................................
GetCos proc uses esi deg:dword
mov esi, SCTblCos
mov ecx,deg
mov eax,dword ptr[esi+ecx*4]
ret
GetCos endp
;...............................................
GetTan proc uses esi deg:dword
mov esi, SCTblTan
mov ecx,deg
       mov eax,dword ptr[esi+ecx*4]
ret
GetTan endp

;-------------------------------------------------------------------------------
5.   If this code


push eax
fld dword ptr[esp]
pop eax
fimul delta
fistp r_cos


      is replaced with this code


xor edx, edx
mov ecx, delta
mul ecx
mov ecx, 1000
div ecx
mov eax, r_cos

       the var «r_cos»  is not defined . The value is not valid. The proc would be:


UMGetPosRound proc uses esi delta:dword,deg:dword ; 138 Clock cycle
LOCAL r_sin,r_cos:dword

cmp deg,3600
jl  @f

      sub deg,3600
      ;
      ; Get Sin[deg] in EAX
      ; -------------------
@@:     invoke GetSin, deg
;                   calculate r_sin
xor edx,edx
mov ecx,delta
mul ecx
mov ecx,1000
div ecx
mov eax,r_sin  ; <= ERROR     => change      mov   r_sin , eax
;      push   eax                                                     ; r_sin
      ;
      ; Get Cos[deg] in EAX
      ; -------------------
           invoke GetCos, deg
      ;                                   calculate r_cos
xor edx,edx
mov ecx,delta
mul ecx
mov ecx,1000
div ecx
mov eax,r_cos     ; <= ERROR   => change      mov    r_cos, eax
      ;
      ; Return r_sin and r_cos
      ; ----------------------
;    pop  edx                       ; r_sin
mov edx, r_sin
mov eax, r_cos
ret
UMGetPosRound endp

If we use push  eax and pop  edx then we dont need mov  edx, r_sin and mov eax, r_cos.
Is this right ? That's all.
stay well
ポ    ゼ      チ
Title: Re: Flicker
Post by: Farabi on June 21, 2005, 03:24:05 AM
Quote from: daydreamer on June 20, 2005, 04:56:29 PM
why not use bresenhams circlealgo instead?


Because I dont understand. IS there any of the ready to use MASM code for that?
Title: Re: Flicker
Post by: Farabi on June 21, 2005, 03:27:47 AM
Quote
if we use push  eax and pop  edx then we dont need mov  edx, r_sin and mov eax, r_cos.
Is this right ? That's all.

Yes you are right.

Quote
mov eax,r_sin  ; <= ERROR     => change      mov   r_sin , eax
;      push   eax                                                     ; r_sin

This is right too. Im just know it this morning. I think you have understand.  :U
Title: Re: Flicker
Post by: daydreamer on June 21, 2005, 05:38:18 AM
Quote from: Farabi on June 21, 2005, 03:24:05 AM
Quote from: daydreamer on June 20, 2005, 04:56:29 PM
why not use bresenhams circlealgo instead?


Because I dont understand. IS there any of the ready to use MASM code for that?
there is, you can just need to change it from using 16-bit registers, download the Gbook and code examples are included to understand several line algos, and circle algo, clipping algo
http://www.rbthomas.freeserve.co.uk/Downloads.html

Title: Re: Flicker
Post by: Farabi on June 22, 2005, 01:13:49 AM
So is the the problem solved? Why it crash?
Title: Re: Flicker
Post by: Farabi on June 23, 2005, 12:05:18 PM
Crash on Win98, annoying error. I cannot close it. Why it run on XP but not on Win98. I dont have Win98 here.