;
;###################################
;# 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



    Source: geocities.com/timessquare/alley/3583/prog

               ( geocities.com/timessquare/alley/3583)                   ( geocities.com/timessquare/alley)                   ( geocities.com/timessquare)