[comp.sys.mac.programmer] Mac II retrace manager and Tick Counts

thomas@eleazar.dartmouth.edu (Thomas Summerall) (09/11/90)

In the never ending quest for smooth animation on the mac, Mac Plus
programmers have one friend:  the tick count coincides with the vertical
retrace period so that programmers can use

tickvalue:=TickCount                  {tickvalue is a LongInt}
repeat until (tickvalue<>TickCount)

to tell them when a new blanking period occurs.  This allows them to simulate
an interrupt driven routine without the headaches caused by interrupt routines.
(ie they can't rely on unlocked handles, etc, because they don't know what the
momory manager might have been doing when the interrupt occured)

Is there anyway to simulate this on the Mac II?  Does the apple video card
generate a tick of some kind?  I just don't have enough experience to know what
I can and can't do in an interrupt driven SlotVInstall routine, and I don't
want to find out by trial and error if I don't have to...

Thanks,
Thomas Summerall

russotto@eng.umd.edu (Matthew T. Russotto) (09/11/90)

In article <24126@dartvax.Dartmouth.EDU> thomas@eleazar.dartmouth.edu (Thomas Summerall) writes:

>I can and can't do in an interrupt driven SlotVInstall routine, and I don't
>want to find out by trial and error if I don't have to...

Use SlotVInstall anyway.  All you have to do is increment one of your own
variables as soon as it your routine is called-- there are various tricks
to getting access to global data from an interrupt routine, I think the
easiest way is to stick extra bytes off the end of the VBL header.  Then,
in the main program, use the same logic, but instead of while (TickCount()...,
use while (myvbl.myvar...)

stephen@cs.uow.edu.au (The Mighty Ogbo) (09/12/90)

thomas@eleazar.dartmouth.edu (Thomas Summerall) writes:

>	[Old way deleted]

>Is there anyway to simulate this on the Mac II?  Does the apple video card
>generate a tick of some kind?  I just don't have enough experience to know what
>I can and can't do in an interrupt driven SlotVInstall routine, and I don't
>want to find out by trial and error if I don't have to...

Have a look in one of the latest MacTutors. It shows how to set up a SlotV
routine, with full Pascal code - easily translated to C if you need - and
the actual call where you use it in the main program is actually quite
simple.

The MacTutor issue is May 1990.

|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Stephen Nicholson (The Mighty Ogbo)                stephen@wraith.cs.uow.edu.au
"Rooster of a Fightin' Stock / Would you let a Saecsen cock
Crow out upon an Irish Rock  / Fly up an teach him manners!" - Planxty
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

jmunkki@hila.hut.fi (Juri Munkki) (09/12/90)

In article <1990Sep12.064502.16870@cs.uow.edu.au> stephen@cs.uow.edu.au (The Mighty Ogbo) writes:
>thomas@eleazar.dartmouth.edu (Thomas Summerall) writes:
>
>>	[Old way deleted]
>
>>Is there anyway to simulate this on the Mac II?  Does the apple video card
>>generate a tick of some kind?  I just don't have enough experience to know what
>>I can and can't do in an interrupt driven SlotVInstall routine, and I don't
>>want to find out by trial and error if I don't have to...
>
>Have a look in one of the latest MacTutors. It shows how to set up a SlotV
>routine, with full Pascal code - easily translated to C if you need - and
>the actual call where you use it in the main program is actually quite
>simple.

Here's something I wrote for the Sega 3D glasses. I have edited out some
parts of it and it only installs a vbl task for the main display. The code
is in Think C and depends on the inline assembler, so it might not be easy
to port to other compilers.

#include <VRetraceMgr.h>

typedef	struct
{
	int	theslot;	/*  Slot number			*/
	int	ticker;		/*  A counter			*/
	int	called;		/*  A flag			*/
	VBLTask	VBL;		/*  VBLTask entry		*/
	long	RealA5;		/*  A5 saved here.		*/
}	VVars;

/*
>>	If A5 points to a VVars structure, the following macro will become
>>	xx(A5), where xx is the offset into that structure element.
*/
#define VBV(field)		((int) &((VVars *) 0)->field)(A5)

/*
>>	SetUpVBLTask contains and sets up a VBL task that
>>	acts as a clock and sets a flag every time through.
>>	It also calls a dirty blitter routine if a flag is
>>	set. Calling the dirty blitter should be an option,
>>	since it might crash any time...
*/
void	SetUpVBLTask()
{
	GDHandle	MainDisplay;
	AuxDCEHandle	DisplayDriver;
	SysEnvRec	theWorld;
	
	long	vbltask;

	asm {
	lea	@myvbltask,A0	;	Get address of vbltask
	move.l	A0,vbltask	;	Store in local variable
	lea	@mybase,A0	;	Get addr of variable base storage
	lea	Vv,A1		;	Get addr of Vv record
	move.l	A1,(A0)		;	Store base in base storage
	move.l	A5,Vv.RealA5
	}

	SysEnvirons(1,&theWorld);	/*  Where are we running?	*/

	Vv.VBL.qType=vType;		/*  Vertical blanking queue.	*/
	Vv.VBL.vblAddr=(ProcPtr)vbltask;/*  Address of task		*/
	Vv.VBL.vblCount=1;		/*  Every tick			*/
	Vv.VBL.vblPhase=0;		/*  0 is ok..			*/

	if(theWorld.hasColorQD)		/*  Possibly more than one monitor?*/
	{	MainDisplay=GetMainDevice();
			/*	Can't handle more than one...		*/
		DisplayDriver=(void *)GetDCtlEntry((*MainDisplay)->gdRefNum);
		Vv.theslot=(*DisplayDriver)->dCtlSlot;
		SlotVInstall(&Vv.VBL,Vv.theslot);
			/*	Use main display VBL queue.		*/
	}
	else
	{	VInstall(&Vv.VBL);	/*  Install task in queue	*/
	}
	return;
	
/*
>>	This is the actual VBL task that gets executed.
>>	It just increments a counter and sets a flag
>>	every time it's called.
*/
asm	{
@myvbltask
	move.l	A5,-(SP)	;	Save A5
	move.l	@mybase,A5	;	Get Vv address into A5
	move.w	#1,VBV(VBL.vblCount)	;	Call again.
	move.w	#1,VBV(called)	;	Flag screen blank
	add.w	#1,VBV(ticker)	;	add one to counter
	
	move.l	(sp)+,A5
	rts
@mybase
	dc.l	0		;	Vv record address stored here.

	}
}

If you need to call one of your own routines that needs access to global
variables, put it before you restore A5 and add the following line before
it:
	move.l	VBV(RealA5),A5

Before you quit the application, you should call the following routine
to remove the VBL task:

	if(theWorld.hasColorQD)
		SlotVRemove(&Vv.VBL,Vv.theslot);
	else
		VRemove(&Vv.VBL);

I hope I remembered to include all the necessary parts.

   ____________________________________________________________________________
  / Juri Munkki	    /  Helsinki University of Technology   /  Wind  / Project /
 / jmunkki@hut.fi  /  Computing Center Macintosh Support  /  Surf  /  STORM  /
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~