Smooth-Scrolling Billboard
For Commodore 64
Paul W. Carlson
This program turns your Commodore 64 into an electronic billboard, smoothly scrolling large, multicolored messages across the screen.
Would you like to be able to glide a message across the Commodore 64's screen in giant, multicolored letters? The program with this article makes it easy. Or perhaps you're a machine language programmer interested in smooth-scrolling techniques. This article explains how it's done.
Jumbo Billboard
To see smooth scrolling in action, type in, save, and run the program. The program takes a few seconds to read the machine language in the DATA statements and then asks if you want multicolored letters. Respond by pressing Y (yes) or N (no); do not press RETURN. The upper part of the screen fills with arrow symbols, with the cursor positioned over the first arrow symbol. Starting at the cursor, type in the text that you want to scroll across the screen. Your text will replace the arrow symbols as you type. Any nongraphics characters can be used (although lowercase letters will scroll as uppercase). You can make changes to your text by overtyping the unwanted letters or by using the DEL key.
Press RETURN when you have entered the entire message. The program reads all of the text up to the first arrow symbol. If the program doesn't find an arrow symbol, it uses the first 250 characters (including blanks) of the message. After you press RETURN, the billboard immediately starts to scroll. The message continues to scroll with two spaces separating the end of the text from the beginning. If you want more separation, add extra spaces at the end of your text. To stop the program, press any key while the text is scrolling.
Changing Colors
You can easily modify the program to display colors of your own choosing. The numbers in lines 70–90 can be changed to any legal color number (0–15). When multicolor letters are in use, the program uses the color numbers in lines 160–230 instead of the foreground color in line 80. The color numbers in lines 160–230 can also be changed to any legal color number. This allows you to match the colors to the content of your message. For example, the letters in a patriotic message might have alternating red and white stripes against a blue background.
If you simply want to use the program, you needn't read any further. The remainder of this article discusses techniques which machine language programmers may find interesting.
Text Input
In order to work, this program must pass a long string—the text of your message—to a machine language subroutine. You may wonder why a simple INPUT statement isn't used to enter the message. After all, that's what INPUT is designed to do. There are two reasons why it isn't used. First, certain characters that you might want to use in your text, such as quotation marks, colons, and commas, can cause problems with INPUT. Second, INPUT can only handle strings up to 80 characters in length, but you might want to display a longer message.
The same limitations apply to the INPUT# statement. In fact, the program takes advantage of the way that INPUT# responds to a colon as input. The INPUT# statement in line 280 halts the program, reads data from the keyboard buffer, and continues execution when you press RETURN. Before we execute that INPUT#, however, the program manipulates the keyboard buffer to prevent INPUT# from processing the text that you type. Line 240 POKEs four values into the keyboard buffer, where they will be found by the INPUT# in line 280. The four values are the ASCII codes for a colon, left cursor, arrow symbol, and left cursor. The colon, because it is a delimiter, causes INPUT# to disregard anything that follows. This allows you to type anything you want without causing an error message. When INPUT# is executed, anything in the keyboard buffer is displayed. The left cursor, arrow symbol, and left cursor are placed in the keyboard buffer to restore the screen by overwriting the colon with an arrow symbol and moving the cursor back to the first screen location.
Smooth Scrolling
As you can see by looking carefully, the large letters move horizontally one pixel (screen dot) at a time, making for very smooth movement. The 64's VIC (Video Interface Controller) chip can instantly position the screen at any one of eight pixel positions. This, combined with the VIC's ability to instantly change the location screen memory, allows you to scroll shapes one pixel at a time. For machine language programmers, here are the steps this programs uses for smooth scrolling:
1. Set aside two 1000-byte memory areas for screen data. One of these can be the normal screen memory area, which starts at location 1024 ($0400). Next, set up pointers in zero-page memory to the two screen memory locations. We'll refer to these locations as SRCE and DEST (for source and destination). In this program, the two screen memory locations are 1024 ($0400) and 15360 ($3C00). It makes no difference which location is initially SRCE or DEST.
2. Clear both screens and fill color memory at locations 55296–56295 ($D800–$DFE7). The four high-order bits of location 53272 ($D018) control which screen is active. Make DEST the active screen. Set the screen size to 38 columns by clearing bit three of location 53270 ($D016). Set the scroll position to seven by setting the three low-order bits of 53270 ($D016).
3. Swap the pointers to SRCE and DEST and copy columns 1–39 of the SRCE screen to columns 0–38 of the DEST screen.
4. Fill column 39 of the DEST screen with new data.
5. Using a time delay, decrement 53270 ($D016) until the three low-order bits are zero. The time delay is approximately equal to the execution time of steps 3 and 4 to prevent jerking.
6. Wait until location 53266 ($D012) equals zero (indicating raster line zero), and then make the inactive screen the active screen and immediately set the scroll position to seven. Go to step 3.
Steps 3 and 4 are performed only on screen rows 9–17 in this program, since these are the only rows that change. In many programs that use smooth scrolling, the time delay between each decrement of 53270 ($D016) in step 5 would be replaced with routines that move sprites, check for collisions, and so on. When this is the case, a time delay loop will usually be needed at the end of step 4 to make the execution time of steps 3 and 4 equal the execution time between decrements of 53270 ($D016).
Smooth scrolling is not as difficult as you may think. The VIC chip does much of your work for you. This article has described only horizontal smooth scrolling, but that's the most difficult direction to scroll. Vertical smooth scrolling is much easier. If you've never tried smooth scrolling, I hope that this article will encourage you to do so. You can find more information about scrolling in Programming the 64 by Raeto West, and Mapping the 64 and 64C by Sheldon Leemon; both books are available from COMPUTE! Books.
Smooth-Scrolling Billboard
For instructions on entering this program, please refer to "COMPUTEI's Guide to Typing In Programs" elsewhere in this issue.
PG 5 REM COPYRIGHT 1987 COMPUTE! PUBLICATIONS, INC {3 SPACES}ALL RIGHTS RESERVED. RS 10 POKE55, 255: POKE56, 59: CLR: POKE53272,(PEEK(53272)AND15)OR16 RX 11 PRINT"{CLR}" RS 12 PRINTTAB(12); "COPYRIGHT {SPACE}1987":PRINTTAB(6);"COMPUTE! PUBLICATIONS, INC. JK 14 PRINTTAB(10);"ALL RIGHTS RESERVED." PF 15 FOR X = 1TO1200:NEXT KH 20 PRINTCHR$(147);"READING {SPACE}MACHINE CODE…": PRINT BR 30 T = 0: FORN = 49152TO49640: READK: POKEN, K:T = T + K: NEXT FF 40 IFT = 72434THEN70 XA 50 PRINT"***ERROR IN DATA STATEMENTS ***":END RX 60 REM ** SCREEN COLORS ** XK 70 BG = 0 :REM BACKGROUND CR 80 FG = 15:REM FOREGROUND JF 90 BR = 0 :REM BORDER KC 100 PRINT"MULTI-COLOR LETTERS (Y/N)? "; MP 110 GETA$: IFA$ = ""THEN110 BM 120 PRINTA$:IF A$ <> "Y"ANDA$ <> "N"THEN 100 BK 130 IF A$ = "N" THENPOKE49649, 0: GOTO 240 DM 140 POKE49649, 1 EP 150 REM ** MULTI-COLOR LETTER COLORS ** MF 160 POKE49648, 4 :REM TOP QJ 170 POKE49647, 2 :REM 2ND GF 180 POKE49646, 8 :REM 3RD HR 190 POKE49645, 7 :REM 4TH XJ 200 POKE49644, 3 :REM 5TH SR 210 POKE49643, 5 :REM 6TH SD 220 POKE49642, 6 :REM 7TH XS 230 POKE49641, 14 :REM 8TH EK 240 POKE198, 4: POKE631,58: POKE632,157: POKE633,95: POKE634.157 BF 250 PRINTCHR$(147):FORN = 1TO12:PRINT:NEXT EA 260 PRINT"{2 SPACES}ENTER TEXT AT CURSOR - PRESS [RETURN]{3 SPACES}WHEN FINISHED.";CHR$(19); QC 270 FORN = 0TO250:PRINTCHR$(95);:NEXT:PRINTCHR$(19); BG 280 OPEN1,0:INPUT#1,A$ CD 290 POKE53280,BR:POKE53281, BGsPOKE49261,FG XH 300 SYS49152 BH 310 POKE53280,14:POKE53281, 6:PRINTCHR$(147);CHR$(154); ER 320 POKE55,0:POKE56,160:CLR:END JG 330 DATA 173, 14, 220, 41, 254, 141, 14, 220 DK 340 DATA 165, 1, 41, 251, 133, 1, 169, 0 HC 350 DATA 133, 251, 133, 253, 169, 208, 133, 252 RD 360 DATA 169, 196, 133, 254, 162, 2, 160, 0 XQ 370 DATA 177, 251, 145, 253, 200, 208, 249, 230 CG 380 DATA 252, 230, 254, 202, 208, 240, 165, 1 SS 390 DATA 9, 4, 133, 1, 173, 14, 220, 9 EM 400 DATA 1, 141, 14, 220, 162, 0, 160, 0 QR 410 DATA 189, 0, 4, 201, 31, 240, 11, 153 BS 420 DATA 0, 198, 232, 224, 250, 240, 3, 200 KE 430 DATA 208, 238, 169, 32, 153, 0, 198, 200 HB 440 DATA 153, 0, 198, 200, 169, 0, 153, 0 KF 450 DATA 198, 173, 241, 193, 208, 24, 133, 253 BQ 460 DATA 169, 216, 133, 254, 169, 14, 162, 4 BG 470 DATA 160, 0, 145, 253, 200, 208, 251, 230 JK 480 DATA 254, 202, 208, 246, 240, 38, 169, 104 MP 490 DATA 133, 253, 169, 217, 133, 254, 162, 8 JJ 500 DATA 160, 0, 189, 232, 193, 145, 253, 200 RX 510 DATA 192, 40, 208, 246, 165, 253, 24, 105 MA 520 DATA 40, 133, 253, 165, 254, 105, 0, 133 CG 530 DATA 254, 202, 208, 228, 169, 4, 133, 252 BA 540 DATA 169, 60, 133, 254, 169, 0, 133, 251 CM 550 DATA 133, 253, 162, 4, 160, 0, 169, 32 SH 560 DATA 145, 251, 145, 253, 200, 208, 249, 230 SK 570 DATA 252, 230, 254, 202, 208, 242, 173, 22 HM 580 DATA 208, 41, 247, 141, 22, 208, 169, 0 BH 590 DATA 141, 250, 193, 172, 250, 193, 238, 250 CD 600 DATA 193, 185, 0, 198, 240, 242, 133, 251 PR 610 DATA 169, 0, 133, 252, 6, 251, 38, 252 EX 620 DATA 6, 251, 38, 252, 6, 251, 38, 252 DA 630 DATA 169, 196, 24, 101, 252, 133, 252, 160 PF 640 DATA 0, 177, 251, 153, 242, 193, 200, 192 DJ 650 DATA 8, 208, 246, 32, 228, 255, 201, 0 HA 660 DATA 240, 27, 173, 22, 208, 9, 8, 141 SA 670 DATA 22, 208, 173, 24, 208, 41, 15, 9 KM 680 DATA 16, 141, 24, 208, 173, 22, 208, 41 FE 690 DATA 248, 141, 22, 208, 96, 169, 61, 133 HA 700 DATA 252, 169, 5, 133, 254, 169, 0, 141 DB 710 DATA 251, 193, 165, 252, 164, 254, 133, 254 QQ 720 DATA 132, 252, 169, 104, 133, 251, 133, 253 FC 730 DATA 162, 8, 160, 39, 177, 251, 136, 145 KG 740 DATA 253, 192, 0, 208, 247, 202, 240, 28 EG 750 DATA 165, 251, 24, 105, 40, 133, 251, 165 FH 760 DATA 252, 105, 0, 133, 252, 165, 253, 24 XX 770 DATA 105, 40, 133, 253, 165, 254, 105, 0 DH 780 DATA 133, 254, 208, 214, 198, 254, 169, 143 MD 790 DATA 133, 253, 162, 0, 160, 0, 30, 242 XP 800 DATA 193, 144, 4, 169, 160, 208, 2, 169 RQ 810 DATA 32, 145, 253, 232, 165, 253, 24, 105 JR 820 DATA 40, 133, 253, 165, 254, 105, 0, 133 CK 830 DATA 254, 224, 8, 208, 225, 173, 22, 208 RP 840 DATA 9, 7, 141, 22, 208, 162, 0, 160 AB 850 DATA 6, 202, 208, 253, 136, 208, 250, 206 RB 860 DATA 22, 208, 173, 22, 208, 41, 7, 208 ED 870 DATA 236, 198, 252, 198, 254, 173, 24, 208 HS 880 DATA 41, 15, 166, 254, 224, 61, 208, 4 PQ 890 DATA 9, 240, 208, 2, 9, 16, 162, 0 EF 900 DATA 236, 18, 208, 208, 251, 141, 24, 208 KH 910 DATA 173, 22, 208, 9, 7, 141, 22, 208 DF 920 DATA 174, 251, 193, 232, 224, 8, 240, 6 HM 930 DATA 142, 251, 193, 76, 50, 193, 76, 211 SH 940 DATA 192