FC/NES 音乐示例程序 生日快乐歌
叶枫写的,我反汇编的。
;开始地址:$bff0
;结束地址:$ffff
;文件长度:$4010
COUNTER = $00
MUSIC_OFFSET1 = $01
MUSIC_OFFSET2 = $02
.org $BFF0
.db "NES",$1A,$01,$01,$00,$00
.dw $00,$00,$00,$00
.start $C000
.org $C000
reset:
sei ; 禁用中断
cld
ldx #$ff ; 初始化栈顶指针到$FF
txs
inx
stx COUNTER
stx MUSIC_OFFSET1
stx MUSIC_OFFSET2
_vb1:
lda $2002
bpl _vb1
_vb2:
lda $2002
bpl _vb2
lda #$00
sta $2001
lda #$0f ; 声音切换:0000 1111,方波#1#2,三角波,噪声
sta $4015
lda #$8f
sta $4000 ; APU方波#1控制端口
lda #$00
sta $4001 ; APU方波#1控制端口
lda #$80 ; 开nmi中断
sta $2000
main:
jmp main
nmi:
inc COUNTER ; 计数器增加
ldx MUSIC_OFFSET1
lda music1,x ; 取得音长
cmp COUNTER ; 判断是否该播放
beq next2 ; 播放
cmp #$ff
beq next1 ; 是否结束
jmp over ; 退出
next1:
ldx #$00 ; 回到开始
stx MUSIC_OFFSET1
jmp over
next2:
lda #$00
sta COUNTER
lda MUSIC_OFFSET2
tay
lda music2,y ; 波长低八位
cmp #$ff ; 结束了吗?
beq next3
sta $4002
iny
lda music2,y ; 波长高三位+音长计数器
cmp #$ff ; 结束了吗?
beq next3
sta $4003
iny ; 下一个音符
sty MUSIC_OFFSET2
inx
stx MUSIC_OFFSET1
jmp over
next3:
ldy #$00 ; 回到开始
sty MUSIC_OFFSET2
over:
rti
music1:
; 音长 8*4+1=33
.db $10,$10,$20,$20,$20,$20,$20,$10
.db $10,$20,$20,$20,$20,$20,$20,$10
.db $10,$20,$20,$20,$20,$20,$20,$20
.db $20,$10,$10,$20,$20,$20,$20,$20
.db $20,$FF
music2:
; 两个一组,$FF为结束 8*8+2=66
.db $1C,$09,$1C,$09,$FD,$08,$1C,$09
.db $D4,$08,$E1,$08,$00,$00,$1C,$09
.db $1C,$D9,$FD,$08,$1C,$09,$BD,$08
.db $D4,$08,$D4,$08,$00,$00,$1C,$09
.db $1C,$09,$8D,$08,$A8,$08,$D4,$08
.db $E1,$08,$FD,$08,$FD,$08,$FD,$08
.db $00,$00,$9F,$08,$9F,$08,$A8,$08
.db $D4,$08,$BD,$08,$D4,$08,$D4,$D4
.db $08,$00,$FF,$FF
irq:
rti
.org $fffa
.dw nmi,reset,irq