From: dmb@wam.umd.edu (David M. Baggett)
Subject: Re: Is page flipping safe, and I need to know about syncing
		<1992Jul23.184657.5699@wam.umd.edu>
		<1992Jul23.222019.27222@infoserver.th-darmstadt.de>
Organization: University of Maryland, College Park
Date: Fri, 24 Jul 1992 14:43:40 GMT

wallmann@backus.pu.informatik.th-darmstadt.de (Natuerlich!) writes:
>dmb@wam.umd.edu (David M. Baggett) writes:
>>The Setscreen and Vsync (X)Bios calls work fine for double buffering
>>(aka "page flipping").  There are some subtleties but for most
>>practical purposes you'll get good results using these calls and your
>>code will work with all versions of TOS (including, in theory, those
>For most practical purposes you do get good results with this.
>
>BUT: the disadvantage is that you don't have precision page flipping. It 
>just may happen that on screen1 you are done drawing in 2 screens and flip 
>then, while on screen2 you need 3 screens. The net effect of that would
>be that if your flip rate is 4 that screen 1 will be displayed 5 VBIs, where 
>screen2 will be displayed only for 3 VBIs.

Nat! is right and has pointed out the "subtlety" I alluded to.  In
practice it doesn't make a whole lot of difference since you don't
often find a game that goes 3, 2, 3, 2, 3, 2 consistently enough to
look jerky; the priciple of locality tends to hold in game timing as
well as it does in the rest of the computer world, and so you usually
find that your game will run something more along the lines of 4, 4, 4,
4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, ...

It isn't so much a problem with the vsync counting code as with
Setscreen.  Remember that you don't wait _exactly_ n vertical retraces
each game turn; you wait long enough to ensure that _at least_ n
vertical retraces have happened since the last game turn.  Assuming n
is 4, your example would work out as follows:

frclock	screen	frames req.	condition to wait on	#frames to wait

1000	1	2		frclock >= 1004		1004-1002 = 2
1004	2	3		frclock >= 1008		1008-1007 = 1
1008	1	2		frclock >= 1012		1012-1010 = 2

screen one is visible through the period from 1004 to 1008, during the
time screen two is being computed and drawn to, which includes the
1-frame wait starting at 1007.

screen two is visible through the period from 1008 to 1012, during the
time screen 1 is being being computed and drawn to, which includes the
2-frame wait starting at 1010.

The vsyncing algorithm I described simply adapts itself dynamically to
the CPU requirements of the game.

The problem is that Setscreen sets the screen as soon as the *next*
vblank comes around.  Nat!'s right in thinking that you need to wait
until the end of your ~n vertical retrace waits to set the actual
screen pointer.  One way around this is to call the adaptive vsync
routine with n-1, then call Setscreen, and then call Vsync().  Then
you're still OK with respect to the cross-machine compatibilty but your
timing is exact.

>If your game nears completion and you are not 100% satisfied with the
>animation I'd suggest that you use the VBL directly to flip pages (you
>can use Setscreen()) there too.  Until then Setscreen() + Vsync() +
>frclock will suffice.

Calling Setscreen from an interupt seems very dodgy to me.  It may
work now, but I wouldn't count on it working forever.

Dave Baggett
dmb@wam.umd.edu
Newsgroups: comp.sys.atari.st.tech