.include "zp.inc"

	FRAME	= $60
	TREE1X	= $61
	TREE2X	= $62

	LETTERL	= $63
	LETTERH = $64
	LETTERX = $65
	LETTERY	= $66
	LETTERD = $67
	LETTER	= $68
	BLARGH	= $69
	MBASE	= $97
	MBOFFSET = $98

	;===================
	; init screen

	jsr	TEXT
	jsr	HOME

	;==================
	; Init vars

	lda	#28
	sta	TREE1X
	lda	#37
	sta	TREE2X

	lda	#0
	sta	MBOFFSET
	lda	#>music
	sta	MBASE

	lda	#<letters
	sta	LETTERL
	lda	#>letters
	sta	LETTERH
	lda	#39
	sta	LETTERX
	lda	#1
	sta	LETTERY
	lda	#15
	sta	LETTERD

	lda	#0
	sta	DISP_PAGE
	lda	#0
	sta	DRAW_PAGE

	;==========================
	; setup mockingboard

	jsr mockingboard_detect_slot4
	stx	MB_DETECTED
	ldx	MB_DETECTED
	beq	no_init_mb

	jsr	mockingboard_init

no_init_mb:


	;==========================
	; setup text screen

	lda	#0
	sta	CH
	sta	CV
	lda	#<line1
	sta	OUTL
	lda	#>line1
	sta	OUTH
	jsr	move_and_print

	inc	CV
	jsr	move_and_print

	inc	CV
	jsr	move_and_print

	inc	CV
	jsr	move_and_print

	inc	CV
	jsr	move_and_print

	inc	CV
	jsr	move_and_print

	; draw the moon
	lda	#0
	sta	CV
	lda	#3
	sta	CH
	jsr	htab_vtab	; vtab(1); htab(4)
	lda	#32	; inverse space
	ldy	#0
	sta	(BASL),Y

	inc	CV
	dec	CH
	jsr	htab_vtab
	lda	#32
	ldy	#0
	sta	(BASL),Y

	inc	CV
	jsr	htab_vtab
	lda	#32
	ldy	#0
	sta	(BASL),Y

	inc	CV
	inc	CH
	jsr	htab_vtab
	lda	#32
	ldy	#0
	sta	(BASL),Y


	; test letters
;letter_loop:
;	lda	#80
;	jsr	WAIT
;	jsr	move_letters
;	jmp	letter_loop

	; Wait

;	jsr	wait_until_keypressed

	; GR part
	bit	LORES
	bit	SET_GR
	bit	FULLGR

	jsr	draw_bottom_green				; 6

	; Wait

;	jsr	wait_until_keypressed

	bit	HIRES


	; Wait

;	jsr	wait_until_keypressed

	;=====================================================
	; attempt vapor lock
	;  by reading the "floating bus" we can see most recently
	;  written value of the display
	; we look for $44 (which is the green grass on low-res)
	;=====================================================
	; See:
	; 	Have an Apple Split by Bob Bishop
	; 	Softalk, October 1982

	; Challenges: each scan line scans 40 bytes.
	; The blanking happens at the *beginning*
	; So 65 bytes are scanned, starting at adress of the line - 25

	; the scan takes 8 cycles, look for 4 repeats of the value
	; to avoid false positive found if the horiz blanking is mirroring
	; the line (max 3 repeats in that case)


vapor_lock_loop:
	LDA #$A0
zxloop:
	LDX #$04
wiloop:
	CMP $C051
	BNE zxloop
	DEX
	BNE wiloop

	LDA #$44
zloop:
	LDX #$04
qloop:
	CMP $C051
	BNE zloop
	DEX
	BNE qloop

	; found first line of low-res green, need to kill time
	; until we can enter at top of screen
	; so we want roughly 5200+4550 - 65 (for the scanline we missed)

	; want 9685
	; Try X=34 Y=55 cycles=9681

	lda	#0							; 2
	lda	#0							; 2

	ldy	#55							; 2
