3-Sep-85 17:07:58-PDT,5533;000000000005 Return-Path: Received: from UCB-VAX.ARPA by SUMEX-AIM.ARPA with TCP; Tue 3 Sep 85 17:07:09-PDT Received: from ucbjade.Berkeley.Edu (ucbjade.ARPA) by UCB-VAX.ARPA (4.24/5.3) id AA08875; Tue, 3 Sep 85 17:03:12 pdt Received: from ucblapis.Berkeley.Edu (ucblapis.ARPA) by ucbjade.Berkeley.Edu (4.19/4.38.2) id AA04885; Tue, 3 Sep 85 17:06:10 pdt Received: by ucblapis.Berkeley.Edu (4.19/4.38.1) id AA19147; Tue, 3 Sep 85 17:06:00 pdt Date: Tue, 3 Sep 85 17:06:00 pdt From: oster%ucblapis.CC@Berkeley Message-Id: <8509040006.AA19147@ucblapis.Berkeley.Edu> To: info-mac@sumex-aim.ARPA Subject: Flicker-free animation on the mac. When you do animation, you show the viewer successive frames at a rate high enough that the viewer percieves the successive frames as continuous motion. At the movies, you just show successive frames. On the computer the frame to frame transition is a little more complex: You draw a frame, erase it, and draw the next. This is ususally optimized to: You draw a frame, undraw the parts that change, and draw the parts that change in the next. If the viewer can percieve the undrawn state, the viewer will call your animation "flickery". The flicker problem of animation is to hide the frame to frame transition from the viewer. A movie projector hides the frame to frame transition by concealing the film with a shutter while it is moving the film. On a TV set, the picture is drawn by sweeping an electron beam across the surface of a cathode ray tube in many horizontal scan lines. If you look closely at the Mac screen, you can see the scan line structure. The Mac picture tube, in order to take advantage of the mass production of the TV industry, follows the TV convention of only drawing while the beam moves from left to right, and drawing each scan line below the previous one. (I don't know why TV was not designed to scan in alternate directions on alternate scan lines and draw scan lines top down in one frame and bottom up in the next. I just know it doesn't.) The beam is deflected by magnetic fields (or electric fields on some older sets). These fields behave as if they had inertia - they can not be changed instantaneously. It takes time to bring the beam back to the position of the start of the next scan line. During that time the Mac can make multiple changes to screen memory, and only the cumulative results of those changes will be seen by the viewer. The Mac circuitry generates an interrupt at the end of each horizontal scan line and at the end of each frame. During the horizontal sync interrupt, while the electron beam is moving back from the right edge of the screen to the left, the Mac may send a byte to the speaker and the floppy motor. The horizontal retrace is completed very quickly, so there isn't time to do much. During the vertical sync interrupt, while the electron beam is moving from the lower right corner to the upper left corner, the Mac executes procedures in its vertical retrace queue. There are system calls for adding and removing procedures from the queue. The standard vertical interrupt procedure increments a global variable called Ticks, a longInt at location $16A. If you pause in you screen modification loop until this changes, your screen modification loop will be synched to the video. (Don't depend on $16A for the time. As I discovered when I wrote my menu bar clock desk accessory, the value drifts slightly so that after ten hours, it will be a minute or two slow.) Synching to the video may not be good enough. If your graphics commands take more than about 1/128th second to execute, they will still be in progress while the beam is scanning out the picture, and syncing to the video will just have traded you intermitant flicker for continuous flicker. The other way of hiding the changes from the viewer is to hide the changes from the viewer - draw where the viewer can't see them and them quickly put them on the screen. There are two ways to do this: 1.) Use the Mac's alternate screen. There is a bit on the Mac's VIA chip that changes which memory locations are shown on the screen. You draw on the hidden one, and when you are done, you make it visible and draw the next frame on the other one. The viewer never sees drawing in progress. This method has problems: a.) The stack is right in the middle of the alternate video page. To begin to use it, you must move the stack out of the way, and when you are done, move the stack back. (There is a parameter to the Launch system call so that when the program exits, the cleaning up will be done for you, but the only way to use that parameter is to write one program that launches a second one, so its pretty useless.) b.) It takes 22k of memory. Any program that uses the alternate video probably won't run on a thin Mac, because there probably isn't room. c.) The Mac XL doesn't have an alternate video page and future Macs probably won't. The second method is the one I prefer: 2.) Do your drawing off screen and use CopyBits when you are done. Allocate a new GrafPort, and change the .bitMap field to point to a new bitMap that you have allocated elsewhere than in screen memory. Copy the portion of the screen that is going to change into it, make the changes, and copy it back. If the new bitMap is aligned to a byte boundary on the screen, the transfers are very fast. -- David Oster, THE unknown hacker.