Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!tut.cis.ohio-state.edu!ucbvax!husc6!brauer!fry From: fry@brauer.harvard.edu (D. Spotts Fry) Newsgroups: comp.sys.mac.programmer Subject: Re: Animation Questions Keywords: CopyBits, VBlank Message-ID: <2851@husc6.harvard.edu> Date: 14 Oct 89 04:05:14 GMT References: <3123@crdgw1.crd.ge.com> <10611@claris.com> <34698@srcsip.UUCP> Sender: news@husc6.harvard.edu Organization: Harvard Math Department Lines: 161 To do synched drawing on a Mac II, you want to use a technique analagous to that of watching TickCount() on the MacPlus, but you have to make your own VBL counter. This should be done with VBLTask tied to the video slot so you really get video synching. To illustrate this, here is some code (in Think C): Dave /* my globals */ extern long VBLcounter; extern short videoSlot; extern VBLTask drawtask; /**************************************************************** Before we do anything, we have to know which slot the card is in. Use this routine. (See Start Manager in IM V.) */ FindVideoSlot() { DefVideoRec defvidrec; GetVideoDefault(&defvidrec); videoSlot = defvidrec.sdSlot; } /******************************************************************* Then we have to install a VBL Task. This is the one I'll use. To use global variables you must setup the A5 register. To do this in MultiFinder requires a special trick, which is demonstrated with the CacheA5 function. */ pascal void ScreenDrawTask() { /* * WARNING! - this is self-modifying code, but it is * necessary to run under MultiFinder...see Tech Note 180 */ long oldA5; asm { move.l a5,oldA5 move.l #0,a5 ; this will be replaced with ; CurrentA5 by the CacheA5 function at runtime } VBLcounter += 1; drawtask.vblCount = 1; asm { move.l oldA5,a5 } } pascal void CacheA5(addr) long addr; /* * This function will place CurrentA5 into the beginning of task * functions which start as: * pascal void FooTask() * { * long junk; * * asm { * move.l a5,junk * move.l #0,a5 ;this will be replaced by CurrentA5 * .... * * See Tech Note #180 */ { asm { move.l addr,a0 add.w #2,a0 ; move past JMP instruction move.l (a0),a0 add.w #0xa,a0 ; move past first part of function move.l CurrentA5,(a0) ; puts CurrentA5 in (*addr)() dc.l location } } /**************************************************************** This function actually sets up the VBL Task. */ StartCounter() { CacheA5(ScreenDrawTask); VBLcounter = 0; drawtask.vblAddr = ScreenDrawTask; drawtask.qType = vType; drawtask.vblCount = 1; drawtask.vblPhase = 0; SlotVInstall(&drawtask,videoSlot); } /********************************************************************* This function removes the VBL Task. */ RemoveCounter() { SlotVRemove(&drawtask,videoSlot); } /********************************************************************* This function holds everything until it's time to draw. Note that it could be replaced by a #define macro (make VBLjunk a global). */ WAIT_FOR_SCREEN() { long VBLjunk; VBLjunk = VBLcounter; do {} while ( VBLcounter == VBLjunk ); /* this is used to synch drawing to screen */ } /******************************************************************** Now, putting this altogether into a program */ main() { /* do your init stuff */ FindVideoSlot(); StartCounter(); /* now, whenever you want to draw something, do this... */ WAIT_FOR_SCREEN(); DrawMyThing(); /* when you're done...*/ RemoveCounter(); }