;====================================================================
;NES Audio Tester v1.3 by Morgan Johansson (5/12-1998)
;====================================================================
; Don't hesitate to contact me!
;      e-mail: morgan.johansson@mbox301.swipnet.se
;
; Use freely but don't forget to credit me!!
;
; And remember! 8-bit forever!!


	PROCESSOR 6502

		ORG $BFF0

Header			dc.b	"N"
			dc.b	"E"
			dc.b	"S"
			dc.b	$1a
			dc.b	1		;1 PRG-ROM
			dc.b	0
			dc.b	1		;vertical mirroring
			dc.b	0
			dc.l	0
			dc.l	0


			ORG $C000

		dc.b	"NES Audio Tester v1.3 (5/12-1998) by Morgan Johansson",0

Reset_Routine		cld			;Clear decimal flag
			sei			;Disable interrupts
.WaitV			lda $2002
			bpl .WaitV		;Wait for vertical blanking interval
			ldx #%10000000		;NMI on!
			stx $2000
			ldx #%00001000
			stx $2001		;Screen is on!
			ldx #$FF
			txs			;Set Stack-pointer
			jsr ResetScroll
			jsr Init		;Init variables
			jsr CopyGraphics1	;Copy graphics to CHR-RAM
			jsr CopyGraphics2	;
			jsr SetPal		;Set palette
			jsr SetLayout		;Print text on screen
			jsr PlaceChar		;Place 00000000 * 4
			jsr PlaceCursor		;Place Cursor
			jsr ResetScroll

Loop:			jsr WaitVbl		;Wait a bit
			jsr MoveCursor		;Check cursor-movements
			jsr ResetScroll		;if $2006 has changed...
			jmp Loop

;--------------------------------------------------------------------

Init:			ldx #0
			stx $72			;H-pos cursor
			stx $73			;V-pos cursor
			stx $74			;Bytevalue 1
			stx $75			;Bytevalue 2
			stx $76			;Bytevalue 3
			stx $77			;Bytealue 4


			ldx #$00		;Address to 
			stx $78			;"hack"
			ldx #$40		;
			stx $79			;

			ldx #0
			stx $7A			;V-pos, cursor2
			ldx #$20		;CHR-RAM pos, cursor2
			stx $7b
			ldx #$93
			stx $7c

			ldx #2			;2=Tile "0"
			stx $80			;Value 1, bit 7
			stx $81			;Value 1, bit 6
			stx $82			;Value 1, bit 5
			stx $83			;Value 1, bit 4
			stx $84			;Value 1, bit 3
			stx $85			;Value 1, bit 2
			stx $86			;Value 1, bit 1
			stx $87			;Value 1, bit 0

			stx $90			;Value 2, bit 7
			stx $91			;Value 2, bit 6
			stx $92			;Value 2, bit 5
			stx $93			;Value 2, bit 4
			stx $94			;Value 2, bit 3
			stx $95			;Value 2, bit 2
			stx $96			;Value 2, bit 1
			stx $97			;Value 2, bit 0

			ldx #2			;2=Tile "0"
			stx $A0			;Value 3, bit 7
			stx $A1			;Value 3, bit 6
			stx $A2			;Value 3, bit 5
			stx $A3			;Value 3, bit 4
			stx $A4			;Value 3, bit 3
			stx $A5			;Value 3, bit 2
			stx $A6			;Value 3, bit 1
			stx $A7			;Value 3, bit 0

			stx $B0			;Value 4, bit 7
			stx $B1			;Value 4, bit 6
			stx $B2			;Value 4, bit 5
			stx $B3			;Value 4, bit 4
			stx $B4			;Value 4, bit 3
			stx $B5			;Value 4, bit 2
			stx $B6			;Value 4, bit 1
			stx $B7			;Value 4, bit 0

			lda #$20		;Address Cursor
			sta $70			;
			lda #$a4		;
			sta $71			;

			lda #$0f		;Enable sound for
			sta $4015		;all channels
			rts

;--------------------------------------------------------------------
; Reset Scroll-registers
;--------------------------------------------------------------------
ResetScroll:		lda #$0
			sta $2005
			sta $2005
			rts