loopA:
	ldx	#34							; 2
loopB:
	dex								; 2
	bne	loopB							; 2nt/3

	dey								; 2
	bne	loopA							; 2nt/3

	jmp	display_loop
.align	$100

	;=====================================================
	;=====================================================
	; Loop forever display loop
	;=====================================================
	;=====================================================
display_loop:
	; each scan line 65 cycles
	;	1 cycle each byte (40cycles) + 25 for horizontal
	;	Total of 12480 cycles to draw screen
	; Vertical blank = 4550 cycles (70 scan lines)
	; Total of 17030 cycles to get back to where was

	;	16666     = 17030      x=1021.8
	;         1000        x


	; TODO: find beginning of scan
	;	Text mode for 6*8=48 scanlines (3120 cycles)
	;	hgr for 64 scalines (4160 cycles)
	;	gr for 80 scalines (5200 cycles)
	;	vblank = 4550 cycles

	; text
	bit	SET_TEXT						; 4

	;================
	; clear bottom green

	jsr	draw_bottom_green				; 2209+6


	;================
	; Draw Small Tree

	lda	#>small_tree				; 2
	sta	INH					; 3
	lda	#<small_tree				; 2
	sta	INL					; 3

	lda	TREE1X					; 3
	sta	XPOS					; 3
	lda	#28					; 2
	sta	YPOS					; 3

	jsr	put_sprite				; 6
							;=========
							; 27
							; + 576
							;========
							; 603


	; want		 3120
	; green		-2215
	; tree1		 -603
	; set_test	   -4
	;=============== 298 cycles

	; Try X=1 Y=27 cycles=298

	ldy	#27							; 2
loop2:
	ldx	#1							; 2
loop1:
	dex								; 2
	bne	loop1							; 2nt/3

	dey								; 2
	bne	loop2							; 2nt/3

;=============================================

	; hgr
	bit	HIRES							; 4
	bit	SET_GR							; 4


	;================
	; Draw Big Tree

	lda	#>big_tree				; 2
	sta	INH					; 3
	lda	#<big_tree				; 2
	sta	INL					; 3

	lda	TREE2X					; 3
	sta	XPOS					; 3
	lda	#30					; 2
	sta	YPOS					; 3

	jsr	put_sprite				; 6
							;=========
							; 27
							; + 1410
							;========
							; 1437

	lda	FRAME							; 3
	and	#$1f							; 2
	and	#$10							; 2

	beq	bird_walking
									; 2
	lda	#>bird_rider_stand_right				; 2
	sta	INH							; 3
	lda	#<bird_rider_stand_right				; 2
	sta	INL							; 3

	jmp	draw_bird						; 3

bird_walking:
									; 3
	lda	#>bird_rider_walk_right					; 2
	sta	INH							; 3
	lda	#<bird_rider_walk_right					; 2
	sta	INL							; 3
	; must be 15
	lda	#0							; 2
	; Must add another 15 as sprite is different
	inc	XPOS							; 5
	inc	XPOS							; 5
	inc	XPOS							; 5


draw_bird:

							; 15 + 7
	lda	#17					; 2
	sta	XPOS					; 3
	lda	#30					; 2
	sta	YPOS					; 3

	jsr	put_sprite				; 6
							;=========
							; 38

							; + 2190
							;========
							; 2228


	;==========================
	; Update frame = 13 cycles


	inc	FRAME			; frame++			; 5
	lda	FRAME							; 3
	and	#$3f			; roll over after 63		; 2
	sta	FRAME							; 3

								;===========
								;        13

	;===========================
	; Update tree1 = 21 cycles
	and	#$3f			; if (frame%64==0)		; 2
	beq	dec_tree1
									; 2
	; need to do 19-5 cycles of nonsense
	inc	TREE1X							; 5
	dec	TREE1X							; 5
	lda	#0							; 2
	lda	#0							; 2

	jmp	done_tree1						; 3

