; Play the KSP theme, but compressed a bit (only write registers that change)
; Still 3-channel
; The KSP theme is fairly small, will need to compress more

.include	"zp.inc"

	;=============================
	; Print message
	;=============================
	jsr     HOME
	jsr     TEXT

	lda	#0
	sta	DRAW_PAGE
	sta	CH
	sta	CV
	sta	DONE_PLAYING
	sta	XPOS

	lda	#1
	sta	MB_FRAME_DIFF

	lda	#<mocking_message
	sta	OUTL
	lda	#>mocking_message
	sta	OUTH
	jsr	move_and_print

	jsr	mockingboard_detect_slot4
	cpx	#$1
	beq	mockingboard_found

	lda	#<not_message
	sta	OUTL
	lda	#>not_message
	sta	OUTH
	inc	CV
	jsr	move_and_print

	jmp	forever_loop

mockingboard_found:
	lda     #<found_message
	sta     OUTL
	lda     #>found_message
	sta     OUTH
	inc     CV
	jsr     move_and_print

	;============================
	; Init the Mockingboard
	;============================

	jsr	mockingboard_init
	jsr	reset_ay_left
	jsr	reset_ay_right
	jsr	clear_ay_left
	jsr	clear_ay_right


	;===========================
	; load pointer to the music
	;===========================

	lda	#<ksp_theme
	sta	INL
	lda	#>ksp_theme
	sta	INH

	lda	(INL),Y		; read in frame delay
	sta	MB_FRAME_DIFF
	inc	INL		; FIXME: should check if we oflowed

	;=========================
	; Setup Interrupt Handler
	;=========================
	; Vector address goes to 0x3fe/0x3ff
	; FIXME: should chain any existing handler

	lda	#<interrupt_handler
	sta	$03fe
	lda	#>interrupt_handler
	sta	$03ff

	;============================
	; Enable 50Hz clock on 6522
	;============================

	lda	#$40		; Generate continuous interrupts, don't touch PB7
	sta	$C40B		; ACR register
	lda	#$7F		; clear all interrupt flags
	sta	$C40E		; IER register (interrupt enable)

	lda	#$C0
	sta	$C40D		; IFR: 1100, enable interrupt on timer one oflow
	sta	$C40E		; IER: 1100, enable timer one interrupt

	lda	#$E7
	sta	$C404		; write into low-order latch
	lda	#$4f
	sta	$C405		; write into high-order latch,
				; load both values into counter
				; clear interrupt and start counting

	; 4fe7 / 1e6 = .020s, 50Hz

	;============================
	; Enable 6502 interrupts
	;============================
	;
	cli		; clear interrupt mask


	bit	SET_GR			; graphics mode
	bit	HIRES			; hires mode
	bit	TEXTGR			; mixed text/graphics
	bit	PAGE0			; first graphics page

	;==========================
	; Graphics
	;==========================
uncompress_graphics:
	jsr	lzss_init		; init R to zero



	;==========================
	;==========================
	; Loading Sequence
	;==========================
	;==========================
	jsr	clear_bottom

	;==========================
	; Squad Logo
	;==========================

	lda	#>squad_logo		; load logo pointer
        sta	BASH
        lda	#<squad_logo
        sta	BASL

	lda	#>squad_logo_end	; load logo end pointer
        sta	LZSS_ENDH
        lda	#<squad_logo_end
        sta	LZSS_ENDL

	; HGR page 2
	lda	#>$2000
	sta	OUTH
	lda	#<$2000
	sta	OUTL

	jsr	lzss_decompress

	lda	#<load_quotes
	sta	NAMEL
	lda	#>load_quotes
	sta	NAMEH

	lda	#$54		; HTAB 4 : VTAB 21
	sta	OUTL
	lda	#$6
	sta	OUTH

	ldy	#31
	lda	#('.'+$80)		; '.'
dot_loop:
	sta	(OUTL),Y
	dey
	bpl	dot_loop

	ldx	#$0
progress_bar_loop:
	ldy	#$0
	lda	#$6
	sta	OUTH
	clc
	txa
	adc	#$54			; HTAB 4 : VTAB 21
	sta	OUTL
	lda	#' '			; inverse space
	sta	(OUTL),Y

	; Halfway, change logo

	cpx	#16
	bne	no_change_logo

	txa
	pha

	jsr	lzss_init		; init R to zero

	lda	#>loading_logo			; load logo pointer
        sta	BASH
        lda	#<loading_logo
        sta	BASL

	lda	#>loading_logo_end		; load logo end pointer
        sta	LZSS_ENDH
        lda	#<loading_logo_end
        sta	LZSS_ENDL

	; HGR page 2
	lda	#>$2000
	sta	OUTH
	lda	#<$2000
	sta	OUTL

	jsr	lzss_decompress

	pla
	tax

no_change_logo:

	; Update message

	txa
	and	#$3
	bne	no_quotes

	; clear line

	lda	#$D0		; VTAB 22
	sta	OUTL
	lda	#$6
	sta	OUTH

	ldy	#40
	lda	#(' '+$80)		; ' '
clear_line:
	sta	(OUTL),Y
	dey
	bpl	clear_line


	ldy	#0
	lda	(NAMEL),Y
	adc	#$CE			; -1 because we inc Y once
					; and another because HTAB starts at 1
	sta	OUTL
	iny
print_quote_loop:
	lda	(NAMEL),Y
	beq	done_quote
	ora	#$80			; make non-inverse
	sta	(OUTL),Y
	iny
	jmp	print_quote_loop