;--------------------------------------------------------------------
; Wait for Vertical blank
;--------------------------------------------------------------------

WaitVbl:		lda $2002
			bpl WaitVbl
			rts

;--------------------------------------------------------------------
; Transforms binary digits -> bytes
;--------------------------------------------------------------------

CalcValue1:		ldx #0

			lda $80
			and #1
			rol
			sta $74

			lda $81
			and #1
			ora $74
			rol
			sta $74

			lda $82
			and #1
			ora $74
			rol
			sta $74

			lda $83
			and #1
			ora $74
			rol
			sta $74


			lda $84
			and #1
			ora $74
			rol
			sta $74


			lda $85
			and #1
			ora $74
			rol
			sta $74


			lda $86
			and #1
			ora $74
			rol
			sta $74

			lda $87
			and #1
			ora $74
			sta $74

			rts


CalcValue2:		ldx #0
			lda $90
			and #1
			rol
			sta $75

			lda $91
			and #1
			ora $75
			rol
			sta $75

			lda $92
			and #1
			ora $75
			rol
			sta $75

			lda $93
			and #1
			ora $75
			rol
			sta $75


			lda $94
			and #1
			ora $75
			rol
			sta $75


			lda $95
			and #1
			ora $75
			rol
			sta $75

			lda $96
			and #1
			ora $75
			rol
			sta $75

			lda $97
			and #1
			ora $75
			sta $75
			rts


CalcValue3:		ldx #0
			lda $A0
			and #1
			rol
			sta $76

			lda $A1
			and #1
			ora $76
			rol
			sta $76

			lda $A2
			and #1
			ora $76
			rol
			sta $76

			lda $A3
			and #1
			ora $76
			rol
			sta $76


			lda $A4
			and #1
			ora $76
			rol
			sta $76


			lda $A5
			and #1
			ora $76
			rol
			sta $76

			lda $A6
			and #1
			ora $76
			rol
			sta $76

			lda $A7
			and #1
			ora $76
			sta $76
			rts


CalcValue4:		ldx #0
			lda $B0
			and #1
			rol
			sta $77

			lda $B1
			and #1
			ora $77
			rol
			sta $77

			lda $B2
			and #1
			ora $77
			rol
			sta $77

			lda $B3
			and #1
			ora $77
			rol
			sta $77

			lda $B4
			and #1
			ora $77
			rol
			sta $77


			lda $B5
			and #1
			ora $77
			rol
			sta $77

			lda $B6
			and #1
			ora $77
			rol
			sta $77

			lda $B7
			and #1
			ora $77
			sta $77
			rts
;--------------------------------------------------------------------
; Listen to the values!!
;--------------------------------------------------------------------

TestStart:		lda $3
			beq TestStartX
			jsr PokeValue		;Change address
			jsr WaitStart	
TestStartX:		rts

WaitStart:		lda $3
			bne WaitStart
			rts

PokeValue:		ldy #0
			lda $74			;value1
			sta ($78),y
			iny
			lda $75			;value2
			sta ($78),y
			iny
			lda $76			;value3
			sta ($78),y
			iny
			lda $77			;value4
			sta ($78),y
			rts


;--------------------------------------------------------------------
; CursorHandler  RIGHT=$7
;--------------------------------------------------------------------
MoveCursor:		jsr	TestRight
			jsr	TestLeft
			jsr	TestUp
			jsr	TestSelect
			jsr	TestStart
			jsr	TestA
			rts
;--------------------------------------------------------------------
TestA:			lda $0			;Button not pressed
			beq TestA_Exit
			jsr EraseCursor2
			lda $7a
			cmp #3
			beq TestA_Reset
			inc $7a
TestA_Proceed:		lda $7a
			beq SetPos2_0
			cmp #1
			beq SetPos2_1
			cmp #2
			beq SetPos2_2
			cmp #3
			beq SetPos2_3
TestA_Proceed2:		jsr PlaceCursor2
			jsr WaitForA
TestA_Exit:		rts

TestA_Reset:		lda #0
			sta $7a
			lda #$20
			sta $7b
			lda #$93
			sta $7c
			jmp TestA_Proceed

