/* Movie Crawl * started on August 11th 2022 * Copyright Michael Juneau, 1Bit Fever Dreams */ #define DELAY 5 typedef struct { TMTask atmTask; long tmRefCon; } TMInfo; typedef TMInfo *TMInfoPtr; typedef struct { StringHandle str; short index; short initIndex; Boolean firstTime; } aTextLine; typedef aTextLine *aTextLinePtr; short size = 28; //biggest font size at the bottom short index = 342; //loop control variable Boolean firstTime = true; Boolean resumeLoop = false; aTextLinePtr myText; TMInfo myTMInfo; void InstallTMTask(void); pascal TMInfoPtr GetTMInfo(void); pascal void MyTask(void); void doCrawl(int whichLine); int findSize(int i); void loadMyText(void); void installTMTask() //Prepping the task record and installing it for the first time { myTMInfo.atmTask.tmAddr = MyTask; myTMInfo.atmTask.tmWakeUp = 0; myTMInfo.atmTask.tmReserved = 0; myTMInfo.tmRefCon = SetCurrentA5(); InsTime((QElemPtr) &myTMInfo); PrimeTime((QElemPtr) &myTMInfo, DELAY); } pascal TMInfoPtr GetTMInfo(void) //equivalent to MOVE.L A1,(SP) = 0x2E89; pascal void MyTask() //the task's only purpose is to greenlight the movie crawl update to proceed by setting this global flag { long oldA5; TMInfoPtr recPtr; recPtr = GetTMInfo(); oldA5 = SetA5(recPtr->tmRefCon); if(resumeLoop == false) resumeLoop = true; oldA5 = SetA5(oldA5); PrimeTime((QElemPtr) recPtr, DELAY); } int findSize(int i) //used to figure out the font size, bigger in the bottom, smaller on top { return size-(342-i)/17; } void doCrawl(int whichLine) //manage the movie crawl graphics, heart of this program { short predictWidth; if(myText[whichLine].index <= 342) //only bother displaying if onscreen { if(myText[whichLine].index != 342) //erase the previous position { TextSize(findSize(myText[whichLine].index+1)); predictWidth = StringWidth(*(myText[whichLine].str)); MoveTo((512-predictWidth)/2,myText[whichLine].index+1); DrawString(*(myText[whichLine].str)); } if(myText[whichLine].index == 342 && myText[whichLine].firstTime == false) //erase topmost position if restarting at the bottom { TextSize(findSize(size)); predictWidth = StringWidth(*(myText[whichLine].str)); MoveTo((512-predictWidth)/2,size); DrawString(*(myText[whichLine].str)); } TextSize(findSize(myText[whichLine].index)); predictWidth = StringWidth(*(myText[whichLine].str)); MoveTo((512-predictWidth)/2,myText[whichLine].index); DrawString(*(myText[whichLine].str)); myText[whichLine].firstTime = false; } myText[whichLine].index--; if(myText[whichLine].index < size) myText[whichLine].index=342; //loop back once the top position has been passed } void loadMyText() { myText = (aTextLinePtr)NewPtr(3*sizeof(aTextLine)); myText[0].str = NewString("\pLong live Eric Helgeson's Mac C Club!"); myText[1].str = NewString("\pCoding in Macintosh THINK C is the best."); myText[2].str = NewString("\pVisit 1Bit Fever Dreams on YouTube."); myText[0].index = myText[0].initIndex = 342; myText[1].index = myText[1].initIndex = 342 + 28; myText[2].index = myText[2].initIndex = 342 + 56; myText[0].firstTime = true; myText[1].firstTime = true; myText[2].firstTime = true; } void main() { int loop; InitMacStuff(); //init Mac toolbox managers HideMyMenuBar(); //get rid of the menu bar, defined in Misc.c MacPlusArea(white, black, false); //Get a centered compact Mac sized active screen, works on compact macs as well loadMyText(); TextMode(srcXor); //inverts pixels, works for erasing and for writing but gotta call both times installTMTask(); //installs the timing delay for the first time, it will call itself on and on while(!Button()) { if(resumeLoop) { for(loop = 0; loop < 3; loop++) doCrawl(loop); //if greenlit by the timing delay, then do the graphics resumeLoop = false; //prevent returning to this loop until the timer says it's greenlit } } ShowMyMenuBar(); //restore the menu, defined in Misc.c RmvTime((QElemPtr) &myTMInfo); //good practice to remove our timing procedure. }