
	;-----------------------------------------------------
	;
	; Bounce a heart around the screen
	; Vic 20 assembly demo by
	; Dennis Katsonis, Sep 2020
	;
	; This is my first 6502 assembly program.  I have a Vic 20
	; but it doens't work.  If I can restore it, I'll be able to
	; run this on native hardware!
	;
	; Compile using ca65
	; cl65 -t vic20 -C vic20.cfg heartvic.asm
	;
	;-----------------------------------------------------

	offset=$FB
	xpos = $FD
	ypos = $FE
	deltax = $F9 		; RS-232 tx pointer ZP location.  We aren't using this.
	deltay = $F8		; We store delta x and y here.
	sndcnt = $FA
	
	SCREENMAP=36869
	HORIZOFFSET=36864
	VERTOFFSET=$9001	; 36865
	COLSIZE=$9002 	;36866
	ROWSIZE=36867
	ROWS=30
	COLUMNS=25
	VOLUME=36878
	SPEAKER2=36875
	SPEAKER3=36874

	lda #1
	sta xpos
	sta ypos		; Set starting coordinates to 1,1
	sta deltax
	sta deltay
	sta sndcnt
	lda $52 		; Save end of basic memory
	sta old52
	lda $56
	sta old56
	lda SCREENMAP
	sta oldSCREENMAP		; Save current pointer to character set and other VIC 


	lda #24			; Set end of basic to $1800
	; This gives us only 2K of space to work in!  Although very limited by
	; todays standards, its more than enough for this program.
	sta $52
	lda #24		      ; Set end of basic to $1800.  This is where our characters
	; will be stored

	; The memory layout of this program is as follows
	; $1000 - $17FF : BASIC
	; $1800 - $1BFF : Custom Characters (We only use the first 512 bytes)
	; $1C00 - $1FFF : Screen map (We only need 750 bytes)
	
	sta $56		; Lower end of basic memory to make room
	; for our custom character set.


	
	lda COLSIZE
	sta oldCOLSIZE
	lda #COLUMNS		; This will clear the 7th bit, moving
	sta COLSIZE		; the location of the screen map to 7160 ($1c00)
	; It will also move the colour map to 37888 ($9400)
	lda ROWSIZE
	sta oldROWSIZE
	and #129
	ora #(ROWS*2)
	sta ROWSIZE

	lda HORIZOFFSET			; information
	sta oldHORIZOFFSET
	clc
	sbc #3			; Shift to the left
	sta HORIZOFFSET
	
	lda VERTOFFSET
	sta oldVERTOFFSET
	clc
	sbc #12			; Shift up
	sta VERTOFFSET


	ldx #0
copychar:
	lda $8000,x
	sta $1800,x
	lda $8100,x
	sta $1900,x
	dex
	bne copychar		; Copy Character memory to location $1800

	ldx #0
copysmiley:
	lda smiley,x
	sta $1800,x
	inx
	cpx #8
	bne copysmiley

	
	lda #254		; 254 is 240 AND 14
	; The 14 refers to the lower three bits, which places the character map at 6144
	; 250 refers to bits 4-7, which with bit 7 of 36866 cleared, places the screen map
	; at 7168
	; This gives the screen map enough space for the extended screen size.
	; Refer to technical documentation for more info.
	sta SCREENMAP		; :Point VIC to our own character set
 	lda #14			; Black background, blue border
	sta $900F 		; Set background/foreground

	ldx #0
	lda #4
colloop1:
	sta $9400,x
	sta $9500,x
	sta $9600,x
	dex
	bne colloop1  		; Loop over color map and set to magenta.
	; We will only worry about the first 768 bytes.
	
	ldx #0
	lda #32
loop1:  sta $1c00,x
	sta $1d00,x
	sta $1E00,x
	dex
	bne loop1 		; Loop over character map and set to space
	; We will only worry about the first 768 bytes.

colorloop:
	ldx xpos
	ldy ypos

	cpx #(COLUMNS-1)			;22nd column
	beq flipx
	cpx #0
	beq flipx
xdone:
	cpy #(ROWS-1)			;23rd row
	beq flipy
	cpy #0
	beq flipy
ydone:
	clc
	txa
	adc deltax		; Add the 'delta x', which would either
	; increment or decrement this by 1.
	tax
	
	clc
	tya
	adc deltay
	tay

	stx xpos
	sty ypos

	jsr plotit
	lda #0			; Load the PETSCII for a heart.
	ldy xpos
	sta (offset),y		; Save the heart at offset + y (which actually holds
	; the X position).
	jsr wait
	lda #32
	ldy xpos
	sta (offset),y
	jsr checksnd
	jsr $ffe1		
	bne colorloop
end:
	lda oldSCREENMAP	; Restore character set and other VIC values to restore
	sta SCREENMAP		; screen size and position.
	lda oldCOLSIZE
	sta COLSIZE
	lda oldROWSIZE
	sta ROWSIZE

	lda oldHORIZOFFSET
	sta HORIZOFFSET
	lda oldVERTOFFSET
	sta VERTOFFSET

	lda old52
	sta $52
	lda old56
	sta $56		; Restore end of basic memory

	rts
	
flipx:
	lda deltax
	eor #$fe		; Negate all the bits except LSB
	sta deltax		;   Effectively alternating between the values
	; of 1 and 254 
	;  If we add 254, it is effectively the same as subtracting 1
	jsr beep
	jmp xdone
flipy:
	lda deltay
	eor #$fe
	sta deltay
	jsr beep
	jmp ydone

plotit:
	lda #00
	sta offset
	lda #$1C
	sta offset+1
	clc
	ldx ypos
	beq endplot 		; Add nothing if row 0
plotitl:
	clc
	lda offset
	adc #COLUMNS
	sta offset
	lda offset+1
	adc #0
	sta offset+1
	dex
	bne plotitl
endplot:
	rts

checksnd:
	lda sndcnt
	cmp #0
	beq skipcheck
	lda VOLUME
	sbc #5
	sta VOLUME
	dec sndcnt
	bne skipcheck
	lda #0
	sta SPEAKER2
	STA SPEAKER3
skipcheck:
	rts
	
wait:
	lda #0
	sta 162
waitl:
	lda 162
	cmp #4
	bne waitl
	rts

beep:
	lda #15
	sta VOLUME
	lda #220
	sta SPEAKER2
	lda #200
	sta SPEAKER3
	lda #3
	sta sndcnt
	rts
	
old52: .byte 0
old56: .byte 0
oldSCREENMAP: .byte 0
oldHORIZOFFSET: .byte 0
oldVERTOFFSET: .byte 0
oldCOLSIZE: .byte 0
oldROWSIZE: .byte 0
smiley: .byte 60,66,165,129,165,153,66,60