WaitForA:		lda $0
			bne WaitForA
			rts

SetPos2_0:		lda #$20
			sta $7b
			lda #$93
			sta $7c

			lda #$00
			sta $78
			lda #$40
			sta $79
			jmp TestA_Proceed2

SetPos2_1:		lda #$20
			sta $7b
			lda #$B3
			sta $7c

			lda #$04
			sta $78
			lda #$40
			sta $79
			jmp TestA_Proceed2
			
SetPos2_2:		lda #$20
			sta $7b
			lda #$d3
			sta $7c
			
			lda #$08
			sta $78
			lda #$40
			sta $79
			jmp TestA_Proceed2
			
SetPos2_3:		lda #$20
			sta $7b
			lda #$F3
			sta $7c

			lda #$0C
			sta $78
			lda #$40
			sta $79

			jmp TestA_Proceed2
;--------------------------------------------------------------------
TestSelect:		lda $2
			beq TestSelX
			jsr EraseCursor

			inc $73				;V-pos
			lda $73
			beq SetPos0
			cmp #1
			beq SetPos1
			cmp #2
			beq SetPos2
			cmp #3
			beq SetPos3
			lda #0
			sta $73
			jmp SetPos0
NextPhase:		lda #0
			sta $72
			jsr PlaceCursor			
			jsr WaitSel
TestSelX:		rts	

SetPos0:		lda #$20
			sta $70
			lda #$A4
			sta $71
			jmp NextPhase
SetPos1:		lda #$20
			sta $70
			lda #$E4
			sta $71
			jmp NextPhase
SetPos2:		lda #$21
			sta $70
			lda #$24
			sta $71
			jmp NextPhase
SetPos3:		lda #$21
			sta $70
			lda #$64
			sta $71
			jmp NextPhase

WaitSel:		lda $2
			bne WaitSel
			rts

;--------------------------------------------------------------------
TestUp:			lda $4
			beq TestUpX
			lda $73
			cmp #0			;Which row on screen?
			beq Rad0
			cmp #1
			beq Rad1
			cmp #2
			beq Rad2
			cmp #3
			beq Rad3
TestUpX0:		jsr CalcValue1		;calculate values
			jsr CalcValue2		;
			jsr CalcValue3		;
			jsr CalcValue4		;
			jsr WaitUpFinal		;Release button please!
TestUpX:		rts


WaitUpFinal:		lda $4
			bne WaitUpFinal
			rts

;--------------------------------------------------------------------
Rad0:			ldx $72
			lda $80,x
			cmp #2
			beq TestUp_0
			lda #2
			sta $80,x
			jsr UpdateChar0
			jmp TestUpX0

TestUp_0:		lda #3
			sta $80,x
			jsr UpdateChar0
			jmp TestUpX0


;--------------------------------------------------------------------
Rad1:			ldx $72
			lda $90,x
			cmp #2
			beq TestUp_1
			lda #2
			sta $90,x
			jsr UpdateChar1
			jmp TestUpX0

TestUp_1:		lda #3
			sta $90,x
			jsr UpdateChar1
			jmp TestUpX0

;--------------------------------------------------------------------
Rad2:			ldx $72
			lda $A0,x
			cmp #2
			beq TestUp_2
			lda #2
			sta $A0,x
			jsr UpdateChar2
			jmp TestUpX0

TestUp_2:		lda #3
			sta $A0,x
			jsr UpdateChar2
			jmp TestUpX0



;--------------------------------------------------------------------
Rad3:			ldx $72
			lda $B0,x
			cmp #2
			beq TestUp_3
			lda #2
			sta $B0,x
			jsr UpdateChar3
			jmp TestUpX0

TestUp_3:		lda #3
			sta $B0,x
			jsr UpdateChar3
			jmp TestUpX0



;--------------------------------------------------------------------
UpdateChar0:		lda #$20
			sta $2006
			lda #$83
			adc $72
			sta $2006
			lda $80,x
			sta $2007
			rts

UpdateChar1:		lda #$20
			sta $2006
			lda #$C3
			adc $72
			sta $2006
			lda $90,x
			sta $2007
			rts

