chaffee@reed.UUCP (Alex Chaffee) (03/02/91)
In the UMPG, there's some code for installing a task on the VBL queue. It sez: Subject:.c2.Sync Drawing (with Code) To do synched drawing on a Mac II, you want to use a technique analogous 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. This is true. The author (Dave) provided some code for doing this. Unfortunately, he used a technique which is clearly taboo - self-modifying code. Here's code for a safer way to do the same thing. It's based on tech note #180; MPW programmers should consult that note to convert my asm{} code into the GetA5() macros. Note that this doesn't deal with multiple monitors or checking for the existence of color quickdraw (which is, I believe, required for the GetVideoDefault call). It's not dangerous to leave the task running, as it gets swapped out by Multifinder. Usage: #include "sync.h" InstallSync(); ... WaitForSync(); CopyBits(...); ... RemoveSync(); --- File: sync.h --- /* Sync.h */ /* Exported Variables */ extern long vCounter; /* just like Ticks - incremented every refresh */ /* Macros/Prototypes */ void InstallSync(void); void RemoveSync(void); void WaitForSync (void); static long vblJunk; #define WaitForSync() vblJunk = vCounter; do {} while (vblJunk == vCounter); --- File: Sync.c --- /* Sync.c Implements a VBL counter (like Ticks) on any Mac. Usage: #include "sync.h" InstallSync(); ... WaitForSync(); CopyBits(...); ... RemoveSync(); Author: Alex Chaffee (chaffee@reed.bitnet) */ #include "Sync.h" /* Types */ typedef struct { long goodA5; VBLTask task; } MYVBLTASK; /* Globals */ long vCounter; static MYVBLTASK mytask; static DefVideoRec video; /* Prototypes */ static pascal void Task(void); /* Task */ static pascal void Task(void) { long oldA5; MYVBLTASK vbltask; asm { move.l A5,oldA5 ; save off the old value of A5 move.l -4(A0), A5 ; A0 points to our VBL task record, and earlier we ; saved CurrentA5 near it } vCounter++; mytask.task.vblCount = 1; /* we want to run again real soon */ asm { move.l oldA5,A5 } } /* InstallSync */ void InstallSync(void) { GetVideoDefault(&video); mytask.goodA5 = (long)CurrentA5; vCounter = 0; mytask.task.qType = vType; mytask.task.vblAddr = (ProcPtr) Task; mytask.task.vblCount = 1; mytask.task.vblPhase = 0; SlotVInstall(&mytask.task, video.sdSlot); } void RemoveSync(void) { SlotVRemove(&mytask.task, video.sdSlot); } /* If you don't want to use the macro, uncomment this function */ /* void WaitForSync (void) { long vJunk = vCounter; do {} while ( vCounter == vJunk ); } */ --------------- Alex Chaffee chaffee@reed.{UUCP,BITNET} Reed College, Portland OR 97202 ____________________ -- Alex Chaffee chaffee@reed.{UUCP,BITNET} Reed College, Portland OR 97202 ____________________