dec_tree1:
									; 3
	dec	TREE1X			; tree1_x--			; 5
	lda	TREE1X							; 3
	bmi	tree1_neg
									; 2
	ldx	TREE1X							; 3
	jmp	done_tree1						; 3
tree1_neg:
							; incoming br     3
	ldx	#37							; 2
	stx	TREE1X							; 3
done_tree1:

	;===========================
	; Update tree2 = 24 cycles
	lda	FRAME							; 3
	and	#$f			; if (frame%16==0)		; 2
	beq	dec_tree2
									; 2
	; need to do 19-5 cycles of nonsense
	inc	TREE2X							; 5
	dec	TREE2X							; 5
	lda	#0							; 2
	lda	#0							; 2

	jmp	done_tree2						; 3

dec_tree2:
									; 3
	dec	TREE2X			; tree2_x--			; 5
	lda	TREE2X							; 3
	bmi	tree2_neg
									; 2
	ldx	TREE2X							; 3
	jmp	done_tree2						; 3
tree2_neg:
							; incoming br     3
	ldx	#37							; 2
	stx	TREE2X							; 3
done_tree2:


	; want                   4160
	; Tree2 Sprite		-1437
	; Sprite		-2228
	; Frame Update		  -13
	; Tree1 Update		  -21
	; Tree2 Update		  -24
	; hgr bits		   -8
	; ======================  429 cycles

	; Try X=13 Y=6 cycles=427 R2

	lda	#0							; 2

	ldy	#6							; 2
loop3:
	ldx	#13							; 2
loop4:
	dex								; 2
	bne	loop4							; 2nt/3

	dey								; 2
	bne	loop3							; 2nt/3

;===========================================================================


	; gr
	bit	LORES							; 4

	;=========================
	; play mockingboard
	; 11+ 84*5 + 10*4 + 21 = 492

	lda	MBASE				; 3
	sta	MB_ADDRH			; 3
	lda	#0				; 2
	sta	MB_ADDRL			; 3
					;=============
					;	11

	ldx	#0				; 2
	ldy	MBOFFSET			; 3
	lda	(MB_ADDRL),Y			; 5
	sta	MB_VALUE			; 3
	jsr	write_ay_both			; 6+65
					;===============
					;	84

	clc					; 2
	lda	#6				; 2
	adc	MB_ADDRH			; 3
	sta	MB_ADDRH			; 3
					;==============
					;	10
	ldx	#2
	ldy	MBOFFSET
	lda	(MB_ADDRL),Y
	sta	MB_VALUE
	jsr	write_ay_both

	clc
	lda	#6
	adc	MB_ADDRH
	sta	MB_ADDRH

	ldx	#3
	ldy	MBOFFSET
	lda	(MB_ADDRL),y
	sta	MB_VALUE
	jsr	write_ay_both

	clc
	lda	#6
	adc	MB_ADDRH
	sta	MB_ADDRH

	ldx	#8
	ldy	MBOFFSET
	lda	(MB_ADDRL),y
	sta	MB_VALUE
	jsr	write_ay_both

	clc
	lda	#6
	adc	MB_ADDRH
	sta	MB_ADDRH

	ldx	#9
	ldy	MBOFFSET
	lda	(MB_ADDRL),y
	sta	MB_VALUE
	jsr	write_ay_both

	;

	lda	FRAME			; 3
	and	#1			; 2
	clc				; 2
	adc	MBOFFSET		; 3
	sta	MBOFFSET		; 3

	lda	MBASE			; 3
	adc	#0			; 2
	sta	MBASE			; 3
				;=============
				;         21

	; 2=2 not loop
	; 2+7+3= 12 = last page
	; 2+7+15=24  = loop

	cmp	#>music+5		; 2
	bne	waste_7		;
					; 2
	lda	MBOFFSET		; 3
	cmp	#16			; 2
	bne	waste_12		;
					; 2
	lda	#>music			; 2
	sta	MBASE			; 3
	lda	#0			; 2
	sta	MBOFFSET		; 3
	jmp	not_ready_to_loop	; 3