UpdateChar2:		lda #$21
			sta $2006
			lda #$03
			adc $72
			sta $2006
			lda $A0,x
			sta $2007
			rts

UpdateChar3:		lda #$21
			sta $2006
			lda #$43
			adc $72
			sta $2006
			lda $B0,x
			sta $2007
			rts

;--------------------------------------------------------------------
TestRight:		lda $7
			beq TestRightX
			lda $72
			cmp #7
			beq TestRightX
			inc $72			
			jsr EraseCursor
			inc $71
			jsr PlaceCursor
			jsr WaitRightFinal
TestRightX:		rts


WaitRightFinal:		lda $7
			bne WaitRightFinal
			rts
;--------------------------------------------------------------------

TestLeft:		lda $6
			beq TestLeftX
			lda $72
			cmp #0
			beq TestLeftX
			dec $72			
			jsr EraseCursor
			dec $71
			jsr PlaceCursor
			jsr WaitLeftFinal
TestLeftX:		rts

WaitLeftFinal:		lda $6
			bne WaitLeftFinal
			rts

;--------------------------------------------------------------------
; Code to handle the two cursors
;--------------------------------------------------------------------
EraseCursor:		lda $70
			sta $2006
			lda $71
			sta $2006
			lda #0
			sta $2007
			rts

EraseCursor2:		lda $7b
			sta $2006
			lda $7c
			sta $2006
			lda #0
			sta $2007
			rts


;--------------------------------------------------------------------
			
PlaceCursor:		lda $70
			sta $2006
			lda $71
			sta $2006
			lda #1
			sta $2007
			rts

PlaceCursor2:		lda $7b
			sta $2006
			lda $7c
			sta $2006
			lda #39
			sta $2007
			rts

;--------------------------------------------------------------------
; Generate rows of 00000000 * 4 on screen
;--------------------------------------------------------------------
PlaceChar:		lda #$20			;$2000+132
			sta $2006
			lda #$84
			sta $2006
			ldx #0
PlaceChar1_Loop:	lda $80,x
			sta $2007
			inx
			cpx #8
			bne PlaceChar1_Loop

			lda #$20			;$20C4
			sta $2006
			lda #$C4
			sta $2006
			ldx #0
PlaceChar2_Loop:	lda $90,x
			sta $2007
			inx
			cpx #8
			bne PlaceChar2_Loop			

			lda #$21			;$2104
			sta $2006
			lda #$04
			sta $2006
			ldx #0
PlaceChar3_Loop:	lda $A0,x
			sta $2007
			inx
			cpx #8
			bne PlaceChar3_Loop			

			lda #$21			;$2144
			sta $2006
			lda #$44
			sta $2006
			ldx #0
PlaceChar4_Loop:	lda $B0,x
			sta $2007
			inx
			cpx #8
			bne PlaceChar4_Loop			
			rts


;--------------------------------------------------------------------
; Set a nice(?) palette
;--------------------------------------------------------------------
SetPal:			lda #$3f			
			sta $2006
			lda #0
			sta $2006

			ldx #3
			stx $2007
			ldx #32
			stx $2007
			rts


;--------------------------------------------------------------------
; Copy CHR-DATA to CHR-RAM
;--------------------------------------------------------------------
CopyGraphics1:		lda #$0
			sta $2006
			sta $2006
			ldx #0				;Chars
			ldy #0 
			sty $50
CopyGraphicsLoop:	lda GraphicsData1,y
			sta $2007
			iny
			inc $50
			lda $50
			cmp #8
			bne CopyGraphicsLoop

			lda #0
			sta $50				;Reset Counter
			sta $2007
			sta $2007
			sta $2007
			sta $2007
			sta $2007
			sta $2007
			sta $2007
			sta $2007
			inx
			cpx #32
			bne CopyGraphicsLoop
			rts


CopyGraphics2:		lda #$02
			sta $2006
			lda #$00
			sta $2006
			ldx #0				;Chars
			ldy #0 
			sty $50
CopyGraphicsLoop2:	lda GraphicsData2,y
			sta $2007
			iny
			inc $50
			lda $50
			cmp #8
			bne CopyGraphicsLoop2

			lda #0
			sta $50				;Reset Counter
			sta $2007
			sta $2007
			sta $2007
			sta $2007
			sta $2007
			sta $2007
			sta $2007
			sta $2007
			inx
			cpx #32
			bne CopyGraphicsLoop2
			rts



