| 1 | /* Movie Crawl | 
    
      | 2 | * started on August 11th 2022 | 
    
      | 3 | * Copyright Michael Juneau, 1Bit Fever Dreams | 
    
      | 4 | */ | 
    
      | 5 |  | 
    
      | 6 |  | 
    
      | 7 | #define DELAY 5 | 
    
      | 8 |  | 
    
      | 9 | typedef struct | 
    
      | 10 | { | 
    
      | 11 | TMTask atmTask; | 
    
      | 12 | long tmRefCon; | 
    
      | 13 | } TMInfo; | 
    
      | 14 |  | 
    
      | 15 | typedef TMInfo *TMInfoPtr; | 
    
      | 16 |  | 
    
      | 17 | typedef struct | 
    
      | 18 | { | 
    
      | 19 | StringHandle str; | 
    
      | 20 | short index; | 
    
      | 21 | short initIndex; | 
    
      | 22 | Boolean firstTime; | 
    
      | 23 | } aTextLine; | 
    
      | 24 |  | 
    
      | 25 | typedef aTextLine *aTextLinePtr; | 
    
      | 26 |  | 
    
      | 27 | short size = 28; //biggest font size at the bottom | 
    
      | 28 | short index = 342; //loop control variable | 
    
      | 29 | Boolean firstTime = true; | 
    
      | 30 | Boolean resumeLoop = false; | 
    
      | 31 | aTextLinePtr myText; | 
    
      | 32 |  | 
    
      | 33 | TMInfo myTMInfo; | 
    
      | 34 |  | 
    
      | 35 |  | 
    
      | 36 | void InstallTMTask(void); | 
    
      | 37 | pascal TMInfoPtr GetTMInfo(void); | 
    
      | 38 | pascal void MyTask(void); | 
    
      | 39 | void doCrawl(int whichLine); | 
    
      | 40 | int findSize(int i); | 
    
      | 41 | void loadMyText(void); | 
    
      | 42 |  | 
    
      | 43 |  | 
    
      | 44 | void installTMTask() //Prepping the task record and installing it for the first time | 
    
      | 45 | { | 
    
      | 46 | myTMInfo.atmTask.tmAddr = MyTask; | 
    
      | 47 | myTMInfo.atmTask.tmWakeUp = 0; | 
    
      | 48 | myTMInfo.atmTask.tmReserved = 0; | 
    
      | 49 | myTMInfo.tmRefCon = SetCurrentA5(); | 
    
      | 50 |  | 
    
      | 51 | InsTime((QElemPtr) &myTMInfo); | 
    
      | 52 | PrimeTime((QElemPtr) &myTMInfo, DELAY); | 
    
      | 53 |  | 
    
      | 54 | } | 
    
      | 55 | pascal TMInfoPtr GetTMInfo(void) //equivalent to MOVE.L A1,(SP) | 
    
      | 56 | = 0x2E89; | 
    
      | 57 |  | 
    
      | 58 | pascal void MyTask() //the task's only purpose is to greenlight the movie crawl update to proceed by setting this global flag | 
    
      | 59 | { | 
    
      | 60 | long oldA5; | 
    
      | 61 | TMInfoPtr recPtr; | 
    
      | 62 |  | 
    
      | 63 | recPtr = GetTMInfo(); | 
    
      | 64 | oldA5 = SetA5(recPtr->tmRefCon); | 
    
      | 65 |  | 
    
      | 66 | if(resumeLoop == false) resumeLoop = true; | 
    
      | 67 |  | 
    
      | 68 | oldA5 = SetA5(oldA5); | 
    
      | 69 |  | 
    
      | 70 | PrimeTime((QElemPtr) recPtr, DELAY); | 
    
      | 71 | } | 
    
      | 72 |  | 
    
      | 73 |  | 
    
      | 74 | int findSize(int i) //used to figure out the font size, bigger in the bottom, smaller on top | 
    
      | 75 | { | 
    
      | 76 | return size-(342-i)/17; | 
    
      | 77 | } | 
    
      | 78 |  | 
    
      | 79 | void doCrawl(int whichLine) //manage the movie crawl graphics, heart of this program | 
    
      | 80 | { | 
    
      | 81 | short predictWidth; | 
    
      | 82 | if(myText[whichLine].index <= 342) //only bother displaying if onscreen | 
    
      | 83 | { | 
    
      | 84 | if(myText[whichLine].index != 342) //erase the previous position | 
    
      | 85 | { | 
    
      | 86 | TextSize(findSize(myText[whichLine].index+1)); | 
    
      | 87 | predictWidth = StringWidth(*(myText[whichLine].str)); | 
    
      | 88 | MoveTo((512-predictWidth)/2,myText[whichLine].index+1); | 
    
      | 89 | DrawString(*(myText[whichLine].str)); | 
    
      | 90 | } | 
    
      | 91 | if(myText[whichLine].index == 342 && myText[whichLine].firstTime == false) //erase topmost position if restarting at the bottom | 
    
      | 92 | { | 
    
      | 93 | TextSize(findSize(size)); | 
    
      | 94 | predictWidth = StringWidth(*(myText[whichLine].str)); | 
    
      | 95 | MoveTo((512-predictWidth)/2,size); | 
    
      | 96 | DrawString(*(myText[whichLine].str)); | 
    
      | 97 | } | 
    
      | 98 | TextSize(findSize(myText[whichLine].index)); | 
    
      | 99 | predictWidth = StringWidth(*(myText[whichLine].str)); | 
    
      | 100 | MoveTo((512-predictWidth)/2,myText[whichLine].index); | 
    
      | 101 | DrawString(*(myText[whichLine].str)); | 
    
      | 102 | myText[whichLine].firstTime = false; | 
    
      | 103 | } | 
    
      | 104 | myText[whichLine].index--; | 
    
      | 105 | if(myText[whichLine].index < size) myText[whichLine].index=342; //loop back once the top position has been passed | 
    
      | 106 |  | 
    
      | 107 | } | 
    
      | 108 |  | 
    
      | 109 | void loadMyText() | 
    
      | 110 | { | 
    
      | 111 | myText = (aTextLinePtr)NewPtr(3*sizeof(aTextLine)); | 
    
      | 112 | myText[0].str = NewString("\pLong live Eric Helgeson's Mac C Club!"); | 
    
      | 113 | myText[1].str = NewString("\pCoding in Macintosh THINK C is the best."); | 
    
      | 114 | myText[2].str = NewString("\pVisit 1Bit Fever Dreams on YouTube."); | 
    
      | 115 |  | 
    
      | 116 | myText[0].index = myText[0].initIndex = 342; | 
    
      | 117 | myText[1].index = myText[1].initIndex = 342 + 28; | 
    
      | 118 | myText[2].index = myText[2].initIndex = 342 + 56; | 
    
      | 119 |  | 
    
      | 120 | myText[0].firstTime = true; | 
    
      | 121 | myText[1].firstTime = true; | 
    
      | 122 | myText[2].firstTime = true; | 
    
      | 123 |  | 
    
      | 124 |  | 
    
      | 125 | } | 
    
      | 126 | void main() | 
    
      | 127 | { | 
    
      | 128 | int loop; | 
    
      | 129 |  | 
    
      | 130 | InitMacStuff(); //init Mac toolbox managers | 
    
      | 131 | HideMyMenuBar(); //get rid of the menu bar, defined in Misc.c | 
    
      | 132 | MacPlusArea(white, black, false); //Get a centered compact Mac sized active screen, works on compact macs as well | 
    
      | 133 |  | 
    
      | 134 | loadMyText(); | 
    
      | 135 |  | 
    
      | 136 | TextMode(srcXor); //inverts pixels, works for erasing and for writing but gotta call both times | 
    
      | 137 | installTMTask(); //installs the timing delay for the first time, it will call itself on and on | 
    
      | 138 |  | 
    
      | 139 | while(!Button()) | 
    
      | 140 | { | 
    
      | 141 | if(resumeLoop) | 
    
      | 142 | { | 
    
      | 143 | for(loop = 0; loop < 3; loop++) doCrawl(loop); //if greenlit by the timing delay, then do the graphics | 
    
      | 144 | resumeLoop = false; //prevent returning to this loop until the timer says it's greenlit | 
    
      | 145 | } | 
    
      | 146 | } | 
    
      | 147 |  | 
    
      | 148 | ShowMyMenuBar(); //restore the menu, defined in Misc.c | 
    
      | 149 | RmvTime((QElemPtr) &myTMInfo); //good practice to remove our timing procedure. | 
    
      | 150 | } |