All good things must end. This series has to end too, and with a small quiver of nostalgia (and a great sigh of relief) we’ll finish it with this installment. We mainly want to describe the interrupt driven sprite program first introduced here so long ago, but there’s one more matter to cover.
In case you missed the orginial sprite article, the listing is included here. I know it’s lengthy, but type it in and run it. Then type RANDOMIZE USR 64776 to start the fun. The little sprite will bounce happily around the screen, and will keep bouncing, even while you type in your own BASIC programs and run them. While you run a BEEP command or do I/O to the cassette or TS2040 printer, he stops, producing a visual indication of whether or not the interrupt is enabled.
There’s nothing unusual about the BASIC program. It mostly just inserts the necessary machine code. Lines 40 and 50 install the standard “Kludge Block” and JP instructions we’ve been using since the beginning of this series. In case your memory needs refreshing, this was to allow IM2 to work even if your system doesn’t have pullup resistors on your data lines. In this program, all the action is in machine code.
Whenever the interrupt occurs, it’s diverted from its intended task of reading the keyboard. Instead, we figure out where the sprite should be moved to, move it, and THEN we allow the computer to read the keyboard, and get back to its real business.
Moving the sprite is fairly easy. Before we ever write the sprite to the screen, we save whatever is already there. When it comes time to move the sprite, we replace the old information, figure out where the new sprite should be, save the character at the new location, and then write the sprite. As such, the sprite passes through an area, leaving everything exactly as it found it.
Well, almost. Let’s suppose that, after writing the sprite in a certain spot, the “foreground” program writes another new character on that same spot. If we moved the sprite exactly as described, it would replace the old character rather than the new one when the sprite moved on. This would never do.
To fix this, the program doesn’t replace the old character until it first checks the supposed location of the sprite. If it doesn’t find the sprite character there, then it assumes your own program has already changed that location, and it doesn’t change it back. Note that all 8 bytes of the screen character must match the 8 bytes of the sprite character. As long as you’re only writing text to the screen, this is OK.
But if you’re PLOTting individual pixels, and just happen to put or clear a pixel on the sprite character, the 8 bytes will no longer match up, a stationary “son of sprite” will be left on the screen. Worse, if you do a CLS, lots of pieces of sprite will remain on the otherwise clear screen. These “spritelets” remain because the screen lines are cleared in the same odd order that you see them filled when you LOAD a SCREEN$. As the sprite moves from space to space, it has lots of chances to get a line or two erased from itself. This modified sprite then stays for good.
As explained in the orginial article, before you do a CLS, or a PLOT, or draw a LINE or CIRCLE, you should first disable the sprite with POKE 64898, 1. When you’re done you can restart the sprite with RAND USR 64776.
But to be practical, it’s probably best just to ignore this little problem. This program is just a demonstrator. It proves its point with the smallest amount of code. It gives an example of how the job is done and how you can use it or some thing like it in your own programs. A quick look at the code will show is how. Table 1 has a quick description of each part of the program.
The block STOR8 is the 8-byte space where the screen character is stored while the sprite is “borrowing” its space. BUG1 conatins the character pattern for the sprite, and you can change it to suit your mood. LOCS is the row and column location of the sprite, and DIRS contains the directions in which it happens to be moving. FLG is the byte you can poke when you want the sprite to go away. When the main sprite program sees a “1” here, then after it replaces the old character, it goes back to IM1, putting an end to all this spritely business.
The code contains four relocatable routines that have to do with display file tricks, and you can copy them to your code for your own use. If you’re familiar with the unusual layout of the display file, you may appreciate some code to make it more manageable. If you actually want to walk through the code, you may first wish to read “Navigating through the Display File Jungle”,(SINCUS NEWS, May/June 1986).
The first relocatable routine, GETDIS, is entered with the character’s line number in the D register, and the column number in E. We exit the routine with the display file address of the top byte of the character in HL. My display file artilce explains how to get at the rest of the bytes when you have the address of the first one.
The next relocatable routine, GET8, puts bytes from 8 consecutive locations at (BC) into the display file character at (HL). As such, it moves data from the sequential order we like to use, into the non-sequential order of the display file. The relocatable routine SAVE8 does it backwards. Moving the 8 non-sequential character bytes at display file address (HL) into 8 consecutive locations at (BC).
The last relocatable routine is COMP8, which compares the 8 sequential bytes at (BC) to the 8 non-sequential bytes at display file locations (HL). We exit the program with Z=1 only if both characters match exactly.
Table 1 describes the rest of the routines quite adequately, so that you can easily follow a dissembly of the other routines. Each routine has been kept deliberately small, so that they’d be easy for you to follow and modify. However, since we’ve already covered the main problems of interrupt driven sprites, we can end it here. With a little work, you should be writing your own more elaborate sprite programs in no time!
Now this series is done, and you are an expert on the subject of TS2068 interrupts. To prove your expertise on the subject, I’m hereby awarding you with a diploma, suitable for framing, lining your bird cage, or making those loose shoes fit just right. If you’d like a full size copy, personally signed by myself in not-quite-flickering orange crayon, just send me a stamped, self addressed envelope and an idea or two on what other technical matters you’d like to see written about. This offer is good until I lose interest and don’t feel like doing it anymore, so write today!