waste_7:
	lda	#0			; 2
	inc	BLARGH			; 5
waste_12:
					; 3
	lda	#0			; 2
	inc	BLARGH			; 5
	inc	BLARGH			; 5

not_ready_to_loop:

	; lores want 	5200
	; mockingboard	-492
	; wrap		 -24
	; softswitch	  -4
	;===================
	;		4680 cycles

	; Try X=7 Y=114 cycles=4675 R5

	inc 	BLARGH							; 5
;	lda	#0							; 2
;	lda	#0							; 2
;	lda	#0							; 2
;	lda	#0							; 2

	ldy	#114							; 2
loop5:
	ldx	#7							; 2
loop6:
	dex								; 2
	bne	loop6							; 2nt/3

	dey								; 2
	bne	loop5							; 2nt/3

;========================================================================

	; vertical blank

	; want 4550 cycles
	; Try X=13 Y=64 cycles=4545 R2

;=========================================================================



	jsr	move_letters					; 6+110

	; Blanking time:	 4550
	; move_letters		 -116
	; JMP at end		   -3
	;========================4431 cycles

	; Try X=176 Y=5 cycles=4431

;	lda	#0							; 2
;	lda	#0							; 2
	ldy	#5							; 2
loop7:
	ldx	#176							; 2
loop8:
	dex								; 2
	bne	loop8							; 2nt/3
	dey								; 2
	bne	loop7							; 2nt/3


	jmp	display_loop						; 3

;===========================================================
;===========================================================
;===========================================================

;wait_until_keypressed:
;	lda	KEYPRESS			; check if keypressed
;	bpl	wait_until_keypressed		; if not, loop
;	bit	KEYRESET
;	rts




	;=============================================
	; put_sprite
	;=============================================
	; Sprite to display in INH,INL
	; Location is XPOS,YPOS
	; Note, only works if YPOS is multiple of two


	; time= 28 setup
	;    Y*outerloop
	;    outerloop = 34 setup
	;	X*innerloop
	;	innerloop = 30 if $00 17+13(done)
	;		    64 if $0X 16+7+8+20(put_sprite_mask)+13(done)
	;		    69 if $X0 16+8+7+5+20(put_sprite_mask)+13(done)
	;		    54 if if $XX 16+8+8+9(put_all)+13(done)


	;       -1 for last iteration
	;    18 (-1 for last)
	;     6 return

	; so cost = 28 + Y*(34+18)+ (INNER-Y) -1 + 6
	;         = 33 + Y*(52)+(INNER-Y)
	;	  = 33 + Y*(52)+ [30A + 64B + 69C + 54D]-Y
.align $100
put_sprite:

	ldy	#0		; byte 0 is xsize			; 2
	lda	(INL),Y							; 5
	sta	CH		; xsize is in CH			; 3
	iny								; 2

	lda	(INL),Y		; byte 1 is ysize			; 5
	sta	CV		; ysize is in CV			; 3
	iny								; 2

	lda	YPOS		; make a copy of ypos			; 3
	sta	TEMPY		; as we modify it			; 3
								;===========
								;	28
put_sprite_loop:
	sty	TEMP		; save sprite pointer			; 3
	ldy	TEMPY							; 3
	lda	gr_offsets,Y	; lookup low-res memory address		; 4
	clc								; 2
	adc	XPOS		; add in xpos				; 3
	sta	OUTL		; store out low byte of addy		; 3
	lda	gr_offsets+1,Y	; look up high byte			; 4
	adc	DRAW_PAGE	;					; 3
	sta	OUTH		; and store it out			; 3
	ldy	TEMP		; restore sprite pointer		; 3

				; OUTH:OUTL now points at right place

	ldx	CH		; load xsize into x			; 3
								;===========
								;	34
