Classic Computer Magazine Archive ANTIC VOL. 4, NO. 6 / OCTOBER 1985

assembly language


Dot-by-dot screen moves, 8 times smoother!


The conclusion of a two-part tutorial on assembly language scrolling, by the author of Atari Roots.  You'll learn how to program screens that scroll with professional smoothness, by controlling the Atari's scrolling registers and vertical blank interrupt vectors.  The demonstration program is written in assembly language and requires either the MAC/65 assembler (O.S.S.) or the Atari Assembler Editor.  It will run on all Atari 8-bit computers, with disk or cassette.  This series is intended for programmers with at least an introductory knowledge of assembly language.

The reason fine scrolling works so smoothly is that it has eight times the resolution of coarse scrolling. When coarse scrolling is used in a program, it causes lines of text to jump across the screen (or up and down) one full character at a time. But when fine scrolling is used, text can be moved around the screen one eighth of a character at a time. Here's how that works.
   Look closely at a text character on your video screen, and you'll see that it's made up of a matrix of tiny dots. If you had a magnifying glass, you'd be able to see that there are 64 dots in each character-eight rows of dots (or scan lines) high, and eight rows of dots (or color clocks) across. And these rows of dots-scan lines and color clocks-are the increments used in fine scrolling.
   To create and implement a fine scrolling routine, several steps are required. First, you must go to your display list and enable fine scrolling by setting certain bits in the LMS instruction that appears before every line you want to scroll. When bit 4 of an LMS instruction is set, the line that follows the LMS instruction can be scrolled horizontally. When bit 5 of an LMS instruction is set, the line that follows the LMS instruction can be scrolled vertically, If both bit 4 and bit 5 of an LMS instruction are set, the line that follows the instruction can be scrolled both horizontally and vertically.

Type in Listing 1. If you've got the listing from last month's scrolling demo, you can edit and expand it to create this month's listing. Those with MAC/65 can use the listing as is. Atari Assembler Editor owners should substitute the alternate lines in Listing 2.
   Antic Disk subscribers will find the MAC/65 source code under the filename FINESCRL. M65, and the object code as FINESCRL. EXE. If you have the Atari Assembler Editor, you must type in the alternate lines from Listing 2. To run the object code from DOS 2, type [L] [RETURN] FINESCRL.EXE [RETURN). .

Take a look at lines 340 through 390 in the program you just typed, and you'll see that the LMS instruction preceding the line which I've labeled SCROLN (the line that scrolls) is $57. Most LMS instructions, as we have seen, begin with the digit 4. Why, then, does this one begin with the digit 5?
   The number $47, expressed in binary notation, is 0100 0111. Bit 4 of that binary number is a zero and, therefore, not set. This means horizontal fine scrolling is not enabled. If you set bit 4, the number becomes 0101 0111 (or $57) and horizontal fine scrolling is enabled. And that's why the last byte in line 380 of Listing 1 is $57.
   Now suppose you wanted to scroll SCRLN vertically instead of horizontally. What would you do? Well, you'd simply set bit 5 of the LMS instruction in line 380. Then the $57 that ends that line would become $67-or in binary notation, 0110 0111. If you wanted to enable both horizontal and vertical scrolling of the line, you'd simply change the last value in line 380 to $77 (0111 0111).
   Fine scrolling, like coarse scrolling, can be performed on any number of lines of text on your screen. Just set the appropriate bits in the proper LMS instructions, and the desired type of scrolling can be implemented for each selected line.
   But what if a display list contains no LMS instruction for a line you want to scroll? Well, in that case, you could simply write one. There's no reason a display list can't have an LMS instruction for every line on the screen. In fact, when an entire screen is to be scrolled, a separate LMS instruction must be used for each line that appears on the screen.

So far, all we've talked about is how to enable fine scrolling. But once fine scrolling has been enabled, how is it implemented?
   When fine scrolling of a line is enabled, control of the line is handed over to one of two scrolling registers that reside in your Atari's operating system. If you have authorized a horizontal scroll on a given line of a display, then that line becomes subject to the control of a horizontal scroll register, which is abbreviated HSCROL and is at memory address $D404.
   When a vertical scroll has been enabled for a given display-list line, that line becomes subject to the control of a vertical scroll register, or VSCROL, at address $D405. If both horizontal and vertical scrolling of a given line are enabled, then that line becomes subject to the control of both the HSCROL and the VSCROL registers.
   After control of a line has been turned over to HSCROL, VSCROL, or both, you can implement fine scrolls by loading a value into the appropriate scrolling registers. When you load a number into the HSCROL register, every display list line that has been put under the control of that register will be shifted to the right by the number of color clocks loaded into HSCROL. Load a number into the VSCROL register, and every line for which a vertical scroll has been enabled will be scrolled upward by the number of scan lines you have specified.
   If both horizontal and vertical scrolling of a given line are enabled, you can move that line left, right, up or down by loading approprIate values into both HSCROL and VSCROL.

