Proper coding for Vsync or similar functionality

Anything QL Software or Programming Related.
User avatar
grafvonb
Bent Pin Expansion Port
Posts: 80
Joined: Sat Jan 05, 2019 7:54 am
Location: Frankfurt/Germany

Proper coding for Vsync or similar functionality

Post by grafvonb »

For my small assembler demo "bouncing lines" I need a Vsync or similar functionality to slow down the loop and get stable redraw of the screen.
I tried the described solution brought by https://www.chibiakumas.com/68000/sinclairql.php:

Code: Select all

waitVBlank
        move.b #%11111111,$18021    ;Clear interrupt bits
waitVBlankAgain
        move.b $18021,d0            ;Read in interrupt state
        tst.b d0                    ;Wait for an interrupt
        beq waitVBlankAgain
        rts
It works with Qemulator (however very notchy).
With a real QL it does not work at all regardless the ROM version (tested with Minerva and MGG).

What is the best way to solve it? How do/did this the guys in the games/demos (as a part of "game/demo loop")?


Loving QL & ZX Spectrum & Amiga...
User avatar
tofro
Font of All Knowledge
Posts: 2700
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: Proper coding for Vsync or similar functionality

Post by tofro »

I dived into that when I worked on the Magnetic Scrolls port and can tell you the following:

