Atari Fine Scrolling
Karl E. Wiegers
Unlock the secrets of fine-scrolling screen displays with this step-by-step tutorial, complete with example programs. Recommended for intermediate BASIC and machine language programmers. The techniques work on all Atari 400/800, XL, and XE computers.
An especially powerful graphics feature of Atari computers is their ability to scroll all or part of a screen display. Both text and graphics screens can be scrolled horizontally, vertically, or diagonally by various increments. Scrolling is seen in such diverse applications as racing games, in which the moving roadway lends apparent motion to the stationary cars, and in strategic war games, in which players can manipulate the screen as a "window" over a much larger map.
There are two general types of scrolling: coarse scrolling and fine scrolling. Coarse scrolling moves the screen in increments of eight pixels (the size of one character); fine scrolling moves the screen in increments of one pixel and is much more realistic. Earlier articles have addressed the rudiments of coarse scrolling (see "Fun with Scrolling" by David Plotkin in COMPUTE!'s Second Book of Atari). As we'll see in a moment, fine scrolling is actually a combination of coarse and fine scrolling. Since these techniques require machine language to work properly, we'll present a vertical blank interrupt routine you can add to your BASIC programs to obtain the smooth, continuous scrolling effect seen in many Atari games.
Let's review some details about how Atari computers display information on the video screen. A special microprocessor chip called ANTIC governs the display process. ANTIC gets its instructions from a short program in memory called the display list. The display list tells ANTIC what kind of graphics mode to use for each display line, how many lines to show, where in RAM to find the data to be displayed, and other information. The starting RAM location of the display list can be found using this formula:
DL = PEEK (560) + 256 * PEEK (561)
Ordinarily, the block of RAM containing screen display data is defined when a GRAPHICS statement is executed in BASIC. The first byte of screen memory—which is displayed in the upper-left corner of the screen—is identified by the fifth and sixth bytes in the display list in the usual low-byte, high-byte format:
MEMST = PEEK (DL + 4) + 256 * PEEK (DL + 5)
An elegant feature of the Atari operating system is that the section of RAM to be displayed on the screen can be altered simply by changing the values in DL+4 and DL + 5, the pointers to screen RAM. For example, consider a graphics mode 2 display, with 20 characters or bytes of RAM per line. If we add 20 to the screen RAM pointers, the twenty-first byte of the original block of screen RAM would appear in the upper-left corner of the screen. This causes every part of the display to jump up by one mode line: a vertical coarse scroll. Conversely, subtracting 20 from the screen RAM pointers scrolls the display downward by one mode line in graphics mode 2.
Program 1 is a simple vertical coarse-scrolling routine written in BASIC for graphics mode 0. (Type this listing with the line numbers shown; we'll be adding to it later.) In line 150, the starting byte of screen RAM is incremented by 40 to generate each step of the scroll. Then the starting location is factored into its corresponding high-and low-byte values (lines 160—170), which are inserted into the display list (lines 180—190). Coarse scrolling can only change the position of display information in relatively large jumps, equal to the height of a character in whatever graphics mode is being used. It yields a jerky, rough appearance when scrolling a screenful of data.
These same principles apply to the concept of horizontal scrolling. However, horizontal scrolling is a bit more complex because it involves fooling the computer into thinking that each mode line is wider than the usual screen display. To make things easier, we'll stick to vertical scrolling.
The secret to fine scrolling, as mentioned above, is to mix coarse and fine scrolling. Atari computers were designed to allow vertical fine scrolling in increments of one video scan line (there are 192 in a normal full-screen display). In graphics mode 0, which has eight scan lines per mode line, the fine scrolling capability thus permits seven increments of vertical movement between mode lines. To scroll a display by more than just one mode line, your program must execute seven fine scrolls, then one coarse scroll. The final coarse scroll, in effect, appears onscreen as the eighth fine scroll.
All of this requires two basic steps. First, the program must inform ANTIC which mode lines in the display are enabled for fine scrolling. Second, the program must store into an appropriate hardware register an integer representing the number of scan lines to scroll.
The first step, enabling the desired mode lines for scrolling, takes us back to the display list. We've already seen how to find the display list in RAM and how to alter the bytes pointing to the start of screen memory. Most of the other instructions in the display list identify the kind of graphics mode line to display. (For a more detailed discussion of display lists, see Craig Chamberlain's article "How to Design Custom Graphics Modes" in COMPUTE!'s First Book of Atari Graphics.) To enable a mode line for vertical fine scrolling, you must set bit 5 of its display list instruction. This is equivalent to adding 32 to the contents of the byte, and it must be done for each mode line you want to scroll. If you like, you can define several blocks of scrollable lines. Mode lines which don't have bit 5 set can be coarse-scrolled, but not fine-scrolled.
The second step, telling ANTIC how many scan lines to scroll, requires a simple POKE into a register called VSCROL at location 54277 (hex $D405). VSCROL affects all lines which have been enabled for vertical fine scrolling. For instance, the statement POKE 54277,4 shifts the display in each enabled mode line upward by four scan lines. Notice that you can POKE only positive integers into VSCROL (or into any other byte, for that matter). In effect, this means you can scroll the display upward but not downward. To simulate downward scrolling, you must start with the display scrolled fully upward (store a 7 in VSCROL for graphics modes 0 or 1, or 15 for mode 2, and so on), then POKE a smaller number into VSCROL to move the contents of each mode line downward by one or more scan lines.
Here, then, is the procedure for a complete mixed-scrolling routine:
- Fine scroll a number of scan lines which is one less than the pixel height of the graphics mode.
- Reset VSCROL to the starting value (0 if scrolling up, the maximum value if scrolling down).
- Coarse scroll by one mode line.
- Repeat the procedure.
A Fine Example
To add vertical fine scrolling to our previous example of coarse scrolling, merge the lines in Program 2 with those in Program 1. After running the program, you must press SYSTEM RESET to restore the original display list.
Notice that the bottom of the screen moves up slightly after running this program. Because of the way that ANTIC works, a block of mode lines enabled for fine scrolling results in a loss of one mode line of display area. This shortens the screen display.
To make this program scroll downward rather than upward, change the following lines:
80 POSITION 2, 5 110 FOR S = 7 TO 0 STEP - 1 150 MEMST = MEMST - 40 200 POKE 54277, 7
As the display scrolls downward, you'll see the display list itself come into view, since it's normally found immediately before the start of screen memory. The display list appears mostly as a string of uppercase Bs. That's because the internal character code for an uppercase B is 34, the same as the display list instruction for a graphics 0 line enabled for vertical fine scrolling. You'll also see the fifth (and occasionally sixth) character in the display list change with each coarse scroll. These are the pointers to screen memory we discussed earlier.
To see a scrolling demo in graphics mode 1 instead of graphics 0, press SYSTEM RESET, type NEW, reload Program 1, and once again add the lines in Program 2. Then substitute these lines:
10 GRAPHICS 1 + 16 60 POKE DL + 6 + X, 38 90 PRINT #6;"MODE ONE DEMO" 150 MEMST = MEMST + 20 220 GOTO 220
Now to convert it for graphics mode 2, press RESET and make these changes:
10 GRAPHICS 2 + 16 50 FOR X = 0 TO 9 60 POKE DL + 6 + X, 39 80 POSITION 2, 11 90 PRINT #6;"MODE TWO DEMO" 100 FOR D = l TO 9 110 FOR S = 0 TO 15
Scrolling Behind The Scenes
As you run these demos, you'll notice that they still suffer from some unsightly flickers and jumps, even though they're clearly a big improvement over simple coarse scrolling. The problem is that BASIC can't POKE the display list and scroll registers fast enough to synchronize with the TV or monitor's electron beam which is displaying the video image. To achieve smooth, flicker-free scrolling, your program must change all the registers during the split-second when the beam is displaying nothing on the screen. This vertical blank interval happens 60 times a second when the beam returns from the bottom to the top of the screen to sweep another video "frame." Since BASIC isn't nearly fast enough for this job, a machine language routine is required.
Program 3 is a BASIC loader which incorporates such a routine. (Program 4 is the source code for machine language programmers; don't type it in unless you have an assembler.) Be sure to save a copy of Program 3 before running it for the first time. When you type RUN, it stores the machine language routine in memory page 6 (starting at location 1536, hex $600), then sets up a vertical blank interrupt (VBI), a mechanism which calls the routine during each vertical blank interval. The program also modifies the display list as described above and initializes a few memory locations (203-206) for the VBI routine.
After the screen clears, you'll see it fill with a mass of apparently random letters, numbers, and graphics symbols. That's because the program has scrolled the display past the end of usable RAM and into the BASIC cartridge itself. The scrolling continues until you press SYSTEM RESET.
An apparent limitation of a VBI scrolling routine is that it can't scroll the display faster than 60 times a second, because it's called only 60 times a second. If you want to scroll faster, you can scroll more than one scan line at a time—although it won't appear as smooth.
There's also a way to scroll more slowly. This routine uses a counter at location 203 to control the scroll rate. It checks to see how many vertical blank intervals have passed since the last fine scroll, then compares the result against a preset limit to see if it's time for another fine scroll. To make the routine wait for more than one vertical blank interval between fine scrolls, change the 1 in line 60 of Program 3 to a higher number.
The comments in Program 4 tell machine language programmers how to modify this VBI routine to work in other graphics modes.
Program 5 is a BASIC loader for a downward-scrolling VBI routine. It's not a stand-alone program—it must be combined with certain lines in Program 3 as described in the REM statements. (Program 6 is the source code for Program 5 so machine language programmers can study the technique. Again, don't type in Program 6 unless you have an assembler.)
So far we've seen simple demos of the Atari's scrolling capabilities. Now let's use them for something fun.
Empire State Building
Scrolling is most often used in programs that have a larger display than can be shown on a single screen. By scrolling across parts of the display data, you can use the screen as a window onto other sections of RAM. Consider, for example, that a graphics mode 2 screen has 12 lines of 20 bytes each, or only 240 bytes of information. That leaves enough memory in the computer to create a display containing thousands of bytes of data—maybe a dozen or more screens. This is the technique seen in such classic Atari games as Caverns of Mars and Eastern Front 1941.
Let's try a simple example. Program 7 shows the Empire State Building as it might appear to a parachutist leaping out of a helicopter over Manhattan. The building is composed of redefined graphics mode 2 characters. It took 1200 bytes of RAM to store the building and background, which are conveniently located in a character string called ESB$. The beauty of this approach to allocating memory is that your program can easily find the first byte of ESB$ with BASIC'S string ADR function. Then it can use this address as the upper-left corner of the screen by modifying the screen display pointers in the mode 2 display list. The 1200 bytes of ESB$ amount to five screens of graphics mode 2 data.
The VBI routine used in the Empire State Building example is slightly different from that in Program 4. First, it had to be modified for graphics mode 2. Second, it has a counter which is incremented after each coarse scroll. When the counter reaches a preset value (corresponding to street level in this case), the scrolling stops. You can change the 48 in line 150 of Program 7 to stop the scrolling at some other point. Press SYSTEM RESET each time before running this program to keep the redefined characters from getting messed up.
Just The Beginning
These examples illustrate the power of the graphics scrolling ability of Atari computers, but they're just a start. We don't have room in this article to cover extensions of these techniques, such as horizontal fine scrolling; diagonal scrolling; joystick-controlled scrolling; and altered perspective scrolling, in which cleverly designed character sets are combined with scrolling routines to create effective three-dimensional effects. With the ideas presented here, you can probe some of these techniques on your own.
For instructions on entering these listings, please refer to "COMPUTE!'s Guide to Typing In Programs" published bimonthly in COMPUTE!.