;--------------------------------------------------------------------

JoyRead1:		ldx #1			;Generate joy-strobe!
			stx $4016		;
			dex			;
			stx $4016		;
			
			lda $4016		;A
			and #1
			sta $0
			;--------
			lda $4016		;B
			and #1
			sta $1
			;--------
			lda $4016		;SELECT
			and #1
			sta $2
			;--------
			lda $4016		;START
			and #1
			sta $3
			;--------
			lda $4016		;UP
			and #1
			sta $4
			;--------
			lda $4016		;DOWN
			and #1
			sta $5
			;--------
			lda $4016		;LEFT
			and #1
			sta $6
			;--------
			lda $4016		;RIGHT
			and #1
			sta $7
			rts

;--------------------------------------------------------------------
; NMI
;--------------------------------------------------------------------
NMI_Routine:		stx $100		;Store registers
			sty $101
			sta $102
			lda #0			;avoid problems?
			sta $2005		;X-scroll
			sta $2005		;Y-scroll

			jsr JoyRead1		;Read joypad 1

			ldx $100		;Restore registers
			ldy $101
			lda $102
IRQ_Routine:		rti

;--------------------------------------------------------------------
; Screen layout
; =============
; Print some stuff on the screen...
;--------------------------------------------------------------------

SetLayout:		lda #$20			;Print
			sta $2006			;NES Audio
			lda #$21			;tester v1.x
			sta $2006
			ldx #0
SetLayout1_Loop:	lda Text,x
			sta $2007
			inx
			cpx #20
			bne SetLayout1_Loop

			lda #$20			;Print Channel
			sta $2006			;names...
			lda #$94			;CHN1
			sta $2006
			ldx #0
SetCHN1_Loop:		lda ChannelText0,x
			sta $2007
			inx
			cpx #4
			bne SetCHN1_Loop

			lda #$20			;CHN2
			sta $2006
			lda #$B4
			sta $2006
			ldx #0
SetCHN2_Loop:		lda ChannelText1,x
			sta $2007
			inx
			cpx #4
			bne SetCHN2_Loop

			lda #$20			;CHN3
			sta $2006
			lda #$d4
			sta $2006
			ldx #0
SetCHN3_Loop:		lda ChannelText2,x
			sta $2007
			inx
			cpx #4
			bne SetCHN3_Loop

			lda #$20			;CHN4
			sta $2006
			lda #$F4
			sta $2006
			ldx #0
SetCHN4_Loop:		lda ChannelText3,x
			sta $2007
			inx
			cpx #4
			bne SetCHN4_Loop

			lda #$20			;Cursor to select
			sta $2006			;soundchannel
			lda #$93
			sta $2006
			lda #39
			sta $2007
			rts

Text:			dc.b	"N"-65+12
			dc.b	"E"-65+12
			dc.b	"S"-65+12
			dc.b	0
			dc.b	"A"-65+12
			dc.b	"U"-65+12
			dc.b	"D"-65+12
			dc.b	"I"-65+12
			dc.b	"O"-65+12
			dc.b	0
			dc.b	"T"-65+12
			dc.b	"E"-65+12
			dc.b	"S"-65+12
			dc.b	"T"-65+12
			dc.b	"E"-65+12
			dc.b	"R"-65+12
			dc.b	0
			dc.b	3		;1
			dc.b	38		;.
			dc.b	5		;1

ChannelText0:		dc.b	"C"-65+12
			dc.b	"H"-65+12
			dc.b	"N"-65+12
			dc.b	3		;1
ChannelText1:		dc.b	"C"-65+12
			dc.b	"H"-65+12
			dc.b	"N"-65+12
			dc.b	4		;2
ChannelText2:		dc.b	"C"-65+12
			dc.b	"H"-65+12
			dc.b	"N"-65+12
			dc.b	5		;3
ChannelText3:		dc.b	"C"-65+12
			dc.b	"H"-65+12
			dc.b	"N"-65+12
			dc.b	6		;4