As always, I’m interested in hearing from what’s on your mind, so feel free to write me, Wes Brzozowski, [address omitted]. Please enclose a stamped, self addressed envelope if you wish a reply. I’m also glad to receive your phone calls, I’m at [phone number omitted]. Please try to call before 9:30pm, and DON’T call collect, thank you. Hope to hear from you soon!
FD00 STOR8 - Temporary storage for the 8 bytes "wiped out" by the sprite
FD08 START - Setup routine that starts up the sprite
FD18 SRVINT - Interrupt service. If the FLG byte contains 00, it moves the
sprite & runs the keyboard routine. Otherwise, it shuts off
the sprite
FD40 NEWBUG - Places the 8 bytes at BUG1 into the display file location
defined by LOCS.
FD4E UPDATE - Computes new location & direction
FD7E LOCS - The row & column location of the sprite
FD80 DIRS - The x and y directions of the sprite
FD82 FLG - Tells SRVINT wether or not to continue running the sprite
FD83 BUG1 - The 8 bytes that make up the sprite
FD8B OLDBLK - Replaces the old character on top of the sprite, provided
that the sprite is still there.
FDA5 GETDIS - Gets the display file address of a character. Input D=line,
E=column. Output HL=address
FDB4 GET8 - Puts bytes from 8 consecutive locations at (BC) into the
display file character at (HL)
FDBE SAVE8 - Puts bytes for 1 character at display file location (HL)
into 8 consecutive locations at (BC)
FDCB COMP8 Compare the bytes for 1 character at display file location
(HL) with 8 consecutive bytes at (BC). Return with Z=1 if all
8 are equal
FDD3 SAVCHR - Saves the character at (LOCS) into STOR8
TABLE 1: Functional Blocks for the Sprite Routine
10 REM Sprite Demonstrator
20 REM Enable Sprite With
RAND USR 64776
30 REM Disable Sprite With
POKE 64898,1
35 CLEAR 64767
40 FOR j=65024 TO 65280: POKE
J,253: NEXT j
50 POKE 65021,195: POKE 65022,
27: POKE 65023,253
90 LET checksum=0
100 RESTORE 1000
110 FOR j=64776 TO 64992
120 READ dat: LET checksum=chec
ksum+dat
130 POKE j,dat
140 NEXT j
150 IF checksum<>30092 THEN CLS
: PRINT "Checksum Error!!!!!!!"
: STOP
1000 DATA 243,237,94,62,254,237,
71,175,50,130
1010 DATA 253,205,211,253,205,64
,253,251,201,245
1020 DATA 197,213,229,205,139,25
3,58,130,253,167
1030 DATA 32,16,205,78,253,205,2
11,253,205,64
1040 DATA 253,225,209,193,241,19
5,56,0,237,86
1050 DATA 225,209,193,241,251,20
1,1,131,253,237
1060 DATA 91,126,253,205,165,253
,205,180,253,201
1070 DATA 237,91,126,253,237,75,
128,253,62,31
1080 DATA 187,32,2,14,255,175,18
7,32,2,14
1090 DATA 1,186,32,2,6,1,62,23,1
86,32
1100 DATA 2,6,255,237,67,128,253
,123,129,95
1110 DATA 122,128,87,237,83,126,
253,201,10,10
1120 DATA 1,255,0,60,66,165,129,
165,153,66
1130 DATA 60,237,91,126,253,205,
165,253,229,1
1140 DATA 131,253,205,200,253,32
,8,225,1,0
1150 DATA 253,205,180,253,201,22
5,201,122,230,7
1160 DATA 15,15,15,179,111,122,2
30,24,246,64
1170 DATA 103,201,22,8,10,119,36
,3,21,32
1180 DATA 249,201,22,8,126,36,2,
3,21,32
1190 DATA 249,201,22,8,10,3,190,
192,36,21
1200 DATA 32,248,201,237,91,126,
253,205,165,253
1210 DATA 1,0,253,205,190,253,20
1
9998 STOP
9999 SAVE CHR$ 18+CHR$ 1+"Sprite
"+CHR$ 18+CHR$ 0 LINE 10