Page Flipping On The Atari
Page flipping is an animation technique in which entire screens can be flashed in rapid sequence, much like flipping through the pages of a book. This makes possible some amazing graphics displays. The article includes two demonstration programs (one for computers with as little as 16K RAM, and another for machines with at least 48K). The programs work on the 400/800, XL, and XE models.
Animation is any sequence of events that creates the illusion of motion. Note the phrase illusion of motion: no actual motion is required. For example, consider the lights on a movie marquee, stadium score-board, or message board. When the lights are flashed in sequence, they produce the illusion of motion, although the bulbs themselves are stationary.
Movies and cartoons work on the same principle. They consist of a series of still pictures, each slightly different than the one before it. When the pictures are projected in rapid succession, we perceive motion. The same principle can be applied to computers, except that few computers can draw high-resolution screens fast enough to fool the eye. The answer is a special programming technique known as screen flipping or page flipping. Screens are drawn beforehand and stored in memory, then displayed one after the other in an instant.
ANTIC And Display Lists
By now, many of you are well acquainted with the Atari ANTIC chip, display lists, and how Atari computers display screen images. Many articles and books have been published on this subject. However, a quick overview will be helpful here.
Besides the 6502 microprocessor, the Atari also contains a special chip known as ANTIC. ANTIC is a true microprocessor with its own instruction set, and it is in charge of displaying all screen data. The program that instructs ANTIC is called a display list. The display list is merely a list of instructions that locates screen memory for ANTIC and tells it which graphics mode to display. The starting address of the display list is stored in the customary low byte/high byte form at memory locations 560 and 561. To find the starting address of the display list in any graphics mode, type the following line in immediate mode:
GR.[mode]:DL=PEEK (560)+256*PEEK(561):PRINT DL
where [mode] is the graphics mode number. This line can also be included in a program to store the display list address in the variable DL.
Screen Memory And Pointers
While display lists differ greatly, depending on the graphics mode, one thing is always certain. The fifth and sixth bytes of the display list contain the low and high bytes of the starting address of screen memory. To find the starting address of screen memory in any graphics mode, use this line:
GR.[mode]:DL=PEEK (560)+256*PEEK(561):ST=PEEK (DL+4)+256*PEEK(DL+5):PRINT ST
Remember that when indexing within a list, you start counting at zero. That's why the fifth element of the display list is calculated at DL + 4 and the sixth at DL + 5. These two bytes together are called a pointer. As ANTIC scans the display list, these two bytes point ANTIC to the start of the screen memory.
The use of pointers is called indirection. Indirection can be a very powerful tool, and thanks to the foresight of Atari's engineers, it makes page flipping possible on Atari computers. Some other computers reserve an area of memory that is dedicated entirely to the video display. To display a new screenful of data, the entire screen must be redrawn. This requires the high speeds of machine language, and at best is a complicated and time-consuming project. Through the use of pointers and indirection, the Atari avoids these complications.
By simply POKEing new values into the screen memory pointer in the display list, any area of memory can be instantly displayed on the screen. There is only one important rule to follow. To avoid garbled displays, screen memory should not cross a 4K memory boundary—that is, any address evenly divisible by 4096.
There is a way around this problem, but there's no room to explain it in detail here. However, you should note that it's impossible to flip pages in GRAPHICS 8 without taking this problem into account. Because GRAPHICS 8 uses about 8K of screen memory, the screen always crosses a 4K boundary. For now, it's probably best to experiment with page flipping in graphics modes 0 through 7, which use less than 4K of screen memory. With careful planning, screen memory need never cross a 4K boundary in these modes.
Setting Up Page Flipping
To implement page flipping, you must first calculate the starting address of the area of memory you wish to display. (You'll have to determine how much memory to set aside depending on the number of pages you want to flip, how much RAM is installed in your machine, etc.) Next, convert this number to its low-/high-byte representation using the following line:
where [address] is the starting memory address.
Then, choose a graphics mode and calculate the starting address of the display list. Finally, POKE the values LO and HI into the screen memory pointers in the display list—LO byte first, HI byte second. Remember, the screen memory pointers are always the fifth and sixth bytes of the display list. Use the following short program as an example:
10 AD = 40960 20 HI = INT(AD/256) :LO = AD - (256 * HI) 30 GRAPHICS 0 40 DL = PEEK (560) + 256 * PEEK(561) 50 POKE DL + 4, LO : POKE DL + 5, HI
When executed, the screen should almost instantly change to display this new area of memory. This area of memory is part of the BASIC ROM, and should be filled with all sorts of interesting data. It will be displayed as characters, since GRAPHICS 0 is a character mode. By substituting different values for the variable AD in the program above, any area of memory can be displayed (as long as it doesn't cross a 4K boundary, remember). Of course, if the area of memory you choose to display is empty, the screen will be blank.
There are two other memory locations that are important to know when page flipping. These are locations 88 and 89, another pointer. They store a memory address in the usual low-byte/high-byte form, and point to the area of memory where all PRINTs, PLOTs, and DRAWTOs will be directed, except for information displayed in text windows. By POKEing new values into these locations, you can redirect all PRINTs, PLOTs, and DRAWTOs to any area of memory. In other words, rather than printing text or drawing graphics on the screen, you can print text or draw graphics anywhere in memory and then display this page instantly.
This makes it possible to construct a series of pictures, each slightly different than the one before it, and each in a separate area of RAM. By rapidly flipping through these pictures in sequence, a program creates the illusion of motion. That's how the demonstration programs below work.
A Spinning Globe
If you have at least 48K RAM, use Program 1. If you have only 16K RAM, use Program 2 and make sure no disk drive is connected. Program 1 creates a spinning globe on the high-resolution GRAPHICS 8 screen. Program 2 creates a spinning globe too, but on the medium-resolution GRAPHICS 7 screen to conserve memory. (Program 2 also works on machines with more than 16K as long as the disk drive is disconnected.)
Both programs GOSUB to a routine that READs machine language DATA into page 6 (starting at location 1536 decimal). After RETURN, Program 1 fills an array with SIN and COSINE values to speed up the drawing process. Program 2 skips this step due to the limited memory on a 16K machine. Both programs switch to a PLOT mode at line 60 and set up the various color registers at line 70. The starting address of the display list is calculated at line 80, and certain variables are initialized at line 90. (When you run Program 1, the screen is blank for about one minute during these steps.)
Lines 100 through 240 use BASIC trigonometric functions to draw three slightly different views of a wire globe. Each drawing is stored in a separate area of RAM. The spokes of this globe are nine degrees apart, and each drawing shows the globe rotated three degrees from the previous one. As each drawing is completed, the ON-GOSUB statement at line 230 directs the program to one of two subroutines at lines 1000 and 2000. These routines POKE the screen memory pointers into the display list, and POKE the PRINT, PLOT, and DRAWTO pointers with the address of the next area of memory to be displayed.
When all of this is completed, line 250 calls the machine language subroutine in page 6. This sets up a vertical blank interrupt routine that rapidly displays the drawings in sequence. The globe appears to spin!
Although machine language is not really necessary for page flipping, it was included here for a reason. Notice that when the globe starts spinning, the READY prompt appears in the text window at the bottom of the screen. You can type LIST to view the program in the text window while it is executing, or even type NEW and enter another program without affecting the display. This allows you to incorporate the spinning globe in your own programs.
Another interesting item is memory location 1554. This location in the vertical blank routine controls the speed of the globe's rotation. It normally contains a 1. Try POKEing 1554 with a 3 to slow down the rotation, or a 0 to speed things up.
For an example of page flipping in BASIC, add these lines to Program 1:
LJ 245 POKE DL + 5, 129 : POKE DL + 101, 144:FOR X=1 TO 10 : NEXT X IJ 246 POKE DL + 5, 97 : POKE DL+101, 112 : FOR X = 1 TO 10: NEXT X FJ 247 POKE DL + 5, 65 : POKE DL+101, 80 : FOR X = 1 TO 10: NEXT X HC 248 GOTO 245
or these lines to Program 2:
AJ 245 POKE DL + 5, 16 : FOR X = 1 TO 10 : NEXT X AI 246 POKE DL + 5, 32 : FOR X = 1 TO 10 : NEXT X BA 247 POKE DL + 5, 48 : FOR X = 1 TO 10 : NEXT X HC 248 GOTO 245
These modifications bypass the machine language, yet show how BASIC is plenty fast enough for page flipping. You can slow down or speed up the globe by changing the values in the FOR-NEXT loops. Or you can press BREAK and enter GOTO 250 in direct mode to let the machine language routine spin the globe.
Feel free to use these programs for your own pursuits. Remember that once they are running, you can enter NEW and type in your own program. Who knows—maybe you can come up with a game that has a rotating planet in the background. (Incidentally, player/missile graphics is an ideal way to add moving objects when flipping screens, because it's not affected by page flipping.)