ChibiSound VRC6
Posted: Fri Apr 23, 2021 12:17 am
Hello! I'm new to the forums but I've been using Keith's tutorials for a couple months now. I'm really interested in Castlevania 3's Famicom version with its enhanced sound, and I've been experimenting with making Keith's ChibiSound driver work with it.
Sadly this will not work on a PAL or North American NES, unless you modify its motherboard to allow for the additional 3 sound channels. On Famicom or NEStopia this will work just fine.
Here's the source code for it. Keep in mind that I'm new to this, and I don't fully understand the Konami VRC6 chip, and the channels might not use the same "syntax?" (I'm not sure what to call it, basically the bits more than likely mean something different for the extra three channels than they do for the 2A03) so this may not be the best implementation. But it does output the extra sound so at least it's working.
It's a bit long, but if you copy and paste this whole thing into a blank .asm file it should work.
org $BFF0
db "NES",$1a ;ID
db $01 ;Rom pages (16k each)
db $0 ;CHR-ROM pages
db %10000010 ;mmmmFTBM mmmm = mapper no bottom 4 bits , Four screen vram layout, Trainer at &7000, Battery ram at &6000, Mirror (0=horiz, 1=vert)
db %00010000 ;mmmm--PV mapper (top 4 bits... Pc10 arcade, Vs unisystem )
db 0 ;Ram pages (this might not be set up correctly)
db 0,0,0,0,0,0,0 ; (this might not be set up correctly)
;THIS CARTRIDGE USES MAPPER 24 WHICH WAS ALSO USED BY THE JAPANESE VERSION OF CASTLEVANIA 3
z_Regs equ $60
Cursor_X equ $40
Cursor_Y equ Cursor_X+1
SpPage equ $0100
UserRam equ $200
vblanked equ $7F ;Zero page address of Vblank count
VRC6_PULSE1_CTRL equ $9000
VRC6_PULSE2_CTRL equ $A000
SAW_ACCUM equ $B000
VRC6_PULSE1_FREQ_LO equ $9001
VRC6_PULSE2_FREQ_LO equ $a001
SAW_FREQ_LO equ $b001
VRC6_PULSE1_FREQ_HI equ $9002
VRC6_PULSE2_FREQ_HI equ $a002
SAW_FREQ_HI equ $b002
IRQ_LATCH equ $f000
IRQ_CTRL equ $f001
IRQ_ACK equ $f002
include "\SrcAll\BasicMacros.asm"
nmihandler: ;This procuedure runs after each frame (See footer.asm)
php
inc vblanked ;Alter Vblank Zero page entry
plp
rti
irqhandler:
rti ;Do nothing
NES_main:
sei ;Interrupts on
cld ;Clear Decimal flag
jsr ScreenInit
jsr Cls
ldx #$ff ;Set up stack
txs
lda #$00
sta $9003 ;Initialize VRC6 audio
lda #$80
InfLoop:
pha
ldx #0
ldy #0
jsr Locate ;Reset Print Location
pla
pha
jsr showhex ;Show A
pla
; pha
; jsr DoVRC6ChannelTest
; pla
pha
jsr ChibisoundVRC6 ;Make sound
jsr Pause ;Slow down loop
pla
sec ;Alter sound for next loop
sbc #1
jmp InfLoop
; DoVRC6ChannelTest:
; lda #%01111111
; STA VRC6_PULSE1_CTRL
; STA VRC6_PULSE2_CTRL
; LDA #%00111111
; STA SAW_ACCUM
; LDA #$7E
; STA VRC6_PULSE1_FREQ_LO
; STA VRC6_PULSE2_FREQ_LO
; STA SAW_FREQ_LO
; LDA #$87
; STA VRC6_PULSE1_FREQ_HI
; STA VRC6_PULSE2_FREQ_HI
; STA SAW_FREQ_HI
; rts
Pause:
ifndef BuildAP2
lda #$50
sta z_b
lda #00
sta z_c
DelayAgain2:
jsr DecBC
lda z_b
ora z_c
bne DelayAgain2
endif
rts
;MUST USE MAPPER 24 OR 26 FOR THIS TO WORK. EXTRA SOUND CAN ONLY BE HEARD ON FAMICOM OR EMULATOR.
;PRIOR TO CALLING THIS SUBROUTINE, WRITE #$00 TO $9003.
ChibiSoundVRC6: ;%NVPPPPPP N=Noise V=Volume P=Pitch
pha
and #%01000000 ;Volume bit
lsr
lsr
lsr
ora #%00110111 ;CCLEVVVV - Fixed Volume, Disable Clock
tax
pla
beq ChibiSound_Silent
bit Bit7 ;Noise
bne ChibiSound_Noise
stx $4000 ;CCLEVVVV - APU Volume/Decay Channel 1 (Rectangle)
stx $9000 ;MDDDVVVV - Mode (1: ignore duty)/Duty Cycle/Volume
stx $a000
stx $b000
jsr swapnibbles ;Swap Pitch Bits --FFffff to ffff--FF
pha
and #%00000011 ;Top 2 bits
ora #%11111000
sta $4003 ;CCCCCHHH - APU Length Channel 1 (Rectangle)
STA $9002 ;E---FFFF - Enable/Frequency High Bits
sta $a002
sta $b002
pla
and #%11110000
sta $4002 ;LLLLLLLL - APU Frequency Channel 1 (Rectangle)
sta $9001 ;ffffffff - Frequency Low Bits
sta $a001
sta $b001
lda #%00000001
ChibiSound_Silent: ;A=0 for silent
sta $4015 ;DF-54321 - DMC/IRQ/length counter status/channel enable
rts
ChibiSound_Noise:
stx $400C ;CCLEVVVV - APU Volume/Decay Channel 1 (Rectangle)
and #%00111100
lsr
lsr
sta $400E ;LLLLLLLL - APU Channel 4 (Noise) Frequency (W)
lda #%00001000 ;DF-54321 - DMC/IRQ/length counter status/channel enable
;We also use this for setting the bottom 3 bits of the noise H freq.
sta $400F ;CCCCCHHH - APU Channel 4 (Noise) Length (W)
jmp ChibiSound_Silent
include "\SrcAll\monitor.asm"
include "\SrcAll\BasicFunctions.asm"
include "\SrcAll\V1_BitmapMemory.asm"
include "\SrcAll\V1_VdpMemory.asm" ;VRAM functions for Tilemap Systems
Bitmapfont:
incbin "\ResALL\Font96.FNT" ;Not used by the VIC due to memory limitations
include "..\SrcALL\V1_Functions.asm"
include "..\SrcALL\V1_Footer.asm"
Sadly this will not work on a PAL or North American NES, unless you modify its motherboard to allow for the additional 3 sound channels. On Famicom or NEStopia this will work just fine.
Here's the source code for it. Keep in mind that I'm new to this, and I don't fully understand the Konami VRC6 chip, and the channels might not use the same "syntax?" (I'm not sure what to call it, basically the bits more than likely mean something different for the extra three channels than they do for the 2A03) so this may not be the best implementation. But it does output the extra sound so at least it's working.
It's a bit long, but if you copy and paste this whole thing into a blank .asm file it should work.
org $BFF0
db "NES",$1a ;ID
db $01 ;Rom pages (16k each)
db $0 ;CHR-ROM pages
db %10000010 ;mmmmFTBM mmmm = mapper no bottom 4 bits , Four screen vram layout, Trainer at &7000, Battery ram at &6000, Mirror (0=horiz, 1=vert)
db %00010000 ;mmmm--PV mapper (top 4 bits... Pc10 arcade, Vs unisystem )
db 0 ;Ram pages (this might not be set up correctly)
db 0,0,0,0,0,0,0 ; (this might not be set up correctly)
;THIS CARTRIDGE USES MAPPER 24 WHICH WAS ALSO USED BY THE JAPANESE VERSION OF CASTLEVANIA 3
z_Regs equ $60
Cursor_X equ $40
Cursor_Y equ Cursor_X+1
SpPage equ $0100
UserRam equ $200
vblanked equ $7F ;Zero page address of Vblank count
VRC6_PULSE1_CTRL equ $9000
VRC6_PULSE2_CTRL equ $A000
SAW_ACCUM equ $B000
VRC6_PULSE1_FREQ_LO equ $9001
VRC6_PULSE2_FREQ_LO equ $a001
SAW_FREQ_LO equ $b001
VRC6_PULSE1_FREQ_HI equ $9002
VRC6_PULSE2_FREQ_HI equ $a002
SAW_FREQ_HI equ $b002
IRQ_LATCH equ $f000
IRQ_CTRL equ $f001
IRQ_ACK equ $f002
include "\SrcAll\BasicMacros.asm"
nmihandler: ;This procuedure runs after each frame (See footer.asm)
php
inc vblanked ;Alter Vblank Zero page entry
plp
rti
irqhandler:
rti ;Do nothing
NES_main:
sei ;Interrupts on
cld ;Clear Decimal flag
jsr ScreenInit
jsr Cls
ldx #$ff ;Set up stack
txs
lda #$00
sta $9003 ;Initialize VRC6 audio
lda #$80
InfLoop:
pha
ldx #0
ldy #0
jsr Locate ;Reset Print Location
pla
pha
jsr showhex ;Show A
pla
; pha
; jsr DoVRC6ChannelTest
; pla
pha
jsr ChibisoundVRC6 ;Make sound
jsr Pause ;Slow down loop
pla
sec ;Alter sound for next loop
sbc #1
jmp InfLoop
; DoVRC6ChannelTest:
; lda #%01111111
; STA VRC6_PULSE1_CTRL
; STA VRC6_PULSE2_CTRL
; LDA #%00111111
; STA SAW_ACCUM
; LDA #$7E
; STA VRC6_PULSE1_FREQ_LO
; STA VRC6_PULSE2_FREQ_LO
; STA SAW_FREQ_LO
; LDA #$87
; STA VRC6_PULSE1_FREQ_HI
; STA VRC6_PULSE2_FREQ_HI
; STA SAW_FREQ_HI
; rts
Pause:
ifndef BuildAP2
lda #$50
sta z_b
lda #00
sta z_c
DelayAgain2:
jsr DecBC
lda z_b
ora z_c
bne DelayAgain2
endif
rts
;MUST USE MAPPER 24 OR 26 FOR THIS TO WORK. EXTRA SOUND CAN ONLY BE HEARD ON FAMICOM OR EMULATOR.
;PRIOR TO CALLING THIS SUBROUTINE, WRITE #$00 TO $9003.
ChibiSoundVRC6: ;%NVPPPPPP N=Noise V=Volume P=Pitch
pha
and #%01000000 ;Volume bit
lsr
lsr
lsr
ora #%00110111 ;CCLEVVVV - Fixed Volume, Disable Clock
tax
pla
beq ChibiSound_Silent
bit Bit7 ;Noise
bne ChibiSound_Noise
stx $4000 ;CCLEVVVV - APU Volume/Decay Channel 1 (Rectangle)
stx $9000 ;MDDDVVVV - Mode (1: ignore duty)/Duty Cycle/Volume
stx $a000
stx $b000
jsr swapnibbles ;Swap Pitch Bits --FFffff to ffff--FF
pha
and #%00000011 ;Top 2 bits
ora #%11111000
sta $4003 ;CCCCCHHH - APU Length Channel 1 (Rectangle)
STA $9002 ;E---FFFF - Enable/Frequency High Bits
sta $a002
sta $b002
pla
and #%11110000
sta $4002 ;LLLLLLLL - APU Frequency Channel 1 (Rectangle)
sta $9001 ;ffffffff - Frequency Low Bits
sta $a001
sta $b001
lda #%00000001
ChibiSound_Silent: ;A=0 for silent
sta $4015 ;DF-54321 - DMC/IRQ/length counter status/channel enable
rts
ChibiSound_Noise:
stx $400C ;CCLEVVVV - APU Volume/Decay Channel 1 (Rectangle)
and #%00111100
lsr
lsr
sta $400E ;LLLLLLLL - APU Channel 4 (Noise) Frequency (W)
lda #%00001000 ;DF-54321 - DMC/IRQ/length counter status/channel enable
;We also use this for setting the bottom 3 bits of the noise H freq.
sta $400F ;CCCCCHHH - APU Channel 4 (Noise) Length (W)
jmp ChibiSound_Silent
include "\SrcAll\monitor.asm"
include "\SrcAll\BasicFunctions.asm"
include "\SrcAll\V1_BitmapMemory.asm"
include "\SrcAll\V1_VdpMemory.asm" ;VRAM functions for Tilemap Systems
Bitmapfont:
incbin "\ResALL\Font96.FNT" ;Not used by the VIC due to memory limitations
include "..\SrcALL\V1_Functions.asm"
include "..\SrcALL\V1_Footer.asm"