done_quote:
	iny
	clc
	tya
	adc	NAMEL
	sta	NAMEL
	lda	#0
	adc	NAMEH
	sta	NAMEH

no_quotes:
	lda	#$f0
	jsr	WAIT
	lda	#$f0
	jsr	WAIT
	lda	#$f0
	jsr	WAIT
	lda	#$f0
	jsr	WAIT

	inx
	cpx	#32
	bpl	done_progress_bar
	jmp	progress_bar_loop
done_progress_bar:
	jsr	clear_bottom


	lda	#>ksp_title		; load logo pointer
        sta	BASH
        lda	#<ksp_title
        sta	BASL

	lda	#>ksp_title_end		; load logo end pointer
        sta	LZSS_ENDH
        lda	#<ksp_title_end
        sta	LZSS_ENDL

	; HGR page 2
	lda	#>$2000
	sta	OUTH
	lda	#<$2000
	sta	OUTL

	jsr	lzss_decompress

	;============================
	; Loop forever
	;============================
playing_loop:
	lda	DONE_PLAYING
	beq	playing_loop

done_play:

				; FIXME: disable timer on 6522
				; FIXME: unhook interrupt handler

	sei			; disable interrupts

	jsr	clear_ay_left
	jsr	clear_ay_right

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

forever_loop:
	jmp	forever_loop

	;=============================
	;=============================
	; simple interrupt handler
	;=============================
	;=============================
	; On Apple II/6502 the interrupt handler jumps to address in 0xfffe
	; This is in the ROM, which saves the registers
	;   on older IIe it saved A to $45 (which could mess with DISK II)
	;   newer IIe doesn't do that.
	; It then calculates if it is a BRK or not (which trashes A)
	; Then it sets up the stack like an interrupt and calls 0x3fe

interrupt_handler:
;	pha			; firmware saves A to $45 for us
	txa			; save X
	pha
	tya
	pha			; save Y



	bit	$C404		; can clear 6522 interrupt by reading T1C-L

	inc	$0401		; DEBUG: increment text char

	dec	MB_FRAME_DIFF
	bne	done_interrupt




	ldy	#0
bottom_regs:
	lda	(INL),Y			; load low reg bitmask
	sta	MASK
	ldx	#$ff			; init to -1
bottom_regs_loop:
	inx				; increment X
	cpx	#$8			; if we reach 8, done
	beq	top_regs		; move on to top

	ror	MASK
	bcc	bottom_regs_loop	; if bit not set in mask, skip reg

	stx	XX			; save X

	iny				; get next output value
	lda	(INL),Y			; read in value

	sty	YY			; save Y

	tax				; value in X
	ldy	XX			; register# in Y

	; reg in Y, value in X
	jsr	write_ay_left		; assume 3 channel (not six)
	jsr	write_ay_right		; so write same to both left/write

	ldx	XX			; restore X
	ldy	YY			; restore Y

	jmp	bottom_regs_loop	; loop

top_regs:
	iny				; point to next value
	lda	(INL),Y			; load top reg bitmask
	sta	MASK
	ldx	#$7			; load X as 7 (we increment first)
top_regs_loop:
	inx				; increment
	cpx	#16
	beq	done_with_masks		; exit if done

	ror	MASK
	bcc	top_regs_loop		; loop if not set

	stx	XX			; save X value

	iny				; point to value
	lda	(INL),Y			; read in output value

	sty	YY			; save Y value

	tax				; value in X
	ldy	XX			; register in Y

	; reg in Y, value in X
	jsr	write_ay_left		; assume 3 channel (not six)
	jsr	write_ay_right		; so write same to both left/write

	ldx	XX
	ldy	YY

	jmp	top_regs_loop

done_with_masks:
new_frame_diff:
	iny
	lda	(INL),Y		; read in frame delay
	cmp	#$ff		; see if end
	bne	not_done	; if so, done
	inc	DONE_PLAYING	; set done playing flag
	jmp	done_interrupt
not_done:
	sta	MB_FRAME_DIFF

	iny
	clc
	tya
	adc	INL
	sta	INL
	lda	#0
	adc	INH
	sta	INH

done_interrupt:
	pla
	tay			; restore y
	pla
	tax			; restore X

	lda	$45		; restore A

	rti





;=========
;routines
;=========
.include	"../asm_routines/gr_offsets.s"
.include	"../asm_routines/text_print.s"
.include	"../asm_routines/mockingboard.s"
.include	"../asm_routines/lzss_decompress.s"
.include	"../asm_routines/gr_fast_clear.s"

;=======
; music
;=======
.include	"ksp_theme_compressed.inc"


;=========
; strings
;=========
mocking_message:	.asciiz "LOOKING FOR MOCKINGBOARD IN SLOT #4"
not_message:		.byte   "NOT "
found_message:		.asciiz "FOUND"
done_message:		.asciiz "DONE PLAYING"

load_quotes:
.byte	10
.asciiz	"Adding Extraneous Ks"
.byte 14
.asciiz "Locating Jeb"
.byte 11
.asciiz "Breaking Quicksaves"
.byte 12
.asciiz "Patching Conics"
.byte 12
.asciiz "Spinning up Duna"
.byte 11
.asciiz "Warming up the 6502"
.byte 10
.asciiz "Preparing Explosions"
.byte 10
.asciiz "Unleashing the Kraken"


;=============
; Grahpics
; Must be at end as get over-written
;=============

.include	"ksp_title.inc"
.include	"ksp_squad.inc"
.include	"ksp_loading.inc"