There is one hitch, though. The scrolling registers are eight bits, and only four of the eight bits in each register are used. That means that fine scrolling can be taken only so far. To work properly, fine scrolling must be combined with coarse scrolling.
   The best way to combine fine and coarse scrolling is to fine scroll a line or column of characters by seven color clocks or scan lines, and then reset the appropriate fine scrolling register to its initial value and implement one coarse scroll. Loop through this kind of procedure over and over, and the result will be a smooth fine scroll. You can see how this procedure works by studying and experimenting with Listing 1.

That's all there is to fine scrolling -if you don't mind putting up with a jerk, a jump or a smear every now and then on your screen. But if these kinds of messy situations don't appeal to you... Well, we've come this far - we might as well go on and talk about how to make fine scrolling perfect.
   As you may know, your computer's screen display is redrawn by an electron gun 60 times every second. Between each of these screen refresh cycles, there's a split-second total screen blackout that takes place too rapidly for you to see.
   So when you write a fine scrolling routine without taking special precautions, some of the scrolling action that you've programmed may take place while your display is actually being drawn on your screen. And this will usually result in unsightly jerks and smears.
   Fortunately there is a way to keep this from happening. The folks who designed your Atari have provided something called a vertical blank interrupt (VBI) vector. Learn how to use that vector, and you can perform all kinds of graphics tricks in real time without messing up your display.
   A vector is a pointer in your computer's operating system that contains the address of a specific routine. The main purpose of a vector is to offer an easy method for implementing often-used routines. When you jump to an OS vector during the course of a program, your program will automatically jump to the OS routine that the vector points to, and you can thus implement that routine without having to rewrite all of the code that it contains.
   Vectors can sometimes be used in another way Sometimes you can "steal" a vector. That is, you can change its value so that it points to a routine you've written yourself, rather than the OS routine it originally pointed to.
   This allows you to use a vector as an easy method for controlling the behavior of your computer's operating system. Listing 1 contains one shamelessly stolen vector-a vertical blank interrupt vector called VVBLKI which is accessed via a pointer at address $0222. (NOTE: There are actually two vertical blank vectors-immediate and deferred. For the purposes of this article we will only deal with the immediate vertical blank vector.)

Here's how the VVBLKI vector works. Every time your Atari starts a vertical blank interrupt, it takes a look at the contents of the VVBLKI pointer. If the program being processed does not make use of the VVBLKI pointer, that pointer will contain nothing but an instruction to jump to a predetermined memory address: specifically, memory location $E45F (SYSVBV). And memory location $E45F usually contains nothing but an instruction for your computer to continue its normal processing.
   By stealing the VVBLKI vector, however, you can make it point to any routine you like-usually one you yourself have written. Then, 60 times every second, your computer will automatically process the routine whose address you have stored in the VVBLKI pointer. When your routine is finished, your computer will resume its normal processing.
   Once you understand how the VVBLKI interrupt works, it isn't difficult to steal them. Here's all you have to do:

   1. Write a short routine you would like to carry out during a vertical blank interrupt.

   2. Make sure that your routine ends with a jump to SYSVBV.

   3. Store the address of your routine at VVBLKI.

   After these steps are taken, your computer will process your new routine 60 times every second-just before it begins each VBI interrupt.

There's just one more important fact that you should remember about VBI vector-stealing. After you've stolen a vector, there's a small chance that an interrupt will begin after the first byte of the pointer that you're using has been updated, but before the second byte has been changed. If that happens, it could crash your program. But this possibility can be avoided by using a routine called SETVBV which begins at memory address $E45C.
   To use the SETVBV routine, first load the 6502 Y register with the low byte of the address of the routine that instructs your computer to begin a vector-changing routine. Then load the x register with the high byte of the address. Next, load the accumulator with a 6-a number which Atari computers recognize as a code for VVBLKI routines. Then do aJSR SETVBV, and your interrupt will be safely enabled.
   In Listing 1, the VVBLKI vector is stolen in lines 830 through 860. The thievery committed in those lines is quite straightforward. The address of the SCROLL routine at line 910 is slipped into the VVBLKI vector, and from then on, the Atari that is running Listing 1 will automatically call the SCROLL routine 60 times per second, thinking the routine is part of its own operating system.

Mark Andrews wrote Atari Roots, probably the finest introduction to Atari assembly language. It has sold out, but hopefully will be back in print fairly soon. Antic published excerpts from this book in November and December 1984.

Listing 1         FINESCRL.M65 Download / View
Object Code  FINESCRL.EXE Download