;--------------------------------------------------------------------
; CHAR-DATA
;--------------------------------------------------------------------
; A=12  B=13  C=14  D=15  E=16  F=17  G=18  H=19  I=20  J=21  K=22
; L=23  M=24  N=25  O=26  P=27  Q=28  R=29  S=30  T=31  U=32  V=33
; W=34  X=35  Y=36  Z=37  .=38 ->=39


GraphicsData1:	DC.B	$00,$00,$00,$00,$00,$00,$00,$00
		DC.B	$10,$38,$7C,$38,$38,$38,$38,$00
		DC.B	$7C,$C6,$CE,$D6,$E6,$C6,$7C,$00
		DC.B	$18,$38,$78,$18,$18,$18,$18,$00
		DC.B	$7C,$C6,$06,$1C,$70,$C0,$FE,$00
		DC.B	$7C,$C6,$06,$1C,$06,$C6,$7C,$00
		DC.B	$1C,$3C,$6C,$CC,$FE,$0C,$0C,$00
		DC.B	$FE,$C0,$C0,$FC,$06,$C6,$7C,$00
		DC.B	$18,$30,$60,$FC,$C6,$C6,$7C,$00
		DC.B	$FE,$06,$0C,$18,$30,$30,$30,$00
		DC.B	$38,$6C,$6C,$7C,$C6,$C6,$7C,$00
		DC.B	$7C,$C6,$C6,$7E,$0C,$18,$30,$00
		DC.B	$38,$6C,$C6,$C6,$FE,$C6,$C6,$00
		DC.B	$FC,$C6,$C6,$FC,$C6,$C6,$FC,$00
		DC.B	$3C,$66,$C0,$C0,$C0,$66,$3C,$00
		DC.B	$F8,$CC,$C6,$C6,$C6,$CC,$F8,$00
		DC.B	$FE,$C0,$C0,$FC,$C0,$C0,$FE,$00
		DC.B	$FE,$C0,$C0,$FC,$C0,$C0,$C0,$00
		DC.B	$3E,$60,$C0,$CE,$C6,$66,$3E,$00
		DC.B	$C6,$C6,$C6,$FE,$C6,$C6,$C6,$00
		DC.B	$7E,$18,$18,$18,$18,$18,$7E,$00
		DC.B	$1E,$06,$06,$06,$C6,$C6,$7C,$00
		DC.B	$C6,$CC,$D8,$F0,$F8,$DC,$CE,$00
		DC.B	$C0,$C0,$C0,$C0,$C0,$C0,$FE,$00
		DC.B	$C6,$EE,$FE,$FE,$D6,$C6,$C6,$00
		DC.B	$C6,$E6,$F6,$FE,$DE,$CE,$C6,$00
		DC.B	$7C,$C6,$C6,$C6,$C6,$C6,$7C,$00
		DC.B	$FC,$C6,$C6,$FC,$C0,$C0,$C0,$00
		DC.B	$7C,$C6,$C6,$C6,$DE,$CC,$7A,$00
		DC.B	$FC,$C6,$C6,$CE,$F8,$DC,$CE,$00
		DC.B	$7C,$C6,$C0,$7C,$06,$C6,$7C,$00
		DC.B	$7E,$18,$18,$18,$18,$18,$18,$00

GraphicsData2:	DC.B	$C6,$C6,$C6,$C6,$C6,$C6,$7C,$00
		DC.B	$C6,$C6,$C6,$EE,$7C,$38,$10,$00
		DC.B	$C6,$C6,$D6,$FE,$FE,$EE,$C6,$00
		DC.B	$C6,$C6,$6C,$38,$6C,$C6,$C6,$00
		DC.B	$66,$66,$66,$3C,$18,$18,$18,$00
		DC.B	$FE,$0E,$1C,$38,$70,$E0,$FE,$00
		DC.B	$00,$00,$00,$00,$00,$00,$18,$00
		DC.B	$00,$08,$FC,$FE,$FC,$08,$00,$00	



;--------------------------------------------------------------------
			ORG $FFFA,0

			dc.w	NMI_Routine
			dc.w	Reset_Routine
			dc.w	IRQ_Routine
		