Working or not working has obviously nothing to do with the ROM version (you're not using the ROM at all in the loop).

To get a 100% stable sync with the display, you need to enter supervisor mode and switch off interrupts - otherwise, the toggling of the timer interrupt bit in the interrupt register will cause QDOS to enter the scheduler before it even runs the loop, with all sorts of things happening that could or could not affect your timing (but very probably will).

Next, your loop doesn't test for blanking, but rather any interrupt - You should test only bit #3 instead of all bits, otherwise you'll catch various possible disturbances on expanded machines.

My code looks like that:

Code: Select all

        bset    #3,PC_INTR
intLp   move.b  PC_INTR,d1              ; wait for (any) interrupt
        btst    #3,d1
        beq     intLp                   ; no, busy wait

        
and syncs pretty well with the display.

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
grafvonb
Bent Pin Expansion Port
Posts: 80
Joined: Sat Jan 05, 2019 7:54 am
Location: Frankfurt/Germany

Re: Proper coding for Vsync or similar functionality

Post by grafvonb »

Hi Tobias, many thanks for your fast and great response!

However my problem still remains. In Qemulator my code works, using a real QL the sync does not (it flickers as it would be without the sync).

Here my code example:

Code: Select all

SCREEN  equ     $20000
PC_INTR equ     $18021

repeat  lea     sinus,a5
        lea     SCREEN,a6
loop    move.l  a6,a0
        move.l  blue,d0
        bsr     draw_ln
        lea     SCREEN,a6
        clr.w   d2
        move.b  (a5)+,d2
        cmpi    #$ff,d2
        beq     repeat        
        mulu    #$80,d2
        adda.l  d2,a6
        move.l  a6,a0
        move.l  white,d0
        bsr     draw_ln

        bset    #3,PC_INTR
intLp   move.b  PC_INTR,d1              ; wait for (any) interrupt
        btst    #3,d1
        beq     intLp                   ; no, busy wait

        jmp     loop

draw_ln 
        move.l  a0,a1
        moveq   #$1f,d1
draw_ln_loop    
        move.l  d0,(a1)+
        dbeq    d1,draw_ln_loop
        rts

waitVBlank
        move.b #%11111111,$18021    ;Clear interrupt bits
waitVBlankAgain
        move.b $18021,d0            ;Read in interrupt state
        tst.b d0                    ;Wait for an interrupt
        beq waitVBlankAgain
        rts

black:  dc.l    %00000000000000000000000000000000   ;line of 8-points black
blue:   dc.l    %00000000010101010000000001010101   ;line of 8-points blue
white:  dc.l    %10101010111111111010101011111111   ;line of 8-points white

sinus:  dc.b    $32,$34,$35,$37,$39,$3b,$3c,$3e
        dc.b    $40,$41,$43,$45,$46,$48,$49,$4b
        dc.b    $4c,$4e,$4f,$51,$52,$53,$55,$56
        dc.b    $57,$58,$59,$5a,$5b,$5c,$5d,$5e
        dc.b    $5f,$60,$60,$61,$62,$62,$63,$63
        dc.b    $63,$64,$64,$64,$64,$64,$64,$64
        dc.b    $64,$64,$63,$63,$63,$62,$62,$61
        dc.b    $60,$60,$5f,$5e,$5d,$5c,$5b,$5a
        dc.b    $59,$58,$57,$56,$55,$53,$52,$51
        dc.b    $4f,$4e,$4c,$4b,$49,$48,$46,$45
        dc.b    $43,$41,$40,$3e,$3c,$3b,$39,$37
        dc.b    $35,$34,$32,$30,$2f,$2d,$2b,$29
        dc.b    $28,$26,$24,$23,$21,$1f,$1e,$1c
        dc.b    $1b,$19,$18,$16,$15,$13,$12,$11
        dc.b    $f,$e,$d,$c,$b,$a,$9,$8
        dc.b    $7,$6,$5,$4,$4,$3,$2,$2
        dc.b    $1,$1,$1,$0,$0,$0,$0,$0
        dc.b    $0,$0,$0,$0,$1,$1,$1,$2
        dc.b    $2,$3,$4,$4,$5,$6,$7,$8
        dc.b    $9,$a,$b,$c,$d,$e,$f,$11
        dc.b    $12,$13,$15,$16,$18,$19,$1b,$1c
        dc.b    $1e,$1f,$21,$23,$24,$26,$28,$29
        dc.b    $2b,$2d,$2f,$30,$32
        dc.b    $ff
Last edited by grafvonb on Fri Feb 14, 2020 5:40 am, edited 1 time in total.


Loving QL & ZX Spectrum & Amiga...
User avatar
grafvonb
Bent Pin Expansion Port
Posts: 80
Joined: Sat Jan 05, 2019 7:54 am
Location: Frankfurt/Germany

Re: Proper coding for Vsync or similar functionality

Post by grafvonb »

To get a 100% stable sync with the display, you need to enter supervisor mode and switch off interrupts - otherwise, the toggling of the timer interrupt bit in the interrupt register will cause QDOS to enter the scheduler before it even runs the loop, with all sorts of things happening that could or could not affect your timing (but very probably will).
Ah, this is probably the reason, isn't it?


Loving QL & ZX Spectrum & Amiga...
User avatar
tofro
Font of All Knowledge
Posts: 2700
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: Proper coding for Vsync or similar functionality

Post by tofro »

grafvonb wrote:
To get a 100% stable sync with the display, you need to enter supervisor mode and switch off interrupts - otherwise, the toggling of the timer interrupt bit in the interrupt register will cause QDOS to enter the scheduler before it even runs the loop, with all sorts of things happening that could or could not affect your timing (but very probably will).
Ah, this is probably the reason, isn't it?

Of course. QDOS being a multi-tasking OS will do all sorts of things in the timer interrupt that disturb your timing if you allow it to.

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
grafvonb
Bent Pin Expansion Port
Posts: 80
Joined: Sat Jan 05, 2019 7:54 am
Location: Frankfurt/Germany

Re: Proper coding for Vsync or similar functionality

Post by grafvonb »

Entering super mode with trap #0, as I understand. But I cannot find a code snippet to switch off interrupts. Can you help me?


Loving QL & ZX Spectrum & Amiga...
User avatar
NormanDunbar
Forum Moderator
Posts: 2273
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: Proper coding for Vsync or similar functionality

Post by NormanDunbar »

grafvonb wrote:Entering super mode with trap #0, as I understand. But I cannot find a code snippet to switch off interrupts. Can you help me?
http://qdosmsq.dunbar-it.co.uk/doku.php ... ap_0:start might help. ;)

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
grafvonb
Bent Pin Expansion Port
Posts: 80
Joined: Sat Jan 05, 2019 7:54 am
Location: Frankfurt/Germany

Re: Proper coding for Vsync or similar functionality

Post by grafvonb »

Thanks, I have found this great side too. Surprisingly the following code:

Code: Select all

        trap    #0
        ori     #%0000011100000000,sr

helped to run the code above smoothly using Qemulator, however my problem with the real QL remains as it was (the sync does not work).


Loving QL & ZX Spectrum & Amiga...
User avatar
M68008
Trump Card
Posts: 224
Joined: Sat Jan 29, 2011 1:55 am
Contact:

Re: Proper coding for Vsync or similar functionality

Post by M68008 »

grafvonb wrote:Thanks, I have found this great side too. Surprisingly the following code:

Code: Select all

        trap    #0
        ori     #%0000011100000000,sr

helped to run the code above smoothly using Qemulator, however my problem with the real QL remains as it was (the sync does not work).
Yes, this disables the interrupts. It's a good way to get all the processor time for your program.
With your vsync mechanism, this also prevents the OS from intercepting and clearing the interrupt before you detect it.

Avoid Minerva and use the MGG you have. It doesn't matter for now since you disable the OS, but it can cause problems if later you decide to call the OS for sound or reading the keyboard. See https://qemulator.blogspot.com/2013/04/ ... games.html.


User avatar
M68008
Trump Card
Posts: 224
Joined: Sat Jan 29, 2011 1:55 am
Contact:

Re: Proper coding for Vsync or similar functionality

Post by M68008 »

grafvonb wrote:however my problem with the real QL remains as it was (the sync does not work).
The code you posted should work fine, just make sure you add the instructions to disable the interrupts at the beginning.


Post Reply