;
;###################################
;# silky smooth sideways scrolling #
;# AS65 source #
;# public domain 13 Mar 1997 #
;# by B.W. van Schooten #
;###################################
;This program demonstrates a smooth scrolling algorithm with double buffering.
;The method can be modified to support bidirectional scrolling. However, it
;won't work for eight-directional scroll. In that case, you'll have to have
;non-smooth scrolling in one of the two axes, or employ a different method for
;that axis. (for example, you could smooth-scroll horizontally using this
;method, and smooth-scroll vertically by using the panning registers).
;
;The method
;----------
;
;Normally, one would define a background by using the characters in the Vic's
;character matrix as tiles. However, if you want to scroll, you'll normally
;have to scroll one whole tile position at a time. This is quite a jump, and
;won't look smooth unless you scroll *very* fast.
;
;This method does allow smooth scrolling using a similar kind of tile map;
;however, the number of different tile shapes you can use in the scroll area is
;limited. The basic idea is that one uses a separate character for each
;possible transition between two neighbouring tiles in the scroll direction.
;
;For example, if we have two tiles A and B, we have to allocate four
;characters, say 0(AA), 1(AB), 2(BA), 3(BB). In general, if you want to use N
;tile definitions, you will need to allocate N^2 characters. The theoretical
;maximum is 16(16^2=256), unless you specifically disallow certain pairings
;of tile shapes, which will however make the algorithm more complicated.
;
;The screen is built up by pairing these 'transition' characters side-to-side,
;like dominoes. For example, if we scroll horizontally,
;
;A A B B ?A AA AB BB B?
;A B A B would become ?A AB BA AB B?
;B A B A ?B BA AB BA A?
;
;Note that the tile shapes at the very left and right are not defined.
;Normally, we would put the characters we are scrolling off, or are about to
;scroll onto the screen in place of the '?'s.
;
;In this program, we scroll to the left. What we do with each of these
;domino characters is
;
;1 load them first with the tile shape that corresponds to the left side of
; the domino,
;
;2 then, shift in, bit by bit, the right side tile shape.
;
;3 When we have shifted 8 bits, the left side will have been replaced by the
; right side, and we have scrolled 8 pixels. Instead of shifting the 8th bit,
; we reload the characters with the left side again, and scroll the screen one
; character to the left, so the screen looks exactly the same as when we
; would have shifted the 8th bit. In this case however, we are effectively
; back at step one and we can repeat the process.
;
;
;
;Initial load pattern
; (left side tile)
;0 1 . n
;
;| | . |
;| | . |
;
;00 10 .. n0 <- 0 } pattern to be
;01 11 .. n1 <- 1 } shifted in
;.. .. .. .. .. . }
;0n 1n .. nn <- n } (right side tile)
;
;
;How to display colours
;----------------------
;
;There is another limitation, namely, the foreground colour must be the same
;for any two neighbouring tiles that both use this colour. If you want to use
;different foreground colours anyway, you'll have to make sure there's empty
;spaces between the tiles in question, or use multicolour mode.
;
;This program uses 8 definitions (64 transition characters), and scrolls in
;multicolour mode. It does not support multiple foreground colours. In that
;case one would have to scroll the colour screen as well, and would be limited
;to a 512-byte screen, because double buffering requires two pages in the
;colour memory, which is only 1024 bytes long.
;------------------------ CONSTANTS USED BY SCROLL ------------------------
;screen1/2 must be multiple of 512.
screen1 equ 7680;1e00
chars1 equ 7168;1c00
colourscr1 equ $9400+(screen1&512)
screen2 equ 6656;1a00
chars2 equ 6144;1800
colourscr2 equ $9400+(screen2&512)
scr1_9005 equ $f0
scr2_9005 equ $e0
chr1_9005 equ $0f
chr2_9005 equ $0e
;----------------------- VARIABLES USED BY SCROLL -------------------------
scrollorvalue equ $ff ;temp variable
;913
newtiles equ $0342 ;shapes about to be scrolled in
oldtiles equ $0342+23 ;shapes scrolled in last time
jmpadr equ $03bd ;2-byte temp variable
scrollphase equ $03bf ;phase 0..3 4..7 (see also scroll)
shiftinpat equ $03c0 ;tile shapes to be shifted in
;----------------------------- MISC VARIABLES -----------------------------
quickrndseed equ $0340;2b
;---------------------------------- MAIN ----------------------------------
org 4095
db lo 4097,hi 4097
db 11,17,205,7,158,'4109',0,0,0 ;BASIC program
entrypoint:
sei ;Prevent glitches
jsr quickrandomize
lda #-1
sta scrollphase
;Define colours and fill screen
lda #$78 ;Bord:BLK Back: YEL
sta $900f
lda #$a0 ;Auxi:LT RED
sta $900e
ldx #0
fillcolour:
lda #$0a ;Fore: RED
sta colourscr1,x
sta colourscr1+256,x
sta colourscr2,x
sta colourscr2+256,x
lda #0
sta screen1,x
sta screen1+256,x
lda #0
sta screen2,x
sta screen2+256,x
inx
bne fillcolour
;Initialise the left side of the first domino characters
ldx #19
initoldtiles:
lda #0
sta oldtiles,x
dex
bpl initoldtiles
mainloop:
;Define some random tile shapes to be scrolled in at the right
ldx #3
chgrndtiles:
jsr quickrnd
and #15
tay
jsr quickrnd
and #7
sta newtiles,y
jsr quickrnd
and #15
clc
adc #4
tay
jsr quickrnd
and #7
sta newtiles,y
dex
bpl chgrndtiles
lda #0
jsr waitsync ;wait for top of screen
jsr scroll
jmp mainloop
;------------------------------ SCROLL -------------------------------------
;This macro reloads the domino characters with their corresponding left
;parts. The loop is unrolled for extra speed.
;I: chardefs.
;u: P A X Y
;O: shiftinpat, chrdst
scroll_reload macro chrdst
ldx #0
ldy #0
scroll_load\?
lda chardefs,x
sta shiftinpat,x
sta chrdst,y
sta chrdst+8,y
sta chrdst+16,y
sta chrdst+24,y
sta chrdst+32,y
sta chrdst+40,y
sta chrdst+48,y
sta chrdst+56,y
lda chardefs+4*8,x
sta shiftinpat+4*8,x
sta chrdst+256,y
sta chrdst+264,y
sta chrdst+272,y
sta chrdst+280,y
sta chrdst+288,y
sta chrdst+296,y
sta chrdst+304,y
sta chrdst+312,y
inx
iny
tya
and #7
bne scroll_load\?
tya
clc
adc #64-8
tay
bne scroll_load\?
endm
;This macro scrolls the screen one tile to the left and draws the domino
;characters that are supposed to scroll in at the right.
;I: scrsrc, oldtiles, newtiles
;u: P A X Y
;O: scrdst, oldtiles
scroll_scrtile macro scrsrc,scrdst
ldx #0
txa
scroll_scr1b\?
pha
ldy #21
scroll_scr1a\?
lda scrsrc+1,x
sta scrdst,x
lda scrsrc+1*22+1,x
sta scrdst+1*22,x
lda scrsrc+10*22+1,x
sta scrdst+10*22,x
lda scrsrc+11*22+1,x
sta scrdst+11*22,x
inx
dey
bne scroll_scr1a\?
pla
tay
pha
lda oldtiles,y
asl a
asl a
asl a
ora newtiles,y
sta scrdst,x
lda oldtiles+1,y
asl a
asl a
asl a
ora newtiles+1,y
sta scrdst+1*22,x
lda oldtiles+10,y
asl a
asl a
asl a
ora newtiles+10,y
sta scrdst+10*22,x
lda oldtiles+11,y
asl a
asl a
asl a
ora newtiles+11,y
sta scrdst+11*22,x
txa
clc
adc #2*22-21
tax
pla
clc
adc #2
cmp #10
bne scroll_scr1b\?
ldx #21
scroll_copytiles_lp\?
lda newtiles,x
sta oldtiles,x
dex
bpl scroll_copytiles_lp\?
endm
;This macro shifts two bits (one multicolour pixel) to the left. The loop
;is unrolled for extra speed.
;I: chrsrc, shiftinpat
;u: P A X Y, scrollorvalue
;O: chrdst, shiftinpat
scroll_shift macro chrsrc,chrdst
ldx #63
scroll_shloop\?
lda #0
asl shiftinpat,x
rol a
asl shiftinpat,x
rol a
sta scrollorvalue
lda chrsrc+8*00,x
asl a
asl a
ora scrollorvalue
sta chrdst+8*00,x
lda chrsrc+8*08,x
asl a
asl a
ora scrollorvalue
sta chrdst+8*08,x
lda chrsrc+8*16,x
asl a
asl a
ora scrollorvalue
sta chrdst+8*16,x
lda chrsrc+8*24,x
asl a
asl a
ora scrollorvalue
sta chrdst+8*24,x
lda chrsrc+8*32,x
asl a
asl a
ora scrollorvalue
sta chrdst+8*32,x
lda chrsrc+8*40,x
asl a
asl a
ora scrollorvalue
sta chrdst+8*40,x
lda chrsrc+8*48,x
asl a
asl a
ora scrollorvalue
sta chrdst+8*48,x
lda chrsrc+8*56,x
asl a
asl a
ora scrollorvalue
sta chrdst+8*56,x
dex
bpl scroll_shloop\?
endm
;Scroll phases (In each phase, 2 pixels are scrolled)
;Ph Action Display
;-- ----------------------- ---------
;0: chr1->chr2 scr1/chr1
;1: chr2->chr1 scr1/chr2
;2: chr1->chr2 scr1/chr1 (same as 0)
;3: reload chr1; scr1->scr2 scr1/chr2
;4: chr1->chr2 scr2/chr1
;5: chr2->chr1 scr2/chr2
;6: chr1->chr2 scr2/chr1 (same as 4)
;7: reload chr1; scr2->scr1 scr2/chr2
;I:scrollphase
;u: P A X Y, jmpadr
;O:scrollphase, whatnot...
scroll:
ldx scrollphase
inx
txa
and #7
sta scrollphase
tax
lda scrphase_hi_tbl,x
sta jmpadr+1
lda scrphase_lo_tbl,x
sta jmpadr
jmp (jmpadr)
scrphase_hi_tbl db hi scroll_0, hi scroll_1, hi scroll_0, hi scroll_3
db hi scroll_4, hi scroll_5, hi scroll_4, hi scroll_7
scrphase_lo_tbl db lo scroll_0, lo scroll_1, lo scroll_0, lo scroll_3
db lo scroll_4, lo scroll_5, lo scroll_4, lo scroll_7
scroll_0:
lda #scr1_9005+chr1_9005
sta $9005
jmp scroll_sh1to2
scroll_1:
lda #scr1_9005+chr2_9005
sta $9005
jmp scroll_sh2to1
scroll_3:
lda #scr1_9005+chr2_9005
sta $9005
scroll_scrtile screen1,screen2
jmp scroll_reload1
scroll_4:
lda #scr2_9005+chr1_9005
sta $9005
jmp scroll_sh1to2
scroll_5:
lda #scr2_9005+chr2_9005
sta $9005
jmp scroll_sh2to1
scroll_7:
lda #scr2_9005+chr2_9005
sta $9005
scroll_scrtile screen2,screen1
; jmp scroll_reload1
scroll_reload1:
scroll_reload chars1
rts
scroll_sh1to2:
scroll_shift chars1,chars2
rts
scroll_sh2to1:
scroll_shift chars2,chars1
rts
;----------------------------- MISCELLANEOUS -------------------------------
;I:A=scan #
;u:P
waitsync:
waitsync_1:
cmp $9004
beq waitsync_1
waitsync_2:
cmp $9004
bne waitsync_2
rts
;u:P A
;O:quickrndseed
quickrandomize:
lda $9116
ora #1 ;Make sure seed is always != 0
sta quickrndseed
lda $9117
sta quickrndseed+1
rts
;u:P quickrndseed
;O:A=RND number
quickrnd:
lda quickrndseed+1
asl quickrndseed
rol quickrndseed+1
adc #0
and #1 ;XOR with bit that was shifted out
ora quickrndseed
sta quickrndseed
rts
;1=BLK 2=RED 3=BROWN 0=LT PUR
chardefs:
db 4#1111
db 4#1111
db 4#1111
db 4#1111
db 4#1111
db 4#1111
db 4#1111
db 4#1111
db 4#1111
db 4#1211
db 4#1311
db 4#3031
db 4#1311
db 4#1211
db 4#1111
db 4#1111
db 4#1111
db 4#2222
db 4#3333
db 4#0000
db 4#0000
db 4#3333
db 4#2222
db 4#1111
db 4#1221
db 4#1331
db 4#2002
db 4#2002
db 4#2002
db 4#2002
db 4#1331
db 4#1221
db 4#3003
db 4#0330
db 4#0220
db 4#0110
db 4#0110
db 4#0220
db 4#0330
db 4#3003
db 4#3232
db 4#2323
db 4#3232
db 4#2323
db 4#3232
db 4#2323
db 4#3232
db 4#2323
db 4#1221
db 4#2332
db 4#3333
db 4#3003
db 4#3003
db 4#3333
db 4#2332
db 4#1221
db 4#2222
db 4#2222
db 4#3113
db 4#0220
db 4#0220
db 4#3113
db 4#2222
db 4#2222
               (
geocities.com/timessquare/alley/3583)                   (
geocities.com/timessquare/alley)                   (
geocities.com/timessquare)