I wrote a program to test the VRC7 audio. For example, you can make up the VRC7 custom instrument and then figure out what it sound like.
Instructions: LEFT/RIGHT = cursor, UP/DOWN = adjust, START = send values. If rightmost "A" is set to 1 then START automatically trigger/untrigger note as well.
Instructions: LEFT/RIGHT = cursor, UP/DOWN = adjust, START = send values. If rightmost "A" is set to 1 then START automatically trigger/untrigger note as well.
Code:
; VRC7 audio test program.
.inesprg 1
.ineschr 1
.inesmir 1
.inesmap 85 ;VRC7
; Macro
.macro write_ppu
lda #\1
sta $2007
.endm
.macro set_ppu
lda #(\1>>8)
sta $2006
lda #(\1&$FF)
sta $2006
.endm
.macro strobe
lda #1
sta $4016
lda #0
sta $4016
.endm
; RAM
.zp
valmem:
; Custom instrument setting 0-7, IIIIVVVV, LLLLLLLL, --STOOOH
; 2 bytes each: hi-nybble lo-nybble
.ds 22
autotrig:
; set if START should trigger/untrigger note
.ds 1
pushed:
; check if button still pushed
.ds 1
cursor:
; cursor position: 0 to 21
.ds 1
; CHR
.code
.bank 2
.org $0000
.incbin "vrc7test.chr"
; PRG
.code
.bank 0
.org $8000
one:
; data for joypad bit testing
.db 1
fill_ppu:
sta $2007
dex
bne fill_ppu
rts
write_vrc7:
; set address
sty $9010
; wait 6 cycles
jsr wait6
; load value
lda <valmem,x
inx
asl a
asl a
asl a
asl a
ora <valmem,x
inx
; set value
sta $9030
; wait 42 cycles (12 per call + 6 to return = 42)
jsr wait6
jsr wait6
jsr wait6
; return
wait6:
rts
Reset:
; disable IRQ and NMI, set address increment +1
sei
lda #%00000000
sta $2000
; display off
lda #%00000000
sta $2001
; initialize RAM
lda #0
sta <cursor
sta <autotrig
; palette
set_ppu $3F00
write_ppu $1D ; black
write_ppu $20 ; white
write_ppu $2A ; green
write_ppu $21 ; blue
; initialize name table
set_ppu $2000
lda #$1E
ldx #(32*4+5)
jsr fill_ppu
; headings - I0..I7
lda #$30
ldx #$20
ldy #8
nt1:
sta $2007
stx $2007
inx
dey
bne nt1
; more headings
write_ppu $50 ;I
write_ppu $53 ;v
write_ppu $52 ;LL
sta $2007 ;LL
write_ppu $54 ;ST
write_ppu $51 ;oH
write_ppu $4A ;A
; gap
lda #$1E
ldx #9
jsr fill_ppu
; values
lda #$00
ldx #23
jsr fill_ppu
; end
lda #$1E
ldx #$FF
jsr fill_ppu
ldx #$FF
jsr fill_ppu
ldx #$FF
jsr fill_ppu
ldx #7
jsr fill_ppu
; display on, enable NMI
lda #%00001110
sta $2001
lda #%10000000
sta $2000
; wait...
w1:
jmp w1
rt:
rti
NMI:
strobe
lda $4016
lda $4016
lda $4016
; delay if buttons held
lda <pushed
beq npu
lda $4016 ;START
bit one
bne rt
lda $4016 ;UP
bit one
bne rt
lda $4016 ;DOWN
bit one
bne rt
lda $4016 ;LEFT
bit one
bne rt
lda $4016 ;RIGHT
bit one
bne rt
dec <pushed
npu:
; check buttons pushed
lda $4016 ;START
bit one
beq ch_up
jmp START
ch_up:
lda $4016 ;UP
bit one
beq ch_down
jmp UP
ch_down:
lda $4016 ;DOWN
bit one
beq ch_left
jmp DOWN
ch_left:
lda $4016 ;LEFT
bit one
beq ch_right
jmp LEFT
ch_right:
lda $4016 ;RIGHT
bit one
beq w2
jmp RIGHT
w2:
; reset scroll position
lda #0
sta $2005
sta $2005
; enable NMI and exit interrupt call
lda #%10000000
sta $2000
rti
w3:
inc <pushed
jmp w2
START:
; disable NMI
lda #%00000000
sta $2000
; check auto-trigger
lda <20
eor <autotrig
sta <20
; write VRC7 audio registers
ldx #0
ldy #$00
jsr write_vrc7
ldy #$01
jsr write_vrc7
ldy #$02
jsr write_vrc7
ldy #$03
jsr write_vrc7
ldy #$04
jsr write_vrc7
ldy #$05
jsr write_vrc7
ldy #$06
jsr write_vrc7
ldy #$07
jsr write_vrc7
ldy #$30
jsr write_vrc7
ldy #$10
jsr write_vrc7
ldy #$20
jsr write_vrc7
; done
jmp w3
UP:
ldx <cursor
lda #$20
sta $2006
lda #(32*5+5)
clc
adc <cursor
sta $2006
inc <valmem,x
lda #$0F
and <valmem,x
sta <valmem,x
sta $2007
jmp w3
DOWN:
ldx <cursor
lda #$20
sta $2006
lda #(32*5+5)
clc
adc <cursor
sta $2006
dec <valmem,x
lda #$0F
and <valmem,x
sta <valmem,x
sta $2007
jmp w3
LEFT:
lda <cursor
beq dez
dec <cursor
lda #$20
sta $2006
lda #(32*6+5)
clc
adc <cursor
sta $2006
write_ppu $1F
write_ppu $1E
dez:
jmp w3
RIGHT:
lda #22
cmp <cursor
beq dez
lda #$20
sta $2006
lda #(32*6+5)
clc
adc <cursor
sta $2006
write_ppu $1E
write_ppu $1F
inc <cursor
jmp w3
; Vectors
.bank 1
.org $FFFA
.dw NMI
.dw Reset
.dw 0
.inesprg 1
.ineschr 1
.inesmir 1
.inesmap 85 ;VRC7
; Macro
.macro write_ppu
lda #\1
sta $2007
.endm
.macro set_ppu
lda #(\1>>8)
sta $2006
lda #(\1&$FF)
sta $2006
.endm
.macro strobe
lda #1
sta $4016
lda #0
sta $4016
.endm
; RAM
.zp
valmem:
; Custom instrument setting 0-7, IIIIVVVV, LLLLLLLL, --STOOOH
; 2 bytes each: hi-nybble lo-nybble
.ds 22
autotrig:
; set if START should trigger/untrigger note
.ds 1
pushed:
; check if button still pushed
.ds 1
cursor:
; cursor position: 0 to 21
.ds 1
; CHR
.code
.bank 2
.org $0000
.incbin "vrc7test.chr"
; PRG
.code
.bank 0
.org $8000
one:
; data for joypad bit testing
.db 1
fill_ppu:
sta $2007
dex
bne fill_ppu
rts
write_vrc7:
; set address
sty $9010
; wait 6 cycles
jsr wait6
; load value
lda <valmem,x
inx
asl a
asl a
asl a
asl a
ora <valmem,x
inx
; set value
sta $9030
; wait 42 cycles (12 per call + 6 to return = 42)
jsr wait6
jsr wait6
jsr wait6
; return
wait6:
rts
Reset:
; disable IRQ and NMI, set address increment +1
sei
lda #%00000000
sta $2000
; display off
lda #%00000000
sta $2001
; initialize RAM
lda #0
sta <cursor
sta <autotrig
; palette
set_ppu $3F00
write_ppu $1D ; black
write_ppu $20 ; white
write_ppu $2A ; green
write_ppu $21 ; blue
; initialize name table
set_ppu $2000
lda #$1E
ldx #(32*4+5)
jsr fill_ppu
; headings - I0..I7
lda #$30
ldx #$20
ldy #8
nt1:
sta $2007
stx $2007
inx
dey
bne nt1
; more headings
write_ppu $50 ;I
write_ppu $53 ;v
write_ppu $52 ;LL
sta $2007 ;LL
write_ppu $54 ;ST
write_ppu $51 ;oH
write_ppu $4A ;A
; gap
lda #$1E
ldx #9
jsr fill_ppu
; values
lda #$00
ldx #23
jsr fill_ppu
; end
lda #$1E
ldx #$FF
jsr fill_ppu
ldx #$FF
jsr fill_ppu
ldx #$FF
jsr fill_ppu
ldx #7
jsr fill_ppu
; display on, enable NMI
lda #%00001110
sta $2001
lda #%10000000
sta $2000
; wait...
w1:
jmp w1
rt:
rti
NMI:
strobe
lda $4016
lda $4016
lda $4016
; delay if buttons held
lda <pushed
beq npu
lda $4016 ;START
bit one
bne rt
lda $4016 ;UP
bit one
bne rt
lda $4016 ;DOWN
bit one
bne rt
lda $4016 ;LEFT
bit one
bne rt
lda $4016 ;RIGHT
bit one
bne rt
dec <pushed
npu:
; check buttons pushed
lda $4016 ;START
bit one
beq ch_up
jmp START
ch_up:
lda $4016 ;UP
bit one
beq ch_down
jmp UP
ch_down:
lda $4016 ;DOWN
bit one
beq ch_left
jmp DOWN
ch_left:
lda $4016 ;LEFT
bit one
beq ch_right
jmp LEFT
ch_right:
lda $4016 ;RIGHT
bit one
beq w2
jmp RIGHT
w2:
; reset scroll position
lda #0
sta $2005
sta $2005
; enable NMI and exit interrupt call
lda #%10000000
sta $2000
rti
w3:
inc <pushed
jmp w2
START:
; disable NMI
lda #%00000000
sta $2000
; check auto-trigger
lda <20
eor <autotrig
sta <20
; write VRC7 audio registers
ldx #0
ldy #$00
jsr write_vrc7
ldy #$01
jsr write_vrc7
ldy #$02
jsr write_vrc7
ldy #$03
jsr write_vrc7
ldy #$04
jsr write_vrc7
ldy #$05
jsr write_vrc7
ldy #$06
jsr write_vrc7
ldy #$07
jsr write_vrc7
ldy #$30
jsr write_vrc7
ldy #$10
jsr write_vrc7
ldy #$20
jsr write_vrc7
; done
jmp w3
UP:
ldx <cursor
lda #$20
sta $2006
lda #(32*5+5)
clc
adc <cursor
sta $2006
inc <valmem,x
lda #$0F
and <valmem,x
sta <valmem,x
sta $2007
jmp w3
DOWN:
ldx <cursor
lda #$20
sta $2006
lda #(32*5+5)
clc
adc <cursor
sta $2006
dec <valmem,x
lda #$0F
and <valmem,x
sta <valmem,x
sta $2007
jmp w3
LEFT:
lda <cursor
beq dez
dec <cursor
lda #$20
sta $2006
lda #(32*6+5)
clc
adc <cursor
sta $2006
write_ppu $1F
write_ppu $1E
dez:
jmp w3
RIGHT:
lda #22
cmp <cursor
beq dez
lda #$20
sta $2006
lda #(32*6+5)
clc
adc <cursor
sta $2006
write_ppu $1E
write_ppu $1F
inc <cursor
jmp w3
; Vectors
.bank 1
.org $FFFA
.dw NMI
.dw Reset
.dw 0