put_sprite_pixel:
	lda	(INL),Y			; get sprite colors		; 5
	iny				; increment sprite pointer	; 2

	sty	TEMP			; save sprite pointer		; 3
	ldy	#$0							; 2

	; check if completely transparent
	; if so, skip

	cmp	#$0			; if all zero, transparent	; 2
	beq	put_sprite_done_draw	; don't draw it			; 2nt/3
								;==============
								;	 16/17

	sta	COLOR			; save color for later		; 3

	; check if top pixel transparent

	and	#$f0			; check if top nibble zero	; 2
	bne	put_sprite_bottom	; if not skip ahead		; 2nt/3
								;==============
								;	7/8

	lda	#$f0			; setup mask			; 2
	sta	MASK							; 3
	bmi	put_sprite_mask		; always?			; 3
								;=============
								;	  8

put_sprite_bottom:
	lda	COLOR			; re-load color			; 3
	and	#$0f			; check if bottom nibble zero	; 2
	bne	put_sprite_all		; if not, skip ahead		; 2nt/3
								;=============
								;	7/8

	lda	#$0f							; 2
	sta	MASK			; setup mask			; 3
								;===========
								;         5

put_sprite_mask:
	lda	(OUTL),Y		; get color at output		; 5
	and	MASK			; mask off unneeded part	; 3
	ora	COLOR			; or the color in		; 3
	sta	(OUTL),Y		; store it back			; 6

	jmp	put_sprite_done_draw	; we are done			; 3
								;===========
								;        20

put_sprite_all:
	lda	COLOR			; load color			; 3
	sta	(OUTL),Y		; and write it out		; 6
								;============
								;	  9

put_sprite_done_draw:

	ldy	TEMP			; restore sprite pointer	; 3

	inc	OUTL			; increment output pointer	; 5
	dex				; decrement x counter		; 2
	bne	put_sprite_pixel	; if not done, keep looping	; 2nt/3
								;==============
								;	12/13

	inc	TEMPY			; each line has two y vars	; 5
	inc	TEMPY							; 5
	dec	CV			; decemenet total y count	; 5
	bne	put_sprite_loop		; loop if not done		; 2nt/3
								;==============
								;	17/18

	rts				; return			; 6



	;====================================
	; Draw bottom green
	;====================================
	; using hlin 7127, optimized a bit but still awful
	; this one is much better
	; 2209 cycles
draw_bottom_green:

	lda	#$44							; 2
	ldx	#39							; 2
green_loop:
	sta	$728,X		; 28					; 5
	sta	$7a8,X		; 30					; 5
	sta	$450,X		; 32					; 5
	sta	$4d0,X		; 34					; 5
	sta	$550,X		; 36					; 5
	sta	$5d0,X		; 38					; 5
	sta	$650,X		; 40					; 5
	sta	$6d0,X		; 42					; 5
	sta	$750,X		; 44					; 5
	sta	$7d0,X		; 46					; 5

	dex								; 2
	bpl	green_loop						; 2nt/3

	rts								; 6

; 4 + (40*55) + 6 - 1

	;===============================================
	; Move Letters
	;===============================================
	; Normal	=10+25+38+9 = 82     need 28  (28)
	; End of line   =10+25+38+37 = 110
	; Next line	=10+5+12+34 = 61     need 49  (28+21)
	; done entirely =10+5+9 = 24         need 86  (28+21+37)

	; all forced to be 109

