Fine Scrolling Part IV
Taking the Plunge

16K Cassette or Disk
by Kyle Peacock


Well, this is it. For the past two issues I've been babbling about how much we need assembly language to accomplish smooth fine scrolling. Hopefully you've also been keeping up with Tom Hudson's Boot Camp series. If not, don't sweat. I've included both BASIC and assembly listings so that novices and advanced programmers alike can enjoy the pleasures of fine scrolling. If you've been keeping up and have a basic understanding of the material covered in issues 13 through 15, you are already well on your way to mastering fine scrolling (and maybe even publishing a best-selling game).

The following BASIC listing contains all the code we need to secure our objective. The assemblylanguage routines are contained in the DATA statements on Lines 8000-10000. All you need to do is get a grip on the parameters passed to my USR routine and the restrictions on said parameters.

The USR call in Line 790 will initialize things. This line can be located anywhere you like, as long as all the proper strings have been initialized. I've done my best to be as diverse as possible. Consequently, there are slightly over a dozen parameters to worry about. Let's examine the USR call and its associated parameters:

A=USR(INIT,VBLANK,DLIST,LINES,MINX,MAXX,
MINY,MAXY,HMAX,VMAX,HSPEED,VSPEED,STICK,
HINVERT,VINVERT,PAGES)

Disclaimer.

Although I have tried to incorporate as many features as possible into these routines, some of you out there may find they will not work for your particular application. For example, the routines will bomb out if you have an LMS instruction that is over 255 bytes away from the beginning of the display list. This problem cannot be easily remedied, as it was a design consideration. Should you encounter any other strange problems, feel free to send me a disk or tape with your program, an explanation of the problem, and a self-addressed stamped envelope. Time permitting, I'll asess the damage and (hopefully) come up with a solution.

Wow! Other than the program listing, I'm all done. I had no idea how involving this column would be. From now on I'll stick to playing and reviewing games. Maybe one day I'll review your masterpieces, incorporating fine scrolling. Until then, see you in the funny papers.

BASIC Listing

FSCROLL4.LST is available in ATASCII format.

The BASIC listing uses an image to display special characters


Checksum Data
100 DATA 526,476,135,536,542,770,544,9
5,988,101,426,664,82,977,88,6950
250 DATA 244,226,971,100,692,844,81,32
1,649,729,188,96,254,794,626,6815
400 DATA 895,83,537,651,890,95,126,944
,705,9,524,871,906,91,167,7494
550 DATA 97,473,854,927,109,517,87,441
,410,96,687,102,929,108,391,6228
700 DATA 275,677,843,103,562,905,727,1
07,7,81,984,717,94,228,100,6410
850 DATA 748,499,339,866,349,748,372,3
20,336,503,504,765,375,771,347,7842
1000 DATA 275,69,277,91,579,580,581,58
2,583,584,578,36,289,995,291,6390
8030 DATA 887,727,417,132,632,360,583,
441,137,645,602,597,879,883,462,8384
8180 DATA 674,461,577,153,472,606,609,
422,417,608,872,762,339,468,561,8001
9000 DATA 291,457,293,620,480,337,650,
474,402,337,885,587,443,344,886,7486
9150 DATA 342,484,688,407,336,434,886,
912,486,653,594,195,472,192,601,7682
9300 DATA 453,616,618,347,586,583,460,
418,369,480,373,492,175,640,390,7000
9450 DATA 625,174,448,594,664,616,330,
670,492,516,784,664,670,923,625,8795
9600 DATA 953,188,554,1695
Assembly Listing

FSCROLL4.ASM is available in ATASCII format

