1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-11-25 18:33:11 +00:00
8bitworkshop/presets/atari8-800/pokeymusic.ca65
2023-02-02 14:46:41 -05:00

165 lines
3.3 KiB
Plaintext

AUDF0 = $d200
AUDC0 = $d201
AUDCTL = $d208
.data
Chan0dur: .res 4 ; current note duration channel 0
Chan0note: .res 4 ; current note pitch channel 0
Chan0duty: .res 4 ; current duty bits channel 0
DurationTimer: .res 1 ; duration until next cmd
CurChannel: .res 1 ; next channel to add note
Volume: .res 1 ; initial volume of note (0-31)
; set_irq() saves/restores entire zeropage segment
; which we don't want!
; so we have to set this with an equate
SongPtr = $fe
;.segment "EXTZP"
;SongPtr: .res 2 ; ptr to next song byte
.code
; Update channel pitch in AUDF0
; 8-bit rotation of duty cycle bits
.export _music_duty
_music_duty:
ldx #3
ldy #0
@loop:
lda Chan0dur,x
beq :++
lda Chan0duty,x
asl
bcc :+
ora #1
: sta Chan0duty,x
lda Chan0note,x
beq :+
; If next bit is set, add 1 to AUDF0
adc #0
sta AUDF0,y
:
iny
iny
dex
bpl @loop
rts
; Decrement the volumes for each channel
.export _music_tick
_music_tick:
ldx #3
ldy #0
@loop1:
lda Chan0dur,x
beq :+
lsr
ora #$a0
sta AUDC0,y
dec Chan0dur,x
:
iny
iny
dex
bpl @loop1
; Also decrement next-note timer, fetch next note
lda DurationTimer
bmi @Done
beq @NextData
dec DurationTimer
rts
; Timer ran out, so fetch next note
@NextData:
ldx #0
lda (SongPtr,x)
bmi @LoadDuration
; < $80, play next note
ldx CurChannel ; next channel
tay
jsr music_do_note
inx
txa
and #3
sta CurChannel ; inc next channel
jsr @IncDataPtr
jmp @NextData
; >= $80, load next duration
@LoadDuration:
cmp #$ff ; $ff = end of song
bne @NoResetTrack
sta DurationTimer
jmp music_done
@NoResetTrack:
and #$7f
; asl
sta DurationTimer ; store duration * 2
@IncDataPtr:
; increment song pointer
inc SongPtr
bne @Done
inc SongPtr+1
@Done:
rts
music_do_note:
; Play a note
; X = channel (0,1)
; Y = note index (0-63)
lda FREQZ,y
sta Chan0note,x
lda DUTYZ,y
sta Chan0duty,x
lda Volume
sta Chan0dur,x
rts
music_done:
rts
.export _music_start
_music_start:
sta SongPtr
stx SongPtr+1
lda #24
sta Volume
lda #0
sta DurationTimer
sta CurChannel
ldx #3
: sta Chan0dur,x
dex
bpl :-
lda #$01
sta AUDCTL
rts
.export _music_get_ptr
_music_get_ptr:
lda SongPtr
ldx SongPtr+1
rts
.export _music_is_done
_music_is_done:
ldx #0
lda (SongPtr,x)
cmp #$ff
php
pla
lsr
and #1
rts
; Table of AUDF base values for each note
FREQZ:
.byte 254, 254, 254, 255, 240, 227, 214, 202, 190, 180, 169, 160, 151, 142, 134, 127, 119, 113, 106, 100, 94, 89, 84, 79, 75, 70, 66, 63, 59, 56, 52, 49, 47, 44, 41, 39, 37, 34, 32, 31, 29, 27, 25, 24, 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7
; Table of duty-cycle bits for each note
DUTYZ:
.byte 0, 0, 0, 0, 181, 1, 17, 1, 219, 0, 239, 17, 17, 181, 181, 0, 239, 0, 181, 181, 239, 85, 73, 181, 1, 239, 219, 0, 73, 0, 239, 219, 0, 17, 219, 73, 0, 239, 239, 0, 17, 85, 239, 73, 0, 181, 73, 1, 0, 0, 0, 0, 1, 17, 85, 219, 0, 73, 181, 1, 85, 0, 85, 0