.base $00
.db "NESM", $1A, $01
.db 1
.db 1
.dw LOAD
.dw INIT
.dw PLAY
names_start:
.db "t*(42&t>>10)"
.dsb names_start+32-$
.db "Johnathan Roatch"
.dsb names_start+64-$
.db "2016 Public domain"
.dsb names_start+96-$
.dw 16640
.db $00,$00,$00,$00,$00,$00,$00,$00
.dw 19998
.db $00
.db $00
.db $00,$00,$00,$00
.enum $00
temp .dsb 2
.ende
.base $dead
LOAD:
.db "u"
INIT:
sei
lda #$00
sta $4015
sta $4011
cld
rts
PLAY:
ldx #0
ldy #0
;;
; The Forty-Two Melody for NES
; https://countercomplex.blogspot.com/2011/10/some-deep-analysis-of-one-line-music.html
; APU_DMC_RAW = t*(42&t>>10)
; At 223 cycles, the sample rate is about 8026hz on NTSC.
; - Position independent executable!
; - Uses temp+0 and temp+1 for scratch space.
; - Time code is in the X and Y registers.
the42melody:
APU_DMC_RAW = $4011
next_sample:
; X is waveform phase
stx temp+0
; Upper 5 bits of Y is the note sequence.
tya
lsr
lsr
; Select which of the 8 frequencies to play. 0 being rest.
and #42
; The loop terminator for the multiply operation.
ora #%10000000
sta temp+1
; caculate wave sample by multiplying temp+0 and temp+1 into A
lda #0
; start in the middle of the loop for branch optimization.
beq start_loop
multiply_loop:
; A lone NOP to correct the total sample rate.
nop
; add temp+0 to A when a bit in temp+1 is set.
bcs cycle_correction_1
nop
bcc $+2
cycle_correction_1:
bcc skip_add
clc
adc temp+0
skip_add:
; multiply operand by 2 each time a LSB of temp+1 is read.
asl temp+0
start_loop:
lsr temp+1
; the terminateing bit is not processed.
bne multiply_loop
; output the 7-bit sample.
lsr
sta APU_DMC_RAW
; increment the 16-bit timer, and do the next sample.
inx
beq cycle_correction_2
nop
cycle_correction_2:
bne skip_inc_hi
iny
skip_inc_hi:
; clc
; bcc next_sample
;; Replace the last two lines with this to terminate after 1 loop.
nop
bne next_sample
rts
.db $00