0100     .OPT NO LIST
0110 ;
0120 ; **************
0130 ; SYSTEM EQUATES
0140 ; **************
0150 ;
0160 POKMSK = $10    ;POKEY INTERRUPT
0170 SDLSTL = $0230  ;DLIST POINTER
0180 STICK0 = $0278  ;JOYSTICK PORT
0190 IRQEN = $D20E   ;INTER. REQUEST
0200 HSCROL = $D404  ;SCROLL REGISTER
0210 VSCROL = $D405  ;SCROLL REGISTER
0220 SETVBV = $E45C  ;SET TIMERS
0230 XITVBV = $E462  ;EXIT DEF VBLANK
0240 ;
0250 ; **********************
0260 ; MEMORY USAGE & EQUATES
0270 ; **********************
0280 ;
0290 LISTLO = $0600  ;DLIST LO-BYTE
0300 LISTHI = $0601  ;DLIST HI-BYTE
0310 MINX =  $0602   ;LEFTMOST LIMIT
0320 MINY =  $0603   ;UPPER LIMIT
0330 MAXX =  $0604   ;RIGHTMOST LIMIT
0340 MAXY =  $0605   ;LOWER LIMIT
0350 HMAX =  $0606   ;LARGEST HSCROL
0360 VMAX =  $0607   ;LARGEST VSCROL
0370 ALINES = $0608  ;# OF D-LINES
0380 STICK = $0609   ;JOYSTICK #
0390 HSPEED = $060A  ;HOR. SPEED
0400 VSPEED = $060B  ;VER. SPEED
0410 HINVERT = $060C ;INVERSION FLAG
0420 VINVERT = $060D ;INVERSION FLAG
0430 PAGES = $CB     ;SCREEN PAGES
0440 ZPAGE = $CD     ;ZERO PAGE INDEX
0450 ;
0460 ; **************************
0470 ; MISCELLANEOUS MEMORY USAGE
0480 ; **************************
0490 ;
0500 HBIT =  $060E   ;'HSCROL' COPY
0510 VBIT =  $060F   ;'VSCROL' COPY
0520 HTIME = $0610   ;'HSPEED' COPY
0530 VTIME = $0611   ;'VSPEED' COPY
0540 HPOINT = $0612  ;SHIFT COUNTER
0550 VPOINT = $0613  ;SHIFT COUNTER
0560 DLINES = $0614  ;LMS OPCODES CNT
0570 COUNT = $0615   ;'DLINES' COPY
0580 TEMP =  $0616   ;TEMP STORAGE
0590 TEMP1 = $0617   ;TEMP STORAGE
0600 XHOLD1 = $0618  ;TEMP STORAGE
0610 XHOLD2 = $0619  ;TEMP STORAGE
0620 OPCODE = $061A  ;DLIST OPCODE
0630 VBLANK = $061B  ;VBLANK VECTOR
0640 OFFSETS = $061D ;OFFSETS TO LMS
0650 STOPALL = $06FF ;HOLD EVERYTHING
1000     .INCLUDE #D:VAR.ASM
1010 ;
1020 ;**********************
1030 ;INITIALIZATION ROUTINE
1040 ;**********************
1050 ;INITIALIZATION ROUTINE
1060     *=  $4000
1070     LDA POKMSK  ;GET IRQ. INT.
1080     AND #$7F    ;NO BREAK KEY
1090     STA POKMSK  ;THE BREAK KEY
1100     STA IRQEN   ;NO LONGER WORKS
1110     CLD         ;CLEAR DECIMAL
1120     PLA         ;# OF ARGUEMENTS
1130     PLA         ;VBLANK HI/BYTE
1140     STA VBLANK+1
1150     PLA         ;VBLANK LO/BYTE
1160     STA VBLANK
1170     PLA         ;DLIST HI/BYTE
1180     STA LISTHI
1190     PLA         ;DLIST LO/BYTE
1200     STA LISTLO
1210     PLA         ;DISCARD
1220     PLA         ;GET 'LINES'
1230     STA ALINES
1240     PLA         ;DISCARD
1250     PLA         ;GET 'MINX'
1260     STA MINX
1270     STA HPOINT  ;RESET TO START
1280     PLA         ;DISCARD
1290     PLA         ;GET 'MAXX'
1300     STA MAXX
1310     PLA         ;DISCARD
1320     PLA         ;GET 'MINY'
1330     STA MINY
1340     STA VPOINT  ;RESET TO START
1350     PLA         ;DISCARD
1360     PLA         ;GET 'MAXY'
1370     STA MAXY
1380     PLA         ;DISCARD
1390     PLA         ;GET 'HMAX'
1400     STA HMAX
1410     PLA         ;DISCARD
1420     PLA         ;GET 'VMAX'
1430     STA VMAX
1440     PLA         ;DISCARD
1450     PLA         ;GET 'HSPEED'
1460     STA HSPEED
1470     PLA         ;DISCARD
1480     PLA         ;GET 'VSPEED'
1490     STA VSPEED
1500     PLA         ;DISCARD
1510     PLA         ;GET 'STICK'
1520     STA STICK
1530     PLA         ;DISCARD
1540     PLA         ;GET 'HINVERT'
1550     STA HINVERT
1560     PLA         ;DISCARD
1570     PLA         ;GET 'VINVERT'
1580     STA VINVERT
1590     PLA         ;PAGE USAGE HI
1600     STA PAGES+1 ;STORE IT
1610     PLA         ;PAGE USAGE LO
1620     STA PAGES   ;STORE IT
1630     LDA #$01    ;INITIALIZE RAM
1640     STA HTIME   ;COPY OF SPEED
1650     STA VTIME   ;TIMERS.
1660 ;
1670 ;*******************************
1680 ;EXAMINE DLIST, NOTE LMS OPCODES
1690 ;*******************************
1700 ;
1710     LDA ZPAGE   ;SAVE WHATEVER
1720     PHA         ;IS IN MEM. LOC.
1730     LDA ZPAGE+1 ;SAVE WHATEVER
1740     PHA         ;IS IN MEM. LOC.
1750     LDA LISTLO  ;GET DLIST/LO &
1760     STA ZPAGE   ;PUT IN WORKAREA
1770     LDA LISTHI  ;GET DLIST/HI &
1780     STA ZPAGE+1 ;PUT IN WORKAREA
1790     LDY #$00    ;SET UP COUNTER
1800     LDX #$00    ;SET UP COUNTER
1810     STX VBIT    ;SET UP SCROLL
1820     STX VBIT    ;BITS TO ZERO
1830 DLOOK LDA (ZPAGE),Y ;GET DISPLAY
1840     STA OPCODE  ;LIST OPCODE
1850     AND #$0F    ;IS IT A BLANK
1860     BEQ NEXT    ;LINE OPCODE?
1870     LDA OPCODE  ;IS IT AN LMS
1880     AND #$40    ;OPCODE?
1890     BEQ NEXT
1900     INY         ;IF SO, SKIP
1910     INY         ;LMS OPERANDS
1920     LDA OPCODE
1930     AND #$0F    ;IS IT A JVB
1940     CMP #$01    ;OPCODE?
1950     BEQ DONE    ;IF SO, STOP.
1960     LDA OPCODE  ;ARE SCROLL BITS
1970     AND #$30    ;OF OPCODE SET?
1980     BEQ NEXT
1990     TYA         ;THIS IS AN LMS
2000     SEC         ;OPCODE W/SROLL
2010     SBC #$02    ;BITS SET. SAVE
2020     STA OFFSETS,X ;THE OFFSET.
2030     INX 
2040 NEXT INY        ;MOVE TO NEXT
2050     BNE DLOOK   ;DLIST OPCODE.
2060 DONE STX DLINES ;SAVE # OF LINES
2070     PLA         ;RESTORE MEM.
2080     STA ZPAGE+1 ;LOCATION.
2090     PLA         ;RESTORE MEM.
2100     STA ZPAGE   ;LOCATION.
2110     LDA #$07    ;TELL SYSTEM TO
2120     LDX VBLANK+1 ;SET UP DEF.
2130     LDY VBLANK  ;VERTICAL BLANK
2140     JSR SETVBV  ;ROUTINE.
2150     RTS         ;ALL DONE. BYE!
7000     .INCLUDE #D:VAR.ASM
7010 ;
7020 ;**************************
7030 ;TIME TO HORIZONTAL SCROLL?
7040 ;**************************
7050 ;
7060     *=  $5000
7070     LDA STOPALL ;IS IT OKAY TO
7080     BEQ PLUNGE  ;EXECUTE?
7090     JMP XITVBV  ;NO! BYE!
7100 PLUNGE CLD      ;YES, CLEAR DEC.
7110     LDA LISTLO  ;TELL ANTIC
7120     STA SDLSTL  ;WHERE YOUR NEW
7130     LDA LISTHI  ;DISPLAY LIST IS
7140     STA SDLSTL+1
7150     DEC HTIME   ;DECREMENT TIMER
7160     BNE ENDIT   ;IF <> 0, STOP!
7170     LDA HSPEED  ;RESET TIMER
7180     STA HTIME
7190     BEQ ENDIT   ;IF = 0, STOP!
7200 ;
7210 ; NOW READ CORRECT JOYSTICK
7220 ;
7230     LDX STICK   ;GET POSITION OF
7240     LDA STICK0,X ;RIGHT JOYSTICK
7250     LDY HINVERT ;SHOULD WE IN-
7260     BNE HOPP    ;VERT HOR. MOVE
7270 ;
7280 ;SCROLL DIRECTION ISN'T INVERTED
7290 ;
7300     AND #$0C    ;SCAN SELECT
7310     CMP #$08    ;JOYSTICK BITS
7320     BEQ HLEFT   ;MOVE LEFT
7330     CMP #$04
7340     BEQ HRIGHT  ;MOVE RIGHT
7350     BNE ENDIT
7360 ;
7370 ;SCROLL DIRECTION IS INVERTED
7380 ;
7390 HOPP AND #$0C   ;SCAN SELECT
7400     CMP #$04    ;JOYSTICK BITS
7410     BEQ HLEFT   ;MOVE LEFT
7420     CMP #$08
7430     BNE ENDH    ;MOVE RIGHT
7440 ;
7450 ; SCROLL RIGHT
7460 ;
7470 HRIGHT INC HBIT ;INCREMENT RAM
7480     LDA HBIT    ;'HSCROL' COPY
7490     CMP HMAX    ;IS IT ABOVE
7500     BEQ ENDH    ;VALID SCROLL
7510     BCC ENDH    ;LIMIT?
7520     LDA HPOINT  ;YES! ARE WE AT
7530     CMP MINX    ;LEFTMOST BOUND?
7540     BNE HOR5    ;NO, CONTINUE
7550     DEC HBIT    ;YES! HALT
7560     BEQ ENDH    ;SCROLL & QUIT
7570     BNE ENDH
7580 HOR5 DEC HPOINT ;CONTINUE.
7590     LDA #$FF    ;PERFORM BYTE
7600     PHA         ;SHIFTING W/HFIX
7610     BMI HFIX    ;ROUTINE
7620 HOR55 LDA #$00  ;RESET 'HSCROL'
7630     STA HBIT    ;RAM COPY.
7640     BEQ ENDH    ;ALL DONE.
7650 ;
7660 ;INC/DEC LMS LO/BYTE OPERANDS
7670 ;
7680 HFIX STA TEMP   ;GET BYTES TO
7690     PLA         ;INC/DEC LO-BYTE
7700     STA TEMP1   ;OF LMS OPERANDS
7710     LDX ALINES  ;GET # OF LINES
7720     DEX         ;MINUS ONE
7730     LDY #$00    ;SET INDEX TO 0
7740 HFIX5 LDA (PAGES),Y ;GET OPERAND
7750     CLC 
7760     ADC TEMP    ;INC/DEC IT
7770     STA (PAGES),Y ;PUT IT BACK
7780     INY         ;CHECK FOR WRAP
7790     LDA (PAGES),Y ;AROUND OF LO
7800     ADC TEMP1   ;BYTE INTO HI
7810     STA (PAGES),Y ;BYTE. FIXITUP
7820     INY         ;ADJUST POINTER
7830     DEX         ;DID WE DO ALL?
7840     BPL HFIX5   ;NO! CONTINUE
7850     LDA TEMP    ;YES! DECIDE
7860     BMI HOR55   ;WHO CALLED THIS
7870     BPL HOR66   ;ROUTINE. RETURN
7880 ;
7890 ;INTERMEDIATE BRANCH
7900 ;
7910 ENDIT BEQ ENDH  ;NO MATTER WHAT
7920     BNE ENDH    ;BRANCH TO END.
7930 ;
7940 ; SCROLL LEFT
7950 ;
7960 HLEFT DEC HBIT  ;DEC HSCROL COPY
7970     BPL ENDH    ;OUT OF RANGE?
7980     LDA HPOINT  ;YES! ARE WE AT
7990     CMP MAXX    ;RIGHT BOUND?
8000     BNE HOR6    ;NO! CONTINUE
8010     INC HBIT    ;YES! HALT
8020     BEQ ENDH    ;SCROLL & QUIT
8030     BNE ENDH
8040 HOR6 INC HPOINT ;NO! PERFORM
8050     LDA #$00    ;BYTE SHIFTING
8060     PHA         ;W/HFIX ROUTINE
8070     LDA #$01
8080     BPL HFIX
8090 HOR66 LDA HMAX  ;RESET 'HSCROL'
8100     STA HBIT    ;RAM COPY
8110 ;
8120 ; TIME TO VERTICAL SCROLL?
8130 ;
8140 ENDH DEC VTIME  ;DEC. TIMER
8150     BNE ENDV    ;IF <> 0, QUIT
8160     LDA VSPEED  ;RESTORE TIMER
8170     STA VTIME   ;FOR NEXT TIME
8180     BEQ ENDV    ;IF = 0, QUIT
8190 ;
8200 ; READ CORRECT JOYSTICK
8210 ;
8220     LDX STICK   ;GET JOYSTICK #
8230     LDA STICK0,X ;GET READING
8240     LDY VINVERT ;IS VER. SCROLL
8250     BNE VOPP    ;INVERTED?
8260 ;
8270 ;VERTICAL SCROLL ISN'T INVERTED
8280 ;
8290     AND #$03    ;SCAN SELECT
8300     CMP #$02    ;BITS
8310     BEQ VUP     ;SCROLL UP
8320     CMP #$01
8330     BEQ VDOWN   ;SCROLL DOWN
8340     BNE ENDV
8350 ;
8360 ;VERTICAL SCROLL IS INVERTED
8370 ;
8380 VOPP AND #$03   ;SCAN SELECT
8390     CMP #$01    ;BITS
8400     BEQ VUP     ;SCROLL UP
8410     CMP #$02    ;SCROLL DOWN
8420     BNE ENDV    ;DO NADA!
8430 ;
8440 ;SCROLL DOWN
8450 ;
8460 VDOWN DEC VBIT  ;DEC VSCROL COPY
8470     BPL ENDV    ;IN VALID RANGE?
8480     LDA VPOINT  ;NO! ARE WE AT
8490     CMP MINY    ;UPPER BOUND?
8500     BNE VER5    ;NO! CONTINUE
8510     INC VBIT    ;YES! STOP
8520     BEQ ENDV    ;SCROLL & QUIT
8530     BNE ENDV
8540 VER5 DEC VPOINT ;ADJUST VERTICAL
8550     LDA VMAX    ;RESET RAM COPY
8560     STA VBIT    ;OF 'VSCROL'
8570     BEQ ENDV    ;ALL DONE!
8580     BNE ENDV
8590 ;
8600 ;SCROLL UP
8610 ;
8620 VUP INC VBIT    ;INC RAM COPY
8630     LDA VBIT    ;OF 'VSCROL'
8640     CMP VMAX    ;IS IT IN VALID
8650     BEQ ENDV    ;RANGE?
8660     BCC ENDV
8670     LDA VPOINT  ;NO! ARE WE AT
8680     CMP MAXY    ;LOWER BOUND?
8690     BNE VER6    ;NO! CONTINUE
8700     DEC VBIT    ;YES! HALT
8710     BEQ ENDV    ;SCROLL & QUIT
8720     BNE ENDV
8730 VER6 INC VPOINT ;ADJUST VERTICAL
8740     LDA #$00    ;RESET RAM COPY
8750     STA VBIT    ;OF 'VSCROL'
8760 ENDV LDA HBIT   ;INSTALL COPY
8770     STA HSCROL  ;INTO 'HSCROL'
8780     LDA VBIT    ;INSTALL COPY
8790     STA VSCROL  ;INTO 'VSCROL'
8800 ;
8810 ;INSTALL PAGE DATA INTO DLIST
8820 ;
8830 FIX LDA DLINES  ;GET # OF LMS
8840     BEQ RTS     ;OPCODES
8850     STA COUNT   ;HOLD ON TO IT
8860     LDA ZPAGE   ;SAVE WHATEVER
8870     PHA         ;IS IN MEM. LOC.
8880     LDA ZPAGE+1 ;SAVE WHATEVER
8890     PHA         ;IS IN MEM. LOC.
8900     LDX #$00    ;SET INDEX TO 0
8910     STX XHOLD1
8920     LDA VPOINT  ;VERTICAL POINT
8930     ASL A       ;MULTIPLY BY 2
8940     STA XHOLD2  ;HOLD ON TO IT
8950     LDA SDLSTL  ;GET LO/DLIST &
8960     STA ZPAGE   ;PUT IN WORKAREA
8970     LDA SDLSTL+1 ;GET HI/DLIST &
8980     STA ZPAGE+1 ;PUT IN WORKAREA
8990 HSTUFF LDY XHOLD2 ;PAGE INDEX
9000     LDA (PAGES),Y ;PAGE DATA
9010     PHA         ;SAVE IT
9020     LDX XHOLD1  ;OFFSET INDEX
9030     LDA OFFSETS,X ;OFFSET TO LMS
9040     TAY         ;HOLD IT
9050     INY         ;PLUS ONE
9060     PLA         ;GET PAGE DATA
9070     STA (ZPAGE),Y ;PUT IN DLIST
9080     INC XHOLD2  ;INC PAGE INDEX
9090     LDY XHOLD2  ;GET IT AGAIN
9100     LDA (PAGES),Y ;PAGE DATA
9110     PHA         ;SAVE IT
9120     LDA OFFSETS,X ;OFFSET TO LMS
9130     TAY         ;HOLD IT
9140     INY         ;PLUS ONE
9150     INY         ;PLUS TWO
9160     PLA         ;GET PAGE DATA
9170     STA (ZPAGE),Y ;PUT IN DLIST
9180     INC XHOLD1  ;INC OFFSET INDEX
9190     INC XHOLD2  ;INC PAGE INDEX
9200     DEC COUNT   ;ARE WE DONE?
9210     BNE HSTUFF  ;NO! KEEP GOING.
9220     PLA         ;RESTORE MEMORY
9230     STA ZPAGE+1 ;LOCATION
9240     PLA         ;RESTORE MEMORY
9250     STA ZPAGE   ;LOCATION
9260 RTS JMP XITVBV  ;ALL DONE. LATER!

Previous | Contents | Next

Original text copyright 1984 by ANALOG Computing. Reprinted with permission by the Digital ANALOG Archive.