assembly language
FINE SCROLLING WORLD: PART II
Dot-by-dot screen moves, 8 times smoother!
by MARK ANDREWSThe 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.
TYPING IT IN
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). .
ENABLING
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.
IMPLEMENTATION
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.
COMBINATIONS
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.
PERFECT SCROLLING
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.)
VBI VECTORS
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.
ONE MORE THING ...
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