move_letters:
	ldy	#0							; 2
	lda	(LETTERL),Y						; 5
	sta	LETTER							; 3
								;==========
								;       10
	bmi	letter_special
									; 2
	lda	LETTERY							; 3
	asl								; 2
	tay								; 2
	lda	gr_offsets,Y	; lookup low-res memory address		; 4
	sta	BASL		; store out low byte of addy		; 3
	lda	gr_offsets+1,Y	; look up high byte			; 4
	sta	BASH							; 3
	lda	#0		; cycle-killer				; 2
								;==========
								;       25

	ldy	#0		; erase old char with space		; 2
	lda	#' '|$80						; 2
	ldy	LETTERX							; 3
	sta	(BASL),Y						; 6

	dey			; draw new char				; 2
	sty	LETTERX							; 3
	lda	LETTER							; 3
	ora	#$80							; 2
	ldy	LETTERX							; 3
	sta	(BASL),Y						; 6

	lda	LETTERX							; 3
	cmp	LETTERD							; 3
								;===========
								;        38
	beq	letter_next
									; 2
	lda	#0							; 2
	lda	#0							; 2
	jmp	waste_28						; 3
								;==========
								;	  9
letter_next:
									; 3
	clc								; 2
	lda	LETTERL							; 3
	adc	#1							; 2
	sta	LETTERL							; 3
	lda	LETTERH							; 3
	adc	#0							; 2
	sta	LETTERH							; 3
	inc	LETTERD							; 5
	lda	#39							; 2
	sta	LETTERX							; 3
	rts								; 6
								;===========
								;        37

letter_special:
									; 3
	cmp	#$ff							; 2
								;==========
								;         5

	beq	letter_done
									; 2
	ldy	#1							; 2
	lda	(LETTERL),Y						; 5
	sta	LETTERY							; 3
								;===========
								;	 12

	iny								; 2
	lda	(LETTERL),Y						; 5
	sta	LETTERD							; 3

	clc								; 2
	lda	LETTERL							; 3
	adc	#3							; 2
	sta	LETTERL							; 3
	lda	LETTERH							; 3
	adc	#0							; 2
	sta	LETTERH							; 3
	lda	LETTERH		; waste					; 3
	jmp	waste_21						; 3

								;===========
								;        34
letter_done:
				; 3
	lda	LETTERH		; 3
	lda	LETTERH		; 3

waste_37:
	ldx	#0		; 2
	inc	BLARGH		; 5
	inc	BLARGH		; 5
	inc	BLARGH		; 5
	inc	BLARGH		; 5
	inc	BLARGH		; 5
	inc	BLARGH		; 5
	inc	BLARGH		; 5
waste_21:
	ldx	#0		; 2
	ldx	#0		; 2
	ldx	#0		; 2
	inc	BLARGH		; 5
	inc	BLARGH		; 5
	inc	BLARGH		; 5

waste_28:
	ldx	#0		; 2
	inc	BLARGH		; 5
	inc	BLARGH		; 5
	inc	BLARGH		; 5
	inc	BLARGH		; 5
	rts			; 6

letters:
	;.byte	1,15
	.byte	     "T A L B O T",128
	.byte	2,14,"F A N T A S Y",128
	.byte	3,16,"S E V E N",128
	.byte	1,15," ",128
	.byte	2,14," ",128
	.byte	3,16," ",128
	.byte	1,19,"BY",128
	.byte	3,14,"VINCE WEAVER",128
	.byte	1,19," ",128
	.byte	3,14," ",128
	.byte	1,16,"MUSIC BY",128
	.byte	3,12,"HIROKAZU TANAKA",128
	.byte	1,16," ",128
	.byte	3,12," ",128
	.byte	2,13,"CYCLE COUNTING",128
	.byte	3,16,"IS HARD!"
	.byte	255


line1:.asciiz	"   *                            .      "
line2:.asciiz	"  *    .                            .  "
line3:.asciiz	"  *                                    "
line4:.asciiz	"   *                                   "
line5:.asciiz	" .                          .    .     "
line6:.asciiz	"             .                         "

.include "../asm_routines/text_print.s"
.include "mockingboard.s"

.align	$100
.include "../asm_routines/gr_offsets.s"
.include "tfv_sprites.inc"

.align	$1000

graphics:
.incbin	"KATC.BIN"

music:
.incbin "music.tfv"
