From: klassa@aurs01.UUCP (John M. Klassa)
Newsgroups: comp.sys.atari.st.tech
Subject: RE: counting vblanks on TT
Keywords: vblanks, TT
Date: 1 Oct 92 10:44:34 GMT
Reply-To: klassa%aurfs1.aur.alcatel.com@rockdal.aud.alcatel.com (John Klassa)
Followup-To: comp.sys.atari.st.tech
Organization: Alcatel Network Systems, Raleigh NC

Someone wrote me and suggested that I explain my situation a little
more...  Here's an edited version of my response to them.

The topic is: "Why does a method of timing that uses the system vblank
counter work on an ST but, seemingly, fail on a TT?"

The scenario: I'm writing a LodeRunner-type game.  The game is set up
so that it can handle a variable number of adversary "sprites."  I
wanted to be sure that all of my processing was getting done in under
3 or 4 vblanks (I don't remember which), so I put in some code to
check things & let me know if I ever ran over the amount of time I
wanted to stay under.  If so, I figured I'd just reduce the number of
adversaries until I got to a point where I never saw the "you're out
of time" message.

The game stores the vblank count, does some processing, then compares
the current vblank count with the one it stored away.  If the
difference is greater than some threshhold (like 3 or 4), the game
displays a message to the effect that it couldn't process everything
it needed to within the amount of time (3 or 4 vblanks) allotted to
it.

Specifics...

I've got the following #define's:

#define VBLANKS     Supexec(get_vbl_count)  /* as per my first message on */
					    /* this topic                 */

#define TO_FRONT(x) { Setscreen(screen_buf[!x], screen_buf[x], -1); Vsync(); }

#define TIMING      3  /* the number of vblanks per update, minus 1 */

I've got an unsigned long variable I call old_vblanks.

I've got a function called restore_screen() which Setscreen()'s physbase
and logbase back to what they were when the game started.

In main(), I've got something kind of like:

	main()
	{
	  init_everything();

	  old_vblanks = VBLANKS;         /* store the old count away... */

	  while (!kbhit()) {
	    iterate();
	  }
	}

In the iterate() code, I've got:

	iterate()
	{

	  /* stuff to restore the background */
	  /* stuff to save the background away for this iteration */
	  /* stuff to update positions */
	  /* stuff to determine new positions for everything */
	  /* stuff to draw everything at new positions */

	  /* and then (and this is right out of my code): */
	
	  if (VBLANKS - old_vblanks > TIMING) {
	    restore_screen();
	    printf("\nvblank timing not sufficient...");
	    while (!kbhit()) {}
	    getch();
	  }

	  while (VBLANKS - old_vblanks < TIMING) {}

	  TO_FRONT(pulse);              /* pulse keeps track of whether I'm
					   writing to screen 0 or screen 1;
					   Warwick used this name in a
					   msg to me & I liked it so much
					   I kept it...  :-) */
  
	  old_vblanks = VBLANKS;

	  pulse = !pulse;

	  return;
	}

What happens, you ask?  On a vintage, 8 MHz 1040 ST, I can run the
thing with 7 adversaries & never see the "timing not sufficient"
message.  On a TT, I get the message immediately, and continually,
until I exit the game.

One possibility is that, for some odd reason, the kbhit() call in main()'s
while loop (which occurs once before the first call to iterate()) takes
extremely long to complete on a TT...  And because it does, the

	(VBLANKS - old_vblanks > TIMING)

check in iterate() causes the "timing not sufficient" message to appear.

Another possibility is that my restore / save / update / redraw code
(in iterate()) takes longer on a TT.  I find this hard to believe,
though...  Especially since I ran the game with just one adversary
(it's a LodeRunner-type game, in case you're wondering) on the TT &
still got the message.  With just one adversary, there's almost
nothing to do in the restore / save / update / redraw code.  And like
I said, I ran the *same* code on a vintage 1040ST, with 7 (SEVEN)
adversaries -- MUCH, MUCH more to do in restore / save / update /
redraw code -- and didn't see the message.

As a benchmark, an earlier version of the game didn't care about vblanks.
It simply did what it did, then called Setscreen() / Vsync() whenever it
was ready.  It had the same kbhit() call in the while loop in main()...  On
that version, the TT would handle 7 adversaries in under one vblank (i.e.
the game speed was the same with 7 adversaries as it was with just 1), and
you wouldn't see a slowdown until you added the 8th one.  On a vintage ST,
you'd see a slowdown with just 2 adversaries.  i.e. the TT flies through
the kind of code this thing uses, so it *really* doesn't make sense that my
vblank timer craps out in this latest version of my game...

Any clues?  Is there anything a TT does worse than an ST, that I might have
inadvertently used in this latest version of my game?  Does it make a
difference that I didn't compile the game on a TT?  It wouldn't make any
sense if it did make a difference, but at this point I'm just grasping at
straws.

Any advice greatly appreciated...

Thanks!
John

BTW -- I'm using Heat & Serve C (Ian Lepore's version of Sozobon C), if
       that matters...

 o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
 o                               John M. Klassa                              o
 o      Alcatel Network Systems, Inc. --- Raleigh, NC --- (919) 850-1246     o
 o        Email: klassa%aurfs1.aur.alcatel.com@rockdal.aud.alcatel.com       o
 o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o